aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/connector/Makefile5
-rw-r--r--Documentation/connector/cn_test.c33
-rw-r--r--Documentation/connector/connector.txt119
-rw-r--r--Documentation/connector/ucon.c62
-rw-r--r--Documentation/kernel-parameters.txt5
-rw-r--r--Documentation/networking/00-INDEX2
-rw-r--r--Documentation/networking/ieee802154.txt11
-rw-r--r--MAINTAINERS23
-rw-r--r--arch/alpha/include/asm/socket.h2
-rw-r--r--arch/arm/include/asm/socket.h3
-rw-r--r--arch/avr32/include/asm/socket.h3
-rw-r--r--arch/cris/include/asm/socket.h3
-rw-r--r--arch/frv/include/asm/socket.h3
-rw-r--r--arch/h8300/include/asm/socket.h3
-rw-r--r--arch/ia64/hp/sim/simeth.c2
-rw-r--r--arch/ia64/include/asm/socket.h3
-rw-r--r--arch/m32r/include/asm/socket.h3
-rw-r--r--arch/m68k/include/asm/socket.h3
-rw-r--r--arch/mips/ar7/platform.c15
-rw-r--r--arch/mips/include/asm/socket.h2
-rw-r--r--arch/mips/kernel/scall64-n32.S2
-rw-r--r--arch/mips/kernel/scall64-o32.S4
-rw-r--r--arch/mn10300/include/asm/socket.h3
-rw-r--r--arch/parisc/include/asm/socket.h2
-rw-r--r--arch/powerpc/include/asm/socket.h3
-rw-r--r--arch/s390/include/asm/socket.h3
-rw-r--r--arch/sparc/include/asm/socket.h3
-rw-r--r--arch/sparc/kernel/sys32.S2
-rw-r--r--arch/um/drivers/net_kern.c2
-rw-r--r--arch/x86/include/asm/socket.h3
-rw-r--r--arch/xtensa/include/asm/socket.h3
-rw-r--r--arch/xtensa/platforms/iss/network.c2
-rw-r--r--drivers/atm/horizon.c4
-rw-r--r--drivers/atm/solos-pci.c2
-rw-r--r--drivers/connector/cn_proc.c3
-rw-r--r--drivers/connector/cn_queue.c7
-rw-r--r--drivers/connector/connector.c6
-rw-r--r--drivers/ieee802154/fakehard.c128
-rw-r--r--drivers/isdn/Kconfig6
-rw-r--r--drivers/isdn/act2000/capi.c3
-rw-r--r--drivers/isdn/act2000/module.c31
-rw-r--r--drivers/isdn/hardware/eicon/message.c4
-rw-r--r--drivers/isdn/hardware/eicon/os_4bri.c3
-rw-r--r--drivers/isdn/hardware/mISDN/Kconfig51
-rw-r--r--drivers/isdn/hardware/mISDN/Makefile8
-rw-r--r--drivers/isdn/hardware/mISDN/avmfritz.c1152
-rw-r--r--drivers/isdn/hardware/mISDN/hfcmulti.c23
-rw-r--r--drivers/isdn/hardware/mISDN/hfcpci.c16
-rw-r--r--drivers/isdn/hardware/mISDN/hfcsusb.c16
-rw-r--r--drivers/isdn/hardware/mISDN/iohelper.h109
-rw-r--r--drivers/isdn/hardware/mISDN/ipac.h405
-rw-r--r--drivers/isdn/hardware/mISDN/isar.h269
-rw-r--r--drivers/isdn/hardware/mISDN/mISDNinfineon.c1178
-rw-r--r--drivers/isdn/hardware/mISDN/mISDNipac.c1655
-rw-r--r--drivers/isdn/hardware/mISDN/mISDNisar.c1726
-rw-r--r--drivers/isdn/hardware/mISDN/netjet.c1156
-rw-r--r--drivers/isdn/hardware/mISDN/netjet.h58
-rw-r--r--drivers/isdn/hardware/mISDN/speedfax.c526
-rw-r--r--drivers/isdn/hardware/mISDN/w6692.c1440
-rw-r--r--drivers/isdn/hardware/mISDN/w6692.h190
-rw-r--r--drivers/isdn/hisax/Kconfig6
-rw-r--r--drivers/isdn/hisax/Makefile4
-rw-r--r--drivers/isdn/hisax/amd7930_fn.c2
-rw-r--r--drivers/isdn/hisax/callc.c4
-rw-r--r--drivers/isdn/hisax/hfc_pci.c2
-rw-r--r--drivers/isdn/hisax/hfc_sx.c2
-rw-r--r--drivers/isdn/hisax/icc.c2
-rw-r--r--drivers/isdn/hisax/isac.c2
-rw-r--r--drivers/isdn/hisax/isdnhdlc.h70
-rw-r--r--drivers/isdn/hisax/isdnl1.c12
-rw-r--r--drivers/isdn/hisax/isdnl2.c4
-rw-r--r--drivers/isdn/hisax/isdnl3.c4
-rw-r--r--drivers/isdn/hisax/l3_1tr6.c20
-rw-r--r--drivers/isdn/hisax/l3dss1.c26
-rw-r--r--drivers/isdn/hisax/l3ni1.c26
-rw-r--r--drivers/isdn/hisax/q931.c24
-rw-r--r--drivers/isdn/hisax/st5481.h2
-rw-r--r--drivers/isdn/hisax/st5481_b.c5
-rw-r--r--drivers/isdn/hisax/st5481_d.c2
-rw-r--r--drivers/isdn/hisax/st5481_usb.c11
-rw-r--r--drivers/isdn/hisax/tei.c4
-rw-r--r--drivers/isdn/hisax/w6692.c2
-rw-r--r--drivers/isdn/hysdn/hysdn_net.c2
-rw-r--r--drivers/isdn/i4l/Kconfig11
-rw-r--r--drivers/isdn/i4l/Makefile1
-rw-r--r--drivers/isdn/i4l/isdn_net.c16
-rw-r--r--drivers/isdn/i4l/isdn_ppp.c6
-rw-r--r--drivers/isdn/i4l/isdnhdlc.c (renamed from drivers/isdn/hisax/isdnhdlc.c)429
-rw-r--r--drivers/isdn/mISDN/hwchannel.c15
-rw-r--r--drivers/isdn/mISDN/layer2.c2
-rw-r--r--drivers/media/dvb/dvb-core/dvb_net.c2
-rw-r--r--drivers/message/fusion/mptlan.c2
-rw-r--r--drivers/misc/sgi-xp/xpnet.c4
-rw-r--r--drivers/net/3c501.c2
-rw-r--r--drivers/net/3c505.c2
-rw-r--r--drivers/net/3c507.c2
-rw-r--r--drivers/net/3c509.c2
-rw-r--r--drivers/net/3c515.c4
-rw-r--r--drivers/net/3c523.c2
-rw-r--r--drivers/net/3c527.c4
-rw-r--r--drivers/net/3c59x.c4
-rw-r--r--drivers/net/7990.c2
-rw-r--r--drivers/net/8139cp.c2
-rw-r--r--drivers/net/8139too.c4
-rw-r--r--drivers/net/82596.c4
-rw-r--r--drivers/net/Kconfig3
-rw-r--r--drivers/net/a2065.c4
-rw-r--r--drivers/net/amd8111e.c2
-rw-r--r--drivers/net/appletalk/cops.c2
-rw-r--r--drivers/net/appletalk/ipddp.c4
-rw-r--r--drivers/net/appletalk/ltpc.c2
-rw-r--r--drivers/net/ariadne.c4
-rw-r--r--drivers/net/arm/am79c961a.c2
-rw-r--r--drivers/net/arm/at91_ether.c2
-rw-r--r--drivers/net/arm/ether1.c2
-rw-r--r--drivers/net/arm/ether3.c4
-rw-r--r--drivers/net/arm/w90p910_ether.c206
-rw-r--r--drivers/net/at1700.c2
-rw-r--r--drivers/net/atarilance.c4
-rw-r--r--drivers/net/atl1c/atl1c_main.c3
-rw-r--r--drivers/net/atl1e/atl1e_main.c3
-rw-r--r--drivers/net/atp.c2
-rw-r--r--drivers/net/au1000_eth.c2
-rw-r--r--drivers/net/b44.c11
-rw-r--r--drivers/net/benet/Kconfig1
-rw-r--r--drivers/net/benet/be.h60
-rw-r--r--drivers/net/benet/be_cmds.c391
-rw-r--r--drivers/net/benet/be_cmds.h57
-rw-r--r--drivers/net/benet/be_ethtool.c21
-rw-r--r--drivers/net/benet/be_hw.h3
-rw-r--r--drivers/net/benet/be_main.c493
-rw-r--r--drivers/net/bfin_mac.c2
-rw-r--r--drivers/net/bmac.c2
-rw-r--r--drivers/net/bnx2.c24
-rw-r--r--drivers/net/bnx2x.h128
-rw-r--r--drivers/net/bnx2x_dump.h890
-rw-r--r--drivers/net/bnx2x_fw_defs.h379
-rw-r--r--drivers/net/bnx2x_hsi.h435
-rw-r--r--drivers/net/bnx2x_init.h320
-rw-r--r--drivers/net/bnx2x_init_ops.h419
-rw-r--r--drivers/net/bnx2x_link.c2578
-rw-r--r--drivers/net/bnx2x_link.h63
-rw-r--r--drivers/net/bnx2x_main.c2322
-rw-r--r--drivers/net/bnx2x_reg.h1065
-rw-r--r--drivers/net/bonding/bond_3ad.c101
-rw-r--r--drivers/net/bonding/bond_alb.c28
-rw-r--r--drivers/net/bonding/bond_ipv6.c4
-rw-r--r--drivers/net/bonding/bond_main.c14
-rw-r--r--drivers/net/bonding/bond_sysfs.c63
-rw-r--r--drivers/net/can/Kconfig7
-rw-r--r--drivers/net/can/sja1000/ems_pci.c152
-rw-r--r--drivers/net/can/sja1000/sja1000.c2
-rw-r--r--drivers/net/cassini.c4
-rw-r--r--drivers/net/cpmac.c44
-rw-r--r--drivers/net/cris/eth_v10.c2
-rw-r--r--drivers/net/cs89x0.c7
-rw-r--r--drivers/net/cxgb3/adapter.h10
-rw-r--r--drivers/net/cxgb3/ael1002.c1193
-rw-r--r--drivers/net/cxgb3/aq100x.c7
-rw-r--r--drivers/net/cxgb3/common.h10
-rw-r--r--drivers/net/cxgb3/cxgb3_main.c99
-rw-r--r--drivers/net/cxgb3/t3_hw.c19
-rw-r--r--drivers/net/cxgb3/xgmac.c11
-rw-r--r--drivers/net/de600.c2
-rw-r--r--drivers/net/de620.c2
-rw-r--r--drivers/net/declance.c4
-rw-r--r--drivers/net/defxx.c6
-rw-r--r--drivers/net/depca.c2
-rw-r--r--drivers/net/dm9000.c127
-rw-r--r--drivers/net/dm9000.h18
-rw-r--r--drivers/net/dnet.c2
-rw-r--r--drivers/net/dummy.c2
-rw-r--r--drivers/net/e100.c2
-rw-r--r--drivers/net/e1000/e1000.h7
-rw-r--r--drivers/net/e1000/e1000_ethtool.c51
-rw-r--r--drivers/net/e1000/e1000_hw.c2
-rw-r--r--drivers/net/e1000/e1000_hw.h3
-rw-r--r--drivers/net/e1000/e1000_main.c483
-rw-r--r--drivers/net/eepro.c4
-rw-r--r--drivers/net/eexpress.c4
-rw-r--r--drivers/net/enc28j60.c2
-rw-r--r--drivers/net/epic100.c4
-rw-r--r--drivers/net/eql.c2
-rw-r--r--drivers/net/eth16i.c4
-rw-r--r--drivers/net/ethoc.c2
-rw-r--r--drivers/net/ewrk3.c2
-rw-r--r--drivers/net/fealnx.c2
-rw-r--r--drivers/net/fec.c2
-rw-r--r--drivers/net/fs_enet/mii-fec.c37
-rw-r--r--drivers/net/gianfar.c1
-rw-r--r--drivers/net/hamachi.c2
-rw-r--r--drivers/net/hamradio/6pack.c2
-rw-r--r--drivers/net/hamradio/baycom_epp.c6
-rw-r--r--drivers/net/hamradio/bpqether.c2
-rw-r--r--drivers/net/hamradio/dmascc.c2
-rw-r--r--drivers/net/hamradio/hdlcdrv.c4
-rw-r--r--drivers/net/hamradio/mkiss.c2
-rw-r--r--drivers/net/hamradio/scc.c6
-rw-r--r--drivers/net/hamradio/yam.c2
-rw-r--r--drivers/net/hp100.c6
-rw-r--r--drivers/net/ibm_newemac/core.c2
-rw-r--r--drivers/net/ibmveth.c2
-rw-r--r--drivers/net/ifb.c2
-rw-r--r--drivers/net/igb/e1000_82575.c193
-rw-r--r--drivers/net/igb/e1000_82575.h6
-rw-r--r--drivers/net/igb/e1000_defines.h8
-rw-r--r--drivers/net/igb/e1000_hw.h18
-rw-r--r--drivers/net/igb/e1000_mac.c175
-rw-r--r--drivers/net/igb/e1000_mac.h3
-rw-r--r--drivers/net/igb/e1000_phy.c4
-rw-r--r--drivers/net/igb/e1000_regs.h1
-rw-r--r--drivers/net/igb/igb_ethtool.c65
-rw-r--r--drivers/net/igb/igb_main.c121
-rw-r--r--drivers/net/igbvf/netdev.c8
-rw-r--r--drivers/net/ioc3-eth.c2
-rw-r--r--drivers/net/irda/ali-ircc.c12
-rw-r--r--drivers/net/irda/au1k_ir.c4
-rw-r--r--drivers/net/irda/donauboe.c8
-rw-r--r--drivers/net/irda/irda-usb.c2
-rw-r--r--drivers/net/irda/nsc-ircc.c10
-rw-r--r--drivers/net/irda/pxaficp_ir.c4
-rw-r--r--drivers/net/irda/sa1100_ir.c4
-rw-r--r--drivers/net/irda/sir_dev.c6
-rw-r--r--drivers/net/irda/smsc-ircc2.c16
-rw-r--r--drivers/net/irda/stir4200.c2
-rw-r--r--drivers/net/irda/via-ircc.c12
-rw-r--r--drivers/net/irda/vlsi_ir.c6
-rw-r--r--drivers/net/irda/w83977af_ir.c4
-rw-r--r--drivers/net/isa-skeleton.c2
-rw-r--r--drivers/net/iseries_veth.c4
-rw-r--r--drivers/net/ixgb/ixgb_main.c7
-rw-r--r--drivers/net/ixgbe/ixgbe.h4
-rw-r--r--drivers/net/ixgbe/ixgbe_82598.c1
-rw-r--r--drivers/net/ixgbe/ixgbe_ethtool.c33
-rw-r--r--drivers/net/ixgbe/ixgbe_main.c14
-rw-r--r--drivers/net/ixgbe/ixgbe_type.h32
-rw-r--r--drivers/net/ixp2000/ixpdev.c4
-rw-r--r--drivers/net/jazzsonic.c10
-rw-r--r--drivers/net/jme.c189
-rw-r--r--drivers/net/jme.h21
-rw-r--r--drivers/net/korina.c44
-rw-r--r--drivers/net/lance.c2
-rw-r--r--drivers/net/lib82596.c4
-rw-r--r--drivers/net/lib8390.c2
-rw-r--r--drivers/net/ll_temac_main.c2
-rw-r--r--drivers/net/loopback.c2
-rw-r--r--drivers/net/lp486e.c4
-rw-r--r--drivers/net/mac89x0.c2
-rw-r--r--drivers/net/macb.c2
-rw-r--r--drivers/net/mace.c2
-rw-r--r--drivers/net/meth.c4
-rw-r--r--drivers/net/mipsnet.c2
-rw-r--r--drivers/net/mlx4/en_main.c5
-rw-r--r--drivers/net/mlx4/en_netdev.c18
-rw-r--r--drivers/net/mlx4/en_resources.c9
-rw-r--r--drivers/net/mlx4/en_rx.c111
-rw-r--r--drivers/net/mlx4/en_tx.c6
-rw-r--r--drivers/net/mlx4/mlx4_en.h17
-rw-r--r--drivers/net/myri10ge/myri10ge.c73
-rw-r--r--drivers/net/myri_sbus.c2
-rw-r--r--drivers/net/natsemi.c2
-rw-r--r--drivers/net/netx-eth.c2
-rw-r--r--drivers/net/netxen/netxen_nic.h365
-rw-r--r--drivers/net/netxen/netxen_nic_ctx.c8
-rw-r--r--drivers/net/netxen/netxen_nic_ethtool.c81
-rw-r--r--drivers/net/netxen/netxen_nic_hdr.h2
-rw-r--r--drivers/net/netxen/netxen_nic_hw.c55
-rw-r--r--drivers/net/netxen/netxen_nic_init.c254
-rw-r--r--drivers/net/netxen/netxen_nic_main.c584
-rw-r--r--drivers/net/ni5010.c2
-rw-r--r--drivers/net/ni52.c4
-rw-r--r--drivers/net/ni65.c2
-rw-r--r--drivers/net/niu.c2
-rw-r--r--drivers/net/pci-skeleton.c2
-rw-r--r--drivers/net/pcmcia/3c574_cs.c2
-rw-r--r--drivers/net/pcmcia/3c589_cs.c2
-rw-r--r--drivers/net/pcmcia/axnet_cs.c4
-rw-r--r--drivers/net/pcmcia/fmvj18x_cs.c4
-rw-r--r--drivers/net/pcmcia/nmclan_cs.c2
-rw-r--r--drivers/net/pcmcia/smc91c92_cs.c6
-rw-r--r--drivers/net/pcmcia/xirc2ps_cs.c4
-rw-r--r--drivers/net/pcnet32.c2
-rw-r--r--drivers/net/phy/Kconfig6
-rw-r--r--drivers/net/phy/Makefile1
-rw-r--r--drivers/net/phy/bcm63xx.c132
-rw-r--r--drivers/net/plip.c2
-rw-r--r--drivers/net/ppp_generic.c4
-rw-r--r--drivers/net/pppoe.c22
-rw-r--r--drivers/net/qlge/qlge_main.c5
-rw-r--r--drivers/net/r6040.c4
-rw-r--r--drivers/net/r8169.c245
-rw-r--r--drivers/net/rionet.c7
-rw-r--r--drivers/net/rrunner.c2
-rw-r--r--drivers/net/s2io.c13
-rw-r--r--drivers/net/sb1000.c2
-rw-r--r--drivers/net/sb1250-mac.c4
-rw-r--r--drivers/net/seeq8005.c4
-rw-r--r--drivers/net/sgiseeq.c6
-rw-r--r--drivers/net/sh_eth.c2
-rw-r--r--drivers/net/sis900.c2
-rw-r--r--drivers/net/skfp/skfddi.c4
-rw-r--r--drivers/net/sky2.c272
-rw-r--r--drivers/net/sky2.h16
-rw-r--r--drivers/net/slip.c6
-rw-r--r--drivers/net/smc911x.c6
-rw-r--r--drivers/net/smc911x.h1
-rw-r--r--drivers/net/smc9194.c8
-rw-r--r--drivers/net/smc91x.c4
-rw-r--r--drivers/net/smsc911x.c31
-rw-r--r--drivers/net/sonic.c4
-rw-r--r--drivers/net/starfire.c2
-rw-r--r--drivers/net/sun3_82586.c4
-rw-r--r--drivers/net/sun3lance.c4
-rw-r--r--drivers/net/sunbmac.c2
-rw-r--r--drivers/net/sundance.c2
-rw-r--r--drivers/net/sunhme.c2
-rw-r--r--drivers/net/sunlance.c2
-rw-r--r--drivers/net/sunqe.c2
-rw-r--r--drivers/net/tc35815.c79
-rw-r--r--drivers/net/tlan.c6
-rw-r--r--drivers/net/tokenring/3c359.c2
-rw-r--r--drivers/net/tokenring/ibmtr.c2
-rw-r--r--drivers/net/tokenring/lanstreamer.c2
-rw-r--r--drivers/net/tokenring/olympic.c2
-rw-r--r--drivers/net/tokenring/smctr.c38
-rw-r--r--drivers/net/tokenring/tms380tr.c2
-rw-r--r--drivers/net/tulip/de2104x.c2
-rw-r--r--drivers/net/tulip/dmfe.c4
-rw-r--r--drivers/net/tulip/tulip_core.c2
-rw-r--r--drivers/net/tulip/uli526x.c4
-rw-r--r--drivers/net/tulip/winbond-840.c2
-rw-r--r--drivers/net/tulip/xircom_cb.c2
-rw-r--r--drivers/net/tun.c18
-rw-r--r--drivers/net/typhoon.c2
-rw-r--r--drivers/net/ucc_geth.c42
-rw-r--r--drivers/net/ucc_geth.h2
-rw-r--r--drivers/net/usb/catc.c2
-rw-r--r--drivers/net/usb/hso.c2
-rw-r--r--drivers/net/usb/kaweth.c4
-rw-r--r--drivers/net/usb/pegasus.c2
-rw-r--r--drivers/net/usb/rndis_host.c50
-rw-r--r--drivers/net/usb/rtl8150.c2
-rw-r--r--drivers/net/usb/smsc95xx.c5
-rw-r--r--drivers/net/usb/usbnet.c88
-rw-r--r--drivers/net/veth.c7
-rw-r--r--drivers/net/via-rhine.c6
-rw-r--r--drivers/net/via-velocity.c3431
-rw-r--r--drivers/net/via-velocity.h6
-rw-r--r--drivers/net/virtio_net.c3
-rw-r--r--drivers/net/vxge/vxge-config.c10
-rw-r--r--drivers/net/vxge/vxge-config.h17
-rw-r--r--drivers/net/vxge/vxge-main.c169
-rw-r--r--drivers/net/vxge/vxge-main.h8
-rw-r--r--drivers/net/vxge/vxge-reg.h9
-rw-r--r--drivers/net/vxge/vxge-traffic.c12
-rw-r--r--drivers/net/vxge/vxge-traffic.h4
-rw-r--r--drivers/net/vxge/vxge-version.h4
-rw-r--r--drivers/net/wan/cycx_x25.c2
-rw-r--r--drivers/net/wan/dlci.c4
-rw-r--r--drivers/net/wan/dscc4.c2
-rw-r--r--drivers/net/wan/farsync.c27
-rw-r--r--drivers/net/wan/hdlc_fr.c6
-rw-r--r--drivers/net/wan/lmc/lmc_main.c9
-rw-r--r--drivers/net/wan/sbni.c4
-rw-r--r--drivers/net/wan/wanxl.c2
-rw-r--r--drivers/net/wan/x25_asy.c10
-rw-r--r--drivers/net/wimax/i2400m/sdio.c12
-rw-r--r--drivers/net/wireless/Kconfig10
-rw-r--r--drivers/net/wireless/adm8211.c20
-rw-r--r--drivers/net/wireless/airo.c14
-rw-r--r--drivers/net/wireless/arlan-main.c4
-rw-r--r--drivers/net/wireless/at76c50x-usb.c21
-rw-r--r--drivers/net/wireless/ath/Kconfig19
-rw-r--r--drivers/net/wireless/ath/ar9170/Kconfig4
-rw-r--r--drivers/net/wireless/ath/ar9170/ar9170.h52
-rw-r--r--drivers/net/wireless/ath/ar9170/led.c11
-rw-r--r--drivers/net/wireless/ath/ar9170/main.c644
-rw-r--r--drivers/net/wireless/ath/ar9170/usb.c2
-rw-r--r--drivers/net/wireless/ath/ath.h30
-rw-r--r--drivers/net/wireless/ath/ath5k/Kconfig3
-rw-r--r--drivers/net/wireless/ath/ath5k/ath5k.h38
-rw-r--r--drivers/net/wireless/ath/ath5k/attach.c63
-rw-r--r--drivers/net/wireless/ath/ath5k/base.c276
-rw-r--r--drivers/net/wireless/ath/ath5k/base.h16
-rw-r--r--drivers/net/wireless/ath/ath5k/debug.c8
-rw-r--r--drivers/net/wireless/ath/ath5k/eeprom.c10
-rw-r--r--drivers/net/wireless/ath/ath5k/eeprom.h4
-rw-r--r--drivers/net/wireless/ath/ath5k/phy.c54
-rw-r--r--drivers/net/wireless/ath/ath5k/qcu.c3
-rw-r--r--drivers/net/wireless/ath/ath5k/reg.h12
-rw-r--r--drivers/net/wireless/ath/ath5k/reset.c156
-rw-r--r--drivers/net/wireless/ath/ath9k/Kconfig13
-rw-r--r--drivers/net/wireless/ath/ath9k/Makefile3
-rw-r--r--drivers/net/wireless/ath/ath9k/ahb.c2
-rw-r--r--drivers/net/wireless/ath/ath9k/ani.c201
-rw-r--r--drivers/net/wireless/ath/ath9k/ani.h5
-rw-r--r--drivers/net/wireless/ath/ath9k/ath9k.h67
-rw-r--r--drivers/net/wireless/ath/ath9k/beacon.c15
-rw-r--r--drivers/net/wireless/ath/ath9k/calib.c141
-rw-r--r--drivers/net/wireless/ath/ath9k/calib.h4
-rw-r--r--drivers/net/wireless/ath/ath9k/debug.c95
-rw-r--r--drivers/net/wireless/ath/ath9k/debug.h54
-rw-r--r--drivers/net/wireless/ath/ath9k/eeprom.c2582
-rw-r--r--drivers/net/wireless/ath/ath9k/eeprom.h284
-rw-r--r--drivers/net/wireless/ath/ath9k/eeprom_4k.c1186
-rw-r--r--drivers/net/wireless/ath/ath9k/eeprom_9287.c1183
-rw-r--r--drivers/net/wireless/ath/ath9k/eeprom_def.c1385
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.c550
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.h51
-rw-r--r--drivers/net/wireless/ath/ath9k/initvals.h2229
-rw-r--r--drivers/net/wireless/ath/ath9k/mac.c47
-rw-r--r--drivers/net/wireless/ath/ath9k/mac.h8
-rw-r--r--drivers/net/wireless/ath/ath9k/main.c222
-rw-r--r--drivers/net/wireless/ath/ath9k/pci.c8
-rw-r--r--drivers/net/wireless/ath/ath9k/phy.c65
-rw-r--r--drivers/net/wireless/ath/ath9k/phy.h25
-rw-r--r--drivers/net/wireless/ath/ath9k/rc.c616
-rw-r--r--drivers/net/wireless/ath/ath9k/rc.h29
-rw-r--r--drivers/net/wireless/ath/ath9k/recv.c140
-rw-r--r--drivers/net/wireless/ath/ath9k/reg.h130
-rw-r--r--drivers/net/wireless/ath/ath9k/virtual.c34
-rw-r--r--drivers/net/wireless/ath/ath9k/xmit.c186
-rw-r--r--drivers/net/wireless/ath/main.c36
-rw-r--r--drivers/net/wireless/ath/regd.c2
-rw-r--r--drivers/net/wireless/ath/regd_common.h2
-rw-r--r--drivers/net/wireless/atmel.c6
-rw-r--r--drivers/net/wireless/b43/b43.h22
-rw-r--r--drivers/net/wireless/b43/dma.c21
-rw-r--r--drivers/net/wireless/b43/main.c250
-rw-r--r--drivers/net/wireless/b43/phy_common.c9
-rw-r--r--drivers/net/wireless/b43/phy_common.h5
-rw-r--r--drivers/net/wireless/b43/phy_lp.c860
-rw-r--r--drivers/net/wireless/b43/phy_lp.h30
-rw-r--r--drivers/net/wireless/b43/phy_n.c3
-rw-r--r--drivers/net/wireless/b43/pio.c2
-rw-r--r--drivers/net/wireless/b43/tables_lpphy.c2151
-rw-r--r--drivers/net/wireless/b43/tables_lpphy.h13
-rw-r--r--drivers/net/wireless/b43/xmit.c7
-rw-r--r--drivers/net/wireless/b43legacy/dma.c22
-rw-r--r--drivers/net/wireless/b43legacy/main.c8
-rw-r--r--drivers/net/wireless/b43legacy/xmit.c3
-rw-r--r--drivers/net/wireless/hostap/hostap_80211_tx.c42
-rw-r--r--drivers/net/wireless/hostap/hostap_cs.c3
-rw-r--r--drivers/net/wireless/ipw2x00/ipw2200.c13
-rw-r--r--drivers/net/wireless/ipw2x00/libipw_tx.c4
-rw-r--r--drivers/net/wireless/iwlwifi/Kconfig3
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-1000.c91
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-3945-hw.h9
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-3945-led.c11
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-3945-rs.c24
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-3945.c83
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-3945.h12
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-4965-hw.h6
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-4965.c93
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-5000.c140
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-6000.c110
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-rs.c168
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.c318
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-calib.c13
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-commands.h40
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.c806
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.h80
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-csr.h10
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-debug.h36
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-debugfs.c1105
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-dev.h269
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-eeprom.c60
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-eeprom.h34
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-hcmd.c65
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-helpers.h21
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-led.c40
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-power.c802
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-power.h115
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-prph.h5
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-rx.c27
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-scan.c39
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-sta.c60
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-tx.c129
-rw-r--r--drivers/net/wireless/iwlwifi/iwl3945-base.c270
-rw-r--r--drivers/net/wireless/iwmc3200wifi/Kconfig1
-rw-r--r--drivers/net/wireless/iwmc3200wifi/Makefile2
-rw-r--r--drivers/net/wireless/iwmc3200wifi/cfg80211.c378
-rw-r--r--drivers/net/wireless/iwmc3200wifi/commands.c195
-rw-r--r--drivers/net/wireless/iwmc3200wifi/commands.h7
-rw-r--r--drivers/net/wireless/iwmc3200wifi/eeprom.c4
-rw-r--r--drivers/net/wireless/iwmc3200wifi/fw.c21
-rw-r--r--drivers/net/wireless/iwmc3200wifi/hal.c16
-rw-r--r--drivers/net/wireless/iwmc3200wifi/iwm.h39
-rw-r--r--drivers/net/wireless/iwmc3200wifi/lmac.h4
-rw-r--r--drivers/net/wireless/iwmc3200wifi/main.c45
-rw-r--r--drivers/net/wireless/iwmc3200wifi/netdev.c28
-rw-r--r--drivers/net/wireless/iwmc3200wifi/rx.c132
-rw-r--r--drivers/net/wireless/iwmc3200wifi/sdio.c10
-rw-r--r--drivers/net/wireless/iwmc3200wifi/sdio.h3
-rw-r--r--drivers/net/wireless/iwmc3200wifi/umac.h8
-rw-r--r--drivers/net/wireless/iwmc3200wifi/wext.c723
-rw-r--r--drivers/net/wireless/libertas/assoc.c16
-rw-r--r--drivers/net/wireless/libertas/dev.h1
-rw-r--r--drivers/net/wireless/libertas/if_cs.c3
-rw-r--r--drivers/net/wireless/libertas/if_sdio.c5
-rw-r--r--drivers/net/wireless/libertas/if_spi.c10
-rw-r--r--drivers/net/wireless/libertas/if_usb.c3
-rw-r--r--drivers/net/wireless/libertas/main.c3
-rw-r--r--drivers/net/wireless/libertas/wext.c4
-rw-r--r--drivers/net/wireless/libertas_tf/main.c3
-rw-r--r--drivers/net/wireless/mac80211_hwsim.c91
-rw-r--r--drivers/net/wireless/mwl8k.c9
-rw-r--r--drivers/net/wireless/netwave_cs.c2
-rw-r--r--drivers/net/wireless/orinoco/Kconfig1
-rw-r--r--drivers/net/wireless/orinoco/Makefile2
-rw-r--r--drivers/net/wireless/orinoco/airport.c98
-rw-r--r--drivers/net/wireless/orinoco/cfg.c203
-rw-r--r--drivers/net/wireless/orinoco/cfg.h15
-rw-r--r--drivers/net/wireless/orinoco/fw.c41
-rw-r--r--drivers/net/wireless/orinoco/hermes.c2
-rw-r--r--drivers/net/wireless/orinoco/hermes.h2
-rw-r--r--drivers/net/wireless/orinoco/hermes_dld.c50
-rw-r--r--drivers/net/wireless/orinoco/hw.c786
-rw-r--r--drivers/net/wireless/orinoco/hw.h16
-rw-r--r--drivers/net/wireless/orinoco/main.c1167
-rw-r--r--drivers/net/wireless/orinoco/main.h3
-rw-r--r--drivers/net/wireless/orinoco/orinoco.h65
-rw-r--r--drivers/net/wireless/orinoco/orinoco_cs.c96
-rw-r--r--drivers/net/wireless/orinoco/orinoco_nortel.c38
-rw-r--r--drivers/net/wireless/orinoco/orinoco_pci.c38
-rw-r--r--drivers/net/wireless/orinoco/orinoco_pci.h57
-rw-r--r--drivers/net/wireless/orinoco/orinoco_plx.c38
-rw-r--r--drivers/net/wireless/orinoco/orinoco_tmd.c38
-rw-r--r--drivers/net/wireless/orinoco/scan.c291
-rw-r--r--drivers/net/wireless/orinoco/scan.h21
-rw-r--r--drivers/net/wireless/orinoco/spectrum_cs.c96
-rw-r--r--drivers/net/wireless/orinoco/wext.c1051
-rw-r--r--drivers/net/wireless/p54/Makefile3
-rw-r--r--drivers/net/wireless/p54/eeprom.c753
-rw-r--r--drivers/net/wireless/p54/eeprom.h226
-rw-r--r--drivers/net/wireless/p54/fwio.c716
-rw-r--r--drivers/net/wireless/p54/led.c162
-rw-r--r--drivers/net/wireless/p54/lmac.h558
-rw-r--r--drivers/net/wireless/p54/main.c642
-rw-r--r--drivers/net/wireless/p54/p54.h151
-rw-r--r--drivers/net/wireless/p54/p54common.c2688
-rw-r--r--drivers/net/wireless/p54/p54common.h644
-rw-r--r--drivers/net/wireless/p54/p54pci.c9
-rw-r--r--drivers/net/wireless/p54/p54spi.c54
-rw-r--r--drivers/net/wireless/p54/p54usb.c42
-rw-r--r--drivers/net/wireless/p54/txrx.c866
-rw-r--r--drivers/net/wireless/prism54/islpci_eth.c2
-rw-r--r--drivers/net/wireless/prism54/islpci_hotplug.c4
-rw-r--r--drivers/net/wireless/ray_cs.c9
-rw-r--r--drivers/net/wireless/rndis_wlan.c926
-rw-r--r--drivers/net/wireless/rt2x00/Kconfig16
-rw-r--r--drivers/net/wireless/rt2x00/Makefile1
-rw-r--r--drivers/net/wireless/rt2x00/rt2400pci.c10
-rw-r--r--drivers/net/wireless/rt2x00/rt2400pci.h2
-rw-r--r--drivers/net/wireless/rt2x00/rt2500pci.c10
-rw-r--r--drivers/net/wireless/rt2x00/rt2500pci.h2
-rw-r--r--drivers/net/wireless/rt2x00/rt2500usb.c23
-rw-r--r--drivers/net/wireless/rt2x00/rt2500usb.h2
-rw-r--r--drivers/net/wireless/rt2x00/rt2800usb.c27
-rw-r--r--drivers/net/wireless/rt2x00/rt2800usb.h2
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00.h51
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00config.c24
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00crypto.c8
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00dev.c30
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00lib.h23
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00link.c168
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00mac.c100
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00queue.c30
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00queue.h10
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00reg.h4
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00rfkill.c127
-rw-r--r--drivers/net/wireless/rt2x00/rt61pci.c25
-rw-r--r--drivers/net/wireless/rt2x00/rt61pci.h2
-rw-r--r--drivers/net/wireless/rt2x00/rt73usb.c18
-rw-r--r--drivers/net/wireless/rt2x00/rt73usb.h4
-rw-r--r--drivers/net/wireless/rtl818x/rtl8180_dev.c5
-rw-r--r--drivers/net/wireless/rtl818x/rtl8187_dev.c5
-rw-r--r--drivers/net/wireless/rtl818x/rtl8187_leds.c10
-rw-r--r--drivers/net/wireless/rtl818x/rtl818x.h14
-rw-r--r--drivers/net/wireless/strip.c11
-rw-r--r--drivers/net/wireless/wavelan.c2
-rw-r--r--drivers/net/wireless/wavelan_cs.c4
-rw-r--r--drivers/net/wireless/wl12xx/Kconfig51
-rw-r--r--drivers/net/wireless/wl12xx/Makefile18
-rw-r--r--drivers/net/wireless/wl12xx/acx.c689
-rw-r--r--drivers/net/wireless/wl12xx/boot.c295
-rw-r--r--drivers/net/wireless/wl12xx/cmd.c353
-rw-r--r--drivers/net/wireless/wl12xx/init.c200
-rw-r--r--drivers/net/wireless/wl12xx/wl1251.c709
-rw-r--r--drivers/net/wireless/wl12xx/wl1251.h467
-rw-r--r--drivers/net/wireless/wl12xx/wl1251_acx.c918
-rw-r--r--drivers/net/wireless/wl12xx/wl1251_acx.h (renamed from drivers/net/wireless/wl12xx/acx.h)345
-rw-r--r--drivers/net/wireless/wl12xx/wl1251_boot.c527
-rw-r--r--drivers/net/wireless/wl12xx/wl1251_boot.h (renamed from drivers/net/wireless/wl12xx/boot.h)13
-rw-r--r--drivers/net/wireless/wl12xx/wl1251_cmd.c412
-rw-r--r--drivers/net/wireless/wl12xx/wl1251_cmd.h (renamed from drivers/net/wireless/wl12xx/cmd.h)196
-rw-r--r--drivers/net/wireless/wl12xx/wl1251_debugfs.c (renamed from drivers/net/wireless/wl12xx/debugfs.c)60
-rw-r--r--drivers/net/wireless/wl12xx/wl1251_debugfs.h (renamed from drivers/net/wireless/wl12xx/debugfs.h)16
-rw-r--r--drivers/net/wireless/wl12xx/wl1251_event.c (renamed from drivers/net/wireless/wl12xx/event.c)57
-rw-r--r--drivers/net/wireless/wl12xx/wl1251_event.h (renamed from drivers/net/wireless/wl12xx/event.h)12
-rw-r--r--drivers/net/wireless/wl12xx/wl1251_init.c413
-rw-r--r--drivers/net/wireless/wl12xx/wl1251_init.h41
-rw-r--r--drivers/net/wireless/wl12xx/wl1251_io.c196
-rw-r--r--drivers/net/wireless/wl12xx/wl1251_io.h64
-rw-r--r--drivers/net/wireless/wl12xx/wl1251_main.c (renamed from drivers/net/wireless/wl12xx/main.c)886
-rw-r--r--drivers/net/wireless/wl12xx/wl1251_netlink.h (renamed from drivers/net/wireless/wl12xx/init.h)22
-rw-r--r--drivers/net/wireless/wl12xx/wl1251_ps.c (renamed from drivers/net/wireless/wl12xx/ps.c)80
-rw-r--r--drivers/net/wireless/wl12xx/wl1251_ps.h (renamed from drivers/net/wireless/wl12xx/ps.h)18
-rw-r--r--drivers/net/wireless/wl12xx/wl1251_reg.h644
-rw-r--r--drivers/net/wireless/wl12xx/wl1251_rx.c (renamed from drivers/net/wireless/wl12xx/rx.c)93
-rw-r--r--drivers/net/wireless/wl12xx/wl1251_rx.h (renamed from drivers/net/wireless/wl12xx/rx.h)24
-rw-r--r--drivers/net/wireless/wl12xx/wl1251_sdio.c205
-rw-r--r--drivers/net/wireless/wl12xx/wl1251_spi.c344
-rw-r--r--drivers/net/wireless/wl12xx/wl1251_spi.h61
-rw-r--r--drivers/net/wireless/wl12xx/wl1251_tx.c (renamed from drivers/net/wireless/wl12xx/tx.c)174
-rw-r--r--drivers/net/wireless/wl12xx/wl1251_tx.h (renamed from drivers/net/wireless/wl12xx/tx.h)21
-rw-r--r--drivers/net/wireless/wl12xx/wl1271.h (renamed from drivers/net/wireless/wl12xx/wl12xx.h)210
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_acx.c961
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_acx.h1221
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_boot.c541
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_boot.h72
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_cmd.c813
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_cmd.h464
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_debugfs.c518
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_debugfs.h33
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_event.c125
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_event.h110
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_init.c397
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_init.h115
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_main.c1397
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_ps.c142
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_ps.h35
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_reg.h (renamed from drivers/net/wireless/wl12xx/reg.h)223
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_rx.c200
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_rx.h121
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_spi.c (renamed from drivers/net/wireless/wl12xx/spi.c)194
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_spi.h (renamed from drivers/net/wireless/wl12xx/spi.h)68
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_tx.c378
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_tx.h130
-rw-r--r--drivers/net/wireless/wl3501_cs.c3
-rw-r--r--drivers/net/wireless/zd1201.c4
-rw-r--r--drivers/net/wireless/zd1211rw/zd_chip.c6
-rw-r--r--drivers/net/wireless/zd1211rw/zd_chip.h6
-rw-r--r--drivers/net/wireless/zd1211rw/zd_mac.c7
-rw-r--r--drivers/net/wireless/zd1211rw/zd_usb.c74
-rw-r--r--drivers/net/xen-netfront.c4
-rw-r--r--drivers/net/xtsonic.c2
-rw-r--r--drivers/net/yellowfin.c4
-rw-r--r--drivers/net/znet.c4
-rw-r--r--drivers/s390/net/claw.c2
-rw-r--r--drivers/s390/net/ctcm_main.c10
-rw-r--r--drivers/s390/net/lcs.c8
-rw-r--r--drivers/s390/net/netiucv.c6
-rw-r--r--drivers/s390/net/qeth_l2_main.c1
-rw-r--r--drivers/s390/net/qeth_l3_main.c1
-rw-r--r--drivers/ssb/pci.c53
-rw-r--r--drivers/staging/agnx/xmit.c3
-rw-r--r--drivers/staging/at76_usb/at76_usb.c8
-rw-r--r--drivers/staging/dst/dcore.c3
-rw-r--r--drivers/staging/epl/VirtualEthernetLinux.c2
-rw-r--r--drivers/staging/otus/usbdrv.c8
-rw-r--r--drivers/staging/otus/wrap_pkt.c3
-rw-r--r--drivers/staging/rt2860/rt_main_dev.c6
-rw-r--r--drivers/staging/rtl8187se/ieee80211/ieee80211_tx.c4
-rw-r--r--drivers/staging/rtl8187se/r8180_core.c4
-rw-r--r--drivers/staging/slicoss/slicoss.c2
-rw-r--r--drivers/staging/stlc45xx/stlc45xx.c3
-rw-r--r--drivers/staging/winbond/wb35rx.c3
-rw-r--r--drivers/staging/wlan-ng/p80211netdev.c2
-rw-r--r--drivers/usb/gadget/f_phonet.c93
-rw-r--r--drivers/usb/gadget/u_ether.c6
-rw-r--r--drivers/video/uvesafb.c3
-rw-r--r--drivers/w1/w1_netlink.c3
-rw-r--r--firmware/Makefile7
-rw-r--r--firmware/WHENCE17
-rw-r--r--firmware/bnx2x-e1-4.8.53.0.fw.ihex10364
-rw-r--r--firmware/bnx2x-e1-5.0.21.0.fw.ihex10184
-rw-r--r--firmware/bnx2x-e1h-4.8.53.0.fw.ihex12028
-rw-r--r--firmware/bnx2x-e1h-5.0.21.0.fw.ihex12855
-rw-r--r--firmware/cxgb3/ael2005_opt_edc.bin.ihex69
-rw-r--r--firmware/cxgb3/ael2005_twx_edc.bin.ihex93
-rw-r--r--firmware/cxgb3/ael2020_twx_edc.bin.ihex100
-rw-r--r--fs/dlm/netlink.c2
-rw-r--r--include/asm-generic/socket.h3
-rw-r--r--include/linux/connector.h6
-rw-r--r--include/linux/ethtool.h1
-rw-r--r--include/linux/icmpv6.h2
-rw-r--r--include/linux/ieee80211.h29
-rw-r--r--include/linux/if_ether.h4
-rw-r--r--include/linux/if_tun.h1
-rw-r--r--include/linux/isdn/hdlc.h82
-rw-r--r--include/linux/mISDNhw.h1
-rw-r--r--include/linux/mISDNif.h16
-rw-r--r--include/linux/mmc/sdio_ids.h6
-rw-r--r--include/linux/net_dropmon.h1
-rw-r--r--include/linux/netdevice.h4
-rw-r--r--include/linux/nl80211.h174
-rw-r--r--include/linux/nl802154.h4
-rw-r--r--include/linux/pci_ids.h2
-rw-r--r--include/linux/rfkill.h15
-rw-r--r--include/linux/skbuff.h6
-rw-r--r--include/linux/ssb/ssb.h44
-rw-r--r--include/linux/ssb/ssb_regs.h66
-rw-r--r--include/linux/tipc.h2
-rw-r--r--include/linux/usb/rndis_host.h13
-rw-r--r--include/linux/usb/usbnet.h15
-rw-r--r--include/linux/wireless.h8
-rw-r--r--include/net/af_ieee802154.h (renamed from include/net/ieee802154/af_ieee802154.h)6
-rw-r--r--include/net/cfg80211.h568
-rw-r--r--include/net/genetlink.h66
-rw-r--r--include/net/ieee802154.h (renamed from include/net/ieee802154/mac_def.h)4
-rw-r--r--include/net/ieee802154/nl802154.h41
-rw-r--r--include/net/ieee802154_netdev.h (renamed from include/net/ieee802154/netdevice.h)0
-rw-r--r--include/net/ip6_fib.h6
-rw-r--r--include/net/ip_vs.h119
-rw-r--r--include/net/ipv6.h12
-rw-r--r--include/net/irda/ircomm_event.h2
-rw-r--r--include/net/irda/ircomm_tty_attach.h4
-rw-r--r--include/net/irda/irlap_event.h2
-rw-r--r--include/net/irda/irlmp_event.h4
-rw-r--r--include/net/iw_handler.h2
-rw-r--r--include/net/mac80211.h162
-rw-r--r--include/net/neighbour.h4
-rw-r--r--include/net/net_namespace.h26
-rw-r--r--include/net/netns/x_tables.h3
-rw-r--r--include/net/nl802154.h126
-rw-r--r--include/net/phonet/pn_dev.h2
-rw-r--r--include/net/pkt_sched.h3
-rw-r--r--include/net/sch_generic.h15
-rw-r--r--include/net/scm.h2
-rw-r--r--include/net/sctp/constants.h4
-rw-r--r--include/net/udp.h3
-rw-r--r--include/net/xfrm.h2
-rw-r--r--include/trace/events/skb.h20
-rw-r--r--kernel/taskstats.c10
-rw-r--r--kernel/trace/Kconfig10
-rw-r--r--kernel/trace/Makefile1
-rw-r--r--kernel/trace/trace.h19
-rw-r--r--kernel/trace/trace_skb_sources.c154
-rw-r--r--net/8021q/vlan.c19
-rw-r--r--net/8021q/vlanproc.c2
-rw-r--r--net/Kconfig20
-rw-r--r--net/Makefile1
-rw-r--r--net/appletalk/ddp.c25
-rw-r--r--net/atm/br2684.c4
-rw-r--r--net/atm/clip.c12
-rw-r--r--net/atm/lec.c17
-rw-r--r--net/atm/mpc.c2
-rw-r--r--net/atm/proc.c9
-rw-r--r--net/bluetooth/af_bluetooth.c4
-rw-r--r--net/bluetooth/bnep/netdev.c6
-rw-r--r--net/bridge/br_device.c2
-rw-r--r--net/bridge/br_forward.c3
-rw-r--r--net/bridge/br_if.c1
-rw-r--r--net/bridge/br_netfilter.c96
-rw-r--r--net/bridge/br_private.h3
-rw-r--r--net/bridge/br_stp.c2
-rw-r--r--net/bridge/br_sysfs_if.c17
-rw-r--r--net/compat.c17
-rw-r--r--net/core/datagram.c3
-rw-r--r--net/core/dev.c59
-rw-r--r--net/core/ethtool.c16
-rw-r--r--net/core/neighbour.c95
-rw-r--r--net/core/net-sysfs.c2
-rw-r--r--net/core/net_namespace.c35
-rw-r--r--net/core/netpoll.c6
-rw-r--r--net/core/rtnetlink.c21
-rw-r--r--net/core/skbuff.c3
-rw-r--r--net/core/sock.c16
-rw-r--r--net/dccp/ccids/ccid3.c4
-rw-r--r--net/dccp/feat.c7
-rw-r--r--net/dccp/proto.c4
-rw-r--r--net/decnet/dn_route.c2
-rw-r--r--net/econet/af_econet.c4
-rw-r--r--net/ieee802154/af_ieee802154.c4
-rw-r--r--net/ieee802154/dgram.c78
-rw-r--r--net/ieee802154/netlink.c144
-rw-r--r--net/ieee802154/nl_policy.c3
-rw-r--r--net/ieee802154/raw.c2
-rw-r--r--net/ipv4/af_inet.c12
-rw-r--r--net/ipv4/fib_trie.c52
-rw-r--r--net/ipv4/ip_gre.c6
-rw-r--r--net/ipv4/ipip.c6
-rw-r--r--net/ipv4/ipmr.c2
-rw-r--r--net/ipv4/route.c2
-rw-r--r--net/ipv4/tcp_output.c58
-rw-r--r--net/ipv4/udp.c144
-rw-r--r--net/ipv4/xfrm4_policy.c37
-rw-r--r--net/ipv6/af_inet6.c20
-rw-r--r--net/ipv6/icmp.c17
-rw-r--r--net/ipv6/ip6_fib.c16
-rw-r--r--net/ipv6/ip6_input.c6
-rw-r--r--net/ipv6/ip6_output.c41
-rw-r--r--net/ipv6/ip6_tunnel.c4
-rw-r--r--net/ipv6/ip6mr.c2
-rw-r--r--net/ipv6/ipv6_sockglue.c5
-rw-r--r--net/ipv6/mcast.c1
-rw-r--r--net/ipv6/ndisc.c4
-rw-r--r--net/ipv6/proc.c4
-rw-r--r--net/ipv6/raw.c5
-rw-r--r--net/ipv6/sit.c6
-rw-r--r--net/ipv6/sysctl_net_ipv6.c4
-rw-r--r--net/ipv6/udp.c146
-rw-r--r--net/ipv6/xfrm6_policy.c38
-rw-r--r--net/irda/ircomm/ircomm_event.c4
-rw-r--r--net/irda/ircomm/ircomm_tty_attach.c4
-rw-r--r--net/irda/iriap.c4
-rw-r--r--net/irda/irlan/irlan_common.c4
-rw-r--r--net/irda/irlan/irlan_eth.c4
-rw-r--r--net/irda/irlap.c2
-rw-r--r--net/irda/irlap_event.c4
-rw-r--r--net/irda/irlmp_event.c6
-rw-r--r--net/irda/irnetlink.c2
-rw-r--r--net/lapb/lapb_iface.c2
-rw-r--r--net/llc/llc_proc.c2
-rw-r--r--net/mac80211/Kconfig37
-rw-r--r--net/mac80211/Makefile4
-rw-r--r--net/mac80211/agg-tx.c3
-rw-r--r--net/mac80211/cfg.c234
-rw-r--r--net/mac80211/debugfs.c2
-rw-r--r--net/mac80211/debugfs_netdev.c46
-rw-r--r--net/mac80211/debugfs_sta.c98
-rw-r--r--net/mac80211/driver-ops.h85
-rw-r--r--net/mac80211/driver-trace.c9
-rw-r--r--net/mac80211/driver-trace.h648
-rw-r--r--net/mac80211/event.c23
-rw-r--r--net/mac80211/ibss.c23
-rw-r--r--net/mac80211/ieee80211_i.h237
-rw-r--r--net/mac80211/iface.c139
-rw-r--r--net/mac80211/key.c28
-rw-r--r--net/mac80211/main.c182
-rw-r--r--net/mac80211/mesh.c158
-rw-r--r--net/mac80211/mesh.h33
-rw-r--r--net/mac80211/mesh_hwmp.c26
-rw-r--r--net/mac80211/mesh_pathtbl.c177
-rw-r--r--net/mac80211/mesh_plink.c2
-rw-r--r--net/mac80211/mlme.c1992
-rw-r--r--net/mac80211/pm.c8
-rw-r--r--net/mac80211/rate.c31
-rw-r--r--net/mac80211/rc80211_minstrel.c39
-rw-r--r--net/mac80211/rc80211_pid_algo.c12
-rw-r--r--net/mac80211/rx.c216
-rw-r--r--net/mac80211/scan.c368
-rw-r--r--net/mac80211/sta_info.c2
-rw-r--r--net/mac80211/sta_info.h30
-rw-r--r--net/mac80211/tx.c572
-rw-r--r--net/mac80211/util.c122
-rw-r--r--net/mac80211/wep.c52
-rw-r--r--net/mac80211/wep.h7
-rw-r--r--net/mac80211/wext.c633
-rw-r--r--net/mac80211/wme.c6
-rw-r--r--net/mac80211/wme.h3
-rw-r--r--net/mac80211/wpa.c3
-rw-r--r--net/netfilter/ipvs/ip_vs_app.c19
-rw-r--r--net/netfilter/ipvs/ip_vs_conn.c17
-rw-r--r--net/netfilter/ipvs/ip_vs_core.c27
-rw-r--r--net/netfilter/ipvs/ip_vs_ctl.c67
-rw-r--r--net/netfilter/ipvs/ip_vs_dh.c7
-rw-r--r--net/netfilter/ipvs/ip_vs_est.c4
-rw-r--r--net/netfilter/ipvs/ip_vs_ftp.c7
-rw-r--r--net/netfilter/ipvs/ip_vs_lblc.c9
-rw-r--r--net/netfilter/ipvs/ip_vs_lblcr.c17
-rw-r--r--net/netfilter/ipvs/ip_vs_lc.c5
-rw-r--r--net/netfilter/ipvs/ip_vs_nq.c5
-rw-r--r--net/netfilter/ipvs/ip_vs_proto.c12
-rw-r--r--net/netfilter/ipvs/ip_vs_proto_ah_esp.c7
-rw-r--r--net/netfilter/ipvs/ip_vs_proto_tcp.c7
-rw-r--r--net/netfilter/ipvs/ip_vs_proto_udp.c7
-rw-r--r--net/netfilter/ipvs/ip_vs_rr.c5
-rw-r--r--net/netfilter/ipvs/ip_vs_sched.c41
-rw-r--r--net/netfilter/ipvs/ip_vs_sed.c5
-rw-r--r--net/netfilter/ipvs/ip_vs_sh.c5
-rw-r--r--net/netfilter/ipvs/ip_vs_sync.c53
-rw-r--r--net/netfilter/ipvs/ip_vs_wlc.c3
-rw-r--r--net/netfilter/ipvs/ip_vs_wrr.c7
-rw-r--r--net/netfilter/ipvs/ip_vs_xmit.c43
-rw-r--r--net/netlabel/netlabel_kapi.c6
-rw-r--r--net/netlink/af_netlink.c72
-rw-r--r--net/netlink/genetlink.c186
-rw-r--r--net/netrom/nr_dev.c4
-rw-r--r--net/packet/af_packet.c246
-rw-r--r--net/phonet/datagram.c5
-rw-r--r--net/phonet/pep-gprs.c4
-rw-r--r--net/phonet/pep.c7
-rw-r--r--net/phonet/pn_dev.c8
-rw-r--r--net/phonet/socket.c97
-rw-r--r--net/rds/connection.c49
-rw-r--r--net/rds/ib.c6
-rw-r--r--net/rds/ib.h18
-rw-r--r--net/rds/ib_cm.c62
-rw-r--r--net/rds/ib_rdma.c12
-rw-r--r--net/rds/ib_recv.c53
-rw-r--r--net/rds/ib_stats.c2
-rw-r--r--net/rds/ib_sysctl.c12
-rw-r--r--net/rds/iw.c15
-rw-r--r--net/rds/iw.h1
-rw-r--r--net/rds/iw_rdma.c28
-rw-r--r--net/rds/iw_send.c2
-rw-r--r--net/rds/iw_stats.c2
-rw-r--r--net/rds/rdma_transport.c10
-rw-r--r--net/rds/rds.h3
-rw-r--r--net/rds/recv.c24
-rw-r--r--net/rds/stats.c4
-rw-r--r--net/rfkill/core.c14
-rw-r--r--net/rose/rose_dev.c2
-rw-r--r--net/rxrpc/ar-ack.c2
-rw-r--r--net/sched/sch_generic.c93
-rw-r--r--net/sched/sch_teql.c6
-rw-r--r--net/sctp/debug.c14
-rw-r--r--net/tipc/netlink.c2
-rw-r--r--net/tipc/socket.c6
-rw-r--r--net/wireless/Kconfig43
-rw-r--r--net/wireless/Makefile5
-rw-r--r--net/wireless/chan.c89
-rw-r--r--net/wireless/core.c481
-rw-r--r--net/wireless/core.h232
-rw-r--r--net/wireless/debugfs.c14
-rw-r--r--net/wireless/debugfs.h8
-rw-r--r--net/wireless/ibss.c290
-rw-r--r--net/wireless/mlme.c618
-rw-r--r--net/wireless/nl80211.c1716
-rw-r--r--net/wireless/nl80211.h71
-rw-r--r--net/wireless/reg.c169
-rw-r--r--net/wireless/reg.h15
-rw-r--r--net/wireless/scan.c99
-rw-r--r--net/wireless/sme.c932
-rw-r--r--net/wireless/util.c82
-rw-r--r--net/wireless/wext-compat.c865
-rw-r--r--net/wireless/wext-compat.h49
-rw-r--r--net/wireless/wext-sme.c404
-rw-r--r--net/wireless/wext.c257
931 files changed, 94363 insertions, 54656 deletions
diff --git a/Documentation/connector/Makefile b/Documentation/connector/Makefile
index 8df1a7285a0..d98e4df98e2 100644
--- a/Documentation/connector/Makefile
+++ b/Documentation/connector/Makefile
@@ -9,3 +9,8 @@ hostprogs-y := ucon
always := $(hostprogs-y)
HOSTCFLAGS_ucon.o += -I$(objtree)/usr/include
+
+all: modules
+
+modules clean:
+ $(MAKE) -C ../.. SUBDIRS=$(PWD) $@
diff --git a/Documentation/connector/cn_test.c b/Documentation/connector/cn_test.c
index 6a5be5d5c8e..1711adc3337 100644
--- a/Documentation/connector/cn_test.c
+++ b/Documentation/connector/cn_test.c
@@ -19,6 +19,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#define pr_fmt(fmt) "cn_test: " fmt
+
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
@@ -27,18 +29,17 @@
#include <linux/connector.h>
-static struct cb_id cn_test_id = { 0x123, 0x456 };
+static struct cb_id cn_test_id = { CN_NETLINK_USERS + 3, 0x456 };
static char cn_test_name[] = "cn_test";
static struct sock *nls;
static struct timer_list cn_test_timer;
-void cn_test_callback(void *data)
+static void cn_test_callback(struct cn_msg *msg)
{
- struct cn_msg *msg = (struct cn_msg *)data;
-
- printk("%s: %lu: idx=%x, val=%x, seq=%u, ack=%u, len=%d: %s.\n",
- __func__, jiffies, msg->id.idx, msg->id.val,
- msg->seq, msg->ack, msg->len, (char *)msg->data);
+ pr_info("%s: %lu: idx=%x, val=%x, seq=%u, ack=%u, len=%d: %s.\n",
+ __func__, jiffies, msg->id.idx, msg->id.val,
+ msg->seq, msg->ack, msg->len,
+ msg->len ? (char *)msg->data : "");
}
/*
@@ -63,9 +64,7 @@ static int cn_test_want_notify(void)
skb = alloc_skb(size, GFP_ATOMIC);
if (!skb) {
- printk(KERN_ERR "Failed to allocate new skb with size=%u.\n",
- size);
-
+ pr_err("failed to allocate new skb with size=%u\n", size);
return -ENOMEM;
}
@@ -114,12 +113,12 @@ static int cn_test_want_notify(void)
//netlink_broadcast(nls, skb, 0, ctl->group, GFP_ATOMIC);
netlink_unicast(nls, skb, 0, 0);
- printk(KERN_INFO "Request was sent. Group=0x%x.\n", ctl->group);
+ pr_info("request was sent: group=0x%x\n", ctl->group);
return 0;
nlmsg_failure:
- printk(KERN_ERR "Failed to send %u.%u\n", msg->seq, msg->ack);
+ pr_err("failed to send %u.%u\n", msg->seq, msg->ack);
kfree_skb(skb);
return -EINVAL;
}
@@ -131,6 +130,8 @@ static void cn_test_timer_func(unsigned long __data)
struct cn_msg *m;
char data[32];
+ pr_debug("%s: timer fired with data %lu\n", __func__, __data);
+
m = kzalloc(sizeof(*m) + sizeof(data), GFP_ATOMIC);
if (m) {
@@ -150,7 +151,7 @@ static void cn_test_timer_func(unsigned long __data)
cn_test_timer_counter++;
- mod_timer(&cn_test_timer, jiffies + HZ);
+ mod_timer(&cn_test_timer, jiffies + msecs_to_jiffies(1000));
}
static int cn_test_init(void)
@@ -168,8 +169,10 @@ static int cn_test_init(void)
}
setup_timer(&cn_test_timer, cn_test_timer_func, 0);
- cn_test_timer.expires = jiffies + HZ;
- add_timer(&cn_test_timer);
+ mod_timer(&cn_test_timer, jiffies + msecs_to_jiffies(1000));
+
+ pr_info("initialized with id={%u.%u}\n",
+ cn_test_id.idx, cn_test_id.val);
return 0;
diff --git a/Documentation/connector/connector.txt b/Documentation/connector/connector.txt
index ad6e0ba7b38..81e6bf6ead5 100644
--- a/Documentation/connector/connector.txt
+++ b/Documentation/connector/connector.txt
@@ -5,10 +5,10 @@ Kernel Connector.
Kernel connector - new netlink based userspace <-> kernel space easy
to use communication module.
-Connector driver adds possibility to connect various agents using
-netlink based network. One must register callback and
-identifier. When driver receives special netlink message with
-appropriate identifier, appropriate callback will be called.
+The Connector driver makes it easy to connect various agents using a
+netlink based network. One must register a callback and an identifier.
+When the driver receives a special netlink message with the appropriate
+identifier, the appropriate callback will be called.
From the userspace point of view it's quite straightforward:
@@ -17,10 +17,10 @@ From the userspace point of view it's quite straightforward:
send();
recv();
-But if kernelspace want to use full power of such connections, driver
-writer must create special sockets, must know about struct sk_buff
-handling... Connector allows any kernelspace agents to use netlink
-based networking for inter-process communication in a significantly
+But if kernelspace wants to use the full power of such connections, the
+driver writer must create special sockets, must know about struct sk_buff
+handling, etc... The Connector driver allows any kernelspace agents to use
+netlink based networking for inter-process communication in a significantly
easier way:
int cn_add_callback(struct cb_id *id, char *name, void (*callback) (void *));
@@ -32,15 +32,15 @@ struct cb_id
__u32 val;
};
-idx and val are unique identifiers which must be registered in
-connector.h for in-kernel usage. void (*callback) (void *) - is a
-callback function which will be called when message with above idx.val
-will be received by connector core. Argument for that function must
+idx and val are unique identifiers which must be registered in the
+connector.h header for in-kernel usage. void (*callback) (void *) is a
+callback function which will be called when a message with above idx.val
+is received by the connector core. The argument for that function must
be dereferenced to struct cn_msg *.
struct cn_msg
{
- struct cb_id id;
+ struct cb_id id;
__u32 seq;
__u32 ack;
@@ -55,92 +55,95 @@ Connector interfaces.
int cn_add_callback(struct cb_id *id, char *name, void (*callback) (void *));
-Registers new callback with connector core.
+ Registers new callback with connector core.
-struct cb_id *id - unique connector's user identifier.
- It must be registered in connector.h for legal in-kernel users.
-char *name - connector's callback symbolic name.
-void (*callback) (void *) - connector's callback.
+ struct cb_id *id - unique connector's user identifier.
+ It must be registered in connector.h for legal in-kernel users.
+ char *name - connector's callback symbolic name.
+ void (*callback) (void *) - connector's callback.
Argument must be dereferenced to struct cn_msg *.
+
void cn_del_callback(struct cb_id *id);
-Unregisters new callback with connector core.
+ Unregisters new callback with connector core.
+
+ struct cb_id *id - unique connector's user identifier.
-struct cb_id *id - unique connector's user identifier.
int cn_netlink_send(struct cn_msg *msg, u32 __groups, int gfp_mask);
-Sends message to the specified groups. It can be safely called from
-softirq context, but may silently fail under strong memory pressure.
-If there are no listeners for given group -ESRCH can be returned.
+ Sends message to the specified groups. It can be safely called from
+ softirq context, but may silently fail under strong memory pressure.
+ If there are no listeners for given group -ESRCH can be returned.
-struct cn_msg * - message header(with attached data).
-u32 __group - destination group.
+ struct cn_msg * - message header(with attached data).
+ u32 __group - destination group.
If __group is zero, then appropriate group will
be searched through all registered connector users,
and message will be delivered to the group which was
created for user with the same ID as in msg.
If __group is not zero, then message will be delivered
to the specified group.
-int gfp_mask - GFP mask.
+ int gfp_mask - GFP mask.
-Note: When registering new callback user, connector core assigns
-netlink group to the user which is equal to it's id.idx.
+ Note: When registering new callback user, connector core assigns
+ netlink group to the user which is equal to it's id.idx.
/*****************************************/
Protocol description.
/*****************************************/
-Current offers transport layer with fixed header. Recommended
-protocol which uses such header is following:
+The current framework offers a transport layer with fixed headers. The
+recommended protocol which uses such a header is as following:
msg->seq and msg->ack are used to determine message genealogy. When
-someone sends message it puts there locally unique sequence and random
-acknowledge numbers. Sequence number may be copied into
+someone sends a message, they use a locally unique sequence and random
+acknowledge number. The sequence number may be copied into
nlmsghdr->nlmsg_seq too.
-Sequence number is incremented with each message to be sent.
+The sequence number is incremented with each message sent.
-If we expect reply to our message, then sequence number in received
-message MUST be the same as in original message, and acknowledge
-number MUST be the same + 1.
+If you expect a reply to the message, then the sequence number in the
+received message MUST be the same as in the original message, and the
+acknowledge number MUST be the same + 1.
-If we receive message and it's sequence number is not equal to one we
-are expecting, then it is new message. If we receive message and it's
-sequence number is the same as one we are expecting, but it's
-acknowledge is not equal acknowledge number in original message + 1,
-then it is new message.
+If we receive a message and its sequence number is not equal to one we
+are expecting, then it is a new message. If we receive a message and
+its sequence number is the same as one we are expecting, but its
+acknowledge is not equal to the acknowledge number in the original
+message + 1, then it is a new message.
-Obviously, protocol header contains above id.
+Obviously, the protocol header contains the above id.
-connector allows event notification in the following form: kernel
+The connector allows event notification in the following form: kernel
driver or userspace process can ask connector to notify it when
-selected id's will be turned on or off(registered or unregistered it's
-callback). It is done by sending special command to connector
-driver(it also registers itself with id={-1, -1}).
+selected ids will be turned on or off (registered or unregistered its
+callback). It is done by sending a special command to the connector
+driver (it also registers itself with id={-1, -1}).
-As example of usage Documentation/connector now contains cn_test.c -
-testing module which uses connector to request notification and to
-send messages.
+As example of this usage can be found in the cn_test.c module which
+uses the connector to request notification and to send messages.
/*****************************************/
Reliability.
/*****************************************/
-Netlink itself is not reliable protocol, that means that messages can
+Netlink itself is not a reliable protocol. That means that messages can
be lost due to memory pressure or process' receiving queue overflowed,
-so caller is warned must be prepared. That is why struct cn_msg [main
-connector's message header] contains u32 seq and u32 ack fields.
+so caller is warned that it must be prepared. That is why the struct
+cn_msg [main connector's message header] contains u32 seq and u32 ack
+fields.
/*****************************************/
Userspace usage.
/*****************************************/
+
2.6.14 has a new netlink socket implementation, which by default does not
-allow to send data to netlink groups other than 1.
-So, if to use netlink socket (for example using connector)
-with different group number userspace application must subscribe to
-that group. It can be achieved by following pseudocode:
+allow people to send data to netlink groups other than 1.
+So, if you wish to use a netlink socket (for example using connector)
+with a different group number, the userspace application must subscribe to
+that group first. It can be achieved by the following pseudocode:
s = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR);
@@ -160,8 +163,8 @@ if (bind(s, (struct sockaddr *)&l_local, sizeof(struct sockaddr_nl)) == -1) {
}
Where 270 above is SOL_NETLINK, and 1 is a NETLINK_ADD_MEMBERSHIP socket
-option. To drop multicast subscription one should call above socket option
-with NETLINK_DROP_MEMBERSHIP parameter which is defined as 0.
+option. To drop a multicast subscription, one should call the above socket
+option with the NETLINK_DROP_MEMBERSHIP parameter which is defined as 0.
2.6.14 netlink code only allows to select a group which is less or equal to
the maximum group number, which is used at netlink_kernel_create() time.
diff --git a/Documentation/connector/ucon.c b/Documentation/connector/ucon.c
index c5092ad0ce4..4848db8c71f 100644
--- a/Documentation/connector/ucon.c
+++ b/Documentation/connector/ucon.c
@@ -30,18 +30,24 @@
#include <arpa/inet.h>
+#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <time.h>
+#include <getopt.h>
#include <linux/connector.h>
#define DEBUG
#define NETLINK_CONNECTOR 11
+/* Hopefully your userspace connector.h matches this kernel */
+#define CN_TEST_IDX CN_NETLINK_USERS + 3
+#define CN_TEST_VAL 0x456
+
#ifdef DEBUG
#define ulog(f, a...) fprintf(stdout, f, ##a)
#else
@@ -83,6 +89,25 @@ static int netlink_send(int s, struct cn_msg *msg)
return err;
}
+static void usage(void)
+{
+ printf(
+ "Usage: ucon [options] [output file]\n"
+ "\n"
+ "\t-h\tthis help screen\n"
+ "\t-s\tsend buffers to the test module\n"
+ "\n"
+ "The default behavior of ucon is to subscribe to the test module\n"
+ "and wait for state messages. Any ones received are dumped to the\n"
+ "specified output file (or stdout). The test module is assumed to\n"
+ "have an id of {%u.%u}\n"
+ "\n"
+ "If you get no output, then verify the cn_test module id matches\n"
+ "the expected id above.\n"
+ , CN_TEST_IDX, CN_TEST_VAL
+ );
+}
+
int main(int argc, char *argv[])
{
int s;
@@ -94,17 +119,34 @@ int main(int argc, char *argv[])
FILE *out;
time_t tm;
struct pollfd pfd;
+ bool send_msgs = false;
- if (argc < 2)
- out = stdout;
- else {
- out = fopen(argv[1], "a+");
+ while ((s = getopt(argc, argv, "hs")) != -1) {
+ switch (s) {
+ case 's':
+ send_msgs = true;
+ break;
+
+ case 'h':
+ usage();
+ return 0;
+
+ default:
+ /* getopt() outputs an error for us */
+ usage();
+ return 1;
+ }
+ }
+
+ if (argc != optind) {
+ out = fopen(argv[optind], "a+");
if (!out) {
ulog("Unable to open %s for writing: %s\n",
argv[1], strerror(errno));
out = stdout;
}
- }
+ } else
+ out = stdout;
memset(buf, 0, sizeof(buf));
@@ -115,9 +157,11 @@ int main(int argc, char *argv[])
}
l_local.nl_family = AF_NETLINK;
- l_local.nl_groups = 0x123; /* bitmask of requested groups */
+ l_local.nl_groups = -1; /* bitmask of requested groups */
l_local.nl_pid = 0;
+ ulog("subscribing to %u.%u\n", CN_TEST_IDX, CN_TEST_VAL);
+
if (bind(s, (struct sockaddr *)&l_local, sizeof(struct sockaddr_nl)) == -1) {
perror("bind");
close(s);
@@ -130,15 +174,15 @@ int main(int argc, char *argv[])
setsockopt(s, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP, &on, sizeof(on));
}
#endif
- if (0) {
+ if (send_msgs) {
int i, j;
memset(buf, 0, sizeof(buf));
data = (struct cn_msg *)buf;
- data->id.idx = 0x123;
- data->id.val = 0x456;
+ data->id.idx = CN_TEST_IDX;
+ data->id.val = CN_TEST_VAL;
data->seq = seq++;
data->ack = 0;
data->len = 0;
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index dd1a6d4bb74..3fe614d405e 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -1531,6 +1531,11 @@ and is between 256 and 4096 characters. It is defined in the file
symbolic names: lapic and ioapic
Example: nmi_watchdog=2 or nmi_watchdog=panic,lapic
+ netpoll.carrier_timeout=
+ [NET] Specifies amount of time (in seconds) that
+ netpoll should wait for a carrier. By default netpoll
+ waits 4 seconds.
+
no387 [BUGS=X86-32] Tells the kernel to use the 387 maths
emulation library even if a 387 maths coprocessor
is present.
diff --git a/Documentation/networking/00-INDEX b/Documentation/networking/00-INDEX
index 1634c6dceca..50189bf07d5 100644
--- a/Documentation/networking/00-INDEX
+++ b/Documentation/networking/00-INDEX
@@ -60,6 +60,8 @@ framerelay.txt
- info on using Frame Relay/Data Link Connection Identifier (DLCI).
generic_netlink.txt
- info on Generic Netlink
+ieee802154.txt
+ - Linux IEEE 802.15.4 implementation, API and drivers
ip-sysctl.txt
- /proc/sys/net/ipv4/* variables
ip_dynaddr.txt
diff --git a/Documentation/networking/ieee802154.txt b/Documentation/networking/ieee802154.txt
index a0280ad2edc..1c0c82c8bc7 100644
--- a/Documentation/networking/ieee802154.txt
+++ b/Documentation/networking/ieee802154.txt
@@ -22,7 +22,7 @@ int sd = socket(PF_IEEE802154, SOCK_DGRAM, 0);
.....
The address family, socket addresses etc. are defined in the
-include/net/ieee802154/af_ieee802154.h header or in the special header
+include/net/af_ieee802154.h header or in the special header
in our userspace package (see either linux-zigbee sourceforge download page
or git tree at git://linux-zigbee.git.sourceforge.net/gitroot/linux-zigbee).
@@ -33,7 +33,7 @@ MLME - MAC Level Management
============================
Most of IEEE 802.15.4 MLME interfaces are directly mapped on netlink commands.
-See the include/net/ieee802154/nl802154.h header. Our userspace tools package
+See the include/net/nl802154.h header. Our userspace tools package
(see above) provides CLI configuration utility for radio interfaces and simple
coordinator for IEEE 802.15.4 networks as an example users of MLME protocol.
@@ -54,7 +54,7 @@ Those types of devices require different approach to be hooked into Linux kernel
HardMAC
=======
-See the header include/net/ieee802154/netdevice.h. You have to implement Linux
+See the header include/net/ieee802154_netdev.h. You have to implement Linux
net_device, with .type = ARPHRD_IEEE802154. Data is exchanged with socket family
code via plain sk_buffs. The control block of sk_buffs will contain additional
info as described in the struct ieee802154_mac_cb.
@@ -69,8 +69,7 @@ We provide an example of simple HardMAC driver at drivers/ieee802154/fakehard.c
SoftMAC
=======
-We are going to provide intermediate layer impelementing IEEE 802.15.4 MAC
+We are going to provide intermediate layer implementing IEEE 802.15.4 MAC
in software. This is currently WIP.
-See header include/net/ieee802154/mac802154.h and several drivers in
-drivers/ieee802154/
+See header include/net/mac802154.h and several drivers in drivers/ieee802154/.
diff --git a/MAINTAINERS b/MAINTAINERS
index aee67a88889..866253d7abd 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3583,9 +3583,12 @@ M: "John W. Linville" <linville@tuxdriver.com>
L: linux-wireless@vger.kernel.org
T: git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-2.6.git
S: Maintained
+F: net/mac80211/
+F: net/rfkill/
F: net/wireless/
F: include/net/ieee80211*
F: include/linux/wireless.h
+F: drivers/net/wireless/
NETWORKING DRIVERS
L: netdev@vger.kernel.org
@@ -4291,7 +4294,7 @@ L: linux-wireless@vger.kernel.org
W: http://linuxwireless.org/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-testing.git
S: Maintained
-F: drivers/net/wireless/rtl818*
+F: drivers/net/wireless/rtl818x/rtl8180*
RTL8187 WIRELESS DRIVER
M: Herton Ronaldo Krzesinski <herton@mandriva.com.br>
@@ -5570,6 +5573,24 @@ M: Miloslav Trmac <mitr@volny.cz>
S: Maintained
F: drivers/input/misc/wistron_btns.c
+WL1251 WIRELESS DRIVER
+P: Kalle Valo
+M: kalle.valo@nokia.com
+L: linux-wireless@vger.kernel.org
+W: http://wireless.kernel.org
+T: git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-testing.git
+S: Maintained
+F: drivers/net/wireless/wl12xx/*
+X: drivers/net/wireless/wl12xx/wl1271*
+
+WL1271 WIRELESS DRIVER
+M: Luciano Coelho <luciano.coelho@nokia.com>
+L: linux-wireless@vger.kernel.org
+W: http://wireless.kernel.org
+T: git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-testing.git
+S: Maintained
+F: drivers/net/wireless/wl12xx/wl1271*
+
WL3501 WIRELESS PCMCIA CARD DRIVER
M: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
L: linux-wireless@vger.kernel.org
diff --git a/arch/alpha/include/asm/socket.h b/arch/alpha/include/asm/socket.h
index 3641ec1452f..26773e3246e 100644
--- a/arch/alpha/include/asm/socket.h
+++ b/arch/alpha/include/asm/socket.h
@@ -32,6 +32,8 @@
#define SO_RCVTIMEO 0x1012
#define SO_SNDTIMEO 0x1013
#define SO_ACCEPTCONN 0x1014
+#define SO_PROTOCOL 0x1028
+#define SO_DOMAIN 0x1029
/* linux-specific, might as well be the same as on i386 */
#define SO_NO_CHECK 11
diff --git a/arch/arm/include/asm/socket.h b/arch/arm/include/asm/socket.h
index 537de4e0ef5..92ac61d294f 100644
--- a/arch/arm/include/asm/socket.h
+++ b/arch/arm/include/asm/socket.h
@@ -57,4 +57,7 @@
#define SO_TIMESTAMPING 37
#define SCM_TIMESTAMPING SO_TIMESTAMPING
+#define SO_PROTOCOL 38
+#define SO_DOMAIN 39
+
#endif /* _ASM_SOCKET_H */
diff --git a/arch/avr32/include/asm/socket.h b/arch/avr32/include/asm/socket.h
index 04c86061970..fe863f9794d 100644
--- a/arch/avr32/include/asm/socket.h
+++ b/arch/avr32/include/asm/socket.h
@@ -57,4 +57,7 @@
#define SO_TIMESTAMPING 37
#define SCM_TIMESTAMPING SO_TIMESTAMPING
+#define SO_PROTOCOL 38
+#define SO_DOMAIN 39
+
#endif /* __ASM_AVR32_SOCKET_H */
diff --git a/arch/cris/include/asm/socket.h b/arch/cris/include/asm/socket.h
index d5cf7400540..45ec49bdb7b 100644
--- a/arch/cris/include/asm/socket.h
+++ b/arch/cris/include/asm/socket.h
@@ -59,6 +59,9 @@
#define SO_TIMESTAMPING 37
#define SCM_TIMESTAMPING SO_TIMESTAMPING
+#define SO_PROTOCOL 38
+#define SO_DOMAIN 39
+
#endif /* _ASM_SOCKET_H */
diff --git a/arch/frv/include/asm/socket.h b/arch/frv/include/asm/socket.h
index 57c3d4054e8..2dea726095c 100644
--- a/arch/frv/include/asm/socket.h
+++ b/arch/frv/include/asm/socket.h
@@ -57,5 +57,8 @@
#define SO_TIMESTAMPING 37
#define SCM_TIMESTAMPING SO_TIMESTAMPING
+#define SO_PROTOCOL 38
+#define SO_DOMAIN 39
+
#endif /* _ASM_SOCKET_H */
diff --git a/arch/h8300/include/asm/socket.h b/arch/h8300/include/asm/socket.h
index 602518a70a1..1547f01c8e2 100644
--- a/arch/h8300/include/asm/socket.h
+++ b/arch/h8300/include/asm/socket.h
@@ -57,4 +57,7 @@
#define SO_TIMESTAMPING 37
#define SCM_TIMESTAMPING SO_TIMESTAMPING
+#define SO_PROTOCOL 38
+#define SO_DOMAIN 39
+
#endif /* _ASM_SOCKET_H */
diff --git a/arch/ia64/hp/sim/simeth.c b/arch/ia64/hp/sim/simeth.c
index e4d8fde6810..7e81966ce48 100644
--- a/arch/ia64/hp/sim/simeth.c
+++ b/arch/ia64/hp/sim/simeth.c
@@ -412,7 +412,7 @@ simeth_tx(struct sk_buff *skb, struct net_device *dev)
*/
dev_kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
}
static inline struct sk_buff *
diff --git a/arch/ia64/include/asm/socket.h b/arch/ia64/include/asm/socket.h
index 745421225ec..0b0d5ff062e 100644
--- a/arch/ia64/include/asm/socket.h
+++ b/arch/ia64/include/asm/socket.h
@@ -66,4 +66,7 @@
#define SO_TIMESTAMPING 37
#define SCM_TIMESTAMPING SO_TIMESTAMPING
+#define SO_PROTOCOL 38
+#define SO_DOMAIN 39
+
#endif /* _ASM_IA64_SOCKET_H */
diff --git a/arch/m32r/include/asm/socket.h b/arch/m32r/include/asm/socket.h
index be7ed589af5..3390a864f22 100644
--- a/arch/m32r/include/asm/socket.h
+++ b/arch/m32r/include/asm/socket.h
@@ -57,4 +57,7 @@
#define SO_TIMESTAMPING 37
#define SCM_TIMESTAMPING SO_TIMESTAMPING
+#define SO_PROTOCOL 38
+#define SO_DOMAIN 39
+
#endif /* _ASM_M32R_SOCKET_H */
diff --git a/arch/m68k/include/asm/socket.h b/arch/m68k/include/asm/socket.h
index ca87f938b03..eee01cce921 100644
--- a/arch/m68k/include/asm/socket.h
+++ b/arch/m68k/include/asm/socket.h
@@ -57,4 +57,7 @@
#define SO_TIMESTAMPING 37
#define SCM_TIMESTAMPING SO_TIMESTAMPING
+#define SO_PROTOCOL 38
+#define SO_DOMAIN 39
+
#endif /* _ASM_SOCKET_H */
diff --git a/arch/mips/ar7/platform.c b/arch/mips/ar7/platform.c
index 2ecab615593..cf50fa29b19 100644
--- a/arch/mips/ar7/platform.c
+++ b/arch/mips/ar7/platform.c
@@ -32,6 +32,8 @@
#include <linux/leds.h>
#include <linux/string.h>
#include <linux/etherdevice.h>
+#include <linux/phy.h>
+#include <linux/phy_fixed.h>
#include <asm/addrspace.h>
#include <asm/mach-ar7/ar7.h>
@@ -208,6 +210,12 @@ static struct physmap_flash_data physmap_flash_data = {
.width = 2,
};
+static struct fixed_phy_status fixed_phy_status __initdata = {
+ .link = 1,
+ .speed = 100,
+ .duplex = 1,
+};
+
static struct plat_cpmac_data cpmac_low_data = {
.reset_bit = 17,
.power_bit = 20,
@@ -530,6 +538,9 @@ static int __init ar7_register_devices(void)
}
if (ar7_has_high_cpmac()) {
+ res = fixed_phy_add(PHY_POLL, cpmac_high.id, &fixed_phy_status);
+ if (res && res != -ENODEV)
+ return res;
cpmac_get_mac(1, cpmac_high_data.dev_addr);
res = platform_device_register(&cpmac_high);
if (res)
@@ -538,6 +549,10 @@ static int __init ar7_register_devices(void)
cpmac_low_data.phy_mask = 0xffffffff;
}
+ res = fixed_phy_add(PHY_POLL, cpmac_low.id, &fixed_phy_status);
+ if (res && res != -ENODEV)
+ return res;
+
cpmac_get_mac(0, cpmac_low_data.dev_addr);
res = platform_device_register(&cpmac_low);
if (res)
diff --git a/arch/mips/include/asm/socket.h b/arch/mips/include/asm/socket.h
index 2abca178016..ae05accd9fe 100644
--- a/arch/mips/include/asm/socket.h
+++ b/arch/mips/include/asm/socket.h
@@ -42,6 +42,8 @@ To add: #define SO_REUSEPORT 0x0200 /* Allow local address and port reuse. */
#define SO_SNDTIMEO 0x1005 /* send timeout */
#define SO_RCVTIMEO 0x1006 /* receive timeout */
#define SO_ACCEPTCONN 0x1009
+#define SO_PROTOCOL 0x1028 /* protocol type */
+#define SO_DOMAIN 0x1029 /* domain/socket family */
/* linux-specific, might as well be the same as on i386 */
#define SO_NO_CHECK 11
diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S
index e855b118a07..1a6ae124635 100644
--- a/arch/mips/kernel/scall64-n32.S
+++ b/arch/mips/kernel/scall64-n32.S
@@ -164,7 +164,7 @@ EXPORT(sysn32_call_table)
PTR sys_connect
PTR sys_accept
PTR sys_sendto
- PTR sys_recvfrom
+ PTR compat_sys_recvfrom
PTR compat_sys_sendmsg /* 6045 */
PTR compat_sys_recvmsg
PTR sys_shutdown
diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S
index 0c49f1a660b..cd31087a651 100644
--- a/arch/mips/kernel/scall64-o32.S
+++ b/arch/mips/kernel/scall64-o32.S
@@ -378,8 +378,8 @@ sys_call_table:
PTR sys_getsockname
PTR sys_getsockopt
PTR sys_listen
- PTR sys_recv /* 4175 */
- PTR sys_recvfrom
+ PTR compat_sys_recv /* 4175 */
+ PTR compat_sys_recvfrom
PTR compat_sys_recvmsg
PTR sys_send
PTR compat_sys_sendmsg
diff --git a/arch/mn10300/include/asm/socket.h b/arch/mn10300/include/asm/socket.h
index fb5daf438ec..4df75af29d7 100644
--- a/arch/mn10300/include/asm/socket.h
+++ b/arch/mn10300/include/asm/socket.h
@@ -57,4 +57,7 @@
#define SO_TIMESTAMPING 37
#define SCM_TIMESTAMPING SO_TIMESTAMPING
+#define SO_PROTOCOL 38
+#define SO_DOMAIN 39
+
#endif /* _ASM_SOCKET_H */
diff --git a/arch/parisc/include/asm/socket.h b/arch/parisc/include/asm/socket.h
index 885472bf7b7..960b1e5d8e1 100644
--- a/arch/parisc/include/asm/socket.h
+++ b/arch/parisc/include/asm/socket.h
@@ -24,6 +24,8 @@
#define SO_RCVTIMEO 0x1006
#define SO_ERROR 0x1007
#define SO_TYPE 0x1008
+#define SO_PROTOCOL 0x1028
+#define SO_DOMAIN 0x1029
#define SO_PEERNAME 0x2000
#define SO_NO_CHECK 0x400b
diff --git a/arch/powerpc/include/asm/socket.h b/arch/powerpc/include/asm/socket.h
index 1e5cfad0e3f..3ab8b3e6feb 100644
--- a/arch/powerpc/include/asm/socket.h
+++ b/arch/powerpc/include/asm/socket.h
@@ -64,4 +64,7 @@
#define SO_TIMESTAMPING 37
#define SCM_TIMESTAMPING SO_TIMESTAMPING
+#define SO_PROTOCOL 38
+#define SO_DOMAIN 39
+
#endif /* _ASM_POWERPC_SOCKET_H */
diff --git a/arch/s390/include/asm/socket.h b/arch/s390/include/asm/socket.h
index 02330c50241..e42df89a0b8 100644
--- a/arch/s390/include/asm/socket.h
+++ b/arch/s390/include/asm/socket.h
@@ -65,4 +65,7 @@
#define SO_TIMESTAMPING 37
#define SCM_TIMESTAMPING SO_TIMESTAMPING
+#define SO_PROTOCOL 38
+#define SO_DOMAIN 39
+
#endif /* _ASM_SOCKET_H */
diff --git a/arch/sparc/include/asm/socket.h b/arch/sparc/include/asm/socket.h
index 982a12f959f..3a5ae3d1208 100644
--- a/arch/sparc/include/asm/socket.h
+++ b/arch/sparc/include/asm/socket.h
@@ -29,6 +29,9 @@
#define SO_RCVBUFFORCE 0x100b
#define SO_ERROR 0x1007
#define SO_TYPE 0x1008
+#define SO_PROTOCOL 0x1028
+#define SO_DOMAIN 0x1029
+
/* Linux specific, keep the same. */
#define SO_NO_CHECK 0x000b
diff --git a/arch/sparc/kernel/sys32.S b/arch/sparc/kernel/sys32.S
index f061c4dda9e..3762f6c7894 100644
--- a/arch/sparc/kernel/sys32.S
+++ b/arch/sparc/kernel/sys32.S
@@ -121,7 +121,7 @@ SIGN2(sys32_syslog, sys_syslog, %o0, %o2)
SIGN1(sys32_umask, sys_umask, %o0)
SIGN3(sys32_tgkill, sys_tgkill, %o0, %o1, %o2)
SIGN1(sys32_sendto, sys_sendto, %o0)
-SIGN1(sys32_recvfrom, sys_recvfrom, %o0)
+SIGN1(sys32_recvfrom, compat_sys_recvfrom, %o0)
SIGN3(sys32_socket, sys_socket, %o0, %o1, %o2)
SIGN2(sys32_connect, sys_connect, %o0, %o2)
SIGN2(sys32_bind, sys_bind, %o0, %o2)
diff --git a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c
index 3b44b47c7e1..4c75409bc09 100644
--- a/arch/um/drivers/net_kern.c
+++ b/arch/um/drivers/net_kern.c
@@ -245,7 +245,7 @@ static int uml_net_start_xmit(struct sk_buff *skb, struct net_device *dev)
dev_kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
}
static void uml_net_set_multicast_list(struct net_device *dev)
diff --git a/arch/x86/include/asm/socket.h b/arch/x86/include/asm/socket.h
index ca8bf2cd0ba..b2a8c74f2d0 100644
--- a/arch/x86/include/asm/socket.h
+++ b/arch/x86/include/asm/socket.h
@@ -57,4 +57,7 @@
#define SO_TIMESTAMPING 37
#define SCM_TIMESTAMPING SO_TIMESTAMPING
+#define SO_PROTOCOL 38
+#define SO_DOMAIN 39
+
#endif /* _ASM_X86_SOCKET_H */
diff --git a/arch/xtensa/include/asm/socket.h b/arch/xtensa/include/asm/socket.h
index dd1a7a4a1ce..beb3a6bdb61 100644
--- a/arch/xtensa/include/asm/socket.h
+++ b/arch/xtensa/include/asm/socket.h
@@ -68,4 +68,7 @@
#define SO_TIMESTAMPING 37
#define SCM_TIMESTAMPING SO_TIMESTAMPING
+#define SO_PROTOCOL 38
+#define SO_DOMAIN 39
+
#endif /* _XTENSA_SOCKET_H */
diff --git a/arch/xtensa/platforms/iss/network.c b/arch/xtensa/platforms/iss/network.c
index edad4156d89..2f0b86b37cf 100644
--- a/arch/xtensa/platforms/iss/network.c
+++ b/arch/xtensa/platforms/iss/network.c
@@ -545,7 +545,7 @@ static int iss_net_start_xmit(struct sk_buff *skb, struct net_device *dev)
spin_unlock_irqrestore(&lp->lock, flags);
dev_kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
}
diff --git a/drivers/atm/horizon.c b/drivers/atm/horizon.c
index 6b969f8c684..01ce241dbea 100644
--- a/drivers/atm/horizon.c
+++ b/drivers/atm/horizon.c
@@ -641,7 +641,7 @@ static int make_rate (const hrz_dev * dev, u32 c, rounding r,
pre = 1;
break;
case round_nearest:
- pre = (br+(c<<div)/2)/(c<<div);
+ pre = DIV_ROUND_CLOSEST(br, c<<div);
// but p must be non-zero
if (!pre)
pre = 1;
@@ -671,7 +671,7 @@ static int make_rate (const hrz_dev * dev, u32 c, rounding r,
pre = DIV_ROUND_UP(br, c<<div);
break;
case round_nearest:
- pre = (br+(c<<div)/2)/(c<<div);
+ pre = DIV_ROUND_CLOSEST(br, c<<div);
break;
default: /* round_up */
pre = br/(c<<div);
diff --git a/drivers/atm/solos-pci.c b/drivers/atm/solos-pci.c
index 9359613addc..307321b32cb 100644
--- a/drivers/atm/solos-pci.c
+++ b/drivers/atm/solos-pci.c
@@ -372,7 +372,7 @@ static int process_status(struct solos_card *card, int port, struct sk_buff *skb
}
snr = next_string(skb);
- if (!str)
+ if (!snr)
return -EIO;
attn = next_string(skb);
if (!attn)
diff --git a/drivers/connector/cn_proc.c b/drivers/connector/cn_proc.c
index c5afc98e267..85e5dc0431f 100644
--- a/drivers/connector/cn_proc.c
+++ b/drivers/connector/cn_proc.c
@@ -202,9 +202,8 @@ static void cn_proc_ack(int err, int rcvd_seq, int rcvd_ack)
* cn_proc_mcast_ctl
* @data: message sent from userspace via the connector
*/
-static void cn_proc_mcast_ctl(void *data)
+static void cn_proc_mcast_ctl(struct cn_msg *msg)
{
- struct cn_msg *msg = data;
enum proc_cn_mcast_op *mc_op = NULL;
int err = 0;
diff --git a/drivers/connector/cn_queue.c b/drivers/connector/cn_queue.c
index 408c2af25d5..4a1dfe1f4ba 100644
--- a/drivers/connector/cn_queue.c
+++ b/drivers/connector/cn_queue.c
@@ -87,7 +87,9 @@ void cn_queue_wrapper(struct work_struct *work)
kfree(d->free);
}
-static struct cn_callback_entry *cn_queue_alloc_callback_entry(char *name, struct cb_id *id, void (*callback)(void *))
+static struct cn_callback_entry *
+cn_queue_alloc_callback_entry(char *name, struct cb_id *id,
+ void (*callback)(struct cn_msg *))
{
struct cn_callback_entry *cbq;
@@ -120,7 +122,8 @@ int cn_cb_equal(struct cb_id *i1, struct cb_id *i2)
return ((i1->idx == i2->idx) && (i1->val == i2->val));
}
-int cn_queue_add_callback(struct cn_queue_dev *dev, char *name, struct cb_id *id, void (*callback)(void *))
+int cn_queue_add_callback(struct cn_queue_dev *dev, char *name, struct cb_id *id,
+ void (*callback)(struct cn_msg *))
{
struct cn_callback_entry *cbq, *__cbq;
int found = 0;
diff --git a/drivers/connector/connector.c b/drivers/connector/connector.c
index 08b2500f21e..74f52af7956 100644
--- a/drivers/connector/connector.c
+++ b/drivers/connector/connector.c
@@ -269,7 +269,8 @@ static void cn_notify(struct cb_id *id, u32 notify_event)
*
* May sleep.
*/
-int cn_add_callback(struct cb_id *id, char *name, void (*callback)(void *))
+int cn_add_callback(struct cb_id *id, char *name,
+ void (*callback)(struct cn_msg *))
{
int err;
struct cn_dev *dev = &cdev;
@@ -351,9 +352,8 @@ static int cn_ctl_msg_equals(struct cn_ctl_msg *m1, struct cn_ctl_msg *m2)
*
* Used for notification of a request's processing.
*/
-static void cn_callback(void *data)
+static void cn_callback(struct cn_msg *msg)
{
- struct cn_msg *msg = data;
struct cn_ctl_msg *ctl;
struct cn_ctl_entry *ent;
u32 size;
diff --git a/drivers/ieee802154/fakehard.c b/drivers/ieee802154/fakehard.c
index 0384144c0b3..262536fae90 100644
--- a/drivers/ieee802154/fakehard.c
+++ b/drivers/ieee802154/fakehard.c
@@ -26,11 +26,17 @@
#include <linux/skbuff.h>
#include <linux/if_arp.h>
-#include <net/ieee802154/af_ieee802154.h>
-#include <net/ieee802154/netdevice.h>
-#include <net/ieee802154/mac_def.h>
-#include <net/ieee802154/nl802154.h>
-
+#include <net/af_ieee802154.h>
+#include <net/ieee802154_netdev.h>
+#include <net/ieee802154.h>
+#include <net/nl802154.h>
+
+/**
+ * fake_get_pan_id - Retrieve the PAN ID of the device.
+ * @dev: The network device to retrieve the PAN of.
+ *
+ * Return the ID of the PAN from the PIB.
+ */
static u16 fake_get_pan_id(struct net_device *dev)
{
BUG_ON(dev->type != ARPHRD_IEEE802154);
@@ -38,6 +44,14 @@ static u16 fake_get_pan_id(struct net_device *dev)
return 0xeba1;
}
+/**
+ * fake_get_short_addr - Retrieve the short address of the device.
+ * @dev: The network device to retrieve the short address of.
+ *
+ * Returns the IEEE 802.15.4 short-form address cached for this
+ * device. If the device has not yet had a short address assigned
+ * then this should return 0xFFFF to indicate a lack of association.
+ */
static u16 fake_get_short_addr(struct net_device *dev)
{
BUG_ON(dev->type != ARPHRD_IEEE802154);
@@ -45,6 +59,19 @@ static u16 fake_get_short_addr(struct net_device *dev)
return 0x1;
}
+/**
+ * fake_get_dsn - Retrieve the DSN of the device.
+ * @dev: The network device to retrieve the DSN for.
+ *
+ * Returns the IEEE 802.15.4 DSN for the network device.
+ * The DSN is the sequence number which will be added to each
+ * packet or MAC command frame by the MAC during transmission.
+ *
+ * DSN means 'Data Sequence Number'.
+ *
+ * Note: This is in section 7.2.1.2 of the IEEE 802.15.4-2006
+ * document.
+ */
static u8 fake_get_dsn(struct net_device *dev)
{
BUG_ON(dev->type != ARPHRD_IEEE802154);
@@ -52,6 +79,19 @@ static u8 fake_get_dsn(struct net_device *dev)
return 0x00; /* DSN are implemented in HW, so return just 0 */
}
+/**
+ * fake_get_bsn - Retrieve the BSN of the device.
+ * @dev: The network device to retrieve the BSN for.
+ *
+ * Returns the IEEE 802.15.4 BSN for the network device.
+ * The BSN is the sequence number which will be added to each
+ * beacon frame sent by the MAC.
+ *
+ * BSN means 'Beacon Sequence Number'.
+ *
+ * Note: This is in section 7.2.1.2 of the IEEE 802.15.4-2006
+ * document.
+ */
static u8 fake_get_bsn(struct net_device *dev)
{
BUG_ON(dev->type != ARPHRD_IEEE802154);
@@ -59,6 +99,19 @@ static u8 fake_get_bsn(struct net_device *dev)
return 0x00; /* BSN are implemented in HW, so return just 0 */
}
+/**
+ * fake_assoc_req - Make an association request to the HW.
+ * @dev: The network device which we are associating to a network.
+ * @addr: The coordinator with which we wish to associate.
+ * @channel: The channel on which to associate.
+ * @cap: The capability information field to use in the association.
+ *
+ * Start an association with a coordinator. The coordinator's address
+ * and PAN ID can be found in @addr.
+ *
+ * Note: This is in section 7.3.1 and 7.5.3.1 of the IEEE
+ * 802.15.4-2006 document.
+ */
static int fake_assoc_req(struct net_device *dev,
struct ieee802154_addr *addr, u8 channel, u8 cap)
{
@@ -67,26 +120,89 @@ static int fake_assoc_req(struct net_device *dev,
IEEE802154_SUCCESS);
}
+/**
+ * fake_assoc_resp - Send an association response to a device.
+ * @dev: The network device on which to send the response.
+ * @addr: The address of the device to respond to.
+ * @short_addr: The assigned short address for the device (if any).
+ * @status: The result of the association request.
+ *
+ * Queue the association response of the coordinator to another
+ * device's attempt to associate with the network which we
+ * coordinate. This is then added to the indirect-send queue to be
+ * transmitted to the end device when it polls for data.
+ *
+ * Note: This is in section 7.3.2 and 7.5.3.1 of the IEEE
+ * 802.15.4-2006 document.
+ */
static int fake_assoc_resp(struct net_device *dev,
struct ieee802154_addr *addr, u16 short_addr, u8 status)
{
return 0;
}
+/**
+ * fake_disassoc_req - Disassociate a device from a network.
+ * @dev: The network device on which we're disassociating a device.
+ * @addr: The device to disassociate from the network.
+ * @reason: The reason to give to the device for being disassociated.
+ *
+ * This sends a disassociation notification to the device being
+ * disassociated from the network.
+ *
+ * Note: This is in section 7.5.3.2 of the IEEE 802.15.4-2006
+ * document, with the reason described in 7.3.3.2.
+ */
static int fake_disassoc_req(struct net_device *dev,
struct ieee802154_addr *addr, u8 reason)
{
return ieee802154_nl_disassoc_confirm(dev, IEEE802154_SUCCESS);
}
+/**
+ * fake_start_req - Start an IEEE 802.15.4 PAN.
+ * @dev: The network device on which to start the PAN.
+ * @addr: The coordinator address to use when starting the PAN.
+ * @channel: The channel on which to start the PAN.
+ * @bcn_ord: Beacon order.
+ * @sf_ord: Superframe order.
+ * @pan_coord: Whether or not we are the PAN coordinator or just
+ * requesting a realignment perhaps?
+ * @blx: Battery Life Extension feature bitfield.
+ * @coord_realign: Something to realign something else.
+ *
+ * If pan_coord is non-zero then this starts a network with the
+ * provided parameters, otherwise it attempts a coordinator
+ * realignment of the stated network instead.
+ *
+ * Note: This is in section 7.5.2.3 of the IEEE 802.15.4-2006
+ * document, with 7.3.8 describing coordinator realignment.
+ */
static int fake_start_req(struct net_device *dev, struct ieee802154_addr *addr,
u8 channel,
u8 bcn_ord, u8 sf_ord, u8 pan_coord, u8 blx,
u8 coord_realign)
{
+ /* We don't emulate beacons here at all, so START should fail */
+ ieee802154_nl_start_confirm(dev, IEEE802154_INVALID_PARAMETER);
return 0;
}
+/**
+ * fake_scan_req - Start a channel scan.
+ * @dev: The network device on which to perform a channel scan.
+ * @type: The type of scan to perform.
+ * @channels: The channel bitmask to scan.
+ * @duration: How long to spend on each channel.
+ *
+ * This starts either a passive (energy) scan or an active (PAN) scan
+ * on the channels indicated in the @channels bitmask. The duration of
+ * the scan is measured in terms of superframe duration. Specifically,
+ * the scan will spend aBaseSuperFrameDuration * ((2^n) + 1) on each
+ * channel.
+ *
+ * Note: This is in section 7.5.2.1 of the IEEE 802.15.4-2006 document.
+ */
static int fake_scan_req(struct net_device *dev, u8 type, u32 channels,
u8 duration)
{
@@ -132,7 +248,7 @@ static int ieee802154_fake_xmit(struct sk_buff *skb, struct net_device *dev)
/* FIXME: do hardware work here ... */
- return 0;
+ return NETDEV_TX_OK;
}
diff --git a/drivers/isdn/Kconfig b/drivers/isdn/Kconfig
index 02bdca6f95c..022a1945295 100644
--- a/drivers/isdn/Kconfig
+++ b/drivers/isdn/Kconfig
@@ -21,8 +21,6 @@ menuconfig ISDN
if ISDN
-source "drivers/isdn/mISDN/Kconfig"
-
menuconfig ISDN_I4L
tristate "Old ISDN4Linux (deprecated)"
---help---
@@ -41,9 +39,9 @@ menuconfig ISDN_I4L
It is still available, though, for use with adapters that are not
supported by the new CAPI subsystem yet.
-if ISDN_I4L
+source "drivers/isdn/mISDN/Kconfig"
+
source "drivers/isdn/i4l/Kconfig"
-endif
menuconfig ISDN_CAPI
tristate "CAPI 2.0 subsystem"
diff --git a/drivers/isdn/act2000/capi.c b/drivers/isdn/act2000/capi.c
index 946c38cf6f8..1f0a9490646 100644
--- a/drivers/isdn/act2000/capi.c
+++ b/drivers/isdn/act2000/capi.c
@@ -78,7 +78,6 @@ static actcapi_msgdsc valid_msg[] = {
#endif
{{ 0x00, 0x00}, NULL},
};
-#define num_valid_msg (sizeof(valid_msg)/sizeof(actcapi_msgdsc))
#define num_valid_imsg 27 /* MANUFACTURER_IND */
/*
@@ -1025,7 +1024,7 @@ actcapi_debug_msg(struct sk_buff *skb, int direction)
#ifdef DEBUG_DUMP_SKB
dump_skb(skb);
#endif
- for (i = 0; i < num_valid_msg; i++)
+ for (i = 0; i < ARRAY_SIZE(valid_msg); i++)
if ((msg->hdr.cmd.cmd == valid_msg[i].cmd.cmd) &&
(msg->hdr.cmd.subcmd == valid_msg[i].cmd.subcmd)) {
descr = valid_msg[i].description;
diff --git a/drivers/isdn/act2000/module.c b/drivers/isdn/act2000/module.c
index 8325022e2be..f774e12bb64 100644
--- a/drivers/isdn/act2000/module.c
+++ b/drivers/isdn/act2000/module.c
@@ -23,7 +23,6 @@ static unsigned short act2000_isa_ports[] =
0x0200, 0x0240, 0x0280, 0x02c0, 0x0300, 0x0340, 0x0380,
0xcfe0, 0xcfa0, 0xcf60, 0xcf20, 0xcee0, 0xcea0, 0xce60,
};
-#define ISA_NRPORTS (sizeof(act2000_isa_ports)/sizeof(unsigned short))
static act2000_card *cards = (act2000_card *) NULL;
@@ -686,21 +685,21 @@ act2000_addcard(int bus, int port, int irq, char *id)
* This may result in more than one card detected.
*/
switch (bus) {
- case ACT2000_BUS_ISA:
- for (i = 0; i < ISA_NRPORTS; i++)
- if (act2000_isa_detect(act2000_isa_ports[i])) {
- printk(KERN_INFO
- "act2000: Detected ISA card at port 0x%x\n",
- act2000_isa_ports[i]);
- act2000_alloccard(bus, act2000_isa_ports[i], irq, id);
- }
- break;
- case ACT2000_BUS_MCA:
- case ACT2000_BUS_PCMCIA:
- default:
- printk(KERN_WARNING
- "act2000: addcard: Invalid BUS type %d\n",
- bus);
+ case ACT2000_BUS_ISA:
+ for (i = 0; i < ARRAY_SIZE(act2000_isa_ports); i++)
+ if (act2000_isa_detect(act2000_isa_ports[i])) {
+ printk(KERN_INFO "act2000: Detected "
+ "ISA card at port 0x%x\n",
+ act2000_isa_ports[i]);
+ act2000_alloccard(bus,
+ act2000_isa_ports[i], irq, id);
+ }
+ break;
+ case ACT2000_BUS_MCA:
+ case ACT2000_BUS_PCMCIA:
+ default:
+ printk(KERN_WARNING
+ "act2000: addcard: Invalid BUS type %d\n", bus);
}
}
if (!cards)
diff --git a/drivers/isdn/hardware/eicon/message.c b/drivers/isdn/hardware/eicon/message.c
index 31f91c18c69..27d5dd68f4f 100644
--- a/drivers/isdn/hardware/eicon/message.c
+++ b/drivers/isdn/hardware/eicon/message.c
@@ -551,9 +551,7 @@ word api_put(APPL * appl, CAPI_MSG * msg)
dbug(1,dprintf("com=%x",msg->header.command));
for(j=0;j<MAX_MSG_PARMS+1;j++) msg_parms[j].length = 0;
- for(i=0, ret = _BAD_MSG;
- i<(sizeof(ftable)/sizeof(struct _ftable));
- i++) {
+ for(i=0, ret = _BAD_MSG; i < ARRAY_SIZE(ftable); i++) {
if(ftable[i].command==msg->header.command) {
/* break loop if the message is correct, otherwise continue scan */
diff --git a/drivers/isdn/hardware/eicon/os_4bri.c b/drivers/isdn/hardware/eicon/os_4bri.c
index c964b8d91ad..cb7616c5b60 100644
--- a/drivers/isdn/hardware/eicon/os_4bri.c
+++ b/drivers/isdn/hardware/eicon/os_4bri.c
@@ -149,8 +149,7 @@ int diva_4bri_init_card(diva_os_xdi_adapter_t * a)
diva_os_xdi_adapter_t *diva_current;
diva_os_xdi_adapter_t *adapter_list[4];
PISDN_ADAPTER Slave;
- unsigned long bar_length[sizeof(_4bri_bar_length) /
- sizeof(_4bri_bar_length[0])];
+ unsigned long bar_length[ARRAY_SIZE(_4bri_bar_length)];
int v2 = _4bri_is_rev_2_card(a->CardOrdinal);
int tasks = _4bri_is_rev_2_bri_card(a->CardOrdinal) ? 1 : MQ_INSTANCE_COUNT;
int factor = (tasks == 1) ? 1 : 2;
diff --git a/drivers/isdn/hardware/mISDN/Kconfig b/drivers/isdn/hardware/mISDN/Kconfig
index 3024566dd09..bde55d7287f 100644
--- a/drivers/isdn/hardware/mISDN/Kconfig
+++ b/drivers/isdn/hardware/mISDN/Kconfig
@@ -39,3 +39,54 @@ config MISDN_HFCUSB
Enable support for USB ISDN TAs with Cologne Chip AG's
HFC-S USB ISDN Controller
+config MISDN_AVMFRITZ
+ tristate "Support for AVM FRITZ!CARD PCI"
+ depends on MISDN
+ depends on PCI
+ select MISDN_IPAC
+ help
+ Enable support for AVMs FRITZ!CARD PCI cards
+
+config MISDN_SPEEDFAX
+ tristate "Support for Sedlbauer Speedfax+"
+ depends on MISDN
+ depends on PCI
+ select MISDN_IPAC
+ select MISDN_ISAR
+ help
+ Enable support for Sedlbauer Speedfax+.
+
+config MISDN_INFINEON
+ tristate "Support for cards with Infineon chipset"
+ depends on MISDN
+ depends on PCI
+ select MISDN_IPAC
+ help
+ Enable support for cards with ISAC + HSCX, IPAC or IPAC-SX
+ chip from Infineon (former manufacturer Siemens).
+
+config MISDN_W6692
+ tristate "Support for cards with Winbond 6692"
+ depends on MISDN
+ depends on PCI
+ help
+ Enable support for Winbond 6692 PCI chip based cards.
+
+config MISDN_NETJET
+ tristate "Support for NETJet cards"
+ depends on MISDN
+ depends on PCI
+ select MISDN_IPAC
+ select ISDN_HDLC
+ help
+ Enable support for Traverse Technologies NETJet PCI cards.
+
+
+config MISDN_IPAC
+ tristate
+ depends on MISDN
+
+config MISDN_ISAR
+ tristate
+ depends on MISDN
+
diff --git a/drivers/isdn/hardware/mISDN/Makefile b/drivers/isdn/hardware/mISDN/Makefile
index b0403526bbb..2987d990993 100644
--- a/drivers/isdn/hardware/mISDN/Makefile
+++ b/drivers/isdn/hardware/mISDN/Makefile
@@ -6,3 +6,11 @@
obj-$(CONFIG_MISDN_HFCPCI) += hfcpci.o
obj-$(CONFIG_MISDN_HFCMULTI) += hfcmulti.o
obj-$(CONFIG_MISDN_HFCUSB) += hfcsusb.o
+obj-$(CONFIG_MISDN_AVMFRITZ) += avmfritz.o
+obj-$(CONFIG_MISDN_SPEEDFAX) += speedfax.o
+obj-$(CONFIG_MISDN_INFINEON) += mISDNinfineon.o
+obj-$(CONFIG_MISDN_W6692) += w6692.o
+obj-$(CONFIG_MISDN_NETJET) += netjet.o
+# chip modules
+obj-$(CONFIG_MISDN_IPAC) += mISDNipac.o
+obj-$(CONFIG_MISDN_ISAR) += mISDNisar.o
diff --git a/drivers/isdn/hardware/mISDN/avmfritz.c b/drivers/isdn/hardware/mISDN/avmfritz.c
new file mode 100644
index 00000000000..81ac541d40d
--- /dev/null
+++ b/drivers/isdn/hardware/mISDN/avmfritz.c
@@ -0,0 +1,1152 @@
+/*
+ * avm_fritz.c low level stuff for AVM FRITZ!CARD PCI ISDN cards
+ * Thanks to AVM, Berlin for informations
+ *
+ * Author Karsten Keil <keil@isdn4linux.de>
+ *
+ * Copyright 2009 by Karsten Keil <keil@isdn4linux.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/mISDNhw.h>
+#include <asm/unaligned.h>
+#include "ipac.h"
+
+
+#define AVMFRITZ_REV "2.1"
+
+static int AVM_cnt;
+static int debug;
+
+enum {
+ AVM_FRITZ_PCI,
+ AVM_FRITZ_PCIV2,
+};
+
+#define HDLC_FIFO 0x0
+#define HDLC_STATUS 0x4
+#define CHIP_WINDOW 0x10
+
+#define CHIP_INDEX 0x4
+#define AVM_HDLC_1 0x00
+#define AVM_HDLC_2 0x01
+#define AVM_ISAC_FIFO 0x02
+#define AVM_ISAC_REG_LOW 0x04
+#define AVM_ISAC_REG_HIGH 0x06
+
+#define AVM_STATUS0_IRQ_ISAC 0x01
+#define AVM_STATUS0_IRQ_HDLC 0x02
+#define AVM_STATUS0_IRQ_TIMER 0x04
+#define AVM_STATUS0_IRQ_MASK 0x07
+
+#define AVM_STATUS0_RESET 0x01
+#define AVM_STATUS0_DIS_TIMER 0x02
+#define AVM_STATUS0_RES_TIMER 0x04
+#define AVM_STATUS0_ENA_IRQ 0x08
+#define AVM_STATUS0_TESTBIT 0x10
+
+#define AVM_STATUS1_INT_SEL 0x0f
+#define AVM_STATUS1_ENA_IOM 0x80
+
+#define HDLC_MODE_ITF_FLG 0x01
+#define HDLC_MODE_TRANS 0x02
+#define HDLC_MODE_CCR_7 0x04
+#define HDLC_MODE_CCR_16 0x08
+#define HDLC_MODE_TESTLOOP 0x80
+
+#define HDLC_INT_XPR 0x80
+#define HDLC_INT_XDU 0x40
+#define HDLC_INT_RPR 0x20
+#define HDLC_INT_MASK 0xE0
+
+#define HDLC_STAT_RME 0x01
+#define HDLC_STAT_RDO 0x10
+#define HDLC_STAT_CRCVFRRAB 0x0E
+#define HDLC_STAT_CRCVFR 0x06
+#define HDLC_STAT_RML_MASK 0x3f00
+
+#define HDLC_CMD_XRS 0x80
+#define HDLC_CMD_XME 0x01
+#define HDLC_CMD_RRS 0x20
+#define HDLC_CMD_XML_MASK 0x3f00
+#define HDLC_FIFO_SIZE 32
+
+/* Fritz PCI v2.0 */
+
+#define AVM_HDLC_FIFO_1 0x10
+#define AVM_HDLC_FIFO_2 0x18
+
+#define AVM_HDLC_STATUS_1 0x14
+#define AVM_HDLC_STATUS_2 0x1c
+
+#define AVM_ISACX_INDEX 0x04
+#define AVM_ISACX_DATA 0x08
+
+/* data struct */
+#define LOG_SIZE 63
+
+struct hdlc_stat_reg {
+#ifdef __BIG_ENDIAN
+ u8 fill;
+ u8 mode;
+ u8 xml;
+ u8 cmd;
+#else
+ u8 cmd;
+ u8 xml;
+ u8 mode;
+ u8 fill;
+#endif
+} __attribute__((packed));
+
+struct hdlc_hw {
+ union {
+ u32 ctrl;
+ struct hdlc_stat_reg sr;
+ } ctrl;
+ u32 stat;
+};
+
+struct fritzcard {
+ struct list_head list;
+ struct pci_dev *pdev;
+ char name[MISDN_MAX_IDLEN];
+ u8 type;
+ u8 ctrlreg;
+ u16 irq;
+ u32 irqcnt;
+ u32 addr;
+ spinlock_t lock; /* hw lock */
+ struct isac_hw isac;
+ struct hdlc_hw hdlc[2];
+ struct bchannel bch[2];
+ char log[LOG_SIZE + 1];
+};
+
+static LIST_HEAD(Cards);
+static DEFINE_RWLOCK(card_lock); /* protect Cards */
+
+static void
+_set_debug(struct fritzcard *card)
+{
+ card->isac.dch.debug = debug;
+ card->bch[0].debug = debug;
+ card->bch[1].debug = debug;
+}
+
+static int
+set_debug(const char *val, struct kernel_param *kp)
+{
+ int ret;
+ struct fritzcard *card;
+
+ ret = param_set_uint(val, kp);
+ if (!ret) {
+ read_lock(&card_lock);
+ list_for_each_entry(card, &Cards, list)
+ _set_debug(card);
+ read_unlock(&card_lock);
+ }
+ return ret;
+}
+
+MODULE_AUTHOR("Karsten Keil");
+MODULE_LICENSE("GPL v2");
+MODULE_VERSION(AVMFRITZ_REV);
+module_param_call(debug, set_debug, param_get_uint, &debug, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "avmfritz debug mask");
+
+/* Interface functions */
+
+static u8
+ReadISAC_V1(void *p, u8 offset)
+{
+ struct fritzcard *fc = p;
+ u8 idx = (offset > 0x2f) ? AVM_ISAC_REG_HIGH : AVM_ISAC_REG_LOW;
+
+ outb(idx, fc->addr + CHIP_INDEX);
+ return inb(fc->addr + CHIP_WINDOW + (offset & 0xf));
+}
+
+static void
+WriteISAC_V1(void *p, u8 offset, u8 value)
+{
+ struct fritzcard *fc = p;
+ u8 idx = (offset > 0x2f) ? AVM_ISAC_REG_HIGH : AVM_ISAC_REG_LOW;
+
+ outb(idx, fc->addr + CHIP_INDEX);
+ outb(value, fc->addr + CHIP_WINDOW + (offset & 0xf));
+}
+
+static void
+ReadFiFoISAC_V1(void *p, u8 off, u8 *data, int size)
+{
+ struct fritzcard *fc = p;
+
+ outb(AVM_ISAC_FIFO, fc->addr + CHIP_INDEX);
+ insb(fc->addr + CHIP_WINDOW, data, size);
+}
+
+static void
+WriteFiFoISAC_V1(void *p, u8 off, u8 *data, int size)
+{
+ struct fritzcard *fc = p;
+
+ outb(AVM_ISAC_FIFO, fc->addr + CHIP_INDEX);
+ outsb(fc->addr + CHIP_WINDOW, data, size);
+}
+
+static u8
+ReadISAC_V2(void *p, u8 offset)
+{
+ struct fritzcard *fc = p;
+
+ outl(offset, fc->addr + AVM_ISACX_INDEX);
+ return 0xff & inl(fc->addr + AVM_ISACX_DATA);
+}
+
+static void
+WriteISAC_V2(void *p, u8 offset, u8 value)
+{
+ struct fritzcard *fc = p;
+
+ outl(offset, fc->addr + AVM_ISACX_INDEX);
+ outl(value, fc->addr + AVM_ISACX_DATA);
+}
+
+static void
+ReadFiFoISAC_V2(void *p, u8 off, u8 *data, int size)
+{
+ struct fritzcard *fc = p;
+ int i;
+
+ outl(off, fc->addr + AVM_ISACX_INDEX);
+ for (i = 0; i < size; i++)
+ data[i] = 0xff & inl(fc->addr + AVM_ISACX_DATA);
+}
+
+static void
+WriteFiFoISAC_V2(void *p, u8 off, u8 *data, int size)
+{
+ struct fritzcard *fc = p;
+ int i;
+
+ outl(off, fc->addr + AVM_ISACX_INDEX);
+ for (i = 0; i < size; i++)
+ outl(data[i], fc->addr + AVM_ISACX_DATA);
+}
+
+static struct bchannel *
+Sel_BCS(struct fritzcard *fc, u32 channel)
+{
+ if (test_bit(FLG_ACTIVE, &fc->bch[0].Flags) &&
+ (fc->bch[0].nr & channel))
+ return &fc->bch[0];
+ else if (test_bit(FLG_ACTIVE, &fc->bch[1].Flags) &&
+ (fc->bch[1].nr & channel))
+ return &fc->bch[1];
+ else
+ return NULL;
+}
+
+static inline void
+__write_ctrl_pci(struct fritzcard *fc, struct hdlc_hw *hdlc, u32 channel) {
+ u32 idx = channel == 2 ? AVM_HDLC_2 : AVM_HDLC_1;
+
+ outl(idx, fc->addr + CHIP_INDEX);
+ outl(hdlc->ctrl.ctrl, fc->addr + CHIP_WINDOW + HDLC_STATUS);
+}
+
+static inline void
+__write_ctrl_pciv2(struct fritzcard *fc, struct hdlc_hw *hdlc, u32 channel) {
+ outl(hdlc->ctrl.ctrl, fc->addr + (channel == 2 ? AVM_HDLC_STATUS_2 :
+ AVM_HDLC_STATUS_1));
+}
+
+void
+write_ctrl(struct bchannel *bch, int which) {
+ struct fritzcard *fc = bch->hw;
+ struct hdlc_hw *hdlc;
+
+ hdlc = &fc->hdlc[(bch->nr - 1) & 1];
+ pr_debug("%s: hdlc %c wr%x ctrl %x\n", fc->name, '@' + bch->nr,
+ which, hdlc->ctrl.ctrl);
+ switch (fc->type) {
+ case AVM_FRITZ_PCIV2:
+ __write_ctrl_pciv2(fc, hdlc, bch->nr);
+ break;
+ case AVM_FRITZ_PCI:
+ __write_ctrl_pci(fc, hdlc, bch->nr);
+ break;
+ }
+}
+
+
+static inline u32
+__read_status_pci(u_long addr, u32 channel)
+{
+ outl(channel == 2 ? AVM_HDLC_2 : AVM_HDLC_1, addr + CHIP_INDEX);
+ return inl(addr + CHIP_WINDOW + HDLC_STATUS);
+}
+
+static inline u32
+__read_status_pciv2(u_long addr, u32 channel)
+{
+ return inl(addr + (channel == 2 ? AVM_HDLC_STATUS_2 :
+ AVM_HDLC_STATUS_1));
+}
+
+
+static u32
+read_status(struct fritzcard *fc, u32 channel)
+{
+ switch (fc->type) {
+ case AVM_FRITZ_PCIV2:
+ return __read_status_pciv2(fc->addr, channel);
+ case AVM_FRITZ_PCI:
+ return __read_status_pci(fc->addr, channel);
+ }
+ /* dummy */
+ return 0;
+}
+
+static void
+enable_hwirq(struct fritzcard *fc)
+{
+ fc->ctrlreg |= AVM_STATUS0_ENA_IRQ;
+ outb(fc->ctrlreg, fc->addr + 2);
+}
+
+static void
+disable_hwirq(struct fritzcard *fc)
+{
+ fc->ctrlreg &= ~AVM_STATUS0_ENA_IRQ;
+ outb(fc->ctrlreg, fc->addr + 2);
+}
+
+static int
+modehdlc(struct bchannel *bch, int protocol)
+{
+ struct fritzcard *fc = bch->hw;
+ struct hdlc_hw *hdlc;
+
+ hdlc = &fc->hdlc[(bch->nr - 1) & 1];
+ pr_debug("%s: hdlc %c protocol %x-->%x ch %d\n", fc->name,
+ '@' + bch->nr, bch->state, protocol, bch->nr);
+ hdlc->ctrl.ctrl = 0;
+ switch (protocol) {
+ case -1: /* used for init */
+ bch->state = -1;
+ case ISDN_P_NONE:
+ if (bch->state == ISDN_P_NONE)
+ break;
+ hdlc->ctrl.sr.cmd = HDLC_CMD_XRS | HDLC_CMD_RRS;
+ hdlc->ctrl.sr.mode = HDLC_MODE_TRANS;
+ write_ctrl(bch, 5);
+ bch->state = ISDN_P_NONE;
+ test_and_clear_bit(FLG_HDLC, &bch->Flags);
+ test_and_clear_bit(FLG_TRANSPARENT, &bch->Flags);
+ break;
+ case ISDN_P_B_RAW:
+ bch->state = protocol;
+ hdlc->ctrl.sr.cmd = HDLC_CMD_XRS | HDLC_CMD_RRS;
+ hdlc->ctrl.sr.mode = HDLC_MODE_TRANS;
+ write_ctrl(bch, 5);
+ hdlc->ctrl.sr.cmd = HDLC_CMD_XRS;
+ write_ctrl(bch, 1);
+ hdlc->ctrl.sr.cmd = 0;
+ test_and_set_bit(FLG_TRANSPARENT, &bch->Flags);
+ break;
+ case ISDN_P_B_HDLC:
+ bch->state = protocol;
+ hdlc->ctrl.sr.cmd = HDLC_CMD_XRS | HDLC_CMD_RRS;
+ hdlc->ctrl.sr.mode = HDLC_MODE_ITF_FLG;
+ write_ctrl(bch, 5);
+ hdlc->ctrl.sr.cmd = HDLC_CMD_XRS;
+ write_ctrl(bch, 1);
+ hdlc->ctrl.sr.cmd = 0;
+ test_and_set_bit(FLG_HDLC, &bch->Flags);
+ break;
+ default:
+ pr_info("%s: protocol not known %x\n", fc->name, protocol);
+ return -ENOPROTOOPT;
+ }
+ return 0;
+}
+
+static void
+hdlc_empty_fifo(struct bchannel *bch, int count)
+{
+ u32 *ptr;
+ u8 *p;
+ u32 val, addr;
+ int cnt = 0;
+ struct fritzcard *fc = bch->hw;
+
+ pr_debug("%s: %s %d\n", fc->name, __func__, count);
+ if (!bch->rx_skb) {
+ bch->rx_skb = mI_alloc_skb(bch->maxlen, GFP_ATOMIC);
+ if (!bch->rx_skb) {
+ pr_info("%s: B receive out of memory\n",
+ fc->name);
+ return;
+ }
+ }
+ if ((bch->rx_skb->len + count) > bch->maxlen) {
+ pr_debug("%s: overrun %d\n", fc->name,
+ bch->rx_skb->len + count);
+ return;
+ }
+ p = skb_put(bch->rx_skb, count);
+ ptr = (u32 *)p;
+ if (AVM_FRITZ_PCIV2 == fc->type)
+ addr = fc->addr + (bch->nr == 2 ?
+ AVM_HDLC_FIFO_2 : AVM_HDLC_FIFO_1);
+ else {
+ addr = fc->addr + CHIP_WINDOW;
+ outl(bch->nr == 2 ? AVM_HDLC_2 : AVM_HDLC_1, fc->addr);
+ }
+ while (cnt < count) {
+ val = le32_to_cpu(inl(addr));
+ put_unaligned(val, ptr);
+ ptr++;
+ cnt += 4;
+ }
+ if (debug & DEBUG_HW_BFIFO) {
+ snprintf(fc->log, LOG_SIZE, "B%1d-recv %s %d ",
+ bch->nr, fc->name, count);
+ print_hex_dump_bytes(fc->log, DUMP_PREFIX_OFFSET, p, count);
+ }
+}
+
+static void
+hdlc_fill_fifo(struct bchannel *bch)
+{
+ struct fritzcard *fc = bch->hw;
+ struct hdlc_hw *hdlc;
+ int count, cnt = 0;
+ u8 *p;
+ u32 *ptr, val, addr;
+
+ hdlc = &fc->hdlc[(bch->nr - 1) & 1];
+ if (!bch->tx_skb)
+ return;
+ count = bch->tx_skb->len - bch->tx_idx;
+ if (count <= 0)
+ return;
+ p = bch->tx_skb->data + bch->tx_idx;
+ hdlc->ctrl.sr.cmd &= ~HDLC_CMD_XME;
+ if (count > HDLC_FIFO_SIZE) {
+ count = HDLC_FIFO_SIZE;
+ } else {
+ if (test_bit(FLG_HDLC, &bch->Flags))
+ hdlc->ctrl.sr.cmd |= HDLC_CMD_XME;
+ }
+ pr_debug("%s: %s %d/%d/%d", fc->name, __func__, count,
+ bch->tx_idx, bch->tx_skb->len);
+ ptr = (u32 *)p;
+ bch->tx_idx += count;
+ hdlc->ctrl.sr.xml = ((count == HDLC_FIFO_SIZE) ? 0 : count);
+ if (AVM_FRITZ_PCIV2 == fc->type) {
+ __write_ctrl_pciv2(fc, hdlc, bch->nr);
+ addr = fc->addr + (bch->nr == 2 ?
+ AVM_HDLC_FIFO_2 : AVM_HDLC_FIFO_1);
+ } else {
+ __write_ctrl_pci(fc, hdlc, bch->nr);
+ addr = fc->addr + CHIP_WINDOW;
+ }
+ while (cnt < count) {
+ val = get_unaligned(ptr);
+ outl(cpu_to_le32(val), addr);
+ ptr++;
+ cnt += 4;
+ }
+ if (debug & DEBUG_HW_BFIFO) {
+ snprintf(fc->log, LOG_SIZE, "B%1d-send %s %d ",
+ bch->nr, fc->name, count);
+ print_hex_dump_bytes(fc->log, DUMP_PREFIX_OFFSET, p, count);
+ }
+}
+
+static void
+HDLC_irq_xpr(struct bchannel *bch)
+{
+ if (bch->tx_skb && bch->tx_idx < bch->tx_skb->len)
+ hdlc_fill_fifo(bch);
+ else {
+ if (bch->tx_skb) {
+ /* send confirm, on trans, free on hdlc. */
+ if (test_bit(FLG_TRANSPARENT, &bch->Flags))
+ confirm_Bsend(bch);
+ dev_kfree_skb(bch->tx_skb);
+ }
+ if (get_next_bframe(bch))
+ hdlc_fill_fifo(bch);
+ }
+}
+
+static void
+HDLC_irq(struct bchannel *bch, u32 stat)
+{
+ struct fritzcard *fc = bch->hw;
+ int len;
+ struct hdlc_hw *hdlc;
+
+ hdlc = &fc->hdlc[(bch->nr - 1) & 1];
+ pr_debug("%s: ch%d stat %#x\n", fc->name, bch->nr, stat);
+ if (stat & HDLC_INT_RPR) {
+ if (stat & HDLC_STAT_RDO) {
+ hdlc->ctrl.sr.xml = 0;
+ hdlc->ctrl.sr.cmd |= HDLC_CMD_RRS;
+ write_ctrl(bch, 1);
+ hdlc->ctrl.sr.cmd &= ~HDLC_CMD_RRS;
+ write_ctrl(bch, 1);
+ if (bch->rx_skb)
+ skb_trim(bch->rx_skb, 0);
+ } else {
+ len = (stat & HDLC_STAT_RML_MASK) >> 8;
+ if (!len)
+ len = 32;
+ hdlc_empty_fifo(bch, len);
+ if (!bch->rx_skb)
+ goto handle_tx;
+ if ((stat & HDLC_STAT_RME) || test_bit(FLG_TRANSPARENT,
+ &bch->Flags)) {
+ if (((stat & HDLC_STAT_CRCVFRRAB) ==
+ HDLC_STAT_CRCVFR) ||
+ test_bit(FLG_TRANSPARENT, &bch->Flags)) {
+ recv_Bchannel(bch, 0);
+ } else {
+ pr_debug("%s: got invalid frame\n",
+ fc->name);
+ skb_trim(bch->rx_skb, 0);
+ }
+ }
+ }
+ }
+handle_tx:
+ if (stat & HDLC_INT_XDU) {
+ /* Here we lost an TX interrupt, so
+ * restart transmitting the whole frame on HDLC
+ * in transparent mode we send the next data
+ */
+ if (bch->tx_skb)
+ pr_debug("%s: ch%d XDU len(%d) idx(%d) Flags(%lx)\n",
+ fc->name, bch->nr, bch->tx_skb->len,
+ bch->tx_idx, bch->Flags);
+ else
+ pr_debug("%s: ch%d XDU no tx_skb Flags(%lx)\n",
+ fc->name, bch->nr, bch->Flags);
+ if (bch->tx_skb && bch->tx_skb->len) {
+ if (!test_bit(FLG_TRANSPARENT, &bch->Flags))
+ bch->tx_idx = 0;
+ }
+ hdlc->ctrl.sr.xml = 0;
+ hdlc->ctrl.sr.cmd |= HDLC_CMD_XRS;
+ write_ctrl(bch, 1);
+ hdlc->ctrl.sr.cmd &= ~HDLC_CMD_XRS;
+ HDLC_irq_xpr(bch);
+ return;
+ } else if (stat & HDLC_INT_XPR)
+ HDLC_irq_xpr(bch);
+}
+
+static inline void
+HDLC_irq_main(struct fritzcard *fc)
+{
+ u32 stat;
+ struct bchannel *bch;
+
+ stat = read_status(fc, 1);
+ if (stat & HDLC_INT_MASK) {
+ bch = Sel_BCS(fc, 1);
+ if (bch)
+ HDLC_irq(bch, stat);
+ else
+ pr_debug("%s: spurious ch1 IRQ\n", fc->name);
+ }
+ stat = read_status(fc, 2);
+ if (stat & HDLC_INT_MASK) {
+ bch = Sel_BCS(fc, 2);
+ if (bch)
+ HDLC_irq(bch, stat);
+ else
+ pr_debug("%s: spurious ch2 IRQ\n", fc->name);
+ }
+}
+
+static irqreturn_t
+avm_fritz_interrupt(int intno, void *dev_id)
+{
+ struct fritzcard *fc = dev_id;
+ u8 val;
+ u8 sval;
+
+ spin_lock(&fc->lock);
+ sval = inb(fc->addr + 2);
+ pr_debug("%s: irq stat0 %x\n", fc->name, sval);
+ if ((sval & AVM_STATUS0_IRQ_MASK) == AVM_STATUS0_IRQ_MASK) {
+ /* shared IRQ from other HW */
+ spin_unlock(&fc->lock);
+ return IRQ_NONE;
+ }
+ fc->irqcnt++;
+
+ if (!(sval & AVM_STATUS0_IRQ_ISAC)) {
+ val = ReadISAC_V1(fc, ISAC_ISTA);
+ mISDNisac_irq(&fc->isac, val);
+ }
+ if (!(sval & AVM_STATUS0_IRQ_HDLC))
+ HDLC_irq_main(fc);
+ spin_unlock(&fc->lock);
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t
+avm_fritzv2_interrupt(int intno, void *dev_id)
+{
+ struct fritzcard *fc = dev_id;
+ u8 val;
+ u8 sval;
+
+ spin_lock(&fc->lock);
+ sval = inb(fc->addr + 2);
+ pr_debug("%s: irq stat0 %x\n", fc->name, sval);
+ if (!(sval & AVM_STATUS0_IRQ_MASK)) {
+ /* shared IRQ from other HW */
+ spin_unlock(&fc->lock);
+ return IRQ_NONE;
+ }
+ fc->irqcnt++;
+
+ if (sval & AVM_STATUS0_IRQ_HDLC)
+ HDLC_irq_main(fc);
+ if (sval & AVM_STATUS0_IRQ_ISAC) {
+ val = ReadISAC_V2(fc, ISACX_ISTA);
+ mISDNisac_irq(&fc->isac, val);
+ }
+ if (sval & AVM_STATUS0_IRQ_TIMER) {
+ pr_debug("%s: timer irq\n", fc->name);
+ outb(fc->ctrlreg | AVM_STATUS0_RES_TIMER, fc->addr + 2);
+ udelay(1);
+ outb(fc->ctrlreg, fc->addr + 2);
+ }
+ spin_unlock(&fc->lock);
+ return IRQ_HANDLED;
+}
+
+static int
+avm_l2l1B(struct mISDNchannel *ch, struct sk_buff *skb)
+{
+ struct bchannel *bch = container_of(ch, struct bchannel, ch);
+ struct fritzcard *fc = bch->hw;
+ int ret = -EINVAL;
+ struct mISDNhead *hh = mISDN_HEAD_P(skb);
+ u32 id;
+ u_long flags;
+
+ switch (hh->prim) {
+ case PH_DATA_REQ:
+ spin_lock_irqsave(&fc->lock, flags);
+ ret = bchannel_senddata(bch, skb);
+ if (ret > 0) { /* direct TX */
+ id = hh->id; /* skb can be freed */
+ hdlc_fill_fifo(bch);
+ ret = 0;
+ spin_unlock_irqrestore(&fc->lock, flags);
+ if (!test_bit(FLG_TRANSPARENT, &bch->Flags))
+ queue_ch_frame(ch, PH_DATA_CNF, id, NULL);
+ } else
+ spin_unlock_irqrestore(&fc->lock, flags);
+ return ret;
+ case PH_ACTIVATE_REQ:
+ spin_lock_irqsave(&fc->lock, flags);
+ if (!test_and_set_bit(FLG_ACTIVE, &bch->Flags))
+ ret = modehdlc(bch, ch->protocol);
+ else
+ ret = 0;
+ spin_unlock_irqrestore(&fc->lock, flags);
+ if (!ret)
+ _queue_data(ch, PH_ACTIVATE_IND, MISDN_ID_ANY, 0,
+ NULL, GFP_KERNEL);
+ break;
+ case PH_DEACTIVATE_REQ:
+ spin_lock_irqsave(&fc->lock, flags);
+ mISDN_clear_bchannel(bch);
+ modehdlc(bch, ISDN_P_NONE);
+ spin_unlock_irqrestore(&fc->lock, flags);
+ _queue_data(ch, PH_DEACTIVATE_IND, MISDN_ID_ANY, 0,
+ NULL, GFP_KERNEL);
+ ret = 0;
+ break;
+ }
+ if (!ret)
+ dev_kfree_skb(skb);
+ return ret;
+}
+
+static void
+inithdlc(struct fritzcard *fc)
+{
+ modehdlc(&fc->bch[0], -1);
+ modehdlc(&fc->bch[1], -1);
+}
+
+void
+clear_pending_hdlc_ints(struct fritzcard *fc)
+{
+ u32 val;
+
+ val = read_status(fc, 1);
+ pr_debug("%s: HDLC 1 STA %x\n", fc->name, val);
+ val = read_status(fc, 2);
+ pr_debug("%s: HDLC 2 STA %x\n", fc->name, val);
+}
+
+static void
+reset_avm(struct fritzcard *fc)
+{
+ switch (fc->type) {
+ case AVM_FRITZ_PCI:
+ fc->ctrlreg = AVM_STATUS0_RESET | AVM_STATUS0_DIS_TIMER;
+ break;
+ case AVM_FRITZ_PCIV2:
+ fc->ctrlreg = AVM_STATUS0_RESET;
+ break;
+ }
+ if (debug & DEBUG_HW)
+ pr_notice("%s: reset\n", fc->name);
+ disable_hwirq(fc);
+ mdelay(5);
+ switch (fc->type) {
+ case AVM_FRITZ_PCI:
+ fc->ctrlreg = AVM_STATUS0_DIS_TIMER | AVM_STATUS0_RES_TIMER;
+ disable_hwirq(fc);
+ outb(AVM_STATUS1_ENA_IOM, fc->addr + 3);
+ break;
+ case AVM_FRITZ_PCIV2:
+ fc->ctrlreg = 0;
+ disable_hwirq(fc);
+ break;
+ }
+ mdelay(1);
+ if (debug & DEBUG_HW)
+ pr_notice("%s: S0/S1 %x/%x\n", fc->name,
+ inb(fc->addr + 2), inb(fc->addr + 3));
+}
+
+static int
+init_card(struct fritzcard *fc)
+{
+ int ret, cnt = 3;
+ u_long flags;
+
+ reset_avm(fc); /* disable IRQ */
+ if (fc->type == AVM_FRITZ_PCIV2)
+ ret = request_irq(fc->irq, avm_fritzv2_interrupt,
+ IRQF_SHARED, fc->name, fc);
+ else
+ ret = request_irq(fc->irq, avm_fritz_interrupt,
+ IRQF_SHARED, fc->name, fc);
+ if (ret) {
+ pr_info("%s: couldn't get interrupt %d\n",
+ fc->name, fc->irq);
+ return ret;
+ }
+ while (cnt--) {
+ spin_lock_irqsave(&fc->lock, flags);
+ ret = fc->isac.init(&fc->isac);
+ if (ret) {
+ spin_unlock_irqrestore(&fc->lock, flags);
+ pr_info("%s: ISAC init failed with %d\n",
+ fc->name, ret);
+ break;
+ }
+ clear_pending_hdlc_ints(fc);
+ inithdlc(fc);
+ enable_hwirq(fc);
+ /* RESET Receiver and Transmitter */
+ if (AVM_FRITZ_PCIV2 == fc->type) {
+ WriteISAC_V2(fc, ISACX_MASK, 0);
+ WriteISAC_V2(fc, ISACX_CMDRD, 0x41);
+ } else {
+ WriteISAC_V1(fc, ISAC_MASK, 0);
+ WriteISAC_V1(fc, ISAC_CMDR, 0x41);
+ }
+ spin_unlock_irqrestore(&fc->lock, flags);
+ /* Timeout 10ms */
+ msleep_interruptible(10);
+ if (debug & DEBUG_HW)
+ pr_notice("%s: IRQ %d count %d\n", fc->name,
+ fc->irq, fc->irqcnt);
+ if (!fc->irqcnt) {
+ pr_info("%s: IRQ(%d) getting no IRQs during init %d\n",
+ fc->name, fc->irq, 3 - cnt);
+ reset_avm(fc);
+ } else
+ return 0;
+ }
+ free_irq(fc->irq, fc);
+ return -EIO;
+}
+
+static int
+channel_bctrl(struct bchannel *bch, struct mISDN_ctrl_req *cq)
+{
+ int ret = 0;
+ struct fritzcard *fc = bch->hw;
+
+ switch (cq->op) {
+ case MISDN_CTRL_GETOP:
+ cq->op = 0;
+ break;
+ /* Nothing implemented yet */
+ case MISDN_CTRL_FILL_EMPTY:
+ default:
+ pr_info("%s: %s unknown Op %x\n", fc->name, __func__, cq->op);
+ ret = -EINVAL;
+ break;
+ }
+ return ret;
+}
+
+static int
+avm_bctrl(struct mISDNchannel *ch, u32 cmd, void *arg)
+{
+ struct bchannel *bch = container_of(ch, struct bchannel, ch);
+ struct fritzcard *fc = bch->hw;
+ int ret = -EINVAL;
+ u_long flags;
+
+ pr_debug("%s: %s cmd:%x %p\n", fc->name, __func__, cmd, arg);
+ switch (cmd) {
+ case CLOSE_CHANNEL:
+ test_and_clear_bit(FLG_OPEN, &bch->Flags);
+ if (test_bit(FLG_ACTIVE, &bch->Flags)) {
+ spin_lock_irqsave(&fc->lock, flags);
+ mISDN_freebchannel(bch);
+ test_and_clear_bit(FLG_TX_BUSY, &bch->Flags);
+ test_and_clear_bit(FLG_ACTIVE, &bch->Flags);
+ modehdlc(bch, ISDN_P_NONE);
+ spin_unlock_irqrestore(&fc->lock, flags);
+ }
+ ch->protocol = ISDN_P_NONE;
+ ch->peer = NULL;
+ module_put(THIS_MODULE);
+ ret = 0;
+ break;
+ case CONTROL_CHANNEL:
+ ret = channel_bctrl(bch, arg);
+ break;
+ default:
+ pr_info("%s: %s unknown prim(%x)\n", fc->name, __func__, cmd);
+ }
+ return ret;
+}
+
+static int
+channel_ctrl(struct fritzcard *fc, struct mISDN_ctrl_req *cq)
+{
+ int ret = 0;
+
+ switch (cq->op) {
+ case MISDN_CTRL_GETOP:
+ cq->op = MISDN_CTRL_LOOP;
+ break;
+ case MISDN_CTRL_LOOP:
+ /* cq->channel: 0 disable, 1 B1 loop 2 B2 loop, 3 both */
+ if (cq->channel < 0 || cq->channel > 3) {
+ ret = -EINVAL;
+ break;
+ }
+ ret = fc->isac.ctrl(&fc->isac, HW_TESTLOOP, cq->channel);
+ break;
+ default:
+ pr_info("%s: %s unknown Op %x\n", fc->name, __func__, cq->op);
+ ret = -EINVAL;
+ break;
+ }
+ return ret;
+}
+
+static int
+open_bchannel(struct fritzcard *fc, struct channel_req *rq)
+{
+ struct bchannel *bch;
+
+ if (rq->adr.channel > 2)
+ return -EINVAL;
+ if (rq->protocol == ISDN_P_NONE)
+ return -EINVAL;
+ bch = &fc->bch[rq->adr.channel - 1];
+ if (test_and_set_bit(FLG_OPEN, &bch->Flags))
+ return -EBUSY; /* b-channel can be only open once */
+ test_and_clear_bit(FLG_FILLEMPTY, &bch->Flags);
+ bch->ch.protocol = rq->protocol;
+ rq->ch = &bch->ch;
+ return 0;
+}
+
+/*
+ * device control function
+ */
+static int
+avm_dctrl(struct mISDNchannel *ch, u32 cmd, void *arg)
+{
+ struct mISDNdevice *dev = container_of(ch, struct mISDNdevice, D);
+ struct dchannel *dch = container_of(dev, struct dchannel, dev);
+ struct fritzcard *fc = dch->hw;
+ struct channel_req *rq;
+ int err = 0;
+
+ pr_debug("%s: %s cmd:%x %p\n", fc->name, __func__, cmd, arg);
+ switch (cmd) {
+ case OPEN_CHANNEL:
+ rq = arg;
+ if (rq->protocol == ISDN_P_TE_S0)
+ err = fc->isac.open(&fc->isac, rq);
+ else
+ err = open_bchannel(fc, rq);
+ if (err)
+ break;
+ if (!try_module_get(THIS_MODULE))
+ pr_info("%s: cannot get module\n", fc->name);
+ break;
+ case CLOSE_CHANNEL:
+ pr_debug("%s: dev(%d) close from %p\n", fc->name, dch->dev.id,
+ __builtin_return_address(0));
+ module_put(THIS_MODULE);
+ break;
+ case CONTROL_CHANNEL:
+ err = channel_ctrl(fc, arg);
+ break;
+ default:
+ pr_debug("%s: %s unknown command %x\n",
+ fc->name, __func__, cmd);
+ return -EINVAL;
+ }
+ return err;
+}
+
+int
+setup_fritz(struct fritzcard *fc)
+{
+ u32 val, ver;
+
+ if (!request_region(fc->addr, 32, fc->name)) {
+ pr_info("%s: AVM config port %x-%x already in use\n",
+ fc->name, fc->addr, fc->addr + 31);
+ return -EIO;
+ }
+ switch (fc->type) {
+ case AVM_FRITZ_PCI:
+ val = inl(fc->addr);
+ outl(AVM_HDLC_1, fc->addr + CHIP_INDEX);
+ ver = inl(fc->addr + CHIP_WINDOW + HDLC_STATUS) >> 24;
+ if (debug & DEBUG_HW) {
+ pr_notice("%s: PCI stat %#x\n", fc->name, val);
+ pr_notice("%s: PCI Class %X Rev %d\n", fc->name,
+ val & 0xff, (val >> 8) & 0xff);
+ pr_notice("%s: HDLC version %x\n", fc->name, ver & 0xf);
+ }
+ ASSIGN_FUNC(V1, ISAC, fc->isac);
+ fc->isac.type = IPAC_TYPE_ISAC;
+ break;
+ case AVM_FRITZ_PCIV2:
+ val = inl(fc->addr);
+ ver = inl(fc->addr + AVM_HDLC_STATUS_1) >> 24;
+ if (debug & DEBUG_HW) {
+ pr_notice("%s: PCI V2 stat %#x\n", fc->name, val);
+ pr_notice("%s: PCI V2 Class %X Rev %d\n", fc->name,
+ val & 0xff, (val>>8) & 0xff);
+ pr_notice("%s: HDLC version %x\n", fc->name, ver & 0xf);
+ }
+ ASSIGN_FUNC(V2, ISAC, fc->isac);
+ fc->isac.type = IPAC_TYPE_ISACX;
+ break;
+ default:
+ release_region(fc->addr, 32);
+ pr_info("%s: AVM unknown type %d\n", fc->name, fc->type);
+ return -ENODEV;
+ }
+ pr_notice("%s: %s config irq:%d base:0x%X\n", fc->name,
+ (fc->type == AVM_FRITZ_PCI) ? "AVM Fritz!CARD PCI" :
+ "AVM Fritz!CARD PCIv2", fc->irq, fc->addr);
+ return 0;
+}
+
+static void
+release_card(struct fritzcard *card)
+{
+ u_long flags;
+
+ disable_hwirq(card);
+ spin_lock_irqsave(&card->lock, flags);
+ modehdlc(&card->bch[0], ISDN_P_NONE);
+ modehdlc(&card->bch[1], ISDN_P_NONE);
+ spin_unlock_irqrestore(&card->lock, flags);
+ card->isac.release(&card->isac);
+ free_irq(card->irq, card);
+ mISDN_freebchannel(&card->bch[1]);
+ mISDN_freebchannel(&card->bch[0]);
+ mISDN_unregister_device(&card->isac.dch.dev);
+ release_region(card->addr, 32);
+ pci_disable_device(card->pdev);
+ pci_set_drvdata(card->pdev, NULL);
+ write_lock_irqsave(&card_lock, flags);
+ list_del(&card->list);
+ write_unlock_irqrestore(&card_lock, flags);
+ kfree(card);
+ AVM_cnt--;
+}
+
+static int __devinit
+setup_instance(struct fritzcard *card)
+{
+ int i, err;
+ u_long flags;
+
+ snprintf(card->name, MISDN_MAX_IDLEN - 1, "AVM.%d", AVM_cnt + 1);
+ write_lock_irqsave(&card_lock, flags);
+ list_add_tail(&card->list, &Cards);
+ write_unlock_irqrestore(&card_lock, flags);
+
+ _set_debug(card);
+ card->isac.name = card->name;
+ spin_lock_init(&card->lock);
+ card->isac.hwlock = &card->lock;
+ mISDNisac_init(&card->isac, card);
+
+ card->isac.dch.dev.Bprotocols = (1 << (ISDN_P_B_RAW & ISDN_P_B_MASK)) |
+ (1 << (ISDN_P_B_HDLC & ISDN_P_B_MASK));
+ card->isac.dch.dev.D.ctrl = avm_dctrl;
+ for (i = 0; i < 2; i++) {
+ card->bch[i].nr = i + 1;
+ set_channelmap(i + 1, card->isac.dch.dev.channelmap);
+ mISDN_initbchannel(&card->bch[i], MAX_DATA_MEM);
+ card->bch[i].hw = card;
+ card->bch[i].ch.send = avm_l2l1B;
+ card->bch[i].ch.ctrl = avm_bctrl;
+ card->bch[i].ch.nr = i + 1;
+ list_add(&card->bch[i].ch.list, &card->isac.dch.dev.bchannels);
+ }
+ err = setup_fritz(card);
+ if (err)
+ goto error;
+ err = mISDN_register_device(&card->isac.dch.dev, &card->pdev->dev,
+ card->name);
+ if (err)
+ goto error_reg;
+ err = init_card(card);
+ if (!err) {
+ AVM_cnt++;
+ pr_notice("AVM %d cards installed DEBUG\n", AVM_cnt);
+ return 0;
+ }
+ mISDN_unregister_device(&card->isac.dch.dev);
+error_reg:
+ release_region(card->addr, 32);
+error:
+ card->isac.release(&card->isac);
+ mISDN_freebchannel(&card->bch[1]);
+ mISDN_freebchannel(&card->bch[0]);
+ write_lock_irqsave(&card_lock, flags);
+ list_del(&card->list);
+ write_unlock_irqrestore(&card_lock, flags);
+ kfree(card);
+ return err;
+}
+
+static int __devinit
+fritzpci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+ int err = -ENOMEM;
+ struct fritzcard *card;
+
+ card = kzalloc(sizeof(struct fritzcard), GFP_KERNEL);
+ if (!card) {
+ pr_info("No kmem for fritzcard\n");
+ return err;
+ }
+ if (pdev->device == PCI_DEVICE_ID_AVM_A1_V2)
+ card->type = AVM_FRITZ_PCIV2;
+ else
+ card->type = AVM_FRITZ_PCI;
+ card->pdev = pdev;
+ err = pci_enable_device(pdev);
+ if (err) {
+ kfree(card);
+ return err;
+ }
+
+ pr_notice("mISDN: found adapter %s at %s\n",
+ (char *) ent->driver_data, pci_name(pdev));
+
+ card->addr = pci_resource_start(pdev, 1);
+ card->irq = pdev->irq;
+ pci_set_drvdata(pdev, card);
+ err = setup_instance(card);
+ if (err)
+ pci_set_drvdata(pdev, NULL);
+ return err;
+}
+
+static void __devexit
+fritz_remove_pci(struct pci_dev *pdev)
+{
+ struct fritzcard *card = pci_get_drvdata(pdev);
+
+ if (card)
+ release_card(card);
+ else
+ if (debug)
+ pr_info("%s: drvdata allready removed\n", __func__);
+}
+
+static struct pci_device_id fcpci_ids[] __devinitdata = {
+ { PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_A1, PCI_ANY_ID, PCI_ANY_ID,
+ 0, 0, (unsigned long) "Fritz!Card PCI"},
+ { PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_A1_V2, PCI_ANY_ID, PCI_ANY_ID,
+ 0, 0, (unsigned long) "Fritz!Card PCI v2" },
+ { }
+};
+MODULE_DEVICE_TABLE(pci, fcpci_ids);
+
+static struct pci_driver fcpci_driver = {
+ .name = "fcpci",
+ .probe = fritzpci_probe,
+ .remove = __devexit_p(fritz_remove_pci),
+ .id_table = fcpci_ids,
+};
+
+static int __init AVM_init(void)
+{
+ int err;
+
+ pr_notice("AVM Fritz PCI driver Rev. %s\n", AVMFRITZ_REV);
+ err = pci_register_driver(&fcpci_driver);
+ return err;
+}
+
+static void __exit AVM_cleanup(void)
+{
+ pci_unregister_driver(&fcpci_driver);
+}
+
+module_init(AVM_init);
+module_exit(AVM_cleanup);
diff --git a/drivers/isdn/hardware/mISDN/hfcmulti.c b/drivers/isdn/hardware/mISDN/hfcmulti.c
index e1dab30aed3..faed794cf75 100644
--- a/drivers/isdn/hardware/mISDN/hfcmulti.c
+++ b/drivers/isdn/hardware/mISDN/hfcmulti.c
@@ -3416,22 +3416,8 @@ deactivate_bchannel(struct bchannel *bch)
u_long flags;
spin_lock_irqsave(&hc->lock, flags);
- if (test_and_clear_bit(FLG_TX_NEXT, &bch->Flags)) {
- dev_kfree_skb(bch->next_skb);
- bch->next_skb = NULL;
- }
- if (bch->tx_skb) {
- dev_kfree_skb(bch->tx_skb);
- bch->tx_skb = NULL;
- }
- bch->tx_idx = 0;
- if (bch->rx_skb) {
- dev_kfree_skb(bch->rx_skb);
- bch->rx_skb = NULL;
- }
+ mISDN_clear_bchannel(bch);
hc->chan[bch->slot].coeff_count = 0;
- test_and_clear_bit(FLG_ACTIVE, &bch->Flags);
- test_and_clear_bit(FLG_TX_BUSY, &bch->Flags);
hc->chan[bch->slot].rx_off = 0;
hc->chan[bch->slot].conf = -1;
mode_hfcmulti(hc, bch->slot, ISDN_P_NONE, -1, 0, -1, 0);
@@ -5384,9 +5370,10 @@ hfcmulti_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
ent->device == PCI_DEVICE_ID_CCD_HFC8S ||
ent->device == PCI_DEVICE_ID_CCD_HFCE1)) {
printk(KERN_ERR
- "Unknown HFC multiport controller (vendor:%x device:%x "
- "subvendor:%x subdevice:%x)\n", ent->vendor, ent->device,
- ent->subvendor, ent->subdevice);
+ "Unknown HFC multiport controller (vendor:%04x device:%04x "
+ "subvendor:%04x subdevice:%04x)\n", pdev->vendor,
+ pdev->device, pdev->subsystem_vendor,
+ pdev->subsystem_device);
printk(KERN_ERR
"Please contact the driver maintainer for support.\n");
return -ENODEV;
diff --git a/drivers/isdn/hardware/mISDN/hfcpci.c b/drivers/isdn/hardware/mISDN/hfcpci.c
index 228ffbed128..70e6b0e0112 100644
--- a/drivers/isdn/hardware/mISDN/hfcpci.c
+++ b/drivers/isdn/hardware/mISDN/hfcpci.c
@@ -1522,22 +1522,8 @@ deactivate_bchannel(struct bchannel *bch)
u_long flags;
spin_lock_irqsave(&hc->lock, flags);
- if (test_and_clear_bit(FLG_TX_NEXT, &bch->Flags)) {
- dev_kfree_skb(bch->next_skb);
- bch->next_skb = NULL;
- }
- if (bch->tx_skb) {
- dev_kfree_skb(bch->tx_skb);
- bch->tx_skb = NULL;
- }
- bch->tx_idx = 0;
- if (bch->rx_skb) {
- dev_kfree_skb(bch->rx_skb);
- bch->rx_skb = NULL;
- }
+ mISDN_clear_bchannel(bch);
mode_hfcpci(bch, bch->nr, ISDN_P_NONE);
- test_and_clear_bit(FLG_ACTIVE, &bch->Flags);
- test_and_clear_bit(FLG_TX_BUSY, &bch->Flags);
spin_unlock_irqrestore(&hc->lock, flags);
}
diff --git a/drivers/isdn/hardware/mISDN/hfcsusb.c b/drivers/isdn/hardware/mISDN/hfcsusb.c
index 6b7704c41b9..fc46a26cb14 100644
--- a/drivers/isdn/hardware/mISDN/hfcsusb.c
+++ b/drivers/isdn/hardware/mISDN/hfcsusb.c
@@ -1809,21 +1809,7 @@ deactivate_bchannel(struct bchannel *bch)
hw->name, __func__, bch->nr);
spin_lock_irqsave(&hw->lock, flags);
- if (test_and_clear_bit(FLG_TX_NEXT, &bch->Flags)) {
- dev_kfree_skb(bch->next_skb);
- bch->next_skb = NULL;
- }
- if (bch->tx_skb) {
- dev_kfree_skb(bch->tx_skb);
- bch->tx_skb = NULL;
- }
- bch->tx_idx = 0;
- if (bch->rx_skb) {
- dev_kfree_skb(bch->rx_skb);
- bch->rx_skb = NULL;
- }
- clear_bit(FLG_ACTIVE, &bch->Flags);
- clear_bit(FLG_TX_BUSY, &bch->Flags);
+ mISDN_clear_bchannel(bch);
spin_unlock_irqrestore(&hw->lock, flags);
hfcsusb_setup_bch(bch, ISDN_P_NONE);
hfcsusb_stop_endpoint(hw, bch->nr);
diff --git a/drivers/isdn/hardware/mISDN/iohelper.h b/drivers/isdn/hardware/mISDN/iohelper.h
new file mode 100644
index 00000000000..b438981107a
--- /dev/null
+++ b/drivers/isdn/hardware/mISDN/iohelper.h
@@ -0,0 +1,109 @@
+/*
+ * iohelper.h
+ * helper for define functions to access ISDN hardware
+ * supported are memory mapped IO
+ * indirect port IO (one port for address, one for data)
+ *
+ * Author Karsten Keil <keil@isdn4linux.de>
+ *
+ * Copyright 2009 by Karsten Keil <keil@isdn4linux.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#ifndef _IOHELPER_H
+#define _IOHELPER_H
+
+typedef u8 (read_reg_func)(void *hwp, u8 offset);
+typedef void (write_reg_func)(void *hwp, u8 offset, u8 value);
+typedef void (fifo_func)(void *hwp, u8 offset, u8 *datap, int size);
+
+struct _ioport {
+ u32 port;
+ u32 ale;
+};
+
+#define IOFUNC_IO(name, hws, ap) \
+ static u8 Read##name##_IO(void *p, u8 off) {\
+ struct hws *hw = p;\
+ return inb(hw->ap.port + off);\
+ } \
+ static void Write##name##_IO(void *p, u8 off, u8 val) {\
+ struct hws *hw = p;\
+ outb(val, hw->ap.port + off);\
+ } \
+ static void ReadFiFo##name##_IO(void *p, u8 off, u8 *dp, int size) {\
+ struct hws *hw = p;\
+ insb(hw->ap.port + off, dp, size);\
+ } \
+ static void WriteFiFo##name##_IO(void *p, u8 off, u8 *dp, int size) {\
+ struct hws *hw = p;\
+ outsb(hw->ap.port + off, dp, size);\
+ }
+
+#define IOFUNC_IND(name, hws, ap) \
+ static u8 Read##name##_IND(void *p, u8 off) {\
+ struct hws *hw = p;\
+ outb(off, hw->ap.ale);\
+ return inb(hw->ap.port);\
+ } \
+ static void Write##name##_IND(void *p, u8 off, u8 val) {\
+ struct hws *hw = p;\
+ outb(off, hw->ap.ale);\
+ outb(val, hw->ap.port);\
+ } \
+ static void ReadFiFo##name##_IND(void *p, u8 off, u8 *dp, int size) {\
+ struct hws *hw = p;\
+ outb(off, hw->ap.ale);\
+ insb(hw->ap.port, dp, size);\
+ } \
+ static void WriteFiFo##name##_IND(void *p, u8 off, u8 *dp, int size) {\
+ struct hws *hw = p;\
+ outb(off, hw->ap.ale);\
+ outsb(hw->ap.port, dp, size);\
+ }
+
+#define IOFUNC_MEMIO(name, hws, typ, adr) \
+ static u8 Read##name##_MIO(void *p, u8 off) {\
+ struct hws *hw = p;\
+ return readb(((typ *)hw->adr) + off);\
+ } \
+ static void Write##name##_MIO(void *p, u8 off, u8 val) {\
+ struct hws *hw = p;\
+ writeb(val, ((typ *)hw->adr) + off);\
+ } \
+ static void ReadFiFo##name##_MIO(void *p, u8 off, u8 *dp, int size) {\
+ struct hws *hw = p;\
+ while (size--)\
+ *dp++ = readb(((typ *)hw->adr) + off);\
+ } \
+ static void WriteFiFo##name##_MIO(void *p, u8 off, u8 *dp, int size) {\
+ struct hws *hw = p;\
+ while (size--)\
+ writeb(*dp++, ((typ *)hw->adr) + off);\
+ }
+
+#define ASSIGN_FUNC(typ, name, dest) do {\
+ dest.read_reg = &Read##name##_##typ;\
+ dest.write_reg = &Write##name##_##typ;\
+ dest.read_fifo = &ReadFiFo##name##_##typ;\
+ dest.write_fifo = &WriteFiFo##name##_##typ;\
+ } while (0)
+#define ASSIGN_FUNC_IPAC(typ, target) do {\
+ ASSIGN_FUNC(typ, ISAC, target.isac);\
+ ASSIGN_FUNC(typ, IPAC, target);\
+ } while (0)
+
+#endif
diff --git a/drivers/isdn/hardware/mISDN/ipac.h b/drivers/isdn/hardware/mISDN/ipac.h
new file mode 100644
index 00000000000..74a6ccf9065
--- /dev/null
+++ b/drivers/isdn/hardware/mISDN/ipac.h
@@ -0,0 +1,405 @@
+/*
+ *
+ * ipac.h Defines for the Infineon (former Siemens) ISDN
+ * chip series
+ *
+ * Author Karsten Keil <keil@isdn4linux.de>
+ *
+ * Copyright 2009 by Karsten Keil <keil@isdn4linux.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include "iohelper.h"
+
+struct isac_hw {
+ struct dchannel dch;
+ u32 type;
+ u32 off; /* offset to isac regs */
+ char *name;
+ spinlock_t *hwlock; /* lock HW acccess */
+ read_reg_func *read_reg;
+ write_reg_func *write_reg;
+ fifo_func *read_fifo;
+ fifo_func *write_fifo;
+ int (*monitor)(void *, u32, u8 *, int);
+ void (*release)(struct isac_hw *);
+ int (*init)(struct isac_hw *);
+ int (*ctrl)(struct isac_hw *, u32, u_long);
+ int (*open)(struct isac_hw *, struct channel_req *);
+ u8 *mon_tx;
+ u8 *mon_rx;
+ int mon_txp;
+ int mon_txc;
+ int mon_rxp;
+ struct arcofi_msg *arcofi_list;
+ struct timer_list arcofitimer;
+ wait_queue_head_t arcofi_wait;
+ u8 arcofi_bc;
+ u8 arcofi_state;
+ u8 mocr;
+ u8 adf2;
+ u8 state;
+};
+
+struct ipac_hw;
+
+struct hscx_hw {
+ struct bchannel bch;
+ struct ipac_hw *ip;
+ u8 fifo_size;
+ u8 off; /* offset to ICA or ICB */
+ u8 slot;
+ char log[64];
+};
+
+struct ipac_hw {
+ struct isac_hw isac;
+ struct hscx_hw hscx[2];
+ char *name;
+ void *hw;
+ spinlock_t *hwlock; /* lock HW acccess */
+ struct module *owner;
+ u32 type;
+ read_reg_func *read_reg;
+ write_reg_func *write_reg;
+ fifo_func *read_fifo;
+ fifo_func *write_fifo;
+ void (*release)(struct ipac_hw *);
+ int (*init)(struct ipac_hw *);
+ int (*ctrl)(struct ipac_hw *, u32, u_long);
+ u8 conf;
+};
+
+#define IPAC_TYPE_ISAC 0x0010
+#define IPAC_TYPE_IPAC 0x0020
+#define IPAC_TYPE_ISACX 0x0040
+#define IPAC_TYPE_IPACX 0x0080
+#define IPAC_TYPE_HSCX 0x0100
+
+#define ISAC_USE_ARCOFI 0x1000
+
+/* Monitor functions */
+#define MONITOR_RX_0 0x1000
+#define MONITOR_RX_1 0x1001
+#define MONITOR_TX_0 0x2000
+#define MONITOR_TX_1 0x2001
+
+/* All registers original Siemens Spec */
+/* IPAC/ISAC registers */
+#define ISAC_MASK 0x20
+#define ISAC_ISTA 0x20
+#define ISAC_STAR 0x21
+#define ISAC_CMDR 0x21
+#define ISAC_EXIR 0x24
+#define ISAC_ADF2 0x39
+#define ISAC_SPCR 0x30
+#define ISAC_ADF1 0x38
+#define ISAC_CIR0 0x31
+#define ISAC_CIX0 0x31
+#define ISAC_CIR1 0x33
+#define ISAC_CIX1 0x33
+#define ISAC_STCR 0x37
+#define ISAC_MODE 0x22
+#define ISAC_RSTA 0x27
+#define ISAC_RBCL 0x25
+#define ISAC_RBCH 0x2A
+#define ISAC_TIMR 0x23
+#define ISAC_SQXR 0x3b
+#define ISAC_SQRR 0x3b
+#define ISAC_MOSR 0x3a
+#define ISAC_MOCR 0x3a
+#define ISAC_MOR0 0x32
+#define ISAC_MOX0 0x32
+#define ISAC_MOR1 0x34
+#define ISAC_MOX1 0x34
+
+#define ISAC_RBCH_XAC 0x80
+
+#define IPAC_D_TIN2 0x01
+
+/* IPAC/HSCX */
+#define IPAC_ISTAB 0x20 /* RD */
+#define IPAC_MASKB 0x20 /* WR */
+#define IPAC_STARB 0x21 /* RD */
+#define IPAC_CMDRB 0x21 /* WR */
+#define IPAC_MODEB 0x22 /* R/W */
+#define IPAC_EXIRB 0x24 /* RD */
+#define IPAC_RBCLB 0x25 /* RD */
+#define IPAC_RAH1 0x26 /* WR */
+#define IPAC_RAH2 0x27 /* WR */
+#define IPAC_RSTAB 0x27 /* RD */
+#define IPAC_RAL1 0x28 /* R/W */
+#define IPAC_RAL2 0x29 /* WR */
+#define IPAC_RHCRB 0x29 /* RD */
+#define IPAC_XBCL 0x2A /* WR */
+#define IPAC_CCR2 0x2C /* R/W */
+#define IPAC_RBCHB 0x2D /* RD */
+#define IPAC_XBCH 0x2D /* WR */
+#define HSCX_VSTR 0x2E /* RD */
+#define IPAC_RLCR 0x2E /* WR */
+#define IPAC_CCR1 0x2F /* R/W */
+#define IPAC_TSAX 0x30 /* WR */
+#define IPAC_TSAR 0x31 /* WR */
+#define IPAC_XCCR 0x32 /* WR */
+#define IPAC_RCCR 0x33 /* WR */
+
+/* IPAC_ISTAB/IPAC_MASKB bits */
+#define IPAC_B_XPR 0x10
+#define IPAC_B_RPF 0x40
+#define IPAC_B_RME 0x80
+#define IPAC_B_ON 0x2F
+
+/* IPAC_EXIRB bits */
+#define IPAC_B_RFS 0x04
+#define IPAC_B_RFO 0x10
+#define IPAC_B_XDU 0x40
+#define IPAC_B_XMR 0x80
+
+/* IPAC special registers */
+#define IPAC_CONF 0xC0 /* R/W */
+#define IPAC_ISTA 0xC1 /* RD */
+#define IPAC_MASK 0xC1 /* WR */
+#define IPAC_ID 0xC2 /* RD */
+#define IPAC_ACFG 0xC3 /* R/W */
+#define IPAC_AOE 0xC4 /* R/W */
+#define IPAC_ARX 0xC5 /* RD */
+#define IPAC_ATX 0xC5 /* WR */
+#define IPAC_PITA1 0xC6 /* R/W */
+#define IPAC_PITA2 0xC7 /* R/W */
+#define IPAC_POTA1 0xC8 /* R/W */
+#define IPAC_POTA2 0xC9 /* R/W */
+#define IPAC_PCFG 0xCA /* R/W */
+#define IPAC_SCFG 0xCB /* R/W */
+#define IPAC_TIMR2 0xCC /* R/W */
+
+/* IPAC_ISTA/_MASK bits */
+#define IPAC__EXB 0x01
+#define IPAC__ICB 0x02
+#define IPAC__EXA 0x04
+#define IPAC__ICA 0x08
+#define IPAC__EXD 0x10
+#define IPAC__ICD 0x20
+#define IPAC__INT0 0x40
+#define IPAC__INT1 0x80
+#define IPAC__ON 0xC0
+
+/* HSCX ISTA/MASK bits */
+#define HSCX__EXB 0x01
+#define HSCX__EXA 0x02
+#define HSCX__ICA 0x04
+
+/* ISAC/ISACX/IPAC/IPACX L1 commands */
+#define ISAC_CMD_TIM 0x0
+#define ISAC_CMD_RS 0x1
+#define ISAC_CMD_SCZ 0x4
+#define ISAC_CMD_SSZ 0x2
+#define ISAC_CMD_AR8 0x8
+#define ISAC_CMD_AR10 0x9
+#define ISAC_CMD_ARL 0xA
+#define ISAC_CMD_DUI 0xF
+
+/* ISAC/ISACX/IPAC/IPACX L1 indications */
+#define ISAC_IND_RS 0x1
+#define ISAC_IND_PU 0x7
+#define ISAC_IND_DR 0x0
+#define ISAC_IND_SD 0x2
+#define ISAC_IND_DIS 0x3
+#define ISAC_IND_EI 0x6
+#define ISAC_IND_RSY 0x4
+#define ISAC_IND_ARD 0x8
+#define ISAC_IND_TI 0xA
+#define ISAC_IND_ATI 0xB
+#define ISAC_IND_AI8 0xC
+#define ISAC_IND_AI10 0xD
+#define ISAC_IND_DID 0xF
+
+/* the new ISACX / IPACX */
+/* D-channel registers */
+#define ISACX_RFIFOD 0x00 /* RD */
+#define ISACX_XFIFOD 0x00 /* WR */
+#define ISACX_ISTAD 0x20 /* RD */
+#define ISACX_MASKD 0x20 /* WR */
+#define ISACX_STARD 0x21 /* RD */
+#define ISACX_CMDRD 0x21 /* WR */
+#define ISACX_MODED 0x22 /* R/W */
+#define ISACX_EXMD1 0x23 /* R/W */
+#define ISACX_TIMR1 0x24 /* R/W */
+#define ISACX_SAP1 0x25 /* WR */
+#define ISACX_SAP2 0x26 /* WR */
+#define ISACX_RBCLD 0x26 /* RD */
+#define ISACX_RBCHD 0x27 /* RD */
+#define ISACX_TEI1 0x27 /* WR */
+#define ISACX_TEI2 0x28 /* WR */
+#define ISACX_RSTAD 0x28 /* RD */
+#define ISACX_TMD 0x29 /* R/W */
+#define ISACX_CIR0 0x2E /* RD */
+#define ISACX_CIX0 0x2E /* WR */
+#define ISACX_CIR1 0x2F /* RD */
+#define ISACX_CIX1 0x2F /* WR */
+
+/* Transceiver registers */
+#define ISACX_TR_CONF0 0x30 /* R/W */
+#define ISACX_TR_CONF1 0x31 /* R/W */
+#define ISACX_TR_CONF2 0x32 /* R/W */
+#define ISACX_TR_STA 0x33 /* RD */
+#define ISACX_TR_CMD 0x34 /* R/W */
+#define ISACX_SQRR1 0x35 /* RD */
+#define ISACX_SQXR1 0x35 /* WR */
+#define ISACX_SQRR2 0x36 /* RD */
+#define ISACX_SQXR2 0x36 /* WR */
+#define ISACX_SQRR3 0x37 /* RD */
+#define ISACX_SQXR3 0x37 /* WR */
+#define ISACX_ISTATR 0x38 /* RD */
+#define ISACX_MASKTR 0x39 /* R/W */
+#define ISACX_TR_MODE 0x3A /* R/W */
+#define ISACX_ACFG1 0x3C /* R/W */
+#define ISACX_ACFG2 0x3D /* R/W */
+#define ISACX_AOE 0x3E /* R/W */
+#define ISACX_ARX 0x3F /* RD */
+#define ISACX_ATX 0x3F /* WR */
+
+/* IOM: Timeslot, DPS, CDA */
+#define ISACX_CDA10 0x40 /* R/W */
+#define ISACX_CDA11 0x41 /* R/W */
+#define ISACX_CDA20 0x42 /* R/W */
+#define ISACX_CDA21 0x43 /* R/W */
+#define ISACX_CDA_TSDP10 0x44 /* R/W */
+#define ISACX_CDA_TSDP11 0x45 /* R/W */
+#define ISACX_CDA_TSDP20 0x46 /* R/W */
+#define ISACX_CDA_TSDP21 0x47 /* R/W */
+#define ISACX_BCHA_TSDP_BC1 0x48 /* R/W */
+#define ISACX_BCHA_TSDP_BC2 0x49 /* R/W */
+#define ISACX_BCHB_TSDP_BC1 0x4A /* R/W */
+#define ISACX_BCHB_TSDP_BC2 0x4B /* R/W */
+#define ISACX_TR_TSDP_BC1 0x4C /* R/W */
+#define ISACX_TR_TSDP_BC2 0x4D /* R/W */
+#define ISACX_CDA1_CR 0x4E /* R/W */
+#define ISACX_CDA2_CR 0x4F /* R/W */
+
+/* IOM: Contol, Sync transfer, Monitor */
+#define ISACX_TR_CR 0x50 /* R/W */
+#define ISACX_TRC_CR 0x50 /* R/W */
+#define ISACX_BCHA_CR 0x51 /* R/W */
+#define ISACX_BCHB_CR 0x52 /* R/W */
+#define ISACX_DCI_CR 0x53 /* R/W */
+#define ISACX_DCIC_CR 0x53 /* R/W */
+#define ISACX_MON_CR 0x54 /* R/W */
+#define ISACX_SDS1_CR 0x55 /* R/W */
+#define ISACX_SDS2_CR 0x56 /* R/W */
+#define ISACX_IOM_CR 0x57 /* R/W */
+#define ISACX_STI 0x58 /* RD */
+#define ISACX_ASTI 0x58 /* WR */
+#define ISACX_MSTI 0x59 /* R/W */
+#define ISACX_SDS_CONF 0x5A /* R/W */
+#define ISACX_MCDA 0x5B /* RD */
+#define ISACX_MOR 0x5C /* RD */
+#define ISACX_MOX 0x5C /* WR */
+#define ISACX_MOSR 0x5D /* RD */
+#define ISACX_MOCR 0x5E /* R/W */
+#define ISACX_MSTA 0x5F /* RD */
+#define ISACX_MCONF 0x5F /* WR */
+
+/* Interrupt and general registers */
+#define ISACX_ISTA 0x60 /* RD */
+#define ISACX_MASK 0x60 /* WR */
+#define ISACX_AUXI 0x61 /* RD */
+#define ISACX_AUXM 0x61 /* WR */
+#define ISACX_MODE1 0x62 /* R/W */
+#define ISACX_MODE2 0x63 /* R/W */
+#define ISACX_ID 0x64 /* RD */
+#define ISACX_SRES 0x64 /* WR */
+#define ISACX_TIMR2 0x65 /* R/W */
+
+/* Register Bits */
+/* ISACX/IPACX _ISTAD (R) and _MASKD (W) */
+#define ISACX_D_XDU 0x04
+#define ISACX_D_XMR 0x08
+#define ISACX_D_XPR 0x10
+#define ISACX_D_RFO 0x20
+#define ISACX_D_RPF 0x40
+#define ISACX_D_RME 0x80
+
+/* ISACX/IPACX _ISTA (R) and _MASK (W) */
+#define ISACX__ICD 0x01
+#define ISACX__MOS 0x02
+#define ISACX__TRAN 0x04
+#define ISACX__AUX 0x08
+#define ISACX__CIC 0x10
+#define ISACX__ST 0x20
+#define IPACX__ICB 0x40
+#define IPACX__ICA 0x80
+#define IPACX__ON 0x2C
+
+/* ISACX/IPACX _CMDRD (W) */
+#define ISACX_CMDRD_XRES 0x01
+#define ISACX_CMDRD_XME 0x02
+#define ISACX_CMDRD_XTF 0x08
+#define ISACX_CMDRD_STI 0x10
+#define ISACX_CMDRD_RRES 0x40
+#define ISACX_CMDRD_RMC 0x80
+
+/* ISACX/IPACX _RSTAD (R) */
+#define ISACX_RSTAD_TA 0x01
+#define ISACX_RSTAD_CR 0x02
+#define ISACX_RSTAD_SA0 0x04
+#define ISACX_RSTAD_SA1 0x08
+#define ISACX_RSTAD_RAB 0x10
+#define ISACX_RSTAD_CRC 0x20
+#define ISACX_RSTAD_RDO 0x40
+#define ISACX_RSTAD_VFR 0x80
+
+/* ISACX/IPACX _CIR0 (R) */
+#define ISACX_CIR0_BAS 0x01
+#define ISACX_CIR0_SG 0x08
+#define ISACX_CIR0_CIC1 0x08
+#define ISACX_CIR0_CIC0 0x08
+
+/* B-channel registers */
+#define IPACX_OFF_ICA 0x70
+#define IPACX_OFF_ICB 0x80
+
+/* ICA: IPACX_OFF_ICA + Reg ICB: IPACX_OFF_ICB + Reg */
+
+#define IPACX_ISTAB 0x00 /* RD */
+#define IPACX_MASKB 0x00 /* WR */
+#define IPACX_STARB 0x01 /* RD */
+#define IPACX_CMDRB 0x01 /* WR */
+#define IPACX_MODEB 0x02 /* R/W */
+#define IPACX_EXMB 0x03 /* R/W */
+#define IPACX_RAH1 0x05 /* WR */
+#define IPACX_RAH2 0x06 /* WR */
+#define IPACX_RBCLB 0x06 /* RD */
+#define IPACX_RBCHB 0x07 /* RD */
+#define IPACX_RAL1 0x07 /* WR */
+#define IPACX_RAL2 0x08 /* WR */
+#define IPACX_RSTAB 0x08 /* RD */
+#define IPACX_TMB 0x09 /* R/W */
+#define IPACX_RFIFOB 0x0A /* RD */
+#define IPACX_XFIFOB 0x0A /* WR */
+
+/* IPACX_ISTAB / IPACX_MASKB bits */
+#define IPACX_B_XDU 0x04
+#define IPACX_B_XPR 0x10
+#define IPACX_B_RFO 0x20
+#define IPACX_B_RPF 0x40
+#define IPACX_B_RME 0x80
+
+#define IPACX_B_ON 0x0B
+
+extern int mISDNisac_init(struct isac_hw *, void *);
+extern irqreturn_t mISDNisac_irq(struct isac_hw *, u8);
+extern u32 mISDNipac_init(struct ipac_hw *, void *);
+extern irqreturn_t mISDNipac_irq(struct ipac_hw *, int);
diff --git a/drivers/isdn/hardware/mISDN/isar.h b/drivers/isdn/hardware/mISDN/isar.h
new file mode 100644
index 00000000000..4a134acd44d
--- /dev/null
+++ b/drivers/isdn/hardware/mISDN/isar.h
@@ -0,0 +1,269 @@
+/*
+ *
+ * isar.h ISAR (Siemens PSB 7110) specific defines
+ *
+ * Author Karsten Keil (keil@isdn4linux.de)
+ *
+ * Copyright 2009 by Karsten Keil <keil@isdn4linux.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include "iohelper.h"
+
+struct isar_hw;
+
+struct isar_ch {
+ struct bchannel bch;
+ struct isar_hw *is;
+ struct timer_list ftimer;
+ u8 nr;
+ u8 dpath;
+ u8 mml;
+ u8 state;
+ u8 cmd;
+ u8 mod;
+ u8 newcmd;
+ u8 newmod;
+ u8 try_mod;
+ u8 conmsg[16];
+};
+
+struct isar_hw {
+ struct isar_ch ch[2];
+ void *hw;
+ spinlock_t *hwlock; /* lock HW acccess */
+ char *name;
+ struct module *owner;
+ read_reg_func *read_reg;
+ write_reg_func *write_reg;
+ fifo_func *read_fifo;
+ fifo_func *write_fifo;
+ int (*ctrl)(void *, u32, u_long);
+ void (*release)(struct isar_hw *);
+ int (*init)(struct isar_hw *);
+ int (*open)(struct isar_hw *, struct channel_req *);
+ int (*firmware)(struct isar_hw *, const u8 *, int);
+ unsigned long Flags;
+ int version;
+ u8 bstat;
+ u8 iis;
+ u8 cmsb;
+ u8 clsb;
+ u8 buf[256];
+ u8 log[256];
+};
+
+#define ISAR_IRQMSK 0x04
+#define ISAR_IRQSTA 0x04
+#define ISAR_IRQBIT 0x75
+#define ISAR_CTRL_H 0x61
+#define ISAR_CTRL_L 0x60
+#define ISAR_IIS 0x58
+#define ISAR_IIA 0x58
+#define ISAR_HIS 0x50
+#define ISAR_HIA 0x50
+#define ISAR_MBOX 0x4c
+#define ISAR_WADR 0x4a
+#define ISAR_RADR 0x48
+
+#define ISAR_HIS_VNR 0x14
+#define ISAR_HIS_DKEY 0x02
+#define ISAR_HIS_FIRM 0x1e
+#define ISAR_HIS_STDSP 0x08
+#define ISAR_HIS_DIAG 0x05
+#define ISAR_HIS_P0CFG 0x3c
+#define ISAR_HIS_P12CFG 0x24
+#define ISAR_HIS_SARTCFG 0x25
+#define ISAR_HIS_PUMPCFG 0x26
+#define ISAR_HIS_PUMPCTRL 0x2a
+#define ISAR_HIS_IOM2CFG 0x27
+#define ISAR_HIS_IOM2REQ 0x07
+#define ISAR_HIS_IOM2CTRL 0x2b
+#define ISAR_HIS_BSTREQ 0x0c
+#define ISAR_HIS_PSTREQ 0x0e
+#define ISAR_HIS_SDATA 0x20
+#define ISAR_HIS_DPS1 0x40
+#define ISAR_HIS_DPS2 0x80
+#define SET_DPS(x) ((x<<6) & 0xc0)
+
+#define ISAR_IIS_MSCMSD 0x3f
+#define ISAR_IIS_VNR 0x15
+#define ISAR_IIS_DKEY 0x03
+#define ISAR_IIS_FIRM 0x1f
+#define ISAR_IIS_STDSP 0x09
+#define ISAR_IIS_DIAG 0x25
+#define ISAR_IIS_GSTEV 0x00
+#define ISAR_IIS_BSTEV 0x28
+#define ISAR_IIS_BSTRSP 0x2c
+#define ISAR_IIS_PSTRSP 0x2e
+#define ISAR_IIS_PSTEV 0x2a
+#define ISAR_IIS_IOM2RSP 0x27
+#define ISAR_IIS_RDATA 0x20
+#define ISAR_IIS_INVMSG 0x3f
+
+#define ISAR_CTRL_SWVER 0x10
+#define ISAR_CTRL_STST 0x40
+
+#define ISAR_MSG_HWVER 0x20
+
+#define ISAR_DP1_USE 1
+#define ISAR_DP2_USE 2
+#define ISAR_RATE_REQ 3
+
+#define PMOD_DISABLE 0
+#define PMOD_FAX 1
+#define PMOD_DATAMODEM 2
+#define PMOD_HALFDUPLEX 3
+#define PMOD_V110 4
+#define PMOD_DTMF 5
+#define PMOD_DTMF_TRANS 6
+#define PMOD_BYPASS 7
+
+#define PCTRL_ORIG 0x80
+#define PV32P2_V23R 0x40
+#define PV32P2_V22A 0x20
+#define PV32P2_V22B 0x10
+#define PV32P2_V22C 0x08
+#define PV32P2_V21 0x02
+#define PV32P2_BEL 0x01
+
+/* LSB MSB in ISAR doc wrong !!! Arghhh */
+#define PV32P3_AMOD 0x80
+#define PV32P3_V32B 0x02
+#define PV32P3_V23B 0x01
+#define PV32P4_48 0x11
+#define PV32P5_48 0x05
+#define PV32P4_UT48 0x11
+#define PV32P5_UT48 0x0d
+#define PV32P4_96 0x11
+#define PV32P5_96 0x03
+#define PV32P4_UT96 0x11
+#define PV32P5_UT96 0x0f
+#define PV32P4_B96 0x91
+#define PV32P5_B96 0x0b
+#define PV32P4_UTB96 0xd1
+#define PV32P5_UTB96 0x0f
+#define PV32P4_120 0xb1
+#define PV32P5_120 0x09
+#define PV32P4_UT120 0xf1
+#define PV32P5_UT120 0x0f
+#define PV32P4_144 0x99
+#define PV32P5_144 0x09
+#define PV32P4_UT144 0xf9
+#define PV32P5_UT144 0x0f
+#define PV32P6_CTN 0x01
+#define PV32P6_ATN 0x02
+
+#define PFAXP2_CTN 0x01
+#define PFAXP2_ATN 0x04
+
+#define PSEV_10MS_TIMER 0x02
+#define PSEV_CON_ON 0x18
+#define PSEV_CON_OFF 0x19
+#define PSEV_V24_OFF 0x20
+#define PSEV_CTS_ON 0x21
+#define PSEV_CTS_OFF 0x22
+#define PSEV_DCD_ON 0x23
+#define PSEV_DCD_OFF 0x24
+#define PSEV_DSR_ON 0x25
+#define PSEV_DSR_OFF 0x26
+#define PSEV_REM_RET 0xcc
+#define PSEV_REM_REN 0xcd
+#define PSEV_GSTN_CLR 0xd4
+
+#define PSEV_RSP_READY 0xbc
+#define PSEV_LINE_TX_H 0xb3
+#define PSEV_LINE_TX_B 0xb2
+#define PSEV_LINE_RX_H 0xb1
+#define PSEV_LINE_RX_B 0xb0
+#define PSEV_RSP_CONN 0xb5
+#define PSEV_RSP_DISC 0xb7
+#define PSEV_RSP_FCERR 0xb9
+#define PSEV_RSP_SILDET 0xbe
+#define PSEV_RSP_SILOFF 0xab
+#define PSEV_FLAGS_DET 0xba
+
+#define PCTRL_CMD_TDTMF 0x5a
+
+#define PCTRL_CMD_FTH 0xa7
+#define PCTRL_CMD_FRH 0xa5
+#define PCTRL_CMD_FTM 0xa8
+#define PCTRL_CMD_FRM 0xa6
+#define PCTRL_CMD_SILON 0xac
+#define PCTRL_CMD_CONT 0xa2
+#define PCTRL_CMD_ESC 0xa4
+#define PCTRL_CMD_SILOFF 0xab
+#define PCTRL_CMD_HALT 0xa9
+
+#define PCTRL_LOC_RET 0xcf
+#define PCTRL_LOC_REN 0xce
+
+#define SMODE_DISABLE 0
+#define SMODE_V14 2
+#define SMODE_HDLC 3
+#define SMODE_BINARY 4
+#define SMODE_FSK_V14 5
+
+#define SCTRL_HDMC_BOTH 0x00
+#define SCTRL_HDMC_DTX 0x80
+#define SCTRL_HDMC_DRX 0x40
+#define S_P1_OVSP 0x40
+#define S_P1_SNP 0x20
+#define S_P1_EOP 0x10
+#define S_P1_EDP 0x08
+#define S_P1_NSB 0x04
+#define S_P1_CHS_8 0x03
+#define S_P1_CHS_7 0x02
+#define S_P1_CHS_6 0x01
+#define S_P1_CHS_5 0x00
+
+#define S_P2_BFT_DEF 0x10
+
+#define IOM_CTRL_ENA 0x80
+#define IOM_CTRL_NOPCM 0x00
+#define IOM_CTRL_ALAW 0x02
+#define IOM_CTRL_ULAW 0x04
+#define IOM_CTRL_RCV 0x01
+
+#define IOM_P1_TXD 0x10
+
+#define HDLC_FED 0x40
+#define HDLC_FSD 0x20
+#define HDLC_FST 0x20
+#define HDLC_ERROR 0x1c
+#define HDLC_ERR_FAD 0x10
+#define HDLC_ERR_RER 0x08
+#define HDLC_ERR_CER 0x04
+#define SART_NMD 0x01
+
+#define BSTAT_RDM0 0x1
+#define BSTAT_RDM1 0x2
+#define BSTAT_RDM2 0x4
+#define BSTAT_RDM3 0x8
+#define BSTEV_TBO 0x1f
+#define BSTEV_RBO 0x2f
+
+/* FAX State Machine */
+#define STFAX_NULL 0
+#define STFAX_READY 1
+#define STFAX_LINE 2
+#define STFAX_CONT 3
+#define STFAX_ACTIV 4
+#define STFAX_ESCAPE 5
+#define STFAX_SILDET 6
+
+extern u32 mISDNisar_init(struct isar_hw *, void *);
+extern void mISDNisar_irq(struct isar_hw *);
diff --git a/drivers/isdn/hardware/mISDN/mISDNinfineon.c b/drivers/isdn/hardware/mISDN/mISDNinfineon.c
new file mode 100644
index 00000000000..62441ba53b9
--- /dev/null
+++ b/drivers/isdn/hardware/mISDN/mISDNinfineon.c
@@ -0,0 +1,1178 @@
+/*
+ * mISDNinfineon.c
+ * Support for cards based on following Infineon ISDN chipsets
+ * - ISAC + HSCX
+ * - IPAC and IPAC-X
+ * - ISAC-SX + HSCX
+ *
+ * Supported cards:
+ * - Dialogic Diva 2.0
+ * - Dialogic Diva 2.0U
+ * - Dialogic Diva 2.01
+ * - Dialogic Diva 2.02
+ * - Sedlbauer Speedwin
+ * - HST Saphir3
+ * - Develo (former ELSA) Microlink PCI (Quickstep 1000)
+ * - Develo (former ELSA) Quickstep 3000
+ * - Berkom Scitel BRIX Quadro
+ * - Dr.Neuhaus (Sagem) Niccy
+ *
+ *
+ *
+ * Author Karsten Keil <keil@isdn4linux.de>
+ *
+ * Copyright 2009 by Karsten Keil <keil@isdn4linux.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/mISDNhw.h>
+#include "ipac.h"
+
+#define INFINEON_REV "1.0"
+
+static int inf_cnt;
+static u32 debug;
+static u32 irqloops = 4;
+
+enum inf_types {
+ INF_NONE,
+ INF_DIVA20,
+ INF_DIVA20U,
+ INF_DIVA201,
+ INF_DIVA202,
+ INF_SPEEDWIN,
+ INF_SAPHIR3,
+ INF_QS1000,
+ INF_QS3000,
+ INF_NICCY,
+ INF_SCT_1,
+ INF_SCT_2,
+ INF_SCT_3,
+ INF_SCT_4,
+ INF_GAZEL_R685,
+ INF_GAZEL_R753
+};
+
+enum addr_mode {
+ AM_NONE = 0,
+ AM_IO,
+ AM_MEMIO,
+ AM_IND_IO,
+};
+
+struct inf_cinfo {
+ enum inf_types typ;
+ const char *full;
+ const char *name;
+ enum addr_mode cfg_mode;
+ enum addr_mode addr_mode;
+ u8 cfg_bar;
+ u8 addr_bar;
+ void *irqfunc;
+};
+
+struct _ioaddr {
+ enum addr_mode mode;
+ union {
+ void __iomem *p;
+ struct _ioport io;
+ } a;
+};
+
+struct _iohandle {
+ enum addr_mode mode;
+ resource_size_t size;
+ resource_size_t start;
+ void __iomem *p;
+};
+
+struct inf_hw {
+ struct list_head list;
+ struct pci_dev *pdev;
+ const struct inf_cinfo *ci;
+ char name[MISDN_MAX_IDLEN];
+ u32 irq;
+ u32 irqcnt;
+ struct _iohandle cfg;
+ struct _iohandle addr;
+ struct _ioaddr isac;
+ struct _ioaddr hscx;
+ spinlock_t lock; /* HW access lock */
+ struct ipac_hw ipac;
+ struct inf_hw *sc[3]; /* slave cards */
+};
+
+
+#define PCI_SUBVENDOR_HST_SAPHIR3 0x52
+#define PCI_SUBVENDOR_SEDLBAUER_PCI 0x53
+#define PCI_SUB_ID_SEDLBAUER 0x01
+
+static struct pci_device_id infineon_ids[] __devinitdata = {
+ { PCI_VENDOR_ID_EICON, PCI_DEVICE_ID_EICON_DIVA20,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, INF_DIVA20},
+ { PCI_VENDOR_ID_EICON, PCI_DEVICE_ID_EICON_DIVA20_U,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, INF_DIVA20U},
+ { PCI_VENDOR_ID_EICON, PCI_DEVICE_ID_EICON_DIVA201,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, INF_DIVA201},
+ { PCI_VENDOR_ID_EICON, PCI_DEVICE_ID_EICON_DIVA202,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, INF_DIVA202},
+ { PCI_VENDOR_ID_TIGERJET, PCI_DEVICE_ID_TIGERJET_100,
+ PCI_SUBVENDOR_SEDLBAUER_PCI, PCI_SUB_ID_SEDLBAUER, 0, 0,
+ INF_SPEEDWIN},
+ { PCI_VENDOR_ID_TIGERJET, PCI_DEVICE_ID_TIGERJET_100,
+ PCI_SUBVENDOR_HST_SAPHIR3, PCI_SUB_ID_SEDLBAUER, 0, 0, INF_SAPHIR3},
+ { PCI_VENDOR_ID_ELSA, PCI_DEVICE_ID_ELSA_MICROLINK,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, INF_QS1000},
+ { PCI_VENDOR_ID_ELSA, PCI_DEVICE_ID_ELSA_QS3000,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, INF_QS3000},
+ { PCI_VENDOR_ID_SATSAGEM, PCI_DEVICE_ID_SATSAGEM_NICCY,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, INF_NICCY},
+ { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
+ PCI_VENDOR_ID_BERKOM, PCI_DEVICE_ID_BERKOM_SCITEL_QUADRO, 0, 0,
+ INF_SCT_1},
+ { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_R685,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, INF_GAZEL_R685},
+ { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_R753,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, INF_GAZEL_R753},
+ { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_DJINN_ITOO,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, INF_GAZEL_R753},
+ { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_OLITEC,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, INF_GAZEL_R753},
+ { }
+};
+MODULE_DEVICE_TABLE(pci, infineon_ids);
+
+/* PCI interface specific defines */
+/* Diva 2.0/2.0U */
+#define DIVA_HSCX_PORT 0x00
+#define DIVA_HSCX_ALE 0x04
+#define DIVA_ISAC_PORT 0x08
+#define DIVA_ISAC_ALE 0x0C
+#define DIVA_PCI_CTRL 0x10
+
+/* DIVA_PCI_CTRL bits */
+#define DIVA_IRQ_BIT 0x01
+#define DIVA_RESET_BIT 0x08
+#define DIVA_EEPROM_CLK 0x40
+#define DIVA_LED_A 0x10
+#define DIVA_LED_B 0x20
+#define DIVA_IRQ_CLR 0x80
+
+/* Diva 2.01/2.02 */
+/* Siemens PITA */
+#define PITA_ICR_REG 0x00
+#define PITA_INT0_STATUS 0x02
+
+#define PITA_MISC_REG 0x1c
+#define PITA_PARA_SOFTRESET 0x01000000
+#define PITA_SER_SOFTRESET 0x02000000
+#define PITA_PARA_MPX_MODE 0x04000000
+#define PITA_INT0_ENABLE 0x00020000
+
+/* TIGER 100 Registers */
+#define TIGER_RESET_ADDR 0x00
+#define TIGER_EXTERN_RESET 0x01
+#define TIGER_AUX_CTRL 0x02
+#define TIGER_AUX_DATA 0x03
+#define TIGER_AUX_IRQMASK 0x05
+#define TIGER_AUX_STATUS 0x07
+
+/* Tiger AUX BITs */
+#define TIGER_IOMASK 0xdd /* 1 and 5 are inputs */
+#define TIGER_IRQ_BIT 0x02
+
+#define TIGER_IPAC_ALE 0xC0
+#define TIGER_IPAC_PORT 0xC8
+
+/* ELSA (now Develo) PCI cards */
+#define ELSA_IRQ_ADDR 0x4c
+#define ELSA_IRQ_MASK 0x04
+#define QS1000_IRQ_OFF 0x01
+#define QS3000_IRQ_OFF 0x03
+#define QS1000_IRQ_ON 0x41
+#define QS3000_IRQ_ON 0x43
+
+/* Dr Neuhaus/Sagem Niccy */
+#define NICCY_ISAC_PORT 0x00
+#define NICCY_HSCX_PORT 0x01
+#define NICCY_ISAC_ALE 0x02
+#define NICCY_HSCX_ALE 0x03
+
+#define NICCY_IRQ_CTRL_REG 0x38
+#define NICCY_IRQ_ENABLE 0x001f00
+#define NICCY_IRQ_DISABLE 0xff0000
+#define NICCY_IRQ_BIT 0x800000
+
+
+/* Scitel PLX */
+#define SCT_PLX_IRQ_ADDR 0x4c
+#define SCT_PLX_RESET_ADDR 0x50
+#define SCT_PLX_IRQ_ENABLE 0x41
+#define SCT_PLX_RESET_BIT 0x04
+
+/* Gazel */
+#define GAZEL_IPAC_DATA_PORT 0x04
+/* Gazel PLX */
+#define GAZEL_CNTRL 0x50
+#define GAZEL_RESET 0x04
+#define GAZEL_RESET_9050 0x40000000
+#define GAZEL_INCSR 0x4C
+#define GAZEL_ISAC_EN 0x08
+#define GAZEL_INT_ISAC 0x20
+#define GAZEL_HSCX_EN 0x01
+#define GAZEL_INT_HSCX 0x04
+#define GAZEL_PCI_EN 0x40
+#define GAZEL_IPAC_EN 0x03
+
+
+static LIST_HEAD(Cards);
+static DEFINE_RWLOCK(card_lock); /* protect Cards */
+
+static void
+_set_debug(struct inf_hw *card)
+{
+ card->ipac.isac.dch.debug = debug;
+ card->ipac.hscx[0].bch.debug = debug;
+ card->ipac.hscx[1].bch.debug = debug;
+}
+
+static int
+set_debug(const char *val, struct kernel_param *kp)
+{
+ int ret;
+ struct inf_hw *card;
+
+ ret = param_set_uint(val, kp);
+ if (!ret) {
+ read_lock(&card_lock);
+ list_for_each_entry(card, &Cards, list)
+ _set_debug(card);
+ read_unlock(&card_lock);
+ }
+ return ret;
+}
+
+MODULE_AUTHOR("Karsten Keil");
+MODULE_LICENSE("GPL v2");
+MODULE_VERSION(INFINEON_REV);
+module_param_call(debug, set_debug, param_get_uint, &debug, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "infineon debug mask");
+module_param(irqloops, uint, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(irqloops, "infineon maximal irqloops (default 4)");
+
+/* Interface functions */
+
+IOFUNC_IO(ISAC, inf_hw, isac.a.io)
+IOFUNC_IO(IPAC, inf_hw, hscx.a.io)
+IOFUNC_IND(ISAC, inf_hw, isac.a.io)
+IOFUNC_IND(IPAC, inf_hw, hscx.a.io)
+IOFUNC_MEMIO(ISAC, inf_hw, u32, isac.a.p)
+IOFUNC_MEMIO(IPAC, inf_hw, u32, hscx.a.p)
+
+static irqreturn_t
+diva_irq(int intno, void *dev_id)
+{
+ struct inf_hw *hw = dev_id;
+ u8 val;
+
+ spin_lock(&hw->lock);
+ val = inb((u32)hw->cfg.start + DIVA_PCI_CTRL);
+ if (!(val & DIVA_IRQ_BIT)) { /* for us or shared ? */
+ spin_unlock(&hw->lock);
+ return IRQ_NONE; /* shared */
+ }
+ hw->irqcnt++;
+ mISDNipac_irq(&hw->ipac, irqloops);
+ spin_unlock(&hw->lock);
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t
+diva20x_irq(int intno, void *dev_id)
+{
+ struct inf_hw *hw = dev_id;
+ u8 val;
+
+ spin_lock(&hw->lock);
+ val = readb(hw->cfg.p);
+ if (!(val & PITA_INT0_STATUS)) { /* for us or shared ? */
+ spin_unlock(&hw->lock);
+ return IRQ_NONE; /* shared */
+ }
+ hw->irqcnt++;
+ mISDNipac_irq(&hw->ipac, irqloops);
+ writeb(PITA_INT0_STATUS, hw->cfg.p); /* ACK PITA INT0 */
+ spin_unlock(&hw->lock);
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t
+tiger_irq(int intno, void *dev_id)
+{
+ struct inf_hw *hw = dev_id;
+ u8 val;
+
+ spin_lock(&hw->lock);
+ val = inb((u32)hw->cfg.start + TIGER_AUX_STATUS);
+ if (val & TIGER_IRQ_BIT) { /* for us or shared ? */
+ spin_unlock(&hw->lock);
+ return IRQ_NONE; /* shared */
+ }
+ hw->irqcnt++;
+ mISDNipac_irq(&hw->ipac, irqloops);
+ spin_unlock(&hw->lock);
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t
+elsa_irq(int intno, void *dev_id)
+{
+ struct inf_hw *hw = dev_id;
+ u8 val;
+
+ spin_lock(&hw->lock);
+ val = inb((u32)hw->cfg.start + ELSA_IRQ_ADDR);
+ if (!(val & ELSA_IRQ_MASK)) {
+ spin_unlock(&hw->lock);
+ return IRQ_NONE; /* shared */
+ }
+ hw->irqcnt++;
+ mISDNipac_irq(&hw->ipac, irqloops);
+ spin_unlock(&hw->lock);
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t
+niccy_irq(int intno, void *dev_id)
+{
+ struct inf_hw *hw = dev_id;
+ u32 val;
+
+ spin_lock(&hw->lock);
+ val = inl((u32)hw->cfg.start + NICCY_IRQ_CTRL_REG);
+ if (!(val & NICCY_IRQ_BIT)) { /* for us or shared ? */
+ spin_unlock(&hw->lock);
+ return IRQ_NONE; /* shared */
+ }
+ outl(val, (u32)hw->cfg.start + NICCY_IRQ_CTRL_REG);
+ hw->irqcnt++;
+ mISDNipac_irq(&hw->ipac, irqloops);
+ spin_unlock(&hw->lock);
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t
+gazel_irq(int intno, void *dev_id)
+{
+ struct inf_hw *hw = dev_id;
+ irqreturn_t ret;
+
+ spin_lock(&hw->lock);
+ ret = mISDNipac_irq(&hw->ipac, irqloops);
+ spin_unlock(&hw->lock);
+ return ret;
+}
+
+static irqreturn_t
+ipac_irq(int intno, void *dev_id)
+{
+ struct inf_hw *hw = dev_id;
+ u8 val;
+
+ spin_lock(&hw->lock);
+ val = hw->ipac.read_reg(hw, IPAC_ISTA);
+ if (!(val & 0x3f)) {
+ spin_unlock(&hw->lock);
+ return IRQ_NONE; /* shared */
+ }
+ hw->irqcnt++;
+ mISDNipac_irq(&hw->ipac, irqloops);
+ spin_unlock(&hw->lock);
+ return IRQ_HANDLED;
+}
+
+static void
+enable_hwirq(struct inf_hw *hw)
+{
+ u16 w;
+ u32 val;
+
+ switch (hw->ci->typ) {
+ case INF_DIVA201:
+ case INF_DIVA202:
+ writel(PITA_INT0_ENABLE, hw->cfg.p);
+ break;
+ case INF_SPEEDWIN:
+ case INF_SAPHIR3:
+ outb(TIGER_IRQ_BIT, (u32)hw->cfg.start + TIGER_AUX_IRQMASK);
+ break;
+ case INF_QS1000:
+ outb(QS1000_IRQ_ON, (u32)hw->cfg.start + ELSA_IRQ_ADDR);
+ break;
+ case INF_QS3000:
+ outb(QS3000_IRQ_ON, (u32)hw->cfg.start + ELSA_IRQ_ADDR);
+ break;
+ case INF_NICCY:
+ val = inl((u32)hw->cfg.start + NICCY_IRQ_CTRL_REG);
+ val |= NICCY_IRQ_ENABLE;;
+ outl(val, (u32)hw->cfg.start + NICCY_IRQ_CTRL_REG);
+ break;
+ case INF_SCT_1:
+ w = inw((u32)hw->cfg.start + SCT_PLX_IRQ_ADDR);
+ w |= SCT_PLX_IRQ_ENABLE;
+ outw(w, (u32)hw->cfg.start + SCT_PLX_IRQ_ADDR);
+ break;
+ case INF_GAZEL_R685:
+ outb(GAZEL_ISAC_EN + GAZEL_HSCX_EN + GAZEL_PCI_EN,
+ (u32)hw->cfg.start + GAZEL_INCSR);
+ break;
+ case INF_GAZEL_R753:
+ outb(GAZEL_IPAC_EN + GAZEL_PCI_EN,
+ (u32)hw->cfg.start + GAZEL_INCSR);
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+disable_hwirq(struct inf_hw *hw)
+{
+ u16 w;
+ u32 val;
+
+ switch (hw->ci->typ) {
+ case INF_DIVA201:
+ case INF_DIVA202:
+ writel(0, hw->cfg.p);
+ break;
+ case INF_SPEEDWIN:
+ case INF_SAPHIR3:
+ outb(0, (u32)hw->cfg.start + TIGER_AUX_IRQMASK);
+ break;
+ case INF_QS1000:
+ outb(QS1000_IRQ_OFF, (u32)hw->cfg.start + ELSA_IRQ_ADDR);
+ break;
+ case INF_QS3000:
+ outb(QS3000_IRQ_OFF, (u32)hw->cfg.start + ELSA_IRQ_ADDR);
+ break;
+ case INF_NICCY:
+ val = inl((u32)hw->cfg.start + NICCY_IRQ_CTRL_REG);
+ val &= NICCY_IRQ_DISABLE;
+ outl(val, (u32)hw->cfg.start + NICCY_IRQ_CTRL_REG);
+ break;
+ case INF_SCT_1:
+ w = inw((u32)hw->cfg.start + SCT_PLX_IRQ_ADDR);
+ w &= (~SCT_PLX_IRQ_ENABLE);
+ outw(w, (u32)hw->cfg.start + SCT_PLX_IRQ_ADDR);
+ break;
+ case INF_GAZEL_R685:
+ case INF_GAZEL_R753:
+ outb(0, (u32)hw->cfg.start + GAZEL_INCSR);
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+ipac_chip_reset(struct inf_hw *hw)
+{
+ hw->ipac.write_reg(hw, IPAC_POTA2, 0x20);
+ mdelay(5);
+ hw->ipac.write_reg(hw, IPAC_POTA2, 0x00);
+ mdelay(5);
+ hw->ipac.write_reg(hw, IPAC_CONF, hw->ipac.conf);
+ hw->ipac.write_reg(hw, IPAC_MASK, 0xc0);
+}
+
+static void
+reset_inf(struct inf_hw *hw)
+{
+ u16 w;
+ u32 val;
+
+ if (debug & DEBUG_HW)
+ pr_notice("%s: resetting card\n", hw->name);
+ switch (hw->ci->typ) {
+ case INF_DIVA20:
+ case INF_DIVA20U:
+ outb(0, (u32)hw->cfg.start + DIVA_PCI_CTRL);
+ mdelay(10);
+ outb(DIVA_RESET_BIT, (u32)hw->cfg.start + DIVA_PCI_CTRL);
+ mdelay(10);
+ /* Workaround PCI9060 */
+ outb(9, (u32)hw->cfg.start + 0x69);
+ outb(DIVA_RESET_BIT | DIVA_LED_A,
+ (u32)hw->cfg.start + DIVA_PCI_CTRL);
+ break;
+ case INF_DIVA201:
+ writel(PITA_PARA_SOFTRESET | PITA_PARA_MPX_MODE,
+ hw->cfg.p + PITA_MISC_REG);
+ mdelay(1);
+ writel(PITA_PARA_MPX_MODE, hw->cfg.p + PITA_MISC_REG);
+ mdelay(10);
+ break;
+ case INF_DIVA202:
+ writel(PITA_PARA_SOFTRESET | PITA_PARA_MPX_MODE,
+ hw->cfg.p + PITA_MISC_REG);
+ mdelay(1);
+ writel(PITA_PARA_MPX_MODE | PITA_SER_SOFTRESET,
+ hw->cfg.p + PITA_MISC_REG);
+ mdelay(10);
+ break;
+ case INF_SPEEDWIN:
+ case INF_SAPHIR3:
+ ipac_chip_reset(hw);
+ hw->ipac.write_reg(hw, IPAC_ACFG, 0xff);
+ hw->ipac.write_reg(hw, IPAC_AOE, 0x00);
+ hw->ipac.write_reg(hw, IPAC_PCFG, 0x12);
+ break;
+ case INF_QS1000:
+ case INF_QS3000:
+ ipac_chip_reset(hw);
+ hw->ipac.write_reg(hw, IPAC_ACFG, 0x00);
+ hw->ipac.write_reg(hw, IPAC_AOE, 0x3c);
+ hw->ipac.write_reg(hw, IPAC_ATX, 0xff);
+ break;
+ case INF_NICCY:
+ break;
+ case INF_SCT_1:
+ w = inw((u32)hw->cfg.start + SCT_PLX_RESET_ADDR);
+ w &= (~SCT_PLX_RESET_BIT);
+ outw(w, (u32)hw->cfg.start + SCT_PLX_RESET_ADDR);
+ mdelay(10);
+ w = inw((u32)hw->cfg.start + SCT_PLX_RESET_ADDR);
+ w |= SCT_PLX_RESET_BIT;
+ outw(w, (u32)hw->cfg.start + SCT_PLX_RESET_ADDR);
+ mdelay(10);
+ break;
+ case INF_GAZEL_R685:
+ val = inl((u32)hw->cfg.start + GAZEL_CNTRL);
+ val |= (GAZEL_RESET_9050 + GAZEL_RESET);
+ outl(val, (u32)hw->cfg.start + GAZEL_CNTRL);
+ val &= ~(GAZEL_RESET_9050 + GAZEL_RESET);
+ mdelay(4);
+ outl(val, (u32)hw->cfg.start + GAZEL_CNTRL);
+ mdelay(10);
+ hw->ipac.isac.adf2 = 0x87;
+ hw->ipac.hscx[0].slot = 0x1f;
+ hw->ipac.hscx[0].slot = 0x23;
+ break;
+ case INF_GAZEL_R753:
+ val = inl((u32)hw->cfg.start + GAZEL_CNTRL);
+ val |= (GAZEL_RESET_9050 + GAZEL_RESET);
+ outl(val, (u32)hw->cfg.start + GAZEL_CNTRL);
+ val &= ~(GAZEL_RESET_9050 + GAZEL_RESET);
+ mdelay(4);
+ outl(val, (u32)hw->cfg.start + GAZEL_CNTRL);
+ mdelay(10);
+ ipac_chip_reset(hw);
+ hw->ipac.write_reg(hw, IPAC_ACFG, 0xff);
+ hw->ipac.write_reg(hw, IPAC_AOE, 0x00);
+ hw->ipac.conf = 0x01; /* IOM off */
+ break;
+ default:
+ return;
+ }
+ enable_hwirq(hw);
+}
+
+static int
+inf_ctrl(struct inf_hw *hw, u32 cmd, u_long arg)
+{
+ int ret = 0;
+
+ switch (cmd) {
+ case HW_RESET_REQ:
+ reset_inf(hw);
+ break;
+ default:
+ pr_info("%s: %s unknown command %x %lx\n",
+ hw->name, __func__, cmd, arg);
+ ret = -EINVAL;
+ break;
+ }
+ return ret;
+}
+
+static int __devinit
+init_irq(struct inf_hw *hw)
+{
+ int ret, cnt = 3;
+ u_long flags;
+
+ if (!hw->ci->irqfunc)
+ return -EINVAL;
+ ret = request_irq(hw->irq, hw->ci->irqfunc, IRQF_SHARED, hw->name, hw);
+ if (ret) {
+ pr_info("%s: couldn't get interrupt %d\n", hw->name, hw->irq);
+ return ret;
+ }
+ while (cnt--) {
+ spin_lock_irqsave(&hw->lock, flags);
+ reset_inf(hw);
+ ret = hw->ipac.init(&hw->ipac);
+ if (ret) {
+ spin_unlock_irqrestore(&hw->lock, flags);
+ pr_info("%s: ISAC init failed with %d\n",
+ hw->name, ret);
+ break;
+ }
+ spin_unlock_irqrestore(&hw->lock, flags);
+ msleep_interruptible(10);
+ if (debug & DEBUG_HW)
+ pr_notice("%s: IRQ %d count %d\n", hw->name,
+ hw->irq, hw->irqcnt);
+ if (!hw->irqcnt) {
+ pr_info("%s: IRQ(%d) got no requests during init %d\n",
+ hw->name, hw->irq, 3 - cnt);
+ } else
+ return 0;
+ }
+ free_irq(hw->irq, hw);
+ return -EIO;
+}
+
+static void
+release_io(struct inf_hw *hw)
+{
+ if (hw->cfg.mode) {
+ if (hw->cfg.p) {
+ release_mem_region(hw->cfg.start, hw->cfg.size);
+ iounmap(hw->cfg.p);
+ } else
+ release_region(hw->cfg.start, hw->cfg.size);
+ hw->cfg.mode = AM_NONE;
+ }
+ if (hw->addr.mode) {
+ if (hw->addr.p) {
+ release_mem_region(hw->addr.start, hw->addr.size);
+ iounmap(hw->addr.p);
+ } else
+ release_region(hw->addr.start, hw->addr.size);
+ hw->addr.mode = AM_NONE;
+ }
+}
+
+static int __devinit
+setup_io(struct inf_hw *hw)
+{
+ int err = 0;
+
+ if (hw->ci->cfg_mode) {
+ hw->cfg.start = pci_resource_start(hw->pdev, hw->ci->cfg_bar);
+ hw->cfg.size = pci_resource_len(hw->pdev, hw->ci->cfg_bar);
+ if (hw->ci->cfg_mode == AM_MEMIO) {
+ if (!request_mem_region(hw->cfg.start, hw->cfg.size,
+ hw->name))
+ err = -EBUSY;
+ } else {
+ if (!request_region(hw->cfg.start, hw->cfg.size,
+ hw->name))
+ err = -EBUSY;
+ }
+ if (err) {
+ pr_info("mISDN: %s config port %lx (%lu bytes)"
+ "already in use\n", hw->name,
+ (ulong)hw->cfg.start, (ulong)hw->cfg.size);
+ return err;
+ }
+ if (hw->ci->cfg_mode == AM_MEMIO)
+ hw->cfg.p = ioremap(hw->cfg.start, hw->cfg.size);
+ hw->cfg.mode = hw->ci->cfg_mode;
+ if (debug & DEBUG_HW)
+ pr_notice("%s: IO cfg %lx (%lu bytes) mode%d\n",
+ hw->name, (ulong)hw->cfg.start,
+ (ulong)hw->cfg.size, hw->ci->cfg_mode);
+
+ }
+ if (hw->ci->addr_mode) {
+ hw->addr.start = pci_resource_start(hw->pdev, hw->ci->addr_bar);
+ hw->addr.size = pci_resource_len(hw->pdev, hw->ci->addr_bar);
+ if (hw->ci->addr_mode == AM_MEMIO) {
+ if (!request_mem_region(hw->addr.start, hw->addr.size,
+ hw->name))
+ err = -EBUSY;
+ } else {
+ if (!request_region(hw->addr.start, hw->addr.size,
+ hw->name))
+ err = -EBUSY;
+ }
+ if (err) {
+ pr_info("mISDN: %s address port %lx (%lu bytes)"
+ "already in use\n", hw->name,
+ (ulong)hw->addr.start, (ulong)hw->addr.size);
+ return err;
+ }
+ if (hw->ci->addr_mode == AM_MEMIO)
+ hw->addr.p = ioremap(hw->addr.start, hw->addr.size);
+ hw->addr.mode = hw->ci->addr_mode;
+ if (debug & DEBUG_HW)
+ pr_notice("%s: IO addr %lx (%lu bytes) mode%d\n",
+ hw->name, (ulong)hw->addr.start,
+ (ulong)hw->addr.size, hw->ci->addr_mode);
+
+ }
+
+ switch (hw->ci->typ) {
+ case INF_DIVA20:
+ case INF_DIVA20U:
+ hw->ipac.type = IPAC_TYPE_ISAC | IPAC_TYPE_HSCX;
+ hw->isac.mode = hw->cfg.mode;
+ hw->isac.a.io.ale = (u32)hw->cfg.start + DIVA_ISAC_ALE;
+ hw->isac.a.io.port = (u32)hw->cfg.start + DIVA_ISAC_PORT;
+ hw->hscx.mode = hw->cfg.mode;
+ hw->hscx.a.io.ale = (u32)hw->cfg.start + DIVA_HSCX_ALE;
+ hw->hscx.a.io.port = (u32)hw->cfg.start + DIVA_HSCX_PORT;
+ break;
+ case INF_DIVA201:
+ hw->ipac.type = IPAC_TYPE_IPAC;
+ hw->ipac.isac.off = 0x80;
+ hw->isac.mode = hw->addr.mode;
+ hw->isac.a.p = hw->addr.p;
+ hw->hscx.mode = hw->addr.mode;
+ hw->hscx.a.p = hw->addr.p;
+ break;
+ case INF_DIVA202:
+ hw->ipac.type = IPAC_TYPE_IPACX;
+ hw->isac.mode = hw->addr.mode;
+ hw->isac.a.p = hw->addr.p;
+ hw->hscx.mode = hw->addr.mode;
+ hw->hscx.a.p = hw->addr.p;
+ break;
+ case INF_SPEEDWIN:
+ case INF_SAPHIR3:
+ hw->ipac.type = IPAC_TYPE_IPAC;
+ hw->ipac.isac.off = 0x80;
+ hw->isac.mode = hw->cfg.mode;
+ hw->isac.a.io.ale = (u32)hw->cfg.start + TIGER_IPAC_ALE;
+ hw->isac.a.io.port = (u32)hw->cfg.start + TIGER_IPAC_PORT;
+ hw->hscx.mode = hw->cfg.mode;
+ hw->hscx.a.io.ale = (u32)hw->cfg.start + TIGER_IPAC_ALE;
+ hw->hscx.a.io.port = (u32)hw->cfg.start + TIGER_IPAC_PORT;
+ outb(0xff, (ulong)hw->cfg.start);
+ mdelay(1);
+ outb(0x00, (ulong)hw->cfg.start);
+ mdelay(1);
+ outb(TIGER_IOMASK, (ulong)hw->cfg.start + TIGER_AUX_CTRL);
+ break;
+ case INF_QS1000:
+ case INF_QS3000:
+ hw->ipac.type = IPAC_TYPE_IPAC;
+ hw->ipac.isac.off = 0x80;
+ hw->isac.a.io.ale = (u32)hw->addr.start;
+ hw->isac.a.io.port = (u32)hw->addr.start + 1;
+ hw->isac.mode = hw->addr.mode;
+ hw->hscx.a.io.ale = (u32)hw->addr.start;
+ hw->hscx.a.io.port = (u32)hw->addr.start + 1;
+ hw->hscx.mode = hw->addr.mode;
+ break;
+ case INF_NICCY:
+ hw->ipac.type = IPAC_TYPE_ISAC | IPAC_TYPE_HSCX;
+ hw->isac.mode = hw->addr.mode;
+ hw->isac.a.io.ale = (u32)hw->addr.start + NICCY_ISAC_ALE;
+ hw->isac.a.io.port = (u32)hw->addr.start + NICCY_ISAC_PORT;
+ hw->hscx.mode = hw->addr.mode;
+ hw->hscx.a.io.ale = (u32)hw->addr.start + NICCY_HSCX_ALE;
+ hw->hscx.a.io.port = (u32)hw->addr.start + NICCY_HSCX_PORT;
+ break;
+ case INF_SCT_1:
+ hw->ipac.type = IPAC_TYPE_IPAC;
+ hw->ipac.isac.off = 0x80;
+ hw->isac.a.io.ale = (u32)hw->addr.start;
+ hw->isac.a.io.port = hw->isac.a.io.ale + 4;
+ hw->isac.mode = hw->addr.mode;
+ hw->hscx.a.io.ale = hw->isac.a.io.ale;
+ hw->hscx.a.io.port = hw->isac.a.io.port;
+ hw->hscx.mode = hw->addr.mode;
+ break;
+ case INF_SCT_2:
+ hw->ipac.type = IPAC_TYPE_IPAC;
+ hw->ipac.isac.off = 0x80;
+ hw->isac.a.io.ale = (u32)hw->addr.start + 0x08;
+ hw->isac.a.io.port = hw->isac.a.io.ale + 4;
+ hw->isac.mode = hw->addr.mode;
+ hw->hscx.a.io.ale = hw->isac.a.io.ale;
+ hw->hscx.a.io.port = hw->isac.a.io.port;
+ hw->hscx.mode = hw->addr.mode;
+ break;
+ case INF_SCT_3:
+ hw->ipac.type = IPAC_TYPE_IPAC;
+ hw->ipac.isac.off = 0x80;
+ hw->isac.a.io.ale = (u32)hw->addr.start + 0x10;
+ hw->isac.a.io.port = hw->isac.a.io.ale + 4;
+ hw->isac.mode = hw->addr.mode;
+ hw->hscx.a.io.ale = hw->isac.a.io.ale;
+ hw->hscx.a.io.port = hw->isac.a.io.port;
+ hw->hscx.mode = hw->addr.mode;
+ break;
+ case INF_SCT_4:
+ hw->ipac.type = IPAC_TYPE_IPAC;
+ hw->ipac.isac.off = 0x80;
+ hw->isac.a.io.ale = (u32)hw->addr.start + 0x20;
+ hw->isac.a.io.port = hw->isac.a.io.ale + 4;
+ hw->isac.mode = hw->addr.mode;
+ hw->hscx.a.io.ale = hw->isac.a.io.ale;
+ hw->hscx.a.io.port = hw->isac.a.io.port;
+ hw->hscx.mode = hw->addr.mode;
+ break;
+ case INF_GAZEL_R685:
+ hw->ipac.type = IPAC_TYPE_ISAC | IPAC_TYPE_HSCX;
+ hw->ipac.isac.off = 0x80;
+ hw->isac.mode = hw->addr.mode;
+ hw->isac.a.io.port = (u32)hw->addr.start;
+ hw->hscx.mode = hw->addr.mode;
+ hw->hscx.a.io.port = hw->isac.a.io.port;
+ break;
+ case INF_GAZEL_R753:
+ hw->ipac.type = IPAC_TYPE_IPAC;
+ hw->ipac.isac.off = 0x80;
+ hw->isac.mode = hw->addr.mode;
+ hw->isac.a.io.ale = (u32)hw->addr.start;
+ hw->isac.a.io.port = (u32)hw->addr.start + GAZEL_IPAC_DATA_PORT;
+ hw->hscx.mode = hw->addr.mode;
+ hw->hscx.a.io.ale = hw->isac.a.io.ale;
+ hw->hscx.a.io.port = hw->isac.a.io.port;
+ break;
+ default:
+ return -EINVAL;
+ }
+ switch (hw->isac.mode) {
+ case AM_MEMIO:
+ ASSIGN_FUNC_IPAC(MIO, hw->ipac);
+ break;
+ case AM_IND_IO:
+ ASSIGN_FUNC_IPAC(IND, hw->ipac);
+ break;
+ case AM_IO:
+ ASSIGN_FUNC_IPAC(IO, hw->ipac);
+ break;
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static void
+release_card(struct inf_hw *card) {
+ ulong flags;
+ int i;
+
+ spin_lock_irqsave(&card->lock, flags);
+ disable_hwirq(card);
+ spin_unlock_irqrestore(&card->lock, flags);
+ card->ipac.isac.release(&card->ipac.isac);
+ free_irq(card->irq, card);
+ mISDN_unregister_device(&card->ipac.isac.dch.dev);
+ release_io(card);
+ write_lock_irqsave(&card_lock, flags);
+ list_del(&card->list);
+ write_unlock_irqrestore(&card_lock, flags);
+ switch (card->ci->typ) {
+ case INF_SCT_2:
+ case INF_SCT_3:
+ case INF_SCT_4:
+ break;
+ case INF_SCT_1:
+ for (i = 0; i < 3; i++) {
+ if (card->sc[i])
+ release_card(card->sc[i]);
+ card->sc[i] = NULL;
+ }
+ default:
+ pci_disable_device(card->pdev);
+ pci_set_drvdata(card->pdev, NULL);
+ break;
+ }
+ kfree(card);
+ inf_cnt--;
+}
+
+static int __devinit
+setup_instance(struct inf_hw *card)
+{
+ int err;
+ ulong flags;
+
+ snprintf(card->name, MISDN_MAX_IDLEN - 1, "%s.%d", card->ci->name,
+ inf_cnt + 1);
+ write_lock_irqsave(&card_lock, flags);
+ list_add_tail(&card->list, &Cards);
+ write_unlock_irqrestore(&card_lock, flags);
+
+ _set_debug(card);
+ card->ipac.isac.name = card->name;
+ card->ipac.name = card->name;
+ card->ipac.owner = THIS_MODULE;
+ spin_lock_init(&card->lock);
+ card->ipac.isac.hwlock = &card->lock;
+ card->ipac.hwlock = &card->lock;
+ card->ipac.ctrl = (void *)&inf_ctrl;
+
+ err = setup_io(card);
+ if (err)
+ goto error_setup;
+
+ card->ipac.isac.dch.dev.Bprotocols =
+ mISDNipac_init(&card->ipac, card);
+
+ if (card->ipac.isac.dch.dev.Bprotocols == 0)
+ goto error_setup;;
+
+ err = mISDN_register_device(&card->ipac.isac.dch.dev,
+ &card->pdev->dev, card->name);
+ if (err)
+ goto error;
+
+ err = init_irq(card);
+ if (!err) {
+ inf_cnt++;
+ pr_notice("Infineon %d cards installed\n", inf_cnt);
+ return 0;
+ }
+ mISDN_unregister_device(&card->ipac.isac.dch.dev);
+error:
+ card->ipac.release(&card->ipac);
+error_setup:
+ release_io(card);
+ write_lock_irqsave(&card_lock, flags);
+ list_del(&card->list);
+ write_unlock_irqrestore(&card_lock, flags);
+ return err;
+}
+
+static const struct inf_cinfo inf_card_info[] = {
+ {
+ INF_DIVA20,
+ "Dialogic Diva 2.0",
+ "diva20",
+ AM_IND_IO, AM_NONE, 2, 0,
+ &diva_irq
+ },
+ {
+ INF_DIVA20U,
+ "Dialogic Diva 2.0U",
+ "diva20U",
+ AM_IND_IO, AM_NONE, 2, 0,
+ &diva_irq
+ },
+ {
+ INF_DIVA201,
+ "Dialogic Diva 2.01",
+ "diva201",
+ AM_MEMIO, AM_MEMIO, 0, 1,
+ &diva20x_irq
+ },
+ {
+ INF_DIVA202,
+ "Dialogic Diva 2.02",
+ "diva202",
+ AM_MEMIO, AM_MEMIO, 0, 1,
+ &diva20x_irq
+ },
+ {
+ INF_SPEEDWIN,
+ "Sedlbauer SpeedWin PCI",
+ "speedwin",
+ AM_IND_IO, AM_NONE, 0, 0,
+ &tiger_irq
+ },
+ {
+ INF_SAPHIR3,
+ "HST Saphir 3",
+ "saphir",
+ AM_IND_IO, AM_NONE, 0, 0,
+ &tiger_irq
+ },
+ {
+ INF_QS1000,
+ "Develo Microlink PCI",
+ "qs1000",
+ AM_IO, AM_IND_IO, 1, 3,
+ &elsa_irq
+ },
+ {
+ INF_QS3000,
+ "Develo QuickStep 3000",
+ "qs3000",
+ AM_IO, AM_IND_IO, 1, 3,
+ &elsa_irq
+ },
+ {
+ INF_NICCY,
+ "Sagem NICCY",
+ "niccy",
+ AM_IO, AM_IND_IO, 0, 1,
+ &niccy_irq
+ },
+ {
+ INF_SCT_1,
+ "SciTel Quadro",
+ "p1_scitel",
+ AM_IO, AM_IND_IO, 1, 5,
+ &ipac_irq
+ },
+ {
+ INF_SCT_2,
+ "SciTel Quadro",
+ "p2_scitel",
+ AM_NONE, AM_IND_IO, 0, 4,
+ &ipac_irq
+ },
+ {
+ INF_SCT_3,
+ "SciTel Quadro",
+ "p3_scitel",
+ AM_NONE, AM_IND_IO, 0, 3,
+ &ipac_irq
+ },
+ {
+ INF_SCT_4,
+ "SciTel Quadro",
+ "p4_scitel",
+ AM_NONE, AM_IND_IO, 0, 2,
+ &ipac_irq
+ },
+ {
+ INF_GAZEL_R685,
+ "Gazel R685",
+ "gazel685",
+ AM_IO, AM_IO, 1, 2,
+ &gazel_irq
+ },
+ {
+ INF_GAZEL_R753,
+ "Gazel R753",
+ "gazel753",
+ AM_IO, AM_IND_IO, 1, 2,
+ &ipac_irq
+ },
+ {
+ INF_NONE,
+ }
+};
+
+static const struct inf_cinfo * __devinit
+get_card_info(enum inf_types typ)
+{
+ const struct inf_cinfo *ci = inf_card_info;
+
+ while (ci->typ != INF_NONE) {
+ if (ci->typ == typ)
+ return ci;
+ ci++;
+ }
+ return NULL;
+}
+
+static int __devinit
+inf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+ int err = -ENOMEM;
+ struct inf_hw *card;
+
+ card = kzalloc(sizeof(struct inf_hw), GFP_KERNEL);
+ if (!card) {
+ pr_info("No memory for Infineon ISDN card\n");
+ return err;
+ }
+ card->pdev = pdev;
+ err = pci_enable_device(pdev);
+ if (err) {
+ kfree(card);
+ return err;
+ }
+ card->ci = get_card_info(ent->driver_data);
+ if (!card->ci) {
+ pr_info("mISDN: do not have informations about adapter at %s\n",
+ pci_name(pdev));
+ kfree(card);
+ return -EINVAL;
+ } else
+ pr_notice("mISDN: found adapter %s at %s\n",
+ card->ci->full, pci_name(pdev));
+
+ card->irq = pdev->irq;
+ pci_set_drvdata(pdev, card);
+ err = setup_instance(card);
+ if (err) {
+ pci_disable_device(card->pdev);
+ kfree(card);
+ pci_set_drvdata(pdev, NULL);
+ } else if (ent->driver_data == INF_SCT_1) {
+ int i;
+ struct inf_hw *sc;
+
+ for (i = 1; i < 4; i++) {
+ sc = kzalloc(sizeof(struct inf_hw), GFP_KERNEL);
+ if (!sc) {
+ release_card(card);
+ return -ENOMEM;
+ }
+ sc->irq = card->irq;
+ sc->pdev = card->pdev;
+ sc->ci = card->ci + i;
+ err = setup_instance(sc);
+ if (err) {
+ kfree(sc);
+ release_card(card);
+ } else
+ card->sc[i - 1] = sc;
+ }
+ }
+ return err;
+}
+
+static void __devexit
+inf_remove(struct pci_dev *pdev)
+{
+ struct inf_hw *card = pci_get_drvdata(pdev);
+
+ if (card)
+ release_card(card);
+ else
+ pr_debug("%s: drvdata allready removed\n", __func__);
+}
+
+static struct pci_driver infineon_driver = {
+ .name = "ISDN Infineon pci",
+ .probe = inf_probe,
+ .remove = __devexit_p(inf_remove),
+ .id_table = infineon_ids,
+};
+
+static int __init
+infineon_init(void)
+{
+ int err;
+
+ pr_notice("Infineon ISDN Driver Rev. %s\n", INFINEON_REV);
+ err = pci_register_driver(&infineon_driver);
+ return err;
+}
+
+static void __exit
+infineon_cleanup(void)
+{
+ pci_unregister_driver(&infineon_driver);
+}
+
+module_init(infineon_init);
+module_exit(infineon_cleanup);
diff --git a/drivers/isdn/hardware/mISDN/mISDNipac.c b/drivers/isdn/hardware/mISDN/mISDNipac.c
new file mode 100644
index 00000000000..613ba043537
--- /dev/null
+++ b/drivers/isdn/hardware/mISDN/mISDNipac.c
@@ -0,0 +1,1655 @@
+/*
+ * isac.c ISAC specific routines
+ *
+ * Author Karsten Keil <keil@isdn4linux.de>
+ *
+ * Copyright 2009 by Karsten Keil <keil@isdn4linux.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/mISDNhw.h>
+#include "ipac.h"
+
+
+#define DBUSY_TIMER_VALUE 80
+#define ARCOFI_USE 1
+
+#define ISAC_REV "2.0"
+
+MODULE_AUTHOR("Karsten Keil");
+MODULE_VERSION(ISAC_REV);
+MODULE_LICENSE("GPL v2");
+
+#define ReadISAC(is, o) (is->read_reg(is->dch.hw, o + is->off))
+#define WriteISAC(is, o, v) (is->write_reg(is->dch.hw, o + is->off, v))
+#define ReadHSCX(h, o) (h->ip->read_reg(h->ip->hw, h->off + o))
+#define WriteHSCX(h, o, v) (h->ip->write_reg(h->ip->hw, h->off + o, v))
+#define ReadIPAC(ip, o) (ip->read_reg(ip->hw, o))
+#define WriteIPAC(ip, o, v) (ip->write_reg(ip->hw, o, v))
+
+static inline void
+ph_command(struct isac_hw *isac, u8 command)
+{
+ pr_debug("%s: ph_command %x\n", isac->name, command);
+ if (isac->type & IPAC_TYPE_ISACX)
+ WriteISAC(isac, ISACX_CIX0, (command << 4) | 0xE);
+ else
+ WriteISAC(isac, ISAC_CIX0, (command << 2) | 3);
+}
+
+static void
+isac_ph_state_change(struct isac_hw *isac)
+{
+ switch (isac->state) {
+ case (ISAC_IND_RS):
+ case (ISAC_IND_EI):
+ ph_command(isac, ISAC_CMD_DUI);
+ }
+ schedule_event(&isac->dch, FLG_PHCHANGE);
+}
+
+static void
+isac_ph_state_bh(struct dchannel *dch)
+{
+ struct isac_hw *isac = container_of(dch, struct isac_hw, dch);
+
+ switch (isac->state) {
+ case ISAC_IND_RS:
+ case ISAC_IND_EI:
+ dch->state = 0;
+ l1_event(dch->l1, HW_RESET_IND);
+ break;
+ case ISAC_IND_DID:
+ dch->state = 3;
+ l1_event(dch->l1, HW_DEACT_CNF);
+ break;
+ case ISAC_IND_DR:
+ dch->state = 3;
+ l1_event(dch->l1, HW_DEACT_IND);
+ break;
+ case ISAC_IND_PU:
+ dch->state = 4;
+ l1_event(dch->l1, HW_POWERUP_IND);
+ break;
+ case ISAC_IND_RSY:
+ if (dch->state <= 5) {
+ dch->state = 5;
+ l1_event(dch->l1, ANYSIGNAL);
+ } else {
+ dch->state = 8;
+ l1_event(dch->l1, LOSTFRAMING);
+ }
+ break;
+ case ISAC_IND_ARD:
+ dch->state = 6;
+ l1_event(dch->l1, INFO2);
+ break;
+ case ISAC_IND_AI8:
+ dch->state = 7;
+ l1_event(dch->l1, INFO4_P8);
+ break;
+ case ISAC_IND_AI10:
+ dch->state = 7;
+ l1_event(dch->l1, INFO4_P10);
+ break;
+ }
+ pr_debug("%s: TE newstate %x\n", isac->name, dch->state);
+}
+
+void
+isac_empty_fifo(struct isac_hw *isac, int count)
+{
+ u8 *ptr;
+
+ pr_debug("%s: %s %d\n", isac->name, __func__, count);
+
+ if (!isac->dch.rx_skb) {
+ isac->dch.rx_skb = mI_alloc_skb(isac->dch.maxlen, GFP_ATOMIC);
+ if (!isac->dch.rx_skb) {
+ pr_info("%s: D receive out of memory\n", isac->name);
+ WriteISAC(isac, ISAC_CMDR, 0x80);
+ return;
+ }
+ }
+ if ((isac->dch.rx_skb->len + count) >= isac->dch.maxlen) {
+ pr_debug("%s: %s overrun %d\n", isac->name, __func__,
+ isac->dch.rx_skb->len + count);
+ WriteISAC(isac, ISAC_CMDR, 0x80);
+ return;
+ }
+ ptr = skb_put(isac->dch.rx_skb, count);
+ isac->read_fifo(isac->dch.hw, isac->off, ptr, count);
+ WriteISAC(isac, ISAC_CMDR, 0x80);
+ if (isac->dch.debug & DEBUG_HW_DFIFO) {
+ char pfx[MISDN_MAX_IDLEN + 16];
+
+ snprintf(pfx, MISDN_MAX_IDLEN + 15, "D-recv %s %d ",
+ isac->name, count);
+ print_hex_dump_bytes(pfx, DUMP_PREFIX_OFFSET, ptr, count);
+ }
+}
+
+static void
+isac_fill_fifo(struct isac_hw *isac)
+{
+ int count, more;
+ u8 *ptr;
+
+ if (!isac->dch.tx_skb)
+ return;
+ count = isac->dch.tx_skb->len - isac->dch.tx_idx;
+ if (count <= 0)
+ return;
+
+ more = 0;
+ if (count > 32) {
+ more = !0;
+ count = 32;
+ }
+ pr_debug("%s: %s %d\n", isac->name, __func__, count);
+ ptr = isac->dch.tx_skb->data + isac->dch.tx_idx;
+ isac->dch.tx_idx += count;
+ isac->write_fifo(isac->dch.hw, isac->off, ptr, count);
+ WriteISAC(isac, ISAC_CMDR, more ? 0x8 : 0xa);
+ if (test_and_set_bit(FLG_BUSY_TIMER, &isac->dch.Flags)) {
+ pr_debug("%s: %s dbusytimer running\n", isac->name, __func__);
+ del_timer(&isac->dch.timer);
+ }
+ init_timer(&isac->dch.timer);
+ isac->dch.timer.expires = jiffies + ((DBUSY_TIMER_VALUE * HZ)/1000);
+ add_timer(&isac->dch.timer);
+ if (isac->dch.debug & DEBUG_HW_DFIFO) {
+ char pfx[MISDN_MAX_IDLEN + 16];
+
+ snprintf(pfx, MISDN_MAX_IDLEN + 15, "D-send %s %d ",
+ isac->name, count);
+ print_hex_dump_bytes(pfx, DUMP_PREFIX_OFFSET, ptr, count);
+ }
+}
+
+static void
+isac_rme_irq(struct isac_hw *isac)
+{
+ u8 val, count;
+
+ val = ReadISAC(isac, ISAC_RSTA);
+ if ((val & 0x70) != 0x20) {
+ if (val & 0x40) {
+ pr_debug("%s: ISAC RDO\n", isac->name);
+#ifdef ERROR_STATISTIC
+ isac->dch.err_rx++;
+#endif
+ }
+ if (!(val & 0x20)) {
+ pr_debug("%s: ISAC CRC error\n", isac->name);
+#ifdef ERROR_STATISTIC
+ isac->dch.err_crc++;
+#endif
+ }
+ WriteISAC(isac, ISAC_CMDR, 0x80);
+ if (isac->dch.rx_skb)
+ dev_kfree_skb(isac->dch.rx_skb);
+ isac->dch.rx_skb = NULL;
+ } else {
+ count = ReadISAC(isac, ISAC_RBCL) & 0x1f;
+ if (count == 0)
+ count = 32;
+ isac_empty_fifo(isac, count);
+ recv_Dchannel(&isac->dch);
+ }
+}
+
+static void
+isac_xpr_irq(struct isac_hw *isac)
+{
+ if (test_and_clear_bit(FLG_BUSY_TIMER, &isac->dch.Flags))
+ del_timer(&isac->dch.timer);
+ if (isac->dch.tx_skb && isac->dch.tx_idx < isac->dch.tx_skb->len) {
+ isac_fill_fifo(isac);
+ } else {
+ if (isac->dch.tx_skb)
+ dev_kfree_skb(isac->dch.tx_skb);
+ if (get_next_dframe(&isac->dch))
+ isac_fill_fifo(isac);
+ }
+}
+
+static void
+isac_retransmit(struct isac_hw *isac)
+{
+ if (test_and_clear_bit(FLG_BUSY_TIMER, &isac->dch.Flags))
+ del_timer(&isac->dch.timer);
+ if (test_bit(FLG_TX_BUSY, &isac->dch.Flags)) {
+ /* Restart frame */
+ isac->dch.tx_idx = 0;
+ isac_fill_fifo(isac);
+ } else if (isac->dch.tx_skb) { /* should not happen */
+ pr_info("%s: tx_skb exist but not busy\n", isac->name);
+ test_and_set_bit(FLG_TX_BUSY, &isac->dch.Flags);
+ isac->dch.tx_idx = 0;
+ isac_fill_fifo(isac);
+ } else {
+ pr_info("%s: ISAC XDU no TX_BUSY\n", isac->name);
+ if (get_next_dframe(&isac->dch))
+ isac_fill_fifo(isac);
+ }
+}
+
+static void
+isac_mos_irq(struct isac_hw *isac)
+{
+ u8 val;
+ int ret;
+
+ val = ReadISAC(isac, ISAC_MOSR);
+ pr_debug("%s: ISAC MOSR %02x\n", isac->name, val);
+#if ARCOFI_USE
+ if (val & 0x08) {
+ if (!isac->mon_rx) {
+ isac->mon_rx = kmalloc(MAX_MON_FRAME, GFP_ATOMIC);
+ if (!isac->mon_rx) {
+ pr_info("%s: ISAC MON RX out of memory!\n",
+ isac->name);
+ isac->mocr &= 0xf0;
+ isac->mocr |= 0x0a;
+ WriteISAC(isac, ISAC_MOCR, isac->mocr);
+ goto afterMONR0;
+ } else
+ isac->mon_rxp = 0;
+ }
+ if (isac->mon_rxp >= MAX_MON_FRAME) {
+ isac->mocr &= 0xf0;
+ isac->mocr |= 0x0a;
+ WriteISAC(isac, ISAC_MOCR, isac->mocr);
+ isac->mon_rxp = 0;
+ pr_debug("%s: ISAC MON RX overflow!\n", isac->name);
+ goto afterMONR0;
+ }
+ isac->mon_rx[isac->mon_rxp++] = ReadISAC(isac, ISAC_MOR0);
+ pr_debug("%s: ISAC MOR0 %02x\n", isac->name,
+ isac->mon_rx[isac->mon_rxp - 1]);
+ if (isac->mon_rxp == 1) {
+ isac->mocr |= 0x04;
+ WriteISAC(isac, ISAC_MOCR, isac->mocr);
+ }
+ }
+afterMONR0:
+ if (val & 0x80) {
+ if (!isac->mon_rx) {
+ isac->mon_rx = kmalloc(MAX_MON_FRAME, GFP_ATOMIC);
+ if (!isac->mon_rx) {
+ pr_info("%s: ISAC MON RX out of memory!\n",
+ isac->name);
+ isac->mocr &= 0x0f;
+ isac->mocr |= 0xa0;
+ WriteISAC(isac, ISAC_MOCR, isac->mocr);
+ goto afterMONR1;
+ } else
+ isac->mon_rxp = 0;
+ }
+ if (isac->mon_rxp >= MAX_MON_FRAME) {
+ isac->mocr &= 0x0f;
+ isac->mocr |= 0xa0;
+ WriteISAC(isac, ISAC_MOCR, isac->mocr);
+ isac->mon_rxp = 0;
+ pr_debug("%s: ISAC MON RX overflow!\n", isac->name);
+ goto afterMONR1;
+ }
+ isac->mon_rx[isac->mon_rxp++] = ReadISAC(isac, ISAC_MOR1);
+ pr_debug("%s: ISAC MOR1 %02x\n", isac->name,
+ isac->mon_rx[isac->mon_rxp - 1]);
+ isac->mocr |= 0x40;
+ WriteISAC(isac, ISAC_MOCR, isac->mocr);
+ }
+afterMONR1:
+ if (val & 0x04) {
+ isac->mocr &= 0xf0;
+ WriteISAC(isac, ISAC_MOCR, isac->mocr);
+ isac->mocr |= 0x0a;
+ WriteISAC(isac, ISAC_MOCR, isac->mocr);
+ if (isac->monitor) {
+ ret = isac->monitor(isac->dch.hw, MONITOR_RX_0,
+ isac->mon_rx, isac->mon_rxp);
+ if (ret)
+ kfree(isac->mon_rx);
+ } else {
+ pr_info("%s: MONITOR 0 received %d but no user\n",
+ isac->name, isac->mon_rxp);
+ kfree(isac->mon_rx);
+ }
+ isac->mon_rx = NULL;
+ isac->mon_rxp = 0;
+ }
+ if (val & 0x40) {
+ isac->mocr &= 0x0f;
+ WriteISAC(isac, ISAC_MOCR, isac->mocr);
+ isac->mocr |= 0xa0;
+ WriteISAC(isac, ISAC_MOCR, isac->mocr);
+ if (isac->monitor) {
+ ret = isac->monitor(isac->dch.hw, MONITOR_RX_1,
+ isac->mon_rx, isac->mon_rxp);
+ if (ret)
+ kfree(isac->mon_rx);
+ } else {
+ pr_info("%s: MONITOR 1 received %d but no user\n",
+ isac->name, isac->mon_rxp);
+ kfree(isac->mon_rx);
+ }
+ isac->mon_rx = NULL;
+ isac->mon_rxp = 0;
+ }
+ if (val & 0x02) {
+ if ((!isac->mon_tx) || (isac->mon_txc &&
+ (isac->mon_txp >= isac->mon_txc) && !(val & 0x08))) {
+ isac->mocr &= 0xf0;
+ WriteISAC(isac, ISAC_MOCR, isac->mocr);
+ isac->mocr |= 0x0a;
+ WriteISAC(isac, ISAC_MOCR, isac->mocr);
+ if (isac->mon_txc && (isac->mon_txp >= isac->mon_txc)) {
+ if (isac->monitor)
+ ret = isac->monitor(isac->dch.hw,
+ MONITOR_TX_0, NULL, 0);
+ }
+ kfree(isac->mon_tx);
+ isac->mon_tx = NULL;
+ isac->mon_txc = 0;
+ isac->mon_txp = 0;
+ goto AfterMOX0;
+ }
+ if (isac->mon_txc && (isac->mon_txp >= isac->mon_txc)) {
+ if (isac->monitor)
+ ret = isac->monitor(isac->dch.hw,
+ MONITOR_TX_0, NULL, 0);
+ kfree(isac->mon_tx);
+ isac->mon_tx = NULL;
+ isac->mon_txc = 0;
+ isac->mon_txp = 0;
+ goto AfterMOX0;
+ }
+ WriteISAC(isac, ISAC_MOX0, isac->mon_tx[isac->mon_txp++]);
+ pr_debug("%s: ISAC %02x -> MOX0\n", isac->name,
+ isac->mon_tx[isac->mon_txp - 1]);
+ }
+AfterMOX0:
+ if (val & 0x20) {
+ if ((!isac->mon_tx) || (isac->mon_txc &&
+ (isac->mon_txp >= isac->mon_txc) && !(val & 0x80))) {
+ isac->mocr &= 0x0f;
+ WriteISAC(isac, ISAC_MOCR, isac->mocr);
+ isac->mocr |= 0xa0;
+ WriteISAC(isac, ISAC_MOCR, isac->mocr);
+ if (isac->mon_txc && (isac->mon_txp >= isac->mon_txc)) {
+ if (isac->monitor)
+ ret = isac->monitor(isac->dch.hw,
+ MONITOR_TX_1, NULL, 0);
+ }
+ kfree(isac->mon_tx);
+ isac->mon_tx = NULL;
+ isac->mon_txc = 0;
+ isac->mon_txp = 0;
+ goto AfterMOX1;
+ }
+ if (isac->mon_txc && (isac->mon_txp >= isac->mon_txc)) {
+ if (isac->monitor)
+ ret = isac->monitor(isac->dch.hw,
+ MONITOR_TX_1, NULL, 0);
+ kfree(isac->mon_tx);
+ isac->mon_tx = NULL;
+ isac->mon_txc = 0;
+ isac->mon_txp = 0;
+ goto AfterMOX1;
+ }
+ WriteISAC(isac, ISAC_MOX1, isac->mon_tx[isac->mon_txp++]);
+ pr_debug("%s: ISAC %02x -> MOX1\n", isac->name,
+ isac->mon_tx[isac->mon_txp - 1]);
+ }
+AfterMOX1:
+ val = 0; /* dummy to avoid warning */
+#endif
+}
+
+static void
+isac_cisq_irq(struct isac_hw *isac) {
+ u8 val;
+
+ val = ReadISAC(isac, ISAC_CIR0);
+ pr_debug("%s: ISAC CIR0 %02X\n", isac->name, val);
+ if (val & 2) {
+ pr_debug("%s: ph_state change %x->%x\n", isac->name,
+ isac->state, (val >> 2) & 0xf);
+ isac->state = (val >> 2) & 0xf;
+ isac_ph_state_change(isac);
+ }
+ if (val & 1) {
+ val = ReadISAC(isac, ISAC_CIR1);
+ pr_debug("%s: ISAC CIR1 %02X\n", isac->name, val);
+ }
+}
+
+static void
+isacsx_cic_irq(struct isac_hw *isac)
+{
+ u8 val;
+
+ val = ReadISAC(isac, ISACX_CIR0);
+ pr_debug("%s: ISACX CIR0 %02X\n", isac->name, val);
+ if (val & ISACX_CIR0_CIC0) {
+ pr_debug("%s: ph_state change %x->%x\n", isac->name,
+ isac->state, val >> 4);
+ isac->state = val >> 4;
+ isac_ph_state_change(isac);
+ }
+}
+
+static void
+isacsx_rme_irq(struct isac_hw *isac)
+{
+ int count;
+ u8 val;
+
+ val = ReadISAC(isac, ISACX_RSTAD);
+ if ((val & (ISACX_RSTAD_VFR |
+ ISACX_RSTAD_RDO |
+ ISACX_RSTAD_CRC |
+ ISACX_RSTAD_RAB))
+ != (ISACX_RSTAD_VFR | ISACX_RSTAD_CRC)) {
+ pr_debug("%s: RSTAD %#x, dropped\n", isac->name, val);
+#ifdef ERROR_STATISTIC
+ if (val & ISACX_RSTAD_CRC)
+ isac->dch.err_rx++;
+ else
+ isac->dch.err_crc++;
+#endif
+ WriteISAC(isac, ISACX_CMDRD, ISACX_CMDRD_RMC);
+ if (isac->dch.rx_skb)
+ dev_kfree_skb(isac->dch.rx_skb);
+ isac->dch.rx_skb = NULL;
+ } else {
+ count = ReadISAC(isac, ISACX_RBCLD) & 0x1f;
+ if (count == 0)
+ count = 32;
+ isac_empty_fifo(isac, count);
+ if (isac->dch.rx_skb) {
+ skb_trim(isac->dch.rx_skb, isac->dch.rx_skb->len - 1);
+ pr_debug("%s: dchannel received %d\n", isac->name,
+ isac->dch.rx_skb->len);
+ recv_Dchannel(&isac->dch);
+ }
+ }
+}
+
+irqreturn_t
+mISDNisac_irq(struct isac_hw *isac, u8 val)
+{
+ if (unlikely(!val))
+ return IRQ_NONE;
+ pr_debug("%s: ISAC interrupt %02x\n", isac->name, val);
+ if (isac->type & IPAC_TYPE_ISACX) {
+ if (val & ISACX__CIC)
+ isacsx_cic_irq(isac);
+ if (val & ISACX__ICD) {
+ val = ReadISAC(isac, ISACX_ISTAD);
+ pr_debug("%s: ISTAD %02x\n", isac->name, val);
+ if (val & ISACX_D_XDU) {
+ pr_debug("%s: ISAC XDU\n", isac->name);
+#ifdef ERROR_STATISTIC
+ isac->dch.err_tx++;
+#endif
+ isac_retransmit(isac);
+ }
+ if (val & ISACX_D_XMR) {
+ pr_debug("%s: ISAC XMR\n", isac->name);
+#ifdef ERROR_STATISTIC
+ isac->dch.err_tx++;
+#endif
+ isac_retransmit(isac);
+ }
+ if (val & ISACX_D_XPR)
+ isac_xpr_irq(isac);
+ if (val & ISACX_D_RFO) {
+ pr_debug("%s: ISAC RFO\n", isac->name);
+ WriteISAC(isac, ISACX_CMDRD, ISACX_CMDRD_RMC);
+ }
+ if (val & ISACX_D_RME)
+ isacsx_rme_irq(isac);
+ if (val & ISACX_D_RPF)
+ isac_empty_fifo(isac, 0x20);
+ }
+ } else {
+ if (val & 0x80) /* RME */
+ isac_rme_irq(isac);
+ if (val & 0x40) /* RPF */
+ isac_empty_fifo(isac, 32);
+ if (val & 0x10) /* XPR */
+ isac_xpr_irq(isac);
+ if (val & 0x04) /* CISQ */
+ isac_cisq_irq(isac);
+ if (val & 0x20) /* RSC - never */
+ pr_debug("%s: ISAC RSC interrupt\n", isac->name);
+ if (val & 0x02) /* SIN - never */
+ pr_debug("%s: ISAC SIN interrupt\n", isac->name);
+ if (val & 0x01) { /* EXI */
+ val = ReadISAC(isac, ISAC_EXIR);
+ pr_debug("%s: ISAC EXIR %02x\n", isac->name, val);
+ if (val & 0x80) /* XMR */
+ pr_debug("%s: ISAC XMR\n", isac->name);
+ if (val & 0x40) { /* XDU */
+ pr_debug("%s: ISAC XDU\n", isac->name);
+#ifdef ERROR_STATISTIC
+ isac->dch.err_tx++;
+#endif
+ isac_retransmit(isac);
+ }
+ if (val & 0x04) /* MOS */
+ isac_mos_irq(isac);
+ }
+ }
+ return IRQ_HANDLED;
+}
+EXPORT_SYMBOL(mISDNisac_irq);
+
+static int
+isac_l1hw(struct mISDNchannel *ch, struct sk_buff *skb)
+{
+ struct mISDNdevice *dev = container_of(ch, struct mISDNdevice, D);
+ struct dchannel *dch = container_of(dev, struct dchannel, dev);
+ struct isac_hw *isac = container_of(dch, struct isac_hw, dch);
+ int ret = -EINVAL;
+ struct mISDNhead *hh = mISDN_HEAD_P(skb);
+ u32 id;
+ u_long flags;
+
+ switch (hh->prim) {
+ case PH_DATA_REQ:
+ spin_lock_irqsave(isac->hwlock, flags);
+ ret = dchannel_senddata(dch, skb);
+ if (ret > 0) { /* direct TX */
+ id = hh->id; /* skb can be freed */
+ isac_fill_fifo(isac);
+ ret = 0;
+ spin_unlock_irqrestore(isac->hwlock, flags);
+ queue_ch_frame(ch, PH_DATA_CNF, id, NULL);
+ } else
+ spin_unlock_irqrestore(isac->hwlock, flags);
+ return ret;
+ case PH_ACTIVATE_REQ:
+ ret = l1_event(dch->l1, hh->prim);
+ break;
+ case PH_DEACTIVATE_REQ:
+ test_and_clear_bit(FLG_L2_ACTIVATED, &dch->Flags);
+ ret = l1_event(dch->l1, hh->prim);
+ break;
+ }
+
+ if (!ret)
+ dev_kfree_skb(skb);
+ return ret;
+}
+
+static int
+isac_ctrl(struct isac_hw *isac, u32 cmd, u_long para)
+{
+ u8 tl = 0;
+ u_long flags;
+
+ switch (cmd) {
+ case HW_TESTLOOP:
+ spin_lock_irqsave(isac->hwlock, flags);
+ if (!(isac->type & IPAC_TYPE_ISACX)) {
+ /* TODO: implement for IPAC_TYPE_ISACX */
+ if (para & 1) /* B1 */
+ tl |= 0x0c;
+ else if (para & 2) /* B2 */
+ tl |= 0x3;
+ /* we only support IOM2 mode */
+ WriteISAC(isac, ISAC_SPCR, tl);
+ if (tl)
+ WriteISAC(isac, ISAC_ADF1, 0x8);
+ else
+ WriteISAC(isac, ISAC_ADF1, 0x0);
+ }
+ spin_unlock_irqrestore(isac->hwlock, flags);
+ break;
+ default:
+ pr_debug("%s: %s unknown command %x %lx\n", isac->name,
+ __func__, cmd, para);
+ return -1;
+ }
+ return 0;
+}
+
+static int
+isac_l1cmd(struct dchannel *dch, u32 cmd)
+{
+ struct isac_hw *isac = container_of(dch, struct isac_hw, dch);
+ u_long flags;
+
+ pr_debug("%s: cmd(%x) state(%02x)\n", isac->name, cmd, isac->state);
+ switch (cmd) {
+ case INFO3_P8:
+ spin_lock_irqsave(isac->hwlock, flags);
+ ph_command(isac, ISAC_CMD_AR8);
+ spin_unlock_irqrestore(isac->hwlock, flags);
+ break;
+ case INFO3_P10:
+ spin_lock_irqsave(isac->hwlock, flags);
+ ph_command(isac, ISAC_CMD_AR10);
+ spin_unlock_irqrestore(isac->hwlock, flags);
+ break;
+ case HW_RESET_REQ:
+ spin_lock_irqsave(isac->hwlock, flags);
+ if ((isac->state == ISAC_IND_EI) ||
+ (isac->state == ISAC_IND_DR) ||
+ (isac->state == ISAC_IND_RS))
+ ph_command(isac, ISAC_CMD_TIM);
+ else
+ ph_command(isac, ISAC_CMD_RS);
+ spin_unlock_irqrestore(isac->hwlock, flags);
+ break;
+ case HW_DEACT_REQ:
+ skb_queue_purge(&dch->squeue);
+ if (dch->tx_skb) {
+ dev_kfree_skb(dch->tx_skb);
+ dch->tx_skb = NULL;
+ }
+ dch->tx_idx = 0;
+ if (dch->rx_skb) {
+ dev_kfree_skb(dch->rx_skb);
+ dch->rx_skb = NULL;
+ }
+ test_and_clear_bit(FLG_TX_BUSY, &dch->Flags);
+ if (test_and_clear_bit(FLG_BUSY_TIMER, &dch->Flags))
+ del_timer(&dch->timer);
+ break;
+ case HW_POWERUP_REQ:
+ spin_lock_irqsave(isac->hwlock, flags);
+ ph_command(isac, ISAC_CMD_TIM);
+ spin_unlock_irqrestore(isac->hwlock, flags);
+ break;
+ case PH_ACTIVATE_IND:
+ test_and_set_bit(FLG_ACTIVE, &dch->Flags);
+ _queue_data(&dch->dev.D, cmd, MISDN_ID_ANY, 0, NULL,
+ GFP_ATOMIC);
+ break;
+ case PH_DEACTIVATE_IND:
+ test_and_clear_bit(FLG_ACTIVE, &dch->Flags);
+ _queue_data(&dch->dev.D, cmd, MISDN_ID_ANY, 0, NULL,
+ GFP_ATOMIC);
+ break;
+ default:
+ pr_debug("%s: %s unknown command %x\n", isac->name,
+ __func__, cmd);
+ return -1;
+ }
+ return 0;
+}
+
+static void
+isac_release(struct isac_hw *isac)
+{
+ if (isac->type & IPAC_TYPE_ISACX)
+ WriteISAC(isac, ISACX_MASK, 0xff);
+ else
+ WriteISAC(isac, ISAC_MASK, 0xff);
+ if (isac->dch.timer.function != NULL) {
+ del_timer(&isac->dch.timer);
+ isac->dch.timer.function = NULL;
+ }
+ kfree(isac->mon_rx);
+ isac->mon_rx = NULL;
+ kfree(isac->mon_tx);
+ isac->mon_tx = NULL;
+ if (isac->dch.l1)
+ l1_event(isac->dch.l1, CLOSE_CHANNEL);
+ mISDN_freedchannel(&isac->dch);
+}
+
+static void
+dbusy_timer_handler(struct isac_hw *isac)
+{
+ int rbch, star;
+ u_long flags;
+
+ if (test_bit(FLG_BUSY_TIMER, &isac->dch.Flags)) {
+ spin_lock_irqsave(isac->hwlock, flags);
+ rbch = ReadISAC(isac, ISAC_RBCH);
+ star = ReadISAC(isac, ISAC_STAR);
+ pr_debug("%s: D-Channel Busy RBCH %02x STAR %02x\n",
+ isac->name, rbch, star);
+ if (rbch & ISAC_RBCH_XAC) /* D-Channel Busy */
+ test_and_set_bit(FLG_L1_BUSY, &isac->dch.Flags);
+ else {
+ /* discard frame; reset transceiver */
+ test_and_clear_bit(FLG_BUSY_TIMER, &isac->dch.Flags);
+ if (isac->dch.tx_idx)
+ isac->dch.tx_idx = 0;
+ else
+ pr_info("%s: ISAC D-Channel Busy no tx_idx\n",
+ isac->name);
+ /* Transmitter reset */
+ WriteISAC(isac, ISAC_CMDR, 0x01);
+ }
+ spin_unlock_irqrestore(isac->hwlock, flags);
+ }
+}
+
+static int
+open_dchannel(struct isac_hw *isac, struct channel_req *rq)
+{
+ pr_debug("%s: %s dev(%d) open from %p\n", isac->name, __func__,
+ isac->dch.dev.id, __builtin_return_address(1));
+ if (rq->protocol != ISDN_P_TE_S0)
+ return -EINVAL;
+ if (rq->adr.channel == 1)
+ /* E-Channel not supported */
+ return -EINVAL;
+ rq->ch = &isac->dch.dev.D;
+ rq->ch->protocol = rq->protocol;
+ if (isac->dch.state == 7)
+ _queue_data(rq->ch, PH_ACTIVATE_IND, MISDN_ID_ANY,
+ 0, NULL, GFP_KERNEL);
+ return 0;
+}
+
+static const char *ISACVer[] =
+{"2086/2186 V1.1", "2085 B1", "2085 B2",
+ "2085 V2.3"};
+
+static int
+isac_init(struct isac_hw *isac)
+{
+ u8 val;
+ int err = 0;
+
+ if (!isac->dch.l1) {
+ err = create_l1(&isac->dch, isac_l1cmd);
+ if (err)
+ return err;
+ }
+ isac->mon_tx = NULL;
+ isac->mon_rx = NULL;
+ isac->dch.timer.function = (void *) dbusy_timer_handler;
+ isac->dch.timer.data = (long)isac;
+ init_timer(&isac->dch.timer);
+ isac->mocr = 0xaa;
+ if (isac->type & IPAC_TYPE_ISACX) {
+ /* Disable all IRQ */
+ WriteISAC(isac, ISACX_MASK, 0xff);
+ val = ReadISAC(isac, ISACX_STARD);
+ pr_debug("%s: ISACX STARD %x\n", isac->name, val);
+ val = ReadISAC(isac, ISACX_ISTAD);
+ pr_debug("%s: ISACX ISTAD %x\n", isac->name, val);
+ val = ReadISAC(isac, ISACX_ISTA);
+ pr_debug("%s: ISACX ISTA %x\n", isac->name, val);
+ /* clear LDD */
+ WriteISAC(isac, ISACX_TR_CONF0, 0x00);
+ /* enable transmitter */
+ WriteISAC(isac, ISACX_TR_CONF2, 0x00);
+ /* transparent mode 0, RAC, stop/go */
+ WriteISAC(isac, ISACX_MODED, 0xc9);
+ /* all HDLC IRQ unmasked */
+ val = ReadISAC(isac, ISACX_ID);
+ if (isac->dch.debug & DEBUG_HW)
+ pr_notice("%s: ISACX Design ID %x\n",
+ isac->name, val & 0x3f);
+ val = ReadISAC(isac, ISACX_CIR0);
+ pr_debug("%s: ISACX CIR0 %02X\n", isac->name, val);
+ isac->state = val >> 4;
+ isac_ph_state_change(isac);
+ ph_command(isac, ISAC_CMD_RS);
+ WriteISAC(isac, ISACX_MASK, IPACX__ON);
+ WriteISAC(isac, ISACX_MASKD, 0x00);
+ } else { /* old isac */
+ WriteISAC(isac, ISAC_MASK, 0xff);
+ val = ReadISAC(isac, ISAC_STAR);
+ pr_debug("%s: ISAC STAR %x\n", isac->name, val);
+ val = ReadISAC(isac, ISAC_MODE);
+ pr_debug("%s: ISAC MODE %x\n", isac->name, val);
+ val = ReadISAC(isac, ISAC_ADF2);
+ pr_debug("%s: ISAC ADF2 %x\n", isac->name, val);
+ val = ReadISAC(isac, ISAC_ISTA);
+ pr_debug("%s: ISAC ISTA %x\n", isac->name, val);
+ if (val & 0x01) {
+ val = ReadISAC(isac, ISAC_EXIR);
+ pr_debug("%s: ISAC EXIR %x\n", isac->name, val);
+ }
+ val = ReadISAC(isac, ISAC_RBCH);
+ if (isac->dch.debug & DEBUG_HW)
+ pr_notice("%s: ISAC version (%x): %s\n", isac->name,
+ val, ISACVer[(val >> 5) & 3]);
+ isac->type |= ((val >> 5) & 3);
+ if (!isac->adf2)
+ isac->adf2 = 0x80;
+ if (!(isac->adf2 & 0x80)) { /* only IOM 2 Mode */
+ pr_info("%s: only support IOM2 mode but adf2=%02x\n",
+ isac->name, isac->adf2);
+ isac_release(isac);
+ return -EINVAL;
+ }
+ WriteISAC(isac, ISAC_ADF2, isac->adf2);
+ WriteISAC(isac, ISAC_SQXR, 0x2f);
+ WriteISAC(isac, ISAC_SPCR, 0x00);
+ WriteISAC(isac, ISAC_STCR, 0x70);
+ WriteISAC(isac, ISAC_MODE, 0xc9);
+ WriteISAC(isac, ISAC_TIMR, 0x00);
+ WriteISAC(isac, ISAC_ADF1, 0x00);
+ val = ReadISAC(isac, ISAC_CIR0);
+ pr_debug("%s: ISAC CIR0 %x\n", isac->name, val);
+ isac->state = (val >> 2) & 0xf;
+ isac_ph_state_change(isac);
+ ph_command(isac, ISAC_CMD_RS);
+ WriteISAC(isac, ISAC_MASK, 0);
+ }
+ return err;
+}
+
+int
+mISDNisac_init(struct isac_hw *isac, void *hw)
+{
+ mISDN_initdchannel(&isac->dch, MAX_DFRAME_LEN_L1, isac_ph_state_bh);
+ isac->dch.hw = hw;
+ isac->dch.dev.D.send = isac_l1hw;
+ isac->init = isac_init;
+ isac->release = isac_release;
+ isac->ctrl = isac_ctrl;
+ isac->open = open_dchannel;
+ isac->dch.dev.Dprotocols = (1 << ISDN_P_TE_S0);
+ isac->dch.dev.nrbchan = 2;
+ return 0;
+}
+EXPORT_SYMBOL(mISDNisac_init);
+
+static void
+waitforCEC(struct hscx_hw *hx)
+{
+ u8 starb, to = 50;
+
+ while (to) {
+ starb = ReadHSCX(hx, IPAC_STARB);
+ if (!(starb & 0x04))
+ break;
+ udelay(1);
+ to--;
+ }
+ if (to < 50)
+ pr_debug("%s: B%1d CEC %d us\n", hx->ip->name, hx->bch.nr,
+ 50 - to);
+ if (!to)
+ pr_info("%s: B%1d CEC timeout\n", hx->ip->name, hx->bch.nr);
+}
+
+
+static void
+waitforXFW(struct hscx_hw *hx)
+{
+ u8 starb, to = 50;
+
+ while (to) {
+ starb = ReadHSCX(hx, IPAC_STARB);
+ if ((starb & 0x44) == 0x40)
+ break;
+ udelay(1);
+ to--;
+ }
+ if (to < 50)
+ pr_debug("%s: B%1d XFW %d us\n", hx->ip->name, hx->bch.nr,
+ 50 - to);
+ if (!to)
+ pr_info("%s: B%1d XFW timeout\n", hx->ip->name, hx->bch.nr);
+}
+
+static void
+hscx_cmdr(struct hscx_hw *hx, u8 cmd)
+{
+ if (hx->ip->type & IPAC_TYPE_IPACX)
+ WriteHSCX(hx, IPACX_CMDRB, cmd);
+ else {
+ waitforCEC(hx);
+ WriteHSCX(hx, IPAC_CMDRB, cmd);
+ }
+}
+
+static void
+hscx_empty_fifo(struct hscx_hw *hscx, u8 count)
+{
+ u8 *p;
+
+ pr_debug("%s: B%1d %d\n", hscx->ip->name, hscx->bch.nr, count);
+ if (!hscx->bch.rx_skb) {
+ hscx->bch.rx_skb = mI_alloc_skb(hscx->bch.maxlen, GFP_ATOMIC);
+ if (!hscx->bch.rx_skb) {
+ pr_info("%s: B receive out of memory\n",
+ hscx->ip->name);
+ hscx_cmdr(hscx, 0x80); /* RMC */
+ return;
+ }
+ }
+ if ((hscx->bch.rx_skb->len + count) > hscx->bch.maxlen) {
+ pr_debug("%s: overrun %d\n", hscx->ip->name,
+ hscx->bch.rx_skb->len + count);
+ skb_trim(hscx->bch.rx_skb, 0);
+ hscx_cmdr(hscx, 0x80); /* RMC */
+ return;
+ }
+ p = skb_put(hscx->bch.rx_skb, count);
+
+ if (hscx->ip->type & IPAC_TYPE_IPACX)
+ hscx->ip->read_fifo(hscx->ip->hw,
+ hscx->off + IPACX_RFIFOB, p, count);
+ else
+ hscx->ip->read_fifo(hscx->ip->hw,
+ hscx->off, p, count);
+
+ hscx_cmdr(hscx, 0x80); /* RMC */
+
+ if (hscx->bch.debug & DEBUG_HW_BFIFO) {
+ snprintf(hscx->log, 64, "B%1d-recv %s %d ",
+ hscx->bch.nr, hscx->ip->name, count);
+ print_hex_dump_bytes(hscx->log, DUMP_PREFIX_OFFSET, p, count);
+ }
+}
+
+static void
+hscx_fill_fifo(struct hscx_hw *hscx)
+{
+ int count, more;
+ u8 *p;
+
+ if (!hscx->bch.tx_skb)
+ return;
+ count = hscx->bch.tx_skb->len - hscx->bch.tx_idx;
+ if (count <= 0)
+ return;
+ p = hscx->bch.tx_skb->data + hscx->bch.tx_idx;
+
+ more = test_bit(FLG_TRANSPARENT, &hscx->bch.Flags) ? 1 : 0;
+ if (count > hscx->fifo_size) {
+ count = hscx->fifo_size;
+ more = 1;
+ }
+ pr_debug("%s: B%1d %d/%d/%d\n", hscx->ip->name, hscx->bch.nr, count,
+ hscx->bch.tx_idx, hscx->bch.tx_skb->len);
+ hscx->bch.tx_idx += count;
+
+ if (hscx->ip->type & IPAC_TYPE_IPACX)
+ hscx->ip->write_fifo(hscx->ip->hw,
+ hscx->off + IPACX_XFIFOB, p, count);
+ else {
+ waitforXFW(hscx);
+ hscx->ip->write_fifo(hscx->ip->hw,
+ hscx->off, p, count);
+ }
+ hscx_cmdr(hscx, more ? 0x08 : 0x0a);
+
+ if (hscx->bch.debug & DEBUG_HW_BFIFO) {
+ snprintf(hscx->log, 64, "B%1d-send %s %d ",
+ hscx->bch.nr, hscx->ip->name, count);
+ print_hex_dump_bytes(hscx->log, DUMP_PREFIX_OFFSET, p, count);
+ }
+}
+
+static void
+hscx_xpr(struct hscx_hw *hx)
+{
+ if (hx->bch.tx_skb && hx->bch.tx_idx < hx->bch.tx_skb->len)
+ hscx_fill_fifo(hx);
+ else {
+ if (hx->bch.tx_skb) {
+ /* send confirm, on trans, free on hdlc. */
+ if (test_bit(FLG_TRANSPARENT, &hx->bch.Flags))
+ confirm_Bsend(&hx->bch);
+ dev_kfree_skb(hx->bch.tx_skb);
+ }
+ if (get_next_bframe(&hx->bch))
+ hscx_fill_fifo(hx);
+ }
+}
+
+static void
+ipac_rme(struct hscx_hw *hx)
+{
+ int count;
+ u8 rstab;
+
+ if (hx->ip->type & IPAC_TYPE_IPACX)
+ rstab = ReadHSCX(hx, IPACX_RSTAB);
+ else
+ rstab = ReadHSCX(hx, IPAC_RSTAB);
+ pr_debug("%s: B%1d RSTAB %02x\n", hx->ip->name, hx->bch.nr, rstab);
+ if ((rstab & 0xf0) != 0xa0) {
+ /* !(VFR && !RDO && CRC && !RAB) */
+ if (!(rstab & 0x80)) {
+ if (hx->bch.debug & DEBUG_HW_BCHANNEL)
+ pr_notice("%s: B%1d invalid frame\n",
+ hx->ip->name, hx->bch.nr);
+ }
+ if (rstab & 0x40) {
+ if (hx->bch.debug & DEBUG_HW_BCHANNEL)
+ pr_notice("%s: B%1d RDO proto=%x\n",
+ hx->ip->name, hx->bch.nr,
+ hx->bch.state);
+ }
+ if (!(rstab & 0x20)) {
+ if (hx->bch.debug & DEBUG_HW_BCHANNEL)
+ pr_notice("%s: B%1d CRC error\n",
+ hx->ip->name, hx->bch.nr);
+ }
+ hscx_cmdr(hx, 0x80); /* Do RMC */
+ return;
+ }
+ if (hx->ip->type & IPAC_TYPE_IPACX)
+ count = ReadHSCX(hx, IPACX_RBCLB);
+ else
+ count = ReadHSCX(hx, IPAC_RBCLB);
+ count &= (hx->fifo_size - 1);
+ if (count == 0)
+ count = hx->fifo_size;
+ hscx_empty_fifo(hx, count);
+ if (!hx->bch.rx_skb)
+ return;
+ if (hx->bch.rx_skb->len < 2) {
+ pr_debug("%s: B%1d frame to short %d\n",
+ hx->ip->name, hx->bch.nr, hx->bch.rx_skb->len);
+ skb_trim(hx->bch.rx_skb, 0);
+ } else {
+ skb_trim(hx->bch.rx_skb, hx->bch.rx_skb->len - 1);
+ recv_Bchannel(&hx->bch, 0);
+ }
+}
+
+static void
+ipac_irq(struct hscx_hw *hx, u8 ista)
+{
+ u8 istab, m, exirb = 0;
+
+ if (hx->ip->type & IPAC_TYPE_IPACX)
+ istab = ReadHSCX(hx, IPACX_ISTAB);
+ else if (hx->ip->type & IPAC_TYPE_IPAC) {
+ istab = ReadHSCX(hx, IPAC_ISTAB);
+ m = (hx->bch.nr & 1) ? IPAC__EXA : IPAC__EXB;
+ if (m & ista) {
+ exirb = ReadHSCX(hx, IPAC_EXIRB);
+ pr_debug("%s: B%1d EXIRB %02x\n", hx->ip->name,
+ hx->bch.nr, exirb);
+ }
+ } else if (hx->bch.nr & 2) { /* HSCX B */
+ if (ista & (HSCX__EXA | HSCX__ICA))
+ ipac_irq(&hx->ip->hscx[0], ista);
+ if (ista & HSCX__EXB) {
+ exirb = ReadHSCX(hx, IPAC_EXIRB);
+ pr_debug("%s: B%1d EXIRB %02x\n", hx->ip->name,
+ hx->bch.nr, exirb);
+ }
+ istab = ista & 0xF8;
+ } else { /* HSCX A */
+ istab = ReadHSCX(hx, IPAC_ISTAB);
+ if (ista & HSCX__EXA) {
+ exirb = ReadHSCX(hx, IPAC_EXIRB);
+ pr_debug("%s: B%1d EXIRB %02x\n", hx->ip->name,
+ hx->bch.nr, exirb);
+ }
+ istab = istab & 0xF8;
+ }
+ if (exirb & IPAC_B_XDU)
+ istab |= IPACX_B_XDU;
+ if (exirb & IPAC_B_RFO)
+ istab |= IPACX_B_RFO;
+ pr_debug("%s: B%1d ISTAB %02x\n", hx->ip->name, hx->bch.nr, istab);
+
+ if (!test_bit(FLG_ACTIVE, &hx->bch.Flags))
+ return;
+
+ if (istab & IPACX_B_RME)
+ ipac_rme(hx);
+
+ if (istab & IPACX_B_RPF) {
+ hscx_empty_fifo(hx, hx->fifo_size);
+ if (test_bit(FLG_TRANSPARENT, &hx->bch.Flags)) {
+ /* receive transparent audio data */
+ if (hx->bch.rx_skb)
+ recv_Bchannel(&hx->bch, 0);
+ }
+ }
+
+ if (istab & IPACX_B_RFO) {
+ pr_debug("%s: B%1d RFO error\n", hx->ip->name, hx->bch.nr);
+ hscx_cmdr(hx, 0x40); /* RRES */
+ }
+
+ if (istab & IPACX_B_XPR)
+ hscx_xpr(hx);
+
+ if (istab & IPACX_B_XDU) {
+ if (test_bit(FLG_TRANSPARENT, &hx->bch.Flags)) {
+ hscx_fill_fifo(hx);
+ return;
+ }
+ pr_debug("%s: B%1d XDU error at len %d\n", hx->ip->name,
+ hx->bch.nr, hx->bch.tx_idx);
+ hx->bch.tx_idx = 0;
+ hscx_cmdr(hx, 0x01); /* XRES */
+ }
+}
+
+irqreturn_t
+mISDNipac_irq(struct ipac_hw *ipac, int maxloop)
+{
+ int cnt = maxloop + 1;
+ u8 ista, istad;
+ struct isac_hw *isac = &ipac->isac;
+
+ if (ipac->type & IPAC_TYPE_IPACX) {
+ ista = ReadIPAC(ipac, ISACX_ISTA);
+ while (ista && cnt--) {
+ pr_debug("%s: ISTA %02x\n", ipac->name, ista);
+ if (ista & IPACX__ICA)
+ ipac_irq(&ipac->hscx[0], ista);
+ if (ista & IPACX__ICB)
+ ipac_irq(&ipac->hscx[1], ista);
+ if (ista & (ISACX__ICD | ISACX__CIC))
+ mISDNisac_irq(&ipac->isac, ista);
+ ista = ReadIPAC(ipac, ISACX_ISTA);
+ }
+ } else if (ipac->type & IPAC_TYPE_IPAC) {
+ ista = ReadIPAC(ipac, IPAC_ISTA);
+ while (ista && cnt--) {
+ pr_debug("%s: ISTA %02x\n", ipac->name, ista);
+ if (ista & (IPAC__ICD | IPAC__EXD)) {
+ istad = ReadISAC(isac, ISAC_ISTA);
+ pr_debug("%s: ISTAD %02x\n", ipac->name, istad);
+ if (istad & IPAC_D_TIN2)
+ pr_debug("%s TIN2 irq\n", ipac->name);
+ if (ista & IPAC__EXD)
+ istad |= 1; /* ISAC EXI */
+ mISDNisac_irq(isac, istad);
+ }
+ if (ista & (IPAC__ICA | IPAC__EXA))
+ ipac_irq(&ipac->hscx[0], ista);
+ if (ista & (IPAC__ICB | IPAC__EXB))
+ ipac_irq(&ipac->hscx[1], ista);
+ ista = ReadIPAC(ipac, IPAC_ISTA);
+ }
+ } else if (ipac->type & IPAC_TYPE_HSCX) {
+ while (cnt) {
+ ista = ReadIPAC(ipac, IPAC_ISTAB + ipac->hscx[1].off);
+ pr_debug("%s: B2 ISTA %02x\n", ipac->name, ista);
+ if (ista)
+ ipac_irq(&ipac->hscx[1], ista);
+ istad = ReadISAC(isac, ISAC_ISTA);
+ pr_debug("%s: ISTAD %02x\n", ipac->name, istad);
+ if (istad)
+ mISDNisac_irq(isac, istad);
+ if (0 == (ista | istad))
+ break;
+ cnt--;
+ }
+ }
+ if (cnt > maxloop) /* only for ISAC/HSCX without PCI IRQ test */
+ return IRQ_NONE;
+ if (cnt < maxloop)
+ pr_debug("%s: %d irqloops cpu%d\n", ipac->name,
+ maxloop - cnt, smp_processor_id());
+ if (maxloop && !cnt)
+ pr_notice("%s: %d IRQ LOOP cpu%d\n", ipac->name,
+ maxloop, smp_processor_id());
+ return IRQ_HANDLED;
+}
+EXPORT_SYMBOL(mISDNipac_irq);
+
+static int
+hscx_mode(struct hscx_hw *hscx, u32 bprotocol)
+{
+ pr_debug("%s: HSCX %c protocol %x-->%x ch %d\n", hscx->ip->name,
+ '@' + hscx->bch.nr, hscx->bch.state, bprotocol, hscx->bch.nr);
+ if (hscx->ip->type & IPAC_TYPE_IPACX) {
+ if (hscx->bch.nr & 1) { /* B1 and ICA */
+ WriteIPAC(hscx->ip, ISACX_BCHA_TSDP_BC1, 0x80);
+ WriteIPAC(hscx->ip, ISACX_BCHA_CR, 0x88);
+ } else { /* B2 and ICB */
+ WriteIPAC(hscx->ip, ISACX_BCHB_TSDP_BC1, 0x81);
+ WriteIPAC(hscx->ip, ISACX_BCHB_CR, 0x88);
+ }
+ switch (bprotocol) {
+ case ISDN_P_NONE: /* init */
+ WriteHSCX(hscx, IPACX_MODEB, 0xC0); /* rec off */
+ WriteHSCX(hscx, IPACX_EXMB, 0x30); /* std adj. */
+ WriteHSCX(hscx, IPACX_MASKB, 0xFF); /* ints off */
+ hscx_cmdr(hscx, 0x41);
+ test_and_clear_bit(FLG_HDLC, &hscx->bch.Flags);
+ test_and_clear_bit(FLG_TRANSPARENT, &hscx->bch.Flags);
+ break;
+ case ISDN_P_B_RAW:
+ WriteHSCX(hscx, IPACX_MODEB, 0x88); /* ex trans */
+ WriteHSCX(hscx, IPACX_EXMB, 0x00); /* trans */
+ hscx_cmdr(hscx, 0x41);
+ WriteHSCX(hscx, IPACX_MASKB, IPACX_B_ON);
+ test_and_set_bit(FLG_TRANSPARENT, &hscx->bch.Flags);
+ break;
+ case ISDN_P_B_HDLC:
+ WriteHSCX(hscx, IPACX_MODEB, 0xC0); /* trans */
+ WriteHSCX(hscx, IPACX_EXMB, 0x00); /* hdlc,crc */
+ hscx_cmdr(hscx, 0x41);
+ WriteHSCX(hscx, IPACX_MASKB, IPACX_B_ON);
+ test_and_set_bit(FLG_HDLC, &hscx->bch.Flags);
+ break;
+ default:
+ pr_info("%s: protocol not known %x\n", hscx->ip->name,
+ bprotocol);
+ return -ENOPROTOOPT;
+ }
+ } else if (hscx->ip->type & IPAC_TYPE_IPAC) { /* IPAC */
+ WriteHSCX(hscx, IPAC_CCR1, 0x82);
+ WriteHSCX(hscx, IPAC_CCR2, 0x30);
+ WriteHSCX(hscx, IPAC_XCCR, 0x07);
+ WriteHSCX(hscx, IPAC_RCCR, 0x07);
+ WriteHSCX(hscx, IPAC_TSAX, hscx->slot);
+ WriteHSCX(hscx, IPAC_TSAR, hscx->slot);
+ switch (bprotocol) {
+ case ISDN_P_NONE:
+ WriteHSCX(hscx, IPAC_TSAX, 0x1F);
+ WriteHSCX(hscx, IPAC_TSAR, 0x1F);
+ WriteHSCX(hscx, IPAC_MODEB, 0x84);
+ WriteHSCX(hscx, IPAC_CCR1, 0x82);
+ WriteHSCX(hscx, IPAC_MASKB, 0xFF); /* ints off */
+ test_and_clear_bit(FLG_HDLC, &hscx->bch.Flags);
+ test_and_clear_bit(FLG_TRANSPARENT, &hscx->bch.Flags);
+ break;
+ case ISDN_P_B_RAW:
+ WriteHSCX(hscx, IPAC_MODEB, 0xe4); /* ex trans */
+ WriteHSCX(hscx, IPAC_CCR1, 0x82);
+ hscx_cmdr(hscx, 0x41);
+ WriteHSCX(hscx, IPAC_MASKB, 0);
+ test_and_set_bit(FLG_TRANSPARENT, &hscx->bch.Flags);
+ break;
+ case ISDN_P_B_HDLC:
+ WriteHSCX(hscx, IPAC_MODEB, 0x8c);
+ WriteHSCX(hscx, IPAC_CCR1, 0x8a);
+ hscx_cmdr(hscx, 0x41);
+ WriteHSCX(hscx, IPAC_MASKB, 0);
+ test_and_set_bit(FLG_HDLC, &hscx->bch.Flags);
+ break;
+ default:
+ pr_info("%s: protocol not known %x\n", hscx->ip->name,
+ bprotocol);
+ return -ENOPROTOOPT;
+ }
+ } else if (hscx->ip->type & IPAC_TYPE_HSCX) { /* HSCX */
+ WriteHSCX(hscx, IPAC_CCR1, 0x85);
+ WriteHSCX(hscx, IPAC_CCR2, 0x30);
+ WriteHSCX(hscx, IPAC_XCCR, 0x07);
+ WriteHSCX(hscx, IPAC_RCCR, 0x07);
+ WriteHSCX(hscx, IPAC_TSAX, hscx->slot);
+ WriteHSCX(hscx, IPAC_TSAR, hscx->slot);
+ switch (bprotocol) {
+ case ISDN_P_NONE:
+ WriteHSCX(hscx, IPAC_TSAX, 0x1F);
+ WriteHSCX(hscx, IPAC_TSAR, 0x1F);
+ WriteHSCX(hscx, IPAC_MODEB, 0x84);
+ WriteHSCX(hscx, IPAC_CCR1, 0x85);
+ WriteHSCX(hscx, IPAC_MASKB, 0xFF); /* ints off */
+ test_and_clear_bit(FLG_HDLC, &hscx->bch.Flags);
+ test_and_clear_bit(FLG_TRANSPARENT, &hscx->bch.Flags);
+ break;
+ case ISDN_P_B_RAW:
+ WriteHSCX(hscx, IPAC_MODEB, 0xe4); /* ex trans */
+ WriteHSCX(hscx, IPAC_CCR1, 0x85);
+ hscx_cmdr(hscx, 0x41);
+ WriteHSCX(hscx, IPAC_MASKB, 0);
+ test_and_set_bit(FLG_TRANSPARENT, &hscx->bch.Flags);
+ break;
+ case ISDN_P_B_HDLC:
+ WriteHSCX(hscx, IPAC_MODEB, 0x8c);
+ WriteHSCX(hscx, IPAC_CCR1, 0x8d);
+ hscx_cmdr(hscx, 0x41);
+ WriteHSCX(hscx, IPAC_MASKB, 0);
+ test_and_set_bit(FLG_HDLC, &hscx->bch.Flags);
+ break;
+ default:
+ pr_info("%s: protocol not known %x\n", hscx->ip->name,
+ bprotocol);
+ return -ENOPROTOOPT;
+ }
+ } else
+ return -EINVAL;
+ hscx->bch.state = bprotocol;
+ return 0;
+}
+
+static int
+hscx_l2l1(struct mISDNchannel *ch, struct sk_buff *skb)
+{
+ struct bchannel *bch = container_of(ch, struct bchannel, ch);
+ struct hscx_hw *hx = container_of(bch, struct hscx_hw, bch);
+ int ret = -EINVAL;
+ struct mISDNhead *hh = mISDN_HEAD_P(skb);
+ u32 id;
+ u_long flags;
+
+ switch (hh->prim) {
+ case PH_DATA_REQ:
+ spin_lock_irqsave(hx->ip->hwlock, flags);
+ ret = bchannel_senddata(bch, skb);
+ if (ret > 0) { /* direct TX */
+ id = hh->id; /* skb can be freed */
+ ret = 0;
+ hscx_fill_fifo(hx);
+ spin_unlock_irqrestore(hx->ip->hwlock, flags);
+ if (!test_bit(FLG_TRANSPARENT, &bch->Flags))
+ queue_ch_frame(ch, PH_DATA_CNF, id, NULL);
+ } else
+ spin_unlock_irqrestore(hx->ip->hwlock, flags);
+ return ret;
+ case PH_ACTIVATE_REQ:
+ spin_lock_irqsave(hx->ip->hwlock, flags);
+ if (!test_and_set_bit(FLG_ACTIVE, &bch->Flags))
+ ret = hscx_mode(hx, ch->protocol);
+ else
+ ret = 0;
+ spin_unlock_irqrestore(hx->ip->hwlock, flags);
+ if (!ret)
+ _queue_data(ch, PH_ACTIVATE_IND, MISDN_ID_ANY, 0,
+ NULL, GFP_KERNEL);
+ break;
+ case PH_DEACTIVATE_REQ:
+ spin_lock_irqsave(hx->ip->hwlock, flags);
+ mISDN_clear_bchannel(bch);
+ hscx_mode(hx, ISDN_P_NONE);
+ spin_unlock_irqrestore(hx->ip->hwlock, flags);
+ _queue_data(ch, PH_DEACTIVATE_IND, MISDN_ID_ANY, 0,
+ NULL, GFP_KERNEL);
+ ret = 0;
+ break;
+ default:
+ pr_info("%s: %s unknown prim(%x,%x)\n",
+ hx->ip->name, __func__, hh->prim, hh->id);
+ ret = -EINVAL;
+ }
+ if (!ret)
+ dev_kfree_skb(skb);
+ return ret;
+}
+
+static int
+channel_bctrl(struct bchannel *bch, struct mISDN_ctrl_req *cq)
+{
+ int ret = 0;
+
+ switch (cq->op) {
+ case MISDN_CTRL_GETOP:
+ cq->op = 0;
+ break;
+ /* Nothing implemented yet */
+ case MISDN_CTRL_FILL_EMPTY:
+ default:
+ pr_info("%s: unknown Op %x\n", __func__, cq->op);
+ ret = -EINVAL;
+ break;
+ }
+ return ret;
+}
+
+static int
+hscx_bctrl(struct mISDNchannel *ch, u32 cmd, void *arg)
+{
+ struct bchannel *bch = container_of(ch, struct bchannel, ch);
+ struct hscx_hw *hx = container_of(bch, struct hscx_hw, bch);
+ int ret = -EINVAL;
+ u_long flags;
+
+ pr_debug("%s: %s cmd:%x %p\n", hx->ip->name, __func__, cmd, arg);
+ switch (cmd) {
+ case CLOSE_CHANNEL:
+ test_and_clear_bit(FLG_OPEN, &bch->Flags);
+ if (test_bit(FLG_ACTIVE, &bch->Flags)) {
+ spin_lock_irqsave(hx->ip->hwlock, flags);
+ mISDN_freebchannel(bch);
+ hscx_mode(hx, ISDN_P_NONE);
+ spin_unlock_irqrestore(hx->ip->hwlock, flags);
+ } else {
+ skb_queue_purge(&bch->rqueue);
+ bch->rcount = 0;
+ }
+ ch->protocol = ISDN_P_NONE;
+ ch->peer = NULL;
+ module_put(hx->ip->owner);
+ ret = 0;
+ break;
+ case CONTROL_CHANNEL:
+ ret = channel_bctrl(bch, arg);
+ break;
+ default:
+ pr_info("%s: %s unknown prim(%x)\n",
+ hx->ip->name, __func__, cmd);
+ }
+ return ret;
+}
+
+static void
+free_ipac(struct ipac_hw *ipac)
+{
+ isac_release(&ipac->isac);
+}
+
+static const char *HSCXVer[] =
+{"A1", "?1", "A2", "?3", "A3", "V2.1", "?6", "?7",
+ "?8", "?9", "?10", "?11", "?12", "?13", "?14", "???"};
+
+
+
+static void
+hscx_init(struct hscx_hw *hx)
+{
+ u8 val;
+
+ WriteHSCX(hx, IPAC_RAH2, 0xFF);
+ WriteHSCX(hx, IPAC_XBCH, 0x00);
+ WriteHSCX(hx, IPAC_RLCR, 0x00);
+
+ if (hx->ip->type & IPAC_TYPE_HSCX) {
+ WriteHSCX(hx, IPAC_CCR1, 0x85);
+ val = ReadHSCX(hx, HSCX_VSTR);
+ pr_debug("%s: HSCX VSTR %02x\n", hx->ip->name, val);
+ if (hx->bch.debug & DEBUG_HW)
+ pr_notice("%s: HSCX version %s\n", hx->ip->name,
+ HSCXVer[val & 0x0f]);
+ } else
+ WriteHSCX(hx, IPAC_CCR1, 0x82);
+ WriteHSCX(hx, IPAC_CCR2, 0x30);
+ WriteHSCX(hx, IPAC_XCCR, 0x07);
+ WriteHSCX(hx, IPAC_RCCR, 0x07);
+}
+
+static int
+ipac_init(struct ipac_hw *ipac)
+{
+ u8 val;
+
+ if (ipac->type & IPAC_TYPE_HSCX) {
+ hscx_init(&ipac->hscx[0]);
+ hscx_init(&ipac->hscx[1]);
+ val = ReadIPAC(ipac, IPAC_ID);
+ } else if (ipac->type & IPAC_TYPE_IPAC) {
+ hscx_init(&ipac->hscx[0]);
+ hscx_init(&ipac->hscx[1]);
+ WriteIPAC(ipac, IPAC_MASK, IPAC__ON);
+ val = ReadIPAC(ipac, IPAC_CONF);
+ /* conf is default 0, but can be overwritten by card setup */
+ pr_debug("%s: IPAC CONF %02x/%02x\n", ipac->name,
+ val, ipac->conf);
+ WriteIPAC(ipac, IPAC_CONF, ipac->conf);
+ val = ReadIPAC(ipac, IPAC_ID);
+ if (ipac->hscx[0].bch.debug & DEBUG_HW)
+ pr_notice("%s: IPAC Design ID %02x\n", ipac->name, val);
+ }
+ /* nothing special for IPACX to do here */
+ return isac_init(&ipac->isac);
+}
+
+static int
+open_bchannel(struct ipac_hw *ipac, struct channel_req *rq)
+{
+ struct bchannel *bch;
+
+ if (rq->adr.channel > 2)
+ return -EINVAL;
+ if (rq->protocol == ISDN_P_NONE)
+ return -EINVAL;
+ bch = &ipac->hscx[rq->adr.channel - 1].bch;
+ if (test_and_set_bit(FLG_OPEN, &bch->Flags))
+ return -EBUSY; /* b-channel can be only open once */
+ test_and_clear_bit(FLG_FILLEMPTY, &bch->Flags);
+ bch->ch.protocol = rq->protocol;
+ rq->ch = &bch->ch;
+ return 0;
+}
+
+static int
+channel_ctrl(struct ipac_hw *ipac, struct mISDN_ctrl_req *cq)
+{
+ int ret = 0;
+
+ switch (cq->op) {
+ case MISDN_CTRL_GETOP:
+ cq->op = MISDN_CTRL_LOOP;
+ break;
+ case MISDN_CTRL_LOOP:
+ /* cq->channel: 0 disable, 1 B1 loop 2 B2 loop, 3 both */
+ if (cq->channel < 0 || cq->channel > 3) {
+ ret = -EINVAL;
+ break;
+ }
+ ret = ipac->ctrl(ipac, HW_TESTLOOP, cq->channel);
+ break;
+ default:
+ pr_info("%s: unknown CTRL OP %x\n", ipac->name, cq->op);
+ ret = -EINVAL;
+ break;
+ }
+ return ret;
+}
+
+static int
+ipac_dctrl(struct mISDNchannel *ch, u32 cmd, void *arg)
+{
+ struct mISDNdevice *dev = container_of(ch, struct mISDNdevice, D);
+ struct dchannel *dch = container_of(dev, struct dchannel, dev);
+ struct isac_hw *isac = container_of(dch, struct isac_hw, dch);
+ struct ipac_hw *ipac = container_of(isac, struct ipac_hw, isac);
+ struct channel_req *rq;
+ int err = 0;
+
+ pr_debug("%s: DCTRL: %x %p\n", ipac->name, cmd, arg);
+ switch (cmd) {
+ case OPEN_CHANNEL:
+ rq = arg;
+ if (rq->protocol == ISDN_P_TE_S0)
+ err = open_dchannel(isac, rq);
+ else
+ err = open_bchannel(ipac, rq);
+ if (err)
+ break;
+ if (!try_module_get(ipac->owner))
+ pr_info("%s: cannot get module\n", ipac->name);
+ break;
+ case CLOSE_CHANNEL:
+ pr_debug("%s: dev(%d) close from %p\n", ipac->name,
+ dch->dev.id, __builtin_return_address(0));
+ module_put(ipac->owner);
+ break;
+ case CONTROL_CHANNEL:
+ err = channel_ctrl(ipac, arg);
+ break;
+ default:
+ pr_debug("%s: unknown DCTRL command %x\n", ipac->name, cmd);
+ return -EINVAL;
+ }
+ return err;
+}
+
+u32
+mISDNipac_init(struct ipac_hw *ipac, void *hw)
+{
+ u32 ret;
+ u8 i;
+
+ ipac->hw = hw;
+ if (ipac->isac.dch.debug & DEBUG_HW)
+ pr_notice("%s: ipac type %x\n", ipac->name, ipac->type);
+ if (ipac->type & IPAC_TYPE_HSCX) {
+ ipac->isac.type = IPAC_TYPE_ISAC;
+ ipac->hscx[0].off = 0;
+ ipac->hscx[1].off = 0x40;
+ ipac->hscx[0].fifo_size = 32;
+ ipac->hscx[1].fifo_size = 32;
+ } else if (ipac->type & IPAC_TYPE_IPAC) {
+ ipac->isac.type = IPAC_TYPE_IPAC | IPAC_TYPE_ISAC;
+ ipac->hscx[0].off = 0;
+ ipac->hscx[1].off = 0x40;
+ ipac->hscx[0].fifo_size = 64;
+ ipac->hscx[1].fifo_size = 64;
+ } else if (ipac->type & IPAC_TYPE_IPACX) {
+ ipac->isac.type = IPAC_TYPE_IPACX | IPAC_TYPE_ISACX;
+ ipac->hscx[0].off = IPACX_OFF_ICA;
+ ipac->hscx[1].off = IPACX_OFF_ICB;
+ ipac->hscx[0].fifo_size = 64;
+ ipac->hscx[1].fifo_size = 64;
+ } else
+ return 0;
+
+ mISDNisac_init(&ipac->isac, hw);
+
+ ipac->isac.dch.dev.D.ctrl = ipac_dctrl;
+
+ for (i = 0; i < 2; i++) {
+ ipac->hscx[i].bch.nr = i + 1;
+ set_channelmap(i + 1, ipac->isac.dch.dev.channelmap);
+ list_add(&ipac->hscx[i].bch.ch.list,
+ &ipac->isac.dch.dev.bchannels);
+ mISDN_initbchannel(&ipac->hscx[i].bch, MAX_DATA_MEM);
+ ipac->hscx[i].bch.ch.nr = i + 1;
+ ipac->hscx[i].bch.ch.send = &hscx_l2l1;
+ ipac->hscx[i].bch.ch.ctrl = hscx_bctrl;
+ ipac->hscx[i].bch.hw = hw;
+ ipac->hscx[i].ip = ipac;
+ /* default values for IOM time slots
+ * can be overwriten by card */
+ ipac->hscx[i].slot = (i == 0) ? 0x2f : 0x03;
+ }
+
+ ipac->init = ipac_init;
+ ipac->release = free_ipac;
+
+ ret = (1 << (ISDN_P_B_RAW & ISDN_P_B_MASK)) |
+ (1 << (ISDN_P_B_HDLC & ISDN_P_B_MASK));
+ return ret;
+}
+EXPORT_SYMBOL(mISDNipac_init);
+
+static int __init
+isac_mod_init(void)
+{
+ pr_notice("mISDNipac module version %s\n", ISAC_REV);
+ return 0;
+}
+
+static void __exit
+isac_mod_cleanup(void)
+{
+ pr_notice("mISDNipac module unloaded\n");
+}
+module_init(isac_mod_init);
+module_exit(isac_mod_cleanup);
diff --git a/drivers/isdn/hardware/mISDN/mISDNisar.c b/drivers/isdn/hardware/mISDN/mISDNisar.c
new file mode 100644
index 00000000000..de352a17673
--- /dev/null
+++ b/drivers/isdn/hardware/mISDN/mISDNisar.c
@@ -0,0 +1,1726 @@
+/*
+ * mISDNisar.c ISAR (Siemens PSB 7110) specific functions
+ *
+ * Author Karsten Keil (keil@isdn4linux.de)
+ *
+ * Copyright 2009 by Karsten Keil <keil@isdn4linux.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+/* define this to enable static debug messages, if you kernel supports
+ * dynamic debugging, you should use debugfs for this
+ */
+/* #define DEBUG */
+
+#include <linux/delay.h>
+#include <linux/vmalloc.h>
+#include <linux/mISDNhw.h>
+#include "isar.h"
+
+#define ISAR_REV "2.1"
+
+MODULE_AUTHOR("Karsten Keil");
+MODULE_LICENSE("GPL v2");
+MODULE_VERSION(ISAR_REV);
+
+#define DEBUG_HW_FIRMWARE_FIFO 0x10000
+
+static const u8 faxmodulation_s[] = "3,24,48,72,73,74,96,97,98,121,122,145,146";
+static const u8 faxmodulation[] = {3, 24, 48, 72, 73, 74, 96, 97, 98, 121,
+ 122, 145, 146};
+#define FAXMODCNT 13
+
+static void isar_setup(struct isar_hw *);
+
+static inline int
+waitforHIA(struct isar_hw *isar, int timeout)
+{
+ int t = timeout;
+ u8 val = isar->read_reg(isar->hw, ISAR_HIA);
+
+ while ((val & 1) && t) {
+ udelay(1);
+ t--;
+ val = isar->read_reg(isar->hw, ISAR_HIA);
+ }
+ pr_debug("%s: HIA after %dus\n", isar->name, timeout - t);
+ return timeout;
+}
+
+/*
+ * send msg to ISAR mailbox
+ * if msg is NULL use isar->buf
+ */
+static int
+send_mbox(struct isar_hw *isar, u8 his, u8 creg, u8 len, u8 *msg)
+{
+ if (!waitforHIA(isar, 1000))
+ return 0;
+ pr_debug("send_mbox(%02x,%02x,%d)\n", his, creg, len);
+ isar->write_reg(isar->hw, ISAR_CTRL_H, creg);
+ isar->write_reg(isar->hw, ISAR_CTRL_L, len);
+ isar->write_reg(isar->hw, ISAR_WADR, 0);
+ if (!msg)
+ msg = isar->buf;
+ if (msg && len) {
+ isar->write_fifo(isar->hw, ISAR_MBOX, msg, len);
+ if (isar->ch[0].bch.debug & DEBUG_HW_BFIFO) {
+ int l = 0;
+
+ while (l < (int)len) {
+ hex_dump_to_buffer(msg + l, len - l, 32, 1,
+ isar->log, 256, 1);
+ pr_debug("%s: %s %02x: %s\n", isar->name,
+ __func__, l, isar->log);
+ l += 32;
+ }
+ }
+ }
+ isar->write_reg(isar->hw, ISAR_HIS, his);
+ waitforHIA(isar, 1000);
+ return 1;
+}
+
+/*
+ * receive message from ISAR mailbox
+ * if msg is NULL use isar->buf
+ */
+static void
+rcv_mbox(struct isar_hw *isar, u8 *msg)
+{
+ if (!msg)
+ msg = isar->buf;
+ isar->write_reg(isar->hw, ISAR_RADR, 0);
+ if (msg && isar->clsb) {
+ isar->read_fifo(isar->hw, ISAR_MBOX, msg, isar->clsb);
+ if (isar->ch[0].bch.debug & DEBUG_HW_BFIFO) {
+ int l = 0;
+
+ while (l < (int)isar->clsb) {
+ hex_dump_to_buffer(msg + l, isar->clsb - l, 32,
+ 1, isar->log, 256, 1);
+ pr_debug("%s: %s %02x: %s\n", isar->name,
+ __func__, l, isar->log);
+ l += 32;
+ }
+ }
+ }
+ isar->write_reg(isar->hw, ISAR_IIA, 0);
+}
+
+static inline void
+get_irq_infos(struct isar_hw *isar)
+{
+ isar->iis = isar->read_reg(isar->hw, ISAR_IIS);
+ isar->cmsb = isar->read_reg(isar->hw, ISAR_CTRL_H);
+ isar->clsb = isar->read_reg(isar->hw, ISAR_CTRL_L);
+ pr_debug("%s: rcv_mbox(%02x,%02x,%d)\n", isar->name,
+ isar->iis, isar->cmsb, isar->clsb);
+}
+
+/*
+ * poll answer message from ISAR mailbox
+ * should be used only with ISAR IRQs disabled before DSP was started
+ *
+ */
+static int
+poll_mbox(struct isar_hw *isar, int maxdelay)
+{
+ int t = maxdelay;
+ u8 irq;
+
+ irq = isar->read_reg(isar->hw, ISAR_IRQBIT);
+ while (t && !(irq & ISAR_IRQSTA)) {
+ udelay(1);
+ t--;
+ }
+ if (t) {
+ get_irq_infos(isar);
+ rcv_mbox(isar, NULL);
+ }
+ pr_debug("%s: pulled %d bytes after %d us\n",
+ isar->name, isar->clsb, maxdelay - t);
+ return t;
+}
+
+static int
+ISARVersion(struct isar_hw *isar)
+{
+ int ver;
+
+ /* disable ISAR IRQ */
+ isar->write_reg(isar->hw, ISAR_IRQBIT, 0);
+ isar->buf[0] = ISAR_MSG_HWVER;
+ isar->buf[1] = 0;
+ isar->buf[2] = 1;
+ if (!send_mbox(isar, ISAR_HIS_VNR, 0, 3, NULL))
+ return -1;
+ if (!poll_mbox(isar, 1000))
+ return -2;
+ if (isar->iis == ISAR_IIS_VNR) {
+ if (isar->clsb == 1) {
+ ver = isar->buf[0] & 0xf;
+ return ver;
+ }
+ return -3;
+ }
+ return -4;
+}
+
+static int
+load_firmware(struct isar_hw *isar, const u8 *buf, int size)
+{
+ u32 saved_debug = isar->ch[0].bch.debug;
+ int ret, cnt;
+ u8 nom, noc;
+ u16 left, val, *sp = (u16 *)buf;
+ u8 *mp;
+ u_long flags;
+
+ struct {
+ u16 sadr;
+ u16 len;
+ u16 d_key;
+ } blk_head;
+
+ if (1 != isar->version) {
+ pr_err("%s: ISAR wrong version %d firmware download aborted\n",
+ isar->name, isar->version);
+ return -EINVAL;
+ }
+ if (!(saved_debug & DEBUG_HW_FIRMWARE_FIFO))
+ isar->ch[0].bch.debug &= ~DEBUG_HW_BFIFO;
+ pr_debug("%s: load firmware %d words (%d bytes)\n",
+ isar->name, size/2, size);
+ cnt = 0;
+ size /= 2;
+ /* disable ISAR IRQ */
+ spin_lock_irqsave(isar->hwlock, flags);
+ isar->write_reg(isar->hw, ISAR_IRQBIT, 0);
+ spin_unlock_irqrestore(isar->hwlock, flags);
+ while (cnt < size) {
+ blk_head.sadr = le16_to_cpu(*sp++);
+ blk_head.len = le16_to_cpu(*sp++);
+ blk_head.d_key = le16_to_cpu(*sp++);
+ cnt += 3;
+ pr_debug("ISAR firmware block (%#x,%d,%#x)\n",
+ blk_head.sadr, blk_head.len, blk_head.d_key & 0xff);
+ left = blk_head.len;
+ if (cnt + left > size) {
+ pr_info("%s: firmware error have %d need %d words\n",
+ isar->name, size, cnt + left);
+ ret = -EINVAL;
+ goto reterrflg;
+ }
+ spin_lock_irqsave(isar->hwlock, flags);
+ if (!send_mbox(isar, ISAR_HIS_DKEY, blk_head.d_key & 0xff,
+ 0, NULL)) {
+ pr_info("ISAR send_mbox dkey failed\n");
+ ret = -ETIME;
+ goto reterror;
+ }
+ if (!poll_mbox(isar, 1000)) {
+ pr_warning("ISAR poll_mbox dkey failed\n");
+ ret = -ETIME;
+ goto reterror;
+ }
+ spin_unlock_irqrestore(isar->hwlock, flags);
+ if ((isar->iis != ISAR_IIS_DKEY) || isar->cmsb || isar->clsb) {
+ pr_info("ISAR wrong dkey response (%x,%x,%x)\n",
+ isar->iis, isar->cmsb, isar->clsb);
+ ret = 1;
+ goto reterrflg;
+ }
+ while (left > 0) {
+ if (left > 126)
+ noc = 126;
+ else
+ noc = left;
+ nom = (2 * noc) + 3;
+ mp = isar->buf;
+ /* the ISAR is big endian */
+ *mp++ = blk_head.sadr >> 8;
+ *mp++ = blk_head.sadr & 0xFF;
+ left -= noc;
+ cnt += noc;
+ *mp++ = noc;
+ pr_debug("%s: load %3d words at %04x\n", isar->name,
+ noc, blk_head.sadr);
+ blk_head.sadr += noc;
+ while (noc) {
+ val = le16_to_cpu(*sp++);
+ *mp++ = val >> 8;
+ *mp++ = val & 0xFF;;
+ noc--;
+ }
+ spin_lock_irqsave(isar->hwlock, flags);
+ if (!send_mbox(isar, ISAR_HIS_FIRM, 0, nom, NULL)) {
+ pr_info("ISAR send_mbox prog failed\n");
+ ret = -ETIME;
+ goto reterror;
+ }
+ if (!poll_mbox(isar, 1000)) {
+ pr_info("ISAR poll_mbox prog failed\n");
+ ret = -ETIME;
+ goto reterror;
+ }
+ spin_unlock_irqrestore(isar->hwlock, flags);
+ if ((isar->iis != ISAR_IIS_FIRM) ||
+ isar->cmsb || isar->clsb) {
+ pr_info("ISAR wrong prog response (%x,%x,%x)\n",
+ isar->iis, isar->cmsb, isar->clsb);
+ ret = -EIO;
+ goto reterrflg;
+ }
+ }
+ pr_debug("%s: ISAR firmware block %d words loaded\n",
+ isar->name, blk_head.len);
+ }
+ isar->ch[0].bch.debug = saved_debug;
+ /* 10ms delay */
+ cnt = 10;
+ while (cnt--)
+ mdelay(1);
+ isar->buf[0] = 0xff;
+ isar->buf[1] = 0xfe;
+ isar->bstat = 0;
+ spin_lock_irqsave(isar->hwlock, flags);
+ if (!send_mbox(isar, ISAR_HIS_STDSP, 0, 2, NULL)) {
+ pr_info("ISAR send_mbox start dsp failed\n");
+ ret = -ETIME;
+ goto reterror;
+ }
+ if (!poll_mbox(isar, 1000)) {
+ pr_info("ISAR poll_mbox start dsp failed\n");
+ ret = -ETIME;
+ goto reterror;
+ }
+ if ((isar->iis != ISAR_IIS_STDSP) || isar->cmsb || isar->clsb) {
+ pr_info("ISAR wrong start dsp response (%x,%x,%x)\n",
+ isar->iis, isar->cmsb, isar->clsb);
+ ret = -EIO;
+ goto reterror;
+ } else
+ pr_debug("%s: ISAR start dsp success\n", isar->name);
+
+ /* NORMAL mode entered */
+ /* Enable IRQs of ISAR */
+ isar->write_reg(isar->hw, ISAR_IRQBIT, ISAR_IRQSTA);
+ spin_unlock_irqrestore(isar->hwlock, flags);
+ cnt = 1000; /* max 1s */
+ while ((!isar->bstat) && cnt) {
+ mdelay(1);
+ cnt--;
+ }
+ if (!cnt) {
+ pr_info("ISAR no general status event received\n");
+ ret = -ETIME;
+ goto reterrflg;
+ } else
+ pr_debug("%s: ISAR general status event %x\n",
+ isar->name, isar->bstat);
+ /* 10ms delay */
+ cnt = 10;
+ while (cnt--)
+ mdelay(1);
+ isar->iis = 0;
+ spin_lock_irqsave(isar->hwlock, flags);
+ if (!send_mbox(isar, ISAR_HIS_DIAG, ISAR_CTRL_STST, 0, NULL)) {
+ pr_info("ISAR send_mbox self tst failed\n");
+ ret = -ETIME;
+ goto reterror;
+ }
+ spin_unlock_irqrestore(isar->hwlock, flags);
+ cnt = 10000; /* max 100 ms */
+ while ((isar->iis != ISAR_IIS_DIAG) && cnt) {
+ udelay(10);
+ cnt--;
+ }
+ mdelay(1);
+ if (!cnt) {
+ pr_info("ISAR no self tst response\n");
+ ret = -ETIME;
+ goto reterrflg;
+ }
+ if ((isar->cmsb == ISAR_CTRL_STST) && (isar->clsb == 1)
+ && (isar->buf[0] == 0))
+ pr_debug("%s: ISAR selftest OK\n", isar->name);
+ else {
+ pr_info("ISAR selftest not OK %x/%x/%x\n",
+ isar->cmsb, isar->clsb, isar->buf[0]);
+ ret = -EIO;
+ goto reterrflg;
+ }
+ spin_lock_irqsave(isar->hwlock, flags);
+ isar->iis = 0;
+ if (!send_mbox(isar, ISAR_HIS_DIAG, ISAR_CTRL_SWVER, 0, NULL)) {
+ pr_info("ISAR RQST SVN failed\n");
+ ret = -ETIME;
+ goto reterror;
+ }
+ spin_unlock_irqrestore(isar->hwlock, flags);
+ cnt = 30000; /* max 300 ms */
+ while ((isar->iis != ISAR_IIS_DIAG) && cnt) {
+ udelay(10);
+ cnt--;
+ }
+ mdelay(1);
+ if (!cnt) {
+ pr_info("ISAR no SVN response\n");
+ ret = -ETIME;
+ goto reterrflg;
+ } else {
+ if ((isar->cmsb == ISAR_CTRL_SWVER) && (isar->clsb == 1)) {
+ pr_notice("%s: ISAR software version %#x\n",
+ isar->name, isar->buf[0]);
+ } else {
+ pr_info("%s: ISAR wrong swver response (%x,%x)"
+ " cnt(%d)\n", isar->name, isar->cmsb,
+ isar->clsb, cnt);
+ ret = -EIO;
+ goto reterrflg;
+ }
+ }
+ spin_lock_irqsave(isar->hwlock, flags);
+ isar_setup(isar);
+ spin_unlock_irqrestore(isar->hwlock, flags);
+ ret = 0;
+reterrflg:
+ spin_lock_irqsave(isar->hwlock, flags);
+reterror:
+ isar->ch[0].bch.debug = saved_debug;
+ if (ret)
+ /* disable ISAR IRQ */
+ isar->write_reg(isar->hw, ISAR_IRQBIT, 0);
+ spin_unlock_irqrestore(isar->hwlock, flags);
+ return ret;
+}
+
+static inline void
+deliver_status(struct isar_ch *ch, int status)
+{
+ pr_debug("%s: HL->LL FAXIND %x\n", ch->is->name, status);
+ _queue_data(&ch->bch.ch, PH_CONTROL_IND, status, 0, NULL, GFP_ATOMIC);
+}
+
+static inline void
+isar_rcv_frame(struct isar_ch *ch)
+{
+ u8 *ptr;
+
+ if (!ch->is->clsb) {
+ pr_debug("%s; ISAR zero len frame\n", ch->is->name);
+ ch->is->write_reg(ch->is->hw, ISAR_IIA, 0);
+ return;
+ }
+ switch (ch->bch.state) {
+ case ISDN_P_NONE:
+ pr_debug("%s: ISAR protocol 0 spurious IIS_RDATA %x/%x/%x\n",
+ ch->is->name, ch->is->iis, ch->is->cmsb, ch->is->clsb);
+ ch->is->write_reg(ch->is->hw, ISAR_IIA, 0);
+ break;
+ case ISDN_P_B_RAW:
+ case ISDN_P_B_L2DTMF:
+ case ISDN_P_B_MODEM_ASYNC:
+ if (!ch->bch.rx_skb) {
+ ch->bch.rx_skb = mI_alloc_skb(ch->bch.maxlen,
+ GFP_ATOMIC);
+ if (unlikely(!ch->bch.rx_skb)) {
+ pr_info("%s: B receive out of memory\n",
+ ch->is->name);
+ ch->is->write_reg(ch->is->hw, ISAR_IIA, 0);
+ break;
+ }
+ }
+ rcv_mbox(ch->is, skb_put(ch->bch.rx_skb, ch->is->clsb));
+ recv_Bchannel(&ch->bch, 0);
+ break;
+ case ISDN_P_B_HDLC:
+ if (!ch->bch.rx_skb) {
+ ch->bch.rx_skb = mI_alloc_skb(ch->bch.maxlen,
+ GFP_ATOMIC);
+ if (unlikely(!ch->bch.rx_skb)) {
+ pr_info("%s: B receive out of memory\n",
+ ch->is->name);
+ ch->is->write_reg(ch->is->hw, ISAR_IIA, 0);
+ break;
+ }
+ }
+ if ((ch->bch.rx_skb->len + ch->is->clsb) >
+ (ch->bch.maxlen + 2)) {
+ pr_debug("%s: incoming packet too large\n",
+ ch->is->name);
+ ch->is->write_reg(ch->is->hw, ISAR_IIA, 0);
+ skb_trim(ch->bch.rx_skb, 0);
+ break;
+ }
+ if (ch->is->cmsb & HDLC_ERROR) {
+ pr_debug("%s: ISAR frame error %x len %d\n",
+ ch->is->name, ch->is->cmsb, ch->is->clsb);
+#ifdef ERROR_STATISTIC
+ if (ch->is->cmsb & HDLC_ERR_RER)
+ ch->bch.err_inv++;
+ if (ch->is->cmsb & HDLC_ERR_CER)
+ ch->bch.err_crc++;
+#endif
+ skb_trim(ch->bch.rx_skb, 0);
+ ch->is->write_reg(ch->is->hw, ISAR_IIA, 0);
+ break;
+ }
+ if (ch->is->cmsb & HDLC_FSD)
+ skb_trim(ch->bch.rx_skb, 0);
+ ptr = skb_put(ch->bch.rx_skb, ch->is->clsb);
+ rcv_mbox(ch->is, ptr);
+ if (ch->is->cmsb & HDLC_FED) {
+ if (ch->bch.rx_skb->len < 3) { /* last 2 are the FCS */
+ pr_debug("%s: ISAR frame to short %d\n",
+ ch->is->name, ch->bch.rx_skb->len);
+ skb_trim(ch->bch.rx_skb, 0);
+ break;
+ }
+ skb_trim(ch->bch.rx_skb, ch->bch.rx_skb->len - 2);
+ recv_Bchannel(&ch->bch, 0);
+ }
+ break;
+ case ISDN_P_B_T30_FAX:
+ if (ch->state != STFAX_ACTIV) {
+ pr_debug("%s: isar_rcv_frame: not ACTIV\n",
+ ch->is->name);
+ ch->is->write_reg(ch->is->hw, ISAR_IIA, 0);
+ if (ch->bch.rx_skb)
+ skb_trim(ch->bch.rx_skb, 0);
+ break;
+ }
+ if (!ch->bch.rx_skb) {
+ ch->bch.rx_skb = mI_alloc_skb(ch->bch.maxlen,
+ GFP_ATOMIC);
+ if (unlikely(!ch->bch.rx_skb)) {
+ pr_info("%s: B receive out of memory\n",
+ __func__);
+ ch->is->write_reg(ch->is->hw, ISAR_IIA, 0);
+ break;
+ }
+ }
+ if (ch->cmd == PCTRL_CMD_FRM) {
+ rcv_mbox(ch->is, skb_put(ch->bch.rx_skb, ch->is->clsb));
+ pr_debug("%s: isar_rcv_frame: %d\n",
+ ch->is->name, ch->bch.rx_skb->len);
+ if (ch->is->cmsb & SART_NMD) { /* ABORT */
+ pr_debug("%s: isar_rcv_frame: no more data\n",
+ ch->is->name);
+ ch->is->write_reg(ch->is->hw, ISAR_IIA, 0);
+ send_mbox(ch->is, SET_DPS(ch->dpath) |
+ ISAR_HIS_PUMPCTRL, PCTRL_CMD_ESC,
+ 0, NULL);
+ ch->state = STFAX_ESCAPE;
+ /* set_skb_flag(skb, DF_NOMOREDATA); */
+ }
+ recv_Bchannel(&ch->bch, 0);
+ if (ch->is->cmsb & SART_NMD)
+ deliver_status(ch, HW_MOD_NOCARR);
+ break;
+ }
+ if (ch->cmd != PCTRL_CMD_FRH) {
+ pr_debug("%s: isar_rcv_frame: unknown fax mode %x\n",
+ ch->is->name, ch->cmd);
+ ch->is->write_reg(ch->is->hw, ISAR_IIA, 0);
+ if (ch->bch.rx_skb)
+ skb_trim(ch->bch.rx_skb, 0);
+ break;
+ }
+ /* PCTRL_CMD_FRH */
+ if ((ch->bch.rx_skb->len + ch->is->clsb) >
+ (ch->bch.maxlen + 2)) {
+ pr_info("%s: %s incoming packet too large\n",
+ ch->is->name, __func__);
+ ch->is->write_reg(ch->is->hw, ISAR_IIA, 0);
+ skb_trim(ch->bch.rx_skb, 0);
+ break;
+ } else if (ch->is->cmsb & HDLC_ERROR) {
+ pr_info("%s: ISAR frame error %x len %d\n",
+ ch->is->name, ch->is->cmsb, ch->is->clsb);
+ skb_trim(ch->bch.rx_skb, 0);
+ ch->is->write_reg(ch->is->hw, ISAR_IIA, 0);
+ break;
+ }
+ if (ch->is->cmsb & HDLC_FSD)
+ skb_trim(ch->bch.rx_skb, 0);
+ ptr = skb_put(ch->bch.rx_skb, ch->is->clsb);
+ rcv_mbox(ch->is, ptr);
+ if (ch->is->cmsb & HDLC_FED) {
+ if (ch->bch.rx_skb->len < 3) { /* last 2 are the FCS */
+ pr_info("%s: ISAR frame to short %d\n",
+ ch->is->name, ch->bch.rx_skb->len);
+ skb_trim(ch->bch.rx_skb, 0);
+ break;
+ }
+ skb_trim(ch->bch.rx_skb, ch->bch.rx_skb->len - 2);
+ recv_Bchannel(&ch->bch, 0);
+ }
+ if (ch->is->cmsb & SART_NMD) { /* ABORT */
+ pr_debug("%s: isar_rcv_frame: no more data\n",
+ ch->is->name);
+ ch->is->write_reg(ch->is->hw, ISAR_IIA, 0);
+ if (ch->bch.rx_skb)
+ skb_trim(ch->bch.rx_skb, 0);
+ send_mbox(ch->is, SET_DPS(ch->dpath) |
+ ISAR_HIS_PUMPCTRL, PCTRL_CMD_ESC, 0, NULL);
+ ch->state = STFAX_ESCAPE;
+ deliver_status(ch, HW_MOD_NOCARR);
+ }
+ break;
+ default:
+ pr_info("isar_rcv_frame protocol (%x)error\n", ch->bch.state);
+ ch->is->write_reg(ch->is->hw, ISAR_IIA, 0);
+ break;
+ }
+}
+
+static void
+isar_fill_fifo(struct isar_ch *ch)
+{
+ int count;
+ u8 msb;
+ u8 *ptr;
+
+ pr_debug("%s: ch%d tx_skb %p tx_idx %d\n",
+ ch->is->name, ch->bch.nr, ch->bch.tx_skb, ch->bch.tx_idx);
+ if (!ch->bch.tx_skb)
+ return;
+ count = ch->bch.tx_skb->len - ch->bch.tx_idx;
+ if (count <= 0)
+ return;
+ if (!(ch->is->bstat &
+ (ch->dpath == 1 ? BSTAT_RDM1 : BSTAT_RDM2)))
+ return;
+ if (count > ch->mml) {
+ msb = 0;
+ count = ch->mml;
+ } else {
+ msb = HDLC_FED;
+ }
+ ptr = ch->bch.tx_skb->data + ch->bch.tx_idx;
+ if (!ch->bch.tx_idx) {
+ pr_debug("%s: frame start\n", ch->is->name);
+ if ((ch->bch.state == ISDN_P_B_T30_FAX) &&
+ (ch->cmd == PCTRL_CMD_FTH)) {
+ if (count > 1) {
+ if ((ptr[0] == 0xff) && (ptr[1] == 0x13)) {
+ /* last frame */
+ test_and_set_bit(FLG_LASTDATA,
+ &ch->bch.Flags);
+ pr_debug("%s: set LASTDATA\n",
+ ch->is->name);
+ if (msb == HDLC_FED)
+ test_and_set_bit(FLG_DLEETX,
+ &ch->bch.Flags);
+ }
+ }
+ }
+ msb |= HDLC_FST;
+ }
+ ch->bch.tx_idx += count;
+ switch (ch->bch.state) {
+ case ISDN_P_NONE:
+ pr_info("%s: wrong protocol 0\n", __func__);
+ break;
+ case ISDN_P_B_RAW:
+ case ISDN_P_B_L2DTMF:
+ case ISDN_P_B_MODEM_ASYNC:
+ send_mbox(ch->is, SET_DPS(ch->dpath) | ISAR_HIS_SDATA,
+ 0, count, ptr);
+ break;
+ case ISDN_P_B_HDLC:
+ send_mbox(ch->is, SET_DPS(ch->dpath) | ISAR_HIS_SDATA,
+ msb, count, ptr);
+ break;
+ case ISDN_P_B_T30_FAX:
+ if (ch->state != STFAX_ACTIV)
+ pr_debug("%s: not ACTIV\n", ch->is->name);
+ else if (ch->cmd == PCTRL_CMD_FTH)
+ send_mbox(ch->is, SET_DPS(ch->dpath) | ISAR_HIS_SDATA,
+ msb, count, ptr);
+ else if (ch->cmd == PCTRL_CMD_FTM)
+ send_mbox(ch->is, SET_DPS(ch->dpath) | ISAR_HIS_SDATA,
+ 0, count, ptr);
+ else
+ pr_debug("%s: not FTH/FTM\n", ch->is->name);
+ break;
+ default:
+ pr_info("%s: protocol(%x) error\n",
+ __func__, ch->bch.state);
+ break;
+ }
+}
+
+static inline struct isar_ch *
+sel_bch_isar(struct isar_hw *isar, u8 dpath)
+{
+ struct isar_ch *base = &isar->ch[0];
+
+ if ((!dpath) || (dpath > 2))
+ return NULL;
+ if (base->dpath == dpath)
+ return base;
+ base++;
+ if (base->dpath == dpath)
+ return base;
+ return NULL;
+}
+
+static void
+send_next(struct isar_ch *ch)
+{
+ pr_debug("%s: %s ch%d tx_skb %p tx_idx %d\n",
+ ch->is->name, __func__, ch->bch.nr,
+ ch->bch.tx_skb, ch->bch.tx_idx);
+ if (ch->bch.state == ISDN_P_B_T30_FAX) {
+ if (ch->cmd == PCTRL_CMD_FTH) {
+ if (test_bit(FLG_LASTDATA, &ch->bch.Flags)) {
+ pr_debug("set NMD_DATA\n");
+ test_and_set_bit(FLG_NMD_DATA, &ch->bch.Flags);
+ }
+ } else if (ch->cmd == PCTRL_CMD_FTM) {
+ if (test_bit(FLG_DLEETX, &ch->bch.Flags)) {
+ test_and_set_bit(FLG_LASTDATA, &ch->bch.Flags);
+ test_and_set_bit(FLG_NMD_DATA, &ch->bch.Flags);
+ }
+ }
+ }
+ if (ch->bch.tx_skb) {
+ /* send confirm, on trans, free on hdlc. */
+ if (test_bit(FLG_TRANSPARENT, &ch->bch.Flags))
+ confirm_Bsend(&ch->bch);
+ dev_kfree_skb(ch->bch.tx_skb);
+ }
+ if (get_next_bframe(&ch->bch))
+ isar_fill_fifo(ch);
+ else {
+ if (test_and_clear_bit(FLG_DLEETX, &ch->bch.Flags)) {
+ if (test_and_clear_bit(FLG_LASTDATA,
+ &ch->bch.Flags)) {
+ if (test_and_clear_bit(FLG_NMD_DATA,
+ &ch->bch.Flags)) {
+ u8 zd = 0;
+ send_mbox(ch->is, SET_DPS(ch->dpath) |
+ ISAR_HIS_SDATA, 0x01, 1, &zd);
+ }
+ test_and_set_bit(FLG_LL_OK, &ch->bch.Flags);
+ } else {
+ deliver_status(ch, HW_MOD_CONNECT);
+ }
+ }
+ }
+}
+
+static void
+check_send(struct isar_hw *isar, u8 rdm)
+{
+ struct isar_ch *ch;
+
+ pr_debug("%s: rdm %x\n", isar->name, rdm);
+ if (rdm & BSTAT_RDM1) {
+ ch = sel_bch_isar(isar, 1);
+ if (ch && test_bit(FLG_ACTIVE, &ch->bch.Flags)) {
+ if (ch->bch.tx_skb && (ch->bch.tx_skb->len >
+ ch->bch.tx_idx))
+ isar_fill_fifo(ch);
+ else
+ send_next(ch);
+ }
+ }
+ if (rdm & BSTAT_RDM2) {
+ ch = sel_bch_isar(isar, 2);
+ if (ch && test_bit(FLG_ACTIVE, &ch->bch.Flags)) {
+ if (ch->bch.tx_skb && (ch->bch.tx_skb->len >
+ ch->bch.tx_idx))
+ isar_fill_fifo(ch);
+ else
+ send_next(ch);
+ }
+ }
+}
+
+const char *dmril[] = {"NO SPEED", "1200/75", "NODEF2", "75/1200", "NODEF4",
+ "300", "600", "1200", "2400", "4800", "7200",
+ "9600nt", "9600t", "12000", "14400", "WRONG"};
+const char *dmrim[] = {"NO MOD", "NO DEF", "V32/V32b", "V22", "V21",
+ "Bell103", "V23", "Bell202", "V17", "V29", "V27ter"};
+
+static void
+isar_pump_status_rsp(struct isar_ch *ch) {
+ u8 ril = ch->is->buf[0];
+ u8 rim;
+
+ if (!test_and_clear_bit(ISAR_RATE_REQ, &ch->is->Flags))
+ return;
+ if (ril > 14) {
+ pr_info("%s: wrong pstrsp ril=%d\n", ch->is->name, ril);
+ ril = 15;
+ }
+ switch (ch->is->buf[1]) {
+ case 0:
+ rim = 0;
+ break;
+ case 0x20:
+ rim = 2;
+ break;
+ case 0x40:
+ rim = 3;
+ break;
+ case 0x41:
+ rim = 4;
+ break;
+ case 0x51:
+ rim = 5;
+ break;
+ case 0x61:
+ rim = 6;
+ break;
+ case 0x71:
+ rim = 7;
+ break;
+ case 0x82:
+ rim = 8;
+ break;
+ case 0x92:
+ rim = 9;
+ break;
+ case 0xa2:
+ rim = 10;
+ break;
+ default:
+ rim = 1;
+ break;
+ }
+ sprintf(ch->conmsg, "%s %s", dmril[ril], dmrim[rim]);
+ pr_debug("%s: pump strsp %s\n", ch->is->name, ch->conmsg);
+}
+
+static void
+isar_pump_statev_modem(struct isar_ch *ch, u8 devt) {
+ u8 dps = SET_DPS(ch->dpath);
+
+ switch (devt) {
+ case PSEV_10MS_TIMER:
+ pr_debug("%s: pump stev TIMER\n", ch->is->name);
+ break;
+ case PSEV_CON_ON:
+ pr_debug("%s: pump stev CONNECT\n", ch->is->name);
+ deliver_status(ch, HW_MOD_CONNECT);
+ break;
+ case PSEV_CON_OFF:
+ pr_debug("%s: pump stev NO CONNECT\n", ch->is->name);
+ send_mbox(ch->is, dps | ISAR_HIS_PSTREQ, 0, 0, NULL);
+ deliver_status(ch, HW_MOD_NOCARR);
+ break;
+ case PSEV_V24_OFF:
+ pr_debug("%s: pump stev V24 OFF\n", ch->is->name);
+ break;
+ case PSEV_CTS_ON:
+ pr_debug("%s: pump stev CTS ON\n", ch->is->name);
+ break;
+ case PSEV_CTS_OFF:
+ pr_debug("%s pump stev CTS OFF\n", ch->is->name);
+ break;
+ case PSEV_DCD_ON:
+ pr_debug("%s: pump stev CARRIER ON\n", ch->is->name);
+ test_and_set_bit(ISAR_RATE_REQ, &ch->is->Flags);
+ send_mbox(ch->is, dps | ISAR_HIS_PSTREQ, 0, 0, NULL);
+ break;
+ case PSEV_DCD_OFF:
+ pr_debug("%s: pump stev CARRIER OFF\n", ch->is->name);
+ break;
+ case PSEV_DSR_ON:
+ pr_debug("%s: pump stev DSR ON\n", ch->is->name);
+ break;
+ case PSEV_DSR_OFF:
+ pr_debug("%s: pump stev DSR_OFF\n", ch->is->name);
+ break;
+ case PSEV_REM_RET:
+ pr_debug("%s: pump stev REMOTE RETRAIN\n", ch->is->name);
+ break;
+ case PSEV_REM_REN:
+ pr_debug("%s: pump stev REMOTE RENEGOTIATE\n", ch->is->name);
+ break;
+ case PSEV_GSTN_CLR:
+ pr_debug("%s: pump stev GSTN CLEAR\n", ch->is->name);
+ break;
+ default:
+ pr_info("u%s: nknown pump stev %x\n", ch->is->name, devt);
+ break;
+ }
+}
+
+static void
+isar_pump_statev_fax(struct isar_ch *ch, u8 devt) {
+ u8 dps = SET_DPS(ch->dpath);
+ u8 p1;
+
+ switch (devt) {
+ case PSEV_10MS_TIMER:
+ pr_debug("%s: pump stev TIMER\n", ch->is->name);
+ break;
+ case PSEV_RSP_READY:
+ pr_debug("%s: pump stev RSP_READY\n", ch->is->name);
+ ch->state = STFAX_READY;
+ deliver_status(ch, HW_MOD_READY);
+#ifdef AUTOCON
+ if (test_bit(BC_FLG_ORIG, &ch->bch.Flags))
+ isar_pump_cmd(bch, HW_MOD_FRH, 3);
+ else
+ isar_pump_cmd(bch, HW_MOD_FTH, 3);
+#endif
+ break;
+ case PSEV_LINE_TX_H:
+ if (ch->state == STFAX_LINE) {
+ pr_debug("%s: pump stev LINE_TX_H\n", ch->is->name);
+ ch->state = STFAX_CONT;
+ send_mbox(ch->is, dps | ISAR_HIS_PUMPCTRL,
+ PCTRL_CMD_CONT, 0, NULL);
+ } else {
+ pr_debug("%s: pump stev LINE_TX_H wrong st %x\n",
+ ch->is->name, ch->state);
+ }
+ break;
+ case PSEV_LINE_RX_H:
+ if (ch->state == STFAX_LINE) {
+ pr_debug("%s: pump stev LINE_RX_H\n", ch->is->name);
+ ch->state = STFAX_CONT;
+ send_mbox(ch->is, dps | ISAR_HIS_PUMPCTRL,
+ PCTRL_CMD_CONT, 0, NULL);
+ } else {
+ pr_debug("%s: pump stev LINE_RX_H wrong st %x\n",
+ ch->is->name, ch->state);
+ }
+ break;
+ case PSEV_LINE_TX_B:
+ if (ch->state == STFAX_LINE) {
+ pr_debug("%s: pump stev LINE_TX_B\n", ch->is->name);
+ ch->state = STFAX_CONT;
+ send_mbox(ch->is, dps | ISAR_HIS_PUMPCTRL,
+ PCTRL_CMD_CONT, 0, NULL);
+ } else {
+ pr_debug("%s: pump stev LINE_TX_B wrong st %x\n",
+ ch->is->name, ch->state);
+ }
+ break;
+ case PSEV_LINE_RX_B:
+ if (ch->state == STFAX_LINE) {
+ pr_debug("%s: pump stev LINE_RX_B\n", ch->is->name);
+ ch->state = STFAX_CONT;
+ send_mbox(ch->is, dps | ISAR_HIS_PUMPCTRL,
+ PCTRL_CMD_CONT, 0, NULL);
+ } else {
+ pr_debug("%s: pump stev LINE_RX_B wrong st %x\n",
+ ch->is->name, ch->state);
+ }
+ break;
+ case PSEV_RSP_CONN:
+ if (ch->state == STFAX_CONT) {
+ pr_debug("%s: pump stev RSP_CONN\n", ch->is->name);
+ ch->state = STFAX_ACTIV;
+ test_and_set_bit(ISAR_RATE_REQ, &ch->is->Flags);
+ send_mbox(ch->is, dps | ISAR_HIS_PSTREQ, 0, 0, NULL);
+ if (ch->cmd == PCTRL_CMD_FTH) {
+ int delay = (ch->mod == 3) ? 1000 : 200;
+ /* 1s (200 ms) Flags before data */
+ if (test_and_set_bit(FLG_FTI_RUN,
+ &ch->bch.Flags))
+ del_timer(&ch->ftimer);
+ ch->ftimer.expires =
+ jiffies + ((delay * HZ)/1000);
+ test_and_set_bit(FLG_LL_CONN,
+ &ch->bch.Flags);
+ add_timer(&ch->ftimer);
+ } else {
+ deliver_status(ch, HW_MOD_CONNECT);
+ }
+ } else {
+ pr_debug("%s: pump stev RSP_CONN wrong st %x\n",
+ ch->is->name, ch->state);
+ }
+ break;
+ case PSEV_FLAGS_DET:
+ pr_debug("%s: pump stev FLAGS_DET\n", ch->is->name);
+ break;
+ case PSEV_RSP_DISC:
+ pr_debug("%s: pump stev RSP_DISC state(%d)\n",
+ ch->is->name, ch->state);
+ if (ch->state == STFAX_ESCAPE) {
+ p1 = 5;
+ switch (ch->newcmd) {
+ case 0:
+ ch->state = STFAX_READY;
+ break;
+ case PCTRL_CMD_FTM:
+ p1 = 2;
+ case PCTRL_CMD_FTH:
+ send_mbox(ch->is, dps | ISAR_HIS_PUMPCTRL,
+ PCTRL_CMD_SILON, 1, &p1);
+ ch->state = STFAX_SILDET;
+ break;
+ case PCTRL_CMD_FRH:
+ case PCTRL_CMD_FRM:
+ ch->mod = ch->newmod;
+ p1 = ch->newmod;
+ ch->newmod = 0;
+ ch->cmd = ch->newcmd;
+ ch->newcmd = 0;
+ send_mbox(ch->is, dps | ISAR_HIS_PUMPCTRL,
+ ch->cmd, 1, &p1);
+ ch->state = STFAX_LINE;
+ ch->try_mod = 3;
+ break;
+ default:
+ pr_debug("%s: RSP_DISC unknown newcmd %x\n",
+ ch->is->name, ch->newcmd);
+ break;
+ }
+ } else if (ch->state == STFAX_ACTIV) {
+ if (test_and_clear_bit(FLG_LL_OK, &ch->bch.Flags))
+ deliver_status(ch, HW_MOD_OK);
+ else if (ch->cmd == PCTRL_CMD_FRM)
+ deliver_status(ch, HW_MOD_NOCARR);
+ else
+ deliver_status(ch, HW_MOD_FCERROR);
+ ch->state = STFAX_READY;
+ } else if (ch->state != STFAX_SILDET) {
+ /* ignore in STFAX_SILDET */
+ ch->state = STFAX_READY;
+ deliver_status(ch, HW_MOD_FCERROR);
+ }
+ break;
+ case PSEV_RSP_SILDET:
+ pr_debug("%s: pump stev RSP_SILDET\n", ch->is->name);
+ if (ch->state == STFAX_SILDET) {
+ ch->mod = ch->newmod;
+ p1 = ch->newmod;
+ ch->newmod = 0;
+ ch->cmd = ch->newcmd;
+ ch->newcmd = 0;
+ send_mbox(ch->is, dps | ISAR_HIS_PUMPCTRL,
+ ch->cmd, 1, &p1);
+ ch->state = STFAX_LINE;
+ ch->try_mod = 3;
+ }
+ break;
+ case PSEV_RSP_SILOFF:
+ pr_debug("%s: pump stev RSP_SILOFF\n", ch->is->name);
+ break;
+ case PSEV_RSP_FCERR:
+ if (ch->state == STFAX_LINE) {
+ pr_debug("%s: pump stev RSP_FCERR try %d\n",
+ ch->is->name, ch->try_mod);
+ if (ch->try_mod--) {
+ send_mbox(ch->is, dps | ISAR_HIS_PUMPCTRL,
+ ch->cmd, 1, &ch->mod);
+ break;
+ }
+ }
+ pr_debug("%s: pump stev RSP_FCERR\n", ch->is->name);
+ ch->state = STFAX_ESCAPE;
+ send_mbox(ch->is, dps | ISAR_HIS_PUMPCTRL, PCTRL_CMD_ESC,
+ 0, NULL);
+ deliver_status(ch, HW_MOD_FCERROR);
+ break;
+ default:
+ break;
+ }
+}
+
+void
+mISDNisar_irq(struct isar_hw *isar)
+{
+ struct isar_ch *ch;
+
+ get_irq_infos(isar);
+ switch (isar->iis & ISAR_IIS_MSCMSD) {
+ case ISAR_IIS_RDATA:
+ ch = sel_bch_isar(isar, isar->iis >> 6);
+ if (ch)
+ isar_rcv_frame(ch);
+ else {
+ pr_debug("%s: ISAR spurious IIS_RDATA %x/%x/%x\n",
+ isar->name, isar->iis, isar->cmsb,
+ isar->clsb);
+ isar->write_reg(isar->hw, ISAR_IIA, 0);
+ }
+ break;
+ case ISAR_IIS_GSTEV:
+ isar->write_reg(isar->hw, ISAR_IIA, 0);
+ isar->bstat |= isar->cmsb;
+ check_send(isar, isar->cmsb);
+ break;
+ case ISAR_IIS_BSTEV:
+#ifdef ERROR_STATISTIC
+ ch = sel_bch_isar(isar, isar->iis >> 6);
+ if (ch) {
+ if (isar->cmsb == BSTEV_TBO)
+ ch->bch.err_tx++;
+ if (isar->cmsb == BSTEV_RBO)
+ ch->bch.err_rdo++;
+ }
+#endif
+ pr_debug("%s: Buffer STEV dpath%d msb(%x)\n",
+ isar->name, isar->iis>>6, isar->cmsb);
+ isar->write_reg(isar->hw, ISAR_IIA, 0);
+ break;
+ case ISAR_IIS_PSTEV:
+ ch = sel_bch_isar(isar, isar->iis >> 6);
+ if (ch) {
+ rcv_mbox(isar, NULL);
+ if (ch->bch.state == ISDN_P_B_MODEM_ASYNC)
+ isar_pump_statev_modem(ch, isar->cmsb);
+ else if (ch->bch.state == ISDN_P_B_T30_FAX)
+ isar_pump_statev_fax(ch, isar->cmsb);
+ else if (ch->bch.state == ISDN_P_B_RAW) {
+ int tt;
+ tt = isar->cmsb | 0x30;
+ if (tt == 0x3e)
+ tt = '*';
+ else if (tt == 0x3f)
+ tt = '#';
+ else if (tt > '9')
+ tt += 7;
+ tt |= DTMF_TONE_VAL;
+ _queue_data(&ch->bch.ch, PH_CONTROL_IND,
+ MISDN_ID_ANY, sizeof(tt), &tt,
+ GFP_ATOMIC);
+ } else
+ pr_debug("%s: ISAR IIS_PSTEV pm %d sta %x\n",
+ isar->name, ch->bch.state,
+ isar->cmsb);
+ } else {
+ pr_debug("%s: ISAR spurious IIS_PSTEV %x/%x/%x\n",
+ isar->name, isar->iis, isar->cmsb,
+ isar->clsb);
+ isar->write_reg(isar->hw, ISAR_IIA, 0);
+ }
+ break;
+ case ISAR_IIS_PSTRSP:
+ ch = sel_bch_isar(isar, isar->iis >> 6);
+ if (ch) {
+ rcv_mbox(isar, NULL);
+ isar_pump_status_rsp(ch);
+ } else {
+ pr_debug("%s: ISAR spurious IIS_PSTRSP %x/%x/%x\n",
+ isar->name, isar->iis, isar->cmsb,
+ isar->clsb);
+ isar->write_reg(isar->hw, ISAR_IIA, 0);
+ }
+ break;
+ case ISAR_IIS_DIAG:
+ case ISAR_IIS_BSTRSP:
+ case ISAR_IIS_IOM2RSP:
+ rcv_mbox(isar, NULL);
+ break;
+ case ISAR_IIS_INVMSG:
+ rcv_mbox(isar, NULL);
+ pr_debug("%s: invalid msg his:%x\n", isar->name, isar->cmsb);
+ break;
+ default:
+ rcv_mbox(isar, NULL);
+ pr_debug("%s: unhandled msg iis(%x) ctrl(%x/%x)\n",
+ isar->name, isar->iis, isar->cmsb, isar->clsb);
+ break;
+ }
+}
+EXPORT_SYMBOL(mISDNisar_irq);
+
+static void
+ftimer_handler(unsigned long data)
+{
+ struct isar_ch *ch = (struct isar_ch *)data;
+
+ pr_debug("%s: ftimer flags %lx\n", ch->is->name, ch->bch.Flags);
+ test_and_clear_bit(FLG_FTI_RUN, &ch->bch.Flags);
+ if (test_and_clear_bit(FLG_LL_CONN, &ch->bch.Flags))
+ deliver_status(ch, HW_MOD_CONNECT);
+}
+
+static void
+setup_pump(struct isar_ch *ch) {
+ u8 dps = SET_DPS(ch->dpath);
+ u8 ctrl, param[6];
+
+ switch (ch->bch.state) {
+ case ISDN_P_NONE:
+ case ISDN_P_B_RAW:
+ case ISDN_P_B_HDLC:
+ send_mbox(ch->is, dps | ISAR_HIS_PUMPCFG, PMOD_BYPASS, 0, NULL);
+ break;
+ case ISDN_P_B_L2DTMF:
+ if (test_bit(FLG_DTMFSEND, &ch->bch.Flags)) {
+ param[0] = 5; /* TOA 5 db */
+ send_mbox(ch->is, dps | ISAR_HIS_PUMPCFG,
+ PMOD_DTMF_TRANS, 1, param);
+ } else {
+ param[0] = 40; /* REL -46 dbm */
+ send_mbox(ch->is, dps | ISAR_HIS_PUMPCFG,
+ PMOD_DTMF, 1, param);
+ }
+ case ISDN_P_B_MODEM_ASYNC:
+ ctrl = PMOD_DATAMODEM;
+ if (test_bit(FLG_ORIGIN, &ch->bch.Flags)) {
+ ctrl |= PCTRL_ORIG;
+ param[5] = PV32P6_CTN;
+ } else {
+ param[5] = PV32P6_ATN;
+ }
+ param[0] = 6; /* 6 db */
+ param[1] = PV32P2_V23R | PV32P2_V22A | PV32P2_V22B |
+ PV32P2_V22C | PV32P2_V21 | PV32P2_BEL;
+ param[2] = PV32P3_AMOD | PV32P3_V32B | PV32P3_V23B;
+ param[3] = PV32P4_UT144;
+ param[4] = PV32P5_UT144;
+ send_mbox(ch->is, dps | ISAR_HIS_PUMPCFG, ctrl, 6, param);
+ break;
+ case ISDN_P_B_T30_FAX:
+ ctrl = PMOD_FAX;
+ if (test_bit(FLG_ORIGIN, &ch->bch.Flags)) {
+ ctrl |= PCTRL_ORIG;
+ param[1] = PFAXP2_CTN;
+ } else {
+ param[1] = PFAXP2_ATN;
+ }
+ param[0] = 6; /* 6 db */
+ send_mbox(ch->is, dps | ISAR_HIS_PUMPCFG, ctrl, 2, param);
+ ch->state = STFAX_NULL;
+ ch->newcmd = 0;
+ ch->newmod = 0;
+ test_and_set_bit(FLG_FTI_RUN, &ch->bch.Flags);
+ break;
+ }
+ udelay(1000);
+ send_mbox(ch->is, dps | ISAR_HIS_PSTREQ, 0, 0, NULL);
+ udelay(1000);
+}
+
+static void
+setup_sart(struct isar_ch *ch) {
+ u8 dps = SET_DPS(ch->dpath);
+ u8 ctrl, param[2] = {0, 0};
+
+ switch (ch->bch.state) {
+ case ISDN_P_NONE:
+ send_mbox(ch->is, dps | ISAR_HIS_SARTCFG, SMODE_DISABLE,
+ 0, NULL);
+ break;
+ case ISDN_P_B_RAW:
+ case ISDN_P_B_L2DTMF:
+ send_mbox(ch->is, dps | ISAR_HIS_SARTCFG, SMODE_BINARY,
+ 2, param);
+ break;
+ case ISDN_P_B_HDLC:
+ case ISDN_P_B_T30_FAX:
+ send_mbox(ch->is, dps | ISAR_HIS_SARTCFG, SMODE_HDLC,
+ 1, param);
+ break;
+ case ISDN_P_B_MODEM_ASYNC:
+ ctrl = SMODE_V14 | SCTRL_HDMC_BOTH;
+ param[0] = S_P1_CHS_8;
+ param[1] = S_P2_BFT_DEF;
+ send_mbox(ch->is, dps | ISAR_HIS_SARTCFG, ctrl, 2, param);
+ break;
+ }
+ udelay(1000);
+ send_mbox(ch->is, dps | ISAR_HIS_BSTREQ, 0, 0, NULL);
+ udelay(1000);
+}
+
+static void
+setup_iom2(struct isar_ch *ch) {
+ u8 dps = SET_DPS(ch->dpath);
+ u8 cmsb = IOM_CTRL_ENA, msg[5] = {IOM_P1_TXD, 0, 0, 0, 0};
+
+ if (ch->bch.nr == 2) {
+ msg[1] = 1;
+ msg[3] = 1;
+ }
+ switch (ch->bch.state) {
+ case ISDN_P_NONE:
+ cmsb = 0;
+ /* dummy slot */
+ msg[1] = ch->dpath + 2;
+ msg[3] = ch->dpath + 2;
+ break;
+ case ISDN_P_B_RAW:
+ case ISDN_P_B_HDLC:
+ break;
+ case ISDN_P_B_MODEM_ASYNC:
+ case ISDN_P_B_T30_FAX:
+ cmsb |= IOM_CTRL_RCV;
+ case ISDN_P_B_L2DTMF:
+ if (test_bit(FLG_DTMFSEND, &ch->bch.Flags))
+ cmsb |= IOM_CTRL_RCV;
+ cmsb |= IOM_CTRL_ALAW;
+ break;
+ }
+ send_mbox(ch->is, dps | ISAR_HIS_IOM2CFG, cmsb, 5, msg);
+ udelay(1000);
+ send_mbox(ch->is, dps | ISAR_HIS_IOM2REQ, 0, 0, NULL);
+ udelay(1000);
+}
+
+static int
+modeisar(struct isar_ch *ch, u32 bprotocol)
+{
+ /* Here we are selecting the best datapath for requested protocol */
+ if (ch->bch.state == ISDN_P_NONE) { /* New Setup */
+ switch (bprotocol) {
+ case ISDN_P_NONE: /* init */
+ if (!ch->dpath)
+ /* no init for dpath 0 */
+ return 0;
+ test_and_clear_bit(FLG_HDLC, &ch->bch.Flags);
+ test_and_clear_bit(FLG_TRANSPARENT, &ch->bch.Flags);
+ break;
+ case ISDN_P_B_RAW:
+ case ISDN_P_B_HDLC:
+ /* best is datapath 2 */
+ if (!test_and_set_bit(ISAR_DP2_USE, &ch->is->Flags))
+ ch->dpath = 2;
+ else if (!test_and_set_bit(ISAR_DP1_USE,
+ &ch->is->Flags))
+ ch->dpath = 1;
+ else {
+ pr_info("modeisar both pathes in use\n");
+ return -EBUSY;
+ }
+ if (bprotocol == ISDN_P_B_HDLC)
+ test_and_set_bit(FLG_HDLC, &ch->bch.Flags);
+ else
+ test_and_set_bit(FLG_TRANSPARENT,
+ &ch->bch.Flags);
+ break;
+ case ISDN_P_B_MODEM_ASYNC:
+ case ISDN_P_B_T30_FAX:
+ case ISDN_P_B_L2DTMF:
+ /* only datapath 1 */
+ if (!test_and_set_bit(ISAR_DP1_USE, &ch->is->Flags))
+ ch->dpath = 1;
+ else {
+ pr_info("%s: ISAR modeisar analog functions"
+ "only with DP1\n", ch->is->name);
+ return -EBUSY;
+ }
+ break;
+ default:
+ pr_info("%s: protocol not known %x\n", ch->is->name,
+ bprotocol);
+ return -ENOPROTOOPT;
+ }
+ }
+ pr_debug("%s: ISAR ch%d dp%d protocol %x->%x\n", ch->is->name,
+ ch->bch.nr, ch->dpath, ch->bch.state, bprotocol);
+ ch->bch.state = bprotocol;
+ setup_pump(ch);
+ setup_iom2(ch);
+ setup_sart(ch);
+ if (ch->bch.state == ISDN_P_NONE) {
+ /* Clear resources */
+ if (ch->dpath == 1)
+ test_and_clear_bit(ISAR_DP1_USE, &ch->is->Flags);
+ else if (ch->dpath == 2)
+ test_and_clear_bit(ISAR_DP2_USE, &ch->is->Flags);
+ ch->dpath = 0;
+ ch->is->ctrl(ch->is->hw, HW_DEACT_IND, ch->bch.nr);
+ } else
+ ch->is->ctrl(ch->is->hw, HW_ACTIVATE_IND, ch->bch.nr);
+ return 0;
+}
+
+static void
+isar_pump_cmd(struct isar_ch *ch, u32 cmd, u8 para)
+{
+ u8 dps = SET_DPS(ch->dpath);
+ u8 ctrl = 0, nom = 0, p1 = 0;
+
+ pr_debug("%s: isar_pump_cmd %x/%x state(%x)\n",
+ ch->is->name, cmd, para, ch->bch.state);
+ switch (cmd) {
+ case HW_MOD_FTM:
+ if (ch->state == STFAX_READY) {
+ p1 = para;
+ ctrl = PCTRL_CMD_FTM;
+ nom = 1;
+ ch->state = STFAX_LINE;
+ ch->cmd = ctrl;
+ ch->mod = para;
+ ch->newmod = 0;
+ ch->newcmd = 0;
+ ch->try_mod = 3;
+ } else if ((ch->state == STFAX_ACTIV) &&
+ (ch->cmd == PCTRL_CMD_FTM) && (ch->mod == para))
+ deliver_status(ch, HW_MOD_CONNECT);
+ else {
+ ch->newmod = para;
+ ch->newcmd = PCTRL_CMD_FTM;
+ nom = 0;
+ ctrl = PCTRL_CMD_ESC;
+ ch->state = STFAX_ESCAPE;
+ }
+ break;
+ case HW_MOD_FTH:
+ if (ch->state == STFAX_READY) {
+ p1 = para;
+ ctrl = PCTRL_CMD_FTH;
+ nom = 1;
+ ch->state = STFAX_LINE;
+ ch->cmd = ctrl;
+ ch->mod = para;
+ ch->newmod = 0;
+ ch->newcmd = 0;
+ ch->try_mod = 3;
+ } else if ((ch->state == STFAX_ACTIV) &&
+ (ch->cmd == PCTRL_CMD_FTH) && (ch->mod == para))
+ deliver_status(ch, HW_MOD_CONNECT);
+ else {
+ ch->newmod = para;
+ ch->newcmd = PCTRL_CMD_FTH;
+ nom = 0;
+ ctrl = PCTRL_CMD_ESC;
+ ch->state = STFAX_ESCAPE;
+ }
+ break;
+ case HW_MOD_FRM:
+ if (ch->state == STFAX_READY) {
+ p1 = para;
+ ctrl = PCTRL_CMD_FRM;
+ nom = 1;
+ ch->state = STFAX_LINE;
+ ch->cmd = ctrl;
+ ch->mod = para;
+ ch->newmod = 0;
+ ch->newcmd = 0;
+ ch->try_mod = 3;
+ } else if ((ch->state == STFAX_ACTIV) &&
+ (ch->cmd == PCTRL_CMD_FRM) && (ch->mod == para))
+ deliver_status(ch, HW_MOD_CONNECT);
+ else {
+ ch->newmod = para;
+ ch->newcmd = PCTRL_CMD_FRM;
+ nom = 0;
+ ctrl = PCTRL_CMD_ESC;
+ ch->state = STFAX_ESCAPE;
+ }
+ break;
+ case HW_MOD_FRH:
+ if (ch->state == STFAX_READY) {
+ p1 = para;
+ ctrl = PCTRL_CMD_FRH;
+ nom = 1;
+ ch->state = STFAX_LINE;
+ ch->cmd = ctrl;
+ ch->mod = para;
+ ch->newmod = 0;
+ ch->newcmd = 0;
+ ch->try_mod = 3;
+ } else if ((ch->state == STFAX_ACTIV) &&
+ (ch->cmd == PCTRL_CMD_FRH) && (ch->mod == para))
+ deliver_status(ch, HW_MOD_CONNECT);
+ else {
+ ch->newmod = para;
+ ch->newcmd = PCTRL_CMD_FRH;
+ nom = 0;
+ ctrl = PCTRL_CMD_ESC;
+ ch->state = STFAX_ESCAPE;
+ }
+ break;
+ case PCTRL_CMD_TDTMF:
+ p1 = para;
+ nom = 1;
+ ctrl = PCTRL_CMD_TDTMF;
+ break;
+ }
+ if (ctrl)
+ send_mbox(ch->is, dps | ISAR_HIS_PUMPCTRL, ctrl, nom, &p1);
+}
+
+static void
+isar_setup(struct isar_hw *isar)
+{
+ u8 msg;
+ int i;
+
+ /* Dpath 1, 2 */
+ msg = 61;
+ for (i = 0; i < 2; i++) {
+ /* Buffer Config */
+ send_mbox(isar, (i ? ISAR_HIS_DPS2 : ISAR_HIS_DPS1) |
+ ISAR_HIS_P12CFG, 4, 1, &msg);
+ isar->ch[i].mml = msg;
+ isar->ch[i].bch.state = 0;
+ isar->ch[i].dpath = i + 1;
+ modeisar(&isar->ch[i], ISDN_P_NONE);
+ }
+}
+
+static int
+isar_l2l1(struct mISDNchannel *ch, struct sk_buff *skb)
+{
+ struct bchannel *bch = container_of(ch, struct bchannel, ch);
+ struct isar_ch *ich = container_of(bch, struct isar_ch, bch);
+ int ret = -EINVAL;
+ struct mISDNhead *hh = mISDN_HEAD_P(skb);
+ u32 id, *val;
+ u_long flags;
+
+ switch (hh->prim) {
+ case PH_DATA_REQ:
+ spin_lock_irqsave(ich->is->hwlock, flags);
+ ret = bchannel_senddata(bch, skb);
+ if (ret > 0) { /* direct TX */
+ id = hh->id; /* skb can be freed */
+ ret = 0;
+ isar_fill_fifo(ich);
+ spin_unlock_irqrestore(ich->is->hwlock, flags);
+ if (!test_bit(FLG_TRANSPARENT, &bch->Flags))
+ queue_ch_frame(ch, PH_DATA_CNF, id, NULL);
+ } else
+ spin_unlock_irqrestore(ich->is->hwlock, flags);
+ return ret;
+ case PH_ACTIVATE_REQ:
+ spin_lock_irqsave(ich->is->hwlock, flags);
+ if (!test_and_set_bit(FLG_ACTIVE, &bch->Flags))
+ ret = modeisar(ich, ch->protocol);
+ else
+ ret = 0;
+ spin_unlock_irqrestore(ich->is->hwlock, flags);
+ if (!ret)
+ _queue_data(ch, PH_ACTIVATE_IND, MISDN_ID_ANY, 0,
+ NULL, GFP_KERNEL);
+ break;
+ case PH_DEACTIVATE_REQ:
+ spin_lock_irqsave(ich->is->hwlock, flags);
+ mISDN_clear_bchannel(bch);
+ modeisar(ich, ISDN_P_NONE);
+ spin_unlock_irqrestore(ich->is->hwlock, flags);
+ _queue_data(ch, PH_DEACTIVATE_IND, MISDN_ID_ANY, 0,
+ NULL, GFP_KERNEL);
+ ret = 0;
+ break;
+ case PH_CONTROL_REQ:
+ val = (u32 *)skb->data;
+ pr_debug("%s: PH_CONTROL | REQUEST %x/%x\n", ich->is->name,
+ hh->id, *val);
+ if ((hh->id == 0) && ((*val & ~DTMF_TONE_MASK) ==
+ DTMF_TONE_VAL)) {
+ if (bch->state == ISDN_P_B_L2DTMF) {
+ char tt = *val & DTMF_TONE_MASK;
+
+ if (tt == '*')
+ tt = 0x1e;
+ else if (tt == '#')
+ tt = 0x1f;
+ else if (tt > '9')
+ tt -= 7;
+ tt &= 0x1f;
+ spin_lock_irqsave(ich->is->hwlock, flags);
+ isar_pump_cmd(ich, PCTRL_CMD_TDTMF, tt);
+ spin_unlock_irqrestore(ich->is->hwlock, flags);
+ } else {
+ pr_info("%s: DTMF send wrong protocol %x\n",
+ __func__, bch->state);
+ return -EINVAL;
+ }
+ } else if ((hh->id == HW_MOD_FRM) || (hh->id == HW_MOD_FRH) ||
+ (hh->id == HW_MOD_FTM) || (hh->id == HW_MOD_FTH)) {
+ for (id = 0; id < FAXMODCNT; id++)
+ if (faxmodulation[id] == *val)
+ break;
+ if ((FAXMODCNT > id) &&
+ test_bit(FLG_INITIALIZED, &bch->Flags)) {
+ pr_debug("%s: isar: new mod\n", ich->is->name);
+ isar_pump_cmd(ich, hh->id, *val);
+ ret = 0;
+ } else {
+ pr_info("%s: wrong modulation\n",
+ ich->is->name);
+ ret = -EINVAL;
+ }
+ } else if (hh->id == HW_MOD_LASTDATA)
+ test_and_set_bit(FLG_DLEETX, &bch->Flags);
+ else {
+ pr_info("%s: unknown PH_CONTROL_REQ %x\n",
+ ich->is->name, hh->id);
+ ret = -EINVAL;
+ }
+ default:
+ pr_info("%s: %s unknown prim(%x,%x)\n",
+ ich->is->name, __func__, hh->prim, hh->id);
+ ret = -EINVAL;
+ }
+ if (!ret)
+ dev_kfree_skb(skb);
+ return ret;
+}
+
+static int
+channel_bctrl(struct bchannel *bch, struct mISDN_ctrl_req *cq)
+{
+ int ret = 0;
+
+ switch (cq->op) {
+ case MISDN_CTRL_GETOP:
+ cq->op = 0;
+ break;
+ /* Nothing implemented yet */
+ case MISDN_CTRL_FILL_EMPTY:
+ default:
+ pr_info("%s: unknown Op %x\n", __func__, cq->op);
+ ret = -EINVAL;
+ break;
+ }
+ return ret;
+}
+
+static int
+isar_bctrl(struct mISDNchannel *ch, u32 cmd, void *arg)
+{
+ struct bchannel *bch = container_of(ch, struct bchannel, ch);
+ struct isar_ch *ich = container_of(bch, struct isar_ch, bch);
+ int ret = -EINVAL;
+ u_long flags;
+
+ pr_debug("%s: %s cmd:%x %p\n", ich->is->name, __func__, cmd, arg);
+ switch (cmd) {
+ case CLOSE_CHANNEL:
+ test_and_clear_bit(FLG_OPEN, &bch->Flags);
+ if (test_bit(FLG_ACTIVE, &bch->Flags)) {
+ spin_lock_irqsave(ich->is->hwlock, flags);
+ mISDN_freebchannel(bch);
+ modeisar(ich, ISDN_P_NONE);
+ spin_unlock_irqrestore(ich->is->hwlock, flags);
+ } else {
+ skb_queue_purge(&bch->rqueue);
+ bch->rcount = 0;
+ }
+ ch->protocol = ISDN_P_NONE;
+ ch->peer = NULL;
+ module_put(ich->is->owner);
+ ret = 0;
+ break;
+ case CONTROL_CHANNEL:
+ ret = channel_bctrl(bch, arg);
+ break;
+ default:
+ pr_info("%s: %s unknown prim(%x)\n",
+ ich->is->name, __func__, cmd);
+ }
+ return ret;
+}
+
+static void
+free_isar(struct isar_hw *isar)
+{
+ modeisar(&isar->ch[0], ISDN_P_NONE);
+ modeisar(&isar->ch[1], ISDN_P_NONE);
+ del_timer(&isar->ch[0].ftimer);
+ del_timer(&isar->ch[1].ftimer);
+ test_and_clear_bit(FLG_INITIALIZED, &isar->ch[0].bch.Flags);
+ test_and_clear_bit(FLG_INITIALIZED, &isar->ch[1].bch.Flags);
+}
+
+static int
+init_isar(struct isar_hw *isar)
+{
+ int cnt = 3;
+
+ while (cnt--) {
+ isar->version = ISARVersion(isar);
+ if (isar->ch[0].bch.debug & DEBUG_HW)
+ pr_notice("%s: Testing version %d (%d time)\n",
+ isar->name, isar->version, 3 - cnt);
+ if (isar->version == 1)
+ break;
+ isar->ctrl(isar->hw, HW_RESET_REQ, 0);
+ }
+ if (isar->version != 1)
+ return -EINVAL;
+ isar->ch[0].ftimer.function = &ftimer_handler;
+ isar->ch[0].ftimer.data = (long)&isar->ch[0];
+ init_timer(&isar->ch[0].ftimer);
+ test_and_set_bit(FLG_INITIALIZED, &isar->ch[0].bch.Flags);
+ isar->ch[1].ftimer.function = &ftimer_handler;
+ isar->ch[1].ftimer.data = (long)&isar->ch[1];
+ init_timer(&isar->ch[1].ftimer);
+ test_and_set_bit(FLG_INITIALIZED, &isar->ch[1].bch.Flags);
+ return 0;
+}
+
+static int
+isar_open(struct isar_hw *isar, struct channel_req *rq)
+{
+ struct bchannel *bch;
+
+ if (rq->adr.channel > 2)
+ return -EINVAL;
+ if (rq->protocol == ISDN_P_NONE)
+ return -EINVAL;
+ bch = &isar->ch[rq->adr.channel - 1].bch;
+ if (test_and_set_bit(FLG_OPEN, &bch->Flags))
+ return -EBUSY; /* b-channel can be only open once */
+ test_and_clear_bit(FLG_FILLEMPTY, &bch->Flags);
+ bch->ch.protocol = rq->protocol;
+ rq->ch = &bch->ch;
+ return 0;
+}
+
+u32
+mISDNisar_init(struct isar_hw *isar, void *hw)
+{
+ u32 ret, i;
+
+ isar->hw = hw;
+ for (i = 0; i < 2; i++) {
+ isar->ch[i].bch.nr = i + 1;
+ mISDN_initbchannel(&isar->ch[i].bch, MAX_DATA_MEM);
+ isar->ch[i].bch.ch.nr = i + 1;
+ isar->ch[i].bch.ch.send = &isar_l2l1;
+ isar->ch[i].bch.ch.ctrl = isar_bctrl;
+ isar->ch[i].bch.hw = hw;
+ isar->ch[i].is = isar;
+ }
+
+ isar->init = &init_isar;
+ isar->release = &free_isar;
+ isar->firmware = &load_firmware;
+ isar->open = &isar_open;
+
+ ret = (1 << (ISDN_P_B_RAW & ISDN_P_B_MASK)) |
+ (1 << (ISDN_P_B_HDLC & ISDN_P_B_MASK)) |
+ (1 << (ISDN_P_B_L2DTMF & ISDN_P_B_MASK)) |
+ (1 << (ISDN_P_B_MODEM_ASYNC & ISDN_P_B_MASK)) |
+ (1 << (ISDN_P_B_T30_FAX & ISDN_P_B_MASK));
+
+ return ret;
+}
+EXPORT_SYMBOL(mISDNisar_init);
+
+static int isar_mod_init(void)
+{
+ pr_notice("mISDN: ISAR driver Rev. %s\n", ISAR_REV);
+ return 0;
+}
+
+static void isar_mod_cleanup(void)
+{
+ pr_notice("mISDN: ISAR module unloaded\n");
+}
+module_init(isar_mod_init);
+module_exit(isar_mod_cleanup);
diff --git a/drivers/isdn/hardware/mISDN/netjet.c b/drivers/isdn/hardware/mISDN/netjet.c
new file mode 100644
index 00000000000..6c1b164937a
--- /dev/null
+++ b/drivers/isdn/hardware/mISDN/netjet.c
@@ -0,0 +1,1156 @@
+/*
+ * NETJet mISDN driver
+ *
+ * Author Karsten Keil <keil@isdn4linux.de>
+ *
+ * Copyright 2009 by Karsten Keil <keil@isdn4linux.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/mISDNhw.h>
+#include "ipac.h"
+#include "iohelper.h"
+#include "netjet.h"
+#include <linux/isdn/hdlc.h>
+
+#define NETJET_REV "2.0"
+
+enum nj_types {
+ NETJET_S_TJ300,
+ NETJET_S_TJ320,
+ ENTERNOW__TJ320,
+};
+
+struct tiger_dma {
+ size_t size;
+ u32 *start;
+ int idx;
+ u32 dmastart;
+ u32 dmairq;
+ u32 dmaend;
+ u32 dmacur;
+};
+
+struct tiger_hw;
+
+struct tiger_ch {
+ struct bchannel bch;
+ struct tiger_hw *nj;
+ int idx;
+ int free;
+ int lastrx;
+ u16 rxstate;
+ u16 txstate;
+ struct isdnhdlc_vars hsend;
+ struct isdnhdlc_vars hrecv;
+ u8 *hsbuf;
+ u8 *hrbuf;
+};
+
+#define TX_INIT 0x0001
+#define TX_IDLE 0x0002
+#define TX_RUN 0x0004
+#define TX_UNDERRUN 0x0100
+#define RX_OVERRUN 0x0100
+
+#define LOG_SIZE 64
+
+struct tiger_hw {
+ struct list_head list;
+ struct pci_dev *pdev;
+ char name[MISDN_MAX_IDLEN];
+ enum nj_types typ;
+ int irq;
+ u32 irqcnt;
+ u32 base;
+ size_t base_s;
+ dma_addr_t dma;
+ void *dma_p;
+ spinlock_t lock; /* lock HW */
+ struct isac_hw isac;
+ struct tiger_dma send;
+ struct tiger_dma recv;
+ struct tiger_ch bc[2];
+ u8 ctrlreg;
+ u8 dmactrl;
+ u8 auxd;
+ u8 last_is0;
+ u8 irqmask0;
+ char log[LOG_SIZE];
+};
+
+static LIST_HEAD(Cards);
+static DEFINE_RWLOCK(card_lock); /* protect Cards */
+static u32 debug;
+static int nj_cnt;
+
+static void
+_set_debug(struct tiger_hw *card)
+{
+ card->isac.dch.debug = debug;
+ card->bc[0].bch.debug = debug;
+ card->bc[1].bch.debug = debug;
+}
+
+static int
+set_debug(const char *val, struct kernel_param *kp)
+{
+ int ret;
+ struct tiger_hw *card;
+
+ ret = param_set_uint(val, kp);
+ if (!ret) {
+ read_lock(&card_lock);
+ list_for_each_entry(card, &Cards, list)
+ _set_debug(card);
+ read_unlock(&card_lock);
+ }
+ return ret;
+}
+
+MODULE_AUTHOR("Karsten Keil");
+MODULE_LICENSE("GPL v2");
+MODULE_VERSION(NETJET_REV);
+module_param_call(debug, set_debug, param_get_uint, &debug, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "Netjet debug mask");
+
+static void
+nj_disable_hwirq(struct tiger_hw *card)
+{
+ outb(0, card->base + NJ_IRQMASK0);
+ outb(0, card->base + NJ_IRQMASK1);
+}
+
+
+static u8
+ReadISAC_nj(void *p, u8 offset)
+{
+ struct tiger_hw *card = p;
+ u8 ret;
+
+ card->auxd &= 0xfc;
+ card->auxd |= (offset >> 4) & 3;
+ outb(card->auxd, card->base + NJ_AUXDATA);
+ ret = inb(card->base + NJ_ISAC_OFF + ((offset & 0x0f) << 2));
+ return ret;
+}
+
+static void
+WriteISAC_nj(void *p, u8 offset, u8 value)
+{
+ struct tiger_hw *card = p;
+
+ card->auxd &= 0xfc;
+ card->auxd |= (offset >> 4) & 3;
+ outb(card->auxd, card->base + NJ_AUXDATA);
+ outb(value, card->base + NJ_ISAC_OFF + ((offset & 0x0f) << 2));
+}
+
+static void
+ReadFiFoISAC_nj(void *p, u8 offset, u8 *data, int size)
+{
+ struct tiger_hw *card = p;
+
+ card->auxd &= 0xfc;
+ outb(card->auxd, card->base + NJ_AUXDATA);
+ insb(card->base + NJ_ISAC_OFF, data, size);
+}
+
+static void
+WriteFiFoISAC_nj(void *p, u8 offset, u8 *data, int size)
+{
+ struct tiger_hw *card = p;
+
+ card->auxd &= 0xfc;
+ outb(card->auxd, card->base + NJ_AUXDATA);
+ outsb(card->base + NJ_ISAC_OFF, data, size);
+}
+
+static void
+fill_mem(struct tiger_ch *bc, u32 idx, u32 cnt, u32 fill)
+{
+ struct tiger_hw *card = bc->bch.hw;
+ u32 mask = 0xff, val;
+
+ pr_debug("%s: B%1d fill %02x len %d idx %d/%d\n", card->name,
+ bc->bch.nr, fill, cnt, idx, card->send.idx);
+ if (bc->bch.nr & 2) {
+ fill <<= 8;
+ mask <<= 8;
+ }
+ mask ^= 0xffffffff;
+ while (cnt--) {
+ val = card->send.start[idx];
+ val &= mask;
+ val |= fill;
+ card->send.start[idx++] = val;
+ if (idx >= card->send.size)
+ idx = 0;
+ }
+}
+
+static int
+mode_tiger(struct tiger_ch *bc, u32 protocol)
+{
+ struct tiger_hw *card = bc->bch.hw;
+
+ pr_debug("%s: B%1d protocol %x-->%x\n", card->name,
+ bc->bch.nr, bc->bch.state, protocol);
+ switch (protocol) {
+ case ISDN_P_NONE:
+ if (bc->bch.state == ISDN_P_NONE)
+ break;
+ fill_mem(bc, 0, card->send.size, 0xff);
+ bc->bch.state = protocol;
+ /* only stop dma and interrupts if both channels NULL */
+ if ((card->bc[0].bch.state == ISDN_P_NONE) &&
+ (card->bc[1].bch.state == ISDN_P_NONE)) {
+ card->dmactrl = 0;
+ outb(card->dmactrl, card->base + NJ_DMACTRL);
+ outb(0, card->base + NJ_IRQMASK0);
+ }
+ test_and_clear_bit(FLG_HDLC, &bc->bch.Flags);
+ test_and_clear_bit(FLG_TRANSPARENT, &bc->bch.Flags);
+ bc->txstate = 0;
+ bc->rxstate = 0;
+ bc->lastrx = -1;
+ break;
+ case ISDN_P_B_RAW:
+ test_and_set_bit(FLG_TRANSPARENT, &bc->bch.Flags);
+ bc->bch.state = protocol;
+ bc->idx = 0;
+ bc->free = card->send.size/2;
+ bc->rxstate = 0;
+ bc->txstate = TX_INIT | TX_IDLE;
+ bc->lastrx = -1;
+ if (!card->dmactrl) {
+ card->dmactrl = 1;
+ outb(card->dmactrl, card->base + NJ_DMACTRL);
+ outb(0x0f, card->base + NJ_IRQMASK0);
+ }
+ break;
+ case ISDN_P_B_HDLC:
+ test_and_set_bit(FLG_HDLC, &bc->bch.Flags);
+ bc->bch.state = protocol;
+ bc->idx = 0;
+ bc->free = card->send.size/2;
+ bc->rxstate = 0;
+ bc->txstate = TX_INIT | TX_IDLE;
+ isdnhdlc_rcv_init(&bc->hrecv, 0);
+ isdnhdlc_out_init(&bc->hsend, 0);
+ bc->lastrx = -1;
+ if (!card->dmactrl) {
+ card->dmactrl = 1;
+ outb(card->dmactrl, card->base + NJ_DMACTRL);
+ outb(0x0f, card->base + NJ_IRQMASK0);
+ }
+ break;
+ default:
+ pr_info("%s: %s protocol %x not handled\n", card->name,
+ __func__, protocol);
+ return -ENOPROTOOPT;
+ }
+ card->send.dmacur = inl(card->base + NJ_DMA_READ_ADR);
+ card->recv.dmacur = inl(card->base + NJ_DMA_WRITE_ADR);
+ card->send.idx = (card->send.dmacur - card->send.dmastart) >> 2;
+ card->recv.idx = (card->recv.dmacur - card->recv.dmastart) >> 2;
+ pr_debug("%s: %s ctrl %x irq %02x/%02x idx %d/%d\n",
+ card->name, __func__,
+ inb(card->base + NJ_DMACTRL),
+ inb(card->base + NJ_IRQMASK0),
+ inb(card->base + NJ_IRQSTAT0),
+ card->send.idx,
+ card->recv.idx);
+ return 0;
+}
+
+static void
+nj_reset(struct tiger_hw *card)
+{
+ outb(0xff, card->base + NJ_CTRL); /* Reset On */
+ mdelay(1);
+
+ /* now edge triggered for TJ320 GE 13/07/00 */
+ /* see comment in IRQ function */
+ if (card->typ == NETJET_S_TJ320) /* TJ320 */
+ card->ctrlreg = 0x40; /* Reset Off and status read clear */
+ else
+ card->ctrlreg = 0x00; /* Reset Off and status read clear */
+ outb(card->ctrlreg, card->base + NJ_CTRL);
+ mdelay(10);
+
+ /* configure AUX pins (all output except ISAC IRQ pin) */
+ card->auxd = 0;
+ card->dmactrl = 0;
+ outb(~NJ_ISACIRQ, card->base + NJ_AUXCTRL);
+ outb(NJ_ISACIRQ, card->base + NJ_IRQMASK1);
+ outb(card->auxd, card->base + NJ_AUXDATA);
+}
+
+static int
+inittiger(struct tiger_hw *card)
+{
+ int i;
+
+ card->dma_p = pci_alloc_consistent(card->pdev, NJ_DMA_SIZE,
+ &card->dma);
+ if (!card->dma_p) {
+ pr_info("%s: No DMA memory\n", card->name);
+ return -ENOMEM;
+ }
+ if ((u64)card->dma > 0xffffffff) {
+ pr_info("%s: DMA outside 32 bit\n", card->name);
+ return -ENOMEM;
+ }
+ for (i = 0; i < 2; i++) {
+ card->bc[i].hsbuf = kmalloc(NJ_DMA_TXSIZE, GFP_KERNEL);
+ if (!card->bc[i].hsbuf) {
+ pr_info("%s: no B%d send buffer\n", card->name, i + 1);
+ return -ENOMEM;
+ }
+ card->bc[i].hrbuf = kmalloc(NJ_DMA_RXSIZE, GFP_KERNEL);
+ if (!card->bc[i].hrbuf) {
+ pr_info("%s: no B%d recv buffer\n", card->name, i + 1);
+ return -ENOMEM;
+ }
+ }
+ memset(card->dma_p, 0xff, NJ_DMA_SIZE);
+
+ card->send.start = card->dma_p;
+ card->send.dmastart = (u32)card->dma;
+ card->send.dmaend = card->send.dmastart +
+ (4 * (NJ_DMA_TXSIZE - 1));
+ card->send.dmairq = card->send.dmastart +
+ (4 * ((NJ_DMA_TXSIZE / 2) - 1));
+ card->send.size = NJ_DMA_TXSIZE;
+
+ if (debug & DEBUG_HW)
+ pr_notice("%s: send buffer phy %#x - %#x - %#x virt %p"
+ " size %zu u32\n", card->name,
+ card->send.dmastart, card->send.dmairq,
+ card->send.dmaend, card->send.start, card->send.size);
+
+ outl(card->send.dmastart, card->base + NJ_DMA_READ_START);
+ outl(card->send.dmairq, card->base + NJ_DMA_READ_IRQ);
+ outl(card->send.dmaend, card->base + NJ_DMA_READ_END);
+
+ card->recv.start = card->dma_p + (NJ_DMA_SIZE / 2);
+ card->recv.dmastart = (u32)card->dma + (NJ_DMA_SIZE / 2);
+ card->recv.dmaend = card->recv.dmastart +
+ (4 * (NJ_DMA_RXSIZE - 1));
+ card->recv.dmairq = card->recv.dmastart +
+ (4 * ((NJ_DMA_RXSIZE / 2) - 1));
+ card->recv.size = NJ_DMA_RXSIZE;
+
+ if (debug & DEBUG_HW)
+ pr_notice("%s: recv buffer phy %#x - %#x - %#x virt %p"
+ " size %zu u32\n", card->name,
+ card->recv.dmastart, card->recv.dmairq,
+ card->recv.dmaend, card->recv.start, card->recv.size);
+
+ outl(card->recv.dmastart, card->base + NJ_DMA_WRITE_START);
+ outl(card->recv.dmairq, card->base + NJ_DMA_WRITE_IRQ);
+ outl(card->recv.dmaend, card->base + NJ_DMA_WRITE_END);
+ return 0;
+}
+
+static void
+read_dma(struct tiger_ch *bc, u32 idx, int cnt)
+{
+ struct tiger_hw *card = bc->bch.hw;
+ int i, stat;
+ u32 val;
+ u8 *p, *pn;
+
+ if (bc->lastrx == idx) {
+ bc->rxstate |= RX_OVERRUN;
+ pr_info("%s: B%1d overrun at idx %d\n", card->name,
+ bc->bch.nr, idx);
+ }
+ bc->lastrx = idx;
+ if (!bc->bch.rx_skb) {
+ bc->bch.rx_skb = mI_alloc_skb(bc->bch.maxlen, GFP_ATOMIC);
+ if (!bc->bch.rx_skb) {
+ pr_info("%s: B%1d receive out of memory\n",
+ card->name, bc->bch.nr);
+ return;
+ }
+ }
+
+ if (test_bit(FLG_TRANSPARENT, &bc->bch.Flags)) {
+ if ((bc->bch.rx_skb->len + cnt) > bc->bch.maxlen) {
+ pr_debug("%s: B%1d overrun %d\n", card->name,
+ bc->bch.nr, bc->bch.rx_skb->len + cnt);
+ skb_trim(bc->bch.rx_skb, 0);
+ return;
+ }
+ p = skb_put(bc->bch.rx_skb, cnt);
+ } else
+ p = bc->hrbuf;
+
+ for (i = 0; i < cnt; i++) {
+ val = card->recv.start[idx++];
+ if (bc->bch.nr & 2)
+ val >>= 8;
+ if (idx >= card->recv.size)
+ idx = 0;
+ p[i] = val & 0xff;
+ }
+ pn = bc->hrbuf;
+next_frame:
+ if (test_bit(FLG_HDLC, &bc->bch.Flags)) {
+ stat = isdnhdlc_decode(&bc->hrecv, pn, cnt, &i,
+ bc->bch.rx_skb->data, bc->bch.maxlen);
+ if (stat > 0) /* valid frame received */
+ p = skb_put(bc->bch.rx_skb, stat);
+ else if (stat == -HDLC_CRC_ERROR)
+ pr_info("%s: B%1d receive frame CRC error\n",
+ card->name, bc->bch.nr);
+ else if (stat == -HDLC_FRAMING_ERROR)
+ pr_info("%s: B%1d receive framing error\n",
+ card->name, bc->bch.nr);
+ else if (stat == -HDLC_LENGTH_ERROR)
+ pr_info("%s: B%1d receive frame too long (> %d)\n",
+ card->name, bc->bch.nr, bc->bch.maxlen);
+ } else
+ stat = cnt;
+
+ if (stat > 0) {
+ if (debug & DEBUG_HW_BFIFO) {
+ snprintf(card->log, LOG_SIZE, "B%1d-recv %s %d ",
+ bc->bch.nr, card->name, stat);
+ print_hex_dump_bytes(card->log, DUMP_PREFIX_OFFSET,
+ p, stat);
+ }
+ recv_Bchannel(&bc->bch, 0);
+ }
+ if (test_bit(FLG_HDLC, &bc->bch.Flags)) {
+ pn += i;
+ cnt -= i;
+ if (!bc->bch.rx_skb) {
+ bc->bch.rx_skb = mI_alloc_skb(bc->bch.maxlen,
+ GFP_ATOMIC);
+ if (!bc->bch.rx_skb) {
+ pr_info("%s: B%1d receive out of memory\n",
+ card->name, bc->bch.nr);
+ return;
+ }
+ }
+ if (cnt > 0)
+ goto next_frame;
+ }
+}
+
+static void
+recv_tiger(struct tiger_hw *card, u8 irq_stat)
+{
+ u32 idx;
+ int cnt = card->recv.size / 2;
+
+ /* Note receive is via the WRITE DMA channel */
+ card->last_is0 &= ~NJ_IRQM0_WR_MASK;
+ card->last_is0 |= (irq_stat & NJ_IRQM0_WR_MASK);
+
+ if (irq_stat & NJ_IRQM0_WR_END)
+ idx = cnt - 1;
+ else
+ idx = card->recv.size - 1;
+
+ if (test_bit(FLG_ACTIVE, &card->bc[0].bch.Flags))
+ read_dma(&card->bc[0], idx, cnt);
+ if (test_bit(FLG_ACTIVE, &card->bc[1].bch.Flags))
+ read_dma(&card->bc[1], idx, cnt);
+}
+
+/* sync with current DMA address at start or after exception */
+static void
+resync(struct tiger_ch *bc, struct tiger_hw *card)
+{
+ card->send.dmacur = inl(card->base | NJ_DMA_READ_ADR);
+ card->send.idx = (card->send.dmacur - card->send.dmastart) >> 2;
+ if (bc->free > card->send.size / 2)
+ bc->free = card->send.size / 2;
+ /* currently we simple sync to the next complete free area
+ * this hast the advantage that we have always maximum time to
+ * handle TX irq
+ */
+ if (card->send.idx < ((card->send.size / 2) - 1))
+ bc->idx = (card->recv.size / 2) - 1;
+ else
+ bc->idx = card->recv.size - 1;
+ bc->txstate = TX_RUN;
+ pr_debug("%s: %s B%1d free %d idx %d/%d\n", card->name,
+ __func__, bc->bch.nr, bc->free, bc->idx, card->send.idx);
+}
+
+static int bc_next_frame(struct tiger_ch *);
+
+static void
+fill_hdlc_flag(struct tiger_ch *bc)
+{
+ struct tiger_hw *card = bc->bch.hw;
+ int count, i;
+ u32 m, v;
+ u8 *p;
+
+ if (bc->free == 0)
+ return;
+ pr_debug("%s: %s B%1d %d state %x idx %d/%d\n", card->name,
+ __func__, bc->bch.nr, bc->free, bc->txstate,
+ bc->idx, card->send.idx);
+ if (bc->txstate & (TX_IDLE | TX_INIT | TX_UNDERRUN))
+ resync(bc, card);
+ count = isdnhdlc_encode(&bc->hsend, NULL, 0, &i,
+ bc->hsbuf, bc->free);
+ pr_debug("%s: B%1d hdlc encoded %d flags\n", card->name,
+ bc->bch.nr, count);
+ bc->free -= count;
+ p = bc->hsbuf;
+ m = (bc->bch.nr & 1) ? 0xffffff00 : 0xffff00ff;
+ for (i = 0; i < count; i++) {
+ if (bc->idx >= card->send.size)
+ bc->idx = 0;
+ v = card->send.start[bc->idx];
+ v &= m;
+ v |= (bc->bch.nr & 1) ? (u32)(p[i]) : ((u32)(p[i])) << 8;
+ card->send.start[bc->idx++] = v;
+ }
+ if (debug & DEBUG_HW_BFIFO) {
+ snprintf(card->log, LOG_SIZE, "B%1d-send %s %d ",
+ bc->bch.nr, card->name, count);
+ print_hex_dump_bytes(card->log, DUMP_PREFIX_OFFSET, p, count);
+ }
+}
+
+static void
+fill_dma(struct tiger_ch *bc)
+{
+ struct tiger_hw *card = bc->bch.hw;
+ int count, i;
+ u32 m, v;
+ u8 *p;
+
+ if (bc->free == 0)
+ return;
+ count = bc->bch.tx_skb->len - bc->bch.tx_idx;
+ if (count <= 0)
+ return;
+ pr_debug("%s: %s B%1d %d/%d/%d/%d state %x idx %d/%d\n", card->name,
+ __func__, bc->bch.nr, count, bc->free, bc->bch.tx_idx,
+ bc->bch.tx_skb->len, bc->txstate, bc->idx, card->send.idx);
+ if (bc->txstate & (TX_IDLE | TX_INIT | TX_UNDERRUN))
+ resync(bc, card);
+ p = bc->bch.tx_skb->data + bc->bch.tx_idx;
+ if (test_bit(FLG_HDLC, &bc->bch.Flags)) {
+ count = isdnhdlc_encode(&bc->hsend, p, count, &i,
+ bc->hsbuf, bc->free);
+ pr_debug("%s: B%1d hdlc encoded %d in %d\n", card->name,
+ bc->bch.nr, i, count);
+ bc->bch.tx_idx += i;
+ bc->free -= count;
+ p = bc->hsbuf;
+ } else {
+ if (count > bc->free)
+ count = bc->free;
+ bc->bch.tx_idx += count;
+ bc->free -= count;
+ }
+ m = (bc->bch.nr & 1) ? 0xffffff00 : 0xffff00ff;
+ for (i = 0; i < count; i++) {
+ if (bc->idx >= card->send.size)
+ bc->idx = 0;
+ v = card->send.start[bc->idx];
+ v &= m;
+ v |= (bc->bch.nr & 1) ? (u32)(p[i]) : ((u32)(p[i])) << 8;
+ card->send.start[bc->idx++] = v;
+ }
+ if (debug & DEBUG_HW_BFIFO) {
+ snprintf(card->log, LOG_SIZE, "B%1d-send %s %d ",
+ bc->bch.nr, card->name, count);
+ print_hex_dump_bytes(card->log, DUMP_PREFIX_OFFSET, p, count);
+ }
+ if (bc->free)
+ bc_next_frame(bc);
+}
+
+
+static int
+bc_next_frame(struct tiger_ch *bc)
+{
+ if (bc->bch.tx_skb && bc->bch.tx_idx < bc->bch.tx_skb->len)
+ fill_dma(bc);
+ else {
+ if (bc->bch.tx_skb) {
+ /* send confirm, on trans, free on hdlc. */
+ if (test_bit(FLG_TRANSPARENT, &bc->bch.Flags))
+ confirm_Bsend(&bc->bch);
+ dev_kfree_skb(bc->bch.tx_skb);
+ }
+ if (get_next_bframe(&bc->bch))
+ fill_dma(bc);
+ else
+ return 0;
+ }
+ return 1;
+}
+
+static void
+send_tiger_bc(struct tiger_hw *card, struct tiger_ch *bc)
+{
+ int ret;
+
+ bc->free += card->send.size / 2;
+ if (bc->free >= card->send.size) {
+ if (!(bc->txstate & (TX_UNDERRUN | TX_INIT))) {
+ pr_info("%s: B%1d TX underrun state %x\n", card->name,
+ bc->bch.nr, bc->txstate);
+ bc->txstate |= TX_UNDERRUN;
+ }
+ bc->free = card->send.size;
+ }
+ ret = bc_next_frame(bc);
+ if (!ret) {
+ if (test_bit(FLG_HDLC, &bc->bch.Flags)) {
+ fill_hdlc_flag(bc);
+ return;
+ }
+ pr_debug("%s: B%1d TX no data free %d idx %d/%d\n", card->name,
+ bc->bch.nr, bc->free, bc->idx, card->send.idx);
+ if (!(bc->txstate & (TX_IDLE | TX_INIT))) {
+ fill_mem(bc, bc->idx, bc->free, 0xff);
+ if (bc->free == card->send.size)
+ bc->txstate |= TX_IDLE;
+ }
+ }
+}
+
+static void
+send_tiger(struct tiger_hw *card, u8 irq_stat)
+{
+ int i;
+
+ /* Note send is via the READ DMA channel */
+ if ((irq_stat & card->last_is0) & NJ_IRQM0_RD_MASK) {
+ pr_info("%s: tiger warn write double dma %x/%x\n",
+ card->name, irq_stat, card->last_is0);
+ return;
+ } else {
+ card->last_is0 &= ~NJ_IRQM0_RD_MASK;
+ card->last_is0 |= (irq_stat & NJ_IRQM0_RD_MASK);
+ }
+ for (i = 0; i < 2; i++) {
+ if (test_bit(FLG_ACTIVE, &card->bc[i].bch.Flags))
+ send_tiger_bc(card, &card->bc[i]);
+ }
+}
+
+static irqreturn_t
+nj_irq(int intno, void *dev_id)
+{
+ struct tiger_hw *card = dev_id;
+ u8 val, s1val, s0val;
+
+ spin_lock(&card->lock);
+ s0val = inb(card->base | NJ_IRQSTAT0);
+ s1val = inb(card->base | NJ_IRQSTAT1);
+ if ((s1val & NJ_ISACIRQ) && (s0val == 0)) {
+ /* shared IRQ */
+ spin_unlock(&card->lock);
+ return IRQ_NONE;
+ }
+ pr_debug("%s: IRQSTAT0 %02x IRQSTAT1 %02x\n", card->name, s0val, s1val);
+ card->irqcnt++;
+ if (!(s1val & NJ_ISACIRQ)) {
+ val = ReadISAC_nj(card, ISAC_ISTA);
+ if (val)
+ mISDNisac_irq(&card->isac, val);
+ }
+
+ if (s0val)
+ /* write to clear */
+ outb(s0val, card->base | NJ_IRQSTAT0);
+ else
+ goto end;
+ s1val = s0val;
+ /* set bits in sval to indicate which page is free */
+ card->recv.dmacur = inl(card->base | NJ_DMA_WRITE_ADR);
+ card->recv.idx = (card->recv.dmacur - card->recv.dmastart) >> 2;
+ if (card->recv.dmacur < card->recv.dmairq)
+ s0val = 0x08; /* the 2nd write area is free */
+ else
+ s0val = 0x04; /* the 1st write area is free */
+
+ card->send.dmacur = inl(card->base | NJ_DMA_READ_ADR);
+ card->send.idx = (card->send.dmacur - card->send.dmastart) >> 2;
+ if (card->send.dmacur < card->send.dmairq)
+ s0val |= 0x02; /* the 2nd read area is free */
+ else
+ s0val |= 0x01; /* the 1st read area is free */
+
+ pr_debug("%s: DMA Status %02x/%02x/%02x %d/%d\n", card->name,
+ s1val, s0val, card->last_is0,
+ card->recv.idx, card->send.idx);
+ /* test if we have a DMA interrupt */
+ if (s0val != card->last_is0) {
+ if ((s0val & NJ_IRQM0_RD_MASK) !=
+ (card->last_is0 & NJ_IRQM0_RD_MASK))
+ /* got a write dma int */
+ send_tiger(card, s0val);
+ if ((s0val & NJ_IRQM0_WR_MASK) !=
+ (card->last_is0 & NJ_IRQM0_WR_MASK))
+ /* got a read dma int */
+ recv_tiger(card, s0val);
+ }
+end:
+ spin_unlock(&card->lock);
+ return IRQ_HANDLED;
+}
+
+static int
+nj_l2l1B(struct mISDNchannel *ch, struct sk_buff *skb)
+{
+ int ret = -EINVAL;
+ struct bchannel *bch = container_of(ch, struct bchannel, ch);
+ struct tiger_ch *bc = container_of(bch, struct tiger_ch, bch);
+ struct tiger_hw *card = bch->hw;
+ struct mISDNhead *hh = mISDN_HEAD_P(skb);
+ u32 id;
+ u_long flags;
+
+ switch (hh->prim) {
+ case PH_DATA_REQ:
+ spin_lock_irqsave(&card->lock, flags);
+ ret = bchannel_senddata(bch, skb);
+ if (ret > 0) { /* direct TX */
+ id = hh->id; /* skb can be freed */
+ fill_dma(bc);
+ ret = 0;
+ spin_unlock_irqrestore(&card->lock, flags);
+ if (!test_bit(FLG_TRANSPARENT, &bch->Flags))
+ queue_ch_frame(ch, PH_DATA_CNF, id, NULL);
+ } else
+ spin_unlock_irqrestore(&card->lock, flags);
+ return ret;
+ case PH_ACTIVATE_REQ:
+ spin_lock_irqsave(&card->lock, flags);
+ if (!test_and_set_bit(FLG_ACTIVE, &bch->Flags))
+ ret = mode_tiger(bc, ch->protocol);
+ else
+ ret = 0;
+ spin_unlock_irqrestore(&card->lock, flags);
+ if (!ret)
+ _queue_data(ch, PH_ACTIVATE_IND, MISDN_ID_ANY, 0,
+ NULL, GFP_KERNEL);
+ break;
+ case PH_DEACTIVATE_REQ:
+ spin_lock_irqsave(&card->lock, flags);
+ mISDN_clear_bchannel(bch);
+ mode_tiger(bc, ISDN_P_NONE);
+ spin_unlock_irqrestore(&card->lock, flags);
+ _queue_data(ch, PH_DEACTIVATE_IND, MISDN_ID_ANY, 0,
+ NULL, GFP_KERNEL);
+ ret = 0;
+ break;
+ }
+ if (!ret)
+ dev_kfree_skb(skb);
+ return ret;
+}
+
+static int
+channel_bctrl(struct tiger_ch *bc, struct mISDN_ctrl_req *cq)
+{
+ int ret = 0;
+ struct tiger_hw *card = bc->bch.hw;
+
+ switch (cq->op) {
+ case MISDN_CTRL_GETOP:
+ cq->op = 0;
+ break;
+ /* Nothing implemented yet */
+ case MISDN_CTRL_FILL_EMPTY:
+ default:
+ pr_info("%s: %s unknown Op %x\n", card->name, __func__, cq->op);
+ ret = -EINVAL;
+ break;
+ }
+ return ret;
+}
+
+static int
+nj_bctrl(struct mISDNchannel *ch, u32 cmd, void *arg)
+{
+ struct bchannel *bch = container_of(ch, struct bchannel, ch);
+ struct tiger_ch *bc = container_of(bch, struct tiger_ch, bch);
+ struct tiger_hw *card = bch->hw;
+ int ret = -EINVAL;
+ u_long flags;
+
+ pr_debug("%s: %s cmd:%x %p\n", card->name, __func__, cmd, arg);
+ switch (cmd) {
+ case CLOSE_CHANNEL:
+ test_and_clear_bit(FLG_OPEN, &bch->Flags);
+ if (test_bit(FLG_ACTIVE, &bch->Flags)) {
+ spin_lock_irqsave(&card->lock, flags);
+ mISDN_freebchannel(bch);
+ test_and_clear_bit(FLG_TX_BUSY, &bch->Flags);
+ test_and_clear_bit(FLG_ACTIVE, &bch->Flags);
+ mode_tiger(bc, ISDN_P_NONE);
+ spin_unlock_irqrestore(&card->lock, flags);
+ }
+ ch->protocol = ISDN_P_NONE;
+ ch->peer = NULL;
+ module_put(THIS_MODULE);
+ ret = 0;
+ break;
+ case CONTROL_CHANNEL:
+ ret = channel_bctrl(bc, arg);
+ break;
+ default:
+ pr_info("%s: %s unknown prim(%x)\n", card->name, __func__, cmd);
+ }
+ return ret;
+}
+
+static int
+channel_ctrl(struct tiger_hw *card, struct mISDN_ctrl_req *cq)
+{
+ int ret = 0;
+
+ switch (cq->op) {
+ case MISDN_CTRL_GETOP:
+ cq->op = MISDN_CTRL_LOOP;
+ break;
+ case MISDN_CTRL_LOOP:
+ /* cq->channel: 0 disable, 1 B1 loop 2 B2 loop, 3 both */
+ if (cq->channel < 0 || cq->channel > 3) {
+ ret = -EINVAL;
+ break;
+ }
+ ret = card->isac.ctrl(&card->isac, HW_TESTLOOP, cq->channel);
+ break;
+ default:
+ pr_info("%s: %s unknown Op %x\n", card->name, __func__, cq->op);
+ ret = -EINVAL;
+ break;
+ }
+ return ret;
+}
+
+static int
+open_bchannel(struct tiger_hw *card, struct channel_req *rq)
+{
+ struct bchannel *bch;
+
+ if (rq->adr.channel > 2)
+ return -EINVAL;
+ if (rq->protocol == ISDN_P_NONE)
+ return -EINVAL;
+ bch = &card->bc[rq->adr.channel - 1].bch;
+ if (test_and_set_bit(FLG_OPEN, &bch->Flags))
+ return -EBUSY; /* b-channel can be only open once */
+ test_and_clear_bit(FLG_FILLEMPTY, &bch->Flags);
+ bch->ch.protocol = rq->protocol;
+ rq->ch = &bch->ch;
+ return 0;
+}
+
+/*
+ * device control function
+ */
+static int
+nj_dctrl(struct mISDNchannel *ch, u32 cmd, void *arg)
+{
+ struct mISDNdevice *dev = container_of(ch, struct mISDNdevice, D);
+ struct dchannel *dch = container_of(dev, struct dchannel, dev);
+ struct tiger_hw *card = dch->hw;
+ struct channel_req *rq;
+ int err = 0;
+
+ pr_debug("%s: %s cmd:%x %p\n", card->name, __func__, cmd, arg);
+ switch (cmd) {
+ case OPEN_CHANNEL:
+ rq = arg;
+ if (rq->protocol == ISDN_P_TE_S0)
+ err = card->isac.open(&card->isac, rq);
+ else
+ err = open_bchannel(card, rq);
+ if (err)
+ break;
+ if (!try_module_get(THIS_MODULE))
+ pr_info("%s: cannot get module\n", card->name);
+ break;
+ case CLOSE_CHANNEL:
+ pr_debug("%s: dev(%d) close from %p\n", card->name, dch->dev.id,
+ __builtin_return_address(0));
+ module_put(THIS_MODULE);
+ break;
+ case CONTROL_CHANNEL:
+ err = channel_ctrl(card, arg);
+ break;
+ default:
+ pr_debug("%s: %s unknown command %x\n",
+ card->name, __func__, cmd);
+ return -EINVAL;
+ }
+ return err;
+}
+
+static int
+nj_init_card(struct tiger_hw *card)
+{
+ u_long flags;
+ int ret;
+
+ spin_lock_irqsave(&card->lock, flags);
+ nj_disable_hwirq(card);
+ spin_unlock_irqrestore(&card->lock, flags);
+
+ card->irq = card->pdev->irq;
+ if (request_irq(card->irq, nj_irq, IRQF_SHARED, card->name, card)) {
+ pr_info("%s: couldn't get interrupt %d\n",
+ card->name, card->irq);
+ card->irq = -1;
+ return -EIO;
+ }
+
+ spin_lock_irqsave(&card->lock, flags);
+ nj_reset(card);
+ ret = card->isac.init(&card->isac);
+ if (ret)
+ goto error;
+ ret = inittiger(card);
+ if (ret)
+ goto error;
+ mode_tiger(&card->bc[0], ISDN_P_NONE);
+ mode_tiger(&card->bc[1], ISDN_P_NONE);
+error:
+ spin_unlock_irqrestore(&card->lock, flags);
+ return ret;
+}
+
+
+static void
+nj_release(struct tiger_hw *card)
+{
+ u_long flags;
+ int i;
+
+ if (card->base_s) {
+ spin_lock_irqsave(&card->lock, flags);
+ nj_disable_hwirq(card);
+ mode_tiger(&card->bc[0], ISDN_P_NONE);
+ mode_tiger(&card->bc[1], ISDN_P_NONE);
+ card->isac.release(&card->isac);
+ spin_unlock_irqrestore(&card->lock, flags);
+ release_region(card->base, card->base_s);
+ card->base_s = 0;
+ }
+ if (card->irq > 0)
+ free_irq(card->irq, card);
+ if (card->isac.dch.dev.dev.class)
+ mISDN_unregister_device(&card->isac.dch.dev);
+
+ for (i = 0; i < 2; i++) {
+ mISDN_freebchannel(&card->bc[i].bch);
+ kfree(card->bc[i].hsbuf);
+ kfree(card->bc[i].hrbuf);
+ }
+ if (card->dma_p)
+ pci_free_consistent(card->pdev, NJ_DMA_SIZE,
+ card->dma_p, card->dma);
+ write_lock_irqsave(&card_lock, flags);
+ list_del(&card->list);
+ write_unlock_irqrestore(&card_lock, flags);
+ pci_clear_master(card->pdev);
+ pci_disable_device(card->pdev);
+ pci_set_drvdata(card->pdev, NULL);
+ kfree(card);
+}
+
+
+static int
+nj_setup(struct tiger_hw *card)
+{
+ card->base = pci_resource_start(card->pdev, 0);
+ card->base_s = pci_resource_len(card->pdev, 0);
+ if (!request_region(card->base, card->base_s, card->name)) {
+ pr_info("%s: NETjet config port %#x-%#x already in use\n",
+ card->name, card->base,
+ (u32)(card->base + card->base_s - 1));
+ card->base_s = 0;
+ return -EIO;
+ }
+ ASSIGN_FUNC(nj, ISAC, card->isac);
+ return 0;
+}
+
+
+static int __devinit
+setup_instance(struct tiger_hw *card)
+{
+ int i, err;
+ u_long flags;
+
+ snprintf(card->name, MISDN_MAX_IDLEN - 1, "netjet.%d", nj_cnt + 1);
+ write_lock_irqsave(&card_lock, flags);
+ list_add_tail(&card->list, &Cards);
+ write_unlock_irqrestore(&card_lock, flags);
+
+ _set_debug(card);
+ card->isac.name = card->name;
+ spin_lock_init(&card->lock);
+ card->isac.hwlock = &card->lock;
+ mISDNisac_init(&card->isac, card);
+
+ card->isac.dch.dev.Bprotocols = (1 << (ISDN_P_B_RAW & ISDN_P_B_MASK)) |
+ (1 << (ISDN_P_B_HDLC & ISDN_P_B_MASK));
+ card->isac.dch.dev.D.ctrl = nj_dctrl;
+ for (i = 0; i < 2; i++) {
+ card->bc[i].bch.nr = i + 1;
+ set_channelmap(i + 1, card->isac.dch.dev.channelmap);
+ mISDN_initbchannel(&card->bc[i].bch, MAX_DATA_MEM);
+ card->bc[i].bch.hw = card;
+ card->bc[i].bch.ch.send = nj_l2l1B;
+ card->bc[i].bch.ch.ctrl = nj_bctrl;
+ card->bc[i].bch.ch.nr = i + 1;
+ list_add(&card->bc[i].bch.ch.list,
+ &card->isac.dch.dev.bchannels);
+ card->bc[i].bch.hw = card;
+ }
+ err = nj_setup(card);
+ if (err)
+ goto error;
+ err = mISDN_register_device(&card->isac.dch.dev, &card->pdev->dev,
+ card->name);
+ if (err)
+ goto error;
+ err = nj_init_card(card);
+ if (!err) {
+ nj_cnt++;
+ pr_notice("Netjet %d cards installed\n", nj_cnt);
+ return 0;
+ }
+error:
+ nj_release(card);
+ return err;
+}
+
+static int __devinit
+nj_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+ int err = -ENOMEM;
+ int cfg;
+ struct tiger_hw *card;
+
+ if (pdev->subsystem_vendor == 0x8086 &&
+ pdev->subsystem_device == 0x0003) {
+ pr_notice("Netjet: Digium X100P/X101P not handled\n");
+ return -ENODEV;
+ }
+
+ if (pdev->subsystem_vendor == 0x55 &&
+ pdev->subsystem_device == 0x02) {
+ pr_notice("Netjet: Enter!Now not handled yet\n");
+ return -ENODEV;
+ }
+
+ card = kzalloc(sizeof(struct tiger_hw), GFP_ATOMIC);
+ if (!card) {
+ pr_info("No kmem for Netjet\n");
+ return err;
+ }
+
+ card->pdev = pdev;
+
+ err = pci_enable_device(pdev);
+ if (err) {
+ kfree(card);
+ return err;
+ }
+
+ printk(KERN_INFO "nj_probe(mISDN): found adapter at %s\n",
+ pci_name(pdev));
+
+ pci_set_master(pdev);
+
+ /* the TJ300 and TJ320 must be detected, the IRQ handling is different
+ * unfortunately the chips use the same device ID, but the TJ320 has
+ * the bit20 in status PCI cfg register set
+ */
+ pci_read_config_dword(pdev, 0x04, &cfg);
+ if (cfg & 0x00100000)
+ card->typ = NETJET_S_TJ320;
+ else
+ card->typ = NETJET_S_TJ300;
+
+ card->base = pci_resource_start(pdev, 0);
+ card->irq = pdev->irq;
+ pci_set_drvdata(pdev, card);
+ err = setup_instance(card);
+ if (err)
+ pci_set_drvdata(pdev, NULL);
+
+ return err;
+}
+
+
+static void __devexit nj_remove(struct pci_dev *pdev)
+{
+ struct tiger_hw *card = pci_get_drvdata(pdev);
+
+ if (card)
+ nj_release(card);
+ else
+ pr_info("%s drvdata already removed\n", __func__);
+}
+
+/* We cannot select cards with PCI_SUB... IDs, since here are cards with
+ * SUB IDs set to PCI_ANY_ID, so we need to match all and reject
+ * known other cards which not work with this driver - see probe function */
+static struct pci_device_id nj_pci_ids[] __devinitdata = {
+ { PCI_VENDOR_ID_TIGERJET, PCI_DEVICE_ID_TIGERJET_300,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ { }
+};
+MODULE_DEVICE_TABLE(pci, nj_pci_ids);
+
+static struct pci_driver nj_driver = {
+ .name = "netjet",
+ .probe = nj_probe,
+ .remove = __devexit_p(nj_remove),
+ .id_table = nj_pci_ids,
+};
+
+static int __init nj_init(void)
+{
+ int err;
+
+ pr_notice("Netjet PCI driver Rev. %s\n", NETJET_REV);
+ err = pci_register_driver(&nj_driver);
+ return err;
+}
+
+static void __exit nj_cleanup(void)
+{
+ pci_unregister_driver(&nj_driver);
+}
+
+module_init(nj_init);
+module_exit(nj_cleanup);
diff --git a/drivers/isdn/hardware/mISDN/netjet.h b/drivers/isdn/hardware/mISDN/netjet.h
new file mode 100644
index 00000000000..d061ff99560
--- /dev/null
+++ b/drivers/isdn/hardware/mISDN/netjet.h
@@ -0,0 +1,58 @@
+/*
+ * NETjet common header file
+ *
+ * Author Karsten Keil
+ * based on work of Matt Henderson and Daniel Potts,
+ * Traverse Technologies P/L www.traverse.com.au
+ *
+ * Copyright 2009 by Karsten Keil <keil@isdn4linux.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#define NJ_CTRL 0x00
+#define NJ_DMACTRL 0x01
+#define NJ_AUXCTRL 0x02
+#define NJ_AUXDATA 0x03
+#define NJ_IRQMASK0 0x04
+#define NJ_IRQMASK1 0x05
+#define NJ_IRQSTAT0 0x06
+#define NJ_IRQSTAT1 0x07
+#define NJ_DMA_READ_START 0x08
+#define NJ_DMA_READ_IRQ 0x0c
+#define NJ_DMA_READ_END 0x10
+#define NJ_DMA_READ_ADR 0x14
+#define NJ_DMA_WRITE_START 0x18
+#define NJ_DMA_WRITE_IRQ 0x1c
+#define NJ_DMA_WRITE_END 0x20
+#define NJ_DMA_WRITE_ADR 0x24
+#define NJ_PULSE_CNT 0x28
+
+#define NJ_ISAC_OFF 0xc0
+#define NJ_ISACIRQ 0x10
+
+#define NJ_IRQM0_RD_MASK 0x03
+#define NJ_IRQM0_RD_IRQ 0x01
+#define NJ_IRQM0_RD_END 0x02
+#define NJ_IRQM0_WR_MASK 0x0c
+#define NJ_IRQM0_WR_IRQ 0x04
+#define NJ_IRQM0_WR_END 0x08
+
+/* one page here is no need to be smaller */
+#define NJ_DMA_SIZE 4096
+/* 2 * 64 byte is a compromise between IRQ count and latency */
+#define NJ_DMA_RXSIZE 128 /* 2 * 64 */
+#define NJ_DMA_TXSIZE 128 /* 2 * 64 */
+
diff --git a/drivers/isdn/hardware/mISDN/speedfax.c b/drivers/isdn/hardware/mISDN/speedfax.c
new file mode 100644
index 00000000000..ff3a4e290da
--- /dev/null
+++ b/drivers/isdn/hardware/mISDN/speedfax.c
@@ -0,0 +1,526 @@
+/*
+ * speedfax.c low level stuff for Sedlbauer Speedfax+ cards
+ * based on the ISAR DSP
+ * Thanks to Sedlbauer AG for informations and HW
+ *
+ * Author Karsten Keil <keil@isdn4linux.de>
+ *
+ * Copyright 2009 by Karsten Keil <keil@isdn4linux.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/mISDNhw.h>
+#include <linux/firmware.h>
+#include "ipac.h"
+#include "isar.h"
+
+#define SPEEDFAX_REV "2.0"
+
+#define PCI_SUBVENDOR_SPEEDFAX_PYRAMID 0x51
+#define PCI_SUBVENDOR_SPEEDFAX_PCI 0x54
+#define PCI_SUB_ID_SEDLBAUER 0x01
+
+#define SFAX_PCI_ADDR 0xc8
+#define SFAX_PCI_ISAC 0xd0
+#define SFAX_PCI_ISAR 0xe0
+
+/* TIGER 100 Registers */
+
+#define TIGER_RESET_ADDR 0x00
+#define TIGER_EXTERN_RESET_ON 0x01
+#define TIGER_EXTERN_RESET_OFF 0x00
+#define TIGER_AUX_CTRL 0x02
+#define TIGER_AUX_DATA 0x03
+#define TIGER_AUX_IRQMASK 0x05
+#define TIGER_AUX_STATUS 0x07
+
+/* Tiger AUX BITs */
+#define SFAX_AUX_IOMASK 0xdd /* 1 and 5 are inputs */
+#define SFAX_ISAR_RESET_BIT_OFF 0x00
+#define SFAX_ISAR_RESET_BIT_ON 0x01
+#define SFAX_TIGER_IRQ_BIT 0x02
+#define SFAX_LED1_BIT 0x08
+#define SFAX_LED2_BIT 0x10
+
+#define SFAX_PCI_RESET_ON (SFAX_ISAR_RESET_BIT_ON)
+#define SFAX_PCI_RESET_OFF (SFAX_LED1_BIT | SFAX_LED2_BIT)
+
+static int sfax_cnt;
+static u32 debug;
+static u32 irqloops = 4;
+
+struct sfax_hw {
+ struct list_head list;
+ struct pci_dev *pdev;
+ char name[MISDN_MAX_IDLEN];
+ u32 irq;
+ u32 irqcnt;
+ u32 cfg;
+ struct _ioport p_isac;
+ struct _ioport p_isar;
+ u8 aux_data;
+ spinlock_t lock; /* HW access lock */
+ struct isac_hw isac;
+ struct isar_hw isar;
+};
+
+static LIST_HEAD(Cards);
+static DEFINE_RWLOCK(card_lock); /* protect Cards */
+
+static void
+_set_debug(struct sfax_hw *card)
+{
+ card->isac.dch.debug = debug;
+ card->isar.ch[0].bch.debug = debug;
+ card->isar.ch[1].bch.debug = debug;
+}
+
+static int
+set_debug(const char *val, struct kernel_param *kp)
+{
+ int ret;
+ struct sfax_hw *card;
+
+ ret = param_set_uint(val, kp);
+ if (!ret) {
+ read_lock(&card_lock);
+ list_for_each_entry(card, &Cards, list)
+ _set_debug(card);
+ read_unlock(&card_lock);
+ }
+ return ret;
+}
+
+MODULE_AUTHOR("Karsten Keil");
+MODULE_LICENSE("GPL v2");
+MODULE_VERSION(SPEEDFAX_REV);
+module_param_call(debug, set_debug, param_get_uint, &debug, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "Speedfax debug mask");
+module_param(irqloops, uint, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(irqloops, "Speedfax maximal irqloops (default 4)");
+
+IOFUNC_IND(ISAC, sfax_hw, p_isac)
+IOFUNC_IND(ISAR, sfax_hw, p_isar)
+
+static irqreturn_t
+speedfax_irq(int intno, void *dev_id)
+{
+ struct sfax_hw *sf = dev_id;
+ u8 val;
+ int cnt = irqloops;
+
+ spin_lock(&sf->lock);
+ val = inb(sf->cfg + TIGER_AUX_STATUS);
+ if (val & SFAX_TIGER_IRQ_BIT) { /* for us or shared ? */
+ spin_unlock(&sf->lock);
+ return IRQ_NONE; /* shared */
+ }
+ sf->irqcnt++;
+ val = ReadISAR_IND(sf, ISAR_IRQBIT);
+Start_ISAR:
+ if (val & ISAR_IRQSTA)
+ mISDNisar_irq(&sf->isar);
+ val = ReadISAC_IND(sf, ISAC_ISTA);
+ if (val)
+ mISDNisac_irq(&sf->isac, val);
+ val = ReadISAR_IND(sf, ISAR_IRQBIT);
+ if ((val & ISAR_IRQSTA) && cnt--)
+ goto Start_ISAR;
+ if (cnt < irqloops)
+ pr_debug("%s: %d irqloops cpu%d\n", sf->name,
+ irqloops - cnt, smp_processor_id());
+ if (irqloops && !cnt)
+ pr_notice("%s: %d IRQ LOOP cpu%d\n", sf->name,
+ irqloops, smp_processor_id());
+ spin_unlock(&sf->lock);
+ return IRQ_HANDLED;
+}
+
+static void
+enable_hwirq(struct sfax_hw *sf)
+{
+ WriteISAC_IND(sf, ISAC_MASK, 0);
+ WriteISAR_IND(sf, ISAR_IRQBIT, ISAR_IRQMSK);
+ outb(SFAX_TIGER_IRQ_BIT, sf->cfg + TIGER_AUX_IRQMASK);
+}
+
+static void
+disable_hwirq(struct sfax_hw *sf)
+{
+ WriteISAC_IND(sf, ISAC_MASK, 0xFF);
+ WriteISAR_IND(sf, ISAR_IRQBIT, 0);
+ outb(0, sf->cfg + TIGER_AUX_IRQMASK);
+}
+
+static void
+reset_speedfax(struct sfax_hw *sf)
+{
+
+ pr_debug("%s: resetting card\n", sf->name);
+ outb(TIGER_EXTERN_RESET_ON, sf->cfg + TIGER_RESET_ADDR);
+ outb(SFAX_PCI_RESET_ON, sf->cfg + TIGER_AUX_DATA);
+ mdelay(1);
+ outb(TIGER_EXTERN_RESET_OFF, sf->cfg + TIGER_RESET_ADDR);
+ sf->aux_data = SFAX_PCI_RESET_OFF;
+ outb(sf->aux_data, sf->cfg + TIGER_AUX_DATA);
+ mdelay(1);
+}
+
+static int
+sfax_ctrl(struct sfax_hw *sf, u32 cmd, u_long arg)
+{
+ int ret = 0;
+
+ switch (cmd) {
+ case HW_RESET_REQ:
+ reset_speedfax(sf);
+ break;
+ case HW_ACTIVATE_IND:
+ if (arg & 1)
+ sf->aux_data &= ~SFAX_LED1_BIT;
+ if (arg & 2)
+ sf->aux_data &= ~SFAX_LED2_BIT;
+ outb(sf->aux_data, sf->cfg + TIGER_AUX_DATA);
+ break;
+ case HW_DEACT_IND:
+ if (arg & 1)
+ sf->aux_data |= SFAX_LED1_BIT;
+ if (arg & 2)
+ sf->aux_data |= SFAX_LED2_BIT;
+ outb(sf->aux_data, sf->cfg + TIGER_AUX_DATA);
+ break;
+ default:
+ pr_info("%s: %s unknown command %x %lx\n",
+ sf->name, __func__, cmd, arg);
+ ret = -EINVAL;
+ break;
+ }
+ return ret;
+}
+
+static int
+channel_ctrl(struct sfax_hw *sf, struct mISDN_ctrl_req *cq)
+{
+ int ret = 0;
+
+ switch (cq->op) {
+ case MISDN_CTRL_GETOP:
+ cq->op = MISDN_CTRL_LOOP;
+ break;
+ case MISDN_CTRL_LOOP:
+ /* cq->channel: 0 disable, 1 B1 loop 2 B2 loop, 3 both */
+ if (cq->channel < 0 || cq->channel > 3) {
+ ret = -EINVAL;
+ break;
+ }
+ ret = sf->isac.ctrl(&sf->isac, HW_TESTLOOP, cq->channel);
+ break;
+ default:
+ pr_info("%s: unknown Op %x\n", sf->name, cq->op);
+ ret = -EINVAL;
+ break;
+ }
+ return ret;
+}
+
+static int
+sfax_dctrl(struct mISDNchannel *ch, u32 cmd, void *arg)
+{
+ struct mISDNdevice *dev = container_of(ch, struct mISDNdevice, D);
+ struct dchannel *dch = container_of(dev, struct dchannel, dev);
+ struct sfax_hw *sf = dch->hw;
+ struct channel_req *rq;
+ int err = 0;
+
+ pr_debug("%s: cmd:%x %p\n", sf->name, cmd, arg);
+ switch (cmd) {
+ case OPEN_CHANNEL:
+ rq = arg;
+ if (rq->protocol == ISDN_P_TE_S0)
+ err = sf->isac.open(&sf->isac, rq);
+ else
+ err = sf->isar.open(&sf->isar, rq);
+ if (err)
+ break;
+ if (!try_module_get(THIS_MODULE))
+ pr_info("%s: cannot get module\n", sf->name);
+ break;
+ case CLOSE_CHANNEL:
+ pr_debug("%s: dev(%d) close from %p\n", sf->name,
+ dch->dev.id, __builtin_return_address(0));
+ module_put(THIS_MODULE);
+ break;
+ case CONTROL_CHANNEL:
+ err = channel_ctrl(sf, arg);
+ break;
+ default:
+ pr_debug("%s: unknown command %x\n", sf->name, cmd);
+ return -EINVAL;
+ }
+ return err;
+}
+
+static int __devinit
+init_card(struct sfax_hw *sf)
+{
+ int ret, cnt = 3;
+ u_long flags;
+
+ ret = request_irq(sf->irq, speedfax_irq, IRQF_SHARED, sf->name, sf);
+ if (ret) {
+ pr_info("%s: couldn't get interrupt %d\n", sf->name, sf->irq);
+ return ret;
+ }
+ while (cnt--) {
+ spin_lock_irqsave(&sf->lock, flags);
+ ret = sf->isac.init(&sf->isac);
+ if (ret) {
+ spin_unlock_irqrestore(&sf->lock, flags);
+ pr_info("%s: ISAC init failed with %d\n",
+ sf->name, ret);
+ break;
+ }
+ enable_hwirq(sf);
+ /* RESET Receiver and Transmitter */
+ WriteISAC_IND(sf, ISAC_CMDR, 0x41);
+ spin_unlock_irqrestore(&sf->lock, flags);
+ msleep_interruptible(10);
+ if (debug & DEBUG_HW)
+ pr_notice("%s: IRQ %d count %d\n", sf->name,
+ sf->irq, sf->irqcnt);
+ if (!sf->irqcnt) {
+ pr_info("%s: IRQ(%d) got no requests during init %d\n",
+ sf->name, sf->irq, 3 - cnt);
+ } else
+ return 0;
+ }
+ free_irq(sf->irq, sf);
+ return -EIO;
+}
+
+
+static int __devinit
+setup_speedfax(struct sfax_hw *sf)
+{
+ u_long flags;
+
+ if (!request_region(sf->cfg, 256, sf->name)) {
+ pr_info("mISDN: %s config port %x-%x already in use\n",
+ sf->name, sf->cfg, sf->cfg + 255);
+ return -EIO;
+ }
+ outb(0xff, sf->cfg);
+ outb(0, sf->cfg);
+ outb(0xdd, sf->cfg + TIGER_AUX_CTRL);
+ outb(0, sf->cfg + TIGER_AUX_IRQMASK);
+
+ sf->isac.type = IPAC_TYPE_ISAC;
+ sf->p_isac.ale = sf->cfg + SFAX_PCI_ADDR;
+ sf->p_isac.port = sf->cfg + SFAX_PCI_ISAC;
+ sf->p_isar.ale = sf->cfg + SFAX_PCI_ADDR;
+ sf->p_isar.port = sf->cfg + SFAX_PCI_ISAR;
+ ASSIGN_FUNC(IND, ISAC, sf->isac);
+ ASSIGN_FUNC(IND, ISAR, sf->isar);
+ spin_lock_irqsave(&sf->lock, flags);
+ reset_speedfax(sf);
+ disable_hwirq(sf);
+ spin_unlock_irqrestore(&sf->lock, flags);
+ return 0;
+}
+
+static void
+release_card(struct sfax_hw *card) {
+ u_long flags;
+
+ spin_lock_irqsave(&card->lock, flags);
+ disable_hwirq(card);
+ spin_unlock_irqrestore(&card->lock, flags);
+ card->isac.release(&card->isac);
+ free_irq(card->irq, card);
+ card->isar.release(&card->isar);
+ mISDN_unregister_device(&card->isac.dch.dev);
+ release_region(card->cfg, 256);
+ pci_disable_device(card->pdev);
+ pci_set_drvdata(card->pdev, NULL);
+ write_lock_irqsave(&card_lock, flags);
+ list_del(&card->list);
+ write_unlock_irqrestore(&card_lock, flags);
+ kfree(card);
+ sfax_cnt--;
+}
+
+static int __devinit
+setup_instance(struct sfax_hw *card)
+{
+ const struct firmware *firmware;
+ int i, err;
+ u_long flags;
+
+ snprintf(card->name, MISDN_MAX_IDLEN - 1, "Speedfax.%d", sfax_cnt + 1);
+ write_lock_irqsave(&card_lock, flags);
+ list_add_tail(&card->list, &Cards);
+ write_unlock_irqrestore(&card_lock, flags);
+ _set_debug(card);
+ spin_lock_init(&card->lock);
+ card->isac.hwlock = &card->lock;
+ card->isar.hwlock = &card->lock;
+ card->isar.ctrl = (void *)&sfax_ctrl;
+ card->isac.name = card->name;
+ card->isar.name = card->name;
+ card->isar.owner = THIS_MODULE;
+
+ err = request_firmware(&firmware, "isdn/ISAR.BIN", &card->pdev->dev);
+ if (err < 0) {
+ pr_info("%s: firmware request failed %d\n",
+ card->name, err);
+ goto error_fw;
+ }
+ if (debug & DEBUG_HW)
+ pr_notice("%s: got firmware %zu bytes\n",
+ card->name, firmware->size);
+
+ mISDNisac_init(&card->isac, card);
+
+ card->isac.dch.dev.D.ctrl = sfax_dctrl;
+ card->isac.dch.dev.Bprotocols =
+ mISDNisar_init(&card->isar, card);
+ for (i = 0; i < 2; i++) {
+ set_channelmap(i + 1, card->isac.dch.dev.channelmap);
+ list_add(&card->isar.ch[i].bch.ch.list,
+ &card->isac.dch.dev.bchannels);
+ }
+
+ err = setup_speedfax(card);
+ if (err)
+ goto error_setup;
+ err = card->isar.init(&card->isar);
+ if (err)
+ goto error;
+ err = mISDN_register_device(&card->isac.dch.dev,
+ &card->pdev->dev, card->name);
+ if (err)
+ goto error;
+ err = init_card(card);
+ if (err)
+ goto error_init;
+ err = card->isar.firmware(&card->isar, firmware->data, firmware->size);
+ if (!err) {
+ release_firmware(firmware);
+ sfax_cnt++;
+ pr_notice("SpeedFax %d cards installed\n", sfax_cnt);
+ return 0;
+ }
+ disable_hwirq(card);
+ free_irq(card->irq, card);
+error_init:
+ mISDN_unregister_device(&card->isac.dch.dev);
+error:
+ release_region(card->cfg, 256);
+error_setup:
+ card->isac.release(&card->isac);
+ card->isar.release(&card->isar);
+ release_firmware(firmware);
+error_fw:
+ pci_disable_device(card->pdev);
+ write_lock_irqsave(&card_lock, flags);
+ list_del(&card->list);
+ write_unlock_irqrestore(&card_lock, flags);
+ kfree(card);
+ return err;
+}
+
+static int __devinit
+sfaxpci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+ int err = -ENOMEM;
+ struct sfax_hw *card = kzalloc(sizeof(struct sfax_hw), GFP_KERNEL);
+
+ if (!card) {
+ pr_info("No memory for Speedfax+ PCI\n");
+ return err;
+ }
+ card->pdev = pdev;
+ err = pci_enable_device(pdev);
+ if (err) {
+ kfree(card);
+ return err;
+ }
+
+ pr_notice("mISDN: Speedfax found adapter %s at %s\n",
+ (char *)ent->driver_data, pci_name(pdev));
+
+ card->cfg = pci_resource_start(pdev, 0);
+ card->irq = pdev->irq;
+ pci_set_drvdata(pdev, card);
+ err = setup_instance(card);
+ if (err)
+ pci_set_drvdata(pdev, NULL);
+ return err;
+}
+
+static void __devexit
+sfax_remove_pci(struct pci_dev *pdev)
+{
+ struct sfax_hw *card = pci_get_drvdata(pdev);
+
+ if (card)
+ release_card(card);
+ else
+ pr_debug("%s: drvdata allready removed\n", __func__);
+}
+
+static struct pci_device_id sfaxpci_ids[] __devinitdata = {
+ { PCI_VENDOR_ID_TIGERJET, PCI_DEVICE_ID_TIGERJET_100,
+ PCI_SUBVENDOR_SPEEDFAX_PYRAMID, PCI_SUB_ID_SEDLBAUER,
+ 0, 0, (unsigned long) "Pyramid Speedfax + PCI"
+ },
+ { PCI_VENDOR_ID_TIGERJET, PCI_DEVICE_ID_TIGERJET_100,
+ PCI_SUBVENDOR_SPEEDFAX_PCI, PCI_SUB_ID_SEDLBAUER,
+ 0, 0, (unsigned long) "Sedlbauer Speedfax + PCI"
+ },
+ { }
+};
+MODULE_DEVICE_TABLE(pci, sfaxpci_ids);
+
+static struct pci_driver sfaxpci_driver = {
+ .name = "speedfax+ pci",
+ .probe = sfaxpci_probe,
+ .remove = __devexit_p(sfax_remove_pci),
+ .id_table = sfaxpci_ids,
+};
+
+static int __init
+Speedfax_init(void)
+{
+ int err;
+
+ pr_notice("Sedlbauer Speedfax+ Driver Rev. %s\n",
+ SPEEDFAX_REV);
+ err = pci_register_driver(&sfaxpci_driver);
+ return err;
+}
+
+static void __exit
+Speedfax_cleanup(void)
+{
+ pci_unregister_driver(&sfaxpci_driver);
+}
+
+module_init(Speedfax_init);
+module_exit(Speedfax_cleanup);
diff --git a/drivers/isdn/hardware/mISDN/w6692.c b/drivers/isdn/hardware/mISDN/w6692.c
new file mode 100644
index 00000000000..d3f1077b709
--- /dev/null
+++ b/drivers/isdn/hardware/mISDN/w6692.c
@@ -0,0 +1,1440 @@
+/*
+ * w6692.c mISDN driver for Winbond w6692 based cards
+ *
+ * Author Karsten Keil <kkeil@suse.de>
+ * based on the w6692 I4L driver from Petr Novak <petr.novak@i.cz>
+ *
+ * Copyright 2009 by Karsten Keil <keil@isdn4linux.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/mISDNhw.h>
+#include "w6692.h"
+
+#define W6692_REV "2.0"
+
+#define DBUSY_TIMER_VALUE 80
+
+enum {
+ W6692_ASUS,
+ W6692_WINBOND,
+ W6692_USR
+};
+
+/* private data in the PCI devices list */
+struct w6692map {
+ u_int subtype;
+ char *name;
+};
+
+static const struct w6692map w6692_map[] =
+{
+ {W6692_ASUS, "Dynalink/AsusCom IS64PH"},
+ {W6692_WINBOND, "Winbond W6692"},
+ {W6692_USR, "USR W6692"}
+};
+
+#ifndef PCI_VENDOR_ID_USR
+#define PCI_VENDOR_ID_USR 0x16ec
+#define PCI_DEVICE_ID_USR_6692 0x3409
+#endif
+
+struct w6692_ch {
+ struct bchannel bch;
+ u32 addr;
+ struct timer_list timer;
+ u8 b_mode;
+};
+
+struct w6692_hw {
+ struct list_head list;
+ struct pci_dev *pdev;
+ char name[MISDN_MAX_IDLEN];
+ u32 irq;
+ u32 irqcnt;
+ u32 addr;
+ u32 fmask; /* feature mask - bit set per card nr */
+ int subtype;
+ spinlock_t lock; /* hw lock */
+ u8 imask;
+ u8 pctl;
+ u8 xaddr;
+ u8 xdata;
+ u8 state;
+ struct w6692_ch bc[2];
+ struct dchannel dch;
+ char log[64];
+};
+
+static LIST_HEAD(Cards);
+static DEFINE_RWLOCK(card_lock); /* protect Cards */
+
+static int w6692_cnt;
+static int debug;
+static u32 led;
+static u32 pots;
+
+static void
+_set_debug(struct w6692_hw *card)
+{
+ card->dch.debug = debug;
+ card->bc[0].bch.debug = debug;
+ card->bc[1].bch.debug = debug;
+}
+
+static int
+set_debug(const char *val, struct kernel_param *kp)
+{
+ int ret;
+ struct w6692_hw *card;
+
+ ret = param_set_uint(val, kp);
+ if (!ret) {
+ read_lock(&card_lock);
+ list_for_each_entry(card, &Cards, list)
+ _set_debug(card);
+ read_unlock(&card_lock);
+ }
+ return ret;
+}
+
+MODULE_AUTHOR("Karsten Keil");
+MODULE_LICENSE("GPL v2");
+MODULE_VERSION(W6692_REV);
+module_param_call(debug, set_debug, param_get_uint, &debug, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "W6692 debug mask");
+module_param(led, uint, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(led, "W6692 LED support bitmask (one bit per card)");
+module_param(pots, uint, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(pots, "W6692 POTS support bitmask (one bit per card)");
+
+static inline u8
+ReadW6692(struct w6692_hw *card, u8 offset)
+{
+ return inb(card->addr + offset);
+}
+
+static inline void
+WriteW6692(struct w6692_hw *card, u8 offset, u8 value)
+{
+ outb(value, card->addr + offset);
+}
+
+static inline u8
+ReadW6692B(struct w6692_ch *bc, u8 offset)
+{
+ return inb(bc->addr + offset);
+}
+
+static inline void
+WriteW6692B(struct w6692_ch *bc, u8 offset, u8 value)
+{
+ outb(value, bc->addr + offset);
+}
+
+static void
+enable_hwirq(struct w6692_hw *card)
+{
+ WriteW6692(card, W_IMASK, card->imask);
+}
+
+static void
+disable_hwirq(struct w6692_hw *card)
+{
+ WriteW6692(card, W_IMASK, 0xff);
+}
+
+static const char *W6692Ver[] = {"V00", "V01", "V10", "V11"};
+
+static void
+W6692Version(struct w6692_hw *card)
+{
+ int val;
+
+ val = ReadW6692(card, W_D_RBCH);
+ pr_notice("%s: Winbond W6692 version: %s\n", card->name,
+ W6692Ver[(val >> 6) & 3]);
+}
+
+static void
+w6692_led_handler(struct w6692_hw *card, int on)
+{
+ if ((!(card->fmask & led)) || card->subtype == W6692_USR)
+ return;
+ if (on) {
+ card->xdata &= 0xfb; /* LED ON */
+ WriteW6692(card, W_XDATA, card->xdata);
+ } else {
+ card->xdata |= 0x04; /* LED OFF */
+ WriteW6692(card, W_XDATA, card->xdata);
+ }
+}
+
+static void
+ph_command(struct w6692_hw *card, u8 cmd)
+{
+ pr_debug("%s: ph_command %x\n", card->name, cmd);
+ WriteW6692(card, W_CIX, cmd);
+}
+
+static void
+W6692_new_ph(struct w6692_hw *card)
+{
+ if (card->state == W_L1CMD_RST)
+ ph_command(card, W_L1CMD_DRC);
+ schedule_event(&card->dch, FLG_PHCHANGE);
+}
+
+static void
+W6692_ph_bh(struct dchannel *dch)
+{
+ struct w6692_hw *card = dch->hw;
+
+ switch (card->state) {
+ case W_L1CMD_RST:
+ dch->state = 0;
+ l1_event(dch->l1, HW_RESET_IND);
+ break;
+ case W_L1IND_CD:
+ dch->state = 3;
+ l1_event(dch->l1, HW_DEACT_CNF);
+ break;
+ case W_L1IND_DRD:
+ dch->state = 3;
+ l1_event(dch->l1, HW_DEACT_IND);
+ break;
+ case W_L1IND_CE:
+ dch->state = 4;
+ l1_event(dch->l1, HW_POWERUP_IND);
+ break;
+ case W_L1IND_LD:
+ if (dch->state <= 5) {
+ dch->state = 5;
+ l1_event(dch->l1, ANYSIGNAL);
+ } else {
+ dch->state = 8;
+ l1_event(dch->l1, LOSTFRAMING);
+ }
+ break;
+ case W_L1IND_ARD:
+ dch->state = 6;
+ l1_event(dch->l1, INFO2);
+ break;
+ case W_L1IND_AI8:
+ dch->state = 7;
+ l1_event(dch->l1, INFO4_P8);
+ break;
+ case W_L1IND_AI10:
+ dch->state = 7;
+ l1_event(dch->l1, INFO4_P10);
+ break;
+ default:
+ pr_debug("%s: TE unknown state %02x dch state %02x\n",
+ card->name, card->state, dch->state);
+ break;
+ }
+ pr_debug("%s: TE newstate %02x\n", card->name, dch->state);
+}
+
+static void
+W6692_empty_Dfifo(struct w6692_hw *card, int count)
+{
+ struct dchannel *dch = &card->dch;
+ u8 *ptr;
+
+ pr_debug("%s: empty_Dfifo %d\n", card->name, count);
+ if (!dch->rx_skb) {
+ dch->rx_skb = mI_alloc_skb(card->dch.maxlen, GFP_ATOMIC);
+ if (!dch->rx_skb) {
+ pr_info("%s: D receive out of memory\n", card->name);
+ WriteW6692(card, W_D_CMDR, W_D_CMDR_RACK);
+ return;
+ }
+ }
+ if ((dch->rx_skb->len + count) >= dch->maxlen) {
+ pr_debug("%s: empty_Dfifo overrun %d\n", card->name,
+ dch->rx_skb->len + count);
+ WriteW6692(card, W_D_CMDR, W_D_CMDR_RACK);
+ return;
+ }
+ ptr = skb_put(dch->rx_skb, count);
+ insb(card->addr + W_D_RFIFO, ptr, count);
+ WriteW6692(card, W_D_CMDR, W_D_CMDR_RACK);
+ if (debug & DEBUG_HW_DFIFO) {
+ snprintf(card->log, 63, "D-recv %s %d ",
+ card->name, count);
+ print_hex_dump_bytes(card->log, DUMP_PREFIX_OFFSET, ptr, count);
+ }
+}
+
+static void
+W6692_fill_Dfifo(struct w6692_hw *card)
+{
+ struct dchannel *dch = &card->dch;
+ int count;
+ u8 *ptr;
+ u8 cmd = W_D_CMDR_XMS;
+
+ pr_debug("%s: fill_Dfifo\n", card->name);
+ if (!dch->tx_skb)
+ return;
+ count = dch->tx_skb->len - dch->tx_idx;
+ if (count <= 0)
+ return;
+ if (count > W_D_FIFO_THRESH)
+ count = W_D_FIFO_THRESH;
+ else
+ cmd |= W_D_CMDR_XME;
+ ptr = dch->tx_skb->data + dch->tx_idx;
+ dch->tx_idx += count;
+ outsb(card->addr + W_D_XFIFO, ptr, count);
+ WriteW6692(card, W_D_CMDR, cmd);
+ if (test_and_set_bit(FLG_BUSY_TIMER, &dch->Flags)) {
+ pr_debug("%s: fill_Dfifo dbusytimer running\n", card->name);
+ del_timer(&dch->timer);
+ }
+ init_timer(&dch->timer);
+ dch->timer.expires = jiffies + ((DBUSY_TIMER_VALUE * HZ)/1000);
+ add_timer(&dch->timer);
+ if (debug & DEBUG_HW_DFIFO) {
+ snprintf(card->log, 63, "D-send %s %d ",
+ card->name, count);
+ print_hex_dump_bytes(card->log, DUMP_PREFIX_OFFSET, ptr, count);
+ }
+}
+
+static void
+d_retransmit(struct w6692_hw *card)
+{
+ struct dchannel *dch = &card->dch;
+
+ if (test_and_clear_bit(FLG_BUSY_TIMER, &dch->Flags))
+ del_timer(&dch->timer);
+#ifdef FIXME
+ if (test_and_clear_bit(FLG_L1_BUSY, &dch->Flags))
+ dchannel_sched_event(dch, D_CLEARBUSY);
+#endif
+ if (test_bit(FLG_TX_BUSY, &dch->Flags)) {
+ /* Restart frame */
+ dch->tx_idx = 0;
+ W6692_fill_Dfifo(card);
+ } else if (dch->tx_skb) { /* should not happen */
+ pr_info("%s: %s without TX_BUSY\n", card->name, __func__);
+ test_and_set_bit(FLG_TX_BUSY, &dch->Flags);
+ dch->tx_idx = 0;
+ W6692_fill_Dfifo(card);
+ } else {
+ pr_info("%s: XDU no TX_BUSY\n", card->name);
+ if (get_next_dframe(dch))
+ W6692_fill_Dfifo(card);
+ }
+}
+
+static void
+handle_rxD(struct w6692_hw *card) {
+ u8 stat;
+ int count;
+
+ stat = ReadW6692(card, W_D_RSTA);
+ if (stat & (W_D_RSTA_RDOV | W_D_RSTA_CRCE | W_D_RSTA_RMB)) {
+ if (stat & W_D_RSTA_RDOV) {
+ pr_debug("%s: D-channel RDOV\n", card->name);
+#ifdef ERROR_STATISTIC
+ card->dch.err_rx++;
+#endif
+ }
+ if (stat & W_D_RSTA_CRCE) {
+ pr_debug("%s: D-channel CRC error\n", card->name);
+#ifdef ERROR_STATISTIC
+ card->dch.err_crc++;
+#endif
+ }
+ if (stat & W_D_RSTA_RMB) {
+ pr_debug("%s: D-channel ABORT\n", card->name);
+#ifdef ERROR_STATISTIC
+ card->dch.err_rx++;
+#endif
+ }
+ if (card->dch.rx_skb)
+ dev_kfree_skb(card->dch.rx_skb);
+ card->dch.rx_skb = NULL;
+ WriteW6692(card, W_D_CMDR, W_D_CMDR_RACK | W_D_CMDR_RRST);
+ } else {
+ count = ReadW6692(card, W_D_RBCL) & (W_D_FIFO_THRESH - 1);
+ if (count == 0)
+ count = W_D_FIFO_THRESH;
+ W6692_empty_Dfifo(card, count);
+ recv_Dchannel(&card->dch);
+ }
+}
+
+static void
+handle_txD(struct w6692_hw *card) {
+ if (test_and_clear_bit(FLG_BUSY_TIMER, &card->dch.Flags))
+ del_timer(&card->dch.timer);
+ if (card->dch.tx_skb && card->dch.tx_idx < card->dch.tx_skb->len) {
+ W6692_fill_Dfifo(card);
+ } else {
+ if (card->dch.tx_skb)
+ dev_kfree_skb(card->dch.tx_skb);
+ if (get_next_dframe(&card->dch))
+ W6692_fill_Dfifo(card);
+ }
+}
+
+static void
+handle_statusD(struct w6692_hw *card)
+{
+ struct dchannel *dch = &card->dch;
+ u8 exval, v1, cir;
+
+ exval = ReadW6692(card, W_D_EXIR);
+
+ pr_debug("%s: D_EXIR %02x\n", card->name, exval);
+ if (exval & (W_D_EXI_XDUN | W_D_EXI_XCOL)) {
+ /* Transmit underrun/collision */
+ pr_debug("%s: D-channel underrun/collision\n", card->name);
+#ifdef ERROR_STATISTIC
+ dch->err_tx++;
+#endif
+ d_retransmit(card);
+ }
+ if (exval & W_D_EXI_RDOV) { /* RDOV */
+ pr_debug("%s: D-channel RDOV\n", card->name);
+ WriteW6692(card, W_D_CMDR, W_D_CMDR_RRST);
+ }
+ if (exval & W_D_EXI_TIN2) /* TIN2 - never */
+ pr_debug("%s: spurious TIN2 interrupt\n", card->name);
+ if (exval & W_D_EXI_MOC) { /* MOC - not supported */
+ v1 = ReadW6692(card, W_MOSR);
+ pr_debug("%s: spurious MOC interrupt MOSR %02x\n",
+ card->name, v1);
+ }
+ if (exval & W_D_EXI_ISC) { /* ISC - Level1 change */
+ cir = ReadW6692(card, W_CIR);
+ pr_debug("%s: ISC CIR %02X\n", card->name, cir);
+ if (cir & W_CIR_ICC) {
+ v1 = cir & W_CIR_COD_MASK;
+ pr_debug("%s: ph_state_change %x -> %x\n", card->name,
+ dch->state, v1);
+ card->state = v1;
+ if (card->fmask & led) {
+ switch (v1) {
+ case W_L1IND_AI8:
+ case W_L1IND_AI10:
+ w6692_led_handler(card, 1);
+ break;
+ default:
+ w6692_led_handler(card, 0);
+ break;
+ }
+ }
+ W6692_new_ph(card);
+ }
+ if (cir & W_CIR_SCC) {
+ v1 = ReadW6692(card, W_SQR);
+ pr_debug("%s: SCC SQR %02X\n", card->name, v1);
+ }
+ }
+ if (exval & W_D_EXI_WEXP)
+ pr_debug("%s: spurious WEXP interrupt!\n", card->name);
+ if (exval & W_D_EXI_TEXP)
+ pr_debug("%s: spurious TEXP interrupt!\n", card->name);
+}
+
+static void
+W6692_empty_Bfifo(struct w6692_ch *wch, int count)
+{
+ struct w6692_hw *card = wch->bch.hw;
+ u8 *ptr;
+
+ pr_debug("%s: empty_Bfifo %d\n", card->name, count);
+ if (unlikely(wch->bch.state == ISDN_P_NONE)) {
+ pr_debug("%s: empty_Bfifo ISDN_P_NONE\n", card->name);
+ WriteW6692B(wch, W_B_CMDR, W_B_CMDR_RACK | W_B_CMDR_RACT);
+ if (wch->bch.rx_skb)
+ skb_trim(wch->bch.rx_skb, 0);
+ return;
+ }
+ if (!wch->bch.rx_skb) {
+ wch->bch.rx_skb = mI_alloc_skb(wch->bch.maxlen, GFP_ATOMIC);
+ if (unlikely(!wch->bch.rx_skb)) {
+ pr_info("%s: B receive out of memory\n", card->name);
+ WriteW6692B(wch, W_B_CMDR, W_B_CMDR_RACK |
+ W_B_CMDR_RACT);
+ return;
+ }
+ }
+ if (wch->bch.rx_skb->len + count > wch->bch.maxlen) {
+ pr_debug("%s: empty_Bfifo incoming packet too large\n",
+ card->name);
+ WriteW6692B(wch, W_B_CMDR, W_B_CMDR_RACK | W_B_CMDR_RACT);
+ skb_trim(wch->bch.rx_skb, 0);
+ return;
+ }
+ ptr = skb_put(wch->bch.rx_skb, count);
+ insb(wch->addr + W_B_RFIFO, ptr, count);
+ WriteW6692B(wch, W_B_CMDR, W_B_CMDR_RACK | W_B_CMDR_RACT);
+ if (debug & DEBUG_HW_DFIFO) {
+ snprintf(card->log, 63, "B%1d-recv %s %d ",
+ wch->bch.nr, card->name, count);
+ print_hex_dump_bytes(card->log, DUMP_PREFIX_OFFSET, ptr, count);
+ }
+}
+
+static void
+W6692_fill_Bfifo(struct w6692_ch *wch)
+{
+ struct w6692_hw *card = wch->bch.hw;
+ int count;
+ u8 *ptr, cmd = W_B_CMDR_RACT | W_B_CMDR_XMS;
+
+ pr_debug("%s: fill Bfifo\n", card->name);
+ if (!wch->bch.tx_skb)
+ return;
+ count = wch->bch.tx_skb->len - wch->bch.tx_idx;
+ if (count <= 0)
+ return;
+ ptr = wch->bch.tx_skb->data + wch->bch.tx_idx;
+ if (count > W_B_FIFO_THRESH)
+ count = W_B_FIFO_THRESH;
+ else if (test_bit(FLG_HDLC, &wch->bch.Flags))
+ cmd |= W_B_CMDR_XME;
+
+ pr_debug("%s: fill Bfifo%d/%d\n", card->name,
+ count, wch->bch.tx_idx);
+ wch->bch.tx_idx += count;
+ outsb(wch->addr + W_B_XFIFO, ptr, count);
+ WriteW6692B(wch, W_B_CMDR, cmd);
+ if (debug & DEBUG_HW_DFIFO) {
+ snprintf(card->log, 63, "B%1d-send %s %d ",
+ wch->bch.nr, card->name, count);
+ print_hex_dump_bytes(card->log, DUMP_PREFIX_OFFSET, ptr, count);
+ }
+}
+
+static int
+setvolume(struct w6692_ch *wch, int mic, struct sk_buff *skb)
+{
+ struct w6692_hw *card = wch->bch.hw;
+ u16 *vol = (u16 *)skb->data;
+ u8 val;
+
+ if ((!(card->fmask & pots)) ||
+ !test_bit(FLG_TRANSPARENT, &wch->bch.Flags))
+ return -ENODEV;
+ if (skb->len < 2)
+ return -EINVAL;
+ if (*vol > 7)
+ return -EINVAL;
+ val = *vol & 7;
+ val = 7 - val;
+ if (mic) {
+ val <<= 3;
+ card->xaddr &= 0xc7;
+ } else {
+ card->xaddr &= 0xf8;
+ }
+ card->xaddr |= val;
+ WriteW6692(card, W_XADDR, card->xaddr);
+ return 0;
+}
+
+static int
+enable_pots(struct w6692_ch *wch)
+{
+ struct w6692_hw *card = wch->bch.hw;
+
+ if ((!(card->fmask & pots)) ||
+ !test_bit(FLG_TRANSPARENT, &wch->bch.Flags))
+ return -ENODEV;
+ wch->b_mode |= W_B_MODE_EPCM | W_B_MODE_BSW0;
+ WriteW6692B(wch, W_B_MODE, wch->b_mode);
+ WriteW6692B(wch, W_B_CMDR, W_B_CMDR_RRST | W_B_CMDR_XRST);
+ card->pctl |= ((wch->bch.nr & 2) ? W_PCTL_PCX : 0);
+ WriteW6692(card, W_PCTL, card->pctl);
+ return 0;
+}
+
+static int
+disable_pots(struct w6692_ch *wch)
+{
+ struct w6692_hw *card = wch->bch.hw;
+
+ if (!(card->fmask & pots))
+ return -ENODEV;
+ wch->b_mode &= ~(W_B_MODE_EPCM | W_B_MODE_BSW0);
+ WriteW6692B(wch, W_B_MODE, wch->b_mode);
+ WriteW6692B(wch, W_B_CMDR, W_B_CMDR_RRST | W_B_CMDR_RACT |
+ W_B_CMDR_XRST);
+ return 0;
+}
+
+static int
+w6692_mode(struct w6692_ch *wch, u32 pr)
+{
+ struct w6692_hw *card;
+
+ card = wch->bch.hw;
+ pr_debug("%s: B%d protocol %x-->%x\n", card->name,
+ wch->bch.nr, wch->bch.state, pr);
+ switch (pr) {
+ case ISDN_P_NONE:
+ if ((card->fmask & pots) && (wch->b_mode & W_B_MODE_EPCM))
+ disable_pots(wch);
+ wch->b_mode = 0;
+ mISDN_clear_bchannel(&wch->bch);
+ WriteW6692B(wch, W_B_MODE, wch->b_mode);
+ WriteW6692B(wch, W_B_CMDR, W_B_CMDR_RRST | W_B_CMDR_XRST);
+ test_and_clear_bit(FLG_HDLC, &wch->bch.Flags);
+ test_and_clear_bit(FLG_TRANSPARENT, &wch->bch.Flags);
+ break;
+ case ISDN_P_B_RAW:
+ wch->b_mode = W_B_MODE_MMS;
+ WriteW6692B(wch, W_B_MODE, wch->b_mode);
+ WriteW6692B(wch, W_B_EXIM, 0);
+ WriteW6692B(wch, W_B_CMDR, W_B_CMDR_RRST | W_B_CMDR_RACT |
+ W_B_CMDR_XRST);
+ test_and_set_bit(FLG_TRANSPARENT, &wch->bch.Flags);
+ break;
+ case ISDN_P_B_HDLC:
+ wch->b_mode = W_B_MODE_ITF;
+ WriteW6692B(wch, W_B_MODE, wch->b_mode);
+ WriteW6692B(wch, W_B_ADM1, 0xff);
+ WriteW6692B(wch, W_B_ADM2, 0xff);
+ WriteW6692B(wch, W_B_EXIM, 0);
+ WriteW6692B(wch, W_B_CMDR, W_B_CMDR_RRST | W_B_CMDR_RACT |
+ W_B_CMDR_XRST);
+ test_and_set_bit(FLG_HDLC, &wch->bch.Flags);
+ break;
+ default:
+ pr_info("%s: protocol %x not known\n", card->name, pr);
+ return -ENOPROTOOPT;
+ }
+ wch->bch.state = pr;
+ return 0;
+}
+
+static void
+send_next(struct w6692_ch *wch)
+{
+ if (wch->bch.tx_skb && wch->bch.tx_idx < wch->bch.tx_skb->len)
+ W6692_fill_Bfifo(wch);
+ else {
+ if (wch->bch.tx_skb) {
+ /* send confirm, on trans, free on hdlc. */
+ if (test_bit(FLG_TRANSPARENT, &wch->bch.Flags))
+ confirm_Bsend(&wch->bch);
+ dev_kfree_skb(wch->bch.tx_skb);
+ }
+ if (get_next_bframe(&wch->bch))
+ W6692_fill_Bfifo(wch);
+ }
+}
+
+static void
+W6692B_interrupt(struct w6692_hw *card, int ch)
+{
+ struct w6692_ch *wch = &card->bc[ch];
+ int count;
+ u8 stat, star = 0;
+
+ stat = ReadW6692B(wch, W_B_EXIR);
+ pr_debug("%s: B%d EXIR %02x\n", card->name, wch->bch.nr, stat);
+ if (stat & W_B_EXI_RME) {
+ star = ReadW6692B(wch, W_B_STAR);
+ if (star & (W_B_STAR_RDOV | W_B_STAR_CRCE | W_B_STAR_RMB)) {
+ if ((star & W_B_STAR_RDOV) &&
+ test_bit(FLG_ACTIVE, &wch->bch.Flags)) {
+ pr_debug("%s: B%d RDOV proto=%x\n", card->name,
+ wch->bch.nr, wch->bch.state);
+#ifdef ERROR_STATISTIC
+ wch->bch.err_rdo++;
+#endif
+ }
+ if (test_bit(FLG_HDLC, &wch->bch.Flags)) {
+ if (star & W_B_STAR_CRCE) {
+ pr_debug("%s: B%d CRC error\n",
+ card->name, wch->bch.nr);
+#ifdef ERROR_STATISTIC
+ wch->bch.err_crc++;
+#endif
+ }
+ if (star & W_B_STAR_RMB) {
+ pr_debug("%s: B%d message abort\n",
+ card->name, wch->bch.nr);
+#ifdef ERROR_STATISTIC
+ wch->bch.err_inv++;
+#endif
+ }
+ }
+ WriteW6692B(wch, W_B_CMDR, W_B_CMDR_RACK |
+ W_B_CMDR_RRST | W_B_CMDR_RACT);
+ if (wch->bch.rx_skb)
+ skb_trim(wch->bch.rx_skb, 0);
+ } else {
+ count = ReadW6692B(wch, W_B_RBCL) &
+ (W_B_FIFO_THRESH - 1);
+ if (count == 0)
+ count = W_B_FIFO_THRESH;
+ W6692_empty_Bfifo(wch, count);
+ recv_Bchannel(&wch->bch, 0);
+ }
+ }
+ if (stat & W_B_EXI_RMR) {
+ if (!(stat & W_B_EXI_RME))
+ star = ReadW6692B(wch, W_B_STAR);
+ if (star & W_B_STAR_RDOV) {
+ pr_debug("%s: B%d RDOV proto=%x\n", card->name,
+ wch->bch.nr, wch->bch.state);
+#ifdef ERROR_STATISTIC
+ wch->bch.err_rdo++;
+#endif
+ WriteW6692B(wch, W_B_CMDR, W_B_CMDR_RACK |
+ W_B_CMDR_RRST | W_B_CMDR_RACT);
+ } else {
+ W6692_empty_Bfifo(wch, W_B_FIFO_THRESH);
+ if (test_bit(FLG_TRANSPARENT, &wch->bch.Flags) &&
+ wch->bch.rx_skb && (wch->bch.rx_skb->len > 0))
+ recv_Bchannel(&wch->bch, 0);
+ }
+ }
+ if (stat & W_B_EXI_RDOV) {
+ /* only if it is not handled yet */
+ if (!(star & W_B_STAR_RDOV)) {
+ pr_debug("%s: B%d RDOV IRQ proto=%x\n", card->name,
+ wch->bch.nr, wch->bch.state);
+#ifdef ERROR_STATISTIC
+ wch->bch.err_rdo++;
+#endif
+ WriteW6692B(wch, W_B_CMDR, W_B_CMDR_RACK |
+ W_B_CMDR_RRST | W_B_CMDR_RACT);
+ }
+ }
+ if (stat & W_B_EXI_XFR) {
+ if (!(stat & (W_B_EXI_RME | W_B_EXI_RMR))) {
+ star = ReadW6692B(wch, W_B_STAR);
+ pr_debug("%s: B%d star %02x\n", card->name,
+ wch->bch.nr, star);
+ }
+ if (star & W_B_STAR_XDOW) {
+ pr_debug("%s: B%d XDOW proto=%x\n", card->name,
+ wch->bch.nr, wch->bch.state);
+#ifdef ERROR_STATISTIC
+ wch->bch.err_xdu++;
+#endif
+ WriteW6692B(wch, W_B_CMDR, W_B_CMDR_XRST |
+ W_B_CMDR_RACT);
+ /* resend */
+ if (wch->bch.tx_skb) {
+ if (!test_bit(FLG_TRANSPARENT, &wch->bch.Flags))
+ wch->bch.tx_idx = 0;
+ }
+ }
+ send_next(wch);
+ if (stat & W_B_EXI_XDUN)
+ return; /* handle XDOW only once */
+ }
+ if (stat & W_B_EXI_XDUN) {
+ pr_debug("%s: B%d XDUN proto=%x\n", card->name,
+ wch->bch.nr, wch->bch.state);
+#ifdef ERROR_STATISTIC
+ wch->bch.err_xdu++;
+#endif
+ WriteW6692B(wch, W_B_CMDR, W_B_CMDR_XRST | W_B_CMDR_RACT);
+ /* resend */
+ if (wch->bch.tx_skb) {
+ if (!test_bit(FLG_TRANSPARENT, &wch->bch.Flags))
+ wch->bch.tx_idx = 0;
+ }
+ send_next(wch);
+ }
+}
+
+static irqreturn_t
+w6692_irq(int intno, void *dev_id)
+{
+ struct w6692_hw *card = dev_id;
+ u8 ista;
+
+ spin_lock(&card->lock);
+ ista = ReadW6692(card, W_ISTA);
+ if ((ista | card->imask) == card->imask) {
+ /* possible a shared IRQ reqest */
+ spin_unlock(&card->lock);
+ return IRQ_NONE;
+ }
+ card->irqcnt++;
+ pr_debug("%s: ista %02x\n", card->name, ista);
+ ista &= ~card->imask;
+ if (ista & W_INT_B1_EXI)
+ W6692B_interrupt(card, 0);
+ if (ista & W_INT_B2_EXI)
+ W6692B_interrupt(card, 1);
+ if (ista & W_INT_D_RME)
+ handle_rxD(card);
+ if (ista & W_INT_D_RMR)
+ W6692_empty_Dfifo(card, W_D_FIFO_THRESH);
+ if (ista & W_INT_D_XFR)
+ handle_txD(card);
+ if (ista & W_INT_D_EXI)
+ handle_statusD(card);
+ if (ista & (W_INT_XINT0 | W_INT_XINT1)) /* XINT0/1 - never */
+ pr_debug("%s: W6692 spurious XINT!\n", card->name);
+/* End IRQ Handler */
+ spin_unlock(&card->lock);
+ return IRQ_HANDLED;
+}
+
+static void
+dbusy_timer_handler(struct dchannel *dch)
+{
+ struct w6692_hw *card = dch->hw;
+ int rbch, star;
+ u_long flags;
+
+ if (test_bit(FLG_BUSY_TIMER, &dch->Flags)) {
+ spin_lock_irqsave(&card->lock, flags);
+ rbch = ReadW6692(card, W_D_RBCH);
+ star = ReadW6692(card, W_D_STAR);
+ pr_debug("%s: D-Channel Busy RBCH %02x STAR %02x\n",
+ card->name, rbch, star);
+ if (star & W_D_STAR_XBZ) /* D-Channel Busy */
+ test_and_set_bit(FLG_L1_BUSY, &dch->Flags);
+ else {
+ /* discard frame; reset transceiver */
+ test_and_clear_bit(FLG_BUSY_TIMER, &dch->Flags);
+ if (dch->tx_idx)
+ dch->tx_idx = 0;
+ else
+ pr_info("%s: W6692 D-Channel Busy no tx_idx\n",
+ card->name);
+ /* Transmitter reset */
+ WriteW6692(card, W_D_CMDR, W_D_CMDR_XRST);
+ }
+ spin_unlock_irqrestore(&card->lock, flags);
+ }
+}
+
+void initW6692(struct w6692_hw *card)
+{
+ u8 val;
+
+ card->dch.timer.function = (void *)dbusy_timer_handler;
+ card->dch.timer.data = (u_long)&card->dch;
+ init_timer(&card->dch.timer);
+ w6692_mode(&card->bc[0], ISDN_P_NONE);
+ w6692_mode(&card->bc[1], ISDN_P_NONE);
+ WriteW6692(card, W_D_CTL, 0x00);
+ disable_hwirq(card);
+ WriteW6692(card, W_D_SAM, 0xff);
+ WriteW6692(card, W_D_TAM, 0xff);
+ WriteW6692(card, W_D_MODE, W_D_MODE_RACT);
+ card->state = W_L1CMD_RST;
+ ph_command(card, W_L1CMD_RST);
+ ph_command(card, W_L1CMD_ECK);
+ /* enable all IRQ but extern */
+ card->imask = 0x18;
+ WriteW6692(card, W_D_EXIM, 0x00);
+ WriteW6692B(&card->bc[0], W_B_EXIM, 0);
+ WriteW6692B(&card->bc[1], W_B_EXIM, 0);
+ /* Reset D-chan receiver and transmitter */
+ WriteW6692(card, W_D_CMDR, W_D_CMDR_RRST | W_D_CMDR_XRST);
+ /* Reset B-chan receiver and transmitter */
+ WriteW6692B(&card->bc[0], W_B_CMDR, W_B_CMDR_RRST | W_B_CMDR_XRST);
+ WriteW6692B(&card->bc[1], W_B_CMDR, W_B_CMDR_RRST | W_B_CMDR_XRST);
+ /* enable peripheral */
+ if (card->subtype == W6692_USR) {
+ /* seems that USR implemented some power control features
+ * Pin 79 is connected to the oscilator circuit so we
+ * have to handle it here
+ */
+ card->pctl = 0x80;
+ card->xdata = 0;
+ WriteW6692(card, W_PCTL, card->pctl);
+ WriteW6692(card, W_XDATA, card->xdata);
+ } else {
+ card->pctl = W_PCTL_OE5 | W_PCTL_OE4 | W_PCTL_OE2 |
+ W_PCTL_OE1 | W_PCTL_OE0;
+ card->xaddr = 0x00;/* all sw off */
+ if (card->fmask & pots)
+ card->xdata |= 0x06; /* POWER UP/ LED OFF / ALAW */
+ if (card->fmask & led)
+ card->xdata |= 0x04; /* LED OFF */
+ if ((card->fmask & pots) || (card->fmask & led)) {
+ WriteW6692(card, W_PCTL, card->pctl);
+ WriteW6692(card, W_XADDR, card->xaddr);
+ WriteW6692(card, W_XDATA, card->xdata);
+ val = ReadW6692(card, W_XADDR);
+ if (debug & DEBUG_HW)
+ pr_notice("%s: W_XADDR=%02x\n",
+ card->name, val);
+ }
+ }
+}
+
+static void
+reset_w6692(struct w6692_hw *card)
+{
+ WriteW6692(card, W_D_CTL, W_D_CTL_SRST);
+ mdelay(10);
+ WriteW6692(card, W_D_CTL, 0);
+}
+
+static int
+init_card(struct w6692_hw *card)
+{
+ int cnt = 3;
+ u_long flags;
+
+ spin_lock_irqsave(&card->lock, flags);
+ disable_hwirq(card);
+ spin_unlock_irqrestore(&card->lock, flags);
+ if (request_irq(card->irq, w6692_irq, IRQF_SHARED, card->name, card)) {
+ pr_info("%s: couldn't get interrupt %d\n", card->name,
+ card->irq);
+ return -EIO;
+ }
+ while (cnt--) {
+ spin_lock_irqsave(&card->lock, flags);
+ initW6692(card);
+ enable_hwirq(card);
+ spin_unlock_irqrestore(&card->lock, flags);
+ /* Timeout 10ms */
+ msleep_interruptible(10);
+ if (debug & DEBUG_HW)
+ pr_notice("%s: IRQ %d count %d\n", card->name,
+ card->irq, card->irqcnt);
+ if (!card->irqcnt) {
+ pr_info("%s: IRQ(%d) getting no IRQs during init %d\n",
+ card->name, card->irq, 3 - cnt);
+ reset_w6692(card);
+ } else
+ return 0;
+ }
+ free_irq(card->irq, card);
+ return -EIO;
+}
+
+static int
+w6692_l2l1B(struct mISDNchannel *ch, struct sk_buff *skb)
+{
+ struct bchannel *bch = container_of(ch, struct bchannel, ch);
+ struct w6692_ch *bc = container_of(bch, struct w6692_ch, bch);
+ struct w6692_hw *card = bch->hw;
+ int ret = -EINVAL;
+ struct mISDNhead *hh = mISDN_HEAD_P(skb);
+ u32 id;
+ u_long flags;
+
+ switch (hh->prim) {
+ case PH_DATA_REQ:
+ spin_lock_irqsave(&card->lock, flags);
+ ret = bchannel_senddata(bch, skb);
+ if (ret > 0) { /* direct TX */
+ id = hh->id; /* skb can be freed */
+ ret = 0;
+ W6692_fill_Bfifo(bc);
+ spin_unlock_irqrestore(&card->lock, flags);
+ if (!test_bit(FLG_TRANSPARENT, &bch->Flags))
+ queue_ch_frame(ch, PH_DATA_CNF, id, NULL);
+ } else
+ spin_unlock_irqrestore(&card->lock, flags);
+ return ret;
+ case PH_ACTIVATE_REQ:
+ spin_lock_irqsave(&card->lock, flags);
+ if (!test_and_set_bit(FLG_ACTIVE, &bch->Flags))
+ ret = w6692_mode(bc, ch->protocol);
+ else
+ ret = 0;
+ spin_unlock_irqrestore(&card->lock, flags);
+ if (!ret)
+ _queue_data(ch, PH_ACTIVATE_IND, MISDN_ID_ANY, 0,
+ NULL, GFP_KERNEL);
+ break;
+ case PH_DEACTIVATE_REQ:
+ spin_lock_irqsave(&card->lock, flags);
+ mISDN_clear_bchannel(bch);
+ w6692_mode(bc, ISDN_P_NONE);
+ spin_unlock_irqrestore(&card->lock, flags);
+ _queue_data(ch, PH_DEACTIVATE_IND, MISDN_ID_ANY, 0,
+ NULL, GFP_KERNEL);
+ ret = 0;
+ break;
+ default:
+ pr_info("%s: %s unknown prim(%x,%x)\n",
+ card->name, __func__, hh->prim, hh->id);
+ ret = -EINVAL;
+ }
+ if (!ret)
+ dev_kfree_skb(skb);
+ return ret;
+}
+
+static int
+channel_bctrl(struct bchannel *bch, struct mISDN_ctrl_req *cq)
+{
+ int ret = 0;
+
+ switch (cq->op) {
+ case MISDN_CTRL_GETOP:
+ cq->op = 0;
+ break;
+ /* Nothing implemented yet */
+ case MISDN_CTRL_FILL_EMPTY:
+ default:
+ pr_info("%s: unknown Op %x\n", __func__, cq->op);
+ ret = -EINVAL;
+ break;
+ }
+ return ret;
+}
+
+static int
+open_bchannel(struct w6692_hw *card, struct channel_req *rq)
+{
+ struct bchannel *bch;
+
+ if (rq->adr.channel > 2)
+ return -EINVAL;
+ if (rq->protocol == ISDN_P_NONE)
+ return -EINVAL;
+ bch = &card->bc[rq->adr.channel - 1].bch;
+ if (test_and_set_bit(FLG_OPEN, &bch->Flags))
+ return -EBUSY; /* b-channel can be only open once */
+ test_and_clear_bit(FLG_FILLEMPTY, &bch->Flags);
+ bch->ch.protocol = rq->protocol;
+ rq->ch = &bch->ch;
+ return 0;
+}
+
+static int
+channel_ctrl(struct w6692_hw *card, struct mISDN_ctrl_req *cq)
+{
+ int ret = 0;
+
+ switch (cq->op) {
+ case MISDN_CTRL_GETOP:
+ cq->op = 0;
+ break;
+ default:
+ pr_info("%s: unknown CTRL OP %x\n", card->name, cq->op);
+ ret = -EINVAL;
+ break;
+ }
+ return ret;
+}
+
+static int
+w6692_bctrl(struct mISDNchannel *ch, u32 cmd, void *arg)
+{
+ struct bchannel *bch = container_of(ch, struct bchannel, ch);
+ struct w6692_ch *bc = container_of(bch, struct w6692_ch, bch);
+ struct w6692_hw *card = bch->hw;
+ int ret = -EINVAL;
+ u_long flags;
+
+ pr_debug("%s: %s cmd:%x %p\n", card->name, __func__, cmd, arg);
+ switch (cmd) {
+ case CLOSE_CHANNEL:
+ test_and_clear_bit(FLG_OPEN, &bch->Flags);
+ if (test_bit(FLG_ACTIVE, &bch->Flags)) {
+ spin_lock_irqsave(&card->lock, flags);
+ mISDN_freebchannel(bch);
+ w6692_mode(bc, ISDN_P_NONE);
+ spin_unlock_irqrestore(&card->lock, flags);
+ } else {
+ skb_queue_purge(&bch->rqueue);
+ bch->rcount = 0;
+ }
+ ch->protocol = ISDN_P_NONE;
+ ch->peer = NULL;
+ module_put(THIS_MODULE);
+ ret = 0;
+ break;
+ case CONTROL_CHANNEL:
+ ret = channel_bctrl(bch, arg);
+ break;
+ default:
+ pr_info("%s: %s unknown prim(%x)\n",
+ card->name, __func__, cmd);
+ }
+ return ret;
+}
+
+static int
+w6692_l2l1D(struct mISDNchannel *ch, struct sk_buff *skb)
+{
+ struct mISDNdevice *dev = container_of(ch, struct mISDNdevice, D);
+ struct dchannel *dch = container_of(dev, struct dchannel, dev);
+ struct w6692_hw *card = container_of(dch, struct w6692_hw, dch);
+ int ret = -EINVAL;
+ struct mISDNhead *hh = mISDN_HEAD_P(skb);
+ u32 id;
+ u_long flags;
+
+ switch (hh->prim) {
+ case PH_DATA_REQ:
+ spin_lock_irqsave(&card->lock, flags);
+ ret = dchannel_senddata(dch, skb);
+ if (ret > 0) { /* direct TX */
+ id = hh->id; /* skb can be freed */
+ W6692_fill_Dfifo(card);
+ ret = 0;
+ spin_unlock_irqrestore(&card->lock, flags);
+ queue_ch_frame(ch, PH_DATA_CNF, id, NULL);
+ } else
+ spin_unlock_irqrestore(&card->lock, flags);
+ return ret;
+ case PH_ACTIVATE_REQ:
+ ret = l1_event(dch->l1, hh->prim);
+ break;
+ case PH_DEACTIVATE_REQ:
+ test_and_clear_bit(FLG_L2_ACTIVATED, &dch->Flags);
+ ret = l1_event(dch->l1, hh->prim);
+ break;
+ }
+
+ if (!ret)
+ dev_kfree_skb(skb);
+ return ret;
+}
+
+static int
+w6692_l1callback(struct dchannel *dch, u32 cmd)
+{
+ struct w6692_hw *card = container_of(dch, struct w6692_hw, dch);
+ u_long flags;
+
+ pr_debug("%s: cmd(%x) state(%02x)\n", card->name, cmd, card->state);
+ switch (cmd) {
+ case INFO3_P8:
+ spin_lock_irqsave(&card->lock, flags);
+ ph_command(card, W_L1CMD_AR8);
+ spin_unlock_irqrestore(&card->lock, flags);
+ break;
+ case INFO3_P10:
+ spin_lock_irqsave(&card->lock, flags);
+ ph_command(card, W_L1CMD_AR10);
+ spin_unlock_irqrestore(&card->lock, flags);
+ break;
+ case HW_RESET_REQ:
+ spin_lock_irqsave(&card->lock, flags);
+ if (card->state != W_L1IND_DRD)
+ ph_command(card, W_L1CMD_RST);
+ ph_command(card, W_L1CMD_ECK);
+ spin_unlock_irqrestore(&card->lock, flags);
+ break;
+ case HW_DEACT_REQ:
+ skb_queue_purge(&dch->squeue);
+ if (dch->tx_skb) {
+ dev_kfree_skb(dch->tx_skb);
+ dch->tx_skb = NULL;
+ }
+ dch->tx_idx = 0;
+ if (dch->rx_skb) {
+ dev_kfree_skb(dch->rx_skb);
+ dch->rx_skb = NULL;
+ }
+ test_and_clear_bit(FLG_TX_BUSY, &dch->Flags);
+ if (test_and_clear_bit(FLG_BUSY_TIMER, &dch->Flags))
+ del_timer(&dch->timer);
+ break;
+ case HW_POWERUP_REQ:
+ spin_lock_irqsave(&card->lock, flags);
+ ph_command(card, W_L1CMD_ECK);
+ spin_unlock_irqrestore(&card->lock, flags);
+ break;
+ case PH_ACTIVATE_IND:
+ test_and_set_bit(FLG_ACTIVE, &dch->Flags);
+ _queue_data(&dch->dev.D, cmd, MISDN_ID_ANY, 0, NULL,
+ GFP_ATOMIC);
+ break;
+ case PH_DEACTIVATE_IND:
+ test_and_clear_bit(FLG_ACTIVE, &dch->Flags);
+ _queue_data(&dch->dev.D, cmd, MISDN_ID_ANY, 0, NULL,
+ GFP_ATOMIC);
+ break;
+ default:
+ pr_debug("%s: %s unknown command %x\n", card->name,
+ __func__, cmd);
+ return -1;
+ }
+ return 0;
+}
+
+static int
+open_dchannel(struct w6692_hw *card, struct channel_req *rq)
+{
+ pr_debug("%s: %s dev(%d) open from %p\n", card->name, __func__,
+ card->dch.dev.id, __builtin_return_address(1));
+ if (rq->protocol != ISDN_P_TE_S0)
+ return -EINVAL;
+ if (rq->adr.channel == 1)
+ /* E-Channel not supported */
+ return -EINVAL;
+ rq->ch = &card->dch.dev.D;
+ rq->ch->protocol = rq->protocol;
+ if (card->dch.state == 7)
+ _queue_data(rq->ch, PH_ACTIVATE_IND, MISDN_ID_ANY,
+ 0, NULL, GFP_KERNEL);
+ return 0;
+}
+
+static int
+w6692_dctrl(struct mISDNchannel *ch, u32 cmd, void *arg)
+{
+ struct mISDNdevice *dev = container_of(ch, struct mISDNdevice, D);
+ struct dchannel *dch = container_of(dev, struct dchannel, dev);
+ struct w6692_hw *card = container_of(dch, struct w6692_hw, dch);
+ struct channel_req *rq;
+ int err = 0;
+
+ pr_debug("%s: DCTRL: %x %p\n", card->name, cmd, arg);
+ switch (cmd) {
+ case OPEN_CHANNEL:
+ rq = arg;
+ if (rq->protocol == ISDN_P_TE_S0)
+ err = open_dchannel(card, rq);
+ else
+ err = open_bchannel(card, rq);
+ if (err)
+ break;
+ if (!try_module_get(THIS_MODULE))
+ pr_info("%s: cannot get module\n", card->name);
+ break;
+ case CLOSE_CHANNEL:
+ pr_debug("%s: dev(%d) close from %p\n", card->name,
+ dch->dev.id, __builtin_return_address(0));
+ module_put(THIS_MODULE);
+ break;
+ case CONTROL_CHANNEL:
+ err = channel_ctrl(card, arg);
+ break;
+ default:
+ pr_debug("%s: unknown DCTRL command %x\n", card->name, cmd);
+ return -EINVAL;
+ }
+ return err;
+}
+
+static int
+setup_w6692(struct w6692_hw *card)
+{
+ u32 val;
+
+ if (!request_region(card->addr, 256, card->name)) {
+ pr_info("%s: config port %x-%x already in use\n", card->name,
+ card->addr, card->addr + 255);
+ return -EIO;
+ }
+ W6692Version(card);
+ card->bc[0].addr = card->addr;
+ card->bc[1].addr = card->addr + 0x40;
+ val = ReadW6692(card, W_ISTA);
+ if (debug & DEBUG_HW)
+ pr_notice("%s ISTA=%02x\n", card->name, val);
+ val = ReadW6692(card, W_IMASK);
+ if (debug & DEBUG_HW)
+ pr_notice("%s IMASK=%02x\n", card->name, val);
+ val = ReadW6692(card, W_D_EXIR);
+ if (debug & DEBUG_HW)
+ pr_notice("%s D_EXIR=%02x\n", card->name, val);
+ val = ReadW6692(card, W_D_EXIM);
+ if (debug & DEBUG_HW)
+ pr_notice("%s D_EXIM=%02x\n", card->name, val);
+ val = ReadW6692(card, W_D_RSTA);
+ if (debug & DEBUG_HW)
+ pr_notice("%s D_RSTA=%02x\n", card->name, val);
+ return 0;
+}
+
+static void
+release_card(struct w6692_hw *card)
+{
+ u_long flags;
+
+ spin_lock_irqsave(&card->lock, flags);
+ disable_hwirq(card);
+ w6692_mode(&card->bc[0], ISDN_P_NONE);
+ w6692_mode(&card->bc[1], ISDN_P_NONE);
+ if ((card->fmask & led) || card->subtype == W6692_USR) {
+ card->xdata |= 0x04; /* LED OFF */
+ WriteW6692(card, W_XDATA, card->xdata);
+ }
+ spin_unlock_irqrestore(&card->lock, flags);
+ free_irq(card->irq, card);
+ l1_event(card->dch.l1, CLOSE_CHANNEL);
+ mISDN_unregister_device(&card->dch.dev);
+ release_region(card->addr, 256);
+ mISDN_freebchannel(&card->bc[1].bch);
+ mISDN_freebchannel(&card->bc[0].bch);
+ mISDN_freedchannel(&card->dch);
+ write_lock_irqsave(&card_lock, flags);
+ list_del(&card->list);
+ write_unlock_irqrestore(&card_lock, flags);
+ pci_disable_device(card->pdev);
+ pci_set_drvdata(card->pdev, NULL);
+ kfree(card);
+}
+
+static int
+setup_instance(struct w6692_hw *card)
+{
+ int i, err;
+ u_long flags;
+
+ snprintf(card->name, MISDN_MAX_IDLEN - 1, "w6692.%d", w6692_cnt + 1);
+ write_lock_irqsave(&card_lock, flags);
+ list_add_tail(&card->list, &Cards);
+ write_unlock_irqrestore(&card_lock, flags);
+ card->fmask = (1 << w6692_cnt);
+ _set_debug(card);
+ spin_lock_init(&card->lock);
+ mISDN_initdchannel(&card->dch, MAX_DFRAME_LEN_L1, W6692_ph_bh);
+ card->dch.dev.Dprotocols = (1 << ISDN_P_TE_S0);
+ card->dch.dev.D.send = w6692_l2l1D;
+ card->dch.dev.D.ctrl = w6692_dctrl;
+ card->dch.dev.Bprotocols = (1 << (ISDN_P_B_RAW & ISDN_P_B_MASK)) |
+ (1 << (ISDN_P_B_HDLC & ISDN_P_B_MASK));
+ card->dch.hw = card;
+ card->dch.dev.nrbchan = 2;
+ for (i = 0; i < 2; i++) {
+ mISDN_initbchannel(&card->bc[i].bch, MAX_DATA_MEM);
+ card->bc[i].bch.hw = card;
+ card->bc[i].bch.nr = i + 1;
+ card->bc[i].bch.ch.nr = i + 1;
+ card->bc[i].bch.ch.send = w6692_l2l1B;
+ card->bc[i].bch.ch.ctrl = w6692_bctrl;
+ set_channelmap(i + 1, card->dch.dev.channelmap);
+ list_add(&card->bc[i].bch.ch.list, &card->dch.dev.bchannels);
+ }
+ err = setup_w6692(card);
+ if (err)
+ goto error_setup;
+ err = mISDN_register_device(&card->dch.dev, &card->pdev->dev,
+ card->name);
+ if (err)
+ goto error_reg;
+ err = init_card(card);
+ if (err)
+ goto error_init;
+ err = create_l1(&card->dch, w6692_l1callback);
+ if (!err) {
+ w6692_cnt++;
+ pr_notice("W6692 %d cards installed\n", w6692_cnt);
+ return 0;
+ }
+
+ free_irq(card->irq, card);
+error_init:
+ mISDN_unregister_device(&card->dch.dev);
+error_reg:
+ release_region(card->addr, 256);
+error_setup:
+ mISDN_freebchannel(&card->bc[1].bch);
+ mISDN_freebchannel(&card->bc[0].bch);
+ mISDN_freedchannel(&card->dch);
+ write_lock_irqsave(&card_lock, flags);
+ list_del(&card->list);
+ write_unlock_irqrestore(&card_lock, flags);
+ kfree(card);
+ return err;
+}
+
+static int __devinit
+w6692_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+ int err = -ENOMEM;
+ struct w6692_hw *card;
+ struct w6692map *m = (struct w6692map *)ent->driver_data;
+
+ card = kzalloc(sizeof(struct w6692_hw), GFP_KERNEL);
+ if (!card) {
+ pr_info("No kmem for w6692 card\n");
+ return err;
+ }
+ card->pdev = pdev;
+ card->subtype = m->subtype;
+ err = pci_enable_device(pdev);
+ if (err) {
+ kfree(card);
+ return err;
+ }
+
+ printk(KERN_INFO "mISDN_w6692: found adapter %s at %s\n",
+ m->name, pci_name(pdev));
+
+ card->addr = pci_resource_start(pdev, 1);
+ card->irq = pdev->irq;
+ pci_set_drvdata(pdev, card);
+ err = setup_instance(card);
+ if (err)
+ pci_set_drvdata(pdev, NULL);
+ return err;
+}
+
+static void __devexit
+w6692_remove_pci(struct pci_dev *pdev)
+{
+ struct w6692_hw *card = pci_get_drvdata(pdev);
+
+ if (card)
+ release_card(card);
+ else
+ if (debug)
+ pr_notice("%s: drvdata allready removed\n", __func__);
+}
+
+static struct pci_device_id w6692_ids[] = {
+ { PCI_VENDOR_ID_DYNALINK, PCI_DEVICE_ID_DYNALINK_IS64PH,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, (ulong)&w6692_map[0]},
+ { PCI_VENDOR_ID_WINBOND2, PCI_DEVICE_ID_WINBOND2_6692,
+ PCI_VENDOR_ID_USR, PCI_DEVICE_ID_USR_6692, 0, 0,
+ (ulong)&w6692_map[2]},
+ { PCI_VENDOR_ID_WINBOND2, PCI_DEVICE_ID_WINBOND2_6692,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, (ulong)&w6692_map[1]},
+ { }
+};
+MODULE_DEVICE_TABLE(pci, w6692_ids);
+
+static struct pci_driver w6692_driver = {
+ .name = "w6692",
+ .probe = w6692_probe,
+ .remove = __devexit_p(w6692_remove_pci),
+ .id_table = w6692_ids,
+};
+
+static int __init w6692_init(void)
+{
+ int err;
+
+ pr_notice("Winbond W6692 PCI driver Rev. %s\n", W6692_REV);
+
+ err = pci_register_driver(&w6692_driver);
+ return err;
+}
+
+static void __exit w6692_cleanup(void)
+{
+ pci_unregister_driver(&w6692_driver);
+}
+
+module_init(w6692_init);
+module_exit(w6692_cleanup);
diff --git a/drivers/isdn/hardware/mISDN/w6692.h b/drivers/isdn/hardware/mISDN/w6692.h
new file mode 100644
index 00000000000..f95697757fd
--- /dev/null
+++ b/drivers/isdn/hardware/mISDN/w6692.h
@@ -0,0 +1,190 @@
+/*
+ * Winbond W6692 specific defines
+ *
+ * Author Karsten Keil <keil@isdn4linux.de>
+ * based on the w6692 I4L driver from Petr Novak <petr.novak@i.cz>
+ *
+ * Copyright 2009 by Karsten Keil <keil@isdn4linux.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+/* Specifications of W6692 registers */
+
+#define W_D_RFIFO 0x00 /* R */
+#define W_D_XFIFO 0x04 /* W */
+#define W_D_CMDR 0x08 /* W */
+#define W_D_MODE 0x0c /* R/W */
+#define W_D_TIMR 0x10 /* R/W */
+#define W_ISTA 0x14 /* R_clr */
+#define W_IMASK 0x18 /* R/W */
+#define W_D_EXIR 0x1c /* R_clr */
+#define W_D_EXIM 0x20 /* R/W */
+#define W_D_STAR 0x24 /* R */
+#define W_D_RSTA 0x28 /* R */
+#define W_D_SAM 0x2c /* R/W */
+#define W_D_SAP1 0x30 /* R/W */
+#define W_D_SAP2 0x34 /* R/W */
+#define W_D_TAM 0x38 /* R/W */
+#define W_D_TEI1 0x3c /* R/W */
+#define W_D_TEI2 0x40 /* R/W */
+#define W_D_RBCH 0x44 /* R */
+#define W_D_RBCL 0x48 /* R */
+#define W_TIMR2 0x4c /* W */
+#define W_L1_RC 0x50 /* R/W */
+#define W_D_CTL 0x54 /* R/W */
+#define W_CIR 0x58 /* R */
+#define W_CIX 0x5c /* W */
+#define W_SQR 0x60 /* R */
+#define W_SQX 0x64 /* W */
+#define W_PCTL 0x68 /* R/W */
+#define W_MOR 0x6c /* R */
+#define W_MOX 0x70 /* R/W */
+#define W_MOSR 0x74 /* R_clr */
+#define W_MOCR 0x78 /* R/W */
+#define W_GCR 0x7c /* R/W */
+
+#define W_B_RFIFO 0x80 /* R */
+#define W_B_XFIFO 0x84 /* W */
+#define W_B_CMDR 0x88 /* W */
+#define W_B_MODE 0x8c /* R/W */
+#define W_B_EXIR 0x90 /* R_clr */
+#define W_B_EXIM 0x94 /* R/W */
+#define W_B_STAR 0x98 /* R */
+#define W_B_ADM1 0x9c /* R/W */
+#define W_B_ADM2 0xa0 /* R/W */
+#define W_B_ADR1 0xa4 /* R/W */
+#define W_B_ADR2 0xa8 /* R/W */
+#define W_B_RBCL 0xac /* R */
+#define W_B_RBCH 0xb0 /* R */
+
+#define W_XADDR 0xf4 /* R/W */
+#define W_XDATA 0xf8 /* R/W */
+#define W_EPCTL 0xfc /* W */
+
+/* W6692 register bits */
+
+#define W_D_CMDR_XRST 0x01
+#define W_D_CMDR_XME 0x02
+#define W_D_CMDR_XMS 0x08
+#define W_D_CMDR_STT 0x10
+#define W_D_CMDR_RRST 0x40
+#define W_D_CMDR_RACK 0x80
+
+#define W_D_MODE_RLP 0x01
+#define W_D_MODE_DLP 0x02
+#define W_D_MODE_MFD 0x04
+#define W_D_MODE_TEE 0x08
+#define W_D_MODE_TMS 0x10
+#define W_D_MODE_RACT 0x40
+#define W_D_MODE_MMS 0x80
+
+#define W_INT_B2_EXI 0x01
+#define W_INT_B1_EXI 0x02
+#define W_INT_D_EXI 0x04
+#define W_INT_XINT0 0x08
+#define W_INT_XINT1 0x10
+#define W_INT_D_XFR 0x20
+#define W_INT_D_RME 0x40
+#define W_INT_D_RMR 0x80
+
+#define W_D_EXI_WEXP 0x01
+#define W_D_EXI_TEXP 0x02
+#define W_D_EXI_ISC 0x04
+#define W_D_EXI_MOC 0x08
+#define W_D_EXI_TIN2 0x10
+#define W_D_EXI_XCOL 0x20
+#define W_D_EXI_XDUN 0x40
+#define W_D_EXI_RDOV 0x80
+
+#define W_D_STAR_DRDY 0x10
+#define W_D_STAR_XBZ 0x20
+#define W_D_STAR_XDOW 0x80
+
+#define W_D_RSTA_RMB 0x10
+#define W_D_RSTA_CRCE 0x20
+#define W_D_RSTA_RDOV 0x40
+
+#define W_D_CTL_SRST 0x20
+
+#define W_CIR_SCC 0x80
+#define W_CIR_ICC 0x40
+#define W_CIR_COD_MASK 0x0f
+
+#define W_PCTL_PCX 0x01
+#define W_PCTL_XMODE 0x02
+#define W_PCTL_OE0 0x04
+#define W_PCTL_OE1 0x08
+#define W_PCTL_OE2 0x10
+#define W_PCTL_OE3 0x20
+#define W_PCTL_OE4 0x40
+#define W_PCTL_OE5 0x80
+
+#define W_B_CMDR_XRST 0x01
+#define W_B_CMDR_XME 0x02
+#define W_B_CMDR_XMS 0x04
+#define W_B_CMDR_RACT 0x20
+#define W_B_CMDR_RRST 0x40
+#define W_B_CMDR_RACK 0x80
+
+#define W_B_MODE_FTS0 0x01
+#define W_B_MODE_FTS1 0x02
+#define W_B_MODE_SW56 0x04
+#define W_B_MODE_BSW0 0x08
+#define W_B_MODE_BSW1 0x10
+#define W_B_MODE_EPCM 0x20
+#define W_B_MODE_ITF 0x40
+#define W_B_MODE_MMS 0x80
+
+#define W_B_EXI_XDUN 0x01
+#define W_B_EXI_XFR 0x02
+#define W_B_EXI_RDOV 0x10
+#define W_B_EXI_RME 0x20
+#define W_B_EXI_RMR 0x40
+
+#define W_B_STAR_XBZ 0x01
+#define W_B_STAR_XDOW 0x04
+#define W_B_STAR_RMB 0x10
+#define W_B_STAR_CRCE 0x20
+#define W_B_STAR_RDOV 0x40
+
+#define W_B_RBCH_LOV 0x20
+
+/* W6692 Layer1 commands */
+
+#define W_L1CMD_ECK 0x00
+#define W_L1CMD_RST 0x01
+#define W_L1CMD_SCP 0x04
+#define W_L1CMD_SSP 0x02
+#define W_L1CMD_AR8 0x08
+#define W_L1CMD_AR10 0x09
+#define W_L1CMD_EAL 0x0a
+#define W_L1CMD_DRC 0x0f
+
+/* W6692 Layer1 indications */
+
+#define W_L1IND_CE 0x07
+#define W_L1IND_DRD 0x00
+#define W_L1IND_LD 0x04
+#define W_L1IND_ARD 0x08
+#define W_L1IND_TI 0x0a
+#define W_L1IND_ATI 0x0b
+#define W_L1IND_AI8 0x0c
+#define W_L1IND_AI10 0x0d
+#define W_L1IND_CD 0x0f
+
+/* FIFO thresholds */
+#define W_D_FIFO_THRESH 64
+#define W_B_FIFO_THRESH 64
diff --git a/drivers/isdn/hisax/Kconfig b/drivers/isdn/hisax/Kconfig
index 7832d8ba8e4..3464ebc4cdb 100644
--- a/drivers/isdn/hisax/Kconfig
+++ b/drivers/isdn/hisax/Kconfig
@@ -391,6 +391,7 @@ comment "HiSax sub driver modules"
config HISAX_ST5481
tristate "ST5481 USB ISDN modem (EXPERIMENTAL)"
depends on USB && EXPERIMENTAL
+ select ISDN_HDLC
select CRC_CCITT
select BITREVERSE
help
@@ -418,11 +419,6 @@ config HISAX_FRITZ_PCIPNP
(the latter also needs you to select "ISA Plug and Play support"
from the menu "Plug and Play configuration")
-config HISAX_HDLC
- bool
- depends on HISAX_ST5481
- default y
-
config HISAX_AVM_A1_PCMCIA
bool
depends on HISAX_AVM_A1_CS
diff --git a/drivers/isdn/hisax/Makefile b/drivers/isdn/hisax/Makefile
index c7a3794bdae..ab638b083df 100644
--- a/drivers/isdn/hisax/Makefile
+++ b/drivers/isdn/hisax/Makefile
@@ -16,10 +16,6 @@ obj-$(CONFIG_HISAX_HFCUSB) += hfc_usb.o
obj-$(CONFIG_HISAX_HFC4S8S) += hfc4s8s_l1.o
obj-$(CONFIG_HISAX_FRITZ_PCIPNP) += hisax_isac.o hisax_fcpcipnp.o
-ifdef CONFIG_HISAX_HDLC
-obj-$(CONFIG_ISDN_DRV_HISAX) += isdnhdlc.o
-endif
-
# Multipart objects.
hisax_st5481-y := st5481_init.o st5481_usb.o st5481_d.o \
diff --git a/drivers/isdn/hisax/amd7930_fn.c b/drivers/isdn/hisax/amd7930_fn.c
index 341faf58a65..bf526a7a63a 100644
--- a/drivers/isdn/hisax/amd7930_fn.c
+++ b/drivers/isdn/hisax/amd7930_fn.c
@@ -238,8 +238,6 @@ Amd7930_bh(struct work_struct *work)
container_of(work, struct IsdnCardState, tqueue);
struct PStack *stptr;
- if (!cs)
- return;
if (test_and_clear_bit(D_CLEARBUSY, &cs->event)) {
if (cs->debug)
debugl1(cs, "Amd7930: bh, D-Channel Busy cleared");
diff --git a/drivers/isdn/hisax/callc.c b/drivers/isdn/hisax/callc.c
index 025a20d487c..475b1a02000 100644
--- a/drivers/isdn/hisax/callc.c
+++ b/drivers/isdn/hisax/callc.c
@@ -833,8 +833,6 @@ static struct FsmNode fnlist[] __initdata =
};
/* *INDENT-ON* */
-#define FNCOUNT (sizeof(fnlist)/sizeof(struct FsmNode))
-
int __init
CallcNew(void)
{
@@ -842,7 +840,7 @@ CallcNew(void)
callcfsm.event_count = EVENT_COUNT;
callcfsm.strEvent = strEvent;
callcfsm.strState = strState;
- return FsmNew(&callcfsm, fnlist, FNCOUNT);
+ return FsmNew(&callcfsm, fnlist, ARRAY_SIZE(fnlist));
}
void
diff --git a/drivers/isdn/hisax/hfc_pci.c b/drivers/isdn/hisax/hfc_pci.c
index 3d337d924c2..d110a77940a 100644
--- a/drivers/isdn/hisax/hfc_pci.c
+++ b/drivers/isdn/hisax/hfc_pci.c
@@ -1506,8 +1506,6 @@ hfcpci_bh(struct work_struct *work)
u_long flags;
// struct PStack *stptr;
- if (!cs)
- return;
if (test_and_clear_bit(D_L1STATECHANGE, &cs->event)) {
if (!cs->hw.hfcpci.nt_mode)
switch (cs->dc.hfcpci.ph_state) {
diff --git a/drivers/isdn/hisax/hfc_sx.c b/drivers/isdn/hisax/hfc_sx.c
index d92e8d6c2ae..419f87cad8c 100644
--- a/drivers/isdn/hisax/hfc_sx.c
+++ b/drivers/isdn/hisax/hfc_sx.c
@@ -1255,8 +1255,6 @@ hfcsx_bh(struct work_struct *work)
container_of(work, struct IsdnCardState, tqueue);
u_long flags;
- if (!cs)
- return;
if (test_and_clear_bit(D_L1STATECHANGE, &cs->event)) {
if (!cs->hw.hfcsx.nt_mode)
switch (cs->dc.hfcsx.ph_state) {
diff --git a/drivers/isdn/hisax/icc.c b/drivers/isdn/hisax/icc.c
index 682cac32f25..9aba646ba22 100644
--- a/drivers/isdn/hisax/icc.c
+++ b/drivers/isdn/hisax/icc.c
@@ -83,8 +83,6 @@ icc_bh(struct work_struct *work)
container_of(work, struct IsdnCardState, tqueue);
struct PStack *stptr;
- if (!cs)
- return;
if (test_and_clear_bit(D_CLEARBUSY, &cs->event)) {
if (cs->debug)
debugl1(cs, "D-Channel Busy cleared");
diff --git a/drivers/isdn/hisax/isac.c b/drivers/isdn/hisax/isac.c
index 07b1673122b..a19354d9434 100644
--- a/drivers/isdn/hisax/isac.c
+++ b/drivers/isdn/hisax/isac.c
@@ -86,8 +86,6 @@ isac_bh(struct work_struct *work)
container_of(work, struct IsdnCardState, tqueue);
struct PStack *stptr;
- if (!cs)
- return;
if (test_and_clear_bit(D_CLEARBUSY, &cs->event)) {
if (cs->debug)
debugl1(cs, "D-Channel Busy cleared");
diff --git a/drivers/isdn/hisax/isdnhdlc.h b/drivers/isdn/hisax/isdnhdlc.h
deleted file mode 100644
index cf0a95a2401..00000000000
--- a/drivers/isdn/hisax/isdnhdlc.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * isdnhdlc.h -- General purpose ISDN HDLC decoder.
- *
- * Implementation of a HDLC decoder/encoder in software.
- * Neccessary because some ISDN devices don't have HDLC
- * controllers. Also included: a bit reversal table.
- *
- *Copyright (C) 2002 Wolfgang Mües <wolfgang@iksw-muees.de>
- * 2001 Frode Isaksen <fisaksen@bewan.com>
- * 2001 Kai Germaschewski <kai.germaschewski@gmx.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#ifndef __ISDNHDLC_H__
-#define __ISDNHDLC_H__
-
-struct isdnhdlc_vars {
- int bit_shift;
- int hdlc_bits1;
- int data_bits;
- int ffbit_shift; // encoding only
- int state;
- int dstpos;
-
- unsigned short crc;
-
- unsigned char cbin;
- unsigned char shift_reg;
- unsigned char ffvalue;
-
- unsigned int data_received:1; // set if transferring data
- unsigned int dchannel:1; // set if D channel (send idle instead of flags)
- unsigned int do_adapt56:1; // set if 56K adaptation
- unsigned int do_closing:1; // set if in closing phase (need to send CRC + flag
-};
-
-
-/*
- The return value from isdnhdlc_decode is
- the frame length, 0 if no complete frame was decoded,
- or a negative error number
-*/
-#define HDLC_FRAMING_ERROR 1
-#define HDLC_CRC_ERROR 2
-#define HDLC_LENGTH_ERROR 3
-
-extern void isdnhdlc_rcv_init (struct isdnhdlc_vars *hdlc, int do_adapt56);
-
-extern int isdnhdlc_decode (struct isdnhdlc_vars *hdlc, const unsigned char *src, int slen,int *count,
- unsigned char *dst, int dsize);
-
-extern void isdnhdlc_out_init (struct isdnhdlc_vars *hdlc,int is_d_channel,int do_adapt56);
-
-extern int isdnhdlc_encode (struct isdnhdlc_vars *hdlc,const unsigned char *src,unsigned short slen,int *count,
- unsigned char *dst,int dsize);
-
-#endif /* __ISDNHDLC_H__ */
diff --git a/drivers/isdn/hisax/isdnl1.c b/drivers/isdn/hisax/isdnl1.c
index 317f16f516f..9ce6abe05b1 100644
--- a/drivers/isdn/hisax/isdnl1.c
+++ b/drivers/isdn/hisax/isdnl1.c
@@ -647,8 +647,6 @@ static struct FsmNode L1SFnList[] __initdata =
{ST_L1_F8, EV_TIMER_DEACT, l1_timer_deact},
};
-#define L1S_FN_COUNT (sizeof(L1SFnList)/sizeof(struct FsmNode))
-
#ifdef HISAX_UINTERFACE
static void
l1_deact_req_u(struct FsmInst *fi, int event, void *arg)
@@ -706,8 +704,6 @@ static struct FsmNode L1UFnList[] __initdata =
{ST_L1_RESET, EV_TIMER_DEACT, l1_timer_deact},
};
-#define L1U_FN_COUNT (sizeof(L1UFnList)/sizeof(struct FsmNode))
-
#endif
static void
@@ -754,8 +750,6 @@ static struct FsmNode L1BFnList[] __initdata =
{ST_L1_WAIT_DEACT, EV_TIMER_DEACT, l1b_timer_deact},
};
-#define L1B_FN_COUNT (sizeof(L1BFnList)/sizeof(struct FsmNode))
-
int __init
Isdnl1New(void)
{
@@ -765,7 +759,7 @@ Isdnl1New(void)
l1fsm_s.event_count = L1_EVENT_COUNT;
l1fsm_s.strEvent = strL1Event;
l1fsm_s.strState = strL1SState;
- retval = FsmNew(&l1fsm_s, L1SFnList, L1S_FN_COUNT);
+ retval = FsmNew(&l1fsm_s, L1SFnList, ARRAY_SIZE(L1SFnList));
if (retval)
return retval;
@@ -773,7 +767,7 @@ Isdnl1New(void)
l1fsm_b.event_count = L1_EVENT_COUNT;
l1fsm_b.strEvent = strL1Event;
l1fsm_b.strState = strL1BState;
- retval = FsmNew(&l1fsm_b, L1BFnList, L1B_FN_COUNT);
+ retval = FsmNew(&l1fsm_b, L1BFnList, ARRAY_SIZE(L1BFnList));
if (retval) {
FsmFree(&l1fsm_s);
return retval;
@@ -783,7 +777,7 @@ Isdnl1New(void)
l1fsm_u.event_count = L1_EVENT_COUNT;
l1fsm_u.strEvent = strL1Event;
l1fsm_u.strState = strL1UState;
- retval = FsmNew(&l1fsm_u, L1UFnList, L1U_FN_COUNT);
+ retval = FsmNew(&l1fsm_u, L1UFnList, ARRAY_SIZE(L1UFnList));
if (retval) {
FsmFree(&l1fsm_s);
FsmFree(&l1fsm_b);
diff --git a/drivers/isdn/hisax/isdnl2.c b/drivers/isdn/hisax/isdnl2.c
index 3446f249d67..7b9496a63b5 100644
--- a/drivers/isdn/hisax/isdnl2.c
+++ b/drivers/isdn/hisax/isdnl2.c
@@ -1623,8 +1623,6 @@ static struct FsmNode L2FnList[] __initdata =
{ST_L2_8, EV_L1_DEACTIVATE, l2_persistent_da},
};
-#define L2_FN_COUNT (sizeof(L2FnList)/sizeof(struct FsmNode))
-
static void
isdnl2_l1l2(struct PStack *st, int pr, void *arg)
{
@@ -1836,7 +1834,7 @@ Isdnl2New(void)
l2fsm.event_count = L2_EVENT_COUNT;
l2fsm.strEvent = strL2Event;
l2fsm.strState = strL2State;
- return FsmNew(&l2fsm, L2FnList, L2_FN_COUNT);
+ return FsmNew(&l2fsm, L2FnList, ARRAY_SIZE(L2FnList));
}
void
diff --git a/drivers/isdn/hisax/isdnl3.c b/drivers/isdn/hisax/isdnl3.c
index 935f23356fa..06766022d3a 100644
--- a/drivers/isdn/hisax/isdnl3.c
+++ b/drivers/isdn/hisax/isdnl3.c
@@ -543,8 +543,6 @@ static struct FsmNode L3FnList[] __initdata =
};
/* *INDENT-ON* */
-#define L3_FN_COUNT (sizeof(L3FnList)/sizeof(struct FsmNode))
-
void
l3_msg(struct PStack *st, int pr, void *arg)
{
@@ -587,7 +585,7 @@ Isdnl3New(void)
l3fsm.event_count = L3_EVENT_COUNT;
l3fsm.strEvent = strL3Event;
l3fsm.strState = strL3State;
- return FsmNew(&l3fsm, L3FnList, L3_FN_COUNT);
+ return FsmNew(&l3fsm, L3FnList, ARRAY_SIZE(L3FnList));
}
void
diff --git a/drivers/isdn/hisax/l3_1tr6.c b/drivers/isdn/hisax/l3_1tr6.c
index c5c36eeff26..b0554f80bfb 100644
--- a/drivers/isdn/hisax/l3_1tr6.c
+++ b/drivers/isdn/hisax/l3_1tr6.c
@@ -698,9 +698,6 @@ static struct stateentry downstl[] =
CC_T308_2, l3_1tr6_t308_2},
};
-#define DOWNSTL_LEN \
- (sizeof(downstl) / sizeof(struct stateentry))
-
static struct stateentry datastln1[] =
{
{SBIT(0),
@@ -735,9 +732,6 @@ static struct stateentry datastln1[] =
MT_N1_REL_ACK, l3_1tr6_rel_ack}
};
-#define DATASTLN1_LEN \
- (sizeof(datastln1) / sizeof(struct stateentry))
-
static struct stateentry manstatelist[] =
{
{SBIT(2),
@@ -746,8 +740,6 @@ static struct stateentry manstatelist[] =
DL_RELEASE | INDICATION, l3_1tr6_dl_release},
};
-#define MANSLLEN \
- (sizeof(manstatelist) / sizeof(struct stateentry))
/* *INDENT-ON* */
static void
@@ -840,11 +832,11 @@ up1tr6(struct PStack *st, int pr, void *arg)
mt = MT_N1_INVALID;
}
}
- for (i = 0; i < DATASTLN1_LEN; i++)
+ for (i = 0; i < ARRAY_SIZE(datastln1); i++)
if ((mt == datastln1[i].primitive) &&
((1 << proc->state) & datastln1[i].state))
break;
- if (i == DATASTLN1_LEN) {
+ if (i == ARRAY_SIZE(datastln1)) {
dev_kfree_skb(skb);
if (st->l3.debug & L3_DEB_STATE) {
sprintf(tmp, "up1tr6%sstate %d mt %x unhandled",
@@ -892,11 +884,11 @@ down1tr6(struct PStack *st, int pr, void *arg)
proc = arg;
}
- for (i = 0; i < DOWNSTL_LEN; i++)
+ for (i = 0; i < ARRAY_SIZE(downstl); i++)
if ((pr == downstl[i].primitive) &&
((1 << proc->state) & downstl[i].state))
break;
- if (i == DOWNSTL_LEN) {
+ if (i == ARRAY_SIZE(downstl)) {
if (st->l3.debug & L3_DEB_STATE) {
sprintf(tmp, "down1tr6 state %d prim %d unhandled",
proc->state, pr);
@@ -922,11 +914,11 @@ man1tr6(struct PStack *st, int pr, void *arg)
printk(KERN_ERR "HiSax man1tr6 without proc pr=%04x\n", pr);
return;
}
- for (i = 0; i < MANSLLEN; i++)
+ for (i = 0; i < ARRAY_SIZE(manstatelist); i++)
if ((pr == manstatelist[i].primitive) &&
((1 << proc->state) & manstatelist[i].state))
break;
- if (i == MANSLLEN) {
+ if (i == ARRAY_SIZE(manstatelist)) {
if (st->l3.debug & L3_DEB_STATE) {
l3_debug(st, "cr %d man1tr6 state %d prim %d unhandled",
proc->callref & 0x7f, proc->state, pr);
diff --git a/drivers/isdn/hisax/l3dss1.c b/drivers/isdn/hisax/l3dss1.c
index 99feae8b921..a12fa4d3490 100644
--- a/drivers/isdn/hisax/l3dss1.c
+++ b/drivers/isdn/hisax/l3dss1.c
@@ -2820,9 +2820,6 @@ static struct stateentry downstatelist[] =
CC_T309, l3dss1_dl_release},
};
-#define DOWNSLLEN \
- (sizeof(downstatelist) / sizeof(struct stateentry))
-
static struct stateentry datastatelist[] =
{
{ALL_STATES,
@@ -2875,9 +2872,6 @@ static struct stateentry datastatelist[] =
MT_RESUME_REJECT, l3dss1_resume_rej},
};
-#define DATASLLEN \
- (sizeof(datastatelist) / sizeof(struct stateentry))
-
static struct stateentry globalmes_list[] =
{
{ALL_STATES,
@@ -2888,8 +2882,6 @@ static struct stateentry globalmes_list[] =
MT_RESTART_ACKNOWLEDGE, l3dss1_restart_ack},
*/
};
-#define GLOBALM_LEN \
- (sizeof(globalmes_list) / sizeof(struct stateentry))
static struct stateentry manstatelist[] =
{
@@ -2903,8 +2895,6 @@ static struct stateentry manstatelist[] =
DL_RELEASE | INDICATION, l3dss1_dl_release},
};
-#define MANSLLEN \
- (sizeof(manstatelist) / sizeof(struct stateentry))
/* *INDENT-ON* */
@@ -2918,11 +2908,11 @@ global_handler(struct PStack *st, int mt, struct sk_buff *skb)
struct l3_process *proc = st->l3.global;
proc->callref = skb->data[2]; /* cr flag */
- for (i = 0; i < GLOBALM_LEN; i++)
+ for (i = 0; i < ARRAY_SIZE(globalmes_list); i++)
if ((mt == globalmes_list[i].primitive) &&
((1 << proc->state) & globalmes_list[i].state))
break;
- if (i == GLOBALM_LEN) {
+ if (i == ARRAY_SIZE(globalmes_list)) {
if (st->l3.debug & L3_DEB_STATE) {
l3_debug(st, "dss1 global state %d mt %x unhandled",
proc->state, mt);
@@ -3097,11 +3087,11 @@ dss1up(struct PStack *st, int pr, void *arg)
}
if ((p = findie(skb->data, skb->len, IE_DISPLAY, 0)) != NULL)
l3dss1_deliver_display(proc, pr, p); /* Display IE included */
- for (i = 0; i < DATASLLEN; i++)
+ for (i = 0; i < ARRAY_SIZE(datastatelist); i++)
if ((mt == datastatelist[i].primitive) &&
((1 << proc->state) & datastatelist[i].state))
break;
- if (i == DATASLLEN) {
+ if (i == ARRAY_SIZE(datastatelist)) {
if (st->l3.debug & L3_DEB_STATE) {
l3_debug(st, "dss1up%sstate %d mt %#x unhandled",
(pr == (DL_DATA | INDICATION)) ? " " : "(broadcast) ",
@@ -3156,11 +3146,11 @@ dss1down(struct PStack *st, int pr, void *arg)
return;
}
- for (i = 0; i < DOWNSLLEN; i++)
+ for (i = 0; i < ARRAY_SIZE(downstatelist); i++)
if ((pr == downstatelist[i].primitive) &&
((1 << proc->state) & downstatelist[i].state))
break;
- if (i == DOWNSLLEN) {
+ if (i == ARRAY_SIZE(downstatelist)) {
if (st->l3.debug & L3_DEB_STATE) {
l3_debug(st, "dss1down state %d prim %#x unhandled",
proc->state, pr);
@@ -3184,11 +3174,11 @@ dss1man(struct PStack *st, int pr, void *arg)
printk(KERN_ERR "HiSax dss1man without proc pr=%04x\n", pr);
return;
}
- for (i = 0; i < MANSLLEN; i++)
+ for (i = 0; i < ARRAY_SIZE(manstatelist); i++)
if ((pr == manstatelist[i].primitive) &&
((1 << proc->state) & manstatelist[i].state))
break;
- if (i == MANSLLEN) {
+ if (i == ARRAY_SIZE(manstatelist)) {
if (st->l3.debug & L3_DEB_STATE) {
l3_debug(st, "cr %d dss1man state %d prim %#x unhandled",
proc->callref & 0x7f, proc->state, pr);
diff --git a/drivers/isdn/hisax/l3ni1.c b/drivers/isdn/hisax/l3ni1.c
index f7041d5ba64..4622d43c7e1 100644
--- a/drivers/isdn/hisax/l3ni1.c
+++ b/drivers/isdn/hisax/l3ni1.c
@@ -2755,9 +2755,6 @@ static struct stateentry downstatelist[] =
CC_TSPID, l3ni1_spid_tout },
};
-#define DOWNSLLEN \
- (sizeof(downstatelist) / sizeof(struct stateentry))
-
static struct stateentry datastatelist[] =
{
{ALL_STATES,
@@ -2810,9 +2807,6 @@ static struct stateentry datastatelist[] =
MT_RESUME_REJECT, l3ni1_resume_rej},
};
-#define DATASLLEN \
- (sizeof(datastatelist) / sizeof(struct stateentry))
-
static struct stateentry globalmes_list[] =
{
{ALL_STATES,
@@ -2825,8 +2819,6 @@ static struct stateentry globalmes_list[] =
{ SBIT( 0 ), MT_DL_ESTABLISHED, l3ni1_spid_send },
{ SBIT( 20 ) | SBIT( 21 ) | SBIT( 22 ), MT_INFORMATION, l3ni1_spid_epid },
};
-#define GLOBALM_LEN \
- (sizeof(globalmes_list) / sizeof(struct stateentry))
static struct stateentry manstatelist[] =
{
@@ -2840,8 +2832,6 @@ static struct stateentry manstatelist[] =
DL_RELEASE | INDICATION, l3ni1_dl_release},
};
-#define MANSLLEN \
- (sizeof(manstatelist) / sizeof(struct stateentry))
/* *INDENT-ON* */
@@ -2858,11 +2848,11 @@ global_handler(struct PStack *st, int mt, struct sk_buff *skb)
proc->callref = skb->data[2]; /* cr flag */
else
proc->callref = 0;
- for (i = 0; i < GLOBALM_LEN; i++)
+ for (i = 0; i < ARRAY_SIZE(globalmes_list); i++)
if ((mt == globalmes_list[i].primitive) &&
((1 << proc->state) & globalmes_list[i].state))
break;
- if (i == GLOBALM_LEN) {
+ if (i == ARRAY_SIZE(globalmes_list)) {
if (st->l3.debug & L3_DEB_STATE) {
l3_debug(st, "ni1 global state %d mt %x unhandled",
proc->state, mt);
@@ -3049,11 +3039,11 @@ ni1up(struct PStack *st, int pr, void *arg)
}
if ((p = findie(skb->data, skb->len, IE_DISPLAY, 0)) != NULL)
l3ni1_deliver_display(proc, pr, p); /* Display IE included */
- for (i = 0; i < DATASLLEN; i++)
+ for (i = 0; i < ARRAY_SIZE(datastatelist); i++)
if ((mt == datastatelist[i].primitive) &&
((1 << proc->state) & datastatelist[i].state))
break;
- if (i == DATASLLEN) {
+ if (i == ARRAY_SIZE(datastatelist)) {
if (st->l3.debug & L3_DEB_STATE) {
l3_debug(st, "ni1up%sstate %d mt %#x unhandled",
(pr == (DL_DATA | INDICATION)) ? " " : "(broadcast) ",
@@ -3108,11 +3098,11 @@ ni1down(struct PStack *st, int pr, void *arg)
return;
}
- for (i = 0; i < DOWNSLLEN; i++)
+ for (i = 0; i < ARRAY_SIZE(downstatelist); i++)
if ((pr == downstatelist[i].primitive) &&
((1 << proc->state) & downstatelist[i].state))
break;
- if (i == DOWNSLLEN) {
+ if (i == ARRAY_SIZE(downstatelist)) {
if (st->l3.debug & L3_DEB_STATE) {
l3_debug(st, "ni1down state %d prim %#x unhandled",
proc->state, pr);
@@ -3136,11 +3126,11 @@ ni1man(struct PStack *st, int pr, void *arg)
printk(KERN_ERR "HiSax ni1man without proc pr=%04x\n", pr);
return;
}
- for (i = 0; i < MANSLLEN; i++)
+ for (i = 0; i < ARRAY_SIZE(manstatelist); i++)
if ((pr == manstatelist[i].primitive) &&
((1 << proc->state) & manstatelist[i].state))
break;
- if (i == MANSLLEN) {
+ if (i == ARRAY_SIZE(manstatelist)) {
if (st->l3.debug & L3_DEB_STATE) {
l3_debug(st, "cr %d ni1man state %d prim %#x unhandled",
proc->callref & 0x7f, proc->state, pr);
diff --git a/drivers/isdn/hisax/q931.c b/drivers/isdn/hisax/q931.c
index aacbf0d14b6..8b853d58e82 100644
--- a/drivers/isdn/hisax/q931.c
+++ b/drivers/isdn/hisax/q931.c
@@ -140,7 +140,7 @@ struct MessageType {
}
};
-#define MTSIZE sizeof(mtlist)/sizeof(struct MessageType)
+#define MTSIZE ARRAY_SIZE(mtlist)
static
struct MessageType mt_n0[] =
@@ -157,7 +157,7 @@ struct MessageType mt_n0[] =
{MT_N0_CLO_ACK, "CLOse ACKnowledge"}
};
-#define MT_N0_LEN (sizeof(mt_n0) / sizeof(struct MessageType))
+#define MT_N0_LEN ARRAY_SIZE(mt_n0)
static
struct MessageType mt_n1[] =
@@ -194,7 +194,7 @@ struct MessageType mt_n1[] =
{MT_N1_STAT, "STATus"}
};
-#define MT_N1_LEN (sizeof(mt_n1) / sizeof(struct MessageType))
+#define MT_N1_LEN ARRAY_SIZE(mt_n1)
static int
@@ -438,7 +438,7 @@ struct CauseValue {
},
};
-#define CVSIZE sizeof(cvlist)/sizeof(struct CauseValue)
+#define CVSIZE ARRAY_SIZE(cvlist)
static
int
@@ -516,7 +516,7 @@ struct MessageType cause_1tr6[] =
{CAUSE_UserInfoDiscarded, "User Info Discarded"}
};
-static int cause_1tr6_len = (sizeof(cause_1tr6) / sizeof(struct MessageType));
+static int cause_1tr6_len = ARRAY_SIZE(cause_1tr6);
static int
prcause_1tr6(char *dest, u_char * p)
@@ -865,7 +865,7 @@ struct DTag { /* Display tags */
{ 0x96, "Redirection name" },
{ 0x9e, "Text" },
};
-#define DTAGSIZE sizeof(dtaglist)/sizeof(struct DTag)
+#define DTAGSIZE ARRAY_SIZE(dtaglist)
static int
disptext_ni1(char *dest, u_char * p)
@@ -1074,7 +1074,7 @@ struct InformationElement {
};
-#define IESIZE sizeof(ielist)/sizeof(struct InformationElement)
+#define IESIZE ARRAY_SIZE(ielist)
static
struct InformationElement ielist_ni1[] = {
@@ -1102,7 +1102,7 @@ struct InformationElement ielist_ni1[] = {
};
-#define IESIZE_NI1 sizeof(ielist_ni1)/sizeof(struct InformationElement)
+#define IESIZE_NI1 ARRAY_SIZE(ielist_ni1)
static
struct InformationElement ielist_ni1_cs5[] = {
@@ -1110,14 +1110,14 @@ struct InformationElement ielist_ni1_cs5[] = {
{ 0x2a, "Display text", disptext_ni1 },
};
-#define IESIZE_NI1_CS5 sizeof(ielist_ni1_cs5)/sizeof(struct InformationElement)
+#define IESIZE_NI1_CS5 ARRAY_SIZE(ielist_ni1_cs5)
static
struct InformationElement ielist_ni1_cs6[] = {
{ 0x7b, "Call appearance", general_ni1 },
};
-#define IESIZE_NI1_CS6 sizeof(ielist_ni1_cs6)/sizeof(struct InformationElement)
+#define IESIZE_NI1_CS6 ARRAY_SIZE(ielist_ni1_cs6)
static struct InformationElement we_0[] =
{
@@ -1133,7 +1133,7 @@ static struct InformationElement we_0[] =
{WE0_userInfo, "User Info", general}
};
-#define WE_0_LEN (sizeof(we_0) / sizeof(struct InformationElement))
+#define WE_0_LEN ARRAY_SIZE(we_0)
static struct InformationElement we_6[] =
{
@@ -1145,7 +1145,7 @@ static struct InformationElement we_6[] =
{WE6_statusCalled, "Status Called", general},
{WE6_addTransAttr, "Additional Transmission Attributes", general}
};
-#define WE_6_LEN (sizeof(we_6) / sizeof(struct InformationElement))
+#define WE_6_LEN ARRAY_SIZE(we_6)
int
QuickHex(char *txt, u_char * p, int cnt)
diff --git a/drivers/isdn/hisax/st5481.h b/drivers/isdn/hisax/st5481.h
index cff7a635433..64f78a8c28c 100644
--- a/drivers/isdn/hisax/st5481.h
+++ b/drivers/isdn/hisax/st5481.h
@@ -226,7 +226,7 @@ printk(KERN_WARNING "%s:%s: " format "\n" , __FILE__, __func__ , ## arg)
#define INFO(format, arg...) \
printk(KERN_INFO "%s:%s: " format "\n" , __FILE__, __func__ , ## arg)
-#include "isdnhdlc.h"
+#include <linux/isdn/hdlc.h>
#include "fsm.h"
#include "hisax_if.h"
#include <linux/skbuff.h>
diff --git a/drivers/isdn/hisax/st5481_b.c b/drivers/isdn/hisax/st5481_b.c
index 0074b600a0e..95b1cdd9795 100644
--- a/drivers/isdn/hisax/st5481_b.c
+++ b/drivers/isdn/hisax/st5481_b.c
@@ -218,7 +218,10 @@ static void st5481B_mode(struct st5481_bcs *bcs, int mode)
if (bcs->mode != L1_MODE_NULL) {
// Open the B channel
if (bcs->mode != L1_MODE_TRANS) {
- isdnhdlc_out_init(&b_out->hdlc_state, 0, bcs->mode == L1_MODE_HDLC_56K);
+ u32 features = HDLC_BITREVERSE;
+ if (bcs->mode == L1_MODE_HDLC_56K)
+ features |= HDLC_56KBIT;
+ isdnhdlc_out_init(&b_out->hdlc_state, features);
}
st5481_usb_pipe_reset(adapter, (bcs->channel+1)*2, NULL, NULL);
diff --git a/drivers/isdn/hisax/st5481_d.c b/drivers/isdn/hisax/st5481_d.c
index 077991c1cd0..39e8e49cfd2 100644
--- a/drivers/isdn/hisax/st5481_d.c
+++ b/drivers/isdn/hisax/st5481_d.c
@@ -417,7 +417,7 @@ static void dout_start_xmit(struct FsmInst *fsm, int event, void *arg)
DBG(2,"len=%d",skb->len);
- isdnhdlc_out_init(&d_out->hdlc_state, 1, 0);
+ isdnhdlc_out_init(&d_out->hdlc_state, HDLC_DCHANNEL | HDLC_BITREVERSE);
if (test_and_set_bit(buf_nr, &d_out->busy)) {
WARNING("ep %d urb %d busy %#lx", EP_D_OUT, buf_nr, d_out->busy);
diff --git a/drivers/isdn/hisax/st5481_usb.c b/drivers/isdn/hisax/st5481_usb.c
index 2b3a055059e..10d41c5d73e 100644
--- a/drivers/isdn/hisax/st5481_usb.c
+++ b/drivers/isdn/hisax/st5481_usb.c
@@ -637,10 +637,13 @@ void st5481_in_mode(struct st5481_in *in, int mode)
usb_unlink_urb(in->urb[1]);
if (in->mode != L1_MODE_NULL) {
- if (in->mode != L1_MODE_TRANS)
- isdnhdlc_rcv_init(&in->hdlc_state,
- in->mode == L1_MODE_HDLC_56K);
-
+ if (in->mode != L1_MODE_TRANS) {
+ u32 features = HDLC_BITREVERSE;
+
+ if (in->mode == L1_MODE_HDLC_56K)
+ features |= HDLC_56KBIT;
+ isdnhdlc_rcv_init(&in->hdlc_state, features);
+ }
st5481_usb_pipe_reset(in->adapter, in->ep, NULL, NULL);
st5481_usb_device_ctrl_msg(in->adapter, in->counter,
in->packet_size,
diff --git a/drivers/isdn/hisax/tei.c b/drivers/isdn/hisax/tei.c
index ceb0df92fd3..6e65424f1f0 100644
--- a/drivers/isdn/hisax/tei.c
+++ b/drivers/isdn/hisax/tei.c
@@ -447,8 +447,6 @@ static struct FsmNode TeiFnList[] __initdata =
{ST_TEI_IDVERIFY, EV_CHKREQ, tei_id_chk_req},
};
-#define TEI_FN_COUNT (sizeof(TeiFnList)/sizeof(struct FsmNode))
-
int __init
TeiNew(void)
{
@@ -456,7 +454,7 @@ TeiNew(void)
teifsm.event_count = TEI_EVENT_COUNT;
teifsm.strEvent = strTeiEvent;
teifsm.strState = strTeiState;
- return FsmNew(&teifsm, TeiFnList, TEI_FN_COUNT);
+ return FsmNew(&teifsm, TeiFnList, ARRAY_SIZE(TeiFnList));
}
void
diff --git a/drivers/isdn/hisax/w6692.c b/drivers/isdn/hisax/w6692.c
index bb1c8dd1a23..c4d862c11a6 100644
--- a/drivers/isdn/hisax/w6692.c
+++ b/drivers/isdn/hisax/w6692.c
@@ -105,8 +105,6 @@ W6692_bh(struct work_struct *work)
container_of(work, struct IsdnCardState, tqueue);
struct PStack *stptr;
- if (!cs)
- return;
if (test_and_clear_bit(D_CLEARBUSY, &cs->event)) {
if (cs->debug)
debugl1(cs, "D-Channel Busy cleared");
diff --git a/drivers/isdn/hysdn/hysdn_net.c b/drivers/isdn/hysdn/hysdn_net.c
index 579974cf4c9..c73004b3b2a 100644
--- a/drivers/isdn/hysdn/hysdn_net.c
+++ b/drivers/isdn/hysdn/hysdn_net.c
@@ -148,7 +148,7 @@ net_send_packet(struct sk_buff *skb, struct net_device *dev)
if (lp->sk_count <= 3) {
schedule_work(&((hysdn_card *) dev->ml_priv)->irq_queue);
}
- return (0); /* success */
+ return NETDEV_TX_OK; /* success */
} /* net_send_packet */
diff --git a/drivers/isdn/i4l/Kconfig b/drivers/isdn/i4l/Kconfig
index ed3510f273d..dd744ffd240 100644
--- a/drivers/isdn/i4l/Kconfig
+++ b/drivers/isdn/i4l/Kconfig
@@ -2,6 +2,8 @@
# Old ISDN4Linux config
#
+if ISDN_I4L
+
config ISDN_PPP
bool "Support synchronous PPP"
depends on INET
@@ -135,3 +137,12 @@ source "drivers/isdn/act2000/Kconfig"
source "drivers/isdn/hysdn/Kconfig"
endmenu
+# end ISDN_I4L
+endif
+
+config ISDN_HDLC
+ tristate
+ depends on HISAX_ST5481
+ select CRC_CCITT
+ select BITREVERSE
+
diff --git a/drivers/isdn/i4l/Makefile b/drivers/isdn/i4l/Makefile
index 49a06c0005d..cb9d3bb9fae 100644
--- a/drivers/isdn/i4l/Makefile
+++ b/drivers/isdn/i4l/Makefile
@@ -4,6 +4,7 @@
obj-$(CONFIG_ISDN_I4L) += isdn.o
obj-$(CONFIG_ISDN_PPP_BSDCOMP) += isdn_bsdcomp.o
+obj-$(CONFIG_ISDN_HDLC) += isdnhdlc.o
# Multipart objects.
diff --git a/drivers/isdn/i4l/isdn_net.c b/drivers/isdn/i4l/isdn_net.c
index de4aad076eb..57bf4bf5027 100644
--- a/drivers/isdn/i4l/isdn_net.c
+++ b/drivers/isdn/i4l/isdn_net.c
@@ -1051,12 +1051,12 @@ isdn_net_xmit(struct net_device *ndev, struct sk_buff *skb)
isdn_net_dev *nd;
isdn_net_local *slp;
isdn_net_local *lp = (isdn_net_local *) netdev_priv(ndev);
- int retv = 0;
+ int retv = NETDEV_TX_OK;
if (((isdn_net_local *) netdev_priv(ndev))->master) {
printk("isdn BUG at %s:%d!\n", __FILE__, __LINE__);
dev_kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
}
/* For the other encaps the header has already been built */
@@ -1202,7 +1202,7 @@ isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev)
if (!(ISDN_NET_DIALMODE(*lp) == ISDN_NET_DM_AUTO)) {
isdn_net_unreachable(ndev, skb, "dial rejected: interface not in dialmode `auto'");
dev_kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
}
if (lp->phone[1]) {
ulong flags;
@@ -1215,7 +1215,7 @@ isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev)
if(time_before(jiffies, lp->dialwait_timer)) {
isdn_net_unreachable(ndev, skb, "dial rejected: retry-time not reached");
dev_kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
} else
lp->dialwait_timer = 0;
}
@@ -1243,7 +1243,7 @@ isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev)
isdn_net_unreachable(ndev, skb,
"No channel");
dev_kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
}
/* Log packet, which triggered dialing */
if (dev->net_verbose)
@@ -1258,7 +1258,7 @@ isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev)
dev_kfree_skb(skb);
isdn_net_unbind_channel(lp);
spin_unlock_irqrestore(&dev->lock, flags);
- return 0; /* STN (skb to nirvana) ;) */
+ return NETDEV_TX_OK; /* STN (skb to nirvana) ;) */
}
#ifdef CONFIG_IPPP_FILTER
if (isdn_ppp_autodial_filter(skb, lp)) {
@@ -1267,7 +1267,7 @@ isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev)
spin_unlock_irqrestore(&dev->lock, flags);
isdn_net_unreachable(ndev, skb, "dial rejected: packet filtered");
dev_kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
}
#endif
spin_unlock_irqrestore(&dev->lock, flags);
@@ -1285,7 +1285,7 @@ isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev)
isdn_net_unreachable(ndev, skb,
"No phone number");
dev_kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
}
} else {
/* Device is connected to an ISDN channel */
diff --git a/drivers/isdn/i4l/isdn_ppp.c b/drivers/isdn/i4l/isdn_ppp.c
index aa30b5cb351..2d14b64202a 100644
--- a/drivers/isdn/i4l/isdn_ppp.c
+++ b/drivers/isdn/i4l/isdn_ppp.c
@@ -1223,7 +1223,7 @@ isdn_ppp_xmit(struct sk_buff *skb, struct net_device *netdev)
isdn_net_dev *nd;
unsigned int proto = PPP_IP; /* 0x21 */
struct ippp_struct *ipt,*ipts;
- int slot, retval = 0;
+ int slot, retval = NETDEV_TX_OK;
mlp = (isdn_net_local *) netdev_priv(netdev);
nd = mlp->netdev; /* get master lp */
@@ -1240,7 +1240,7 @@ isdn_ppp_xmit(struct sk_buff *skb, struct net_device *netdev)
if (!(ipts->pppcfg & SC_ENABLE_IP)) { /* PPP connected ? */
if (ipts->debug & 0x1)
printk(KERN_INFO "%s: IP frame delayed.\n", netdev->name);
- retval = 1;
+ retval = NETDEV_TX_BUSY;
goto out;
}
@@ -1261,7 +1261,7 @@ isdn_ppp_xmit(struct sk_buff *skb, struct net_device *netdev)
lp = isdn_net_get_locked_lp(nd);
if (!lp) {
printk(KERN_WARNING "%s: all channels busy - requeuing!\n", netdev->name);
- retval = 1;
+ retval = NETDEV_TX_BUSY;
goto out;
}
/* we have our lp locked from now on */
diff --git a/drivers/isdn/hisax/isdnhdlc.c b/drivers/isdn/i4l/isdnhdlc.c
index c69a77a8006..c989aa35dc2 100644
--- a/drivers/isdn/hisax/isdnhdlc.c
+++ b/drivers/isdn/i4l/isdnhdlc.c
@@ -1,29 +1,32 @@
/*
* isdnhdlc.c -- General purpose ISDN HDLC decoder.
*
- *Copyright (C) 2002 Wolfgang Mües <wolfgang@iksw-muees.de>
- * 2001 Frode Isaksen <fisaksen@bewan.com>
- * 2001 Kai Germaschewski <kai.germaschewski@gmx.de>
+ * Copyright (C)
+ * 2009 Karsten Keil <keil@b1-systems.de>
+ * 2002 Wolfgang Mües <wolfgang@iksw-muees.de>
+ * 2001 Frode Isaksen <fisaksen@bewan.com>
+ * 2001 Kai Germaschewski <kai.germaschewski@gmx.de>
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
*
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/crc-ccitt.h>
-#include "isdnhdlc.h"
+#include <linux/isdn/hdlc.h>
+#include <linux/bitrev.h>
/*-------------------------------------------------------------------*/
@@ -36,44 +39,32 @@ MODULE_LICENSE("GPL");
/*-------------------------------------------------------------------*/
enum {
- HDLC_FAST_IDLE,HDLC_GET_FLAG_B0,HDLC_GETFLAG_B1A6,HDLC_GETFLAG_B7,
- HDLC_GET_DATA,HDLC_FAST_FLAG
+ HDLC_FAST_IDLE, HDLC_GET_FLAG_B0, HDLC_GETFLAG_B1A6, HDLC_GETFLAG_B7,
+ HDLC_GET_DATA, HDLC_FAST_FLAG
};
enum {
- HDLC_SEND_DATA,HDLC_SEND_CRC1,HDLC_SEND_FAST_FLAG,
- HDLC_SEND_FIRST_FLAG,HDLC_SEND_CRC2,HDLC_SEND_CLOSING_FLAG,
- HDLC_SEND_IDLE1,HDLC_SEND_FAST_IDLE,HDLC_SENDFLAG_B0,
- HDLC_SENDFLAG_B1A6,HDLC_SENDFLAG_B7,STOPPED
+ HDLC_SEND_DATA, HDLC_SEND_CRC1, HDLC_SEND_FAST_FLAG,
+ HDLC_SEND_FIRST_FLAG, HDLC_SEND_CRC2, HDLC_SEND_CLOSING_FLAG,
+ HDLC_SEND_IDLE1, HDLC_SEND_FAST_IDLE, HDLC_SENDFLAG_B0,
+ HDLC_SENDFLAG_B1A6, HDLC_SENDFLAG_B7, STOPPED, HDLC_SENDFLAG_ONE
};
-void isdnhdlc_rcv_init (struct isdnhdlc_vars *hdlc, int do_adapt56)
+void isdnhdlc_rcv_init(struct isdnhdlc_vars *hdlc, u32 features)
{
- hdlc->bit_shift = 0;
- hdlc->hdlc_bits1 = 0;
- hdlc->data_bits = 0;
- hdlc->ffbit_shift = 0;
- hdlc->data_received = 0;
+ memset(hdlc, 0, sizeof(struct isdnhdlc_vars));
hdlc->state = HDLC_GET_DATA;
- hdlc->do_adapt56 = do_adapt56;
- hdlc->dchannel = 0;
- hdlc->crc = 0;
- hdlc->cbin = 0;
- hdlc->shift_reg = 0;
- hdlc->ffvalue = 0;
- hdlc->dstpos = 0;
+ if (features & HDLC_56KBIT)
+ hdlc->do_adapt56 = 1;
+ if (features & HDLC_BITREVERSE)
+ hdlc->do_bitreverse = 1;
}
+EXPORT_SYMBOL(isdnhdlc_out_init);
-void isdnhdlc_out_init (struct isdnhdlc_vars *hdlc, int is_d_channel, int do_adapt56)
+void isdnhdlc_out_init(struct isdnhdlc_vars *hdlc, u32 features)
{
- hdlc->bit_shift = 0;
- hdlc->hdlc_bits1 = 0;
- hdlc->data_bits = 0;
- hdlc->ffbit_shift = 0;
- hdlc->data_received = 0;
- hdlc->do_closing = 0;
- hdlc->ffvalue = 0;
- if (is_d_channel) {
+ memset(hdlc, 0, sizeof(struct isdnhdlc_vars));
+ if (features & HDLC_DCHANNEL) {
hdlc->dchannel = 1;
hdlc->state = HDLC_SEND_FIRST_FLAG;
} else {
@@ -82,16 +73,32 @@ void isdnhdlc_out_init (struct isdnhdlc_vars *hdlc, int is_d_channel, int do_ada
hdlc->ffvalue = 0x7e;
}
hdlc->cbin = 0x7e;
- hdlc->bit_shift = 0;
- if(do_adapt56){
+ if (features & HDLC_56KBIT) {
hdlc->do_adapt56 = 1;
- hdlc->data_bits = 0;
hdlc->state = HDLC_SENDFLAG_B0;
- } else {
- hdlc->do_adapt56 = 0;
+ } else
hdlc->data_bits = 8;
+ if (features & HDLC_BITREVERSE)
+ hdlc->do_bitreverse = 1;
+}
+EXPORT_SYMBOL(isdnhdlc_rcv_init);
+
+static int
+check_frame(struct isdnhdlc_vars *hdlc)
+{
+ int status;
+
+ if (hdlc->dstpos < 2) /* too small - framing error */
+ status = -HDLC_FRAMING_ERROR;
+ else if (hdlc->crc != 0xf0b8) /* crc error */
+ status = -HDLC_CRC_ERROR;
+ else {
+ /* remove CRC */
+ hdlc->dstpos -= 2;
+ /* good frame */
+ status = hdlc->dstpos;
}
- hdlc->shift_reg = 0;
+ return status;
}
/*
@@ -121,40 +128,67 @@ void isdnhdlc_out_init (struct isdnhdlc_vars *hdlc, int is_d_channel, int do_ada
returns - number of decoded bytes in the destination buffer and status
flag.
*/
-int isdnhdlc_decode (struct isdnhdlc_vars *hdlc, const unsigned char *src,
- int slen, int *count, unsigned char *dst, int dsize)
+int isdnhdlc_decode(struct isdnhdlc_vars *hdlc, const u8 *src, int slen,
+ int *count, u8 *dst, int dsize)
{
- int status=0;
+ int status = 0;
- static const unsigned char fast_flag[]={
- 0x00,0x00,0x00,0x20,0x30,0x38,0x3c,0x3e,0x3f
+ static const unsigned char fast_flag[] = {
+ 0x00, 0x00, 0x00, 0x20, 0x30, 0x38, 0x3c, 0x3e, 0x3f
};
- static const unsigned char fast_flag_value[]={
- 0x00,0x7e,0xfc,0xf9,0xf3,0xe7,0xcf,0x9f,0x3f
+ static const unsigned char fast_flag_value[] = {
+ 0x00, 0x7e, 0xfc, 0xf9, 0xf3, 0xe7, 0xcf, 0x9f, 0x3f
};
- static const unsigned char fast_abort[]={
- 0x00,0x00,0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe,0xff
+ static const unsigned char fast_abort[] = {
+ 0x00, 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff
};
+#define handle_fast_flag(h) \
+ do {\
+ if (h->cbin == fast_flag[h->bit_shift]) {\
+ h->ffvalue = fast_flag_value[h->bit_shift];\
+ h->state = HDLC_FAST_FLAG;\
+ h->ffbit_shift = h->bit_shift;\
+ h->bit_shift = 1;\
+ } else {\
+ h->state = HDLC_GET_DATA;\
+ h->data_received = 0;\
+ } \
+ } while (0)
+
+#define handle_abort(h) \
+ do {\
+ h->shift_reg = fast_abort[h->ffbit_shift - 1];\
+ h->hdlc_bits1 = h->ffbit_shift - 2;\
+ if (h->hdlc_bits1 < 0)\
+ h->hdlc_bits1 = 0;\
+ h->data_bits = h->ffbit_shift - 1;\
+ h->state = HDLC_GET_DATA;\
+ h->data_received = 0;\
+ } while (0)
+
*count = slen;
- while(slen > 0){
- if(hdlc->bit_shift==0){
- hdlc->cbin = *src++;
+ while (slen > 0) {
+ if (hdlc->bit_shift == 0) {
+ /* the code is for bitreverse streams */
+ if (hdlc->do_bitreverse == 0)
+ hdlc->cbin = bitrev8(*src++);
+ else
+ hdlc->cbin = *src++;
slen--;
hdlc->bit_shift = 8;
- if(hdlc->do_adapt56){
- hdlc->bit_shift --;
- }
+ if (hdlc->do_adapt56)
+ hdlc->bit_shift--;
}
- switch(hdlc->state){
+ switch (hdlc->state) {
case STOPPED:
return 0;
case HDLC_FAST_IDLE:
- if(hdlc->cbin == 0xff){
+ if (hdlc->cbin == 0xff) {
hdlc->bit_shift = 0;
break;
}
@@ -163,32 +197,30 @@ int isdnhdlc_decode (struct isdnhdlc_vars *hdlc, const unsigned char *src,
hdlc->bit_shift = 8;
break;
case HDLC_GET_FLAG_B0:
- if(!(hdlc->cbin & 0x80)) {
+ if (!(hdlc->cbin & 0x80)) {
hdlc->state = HDLC_GETFLAG_B1A6;
hdlc->hdlc_bits1 = 0;
} else {
- if(!hdlc->do_adapt56){
- if(++hdlc->hdlc_bits1 >=8 ) if(hdlc->bit_shift==1)
+ if ((!hdlc->do_adapt56) &&
+ (++hdlc->hdlc_bits1 >= 8) &&
+ (hdlc->bit_shift == 1))
hdlc->state = HDLC_FAST_IDLE;
- }
}
- hdlc->cbin<<=1;
- hdlc->bit_shift --;
+ hdlc->cbin <<= 1;
+ hdlc->bit_shift--;
break;
case HDLC_GETFLAG_B1A6:
- if(hdlc->cbin & 0x80){
+ if (hdlc->cbin & 0x80) {
hdlc->hdlc_bits1++;
- if(hdlc->hdlc_bits1==6){
+ if (hdlc->hdlc_bits1 == 6)
hdlc->state = HDLC_GETFLAG_B7;
- }
- } else {
+ } else
hdlc->hdlc_bits1 = 0;
- }
- hdlc->cbin<<=1;
- hdlc->bit_shift --;
+ hdlc->cbin <<= 1;
+ hdlc->bit_shift--;
break;
case HDLC_GETFLAG_B7:
- if(hdlc->cbin & 0x80) {
+ if (hdlc->cbin & 0x80) {
hdlc->state = HDLC_GET_FLAG_B0;
} else {
hdlc->state = HDLC_GET_DATA;
@@ -198,74 +230,55 @@ int isdnhdlc_decode (struct isdnhdlc_vars *hdlc, const unsigned char *src,
hdlc->data_bits = 0;
hdlc->data_received = 0;
}
- hdlc->cbin<<=1;
- hdlc->bit_shift --;
+ hdlc->cbin <<= 1;
+ hdlc->bit_shift--;
break;
case HDLC_GET_DATA:
- if(hdlc->cbin & 0x80){
+ if (hdlc->cbin & 0x80) {
hdlc->hdlc_bits1++;
- switch(hdlc->hdlc_bits1){
+ switch (hdlc->hdlc_bits1) {
case 6:
break;
case 7:
- if(hdlc->data_received) {
- // bad frame
+ if (hdlc->data_received)
+ /* bad frame */
status = -HDLC_FRAMING_ERROR;
- }
- if(!hdlc->do_adapt56){
- if(hdlc->cbin==fast_abort[hdlc->bit_shift+1]){
- hdlc->state = HDLC_FAST_IDLE;
- hdlc->bit_shift=1;
+ if (!hdlc->do_adapt56) {
+ if (hdlc->cbin == fast_abort
+ [hdlc->bit_shift + 1]) {
+ hdlc->state =
+ HDLC_FAST_IDLE;
+ hdlc->bit_shift = 1;
break;
}
- } else {
+ } else
hdlc->state = HDLC_GET_FLAG_B0;
- }
break;
default:
- hdlc->shift_reg>>=1;
+ hdlc->shift_reg >>= 1;
hdlc->shift_reg |= 0x80;
hdlc->data_bits++;
break;
}
} else {
- switch(hdlc->hdlc_bits1){
+ switch (hdlc->hdlc_bits1) {
case 5:
break;
case 6:
- if(hdlc->data_received){
- if (hdlc->dstpos < 2) {
- status = -HDLC_FRAMING_ERROR;
- } else if (hdlc->crc != 0xf0b8){
- // crc error
- status = -HDLC_CRC_ERROR;
- } else {
- // remove CRC
- hdlc->dstpos -= 2;
- // good frame
- status = hdlc->dstpos;
- }
- }
+ if (hdlc->data_received)
+ status = check_frame(hdlc);
hdlc->crc = 0xffff;
hdlc->shift_reg = 0;
hdlc->data_bits = 0;
- if(!hdlc->do_adapt56){
- if(hdlc->cbin==fast_flag[hdlc->bit_shift]){
- hdlc->ffvalue = fast_flag_value[hdlc->bit_shift];
- hdlc->state = HDLC_FAST_FLAG;
- hdlc->ffbit_shift = hdlc->bit_shift;
- hdlc->bit_shift = 1;
- } else {
- hdlc->state = HDLC_GET_DATA;
- hdlc->data_received = 0;
- }
- } else {
+ if (!hdlc->do_adapt56)
+ handle_fast_flag(hdlc);
+ else {
hdlc->state = HDLC_GET_DATA;
hdlc->data_received = 0;
}
break;
default:
- hdlc->shift_reg>>=1;
+ hdlc->shift_reg >>= 1;
hdlc->data_bits++;
break;
}
@@ -278,16 +291,17 @@ int isdnhdlc_decode (struct isdnhdlc_vars *hdlc, const unsigned char *src,
hdlc->bit_shift--;
return status;
}
- if(hdlc->data_bits==8){
+ if (hdlc->data_bits == 8) {
hdlc->data_bits = 0;
hdlc->data_received = 1;
- hdlc->crc = crc_ccitt_byte(hdlc->crc, hdlc->shift_reg);
+ hdlc->crc = crc_ccitt_byte(hdlc->crc,
+ hdlc->shift_reg);
- // good byte received
- if (hdlc->dstpos < dsize) {
+ /* good byte received */
+ if (hdlc->dstpos < dsize)
dst[hdlc->dstpos++] = hdlc->shift_reg;
- } else {
- // frame too long
+ else {
+ /* frame too long */
status = -HDLC_LENGTH_ERROR;
hdlc->dstpos = 0;
}
@@ -296,24 +310,18 @@ int isdnhdlc_decode (struct isdnhdlc_vars *hdlc, const unsigned char *src,
hdlc->bit_shift--;
break;
case HDLC_FAST_FLAG:
- if(hdlc->cbin==hdlc->ffvalue){
+ if (hdlc->cbin == hdlc->ffvalue) {
hdlc->bit_shift = 0;
break;
} else {
- if(hdlc->cbin == 0xff){
+ if (hdlc->cbin == 0xff) {
hdlc->state = HDLC_FAST_IDLE;
- hdlc->bit_shift=0;
- } else if(hdlc->ffbit_shift==8){
+ hdlc->bit_shift = 0;
+ } else if (hdlc->ffbit_shift == 8) {
hdlc->state = HDLC_GETFLAG_B7;
break;
- } else {
- hdlc->shift_reg = fast_abort[hdlc->ffbit_shift-1];
- hdlc->hdlc_bits1 = hdlc->ffbit_shift-2;
- if(hdlc->hdlc_bits1<0)hdlc->hdlc_bits1 = 0;
- hdlc->data_bits = hdlc->ffbit_shift-1;
- hdlc->state = HDLC_GET_DATA;
- hdlc->data_received = 0;
- }
+ } else
+ handle_abort(hdlc);
}
break;
default:
@@ -323,7 +331,7 @@ int isdnhdlc_decode (struct isdnhdlc_vars *hdlc, const unsigned char *src,
*count -= slen;
return 0;
}
-
+EXPORT_SYMBOL(isdnhdlc_decode);
/*
isdnhdlc_encode - encodes HDLC frames to a transparent bit stream.
@@ -343,59 +351,70 @@ int isdnhdlc_decode (struct isdnhdlc_vars *hdlc, const unsigned char *src,
dsize - destination buffer size
returns - number of encoded bytes in the destination buffer
*/
-int isdnhdlc_encode(struct isdnhdlc_vars *hdlc, const unsigned char *src,
- unsigned short slen, int *count,
- unsigned char *dst, int dsize)
+int isdnhdlc_encode(struct isdnhdlc_vars *hdlc, const u8 *src, u16 slen,
+ int *count, u8 *dst, int dsize)
{
static const unsigned char xfast_flag_value[] = {
- 0x7e,0x3f,0x9f,0xcf,0xe7,0xf3,0xf9,0xfc,0x7e
+ 0x7e, 0x3f, 0x9f, 0xcf, 0xe7, 0xf3, 0xf9, 0xfc, 0x7e
};
int len = 0;
*count = slen;
+ /* special handling for one byte frames */
+ if ((slen == 1) && (hdlc->state == HDLC_SEND_FAST_FLAG))
+ hdlc->state = HDLC_SENDFLAG_ONE;
while (dsize > 0) {
- if(hdlc->bit_shift==0){
- if(slen && !hdlc->do_closing){
+ if (hdlc->bit_shift == 0) {
+ if (slen && !hdlc->do_closing) {
hdlc->shift_reg = *src++;
slen--;
if (slen == 0)
- hdlc->do_closing = 1; /* closing sequence, CRC + flag(s) */
+ /* closing sequence, CRC + flag(s) */
+ hdlc->do_closing = 1;
hdlc->bit_shift = 8;
} else {
- if(hdlc->state == HDLC_SEND_DATA){
- if(hdlc->data_received){
+ if (hdlc->state == HDLC_SEND_DATA) {
+ if (hdlc->data_received) {
hdlc->state = HDLC_SEND_CRC1;
hdlc->crc ^= 0xffff;
hdlc->bit_shift = 8;
- hdlc->shift_reg = hdlc->crc & 0xff;
- } else if(!hdlc->do_adapt56){
- hdlc->state = HDLC_SEND_FAST_FLAG;
- } else {
- hdlc->state = HDLC_SENDFLAG_B0;
- }
+ hdlc->shift_reg =
+ hdlc->crc & 0xff;
+ } else if (!hdlc->do_adapt56)
+ hdlc->state =
+ HDLC_SEND_FAST_FLAG;
+ else
+ hdlc->state =
+ HDLC_SENDFLAG_B0;
}
}
}
- switch(hdlc->state){
+ switch (hdlc->state) {
case STOPPED:
while (dsize--)
*dst++ = 0xff;
-
return dsize;
case HDLC_SEND_FAST_FLAG:
hdlc->do_closing = 0;
- if(slen == 0){
- *dst++ = hdlc->ffvalue;
+ if (slen == 0) {
+ /* the code is for bitreverse streams */
+ if (hdlc->do_bitreverse == 0)
+ *dst++ = bitrev8(hdlc->ffvalue);
+ else
+ *dst++ = hdlc->ffvalue;
len++;
dsize--;
break;
}
- if(hdlc->bit_shift==8){
- hdlc->cbin = hdlc->ffvalue>>(8-hdlc->data_bits);
+ /* fall through */
+ case HDLC_SENDFLAG_ONE:
+ if (hdlc->bit_shift == 8) {
+ hdlc->cbin = hdlc->ffvalue >>
+ (8 - hdlc->data_bits);
hdlc->state = HDLC_SEND_DATA;
hdlc->crc = 0xffff;
hdlc->hdlc_bits1 = 0;
@@ -413,17 +432,17 @@ int isdnhdlc_encode(struct isdnhdlc_vars *hdlc, const unsigned char *src,
hdlc->cbin <<= 1;
hdlc->data_bits++;
hdlc->cbin++;
- if(++hdlc->hdlc_bits1 == 6)
+ if (++hdlc->hdlc_bits1 == 6)
hdlc->state = HDLC_SENDFLAG_B7;
break;
case HDLC_SENDFLAG_B7:
hdlc->cbin <<= 1;
hdlc->data_bits++;
- if(slen == 0){
+ if (slen == 0) {
hdlc->state = HDLC_SENDFLAG_B0;
break;
}
- if(hdlc->bit_shift==8){
+ if (hdlc->bit_shift == 8) {
hdlc->state = HDLC_SEND_DATA;
hdlc->crc = 0xffff;
hdlc->hdlc_bits1 = 0;
@@ -432,7 +451,7 @@ int isdnhdlc_encode(struct isdnhdlc_vars *hdlc, const unsigned char *src,
break;
case HDLC_SEND_FIRST_FLAG:
hdlc->data_received = 1;
- if(hdlc->data_bits==8){
+ if (hdlc->data_bits == 8) {
hdlc->state = HDLC_SEND_DATA;
hdlc->crc = 0xffff;
hdlc->hdlc_bits1 = 0;
@@ -440,11 +459,11 @@ int isdnhdlc_encode(struct isdnhdlc_vars *hdlc, const unsigned char *src,
}
hdlc->cbin <<= 1;
hdlc->data_bits++;
- if(hdlc->shift_reg & 0x01)
+ if (hdlc->shift_reg & 0x01)
hdlc->cbin++;
hdlc->shift_reg >>= 1;
hdlc->bit_shift--;
- if(hdlc->bit_shift==0){
+ if (hdlc->bit_shift == 0) {
hdlc->state = HDLC_SEND_DATA;
hdlc->crc = 0xffff;
hdlc->hdlc_bits1 = 0;
@@ -453,14 +472,14 @@ int isdnhdlc_encode(struct isdnhdlc_vars *hdlc, const unsigned char *src,
case HDLC_SEND_DATA:
hdlc->cbin <<= 1;
hdlc->data_bits++;
- if(hdlc->hdlc_bits1 == 5){
+ if (hdlc->hdlc_bits1 == 5) {
hdlc->hdlc_bits1 = 0;
break;
}
- if(hdlc->bit_shift==8){
- hdlc->crc = crc_ccitt_byte(hdlc->crc, hdlc->shift_reg);
- }
- if(hdlc->shift_reg & 0x01){
+ if (hdlc->bit_shift == 8)
+ hdlc->crc = crc_ccitt_byte(hdlc->crc,
+ hdlc->shift_reg);
+ if (hdlc->shift_reg & 0x01) {
hdlc->hdlc_bits1++;
hdlc->cbin++;
hdlc->shift_reg >>= 1;
@@ -474,11 +493,11 @@ int isdnhdlc_encode(struct isdnhdlc_vars *hdlc, const unsigned char *src,
case HDLC_SEND_CRC1:
hdlc->cbin <<= 1;
hdlc->data_bits++;
- if(hdlc->hdlc_bits1 == 5){
+ if (hdlc->hdlc_bits1 == 5) {
hdlc->hdlc_bits1 = 0;
break;
}
- if(hdlc->shift_reg & 0x01){
+ if (hdlc->shift_reg & 0x01) {
hdlc->hdlc_bits1++;
hdlc->cbin++;
hdlc->shift_reg >>= 1;
@@ -488,7 +507,7 @@ int isdnhdlc_encode(struct isdnhdlc_vars *hdlc, const unsigned char *src,
hdlc->shift_reg >>= 1;
hdlc->bit_shift--;
}
- if(hdlc->bit_shift==0){
+ if (hdlc->bit_shift == 0) {
hdlc->shift_reg = (hdlc->crc >> 8);
hdlc->state = HDLC_SEND_CRC2;
hdlc->bit_shift = 8;
@@ -497,11 +516,11 @@ int isdnhdlc_encode(struct isdnhdlc_vars *hdlc, const unsigned char *src,
case HDLC_SEND_CRC2:
hdlc->cbin <<= 1;
hdlc->data_bits++;
- if(hdlc->hdlc_bits1 == 5){
+ if (hdlc->hdlc_bits1 == 5) {
hdlc->hdlc_bits1 = 0;
break;
}
- if(hdlc->shift_reg & 0x01){
+ if (hdlc->shift_reg & 0x01) {
hdlc->hdlc_bits1++;
hdlc->cbin++;
hdlc->shift_reg >>= 1;
@@ -511,7 +530,7 @@ int isdnhdlc_encode(struct isdnhdlc_vars *hdlc, const unsigned char *src,
hdlc->shift_reg >>= 1;
hdlc->bit_shift--;
}
- if(hdlc->bit_shift==0){
+ if (hdlc->bit_shift == 0) {
hdlc->shift_reg = 0x7e;
hdlc->state = HDLC_SEND_CLOSING_FLAG;
hdlc->bit_shift = 8;
@@ -520,33 +539,36 @@ int isdnhdlc_encode(struct isdnhdlc_vars *hdlc, const unsigned char *src,
case HDLC_SEND_CLOSING_FLAG:
hdlc->cbin <<= 1;
hdlc->data_bits++;
- if(hdlc->hdlc_bits1 == 5){
+ if (hdlc->hdlc_bits1 == 5) {
hdlc->hdlc_bits1 = 0;
break;
}
- if(hdlc->shift_reg & 0x01){
+ if (hdlc->shift_reg & 0x01)
hdlc->cbin++;
- }
hdlc->shift_reg >>= 1;
hdlc->bit_shift--;
- if(hdlc->bit_shift==0){
- hdlc->ffvalue = xfast_flag_value[hdlc->data_bits];
- if(hdlc->dchannel){
+ if (hdlc->bit_shift == 0) {
+ hdlc->ffvalue =
+ xfast_flag_value[hdlc->data_bits];
+ if (hdlc->dchannel) {
hdlc->ffvalue = 0x7e;
hdlc->state = HDLC_SEND_IDLE1;
hdlc->bit_shift = 8-hdlc->data_bits;
- if(hdlc->bit_shift==0)
- hdlc->state = HDLC_SEND_FAST_IDLE;
+ if (hdlc->bit_shift == 0)
+ hdlc->state =
+ HDLC_SEND_FAST_IDLE;
} else {
- if(!hdlc->do_adapt56){
- hdlc->state = HDLC_SEND_FAST_FLAG;
+ if (!hdlc->do_adapt56) {
+ hdlc->state =
+ HDLC_SEND_FAST_FLAG;
hdlc->data_received = 0;
} else {
hdlc->state = HDLC_SENDFLAG_B0;
hdlc->data_received = 0;
}
- // Finished with this frame, send flags
- if (dsize > 1) dsize = 1;
+ /* Finished this frame, send flags */
+ if (dsize > 1)
+ dsize = 1;
}
}
break;
@@ -556,7 +578,7 @@ int isdnhdlc_encode(struct isdnhdlc_vars *hdlc, const unsigned char *src,
hdlc->cbin++;
hdlc->data_bits++;
hdlc->bit_shift--;
- if(hdlc->bit_shift==0){
+ if (hdlc->bit_shift == 0) {
hdlc->state = HDLC_SEND_FAST_IDLE;
hdlc->bit_shift = 0;
}
@@ -565,12 +587,17 @@ int isdnhdlc_encode(struct isdnhdlc_vars *hdlc, const unsigned char *src,
hdlc->do_closing = 0;
hdlc->cbin = 0xff;
hdlc->data_bits = 8;
- if(hdlc->bit_shift == 8){
+ if (hdlc->bit_shift == 8) {
hdlc->cbin = 0x7e;
hdlc->state = HDLC_SEND_FIRST_FLAG;
} else {
- *dst++ = hdlc->cbin;
- hdlc->bit_shift = hdlc->data_bits = 0;
+ /* the code is for bitreverse streams */
+ if (hdlc->do_bitreverse == 0)
+ *dst++ = bitrev8(hdlc->cbin);
+ else
+ *dst++ = hdlc->cbin;
+ hdlc->bit_shift = 0;
+ hdlc->data_bits = 0;
len++;
dsize = 0;
}
@@ -578,15 +605,19 @@ int isdnhdlc_encode(struct isdnhdlc_vars *hdlc, const unsigned char *src,
default:
break;
}
- if(hdlc->do_adapt56){
- if(hdlc->data_bits==7){
+ if (hdlc->do_adapt56) {
+ if (hdlc->data_bits == 7) {
hdlc->cbin <<= 1;
hdlc->cbin++;
hdlc->data_bits++;
}
}
- if(hdlc->data_bits==8){
- *dst++ = hdlc->cbin;
+ if (hdlc->data_bits == 8) {
+ /* the code is for bitreverse streams */
+ if (hdlc->do_bitreverse == 0)
+ *dst++ = bitrev8(hdlc->cbin);
+ else
+ *dst++ = hdlc->cbin;
hdlc->data_bits = 0;
len++;
dsize--;
@@ -596,8 +627,4 @@ int isdnhdlc_encode(struct isdnhdlc_vars *hdlc, const unsigned char *src,
return len;
}
-
-EXPORT_SYMBOL(isdnhdlc_rcv_init);
-EXPORT_SYMBOL(isdnhdlc_decode);
-EXPORT_SYMBOL(isdnhdlc_out_init);
EXPORT_SYMBOL(isdnhdlc_encode);
diff --git a/drivers/isdn/mISDN/hwchannel.c b/drivers/isdn/mISDN/hwchannel.c
index 0481a0cdf6d..e8049be552a 100644
--- a/drivers/isdn/mISDN/hwchannel.c
+++ b/drivers/isdn/mISDN/hwchannel.c
@@ -114,13 +114,14 @@ mISDN_freedchannel(struct dchannel *ch)
}
EXPORT_SYMBOL(mISDN_freedchannel);
-int
-mISDN_freebchannel(struct bchannel *ch)
+void
+mISDN_clear_bchannel(struct bchannel *ch)
{
if (ch->tx_skb) {
dev_kfree_skb(ch->tx_skb);
ch->tx_skb = NULL;
}
+ ch->tx_idx = 0;
if (ch->rx_skb) {
dev_kfree_skb(ch->rx_skb);
ch->rx_skb = NULL;
@@ -129,6 +130,16 @@ mISDN_freebchannel(struct bchannel *ch)
dev_kfree_skb(ch->next_skb);
ch->next_skb = NULL;
}
+ test_and_clear_bit(FLG_TX_BUSY, &ch->Flags);
+ test_and_clear_bit(FLG_TX_NEXT, &ch->Flags);
+ test_and_clear_bit(FLG_ACTIVE, &ch->Flags);
+}
+EXPORT_SYMBOL(mISDN_clear_bchannel);
+
+int
+mISDN_freebchannel(struct bchannel *ch)
+{
+ mISDN_clear_bchannel(ch);
skb_queue_purge(&ch->rqueue);
ch->rcount = 0;
flush_scheduled_work();
diff --git a/drivers/isdn/mISDN/layer2.c b/drivers/isdn/mISDN/layer2.c
index 9c2589e986d..e17f0044e0b 100644
--- a/drivers/isdn/mISDN/layer2.c
+++ b/drivers/isdn/mISDN/layer2.c
@@ -1832,8 +1832,6 @@ static struct FsmNode L2FnList[] =
{ST_L2_8, EV_L1_DEACTIVATE, l2_persistant_da},
};
-#define L2_FN_COUNT (sizeof(L2FnList)/sizeof(struct FsmNode))
-
static int
ph_data_indication(struct layer2 *l2, struct mISDNhead *hh, struct sk_buff *skb)
{
diff --git a/drivers/media/dvb/dvb-core/dvb_net.c b/drivers/media/dvb/dvb-core/dvb_net.c
index 8280f8d66a3..8c9ae0a3a27 100644
--- a/drivers/media/dvb/dvb-core/dvb_net.c
+++ b/drivers/media/dvb/dvb-core/dvb_net.c
@@ -904,7 +904,7 @@ static int dvb_net_sec_callback(const u8 *buffer1, size_t buffer1_len,
static int dvb_net_tx(struct sk_buff *skb, struct net_device *dev)
{
dev_kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
}
static u8 mask_normal[6]={0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
diff --git a/drivers/message/fusion/mptlan.c b/drivers/message/fusion/mptlan.c
index a9e48e28b1d..bc2ec2182c0 100644
--- a/drivers/message/fusion/mptlan.c
+++ b/drivers/message/fusion/mptlan.c
@@ -795,7 +795,7 @@ mpt_lan_sdu_send (struct sk_buff *skb, struct net_device *dev)
IOC_AND_NETDEV_NAMES_s_s(dev),
le32_to_cpu(pSimple->FlagsLength)));
- return 0;
+ return NETDEV_TX_OK;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
diff --git a/drivers/misc/sgi-xp/xpnet.c b/drivers/misc/sgi-xp/xpnet.c
index 5d778ec8cdb..212da9af1ce 100644
--- a/drivers/misc/sgi-xp/xpnet.c
+++ b/drivers/misc/sgi-xp/xpnet.c
@@ -436,7 +436,7 @@ xpnet_dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
if (skb->data[0] == 0x33) {
dev_kfree_skb(skb);
- return 0; /* nothing needed to be done */
+ return NETDEV_TX_OK; /* nothing needed to be done */
}
/*
@@ -503,7 +503,7 @@ xpnet_dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
dev->stats.tx_packets++;
dev->stats.tx_bytes += skb->len;
- return 0;
+ return NETDEV_TX_OK;
}
/*
diff --git a/drivers/net/3c501.c b/drivers/net/3c501.c
index 367bec63620..e29fb1a4a61 100644
--- a/drivers/net/3c501.c
+++ b/drivers/net/3c501.c
@@ -485,7 +485,7 @@ static int el_start_xmit(struct sk_buff *skb, struct net_device *dev)
if (el_debug > 2)
pr_debug(" queued xmit.\n");
dev_kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
}
/* A receive upset our load, despite our best efforts */
if (el_debug > 2)
diff --git a/drivers/net/3c505.c b/drivers/net/3c505.c
index f71b3540275..7bba480d722 100644
--- a/drivers/net/3c505.c
+++ b/drivers/net/3c505.c
@@ -1101,7 +1101,7 @@ static int elp_start_xmit(struct sk_buff *skb, struct net_device *dev)
prime_rx(dev);
spin_unlock_irqrestore(&adapter->lock, flags);
netif_start_queue(dev);
- return 0;
+ return NETDEV_TX_OK;
}
/******************************************************
diff --git a/drivers/net/3c507.c b/drivers/net/3c507.c
index 96b86659381..9e93a0b39b6 100644
--- a/drivers/net/3c507.c
+++ b/drivers/net/3c507.c
@@ -537,7 +537,7 @@ static int el16_send_packet (struct sk_buff *skb, struct net_device *dev)
/* You might need to clean up and record Tx statistics here. */
- return 0;
+ return NETDEV_TX_OK;
}
/* The typical workload of the driver:
diff --git a/drivers/net/3c509.c b/drivers/net/3c509.c
index d2137efbd45..d2515d840c0 100644
--- a/drivers/net/3c509.c
+++ b/drivers/net/3c509.c
@@ -892,7 +892,7 @@ el3_start_xmit(struct sk_buff *skb, struct net_device *dev)
outb(0x00, ioaddr + TX_STATUS); /* Pop the status stack. */
}
}
- return 0;
+ return NETDEV_TX_OK;
}
/* The EL3 interrupt handler. */
diff --git a/drivers/net/3c515.c b/drivers/net/3c515.c
index 4a7c32895be..3116410b349 100644
--- a/drivers/net/3c515.c
+++ b/drivers/net/3c515.c
@@ -1056,7 +1056,7 @@ static int corkscrew_start_xmit(struct sk_buff *skb,
netif_wake_queue(dev);
}
dev->trans_start = jiffies;
- return 0;
+ return NETDEV_TX_OK;
}
/* Put out the doubleword header... */
outl(skb->len, ioaddr + TX_FIFO);
@@ -1119,7 +1119,7 @@ static int corkscrew_start_xmit(struct sk_buff *skb,
outb(0x00, ioaddr + TxStatus); /* Pop the status stack. */
}
}
- return 0;
+ return NETDEV_TX_OK;
}
/* The interrupt handler does all of the Rx thread work and cleans up
diff --git a/drivers/net/3c523.c b/drivers/net/3c523.c
index cdd955c4014..70c701b80d9 100644
--- a/drivers/net/3c523.c
+++ b/drivers/net/3c523.c
@@ -1198,7 +1198,7 @@ static int elmc_send_packet(struct sk_buff *skb, struct net_device *dev)
netif_wake_queue(dev);
dev_kfree_skb(skb);
#endif
- return 0;
+ return NETDEV_TX_OK;
}
/*******************************************
diff --git a/drivers/net/3c527.c b/drivers/net/3c527.c
index aaa8a9f405d..72b9ed7f464 100644
--- a/drivers/net/3c527.c
+++ b/drivers/net/3c527.c
@@ -1035,7 +1035,7 @@ static int mc32_send_packet(struct sk_buff *skb, struct net_device *dev)
if (skb_padto(skb, ETH_ZLEN)) {
netif_wake_queue(dev);
- return 0;
+ return NETDEV_TX_OK;
}
atomic_dec(&lp->tx_count);
@@ -1066,7 +1066,7 @@ static int mc32_send_packet(struct sk_buff *skb, struct net_device *dev)
p->control &= ~CONTROL_EOL;
netif_wake_queue(dev);
- return 0;
+ return NETDEV_TX_OK;
}
diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c
index 45675889850..beb040264db 100644
--- a/drivers/net/3c59x.c
+++ b/drivers/net/3c59x.c
@@ -2087,7 +2087,7 @@ vortex_start_xmit(struct sk_buff *skb, struct net_device *dev)
iowrite8(0x00, ioaddr + TxStatus); /* Pop the status stack. */
}
}
- return 0;
+ return NETDEV_TX_OK;
}
static int
@@ -2177,7 +2177,7 @@ boomerang_start_xmit(struct sk_buff *skb, struct net_device *dev)
iowrite16(DownUnstall, ioaddr + EL3_CMD);
spin_unlock_irqrestore(&vp->lock, flags);
dev->trans_start = jiffies;
- return 0;
+ return NETDEV_TX_OK;
}
/* The interrupt handler does all of the Rx thread work and cleans up
diff --git a/drivers/net/7990.c b/drivers/net/7990.c
index 69f5b7d298a..b1e5764628c 100644
--- a/drivers/net/7990.c
+++ b/drivers/net/7990.c
@@ -585,7 +585,7 @@ int lance_start_xmit (struct sk_buff *skb, struct net_device *dev)
lp->tx_full = 1;
spin_unlock_irqrestore (&lp->devlock, flags);
- return 0;
+ return NETDEV_TX_OK;
}
EXPORT_SYMBOL_GPL(lance_start_xmit);
diff --git a/drivers/net/8139cp.c b/drivers/net/8139cp.c
index d0dbbf39349..4a8995aaeca 100644
--- a/drivers/net/8139cp.c
+++ b/drivers/net/8139cp.c
@@ -890,7 +890,7 @@ static int cp_start_xmit (struct sk_buff *skb, struct net_device *dev)
cpw8(TxPoll, NormalTxPoll);
dev->trans_start = jiffies;
- return 0;
+ return NETDEV_TX_OK;
}
/* Set or clear the multicast filter for this adaptor.
diff --git a/drivers/net/8139too.c b/drivers/net/8139too.c
index 0e2ba21d444..b39ec98345e 100644
--- a/drivers/net/8139too.c
+++ b/drivers/net/8139too.c
@@ -1707,7 +1707,7 @@ static int rtl8139_start_xmit (struct sk_buff *skb, struct net_device *dev)
} else {
dev_kfree_skb(skb);
dev->stats.tx_dropped++;
- return 0;
+ return NETDEV_TX_OK;
}
spin_lock_irqsave(&tp->lock, flags);
@@ -1732,7 +1732,7 @@ static int rtl8139_start_xmit (struct sk_buff *skb, struct net_device *dev)
pr_debug("%s: Queued Tx packet size %u to slot %d.\n",
dev->name, len, entry);
- return 0;
+ return NETDEV_TX_OK;
}
diff --git a/drivers/net/82596.c b/drivers/net/82596.c
index 77547545509..996cc910221 100644
--- a/drivers/net/82596.c
+++ b/drivers/net/82596.c
@@ -1068,7 +1068,7 @@ static int i596_start_xmit(struct sk_buff *skb, struct net_device *dev)
if (skb->len < ETH_ZLEN) {
if (skb_padto(skb, ETH_ZLEN))
- return 0;
+ return NETDEV_TX_OK;
length = ETH_ZLEN;
}
netif_stop_queue(dev);
@@ -1110,7 +1110,7 @@ static int i596_start_xmit(struct sk_buff *skb, struct net_device *dev)
netif_start_queue(dev);
- return 0;
+ return NETDEV_TX_OK;
}
static void print_eth(unsigned char *add, char *str)
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 5f6509a5f64..29935a9fb1a 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -1774,7 +1774,7 @@ config SC92031
config CPMAC
tristate "TI AR7 CPMAC Ethernet support (EXPERIMENTAL)"
- depends on NET_ETHERNET && EXPERIMENTAL && AR7 && BROKEN
+ depends on NET_ETHERNET && EXPERIMENTAL && AR7
select PHYLIB
help
TI AR7 CPMAC Ethernet support
@@ -2722,6 +2722,7 @@ config BNX2X
select FW_LOADER
select ZLIB_INFLATE
select LIBCRC32C
+ select MDIO
help
This driver supports Broadcom NetXtremeII 10 gigabit Ethernet cards.
To compile this driver as a module, choose M here: the module
diff --git a/drivers/net/a2065.c b/drivers/net/a2065.c
index 08787f5a22a..174a81187a9 100644
--- a/drivers/net/a2065.c
+++ b/drivers/net/a2065.c
@@ -553,11 +553,11 @@ static int lance_start_xmit (struct sk_buff *skb, struct net_device *dev)
volatile struct lance_regs *ll = lp->ll;
volatile struct lance_init_block *ib = lp->init_block;
int entry, skblen;
- int status = 0;
+ int status = NETDEV_TX_OK;
unsigned long flags;
if (skb_padto(skb, ETH_ZLEN))
- return 0;
+ return NETDEV_TX_OK;
skblen = max_t(unsigned, skb->len, ETH_ZLEN);
local_irq_save(flags);
diff --git a/drivers/net/amd8111e.c b/drivers/net/amd8111e.c
index 19831bd6401..61ac671f97b 100644
--- a/drivers/net/amd8111e.c
+++ b/drivers/net/amd8111e.c
@@ -1346,7 +1346,7 @@ static int amd8111e_start_xmit(struct sk_buff *skb, struct net_device * dev)
netif_stop_queue(dev);
}
spin_unlock_irqrestore(&lp->lock, flags);
- return 0;
+ return NETDEV_TX_OK;
}
/*
This function returns all the memory mapped registers of the device.
diff --git a/drivers/net/appletalk/cops.c b/drivers/net/appletalk/cops.c
index 7f832541980..29b279f88ef 100644
--- a/drivers/net/appletalk/cops.c
+++ b/drivers/net/appletalk/cops.c
@@ -920,7 +920,7 @@ static int cops_send_packet(struct sk_buff *skb, struct net_device *dev)
dev->stats.tx_bytes += skb->len;
dev->trans_start = jiffies;
dev_kfree_skb (skb);
- return 0;
+ return NETDEV_TX_OK;
}
/*
diff --git a/drivers/net/appletalk/ipddp.c b/drivers/net/appletalk/ipddp.c
index 78cea5e80b1..6cfd961bb8d 100644
--- a/drivers/net/appletalk/ipddp.c
+++ b/drivers/net/appletalk/ipddp.c
@@ -132,7 +132,7 @@ static int ipddp_xmit(struct sk_buff *skb, struct net_device *dev)
}
if(rt == NULL) {
spin_unlock(&ipddp_route_lock);
- return 0;
+ return NETDEV_TX_OK;
}
our_addr = atalk_find_dev_addr(rt->dev);
@@ -181,7 +181,7 @@ static int ipddp_xmit(struct sk_buff *skb, struct net_device *dev)
spin_unlock(&ipddp_route_lock);
- return 0;
+ return NETDEV_TX_OK;
}
/*
diff --git a/drivers/net/appletalk/ltpc.c b/drivers/net/appletalk/ltpc.c
index b642647170b..c80fb9cf8ff 100644
--- a/drivers/net/appletalk/ltpc.c
+++ b/drivers/net/appletalk/ltpc.c
@@ -932,7 +932,7 @@ static int ltpc_xmit(struct sk_buff *skb, struct net_device *dev)
dev->stats.tx_bytes += skb->len;
dev_kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
}
/* initialization stuff */
diff --git a/drivers/net/ariadne.c b/drivers/net/ariadne.c
index 58e8d522e5b..47d976cc3d7 100644
--- a/drivers/net/ariadne.c
+++ b/drivers/net/ariadne.c
@@ -610,7 +610,7 @@ static int ariadne_start_xmit(struct sk_buff *skb, struct net_device *dev)
if (skb->len < ETH_ZLEN)
{
if (skb_padto(skb, ETH_ZLEN))
- return 0;
+ return NETDEV_TX_OK;
len = ETH_ZLEN;
}
@@ -685,7 +685,7 @@ static int ariadne_start_xmit(struct sk_buff *skb, struct net_device *dev)
}
local_irq_restore(flags);
- return 0;
+ return NETDEV_TX_OK;
}
diff --git a/drivers/net/arm/am79c961a.c b/drivers/net/arm/am79c961a.c
index 627bc75da17..164b37e85ee 100644
--- a/drivers/net/arm/am79c961a.c
+++ b/drivers/net/arm/am79c961a.c
@@ -482,7 +482,7 @@ am79c961_sendpacket(struct sk_buff *skb, struct net_device *dev)
dev_kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
}
/*
diff --git a/drivers/net/arm/at91_ether.c b/drivers/net/arm/at91_ether.c
index 5041d10bae9..c8bc60a7040 100644
--- a/drivers/net/arm/at91_ether.c
+++ b/drivers/net/arm/at91_ether.c
@@ -834,7 +834,7 @@ static int at91ether_start_xmit(struct sk_buff *skb, struct net_device *dev)
we free and return(0) or don't free and return 1 */
}
- return 0;
+ return NETDEV_TX_OK;
}
/*
diff --git a/drivers/net/arm/ether1.c b/drivers/net/arm/ether1.c
index edf770f639f..e47c0d96285 100644
--- a/drivers/net/arm/ether1.c
+++ b/drivers/net/arm/ether1.c
@@ -748,7 +748,7 @@ ether1_sendpacket (struct sk_buff *skb, struct net_device *dev)
netif_stop_queue(dev);
out:
- return 0;
+ return NETDEV_TX_OK;
}
static void
diff --git a/drivers/net/arm/ether3.c b/drivers/net/arm/ether3.c
index 455037134aa..1f7a69c929a 100644
--- a/drivers/net/arm/ether3.c
+++ b/drivers/net/arm/ether3.c
@@ -511,7 +511,7 @@ ether3_sendpacket(struct sk_buff *skb, struct net_device *dev)
dev_kfree_skb(skb);
priv(dev)->stats.tx_dropped ++;
netif_start_queue(dev);
- return 0;
+ return NETDEV_TX_OK;
}
length = (length + 1) & ~1;
@@ -562,7 +562,7 @@ ether3_sendpacket(struct sk_buff *skb, struct net_device *dev)
netif_stop_queue(dev);
out:
- return 0;
+ return NETDEV_TX_OK;
}
static irqreturn_t
diff --git a/drivers/net/arm/w90p910_ether.c b/drivers/net/arm/w90p910_ether.c
index 616fb7985a3..890716f6c01 100644
--- a/drivers/net/arm/w90p910_ether.c
+++ b/drivers/net/arm/w90p910_ether.c
@@ -143,16 +143,17 @@ struct recv_pdesc {
struct tran_pdesc {
struct w90p910_txbd desclist[TX_DESC_SIZE];
- char tran_buf[RX_DESC_SIZE][MAX_TBUFF_SZ];
+ char tran_buf[TX_DESC_SIZE][MAX_TBUFF_SZ];
};
struct w90p910_ether {
struct recv_pdesc *rdesc;
- struct recv_pdesc *rdesc_phys;
struct tran_pdesc *tdesc;
- struct tran_pdesc *tdesc_phys;
+ dma_addr_t rdesc_phys;
+ dma_addr_t tdesc_phys;
struct net_device_stats stats;
struct platform_device *pdev;
+ struct resource *res;
struct sk_buff *skb;
struct clk *clk;
struct clk *rmiiclk;
@@ -169,7 +170,6 @@ struct w90p910_ether {
unsigned int start_tx_ptr;
unsigned int start_rx_ptr;
unsigned int linkflag;
- spinlock_t lock;
};
static void update_linkspeed_register(struct net_device *dev,
@@ -275,59 +275,75 @@ static void w90p910_write_cam(struct net_device *dev,
__raw_writel(msw, ether->reg + REG_CAMM_BASE + x * CAM_ENTRY_SIZE);
}
-static void w90p910_init_desc(struct net_device *dev)
+static int w90p910_init_desc(struct net_device *dev)
{
struct w90p910_ether *ether;
- struct w90p910_txbd *tdesc, *tdesc_phys;
- struct w90p910_rxbd *rdesc, *rdesc_phys;
- unsigned int i, j;
+ struct w90p910_txbd *tdesc;
+ struct w90p910_rxbd *rdesc;
+ struct platform_device *pdev;
+ unsigned int i;
ether = netdev_priv(dev);
+ pdev = ether->pdev;
ether->tdesc = (struct tran_pdesc *)
- dma_alloc_coherent(NULL, sizeof(struct tran_pdesc),
- (dma_addr_t *) &ether->tdesc_phys, GFP_KERNEL);
+ dma_alloc_coherent(&pdev->dev, sizeof(struct tran_pdesc),
+ &ether->tdesc_phys, GFP_KERNEL);
+
+ if (!ether->tdesc) {
+ dev_err(&pdev->dev, "Failed to allocate memory for tx desc\n");
+ return -ENOMEM;
+ }
ether->rdesc = (struct recv_pdesc *)
- dma_alloc_coherent(NULL, sizeof(struct recv_pdesc),
- (dma_addr_t *) &ether->rdesc_phys, GFP_KERNEL);
+ dma_alloc_coherent(&pdev->dev, sizeof(struct recv_pdesc),
+ &ether->rdesc_phys, GFP_KERNEL);
+
+ if (!ether->rdesc) {
+ dev_err(&pdev->dev, "Failed to allocate memory for rx desc\n");
+ dma_free_coherent(&pdev->dev, sizeof(struct tran_pdesc),
+ ether->tdesc, ether->tdesc_phys);
+ return -ENOMEM;
+ }
for (i = 0; i < TX_DESC_SIZE; i++) {
- tdesc = &(ether->tdesc->desclist[i]);
+ unsigned int offset;
- j = ((i + 1) / TX_DESC_SIZE);
+ tdesc = &(ether->tdesc->desclist[i]);
- if (j != 0) {
- tdesc_phys = &(ether->tdesc_phys->desclist[0]);
- ether->start_tx_ptr = (unsigned int)tdesc_phys;
- tdesc->next = (unsigned int)ether->start_tx_ptr;
- } else {
- tdesc_phys = &(ether->tdesc_phys->desclist[i+1]);
- tdesc->next = (unsigned int)tdesc_phys;
- }
+ if (i == TX_DESC_SIZE - 1)
+ offset = offsetof(struct tran_pdesc, desclist[0]);
+ else
+ offset = offsetof(struct tran_pdesc, desclist[i + 1]);
- tdesc->buffer = (unsigned int)ether->tdesc_phys->tran_buf[i];
+ tdesc->next = ether->tdesc_phys + offset;
+ tdesc->buffer = ether->tdesc_phys +
+ offsetof(struct tran_pdesc, tran_buf[i]);
tdesc->sl = 0;
tdesc->mode = 0;
}
+ ether->start_tx_ptr = ether->tdesc_phys;
+
for (i = 0; i < RX_DESC_SIZE; i++) {
- rdesc = &(ether->rdesc->desclist[i]);
+ unsigned int offset;
- j = ((i + 1) / RX_DESC_SIZE);
+ rdesc = &(ether->rdesc->desclist[i]);
- if (j != 0) {
- rdesc_phys = &(ether->rdesc_phys->desclist[0]);
- ether->start_rx_ptr = (unsigned int)rdesc_phys;
- rdesc->next = (unsigned int)ether->start_rx_ptr;
- } else {
- rdesc_phys = &(ether->rdesc_phys->desclist[i+1]);
- rdesc->next = (unsigned int)rdesc_phys;
- }
+ if (i == RX_DESC_SIZE - 1)
+ offset = offsetof(struct recv_pdesc, desclist[0]);
+ else
+ offset = offsetof(struct recv_pdesc, desclist[i + 1]);
+ rdesc->next = ether->rdesc_phys + offset;
rdesc->sl = RX_OWEN_DMA;
- rdesc->buffer = (unsigned int)ether->rdesc_phys->recv_buf[i];
+ rdesc->buffer = ether->rdesc_phys +
+ offsetof(struct recv_pdesc, recv_buf[i]);
}
+
+ ether->start_rx_ptr = ether->rdesc_phys;
+
+ return 0;
}
static void w90p910_set_fifo_threshold(struct net_device *dev)
@@ -456,8 +472,6 @@ static void w90p910_reset_mac(struct net_device *dev)
{
struct w90p910_ether *ether = netdev_priv(dev);
- spin_lock(&ether->lock);
-
w90p910_enable_tx(dev, 0);
w90p910_enable_rx(dev, 0);
w90p910_set_fifo_threshold(dev);
@@ -486,8 +500,6 @@ static void w90p910_reset_mac(struct net_device *dev)
if (netif_queue_stopped(dev))
netif_wake_queue(dev);
-
- spin_unlock(&ether->lock);
}
static void w90p910_mdio_write(struct net_device *dev,
@@ -541,7 +553,7 @@ static int w90p910_mdio_read(struct net_device *dev, int phy_id, int reg)
return data;
}
-static int set_mac_address(struct net_device *dev, void *addr)
+static int w90p910_set_mac_address(struct net_device *dev, void *addr)
{
struct sockaddr *address = addr;
@@ -557,11 +569,14 @@ static int set_mac_address(struct net_device *dev, void *addr)
static int w90p910_ether_close(struct net_device *dev)
{
struct w90p910_ether *ether = netdev_priv(dev);
+ struct platform_device *pdev;
- dma_free_writecombine(NULL, sizeof(struct w90p910_rxbd),
- ether->rdesc, (dma_addr_t)ether->rdesc_phys);
- dma_free_writecombine(NULL, sizeof(struct w90p910_txbd),
- ether->tdesc, (dma_addr_t)ether->tdesc_phys);
+ pdev = ether->pdev;
+
+ dma_free_coherent(&pdev->dev, sizeof(struct recv_pdesc),
+ ether->rdesc, ether->rdesc_phys);
+ dma_free_coherent(&pdev->dev, sizeof(struct tran_pdesc),
+ ether->tdesc, ether->tdesc_phys);
netif_stop_queue(dev);
@@ -597,6 +612,7 @@ static int w90p910_send_frame(struct net_device *dev,
txbd = &ether->tdesc->desclist[ether->cur_tx];
buffer = ether->tdesc->tran_buf[ether->cur_tx];
+
if (length > 1514) {
dev_err(&pdev->dev, "send data %d bytes, check it\n", length);
length = 1514;
@@ -612,7 +628,9 @@ static int w90p910_send_frame(struct net_device *dev,
w90p910_trigger_tx(dev);
- ether->cur_tx = (ether->cur_tx+1) % TX_DESC_SIZE;
+ if (++ether->cur_tx >= TX_DESC_SIZE)
+ ether->cur_tx = 0;
+
txbd = &ether->tdesc->desclist[ether->cur_tx];
dev->trans_start = jiffies;
@@ -632,7 +650,7 @@ static int w90p910_ether_start_xmit(struct sk_buff *skb, struct net_device *dev)
dev_kfree_skb_irq(skb);
return 0;
}
- return -1;
+ return -EAGAIN;
}
static irqreturn_t w90p910_tx_interrupt(int irq, void *dev_id)
@@ -640,27 +658,25 @@ static irqreturn_t w90p910_tx_interrupt(int irq, void *dev_id)
struct w90p910_ether *ether;
struct w90p910_txbd *txbd;
struct platform_device *pdev;
- struct tran_pdesc *tran_pdesc;
struct net_device *dev;
unsigned int cur_entry, entry, status;
- dev = (struct net_device *)dev_id;
+ dev = dev_id;
ether = netdev_priv(dev);
pdev = ether->pdev;
- spin_lock(&ether->lock);
-
w90p910_get_and_clear_int(dev, &status);
cur_entry = __raw_readl(ether->reg + REG_CTXDSA);
- tran_pdesc = ether->tdesc_phys;
- entry = (unsigned int)(&tran_pdesc->desclist[ether->finish_tx]);
+ entry = ether->tdesc_phys +
+ offsetof(struct tran_pdesc, desclist[ether->finish_tx]);
while (entry != cur_entry) {
txbd = &ether->tdesc->desclist[ether->finish_tx];
- ether->finish_tx = (ether->finish_tx + 1) % TX_DESC_SIZE;
+ if (++ether->finish_tx >= TX_DESC_SIZE)
+ ether->finish_tx = 0;
if (txbd->sl & TXDS_TXCP) {
ether->stats.tx_packets++;
@@ -675,20 +691,19 @@ static irqreturn_t w90p910_tx_interrupt(int irq, void *dev_id)
if (netif_queue_stopped(dev))
netif_wake_queue(dev);
- entry = (unsigned int)(&tran_pdesc->desclist[ether->finish_tx]);
+ entry = ether->tdesc_phys +
+ offsetof(struct tran_pdesc, desclist[ether->finish_tx]);
}
if (status & MISTA_EXDEF) {
dev_err(&pdev->dev, "emc defer exceed interrupt\n");
} else if (status & MISTA_TXBERR) {
- dev_err(&pdev->dev, "emc bus error interrupt\n");
- w90p910_reset_mac(dev);
- } else if (status & MISTA_TDU) {
- if (netif_queue_stopped(dev))
- netif_wake_queue(dev);
- }
-
- spin_unlock(&ether->lock);
+ dev_err(&pdev->dev, "emc bus error interrupt\n");
+ w90p910_reset_mac(dev);
+ } else if (status & MISTA_TDU) {
+ if (netif_queue_stopped(dev))
+ netif_wake_queue(dev);
+ }
return IRQ_HANDLED;
}
@@ -698,20 +713,20 @@ static void netdev_rx(struct net_device *dev)
struct w90p910_ether *ether;
struct w90p910_rxbd *rxbd;
struct platform_device *pdev;
- struct recv_pdesc *rdesc_phys;
struct sk_buff *skb;
unsigned char *data;
unsigned int length, status, val, entry;
ether = netdev_priv(dev);
pdev = ether->pdev;
- rdesc_phys = ether->rdesc_phys;
rxbd = &ether->rdesc->desclist[ether->cur_rx];
do {
val = __raw_readl(ether->reg + REG_CRXDSA);
- entry = (unsigned int)&rdesc_phys->desclist[ether->cur_rx];
+
+ entry = ether->rdesc_phys +
+ offsetof(struct recv_pdesc, desclist[ether->cur_rx]);
if (val == entry)
break;
@@ -743,22 +758,23 @@ static void netdev_rx(struct net_device *dev)
dev_err(&pdev->dev, "rx runt err\n");
ether->stats.rx_length_errors++;
} else if (status & RXDS_CRCE) {
- dev_err(&pdev->dev, "rx crc err\n");
- ether->stats.rx_crc_errors++;
- }
-
- if (status & RXDS_ALIE) {
+ dev_err(&pdev->dev, "rx crc err\n");
+ ether->stats.rx_crc_errors++;
+ } else if (status & RXDS_ALIE) {
dev_err(&pdev->dev, "rx aligment err\n");
ether->stats.rx_frame_errors++;
} else if (status & RXDS_PTLE) {
- dev_err(&pdev->dev, "rx longer err\n");
- ether->stats.rx_over_errors++;
- }
+ dev_err(&pdev->dev, "rx longer err\n");
+ ether->stats.rx_over_errors++;
}
+ }
rxbd->sl = RX_OWEN_DMA;
rxbd->reserved = 0x0;
- ether->cur_rx = (ether->cur_rx+1) % RX_DESC_SIZE;
+
+ if (++ether->cur_rx >= RX_DESC_SIZE)
+ ether->cur_rx = 0;
+
rxbd = &ether->rdesc->desclist[ether->cur_rx];
dev->last_rx = jiffies;
@@ -772,28 +788,23 @@ static irqreturn_t w90p910_rx_interrupt(int irq, void *dev_id)
struct platform_device *pdev;
unsigned int status;
- dev = (struct net_device *)dev_id;
+ dev = dev_id;
ether = netdev_priv(dev);
pdev = ether->pdev;
- spin_lock(&ether->lock);
-
w90p910_get_and_clear_int(dev, &status);
if (status & MISTA_RDU) {
netdev_rx(dev);
-
w90p910_trigger_rx(dev);
- spin_unlock(&ether->lock);
return IRQ_HANDLED;
} else if (status & MISTA_RXBERR) {
- dev_err(&pdev->dev, "emc rx bus error\n");
- w90p910_reset_mac(dev);
- }
+ dev_err(&pdev->dev, "emc rx bus error\n");
+ w90p910_reset_mac(dev);
+ }
netdev_rx(dev);
- spin_unlock(&ether->lock);
return IRQ_HANDLED;
}
@@ -826,6 +837,7 @@ static int w90p910_ether_open(struct net_device *dev)
if (request_irq(ether->rxirq, w90p910_rx_interrupt,
0x0, pdev->name, dev)) {
dev_err(&pdev->dev, "register irq rx failed\n");
+ free_irq(ether->txirq, dev);
return -EAGAIN;
}
@@ -908,7 +920,7 @@ static const struct net_device_ops w90p910_ether_netdev_ops = {
.ndo_start_xmit = w90p910_ether_start_xmit,
.ndo_get_stats = w90p910_ether_stats,
.ndo_set_multicast_list = w90p910_ether_set_multicast_list,
- .ndo_set_mac_address = set_mac_address,
+ .ndo_set_mac_address = w90p910_set_mac_address,
.ndo_do_ioctl = w90p910_ether_ioctl,
.ndo_validate_addr = eth_validate_addr,
.ndo_change_mtu = eth_change_mtu,
@@ -949,8 +961,6 @@ static int w90p910_ether_setup(struct net_device *dev)
get_mac_address(dev);
- spin_lock_init(&ether->lock);
-
ether->cur_tx = 0x0;
ether->cur_rx = 0x0;
ether->finish_tx = 0x0;
@@ -972,30 +982,29 @@ static int __devinit w90p910_ether_probe(struct platform_device *pdev)
{
struct w90p910_ether *ether;
struct net_device *dev;
- struct resource *res;
int error;
dev = alloc_etherdev(sizeof(struct w90p910_ether));
if (!dev)
return -ENOMEM;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (res == NULL) {
+ ether = netdev_priv(dev);
+
+ ether->res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (ether->res == NULL) {
dev_err(&pdev->dev, "failed to get I/O memory\n");
error = -ENXIO;
goto failed_free;
}
- res = request_mem_region(res->start, resource_size(res), pdev->name);
- if (res == NULL) {
+ if (!request_mem_region(ether->res->start,
+ resource_size(ether->res), pdev->name)) {
dev_err(&pdev->dev, "failed to request I/O memory\n");
error = -EBUSY;
goto failed_free;
}
- ether = netdev_priv(dev);
-
- ether->reg = ioremap(res->start, resource_size(res));
+ ether->reg = ioremap(ether->res->start, resource_size(ether->res));
if (ether->reg == NULL) {
dev_err(&pdev->dev, "failed to remap I/O memory\n");
error = -ENXIO;
@@ -1056,7 +1065,7 @@ failed_free_txirq:
failed_free_io:
iounmap(ether->reg);
failed_free_mem:
- release_mem_region(res->start, resource_size(res));
+ release_mem_region(ether->res->start, resource_size(ether->res));
failed_free:
free_netdev(dev);
return error;
@@ -1068,10 +1077,19 @@ static int __devexit w90p910_ether_remove(struct platform_device *pdev)
struct w90p910_ether *ether = netdev_priv(dev);
unregister_netdev(dev);
+
clk_put(ether->rmiiclk);
clk_put(ether->clk);
+
+ iounmap(ether->reg);
+ release_mem_region(ether->res->start, resource_size(ether->res));
+
+ free_irq(ether->txirq, dev);
+ free_irq(ether->rxirq, dev);
+
del_timer_sync(&ether->check_timer);
platform_set_drvdata(pdev, NULL);
+
free_netdev(dev);
return 0;
}
diff --git a/drivers/net/at1700.c b/drivers/net/at1700.c
index cf30e278f18..5349c58d1fa 100644
--- a/drivers/net/at1700.c
+++ b/drivers/net/at1700.c
@@ -643,7 +643,7 @@ static int net_send_packet (struct sk_buff *skb, struct net_device *dev)
netif_start_queue (dev);
dev_kfree_skb (skb);
- return 0;
+ return NETDEV_TX_OK;
}
/* The typical workload of the driver:
diff --git a/drivers/net/atarilance.c b/drivers/net/atarilance.c
index 5425ab0c38c..0c0deceb693 100644
--- a/drivers/net/atarilance.c
+++ b/drivers/net/atarilance.c
@@ -796,7 +796,7 @@ static int lance_start_xmit( struct sk_buff *skb, struct net_device *dev )
if (len > skb->len) {
if (skb_padto(skb, len))
- return 0;
+ return NETDEV_TX_OK;
}
netif_stop_queue (dev);
@@ -846,7 +846,7 @@ static int lance_start_xmit( struct sk_buff *skb, struct net_device *dev )
lp->tx_full = 1;
spin_unlock_irqrestore (&lp->devlock, flags);
- return 0;
+ return NETDEV_TX_OK;
}
/* The LANCE interrupt handler. */
diff --git a/drivers/net/atl1c/atl1c_main.c b/drivers/net/atl1c/atl1c_main.c
index a383122679d..1d601ce7d5b 100644
--- a/drivers/net/atl1c/atl1c_main.c
+++ b/drivers/net/atl1c/atl1c_main.c
@@ -2678,6 +2678,9 @@ static pci_ers_result_t atl1c_io_error_detected(struct pci_dev *pdev,
netif_device_detach(netdev);
+ if (state == pci_channel_io_perm_failure)
+ return PCI_ERS_RESULT_DISCONNECT;
+
if (netif_running(netdev))
atl1c_down(adapter);
diff --git a/drivers/net/atl1e/atl1e_main.c b/drivers/net/atl1e/atl1e_main.c
index 9fc6d6d9060..4570749e3d3 100644
--- a/drivers/net/atl1e/atl1e_main.c
+++ b/drivers/net/atl1e/atl1e_main.c
@@ -2497,6 +2497,9 @@ atl1e_io_error_detected(struct pci_dev *pdev, pci_channel_state_t state)
netif_device_detach(netdev);
+ if (state == pci_channel_io_perm_failure)
+ return PCI_ERS_RESULT_DISCONNECT;
+
if (netif_running(netdev))
atl1e_down(adapter);
diff --git a/drivers/net/atp.c b/drivers/net/atp.c
index 4317b3edb3d..4beacc9c909 100644
--- a/drivers/net/atp.c
+++ b/drivers/net/atp.c
@@ -587,7 +587,7 @@ static int atp_send_packet(struct sk_buff *skb, struct net_device *dev)
dev->trans_start = jiffies;
dev_kfree_skb (skb);
- return 0;
+ return NETDEV_TX_OK;
}
diff --git a/drivers/net/au1000_eth.c b/drivers/net/au1000_eth.c
index d3c734f4d67..2aab1ebc6cd 100644
--- a/drivers/net/au1000_eth.c
+++ b/drivers/net/au1000_eth.c
@@ -988,7 +988,7 @@ static int au1000_tx(struct sk_buff *skb, struct net_device *dev)
dev_kfree_skb(skb);
aup->tx_head = (aup->tx_head + 1) & (NUM_TX_DMA - 1);
dev->trans_start = jiffies;
- return 0;
+ return NETDEV_TX_OK;
}
/*
diff --git a/drivers/net/b44.c b/drivers/net/b44.c
index 36d4d377ec2..07c92f34d8d 100644
--- a/drivers/net/b44.c
+++ b/drivers/net/b44.c
@@ -1297,7 +1297,8 @@ static void b44_chip_reset(struct b44 *bp, int reset_kind)
switch (sdev->bus->bustype) {
case SSB_BUSTYPE_SSB:
bw32(bp, B44_MDIO_CTRL, (MDIO_CTRL_PREAMBLE |
- (((ssb_clockspeed(sdev->bus) + (B44_MDC_RATIO / 2)) / B44_MDC_RATIO)
+ (DIV_ROUND_CLOSEST(ssb_clockspeed(sdev->bus),
+ B44_MDC_RATIO)
& MDIO_CTRL_MAXF_MASK)));
break;
case SSB_BUSTYPE_PCI:
@@ -1756,15 +1757,15 @@ static void b44_get_drvinfo (struct net_device *dev, struct ethtool_drvinfo *inf
struct b44 *bp = netdev_priv(dev);
struct ssb_bus *bus = bp->sdev->bus;
- strncpy(info->driver, DRV_MODULE_NAME, sizeof(info->driver));
- strncpy(info->version, DRV_MODULE_VERSION, sizeof(info->driver));
+ strlcpy(info->driver, DRV_MODULE_NAME, sizeof(info->driver));
+ strlcpy(info->version, DRV_MODULE_VERSION, sizeof(info->version));
switch (bus->bustype) {
case SSB_BUSTYPE_PCI:
- strncpy(info->bus_info, pci_name(bus->host_pci), sizeof(info->bus_info));
+ strlcpy(info->bus_info, pci_name(bus->host_pci), sizeof(info->bus_info));
break;
case SSB_BUSTYPE_PCMCIA:
case SSB_BUSTYPE_SSB:
- strncpy(info->bus_info, "SSB", sizeof(info->bus_info));
+ strlcpy(info->bus_info, "SSB", sizeof(info->bus_info));
break;
}
}
diff --git a/drivers/net/benet/Kconfig b/drivers/net/benet/Kconfig
index c6934f179c0..fdb6e81a437 100644
--- a/drivers/net/benet/Kconfig
+++ b/drivers/net/benet/Kconfig
@@ -1,7 +1,6 @@
config BE2NET
tristate "ServerEngines' 10Gbps NIC - BladeEngine 2"
depends on PCI && INET
- select INET_LRO
help
This driver implements the NIC functionality for ServerEngines'
10Gbps network adapter - BladeEngine 2.
diff --git a/drivers/net/benet/be.h b/drivers/net/benet/be.h
index 5b4bf3d2cdc..beb13139923 100644
--- a/drivers/net/benet/be.h
+++ b/drivers/net/benet/be.h
@@ -28,11 +28,10 @@
#include <linux/if_vlan.h>
#include <linux/workqueue.h>
#include <linux/interrupt.h>
-#include <linux/inet_lro.h>
#include "be_hw.h"
-#define DRV_VER "2.0.348"
+#define DRV_VER "2.0.400"
#define DRV_NAME "be2net"
#define BE_NAME "ServerEngines BladeEngine2 10Gbps NIC"
#define OC_NAME "Emulex OneConnect 10Gbps NIC"
@@ -72,8 +71,7 @@ static inline char *nic_name(struct pci_dev *pdev)
#define MAX_RX_POST BE_NAPI_WEIGHT /* Frags posted at a time */
#define RX_FRAGS_REFILL_WM (RX_Q_LEN - MAX_RX_POST)
-#define BE_MAX_LRO_DESCRIPTORS 16
-#define BE_MAX_FRAGS_PER_FRAME (min((u32) 16, (u32) MAX_SKB_FRAGS))
+#define FW_VER_LEN 32
struct be_dma_mem {
void *va;
@@ -127,7 +125,6 @@ static inline void queue_tail_inc(struct be_queue_info *q)
index_inc(&q->tail, q->len);
}
-
struct be_eq_obj {
struct be_queue_info q;
char desc[32];
@@ -146,31 +143,6 @@ struct be_mcc_obj {
struct be_queue_info cq;
};
-struct be_ctrl_info {
- u8 __iomem *csr;
- u8 __iomem *db; /* Door Bell */
- u8 __iomem *pcicfg; /* PCI config space */
- int pci_func;
-
- /* Mbox used for cmd request/response */
- spinlock_t mbox_lock; /* For serializing mbox cmds to BE card */
- struct be_dma_mem mbox_mem;
- /* Mbox mem is adjusted to align to 16 bytes. The allocated addr
- * is stored for freeing purpose */
- struct be_dma_mem mbox_mem_alloced;
-
- /* MCC Rings */
- struct be_mcc_obj mcc_obj;
- spinlock_t mcc_lock; /* For serializing mcc cmds to BE card */
- spinlock_t mcc_cq_lock;
-
- /* MCC Async callback */
- void (*async_cb)(void *adapter, bool link_up);
- void *adapter_ctxt;
-};
-
-#include "be_cmds.h"
-
struct be_drvr_stats {
u32 be_tx_reqs; /* number of TX requests initiated */
u32 be_tx_stops; /* number of times TX Q was stopped */
@@ -189,8 +161,6 @@ struct be_drvr_stats {
u32 be_polls; /* number of times NAPI called poll function */
u32 be_rx_events; /* number of ucast rx completion events */
u32 be_rx_compl; /* number of rx completion entries processed */
- u32 be_lro_hgram_data[8]; /* histogram of LRO data packets */
- u32 be_lro_hgram_ack[8]; /* histogram of LRO ACKs */
ulong be_rx_jiffies;
u64 be_rx_bytes;
u64 be_rx_bytes_prev;
@@ -233,8 +203,6 @@ struct be_rx_obj {
struct be_queue_info q;
struct be_queue_info cq;
struct be_rx_page_info page_info_tbl[RX_Q_LEN];
- struct net_lro_mgr lro_mgr;
- struct net_lro_desc lro_desc[BE_MAX_LRO_DESCRIPTORS];
};
#define BE_NUM_MSIX_VECTORS 2 /* 1 each for Tx and Rx */
@@ -242,8 +210,19 @@ struct be_adapter {
struct pci_dev *pdev;
struct net_device *netdev;
- /* Mbox, pci config, csr address information */
- struct be_ctrl_info ctrl;
+ u8 __iomem *csr;
+ u8 __iomem *db; /* Door Bell */
+ u8 __iomem *pcicfg; /* PCI config space */
+
+ spinlock_t mbox_lock; /* For serializing mbox cmds to BE card */
+ struct be_dma_mem mbox_mem;
+ /* Mbox mem is adjusted to align to 16 bytes. The allocated addr
+ * is stored for freeing purpose */
+ struct be_dma_mem mbox_mem_alloced;
+
+ struct be_mcc_obj mcc_obj;
+ spinlock_t mcc_lock; /* For serializing mcc cmds to BE card */
+ spinlock_t mcc_cq_lock;
struct msix_entry msix_entries[BE_NUM_MSIX_VECTORS];
bool msix_enabled;
@@ -271,7 +250,6 @@ struct be_adapter {
/* Ethtool knobs and info */
bool rx_csum; /* BE card must perform rx-checksumming */
- u32 max_rx_coal;
char fw_ver[FW_VER_LEN];
u32 if_handle; /* Used to configure filtering */
u32 pmac_id; /* MAC addr handle used by BE card */
@@ -285,6 +263,11 @@ extern struct ethtool_ops be_ethtool_ops;
#define drvr_stats(adapter) (&adapter->stats.drvr_stats)
+static inline unsigned int be_pci_func(struct be_adapter *adapter)
+{
+ return PCI_FUNC(adapter->pdev->devfn);
+}
+
#define BE_SET_NETDEV_OPS(netdev, ops) (netdev->netdev_ops = ops)
#define PAGE_SHIFT_4K 12
@@ -375,6 +358,7 @@ static inline u8 is_udp_pkt(struct sk_buff *skb)
return val;
}
-extern void be_cq_notify(struct be_ctrl_info *ctrl, u16 qid, bool arm,
+extern void be_cq_notify(struct be_adapter *adapter, u16 qid, bool arm,
u16 num_popped);
+extern void be_link_status_update(struct be_adapter *adapter, bool link_up);
#endif /* BE_H */
diff --git a/drivers/net/benet/be_cmds.c b/drivers/net/benet/be_cmds.c
index 583517ed56f..2547ee296a7 100644
--- a/drivers/net/benet/be_cmds.c
+++ b/drivers/net/benet/be_cmds.c
@@ -16,21 +16,22 @@
*/
#include "be.h"
+#include "be_cmds.h"
-static void be_mcc_notify(struct be_ctrl_info *ctrl)
+static void be_mcc_notify(struct be_adapter *adapter)
{
- struct be_queue_info *mccq = &ctrl->mcc_obj.q;
+ struct be_queue_info *mccq = &adapter->mcc_obj.q;
u32 val = 0;
val |= mccq->id & DB_MCCQ_RING_ID_MASK;
val |= 1 << DB_MCCQ_NUM_POSTED_SHIFT;
- iowrite32(val, ctrl->db + DB_MCCQ_OFFSET);
+ iowrite32(val, adapter->db + DB_MCCQ_OFFSET);
}
/* To check if valid bit is set, check the entire word as we don't know
* the endianness of the data (old entry is host endian while a new entry is
* little endian) */
-static inline bool be_mcc_compl_is_new(struct be_mcc_cq_entry *compl)
+static inline bool be_mcc_compl_is_new(struct be_mcc_compl *compl)
{
if (compl->flags != 0) {
compl->flags = le32_to_cpu(compl->flags);
@@ -42,13 +43,13 @@ static inline bool be_mcc_compl_is_new(struct be_mcc_cq_entry *compl)
}
/* Need to reset the entire word that houses the valid bit */
-static inline void be_mcc_compl_use(struct be_mcc_cq_entry *compl)
+static inline void be_mcc_compl_use(struct be_mcc_compl *compl)
{
compl->flags = 0;
}
-static int be_mcc_compl_process(struct be_ctrl_info *ctrl,
- struct be_mcc_cq_entry *compl)
+static int be_mcc_compl_process(struct be_adapter *adapter,
+ struct be_mcc_compl *compl)
{
u16 compl_status, extd_status;
@@ -61,8 +62,8 @@ static int be_mcc_compl_process(struct be_ctrl_info *ctrl,
if (compl_status != MCC_STATUS_SUCCESS) {
extd_status = (compl->status >> CQE_STATUS_EXTD_SHIFT) &
CQE_STATUS_EXTD_MASK;
- printk(KERN_WARNING DRV_NAME
- " error in cmd completion: status(compl/extd)=%d/%d\n",
+ dev_warn(&adapter->pdev->dev,
+ "Error in cmd completion: status(compl/extd)=%d/%d\n",
compl_status, extd_status);
return -1;
}
@@ -70,11 +71,11 @@ static int be_mcc_compl_process(struct be_ctrl_info *ctrl,
}
/* Link state evt is a string of bytes; no need for endian swapping */
-static void be_async_link_state_process(struct be_ctrl_info *ctrl,
+static void be_async_link_state_process(struct be_adapter *adapter,
struct be_async_event_link_state *evt)
{
- ctrl->async_cb(ctrl->adapter_ctxt,
- evt->port_link_status == ASYNC_EVENT_LINK_UP ? true : false);
+ be_link_status_update(adapter,
+ evt->port_link_status == ASYNC_EVENT_LINK_UP);
}
static inline bool is_link_state_evt(u32 trailer)
@@ -84,10 +85,10 @@ static inline bool is_link_state_evt(u32 trailer)
ASYNC_EVENT_CODE_LINK_STATE);
}
-static struct be_mcc_cq_entry *be_mcc_compl_get(struct be_ctrl_info *ctrl)
+static struct be_mcc_compl *be_mcc_compl_get(struct be_adapter *adapter)
{
- struct be_queue_info *mcc_cq = &ctrl->mcc_obj.cq;
- struct be_mcc_cq_entry *compl = queue_tail_node(mcc_cq);
+ struct be_queue_info *mcc_cq = &adapter->mcc_obj.cq;
+ struct be_mcc_compl *compl = queue_tail_node(mcc_cq);
if (be_mcc_compl_is_new(compl)) {
queue_tail_inc(mcc_cq);
@@ -96,55 +97,55 @@ static struct be_mcc_cq_entry *be_mcc_compl_get(struct be_ctrl_info *ctrl)
return NULL;
}
-void be_process_mcc(struct be_ctrl_info *ctrl)
+void be_process_mcc(struct be_adapter *adapter)
{
- struct be_mcc_cq_entry *compl;
+ struct be_mcc_compl *compl;
int num = 0;
- spin_lock_bh(&ctrl->mcc_cq_lock);
- while ((compl = be_mcc_compl_get(ctrl))) {
+ spin_lock_bh(&adapter->mcc_cq_lock);
+ while ((compl = be_mcc_compl_get(adapter))) {
if (compl->flags & CQE_FLAGS_ASYNC_MASK) {
/* Interpret flags as an async trailer */
BUG_ON(!is_link_state_evt(compl->flags));
/* Interpret compl as a async link evt */
- be_async_link_state_process(ctrl,
+ be_async_link_state_process(adapter,
(struct be_async_event_link_state *) compl);
} else {
- be_mcc_compl_process(ctrl, compl);
- atomic_dec(&ctrl->mcc_obj.q.used);
+ be_mcc_compl_process(adapter, compl);
+ atomic_dec(&adapter->mcc_obj.q.used);
}
be_mcc_compl_use(compl);
num++;
}
if (num)
- be_cq_notify(ctrl, ctrl->mcc_obj.cq.id, true, num);
- spin_unlock_bh(&ctrl->mcc_cq_lock);
+ be_cq_notify(adapter, adapter->mcc_obj.cq.id, true, num);
+ spin_unlock_bh(&adapter->mcc_cq_lock);
}
/* Wait till no more pending mcc requests are present */
-static void be_mcc_wait_compl(struct be_ctrl_info *ctrl)
+static void be_mcc_wait_compl(struct be_adapter *adapter)
{
#define mcc_timeout 50000 /* 5s timeout */
int i;
for (i = 0; i < mcc_timeout; i++) {
- be_process_mcc(ctrl);
- if (atomic_read(&ctrl->mcc_obj.q.used) == 0)
+ be_process_mcc(adapter);
+ if (atomic_read(&adapter->mcc_obj.q.used) == 0)
break;
udelay(100);
}
if (i == mcc_timeout)
- printk(KERN_WARNING DRV_NAME "mcc poll timed out\n");
+ dev_err(&adapter->pdev->dev, "mccq poll timed out\n");
}
/* Notify MCC requests and wait for completion */
-static void be_mcc_notify_wait(struct be_ctrl_info *ctrl)
+static void be_mcc_notify_wait(struct be_adapter *adapter)
{
- be_mcc_notify(ctrl);
- be_mcc_wait_compl(ctrl);
+ be_mcc_notify(adapter);
+ be_mcc_wait_compl(adapter);
}
-static int be_mbox_db_ready_wait(void __iomem *db)
+static int be_mbox_db_ready_wait(struct be_adapter *adapter, void __iomem *db)
{
int cnt = 0, wait = 5;
u32 ready;
@@ -155,8 +156,7 @@ static int be_mbox_db_ready_wait(void __iomem *db)
break;
if (cnt > 200000) {
- printk(KERN_WARNING DRV_NAME
- ": mbox_db poll timed out\n");
+ dev_err(&adapter->pdev->dev, "mbox poll timed out\n");
return -1;
}
@@ -173,55 +173,52 @@ static int be_mbox_db_ready_wait(void __iomem *db)
* Insert the mailbox address into the doorbell in two steps
* Polls on the mbox doorbell till a command completion (or a timeout) occurs
*/
-static int be_mbox_db_ring(struct be_ctrl_info *ctrl)
+static int be_mbox_notify(struct be_adapter *adapter)
{
int status;
u32 val = 0;
- void __iomem *db = ctrl->db + MPU_MAILBOX_DB_OFFSET;
- struct be_dma_mem *mbox_mem = &ctrl->mbox_mem;
+ void __iomem *db = adapter->db + MPU_MAILBOX_DB_OFFSET;
+ struct be_dma_mem *mbox_mem = &adapter->mbox_mem;
struct be_mcc_mailbox *mbox = mbox_mem->va;
- struct be_mcc_cq_entry *cqe = &mbox->cqe;
+ struct be_mcc_compl *compl = &mbox->compl;
- memset(cqe, 0, sizeof(*cqe));
+ memset(compl, 0, sizeof(*compl));
- val &= ~MPU_MAILBOX_DB_RDY_MASK;
val |= MPU_MAILBOX_DB_HI_MASK;
/* at bits 2 - 31 place mbox dma addr msb bits 34 - 63 */
val |= (upper_32_bits(mbox_mem->dma) >> 2) << 2;
iowrite32(val, db);
/* wait for ready to be set */
- status = be_mbox_db_ready_wait(db);
+ status = be_mbox_db_ready_wait(adapter, db);
if (status != 0)
return status;
val = 0;
- val &= ~MPU_MAILBOX_DB_RDY_MASK;
- val &= ~MPU_MAILBOX_DB_HI_MASK;
/* at bits 2 - 31 place mbox dma addr lsb bits 4 - 33 */
val |= (u32)(mbox_mem->dma >> 4) << 2;
iowrite32(val, db);
- status = be_mbox_db_ready_wait(db);
+ status = be_mbox_db_ready_wait(adapter, db);
if (status != 0)
return status;
/* A cq entry has been made now */
- if (be_mcc_compl_is_new(cqe)) {
- status = be_mcc_compl_process(ctrl, &mbox->cqe);
- be_mcc_compl_use(cqe);
+ if (be_mcc_compl_is_new(compl)) {
+ status = be_mcc_compl_process(adapter, &mbox->compl);
+ be_mcc_compl_use(compl);
if (status)
return status;
} else {
- printk(KERN_WARNING DRV_NAME "invalid mailbox completion\n");
+ dev_err(&adapter->pdev->dev, "invalid mailbox completion\n");
return -1;
}
return 0;
}
-static int be_POST_stage_get(struct be_ctrl_info *ctrl, u16 *stage)
+static int be_POST_stage_get(struct be_adapter *adapter, u16 *stage)
{
- u32 sem = ioread32(ctrl->csr + MPU_EP_SEMAPHORE_OFFSET);
+ u32 sem = ioread32(adapter->csr + MPU_EP_SEMAPHORE_OFFSET);
*stage = sem & EP_SEMAPHORE_POST_STAGE_MASK;
if ((sem >> EP_SEMAPHORE_POST_ERR_SHIFT) & EP_SEMAPHORE_POST_ERR_MASK)
@@ -230,54 +227,17 @@ static int be_POST_stage_get(struct be_ctrl_info *ctrl, u16 *stage)
return 0;
}
-static int be_POST_stage_poll(struct be_ctrl_info *ctrl, u16 poll_stage)
-{
- u16 stage, cnt, error;
- for (cnt = 0; cnt < 5000; cnt++) {
- error = be_POST_stage_get(ctrl, &stage);
- if (error)
- return -1;
-
- if (stage == poll_stage)
- break;
- udelay(1000);
- }
- if (stage != poll_stage)
- return -1;
- return 0;
-}
-
-
-int be_cmd_POST(struct be_ctrl_info *ctrl)
+int be_cmd_POST(struct be_adapter *adapter)
{
u16 stage, error;
- error = be_POST_stage_get(ctrl, &stage);
- if (error)
- goto err;
-
- if (stage == POST_STAGE_ARMFW_RDY)
- return 0;
-
- if (stage != POST_STAGE_AWAITING_HOST_RDY)
- goto err;
-
- /* On awaiting host rdy, reset and again poll on awaiting host rdy */
- iowrite32(POST_STAGE_BE_RESET, ctrl->csr + MPU_EP_SEMAPHORE_OFFSET);
- error = be_POST_stage_poll(ctrl, POST_STAGE_AWAITING_HOST_RDY);
- if (error)
- goto err;
-
- /* Now kickoff POST and poll on armfw ready */
- iowrite32(POST_STAGE_HOST_RDY, ctrl->csr + MPU_EP_SEMAPHORE_OFFSET);
- error = be_POST_stage_poll(ctrl, POST_STAGE_ARMFW_RDY);
- if (error)
- goto err;
+ error = be_POST_stage_get(adapter, &stage);
+ if (error || stage != POST_STAGE_ARMFW_RDY) {
+ dev_err(&adapter->pdev->dev, "POST failed.\n");
+ return -1;
+ }
return 0;
-err:
- printk(KERN_WARNING DRV_NAME ": ERROR, stage=%d\n", stage);
- return -1;
}
static inline void *embedded_payload(struct be_mcc_wrb *wrb)
@@ -367,16 +327,16 @@ static inline struct be_mcc_wrb *wrb_from_mcc(struct be_queue_info *mccq)
return wrb;
}
-int be_cmd_eq_create(struct be_ctrl_info *ctrl,
+int be_cmd_eq_create(struct be_adapter *adapter,
struct be_queue_info *eq, int eq_delay)
{
- struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
+ struct be_mcc_wrb *wrb = wrb_from_mbox(&adapter->mbox_mem);
struct be_cmd_req_eq_create *req = embedded_payload(wrb);
struct be_cmd_resp_eq_create *resp = embedded_payload(wrb);
struct be_dma_mem *q_mem = &eq->dma_mem;
int status;
- spin_lock(&ctrl->mbox_lock);
+ spin_lock(&adapter->mbox_lock);
memset(wrb, 0, sizeof(*wrb));
be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
@@ -387,7 +347,7 @@ int be_cmd_eq_create(struct be_ctrl_info *ctrl,
req->num_pages = cpu_to_le16(PAGES_4K_SPANNED(q_mem->va, q_mem->size));
AMAP_SET_BITS(struct amap_eq_context, func, req->context,
- ctrl->pci_func);
+ be_pci_func(adapter));
AMAP_SET_BITS(struct amap_eq_context, valid, req->context, 1);
/* 4byte eqe*/
AMAP_SET_BITS(struct amap_eq_context, size, req->context, 0);
@@ -399,24 +359,24 @@ int be_cmd_eq_create(struct be_ctrl_info *ctrl,
be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem);
- status = be_mbox_db_ring(ctrl);
+ status = be_mbox_notify(adapter);
if (!status) {
eq->id = le16_to_cpu(resp->eq_id);
eq->created = true;
}
- spin_unlock(&ctrl->mbox_lock);
+ spin_unlock(&adapter->mbox_lock);
return status;
}
-int be_cmd_mac_addr_query(struct be_ctrl_info *ctrl, u8 *mac_addr,
+int be_cmd_mac_addr_query(struct be_adapter *adapter, u8 *mac_addr,
u8 type, bool permanent, u32 if_handle)
{
- struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
+ struct be_mcc_wrb *wrb = wrb_from_mbox(&adapter->mbox_mem);
struct be_cmd_req_mac_query *req = embedded_payload(wrb);
struct be_cmd_resp_mac_query *resp = embedded_payload(wrb);
int status;
- spin_lock(&ctrl->mbox_lock);
+ spin_lock(&adapter->mbox_lock);
memset(wrb, 0, sizeof(*wrb));
be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
@@ -432,22 +392,22 @@ int be_cmd_mac_addr_query(struct be_ctrl_info *ctrl, u8 *mac_addr,
req->permanent = 0;
}
- status = be_mbox_db_ring(ctrl);
+ status = be_mbox_notify(adapter);
if (!status)
memcpy(mac_addr, resp->mac.addr, ETH_ALEN);
- spin_unlock(&ctrl->mbox_lock);
+ spin_unlock(&adapter->mbox_lock);
return status;
}
-int be_cmd_pmac_add(struct be_ctrl_info *ctrl, u8 *mac_addr,
+int be_cmd_pmac_add(struct be_adapter *adapter, u8 *mac_addr,
u32 if_id, u32 *pmac_id)
{
- struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
+ struct be_mcc_wrb *wrb = wrb_from_mbox(&adapter->mbox_mem);
struct be_cmd_req_pmac_add *req = embedded_payload(wrb);
int status;
- spin_lock(&ctrl->mbox_lock);
+ spin_lock(&adapter->mbox_lock);
memset(wrb, 0, sizeof(*wrb));
be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
@@ -458,23 +418,23 @@ int be_cmd_pmac_add(struct be_ctrl_info *ctrl, u8 *mac_addr,
req->if_id = cpu_to_le32(if_id);
memcpy(req->mac_address, mac_addr, ETH_ALEN);
- status = be_mbox_db_ring(ctrl);
+ status = be_mbox_notify(adapter);
if (!status) {
struct be_cmd_resp_pmac_add *resp = embedded_payload(wrb);
*pmac_id = le32_to_cpu(resp->pmac_id);
}
- spin_unlock(&ctrl->mbox_lock);
+ spin_unlock(&adapter->mbox_lock);
return status;
}
-int be_cmd_pmac_del(struct be_ctrl_info *ctrl, u32 if_id, u32 pmac_id)
+int be_cmd_pmac_del(struct be_adapter *adapter, u32 if_id, u32 pmac_id)
{
- struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
+ struct be_mcc_wrb *wrb = wrb_from_mbox(&adapter->mbox_mem);
struct be_cmd_req_pmac_del *req = embedded_payload(wrb);
int status;
- spin_lock(&ctrl->mbox_lock);
+ spin_lock(&adapter->mbox_lock);
memset(wrb, 0, sizeof(*wrb));
be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
@@ -485,24 +445,24 @@ int be_cmd_pmac_del(struct be_ctrl_info *ctrl, u32 if_id, u32 pmac_id)
req->if_id = cpu_to_le32(if_id);
req->pmac_id = cpu_to_le32(pmac_id);
- status = be_mbox_db_ring(ctrl);
- spin_unlock(&ctrl->mbox_lock);
+ status = be_mbox_notify(adapter);
+ spin_unlock(&adapter->mbox_lock);
return status;
}
-int be_cmd_cq_create(struct be_ctrl_info *ctrl,
+int be_cmd_cq_create(struct be_adapter *adapter,
struct be_queue_info *cq, struct be_queue_info *eq,
bool sol_evts, bool no_delay, int coalesce_wm)
{
- struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
+ struct be_mcc_wrb *wrb = wrb_from_mbox(&adapter->mbox_mem);
struct be_cmd_req_cq_create *req = embedded_payload(wrb);
struct be_cmd_resp_cq_create *resp = embedded_payload(wrb);
struct be_dma_mem *q_mem = &cq->dma_mem;
void *ctxt = &req->context;
int status;
- spin_lock(&ctrl->mbox_lock);
+ spin_lock(&adapter->mbox_lock);
memset(wrb, 0, sizeof(*wrb));
be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
@@ -521,17 +481,17 @@ int be_cmd_cq_create(struct be_ctrl_info *ctrl,
AMAP_SET_BITS(struct amap_cq_context, eventable, ctxt, 1);
AMAP_SET_BITS(struct amap_cq_context, eqid, ctxt, eq->id);
AMAP_SET_BITS(struct amap_cq_context, armed, ctxt, 1);
- AMAP_SET_BITS(struct amap_cq_context, func, ctxt, ctrl->pci_func);
+ AMAP_SET_BITS(struct amap_cq_context, func, ctxt, be_pci_func(adapter));
be_dws_cpu_to_le(ctxt, sizeof(req->context));
be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem);
- status = be_mbox_db_ring(ctrl);
+ status = be_mbox_notify(adapter);
if (!status) {
cq->id = le16_to_cpu(resp->cq_id);
cq->created = true;
}
- spin_unlock(&ctrl->mbox_lock);
+ spin_unlock(&adapter->mbox_lock);
return status;
}
@@ -544,17 +504,17 @@ static u32 be_encoded_q_len(int q_len)
return len_encoded;
}
-int be_cmd_mccq_create(struct be_ctrl_info *ctrl,
+int be_cmd_mccq_create(struct be_adapter *adapter,
struct be_queue_info *mccq,
struct be_queue_info *cq)
{
- struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
+ struct be_mcc_wrb *wrb = wrb_from_mbox(&adapter->mbox_mem);
struct be_cmd_req_mcc_create *req = embedded_payload(wrb);
struct be_dma_mem *q_mem = &mccq->dma_mem;
void *ctxt = &req->context;
int status;
- spin_lock(&ctrl->mbox_lock);
+ spin_lock(&adapter->mbox_lock);
memset(wrb, 0, sizeof(*wrb));
be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
@@ -564,7 +524,7 @@ int be_cmd_mccq_create(struct be_ctrl_info *ctrl,
req->num_pages = PAGES_4K_SPANNED(q_mem->va, q_mem->size);
- AMAP_SET_BITS(struct amap_mcc_context, fid, ctxt, ctrl->pci_func);
+ AMAP_SET_BITS(struct amap_mcc_context, fid, ctxt, be_pci_func(adapter));
AMAP_SET_BITS(struct amap_mcc_context, valid, ctxt, 1);
AMAP_SET_BITS(struct amap_mcc_context, ring_size, ctxt,
be_encoded_q_len(mccq->len));
@@ -574,29 +534,29 @@ int be_cmd_mccq_create(struct be_ctrl_info *ctrl,
be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem);
- status = be_mbox_db_ring(ctrl);
+ status = be_mbox_notify(adapter);
if (!status) {
struct be_cmd_resp_mcc_create *resp = embedded_payload(wrb);
mccq->id = le16_to_cpu(resp->id);
mccq->created = true;
}
- spin_unlock(&ctrl->mbox_lock);
+ spin_unlock(&adapter->mbox_lock);
return status;
}
-int be_cmd_txq_create(struct be_ctrl_info *ctrl,
+int be_cmd_txq_create(struct be_adapter *adapter,
struct be_queue_info *txq,
struct be_queue_info *cq)
{
- struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
+ struct be_mcc_wrb *wrb = wrb_from_mbox(&adapter->mbox_mem);
struct be_cmd_req_eth_tx_create *req = embedded_payload(wrb);
struct be_dma_mem *q_mem = &txq->dma_mem;
void *ctxt = &req->context;
int status;
u32 len_encoded;
- spin_lock(&ctrl->mbox_lock);
+ spin_lock(&adapter->mbox_lock);
memset(wrb, 0, sizeof(*wrb));
be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
@@ -613,7 +573,7 @@ int be_cmd_txq_create(struct be_ctrl_info *ctrl,
len_encoded = 0;
AMAP_SET_BITS(struct amap_tx_context, tx_ring_size, ctxt, len_encoded);
AMAP_SET_BITS(struct amap_tx_context, pci_func_id, ctxt,
- ctrl->pci_func);
+ be_pci_func(adapter));
AMAP_SET_BITS(struct amap_tx_context, ctx_valid, ctxt, 1);
AMAP_SET_BITS(struct amap_tx_context, cq_id_send, ctxt, cq->id);
@@ -621,27 +581,27 @@ int be_cmd_txq_create(struct be_ctrl_info *ctrl,
be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem);
- status = be_mbox_db_ring(ctrl);
+ status = be_mbox_notify(adapter);
if (!status) {
struct be_cmd_resp_eth_tx_create *resp = embedded_payload(wrb);
txq->id = le16_to_cpu(resp->cid);
txq->created = true;
}
- spin_unlock(&ctrl->mbox_lock);
+ spin_unlock(&adapter->mbox_lock);
return status;
}
-int be_cmd_rxq_create(struct be_ctrl_info *ctrl,
+int be_cmd_rxq_create(struct be_adapter *adapter,
struct be_queue_info *rxq, u16 cq_id, u16 frag_size,
u16 max_frame_size, u32 if_id, u32 rss)
{
- struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
+ struct be_mcc_wrb *wrb = wrb_from_mbox(&adapter->mbox_mem);
struct be_cmd_req_eth_rx_create *req = embedded_payload(wrb);
struct be_dma_mem *q_mem = &rxq->dma_mem;
int status;
- spin_lock(&ctrl->mbox_lock);
+ spin_lock(&adapter->mbox_lock);
memset(wrb, 0, sizeof(*wrb));
be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
@@ -657,27 +617,27 @@ int be_cmd_rxq_create(struct be_ctrl_info *ctrl,
req->max_frame_size = cpu_to_le16(max_frame_size);
req->rss_queue = cpu_to_le32(rss);
- status = be_mbox_db_ring(ctrl);
+ status = be_mbox_notify(adapter);
if (!status) {
struct be_cmd_resp_eth_rx_create *resp = embedded_payload(wrb);
rxq->id = le16_to_cpu(resp->id);
rxq->created = true;
}
- spin_unlock(&ctrl->mbox_lock);
+ spin_unlock(&adapter->mbox_lock);
return status;
}
/* Generic destroyer function for all types of queues */
-int be_cmd_q_destroy(struct be_ctrl_info *ctrl, struct be_queue_info *q,
+int be_cmd_q_destroy(struct be_adapter *adapter, struct be_queue_info *q,
int queue_type)
{
- struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
+ struct be_mcc_wrb *wrb = wrb_from_mbox(&adapter->mbox_mem);
struct be_cmd_req_q_destroy *req = embedded_payload(wrb);
u8 subsys = 0, opcode = 0;
int status;
- spin_lock(&ctrl->mbox_lock);
+ spin_lock(&adapter->mbox_lock);
memset(wrb, 0, sizeof(*wrb));
be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
@@ -704,29 +664,27 @@ int be_cmd_q_destroy(struct be_ctrl_info *ctrl, struct be_queue_info *q,
opcode = OPCODE_COMMON_MCC_DESTROY;
break;
default:
- printk(KERN_WARNING DRV_NAME ":bad Q type in Q destroy cmd\n");
- status = -1;
- goto err;
+ BUG();
}
be_cmd_hdr_prepare(&req->hdr, subsys, opcode, sizeof(*req));
req->id = cpu_to_le16(q->id);
- status = be_mbox_db_ring(ctrl);
-err:
- spin_unlock(&ctrl->mbox_lock);
+ status = be_mbox_notify(adapter);
+
+ spin_unlock(&adapter->mbox_lock);
return status;
}
/* Create an rx filtering policy configuration on an i/f */
-int be_cmd_if_create(struct be_ctrl_info *ctrl, u32 flags, u8 *mac,
+int be_cmd_if_create(struct be_adapter *adapter, u32 flags, u8 *mac,
bool pmac_invalid, u32 *if_handle, u32 *pmac_id)
{
- struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
+ struct be_mcc_wrb *wrb = wrb_from_mbox(&adapter->mbox_mem);
struct be_cmd_req_if_create *req = embedded_payload(wrb);
int status;
- spin_lock(&ctrl->mbox_lock);
+ spin_lock(&adapter->mbox_lock);
memset(wrb, 0, sizeof(*wrb));
be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
@@ -739,7 +697,7 @@ int be_cmd_if_create(struct be_ctrl_info *ctrl, u32 flags, u8 *mac,
if (!pmac_invalid)
memcpy(req->mac_addr, mac, ETH_ALEN);
- status = be_mbox_db_ring(ctrl);
+ status = be_mbox_notify(adapter);
if (!status) {
struct be_cmd_resp_if_create *resp = embedded_payload(wrb);
*if_handle = le32_to_cpu(resp->interface_id);
@@ -747,17 +705,17 @@ int be_cmd_if_create(struct be_ctrl_info *ctrl, u32 flags, u8 *mac,
*pmac_id = le32_to_cpu(resp->pmac_id);
}
- spin_unlock(&ctrl->mbox_lock);
+ spin_unlock(&adapter->mbox_lock);
return status;
}
-int be_cmd_if_destroy(struct be_ctrl_info *ctrl, u32 interface_id)
+int be_cmd_if_destroy(struct be_adapter *adapter, u32 interface_id)
{
- struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
+ struct be_mcc_wrb *wrb = wrb_from_mbox(&adapter->mbox_mem);
struct be_cmd_req_if_destroy *req = embedded_payload(wrb);
int status;
- spin_lock(&ctrl->mbox_lock);
+ spin_lock(&adapter->mbox_lock);
memset(wrb, 0, sizeof(*wrb));
be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
@@ -766,9 +724,9 @@ int be_cmd_if_destroy(struct be_ctrl_info *ctrl, u32 interface_id)
OPCODE_COMMON_NTWK_INTERFACE_DESTROY, sizeof(*req));
req->interface_id = cpu_to_le32(interface_id);
- status = be_mbox_db_ring(ctrl);
+ status = be_mbox_notify(adapter);
- spin_unlock(&ctrl->mbox_lock);
+ spin_unlock(&adapter->mbox_lock);
return status;
}
@@ -776,14 +734,14 @@ int be_cmd_if_destroy(struct be_ctrl_info *ctrl, u32 interface_id)
/* Get stats is a non embedded command: the request is not embedded inside
* WRB but is a separate dma memory block
*/
-int be_cmd_get_stats(struct be_ctrl_info *ctrl, struct be_dma_mem *nonemb_cmd)
+int be_cmd_get_stats(struct be_adapter *adapter, struct be_dma_mem *nonemb_cmd)
{
- struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
+ struct be_mcc_wrb *wrb = wrb_from_mbox(&adapter->mbox_mem);
struct be_cmd_req_get_stats *req = nonemb_cmd->va;
struct be_sge *sge = nonembedded_sgl(wrb);
int status;
- spin_lock(&ctrl->mbox_lock);
+ spin_lock(&adapter->mbox_lock);
memset(wrb, 0, sizeof(*wrb));
memset(req, 0, sizeof(*req));
@@ -796,24 +754,24 @@ int be_cmd_get_stats(struct be_ctrl_info *ctrl, struct be_dma_mem *nonemb_cmd)
sge->pa_lo = cpu_to_le32(nonemb_cmd->dma & 0xFFFFFFFF);
sge->len = cpu_to_le32(nonemb_cmd->size);
- status = be_mbox_db_ring(ctrl);
+ status = be_mbox_notify(adapter);
if (!status) {
struct be_cmd_resp_get_stats *resp = nonemb_cmd->va;
be_dws_le_to_cpu(&resp->hw_stats, sizeof(resp->hw_stats));
}
- spin_unlock(&ctrl->mbox_lock);
+ spin_unlock(&adapter->mbox_lock);
return status;
}
-int be_cmd_link_status_query(struct be_ctrl_info *ctrl,
+int be_cmd_link_status_query(struct be_adapter *adapter,
bool *link_up)
{
- struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
+ struct be_mcc_wrb *wrb = wrb_from_mbox(&adapter->mbox_mem);
struct be_cmd_req_link_status *req = embedded_payload(wrb);
int status;
- spin_lock(&ctrl->mbox_lock);
+ spin_lock(&adapter->mbox_lock);
*link_up = false;
memset(wrb, 0, sizeof(*wrb));
@@ -823,24 +781,24 @@ int be_cmd_link_status_query(struct be_ctrl_info *ctrl,
be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
OPCODE_COMMON_NTWK_LINK_STATUS_QUERY, sizeof(*req));
- status = be_mbox_db_ring(ctrl);
+ status = be_mbox_notify(adapter);
if (!status) {
struct be_cmd_resp_link_status *resp = embedded_payload(wrb);
if (resp->mac_speed != PHY_LINK_SPEED_ZERO)
*link_up = true;
}
- spin_unlock(&ctrl->mbox_lock);
+ spin_unlock(&adapter->mbox_lock);
return status;
}
-int be_cmd_get_fw_ver(struct be_ctrl_info *ctrl, char *fw_ver)
+int be_cmd_get_fw_ver(struct be_adapter *adapter, char *fw_ver)
{
- struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
+ struct be_mcc_wrb *wrb = wrb_from_mbox(&adapter->mbox_mem);
struct be_cmd_req_get_fw_version *req = embedded_payload(wrb);
int status;
- spin_lock(&ctrl->mbox_lock);
+ spin_lock(&adapter->mbox_lock);
memset(wrb, 0, sizeof(*wrb));
be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
@@ -848,24 +806,24 @@ int be_cmd_get_fw_ver(struct be_ctrl_info *ctrl, char *fw_ver)
be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
OPCODE_COMMON_GET_FW_VERSION, sizeof(*req));
- status = be_mbox_db_ring(ctrl);
+ status = be_mbox_notify(adapter);
if (!status) {
struct be_cmd_resp_get_fw_version *resp = embedded_payload(wrb);
strncpy(fw_ver, resp->firmware_version_string, FW_VER_LEN);
}
- spin_unlock(&ctrl->mbox_lock);
+ spin_unlock(&adapter->mbox_lock);
return status;
}
/* set the EQ delay interval of an EQ to specified value */
-int be_cmd_modify_eqd(struct be_ctrl_info *ctrl, u32 eq_id, u32 eqd)
+int be_cmd_modify_eqd(struct be_adapter *adapter, u32 eq_id, u32 eqd)
{
- struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
+ struct be_mcc_wrb *wrb = wrb_from_mbox(&adapter->mbox_mem);
struct be_cmd_req_modify_eq_delay *req = embedded_payload(wrb);
int status;
- spin_lock(&ctrl->mbox_lock);
+ spin_lock(&adapter->mbox_lock);
memset(wrb, 0, sizeof(*wrb));
be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
@@ -878,20 +836,20 @@ int be_cmd_modify_eqd(struct be_ctrl_info *ctrl, u32 eq_id, u32 eqd)
req->delay[0].phase = 0;
req->delay[0].delay_multiplier = cpu_to_le32(eqd);
- status = be_mbox_db_ring(ctrl);
+ status = be_mbox_notify(adapter);
- spin_unlock(&ctrl->mbox_lock);
+ spin_unlock(&adapter->mbox_lock);
return status;
}
-int be_cmd_vlan_config(struct be_ctrl_info *ctrl, u32 if_id, u16 *vtag_array,
+int be_cmd_vlan_config(struct be_adapter *adapter, u32 if_id, u16 *vtag_array,
u32 num, bool untagged, bool promiscuous)
{
- struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
+ struct be_mcc_wrb *wrb = wrb_from_mbox(&adapter->mbox_mem);
struct be_cmd_req_vlan_config *req = embedded_payload(wrb);
int status;
- spin_lock(&ctrl->mbox_lock);
+ spin_lock(&adapter->mbox_lock);
memset(wrb, 0, sizeof(*wrb));
be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
@@ -908,21 +866,21 @@ int be_cmd_vlan_config(struct be_ctrl_info *ctrl, u32 if_id, u16 *vtag_array,
req->num_vlan * sizeof(vtag_array[0]));
}
- status = be_mbox_db_ring(ctrl);
+ status = be_mbox_notify(adapter);
- spin_unlock(&ctrl->mbox_lock);
+ spin_unlock(&adapter->mbox_lock);
return status;
}
/* Use MCC for this command as it may be called in BH context */
-int be_cmd_promiscuous_config(struct be_ctrl_info *ctrl, u8 port_num, bool en)
+int be_cmd_promiscuous_config(struct be_adapter *adapter, u8 port_num, bool en)
{
struct be_mcc_wrb *wrb;
struct be_cmd_req_promiscuous_config *req;
- spin_lock_bh(&ctrl->mcc_lock);
+ spin_lock_bh(&adapter->mcc_lock);
- wrb = wrb_from_mcc(&ctrl->mcc_obj.q);
+ wrb = wrb_from_mcc(&adapter->mcc_obj.q);
BUG_ON(!wrb);
req = embedded_payload(wrb);
@@ -937,9 +895,9 @@ int be_cmd_promiscuous_config(struct be_ctrl_info *ctrl, u8 port_num, bool en)
else
req->port0_promiscuous = en;
- be_mcc_notify_wait(ctrl);
+ be_mcc_notify_wait(adapter);
- spin_unlock_bh(&ctrl->mcc_lock);
+ spin_unlock_bh(&adapter->mcc_lock);
return 0;
}
@@ -947,16 +905,16 @@ int be_cmd_promiscuous_config(struct be_ctrl_info *ctrl, u8 port_num, bool en)
* Use MCC for this command as it may be called in BH context
* (mc == NULL) => multicast promiscous
*/
-int be_cmd_multicast_set(struct be_ctrl_info *ctrl, u32 if_id,
+int be_cmd_multicast_set(struct be_adapter *adapter, u32 if_id,
struct dev_mc_list *mc_list, u32 mc_count)
{
#define BE_MAX_MC 32 /* set mcast promisc if > 32 */
struct be_mcc_wrb *wrb;
struct be_cmd_req_mcast_mac_config *req;
- spin_lock_bh(&ctrl->mcc_lock);
+ spin_lock_bh(&adapter->mcc_lock);
- wrb = wrb_from_mcc(&ctrl->mcc_obj.q);
+ wrb = wrb_from_mcc(&adapter->mcc_obj.q);
BUG_ON(!wrb);
req = embedded_payload(wrb);
@@ -979,20 +937,20 @@ int be_cmd_multicast_set(struct be_ctrl_info *ctrl, u32 if_id,
req->promiscuous = 1;
}
- be_mcc_notify_wait(ctrl);
+ be_mcc_notify_wait(adapter);
- spin_unlock_bh(&ctrl->mcc_lock);
+ spin_unlock_bh(&adapter->mcc_lock);
return 0;
}
-int be_cmd_set_flow_control(struct be_ctrl_info *ctrl, u32 tx_fc, u32 rx_fc)
+int be_cmd_set_flow_control(struct be_adapter *adapter, u32 tx_fc, u32 rx_fc)
{
- struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
+ struct be_mcc_wrb *wrb = wrb_from_mbox(&adapter->mbox_mem);
struct be_cmd_req_set_flow_control *req = embedded_payload(wrb);
int status;
- spin_lock(&ctrl->mbox_lock);
+ spin_lock(&adapter->mbox_lock);
memset(wrb, 0, sizeof(*wrb));
@@ -1004,19 +962,19 @@ int be_cmd_set_flow_control(struct be_ctrl_info *ctrl, u32 tx_fc, u32 rx_fc)
req->tx_flow_control = cpu_to_le16((u16)tx_fc);
req->rx_flow_control = cpu_to_le16((u16)rx_fc);
- status = be_mbox_db_ring(ctrl);
+ status = be_mbox_notify(adapter);
- spin_unlock(&ctrl->mbox_lock);
+ spin_unlock(&adapter->mbox_lock);
return status;
}
-int be_cmd_get_flow_control(struct be_ctrl_info *ctrl, u32 *tx_fc, u32 *rx_fc)
+int be_cmd_get_flow_control(struct be_adapter *adapter, u32 *tx_fc, u32 *rx_fc)
{
- struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
+ struct be_mcc_wrb *wrb = wrb_from_mbox(&adapter->mbox_mem);
struct be_cmd_req_get_flow_control *req = embedded_payload(wrb);
int status;
- spin_lock(&ctrl->mbox_lock);
+ spin_lock(&adapter->mbox_lock);
memset(wrb, 0, sizeof(*wrb));
@@ -1025,7 +983,7 @@ int be_cmd_get_flow_control(struct be_ctrl_info *ctrl, u32 *tx_fc, u32 *rx_fc)
be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
OPCODE_COMMON_GET_FLOW_CONTROL, sizeof(*req));
- status = be_mbox_db_ring(ctrl);
+ status = be_mbox_notify(adapter);
if (!status) {
struct be_cmd_resp_get_flow_control *resp =
embedded_payload(wrb);
@@ -1033,17 +991,17 @@ int be_cmd_get_flow_control(struct be_ctrl_info *ctrl, u32 *tx_fc, u32 *rx_fc)
*rx_fc = le16_to_cpu(resp->rx_flow_control);
}
- spin_unlock(&ctrl->mbox_lock);
+ spin_unlock(&adapter->mbox_lock);
return status;
}
-int be_cmd_query_fw_cfg(struct be_ctrl_info *ctrl, u32 *port_num)
+int be_cmd_query_fw_cfg(struct be_adapter *adapter, u32 *port_num)
{
- struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
+ struct be_mcc_wrb *wrb = wrb_from_mbox(&adapter->mbox_mem);
struct be_cmd_req_query_fw_cfg *req = embedded_payload(wrb);
int status;
- spin_lock(&ctrl->mbox_lock);
+ spin_lock(&adapter->mbox_lock);
memset(wrb, 0, sizeof(*wrb));
@@ -1052,12 +1010,33 @@ int be_cmd_query_fw_cfg(struct be_ctrl_info *ctrl, u32 *port_num)
be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
OPCODE_COMMON_QUERY_FIRMWARE_CONFIG, sizeof(*req));
- status = be_mbox_db_ring(ctrl);
+ status = be_mbox_notify(adapter);
if (!status) {
struct be_cmd_resp_query_fw_cfg *resp = embedded_payload(wrb);
*port_num = le32_to_cpu(resp->phys_port);
}
- spin_unlock(&ctrl->mbox_lock);
+ spin_unlock(&adapter->mbox_lock);
+ return status;
+}
+
+int be_cmd_reset_function(struct be_adapter *adapter)
+{
+ struct be_mcc_wrb *wrb = wrb_from_mbox(&adapter->mbox_mem);
+ struct be_cmd_req_hdr *req = embedded_payload(wrb);
+ int status;
+
+ spin_lock(&adapter->mbox_lock);
+
+ memset(wrb, 0, sizeof(*wrb));
+
+ be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
+
+ be_cmd_hdr_prepare(req, CMD_SUBSYSTEM_COMMON,
+ OPCODE_COMMON_FUNCTION_RESET, sizeof(*req));
+
+ status = be_mbox_notify(adapter);
+
+ spin_unlock(&adapter->mbox_lock);
return status;
}
diff --git a/drivers/net/benet/be_cmds.h b/drivers/net/benet/be_cmds.h
index 747626da7b4..70618064ae1 100644
--- a/drivers/net/benet/be_cmds.h
+++ b/drivers/net/benet/be_cmds.h
@@ -69,7 +69,7 @@ enum {
#define CQE_STATUS_EXTD_MASK 0xFFFF
#define CQE_STATUS_EXTD_SHIFT 0 /* bits 0 - 15 */
-struct be_mcc_cq_entry {
+struct be_mcc_compl {
u32 status; /* dword 0 */
u32 tag0; /* dword 1 */
u32 tag1; /* dword 2 */
@@ -106,7 +106,7 @@ struct be_async_event_link_state {
struct be_mcc_mailbox {
struct be_mcc_wrb wrb;
- struct be_mcc_cq_entry cqe;
+ struct be_mcc_compl compl;
};
#define CMD_SUBSYSTEM_COMMON 0x1
@@ -135,6 +135,7 @@ struct be_mcc_mailbox {
#define OPCODE_COMMON_QUERY_FIRMWARE_CONFIG 58
#define OPCODE_COMMON_NTWK_PMAC_ADD 59
#define OPCODE_COMMON_NTWK_PMAC_DEL 60
+#define OPCODE_COMMON_FUNCTION_RESET 61
#define OPCODE_ETH_ACPI_CONFIG 2
#define OPCODE_ETH_PROMISCUOUS 3
@@ -634,7 +635,6 @@ struct be_cmd_resp_link_status {
} __packed;
/******************** Get FW Version *******************/
-#define FW_VER_LEN 32
struct be_cmd_req_get_fw_version {
struct be_cmd_req_hdr hdr;
u8 rsvd0[FW_VER_LEN];
@@ -697,52 +697,53 @@ struct be_cmd_resp_query_fw_cfg {
u32 rsvd[26];
};
-extern int be_pci_fnum_get(struct be_ctrl_info *ctrl);
-extern int be_cmd_POST(struct be_ctrl_info *ctrl);
-extern int be_cmd_mac_addr_query(struct be_ctrl_info *ctrl, u8 *mac_addr,
+extern int be_pci_fnum_get(struct be_adapter *adapter);
+extern int be_cmd_POST(struct be_adapter *adapter);
+extern int be_cmd_mac_addr_query(struct be_adapter *adapter, u8 *mac_addr,
u8 type, bool permanent, u32 if_handle);
-extern int be_cmd_pmac_add(struct be_ctrl_info *ctrl, u8 *mac_addr,
+extern int be_cmd_pmac_add(struct be_adapter *adapter, u8 *mac_addr,
u32 if_id, u32 *pmac_id);
-extern int be_cmd_pmac_del(struct be_ctrl_info *ctrl, u32 if_id, u32 pmac_id);
-extern int be_cmd_if_create(struct be_ctrl_info *ctrl, u32 if_flags, u8 *mac,
+extern int be_cmd_pmac_del(struct be_adapter *adapter, u32 if_id, u32 pmac_id);
+extern int be_cmd_if_create(struct be_adapter *adapter, u32 if_flags, u8 *mac,
bool pmac_invalid, u32 *if_handle, u32 *pmac_id);
-extern int be_cmd_if_destroy(struct be_ctrl_info *ctrl, u32 if_handle);
-extern int be_cmd_eq_create(struct be_ctrl_info *ctrl,
+extern int be_cmd_if_destroy(struct be_adapter *adapter, u32 if_handle);
+extern int be_cmd_eq_create(struct be_adapter *adapter,
struct be_queue_info *eq, int eq_delay);
-extern int be_cmd_cq_create(struct be_ctrl_info *ctrl,
+extern int be_cmd_cq_create(struct be_adapter *adapter,
struct be_queue_info *cq, struct be_queue_info *eq,
bool sol_evts, bool no_delay,
int num_cqe_dma_coalesce);
-extern int be_cmd_mccq_create(struct be_ctrl_info *ctrl,
+extern int be_cmd_mccq_create(struct be_adapter *adapter,
struct be_queue_info *mccq,
struct be_queue_info *cq);
-extern int be_cmd_txq_create(struct be_ctrl_info *ctrl,
+extern int be_cmd_txq_create(struct be_adapter *adapter,
struct be_queue_info *txq,
struct be_queue_info *cq);
-extern int be_cmd_rxq_create(struct be_ctrl_info *ctrl,
+extern int be_cmd_rxq_create(struct be_adapter *adapter,
struct be_queue_info *rxq, u16 cq_id,
u16 frag_size, u16 max_frame_size, u32 if_id,
u32 rss);
-extern int be_cmd_q_destroy(struct be_ctrl_info *ctrl, struct be_queue_info *q,
+extern int be_cmd_q_destroy(struct be_adapter *adapter, struct be_queue_info *q,
int type);
-extern int be_cmd_link_status_query(struct be_ctrl_info *ctrl,
+extern int be_cmd_link_status_query(struct be_adapter *adapter,
bool *link_up);
-extern int be_cmd_reset(struct be_ctrl_info *ctrl);
-extern int be_cmd_get_stats(struct be_ctrl_info *ctrl,
+extern int be_cmd_reset(struct be_adapter *adapter);
+extern int be_cmd_get_stats(struct be_adapter *adapter,
struct be_dma_mem *nonemb_cmd);
-extern int be_cmd_get_fw_ver(struct be_ctrl_info *ctrl, char *fw_ver);
+extern int be_cmd_get_fw_ver(struct be_adapter *adapter, char *fw_ver);
-extern int be_cmd_modify_eqd(struct be_ctrl_info *ctrl, u32 eq_id, u32 eqd);
-extern int be_cmd_vlan_config(struct be_ctrl_info *ctrl, u32 if_id,
+extern int be_cmd_modify_eqd(struct be_adapter *adapter, u32 eq_id, u32 eqd);
+extern int be_cmd_vlan_config(struct be_adapter *adapter, u32 if_id,
u16 *vtag_array, u32 num, bool untagged,
bool promiscuous);
-extern int be_cmd_promiscuous_config(struct be_ctrl_info *ctrl,
+extern int be_cmd_promiscuous_config(struct be_adapter *adapter,
u8 port_num, bool en);
-extern int be_cmd_multicast_set(struct be_ctrl_info *ctrl, u32 if_id,
+extern int be_cmd_multicast_set(struct be_adapter *adapter, u32 if_id,
struct dev_mc_list *mc_list, u32 mc_count);
-extern int be_cmd_set_flow_control(struct be_ctrl_info *ctrl,
+extern int be_cmd_set_flow_control(struct be_adapter *adapter,
u32 tx_fc, u32 rx_fc);
-extern int be_cmd_get_flow_control(struct be_ctrl_info *ctrl,
+extern int be_cmd_get_flow_control(struct be_adapter *adapter,
u32 *tx_fc, u32 *rx_fc);
-extern int be_cmd_query_fw_cfg(struct be_ctrl_info *ctrl, u32 *port_num);
-extern void be_process_mcc(struct be_ctrl_info *ctrl);
+extern int be_cmd_query_fw_cfg(struct be_adapter *adapter, u32 *port_num);
+extern int be_cmd_reset_function(struct be_adapter *adapter);
+extern void be_process_mcc(struct be_adapter *adapter);
diff --git a/drivers/net/benet/be_ethtool.c b/drivers/net/benet/be_ethtool.c
index cccc5419ad7..c480c19200d 100644
--- a/drivers/net/benet/be_ethtool.c
+++ b/drivers/net/benet/be_ethtool.c
@@ -16,6 +16,7 @@
*/
#include "be.h"
+#include "be_cmds.h"
#include <linux/ethtool.h>
struct be_ethtool_stat {
@@ -127,8 +128,6 @@ be_get_coalesce(struct net_device *netdev, struct ethtool_coalesce *coalesce)
struct be_eq_obj *rx_eq = &adapter->rx_eq;
struct be_eq_obj *tx_eq = &adapter->tx_eq;
- coalesce->rx_max_coalesced_frames = adapter->max_rx_coal;
-
coalesce->rx_coalesce_usecs = rx_eq->cur_eqd;
coalesce->rx_coalesce_usecs_high = rx_eq->max_eqd;
coalesce->rx_coalesce_usecs_low = rx_eq->min_eqd;
@@ -144,14 +143,12 @@ be_get_coalesce(struct net_device *netdev, struct ethtool_coalesce *coalesce)
}
/*
- * This routine is used to set interrup coalescing delay *as well as*
- * the number of pkts to coalesce for LRO.
+ * This routine is used to set interrup coalescing delay
*/
static int
be_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *coalesce)
{
struct be_adapter *adapter = netdev_priv(netdev);
- struct be_ctrl_info *ctrl = &adapter->ctrl;
struct be_eq_obj *rx_eq = &adapter->rx_eq;
struct be_eq_obj *tx_eq = &adapter->tx_eq;
u32 tx_max, tx_min, tx_cur;
@@ -161,10 +158,6 @@ be_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *coalesce)
if (coalesce->use_adaptive_tx_coalesce == 1)
return -EINVAL;
- adapter->max_rx_coal = coalesce->rx_max_coalesced_frames;
- if (adapter->max_rx_coal > BE_MAX_FRAGS_PER_FRAME)
- adapter->max_rx_coal = BE_MAX_FRAGS_PER_FRAME;
-
/* if AIC is being turned on now, start with an EQD of 0 */
if (rx_eq->enable_aic == 0 &&
coalesce->use_adaptive_rx_coalesce == 1) {
@@ -183,7 +176,7 @@ be_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *coalesce)
if (tx_cur > BE_MAX_EQD)
tx_cur = BE_MAX_EQD;
if (tx_eq->cur_eqd != tx_cur) {
- status = be_cmd_modify_eqd(ctrl, tx_eq->q.id, tx_cur);
+ status = be_cmd_modify_eqd(adapter, tx_eq->q.id, tx_cur);
if (!status)
tx_eq->cur_eqd = tx_cur;
}
@@ -203,7 +196,8 @@ be_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *coalesce)
if (rx_cur > BE_MAX_EQD)
rx_cur = BE_MAX_EQD;
if (rx_eq->cur_eqd != rx_cur) {
- status = be_cmd_modify_eqd(ctrl, rx_eq->q.id, rx_cur);
+ status = be_cmd_modify_eqd(adapter, rx_eq->q.id,
+ rx_cur);
if (!status)
rx_eq->cur_eqd = rx_cur;
}
@@ -317,8 +311,7 @@ be_get_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *ecmd)
{
struct be_adapter *adapter = netdev_priv(netdev);
- be_cmd_get_flow_control(&adapter->ctrl, &ecmd->tx_pause,
- &ecmd->rx_pause);
+ be_cmd_get_flow_control(adapter, &ecmd->tx_pause, &ecmd->rx_pause);
ecmd->autoneg = 0;
}
@@ -331,7 +324,7 @@ be_set_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *ecmd)
if (ecmd->autoneg != 0)
return -EINVAL;
- status = be_cmd_set_flow_control(&adapter->ctrl, ecmd->tx_pause,
+ status = be_cmd_set_flow_control(adapter, ecmd->tx_pause,
ecmd->rx_pause);
if (!status)
dev_warn(&adapter->pdev->dev, "Pause param set failed.\n");
diff --git a/drivers/net/benet/be_hw.h b/drivers/net/benet/be_hw.h
index 29c33c709c6..d28f0c679bc 100644
--- a/drivers/net/benet/be_hw.h
+++ b/drivers/net/benet/be_hw.h
@@ -51,9 +51,6 @@
* with the OS.
*/
#define MEMBAR_CTRL_INT_CTRL_HOSTINTR_MASK (1 << 29) /* bit 29 */
-/* PCI physical function number */
-#define MEMBAR_CTRL_INT_CTRL_PFUNC_MASK 0x7 /* bits 26 - 28 */
-#define MEMBAR_CTRL_INT_CTRL_PFUNC_SHIFT 26
/********* ISR0 Register offset **********/
#define CEV_ISR0_OFFSET 0xC18
diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c
index dea3155688b..45507d88e6a 100644
--- a/drivers/net/benet/be_main.c
+++ b/drivers/net/benet/be_main.c
@@ -16,6 +16,7 @@
*/
#include "be.h"
+#include "be_cmds.h"
#include <asm/div64.h>
MODULE_VERSION(DRV_VER);
@@ -60,40 +61,39 @@ static int be_queue_alloc(struct be_adapter *adapter, struct be_queue_info *q,
return 0;
}
-static void be_intr_set(struct be_ctrl_info *ctrl, bool enable)
+static void be_intr_set(struct be_adapter *adapter, bool enable)
{
- u8 __iomem *addr = ctrl->pcicfg + PCICFG_MEMBAR_CTRL_INT_CTRL_OFFSET;
+ u8 __iomem *addr = adapter->pcicfg + PCICFG_MEMBAR_CTRL_INT_CTRL_OFFSET;
u32 reg = ioread32(addr);
u32 enabled = reg & MEMBAR_CTRL_INT_CTRL_HOSTINTR_MASK;
- if (!enabled && enable) {
+
+ if (!enabled && enable)
reg |= MEMBAR_CTRL_INT_CTRL_HOSTINTR_MASK;
- } else if (enabled && !enable) {
+ else if (enabled && !enable)
reg &= ~MEMBAR_CTRL_INT_CTRL_HOSTINTR_MASK;
- } else {
- printk(KERN_WARNING DRV_NAME
- ": bad value in membar_int_ctrl reg=0x%x\n", reg);
+ else
return;
- }
+
iowrite32(reg, addr);
}
-static void be_rxq_notify(struct be_ctrl_info *ctrl, u16 qid, u16 posted)
+static void be_rxq_notify(struct be_adapter *adapter, u16 qid, u16 posted)
{
u32 val = 0;
val |= qid & DB_RQ_RING_ID_MASK;
val |= posted << DB_RQ_NUM_POSTED_SHIFT;
- iowrite32(val, ctrl->db + DB_RQ_OFFSET);
+ iowrite32(val, adapter->db + DB_RQ_OFFSET);
}
-static void be_txq_notify(struct be_ctrl_info *ctrl, u16 qid, u16 posted)
+static void be_txq_notify(struct be_adapter *adapter, u16 qid, u16 posted)
{
u32 val = 0;
val |= qid & DB_TXULP_RING_ID_MASK;
val |= (posted & DB_TXULP_NUM_POSTED_MASK) << DB_TXULP_NUM_POSTED_SHIFT;
- iowrite32(val, ctrl->db + DB_TXULP1_OFFSET);
+ iowrite32(val, adapter->db + DB_TXULP1_OFFSET);
}
-static void be_eq_notify(struct be_ctrl_info *ctrl, u16 qid,
+static void be_eq_notify(struct be_adapter *adapter, u16 qid,
bool arm, bool clear_int, u16 num_popped)
{
u32 val = 0;
@@ -104,18 +104,17 @@ static void be_eq_notify(struct be_ctrl_info *ctrl, u16 qid,
val |= 1 << DB_EQ_CLR_SHIFT;
val |= 1 << DB_EQ_EVNT_SHIFT;
val |= num_popped << DB_EQ_NUM_POPPED_SHIFT;
- iowrite32(val, ctrl->db + DB_EQ_OFFSET);
+ iowrite32(val, adapter->db + DB_EQ_OFFSET);
}
-void be_cq_notify(struct be_ctrl_info *ctrl, u16 qid,
- bool arm, u16 num_popped)
+void be_cq_notify(struct be_adapter *adapter, u16 qid, bool arm, u16 num_popped)
{
u32 val = 0;
val |= qid & DB_CQ_RING_ID_MASK;
if (arm)
val |= 1 << DB_CQ_REARM_SHIFT;
val |= num_popped << DB_CQ_NUM_POPPED_SHIFT;
- iowrite32(val, ctrl->db + DB_CQ_OFFSET);
+ iowrite32(val, adapter->db + DB_CQ_OFFSET);
}
@@ -126,12 +125,12 @@ static int be_mac_addr_set(struct net_device *netdev, void *p)
int status = 0;
if (netif_running(netdev)) {
- status = be_cmd_pmac_del(&adapter->ctrl, adapter->if_handle,
+ status = be_cmd_pmac_del(adapter, adapter->if_handle,
adapter->pmac_id);
if (status)
return status;
- status = be_cmd_pmac_add(&adapter->ctrl, (u8 *)addr->sa_data,
+ status = be_cmd_pmac_add(adapter, (u8 *)addr->sa_data,
adapter->if_handle, &adapter->pmac_id);
}
@@ -214,9 +213,8 @@ static void netdev_stats_update(struct be_adapter *adapter)
dev_stats->tx_window_errors = 0;
}
-void be_link_status_update(void *ctxt, bool link_up)
+void be_link_status_update(struct be_adapter *adapter, bool link_up)
{
- struct be_adapter *adapter = ctxt;
struct net_device *netdev = adapter->netdev;
/* If link came up or went down */
@@ -237,7 +235,6 @@ void be_link_status_update(void *ctxt, bool link_up)
/* Update the EQ delay n BE based on the RX frags consumed / sec */
static void be_rx_eqd_update(struct be_adapter *adapter)
{
- struct be_ctrl_info *ctrl = &adapter->ctrl;
struct be_eq_obj *rx_eq = &adapter->rx_eq;
struct be_drvr_stats *stats = &adapter->stats.drvr_stats;
ulong now = jiffies;
@@ -270,7 +267,7 @@ static void be_rx_eqd_update(struct be_adapter *adapter)
if (eqd < 10)
eqd = 0;
if (eqd != rx_eq->cur_eqd)
- be_cmd_modify_eqd(ctrl, rx_eq->q.id, eqd);
+ be_cmd_modify_eqd(adapter, rx_eq->q.id, eqd);
rx_eq->cur_eqd = eqd;
}
@@ -412,8 +409,8 @@ static int make_tx_wrbs(struct be_adapter *adapter,
struct skb_frag_struct *frag =
&skb_shinfo(skb)->frags[i];
busaddr = pci_map_page(pdev, frag->page,
- frag->page_offset,
- frag->size, PCI_DMA_TODEVICE);
+ frag->page_offset,
+ frag->size, PCI_DMA_TODEVICE);
wrb = queue_head_node(txq);
wrb_fill(wrb, busaddr, frag->size);
be_dws_cpu_to_le(wrb, sizeof(*wrb));
@@ -461,7 +458,7 @@ static int be_xmit(struct sk_buff *skb, struct net_device *netdev)
stopped = true;
}
- be_txq_notify(&adapter->ctrl, txq->id, wrb_cnt);
+ be_txq_notify(adapter, txq->id, wrb_cnt);
be_tx_stats_update(adapter, wrb_cnt, copied, stopped);
return NETDEV_TX_OK;
@@ -502,10 +499,10 @@ static void be_vid_config(struct net_device *netdev)
ntags++;
}
}
- be_cmd_vlan_config(&adapter->ctrl, adapter->if_handle,
+ be_cmd_vlan_config(adapter, adapter->if_handle,
vtag, ntags, 1, 0);
} else {
- be_cmd_vlan_config(&adapter->ctrl, adapter->if_handle,
+ be_cmd_vlan_config(adapter, adapter->if_handle,
NULL, 0, 1, 1);
}
}
@@ -515,13 +512,12 @@ static void be_vlan_register(struct net_device *netdev, struct vlan_group *grp)
struct be_adapter *adapter = netdev_priv(netdev);
struct be_eq_obj *rx_eq = &adapter->rx_eq;
struct be_eq_obj *tx_eq = &adapter->tx_eq;
- struct be_ctrl_info *ctrl = &adapter->ctrl;
- be_eq_notify(ctrl, rx_eq->q.id, false, false, 0);
- be_eq_notify(ctrl, tx_eq->q.id, false, false, 0);
+ be_eq_notify(adapter, rx_eq->q.id, false, false, 0);
+ be_eq_notify(adapter, tx_eq->q.id, false, false, 0);
adapter->vlan_grp = grp;
- be_eq_notify(ctrl, rx_eq->q.id, true, false, 0);
- be_eq_notify(ctrl, tx_eq->q.id, true, false, 0);
+ be_eq_notify(adapter, rx_eq->q.id, true, false, 0);
+ be_eq_notify(adapter, tx_eq->q.id, true, false, 0);
}
static void be_vlan_add_vid(struct net_device *netdev, u16 vid)
@@ -548,10 +544,9 @@ static void be_vlan_rem_vid(struct net_device *netdev, u16 vid)
static void be_set_multicast_list(struct net_device *netdev)
{
struct be_adapter *adapter = netdev_priv(netdev);
- struct be_ctrl_info *ctrl = &adapter->ctrl;
if (netdev->flags & IFF_PROMISC) {
- be_cmd_promiscuous_config(ctrl, adapter->port_num, 1);
+ be_cmd_promiscuous_config(adapter, adapter->port_num, 1);
adapter->promiscuous = true;
goto done;
}
@@ -559,15 +554,15 @@ static void be_set_multicast_list(struct net_device *netdev)
/* BE was previously in promiscous mode; disable it */
if (adapter->promiscuous) {
adapter->promiscuous = false;
- be_cmd_promiscuous_config(ctrl, adapter->port_num, 0);
+ be_cmd_promiscuous_config(adapter, adapter->port_num, 0);
}
if (netdev->flags & IFF_ALLMULTI) {
- be_cmd_multicast_set(ctrl, adapter->if_handle, NULL, 0);
+ be_cmd_multicast_set(adapter, adapter->if_handle, NULL, 0);
goto done;
}
- be_cmd_multicast_set(ctrl, adapter->if_handle, netdev->mc_list,
+ be_cmd_multicast_set(adapter, adapter->if_handle, netdev->mc_list,
netdev->mc_count);
done:
return;
@@ -742,7 +737,7 @@ done:
return;
}
-/* Process the RX completion indicated by rxcp when LRO is disabled */
+/* Process the RX completion indicated by rxcp when GRO is disabled */
static void be_rx_compl_process(struct be_adapter *adapter,
struct be_eth_rx_compl *rxcp)
{
@@ -789,13 +784,14 @@ static void be_rx_compl_process(struct be_adapter *adapter,
return;
}
-/* Process the RX completion indicated by rxcp when LRO is enabled */
-static void be_rx_compl_process_lro(struct be_adapter *adapter,
+/* Process the RX completion indicated by rxcp when GRO is enabled */
+static void be_rx_compl_process_gro(struct be_adapter *adapter,
struct be_eth_rx_compl *rxcp)
{
struct be_rx_page_info *page_info;
- struct skb_frag_struct rx_frags[BE_MAX_FRAGS_PER_FRAME];
+ struct sk_buff *skb = NULL;
struct be_queue_info *rxq = &adapter->rx_obj.q;
+ struct be_eq_obj *eq_obj = &adapter->rx_eq;
u32 num_rcvd, pkt_size, remaining, vlanf, curr_frag_len;
u16 i, rxq_idx = 0, vid, j;
@@ -804,6 +800,12 @@ static void be_rx_compl_process_lro(struct be_adapter *adapter,
vlanf = AMAP_GET_BITS(struct amap_eth_rx_compl, vtp, rxcp);
rxq_idx = AMAP_GET_BITS(struct amap_eth_rx_compl, fragndx, rxcp);
+ skb = napi_get_frags(&eq_obj->napi);
+ if (!skb) {
+ be_rx_compl_discard(adapter, rxcp);
+ return;
+ }
+
remaining = pkt_size;
for (i = 0, j = -1; i < num_rcvd; i++) {
page_info = get_rx_page_info(adapter, rxq_idx);
@@ -814,13 +816,14 @@ static void be_rx_compl_process_lro(struct be_adapter *adapter,
if (i == 0 || page_info->page_offset == 0) {
/* First frag or Fresh page */
j++;
- rx_frags[j].page = page_info->page;
- rx_frags[j].page_offset = page_info->page_offset;
- rx_frags[j].size = 0;
+ skb_shinfo(skb)->frags[j].page = page_info->page;
+ skb_shinfo(skb)->frags[j].page_offset =
+ page_info->page_offset;
+ skb_shinfo(skb)->frags[j].size = 0;
} else {
put_page(page_info->page);
}
- rx_frags[j].size += curr_frag_len;
+ skb_shinfo(skb)->frags[j].size += curr_frag_len;
remaining -= curr_frag_len;
index_inc(&rxq_idx, rxq->len);
@@ -828,9 +831,14 @@ static void be_rx_compl_process_lro(struct be_adapter *adapter,
}
BUG_ON(j > MAX_SKB_FRAGS);
+ skb_shinfo(skb)->nr_frags = j + 1;
+ skb->len = pkt_size;
+ skb->data_len = pkt_size;
+ skb->truesize += pkt_size;
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+
if (likely(!vlanf)) {
- lro_receive_frags(&adapter->rx_obj.lro_mgr, rx_frags, pkt_size,
- pkt_size, NULL, 0);
+ napi_gro_frags(&eq_obj->napi);
} else {
vid = AMAP_GET_BITS(struct amap_eth_rx_compl, vlan_tag, rxcp);
vid = be16_to_cpu(vid);
@@ -838,9 +846,7 @@ static void be_rx_compl_process_lro(struct be_adapter *adapter,
if (!adapter->vlan_grp || adapter->num_vlans == 0)
return;
- lro_vlan_hwaccel_receive_frags(&adapter->rx_obj.lro_mgr,
- rx_frags, pkt_size, pkt_size, adapter->vlan_grp,
- vid, NULL, 0);
+ vlan_gro_frags(&eq_obj->napi, adapter->vlan_grp, vid);
}
be_rx_stats_update(adapter, pkt_size, num_rcvd);
@@ -931,7 +937,7 @@ static void be_post_rx_frags(struct be_adapter *adapter)
if (posted) {
atomic_add(posted, &rxq->used);
- be_rxq_notify(&adapter->ctrl, rxq->id, posted);
+ be_rxq_notify(adapter, rxq->id, posted);
} else if (atomic_read(&rxq->used) == 0) {
/* Let be_worker replenish when memory is available */
adapter->rx_post_starved = true;
@@ -987,6 +993,56 @@ static void be_tx_compl_process(struct be_adapter *adapter, u16 last_index)
kfree_skb(sent_skb);
}
+static inline struct be_eq_entry *event_get(struct be_eq_obj *eq_obj)
+{
+ struct be_eq_entry *eqe = queue_tail_node(&eq_obj->q);
+
+ if (!eqe->evt)
+ return NULL;
+
+ eqe->evt = le32_to_cpu(eqe->evt);
+ queue_tail_inc(&eq_obj->q);
+ return eqe;
+}
+
+static int event_handle(struct be_adapter *adapter,
+ struct be_eq_obj *eq_obj)
+{
+ struct be_eq_entry *eqe;
+ u16 num = 0;
+
+ while ((eqe = event_get(eq_obj)) != NULL) {
+ eqe->evt = 0;
+ num++;
+ }
+
+ /* Deal with any spurious interrupts that come
+ * without events
+ */
+ be_eq_notify(adapter, eq_obj->q.id, true, true, num);
+ if (num)
+ napi_schedule(&eq_obj->napi);
+
+ return num;
+}
+
+/* Just read and notify events without processing them.
+ * Used at the time of destroying event queues */
+static void be_eq_clean(struct be_adapter *adapter,
+ struct be_eq_obj *eq_obj)
+{
+ struct be_eq_entry *eqe;
+ u16 num = 0;
+
+ while ((eqe = event_get(eq_obj)) != NULL) {
+ eqe->evt = 0;
+ num++;
+ }
+
+ if (num)
+ be_eq_notify(adapter, eq_obj->q.id, false, true, num);
+}
+
static void be_rx_q_clean(struct be_adapter *adapter)
{
struct be_rx_page_info *page_info;
@@ -999,12 +1055,12 @@ static void be_rx_q_clean(struct be_adapter *adapter)
while ((rxcp = be_rx_compl_get(adapter)) != NULL) {
be_rx_compl_discard(adapter, rxcp);
be_rx_compl_reset(rxcp);
- be_cq_notify(&adapter->ctrl, rx_cq->id, true, 1);
+ be_cq_notify(adapter, rx_cq->id, true, 1);
}
/* Then free posted rx buffer that were not used */
tail = (rxq->head + rxq->len - atomic_read(&rxq->used)) % rxq->len;
- for (; tail != rxq->head; index_inc(&tail, rxq->len)) {
+ for (; atomic_read(&rxq->used) > 0; index_inc(&tail, rxq->len)) {
page_info = get_rx_page_info(adapter, tail);
put_page(page_info->page);
memset(page_info, 0, sizeof(*page_info));
@@ -1012,36 +1068,49 @@ static void be_rx_q_clean(struct be_adapter *adapter)
BUG_ON(atomic_read(&rxq->used));
}
-static void be_tx_q_clean(struct be_adapter *adapter)
+static void be_tx_compl_clean(struct be_adapter *adapter)
{
- struct sk_buff **sent_skbs = adapter->tx_obj.sent_skb_list;
- struct sk_buff *sent_skb;
+ struct be_queue_info *tx_cq = &adapter->tx_obj.cq;
struct be_queue_info *txq = &adapter->tx_obj.q;
- u16 last_index;
- bool dummy_wrb;
-
- while (atomic_read(&txq->used)) {
- sent_skb = sent_skbs[txq->tail];
- last_index = txq->tail;
- index_adv(&last_index,
- wrb_cnt_for_skb(sent_skb, &dummy_wrb) - 1, txq->len);
- be_tx_compl_process(adapter, last_index);
- }
+ struct be_eth_tx_compl *txcp;
+ u16 end_idx, cmpl = 0, timeo = 0;
+
+ /* Wait for a max of 200ms for all the tx-completions to arrive. */
+ do {
+ while ((txcp = be_tx_compl_get(tx_cq))) {
+ end_idx = AMAP_GET_BITS(struct amap_eth_tx_compl,
+ wrb_index, txcp);
+ be_tx_compl_process(adapter, end_idx);
+ cmpl++;
+ }
+ if (cmpl) {
+ be_cq_notify(adapter, tx_cq->id, false, cmpl);
+ cmpl = 0;
+ }
+
+ if (atomic_read(&txq->used) == 0 || ++timeo > 200)
+ break;
+
+ mdelay(1);
+ } while (true);
+
+ if (atomic_read(&txq->used))
+ dev_err(&adapter->pdev->dev, "%d pending tx-completions\n",
+ atomic_read(&txq->used));
}
static void be_mcc_queues_destroy(struct be_adapter *adapter)
{
struct be_queue_info *q;
- struct be_ctrl_info *ctrl = &adapter->ctrl;
- q = &ctrl->mcc_obj.q;
+ q = &adapter->mcc_obj.q;
if (q->created)
- be_cmd_q_destroy(ctrl, q, QTYPE_MCCQ);
+ be_cmd_q_destroy(adapter, q, QTYPE_MCCQ);
be_queue_free(adapter, q);
- q = &ctrl->mcc_obj.cq;
+ q = &adapter->mcc_obj.cq;
if (q->created)
- be_cmd_q_destroy(ctrl, q, QTYPE_CQ);
+ be_cmd_q_destroy(adapter, q, QTYPE_CQ);
be_queue_free(adapter, q);
}
@@ -1049,25 +1118,24 @@ static void be_mcc_queues_destroy(struct be_adapter *adapter)
static int be_mcc_queues_create(struct be_adapter *adapter)
{
struct be_queue_info *q, *cq;
- struct be_ctrl_info *ctrl = &adapter->ctrl;
/* Alloc MCC compl queue */
- cq = &ctrl->mcc_obj.cq;
+ cq = &adapter->mcc_obj.cq;
if (be_queue_alloc(adapter, cq, MCC_CQ_LEN,
- sizeof(struct be_mcc_cq_entry)))
+ sizeof(struct be_mcc_compl)))
goto err;
/* Ask BE to create MCC compl queue; share TX's eq */
- if (be_cmd_cq_create(ctrl, cq, &adapter->tx_eq.q, false, true, 0))
+ if (be_cmd_cq_create(adapter, cq, &adapter->tx_eq.q, false, true, 0))
goto mcc_cq_free;
/* Alloc MCC queue */
- q = &ctrl->mcc_obj.q;
+ q = &adapter->mcc_obj.q;
if (be_queue_alloc(adapter, q, MCC_Q_LEN, sizeof(struct be_mcc_wrb)))
goto mcc_cq_destroy;
/* Ask BE to create MCC queue */
- if (be_cmd_mccq_create(ctrl, q, cq))
+ if (be_cmd_mccq_create(adapter, q, cq))
goto mcc_q_free;
return 0;
@@ -1075,7 +1143,7 @@ static int be_mcc_queues_create(struct be_adapter *adapter)
mcc_q_free:
be_queue_free(adapter, q);
mcc_cq_destroy:
- be_cmd_q_destroy(ctrl, cq, QTYPE_CQ);
+ be_cmd_q_destroy(adapter, cq, QTYPE_CQ);
mcc_cq_free:
be_queue_free(adapter, cq);
err:
@@ -1087,23 +1155,21 @@ static void be_tx_queues_destroy(struct be_adapter *adapter)
struct be_queue_info *q;
q = &adapter->tx_obj.q;
- if (q->created) {
- be_cmd_q_destroy(&adapter->ctrl, q, QTYPE_TXQ);
-
- /* No more tx completions can be rcvd now; clean up if there
- * are any pending completions or pending tx requests */
- be_tx_q_clean(adapter);
- }
+ if (q->created)
+ be_cmd_q_destroy(adapter, q, QTYPE_TXQ);
be_queue_free(adapter, q);
q = &adapter->tx_obj.cq;
if (q->created)
- be_cmd_q_destroy(&adapter->ctrl, q, QTYPE_CQ);
+ be_cmd_q_destroy(adapter, q, QTYPE_CQ);
be_queue_free(adapter, q);
+ /* Clear any residual events */
+ be_eq_clean(adapter, &adapter->tx_eq);
+
q = &adapter->tx_eq.q;
if (q->created)
- be_cmd_q_destroy(&adapter->ctrl, q, QTYPE_EQ);
+ be_cmd_q_destroy(adapter, q, QTYPE_EQ);
be_queue_free(adapter, q);
}
@@ -1121,7 +1187,7 @@ static int be_tx_queues_create(struct be_adapter *adapter)
return -1;
/* Ask BE to create Tx Event queue */
- if (be_cmd_eq_create(&adapter->ctrl, eq, adapter->tx_eq.cur_eqd))
+ if (be_cmd_eq_create(adapter, eq, adapter->tx_eq.cur_eqd))
goto tx_eq_free;
/* Alloc TX eth compl queue */
cq = &adapter->tx_obj.cq;
@@ -1130,7 +1196,7 @@ static int be_tx_queues_create(struct be_adapter *adapter)
goto tx_eq_destroy;
/* Ask BE to create Tx eth compl queue */
- if (be_cmd_cq_create(&adapter->ctrl, cq, eq, false, false, 3))
+ if (be_cmd_cq_create(adapter, cq, eq, false, false, 3))
goto tx_cq_free;
/* Alloc TX eth queue */
@@ -1139,18 +1205,18 @@ static int be_tx_queues_create(struct be_adapter *adapter)
goto tx_cq_destroy;
/* Ask BE to create Tx eth queue */
- if (be_cmd_txq_create(&adapter->ctrl, q, cq))
+ if (be_cmd_txq_create(adapter, q, cq))
goto tx_q_free;
return 0;
tx_q_free:
be_queue_free(adapter, q);
tx_cq_destroy:
- be_cmd_q_destroy(&adapter->ctrl, cq, QTYPE_CQ);
+ be_cmd_q_destroy(adapter, cq, QTYPE_CQ);
tx_cq_free:
be_queue_free(adapter, cq);
tx_eq_destroy:
- be_cmd_q_destroy(&adapter->ctrl, eq, QTYPE_EQ);
+ be_cmd_q_destroy(adapter, eq, QTYPE_EQ);
tx_eq_free:
be_queue_free(adapter, eq);
return -1;
@@ -1162,19 +1228,22 @@ static void be_rx_queues_destroy(struct be_adapter *adapter)
q = &adapter->rx_obj.q;
if (q->created) {
- be_cmd_q_destroy(&adapter->ctrl, q, QTYPE_RXQ);
+ be_cmd_q_destroy(adapter, q, QTYPE_RXQ);
be_rx_q_clean(adapter);
}
be_queue_free(adapter, q);
q = &adapter->rx_obj.cq;
if (q->created)
- be_cmd_q_destroy(&adapter->ctrl, q, QTYPE_CQ);
+ be_cmd_q_destroy(adapter, q, QTYPE_CQ);
be_queue_free(adapter, q);
+ /* Clear any residual events */
+ be_eq_clean(adapter, &adapter->rx_eq);
+
q = &adapter->rx_eq.q;
if (q->created)
- be_cmd_q_destroy(&adapter->ctrl, q, QTYPE_EQ);
+ be_cmd_q_destroy(adapter, q, QTYPE_EQ);
be_queue_free(adapter, q);
}
@@ -1183,7 +1252,6 @@ static int be_rx_queues_create(struct be_adapter *adapter)
struct be_queue_info *eq, *q, *cq;
int rc;
- adapter->max_rx_coal = BE_MAX_FRAGS_PER_FRAME;
adapter->big_page_size = (1 << get_order(rx_frag_size)) * PAGE_SIZE;
adapter->rx_eq.max_eqd = BE_MAX_EQD;
adapter->rx_eq.min_eqd = 0;
@@ -1198,7 +1266,7 @@ static int be_rx_queues_create(struct be_adapter *adapter)
return rc;
/* Ask BE to create Rx Event queue */
- rc = be_cmd_eq_create(&adapter->ctrl, eq, adapter->rx_eq.cur_eqd);
+ rc = be_cmd_eq_create(adapter, eq, adapter->rx_eq.cur_eqd);
if (rc)
goto rx_eq_free;
@@ -1210,7 +1278,7 @@ static int be_rx_queues_create(struct be_adapter *adapter)
goto rx_eq_destroy;
/* Ask BE to create Rx eth compl queue */
- rc = be_cmd_cq_create(&adapter->ctrl, cq, eq, false, false, 3);
+ rc = be_cmd_cq_create(adapter, cq, eq, false, false, 3);
if (rc)
goto rx_cq_free;
@@ -1221,7 +1289,7 @@ static int be_rx_queues_create(struct be_adapter *adapter)
goto rx_cq_destroy;
/* Ask BE to create Rx eth queue */
- rc = be_cmd_rxq_create(&adapter->ctrl, q, cq->id, rx_frag_size,
+ rc = be_cmd_rxq_create(adapter, q, cq->id, rx_frag_size,
BE_MAX_JUMBO_FRAME_SIZE, adapter->if_handle, false);
if (rc)
goto rx_q_free;
@@ -1230,68 +1298,37 @@ static int be_rx_queues_create(struct be_adapter *adapter)
rx_q_free:
be_queue_free(adapter, q);
rx_cq_destroy:
- be_cmd_q_destroy(&adapter->ctrl, cq, QTYPE_CQ);
+ be_cmd_q_destroy(adapter, cq, QTYPE_CQ);
rx_cq_free:
be_queue_free(adapter, cq);
rx_eq_destroy:
- be_cmd_q_destroy(&adapter->ctrl, eq, QTYPE_EQ);
+ be_cmd_q_destroy(adapter, eq, QTYPE_EQ);
rx_eq_free:
be_queue_free(adapter, eq);
return rc;
}
-static bool event_get(struct be_eq_obj *eq_obj, u16 *rid)
-{
- struct be_eq_entry *entry = queue_tail_node(&eq_obj->q);
- u32 evt = entry->evt;
-
- if (!evt)
- return false;
-
- evt = le32_to_cpu(evt);
- *rid = (evt >> EQ_ENTRY_RES_ID_SHIFT) & EQ_ENTRY_RES_ID_MASK;
- entry->evt = 0;
- queue_tail_inc(&eq_obj->q);
- return true;
-}
-
-static int event_handle(struct be_ctrl_info *ctrl,
- struct be_eq_obj *eq_obj)
-{
- u16 rid = 0, num = 0;
-
- while (event_get(eq_obj, &rid))
- num++;
-
- /* We can see an interrupt and no event */
- be_eq_notify(ctrl, eq_obj->q.id, true, true, num);
- if (num)
- napi_schedule(&eq_obj->napi);
-
- return num;
-}
static irqreturn_t be_intx(int irq, void *dev)
{
struct be_adapter *adapter = dev;
- struct be_ctrl_info *ctrl = &adapter->ctrl;
- int isr;
+ int isr;
- isr = ioread32(ctrl->csr + CEV_ISR0_OFFSET +
- ctrl->pci_func * CEV_ISR_SIZE);
+ isr = ioread32(adapter->csr + CEV_ISR0_OFFSET +
+ be_pci_func(adapter) * CEV_ISR_SIZE);
if (!isr)
- return IRQ_NONE;
+ return IRQ_NONE;
- event_handle(ctrl, &adapter->tx_eq);
- event_handle(ctrl, &adapter->rx_eq);
+ event_handle(adapter, &adapter->tx_eq);
+ event_handle(adapter, &adapter->rx_eq);
- return IRQ_HANDLED;
+ return IRQ_HANDLED;
}
static irqreturn_t be_msix_rx(int irq, void *dev)
{
struct be_adapter *adapter = dev;
- event_handle(&adapter->ctrl, &adapter->rx_eq);
+ event_handle(adapter, &adapter->rx_eq);
return IRQ_HANDLED;
}
@@ -1300,12 +1337,12 @@ static irqreturn_t be_msix_tx_mcc(int irq, void *dev)
{
struct be_adapter *adapter = dev;
- event_handle(&adapter->ctrl, &adapter->tx_eq);
+ event_handle(adapter, &adapter->tx_eq);
return IRQ_HANDLED;
}
-static inline bool do_lro(struct be_adapter *adapter,
+static inline bool do_gro(struct be_adapter *adapter,
struct be_eth_rx_compl *rxcp)
{
int err = AMAP_GET_BITS(struct amap_eth_rx_compl, err, rxcp);
@@ -1314,8 +1351,7 @@ static inline bool do_lro(struct be_adapter *adapter,
if (err)
drvr_stats(adapter)->be_rxcp_err++;
- return (!tcp_frame || err || (adapter->max_rx_coal <= 1)) ?
- false : true;
+ return (tcp_frame && !err) ? true : false;
}
int be_poll_rx(struct napi_struct *napi, int budget)
@@ -1332,16 +1368,14 @@ int be_poll_rx(struct napi_struct *napi, int budget)
if (!rxcp)
break;
- if (do_lro(adapter, rxcp))
- be_rx_compl_process_lro(adapter, rxcp);
+ if (do_gro(adapter, rxcp))
+ be_rx_compl_process_gro(adapter, rxcp);
else
be_rx_compl_process(adapter, rxcp);
be_rx_compl_reset(rxcp);
}
- lro_flush_all(&adapter->rx_obj.lro_mgr);
-
/* Refill the queue */
if (atomic_read(&adapter->rx_obj.q.used) < RX_FRAGS_REFILL_WM)
be_post_rx_frags(adapter);
@@ -1349,10 +1383,10 @@ int be_poll_rx(struct napi_struct *napi, int budget)
/* All consumed */
if (work_done < budget) {
napi_complete(napi);
- be_cq_notify(&adapter->ctrl, rx_cq->id, true, work_done);
+ be_cq_notify(adapter, rx_cq->id, true, work_done);
} else {
/* More to be consumed; continue with interrupts disabled */
- be_cq_notify(&adapter->ctrl, rx_cq->id, false, work_done);
+ be_cq_notify(adapter, rx_cq->id, false, work_done);
}
return work_done;
}
@@ -1373,7 +1407,7 @@ void be_process_tx(struct be_adapter *adapter)
}
if (num_cmpl) {
- be_cq_notify(&adapter->ctrl, tx_cq->id, true, num_cmpl);
+ be_cq_notify(adapter, tx_cq->id, true, num_cmpl);
/* As Tx wrbs have been freed up, wake up netdev queue if
* it was stopped due to lack of tx wrbs.
@@ -1401,7 +1435,7 @@ static int be_poll_tx_mcc(struct napi_struct *napi, int budget)
be_process_tx(adapter);
- be_process_mcc(&adapter->ctrl);
+ be_process_mcc(adapter);
return 1;
}
@@ -1413,7 +1447,7 @@ static void be_worker(struct work_struct *work)
int status;
/* Get Stats */
- status = be_cmd_get_stats(&adapter->ctrl, &adapter->stats.cmd);
+ status = be_cmd_get_stats(adapter, &adapter->stats.cmd);
if (!status)
netdev_stats_update(adapter);
@@ -1447,8 +1481,7 @@ static void be_msix_enable(struct be_adapter *adapter)
static inline int be_msix_vec_get(struct be_adapter *adapter, u32 eq_id)
{
- return adapter->msix_entries[eq_id -
- 8 * adapter->ctrl.pci_func].vector;
+ return adapter->msix_entries[eq_id - 8 * be_pci_func(adapter)].vector;
}
static int be_msix_register(struct be_adapter *adapter)
@@ -1533,7 +1566,6 @@ done:
static int be_open(struct net_device *netdev)
{
struct be_adapter *adapter = netdev_priv(netdev);
- struct be_ctrl_info *ctrl = &adapter->ctrl;
struct be_eq_obj *rx_eq = &adapter->rx_eq;
struct be_eq_obj *tx_eq = &adapter->tx_eq;
bool link_up;
@@ -1547,16 +1579,16 @@ static int be_open(struct net_device *netdev)
be_irq_register(adapter);
- be_intr_set(ctrl, true);
+ be_intr_set(adapter, true);
/* The evt queues are created in unarmed state; arm them */
- be_eq_notify(ctrl, rx_eq->q.id, true, false, 0);
- be_eq_notify(ctrl, tx_eq->q.id, true, false, 0);
+ be_eq_notify(adapter, rx_eq->q.id, true, false, 0);
+ be_eq_notify(adapter, tx_eq->q.id, true, false, 0);
/* Rx compl queue may be in unarmed state; rearm it */
- be_cq_notify(ctrl, adapter->rx_obj.cq.id, true, 0);
+ be_cq_notify(adapter, adapter->rx_obj.cq.id, true, 0);
- status = be_cmd_link_status_query(ctrl, &link_up);
+ status = be_cmd_link_status_query(adapter, &link_up);
if (status)
return status;
be_link_status_update(adapter, link_up);
@@ -1567,7 +1599,6 @@ static int be_open(struct net_device *netdev)
static int be_setup(struct be_adapter *adapter)
{
- struct be_ctrl_info *ctrl = &adapter->ctrl;
struct net_device *netdev = adapter->netdev;
u32 if_flags;
int status;
@@ -1575,7 +1606,7 @@ static int be_setup(struct be_adapter *adapter)
if_flags = BE_IF_FLAGS_BROADCAST | BE_IF_FLAGS_PROMISCUOUS |
BE_IF_FLAGS_MCAST_PROMISCUOUS | BE_IF_FLAGS_UNTAGGED |
BE_IF_FLAGS_PASS_L3L4_ERRORS;
- status = be_cmd_if_create(ctrl, if_flags, netdev->dev_addr,
+ status = be_cmd_if_create(adapter, if_flags, netdev->dev_addr,
false/* pmac_invalid */, &adapter->if_handle,
&adapter->pmac_id);
if (status != 0)
@@ -1583,7 +1614,7 @@ static int be_setup(struct be_adapter *adapter)
be_vid_config(netdev);
- status = be_cmd_set_flow_control(ctrl, true, true);
+ status = be_cmd_set_flow_control(adapter, true, true);
if (status != 0)
goto if_destroy;
@@ -1606,19 +1637,17 @@ rx_qs_destroy:
tx_qs_destroy:
be_tx_queues_destroy(adapter);
if_destroy:
- be_cmd_if_destroy(ctrl, adapter->if_handle);
+ be_cmd_if_destroy(adapter, adapter->if_handle);
do_none:
return status;
}
static int be_clear(struct be_adapter *adapter)
{
- struct be_ctrl_info *ctrl = &adapter->ctrl;
-
be_rx_queues_destroy(adapter);
be_tx_queues_destroy(adapter);
- be_cmd_if_destroy(ctrl, adapter->if_handle);
+ be_cmd_if_destroy(adapter, adapter->if_handle);
be_mcc_queues_destroy(adapter);
return 0;
@@ -1627,7 +1656,6 @@ static int be_clear(struct be_adapter *adapter)
static int be_close(struct net_device *netdev)
{
struct be_adapter *adapter = netdev_priv(netdev);
- struct be_ctrl_info *ctrl = &adapter->ctrl;
struct be_eq_obj *rx_eq = &adapter->rx_eq;
struct be_eq_obj *tx_eq = &adapter->tx_eq;
int vec;
@@ -1638,7 +1666,7 @@ static int be_close(struct net_device *netdev)
netif_carrier_off(netdev);
adapter->link_up = false;
- be_intr_set(ctrl, false);
+ be_intr_set(adapter, false);
if (adapter->msix_enabled) {
vec = be_msix_vec_get(adapter, tx_eq->q.id);
@@ -1653,60 +1681,14 @@ static int be_close(struct net_device *netdev)
napi_disable(&rx_eq->napi);
napi_disable(&tx_eq->napi);
- return 0;
-}
-
-static int be_get_frag_header(struct skb_frag_struct *frag, void **mac_hdr,
- void **ip_hdr, void **tcpudp_hdr,
- u64 *hdr_flags, void *priv)
-{
- struct ethhdr *eh;
- struct vlan_ethhdr *veh;
- struct iphdr *iph;
- u8 *va = page_address(frag->page) + frag->page_offset;
- unsigned long ll_hlen;
-
- prefetch(va);
- eh = (struct ethhdr *)va;
- *mac_hdr = eh;
- ll_hlen = ETH_HLEN;
- if (eh->h_proto != htons(ETH_P_IP)) {
- if (eh->h_proto == htons(ETH_P_8021Q)) {
- veh = (struct vlan_ethhdr *)va;
- if (veh->h_vlan_encapsulated_proto != htons(ETH_P_IP))
- return -1;
-
- ll_hlen += VLAN_HLEN;
- } else {
- return -1;
- }
- }
- *hdr_flags = LRO_IPV4;
- iph = (struct iphdr *)(va + ll_hlen);
- *ip_hdr = iph;
- if (iph->protocol != IPPROTO_TCP)
- return -1;
- *hdr_flags |= LRO_TCP;
- *tcpudp_hdr = (u8 *) (*ip_hdr) + (iph->ihl << 2);
+ /* Wait for all pending tx completions to arrive so that
+ * all tx skbs are freed.
+ */
+ be_tx_compl_clean(adapter);
return 0;
}
-static void be_lro_init(struct be_adapter *adapter, struct net_device *netdev)
-{
- struct net_lro_mgr *lro_mgr;
-
- lro_mgr = &adapter->rx_obj.lro_mgr;
- lro_mgr->dev = netdev;
- lro_mgr->features = LRO_F_NAPI;
- lro_mgr->ip_summed = CHECKSUM_UNNECESSARY;
- lro_mgr->ip_summed_aggr = CHECKSUM_UNNECESSARY;
- lro_mgr->max_desc = BE_MAX_LRO_DESCRIPTORS;
- lro_mgr->lro_arr = adapter->rx_obj.lro_desc;
- lro_mgr->get_frag_header = be_get_frag_header;
- lro_mgr->max_aggr = BE_MAX_FRAGS_PER_FRAME;
-}
-
static struct net_device_ops be_netdev_ops = {
.ndo_open = be_open,
.ndo_stop = be_close,
@@ -1727,7 +1709,7 @@ static void be_netdev_init(struct net_device *netdev)
netdev->features |= NETIF_F_SG | NETIF_F_HW_VLAN_RX | NETIF_F_TSO |
NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_FILTER | NETIF_F_IP_CSUM |
- NETIF_F_IPV6_CSUM;
+ NETIF_F_IPV6_CSUM | NETIF_F_GRO;
netdev->flags |= IFF_MULTICAST;
@@ -1737,8 +1719,6 @@ static void be_netdev_init(struct net_device *netdev)
SET_ETHTOOL_OPS(netdev, &be_ethtool_ops);
- be_lro_init(adapter, netdev);
-
netif_napi_add(netdev, &adapter->rx_eq.napi, be_poll_rx,
BE_NAPI_WEIGHT);
netif_napi_add(netdev, &adapter->tx_eq.napi, be_poll_tx_mcc,
@@ -1750,13 +1730,12 @@ static void be_netdev_init(struct net_device *netdev)
static void be_unmap_pci_bars(struct be_adapter *adapter)
{
- struct be_ctrl_info *ctrl = &adapter->ctrl;
- if (ctrl->csr)
- iounmap(ctrl->csr);
- if (ctrl->db)
- iounmap(ctrl->db);
- if (ctrl->pcicfg)
- iounmap(ctrl->pcicfg);
+ if (adapter->csr)
+ iounmap(adapter->csr);
+ if (adapter->db)
+ iounmap(adapter->db);
+ if (adapter->pcicfg)
+ iounmap(adapter->pcicfg);
}
static int be_map_pci_bars(struct be_adapter *adapter)
@@ -1767,19 +1746,19 @@ static int be_map_pci_bars(struct be_adapter *adapter)
pci_resource_len(adapter->pdev, 2));
if (addr == NULL)
return -ENOMEM;
- adapter->ctrl.csr = addr;
+ adapter->csr = addr;
addr = ioremap_nocache(pci_resource_start(adapter->pdev, 4),
128 * 1024);
if (addr == NULL)
goto pci_map_err;
- adapter->ctrl.db = addr;
+ adapter->db = addr;
addr = ioremap_nocache(pci_resource_start(adapter->pdev, 1),
pci_resource_len(adapter->pdev, 1));
if (addr == NULL)
goto pci_map_err;
- adapter->ctrl.pcicfg = addr;
+ adapter->pcicfg = addr;
return 0;
pci_map_err:
@@ -1790,7 +1769,7 @@ pci_map_err:
static void be_ctrl_cleanup(struct be_adapter *adapter)
{
- struct be_dma_mem *mem = &adapter->ctrl.mbox_mem_alloced;
+ struct be_dma_mem *mem = &adapter->mbox_mem_alloced;
be_unmap_pci_bars(adapter);
@@ -1799,14 +1778,11 @@ static void be_ctrl_cleanup(struct be_adapter *adapter)
mem->va, mem->dma);
}
-/* Initialize the mbox required to send cmds to BE */
static int be_ctrl_init(struct be_adapter *adapter)
{
- struct be_ctrl_info *ctrl = &adapter->ctrl;
- struct be_dma_mem *mbox_mem_alloc = &ctrl->mbox_mem_alloced;
- struct be_dma_mem *mbox_mem_align = &ctrl->mbox_mem;
+ struct be_dma_mem *mbox_mem_alloc = &adapter->mbox_mem_alloced;
+ struct be_dma_mem *mbox_mem_align = &adapter->mbox_mem;
int status;
- u32 val;
status = be_map_pci_bars(adapter);
if (status)
@@ -1823,16 +1799,10 @@ static int be_ctrl_init(struct be_adapter *adapter)
mbox_mem_align->va = PTR_ALIGN(mbox_mem_alloc->va, 16);
mbox_mem_align->dma = PTR_ALIGN(mbox_mem_alloc->dma, 16);
memset(mbox_mem_align->va, 0, sizeof(struct be_mcc_mailbox));
- spin_lock_init(&ctrl->mbox_lock);
- spin_lock_init(&ctrl->mcc_lock);
- spin_lock_init(&ctrl->mcc_cq_lock);
-
- ctrl->async_cb = be_link_status_update;
- ctrl->adapter_ctxt = adapter;
+ spin_lock_init(&adapter->mbox_lock);
+ spin_lock_init(&adapter->mcc_lock);
+ spin_lock_init(&adapter->mcc_cq_lock);
- val = ioread32(ctrl->pcicfg + PCICFG_MEMBAR_CTRL_INT_CTRL_OFFSET);
- ctrl->pci_func = (val >> MEMBAR_CTRL_INT_CTRL_PFUNC_SHIFT) &
- MEMBAR_CTRL_INT_CTRL_PFUNC_MASK;
return 0;
}
@@ -1886,18 +1856,17 @@ static void __devexit be_remove(struct pci_dev *pdev)
static int be_hw_up(struct be_adapter *adapter)
{
- struct be_ctrl_info *ctrl = &adapter->ctrl;
int status;
- status = be_cmd_POST(ctrl);
+ status = be_cmd_POST(adapter);
if (status)
return status;
- status = be_cmd_get_fw_ver(ctrl, adapter->fw_ver);
+ status = be_cmd_get_fw_ver(adapter, adapter->fw_ver);
if (status)
return status;
- status = be_cmd_query_fw_cfg(ctrl, &adapter->port_num);
+ status = be_cmd_query_fw_cfg(adapter, &adapter->port_num);
return status;
}
@@ -1907,7 +1876,6 @@ static int __devinit be_probe(struct pci_dev *pdev,
int status = 0;
struct be_adapter *adapter;
struct net_device *netdev;
- struct be_ctrl_info *ctrl;
u8 mac[ETH_ALEN];
status = pci_enable_device(pdev);
@@ -1942,11 +1910,14 @@ static int __devinit be_probe(struct pci_dev *pdev,
}
}
- ctrl = &adapter->ctrl;
status = be_ctrl_init(adapter);
if (status)
goto free_netdev;
+ status = be_cmd_reset_function(adapter);
+ if (status)
+ goto ctrl_clean;
+
status = be_stats_init(adapter);
if (status)
goto ctrl_clean;
@@ -1955,7 +1926,7 @@ static int __devinit be_probe(struct pci_dev *pdev,
if (status)
goto stats_clean;
- status = be_cmd_mac_addr_query(ctrl, mac, MAC_ADDRESS_TYPE_NETWORK,
+ status = be_cmd_mac_addr_query(adapter, mac, MAC_ADDRESS_TYPE_NETWORK,
true /* permanent */, 0);
if (status)
goto stats_clean;
@@ -2001,9 +1972,9 @@ static int be_suspend(struct pci_dev *pdev, pm_message_t state)
if (netif_running(netdev)) {
rtnl_lock();
be_close(netdev);
- be_clear(adapter);
rtnl_unlock();
}
+ be_clear(adapter);
pci_save_state(pdev);
pci_disable_device(pdev);
@@ -2026,9 +1997,9 @@ static int be_resume(struct pci_dev *pdev)
pci_set_power_state(pdev, 0);
pci_restore_state(pdev);
+ be_setup(adapter);
if (netif_running(netdev)) {
rtnl_lock();
- be_setup(adapter);
be_open(netdev);
rtnl_unlock();
}
@@ -2054,12 +2025,6 @@ static int __init be_init_module(void)
" Using 2048\n");
rx_frag_size = 2048;
}
- /* Ensure rx_frag_size is aligned to chache line */
- if (SKB_DATA_ALIGN(rx_frag_size) != rx_frag_size) {
- printk(KERN_WARNING DRV_NAME
- " : Bad module param rx_frag_size. Using 2048\n");
- rx_frag_size = 2048;
- }
return pci_register_driver(&be_driver);
}
diff --git a/drivers/net/bfin_mac.c b/drivers/net/bfin_mac.c
index c15fc281f79..f580b21eabd 100644
--- a/drivers/net/bfin_mac.c
+++ b/drivers/net/bfin_mac.c
@@ -656,7 +656,7 @@ out:
dev->trans_start = jiffies;
dev->stats.tx_packets++;
dev->stats.tx_bytes += (skb->len);
- return 0;
+ return NETDEV_TX_OK;
}
static void bfin_mac_rx(struct net_device *dev)
diff --git a/drivers/net/bmac.c b/drivers/net/bmac.c
index 206144f2470..406f0642425 100644
--- a/drivers/net/bmac.c
+++ b/drivers/net/bmac.c
@@ -1489,7 +1489,7 @@ bmac_output(struct sk_buff *skb, struct net_device *dev)
struct bmac_data *bp = netdev_priv(dev);
skb_queue_tail(bp->queue, skb);
bmac_start(dev);
- return 0;
+ return NETDEV_TX_OK;
}
static void bmac_tx_timeout(unsigned long data)
diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
index b70cc99962f..756d4b4f0a9 100644
--- a/drivers/net/bnx2.c
+++ b/drivers/net/bnx2.c
@@ -8023,6 +8023,13 @@ static const struct net_device_ops bnx2_netdev_ops = {
#endif
};
+static void inline vlan_features_add(struct net_device *dev, unsigned long flags)
+{
+#ifdef BCM_VLAN
+ dev->vlan_features |= flags;
+#endif
+}
+
static int __devinit
bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
{
@@ -8064,16 +8071,20 @@ bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
memcpy(dev->perm_addr, bp->mac_addr, 6);
dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG;
- if (CHIP_NUM(bp) == CHIP_NUM_5709)
+ vlan_features_add(dev, NETIF_F_IP_CSUM | NETIF_F_SG);
+ if (CHIP_NUM(bp) == CHIP_NUM_5709) {
dev->features |= NETIF_F_IPV6_CSUM;
-
+ vlan_features_add(dev, NETIF_F_IPV6_CSUM);
+ }
#ifdef BCM_VLAN
dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
#endif
dev->features |= NETIF_F_TSO | NETIF_F_TSO_ECN;
- if (CHIP_NUM(bp) == CHIP_NUM_5709)
+ vlan_features_add(dev, NETIF_F_TSO | NETIF_F_TSO_ECN);
+ if (CHIP_NUM(bp) == CHIP_NUM_5709) {
dev->features |= NETIF_F_TSO6;
-
+ vlan_features_add(dev, NETIF_F_TSO6);
+ }
if ((rc = register_netdev(dev))) {
dev_err(&pdev->dev, "Cannot register net device\n");
goto error;
@@ -8188,6 +8199,11 @@ static pci_ers_result_t bnx2_io_error_detected(struct pci_dev *pdev,
rtnl_lock();
netif_device_detach(dev);
+ if (state == pci_channel_io_perm_failure) {
+ rtnl_unlock();
+ return PCI_ERS_RESULT_DISCONNECT;
+ }
+
if (netif_running(dev)) {
bnx2_netif_stop(bp);
del_timer_sync(&bp->timer);
diff --git a/drivers/net/bnx2x.h b/drivers/net/bnx2x.h
index 85a737c5c23..bbf842284eb 100644
--- a/drivers/net/bnx2x.h
+++ b/drivers/net/bnx2x.h
@@ -30,6 +30,8 @@
#define BNX2X_NEW_NAPI
+
+#include <linux/mdio.h>
#include "bnx2x_reg.h"
#include "bnx2x_fw_defs.h"
#include "bnx2x_hsi.h"
@@ -87,6 +89,7 @@
} while (0)
#else
#define bnx2x_panic() do { \
+ bp->panic = 1; \
BNX2X_ERR("driver assert\n"); \
bnx2x_panic_dump(bp); \
} while (0)
@@ -113,21 +116,32 @@
#define REG_RD_DMAE(bp, offset, valp, len32) \
do { \
bnx2x_read_dmae(bp, offset, len32);\
- memcpy(valp, bnx2x_sp(bp, wb_data[0]), len32 * 4); \
+ memcpy(valp, bnx2x_sp(bp, wb_data[0]), (len32) * 4); \
} while (0)
#define REG_WR_DMAE(bp, offset, valp, len32) \
do { \
- memcpy(bnx2x_sp(bp, wb_data[0]), valp, len32 * 4); \
+ memcpy(bnx2x_sp(bp, wb_data[0]), valp, (len32) * 4); \
bnx2x_write_dmae(bp, bnx2x_sp_mapping(bp, wb_data), \
offset, len32); \
} while (0)
+#define VIRT_WR_DMAE_LEN(bp, data, addr, len32) \
+ do { \
+ memcpy(GUNZIP_BUF(bp), data, (len32) * 4); \
+ bnx2x_write_big_buf_wb(bp, addr, len32); \
+ } while (0)
+
#define SHMEM_ADDR(bp, field) (bp->common.shmem_base + \
offsetof(struct shmem_region, field))
#define SHMEM_RD(bp, field) REG_RD(bp, SHMEM_ADDR(bp, field))
#define SHMEM_WR(bp, field, val) REG_WR(bp, SHMEM_ADDR(bp, field), val)
+#define SHMEM2_ADDR(bp, field) (bp->common.shmem2_base + \
+ offsetof(struct shmem2_region, field))
+#define SHMEM2_RD(bp, field) REG_RD(bp, SHMEM2_ADDR(bp, field))
+#define SHMEM2_WR(bp, field, val) REG_WR(bp, SHMEM2_ADDR(bp, field), val)
+
#define EMAC_RD(bp, reg) REG_RD(bp, emac_base + reg)
#define EMAC_WR(bp, reg, val) REG_WR(bp, emac_base + reg, val)
@@ -142,6 +156,9 @@ struct sw_rx_bd {
struct sw_tx_bd {
struct sk_buff *skb;
u16 first_bd;
+ u8 flags;
+/* Set on the first BD descriptor when there is a split BD */
+#define BNX2X_TSO_SPLIT_BD (1<<0)
};
struct sw_rx_page {
@@ -149,6 +166,11 @@ struct sw_rx_page {
DECLARE_PCI_UNMAP_ADDR(mapping)
};
+union db_prod {
+ struct doorbell_set_prod data;
+ u32 raw;
+};
+
/* MC hsi */
#define BCM_PAGE_SHIFT 12
@@ -160,7 +182,7 @@ struct sw_rx_page {
#define PAGES_PER_SGE (1 << PAGES_PER_SGE_SHIFT)
#define SGE_PAGE_SIZE PAGE_SIZE
#define SGE_PAGE_SHIFT PAGE_SHIFT
-#define SGE_PAGE_ALIGN(addr) PAGE_ALIGN((typeof(PAGE_SIZE))addr)
+#define SGE_PAGE_ALIGN(addr) PAGE_ALIGN((typeof(PAGE_SIZE))(addr))
/* SGE ring related macros */
#define NUM_RX_SGE_PAGES 2
@@ -234,15 +256,14 @@ struct bnx2x_fastpath {
struct napi_struct napi;
+ u8 is_rx_queue;
+
struct host_status_block *status_blk;
dma_addr_t status_blk_mapping;
- struct eth_tx_db_data *hw_tx_prods;
- dma_addr_t tx_prods_mapping;
-
struct sw_tx_bd *tx_buf_ring;
- struct eth_tx_bd *tx_desc_ring;
+ union eth_tx_bd_types *tx_desc_ring;
dma_addr_t tx_desc_mapping;
struct sw_rx_bd *rx_buf_ring; /* BDs mappings ring */
@@ -272,6 +293,8 @@ struct bnx2x_fastpath {
u8 cl_id; /* eth client id */
u8 sb_id; /* status block number in HW */
+ union db_prod tx_db;
+
u16 tx_pkt_prod;
u16 tx_pkt_cons;
u16 tx_bd_prod;
@@ -291,9 +314,11 @@ struct bnx2x_fastpath {
__le16 *rx_cons_sb;
__le16 *rx_bd_cons_sb;
+
unsigned long tx_pkt,
rx_pkt,
rx_calls;
+
/* TPA related */
struct sw_rx_bd tpa_pool[ETH_MAX_AGGREGATION_QUEUES_E1H];
u8 tpa_state[ETH_MAX_AGGREGATION_QUEUES_E1H];
@@ -309,21 +334,24 @@ struct bnx2x_fastpath {
struct xstorm_per_client_stats old_xclient;
struct bnx2x_eth_q_stats eth_q_stats;
- char name[IFNAMSIZ];
+ /* The size is calculated using the following:
+ sizeof name field from netdev structure +
+ 4 ('-Xx-' string) +
+ 4 (for the digits and to make it DWORD aligned) */
+#define FP_NAME_SIZE (sizeof(((struct net_device *)0)->name) + 8)
+ char name[FP_NAME_SIZE];
struct bnx2x *bp; /* parent */
};
#define bnx2x_fp(bp, nr, var) (bp->fp[nr].var)
-#define BNX2X_HAS_WORK(fp) (bnx2x_has_rx_work(fp) || bnx2x_has_tx_work(fp))
-
/* MC hsi */
#define MAX_FETCH_BD 13 /* HW max BDs per packet */
#define RX_COPY_THRESH 92
#define NUM_TX_RINGS 16
-#define TX_DESC_CNT (BCM_PAGE_SIZE / sizeof(struct eth_tx_bd))
+#define TX_DESC_CNT (BCM_PAGE_SIZE / sizeof(union eth_tx_bd_types))
#define MAX_TX_DESC_CNT (TX_DESC_CNT - 1)
#define NUM_TX_BD (TX_DESC_CNT * NUM_TX_RINGS)
#define MAX_TX_BD (NUM_TX_BD - 1)
@@ -395,7 +423,7 @@ struct bnx2x_fastpath {
#define DPM_TRIGER_TYPE 0x40
#define DOORBELL(bp, cid, val) \
do { \
- writel((u32)val, (bp)->doorbells + (BCM_PAGE_SIZE * cid) + \
+ writel((u32)(val), bp->doorbells + (BCM_PAGE_SIZE * (cid)) + \
DPM_TRIGER_TYPE); \
} while (0)
@@ -523,6 +551,7 @@ struct bnx2x_common {
#define NVRAM_PAGE_SIZE 256
u32 shmem_base;
+ u32 shmem2_base;
u32 hw_config;
@@ -757,6 +786,7 @@ struct bnx2x_slowpath {
struct nig_stats nig_stats;
struct host_port_stats port_stats;
struct host_func_stats func_stats;
+ struct host_func_stats func_stats_base;
u32 wb_comp;
u32 wb_data[4];
@@ -877,6 +907,7 @@ struct bnx2x {
struct link_params link_params;
struct link_vars link_vars;
+ struct mdio_if_info mdio;
struct bnx2x_common common;
struct bnx2x_port port;
@@ -902,8 +933,6 @@ struct bnx2x {
u16 rx_quick_cons_trip;
u16 rx_ticks_int;
u16 rx_ticks;
-/* Maximal coalescing timeout in us */
-#define BNX2X_MAX_COALESCE_TOUT (0xf0*12)
u32 lin_cnt;
@@ -947,10 +976,11 @@ struct bnx2x {
dma_addr_t qm_mapping;
#endif
+ int dropless_fc;
+
int dmae_ready;
/* used to synchronize dmae accesses */
struct mutex dmae_mutex;
- struct dmae_command init_dmae;
/* used to synchronize stats collecting */
int stats_state;
@@ -966,38 +996,54 @@ struct bnx2x {
dma_addr_t gunzip_mapping;
int gunzip_outlen;
#define FW_BUF_SIZE 0x8000
+#define GUNZIP_BUF(bp) (bp->gunzip_buf)
+#define GUNZIP_PHYS(bp) (bp->gunzip_mapping)
+#define GUNZIP_OUTLEN(bp) (bp->gunzip_outlen)
- struct raw_op *init_ops;
+ struct raw_op *init_ops;
/* Init blocks offsets inside init_ops */
- u16 *init_ops_offsets;
+ u16 *init_ops_offsets;
/* Data blob - has 32 bit granularity */
- u32 *init_data;
+ u32 *init_data;
/* Zipped PRAM blobs - raw data */
- const u8 *tsem_int_table_data;
- const u8 *tsem_pram_data;
- const u8 *usem_int_table_data;
- const u8 *usem_pram_data;
- const u8 *xsem_int_table_data;
- const u8 *xsem_pram_data;
- const u8 *csem_int_table_data;
- const u8 *csem_pram_data;
- const struct firmware *firmware;
+ const u8 *tsem_int_table_data;
+ const u8 *tsem_pram_data;
+ const u8 *usem_int_table_data;
+ const u8 *usem_pram_data;
+ const u8 *xsem_int_table_data;
+ const u8 *xsem_pram_data;
+ const u8 *csem_int_table_data;
+ const u8 *csem_pram_data;
+#define INIT_OPS(bp) (bp->init_ops)
+#define INIT_OPS_OFFSETS(bp) (bp->init_ops_offsets)
+#define INIT_DATA(bp) (bp->init_data)
+#define INIT_TSEM_INT_TABLE_DATA(bp) (bp->tsem_int_table_data)
+#define INIT_TSEM_PRAM_DATA(bp) (bp->tsem_pram_data)
+#define INIT_USEM_INT_TABLE_DATA(bp) (bp->usem_int_table_data)
+#define INIT_USEM_PRAM_DATA(bp) (bp->usem_pram_data)
+#define INIT_XSEM_INT_TABLE_DATA(bp) (bp->xsem_int_table_data)
+#define INIT_XSEM_PRAM_DATA(bp) (bp->xsem_pram_data)
+#define INIT_CSEM_INT_TABLE_DATA(bp) (bp->csem_int_table_data)
+#define INIT_CSEM_PRAM_DATA(bp) (bp->csem_pram_data)
+
+ const struct firmware *firmware;
};
-#define BNX2X_MAX_QUEUES(bp) (IS_E1HMF(bp) ? (MAX_CONTEXT / E1HVN_MAX) : \
- MAX_CONTEXT)
-#define BNX2X_NUM_QUEUES(bp) max(bp->num_rx_queues, bp->num_tx_queues)
-#define is_multi(bp) (BNX2X_NUM_QUEUES(bp) > 1)
+#define BNX2X_MAX_QUEUES(bp) (IS_E1HMF(bp) ? (MAX_CONTEXT/(2 * E1HVN_MAX)) \
+ : (MAX_CONTEXT/2))
+#define BNX2X_NUM_QUEUES(bp) (bp->num_rx_queues + bp->num_tx_queues)
+#define is_multi(bp) (BNX2X_NUM_QUEUES(bp) > 2)
#define for_each_rx_queue(bp, var) \
for (var = 0; var < bp->num_rx_queues; var++)
#define for_each_tx_queue(bp, var) \
- for (var = 0; var < bp->num_tx_queues; var++)
+ for (var = bp->num_rx_queues; \
+ var < BNX2X_NUM_QUEUES(bp); var++)
#define for_each_queue(bp, var) \
for (var = 0; var < BNX2X_NUM_QUEUES(bp); var++)
#define for_each_nondefault_queue(bp, var) \
- for (var = 1; var < BNX2X_NUM_QUEUES(bp); var++)
+ for (var = 1; var < bp->num_rx_queues; var++)
void bnx2x_read_dmae(struct bnx2x *bp, u32 src_addr, u32 len32);
@@ -1006,6 +1052,10 @@ void bnx2x_write_dmae(struct bnx2x *bp, dma_addr_t dma_addr, u32 dst_addr,
int bnx2x_get_gpio(struct bnx2x *bp, int gpio_num, u8 port);
int bnx2x_set_gpio(struct bnx2x *bp, int gpio_num, u32 mode, u8 port);
int bnx2x_set_gpio_int(struct bnx2x *bp, int gpio_num, u32 mode, u8 port);
+u32 bnx2x_fw_command(struct bnx2x *bp, u32 command);
+void bnx2x_reg_wr_ind(struct bnx2x *bp, u32 addr, u32 val);
+void bnx2x_write_dmae_phys_len(struct bnx2x *bp, dma_addr_t phys_addr,
+ u32 addr, u32 len);
static inline u32 reg_poll(struct bnx2x *bp, u32 reg, u32 expected, int ms,
int wait)
@@ -1063,9 +1113,9 @@ static inline u32 reg_poll(struct bnx2x *bp, u32 reg, u32 expected, int ms,
#define DMAE_COMP_VAL 0xe0d0d0ae
#define MAX_DMAE_C_PER_PORT 8
-#define INIT_DMAE_C(bp) (BP_PORT(bp)*MAX_DMAE_C_PER_PORT + \
+#define INIT_DMAE_C(bp) (BP_PORT(bp) * MAX_DMAE_C_PER_PORT + \
BP_E1HVN(bp))
-#define PMF_DMAE_C(bp) (BP_PORT(bp)*MAX_DMAE_C_PER_PORT + \
+#define PMF_DMAE_C(bp) (BP_PORT(bp) * MAX_DMAE_C_PER_PORT + \
E1HVN_MAX)
@@ -1090,7 +1140,8 @@ static inline u32 reg_poll(struct bnx2x *bp, u32 reg, u32 expected, int ms,
/* must be used on a CID before placing it on a HW ring */
-#define HW_CID(bp, x) ((BP_PORT(bp) << 23) | (BP_E1HVN(bp) << 17) | x)
+#define HW_CID(bp, x) ((BP_PORT(bp) << 23) | \
+ (BP_E1HVN(bp) << 17) | (x))
#define SP_DESC_CNT (BCM_PAGE_SIZE / sizeof(struct eth_spe))
#define MAX_SP_DESC_CNT (SP_DESC_CNT - 1)
@@ -1178,8 +1229,8 @@ static inline u32 reg_poll(struct bnx2x *bp, u32 reg, u32 expected, int ms,
AEU_INPUTS_ATTN_BITS_QM_PARITY_ERROR | \
AEU_INPUTS_ATTN_BITS_XSDM_PARITY_ERROR | \
AEU_INPUTS_ATTN_BITS_XSEMI_PARITY_ERROR | \
- AEU_INPUTS_ATTN_BITS_DOORBELLQ_PARITY_ERROR |\
- AEU_INPUTS_ATTN_BITS_VAUX_PCI_CORE_PARITY_ERROR |\
+ AEU_INPUTS_ATTN_BITS_DOORBELLQ_PARITY_ERROR |\
+ AEU_INPUTS_ATTN_BITS_VAUX_PCI_CORE_PARITY_ERROR |\
AEU_INPUTS_ATTN_BITS_DEBUG_PARITY_ERROR | \
AEU_INPUTS_ATTN_BITS_USDM_PARITY_ERROR | \
AEU_INPUTS_ATTN_BITS_USEMI_PARITY_ERROR | \
@@ -1207,7 +1258,6 @@ static inline u32 reg_poll(struct bnx2x *bp, u32 reg, u32 expected, int ms,
TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV6_TCP_CAPABILITY | \
(bp->multi_mode << \
TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_MODE_SHIFT))
-
#define MULTI_MASK 0x7f
diff --git a/drivers/net/bnx2x_dump.h b/drivers/net/bnx2x_dump.h
index 78c6b0353ad..3bb9a91bb3f 100644
--- a/drivers/net/bnx2x_dump.h
+++ b/drivers/net/bnx2x_dump.h
@@ -13,31 +13,35 @@
* The signature is time stamp, diag version and grc_dump version
*/
+#ifndef BNX2X_DUMP_H
+#define BNX2X_DUMP_H
+
+
struct dump_sign {
u32 time_stamp;
u32 diag_ver;
u32 grc_dump_ver;
};
-#define TSTORM_WAITP_ADDR 0x1b8a80
-#define CSTORM_WAITP_ADDR 0x238a80
-#define XSTORM_WAITP_ADDR 0x2b8a80
-#define USTORM_WAITP_ADDR 0x338a80
-#define TSTORM_CAM_MODE 0x1b1440
+#define TSTORM_WAITP_ADDR 0x1b8a80
+#define CSTORM_WAITP_ADDR 0x238a80
+#define XSTORM_WAITP_ADDR 0x2b8a80
+#define USTORM_WAITP_ADDR 0x338a80
+#define TSTORM_CAM_MODE 0x1b1440
-#define RI_E1 0x1
-#define RI_E1H 0x2
-#define RI_ONLINE 0x100
+#define RI_E1 0x1
+#define RI_E1H 0x2
+#define RI_ONLINE 0x100
-#define RI_E1_OFFLINE (RI_E1)
-#define RI_E1_ONLINE (RI_E1 | RI_ONLINE)
-#define RI_E1H_OFFLINE (RI_E1H)
-#define RI_E1H_ONLINE (RI_E1H | RI_ONLINE)
-#define RI_ALL_OFFLINE (RI_E1 | RI_E1H)
-#define RI_ALL_ONLINE (RI_E1 | RI_E1H | RI_ONLINE)
+#define RI_E1_OFFLINE (RI_E1)
+#define RI_E1_ONLINE (RI_E1 | RI_ONLINE)
+#define RI_E1H_OFFLINE (RI_E1H)
+#define RI_E1H_ONLINE (RI_E1H | RI_ONLINE)
+#define RI_ALL_OFFLINE (RI_E1 | RI_E1H)
+#define RI_ALL_ONLINE (RI_E1 | RI_E1H | RI_ONLINE)
-#define MAX_TIMER_PENDING 200
-#define TIMER_SCAN_DONT_CARE 0xFF
+#define MAX_TIMER_PENDING 200
+#define TIMER_SCAN_DONT_CARE 0xFF
struct dump_hdr {
@@ -67,443 +71,444 @@ struct wreg_addr {
};
-#define REGS_COUNT 558
+#define REGS_COUNT 558
static const struct reg_addr reg_addrs[REGS_COUNT] = {
- { 0x2000, 341, RI_ALL_ONLINE}, { 0x2800, 103, RI_ALL_ONLINE},
- { 0x3000, 287, RI_ALL_ONLINE}, { 0x3800, 331, RI_ALL_ONLINE},
- { 0x8800, 6, RI_E1_ONLINE}, { 0xa000, 223, RI_ALL_ONLINE},
- { 0xa388, 1, RI_ALL_ONLINE}, { 0xa398, 1, RI_ALL_ONLINE},
- { 0xa39c, 7, RI_E1H_ONLINE}, { 0xa3c0, 3, RI_E1H_ONLINE},
- { 0xa3d0, 1, RI_E1H_ONLINE}, { 0xa3d8, 1, RI_E1H_ONLINE},
- { 0xa3e0, 1, RI_E1H_ONLINE}, { 0xa3e8, 1, RI_E1H_ONLINE},
- { 0xa3f0, 1, RI_E1H_ONLINE}, { 0xa3f8, 1, RI_E1H_ONLINE},
- { 0xa400, 69, RI_ALL_ONLINE}, { 0xa518, 1, RI_ALL_ONLINE},
- { 0xa520, 1, RI_ALL_ONLINE}, { 0xa528, 1, RI_ALL_ONLINE},
- { 0xa530, 1, RI_ALL_ONLINE}, { 0xa538, 1, RI_ALL_ONLINE},
- { 0xa540, 1, RI_ALL_ONLINE}, { 0xa548, 1, RI_ALL_ONLINE},
- { 0xa550, 1, RI_ALL_ONLINE}, { 0xa558, 1, RI_ALL_ONLINE},
- { 0xa560, 1, RI_ALL_ONLINE}, { 0xa568, 1, RI_ALL_ONLINE},
- { 0xa570, 1, RI_ALL_ONLINE}, { 0xa580, 1, RI_ALL_ONLINE},
- { 0xa590, 1, RI_ALL_ONLINE}, { 0xa5a0, 1, RI_ALL_ONLINE},
- { 0xa5c0, 1, RI_ALL_ONLINE}, { 0xa5e0, 1, RI_E1H_ONLINE},
- { 0xa5e8, 1, RI_E1H_ONLINE}, { 0xa5f0, 1, RI_E1H_ONLINE},
- { 0xa5f8, 10, RI_E1H_ONLINE}, { 0x10000, 236, RI_ALL_ONLINE},
- { 0x103bc, 1, RI_ALL_ONLINE}, { 0x103cc, 1, RI_ALL_ONLINE},
- { 0x103dc, 1, RI_ALL_ONLINE}, { 0x10400, 57, RI_ALL_ONLINE},
- { 0x104e8, 2, RI_ALL_ONLINE}, { 0x104f4, 2, RI_ALL_ONLINE},
- { 0x10500, 146, RI_ALL_ONLINE}, { 0x10750, 2, RI_ALL_ONLINE},
- { 0x10760, 2, RI_ALL_ONLINE}, { 0x10770, 2, RI_ALL_ONLINE},
- { 0x10780, 2, RI_ALL_ONLINE}, { 0x10790, 2, RI_ALL_ONLINE},
- { 0x107a0, 2, RI_ALL_ONLINE}, { 0x107b0, 2, RI_ALL_ONLINE},
- { 0x107c0, 2, RI_ALL_ONLINE}, { 0x107d0, 2, RI_ALL_ONLINE},
- { 0x107e0, 2, RI_ALL_ONLINE}, { 0x10880, 2, RI_ALL_ONLINE},
- { 0x10900, 2, RI_ALL_ONLINE}, { 0x12000, 1, RI_ALL_ONLINE},
- { 0x14000, 1, RI_ALL_ONLINE}, { 0x16000, 26, RI_E1H_ONLINE},
- { 0x16070, 18, RI_E1H_ONLINE}, { 0x160c0, 27, RI_E1H_ONLINE},
- { 0x16140, 1, RI_E1H_ONLINE}, { 0x16160, 1, RI_E1H_ONLINE},
- { 0x16180, 2, RI_E1H_ONLINE}, { 0x161c0, 2, RI_E1H_ONLINE},
- { 0x16204, 5, RI_E1H_ONLINE}, { 0x18000, 1, RI_E1H_ONLINE},
- { 0x18008, 1, RI_E1H_ONLINE}, { 0x20000, 24, RI_ALL_ONLINE},
- { 0x20060, 8, RI_ALL_ONLINE}, { 0x20080, 138, RI_ALL_ONLINE},
- { 0x202b4, 1, RI_ALL_ONLINE}, { 0x202c4, 1, RI_ALL_ONLINE},
- { 0x20400, 2, RI_ALL_ONLINE}, { 0x2040c, 8, RI_ALL_ONLINE},
- { 0x2042c, 18, RI_E1H_ONLINE}, { 0x20480, 1, RI_ALL_ONLINE},
- { 0x20500, 1, RI_ALL_ONLINE}, { 0x20600, 1, RI_ALL_ONLINE},
- { 0x28000, 1, RI_ALL_ONLINE}, { 0x28004, 8191, RI_ALL_OFFLINE},
- { 0x30000, 1, RI_ALL_ONLINE}, { 0x30004, 16383, RI_ALL_OFFLINE},
- { 0x40000, 98, RI_ALL_ONLINE}, { 0x40194, 1, RI_ALL_ONLINE},
- { 0x401a4, 1, RI_ALL_ONLINE}, { 0x401a8, 11, RI_E1H_ONLINE},
- { 0x40200, 4, RI_ALL_ONLINE}, { 0x40400, 43, RI_ALL_ONLINE},
- { 0x404b8, 1, RI_ALL_ONLINE}, { 0x404c8, 1, RI_ALL_ONLINE},
- { 0x404cc, 3, RI_E1H_ONLINE}, { 0x40500, 2, RI_ALL_ONLINE},
- { 0x40510, 2, RI_ALL_ONLINE}, { 0x40520, 2, RI_ALL_ONLINE},
- { 0x40530, 2, RI_ALL_ONLINE}, { 0x40540, 2, RI_ALL_ONLINE},
- { 0x42000, 164, RI_ALL_ONLINE}, { 0x4229c, 1, RI_ALL_ONLINE},
- { 0x422ac, 1, RI_ALL_ONLINE}, { 0x422bc, 1, RI_ALL_ONLINE},
- { 0x422d4, 5, RI_E1H_ONLINE}, { 0x42400, 49, RI_ALL_ONLINE},
- { 0x424c8, 38, RI_ALL_ONLINE}, { 0x42568, 2, RI_ALL_ONLINE},
- { 0x42800, 1, RI_ALL_ONLINE}, { 0x50000, 20, RI_ALL_ONLINE},
- { 0x50050, 8, RI_ALL_ONLINE}, { 0x50070, 88, RI_ALL_ONLINE},
- { 0x501dc, 1, RI_ALL_ONLINE}, { 0x501ec, 1, RI_ALL_ONLINE},
- { 0x501f0, 4, RI_E1H_ONLINE}, { 0x50200, 2, RI_ALL_ONLINE},
- { 0x5020c, 7, RI_ALL_ONLINE}, { 0x50228, 6, RI_E1H_ONLINE},
- { 0x50240, 1, RI_ALL_ONLINE}, { 0x50280, 1, RI_ALL_ONLINE},
- { 0x52000, 1, RI_ALL_ONLINE}, { 0x54000, 1, RI_ALL_ONLINE},
- { 0x54004, 3327, RI_ALL_OFFLINE}, { 0x58000, 1, RI_ALL_ONLINE},
- { 0x58004, 8191, RI_ALL_OFFLINE}, { 0x60000, 71, RI_ALL_ONLINE},
- { 0x60128, 1, RI_ALL_ONLINE}, { 0x60138, 1, RI_ALL_ONLINE},
- { 0x6013c, 24, RI_E1H_ONLINE}, { 0x60200, 1, RI_ALL_ONLINE},
- { 0x61000, 1, RI_ALL_ONLINE}, { 0x61004, 511, RI_ALL_OFFLINE},
- { 0x70000, 8, RI_ALL_ONLINE}, { 0x70020, 21496, RI_ALL_OFFLINE},
- { 0x85000, 3, RI_ALL_ONLINE}, { 0x8500c, 4, RI_ALL_OFFLINE},
- { 0x8501c, 7, RI_ALL_ONLINE}, { 0x85038, 4, RI_ALL_OFFLINE},
- { 0x85048, 1, RI_ALL_ONLINE}, { 0x8504c, 109, RI_ALL_OFFLINE},
- { 0x85200, 32, RI_ALL_ONLINE}, { 0x85280, 11104, RI_ALL_OFFLINE},
- { 0xa0000, 16384, RI_ALL_ONLINE}, { 0xb0000, 16384, RI_E1H_ONLINE},
- { 0xc1000, 7, RI_ALL_ONLINE}, { 0xc1028, 1, RI_ALL_ONLINE},
- { 0xc1038, 1, RI_ALL_ONLINE}, { 0xc1800, 2, RI_ALL_ONLINE},
- { 0xc2000, 164, RI_ALL_ONLINE}, { 0xc229c, 1, RI_ALL_ONLINE},
- { 0xc22ac, 1, RI_ALL_ONLINE}, { 0xc22bc, 1, RI_ALL_ONLINE},
- { 0xc2400, 49, RI_ALL_ONLINE}, { 0xc24c8, 38, RI_ALL_ONLINE},
- { 0xc2568, 2, RI_ALL_ONLINE}, { 0xc2600, 1, RI_ALL_ONLINE},
- { 0xc4000, 165, RI_ALL_ONLINE}, { 0xc42a0, 1, RI_ALL_ONLINE},
- { 0xc42b0, 1, RI_ALL_ONLINE}, { 0xc42c0, 1, RI_ALL_ONLINE},
- { 0xc42e0, 7, RI_E1H_ONLINE}, { 0xc4400, 51, RI_ALL_ONLINE},
- { 0xc44d0, 38, RI_ALL_ONLINE}, { 0xc4570, 2, RI_ALL_ONLINE},
- { 0xc4600, 1, RI_ALL_ONLINE}, { 0xd0000, 19, RI_ALL_ONLINE},
- { 0xd004c, 8, RI_ALL_ONLINE}, { 0xd006c, 91, RI_ALL_ONLINE},
- { 0xd01e4, 1, RI_ALL_ONLINE}, { 0xd01f4, 1, RI_ALL_ONLINE},
- { 0xd0200, 2, RI_ALL_ONLINE}, { 0xd020c, 7, RI_ALL_ONLINE},
- { 0xd0228, 18, RI_E1H_ONLINE}, { 0xd0280, 1, RI_ALL_ONLINE},
- { 0xd0300, 1, RI_ALL_ONLINE}, { 0xd0400, 1, RI_ALL_ONLINE},
- { 0xd4000, 1, RI_ALL_ONLINE}, { 0xd4004, 2559, RI_ALL_OFFLINE},
- { 0xd8000, 1, RI_ALL_ONLINE}, { 0xd8004, 8191, RI_ALL_OFFLINE},
- { 0xe0000, 21, RI_ALL_ONLINE}, { 0xe0054, 8, RI_ALL_ONLINE},
- { 0xe0074, 85, RI_ALL_ONLINE}, { 0xe01d4, 1, RI_ALL_ONLINE},
- { 0xe01e4, 1, RI_ALL_ONLINE}, { 0xe0200, 2, RI_ALL_ONLINE},
- { 0xe020c, 8, RI_ALL_ONLINE}, { 0xe022c, 18, RI_E1H_ONLINE},
- { 0xe0280, 1, RI_ALL_ONLINE}, { 0xe0300, 1, RI_ALL_ONLINE},
- { 0xe1000, 1, RI_ALL_ONLINE}, { 0xe2000, 1, RI_ALL_ONLINE},
- { 0xe2004, 2047, RI_ALL_OFFLINE}, { 0xf0000, 1, RI_ALL_ONLINE},
- { 0xf0004, 16383, RI_ALL_OFFLINE}, { 0x101000, 12, RI_ALL_ONLINE},
- { 0x10103c, 1, RI_ALL_ONLINE}, { 0x10104c, 1, RI_ALL_ONLINE},
- { 0x101050, 1, RI_E1H_ONLINE}, { 0x101100, 1, RI_ALL_ONLINE},
- { 0x101800, 8, RI_ALL_ONLINE}, { 0x102000, 18, RI_ALL_ONLINE},
- { 0x102054, 1, RI_ALL_ONLINE}, { 0x102064, 1, RI_ALL_ONLINE},
- { 0x102080, 17, RI_ALL_ONLINE}, { 0x1020c8, 8, RI_E1H_ONLINE},
- { 0x102400, 1, RI_ALL_ONLINE}, { 0x103000, 26, RI_ALL_ONLINE},
- { 0x103074, 1, RI_ALL_ONLINE}, { 0x103084, 1, RI_ALL_ONLINE},
- { 0x103094, 1, RI_ALL_ONLINE}, { 0x103098, 5, RI_E1H_ONLINE},
- { 0x103800, 8, RI_ALL_ONLINE}, { 0x104000, 63, RI_ALL_ONLINE},
- { 0x104108, 1, RI_ALL_ONLINE}, { 0x104118, 1, RI_ALL_ONLINE},
- { 0x104200, 17, RI_ALL_ONLINE}, { 0x104400, 64, RI_ALL_ONLINE},
- { 0x104500, 192, RI_ALL_OFFLINE}, { 0x104800, 64, RI_ALL_ONLINE},
- { 0x104900, 192, RI_ALL_OFFLINE}, { 0x105000, 7, RI_ALL_ONLINE},
- { 0x10501c, 1, RI_ALL_OFFLINE}, { 0x105020, 3, RI_ALL_ONLINE},
- { 0x10502c, 1, RI_ALL_OFFLINE}, { 0x105030, 3, RI_ALL_ONLINE},
- { 0x10503c, 1, RI_ALL_OFFLINE}, { 0x105040, 3, RI_ALL_ONLINE},
- { 0x10504c, 1, RI_ALL_OFFLINE}, { 0x105050, 3, RI_ALL_ONLINE},
- { 0x10505c, 1, RI_ALL_OFFLINE}, { 0x105060, 3, RI_ALL_ONLINE},
- { 0x10506c, 1, RI_ALL_OFFLINE}, { 0x105070, 3, RI_ALL_ONLINE},
- { 0x10507c, 1, RI_ALL_OFFLINE}, { 0x105080, 3, RI_ALL_ONLINE},
- { 0x10508c, 1, RI_ALL_OFFLINE}, { 0x105090, 3, RI_ALL_ONLINE},
- { 0x10509c, 1, RI_ALL_OFFLINE}, { 0x1050a0, 3, RI_ALL_ONLINE},
- { 0x1050ac, 1, RI_ALL_OFFLINE}, { 0x1050b0, 3, RI_ALL_ONLINE},
- { 0x1050bc, 1, RI_ALL_OFFLINE}, { 0x1050c0, 3, RI_ALL_ONLINE},
- { 0x1050cc, 1, RI_ALL_OFFLINE}, { 0x1050d0, 3, RI_ALL_ONLINE},
- { 0x1050dc, 1, RI_ALL_OFFLINE}, { 0x1050e0, 3, RI_ALL_ONLINE},
- { 0x1050ec, 1, RI_ALL_OFFLINE}, { 0x1050f0, 3, RI_ALL_ONLINE},
- { 0x1050fc, 1, RI_ALL_OFFLINE}, { 0x105100, 3, RI_ALL_ONLINE},
- { 0x10510c, 1, RI_ALL_OFFLINE}, { 0x105110, 3, RI_ALL_ONLINE},
- { 0x10511c, 1, RI_ALL_OFFLINE}, { 0x105120, 3, RI_ALL_ONLINE},
- { 0x10512c, 1, RI_ALL_OFFLINE}, { 0x105130, 3, RI_ALL_ONLINE},
- { 0x10513c, 1, RI_ALL_OFFLINE}, { 0x105140, 3, RI_ALL_ONLINE},
- { 0x10514c, 1, RI_ALL_OFFLINE}, { 0x105150, 3, RI_ALL_ONLINE},
- { 0x10515c, 1, RI_ALL_OFFLINE}, { 0x105160, 3, RI_ALL_ONLINE},
- { 0x10516c, 1, RI_ALL_OFFLINE}, { 0x105170, 3, RI_ALL_ONLINE},
- { 0x10517c, 1, RI_ALL_OFFLINE}, { 0x105180, 3, RI_ALL_ONLINE},
- { 0x10518c, 1, RI_ALL_OFFLINE}, { 0x105190, 3, RI_ALL_ONLINE},
- { 0x10519c, 1, RI_ALL_OFFLINE}, { 0x1051a0, 3, RI_ALL_ONLINE},
- { 0x1051ac, 1, RI_ALL_OFFLINE}, { 0x1051b0, 3, RI_ALL_ONLINE},
- { 0x1051bc, 1, RI_ALL_OFFLINE}, { 0x1051c0, 3, RI_ALL_ONLINE},
- { 0x1051cc, 1, RI_ALL_OFFLINE}, { 0x1051d0, 3, RI_ALL_ONLINE},
- { 0x1051dc, 1, RI_ALL_OFFLINE}, { 0x1051e0, 3, RI_ALL_ONLINE},
- { 0x1051ec, 1, RI_ALL_OFFLINE}, { 0x1051f0, 3, RI_ALL_ONLINE},
- { 0x1051fc, 1, RI_ALL_OFFLINE}, { 0x105200, 3, RI_ALL_ONLINE},
- { 0x10520c, 1, RI_ALL_OFFLINE}, { 0x105210, 3, RI_ALL_ONLINE},
- { 0x10521c, 1, RI_ALL_OFFLINE}, { 0x105220, 3, RI_ALL_ONLINE},
- { 0x10522c, 1, RI_ALL_OFFLINE}, { 0x105230, 3, RI_ALL_ONLINE},
- { 0x10523c, 1, RI_ALL_OFFLINE}, { 0x105240, 3, RI_ALL_ONLINE},
- { 0x10524c, 1, RI_ALL_OFFLINE}, { 0x105250, 3, RI_ALL_ONLINE},
- { 0x10525c, 1, RI_ALL_OFFLINE}, { 0x105260, 3, RI_ALL_ONLINE},
- { 0x10526c, 1, RI_ALL_OFFLINE}, { 0x105270, 3, RI_ALL_ONLINE},
- { 0x10527c, 1, RI_ALL_OFFLINE}, { 0x105280, 3, RI_ALL_ONLINE},
- { 0x10528c, 1, RI_ALL_OFFLINE}, { 0x105290, 3, RI_ALL_ONLINE},
- { 0x10529c, 1, RI_ALL_OFFLINE}, { 0x1052a0, 3, RI_ALL_ONLINE},
- { 0x1052ac, 1, RI_ALL_OFFLINE}, { 0x1052b0, 3, RI_ALL_ONLINE},
- { 0x1052bc, 1, RI_ALL_OFFLINE}, { 0x1052c0, 3, RI_ALL_ONLINE},
- { 0x1052cc, 1, RI_ALL_OFFLINE}, { 0x1052d0, 3, RI_ALL_ONLINE},
- { 0x1052dc, 1, RI_ALL_OFFLINE}, { 0x1052e0, 3, RI_ALL_ONLINE},
- { 0x1052ec, 1, RI_ALL_OFFLINE}, { 0x1052f0, 3, RI_ALL_ONLINE},
- { 0x1052fc, 1, RI_ALL_OFFLINE}, { 0x105300, 3, RI_ALL_ONLINE},
- { 0x10530c, 1, RI_ALL_OFFLINE}, { 0x105310, 3, RI_ALL_ONLINE},
- { 0x10531c, 1, RI_ALL_OFFLINE}, { 0x105320, 3, RI_ALL_ONLINE},
- { 0x10532c, 1, RI_ALL_OFFLINE}, { 0x105330, 3, RI_ALL_ONLINE},
- { 0x10533c, 1, RI_ALL_OFFLINE}, { 0x105340, 3, RI_ALL_ONLINE},
- { 0x10534c, 1, RI_ALL_OFFLINE}, { 0x105350, 3, RI_ALL_ONLINE},
- { 0x10535c, 1, RI_ALL_OFFLINE}, { 0x105360, 3, RI_ALL_ONLINE},
- { 0x10536c, 1, RI_ALL_OFFLINE}, { 0x105370, 3, RI_ALL_ONLINE},
- { 0x10537c, 1, RI_ALL_OFFLINE}, { 0x105380, 3, RI_ALL_ONLINE},
- { 0x10538c, 1, RI_ALL_OFFLINE}, { 0x105390, 3, RI_ALL_ONLINE},
- { 0x10539c, 1, RI_ALL_OFFLINE}, { 0x1053a0, 3, RI_ALL_ONLINE},
- { 0x1053ac, 1, RI_ALL_OFFLINE}, { 0x1053b0, 3, RI_ALL_ONLINE},
- { 0x1053bc, 1, RI_ALL_OFFLINE}, { 0x1053c0, 3, RI_ALL_ONLINE},
- { 0x1053cc, 1, RI_ALL_OFFLINE}, { 0x1053d0, 3, RI_ALL_ONLINE},
- { 0x1053dc, 1, RI_ALL_OFFLINE}, { 0x1053e0, 3, RI_ALL_ONLINE},
- { 0x1053ec, 1, RI_ALL_OFFLINE}, { 0x1053f0, 3, RI_ALL_ONLINE},
- { 0x1053fc, 769, RI_ALL_OFFLINE}, { 0x108000, 33, RI_ALL_ONLINE},
- { 0x108090, 1, RI_ALL_ONLINE}, { 0x1080a0, 1, RI_ALL_ONLINE},
- { 0x1080ac, 5, RI_E1H_ONLINE}, { 0x108100, 5, RI_ALL_ONLINE},
- { 0x108120, 5, RI_ALL_ONLINE}, { 0x108200, 74, RI_ALL_ONLINE},
- { 0x108400, 74, RI_ALL_ONLINE}, { 0x108800, 152, RI_ALL_ONLINE},
- { 0x109000, 1, RI_ALL_ONLINE}, { 0x120000, 347, RI_ALL_ONLINE},
- { 0x120578, 1, RI_ALL_ONLINE}, { 0x120588, 1, RI_ALL_ONLINE},
- { 0x120598, 1, RI_ALL_ONLINE}, { 0x12059c, 23, RI_E1H_ONLINE},
- { 0x120614, 1, RI_E1H_ONLINE}, { 0x12061c, 30, RI_E1H_ONLINE},
- { 0x12080c, 65, RI_ALL_ONLINE}, { 0x120a00, 2, RI_ALL_ONLINE},
- { 0x122000, 2, RI_ALL_ONLINE}, { 0x128000, 2, RI_E1H_ONLINE},
- { 0x140000, 114, RI_ALL_ONLINE}, { 0x1401d4, 1, RI_ALL_ONLINE},
- { 0x1401e4, 1, RI_ALL_ONLINE}, { 0x140200, 6, RI_ALL_ONLINE},
- { 0x144000, 4, RI_ALL_ONLINE}, { 0x148000, 4, RI_ALL_ONLINE},
- { 0x14c000, 4, RI_ALL_ONLINE}, { 0x150000, 4, RI_ALL_ONLINE},
- { 0x154000, 4, RI_ALL_ONLINE}, { 0x158000, 4, RI_ALL_ONLINE},
- { 0x15c000, 7, RI_E1H_ONLINE}, { 0x161000, 7, RI_ALL_ONLINE},
- { 0x161028, 1, RI_ALL_ONLINE}, { 0x161038, 1, RI_ALL_ONLINE},
- { 0x161800, 2, RI_ALL_ONLINE}, { 0x164000, 60, RI_ALL_ONLINE},
- { 0x1640fc, 1, RI_ALL_ONLINE}, { 0x16410c, 1, RI_ALL_ONLINE},
- { 0x164110, 2, RI_E1H_ONLINE}, { 0x164200, 1, RI_ALL_ONLINE},
- { 0x164208, 1, RI_ALL_ONLINE}, { 0x164210, 1, RI_ALL_ONLINE},
- { 0x164218, 1, RI_ALL_ONLINE}, { 0x164220, 1, RI_ALL_ONLINE},
- { 0x164228, 1, RI_ALL_ONLINE}, { 0x164230, 1, RI_ALL_ONLINE},
- { 0x164238, 1, RI_ALL_ONLINE}, { 0x164240, 1, RI_ALL_ONLINE},
- { 0x164248, 1, RI_ALL_ONLINE}, { 0x164250, 1, RI_ALL_ONLINE},
- { 0x164258, 1, RI_ALL_ONLINE}, { 0x164260, 1, RI_ALL_ONLINE},
- { 0x164270, 2, RI_ALL_ONLINE}, { 0x164280, 2, RI_ALL_ONLINE},
- { 0x164800, 2, RI_ALL_ONLINE}, { 0x165000, 2, RI_ALL_ONLINE},
- { 0x166000, 164, RI_ALL_ONLINE}, { 0x16629c, 1, RI_ALL_ONLINE},
- { 0x1662ac, 1, RI_ALL_ONLINE}, { 0x1662bc, 1, RI_ALL_ONLINE},
- { 0x166400, 49, RI_ALL_ONLINE}, { 0x1664c8, 38, RI_ALL_ONLINE},
- { 0x166568, 2, RI_ALL_ONLINE}, { 0x166800, 1, RI_ALL_ONLINE},
- { 0x168000, 270, RI_ALL_ONLINE}, { 0x168444, 1, RI_ALL_ONLINE},
- { 0x168454, 1, RI_ALL_ONLINE}, { 0x168800, 19, RI_ALL_ONLINE},
- { 0x168900, 1, RI_ALL_ONLINE}, { 0x168a00, 128, RI_ALL_ONLINE},
- { 0x16a000, 1, RI_ALL_ONLINE}, { 0x16a004, 1535, RI_ALL_OFFLINE},
- { 0x16c000, 1, RI_ALL_ONLINE}, { 0x16c004, 1535, RI_ALL_OFFLINE},
- { 0x16e000, 16, RI_E1H_ONLINE}, { 0x16e100, 1, RI_E1H_ONLINE},
- { 0x16e200, 2, RI_E1H_ONLINE}, { 0x16e400, 183, RI_E1H_ONLINE},
- { 0x170000, 93, RI_ALL_ONLINE}, { 0x170180, 1, RI_ALL_ONLINE},
- { 0x170190, 1, RI_ALL_ONLINE}, { 0x170200, 4, RI_ALL_ONLINE},
- { 0x170214, 1, RI_ALL_ONLINE}, { 0x178000, 1, RI_ALL_ONLINE},
- { 0x180000, 61, RI_ALL_ONLINE}, { 0x180100, 1, RI_ALL_ONLINE},
- { 0x180110, 1, RI_ALL_ONLINE}, { 0x180120, 1, RI_ALL_ONLINE},
- { 0x180130, 1, RI_ALL_ONLINE}, { 0x18013c, 2, RI_E1H_ONLINE},
- { 0x180200, 58, RI_ALL_ONLINE}, { 0x180340, 4, RI_ALL_ONLINE},
- { 0x180400, 1, RI_ALL_ONLINE}, { 0x180404, 255, RI_ALL_OFFLINE},
- { 0x181000, 4, RI_ALL_ONLINE}, { 0x181010, 1020, RI_ALL_OFFLINE},
- { 0x1a0000, 1, RI_ALL_ONLINE}, { 0x1a0004, 1023, RI_ALL_OFFLINE},
- { 0x1a1000, 1, RI_ALL_ONLINE}, { 0x1a1004, 4607, RI_ALL_OFFLINE},
- { 0x1a5800, 2560, RI_E1H_OFFLINE}, { 0x1a8000, 64, RI_ALL_OFFLINE},
- { 0x1a8100, 1984, RI_E1H_OFFLINE}, { 0x1aa000, 1, RI_E1H_ONLINE},
- { 0x1aa004, 6655, RI_E1H_OFFLINE}, { 0x1b1800, 128, RI_ALL_OFFLINE},
- { 0x1b1c00, 128, RI_ALL_OFFLINE}, { 0x1b2000, 1, RI_ALL_OFFLINE},
- { 0x1b2400, 64, RI_E1H_OFFLINE}, { 0x1b8200, 1, RI_ALL_ONLINE},
- { 0x1b8240, 1, RI_ALL_ONLINE}, { 0x1b8280, 1, RI_ALL_ONLINE},
- { 0x1b82c0, 1, RI_ALL_ONLINE}, { 0x1b8a00, 1, RI_ALL_ONLINE},
- { 0x1b8a80, 1, RI_ALL_ONLINE}, { 0x1c0000, 2, RI_ALL_ONLINE},
- { 0x200000, 65, RI_ALL_ONLINE}, { 0x200110, 1, RI_ALL_ONLINE},
- { 0x200120, 1, RI_ALL_ONLINE}, { 0x200130, 1, RI_ALL_ONLINE},
- { 0x200140, 1, RI_ALL_ONLINE}, { 0x20014c, 2, RI_E1H_ONLINE},
- { 0x200200, 58, RI_ALL_ONLINE}, { 0x200340, 4, RI_ALL_ONLINE},
- { 0x200400, 1, RI_ALL_ONLINE}, { 0x200404, 255, RI_ALL_OFFLINE},
- { 0x202000, 4, RI_ALL_ONLINE}, { 0x202010, 2044, RI_ALL_OFFLINE},
- { 0x220000, 1, RI_ALL_ONLINE}, { 0x220004, 1023, RI_ALL_OFFLINE},
- { 0x221000, 1, RI_ALL_ONLINE}, { 0x221004, 4607, RI_ALL_OFFLINE},
- { 0x225800, 1536, RI_E1H_OFFLINE}, { 0x227000, 1, RI_E1H_ONLINE},
- { 0x227004, 1023, RI_E1H_OFFLINE}, { 0x228000, 64, RI_ALL_OFFLINE},
- { 0x228100, 8640, RI_E1H_OFFLINE}, { 0x231800, 128, RI_ALL_OFFLINE},
- { 0x231c00, 128, RI_ALL_OFFLINE}, { 0x232000, 1, RI_ALL_OFFLINE},
- { 0x232400, 64, RI_E1H_OFFLINE}, { 0x238200, 1, RI_ALL_ONLINE},
- { 0x238240, 1, RI_ALL_ONLINE}, { 0x238280, 1, RI_ALL_ONLINE},
- { 0x2382c0, 1, RI_ALL_ONLINE}, { 0x238a00, 1, RI_ALL_ONLINE},
- { 0x238a80, 1, RI_ALL_ONLINE}, { 0x240000, 2, RI_ALL_ONLINE},
- { 0x280000, 65, RI_ALL_ONLINE}, { 0x280110, 1, RI_ALL_ONLINE},
- { 0x280120, 1, RI_ALL_ONLINE}, { 0x280130, 1, RI_ALL_ONLINE},
- { 0x280140, 1, RI_ALL_ONLINE}, { 0x28014c, 2, RI_E1H_ONLINE},
- { 0x280200, 58, RI_ALL_ONLINE}, { 0x280340, 4, RI_ALL_ONLINE},
- { 0x280400, 1, RI_ALL_ONLINE}, { 0x280404, 255, RI_ALL_OFFLINE},
- { 0x282000, 4, RI_ALL_ONLINE}, { 0x282010, 2044, RI_ALL_OFFLINE},
- { 0x2a0000, 1, RI_ALL_ONLINE}, { 0x2a0004, 1023, RI_ALL_OFFLINE},
- { 0x2a1000, 1, RI_ALL_ONLINE}, { 0x2a1004, 4607, RI_ALL_OFFLINE},
- { 0x2a5800, 2560, RI_E1H_OFFLINE}, { 0x2a8000, 64, RI_ALL_OFFLINE},
- { 0x2a8100, 960, RI_E1H_OFFLINE}, { 0x2a9000, 1, RI_E1H_ONLINE},
- { 0x2a9004, 7679, RI_E1H_OFFLINE}, { 0x2b1800, 128, RI_ALL_OFFLINE},
- { 0x2b1c00, 128, RI_ALL_OFFLINE}, { 0x2b2000, 1, RI_ALL_OFFLINE},
- { 0x2b2400, 64, RI_E1H_OFFLINE}, { 0x2b8200, 1, RI_ALL_ONLINE},
- { 0x2b8240, 1, RI_ALL_ONLINE}, { 0x2b8280, 1, RI_ALL_ONLINE},
- { 0x2b82c0, 1, RI_ALL_ONLINE}, { 0x2b8a00, 1, RI_ALL_ONLINE},
- { 0x2b8a80, 1, RI_ALL_ONLINE}, { 0x2c0000, 2, RI_ALL_ONLINE},
- { 0x300000, 65, RI_ALL_ONLINE}, { 0x300110, 1, RI_ALL_ONLINE},
- { 0x300120, 1, RI_ALL_ONLINE}, { 0x300130, 1, RI_ALL_ONLINE},
- { 0x300140, 1, RI_ALL_ONLINE}, { 0x30014c, 2, RI_E1H_ONLINE},
- { 0x300200, 58, RI_ALL_ONLINE}, { 0x300340, 4, RI_ALL_ONLINE},
- { 0x300400, 1, RI_ALL_ONLINE}, { 0x300404, 255, RI_ALL_OFFLINE},
- { 0x302000, 4, RI_ALL_ONLINE}, { 0x302010, 2044, RI_ALL_OFFLINE},
- { 0x320000, 1, RI_ALL_ONLINE}, { 0x320004, 1023, RI_ALL_OFFLINE},
- { 0x321000, 1, RI_ALL_ONLINE}, { 0x321004, 4607, RI_ALL_OFFLINE},
- { 0x325800, 2560, RI_E1H_OFFLINE}, { 0x328000, 64, RI_ALL_OFFLINE},
- { 0x328100, 536, RI_E1H_OFFLINE}, { 0x328960, 1, RI_E1H_ONLINE},
- { 0x328964, 8103, RI_E1H_OFFLINE}, { 0x331800, 128, RI_ALL_OFFLINE},
- { 0x331c00, 128, RI_ALL_OFFLINE}, { 0x332000, 1, RI_ALL_OFFLINE},
- { 0x332400, 64, RI_E1H_OFFLINE}, { 0x338200, 1, RI_ALL_ONLINE},
- { 0x338240, 1, RI_ALL_ONLINE}, { 0x338280, 1, RI_ALL_ONLINE},
- { 0x3382c0, 1, RI_ALL_ONLINE}, { 0x338a00, 1, RI_ALL_ONLINE},
- { 0x338a80, 1, RI_ALL_ONLINE}, { 0x340000, 2, RI_ALL_ONLINE}
+ { 0x2000, 341, RI_ALL_ONLINE }, { 0x2800, 103, RI_ALL_ONLINE },
+ { 0x3000, 287, RI_ALL_ONLINE }, { 0x3800, 331, RI_ALL_ONLINE },
+ { 0x8800, 6, RI_E1_ONLINE }, { 0xa000, 223, RI_ALL_ONLINE },
+ { 0xa388, 1, RI_ALL_ONLINE }, { 0xa398, 1, RI_ALL_ONLINE },
+ { 0xa39c, 7, RI_E1H_ONLINE }, { 0xa3c0, 3, RI_E1H_ONLINE },
+ { 0xa3d0, 1, RI_E1H_ONLINE }, { 0xa3d8, 1, RI_E1H_ONLINE },
+ { 0xa3e0, 1, RI_E1H_ONLINE }, { 0xa3e8, 1, RI_E1H_ONLINE },
+ { 0xa3f0, 1, RI_E1H_ONLINE }, { 0xa3f8, 1, RI_E1H_ONLINE },
+ { 0xa400, 69, RI_ALL_ONLINE }, { 0xa518, 1, RI_ALL_ONLINE },
+ { 0xa520, 1, RI_ALL_ONLINE }, { 0xa528, 1, RI_ALL_ONLINE },
+ { 0xa530, 1, RI_ALL_ONLINE }, { 0xa538, 1, RI_ALL_ONLINE },
+ { 0xa540, 1, RI_ALL_ONLINE }, { 0xa548, 1, RI_ALL_ONLINE },
+ { 0xa550, 1, RI_ALL_ONLINE }, { 0xa558, 1, RI_ALL_ONLINE },
+ { 0xa560, 1, RI_ALL_ONLINE }, { 0xa568, 1, RI_ALL_ONLINE },
+ { 0xa570, 1, RI_ALL_ONLINE }, { 0xa580, 1, RI_ALL_ONLINE },
+ { 0xa590, 1, RI_ALL_ONLINE }, { 0xa5a0, 1, RI_ALL_ONLINE },
+ { 0xa5c0, 1, RI_ALL_ONLINE }, { 0xa5e0, 1, RI_E1H_ONLINE },
+ { 0xa5e8, 1, RI_E1H_ONLINE }, { 0xa5f0, 1, RI_E1H_ONLINE },
+ { 0xa5f8, 10, RI_E1H_ONLINE }, { 0x10000, 236, RI_ALL_ONLINE },
+ { 0x103bc, 1, RI_ALL_ONLINE }, { 0x103cc, 1, RI_ALL_ONLINE },
+ { 0x103dc, 1, RI_ALL_ONLINE }, { 0x10400, 57, RI_ALL_ONLINE },
+ { 0x104e8, 2, RI_ALL_ONLINE }, { 0x104f4, 2, RI_ALL_ONLINE },
+ { 0x10500, 146, RI_ALL_ONLINE }, { 0x10750, 2, RI_ALL_ONLINE },
+ { 0x10760, 2, RI_ALL_ONLINE }, { 0x10770, 2, RI_ALL_ONLINE },
+ { 0x10780, 2, RI_ALL_ONLINE }, { 0x10790, 2, RI_ALL_ONLINE },
+ { 0x107a0, 2, RI_ALL_ONLINE }, { 0x107b0, 2, RI_ALL_ONLINE },
+ { 0x107c0, 2, RI_ALL_ONLINE }, { 0x107d0, 2, RI_ALL_ONLINE },
+ { 0x107e0, 2, RI_ALL_ONLINE }, { 0x10880, 2, RI_ALL_ONLINE },
+ { 0x10900, 2, RI_ALL_ONLINE }, { 0x12000, 1, RI_ALL_ONLINE },
+ { 0x14000, 1, RI_ALL_ONLINE }, { 0x16000, 26, RI_E1H_ONLINE },
+ { 0x16070, 18, RI_E1H_ONLINE }, { 0x160c0, 27, RI_E1H_ONLINE },
+ { 0x16140, 1, RI_E1H_ONLINE }, { 0x16160, 1, RI_E1H_ONLINE },
+ { 0x16180, 2, RI_E1H_ONLINE }, { 0x161c0, 2, RI_E1H_ONLINE },
+ { 0x16204, 5, RI_E1H_ONLINE }, { 0x18000, 1, RI_E1H_ONLINE },
+ { 0x18008, 1, RI_E1H_ONLINE }, { 0x20000, 24, RI_ALL_ONLINE },
+ { 0x20060, 8, RI_ALL_ONLINE }, { 0x20080, 138, RI_ALL_ONLINE },
+ { 0x202b4, 1, RI_ALL_ONLINE }, { 0x202c4, 1, RI_ALL_ONLINE },
+ { 0x20400, 2, RI_ALL_ONLINE }, { 0x2040c, 8, RI_ALL_ONLINE },
+ { 0x2042c, 18, RI_E1H_ONLINE }, { 0x20480, 1, RI_ALL_ONLINE },
+ { 0x20500, 1, RI_ALL_ONLINE }, { 0x20600, 1, RI_ALL_ONLINE },
+ { 0x28000, 1, RI_ALL_ONLINE }, { 0x28004, 8191, RI_ALL_OFFLINE },
+ { 0x30000, 1, RI_ALL_ONLINE }, { 0x30004, 16383, RI_ALL_OFFLINE },
+ { 0x40000, 98, RI_ALL_ONLINE }, { 0x40194, 1, RI_ALL_ONLINE },
+ { 0x401a4, 1, RI_ALL_ONLINE }, { 0x401a8, 11, RI_E1H_ONLINE },
+ { 0x40200, 4, RI_ALL_ONLINE }, { 0x40400, 43, RI_ALL_ONLINE },
+ { 0x404b8, 1, RI_ALL_ONLINE }, { 0x404c8, 1, RI_ALL_ONLINE },
+ { 0x404cc, 3, RI_E1H_ONLINE }, { 0x40500, 2, RI_ALL_ONLINE },
+ { 0x40510, 2, RI_ALL_ONLINE }, { 0x40520, 2, RI_ALL_ONLINE },
+ { 0x40530, 2, RI_ALL_ONLINE }, { 0x40540, 2, RI_ALL_ONLINE },
+ { 0x42000, 164, RI_ALL_ONLINE }, { 0x4229c, 1, RI_ALL_ONLINE },
+ { 0x422ac, 1, RI_ALL_ONLINE }, { 0x422bc, 1, RI_ALL_ONLINE },
+ { 0x422d4, 5, RI_E1H_ONLINE }, { 0x42400, 49, RI_ALL_ONLINE },
+ { 0x424c8, 38, RI_ALL_ONLINE }, { 0x42568, 2, RI_ALL_ONLINE },
+ { 0x42800, 1, RI_ALL_ONLINE }, { 0x50000, 20, RI_ALL_ONLINE },
+ { 0x50050, 8, RI_ALL_ONLINE }, { 0x50070, 88, RI_ALL_ONLINE },
+ { 0x501dc, 1, RI_ALL_ONLINE }, { 0x501ec, 1, RI_ALL_ONLINE },
+ { 0x501f0, 4, RI_E1H_ONLINE }, { 0x50200, 2, RI_ALL_ONLINE },
+ { 0x5020c, 7, RI_ALL_ONLINE }, { 0x50228, 6, RI_E1H_ONLINE },
+ { 0x50240, 1, RI_ALL_ONLINE }, { 0x50280, 1, RI_ALL_ONLINE },
+ { 0x52000, 1, RI_ALL_ONLINE }, { 0x54000, 1, RI_ALL_ONLINE },
+ { 0x54004, 3327, RI_ALL_OFFLINE }, { 0x58000, 1, RI_ALL_ONLINE },
+ { 0x58004, 8191, RI_ALL_OFFLINE }, { 0x60000, 71, RI_ALL_ONLINE },
+ { 0x60128, 1, RI_ALL_ONLINE }, { 0x60138, 1, RI_ALL_ONLINE },
+ { 0x6013c, 24, RI_E1H_ONLINE }, { 0x60200, 1, RI_ALL_ONLINE },
+ { 0x61000, 1, RI_ALL_ONLINE }, { 0x61004, 511, RI_ALL_OFFLINE },
+ { 0x70000, 8, RI_ALL_ONLINE }, { 0x70020, 21496, RI_ALL_OFFLINE },
+ { 0x85000, 3, RI_ALL_ONLINE }, { 0x8500c, 4, RI_ALL_OFFLINE },
+ { 0x8501c, 7, RI_ALL_ONLINE }, { 0x85038, 4, RI_ALL_OFFLINE },
+ { 0x85048, 1, RI_ALL_ONLINE }, { 0x8504c, 109, RI_ALL_OFFLINE },
+ { 0x85200, 32, RI_ALL_ONLINE }, { 0x85280, 11104, RI_ALL_OFFLINE },
+ { 0xa0000, 16384, RI_ALL_ONLINE }, { 0xb0000, 16384, RI_E1H_ONLINE },
+ { 0xc1000, 7, RI_ALL_ONLINE }, { 0xc1028, 1, RI_ALL_ONLINE },
+ { 0xc1038, 1, RI_ALL_ONLINE }, { 0xc1800, 2, RI_ALL_ONLINE },
+ { 0xc2000, 164, RI_ALL_ONLINE }, { 0xc229c, 1, RI_ALL_ONLINE },
+ { 0xc22ac, 1, RI_ALL_ONLINE }, { 0xc22bc, 1, RI_ALL_ONLINE },
+ { 0xc2400, 49, RI_ALL_ONLINE }, { 0xc24c8, 38, RI_ALL_ONLINE },
+ { 0xc2568, 2, RI_ALL_ONLINE }, { 0xc2600, 1, RI_ALL_ONLINE },
+ { 0xc4000, 165, RI_ALL_ONLINE }, { 0xc42a0, 1, RI_ALL_ONLINE },
+ { 0xc42b0, 1, RI_ALL_ONLINE }, { 0xc42c0, 1, RI_ALL_ONLINE },
+ { 0xc42e0, 7, RI_E1H_ONLINE }, { 0xc4400, 51, RI_ALL_ONLINE },
+ { 0xc44d0, 38, RI_ALL_ONLINE }, { 0xc4570, 2, RI_ALL_ONLINE },
+ { 0xc4600, 1, RI_ALL_ONLINE }, { 0xd0000, 19, RI_ALL_ONLINE },
+ { 0xd004c, 8, RI_ALL_ONLINE }, { 0xd006c, 91, RI_ALL_ONLINE },
+ { 0xd01e4, 1, RI_ALL_ONLINE }, { 0xd01f4, 1, RI_ALL_ONLINE },
+ { 0xd0200, 2, RI_ALL_ONLINE }, { 0xd020c, 7, RI_ALL_ONLINE },
+ { 0xd0228, 18, RI_E1H_ONLINE }, { 0xd0280, 1, RI_ALL_ONLINE },
+ { 0xd0300, 1, RI_ALL_ONLINE }, { 0xd0400, 1, RI_ALL_ONLINE },
+ { 0xd4000, 1, RI_ALL_ONLINE }, { 0xd4004, 2559, RI_ALL_OFFLINE },
+ { 0xd8000, 1, RI_ALL_ONLINE }, { 0xd8004, 8191, RI_ALL_OFFLINE },
+ { 0xe0000, 21, RI_ALL_ONLINE }, { 0xe0054, 8, RI_ALL_ONLINE },
+ { 0xe0074, 85, RI_ALL_ONLINE }, { 0xe01d4, 1, RI_ALL_ONLINE },
+ { 0xe01e4, 1, RI_ALL_ONLINE }, { 0xe0200, 2, RI_ALL_ONLINE },
+ { 0xe020c, 8, RI_ALL_ONLINE }, { 0xe022c, 18, RI_E1H_ONLINE },
+ { 0xe0280, 1, RI_ALL_ONLINE }, { 0xe0300, 1, RI_ALL_ONLINE },
+ { 0xe1000, 1, RI_ALL_ONLINE }, { 0xe2000, 1, RI_ALL_ONLINE },
+ { 0xe2004, 2047, RI_ALL_OFFLINE }, { 0xf0000, 1, RI_ALL_ONLINE },
+ { 0xf0004, 16383, RI_ALL_OFFLINE }, { 0x101000, 12, RI_ALL_ONLINE },
+ { 0x10103c, 1, RI_ALL_ONLINE }, { 0x10104c, 1, RI_ALL_ONLINE },
+ { 0x101050, 1, RI_E1H_ONLINE }, { 0x101100, 1, RI_ALL_ONLINE },
+ { 0x101800, 8, RI_ALL_ONLINE }, { 0x102000, 18, RI_ALL_ONLINE },
+ { 0x102054, 1, RI_ALL_ONLINE }, { 0x102064, 1, RI_ALL_ONLINE },
+ { 0x102080, 17, RI_ALL_ONLINE }, { 0x1020c8, 8, RI_E1H_ONLINE },
+ { 0x102400, 1, RI_ALL_ONLINE }, { 0x103000, 26, RI_ALL_ONLINE },
+ { 0x103074, 1, RI_ALL_ONLINE }, { 0x103084, 1, RI_ALL_ONLINE },
+ { 0x103094, 1, RI_ALL_ONLINE }, { 0x103098, 5, RI_E1H_ONLINE },
+ { 0x103800, 8, RI_ALL_ONLINE }, { 0x104000, 63, RI_ALL_ONLINE },
+ { 0x104108, 1, RI_ALL_ONLINE }, { 0x104118, 1, RI_ALL_ONLINE },
+ { 0x104200, 17, RI_ALL_ONLINE }, { 0x104400, 64, RI_ALL_ONLINE },
+ { 0x104500, 192, RI_ALL_OFFLINE }, { 0x104800, 64, RI_ALL_ONLINE },
+ { 0x104900, 192, RI_ALL_OFFLINE }, { 0x105000, 7, RI_ALL_ONLINE },
+ { 0x10501c, 1, RI_ALL_OFFLINE }, { 0x105020, 3, RI_ALL_ONLINE },
+ { 0x10502c, 1, RI_ALL_OFFLINE }, { 0x105030, 3, RI_ALL_ONLINE },
+ { 0x10503c, 1, RI_ALL_OFFLINE }, { 0x105040, 3, RI_ALL_ONLINE },
+ { 0x10504c, 1, RI_ALL_OFFLINE }, { 0x105050, 3, RI_ALL_ONLINE },
+ { 0x10505c, 1, RI_ALL_OFFLINE }, { 0x105060, 3, RI_ALL_ONLINE },
+ { 0x10506c, 1, RI_ALL_OFFLINE }, { 0x105070, 3, RI_ALL_ONLINE },
+ { 0x10507c, 1, RI_ALL_OFFLINE }, { 0x105080, 3, RI_ALL_ONLINE },
+ { 0x10508c, 1, RI_ALL_OFFLINE }, { 0x105090, 3, RI_ALL_ONLINE },
+ { 0x10509c, 1, RI_ALL_OFFLINE }, { 0x1050a0, 3, RI_ALL_ONLINE },
+ { 0x1050ac, 1, RI_ALL_OFFLINE }, { 0x1050b0, 3, RI_ALL_ONLINE },
+ { 0x1050bc, 1, RI_ALL_OFFLINE }, { 0x1050c0, 3, RI_ALL_ONLINE },
+ { 0x1050cc, 1, RI_ALL_OFFLINE }, { 0x1050d0, 3, RI_ALL_ONLINE },
+ { 0x1050dc, 1, RI_ALL_OFFLINE }, { 0x1050e0, 3, RI_ALL_ONLINE },
+ { 0x1050ec, 1, RI_ALL_OFFLINE }, { 0x1050f0, 3, RI_ALL_ONLINE },
+ { 0x1050fc, 1, RI_ALL_OFFLINE }, { 0x105100, 3, RI_ALL_ONLINE },
+ { 0x10510c, 1, RI_ALL_OFFLINE }, { 0x105110, 3, RI_ALL_ONLINE },
+ { 0x10511c, 1, RI_ALL_OFFLINE }, { 0x105120, 3, RI_ALL_ONLINE },
+ { 0x10512c, 1, RI_ALL_OFFLINE }, { 0x105130, 3, RI_ALL_ONLINE },
+ { 0x10513c, 1, RI_ALL_OFFLINE }, { 0x105140, 3, RI_ALL_ONLINE },
+ { 0x10514c, 1, RI_ALL_OFFLINE }, { 0x105150, 3, RI_ALL_ONLINE },
+ { 0x10515c, 1, RI_ALL_OFFLINE }, { 0x105160, 3, RI_ALL_ONLINE },
+ { 0x10516c, 1, RI_ALL_OFFLINE }, { 0x105170, 3, RI_ALL_ONLINE },
+ { 0x10517c, 1, RI_ALL_OFFLINE }, { 0x105180, 3, RI_ALL_ONLINE },
+ { 0x10518c, 1, RI_ALL_OFFLINE }, { 0x105190, 3, RI_ALL_ONLINE },
+ { 0x10519c, 1, RI_ALL_OFFLINE }, { 0x1051a0, 3, RI_ALL_ONLINE },
+ { 0x1051ac, 1, RI_ALL_OFFLINE }, { 0x1051b0, 3, RI_ALL_ONLINE },
+ { 0x1051bc, 1, RI_ALL_OFFLINE }, { 0x1051c0, 3, RI_ALL_ONLINE },
+ { 0x1051cc, 1, RI_ALL_OFFLINE }, { 0x1051d0, 3, RI_ALL_ONLINE },
+ { 0x1051dc, 1, RI_ALL_OFFLINE }, { 0x1051e0, 3, RI_ALL_ONLINE },
+ { 0x1051ec, 1, RI_ALL_OFFLINE }, { 0x1051f0, 3, RI_ALL_ONLINE },
+ { 0x1051fc, 1, RI_ALL_OFFLINE }, { 0x105200, 3, RI_ALL_ONLINE },
+ { 0x10520c, 1, RI_ALL_OFFLINE }, { 0x105210, 3, RI_ALL_ONLINE },
+ { 0x10521c, 1, RI_ALL_OFFLINE }, { 0x105220, 3, RI_ALL_ONLINE },
+ { 0x10522c, 1, RI_ALL_OFFLINE }, { 0x105230, 3, RI_ALL_ONLINE },
+ { 0x10523c, 1, RI_ALL_OFFLINE }, { 0x105240, 3, RI_ALL_ONLINE },
+ { 0x10524c, 1, RI_ALL_OFFLINE }, { 0x105250, 3, RI_ALL_ONLINE },
+ { 0x10525c, 1, RI_ALL_OFFLINE }, { 0x105260, 3, RI_ALL_ONLINE },
+ { 0x10526c, 1, RI_ALL_OFFLINE }, { 0x105270, 3, RI_ALL_ONLINE },
+ { 0x10527c, 1, RI_ALL_OFFLINE }, { 0x105280, 3, RI_ALL_ONLINE },
+ { 0x10528c, 1, RI_ALL_OFFLINE }, { 0x105290, 3, RI_ALL_ONLINE },
+ { 0x10529c, 1, RI_ALL_OFFLINE }, { 0x1052a0, 3, RI_ALL_ONLINE },
+ { 0x1052ac, 1, RI_ALL_OFFLINE }, { 0x1052b0, 3, RI_ALL_ONLINE },
+ { 0x1052bc, 1, RI_ALL_OFFLINE }, { 0x1052c0, 3, RI_ALL_ONLINE },
+ { 0x1052cc, 1, RI_ALL_OFFLINE }, { 0x1052d0, 3, RI_ALL_ONLINE },
+ { 0x1052dc, 1, RI_ALL_OFFLINE }, { 0x1052e0, 3, RI_ALL_ONLINE },
+ { 0x1052ec, 1, RI_ALL_OFFLINE }, { 0x1052f0, 3, RI_ALL_ONLINE },
+ { 0x1052fc, 1, RI_ALL_OFFLINE }, { 0x105300, 3, RI_ALL_ONLINE },
+ { 0x10530c, 1, RI_ALL_OFFLINE }, { 0x105310, 3, RI_ALL_ONLINE },
+ { 0x10531c, 1, RI_ALL_OFFLINE }, { 0x105320, 3, RI_ALL_ONLINE },
+ { 0x10532c, 1, RI_ALL_OFFLINE }, { 0x105330, 3, RI_ALL_ONLINE },
+ { 0x10533c, 1, RI_ALL_OFFLINE }, { 0x105340, 3, RI_ALL_ONLINE },
+ { 0x10534c, 1, RI_ALL_OFFLINE }, { 0x105350, 3, RI_ALL_ONLINE },
+ { 0x10535c, 1, RI_ALL_OFFLINE }, { 0x105360, 3, RI_ALL_ONLINE },
+ { 0x10536c, 1, RI_ALL_OFFLINE }, { 0x105370, 3, RI_ALL_ONLINE },
+ { 0x10537c, 1, RI_ALL_OFFLINE }, { 0x105380, 3, RI_ALL_ONLINE },
+ { 0x10538c, 1, RI_ALL_OFFLINE }, { 0x105390, 3, RI_ALL_ONLINE },
+ { 0x10539c, 1, RI_ALL_OFFLINE }, { 0x1053a0, 3, RI_ALL_ONLINE },
+ { 0x1053ac, 1, RI_ALL_OFFLINE }, { 0x1053b0, 3, RI_ALL_ONLINE },
+ { 0x1053bc, 1, RI_ALL_OFFLINE }, { 0x1053c0, 3, RI_ALL_ONLINE },
+ { 0x1053cc, 1, RI_ALL_OFFLINE }, { 0x1053d0, 3, RI_ALL_ONLINE },
+ { 0x1053dc, 1, RI_ALL_OFFLINE }, { 0x1053e0, 3, RI_ALL_ONLINE },
+ { 0x1053ec, 1, RI_ALL_OFFLINE }, { 0x1053f0, 3, RI_ALL_ONLINE },
+ { 0x1053fc, 769, RI_ALL_OFFLINE }, { 0x108000, 33, RI_ALL_ONLINE },
+ { 0x108090, 1, RI_ALL_ONLINE }, { 0x1080a0, 1, RI_ALL_ONLINE },
+ { 0x1080ac, 5, RI_E1H_ONLINE }, { 0x108100, 5, RI_ALL_ONLINE },
+ { 0x108120, 5, RI_ALL_ONLINE }, { 0x108200, 74, RI_ALL_ONLINE },
+ { 0x108400, 74, RI_ALL_ONLINE }, { 0x108800, 152, RI_ALL_ONLINE },
+ { 0x109000, 1, RI_ALL_ONLINE }, { 0x120000, 347, RI_ALL_ONLINE },
+ { 0x120578, 1, RI_ALL_ONLINE }, { 0x120588, 1, RI_ALL_ONLINE },
+ { 0x120598, 1, RI_ALL_ONLINE }, { 0x12059c, 23, RI_E1H_ONLINE },
+ { 0x120614, 1, RI_E1H_ONLINE }, { 0x12061c, 30, RI_E1H_ONLINE },
+ { 0x12080c, 65, RI_ALL_ONLINE }, { 0x120a00, 2, RI_ALL_ONLINE },
+ { 0x122000, 2, RI_ALL_ONLINE }, { 0x128000, 2, RI_E1H_ONLINE },
+ { 0x140000, 114, RI_ALL_ONLINE }, { 0x1401d4, 1, RI_ALL_ONLINE },
+ { 0x1401e4, 1, RI_ALL_ONLINE }, { 0x140200, 6, RI_ALL_ONLINE },
+ { 0x144000, 4, RI_ALL_ONLINE }, { 0x148000, 4, RI_ALL_ONLINE },
+ { 0x14c000, 4, RI_ALL_ONLINE }, { 0x150000, 4, RI_ALL_ONLINE },
+ { 0x154000, 4, RI_ALL_ONLINE }, { 0x158000, 4, RI_ALL_ONLINE },
+ { 0x15c000, 7, RI_E1H_ONLINE }, { 0x161000, 7, RI_ALL_ONLINE },
+ { 0x161028, 1, RI_ALL_ONLINE }, { 0x161038, 1, RI_ALL_ONLINE },
+ { 0x161800, 2, RI_ALL_ONLINE }, { 0x164000, 60, RI_ALL_ONLINE },
+ { 0x1640fc, 1, RI_ALL_ONLINE }, { 0x16410c, 1, RI_ALL_ONLINE },
+ { 0x164110, 2, RI_E1H_ONLINE }, { 0x164200, 1, RI_ALL_ONLINE },
+ { 0x164208, 1, RI_ALL_ONLINE }, { 0x164210, 1, RI_ALL_ONLINE },
+ { 0x164218, 1, RI_ALL_ONLINE }, { 0x164220, 1, RI_ALL_ONLINE },
+ { 0x164228, 1, RI_ALL_ONLINE }, { 0x164230, 1, RI_ALL_ONLINE },
+ { 0x164238, 1, RI_ALL_ONLINE }, { 0x164240, 1, RI_ALL_ONLINE },
+ { 0x164248, 1, RI_ALL_ONLINE }, { 0x164250, 1, RI_ALL_ONLINE },
+ { 0x164258, 1, RI_ALL_ONLINE }, { 0x164260, 1, RI_ALL_ONLINE },
+ { 0x164270, 2, RI_ALL_ONLINE }, { 0x164280, 2, RI_ALL_ONLINE },
+ { 0x164800, 2, RI_ALL_ONLINE }, { 0x165000, 2, RI_ALL_ONLINE },
+ { 0x166000, 164, RI_ALL_ONLINE }, { 0x16629c, 1, RI_ALL_ONLINE },
+ { 0x1662ac, 1, RI_ALL_ONLINE }, { 0x1662bc, 1, RI_ALL_ONLINE },
+ { 0x166400, 49, RI_ALL_ONLINE }, { 0x1664c8, 38, RI_ALL_ONLINE },
+ { 0x166568, 2, RI_ALL_ONLINE }, { 0x166800, 1, RI_ALL_ONLINE },
+ { 0x168000, 270, RI_ALL_ONLINE }, { 0x168444, 1, RI_ALL_ONLINE },
+ { 0x168454, 1, RI_ALL_ONLINE }, { 0x168800, 19, RI_ALL_ONLINE },
+ { 0x168900, 1, RI_ALL_ONLINE }, { 0x168a00, 128, RI_ALL_ONLINE },
+ { 0x16a000, 1, RI_ALL_ONLINE }, { 0x16a004, 1535, RI_ALL_OFFLINE },
+ { 0x16c000, 1, RI_ALL_ONLINE }, { 0x16c004, 1535, RI_ALL_OFFLINE },
+ { 0x16e000, 16, RI_E1H_ONLINE }, { 0x16e100, 1, RI_E1H_ONLINE },
+ { 0x16e200, 2, RI_E1H_ONLINE }, { 0x16e400, 183, RI_E1H_ONLINE },
+ { 0x170000, 93, RI_ALL_ONLINE }, { 0x170180, 1, RI_ALL_ONLINE },
+ { 0x170190, 1, RI_ALL_ONLINE }, { 0x170200, 4, RI_ALL_ONLINE },
+ { 0x170214, 1, RI_ALL_ONLINE }, { 0x178000, 1, RI_ALL_ONLINE },
+ { 0x180000, 61, RI_ALL_ONLINE }, { 0x180100, 1, RI_ALL_ONLINE },
+ { 0x180110, 1, RI_ALL_ONLINE }, { 0x180120, 1, RI_ALL_ONLINE },
+ { 0x180130, 1, RI_ALL_ONLINE }, { 0x18013c, 2, RI_E1H_ONLINE },
+ { 0x180200, 58, RI_ALL_ONLINE }, { 0x180340, 4, RI_ALL_ONLINE },
+ { 0x180400, 1, RI_ALL_ONLINE }, { 0x180404, 255, RI_ALL_OFFLINE },
+ { 0x181000, 4, RI_ALL_ONLINE }, { 0x181010, 1020, RI_ALL_OFFLINE },
+ { 0x1a0000, 1, RI_ALL_ONLINE }, { 0x1a0004, 1023, RI_ALL_OFFLINE },
+ { 0x1a1000, 1, RI_ALL_ONLINE }, { 0x1a1004, 4607, RI_ALL_OFFLINE },
+ { 0x1a5800, 2560, RI_E1H_OFFLINE }, { 0x1a8000, 64, RI_ALL_OFFLINE },
+ { 0x1a8100, 1984, RI_E1H_OFFLINE }, { 0x1aa000, 1, RI_E1H_ONLINE },
+ { 0x1aa004, 6655, RI_E1H_OFFLINE }, { 0x1b1800, 128, RI_ALL_OFFLINE },
+ { 0x1b1c00, 128, RI_ALL_OFFLINE }, { 0x1b2000, 1, RI_ALL_OFFLINE },
+ { 0x1b2400, 64, RI_E1H_OFFLINE }, { 0x1b8200, 1, RI_ALL_ONLINE },
+ { 0x1b8240, 1, RI_ALL_ONLINE }, { 0x1b8280, 1, RI_ALL_ONLINE },
+ { 0x1b82c0, 1, RI_ALL_ONLINE }, { 0x1b8a00, 1, RI_ALL_ONLINE },
+ { 0x1b8a80, 1, RI_ALL_ONLINE }, { 0x1c0000, 2, RI_ALL_ONLINE },
+ { 0x200000, 65, RI_ALL_ONLINE }, { 0x200110, 1, RI_ALL_ONLINE },
+ { 0x200120, 1, RI_ALL_ONLINE }, { 0x200130, 1, RI_ALL_ONLINE },
+ { 0x200140, 1, RI_ALL_ONLINE }, { 0x20014c, 2, RI_E1H_ONLINE },
+ { 0x200200, 58, RI_ALL_ONLINE }, { 0x200340, 4, RI_ALL_ONLINE },
+ { 0x200400, 1, RI_ALL_ONLINE }, { 0x200404, 255, RI_ALL_OFFLINE },
+ { 0x202000, 4, RI_ALL_ONLINE }, { 0x202010, 2044, RI_ALL_OFFLINE },
+ { 0x220000, 1, RI_ALL_ONLINE }, { 0x220004, 1023, RI_ALL_OFFLINE },
+ { 0x221000, 1, RI_ALL_ONLINE }, { 0x221004, 4607, RI_ALL_OFFLINE },
+ { 0x225800, 1536, RI_E1H_OFFLINE }, { 0x227000, 1, RI_E1H_ONLINE },
+ { 0x227004, 1023, RI_E1H_OFFLINE }, { 0x228000, 64, RI_ALL_OFFLINE },
+ { 0x228100, 8640, RI_E1H_OFFLINE }, { 0x231800, 128, RI_ALL_OFFLINE },
+ { 0x231c00, 128, RI_ALL_OFFLINE }, { 0x232000, 1, RI_ALL_OFFLINE },
+ { 0x232400, 64, RI_E1H_OFFLINE }, { 0x238200, 1, RI_ALL_ONLINE },
+ { 0x238240, 1, RI_ALL_ONLINE }, { 0x238280, 1, RI_ALL_ONLINE },
+ { 0x2382c0, 1, RI_ALL_ONLINE }, { 0x238a00, 1, RI_ALL_ONLINE },
+ { 0x238a80, 1, RI_ALL_ONLINE }, { 0x240000, 2, RI_ALL_ONLINE },
+ { 0x280000, 65, RI_ALL_ONLINE }, { 0x280110, 1, RI_ALL_ONLINE },
+ { 0x280120, 1, RI_ALL_ONLINE }, { 0x280130, 1, RI_ALL_ONLINE },
+ { 0x280140, 1, RI_ALL_ONLINE }, { 0x28014c, 2, RI_E1H_ONLINE },
+ { 0x280200, 58, RI_ALL_ONLINE }, { 0x280340, 4, RI_ALL_ONLINE },
+ { 0x280400, 1, RI_ALL_ONLINE }, { 0x280404, 255, RI_ALL_OFFLINE },
+ { 0x282000, 4, RI_ALL_ONLINE }, { 0x282010, 2044, RI_ALL_OFFLINE },
+ { 0x2a0000, 1, RI_ALL_ONLINE }, { 0x2a0004, 1023, RI_ALL_OFFLINE },
+ { 0x2a1000, 1, RI_ALL_ONLINE }, { 0x2a1004, 4607, RI_ALL_OFFLINE },
+ { 0x2a5800, 2560, RI_E1H_OFFLINE }, { 0x2a8000, 64, RI_ALL_OFFLINE },
+ { 0x2a8100, 960, RI_E1H_OFFLINE }, { 0x2a9000, 1, RI_E1H_ONLINE },
+ { 0x2a9004, 7679, RI_E1H_OFFLINE }, { 0x2b1800, 128, RI_ALL_OFFLINE },
+ { 0x2b1c00, 128, RI_ALL_OFFLINE }, { 0x2b2000, 1, RI_ALL_OFFLINE },
+ { 0x2b2400, 64, RI_E1H_OFFLINE }, { 0x2b8200, 1, RI_ALL_ONLINE },
+ { 0x2b8240, 1, RI_ALL_ONLINE }, { 0x2b8280, 1, RI_ALL_ONLINE },
+ { 0x2b82c0, 1, RI_ALL_ONLINE }, { 0x2b8a00, 1, RI_ALL_ONLINE },
+ { 0x2b8a80, 1, RI_ALL_ONLINE }, { 0x2c0000, 2, RI_ALL_ONLINE },
+ { 0x300000, 65, RI_ALL_ONLINE }, { 0x300110, 1, RI_ALL_ONLINE },
+ { 0x300120, 1, RI_ALL_ONLINE }, { 0x300130, 1, RI_ALL_ONLINE },
+ { 0x300140, 1, RI_ALL_ONLINE }, { 0x30014c, 2, RI_E1H_ONLINE },
+ { 0x300200, 58, RI_ALL_ONLINE }, { 0x300340, 4, RI_ALL_ONLINE },
+ { 0x300400, 1, RI_ALL_ONLINE }, { 0x300404, 255, RI_ALL_OFFLINE },
+ { 0x302000, 4, RI_ALL_ONLINE }, { 0x302010, 2044, RI_ALL_OFFLINE },
+ { 0x320000, 1, RI_ALL_ONLINE }, { 0x320004, 1023, RI_ALL_OFFLINE },
+ { 0x321000, 1, RI_ALL_ONLINE }, { 0x321004, 4607, RI_ALL_OFFLINE },
+ { 0x325800, 2560, RI_E1H_OFFLINE }, { 0x328000, 64, RI_ALL_OFFLINE },
+ { 0x328100, 536, RI_E1H_OFFLINE }, { 0x328960, 1, RI_E1H_ONLINE },
+ { 0x328964, 8103, RI_E1H_OFFLINE }, { 0x331800, 128, RI_ALL_OFFLINE },
+ { 0x331c00, 128, RI_ALL_OFFLINE }, { 0x332000, 1, RI_ALL_OFFLINE },
+ { 0x332400, 64, RI_E1H_OFFLINE }, { 0x338200, 1, RI_ALL_ONLINE },
+ { 0x338240, 1, RI_ALL_ONLINE }, { 0x338280, 1, RI_ALL_ONLINE },
+ { 0x3382c0, 1, RI_ALL_ONLINE }, { 0x338a00, 1, RI_ALL_ONLINE },
+ { 0x338a80, 1, RI_ALL_ONLINE }, { 0x340000, 2, RI_ALL_ONLINE }
};
-#define IDLEREGS_COUNT 277
-static const struct reg_addr idle_addrs[IDLEREGS_COUNT] = {
- { 0x2114, 1, RI_ALL_ONLINE}, { 0x2120, 1, RI_ALL_ONLINE},
- { 0x212c, 4, RI_ALL_ONLINE}, { 0x2814, 1, RI_ALL_ONLINE},
- { 0x281c, 2, RI_ALL_ONLINE}, { 0xa38c, 1, RI_ALL_ONLINE},
- { 0xa408, 1, RI_ALL_ONLINE}, { 0xa42c, 12, RI_ALL_ONLINE},
- { 0xa600, 5, RI_E1H_ONLINE}, { 0xa618, 1, RI_E1H_ONLINE},
- { 0xc09c, 1, RI_ALL_ONLINE}, { 0x103b0, 1, RI_ALL_ONLINE},
- { 0x103c0, 1, RI_ALL_ONLINE}, { 0x103d0, 1, RI_E1H_ONLINE},
- { 0x2021c, 11, RI_ALL_ONLINE}, { 0x202a8, 1, RI_ALL_ONLINE},
- { 0x202b8, 1, RI_ALL_ONLINE}, { 0x20404, 1, RI_ALL_ONLINE},
- { 0x2040c, 2, RI_ALL_ONLINE}, { 0x2041c, 2, RI_ALL_ONLINE},
- { 0x40154, 14, RI_ALL_ONLINE}, { 0x40198, 1, RI_ALL_ONLINE},
- { 0x404ac, 1, RI_ALL_ONLINE}, { 0x404bc, 1, RI_ALL_ONLINE},
- { 0x42290, 1, RI_ALL_ONLINE}, { 0x422a0, 1, RI_ALL_ONLINE},
- { 0x422b0, 1, RI_ALL_ONLINE}, { 0x42548, 1, RI_ALL_ONLINE},
- { 0x42550, 1, RI_ALL_ONLINE}, { 0x42558, 1, RI_ALL_ONLINE},
- { 0x50160, 8, RI_ALL_ONLINE}, { 0x501d0, 1, RI_ALL_ONLINE},
- { 0x501e0, 1, RI_ALL_ONLINE}, { 0x50204, 1, RI_ALL_ONLINE},
- { 0x5020c, 2, RI_ALL_ONLINE}, { 0x5021c, 1, RI_ALL_ONLINE},
- { 0x60090, 1, RI_ALL_ONLINE}, { 0x6011c, 1, RI_ALL_ONLINE},
- { 0x6012c, 1, RI_ALL_ONLINE}, { 0xc101c, 1, RI_ALL_ONLINE},
- { 0xc102c, 1, RI_ALL_ONLINE}, { 0xc2290, 1, RI_ALL_ONLINE},
- { 0xc22a0, 1, RI_ALL_ONLINE}, { 0xc22b0, 1, RI_ALL_ONLINE},
- { 0xc2548, 1, RI_ALL_ONLINE}, { 0xc2550, 1, RI_ALL_ONLINE},
- { 0xc2558, 1, RI_ALL_ONLINE}, { 0xc4294, 1, RI_ALL_ONLINE},
- { 0xc42a4, 1, RI_ALL_ONLINE}, { 0xc42b4, 1, RI_ALL_ONLINE},
- { 0xc4550, 1, RI_ALL_ONLINE}, { 0xc4558, 1, RI_ALL_ONLINE},
- { 0xc4560, 1, RI_ALL_ONLINE}, { 0xd016c, 8, RI_ALL_ONLINE},
- { 0xd01d8, 1, RI_ALL_ONLINE}, { 0xd01e8, 1, RI_ALL_ONLINE},
- { 0xd0204, 1, RI_ALL_ONLINE}, { 0xd020c, 3, RI_ALL_ONLINE},
- { 0xe0154, 8, RI_ALL_ONLINE}, { 0xe01c8, 1, RI_ALL_ONLINE},
- { 0xe01d8, 1, RI_ALL_ONLINE}, { 0xe0204, 1, RI_ALL_ONLINE},
- { 0xe020c, 2, RI_ALL_ONLINE}, { 0xe021c, 2, RI_ALL_ONLINE},
- { 0x101014, 1, RI_ALL_ONLINE}, { 0x101030, 1, RI_ALL_ONLINE},
- { 0x101040, 1, RI_ALL_ONLINE}, { 0x102058, 1, RI_ALL_ONLINE},
- { 0x102080, 16, RI_ALL_ONLINE}, { 0x103004, 2, RI_ALL_ONLINE},
- { 0x103068, 1, RI_ALL_ONLINE}, { 0x103078, 1, RI_ALL_ONLINE},
- { 0x103088, 1, RI_ALL_ONLINE}, { 0x10309c, 2, RI_E1H_ONLINE},
- { 0x104004, 1, RI_ALL_ONLINE}, { 0x104018, 1, RI_ALL_ONLINE},
- { 0x104020, 1, RI_ALL_ONLINE}, { 0x10403c, 1, RI_ALL_ONLINE},
- { 0x1040fc, 1, RI_ALL_ONLINE}, { 0x10410c, 1, RI_ALL_ONLINE},
- { 0x104400, 64, RI_ALL_ONLINE}, { 0x104800, 64, RI_ALL_ONLINE},
- { 0x105000, 3, RI_ALL_ONLINE}, { 0x105010, 3, RI_ALL_ONLINE},
- { 0x105020, 3, RI_ALL_ONLINE}, { 0x105030, 3, RI_ALL_ONLINE},
- { 0x105040, 3, RI_ALL_ONLINE}, { 0x105050, 3, RI_ALL_ONLINE},
- { 0x105060, 3, RI_ALL_ONLINE}, { 0x105070, 3, RI_ALL_ONLINE},
- { 0x105080, 3, RI_ALL_ONLINE}, { 0x105090, 3, RI_ALL_ONLINE},
- { 0x1050a0, 3, RI_ALL_ONLINE}, { 0x1050b0, 3, RI_ALL_ONLINE},
- { 0x1050c0, 3, RI_ALL_ONLINE}, { 0x1050d0, 3, RI_ALL_ONLINE},
- { 0x1050e0, 3, RI_ALL_ONLINE}, { 0x1050f0, 3, RI_ALL_ONLINE},
- { 0x105100, 3, RI_ALL_ONLINE}, { 0x105110, 3, RI_ALL_ONLINE},
- { 0x105120, 3, RI_ALL_ONLINE}, { 0x105130, 3, RI_ALL_ONLINE},
- { 0x105140, 3, RI_ALL_ONLINE}, { 0x105150, 3, RI_ALL_ONLINE},
- { 0x105160, 3, RI_ALL_ONLINE}, { 0x105170, 3, RI_ALL_ONLINE},
- { 0x105180, 3, RI_ALL_ONLINE}, { 0x105190, 3, RI_ALL_ONLINE},
- { 0x1051a0, 3, RI_ALL_ONLINE}, { 0x1051b0, 3, RI_ALL_ONLINE},
- { 0x1051c0, 3, RI_ALL_ONLINE}, { 0x1051d0, 3, RI_ALL_ONLINE},
- { 0x1051e0, 3, RI_ALL_ONLINE}, { 0x1051f0, 3, RI_ALL_ONLINE},
- { 0x105200, 3, RI_ALL_ONLINE}, { 0x105210, 3, RI_ALL_ONLINE},
- { 0x105220, 3, RI_ALL_ONLINE}, { 0x105230, 3, RI_ALL_ONLINE},
- { 0x105240, 3, RI_ALL_ONLINE}, { 0x105250, 3, RI_ALL_ONLINE},
- { 0x105260, 3, RI_ALL_ONLINE}, { 0x105270, 3, RI_ALL_ONLINE},
- { 0x105280, 3, RI_ALL_ONLINE}, { 0x105290, 3, RI_ALL_ONLINE},
- { 0x1052a0, 3, RI_ALL_ONLINE}, { 0x1052b0, 3, RI_ALL_ONLINE},
- { 0x1052c0, 3, RI_ALL_ONLINE}, { 0x1052d0, 3, RI_ALL_ONLINE},
- { 0x1052e0, 3, RI_ALL_ONLINE}, { 0x1052f0, 3, RI_ALL_ONLINE},
- { 0x105300, 3, RI_ALL_ONLINE}, { 0x105310, 3, RI_ALL_ONLINE},
- { 0x105320, 3, RI_ALL_ONLINE}, { 0x105330, 3, RI_ALL_ONLINE},
- { 0x105340, 3, RI_ALL_ONLINE}, { 0x105350, 3, RI_ALL_ONLINE},
- { 0x105360, 3, RI_ALL_ONLINE}, { 0x105370, 3, RI_ALL_ONLINE},
- { 0x105380, 3, RI_ALL_ONLINE}, { 0x105390, 3, RI_ALL_ONLINE},
- { 0x1053a0, 3, RI_ALL_ONLINE}, { 0x1053b0, 3, RI_ALL_ONLINE},
- { 0x1053c0, 3, RI_ALL_ONLINE}, { 0x1053d0, 3, RI_ALL_ONLINE},
- { 0x1053e0, 3, RI_ALL_ONLINE}, { 0x1053f0, 3, RI_ALL_ONLINE},
- { 0x108094, 1, RI_ALL_ONLINE}, { 0x1201b0, 2, RI_ALL_ONLINE},
- { 0x12032c, 1, RI_ALL_ONLINE}, { 0x12036c, 3, RI_ALL_ONLINE},
- { 0x120408, 2, RI_ALL_ONLINE}, { 0x120414, 15, RI_ALL_ONLINE},
- { 0x120478, 2, RI_ALL_ONLINE}, { 0x12052c, 1, RI_ALL_ONLINE},
- { 0x120564, 3, RI_ALL_ONLINE}, { 0x12057c, 1, RI_ALL_ONLINE},
- { 0x12058c, 1, RI_ALL_ONLINE}, { 0x120608, 1, RI_E1H_ONLINE},
- { 0x120808, 1, RI_E1_ONLINE}, { 0x12080c, 2, RI_ALL_ONLINE},
- { 0x120818, 1, RI_ALL_ONLINE}, { 0x120820, 1, RI_ALL_ONLINE},
- { 0x120828, 1, RI_ALL_ONLINE}, { 0x120830, 1, RI_ALL_ONLINE},
- { 0x120838, 1, RI_ALL_ONLINE}, { 0x120840, 1, RI_ALL_ONLINE},
- { 0x120848, 1, RI_ALL_ONLINE}, { 0x120850, 1, RI_ALL_ONLINE},
- { 0x120858, 1, RI_ALL_ONLINE}, { 0x120860, 1, RI_ALL_ONLINE},
- { 0x120868, 1, RI_ALL_ONLINE}, { 0x120870, 1, RI_ALL_ONLINE},
- { 0x120878, 1, RI_ALL_ONLINE}, { 0x120880, 1, RI_ALL_ONLINE},
- { 0x120888, 1, RI_ALL_ONLINE}, { 0x120890, 1, RI_ALL_ONLINE},
- { 0x120898, 1, RI_ALL_ONLINE}, { 0x1208a0, 1, RI_ALL_ONLINE},
- { 0x1208a8, 1, RI_ALL_ONLINE}, { 0x1208b0, 1, RI_ALL_ONLINE},
- { 0x1208b8, 1, RI_ALL_ONLINE}, { 0x1208c0, 1, RI_ALL_ONLINE},
- { 0x1208c8, 1, RI_ALL_ONLINE}, { 0x1208d0, 1, RI_ALL_ONLINE},
- { 0x1208d8, 1, RI_ALL_ONLINE}, { 0x1208e0, 1, RI_ALL_ONLINE},
- { 0x1208e8, 1, RI_ALL_ONLINE}, { 0x1208f0, 1, RI_ALL_ONLINE},
- { 0x1208f8, 1, RI_ALL_ONLINE}, { 0x120900, 1, RI_ALL_ONLINE},
- { 0x120908, 1, RI_ALL_ONLINE}, { 0x14005c, 2, RI_ALL_ONLINE},
- { 0x1400d0, 2, RI_ALL_ONLINE}, { 0x1400e0, 1, RI_ALL_ONLINE},
- { 0x1401c8, 1, RI_ALL_ONLINE}, { 0x140200, 6, RI_ALL_ONLINE},
- { 0x16101c, 1, RI_ALL_ONLINE}, { 0x16102c, 1, RI_ALL_ONLINE},
- { 0x164014, 2, RI_ALL_ONLINE}, { 0x1640f0, 1, RI_ALL_ONLINE},
- { 0x166290, 1, RI_ALL_ONLINE}, { 0x1662a0, 1, RI_ALL_ONLINE},
- { 0x1662b0, 1, RI_ALL_ONLINE}, { 0x166548, 1, RI_ALL_ONLINE},
- { 0x166550, 1, RI_ALL_ONLINE}, { 0x166558, 1, RI_ALL_ONLINE},
- { 0x168000, 1, RI_ALL_ONLINE}, { 0x168008, 1, RI_ALL_ONLINE},
- { 0x168010, 1, RI_ALL_ONLINE}, { 0x168018, 1, RI_ALL_ONLINE},
- { 0x168028, 2, RI_ALL_ONLINE}, { 0x168058, 4, RI_ALL_ONLINE},
- { 0x168070, 1, RI_ALL_ONLINE}, { 0x168238, 1, RI_ALL_ONLINE},
- { 0x1682d0, 2, RI_ALL_ONLINE}, { 0x1682e0, 1, RI_ALL_ONLINE},
- { 0x168300, 67, RI_ALL_ONLINE}, { 0x168410, 2, RI_ALL_ONLINE},
- { 0x168438, 1, RI_ALL_ONLINE}, { 0x168448, 1, RI_ALL_ONLINE},
- { 0x168a00, 128, RI_ALL_ONLINE}, { 0x16e200, 128, RI_E1H_ONLINE},
- { 0x16e404, 2, RI_E1H_ONLINE}, { 0x16e584, 70, RI_E1H_ONLINE},
- { 0x1700a4, 1, RI_ALL_ONLINE}, { 0x1700ac, 2, RI_ALL_ONLINE},
- { 0x1700c0, 1, RI_ALL_ONLINE}, { 0x170174, 1, RI_ALL_ONLINE},
- { 0x170184, 1, RI_ALL_ONLINE}, { 0x1800f4, 1, RI_ALL_ONLINE},
- { 0x180104, 1, RI_ALL_ONLINE}, { 0x180114, 1, RI_ALL_ONLINE},
- { 0x180124, 1, RI_ALL_ONLINE}, { 0x18026c, 1, RI_ALL_ONLINE},
- { 0x1802a0, 1, RI_ALL_ONLINE}, { 0x1a1000, 1, RI_ALL_ONLINE},
- { 0x1aa000, 1, RI_E1H_ONLINE}, { 0x1b8000, 1, RI_ALL_ONLINE},
- { 0x1b8040, 1, RI_ALL_ONLINE}, { 0x1b8080, 1, RI_ALL_ONLINE},
- { 0x1b80c0, 1, RI_ALL_ONLINE}, { 0x200104, 1, RI_ALL_ONLINE},
- { 0x200114, 1, RI_ALL_ONLINE}, { 0x200124, 1, RI_ALL_ONLINE},
- { 0x200134, 1, RI_ALL_ONLINE}, { 0x20026c, 1, RI_ALL_ONLINE},
- { 0x2002a0, 1, RI_ALL_ONLINE}, { 0x221000, 1, RI_ALL_ONLINE},
- { 0x227000, 1, RI_E1H_ONLINE}, { 0x238000, 1, RI_ALL_ONLINE},
- { 0x238040, 1, RI_ALL_ONLINE}, { 0x238080, 1, RI_ALL_ONLINE},
- { 0x2380c0, 1, RI_ALL_ONLINE}, { 0x280104, 1, RI_ALL_ONLINE},
- { 0x280114, 1, RI_ALL_ONLINE}, { 0x280124, 1, RI_ALL_ONLINE},
- { 0x280134, 1, RI_ALL_ONLINE}, { 0x28026c, 1, RI_ALL_ONLINE},
- { 0x2802a0, 1, RI_ALL_ONLINE}, { 0x2a1000, 1, RI_ALL_ONLINE},
- { 0x2a9000, 1, RI_E1H_ONLINE}, { 0x2b8000, 1, RI_ALL_ONLINE},
- { 0x2b8040, 1, RI_ALL_ONLINE}, { 0x2b8080, 1, RI_ALL_ONLINE},
- { 0x2b80c0, 1, RI_ALL_ONLINE}, { 0x300104, 1, RI_ALL_ONLINE},
- { 0x300114, 1, RI_ALL_ONLINE}, { 0x300124, 1, RI_ALL_ONLINE},
- { 0x300134, 1, RI_ALL_ONLINE}, { 0x30026c, 1, RI_ALL_ONLINE},
- { 0x3002a0, 1, RI_ALL_ONLINE}, { 0x321000, 1, RI_ALL_ONLINE},
- { 0x328960, 1, RI_E1H_ONLINE}, { 0x338000, 1, RI_ALL_ONLINE},
- { 0x338040, 1, RI_ALL_ONLINE}, { 0x338080, 1, RI_ALL_ONLINE},
- { 0x3380c0, 1, RI_ALL_ONLINE}
+#define IDLE_REGS_COUNT 277
+static const struct reg_addr idle_addrs[IDLE_REGS_COUNT] = {
+ { 0x2114, 1, RI_ALL_ONLINE }, { 0x2120, 1, RI_ALL_ONLINE },
+ { 0x212c, 4, RI_ALL_ONLINE }, { 0x2814, 1, RI_ALL_ONLINE },
+ { 0x281c, 2, RI_ALL_ONLINE }, { 0xa38c, 1, RI_ALL_ONLINE },
+ { 0xa408, 1, RI_ALL_ONLINE }, { 0xa42c, 12, RI_ALL_ONLINE },
+ { 0xa600, 5, RI_E1H_ONLINE }, { 0xa618, 1, RI_E1H_ONLINE },
+ { 0xc09c, 1, RI_ALL_ONLINE }, { 0x103b0, 1, RI_ALL_ONLINE },
+ { 0x103c0, 1, RI_ALL_ONLINE }, { 0x103d0, 1, RI_E1H_ONLINE },
+ { 0x2021c, 11, RI_ALL_ONLINE }, { 0x202a8, 1, RI_ALL_ONLINE },
+ { 0x202b8, 1, RI_ALL_ONLINE }, { 0x20404, 1, RI_ALL_ONLINE },
+ { 0x2040c, 2, RI_ALL_ONLINE }, { 0x2041c, 2, RI_ALL_ONLINE },
+ { 0x40154, 14, RI_ALL_ONLINE }, { 0x40198, 1, RI_ALL_ONLINE },
+ { 0x404ac, 1, RI_ALL_ONLINE }, { 0x404bc, 1, RI_ALL_ONLINE },
+ { 0x42290, 1, RI_ALL_ONLINE }, { 0x422a0, 1, RI_ALL_ONLINE },
+ { 0x422b0, 1, RI_ALL_ONLINE }, { 0x42548, 1, RI_ALL_ONLINE },
+ { 0x42550, 1, RI_ALL_ONLINE }, { 0x42558, 1, RI_ALL_ONLINE },
+ { 0x50160, 8, RI_ALL_ONLINE }, { 0x501d0, 1, RI_ALL_ONLINE },
+ { 0x501e0, 1, RI_ALL_ONLINE }, { 0x50204, 1, RI_ALL_ONLINE },
+ { 0x5020c, 2, RI_ALL_ONLINE }, { 0x5021c, 1, RI_ALL_ONLINE },
+ { 0x60090, 1, RI_ALL_ONLINE }, { 0x6011c, 1, RI_ALL_ONLINE },
+ { 0x6012c, 1, RI_ALL_ONLINE }, { 0xc101c, 1, RI_ALL_ONLINE },
+ { 0xc102c, 1, RI_ALL_ONLINE }, { 0xc2290, 1, RI_ALL_ONLINE },
+ { 0xc22a0, 1, RI_ALL_ONLINE }, { 0xc22b0, 1, RI_ALL_ONLINE },
+ { 0xc2548, 1, RI_ALL_ONLINE }, { 0xc2550, 1, RI_ALL_ONLINE },
+ { 0xc2558, 1, RI_ALL_ONLINE }, { 0xc4294, 1, RI_ALL_ONLINE },
+ { 0xc42a4, 1, RI_ALL_ONLINE }, { 0xc42b4, 1, RI_ALL_ONLINE },
+ { 0xc4550, 1, RI_ALL_ONLINE }, { 0xc4558, 1, RI_ALL_ONLINE },
+ { 0xc4560, 1, RI_ALL_ONLINE }, { 0xd016c, 8, RI_ALL_ONLINE },
+ { 0xd01d8, 1, RI_ALL_ONLINE }, { 0xd01e8, 1, RI_ALL_ONLINE },
+ { 0xd0204, 1, RI_ALL_ONLINE }, { 0xd020c, 3, RI_ALL_ONLINE },
+ { 0xe0154, 8, RI_ALL_ONLINE }, { 0xe01c8, 1, RI_ALL_ONLINE },
+ { 0xe01d8, 1, RI_ALL_ONLINE }, { 0xe0204, 1, RI_ALL_ONLINE },
+ { 0xe020c, 2, RI_ALL_ONLINE }, { 0xe021c, 2, RI_ALL_ONLINE },
+ { 0x101014, 1, RI_ALL_ONLINE }, { 0x101030, 1, RI_ALL_ONLINE },
+ { 0x101040, 1, RI_ALL_ONLINE }, { 0x102058, 1, RI_ALL_ONLINE },
+ { 0x102080, 16, RI_ALL_ONLINE }, { 0x103004, 2, RI_ALL_ONLINE },
+ { 0x103068, 1, RI_ALL_ONLINE }, { 0x103078, 1, RI_ALL_ONLINE },
+ { 0x103088, 1, RI_ALL_ONLINE }, { 0x10309c, 2, RI_E1H_ONLINE },
+ { 0x104004, 1, RI_ALL_ONLINE }, { 0x104018, 1, RI_ALL_ONLINE },
+ { 0x104020, 1, RI_ALL_ONLINE }, { 0x10403c, 1, RI_ALL_ONLINE },
+ { 0x1040fc, 1, RI_ALL_ONLINE }, { 0x10410c, 1, RI_ALL_ONLINE },
+ { 0x104400, 64, RI_ALL_ONLINE }, { 0x104800, 64, RI_ALL_ONLINE },
+ { 0x105000, 3, RI_ALL_ONLINE }, { 0x105010, 3, RI_ALL_ONLINE },
+ { 0x105020, 3, RI_ALL_ONLINE }, { 0x105030, 3, RI_ALL_ONLINE },
+ { 0x105040, 3, RI_ALL_ONLINE }, { 0x105050, 3, RI_ALL_ONLINE },
+ { 0x105060, 3, RI_ALL_ONLINE }, { 0x105070, 3, RI_ALL_ONLINE },
+ { 0x105080, 3, RI_ALL_ONLINE }, { 0x105090, 3, RI_ALL_ONLINE },
+ { 0x1050a0, 3, RI_ALL_ONLINE }, { 0x1050b0, 3, RI_ALL_ONLINE },
+ { 0x1050c0, 3, RI_ALL_ONLINE }, { 0x1050d0, 3, RI_ALL_ONLINE },
+ { 0x1050e0, 3, RI_ALL_ONLINE }, { 0x1050f0, 3, RI_ALL_ONLINE },
+ { 0x105100, 3, RI_ALL_ONLINE }, { 0x105110, 3, RI_ALL_ONLINE },
+ { 0x105120, 3, RI_ALL_ONLINE }, { 0x105130, 3, RI_ALL_ONLINE },
+ { 0x105140, 3, RI_ALL_ONLINE }, { 0x105150, 3, RI_ALL_ONLINE },
+ { 0x105160, 3, RI_ALL_ONLINE }, { 0x105170, 3, RI_ALL_ONLINE },
+ { 0x105180, 3, RI_ALL_ONLINE }, { 0x105190, 3, RI_ALL_ONLINE },
+ { 0x1051a0, 3, RI_ALL_ONLINE }, { 0x1051b0, 3, RI_ALL_ONLINE },
+ { 0x1051c0, 3, RI_ALL_ONLINE }, { 0x1051d0, 3, RI_ALL_ONLINE },
+ { 0x1051e0, 3, RI_ALL_ONLINE }, { 0x1051f0, 3, RI_ALL_ONLINE },
+ { 0x105200, 3, RI_ALL_ONLINE }, { 0x105210, 3, RI_ALL_ONLINE },
+ { 0x105220, 3, RI_ALL_ONLINE }, { 0x105230, 3, RI_ALL_ONLINE },
+ { 0x105240, 3, RI_ALL_ONLINE }, { 0x105250, 3, RI_ALL_ONLINE },
+ { 0x105260, 3, RI_ALL_ONLINE }, { 0x105270, 3, RI_ALL_ONLINE },
+ { 0x105280, 3, RI_ALL_ONLINE }, { 0x105290, 3, RI_ALL_ONLINE },
+ { 0x1052a0, 3, RI_ALL_ONLINE }, { 0x1052b0, 3, RI_ALL_ONLINE },
+ { 0x1052c0, 3, RI_ALL_ONLINE }, { 0x1052d0, 3, RI_ALL_ONLINE },
+ { 0x1052e0, 3, RI_ALL_ONLINE }, { 0x1052f0, 3, RI_ALL_ONLINE },
+ { 0x105300, 3, RI_ALL_ONLINE }, { 0x105310, 3, RI_ALL_ONLINE },
+ { 0x105320, 3, RI_ALL_ONLINE }, { 0x105330, 3, RI_ALL_ONLINE },
+ { 0x105340, 3, RI_ALL_ONLINE }, { 0x105350, 3, RI_ALL_ONLINE },
+ { 0x105360, 3, RI_ALL_ONLINE }, { 0x105370, 3, RI_ALL_ONLINE },
+ { 0x105380, 3, RI_ALL_ONLINE }, { 0x105390, 3, RI_ALL_ONLINE },
+ { 0x1053a0, 3, RI_ALL_ONLINE }, { 0x1053b0, 3, RI_ALL_ONLINE },
+ { 0x1053c0, 3, RI_ALL_ONLINE }, { 0x1053d0, 3, RI_ALL_ONLINE },
+ { 0x1053e0, 3, RI_ALL_ONLINE }, { 0x1053f0, 3, RI_ALL_ONLINE },
+ { 0x108094, 1, RI_ALL_ONLINE }, { 0x1201b0, 2, RI_ALL_ONLINE },
+ { 0x12032c, 1, RI_ALL_ONLINE }, { 0x12036c, 3, RI_ALL_ONLINE },
+ { 0x120408, 2, RI_ALL_ONLINE }, { 0x120414, 15, RI_ALL_ONLINE },
+ { 0x120478, 2, RI_ALL_ONLINE }, { 0x12052c, 1, RI_ALL_ONLINE },
+ { 0x120564, 3, RI_ALL_ONLINE }, { 0x12057c, 1, RI_ALL_ONLINE },
+ { 0x12058c, 1, RI_ALL_ONLINE }, { 0x120608, 1, RI_E1H_ONLINE },
+ { 0x120808, 1, RI_E1_ONLINE }, { 0x12080c, 2, RI_ALL_ONLINE },
+ { 0x120818, 1, RI_ALL_ONLINE }, { 0x120820, 1, RI_ALL_ONLINE },
+ { 0x120828, 1, RI_ALL_ONLINE }, { 0x120830, 1, RI_ALL_ONLINE },
+ { 0x120838, 1, RI_ALL_ONLINE }, { 0x120840, 1, RI_ALL_ONLINE },
+ { 0x120848, 1, RI_ALL_ONLINE }, { 0x120850, 1, RI_ALL_ONLINE },
+ { 0x120858, 1, RI_ALL_ONLINE }, { 0x120860, 1, RI_ALL_ONLINE },
+ { 0x120868, 1, RI_ALL_ONLINE }, { 0x120870, 1, RI_ALL_ONLINE },
+ { 0x120878, 1, RI_ALL_ONLINE }, { 0x120880, 1, RI_ALL_ONLINE },
+ { 0x120888, 1, RI_ALL_ONLINE }, { 0x120890, 1, RI_ALL_ONLINE },
+ { 0x120898, 1, RI_ALL_ONLINE }, { 0x1208a0, 1, RI_ALL_ONLINE },
+ { 0x1208a8, 1, RI_ALL_ONLINE }, { 0x1208b0, 1, RI_ALL_ONLINE },
+ { 0x1208b8, 1, RI_ALL_ONLINE }, { 0x1208c0, 1, RI_ALL_ONLINE },
+ { 0x1208c8, 1, RI_ALL_ONLINE }, { 0x1208d0, 1, RI_ALL_ONLINE },
+ { 0x1208d8, 1, RI_ALL_ONLINE }, { 0x1208e0, 1, RI_ALL_ONLINE },
+ { 0x1208e8, 1, RI_ALL_ONLINE }, { 0x1208f0, 1, RI_ALL_ONLINE },
+ { 0x1208f8, 1, RI_ALL_ONLINE }, { 0x120900, 1, RI_ALL_ONLINE },
+ { 0x120908, 1, RI_ALL_ONLINE }, { 0x14005c, 2, RI_ALL_ONLINE },
+ { 0x1400d0, 2, RI_ALL_ONLINE }, { 0x1400e0, 1, RI_ALL_ONLINE },
+ { 0x1401c8, 1, RI_ALL_ONLINE }, { 0x140200, 6, RI_ALL_ONLINE },
+ { 0x16101c, 1, RI_ALL_ONLINE }, { 0x16102c, 1, RI_ALL_ONLINE },
+ { 0x164014, 2, RI_ALL_ONLINE }, { 0x1640f0, 1, RI_ALL_ONLINE },
+ { 0x166290, 1, RI_ALL_ONLINE }, { 0x1662a0, 1, RI_ALL_ONLINE },
+ { 0x1662b0, 1, RI_ALL_ONLINE }, { 0x166548, 1, RI_ALL_ONLINE },
+ { 0x166550, 1, RI_ALL_ONLINE }, { 0x166558, 1, RI_ALL_ONLINE },
+ { 0x168000, 1, RI_ALL_ONLINE }, { 0x168008, 1, RI_ALL_ONLINE },
+ { 0x168010, 1, RI_ALL_ONLINE }, { 0x168018, 1, RI_ALL_ONLINE },
+ { 0x168028, 2, RI_ALL_ONLINE }, { 0x168058, 4, RI_ALL_ONLINE },
+ { 0x168070, 1, RI_ALL_ONLINE }, { 0x168238, 1, RI_ALL_ONLINE },
+ { 0x1682d0, 2, RI_ALL_ONLINE }, { 0x1682e0, 1, RI_ALL_ONLINE },
+ { 0x168300, 67, RI_ALL_ONLINE }, { 0x168410, 2, RI_ALL_ONLINE },
+ { 0x168438, 1, RI_ALL_ONLINE }, { 0x168448, 1, RI_ALL_ONLINE },
+ { 0x168a00, 128, RI_ALL_ONLINE }, { 0x16e200, 128, RI_E1H_ONLINE },
+ { 0x16e404, 2, RI_E1H_ONLINE }, { 0x16e584, 70, RI_E1H_ONLINE },
+ { 0x1700a4, 1, RI_ALL_ONLINE }, { 0x1700ac, 2, RI_ALL_ONLINE },
+ { 0x1700c0, 1, RI_ALL_ONLINE }, { 0x170174, 1, RI_ALL_ONLINE },
+ { 0x170184, 1, RI_ALL_ONLINE }, { 0x1800f4, 1, RI_ALL_ONLINE },
+ { 0x180104, 1, RI_ALL_ONLINE }, { 0x180114, 1, RI_ALL_ONLINE },
+ { 0x180124, 1, RI_ALL_ONLINE }, { 0x18026c, 1, RI_ALL_ONLINE },
+ { 0x1802a0, 1, RI_ALL_ONLINE }, { 0x1a1000, 1, RI_ALL_ONLINE },
+ { 0x1aa000, 1, RI_E1H_ONLINE }, { 0x1b8000, 1, RI_ALL_ONLINE },
+ { 0x1b8040, 1, RI_ALL_ONLINE }, { 0x1b8080, 1, RI_ALL_ONLINE },
+ { 0x1b80c0, 1, RI_ALL_ONLINE }, { 0x200104, 1, RI_ALL_ONLINE },
+ { 0x200114, 1, RI_ALL_ONLINE }, { 0x200124, 1, RI_ALL_ONLINE },
+ { 0x200134, 1, RI_ALL_ONLINE }, { 0x20026c, 1, RI_ALL_ONLINE },
+ { 0x2002a0, 1, RI_ALL_ONLINE }, { 0x221000, 1, RI_ALL_ONLINE },
+ { 0x227000, 1, RI_E1H_ONLINE }, { 0x238000, 1, RI_ALL_ONLINE },
+ { 0x238040, 1, RI_ALL_ONLINE }, { 0x238080, 1, RI_ALL_ONLINE },
+ { 0x2380c0, 1, RI_ALL_ONLINE }, { 0x280104, 1, RI_ALL_ONLINE },
+ { 0x280114, 1, RI_ALL_ONLINE }, { 0x280124, 1, RI_ALL_ONLINE },
+ { 0x280134, 1, RI_ALL_ONLINE }, { 0x28026c, 1, RI_ALL_ONLINE },
+ { 0x2802a0, 1, RI_ALL_ONLINE }, { 0x2a1000, 1, RI_ALL_ONLINE },
+ { 0x2a9000, 1, RI_E1H_ONLINE }, { 0x2b8000, 1, RI_ALL_ONLINE },
+ { 0x2b8040, 1, RI_ALL_ONLINE }, { 0x2b8080, 1, RI_ALL_ONLINE },
+ { 0x2b80c0, 1, RI_ALL_ONLINE }, { 0x300104, 1, RI_ALL_ONLINE },
+ { 0x300114, 1, RI_ALL_ONLINE }, { 0x300124, 1, RI_ALL_ONLINE },
+ { 0x300134, 1, RI_ALL_ONLINE }, { 0x30026c, 1, RI_ALL_ONLINE },
+ { 0x3002a0, 1, RI_ALL_ONLINE }, { 0x321000, 1, RI_ALL_ONLINE },
+ { 0x328960, 1, RI_E1H_ONLINE }, { 0x338000, 1, RI_ALL_ONLINE },
+ { 0x338040, 1, RI_ALL_ONLINE }, { 0x338080, 1, RI_ALL_ONLINE },
+ { 0x3380c0, 1, RI_ALL_ONLINE }
};
+#define WREGS_COUNT_E1 1
static const u32 read_reg_e1_0[] = { 0x1b1000 };
-#define WREGS_COUNT_E1 1
static const struct wreg_addr wreg_addrs_e1[WREGS_COUNT_E1] = {
{ 0x1b0c00, 192, 1, read_reg_e1_0, RI_E1_OFFLINE }
};
+
+#define WREGS_COUNT_E1H 1
static const u32 read_reg_e1h_0[] = { 0x1b1040, 0x1b1000 };
-#define WREGS_COUNT_E1H 1
static const struct wreg_addr wreg_addrs_e1h[WREGS_COUNT_E1H] = {
{ 0x1b0c00, 256, 2, read_reg_e1h_0, RI_E1H_OFFLINE }
};
@@ -512,15 +517,18 @@ static const struct wreg_addr wreg_addrs_e1h[WREGS_COUNT_E1H] = {
static const struct dump_sign dump_sign_all = { 0x49aa93ee, 0x40835, 0x22 };
-#define TIMER_REGS_COUNT_E1 2
+#define TIMER_REGS_COUNT_E1 2
static const u32 timer_status_regs_e1[TIMER_REGS_COUNT_E1] =
{ 0x164014, 0x164018 };
static const u32 timer_scan_regs_e1[TIMER_REGS_COUNT_E1] =
{ 0x1640d0, 0x1640d4 };
-#define TIMER_REGS_COUNT_E1H 2
+
+#define TIMER_REGS_COUNT_E1H 2
static const u32 timer_status_regs_e1h[TIMER_REGS_COUNT_E1H] =
{ 0x164014, 0x164018 };
static const u32 timer_scan_regs_e1h[TIMER_REGS_COUNT_E1H] =
{ 0x1640d0, 0x1640d4 };
+
+#endif /* BNX2X_DUMP_H */
diff --git a/drivers/net/bnx2x_fw_defs.h b/drivers/net/bnx2x_fw_defs.h
index e2df2380359..931dcace562 100644
--- a/drivers/net/bnx2x_fw_defs.h
+++ b/drivers/net/bnx2x_fw_defs.h
@@ -12,48 +12,117 @@
(IS_E1H_OFFSET ? 0x7000 : 0x1000)
#define CSTORM_ASSERT_LIST_OFFSET(idx) \
(IS_E1H_OFFSET ? (0x7020 + (idx * 0x10)) : (0x1020 + (idx * 0x10)))
-#define CSTORM_DEF_SB_HC_DISABLE_OFFSET(function, index) \
- (IS_E1H_OFFSET ? (0x8522 + ((function>>1) * 0x40) + \
- ((function&1) * 0x100) + (index * 0x4)) : (0x1922 + (function * \
+#define CSTORM_DEF_SB_HC_DISABLE_C_OFFSET(function, index) \
+ (IS_E1H_OFFSET ? (0x8622 + ((function>>1) * 0x40) + \
+ ((function&1) * 0x100) + (index * 0x4)) : (0x3562 + (function * \
0x40) + (index * 0x4)))
-#define CSTORM_DEF_SB_HOST_SB_ADDR_OFFSET(function) \
- (IS_E1H_OFFSET ? (0x8500 + ((function>>1) * 0x40) + \
- ((function&1) * 0x100)) : (0x1900 + (function * 0x40)))
-#define CSTORM_DEF_SB_HOST_STATUS_BLOCK_OFFSET(function) \
- (IS_E1H_OFFSET ? (0x8508 + ((function>>1) * 0x40) + \
- ((function&1) * 0x100)) : (0x1908 + (function * 0x40)))
+#define CSTORM_DEF_SB_HC_DISABLE_U_OFFSET(function, index) \
+ (IS_E1H_OFFSET ? (0x8822 + ((function>>1) * 0x80) + \
+ ((function&1) * 0x200) + (index * 0x4)) : (0x35e2 + (function * \
+ 0x80) + (index * 0x4)))
+#define CSTORM_DEF_SB_HOST_SB_ADDR_C_OFFSET(function) \
+ (IS_E1H_OFFSET ? (0x8600 + ((function>>1) * 0x40) + \
+ ((function&1) * 0x100)) : (0x3540 + (function * 0x40)))
+#define CSTORM_DEF_SB_HOST_SB_ADDR_U_OFFSET(function) \
+ (IS_E1H_OFFSET ? (0x8800 + ((function>>1) * 0x80) + \
+ ((function&1) * 0x200)) : (0x35c0 + (function * 0x80)))
+#define CSTORM_DEF_SB_HOST_STATUS_BLOCK_C_OFFSET(function) \
+ (IS_E1H_OFFSET ? (0x8608 + ((function>>1) * 0x40) + \
+ ((function&1) * 0x100)) : (0x3548 + (function * 0x40)))
+#define CSTORM_DEF_SB_HOST_STATUS_BLOCK_U_OFFSET(function) \
+ (IS_E1H_OFFSET ? (0x8808 + ((function>>1) * 0x80) + \
+ ((function&1) * 0x200)) : (0x35c8 + (function * 0x80)))
#define CSTORM_FUNCTION_MODE_OFFSET \
(IS_E1H_OFFSET ? 0x11e8 : 0xffffffff)
-#define CSTORM_HC_BTR_OFFSET(port) \
- (IS_E1H_OFFSET ? (0x8704 + (port * 0xf0)) : (0x1984 + (port * 0xc0)))
-#define CSTORM_SB_HC_DISABLE_OFFSET(port, cpu_id, index) \
- (IS_E1H_OFFSET ? (0x801a + (port * 0x280) + (cpu_id * 0x28) + \
- (index * 0x4)) : (0x141a + (port * 0x280) + (cpu_id * 0x28) + \
+#define CSTORM_HC_BTR_C_OFFSET(port) \
+ (IS_E1H_OFFSET ? (0x8c04 + (port * 0xf0)) : (0x36c4 + (port * 0xc0)))
+#define CSTORM_HC_BTR_U_OFFSET(port) \
+ (IS_E1H_OFFSET ? (0x8de4 + (port * 0xf0)) : (0x3844 + (port * 0xc0)))
+#define CSTORM_ISCSI_CQ_SIZE_OFFSET(function) \
+ (IS_E1H_OFFSET ? (0x6680 + (function * 0x8)) : (0x25a0 + \
+ (function * 0x8)))
+#define CSTORM_ISCSI_CQ_SQN_SIZE_OFFSET(function) \
+ (IS_E1H_OFFSET ? (0x66c0 + (function * 0x8)) : (0x25b0 + \
+ (function * 0x8)))
+#define CSTORM_ISCSI_EQ_CONS_OFFSET(function, eqIdx) \
+ (IS_E1H_OFFSET ? (0x6040 + (function * 0xc0) + (eqIdx * 0x18)) : \
+ (0x2410 + (function * 0xc0) + (eqIdx * 0x18)))
+#define CSTORM_ISCSI_EQ_NEXT_EQE_ADDR_OFFSET(function, eqIdx) \
+ (IS_E1H_OFFSET ? (0x6044 + (function * 0xc0) + (eqIdx * 0x18)) : \
+ (0x2414 + (function * 0xc0) + (eqIdx * 0x18)))
+#define CSTORM_ISCSI_EQ_NEXT_PAGE_ADDR_OFFSET(function, eqIdx) \
+ (IS_E1H_OFFSET ? (0x604c + (function * 0xc0) + (eqIdx * 0x18)) : \
+ (0x241c + (function * 0xc0) + (eqIdx * 0x18)))
+#define CSTORM_ISCSI_EQ_NEXT_PAGE_ADDR_VALID_OFFSET(function, eqIdx) \
+ (IS_E1H_OFFSET ? (0x6057 + (function * 0xc0) + (eqIdx * 0x18)) : \
+ (0x2427 + (function * 0xc0) + (eqIdx * 0x18)))
+#define CSTORM_ISCSI_EQ_PROD_OFFSET(function, eqIdx) \
+ (IS_E1H_OFFSET ? (0x6042 + (function * 0xc0) + (eqIdx * 0x18)) : \
+ (0x2412 + (function * 0xc0) + (eqIdx * 0x18)))
+#define CSTORM_ISCSI_EQ_SB_INDEX_OFFSET(function, eqIdx) \
+ (IS_E1H_OFFSET ? (0x6056 + (function * 0xc0) + (eqIdx * 0x18)) : \
+ (0x2426 + (function * 0xc0) + (eqIdx * 0x18)))
+#define CSTORM_ISCSI_EQ_SB_NUM_OFFSET(function, eqIdx) \
+ (IS_E1H_OFFSET ? (0x6054 + (function * 0xc0) + (eqIdx * 0x18)) : \
+ (0x2424 + (function * 0xc0) + (eqIdx * 0x18)))
+#define CSTORM_ISCSI_HQ_SIZE_OFFSET(function) \
+ (IS_E1H_OFFSET ? (0x6640 + (function * 0x8)) : (0x2590 + \
+ (function * 0x8)))
+#define CSTORM_ISCSI_NUM_OF_TASKS_OFFSET(function) \
+ (IS_E1H_OFFSET ? (0x6004 + (function * 0x8)) : (0x2404 + \
+ (function * 0x8)))
+#define CSTORM_ISCSI_PAGE_SIZE_LOG_OFFSET(function) \
+ (IS_E1H_OFFSET ? (0x6002 + (function * 0x8)) : (0x2402 + \
+ (function * 0x8)))
+#define CSTORM_ISCSI_PAGE_SIZE_OFFSET(function) \
+ (IS_E1H_OFFSET ? (0x6000 + (function * 0x8)) : (0x2400 + \
+ (function * 0x8)))
+#define CSTORM_SB_HC_DISABLE_C_OFFSET(port, cpu_id, index) \
+ (IS_E1H_OFFSET ? (0x811a + (port * 0x280) + (cpu_id * 0x28) + \
+ (index * 0x4)) : (0x305a + (port * 0x280) + (cpu_id * 0x28) + \
+ (index * 0x4)))
+#define CSTORM_SB_HC_DISABLE_U_OFFSET(port, cpu_id, index) \
+ (IS_E1H_OFFSET ? (0xb01a + (port * 0x800) + (cpu_id * 0x80) + \
+ (index * 0x4)) : (0x401a + (port * 0x800) + (cpu_id * 0x80) + \
(index * 0x4)))
-#define CSTORM_SB_HC_TIMEOUT_OFFSET(port, cpu_id, index) \
- (IS_E1H_OFFSET ? (0x8018 + (port * 0x280) + (cpu_id * 0x28) + \
- (index * 0x4)) : (0x1418 + (port * 0x280) + (cpu_id * 0x28) + \
+#define CSTORM_SB_HC_TIMEOUT_C_OFFSET(port, cpu_id, index) \
+ (IS_E1H_OFFSET ? (0x8118 + (port * 0x280) + (cpu_id * 0x28) + \
+ (index * 0x4)) : (0x3058 + (port * 0x280) + (cpu_id * 0x28) + \
(index * 0x4)))
-#define CSTORM_SB_HOST_SB_ADDR_OFFSET(port, cpu_id) \
- (IS_E1H_OFFSET ? (0x8000 + (port * 0x280) + (cpu_id * 0x28)) : \
- (0x1400 + (port * 0x280) + (cpu_id * 0x28)))
-#define CSTORM_SB_HOST_STATUS_BLOCK_OFFSET(port, cpu_id) \
- (IS_E1H_OFFSET ? (0x8008 + (port * 0x280) + (cpu_id * 0x28)) : \
- (0x1408 + (port * 0x280) + (cpu_id * 0x28)))
+#define CSTORM_SB_HC_TIMEOUT_U_OFFSET(port, cpu_id, index) \
+ (IS_E1H_OFFSET ? (0xb018 + (port * 0x800) + (cpu_id * 0x80) + \
+ (index * 0x4)) : (0x4018 + (port * 0x800) + (cpu_id * 0x80) + \
+ (index * 0x4)))
+#define CSTORM_SB_HOST_SB_ADDR_C_OFFSET(port, cpu_id) \
+ (IS_E1H_OFFSET ? (0x8100 + (port * 0x280) + (cpu_id * 0x28)) : \
+ (0x3040 + (port * 0x280) + (cpu_id * 0x28)))
+#define CSTORM_SB_HOST_SB_ADDR_U_OFFSET(port, cpu_id) \
+ (IS_E1H_OFFSET ? (0xb000 + (port * 0x800) + (cpu_id * 0x80)) : \
+ (0x4000 + (port * 0x800) + (cpu_id * 0x80)))
+#define CSTORM_SB_HOST_STATUS_BLOCK_C_OFFSET(port, cpu_id) \
+ (IS_E1H_OFFSET ? (0x8108 + (port * 0x280) + (cpu_id * 0x28)) : \
+ (0x3048 + (port * 0x280) + (cpu_id * 0x28)))
+#define CSTORM_SB_HOST_STATUS_BLOCK_U_OFFSET(port, cpu_id) \
+ (IS_E1H_OFFSET ? (0xb008 + (port * 0x800) + (cpu_id * 0x80)) : \
+ (0x4008 + (port * 0x800) + (cpu_id * 0x80)))
+#define CSTORM_SB_STATUS_BLOCK_C_SIZE 0x10
+#define CSTORM_SB_STATUS_BLOCK_U_SIZE 0x60
#define CSTORM_STATS_FLAGS_OFFSET(function) \
(IS_E1H_OFFSET ? (0x1108 + (function * 0x8)) : (0x5108 + \
(function * 0x8)))
#define TSTORM_APPROXIMATE_MATCH_MULTICAST_FILTERING_OFFSET(function) \
- (IS_E1H_OFFSET ? (0x31c0 + (function * 0x20)) : 0xffffffff)
+ (IS_E1H_OFFSET ? (0x3200 + (function * 0x20)) : 0xffffffff)
#define TSTORM_ASSERT_LIST_INDEX_OFFSET \
(IS_E1H_OFFSET ? 0xa000 : 0x1000)
#define TSTORM_ASSERT_LIST_OFFSET(idx) \
(IS_E1H_OFFSET ? (0xa020 + (idx * 0x10)) : (0x1020 + (idx * 0x10)))
#define TSTORM_CLIENT_CONFIG_OFFSET(port, client_id) \
- (IS_E1H_OFFSET ? (0x3350 + (port * 0x190) + (client_id * 0x10)) \
- : (0x9c0 + (port * 0x130) + (client_id * 0x10)))
+ (IS_E1H_OFFSET ? (0x33a0 + (port * 0x1a0) + (client_id * 0x10)) \
+ : (0x9c0 + (port * 0x120) + (client_id * 0x10)))
#define TSTORM_COMMON_SAFC_WORKAROUND_ENABLE_OFFSET \
- (IS_E1H_OFFSET ? 0x1ad8 : 0xffffffff)
+ (IS_E1H_OFFSET ? 0x1ed8 : 0xffffffff)
+#define TSTORM_COMMON_SAFC_WORKAROUND_TIMEOUT_10USEC_OFFSET \
+ (IS_E1H_OFFSET ? 0x1eda : 0xffffffff)
#define TSTORM_DEF_SB_HC_DISABLE_OFFSET(function, index) \
(IS_E1H_OFFSET ? (0xb01a + ((function>>1) * 0x28) + \
((function&1) * 0xa0) + (index * 0x4)) : (0x141a + (function * \
@@ -65,95 +134,133 @@
(IS_E1H_OFFSET ? (0xb008 + ((function>>1) * 0x28) + \
((function&1) * 0xa0)) : (0x1408 + (function * 0x28)))
#define TSTORM_ETH_STATS_QUERY_ADDR_OFFSET(function) \
- (IS_E1H_OFFSET ? (0x2b80 + (function * 0x8)) : (0x4b68 + \
+ (IS_E1H_OFFSET ? (0x2940 + (function * 0x8)) : (0x4928 + \
(function * 0x8)))
#define TSTORM_FUNCTION_COMMON_CONFIG_OFFSET(function) \
- (IS_E1H_OFFSET ? (0x3000 + (function * 0x38)) : (0x1500 + \
- (function * 0x38)))
+ (IS_E1H_OFFSET ? (0x3000 + (function * 0x40)) : (0x1500 + \
+ (function * 0x40)))
#define TSTORM_FUNCTION_MODE_OFFSET \
- (IS_E1H_OFFSET ? 0x1ad0 : 0xffffffff)
+ (IS_E1H_OFFSET ? 0x1ed0 : 0xffffffff)
#define TSTORM_HC_BTR_OFFSET(port) \
(IS_E1H_OFFSET ? (0xb144 + (port * 0x30)) : (0x1454 + (port * 0x18)))
#define TSTORM_INDIRECTION_TABLE_OFFSET(function) \
(IS_E1H_OFFSET ? (0x12c8 + (function * 0x80)) : (0x22c8 + \
(function * 0x80)))
#define TSTORM_INDIRECTION_TABLE_SIZE 0x80
+#define TSTORM_ISCSI_CONN_BUF_PBL_OFFSET(function, pblEntry) \
+ (IS_E1H_OFFSET ? (0x60c0 + (function * 0x40) + (pblEntry * 0x8)) \
+ : (0x4c30 + (function * 0x40) + (pblEntry * 0x8)))
+#define TSTORM_ISCSI_ERROR_BITMAP_OFFSET(function) \
+ (IS_E1H_OFFSET ? (0x6340 + (function * 0x8)) : (0x4cd0 + \
+ (function * 0x8)))
+#define TSTORM_ISCSI_NUM_OF_TASKS_OFFSET(function) \
+ (IS_E1H_OFFSET ? (0x6004 + (function * 0x8)) : (0x4c04 + \
+ (function * 0x8)))
+#define TSTORM_ISCSI_PAGE_SIZE_LOG_OFFSET(function) \
+ (IS_E1H_OFFSET ? (0x6002 + (function * 0x8)) : (0x4c02 + \
+ (function * 0x8)))
+#define TSTORM_ISCSI_PAGE_SIZE_OFFSET(function) \
+ (IS_E1H_OFFSET ? (0x6000 + (function * 0x8)) : (0x4c00 + \
+ (function * 0x8)))
+#define TSTORM_ISCSI_RQ_SIZE_OFFSET(function) \
+ (IS_E1H_OFFSET ? (0x6080 + (function * 0x8)) : (0x4c20 + \
+ (function * 0x8)))
+#define TSTORM_ISCSI_TCP_VARS_FLAGS_OFFSET(function) \
+ (IS_E1H_OFFSET ? (0x6040 + (function * 0x8)) : (0x4c10 + \
+ (function * 0x8)))
+#define TSTORM_ISCSI_TCP_VARS_LSB_LOCAL_MAC_ADDR_OFFSET(function) \
+ (IS_E1H_OFFSET ? (0x6042 + (function * 0x8)) : (0x4c12 + \
+ (function * 0x8)))
+#define TSTORM_ISCSI_TCP_VARS_MSB_LOCAL_MAC_ADDR_OFFSET(function) \
+ (IS_E1H_OFFSET ? (0x6044 + (function * 0x8)) : (0x4c14 + \
+ (function * 0x8)))
#define TSTORM_MAC_FILTER_CONFIG_OFFSET(function) \
- (IS_E1H_OFFSET ? (0x3008 + (function * 0x38)) : (0x1508 + \
- (function * 0x38)))
+ (IS_E1H_OFFSET ? (0x3008 + (function * 0x40)) : (0x1508 + \
+ (function * 0x40)))
#define TSTORM_PER_COUNTER_ID_STATS_OFFSET(port, stats_counter_id) \
- (IS_E1H_OFFSET ? (0x2010 + (port * 0x5b0) + (stats_counter_id * \
- 0x50)) : (0x4080 + (port * 0x5b0) + (stats_counter_id * 0x50)))
+ (IS_E1H_OFFSET ? (0x2010 + (port * 0x490) + (stats_counter_id * \
+ 0x40)) : (0x4010 + (port * 0x490) + (stats_counter_id * 0x40)))
#define TSTORM_STATS_FLAGS_OFFSET(function) \
- (IS_E1H_OFFSET ? (0x2c00 + (function * 0x8)) : (0x4b88 + \
+ (IS_E1H_OFFSET ? (0x29c0 + (function * 0x8)) : (0x4948 + \
(function * 0x8)))
-#define TSTORM_TPA_EXIST_OFFSET (IS_E1H_OFFSET ? 0x3680 : 0x1c20)
-#define USTORM_AGG_DATA_OFFSET (IS_E1H_OFFSET ? 0xa040 : 0x2c10)
-#define USTORM_AGG_DATA_SIZE (IS_E1H_OFFSET ? 0x2440 : 0x1200)
+#define TSTORM_TCP_MAX_CWND_OFFSET(function) \
+ (IS_E1H_OFFSET ? (0x4004 + (function * 0x8)) : (0x1fb4 + \
+ (function * 0x8)))
+#define USTORM_AGG_DATA_OFFSET (IS_E1H_OFFSET ? 0xa000 : 0x3000)
+#define USTORM_AGG_DATA_SIZE (IS_E1H_OFFSET ? 0x2000 : 0x1000)
#define USTORM_ASSERT_LIST_INDEX_OFFSET \
- (IS_E1H_OFFSET ? 0x8960 : 0x1000)
+ (IS_E1H_OFFSET ? 0x8000 : 0x1000)
#define USTORM_ASSERT_LIST_OFFSET(idx) \
- (IS_E1H_OFFSET ? (0x8980 + (idx * 0x10)) : (0x1020 + (idx * 0x10)))
+ (IS_E1H_OFFSET ? (0x8020 + (idx * 0x10)) : (0x1020 + (idx * 0x10)))
#define USTORM_CQE_PAGE_BASE_OFFSET(port, clientId) \
- (IS_E1H_OFFSET ? (0x8018 + (port * 0x4b0) + (clientId * 0x30)) : \
- (0x5330 + (port * 0x260) + (clientId * 0x20)))
-#define USTORM_DEF_SB_HC_DISABLE_OFFSET(function, index) \
- (IS_E1H_OFFSET ? (0x9522 + ((function>>1) * 0x40) + \
- ((function&1) * 0x100) + (index * 0x4)) : (0x1922 + (function * \
- 0x40) + (index * 0x4)))
-#define USTORM_DEF_SB_HOST_SB_ADDR_OFFSET(function) \
- (IS_E1H_OFFSET ? (0x9500 + ((function>>1) * 0x40) + \
- ((function&1) * 0x100)) : (0x1900 + (function * 0x40)))
-#define USTORM_DEF_SB_HOST_STATUS_BLOCK_OFFSET(function) \
- (IS_E1H_OFFSET ? (0x9508 + ((function>>1) * 0x40) + \
- ((function&1) * 0x100)) : (0x1908 + (function * 0x40)))
+ (IS_E1H_OFFSET ? (0x1010 + (port * 0x680) + (clientId * 0x40)) : \
+ (0x4010 + (port * 0x360) + (clientId * 0x30)))
+#define USTORM_CQE_PAGE_NEXT_OFFSET(port, clientId) \
+ (IS_E1H_OFFSET ? (0x1028 + (port * 0x680) + (clientId * 0x40)) : \
+ (0x4028 + (port * 0x360) + (clientId * 0x30)))
+#define USTORM_ETH_PAUSE_ENABLED_OFFSET(port) \
+ (IS_E1H_OFFSET ? (0x2ad4 + (port * 0x8)) : 0xffffffff)
#define USTORM_ETH_RING_PAUSE_DATA_OFFSET(port, clientId) \
- (IS_E1H_OFFSET ? (0x8020 + (port * 0x4b0) + (clientId * 0x30)) : \
+ (IS_E1H_OFFSET ? (0x1030 + (port * 0x680) + (clientId * 0x40)) : \
0xffffffff)
#define USTORM_ETH_STATS_QUERY_ADDR_OFFSET(function) \
- (IS_E1H_OFFSET ? (0x2a50 + (function * 0x8)) : (0x1d98 + \
+ (IS_E1H_OFFSET ? (0x2a50 + (function * 0x8)) : (0x1dd0 + \
(function * 0x8)))
#define USTORM_FUNCTION_MODE_OFFSET \
(IS_E1H_OFFSET ? 0x2448 : 0xffffffff)
-#define USTORM_HC_BTR_OFFSET(port) \
- (IS_E1H_OFFSET ? (0x9704 + (port * 0xf0)) : (0x1984 + (port * 0xc0)))
+#define USTORM_ISCSI_CQ_SIZE_OFFSET(function) \
+ (IS_E1H_OFFSET ? (0x7044 + (function * 0x8)) : (0x2414 + \
+ (function * 0x8)))
+#define USTORM_ISCSI_CQ_SQN_SIZE_OFFSET(function) \
+ (IS_E1H_OFFSET ? (0x7046 + (function * 0x8)) : (0x2416 + \
+ (function * 0x8)))
+#define USTORM_ISCSI_ERROR_BITMAP_OFFSET(function) \
+ (IS_E1H_OFFSET ? (0x7688 + (function * 0x8)) : (0x29c8 + \
+ (function * 0x8)))
+#define USTORM_ISCSI_GLOBAL_BUF_PHYS_ADDR_OFFSET(function) \
+ (IS_E1H_OFFSET ? (0x7648 + (function * 0x8)) : (0x29b8 + \
+ (function * 0x8)))
+#define USTORM_ISCSI_NUM_OF_TASKS_OFFSET(function) \
+ (IS_E1H_OFFSET ? (0x7004 + (function * 0x8)) : (0x2404 + \
+ (function * 0x8)))
+#define USTORM_ISCSI_PAGE_SIZE_LOG_OFFSET(function) \
+ (IS_E1H_OFFSET ? (0x7002 + (function * 0x8)) : (0x2402 + \
+ (function * 0x8)))
+#define USTORM_ISCSI_PAGE_SIZE_OFFSET(function) \
+ (IS_E1H_OFFSET ? (0x7000 + (function * 0x8)) : (0x2400 + \
+ (function * 0x8)))
+#define USTORM_ISCSI_R2TQ_SIZE_OFFSET(function) \
+ (IS_E1H_OFFSET ? (0x7040 + (function * 0x8)) : (0x2410 + \
+ (function * 0x8)))
+#define USTORM_ISCSI_RQ_BUFFER_SIZE_OFFSET(function) \
+ (IS_E1H_OFFSET ? (0x7080 + (function * 0x8)) : (0x2420 + \
+ (function * 0x8)))
+#define USTORM_ISCSI_RQ_SIZE_OFFSET(function) \
+ (IS_E1H_OFFSET ? (0x7084 + (function * 0x8)) : (0x2424 + \
+ (function * 0x8)))
#define USTORM_MAX_AGG_SIZE_OFFSET(port, clientId) \
- (IS_E1H_OFFSET ? (0x8010 + (port * 0x4b0) + (clientId * 0x30)) : \
- (0x5328 + (port * 0x260) + (clientId * 0x20)))
+ (IS_E1H_OFFSET ? (0x1018 + (port * 0x680) + (clientId * 0x40)) : \
+ (0x4018 + (port * 0x360) + (clientId * 0x30)))
#define USTORM_MEM_WORKAROUND_ADDRESS_OFFSET(function) \
- (IS_E1H_OFFSET ? (0x2408 + (function * 0x8)) : (0x5308 + \
+ (IS_E1H_OFFSET ? (0x2408 + (function * 0x8)) : (0x1da8 + \
(function * 0x8)))
-#define USTORM_PAUSE_ENABLED_OFFSET(port) \
- (IS_E1H_OFFSET ? (0x2ad4 + (port * 0x8)) : 0xffffffff)
#define USTORM_PER_COUNTER_ID_STATS_OFFSET(port, stats_counter_id) \
(IS_E1H_OFFSET ? (0x2450 + (port * 0x2d0) + (stats_counter_id * \
- 0x28)) : (0x4740 + (port * 0x2d0) + (stats_counter_id * 0x28)))
+ 0x28)) : (0x1500 + (port * 0x2d0) + (stats_counter_id * 0x28)))
#define USTORM_RX_PRODS_OFFSET(port, client_id) \
- (IS_E1H_OFFSET ? (0x8000 + (port * 0x4b0) + (client_id * 0x30)) \
- : (0x5318 + (port * 0x260) + (client_id * 0x20)))
-#define USTORM_SB_HC_DISABLE_OFFSET(port, cpu_id, index) \
- (IS_E1H_OFFSET ? (0x901a + (port * 0x280) + (cpu_id * 0x28) + \
- (index * 0x4)) : (0x141a + (port * 0x280) + (cpu_id * 0x28) + \
- (index * 0x4)))
-#define USTORM_SB_HC_TIMEOUT_OFFSET(port, cpu_id, index) \
- (IS_E1H_OFFSET ? (0x9018 + (port * 0x280) + (cpu_id * 0x28) + \
- (index * 0x4)) : (0x1418 + (port * 0x280) + (cpu_id * 0x28) + \
- (index * 0x4)))
-#define USTORM_SB_HOST_SB_ADDR_OFFSET(port, cpu_id) \
- (IS_E1H_OFFSET ? (0x9000 + (port * 0x280) + (cpu_id * 0x28)) : \
- (0x1400 + (port * 0x280) + (cpu_id * 0x28)))
-#define USTORM_SB_HOST_STATUS_BLOCK_OFFSET(port, cpu_id) \
- (IS_E1H_OFFSET ? (0x9008 + (port * 0x280) + (cpu_id * 0x28)) : \
- (0x1408 + (port * 0x280) + (cpu_id * 0x28)))
+ (IS_E1H_OFFSET ? (0x1000 + (port * 0x680) + (client_id * 0x40)) \
+ : (0x4000 + (port * 0x360) + (client_id * 0x30)))
#define USTORM_STATS_FLAGS_OFFSET(function) \
- (IS_E1H_OFFSET ? (0x29f0 + (function * 0x8)) : (0x1d80 + \
+ (IS_E1H_OFFSET ? (0x29f0 + (function * 0x8)) : (0x1db8 + \
(function * 0x8)))
+#define USTORM_TPA_BTR_OFFSET (IS_E1H_OFFSET ? 0x3da5 : 0x5095)
+#define USTORM_TPA_BTR_SIZE 0x1
#define XSTORM_ASSERT_LIST_INDEX_OFFSET \
(IS_E1H_OFFSET ? 0x9000 : 0x1000)
#define XSTORM_ASSERT_LIST_OFFSET(idx) \
(IS_E1H_OFFSET ? (0x9020 + (idx * 0x10)) : (0x1020 + (idx * 0x10)))
#define XSTORM_CMNG_PER_PORT_VARS_OFFSET(port) \
- (IS_E1H_OFFSET ? (0x24a8 + (port * 0x50)) : (0x3ba0 + (port * 0x50)))
+ (IS_E1H_OFFSET ? (0x24a8 + (port * 0x50)) : (0x3a80 + (port * 0x50)))
#define XSTORM_DEF_SB_HC_DISABLE_OFFSET(function, index) \
(IS_E1H_OFFSET ? (0xa01a + ((function>>1) * 0x28) + \
((function&1) * 0xa0) + (index * 0x4)) : (0x141a + (function * \
@@ -165,22 +272,73 @@
(IS_E1H_OFFSET ? (0xa008 + ((function>>1) * 0x28) + \
((function&1) * 0xa0)) : (0x1408 + (function * 0x28)))
#define XSTORM_E1HOV_OFFSET(function) \
- (IS_E1H_OFFSET ? (0x2c10 + (function * 0x2)) : 0xffffffff)
+ (IS_E1H_OFFSET ? (0x2c10 + (function * 0x8)) : 0xffffffff)
#define XSTORM_ETH_STATS_QUERY_ADDR_OFFSET(function) \
- (IS_E1H_OFFSET ? (0x2418 + (function * 0x8)) : (0x3b70 + \
+ (IS_E1H_OFFSET ? (0x2418 + (function * 0x8)) : (0x3a50 + \
(function * 0x8)))
#define XSTORM_FAIRNESS_PER_VN_VARS_OFFSET(function) \
- (IS_E1H_OFFSET ? (0x2588 + (function * 0x90)) : (0x3c80 + \
+ (IS_E1H_OFFSET ? (0x2588 + (function * 0x90)) : (0x3b60 + \
(function * 0x90)))
#define XSTORM_FUNCTION_MODE_OFFSET \
- (IS_E1H_OFFSET ? 0x2c20 : 0xffffffff)
+ (IS_E1H_OFFSET ? 0x2c50 : 0xffffffff)
#define XSTORM_HC_BTR_OFFSET(port) \
(IS_E1H_OFFSET ? (0xa144 + (port * 0x30)) : (0x1454 + (port * 0x18)))
+#define XSTORM_ISCSI_HQ_SIZE_OFFSET(function) \
+ (IS_E1H_OFFSET ? (0x80c0 + (function * 0x8)) : (0x1c30 + \
+ (function * 0x8)))
+#define XSTORM_ISCSI_LOCAL_MAC_ADDR0_OFFSET(function) \
+ (IS_E1H_OFFSET ? (0x8080 + (function * 0x8)) : (0x1c20 + \
+ (function * 0x8)))
+#define XSTORM_ISCSI_LOCAL_MAC_ADDR1_OFFSET(function) \
+ (IS_E1H_OFFSET ? (0x8081 + (function * 0x8)) : (0x1c21 + \
+ (function * 0x8)))
+#define XSTORM_ISCSI_LOCAL_MAC_ADDR2_OFFSET(function) \
+ (IS_E1H_OFFSET ? (0x8082 + (function * 0x8)) : (0x1c22 + \
+ (function * 0x8)))
+#define XSTORM_ISCSI_LOCAL_MAC_ADDR3_OFFSET(function) \
+ (IS_E1H_OFFSET ? (0x8083 + (function * 0x8)) : (0x1c23 + \
+ (function * 0x8)))
+#define XSTORM_ISCSI_LOCAL_MAC_ADDR4_OFFSET(function) \
+ (IS_E1H_OFFSET ? (0x8084 + (function * 0x8)) : (0x1c24 + \
+ (function * 0x8)))
+#define XSTORM_ISCSI_LOCAL_MAC_ADDR5_OFFSET(function) \
+ (IS_E1H_OFFSET ? (0x8085 + (function * 0x8)) : (0x1c25 + \
+ (function * 0x8)))
+#define XSTORM_ISCSI_LOCAL_VLAN_OFFSET(function) \
+ (IS_E1H_OFFSET ? (0x8086 + (function * 0x8)) : (0x1c26 + \
+ (function * 0x8)))
+#define XSTORM_ISCSI_NUM_OF_TASKS_OFFSET(function) \
+ (IS_E1H_OFFSET ? (0x8004 + (function * 0x8)) : (0x1c04 + \
+ (function * 0x8)))
+#define XSTORM_ISCSI_PAGE_SIZE_LOG_OFFSET(function) \
+ (IS_E1H_OFFSET ? (0x8002 + (function * 0x8)) : (0x1c02 + \
+ (function * 0x8)))
+#define XSTORM_ISCSI_PAGE_SIZE_OFFSET(function) \
+ (IS_E1H_OFFSET ? (0x8000 + (function * 0x8)) : (0x1c00 + \
+ (function * 0x8)))
+#define XSTORM_ISCSI_R2TQ_SIZE_OFFSET(function) \
+ (IS_E1H_OFFSET ? (0x80c4 + (function * 0x8)) : (0x1c34 + \
+ (function * 0x8)))
+#define XSTORM_ISCSI_SQ_SIZE_OFFSET(function) \
+ (IS_E1H_OFFSET ? (0x80c2 + (function * 0x8)) : (0x1c32 + \
+ (function * 0x8)))
+#define XSTORM_ISCSI_TCP_VARS_ADV_WND_SCL_OFFSET(function) \
+ (IS_E1H_OFFSET ? (0x8043 + (function * 0x8)) : (0x1c13 + \
+ (function * 0x8)))
+#define XSTORM_ISCSI_TCP_VARS_FLAGS_OFFSET(function) \
+ (IS_E1H_OFFSET ? (0x8042 + (function * 0x8)) : (0x1c12 + \
+ (function * 0x8)))
+#define XSTORM_ISCSI_TCP_VARS_TOS_OFFSET(function) \
+ (IS_E1H_OFFSET ? (0x8041 + (function * 0x8)) : (0x1c11 + \
+ (function * 0x8)))
+#define XSTORM_ISCSI_TCP_VARS_TTL_OFFSET(function) \
+ (IS_E1H_OFFSET ? (0x8040 + (function * 0x8)) : (0x1c10 + \
+ (function * 0x8)))
#define XSTORM_PER_COUNTER_ID_STATS_OFFSET(port, stats_counter_id) \
- (IS_E1H_OFFSET ? (0xc000 + (port * 0x3f0) + (stats_counter_id * \
- 0x38)) : (0x3378 + (port * 0x3f0) + (stats_counter_id * 0x38)))
+ (IS_E1H_OFFSET ? (0xc000 + (port * 0x360) + (stats_counter_id * \
+ 0x30)) : (0x3378 + (port * 0x360) + (stats_counter_id * 0x30)))
#define XSTORM_RATE_SHAPING_PER_VN_VARS_OFFSET(function) \
- (IS_E1H_OFFSET ? (0x2548 + (function * 0x90)) : (0x3c40 + \
+ (IS_E1H_OFFSET ? (0x2548 + (function * 0x90)) : (0x3b20 + \
(function * 0x90)))
#define XSTORM_SPQ_PAGE_BASE_OFFSET(function) \
(IS_E1H_OFFSET ? (0x2000 + (function * 0x10)) : (0x3328 + \
@@ -189,8 +347,15 @@
(IS_E1H_OFFSET ? (0x2008 + (function * 0x10)) : (0x3330 + \
(function * 0x10)))
#define XSTORM_STATS_FLAGS_OFFSET(function) \
- (IS_E1H_OFFSET ? (0x23d8 + (function * 0x8)) : (0x3b60 + \
+ (IS_E1H_OFFSET ? (0x23d8 + (function * 0x8)) : (0x3a40 + \
(function * 0x8)))
+#define XSTORM_TCP_GLOBAL_DEL_ACK_COUNTER_ENABLED_OFFSET(port) \
+ (IS_E1H_OFFSET ? (0x4000 + (port * 0x8)) : (0x1960 + (port * 0x8)))
+#define XSTORM_TCP_GLOBAL_DEL_ACK_COUNTER_MAX_COUNT_OFFSET(port) \
+ (IS_E1H_OFFSET ? (0x4001 + (port * 0x8)) : (0x1961 + (port * 0x8)))
+#define XSTORM_TCP_TX_SWS_TIMER_VAL_OFFSET(function) \
+ (IS_E1H_OFFSET ? (0x4060 + ((function>>1) * 0x8) + ((function&1) \
+ * 0x4)) : (0x1978 + (function * 0x4)))
#define COMMON_ASM_INVALID_ASSERT_OPCODE 0x0
/**
@@ -211,6 +376,9 @@
#define TCP_IPV4_HASH_TYPE 2
#define IPV6_HASH_TYPE 3
#define TCP_IPV6_HASH_TYPE 4
+#define VLAN_PRI_HASH_TYPE 5
+#define E1HOV_PRI_HASH_TYPE 6
+#define DSCP_HASH_TYPE 7
/* Ethernet Ring parameters */
@@ -218,30 +386,26 @@
#define FIRST_BD_IN_PKT 0
#define PARSE_BD_INDEX 1
#define NUM_OF_ETH_BDS_IN_PAGE ((PAGE_SIZE)/(STRUCT_SIZE(eth_tx_bd)/8))
-
+#define U_ETH_NUM_OF_SGES_TO_FETCH 8
+#define U_ETH_MAX_SGES_FOR_PACKET 3
/* Rx ring params */
-#define U_ETH_LOCAL_BD_RING_SIZE 16
-#define U_ETH_LOCAL_SGE_RING_SIZE 12
+#define U_ETH_LOCAL_BD_RING_SIZE 8
+#define U_ETH_LOCAL_SGE_RING_SIZE 10
#define U_ETH_SGL_SIZE 8
-#define U_ETH_BDS_PER_PAGE_MASK \
- ((PAGE_SIZE/(STRUCT_SIZE(eth_rx_bd)/8))-1)
-#define U_ETH_CQE_PER_PAGE_MASK \
- ((PAGE_SIZE/(STRUCT_SIZE(eth_rx_cqe)/8))-1)
-#define U_ETH_SGES_PER_PAGE_MASK \
- ((PAGE_SIZE/(STRUCT_SIZE(eth_rx_sge)/8))-1)
-
#define U_ETH_SGES_PER_PAGE_INVERSE_MASK \
(0xFFFF - ((PAGE_SIZE/((STRUCT_SIZE(eth_rx_sge))/8))-1))
-
-#define TU_ETH_CQES_PER_PAGE \
- (PAGE_SIZE/(STRUCT_SIZE(eth_rx_cqe_next_page)/8))
+#define TU_ETH_CQES_PER_PAGE (PAGE_SIZE/(STRUCT_SIZE(eth_rx_cqe)/8))
#define U_ETH_BDS_PER_PAGE (PAGE_SIZE/(STRUCT_SIZE(eth_rx_bd)/8))
#define U_ETH_SGES_PER_PAGE (PAGE_SIZE/(STRUCT_SIZE(eth_rx_sge)/8))
+#define U_ETH_BDS_PER_PAGE_MASK (U_ETH_BDS_PER_PAGE-1)
+#define U_ETH_CQE_PER_PAGE_MASK (TU_ETH_CQES_PER_PAGE-1)
+#define U_ETH_SGES_PER_PAGE_MASK (U_ETH_SGES_PER_PAGE-1)
+
#define U_ETH_UNDEFINED_Q 0xFF
/* values of command IDs in the ramrod message */
@@ -266,8 +430,8 @@
#define T_ETH_CRC32_HASH_SEED 0x00000000
/* Maximal L2 clients supported */
-#define ETH_MAX_RX_CLIENTS_E1 19
-#define ETH_MAX_RX_CLIENTS_E1H 25
+#define ETH_MAX_RX_CLIENTS_E1 18
+#define ETH_MAX_RX_CLIENTS_E1H 26
/* Maximal aggregation queues supported */
#define ETH_MAX_AGGREGATION_QUEUES_E1 32
@@ -276,6 +440,9 @@
/* ETH RSS modes */
#define ETH_RSS_MODE_DISABLED 0
#define ETH_RSS_MODE_REGULAR 1
+#define ETH_RSS_MODE_VLAN_PRI 2
+#define ETH_RSS_MODE_E1HOV_PRI 3
+#define ETH_RSS_MODE_IP_DSCP 4
/**
@@ -332,12 +499,14 @@
#define HC_INDEX_DEF_C_ETH_SLOW_PATH 3
#define HC_INDEX_DEF_C_ETH_RDMA_CQ_CONS 4
#define HC_INDEX_DEF_C_ETH_ISCSI_CQ_CONS 5
+#define HC_INDEX_DEF_C_ETH_FCOE_CQ_CONS 6
#define HC_INDEX_DEF_U_ETH_RDMA_RX_CQ_CONS 0
#define HC_INDEX_DEF_U_ETH_ISCSI_RX_CQ_CONS 1
#define HC_INDEX_DEF_U_ETH_RDMA_RX_BD_CONS 2
#define HC_INDEX_DEF_U_ETH_ISCSI_RX_BD_CONS 3
-
+#define HC_INDEX_DEF_U_ETH_FCOE_RX_CQ_CONS 4
+#define HC_INDEX_DEF_U_ETH_FCOE_RX_BD_CONS 5
/* used by the driver to get the SB offset */
#define USTORM_ID 0
diff --git a/drivers/net/bnx2x_hsi.h b/drivers/net/bnx2x_hsi.h
index 03c62421d99..8e2261fad48 100644
--- a/drivers/net/bnx2x_hsi.h
+++ b/drivers/net/bnx2x_hsi.h
@@ -91,6 +91,21 @@ struct shared_hw_cfg { /* NVRAM Offset */
#define SHARED_HW_CFG_HIDE_PORT1 0x00002000
+ /* The fan failure mechanism is usually related to the PHY type
+ since the power consumption of the board is determined by the PHY.
+ Currently, fan is required for most designs with SFX7101, BCM8727
+ and BCM8481. If a fan is not required for a board which uses one
+ of those PHYs, this field should be set to "Disabled". If a fan is
+ required for a different PHY type, this option should be set to
+ "Enabled".
+ The fan failure indication is expected on
+ SPIO5 */
+#define SHARED_HW_CFG_FAN_FAILURE_MASK 0x00180000
+#define SHARED_HW_CFG_FAN_FAILURE_SHIFT 19
+#define SHARED_HW_CFG_FAN_FAILURE_PHY_TYPE 0x00000000
+#define SHARED_HW_CFG_FAN_FAILURE_DISABLED 0x00080000
+#define SHARED_HW_CFG_FAN_FAILURE_ENABLED 0x00100000
+
u32 power_dissipated; /* 0x11c */
#define SHARED_HW_CFG_POWER_DIS_CMN_MASK 0xff000000
#define SHARED_HW_CFG_POWER_DIS_CMN_SHIFT 24
@@ -233,6 +248,8 @@ struct port_hw_cfg { /* port 0: 0x12c port 1: 0x2bc */
#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726 0x00000600
#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481 0x00000700
#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101 0x00000800
+#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727 0x00000900
+#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727_NOC 0x00000a00
#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE 0x0000fd00
#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN 0x0000ff00
@@ -343,10 +360,16 @@ struct port_feat_cfg { /* port 0: 0x454 port 1: 0x4c8 */
#define PORT_FEATURE_MBA_ENABLED 0x02000000
#define PORT_FEATURE_MFW_ENABLED 0x04000000
- /* Check the optic vendor via i2c before allowing it to be used by
- SW */
-#define PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_DISABLED 0x00000000
-#define PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_ENABLED 0x08000000
+ /* Reserved bits: 28-29 */
+ /* Check the optic vendor via i2c against a list of approved modules
+ in a separate nvram image */
+#define PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK 0xE0000000
+#define PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_SHIFT 29
+#define PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_NO_ENFORCEMENT 0x00000000
+#define PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_DISABLE_TX_LASER 0x20000000
+#define PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_WARNING_MSG 0x40000000
+#define PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_POWER_DOWN 0x60000000
+
u32 wol_config;
/* Default is used when driver sets to "auto" mode */
@@ -635,6 +658,8 @@ struct drv_func_mb {
#define DRV_MSG_CODE_UNLOAD_REQ_WOL_DIS 0x20010000
#define DRV_MSG_CODE_UNLOAD_REQ_WOL_MCP 0x20020000
#define DRV_MSG_CODE_UNLOAD_DONE 0x21000000
+#define DRV_MSG_CODE_DCC_OK 0x30000000
+#define DRV_MSG_CODE_DCC_FAILURE 0x31000000
#define DRV_MSG_CODE_DIAG_ENTER_REQ 0x50000000
#define DRV_MSG_CODE_DIAG_EXIT_REQ 0x60000000
#define DRV_MSG_CODE_VALIDATE_KEY 0x70000000
@@ -642,6 +667,12 @@ struct drv_func_mb {
#define DRV_MSG_CODE_GET_UPGRADE_KEY 0x81000000
#define DRV_MSG_CODE_GET_MANUF_KEY 0x82000000
#define DRV_MSG_CODE_LOAD_L2B_PRAM 0x90000000
+ /*
+ * The optic module verification commands requris bootcode
+ * v5.0.6 or later
+ */
+#define DRV_MSG_CODE_VRFY_OPT_MDL 0xa0000000
+#define REQ_BC_VER_4_VRFY_OPT_MDL 0x00050006
#define BIOS_MSG_CODE_LIC_CHALLENGE 0xff010000
#define BIOS_MSG_CODE_LIC_RESPONSE 0xff020000
@@ -663,6 +694,7 @@ struct drv_func_mb {
#define FW_MSG_CODE_DRV_UNLOAD_PORT 0x20110000
#define FW_MSG_CODE_DRV_UNLOAD_FUNCTION 0x20120000
#define FW_MSG_CODE_DRV_UNLOAD_DONE 0x21100000
+#define FW_MSG_CODE_DCC_DONE 0x30100000
#define FW_MSG_CODE_DIAG_ENTER_DONE 0x50100000
#define FW_MSG_CODE_DIAG_REFUSE 0x50200000
#define FW_MSG_CODE_DIAG_EXIT_DONE 0x60100000
@@ -676,6 +708,9 @@ struct drv_func_mb {
#define FW_MSG_CODE_L2B_PRAM_C_LOAD_FAILURE 0x90220000
#define FW_MSG_CODE_L2B_PRAM_X_LOAD_FAILURE 0x90230000
#define FW_MSG_CODE_L2B_PRAM_U_LOAD_FAILURE 0x90240000
+#define FW_MSG_CODE_VRFY_OPT_MDL_SUCCESS 0xa0100000
+#define FW_MSG_CODE_VRFY_OPT_MDL_INVLD_IMG 0xa0200000
+#define FW_MSG_CODE_VRFY_OPT_MDL_UNAPPROVED 0xa0300000
#define FW_MSG_CODE_LIC_CHALLENGE 0xff010000
#define FW_MSG_CODE_LIC_RESPONSE 0xff020000
@@ -710,6 +745,14 @@ struct drv_func_mb {
u32 drv_status;
#define DRV_STATUS_PMF 0x00000001
+#define DRV_STATUS_DCC_EVENT_MASK 0x0000ff00
+#define DRV_STATUS_DCC_DISABLE_ENABLE_PF 0x00000100
+#define DRV_STATUS_DCC_BANDWIDTH_ALLOCATION 0x00000200
+#define DRV_STATUS_DCC_CHANGE_MAC_ADDRESS 0x00000400
+#define DRV_STATUS_DCC_RESERVED1 0x00000800
+#define DRV_STATUS_DCC_SET_PROTOCOL 0x00001000
+#define DRV_STATUS_DCC_SET_PRIORITY 0x00002000
+
u32 virt_mac_upper;
#define VIRT_MAC_SIGN_MASK 0xffff0000
#define VIRT_MAC_SIGNATURE 0x564d0000
@@ -746,10 +789,9 @@ struct shared_mf_cfg {
struct port_mf_cfg {
u32 dynamic_cfg; /* device control channel */
-#define PORT_MF_CFG_OUTER_VLAN_TAG_MASK 0x0000ffff
-#define PORT_MF_CFG_OUTER_VLAN_TAG_SHIFT 0
-#define PORT_MF_CFG_DYNAMIC_CFG_ENABLED 0x00010000
-#define PORT_MF_CFG_DYNAMIC_CFG_DEFAULT 0x00000000
+#define PORT_MF_CFG_E1HOV_TAG_MASK 0x0000ffff
+#define PORT_MF_CFG_E1HOV_TAG_SHIFT 0
+#define PORT_MF_CFG_E1HOV_TAG_DEFAULT PORT_MF_CFG_E1HOV_TAG_MASK
u32 reserved[3];
@@ -853,6 +895,22 @@ struct shmem_region { /* SharedMem Offset (size) */
}; /* 0x6dc */
+struct shmem2_region {
+
+ u32 size;
+
+ u32 dcc_support;
+#define SHMEM_DCC_SUPPORT_NONE 0x00000000
+#define SHMEM_DCC_SUPPORT_DISABLE_ENABLE_PF_TLV 0x00000001
+#define SHMEM_DCC_SUPPORT_BANDWIDTH_ALLOCATION_TLV 0x00000004
+#define SHMEM_DCC_SUPPORT_CHANGE_MAC_ADDRESS_TLV 0x00000008
+#define SHMEM_DCC_SUPPORT_SET_PROTOCOL_TLV 0x00000040
+#define SHMEM_DCC_SUPPORT_SET_PRIORITY_TLV 0x00000080
+#define SHMEM_DCC_SUPPORT_DEFAULT SHMEM_DCC_SUPPORT_NONE
+
+};
+
+
struct emac_stats {
u32 rx_stat_ifhcinoctets;
u32 rx_stat_ifhcinbadoctets;
@@ -1186,9 +1244,9 @@ struct host_func_stats {
};
-#define BCM_5710_FW_MAJOR_VERSION 4
-#define BCM_5710_FW_MINOR_VERSION 8
-#define BCM_5710_FW_REVISION_VERSION 53
+#define BCM_5710_FW_MAJOR_VERSION 5
+#define BCM_5710_FW_MINOR_VERSION 0
+#define BCM_5710_FW_REVISION_VERSION 21
#define BCM_5710_FW_ENGINEERING_VERSION 0
#define BCM_5710_FW_COMPILE_FLAGS 1
@@ -1238,6 +1296,22 @@ struct doorbell {
/*
+ * doorbell message sent to the chip
+ */
+struct doorbell_set_prod {
+#if defined(__BIG_ENDIAN)
+ u16 prod;
+ u8 zero_fill1;
+ struct doorbell_hdr header;
+#elif defined(__LITTLE_ENDIAN)
+ struct doorbell_hdr header;
+ u8 zero_fill1;
+ u16 prod;
+#endif
+};
+
+
+/*
* IGU driver acknowledgement register
*/
struct igu_ack_register {
@@ -1272,6 +1346,62 @@ struct igu_ack_register {
/*
+ * IGU driver acknowledgement register
+ */
+struct igu_backward_compatible {
+ u32 sb_id_and_flags;
+#define IGU_BACKWARD_COMPATIBLE_SB_INDEX (0xFFFF<<0)
+#define IGU_BACKWARD_COMPATIBLE_SB_INDEX_SHIFT 0
+#define IGU_BACKWARD_COMPATIBLE_SB_SELECT (0x1F<<16)
+#define IGU_BACKWARD_COMPATIBLE_SB_SELECT_SHIFT 16
+#define IGU_BACKWARD_COMPATIBLE_SEGMENT_ACCESS (0x7<<21)
+#define IGU_BACKWARD_COMPATIBLE_SEGMENT_ACCESS_SHIFT 21
+#define IGU_BACKWARD_COMPATIBLE_BUPDATE (0x1<<24)
+#define IGU_BACKWARD_COMPATIBLE_BUPDATE_SHIFT 24
+#define IGU_BACKWARD_COMPATIBLE_ENABLE_INT (0x3<<25)
+#define IGU_BACKWARD_COMPATIBLE_ENABLE_INT_SHIFT 25
+#define IGU_BACKWARD_COMPATIBLE_RESERVED_0 (0x1F<<27)
+#define IGU_BACKWARD_COMPATIBLE_RESERVED_0_SHIFT 27
+ u32 reserved_2;
+};
+
+
+/*
+ * IGU driver acknowledgement register
+ */
+struct igu_regular {
+ u32 sb_id_and_flags;
+#define IGU_REGULAR_SB_INDEX (0xFFFFF<<0)
+#define IGU_REGULAR_SB_INDEX_SHIFT 0
+#define IGU_REGULAR_RESERVED0 (0x1<<20)
+#define IGU_REGULAR_RESERVED0_SHIFT 20
+#define IGU_REGULAR_SEGMENT_ACCESS (0x7<<21)
+#define IGU_REGULAR_SEGMENT_ACCESS_SHIFT 21
+#define IGU_REGULAR_BUPDATE (0x1<<24)
+#define IGU_REGULAR_BUPDATE_SHIFT 24
+#define IGU_REGULAR_ENABLE_INT (0x3<<25)
+#define IGU_REGULAR_ENABLE_INT_SHIFT 25
+#define IGU_REGULAR_RESERVED_1 (0x1<<27)
+#define IGU_REGULAR_RESERVED_1_SHIFT 27
+#define IGU_REGULAR_CLEANUP_TYPE (0x3<<28)
+#define IGU_REGULAR_CLEANUP_TYPE_SHIFT 28
+#define IGU_REGULAR_CLEANUP_SET (0x1<<30)
+#define IGU_REGULAR_CLEANUP_SET_SHIFT 30
+#define IGU_REGULAR_BCLEANUP (0x1<<31)
+#define IGU_REGULAR_BCLEANUP_SHIFT 31
+ u32 reserved_2;
+};
+
+/*
+ * IGU driver acknowledgement register
+ */
+union igu_consprod_reg {
+ struct igu_regular regular;
+ struct igu_backward_compatible backward_compatible;
+};
+
+
+/*
* Parser parsing flags field
*/
struct parsing_flags {
@@ -1402,12 +1532,10 @@ struct ustorm_eth_st_context_config {
#define USTORM_ETH_ST_CONTEXT_CONFIG_ENABLE_DYNAMIC_HC_SHIFT 1
#define USTORM_ETH_ST_CONTEXT_CONFIG_ENABLE_TPA (0x1<<2)
#define USTORM_ETH_ST_CONTEXT_CONFIG_ENABLE_TPA_SHIFT 2
-#define USTORM_ETH_ST_CONTEXT_CONFIG_ENABLE_SGE_RING (0x1<<3)
-#define USTORM_ETH_ST_CONTEXT_CONFIG_ENABLE_SGE_RING_SHIFT 3
-#define USTORM_ETH_ST_CONTEXT_CONFIG_ENABLE_STATISTICS (0x1<<4)
-#define USTORM_ETH_ST_CONTEXT_CONFIG_ENABLE_STATISTICS_SHIFT 4
-#define __USTORM_ETH_ST_CONTEXT_CONFIG_RESERVED0 (0x7<<5)
-#define __USTORM_ETH_ST_CONTEXT_CONFIG_RESERVED0_SHIFT 5
+#define USTORM_ETH_ST_CONTEXT_CONFIG_ENABLE_STATISTICS (0x1<<3)
+#define USTORM_ETH_ST_CONTEXT_CONFIG_ENABLE_STATISTICS_SHIFT 3
+#define __USTORM_ETH_ST_CONTEXT_CONFIG_RESERVED0 (0xF<<4)
+#define __USTORM_ETH_ST_CONTEXT_CONFIG_RESERVED0_SHIFT 4
u8 status_block_id;
u8 clientId;
u8 sb_index_numbers;
@@ -1430,12 +1558,10 @@ struct ustorm_eth_st_context_config {
#define USTORM_ETH_ST_CONTEXT_CONFIG_ENABLE_DYNAMIC_HC_SHIFT 1
#define USTORM_ETH_ST_CONTEXT_CONFIG_ENABLE_TPA (0x1<<2)
#define USTORM_ETH_ST_CONTEXT_CONFIG_ENABLE_TPA_SHIFT 2
-#define USTORM_ETH_ST_CONTEXT_CONFIG_ENABLE_SGE_RING (0x1<<3)
-#define USTORM_ETH_ST_CONTEXT_CONFIG_ENABLE_SGE_RING_SHIFT 3
-#define USTORM_ETH_ST_CONTEXT_CONFIG_ENABLE_STATISTICS (0x1<<4)
-#define USTORM_ETH_ST_CONTEXT_CONFIG_ENABLE_STATISTICS_SHIFT 4
-#define __USTORM_ETH_ST_CONTEXT_CONFIG_RESERVED0 (0x7<<5)
-#define __USTORM_ETH_ST_CONTEXT_CONFIG_RESERVED0_SHIFT 5
+#define USTORM_ETH_ST_CONTEXT_CONFIG_ENABLE_STATISTICS (0x1<<3)
+#define USTORM_ETH_ST_CONTEXT_CONFIG_ENABLE_STATISTICS_SHIFT 3
+#define __USTORM_ETH_ST_CONTEXT_CONFIG_RESERVED0 (0xF<<4)
+#define __USTORM_ETH_ST_CONTEXT_CONFIG_RESERVED0_SHIFT 4
#endif
#if defined(__BIG_ENDIAN)
u16 bd_buff_size;
@@ -1455,11 +1581,36 @@ struct ustorm_eth_st_context_config {
u8 __local_bd_prod;
u8 __local_sge_prod;
#endif
- u32 reserved;
+#if defined(__BIG_ENDIAN)
+ u16 __sdm_bd_expected_counter;
+ u8 cstorm_agg_int;
+ u8 __expected_bds_on_ram;
+#elif defined(__LITTLE_ENDIAN)
+ u8 __expected_bds_on_ram;
+ u8 cstorm_agg_int;
+ u16 __sdm_bd_expected_counter;
+#endif
+#if defined(__BIG_ENDIAN)
+ u16 __ring_data_ram_addr;
+ u16 __hc_cstorm_ram_addr;
+#elif defined(__LITTLE_ENDIAN)
+ u16 __hc_cstorm_ram_addr;
+ u16 __ring_data_ram_addr;
+#endif
+#if defined(__BIG_ENDIAN)
+ u8 reserved1;
+ u8 max_sges_for_packet;
+ u16 __bd_ring_ram_addr;
+#elif defined(__LITTLE_ENDIAN)
+ u16 __bd_ring_ram_addr;
+ u8 max_sges_for_packet;
+ u8 reserved1;
+#endif
u32 bd_page_base_lo;
u32 bd_page_base_hi;
u32 sge_page_base_lo;
u32 sge_page_base_hi;
+ struct regpair reserved2;
};
/*
@@ -1482,8 +1633,8 @@ struct eth_rx_sge {
* Local BDs and SGEs rings (in ETH)
*/
struct eth_local_rx_rings {
- struct eth_rx_bd __local_bd_ring[16];
- struct eth_rx_sge __local_sge_ring[12];
+ struct eth_rx_bd __local_bd_ring[8];
+ struct eth_rx_sge __local_sge_ring[10];
};
/*
@@ -1575,13 +1726,13 @@ struct xstorm_eth_extra_ag_context_section {
*/
struct xstorm_eth_ag_context {
#if defined(__BIG_ENDIAN)
- u16 __bd_prod;
+ u16 agg_val1;
u8 __agg_vars1;
u8 __state;
#elif defined(__LITTLE_ENDIAN)
u8 __state;
u8 __agg_vars1;
- u16 __bd_prod;
+ u16 agg_val1;
#endif
#if defined(__BIG_ENDIAN)
u8 cdu_reserved;
@@ -1594,7 +1745,7 @@ struct xstorm_eth_ag_context {
u8 __agg_vars4;
u8 cdu_reserved;
#endif
- u32 __more_packets_to_send;
+ u32 __bd_prod;
#if defined(__BIG_ENDIAN)
u16 __agg_vars5;
u16 __agg_val4_th;
@@ -1860,8 +2011,8 @@ struct eth_tx_bd_flags {
#define ETH_TX_BD_FLAGS_VLAN_TAG_SHIFT 0
#define ETH_TX_BD_FLAGS_IP_CSUM (0x1<<1)
#define ETH_TX_BD_FLAGS_IP_CSUM_SHIFT 1
-#define ETH_TX_BD_FLAGS_TCP_CSUM (0x1<<2)
-#define ETH_TX_BD_FLAGS_TCP_CSUM_SHIFT 2
+#define ETH_TX_BD_FLAGS_L4_CSUM (0x1<<2)
+#define ETH_TX_BD_FLAGS_L4_CSUM_SHIFT 2
#define ETH_TX_BD_FLAGS_END_BD (0x1<<3)
#define ETH_TX_BD_FLAGS_END_BD_SHIFT 3
#define ETH_TX_BD_FLAGS_START_BD (0x1<<4)
@@ -1877,7 +2028,7 @@ struct eth_tx_bd_flags {
/*
* The eth Tx Buffer Descriptor
*/
-struct eth_tx_bd {
+struct eth_tx_start_bd {
__le32 addr_lo;
__le32 addr_hi;
__le16 nbd;
@@ -1885,10 +2036,21 @@ struct eth_tx_bd {
__le16 vlan;
struct eth_tx_bd_flags bd_flags;
u8 general_data;
-#define ETH_TX_BD_HDR_NBDS (0x3F<<0)
-#define ETH_TX_BD_HDR_NBDS_SHIFT 0
-#define ETH_TX_BD_ETH_ADDR_TYPE (0x3<<6)
-#define ETH_TX_BD_ETH_ADDR_TYPE_SHIFT 6
+#define ETH_TX_START_BD_HDR_NBDS (0x3F<<0)
+#define ETH_TX_START_BD_HDR_NBDS_SHIFT 0
+#define ETH_TX_START_BD_ETH_ADDR_TYPE (0x3<<6)
+#define ETH_TX_START_BD_ETH_ADDR_TYPE_SHIFT 6
+};
+
+/*
+ * Tx regular BD structure
+ */
+struct eth_tx_bd {
+ u32 addr_lo;
+ u32 addr_hi;
+ u16 total_pkt_bytes;
+ u16 nbytes;
+ u8 reserved[4];
};
/*
@@ -1898,8 +2060,8 @@ struct eth_tx_parse_bd {
u8 global_data;
#define ETH_TX_PARSE_BD_IP_HDR_START_OFFSET (0xF<<0)
#define ETH_TX_PARSE_BD_IP_HDR_START_OFFSET_SHIFT 0
-#define ETH_TX_PARSE_BD_CS_ANY_FLG (0x1<<4)
-#define ETH_TX_PARSE_BD_CS_ANY_FLG_SHIFT 4
+#define ETH_TX_PARSE_BD_UDP_CS_FLG (0x1<<4)
+#define ETH_TX_PARSE_BD_UDP_CS_FLG_SHIFT 4
#define ETH_TX_PARSE_BD_PSEUDO_CS_WITHOUT_LEN (0x1<<5)
#define ETH_TX_PARSE_BD_PSEUDO_CS_WITHOUT_LEN_SHIFT 5
#define ETH_TX_PARSE_BD_LLC_SNAP_EN (0x1<<6)
@@ -1924,10 +2086,10 @@ struct eth_tx_parse_bd {
#define ETH_TX_PARSE_BD_CWR_FLG (0x1<<7)
#define ETH_TX_PARSE_BD_CWR_FLG_SHIFT 7
u8 ip_hlen;
- s8 cs_offset;
+ s8 reserved;
__le16 total_hlen;
- __le16 lso_mss;
__le16 tcp_pseudo_csum;
+ __le16 lso_mss;
__le16 ip_id;
__le32 tcp_send_seq;
};
@@ -1936,15 +2098,16 @@ struct eth_tx_parse_bd {
* The last BD in the BD memory will hold a pointer to the next BD memory
*/
struct eth_tx_next_bd {
- u32 addr_lo;
- u32 addr_hi;
+ __le32 addr_lo;
+ __le32 addr_hi;
u8 reserved[8];
};
/*
- * union for 3 Bd types
+ * union for 4 Bd types
*/
union eth_tx_bd_types {
+ struct eth_tx_start_bd start_bd;
struct eth_tx_bd reg_bd;
struct eth_tx_parse_bd parse_bd;
struct eth_tx_next_bd next_bd;
@@ -1973,11 +2136,35 @@ struct xstorm_eth_st_context {
#define XSTORM_ETH_ST_CONTEXT_STATISTICS_ENABLE_SHIFT 7
u16 tx_bd_cons;
#endif
- u32 db_data_addr_lo;
- u32 db_data_addr_hi;
- u32 __pkt_cons;
- u32 __gso_next;
- u32 is_eth_conn_1b;
+ u32 __reserved1;
+ u32 __reserved2;
+#if defined(__BIG_ENDIAN)
+ u8 __ram_cache_index;
+ u8 __double_buffer_client;
+ u16 __pkt_cons;
+#elif defined(__LITTLE_ENDIAN)
+ u16 __pkt_cons;
+ u8 __double_buffer_client;
+ u8 __ram_cache_index;
+#endif
+#if defined(__BIG_ENDIAN)
+ u16 __statistics_address;
+ u16 __gso_next;
+#elif defined(__LITTLE_ENDIAN)
+ u16 __gso_next;
+ u16 __statistics_address;
+#endif
+#if defined(__BIG_ENDIAN)
+ u8 __local_tx_bd_cons;
+ u8 safc_group_num;
+ u8 safc_group_en;
+ u8 __is_eth_conn;
+#elif defined(__LITTLE_ENDIAN)
+ u8 __is_eth_conn;
+ u8 safc_group_en;
+ u8 safc_group_num;
+ u8 __local_tx_bd_cons;
+#endif
union eth_tx_bd_types __bds[13];
};
@@ -2042,9 +2229,9 @@ struct eth_tx_doorbell {
/*
- * ustorm status block
+ * cstorm default status block, generated by ustorm
*/
-struct ustorm_def_status_block {
+struct cstorm_def_status_block_u {
__le16 index_values[HC_USTORM_DEF_SB_NUM_INDICES];
__le16 status_block_index;
u8 func;
@@ -2053,9 +2240,9 @@ struct ustorm_def_status_block {
};
/*
- * cstorm status block
+ * cstorm default status block, generated by cstorm
*/
-struct cstorm_def_status_block {
+struct cstorm_def_status_block_c {
__le16 index_values[HC_CSTORM_DEF_SB_NUM_INDICES];
__le16 status_block_index;
u8 func;
@@ -2090,17 +2277,17 @@ struct tstorm_def_status_block {
*/
struct host_def_status_block {
struct atten_def_status_block atten_status_block;
- struct ustorm_def_status_block u_def_status_block;
- struct cstorm_def_status_block c_def_status_block;
+ struct cstorm_def_status_block_u u_def_status_block;
+ struct cstorm_def_status_block_c c_def_status_block;
struct xstorm_def_status_block x_def_status_block;
struct tstorm_def_status_block t_def_status_block;
};
/*
- * ustorm status block
+ * cstorm status block, generated by ustorm
*/
-struct ustorm_status_block {
+struct cstorm_status_block_u {
__le16 index_values[HC_USTORM_SB_NUM_INDICES];
__le16 status_block_index;
u8 func;
@@ -2109,9 +2296,9 @@ struct ustorm_status_block {
};
/*
- * cstorm status block
+ * cstorm status block, generated by cstorm
*/
-struct cstorm_status_block {
+struct cstorm_status_block_c {
__le16 index_values[HC_CSTORM_SB_NUM_INDICES];
__le16 status_block_index;
u8 func;
@@ -2123,8 +2310,8 @@ struct cstorm_status_block {
* host status block
*/
struct host_status_block {
- struct ustorm_status_block u_status_block;
- struct cstorm_status_block c_status_block;
+ struct cstorm_status_block_u u_status_block;
+ struct cstorm_status_block_c c_status_block;
};
@@ -2140,15 +2327,6 @@ struct eth_client_setup_ramrod_data {
/*
- * L2 dynamic host coalescing init parameters
- */
-struct eth_dynamic_hc_config {
- u32 threshold[3];
- u8 hc_timeout[4];
-};
-
-
-/*
* regular eth FP CQE parameters struct
*/
struct eth_fast_path_rx_cqe {
@@ -2312,12 +2490,10 @@ struct eth_spe {
/*
- * doorbell data in host memory
+ * array of 13 bds as appears in the eth xstorm context
*/
-struct eth_tx_db_data {
- __le32 packets_prod;
- __le16 bds_prod;
- __le16 reserved;
+struct eth_tx_bds_array {
+ union eth_tx_bd_types bds[13];
};
@@ -2345,8 +2521,10 @@ struct tstorm_eth_function_common_config {
#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_VLAN_IN_CAM_SHIFT 8
#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_E1HOV_IN_CAM (0x1<<9)
#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_E1HOV_IN_CAM_SHIFT 9
-#define __TSTORM_ETH_FUNCTION_COMMON_CONFIG_RESERVED0 (0x3F<<10)
-#define __TSTORM_ETH_FUNCTION_COMMON_CONFIG_RESERVED0_SHIFT 10
+#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_ENABLE_TPA (0x1<<10)
+#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_ENABLE_TPA_SHIFT 10
+#define __TSTORM_ETH_FUNCTION_COMMON_CONFIG_RESERVED0 (0x1F<<11)
+#define __TSTORM_ETH_FUNCTION_COMMON_CONFIG_RESERVED0_SHIFT 11
#elif defined(__LITTLE_ENDIAN)
u16 config_flags;
#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV4_CAPABILITY (0x1<<0)
@@ -2365,8 +2543,10 @@ struct tstorm_eth_function_common_config {
#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_VLAN_IN_CAM_SHIFT 8
#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_E1HOV_IN_CAM (0x1<<9)
#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_E1HOV_IN_CAM_SHIFT 9
-#define __TSTORM_ETH_FUNCTION_COMMON_CONFIG_RESERVED0 (0x3F<<10)
-#define __TSTORM_ETH_FUNCTION_COMMON_CONFIG_RESERVED0_SHIFT 10
+#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_ENABLE_TPA (0x1<<10)
+#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_ENABLE_TPA_SHIFT 10
+#define __TSTORM_ETH_FUNCTION_COMMON_CONFIG_RESERVED0 (0x1F<<11)
+#define __TSTORM_ETH_FUNCTION_COMMON_CONFIG_RESERVED0_SHIFT 11
u8 rss_result_mask;
u8 leading_client_id;
#endif
@@ -2374,11 +2554,38 @@ struct tstorm_eth_function_common_config {
};
/*
+ * RSS idirection table update configuration
+ */
+struct rss_update_config {
+#if defined(__BIG_ENDIAN)
+ u16 toe_rss_bitmap;
+ u16 flags;
+#define RSS_UPDATE_CONFIG_ETH_UPDATE_ENABLE (0x1<<0)
+#define RSS_UPDATE_CONFIG_ETH_UPDATE_ENABLE_SHIFT 0
+#define RSS_UPDATE_CONFIG_TOE_UPDATE_ENABLE (0x1<<1)
+#define RSS_UPDATE_CONFIG_TOE_UPDATE_ENABLE_SHIFT 1
+#define __RSS_UPDATE_CONFIG_RESERVED0 (0x3FFF<<2)
+#define __RSS_UPDATE_CONFIG_RESERVED0_SHIFT 2
+#elif defined(__LITTLE_ENDIAN)
+ u16 flags;
+#define RSS_UPDATE_CONFIG_ETH_UPDATE_ENABLE (0x1<<0)
+#define RSS_UPDATE_CONFIG_ETH_UPDATE_ENABLE_SHIFT 0
+#define RSS_UPDATE_CONFIG_TOE_UPDATE_ENABLE (0x1<<1)
+#define RSS_UPDATE_CONFIG_TOE_UPDATE_ENABLE_SHIFT 1
+#define __RSS_UPDATE_CONFIG_RESERVED0 (0x3FFF<<2)
+#define __RSS_UPDATE_CONFIG_RESERVED0_SHIFT 2
+ u16 toe_rss_bitmap;
+#endif
+ u32 reserved1;
+};
+
+/*
* parameters for eth update ramrod
*/
struct eth_update_ramrod_data {
struct tstorm_eth_function_common_config func_config;
u8 indirectionTable[128];
+ struct rss_update_config rss_config;
};
@@ -2423,8 +2630,9 @@ struct tstorm_cam_target_table_entry {
#define TSTORM_CAM_TARGET_TABLE_ENTRY_RDMA_MAC_SHIFT 3
#define TSTORM_CAM_TARGET_TABLE_ENTRY_RESERVED0 (0xF<<4)
#define TSTORM_CAM_TARGET_TABLE_ENTRY_RESERVED0_SHIFT 4
- u8 client_id;
+ u8 reserved1;
u16 vlan_id;
+ u32 clients_bit_vector;
};
/*
@@ -2453,7 +2661,7 @@ struct mac_configuration_entry_e1h {
__le16 msb_mac_addr;
__le16 vlan_id;
__le16 e1hov_id;
- u8 client_id;
+ u8 reserved0;
u8 flags;
#define MAC_CONFIGURATION_ENTRY_E1H_PORT (0x1<<0)
#define MAC_CONFIGURATION_ENTRY_E1H_PORT_SHIFT 0
@@ -2461,8 +2669,9 @@ struct mac_configuration_entry_e1h {
#define MAC_CONFIGURATION_ENTRY_E1H_ACTION_TYPE_SHIFT 1
#define MAC_CONFIGURATION_ENTRY_E1H_RDMA_MAC (0x1<<2)
#define MAC_CONFIGURATION_ENTRY_E1H_RDMA_MAC_SHIFT 2
-#define MAC_CONFIGURATION_ENTRY_E1H_RESERVED0 (0x1F<<3)
-#define MAC_CONFIGURATION_ENTRY_E1H_RESERVED0_SHIFT 3
+#define MAC_CONFIGURATION_ENTRY_E1H_RESERVED1 (0x1F<<3)
+#define MAC_CONFIGURATION_ENTRY_E1H_RESERVED1_SHIFT 3
+ u32 clients_bit_vector;
};
/*
@@ -2487,13 +2696,13 @@ struct tstorm_eth_approximate_match_multicast_filtering {
*/
struct tstorm_eth_client_config {
#if defined(__BIG_ENDIAN)
- u8 max_sges_for_packet;
+ u8 reserved0;
u8 statistics_counter_id;
u16 mtu;
#elif defined(__LITTLE_ENDIAN)
u16 mtu;
u8 statistics_counter_id;
- u8 max_sges_for_packet;
+ u8 reserved0;
#endif
#if defined(__BIG_ENDIAN)
u16 drop_flags;
@@ -2505,8 +2714,8 @@ struct tstorm_eth_client_config {
#define TSTORM_ETH_CLIENT_CONFIG_DROP_TTL0_SHIFT 2
#define TSTORM_ETH_CLIENT_CONFIG_DROP_UDP_CS_ERR (0x1<<3)
#define TSTORM_ETH_CLIENT_CONFIG_DROP_UDP_CS_ERR_SHIFT 3
-#define __TSTORM_ETH_CLIENT_CONFIG_RESERVED1 (0xFFF<<4)
-#define __TSTORM_ETH_CLIENT_CONFIG_RESERVED1_SHIFT 4
+#define __TSTORM_ETH_CLIENT_CONFIG_RESERVED2 (0xFFF<<4)
+#define __TSTORM_ETH_CLIENT_CONFIG_RESERVED2_SHIFT 4
u16 config_flags;
#define TSTORM_ETH_CLIENT_CONFIG_VLAN_REM_ENABLE (0x1<<0)
#define TSTORM_ETH_CLIENT_CONFIG_VLAN_REM_ENABLE_SHIFT 0
@@ -2514,10 +2723,8 @@ struct tstorm_eth_client_config {
#define TSTORM_ETH_CLIENT_CONFIG_E1HOV_REM_ENABLE_SHIFT 1
#define TSTORM_ETH_CLIENT_CONFIG_STATSITICS_ENABLE (0x1<<2)
#define TSTORM_ETH_CLIENT_CONFIG_STATSITICS_ENABLE_SHIFT 2
-#define TSTORM_ETH_CLIENT_CONFIG_ENABLE_SGE_RING (0x1<<3)
-#define TSTORM_ETH_CLIENT_CONFIG_ENABLE_SGE_RING_SHIFT 3
-#define __TSTORM_ETH_CLIENT_CONFIG_RESERVED0 (0xFFF<<4)
-#define __TSTORM_ETH_CLIENT_CONFIG_RESERVED0_SHIFT 4
+#define __TSTORM_ETH_CLIENT_CONFIG_RESERVED1 (0x1FFF<<3)
+#define __TSTORM_ETH_CLIENT_CONFIG_RESERVED1_SHIFT 3
#elif defined(__LITTLE_ENDIAN)
u16 config_flags;
#define TSTORM_ETH_CLIENT_CONFIG_VLAN_REM_ENABLE (0x1<<0)
@@ -2526,10 +2733,8 @@ struct tstorm_eth_client_config {
#define TSTORM_ETH_CLIENT_CONFIG_E1HOV_REM_ENABLE_SHIFT 1
#define TSTORM_ETH_CLIENT_CONFIG_STATSITICS_ENABLE (0x1<<2)
#define TSTORM_ETH_CLIENT_CONFIG_STATSITICS_ENABLE_SHIFT 2
-#define TSTORM_ETH_CLIENT_CONFIG_ENABLE_SGE_RING (0x1<<3)
-#define TSTORM_ETH_CLIENT_CONFIG_ENABLE_SGE_RING_SHIFT 3
-#define __TSTORM_ETH_CLIENT_CONFIG_RESERVED0 (0xFFF<<4)
-#define __TSTORM_ETH_CLIENT_CONFIG_RESERVED0_SHIFT 4
+#define __TSTORM_ETH_CLIENT_CONFIG_RESERVED1 (0x1FFF<<3)
+#define __TSTORM_ETH_CLIENT_CONFIG_RESERVED1_SHIFT 3
u16 drop_flags;
#define TSTORM_ETH_CLIENT_CONFIG_DROP_IP_CS_ERR (0x1<<0)
#define TSTORM_ETH_CLIENT_CONFIG_DROP_IP_CS_ERR_SHIFT 0
@@ -2539,8 +2744,8 @@ struct tstorm_eth_client_config {
#define TSTORM_ETH_CLIENT_CONFIG_DROP_TTL0_SHIFT 2
#define TSTORM_ETH_CLIENT_CONFIG_DROP_UDP_CS_ERR (0x1<<3)
#define TSTORM_ETH_CLIENT_CONFIG_DROP_UDP_CS_ERR_SHIFT 3
-#define __TSTORM_ETH_CLIENT_CONFIG_RESERVED1 (0xFFF<<4)
-#define __TSTORM_ETH_CLIENT_CONFIG_RESERVED1_SHIFT 4
+#define __TSTORM_ETH_CLIENT_CONFIG_RESERVED2 (0xFFF<<4)
+#define __TSTORM_ETH_CLIENT_CONFIG_RESERVED2_SHIFT 4
#endif
};
@@ -2663,7 +2868,6 @@ struct rate_shaping_vars_per_port {
u32 rs_threshold;
};
-
/*
* per-port fairness variables
*/
@@ -2673,7 +2877,6 @@ struct fairness_vars_per_port {
u32 fairness_timeout;
};
-
/*
* per-port SAFC variables
*/
@@ -2690,7 +2893,6 @@ struct safc_struct_per_port {
u16 cos_to_pause_mask[NUM_OF_SAFC_BITS];
};
-
/*
* Per-port congestion management variables
*/
@@ -2703,11 +2905,23 @@ struct cmng_struct_per_port {
/*
+ * Dynamic host coalescing init parameters
+ */
+struct dynamic_hc_config {
+ u32 threshold[3];
+ u8 shift_per_protocol[HC_USTORM_SB_NUM_INDICES];
+ u8 hc_timeout0[HC_USTORM_SB_NUM_INDICES];
+ u8 hc_timeout1[HC_USTORM_SB_NUM_INDICES];
+ u8 hc_timeout2[HC_USTORM_SB_NUM_INDICES];
+ u8 hc_timeout3[HC_USTORM_SB_NUM_INDICES];
+};
+
+
+/*
* Protocol-common statistics collected by the Xstorm (per client)
*/
struct xstorm_per_client_stats {
- struct regpair total_sent_bytes;
- __le32 total_sent_pkts;
+ __le32 reserved0;
__le32 unicast_pkts_sent;
struct regpair unicast_bytes_sent;
struct regpair multicast_bytes_sent;
@@ -2715,11 +2929,10 @@ struct xstorm_per_client_stats {
__le32 broadcast_pkts_sent;
struct regpair broadcast_bytes_sent;
__le16 stats_counter;
- __le16 reserved0;
- __le32 reserved1;
+ __le16 reserved1;
+ __le32 reserved2;
};
-
/*
* Common statistics collected by the Xstorm (per port)
*/
@@ -2727,7 +2940,6 @@ struct xstorm_common_stats {
struct xstorm_per_client_stats client_statistics[MAX_X_STAT_COUNTER_ID];
};
-
/*
* Protocol-common statistics collected by the Tstorm (per port)
*/
@@ -2738,19 +2950,16 @@ struct tstorm_per_port_stats {
__le32 mac_discard;
};
-
/*
* Protocol-common statistics collected by the Tstorm (per client)
*/
struct tstorm_per_client_stats {
- struct regpair total_rcv_bytes;
struct regpair rcv_unicast_bytes;
struct regpair rcv_broadcast_bytes;
struct regpair rcv_multicast_bytes;
struct regpair rcv_error_bytes;
__le32 checksum_discard;
__le32 packets_too_big_discard;
- __le32 total_rcv_pkts;
__le32 rcv_unicast_pkts;
__le32 rcv_broadcast_pkts;
__le32 rcv_multicast_pkts;
@@ -2758,7 +2967,6 @@ struct tstorm_per_client_stats {
__le32 ttl0_discard;
__le16 stats_counter;
__le16 reserved0;
- __le32 reserved1;
};
/*
@@ -2861,6 +3069,15 @@ struct pram_fw_version {
/*
+ * The send queue element
+ */
+struct protocol_common_spe {
+ struct spe_hdr hdr;
+ struct regpair phy_address;
+};
+
+
+/*
* a single rate shaping counter. can be used as protocol or vnic counter
*/
struct rate_shaping_counter {
diff --git a/drivers/net/bnx2x_init.h b/drivers/net/bnx2x_init.h
index 3ba4d888068..65b26cbfe3e 100644
--- a/drivers/net/bnx2x_init.h
+++ b/drivers/net/bnx2x_init.h
@@ -15,24 +15,11 @@
#ifndef BNX2X_INIT_H
#define BNX2X_INIT_H
-#define COMMON 0x1
-#define PORT0 0x2
-#define PORT1 0x4
-
-#define INIT_EMULATION 0x1
-#define INIT_FPGA 0x2
-#define INIT_ASIC 0x4
-#define INIT_HARDWARE 0x7
-
-#define TSTORM_INTMEM_ADDR TSEM_REG_FAST_MEMORY
-#define CSTORM_INTMEM_ADDR CSEM_REG_FAST_MEMORY
-#define XSTORM_INTMEM_ADDR XSEM_REG_FAST_MEMORY
-#define USTORM_INTMEM_ADDR USEM_REG_FAST_MEMORY
/* RAM0 size in bytes */
#define STORM_INTMEM_SIZE_E1 0x5800
#define STORM_INTMEM_SIZE_E1H 0x10000
-#define STORM_INTMEM_SIZE(bp) ((CHIP_IS_E1H(bp) ? STORM_INTMEM_SIZE_E1H : \
- STORM_INTMEM_SIZE_E1) / 4)
+#define STORM_INTMEM_SIZE(bp) ((CHIP_IS_E1(bp) ? STORM_INTMEM_SIZE_E1 : \
+ STORM_INTMEM_SIZE_E1H) / 4)
/* Init operation types and structures */
@@ -53,65 +40,68 @@
#define OP_WR_ASIC 0xc /* write single register on ASIC */
/* Init stages */
-#define COMMON_STAGE 0
-#define PORT0_STAGE 1
-#define PORT1_STAGE 2
-/* Never reorder FUNCx stages !!! */
-#define FUNC0_STAGE 3
-#define FUNC1_STAGE 4
-#define FUNC2_STAGE 5
-#define FUNC3_STAGE 6
-#define FUNC4_STAGE 7
-#define FUNC5_STAGE 8
-#define FUNC6_STAGE 9
-#define FUNC7_STAGE 10
-#define STAGE_IDX_MAX 11
-
-#define STAGE_START 0
-#define STAGE_END 1
+/* Never reorder stages !!! */
+#define COMMON_STAGE 0
+#define PORT0_STAGE 1
+#define PORT1_STAGE 2
+#define FUNC0_STAGE 3
+#define FUNC1_STAGE 4
+#define FUNC2_STAGE 5
+#define FUNC3_STAGE 6
+#define FUNC4_STAGE 7
+#define FUNC5_STAGE 8
+#define FUNC6_STAGE 9
+#define FUNC7_STAGE 10
+#define STAGE_IDX_MAX 11
+
+#define STAGE_START 0
+#define STAGE_END 1
/* Indices of blocks */
-#define PRS_BLOCK 0
-#define SRCH_BLOCK 1
-#define TSDM_BLOCK 2
-#define TCM_BLOCK 3
-#define BRB1_BLOCK 4
-#define TSEM_BLOCK 5
-#define PXPCS_BLOCK 6
-#define EMAC0_BLOCK 7
-#define EMAC1_BLOCK 8
-#define DBU_BLOCK 9
-#define MISC_BLOCK 10
-#define DBG_BLOCK 11
-#define NIG_BLOCK 12
-#define MCP_BLOCK 13
-#define UPB_BLOCK 14
-#define CSDM_BLOCK 15
-#define USDM_BLOCK 16
-#define CCM_BLOCK 17
-#define UCM_BLOCK 18
-#define USEM_BLOCK 19
-#define CSEM_BLOCK 20
-#define XPB_BLOCK 21
-#define DQ_BLOCK 22
-#define TIMERS_BLOCK 23
-#define XSDM_BLOCK 24
-#define QM_BLOCK 25
-#define PBF_BLOCK 26
-#define XCM_BLOCK 27
-#define XSEM_BLOCK 28
-#define CDU_BLOCK 29
-#define DMAE_BLOCK 30
-#define PXP_BLOCK 31
-#define CFC_BLOCK 32
-#define HC_BLOCK 33
-#define PXP2_BLOCK 34
-#define MISC_AEU_BLOCK 35
+#define PRS_BLOCK 0
+#define SRCH_BLOCK 1
+#define TSDM_BLOCK 2
+#define TCM_BLOCK 3
+#define BRB1_BLOCK 4
+#define TSEM_BLOCK 5
+#define PXPCS_BLOCK 6
+#define EMAC0_BLOCK 7
+#define EMAC1_BLOCK 8
+#define DBU_BLOCK 9
+#define MISC_BLOCK 10
+#define DBG_BLOCK 11
+#define NIG_BLOCK 12
+#define MCP_BLOCK 13
+#define UPB_BLOCK 14
+#define CSDM_BLOCK 15
+#define USDM_BLOCK 16
+#define CCM_BLOCK 17
+#define UCM_BLOCK 18
+#define USEM_BLOCK 19
+#define CSEM_BLOCK 20
+#define XPB_BLOCK 21
+#define DQ_BLOCK 22
+#define TIMERS_BLOCK 23
+#define XSDM_BLOCK 24
+#define QM_BLOCK 25
+#define PBF_BLOCK 26
+#define XCM_BLOCK 27
+#define XSEM_BLOCK 28
+#define CDU_BLOCK 29
+#define DMAE_BLOCK 30
+#define PXP_BLOCK 31
+#define CFC_BLOCK 32
+#define HC_BLOCK 33
+#define PXP2_BLOCK 34
+#define MISC_AEU_BLOCK 35
+#define PGLUE_B_BLOCK 36
+#define IGU_BLOCK 37
+
/* Returns the index of start or end of a specific block stage in ops array*/
#define BLOCK_OPS_IDX(block, stage, end) \
- (2*(((block)*STAGE_IDX_MAX) + (stage)) + (end))
+ (2*(((block)*STAGE_IDX_MAX) + (stage)) + (end))
struct raw_op {
@@ -158,199 +148,5 @@ union init_op {
struct raw_op raw;
};
-/****************************************************************************
-* PXP
-****************************************************************************/
-/*
- * This code configures the PCI read/write arbiter
- * which implements a weighted round robin
- * between the virtual queues in the chip.
- *
- * The values were derived for each PCI max payload and max request size.
- * since max payload and max request size are only known at run time,
- * this is done as a separate init stage.
- */
-
-#define NUM_WR_Q 13
-#define NUM_RD_Q 29
-#define MAX_RD_ORD 3
-#define MAX_WR_ORD 2
-
-/* configuration for one arbiter queue */
-struct arb_line {
- int l;
- int add;
- int ubound;
-};
-
-/* derived configuration for each read queue for each max request size */
-static const struct arb_line read_arb_data[NUM_RD_Q][MAX_RD_ORD + 1] = {
-/* 1 */ { {8, 64, 25}, {16, 64, 25}, {32, 64, 25}, {64, 64, 41} },
- { {4, 8, 4}, {4, 8, 4}, {4, 8, 4}, {4, 8, 4} },
- { {4, 3, 3}, {4, 3, 3}, {4, 3, 3}, {4, 3, 3} },
- { {8, 3, 6}, {16, 3, 11}, {16, 3, 11}, {16, 3, 11} },
- { {8, 64, 25}, {16, 64, 25}, {32, 64, 25}, {64, 64, 41} },
- { {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {64, 3, 41} },
- { {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {64, 3, 41} },
- { {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {64, 3, 41} },
- { {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {64, 3, 41} },
-/* 10 */{ {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {32, 3, 21} },
- { {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {32, 3, 21} },
- { {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {32, 3, 21} },
- { {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {32, 3, 21} },
- { {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {32, 3, 21} },
- { {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {32, 3, 21} },
- { {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {32, 3, 21} },
- { {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {32, 3, 21} },
- { {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {32, 3, 21} },
- { {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {32, 3, 21} },
-/* 20 */{ {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {32, 3, 21} },
- { {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {32, 3, 21} },
- { {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {32, 3, 21} },
- { {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {32, 3, 21} },
- { {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {32, 3, 21} },
- { {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {32, 3, 21} },
- { {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {32, 3, 21} },
- { {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {32, 3, 21} },
- { {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {32, 3, 21} },
- { {8, 64, 25}, {16, 64, 41}, {32, 64, 81}, {64, 64, 120} }
-};
-
-/* derived configuration for each write queue for each max request size */
-static const struct arb_line write_arb_data[NUM_WR_Q][MAX_WR_ORD + 1] = {
-/* 1 */ { {4, 6, 3}, {4, 6, 3}, {4, 6, 3} },
- { {4, 2, 3}, {4, 2, 3}, {4, 2, 3} },
- { {8, 2, 6}, {16, 2, 11}, {16, 2, 11} },
- { {8, 2, 6}, {16, 2, 11}, {32, 2, 21} },
- { {8, 2, 6}, {16, 2, 11}, {32, 2, 21} },
- { {8, 2, 6}, {16, 2, 11}, {32, 2, 21} },
- { {8, 64, 25}, {16, 64, 25}, {32, 64, 25} },
- { {8, 2, 6}, {16, 2, 11}, {16, 2, 11} },
- { {8, 2, 6}, {16, 2, 11}, {16, 2, 11} },
-/* 10 */{ {8, 9, 6}, {16, 9, 11}, {32, 9, 21} },
- { {8, 47, 19}, {16, 47, 19}, {32, 47, 21} },
- { {8, 9, 6}, {16, 9, 11}, {16, 9, 11} },
- { {8, 64, 25}, {16, 64, 41}, {32, 64, 81} }
-};
-
-/* register addresses for read queues */
-static const struct arb_line read_arb_addr[NUM_RD_Q-1] = {
-/* 1 */ {PXP2_REG_RQ_BW_RD_L0, PXP2_REG_RQ_BW_RD_ADD0,
- PXP2_REG_RQ_BW_RD_UBOUND0},
- {PXP2_REG_PSWRQ_BW_L1, PXP2_REG_PSWRQ_BW_ADD1,
- PXP2_REG_PSWRQ_BW_UB1},
- {PXP2_REG_PSWRQ_BW_L2, PXP2_REG_PSWRQ_BW_ADD2,
- PXP2_REG_PSWRQ_BW_UB2},
- {PXP2_REG_PSWRQ_BW_L3, PXP2_REG_PSWRQ_BW_ADD3,
- PXP2_REG_PSWRQ_BW_UB3},
- {PXP2_REG_RQ_BW_RD_L4, PXP2_REG_RQ_BW_RD_ADD4,
- PXP2_REG_RQ_BW_RD_UBOUND4},
- {PXP2_REG_RQ_BW_RD_L5, PXP2_REG_RQ_BW_RD_ADD5,
- PXP2_REG_RQ_BW_RD_UBOUND5},
- {PXP2_REG_PSWRQ_BW_L6, PXP2_REG_PSWRQ_BW_ADD6,
- PXP2_REG_PSWRQ_BW_UB6},
- {PXP2_REG_PSWRQ_BW_L7, PXP2_REG_PSWRQ_BW_ADD7,
- PXP2_REG_PSWRQ_BW_UB7},
- {PXP2_REG_PSWRQ_BW_L8, PXP2_REG_PSWRQ_BW_ADD8,
- PXP2_REG_PSWRQ_BW_UB8},
-/* 10 */{PXP2_REG_PSWRQ_BW_L9, PXP2_REG_PSWRQ_BW_ADD9,
- PXP2_REG_PSWRQ_BW_UB9},
- {PXP2_REG_PSWRQ_BW_L10, PXP2_REG_PSWRQ_BW_ADD10,
- PXP2_REG_PSWRQ_BW_UB10},
- {PXP2_REG_PSWRQ_BW_L11, PXP2_REG_PSWRQ_BW_ADD11,
- PXP2_REG_PSWRQ_BW_UB11},
- {PXP2_REG_RQ_BW_RD_L12, PXP2_REG_RQ_BW_RD_ADD12,
- PXP2_REG_RQ_BW_RD_UBOUND12},
- {PXP2_REG_RQ_BW_RD_L13, PXP2_REG_RQ_BW_RD_ADD13,
- PXP2_REG_RQ_BW_RD_UBOUND13},
- {PXP2_REG_RQ_BW_RD_L14, PXP2_REG_RQ_BW_RD_ADD14,
- PXP2_REG_RQ_BW_RD_UBOUND14},
- {PXP2_REG_RQ_BW_RD_L15, PXP2_REG_RQ_BW_RD_ADD15,
- PXP2_REG_RQ_BW_RD_UBOUND15},
- {PXP2_REG_RQ_BW_RD_L16, PXP2_REG_RQ_BW_RD_ADD16,
- PXP2_REG_RQ_BW_RD_UBOUND16},
- {PXP2_REG_RQ_BW_RD_L17, PXP2_REG_RQ_BW_RD_ADD17,
- PXP2_REG_RQ_BW_RD_UBOUND17},
- {PXP2_REG_RQ_BW_RD_L18, PXP2_REG_RQ_BW_RD_ADD18,
- PXP2_REG_RQ_BW_RD_UBOUND18},
-/* 20 */{PXP2_REG_RQ_BW_RD_L19, PXP2_REG_RQ_BW_RD_ADD19,
- PXP2_REG_RQ_BW_RD_UBOUND19},
- {PXP2_REG_RQ_BW_RD_L20, PXP2_REG_RQ_BW_RD_ADD20,
- PXP2_REG_RQ_BW_RD_UBOUND20},
- {PXP2_REG_RQ_BW_RD_L22, PXP2_REG_RQ_BW_RD_ADD22,
- PXP2_REG_RQ_BW_RD_UBOUND22},
- {PXP2_REG_RQ_BW_RD_L23, PXP2_REG_RQ_BW_RD_ADD23,
- PXP2_REG_RQ_BW_RD_UBOUND23},
- {PXP2_REG_RQ_BW_RD_L24, PXP2_REG_RQ_BW_RD_ADD24,
- PXP2_REG_RQ_BW_RD_UBOUND24},
- {PXP2_REG_RQ_BW_RD_L25, PXP2_REG_RQ_BW_RD_ADD25,
- PXP2_REG_RQ_BW_RD_UBOUND25},
- {PXP2_REG_RQ_BW_RD_L26, PXP2_REG_RQ_BW_RD_ADD26,
- PXP2_REG_RQ_BW_RD_UBOUND26},
- {PXP2_REG_RQ_BW_RD_L27, PXP2_REG_RQ_BW_RD_ADD27,
- PXP2_REG_RQ_BW_RD_UBOUND27},
- {PXP2_REG_PSWRQ_BW_L28, PXP2_REG_PSWRQ_BW_ADD28,
- PXP2_REG_PSWRQ_BW_UB28}
-};
-
-/* register addresses for write queues */
-static const struct arb_line write_arb_addr[NUM_WR_Q-1] = {
-/* 1 */ {PXP2_REG_PSWRQ_BW_L1, PXP2_REG_PSWRQ_BW_ADD1,
- PXP2_REG_PSWRQ_BW_UB1},
- {PXP2_REG_PSWRQ_BW_L2, PXP2_REG_PSWRQ_BW_ADD2,
- PXP2_REG_PSWRQ_BW_UB2},
- {PXP2_REG_PSWRQ_BW_L3, PXP2_REG_PSWRQ_BW_ADD3,
- PXP2_REG_PSWRQ_BW_UB3},
- {PXP2_REG_PSWRQ_BW_L6, PXP2_REG_PSWRQ_BW_ADD6,
- PXP2_REG_PSWRQ_BW_UB6},
- {PXP2_REG_PSWRQ_BW_L7, PXP2_REG_PSWRQ_BW_ADD7,
- PXP2_REG_PSWRQ_BW_UB7},
- {PXP2_REG_PSWRQ_BW_L8, PXP2_REG_PSWRQ_BW_ADD8,
- PXP2_REG_PSWRQ_BW_UB8},
- {PXP2_REG_PSWRQ_BW_L9, PXP2_REG_PSWRQ_BW_ADD9,
- PXP2_REG_PSWRQ_BW_UB9},
- {PXP2_REG_PSWRQ_BW_L10, PXP2_REG_PSWRQ_BW_ADD10,
- PXP2_REG_PSWRQ_BW_UB10},
- {PXP2_REG_PSWRQ_BW_L11, PXP2_REG_PSWRQ_BW_ADD11,
- PXP2_REG_PSWRQ_BW_UB11},
-/* 10 */{PXP2_REG_PSWRQ_BW_L28, PXP2_REG_PSWRQ_BW_ADD28,
- PXP2_REG_PSWRQ_BW_UB28},
- {PXP2_REG_RQ_BW_WR_L29, PXP2_REG_RQ_BW_WR_ADD29,
- PXP2_REG_RQ_BW_WR_UBOUND29},
- {PXP2_REG_RQ_BW_WR_L30, PXP2_REG_RQ_BW_WR_ADD30,
- PXP2_REG_RQ_BW_WR_UBOUND30}
-};
-
-
-/****************************************************************************
-* CDU
-****************************************************************************/
-
-#define CDU_REGION_NUMBER_XCM_AG 2
-#define CDU_REGION_NUMBER_UCM_AG 4
-
-/**
- * String-to-compress [31:8] = CID (all 24 bits)
- * String-to-compress [7:4] = Region
- * String-to-compress [3:0] = Type
- */
-#define CDU_VALID_DATA(_cid, _region, _type) \
- (((_cid) << 8) | (((_region) & 0xf) << 4) | (((_type) & 0xf)))
-#define CDU_CRC8(_cid, _region, _type) \
- calc_crc8(CDU_VALID_DATA(_cid, _region, _type), 0xff)
-#define CDU_RSRVD_VALUE_TYPE_A(_cid, _region, _type) \
- (0x80 | (CDU_CRC8(_cid, _region, _type) & 0x7f))
-#define CDU_RSRVD_VALUE_TYPE_B(_crc, _type) \
- (0x80 | ((_type) & 0xf << 3) | (CDU_CRC8(_cid, _region, _type) & 0x7))
-#define CDU_RSRVD_INVALIDATE_CONTEXT_VALUE(_val) ((_val) & ~0x80)
-
-
-/* registers addresses are not in order
- so these arrays help simplify the code */
-static const int cm_blocks[9] = {
- MISC_BLOCK, TCM_BLOCK, UCM_BLOCK, CCM_BLOCK, XCM_BLOCK,
- TSEM_BLOCK, USEM_BLOCK, CSEM_BLOCK, XSEM_BLOCK
-};
-
#endif /* BNX2X_INIT_H */
diff --git a/drivers/net/bnx2x_init_ops.h b/drivers/net/bnx2x_init_ops.h
index 32552b9366c..38b970a14fd 100644
--- a/drivers/net/bnx2x_init_ops.h
+++ b/drivers/net/bnx2x_init_ops.h
@@ -11,85 +11,68 @@
* Maintained by: Eilon Greenstein <eilong@broadcom.com>
* Written by: Vladislav Zolotarov <vladz@broadcom.com>
*/
+
#ifndef BNX2X_INIT_OPS_H
#define BNX2X_INIT_OPS_H
-static void bnx2x_reg_wr_ind(struct bnx2x *bp, u32 addr, u32 val);
static int bnx2x_gunzip(struct bnx2x *bp, const u8 *zbuf, int len);
+
static void bnx2x_init_str_wr(struct bnx2x *bp, u32 addr, const u32 *data,
u32 len)
{
- int i;
+ u32 i;
- for (i = 0; i < len; i++) {
+ for (i = 0; i < len; i++)
REG_WR(bp, addr + i*4, data[i]);
- if (!(i % 10000)) {
- touch_softlockup_watchdog();
- cpu_relax();
- }
- }
}
static void bnx2x_init_ind_wr(struct bnx2x *bp, u32 addr, const u32 *data,
- u16 len)
+ u32 len)
{
- int i;
+ u32 i;
- for (i = 0; i < len; i++) {
+ for (i = 0; i < len; i++)
REG_WR_IND(bp, addr + i*4, data[i]);
- if (!(i % 10000)) {
- touch_softlockup_watchdog();
- cpu_relax();
- }
- }
}
static void bnx2x_write_big_buf(struct bnx2x *bp, u32 addr, u32 len)
{
- int offset = 0;
-
- if (bp->dmae_ready) {
- while (len > DMAE_LEN32_WR_MAX) {
- bnx2x_write_dmae(bp, bp->gunzip_mapping + offset,
- addr + offset, DMAE_LEN32_WR_MAX);
- offset += DMAE_LEN32_WR_MAX * 4;
- len -= DMAE_LEN32_WR_MAX;
- }
- bnx2x_write_dmae(bp, bp->gunzip_mapping + offset,
- addr + offset, len);
- } else
- bnx2x_init_str_wr(bp, addr, bp->gunzip_buf, len);
+ if (bp->dmae_ready)
+ bnx2x_write_dmae_phys_len(bp, GUNZIP_PHYS(bp), addr, len);
+ else
+ bnx2x_init_str_wr(bp, addr, GUNZIP_BUF(bp), len);
}
static void bnx2x_init_fill(struct bnx2x *bp, u32 addr, int fill, u32 len)
{
- u32 buf_len = (((len * 4) > FW_BUF_SIZE) ? FW_BUF_SIZE : (len * 4));
- u32 buf_len32 = buf_len / 4;
- int i;
+ u32 buf_len = (((len*4) > FW_BUF_SIZE) ? FW_BUF_SIZE : (len*4));
+ u32 buf_len32 = buf_len/4;
+ u32 i;
- memset(bp->gunzip_buf, fill, buf_len);
+ memset(GUNZIP_BUF(bp), (u8)fill, buf_len);
for (i = 0; i < len; i += buf_len32) {
u32 cur_len = min(buf_len32, len - i);
- bnx2x_write_big_buf(bp, addr + i * 4, cur_len);
+ bnx2x_write_big_buf(bp, addr + i*4, cur_len);
}
}
static void bnx2x_init_wr_64(struct bnx2x *bp, u32 addr, const u32 *data,
u32 len64)
{
- u32 buf_len32 = FW_BUF_SIZE / 4;
- u32 len = len64 * 2;
+ u32 buf_len32 = FW_BUF_SIZE/4;
+ u32 len = len64*2;
u64 data64 = 0;
- int i;
+ u32 i;
/* 64 bit value is in a blob: first low DWORD, then high DWORD */
data64 = HILO_U64((*(data + 1)), (*data));
+
len64 = min((u32)(FW_BUF_SIZE/8), len64);
for (i = 0; i < len64; i++) {
- u64 *pdata = ((u64 *)(bp->gunzip_buf)) + i;
+ u64 *pdata = ((u64 *)(GUNZIP_BUF(bp))) + i;
*pdata = data64;
}
@@ -97,7 +80,7 @@ static void bnx2x_init_wr_64(struct bnx2x *bp, u32 addr, const u32 *data,
for (i = 0; i < len; i += buf_len32) {
u32 cur_len = min(buf_len32, len - i);
- bnx2x_write_big_buf(bp, addr + i * 4, cur_len);
+ bnx2x_write_big_buf(bp, addr + i*4, cur_len);
}
}
@@ -118,97 +101,81 @@ static void bnx2x_init_wr_64(struct bnx2x *bp, u32 addr, const u32 *data,
static const u8 *bnx2x_sel_blob(struct bnx2x *bp, u32 addr, const u8 *data)
{
IF_IS_INT_TABLE_ADDR(TSEM_REG_INT_TABLE, addr)
- data = bp->tsem_int_table_data;
- else IF_IS_INT_TABLE_ADDR(CSEM_REG_INT_TABLE, addr)
- data = bp->csem_int_table_data;
- else IF_IS_INT_TABLE_ADDR(USEM_REG_INT_TABLE, addr)
- data = bp->usem_int_table_data;
- else IF_IS_INT_TABLE_ADDR(XSEM_REG_INT_TABLE, addr)
- data = bp->xsem_int_table_data;
- else IF_IS_PRAM_ADDR(TSEM_REG_PRAM, addr)
- data = bp->tsem_pram_data;
- else IF_IS_PRAM_ADDR(CSEM_REG_PRAM, addr)
- data = bp->csem_pram_data;
- else IF_IS_PRAM_ADDR(USEM_REG_PRAM, addr)
- data = bp->usem_pram_data;
- else IF_IS_PRAM_ADDR(XSEM_REG_PRAM, addr)
- data = bp->xsem_pram_data;
+ data = INIT_TSEM_INT_TABLE_DATA(bp);
+ else
+ IF_IS_INT_TABLE_ADDR(CSEM_REG_INT_TABLE, addr)
+ data = INIT_CSEM_INT_TABLE_DATA(bp);
+ else
+ IF_IS_INT_TABLE_ADDR(USEM_REG_INT_TABLE, addr)
+ data = INIT_USEM_INT_TABLE_DATA(bp);
+ else
+ IF_IS_INT_TABLE_ADDR(XSEM_REG_INT_TABLE, addr)
+ data = INIT_XSEM_INT_TABLE_DATA(bp);
+ else
+ IF_IS_PRAM_ADDR(TSEM_REG_PRAM, addr)
+ data = INIT_TSEM_PRAM_DATA(bp);
+ else
+ IF_IS_PRAM_ADDR(CSEM_REG_PRAM, addr)
+ data = INIT_CSEM_PRAM_DATA(bp);
+ else
+ IF_IS_PRAM_ADDR(USEM_REG_PRAM, addr)
+ data = INIT_USEM_PRAM_DATA(bp);
+ else
+ IF_IS_PRAM_ADDR(XSEM_REG_PRAM, addr)
+ data = INIT_XSEM_PRAM_DATA(bp);
return data;
}
static void bnx2x_write_big_buf_wb(struct bnx2x *bp, u32 addr, u32 len)
{
- int offset = 0;
-
- if (bp->dmae_ready) {
- while (len > DMAE_LEN32_WR_MAX) {
- bnx2x_write_dmae(bp, bp->gunzip_mapping + offset,
- addr + offset, DMAE_LEN32_WR_MAX);
- offset += DMAE_LEN32_WR_MAX * 4;
- len -= DMAE_LEN32_WR_MAX;
- }
- bnx2x_write_dmae(bp, bp->gunzip_mapping + offset,
- addr + offset, len);
- } else
- bnx2x_init_ind_wr(bp, addr, bp->gunzip_buf, len);
+ if (bp->dmae_ready)
+ bnx2x_write_dmae_phys_len(bp, GUNZIP_PHYS(bp), addr, len);
+ else
+ bnx2x_init_ind_wr(bp, addr, GUNZIP_BUF(bp), len);
}
static void bnx2x_init_wr_wb(struct bnx2x *bp, u32 addr, const u32 *data,
u32 len)
{
- /* This is needed for NO_ZIP mode, currently supported
- in little endian mode only */
- data = (const u32*)bnx2x_sel_blob(bp, addr, (const u8*)data);
+ data = (const u32 *)bnx2x_sel_blob(bp, addr, (const u8 *)data);
- if ((len * 4) > FW_BUF_SIZE) {
- BNX2X_ERR("LARGE DMAE OPERATION ! "
- "addr 0x%x len 0x%x\n", addr, len*4);
- return;
- }
- memcpy(bp->gunzip_buf, data, len * 4);
-
- bnx2x_write_big_buf_wb(bp, addr, len);
+ if (bp->dmae_ready)
+ VIRT_WR_DMAE_LEN(bp, data, addr, len);
+ else
+ bnx2x_init_ind_wr(bp, addr, data, len);
}
-static void bnx2x_init_wr_zp(struct bnx2x *bp, u32 addr,
- u32 len, u32 blob_off)
+static void bnx2x_init_wr_zp(struct bnx2x *bp, u32 addr, u32 len, u32 blob_off)
{
- int rc, i;
- const u8 *data = NULL;
+ const u8 *data = NULL;
+ int rc;
+ u32 i;
- data = bnx2x_sel_blob(bp, addr, data) + 4*blob_off;
-
- if (data == NULL) {
- panic("Blob not found for addr 0x%x\n", addr);
- return;
- }
+ data = bnx2x_sel_blob(bp, addr, data) + blob_off*4;
rc = bnx2x_gunzip(bp, data, len);
- if (rc) {
- BNX2X_ERR("gunzip failed ! addr 0x%x rc %d\n", addr, rc);
- BNX2X_ERR("blob_offset=0x%x\n", blob_off);
+ if (rc)
return;
- }
/* gunzip_outlen is in dwords */
- len = bp->gunzip_outlen;
+ len = GUNZIP_OUTLEN(bp);
for (i = 0; i < len; i++)
- ((u32 *)bp->gunzip_buf)[i] =
- cpu_to_le32(((u32 *)bp->gunzip_buf)[i]);
+ ((u32 *)GUNZIP_BUF(bp))[i] =
+ cpu_to_le32(((u32 *)GUNZIP_BUF(bp))[i]);
bnx2x_write_big_buf_wb(bp, addr, len);
}
static void bnx2x_init_block(struct bnx2x *bp, u32 block, u32 stage)
{
- int hw_wr, i;
u16 op_start =
- bp->init_ops_offsets[BLOCK_OPS_IDX(block,stage,STAGE_START)];
+ INIT_OPS_OFFSETS(bp)[BLOCK_OPS_IDX(block, stage, STAGE_START)];
u16 op_end =
- bp->init_ops_offsets[BLOCK_OPS_IDX(block,stage,STAGE_END)];
+ INIT_OPS_OFFSETS(bp)[BLOCK_OPS_IDX(block, stage, STAGE_END)];
union init_op *op;
- u32 op_type, addr, len;
+ int hw_wr;
+ u32 i, op_type, addr, len;
const u32 *data, *data_base;
/* If empty block */
@@ -222,11 +189,11 @@ static void bnx2x_init_block(struct bnx2x *bp, u32 block, u32 stage)
else
hw_wr = OP_WR_ASIC;
- data_base = bp->init_data;
+ data_base = INIT_DATA(bp);
for (i = op_start; i < op_end; i++) {
- op = (union init_op *)&(bp->init_ops[i]);
+ op = (union init_op *)&(INIT_OPS(bp)[i]);
op_type = op->str_wr.op;
addr = op->str_wr.offset;
@@ -234,7 +201,7 @@ static void bnx2x_init_block(struct bnx2x *bp, u32 block, u32 stage)
data = data_base + op->str_wr.data_off;
/* HW/EMUL specific */
- if (unlikely((op_type > OP_WB) && (op_type == hw_wr)))
+ if ((op_type > OP_WB) && (op_type == hw_wr))
op_type = OP_WR;
switch (op_type) {
@@ -265,35 +232,179 @@ static void bnx2x_init_block(struct bnx2x *bp, u32 block, u32 stage)
break;
default:
/* happens whenever an op is of a diff HW */
-#if 0
- DP(NETIF_MSG_HW, "skipping init operation "
- "index %d[%d:%d]: type %d addr 0x%x "
- "len %d(0x%x)\n",
- i, op_start, op_end, op_type, addr, len, len);
-#endif
break;
}
}
}
-/* PXP */
-static void bnx2x_init_pxp(struct bnx2x *bp)
+
+/****************************************************************************
+* PXP Arbiter
+****************************************************************************/
+/*
+ * This code configures the PCI read/write arbiter
+ * which implements a weighted round robin
+ * between the virtual queues in the chip.
+ *
+ * The values were derived for each PCI max payload and max request size.
+ * since max payload and max request size are only known at run time,
+ * this is done as a separate init stage.
+ */
+
+#define NUM_WR_Q 13
+#define NUM_RD_Q 29
+#define MAX_RD_ORD 3
+#define MAX_WR_ORD 2
+
+/* configuration for one arbiter queue */
+struct arb_line {
+ int l;
+ int add;
+ int ubound;
+};
+
+/* derived configuration for each read queue for each max request size */
+static const struct arb_line read_arb_data[NUM_RD_Q][MAX_RD_ORD + 1] = {
+/* 1 */ { {8, 64, 25}, {16, 64, 25}, {32, 64, 25}, {64, 64, 41} },
+ { {4, 8, 4}, {4, 8, 4}, {4, 8, 4}, {4, 8, 4} },
+ { {4, 3, 3}, {4, 3, 3}, {4, 3, 3}, {4, 3, 3} },
+ { {8, 3, 6}, {16, 3, 11}, {16, 3, 11}, {16, 3, 11} },
+ { {8, 64, 25}, {16, 64, 25}, {32, 64, 25}, {64, 64, 41} },
+ { {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {64, 3, 41} },
+ { {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {64, 3, 41} },
+ { {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {64, 3, 41} },
+ { {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {64, 3, 41} },
+/* 10 */{ {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {32, 3, 21} },
+ { {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {32, 3, 21} },
+ { {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {32, 3, 21} },
+ { {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {32, 3, 21} },
+ { {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {32, 3, 21} },
+ { {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {32, 3, 21} },
+ { {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {32, 3, 21} },
+ { {8, 64, 6}, {16, 64, 11}, {32, 64, 21}, {32, 64, 21} },
+ { {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {32, 3, 21} },
+ { {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {32, 3, 21} },
+/* 20 */{ {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {32, 3, 21} },
+ { {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {32, 3, 21} },
+ { {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {32, 3, 21} },
+ { {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {32, 3, 21} },
+ { {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {32, 3, 21} },
+ { {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {32, 3, 21} },
+ { {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {32, 3, 21} },
+ { {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {32, 3, 21} },
+ { {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {32, 3, 21} },
+ { {8, 64, 25}, {16, 64, 41}, {32, 64, 81}, {64, 64, 120} }
+};
+
+/* derived configuration for each write queue for each max request size */
+static const struct arb_line write_arb_data[NUM_WR_Q][MAX_WR_ORD + 1] = {
+/* 1 */ { {4, 6, 3}, {4, 6, 3}, {4, 6, 3} },
+ { {4, 2, 3}, {4, 2, 3}, {4, 2, 3} },
+ { {8, 2, 6}, {16, 2, 11}, {16, 2, 11} },
+ { {8, 2, 6}, {16, 2, 11}, {32, 2, 21} },
+ { {8, 2, 6}, {16, 2, 11}, {32, 2, 21} },
+ { {8, 2, 6}, {16, 2, 11}, {32, 2, 21} },
+ { {8, 64, 25}, {16, 64, 25}, {32, 64, 25} },
+ { {8, 2, 6}, {16, 2, 11}, {16, 2, 11} },
+ { {8, 2, 6}, {16, 2, 11}, {16, 2, 11} },
+/* 10 */{ {8, 9, 6}, {16, 9, 11}, {32, 9, 21} },
+ { {8, 47, 19}, {16, 47, 19}, {32, 47, 21} },
+ { {8, 9, 6}, {16, 9, 11}, {16, 9, 11} },
+ { {8, 64, 25}, {16, 64, 41}, {32, 64, 81} }
+};
+
+/* register addresses for read queues */
+static const struct arb_line read_arb_addr[NUM_RD_Q-1] = {
+/* 1 */ {PXP2_REG_RQ_BW_RD_L0, PXP2_REG_RQ_BW_RD_ADD0,
+ PXP2_REG_RQ_BW_RD_UBOUND0},
+ {PXP2_REG_PSWRQ_BW_L1, PXP2_REG_PSWRQ_BW_ADD1,
+ PXP2_REG_PSWRQ_BW_UB1},
+ {PXP2_REG_PSWRQ_BW_L2, PXP2_REG_PSWRQ_BW_ADD2,
+ PXP2_REG_PSWRQ_BW_UB2},
+ {PXP2_REG_PSWRQ_BW_L3, PXP2_REG_PSWRQ_BW_ADD3,
+ PXP2_REG_PSWRQ_BW_UB3},
+ {PXP2_REG_RQ_BW_RD_L4, PXP2_REG_RQ_BW_RD_ADD4,
+ PXP2_REG_RQ_BW_RD_UBOUND4},
+ {PXP2_REG_RQ_BW_RD_L5, PXP2_REG_RQ_BW_RD_ADD5,
+ PXP2_REG_RQ_BW_RD_UBOUND5},
+ {PXP2_REG_PSWRQ_BW_L6, PXP2_REG_PSWRQ_BW_ADD6,
+ PXP2_REG_PSWRQ_BW_UB6},
+ {PXP2_REG_PSWRQ_BW_L7, PXP2_REG_PSWRQ_BW_ADD7,
+ PXP2_REG_PSWRQ_BW_UB7},
+ {PXP2_REG_PSWRQ_BW_L8, PXP2_REG_PSWRQ_BW_ADD8,
+ PXP2_REG_PSWRQ_BW_UB8},
+/* 10 */{PXP2_REG_PSWRQ_BW_L9, PXP2_REG_PSWRQ_BW_ADD9,
+ PXP2_REG_PSWRQ_BW_UB9},
+ {PXP2_REG_PSWRQ_BW_L10, PXP2_REG_PSWRQ_BW_ADD10,
+ PXP2_REG_PSWRQ_BW_UB10},
+ {PXP2_REG_PSWRQ_BW_L11, PXP2_REG_PSWRQ_BW_ADD11,
+ PXP2_REG_PSWRQ_BW_UB11},
+ {PXP2_REG_RQ_BW_RD_L12, PXP2_REG_RQ_BW_RD_ADD12,
+ PXP2_REG_RQ_BW_RD_UBOUND12},
+ {PXP2_REG_RQ_BW_RD_L13, PXP2_REG_RQ_BW_RD_ADD13,
+ PXP2_REG_RQ_BW_RD_UBOUND13},
+ {PXP2_REG_RQ_BW_RD_L14, PXP2_REG_RQ_BW_RD_ADD14,
+ PXP2_REG_RQ_BW_RD_UBOUND14},
+ {PXP2_REG_RQ_BW_RD_L15, PXP2_REG_RQ_BW_RD_ADD15,
+ PXP2_REG_RQ_BW_RD_UBOUND15},
+ {PXP2_REG_RQ_BW_RD_L16, PXP2_REG_RQ_BW_RD_ADD16,
+ PXP2_REG_RQ_BW_RD_UBOUND16},
+ {PXP2_REG_RQ_BW_RD_L17, PXP2_REG_RQ_BW_RD_ADD17,
+ PXP2_REG_RQ_BW_RD_UBOUND17},
+ {PXP2_REG_RQ_BW_RD_L18, PXP2_REG_RQ_BW_RD_ADD18,
+ PXP2_REG_RQ_BW_RD_UBOUND18},
+/* 20 */{PXP2_REG_RQ_BW_RD_L19, PXP2_REG_RQ_BW_RD_ADD19,
+ PXP2_REG_RQ_BW_RD_UBOUND19},
+ {PXP2_REG_RQ_BW_RD_L20, PXP2_REG_RQ_BW_RD_ADD20,
+ PXP2_REG_RQ_BW_RD_UBOUND20},
+ {PXP2_REG_RQ_BW_RD_L22, PXP2_REG_RQ_BW_RD_ADD22,
+ PXP2_REG_RQ_BW_RD_UBOUND22},
+ {PXP2_REG_RQ_BW_RD_L23, PXP2_REG_RQ_BW_RD_ADD23,
+ PXP2_REG_RQ_BW_RD_UBOUND23},
+ {PXP2_REG_RQ_BW_RD_L24, PXP2_REG_RQ_BW_RD_ADD24,
+ PXP2_REG_RQ_BW_RD_UBOUND24},
+ {PXP2_REG_RQ_BW_RD_L25, PXP2_REG_RQ_BW_RD_ADD25,
+ PXP2_REG_RQ_BW_RD_UBOUND25},
+ {PXP2_REG_RQ_BW_RD_L26, PXP2_REG_RQ_BW_RD_ADD26,
+ PXP2_REG_RQ_BW_RD_UBOUND26},
+ {PXP2_REG_RQ_BW_RD_L27, PXP2_REG_RQ_BW_RD_ADD27,
+ PXP2_REG_RQ_BW_RD_UBOUND27},
+ {PXP2_REG_PSWRQ_BW_L28, PXP2_REG_PSWRQ_BW_ADD28,
+ PXP2_REG_PSWRQ_BW_UB28}
+};
+
+/* register addresses for write queues */
+static const struct arb_line write_arb_addr[NUM_WR_Q-1] = {
+/* 1 */ {PXP2_REG_PSWRQ_BW_L1, PXP2_REG_PSWRQ_BW_ADD1,
+ PXP2_REG_PSWRQ_BW_UB1},
+ {PXP2_REG_PSWRQ_BW_L2, PXP2_REG_PSWRQ_BW_ADD2,
+ PXP2_REG_PSWRQ_BW_UB2},
+ {PXP2_REG_PSWRQ_BW_L3, PXP2_REG_PSWRQ_BW_ADD3,
+ PXP2_REG_PSWRQ_BW_UB3},
+ {PXP2_REG_PSWRQ_BW_L6, PXP2_REG_PSWRQ_BW_ADD6,
+ PXP2_REG_PSWRQ_BW_UB6},
+ {PXP2_REG_PSWRQ_BW_L7, PXP2_REG_PSWRQ_BW_ADD7,
+ PXP2_REG_PSWRQ_BW_UB7},
+ {PXP2_REG_PSWRQ_BW_L8, PXP2_REG_PSWRQ_BW_ADD8,
+ PXP2_REG_PSWRQ_BW_UB8},
+ {PXP2_REG_PSWRQ_BW_L9, PXP2_REG_PSWRQ_BW_ADD9,
+ PXP2_REG_PSWRQ_BW_UB9},
+ {PXP2_REG_PSWRQ_BW_L10, PXP2_REG_PSWRQ_BW_ADD10,
+ PXP2_REG_PSWRQ_BW_UB10},
+ {PXP2_REG_PSWRQ_BW_L11, PXP2_REG_PSWRQ_BW_ADD11,
+ PXP2_REG_PSWRQ_BW_UB11},
+/* 10 */{PXP2_REG_PSWRQ_BW_L28, PXP2_REG_PSWRQ_BW_ADD28,
+ PXP2_REG_PSWRQ_BW_UB28},
+ {PXP2_REG_RQ_BW_WR_L29, PXP2_REG_RQ_BW_WR_ADD29,
+ PXP2_REG_RQ_BW_WR_UBOUND29},
+ {PXP2_REG_RQ_BW_WR_L30, PXP2_REG_RQ_BW_WR_ADD30,
+ PXP2_REG_RQ_BW_WR_UBOUND30}
+};
+
+static void bnx2x_init_pxp_arb(struct bnx2x *bp, int r_order, int w_order)
{
- u16 devctl;
- int r_order, w_order;
u32 val, i;
- pci_read_config_word(bp->pdev,
- bp->pcie_cap + PCI_EXP_DEVCTL, &devctl);
- DP(NETIF_MSG_HW, "read 0x%x from devctl\n", devctl);
- w_order = ((devctl & PCI_EXP_DEVCTL_PAYLOAD) >> 5);
- if (bp->mrrs == -1)
- r_order = ((devctl & PCI_EXP_DEVCTL_READRQ) >> 12);
- else {
- DP(NETIF_MSG_HW, "force read order to %d\n", bp->mrrs);
- r_order = bp->mrrs;
- }
-
if (r_order > MAX_RD_ORD) {
DP(NETIF_MSG_HW, "read order of %d order adjusted to %d\n",
r_order, MAX_RD_ORD);
@@ -367,6 +478,11 @@ static void bnx2x_init_pxp(struct bnx2x *bp)
REG_WR(bp, PXP2_REG_WR_USDMDP_TH, (0x18 << w_order));
if (CHIP_IS_E1H(bp)) {
+ /* MPS w_order optimal TH presently TH
+ * 128 0 0 2
+ * 256 1 1 3
+ * >=512 2 2 3
+ */
val = ((w_order == 0) ? 2 : 3);
REG_WR(bp, PXP2_REG_WR_HC_MPS, val);
REG_WR(bp, PXP2_REG_WR_USDM_MPS, val);
@@ -382,61 +498,4 @@ static void bnx2x_init_pxp(struct bnx2x *bp)
}
}
-/*****************************************************************************
- * Description:
- * Calculates crc 8 on a word value: polynomial 0-1-2-8
- * Code was translated from Verilog.
- ****************************************************************************/
-static u8 calc_crc8(u32 data, u8 crc)
-{
- u8 D[32];
- u8 NewCRC[8];
- u8 C[8];
- u8 crc_res;
- u8 i;
-
- /* split the data into 31 bits */
- for (i = 0; i < 32; i++) {
- D[i] = data & 1;
- data = data >> 1;
- }
-
- /* split the crc into 8 bits */
- for (i = 0; i < 8; i++) {
- C[i] = crc & 1;
- crc = crc >> 1;
- }
-
- NewCRC[0] = D[31] ^ D[30] ^ D[28] ^ D[23] ^ D[21] ^ D[19] ^ D[18] ^
- D[16] ^ D[14] ^ D[12] ^ D[8] ^ D[7] ^ D[6] ^ D[0] ^ C[4] ^
- C[6] ^ C[7];
- NewCRC[1] = D[30] ^ D[29] ^ D[28] ^ D[24] ^ D[23] ^ D[22] ^ D[21] ^
- D[20] ^ D[18] ^ D[17] ^ D[16] ^ D[15] ^ D[14] ^ D[13] ^
- D[12] ^ D[9] ^ D[6] ^ D[1] ^ D[0] ^ C[0] ^ C[4] ^ C[5] ^ C[6];
- NewCRC[2] = D[29] ^ D[28] ^ D[25] ^ D[24] ^ D[22] ^ D[17] ^ D[15] ^
- D[13] ^ D[12] ^ D[10] ^ D[8] ^ D[6] ^ D[2] ^ D[1] ^ D[0] ^
- C[0] ^ C[1] ^ C[4] ^ C[5];
- NewCRC[3] = D[30] ^ D[29] ^ D[26] ^ D[25] ^ D[23] ^ D[18] ^ D[16] ^
- D[14] ^ D[13] ^ D[11] ^ D[9] ^ D[7] ^ D[3] ^ D[2] ^ D[1] ^
- C[1] ^ C[2] ^ C[5] ^ C[6];
- NewCRC[4] = D[31] ^ D[30] ^ D[27] ^ D[26] ^ D[24] ^ D[19] ^ D[17] ^
- D[15] ^ D[14] ^ D[12] ^ D[10] ^ D[8] ^ D[4] ^ D[3] ^ D[2] ^
- C[0] ^ C[2] ^ C[3] ^ C[6] ^ C[7];
- NewCRC[5] = D[31] ^ D[28] ^ D[27] ^ D[25] ^ D[20] ^ D[18] ^ D[16] ^
- D[15] ^ D[13] ^ D[11] ^ D[9] ^ D[5] ^ D[4] ^ D[3] ^ C[1] ^
- C[3] ^ C[4] ^ C[7];
- NewCRC[6] = D[29] ^ D[28] ^ D[26] ^ D[21] ^ D[19] ^ D[17] ^ D[16] ^
- D[14] ^ D[12] ^ D[10] ^ D[6] ^ D[5] ^ D[4] ^ C[2] ^ C[4] ^
- C[5];
- NewCRC[7] = D[30] ^ D[29] ^ D[27] ^ D[22] ^ D[20] ^ D[18] ^ D[17] ^
- D[15] ^ D[13] ^ D[11] ^ D[7] ^ D[6] ^ D[5] ^ C[3] ^ C[5] ^
- C[6];
-
- crc_res = 0;
- for (i = 0; i < 8; i++)
- crc_res |= (NewCRC[i] << i);
-
- return crc_res;
-}
-
#endif /* BNX2X_INIT_OPS_H */
diff --git a/drivers/net/bnx2x_link.c b/drivers/net/bnx2x_link.c
index 2ee581a2cde..e32d3370862 100644
--- a/drivers/net/bnx2x_link.c
+++ b/drivers/net/bnx2x_link.c
@@ -37,6 +37,10 @@
/* Shortcut definitions */
/***********************************************************/
+#define NIG_LATCH_BC_ENABLE_MI_INT 0
+
+#define NIG_STATUS_EMAC0_MI_INT \
+ NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_EMAC0_MISC_MI_INT
#define NIG_STATUS_XGXS0_LINK10G \
NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_XGXS0_LINK10G
#define NIG_STATUS_XGXS0_LINK_STATUS \
@@ -139,21 +143,26 @@
#define SFP_EEPROM_CON_TYPE_VAL_LC 0x7
#define SFP_EEPROM_CON_TYPE_VAL_COPPER 0x21
+
+#define SFP_EEPROM_COMP_CODE_ADDR 0x3
+ #define SFP_EEPROM_COMP_CODE_SR_MASK (1<<4)
+ #define SFP_EEPROM_COMP_CODE_LR_MASK (1<<5)
+ #define SFP_EEPROM_COMP_CODE_LRM_MASK (1<<6)
+
#define SFP_EEPROM_FC_TX_TECH_ADDR 0x8
#define SFP_EEPROM_FC_TX_TECH_BITMASK_COPPER_PASSIVE 0x4
#define SFP_EEPROM_FC_TX_TECH_BITMASK_COPPER_ACTIVE 0x8
-#define SFP_EEPROM_VENDOR_NAME_ADDR 0x14
-#define SFP_EEPROM_VENDOR_NAME_SIZE 16
+
#define SFP_EEPROM_OPTIONS_ADDR 0x40
#define SFP_EEPROM_OPTIONS_LINEAR_RX_OUT_MASK 0x1
#define SFP_EEPROM_OPTIONS_SIZE 2
-#define SFP_MODULE_TYPE_UNKNOWN 0x0
-#define SFP_MODULE_TYPE_LC 0x1
-#define SFP_MODULE_TYPE_ACTIVE_COPPER_CABLE 0x2
-#define SFP_MODULE_TYPE_PASSIVE_COPPER_CABLE 0x3
+#define EDC_MODE_LINEAR 0x0022
+#define EDC_MODE_LIMITING 0x0044
+#define EDC_MODE_PASSIVE_DAC 0x0055
+
+
-#define SFP_LIMITING_MODE_VALUE 0x0044
/**********************************************************/
/* INTERFACE */
/**********************************************************/
@@ -173,6 +182,7 @@ static void bnx2x_set_serdes_access(struct link_params *params)
{
struct bnx2x *bp = params->bp;
u32 emac_base = (params->port) ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
+
/* Set Clause 22 */
REG_WR(bp, NIG_REG_SERDES0_CTRL_MD_ST + params->port*0x10, 1);
REG_WR(bp, emac_base + EMAC_REG_EMAC_MDIO_COMM, 0x245f8000);
@@ -185,6 +195,7 @@ static void bnx2x_set_serdes_access(struct link_params *params)
static void bnx2x_set_phy_mdio(struct link_params *params, u8 phy_flags)
{
struct bnx2x *bp = params->bp;
+
if (phy_flags & PHY_XGXS_FLAG) {
REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_ST +
params->port*0x18, 0);
@@ -388,7 +399,8 @@ static u8 bnx2x_emac_enable(struct link_params *params,
/* enable access for bmac registers */
REG_WR(bp, NIG_REG_BMAC0_REGS_OUT_EN + port*4, 0x1);
- }
+ } else
+ REG_WR(bp, NIG_REG_BMAC0_REGS_OUT_EN + port*4, 0x0);
vars->mac_type = MAC_TYPE_EMAC;
return 0;
@@ -455,7 +467,6 @@ static u8 bnx2x_bmac_enable(struct link_params *params, struct link_vars *vars,
REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_BMAC_CONTROL,
wb_data, 2);
-
/* set rx mtu */
wb_data[0] = ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVREHEAD;
wb_data[1] = 0;
@@ -674,6 +685,7 @@ void bnx2x_link_status_update(struct link_params *params,
static void bnx2x_update_mng(struct link_params *params, u32 link_status)
{
struct bnx2x *bp = params->bp;
+
REG_WR(bp, params->shmem_base +
offsetof(struct shmem_region,
port_mb[params->port].link_status),
@@ -770,7 +782,6 @@ static u8 bnx2x_pbf_update(struct link_params *params, u32 flow_ctrl,
DP(NETIF_MSG_LINK, "Invalid line_speed 0x%x\n",
line_speed);
return -EINVAL;
- break;
}
}
REG_WR(bp, PBF_REG_P0_INIT_CRD + port*4, init_crd);
@@ -790,9 +801,11 @@ static u8 bnx2x_pbf_update(struct link_params *params, u32 flow_ctrl,
static u32 bnx2x_get_emac_base(struct bnx2x *bp, u32 ext_phy_type, u8 port)
{
u32 emac_base;
+
switch (ext_phy_type) {
case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072:
case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726:
+ case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727:
/* All MDC/MDIO is directed through single EMAC */
if (REG_RD(bp, NIG_REG_PORT_SWAP))
emac_base = GRCBASE_EMAC0;
@@ -894,7 +907,7 @@ u8 bnx2x_cl45_read(struct bnx2x *bp, u8 port, u32 ext_phy_type,
val = saved_mode & ((EMAC_MDIO_MODE_AUTO_POLL |
EMAC_MDIO_MODE_CLOCK_CNT));
val |= (EMAC_MDIO_MODE_CLAUSE_45 |
- (49 << EMAC_MDIO_MODE_CLOCK_CNT_BITSHIFT));
+ (49L << EMAC_MDIO_MODE_CLOCK_CNT_BITSHIFT));
REG_WR(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE, val);
REG_RD(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE);
udelay(40);
@@ -1011,8 +1024,8 @@ static u8 bnx2x_reset_unicore(struct link_params *params)
MDIO_COMBO_IEEE0_MII_CONTROL,
(mii_control |
MDIO_COMBO_IEEO_MII_CONTROL_RESET));
-
- bnx2x_set_serdes_access(params);
+ if (params->switch_cfg == SWITCH_CFG_1G)
+ bnx2x_set_serdes_access(params);
/* wait for the reset to self clear */
for (i = 0; i < MDIO_ACCESS_TIMEOUT; i++) {
@@ -1141,7 +1154,8 @@ static void bnx2x_set_parallel_detection(struct link_params *params,
}
static void bnx2x_set_autoneg(struct link_params *params,
- struct link_vars *vars)
+ struct link_vars *vars,
+ u8 enable_cl73)
{
struct bnx2x *bp = params->bp;
u16 reg_val;
@@ -1171,7 +1185,9 @@ static void bnx2x_set_autoneg(struct link_params *params,
params->phy_addr,
MDIO_REG_BANK_SERDES_DIGITAL,
MDIO_SERDES_DIGITAL_A_1000X_CONTROL1, &reg_val);
- reg_val &= ~MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_SIGNAL_DETECT_EN;
+ reg_val &= ~(MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_SIGNAL_DETECT_EN |
+ MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_INVERT_SIGNAL_DETECT);
+ reg_val |= MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_FIBER_MODE;
if (vars->line_speed == SPEED_AUTO_NEG)
reg_val |= MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_AUTODET;
else
@@ -1203,8 +1219,51 @@ static void bnx2x_set_autoneg(struct link_params *params,
MDIO_BAM_NEXT_PAGE_MP5_NEXT_PAGE_CTRL,
reg_val);
- /* CL73 Autoneg Disabled */
- reg_val = 0;
+ if (enable_cl73) {
+ /* Enable Cl73 FSM status bits */
+ CL45_WR_OVER_CL22(bp, params->port,
+ params->phy_addr,
+ MDIO_REG_BANK_CL73_USERB0,
+ MDIO_CL73_USERB0_CL73_UCTRL,
+ MDIO_CL73_USERB0_CL73_UCTRL_USTAT1_MUXSEL);
+
+ /* Enable BAM Station Manager*/
+ CL45_WR_OVER_CL22(bp, params->port,
+ params->phy_addr,
+ MDIO_REG_BANK_CL73_USERB0,
+ MDIO_CL73_USERB0_CL73_BAM_CTRL1,
+ MDIO_CL73_USERB0_CL73_BAM_CTRL1_BAM_EN |
+ MDIO_CL73_USERB0_CL73_BAM_CTRL1_BAM_STATION_MNGR_EN |
+ MDIO_CL73_USERB0_CL73_BAM_CTRL1_BAM_NP_AFTER_BP_EN);
+
+ /* Merge CL73 and CL37 aneg resolution */
+ CL45_RD_OVER_CL22(bp, params->port,
+ params->phy_addr,
+ MDIO_REG_BANK_CL73_USERB0,
+ MDIO_CL73_USERB0_CL73_BAM_CTRL3,
+ &reg_val);
+
+ if (params->speed_cap_mask &
+ PORT_HW_CFG_SPEED_CAPABILITY_D0_10G) {
+ /* Set the CL73 AN speed */
+ CL45_RD_OVER_CL22(bp, params->port,
+ params->phy_addr,
+ MDIO_REG_BANK_CL73_IEEEB1,
+ MDIO_CL73_IEEEB1_AN_ADV2,
+ &reg_val);
+
+ CL45_WR_OVER_CL22(bp, params->port,
+ params->phy_addr,
+ MDIO_REG_BANK_CL73_IEEEB1,
+ MDIO_CL73_IEEEB1_AN_ADV2,
+ reg_val | MDIO_CL73_IEEEB1_AN_ADV2_ADVR_10G_KX4);
+
+ }
+ /* CL73 Autoneg Enabled */
+ reg_val = MDIO_CL73_IEEEB0_CL73_AN_CONTROL_AN_EN;
+
+ } else /* CL73 Autoneg Disabled */
+ reg_val = 0;
CL45_WR_OVER_CL22(bp, params->port,
params->phy_addr,
@@ -1219,14 +1278,14 @@ static void bnx2x_program_serdes(struct link_params *params,
struct bnx2x *bp = params->bp;
u16 reg_val;
- /* program duplex, disable autoneg */
-
+ /* program duplex, disable autoneg and sgmii*/
CL45_RD_OVER_CL22(bp, params->port,
params->phy_addr,
MDIO_REG_BANK_COMBO_IEEE0,
MDIO_COMBO_IEEE0_MII_CONTROL, &reg_val);
reg_val &= ~(MDIO_COMBO_IEEO_MII_CONTROL_FULL_DUPLEX |
- MDIO_COMBO_IEEO_MII_CONTROL_AN_EN);
+ MDIO_COMBO_IEEO_MII_CONTROL_AN_EN |
+ MDIO_COMBO_IEEO_MII_CONTROL_MAN_SGMII_SP_MASK);
if (params->req_duplex == DUPLEX_FULL)
reg_val |= MDIO_COMBO_IEEO_MII_CONTROL_FULL_DUPLEX;
CL45_WR_OVER_CL22(bp, params->port,
@@ -1287,10 +1346,10 @@ static void bnx2x_set_brcm_cl37_advertisment(struct link_params *params)
CL45_WR_OVER_CL22(bp, params->port,
params->phy_addr,
MDIO_REG_BANK_OVER_1G,
- MDIO_OVER_1G_UP3, 0);
+ MDIO_OVER_1G_UP3, 0x400);
}
-static void bnx2x_calc_ieee_aneg_adv(struct link_params *params, u32 *ieee_fc)
+static void bnx2x_calc_ieee_aneg_adv(struct link_params *params, u16 *ieee_fc)
{
*ieee_fc = MDIO_COMBO_IEEE0_AUTO_NEG_ADV_FULL_DUPLEX;
/* resolve pause mode and advertisement
@@ -1324,7 +1383,7 @@ static void bnx2x_calc_ieee_aneg_adv(struct link_params *params, u32 *ieee_fc)
}
static void bnx2x_set_ieee_aneg_advertisment(struct link_params *params,
- u32 ieee_fc)
+ u16 ieee_fc)
{
struct bnx2x *bp = params->bp;
/* for AN, we are always publishing full duplex */
@@ -1332,31 +1391,49 @@ static void bnx2x_set_ieee_aneg_advertisment(struct link_params *params,
CL45_WR_OVER_CL22(bp, params->port,
params->phy_addr,
MDIO_REG_BANK_COMBO_IEEE0,
- MDIO_COMBO_IEEE0_AUTO_NEG_ADV, (u16)ieee_fc);
+ MDIO_COMBO_IEEE0_AUTO_NEG_ADV, ieee_fc);
}
-static void bnx2x_restart_autoneg(struct link_params *params)
+static void bnx2x_restart_autoneg(struct link_params *params, u8 enable_cl73)
{
struct bnx2x *bp = params->bp;
u16 mii_control;
+
DP(NETIF_MSG_LINK, "bnx2x_restart_autoneg\n");
/* Enable and restart BAM/CL37 aneg */
- CL45_RD_OVER_CL22(bp, params->port,
- params->phy_addr,
- MDIO_REG_BANK_COMBO_IEEE0,
- MDIO_COMBO_IEEE0_MII_CONTROL,
- &mii_control);
- DP(NETIF_MSG_LINK,
- "bnx2x_restart_autoneg mii_control before = 0x%x\n",
- mii_control);
- CL45_WR_OVER_CL22(bp, params->port,
- params->phy_addr,
- MDIO_REG_BANK_COMBO_IEEE0,
- MDIO_COMBO_IEEE0_MII_CONTROL,
- (mii_control |
- MDIO_COMBO_IEEO_MII_CONTROL_AN_EN |
- MDIO_COMBO_IEEO_MII_CONTROL_RESTART_AN));
+ if (enable_cl73) {
+ CL45_RD_OVER_CL22(bp, params->port,
+ params->phy_addr,
+ MDIO_REG_BANK_CL73_IEEEB0,
+ MDIO_CL73_IEEEB0_CL73_AN_CONTROL,
+ &mii_control);
+
+ CL45_WR_OVER_CL22(bp, params->port,
+ params->phy_addr,
+ MDIO_REG_BANK_CL73_IEEEB0,
+ MDIO_CL73_IEEEB0_CL73_AN_CONTROL,
+ (mii_control |
+ MDIO_CL73_IEEEB0_CL73_AN_CONTROL_AN_EN |
+ MDIO_CL73_IEEEB0_CL73_AN_CONTROL_RESTART_AN));
+ } else {
+
+ CL45_RD_OVER_CL22(bp, params->port,
+ params->phy_addr,
+ MDIO_REG_BANK_COMBO_IEEE0,
+ MDIO_COMBO_IEEE0_MII_CONTROL,
+ &mii_control);
+ DP(NETIF_MSG_LINK,
+ "bnx2x_restart_autoneg mii_control before = 0x%x\n",
+ mii_control);
+ CL45_WR_OVER_CL22(bp, params->port,
+ params->phy_addr,
+ MDIO_REG_BANK_COMBO_IEEE0,
+ MDIO_COMBO_IEEE0_MII_CONTROL,
+ (mii_control |
+ MDIO_COMBO_IEEO_MII_CONTROL_AN_EN |
+ MDIO_COMBO_IEEO_MII_CONTROL_RESTART_AN));
+ }
}
static void bnx2x_initialize_sgmii_process(struct link_params *params,
@@ -1428,7 +1505,7 @@ static void bnx2x_initialize_sgmii_process(struct link_params *params,
} else { /* AN mode */
/* enable and restart AN */
- bnx2x_restart_autoneg(params);
+ bnx2x_restart_autoneg(params, 0);
}
}
@@ -1460,22 +1537,19 @@ static void bnx2x_pause_resolve(struct link_vars *vars, u32 pause_result)
}
}
-static u8 bnx2x_ext_phy_resove_fc(struct link_params *params,
+static u8 bnx2x_ext_phy_resolve_fc(struct link_params *params,
struct link_vars *vars)
{
struct bnx2x *bp = params->bp;
u8 ext_phy_addr;
- u16 ld_pause; /* local */
- u16 lp_pause; /* link partner */
- u16 an_complete; /* AN complete */
+ u16 ld_pause; /* local */
+ u16 lp_pause; /* link partner */
+ u16 an_complete; /* AN complete */
u16 pause_result;
u8 ret = 0;
u32 ext_phy_type;
u8 port = params->port;
- ext_phy_addr = ((params->ext_phy_config &
- PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
- PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
-
+ ext_phy_addr = XGXS_EXT_PHY_ADDR(params->ext_phy_config);
ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
/* read twice */
@@ -1570,7 +1644,7 @@ static void bnx2x_flow_ctrl_resolve(struct link_params *params,
DP(NETIF_MSG_LINK, "pause_result 0x%x\n", pause_result);
bnx2x_pause_resolve(vars, pause_result);
} else if ((params->req_flow_ctrl == BNX2X_FLOW_CTRL_AUTO) &&
- (bnx2x_ext_phy_resove_fc(params, vars))) {
+ (bnx2x_ext_phy_resolve_fc(params, vars))) {
return;
} else {
if (params->req_flow_ctrl == BNX2X_FLOW_CTRL_AUTO)
@@ -1581,10 +1655,77 @@ static void bnx2x_flow_ctrl_resolve(struct link_params *params,
DP(NETIF_MSG_LINK, "flow_ctrl 0x%x\n", vars->flow_ctrl);
}
-
+static void bnx2x_check_fallback_to_cl37(struct link_params *params)
+{
+ struct bnx2x *bp = params->bp;
+ u16 rx_status, ustat_val, cl37_fsm_recieved;
+ DP(NETIF_MSG_LINK, "bnx2x_check_fallback_to_cl37\n");
+ /* Step 1: Make sure signal is detected */
+ CL45_RD_OVER_CL22(bp, params->port,
+ params->phy_addr,
+ MDIO_REG_BANK_RX0,
+ MDIO_RX0_RX_STATUS,
+ &rx_status);
+ if ((rx_status & MDIO_RX0_RX_STATUS_SIGDET) !=
+ (MDIO_RX0_RX_STATUS_SIGDET)) {
+ DP(NETIF_MSG_LINK, "Signal is not detected. Restoring CL73."
+ "rx_status(0x80b0) = 0x%x\n", rx_status);
+ CL45_WR_OVER_CL22(bp, params->port,
+ params->phy_addr,
+ MDIO_REG_BANK_CL73_IEEEB0,
+ MDIO_CL73_IEEEB0_CL73_AN_CONTROL,
+ MDIO_CL73_IEEEB0_CL73_AN_CONTROL_AN_EN);
+ return;
+ }
+ /* Step 2: Check CL73 state machine */
+ CL45_RD_OVER_CL22(bp, params->port,
+ params->phy_addr,
+ MDIO_REG_BANK_CL73_USERB0,
+ MDIO_CL73_USERB0_CL73_USTAT1,
+ &ustat_val);
+ if ((ustat_val &
+ (MDIO_CL73_USERB0_CL73_USTAT1_LINK_STATUS_CHECK |
+ MDIO_CL73_USERB0_CL73_USTAT1_AN_GOOD_CHECK_BAM37)) !=
+ (MDIO_CL73_USERB0_CL73_USTAT1_LINK_STATUS_CHECK |
+ MDIO_CL73_USERB0_CL73_USTAT1_AN_GOOD_CHECK_BAM37)) {
+ DP(NETIF_MSG_LINK, "CL73 state-machine is not stable. "
+ "ustat_val(0x8371) = 0x%x\n", ustat_val);
+ return;
+ }
+ /* Step 3: Check CL37 Message Pages received to indicate LP
+ supports only CL37 */
+ CL45_RD_OVER_CL22(bp, params->port,
+ params->phy_addr,
+ MDIO_REG_BANK_REMOTE_PHY,
+ MDIO_REMOTE_PHY_MISC_RX_STATUS,
+ &cl37_fsm_recieved);
+ if ((cl37_fsm_recieved &
+ (MDIO_REMOTE_PHY_MISC_RX_STATUS_CL37_FSM_RECEIVED_OVER1G_MSG |
+ MDIO_REMOTE_PHY_MISC_RX_STATUS_CL37_FSM_RECEIVED_BRCM_OUI_MSG)) !=
+ (MDIO_REMOTE_PHY_MISC_RX_STATUS_CL37_FSM_RECEIVED_OVER1G_MSG |
+ MDIO_REMOTE_PHY_MISC_RX_STATUS_CL37_FSM_RECEIVED_BRCM_OUI_MSG)) {
+ DP(NETIF_MSG_LINK, "No CL37 FSM were received. "
+ "misc_rx_status(0x8330) = 0x%x\n",
+ cl37_fsm_recieved);
+ return;
+ }
+ /* The combined cl37/cl73 fsm state information indicating that we are
+ connected to a device which does not support cl73, but does support
+ cl37 BAM. In this case we disable cl73 and restart cl37 auto-neg */
+ /* Disable CL73 */
+ CL45_WR_OVER_CL22(bp, params->port,
+ params->phy_addr,
+ MDIO_REG_BANK_CL73_IEEEB0,
+ MDIO_CL73_IEEEB0_CL73_AN_CONTROL,
+ 0);
+ /* Restart CL37 autoneg */
+ bnx2x_restart_autoneg(params, 0);
+ DP(NETIF_MSG_LINK, "Disabling CL73, and restarting CL37 autoneg\n");
+}
static u8 bnx2x_link_settings_status(struct link_params *params,
- struct link_vars *vars,
- u32 gp_status)
+ struct link_vars *vars,
+ u32 gp_status,
+ u8 ext_phy_link_up)
{
struct bnx2x *bp = params->bp;
u16 new_line_speed;
@@ -1645,7 +1786,7 @@ static u8 bnx2x_link_settings_status(struct link_params *params,
"link speed unsupported gp_status 0x%x\n",
gp_status);
return -EINVAL;
- break;
+
case GP_STATUS_10G_KX4:
case GP_STATUS_10G_HIG:
case GP_STATUS_10G_CX4:
@@ -1682,14 +1823,23 @@ static u8 bnx2x_link_settings_status(struct link_params *params,
DP(NETIF_MSG_LINK,
"link speed unsupported gp_status 0x%x\n",
gp_status);
- return -EINVAL;
- break;
+ return -EINVAL;
}
/* Upon link speed change set the NIG into drain mode.
Comes to deals with possible FIFO glitch due to clk change
when speed is decreased without link down indicator */
if (new_line_speed != vars->line_speed) {
+ if (XGXS_EXT_PHY_TYPE(params->ext_phy_config) !=
+ PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT &&
+ ext_phy_link_up) {
+ DP(NETIF_MSG_LINK, "Internal link speed %d is"
+ " different than the external"
+ " link speed %d\n", new_line_speed,
+ vars->line_speed);
+ vars->phy_link_up = 0;
+ return 0;
+ }
REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE
+ params->port*4, 0);
msleep(1);
@@ -1703,9 +1853,7 @@ static u8 bnx2x_link_settings_status(struct link_params *params,
(XGXS_EXT_PHY_TYPE(params->ext_phy_config) ==
PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705) ||
(XGXS_EXT_PHY_TYPE(params->ext_phy_config) ==
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726) ||
- (XGXS_EXT_PHY_TYPE(params->ext_phy_config) ==
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481))) {
+ PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726))) {
vars->autoneg = AUTO_NEG_ENABLED;
if (gp_status & MDIO_AN_CL73_OR_37_COMPLETE) {
@@ -1736,6 +1884,13 @@ static u8 bnx2x_link_settings_status(struct link_params *params,
vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
vars->autoneg = AUTO_NEG_DISABLED;
vars->mac_type = MAC_TYPE_NONE;
+
+ if ((params->req_line_speed == SPEED_AUTO_NEG) &&
+ ((XGXS_EXT_PHY_TYPE(params->ext_phy_config) ==
+ PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT))) {
+ /* Check signal is detected */
+ bnx2x_check_fallback_to_cl37(params);
+ }
}
DP(NETIF_MSG_LINK, "gp_status 0x%x phy_link_up %x line_speed %x \n",
@@ -1840,7 +1995,7 @@ static u8 bnx2x_emac_program(struct link_params *params,
/*****************************************************************************/
/* External Phy section */
/*****************************************************************************/
-static void bnx2x_hw_reset(struct bnx2x *bp, u8 port)
+void bnx2x_ext_phy_hw_reset(struct bnx2x *bp, u8 port)
{
bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
MISC_REGISTERS_GPIO_OUTPUT_LOW, port);
@@ -1854,9 +2009,8 @@ static void bnx2x_ext_phy_reset(struct link_params *params,
{
struct bnx2x *bp = params->bp;
u32 ext_phy_type;
- u8 ext_phy_addr = ((params->ext_phy_config &
- PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
- PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
+ u8 ext_phy_addr = XGXS_EXT_PHY_ADDR(params->ext_phy_config);
+
DP(NETIF_MSG_LINK, "Port %x: bnx2x_ext_phy_reset\n", params->port);
ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
/* The PHY reset is controled by GPIO 1
@@ -1879,7 +2033,7 @@ static void bnx2x_ext_phy_reset(struct link_params *params,
params->port);
/* HW reset */
- bnx2x_hw_reset(bp, params->port);
+ bnx2x_ext_phy_hw_reset(bp, params->port);
bnx2x_cl45_write(bp, params->port,
ext_phy_type,
@@ -1887,6 +2041,10 @@ static void bnx2x_ext_phy_reset(struct link_params *params,
MDIO_PMA_DEVAD,
MDIO_PMA_REG_CTRL, 0xa040);
break;
+
+ case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727:
+ break;
+
case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726:
/* Restore normal power mode*/
@@ -1904,16 +2062,17 @@ static void bnx2x_ext_phy_reset(struct link_params *params,
MDIO_PMA_DEVAD,
MDIO_PMA_REG_CTRL,
1<<15);
-
break;
+
case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072:
+ DP(NETIF_MSG_LINK, "XGXS 8072\n");
+
/* Unset Low Power Mode and SW reset */
/* Restore normal power mode*/
bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
MISC_REGISTERS_GPIO_OUTPUT_HIGH,
params->port);
- DP(NETIF_MSG_LINK, "XGXS 8072\n");
bnx2x_cl45_write(bp, params->port,
ext_phy_type,
ext_phy_addr,
@@ -1921,8 +2080,9 @@ static void bnx2x_ext_phy_reset(struct link_params *params,
MDIO_PMA_REG_CTRL,
1<<15);
break;
+
case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
- {
+ DP(NETIF_MSG_LINK, "XGXS 8073\n");
/* Restore normal power mode*/
bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
@@ -1932,9 +2092,6 @@ static void bnx2x_ext_phy_reset(struct link_params *params,
bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
MISC_REGISTERS_GPIO_OUTPUT_HIGH,
params->port);
-
- DP(NETIF_MSG_LINK, "XGXS 8073\n");
- }
break;
case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101:
@@ -1946,19 +2103,17 @@ static void bnx2x_ext_phy_reset(struct link_params *params,
params->port);
/* HW reset */
- bnx2x_hw_reset(bp, params->port);
-
+ bnx2x_ext_phy_hw_reset(bp, params->port);
break;
case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481:
-
/* Restore normal power mode*/
bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
MISC_REGISTERS_GPIO_OUTPUT_HIGH,
params->port);
/* HW reset */
- bnx2x_hw_reset(bp, params->port);
+ bnx2x_ext_phy_hw_reset(bp, params->port);
bnx2x_cl45_write(bp, params->port,
ext_phy_type,
@@ -1986,24 +2141,22 @@ static void bnx2x_ext_phy_reset(struct link_params *params,
case PORT_HW_CFG_SERDES_EXT_PHY_TYPE_BCM5482:
DP(NETIF_MSG_LINK, "SerDes 5482\n");
- bnx2x_hw_reset(bp, params->port);
+ bnx2x_ext_phy_hw_reset(bp, params->port);
break;
default:
- DP(NETIF_MSG_LINK,
- "BAD SerDes ext_phy_config 0x%x\n",
+ DP(NETIF_MSG_LINK, "BAD SerDes ext_phy_config 0x%x\n",
params->ext_phy_config);
break;
}
}
}
-
static void bnx2x_save_spirom_version(struct bnx2x *bp, u8 port,
u32 shmem_base, u32 spirom_ver)
{
- DP(NETIF_MSG_LINK, "FW version 0x%x:0x%x\n",
- (u16)(spirom_ver>>16), (u16)spirom_ver);
+ DP(NETIF_MSG_LINK, "FW version 0x%x:0x%x for port %d\n",
+ (u16)(spirom_ver>>16), (u16)spirom_ver, port);
REG_WR(bp, shmem_base +
offsetof(struct shmem_region,
port_mb[port].ext_phy_fw_version),
@@ -2015,6 +2168,7 @@ static void bnx2x_save_bcm_spirom_ver(struct bnx2x *bp, u8 port,
u32 shmem_base)
{
u16 fw_ver1, fw_ver2;
+
bnx2x_cl45_read(bp, port, ext_phy_type, ext_phy_addr, MDIO_PMA_DEVAD,
MDIO_PMA_REG_ROM_VER1, &fw_ver1);
bnx2x_cl45_read(bp, port, ext_phy_type, ext_phy_addr, MDIO_PMA_DEVAD,
@@ -2023,13 +2177,116 @@ static void bnx2x_save_bcm_spirom_ver(struct bnx2x *bp, u8 port,
(u32)(fw_ver1<<16 | fw_ver2));
}
+
+static void bnx2x_save_8481_spirom_version(struct bnx2x *bp, u8 port,
+ u8 ext_phy_addr, u32 shmem_base)
+{
+ u16 val, fw_ver1, fw_ver2, cnt;
+ /* For the 32 bits registers in 8481, access via MDIO2ARM interface.*/
+ /* (1) set register 0xc200_0014(SPI_BRIDGE_CTRL_2) to 0x03000000 */
+ bnx2x_cl45_write(bp, port,
+ PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481,
+ ext_phy_addr, MDIO_PMA_DEVAD,
+ 0xA819, 0x0014);
+ bnx2x_cl45_write(bp, port,
+ PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481,
+ ext_phy_addr,
+ MDIO_PMA_DEVAD,
+ 0xA81A,
+ 0xc200);
+ bnx2x_cl45_write(bp, port,
+ PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481,
+ ext_phy_addr,
+ MDIO_PMA_DEVAD,
+ 0xA81B,
+ 0x0000);
+ bnx2x_cl45_write(bp, port,
+ PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481,
+ ext_phy_addr,
+ MDIO_PMA_DEVAD,
+ 0xA81C,
+ 0x0300);
+ bnx2x_cl45_write(bp, port,
+ PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481,
+ ext_phy_addr,
+ MDIO_PMA_DEVAD,
+ 0xA817,
+ 0x0009);
+
+ for (cnt = 0; cnt < 100; cnt++) {
+ bnx2x_cl45_read(bp, port,
+ PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481,
+ ext_phy_addr,
+ MDIO_PMA_DEVAD,
+ 0xA818,
+ &val);
+ if (val & 1)
+ break;
+ udelay(5);
+ }
+ if (cnt == 100) {
+ DP(NETIF_MSG_LINK, "Unable to read 8481 phy fw version(1)\n");
+ bnx2x_save_spirom_version(bp, port,
+ shmem_base, 0);
+ return;
+ }
+
+
+ /* 2) read register 0xc200_0000 (SPI_FW_STATUS) */
+ bnx2x_cl45_write(bp, port,
+ PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481,
+ ext_phy_addr, MDIO_PMA_DEVAD,
+ 0xA819, 0x0000);
+ bnx2x_cl45_write(bp, port,
+ PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481,
+ ext_phy_addr, MDIO_PMA_DEVAD,
+ 0xA81A, 0xc200);
+ bnx2x_cl45_write(bp, port,
+ PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481,
+ ext_phy_addr, MDIO_PMA_DEVAD,
+ 0xA817, 0x000A);
+ for (cnt = 0; cnt < 100; cnt++) {
+ bnx2x_cl45_read(bp, port,
+ PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481,
+ ext_phy_addr,
+ MDIO_PMA_DEVAD,
+ 0xA818,
+ &val);
+ if (val & 1)
+ break;
+ udelay(5);
+ }
+ if (cnt == 100) {
+ DP(NETIF_MSG_LINK, "Unable to read 8481 phy fw version(2)\n");
+ bnx2x_save_spirom_version(bp, port,
+ shmem_base, 0);
+ return;
+ }
+
+ /* lower 16 bits of the register SPI_FW_STATUS */
+ bnx2x_cl45_read(bp, port,
+ PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481,
+ ext_phy_addr,
+ MDIO_PMA_DEVAD,
+ 0xA81B,
+ &fw_ver1);
+ /* upper 16 bits of register SPI_FW_STATUS */
+ bnx2x_cl45_read(bp, port,
+ PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481,
+ ext_phy_addr,
+ MDIO_PMA_DEVAD,
+ 0xA81C,
+ &fw_ver2);
+
+ bnx2x_save_spirom_version(bp, port,
+ shmem_base, (fw_ver2<<16) | fw_ver1);
+}
+
static void bnx2x_bcm8072_external_rom_boot(struct link_params *params)
{
struct bnx2x *bp = params->bp;
u8 port = params->port;
- u8 ext_phy_addr = ((params->ext_phy_config &
- PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
- PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
+ u8 ext_phy_addr = XGXS_EXT_PHY_ADDR(params->ext_phy_config);
u32 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
/* Need to wait 200ms after reset */
@@ -2077,9 +2334,7 @@ static u8 bnx2x_8073_is_snr_needed(struct link_params *params)
/* This is only required for 8073A1, version 102 only */
struct bnx2x *bp = params->bp;
- u8 ext_phy_addr = ((params->ext_phy_config &
- PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
- PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
+ u8 ext_phy_addr = XGXS_EXT_PHY_ADDR(params->ext_phy_config);
u16 val;
/* Read 8073 HW revision*/
@@ -2110,9 +2365,7 @@ static u8 bnx2x_8073_is_snr_needed(struct link_params *params)
static u8 bnx2x_bcm8073_xaui_wa(struct link_params *params)
{
struct bnx2x *bp = params->bp;
- u8 ext_phy_addr = ((params->ext_phy_config &
- PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
- PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
+ u8 ext_phy_addr = XGXS_EXT_PHY_ADDR(params->ext_phy_config);
u16 val, cnt, cnt1 ;
bnx2x_cl45_read(bp, params->port,
@@ -2168,16 +2421,17 @@ static u8 bnx2x_bcm8073_xaui_wa(struct link_params *params)
}
DP(NETIF_MSG_LINK, "Warning: XAUI work-around timeout !!!\n");
return -EINVAL;
-
}
-static void bnx2x_bcm8073_external_rom_boot(struct bnx2x *bp, u8 port,
- u8 ext_phy_addr, u32 shmem_base)
+static void bnx2x_bcm8073_bcm8727_external_rom_boot(struct bnx2x *bp, u8 port,
+ u8 ext_phy_addr,
+ u32 ext_phy_type,
+ u32 shmem_base)
{
/* Boot port from external ROM */
/* EDC grst */
bnx2x_cl45_write(bp, port,
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
+ ext_phy_type,
ext_phy_addr,
MDIO_PMA_DEVAD,
MDIO_PMA_REG_GEN_CTRL,
@@ -2185,21 +2439,21 @@ static void bnx2x_bcm8073_external_rom_boot(struct bnx2x *bp, u8 port,
/* ucode reboot and rst */
bnx2x_cl45_write(bp, port,
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
+ ext_phy_type,
ext_phy_addr,
MDIO_PMA_DEVAD,
MDIO_PMA_REG_GEN_CTRL,
0x008c);
bnx2x_cl45_write(bp, port,
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
+ ext_phy_type,
ext_phy_addr,
MDIO_PMA_DEVAD,
MDIO_PMA_REG_MISC_CTRL1, 0x0001);
/* Reset internal microprocessor */
bnx2x_cl45_write(bp, port,
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
+ ext_phy_type,
ext_phy_addr,
MDIO_PMA_DEVAD,
MDIO_PMA_REG_GEN_CTRL,
@@ -2207,7 +2461,7 @@ static void bnx2x_bcm8073_external_rom_boot(struct bnx2x *bp, u8 port,
/* Release srst bit */
bnx2x_cl45_write(bp, port,
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
+ ext_phy_type,
ext_phy_addr,
MDIO_PMA_DEVAD,
MDIO_PMA_REG_GEN_CTRL,
@@ -2218,24 +2472,41 @@ static void bnx2x_bcm8073_external_rom_boot(struct bnx2x *bp, u8 port,
/* Clear ser_boot_ctl bit */
bnx2x_cl45_write(bp, port,
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
+ ext_phy_type,
ext_phy_addr,
MDIO_PMA_DEVAD,
MDIO_PMA_REG_MISC_CTRL1, 0x0000);
bnx2x_save_bcm_spirom_ver(bp, port,
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
+ ext_phy_type,
ext_phy_addr,
shmem_base);
}
+static void bnx2x_bcm8073_external_rom_boot(struct bnx2x *bp, u8 port,
+ u8 ext_phy_addr,
+ u32 shmem_base)
+{
+ bnx2x_bcm8073_bcm8727_external_rom_boot(bp, port, ext_phy_addr,
+ PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
+ shmem_base);
+}
+
+static void bnx2x_bcm8727_external_rom_boot(struct bnx2x *bp, u8 port,
+ u8 ext_phy_addr,
+ u32 shmem_base)
+{
+ bnx2x_bcm8073_bcm8727_external_rom_boot(bp, port, ext_phy_addr,
+ PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727,
+ shmem_base);
+
+}
+
static void bnx2x_bcm8726_external_rom_boot(struct link_params *params)
{
struct bnx2x *bp = params->bp;
u8 port = params->port;
- u8 ext_phy_addr = ((params->ext_phy_config &
- PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
- PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
+ u8 ext_phy_addr = XGXS_EXT_PHY_ADDR(params->ext_phy_config);
u32 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
/* Need to wait 100ms after reset */
@@ -2258,9 +2529,10 @@ static void bnx2x_bcm8726_external_rom_boot(struct link_params *params)
MDIO_PMA_REG_GEN_CTRL,
MDIO_PMA_REG_GEN_CTRL_ROM_MICRO_RESET);
+ /* Set PLL register value to be same like in P13 ver */
bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
MDIO_PMA_DEVAD,
- MDIO_PMA_REG_GEN_CTRL2,
+ MDIO_PMA_REG_PLL_CTRL,
0x73A0);
/* Clear soft reset.
@@ -2285,15 +2557,17 @@ static void bnx2x_bcm8726_external_rom_boot(struct link_params *params)
params->shmem_base);
}
-static void bnx2x_bcm8726_set_transmitter(struct bnx2x *bp, u8 port,
- u8 ext_phy_addr, u8 tx_en)
+static void bnx2x_sfp_set_transmitter(struct bnx2x *bp, u8 port,
+ u32 ext_phy_type, u8 ext_phy_addr,
+ u8 tx_en)
{
u16 val;
+
DP(NETIF_MSG_LINK, "Setting transmitter tx_en=%x for port %x\n",
tx_en, port);
/* Disable/Enable transmitter ( TX laser of the SFP+ module.)*/
bnx2x_cl45_read(bp, port,
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726,
+ ext_phy_type,
ext_phy_addr,
MDIO_PMA_DEVAD,
MDIO_PMA_REG_PHY_IDENTIFIER,
@@ -2305,23 +2579,23 @@ static void bnx2x_bcm8726_set_transmitter(struct bnx2x *bp, u8 port,
val |= (1<<15);
bnx2x_cl45_write(bp, port,
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726,
+ ext_phy_type,
ext_phy_addr,
MDIO_PMA_DEVAD,
MDIO_PMA_REG_PHY_IDENTIFIER,
val);
}
-
-static u8 bnx2x_read_sfp_module_eeprom(struct link_params *params, u16 addr,
- u8 byte_cnt, u8 *o_buf) {
+static u8 bnx2x_8726_read_sfp_module_eeprom(struct link_params *params,
+ u16 addr, u8 byte_cnt, u8 *o_buf)
+{
struct bnx2x *bp = params->bp;
- u16 val, i;
+ u16 val = 0;
+ u16 i;
u8 port = params->port;
- u8 ext_phy_addr = ((params->ext_phy_config &
- PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
- PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
+ u8 ext_phy_addr = XGXS_EXT_PHY_ADDR(params->ext_phy_config);
u32 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
+
if (byte_cnt > 16) {
DP(NETIF_MSG_LINK, "Reading from eeprom is"
" is limited to 0xf\n");
@@ -2332,7 +2606,7 @@ static u8 bnx2x_read_sfp_module_eeprom(struct link_params *params, u16 addr,
ext_phy_type,
ext_phy_addr,
MDIO_PMA_DEVAD,
- MDIO_PMA_REG_8726_TWO_WIRE_BYTE_CNT,
+ MDIO_PMA_REG_SFP_TWO_WIRE_BYTE_CNT,
(byte_cnt | 0xa000));
/* Set the read command address */
@@ -2340,7 +2614,7 @@ static u8 bnx2x_read_sfp_module_eeprom(struct link_params *params, u16 addr,
ext_phy_type,
ext_phy_addr,
MDIO_PMA_DEVAD,
- MDIO_PMA_REG_8726_TWO_WIRE_MEM_ADDR,
+ MDIO_PMA_REG_SFP_TWO_WIRE_MEM_ADDR,
addr);
/* Activate read command */
@@ -2348,7 +2622,7 @@ static u8 bnx2x_read_sfp_module_eeprom(struct link_params *params, u16 addr,
ext_phy_type,
ext_phy_addr,
MDIO_PMA_DEVAD,
- MDIO_PMA_REG_8726_TWO_WIRE_CTRL,
+ MDIO_PMA_REG_SFP_TWO_WIRE_CTRL,
0x2c0f);
/* Wait up to 500us for command complete status */
@@ -2357,18 +2631,18 @@ static u8 bnx2x_read_sfp_module_eeprom(struct link_params *params, u16 addr,
ext_phy_type,
ext_phy_addr,
MDIO_PMA_DEVAD,
- MDIO_PMA_REG_8726_TWO_WIRE_CTRL, &val);
- if ((val & MDIO_PMA_REG_8726_TWO_WIRE_CTRL_STATUS_MASK) ==
- MDIO_PMA_REG_8726_TWO_WIRE_STATUS_COMPLETE)
+ MDIO_PMA_REG_SFP_TWO_WIRE_CTRL, &val);
+ if ((val & MDIO_PMA_REG_SFP_TWO_WIRE_CTRL_STATUS_MASK) ==
+ MDIO_PMA_REG_SFP_TWO_WIRE_STATUS_COMPLETE)
break;
udelay(5);
}
- if ((val & MDIO_PMA_REG_8726_TWO_WIRE_CTRL_STATUS_MASK) !=
- MDIO_PMA_REG_8726_TWO_WIRE_STATUS_COMPLETE) {
+ if ((val & MDIO_PMA_REG_SFP_TWO_WIRE_CTRL_STATUS_MASK) !=
+ MDIO_PMA_REG_SFP_TWO_WIRE_STATUS_COMPLETE) {
DP(NETIF_MSG_LINK,
"Got bad status 0x%x when reading from SFP+ EEPROM\n",
- (val & MDIO_PMA_REG_8726_TWO_WIRE_CTRL_STATUS_MASK));
+ (val & MDIO_PMA_REG_SFP_TWO_WIRE_CTRL_STATUS_MASK));
return -EINVAL;
}
@@ -2387,29 +2661,145 @@ static u8 bnx2x_read_sfp_module_eeprom(struct link_params *params, u16 addr,
ext_phy_type,
ext_phy_addr,
MDIO_PMA_DEVAD,
- MDIO_PMA_REG_8726_TWO_WIRE_CTRL, &val);
- if ((val & MDIO_PMA_REG_8726_TWO_WIRE_CTRL_STATUS_MASK) ==
- MDIO_PMA_REG_8726_TWO_WIRE_STATUS_IDLE)
+ MDIO_PMA_REG_SFP_TWO_WIRE_CTRL, &val);
+ if ((val & MDIO_PMA_REG_SFP_TWO_WIRE_CTRL_STATUS_MASK) ==
+ MDIO_PMA_REG_SFP_TWO_WIRE_STATUS_IDLE)
return 0;;
msleep(1);
}
return -EINVAL;
}
+static u8 bnx2x_8727_read_sfp_module_eeprom(struct link_params *params,
+ u16 addr, u8 byte_cnt, u8 *o_buf)
+{
+ struct bnx2x *bp = params->bp;
+ u16 val, i;
+ u8 port = params->port;
+ u8 ext_phy_addr = XGXS_EXT_PHY_ADDR(params->ext_phy_config);
+ u32 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
-static u8 bnx2x_get_sfp_module_type(struct link_params *params,
- u8 *module_type)
+ if (byte_cnt > 16) {
+ DP(NETIF_MSG_LINK, "Reading from eeprom is"
+ " is limited to 0xf\n");
+ return -EINVAL;
+ }
+
+ /* Need to read from 1.8000 to clear it */
+ bnx2x_cl45_read(bp, port,
+ PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727,
+ ext_phy_addr,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_SFP_TWO_WIRE_CTRL,
+ &val);
+
+ /* Set the read command byte count */
+ bnx2x_cl45_write(bp, port,
+ ext_phy_type,
+ ext_phy_addr,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_SFP_TWO_WIRE_BYTE_CNT,
+ ((byte_cnt < 2) ? 2 : byte_cnt));
+
+ /* Set the read command address */
+ bnx2x_cl45_write(bp, port,
+ ext_phy_type,
+ ext_phy_addr,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_SFP_TWO_WIRE_MEM_ADDR,
+ addr);
+ /* Set the destination address */
+ bnx2x_cl45_write(bp, port,
+ ext_phy_type,
+ ext_phy_addr,
+ MDIO_PMA_DEVAD,
+ 0x8004,
+ MDIO_PMA_REG_8727_TWO_WIRE_DATA_BUF);
+
+ /* Activate read command */
+ bnx2x_cl45_write(bp, port,
+ ext_phy_type,
+ ext_phy_addr,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_SFP_TWO_WIRE_CTRL,
+ 0x8002);
+ /* Wait appropriate time for two-wire command to finish before
+ polling the status register */
+ msleep(1);
+
+ /* Wait up to 500us for command complete status */
+ for (i = 0; i < 100; i++) {
+ bnx2x_cl45_read(bp, port,
+ ext_phy_type,
+ ext_phy_addr,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_SFP_TWO_WIRE_CTRL, &val);
+ if ((val & MDIO_PMA_REG_SFP_TWO_WIRE_CTRL_STATUS_MASK) ==
+ MDIO_PMA_REG_SFP_TWO_WIRE_STATUS_COMPLETE)
+ break;
+ udelay(5);
+ }
+
+ if ((val & MDIO_PMA_REG_SFP_TWO_WIRE_CTRL_STATUS_MASK) !=
+ MDIO_PMA_REG_SFP_TWO_WIRE_STATUS_COMPLETE) {
+ DP(NETIF_MSG_LINK,
+ "Got bad status 0x%x when reading from SFP+ EEPROM\n",
+ (val & MDIO_PMA_REG_SFP_TWO_WIRE_CTRL_STATUS_MASK));
+ return -EINVAL;
+ }
+
+ /* Read the buffer */
+ for (i = 0; i < byte_cnt; i++) {
+ bnx2x_cl45_read(bp, port,
+ ext_phy_type,
+ ext_phy_addr,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_8727_TWO_WIRE_DATA_BUF + i, &val);
+ o_buf[i] = (u8)(val & MDIO_PMA_REG_8727_TWO_WIRE_DATA_MASK);
+ }
+
+ for (i = 0; i < 100; i++) {
+ bnx2x_cl45_read(bp, port,
+ ext_phy_type,
+ ext_phy_addr,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_SFP_TWO_WIRE_CTRL, &val);
+ if ((val & MDIO_PMA_REG_SFP_TWO_WIRE_CTRL_STATUS_MASK) ==
+ MDIO_PMA_REG_SFP_TWO_WIRE_STATUS_IDLE)
+ return 0;;
+ msleep(1);
+ }
+
+ return -EINVAL;
+}
+
+u8 bnx2x_read_sfp_module_eeprom(struct link_params *params, u16 addr,
+ u8 byte_cnt, u8 *o_buf)
+{
+ u32 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
+
+ if (ext_phy_type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726)
+ return bnx2x_8726_read_sfp_module_eeprom(params, addr,
+ byte_cnt, o_buf);
+ else if (ext_phy_type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727)
+ return bnx2x_8727_read_sfp_module_eeprom(params, addr,
+ byte_cnt, o_buf);
+ return -EINVAL;
+}
+
+static u8 bnx2x_get_edc_mode(struct link_params *params,
+ u16 *edc_mode)
{
struct bnx2x *bp = params->bp;
- u8 val;
- *module_type = SFP_MODULE_TYPE_UNKNOWN;
+ u8 val, check_limiting_mode = 0;
+ *edc_mode = EDC_MODE_LIMITING;
/* First check for copper cable */
if (bnx2x_read_sfp_module_eeprom(params,
SFP_EEPROM_CON_TYPE_ADDR,
1,
&val) != 0) {
- DP(NETIF_MSG_LINK, "Failed to read from SFP+ module EEPROM");
+ DP(NETIF_MSG_LINK, "Failed to read from SFP+ module EEPROM\n");
return -EINVAL;
}
@@ -2417,6 +2807,7 @@ static u8 bnx2x_get_sfp_module_type(struct link_params *params,
case SFP_EEPROM_CON_TYPE_VAL_COPPER:
{
u8 copper_module_type;
+
/* Check if its active cable( includes SFP+ module)
of passive cable*/
if (bnx2x_read_sfp_module_eeprom(params,
@@ -2433,13 +2824,13 @@ static u8 bnx2x_get_sfp_module_type(struct link_params *params,
if (copper_module_type &
SFP_EEPROM_FC_TX_TECH_BITMASK_COPPER_ACTIVE) {
DP(NETIF_MSG_LINK, "Active Copper cable detected\n");
- *module_type = SFP_MODULE_TYPE_ACTIVE_COPPER_CABLE;
+ check_limiting_mode = 1;
} else if (copper_module_type &
SFP_EEPROM_FC_TX_TECH_BITMASK_COPPER_PASSIVE) {
DP(NETIF_MSG_LINK, "Passive Copper"
" cable detected\n");
- *module_type =
- SFP_MODULE_TYPE_PASSIVE_COPPER_CABLE;
+ *edc_mode =
+ EDC_MODE_PASSIVE_DAC;
} else {
DP(NETIF_MSG_LINK, "Unknown copper-cable-"
"type 0x%x !!!\n", copper_module_type);
@@ -2449,97 +2840,97 @@ static u8 bnx2x_get_sfp_module_type(struct link_params *params,
}
case SFP_EEPROM_CON_TYPE_VAL_LC:
DP(NETIF_MSG_LINK, "Optic module detected\n");
- *module_type = SFP_MODULE_TYPE_LC;
+ check_limiting_mode = 1;
break;
-
default:
DP(NETIF_MSG_LINK, "Unable to determine module type 0x%x !!!\n",
val);
return -EINVAL;
}
+
+ if (check_limiting_mode) {
+ u8 options[SFP_EEPROM_OPTIONS_SIZE];
+ if (bnx2x_read_sfp_module_eeprom(params,
+ SFP_EEPROM_OPTIONS_ADDR,
+ SFP_EEPROM_OPTIONS_SIZE,
+ options) != 0) {
+ DP(NETIF_MSG_LINK, "Failed to read Option"
+ " field from module EEPROM\n");
+ return -EINVAL;
+ }
+ if ((options[0] & SFP_EEPROM_OPTIONS_LINEAR_RX_OUT_MASK))
+ *edc_mode = EDC_MODE_LINEAR;
+ else
+ *edc_mode = EDC_MODE_LIMITING;
+ }
+ DP(NETIF_MSG_LINK, "EDC mode is set to 0x%x\n", *edc_mode);
return 0;
}
-
/* This function read the relevant field from the module ( SFP+ ),
and verify it is compliant with this board */
-static u8 bnx2x_verify_sfp_module(struct link_params *params,
- u8 module_type)
+static u8 bnx2x_verify_sfp_module(struct link_params *params)
{
struct bnx2x *bp = params->bp;
- u8 *str_p, *tmp_buf;
- u16 i;
-
-#define COMPLIANCE_STR_CNT 6
- u8 *compliance_str[] = {"Broadcom", "JDSU", "Molex Inc", "PICOLIGHT",
- "FINISAR CORP. ", "Amphenol"};
- u8 buf[SFP_EEPROM_VENDOR_NAME_SIZE];
- /* Passive Copper cables are allowed to participate,
- since the module is hardwired to the copper cable */
-
- if (!(params->feature_config_flags &
- FEATURE_CONFIG_MODULE_ENFORCMENT_ENABLED)) {
+ u32 val;
+ u32 fw_resp;
+ char vendor_name[SFP_EEPROM_VENDOR_NAME_SIZE+1];
+ char vendor_pn[SFP_EEPROM_PART_NO_SIZE+1];
+
+ val = REG_RD(bp, params->shmem_base +
+ offsetof(struct shmem_region, dev_info.
+ port_feature_config[params->port].config));
+ if ((val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) ==
+ PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_NO_ENFORCEMENT) {
DP(NETIF_MSG_LINK, "NOT enforcing module verification\n");
return 0;
}
- if (module_type != SFP_MODULE_TYPE_LC) {
- DP(NETIF_MSG_LINK, "No need to verify copper cable\n");
+ /* Ask the FW to validate the module */
+ if (!(params->feature_config_flags &
+ FEATURE_CONFIG_BC_SUPPORTS_OPT_MDL_VRFY)) {
+ DP(NETIF_MSG_LINK, "FW does not support OPT MDL "
+ "verification\n");
+ return -EINVAL;
+ }
+
+ fw_resp = bnx2x_fw_command(bp, DRV_MSG_CODE_VRFY_OPT_MDL);
+ if (fw_resp == FW_MSG_CODE_VRFY_OPT_MDL_SUCCESS) {
+ DP(NETIF_MSG_LINK, "Approved module\n");
return 0;
}
- /* In case of non copper cable or Active copper cable,
- verify that the SFP+ module is compliant with this board*/
+ /* format the warning message */
if (bnx2x_read_sfp_module_eeprom(params,
SFP_EEPROM_VENDOR_NAME_ADDR,
SFP_EEPROM_VENDOR_NAME_SIZE,
- buf) != 0) {
- DP(NETIF_MSG_LINK, "Failed to read Vendor-Name from"
- " module EEPROM\n");
- return -EINVAL;
- }
- for (i = 0; i < COMPLIANCE_STR_CNT; i++) {
- str_p = compliance_str[i];
- tmp_buf = buf;
- while (*str_p) {
- if ((u8)(*tmp_buf) != (u8)(*str_p))
- break;
- str_p++;
- tmp_buf++;
- }
+ (u8 *)vendor_name))
+ vendor_name[0] = '\0';
+ else
+ vendor_name[SFP_EEPROM_VENDOR_NAME_SIZE] = '\0';
+ if (bnx2x_read_sfp_module_eeprom(params,
+ SFP_EEPROM_PART_NO_ADDR,
+ SFP_EEPROM_PART_NO_SIZE,
+ (u8 *)vendor_pn))
+ vendor_pn[0] = '\0';
+ else
+ vendor_pn[SFP_EEPROM_PART_NO_SIZE] = '\0';
- if (!(*str_p)) {
- DP(NETIF_MSG_LINK, "SFP+ Module verified, "
- "index=%x\n", i);
- return 0;
- }
- }
- DP(NETIF_MSG_LINK, "Incompliant SFP+ module. Disable module !!!\n");
+ printk(KERN_INFO PFX "Warning: "
+ "Unqualified SFP+ module "
+ "detected on %s, Port %d from %s part number %s\n"
+ , bp->dev->name, params->port,
+ vendor_name, vendor_pn);
return -EINVAL;
}
-
static u8 bnx2x_bcm8726_set_limiting_mode(struct link_params *params,
- u8 module_type)
+ u16 edc_mode)
{
struct bnx2x *bp = params->bp;
u8 port = params->port;
- u8 options[SFP_EEPROM_OPTIONS_SIZE];
- u8 limiting_mode;
- u8 ext_phy_addr = ((params->ext_phy_config &
- PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
- PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
+ u8 ext_phy_addr = XGXS_EXT_PHY_ADDR(params->ext_phy_config);
u16 cur_limiting_mode;
- if (bnx2x_read_sfp_module_eeprom(params,
- SFP_EEPROM_OPTIONS_ADDR,
- SFP_EEPROM_OPTIONS_SIZE,
- options) != 0) {
- DP(NETIF_MSG_LINK, "Failed to read Option field from"
- " module EEPROM\n");
- return -EINVAL;
- }
- limiting_mode = !(options[0] &
- SFP_EEPROM_OPTIONS_LINEAR_RX_OUT_MASK);
bnx2x_cl45_read(bp, port,
PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726,
@@ -2550,26 +2941,23 @@ static u8 bnx2x_bcm8726_set_limiting_mode(struct link_params *params,
DP(NETIF_MSG_LINK, "Current Limiting mode is 0x%x\n",
cur_limiting_mode);
- if (limiting_mode &&
- (module_type != SFP_MODULE_TYPE_PASSIVE_COPPER_CABLE)) {
+ if (edc_mode == EDC_MODE_LIMITING) {
DP(NETIF_MSG_LINK,
- "Module options = 0x%x.Setting LIMITING MODE\n",
- options[0]);
+ "Setting LIMITING MODE\n");
bnx2x_cl45_write(bp, port,
PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726,
ext_phy_addr,
MDIO_PMA_DEVAD,
MDIO_PMA_REG_ROM_VER2,
- SFP_LIMITING_MODE_VALUE);
+ EDC_MODE_LIMITING);
} else { /* LRM mode ( default )*/
- DP(NETIF_MSG_LINK, "Module options = 0x%x.Setting LRM MODE\n",
- options[0]);
+ DP(NETIF_MSG_LINK, "Setting LRM MODE\n");
/* Changing to LRM mode takes quite few seconds.
So do it only if current mode is limiting
( default is LRM )*/
- if (cur_limiting_mode != SFP_LIMITING_MODE_VALUE)
+ if (cur_limiting_mode != EDC_MODE_LIMITING)
return 0;
bnx2x_cl45_write(bp, port,
@@ -2600,6 +2988,54 @@ static u8 bnx2x_bcm8726_set_limiting_mode(struct link_params *params,
return 0;
}
+static u8 bnx2x_bcm8727_set_limiting_mode(struct link_params *params,
+ u16 edc_mode)
+{
+ struct bnx2x *bp = params->bp;
+ u8 port = params->port;
+ u16 phy_identifier;
+ u16 rom_ver2_val;
+ u8 ext_phy_addr = XGXS_EXT_PHY_ADDR(params->ext_phy_config);
+
+ bnx2x_cl45_read(bp, port,
+ PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727,
+ ext_phy_addr,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_PHY_IDENTIFIER,
+ &phy_identifier);
+
+ bnx2x_cl45_write(bp, port,
+ PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727,
+ ext_phy_addr,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_PHY_IDENTIFIER,
+ (phy_identifier & ~(1<<9)));
+
+ bnx2x_cl45_read(bp, port,
+ PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727,
+ ext_phy_addr,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_ROM_VER2,
+ &rom_ver2_val);
+ /* Keep the MSB 8-bits, and set the LSB 8-bits with the edc_mode */
+ bnx2x_cl45_write(bp, port,
+ PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727,
+ ext_phy_addr,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_ROM_VER2,
+ (rom_ver2_val & 0xff00) | (edc_mode & 0x00ff));
+
+ bnx2x_cl45_write(bp, port,
+ PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727,
+ ext_phy_addr,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_PHY_IDENTIFIER,
+ (phy_identifier | (1<<9)));
+
+ return 0;
+}
+
+
static u8 bnx2x_wait_for_sfp_module_initialized(struct link_params *params)
{
u8 val;
@@ -2619,61 +3055,112 @@ static u8 bnx2x_wait_for_sfp_module_initialized(struct link_params *params)
return -EINVAL;
}
+static void bnx2x_8727_power_module(struct bnx2x *bp,
+ struct link_params *params,
+ u8 ext_phy_addr, u8 is_power_up) {
+ /* Make sure GPIOs are not using for LED mode */
+ u16 val;
+ u8 port = params->port;
+ /*
+ * In the GPIO register, bit 4 is use to detemine if the GPIOs are
+ * operating as INPUT or as OUTPUT. Bit 1 is for input, and 0 for
+ * output
+ * Bits 0-1 determine the gpios value for OUTPUT in case bit 4 val is 0
+ * Bits 8-9 determine the gpios value for INPUT in case bit 4 val is 1
+ * where the 1st bit is the over-current(only input), and 2nd bit is
+ * for power( only output )
+ */
+
+ /*
+ * In case of NOC feature is disabled and power is up, set GPIO control
+ * as input to enable listening of over-current indication
+ */
+
+ if (!(params->feature_config_flags &
+ FEATURE_CONFIG_BCM8727_NOC) && is_power_up)
+ val = (1<<4);
+ else
+ /*
+ * Set GPIO control to OUTPUT, and set the power bit
+ * to according to the is_power_up
+ */
+ val = ((!(is_power_up)) << 1);
+
+ bnx2x_cl45_write(bp, port,
+ PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727,
+ ext_phy_addr,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_8727_GPIO_CTRL,
+ val);
+}
+
static u8 bnx2x_sfp_module_detection(struct link_params *params)
{
struct bnx2x *bp = params->bp;
- u8 module_type;
- u8 ext_phy_addr = ((params->ext_phy_config &
- PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
- PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
+ u16 edc_mode;
+ u8 rc = 0;
+ u8 ext_phy_addr = XGXS_EXT_PHY_ADDR(params->ext_phy_config);
u32 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
-
- if (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726) {
- DP(NETIF_MSG_LINK, "Module detection is not required "
- "for this phy\n");
- return 0;
- }
+ u32 val = REG_RD(bp, params->shmem_base +
+ offsetof(struct shmem_region, dev_info.
+ port_feature_config[params->port].config));
DP(NETIF_MSG_LINK, "SFP+ module plugged in/out detected on port %d\n",
params->port);
- if (bnx2x_get_sfp_module_type(params,
- &module_type) != 0) {
+ if (bnx2x_get_edc_mode(params, &edc_mode) != 0) {
DP(NETIF_MSG_LINK, "Failed to get valid module type\n");
- if (!(params->feature_config_flags &
- FEATURE_CONFIG_MODULE_ENFORCMENT_ENABLED)) {
- /* In case module detection is disabled, it trys to
- link up. The issue that can happen here is LRM /
- LIMITING mode which set according to the module-type*/
- DP(NETIF_MSG_LINK, "Unable to read module-type."
- "Probably due to Bit Stretching."
- " Proceeding...\n");
- } else {
- return -EINVAL;
- }
- } else if (bnx2x_verify_sfp_module(params, module_type) !=
+ return -EINVAL;
+ } else if (bnx2x_verify_sfp_module(params) !=
0) {
/* check SFP+ module compatibility */
DP(NETIF_MSG_LINK, "Module verification failed!!\n");
+ rc = -EINVAL;
/* Turn on fault module-detected led */
bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_0,
MISC_REGISTERS_GPIO_HIGH,
params->port);
- return -EINVAL;
+ if ((ext_phy_type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727) &&
+ ((val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) ==
+ PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_POWER_DOWN)) {
+ /* Shutdown SFP+ module */
+ DP(NETIF_MSG_LINK, "Shutdown SFP+ module!!\n");
+ bnx2x_8727_power_module(bp, params,
+ ext_phy_addr, 0);
+ return rc;
+ }
+ } else {
+ /* Turn off fault module-detected led */
+ DP(NETIF_MSG_LINK, "Turn off fault module-detected led\n");
+ bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_0,
+ MISC_REGISTERS_GPIO_LOW,
+ params->port);
}
- /* Turn off fault module-detected led */
- bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_0,
- MISC_REGISTERS_GPIO_LOW,
- params->port);
+ /* power up the SFP module */
+ if (ext_phy_type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727)
+ bnx2x_8727_power_module(bp, params, ext_phy_addr, 1);
- /* Check and set limiting mode / LRM mode */
- bnx2x_bcm8726_set_limiting_mode(params, module_type);
+ /* Check and set limiting mode / LRM mode on 8726.
+ On 8727 it is done automatically */
+ if (ext_phy_type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726)
+ bnx2x_bcm8726_set_limiting_mode(params, edc_mode);
+ else
+ bnx2x_bcm8727_set_limiting_mode(params, edc_mode);
+ /*
+ * Enable transmit for this module if the module is approved, or
+ * if unapproved modules should also enable the Tx laser
+ */
+ if (rc == 0 ||
+ (val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) !=
+ PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_DISABLE_TX_LASER)
+ bnx2x_sfp_set_transmitter(bp, params->port,
+ ext_phy_type, ext_phy_addr, 1);
+ else
+ bnx2x_sfp_set_transmitter(bp, params->port,
+ ext_phy_type, ext_phy_addr, 0);
- /* Enable transmit for this module */
- bnx2x_bcm8726_set_transmitter(bp, params->port,
- ext_phy_addr, 1);
- return 0;
+ return rc;
}
void bnx2x_handle_module_detect_int(struct link_params *params)
@@ -2681,6 +3168,7 @@ void bnx2x_handle_module_detect_int(struct link_params *params)
struct bnx2x *bp = params->bp;
u32 gpio_val;
u8 port = params->port;
+
/* Set valid module led off */
bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_0,
MISC_REGISTERS_GPIO_HIGH,
@@ -2696,22 +3184,30 @@ void bnx2x_handle_module_detect_int(struct link_params *params)
MISC_REGISTERS_GPIO_INT_OUTPUT_CLR,
port);
- if (bnx2x_wait_for_sfp_module_initialized(params)
- == 0)
+ if (bnx2x_wait_for_sfp_module_initialized(params) ==
+ 0)
bnx2x_sfp_module_detection(params);
else
DP(NETIF_MSG_LINK, "SFP+ module is not initialized\n");
} else {
- u8 ext_phy_addr = ((params->ext_phy_config &
- PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
- PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
+ u8 ext_phy_addr = XGXS_EXT_PHY_ADDR(params->ext_phy_config);
+
+ u32 ext_phy_type =
+ XGXS_EXT_PHY_TYPE(params->ext_phy_config);
+ u32 val = REG_RD(bp, params->shmem_base +
+ offsetof(struct shmem_region, dev_info.
+ port_feature_config[params->port].
+ config));
+
bnx2x_set_gpio_int(bp, MISC_REGISTERS_GPIO_3,
MISC_REGISTERS_GPIO_INT_OUTPUT_SET,
port);
/* Module was plugged out. */
/* Disable transmit for this module */
- bnx2x_bcm8726_set_transmitter(bp, params->port,
- ext_phy_addr, 0);
+ if ((val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) ==
+ PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_DISABLE_TX_LASER)
+ bnx2x_sfp_set_transmitter(bp, params->port,
+ ext_phy_type, ext_phy_addr, 0);
}
}
@@ -2719,9 +3215,7 @@ static void bnx2x_bcm807x_force_10G(struct link_params *params)
{
struct bnx2x *bp = params->bp;
u8 port = params->port;
- u8 ext_phy_addr = ((params->ext_phy_config &
- PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
- PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
+ u8 ext_phy_addr = XGXS_EXT_PHY_ADDR(params->ext_phy_config);
u32 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
/* Force KR or KX */
@@ -2742,14 +3236,13 @@ static void bnx2x_bcm807x_force_10G(struct link_params *params)
MDIO_AN_REG_CTRL,
0x0000);
}
+
static void bnx2x_bcm8073_set_xaui_low_power_mode(struct link_params *params)
{
struct bnx2x *bp = params->bp;
u8 port = params->port;
u16 val;
- u8 ext_phy_addr = ((params->ext_phy_config &
- PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
- PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
+ u8 ext_phy_addr = XGXS_EXT_PHY_ADDR(params->ext_phy_config);
u32 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
bnx2x_cl45_read(bp, params->port,
@@ -2811,12 +3304,9 @@ static void bnx2x_bcm8073_set_xaui_low_power_mode(struct link_params *params)
static void bnx2x_8073_set_pause_cl37(struct link_params *params,
struct link_vars *vars)
{
-
struct bnx2x *bp = params->bp;
u16 cl37_val;
- u8 ext_phy_addr = ((params->ext_phy_config &
- PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
- PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
+ u8 ext_phy_addr = XGXS_EXT_PHY_ADDR(params->ext_phy_config);
u32 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
bnx2x_cl45_read(bp, params->port,
@@ -2859,9 +3349,7 @@ static void bnx2x_ext_phy_set_pause(struct link_params *params,
{
struct bnx2x *bp = params->bp;
u16 val;
- u8 ext_phy_addr = ((params->ext_phy_config &
- PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
- PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
+ u8 ext_phy_addr = XGXS_EXT_PHY_ADDR(params->ext_phy_config);
u32 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
/* read modify write pause advertizing */
@@ -2918,10 +3406,136 @@ static void bnx2x_set_preemphasis(struct link_params *params)
}
}
+
+static void bnx2x_8481_set_led4(struct link_params *params,
+ u32 ext_phy_type, u8 ext_phy_addr)
+{
+ struct bnx2x *bp = params->bp;
+
+ /* PHYC_CTL_LED_CTL */
+ bnx2x_cl45_write(bp, params->port,
+ ext_phy_type,
+ ext_phy_addr,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_8481_LINK_SIGNAL, 0xa482);
+
+ /* Unmask LED4 for 10G link */
+ bnx2x_cl45_write(bp, params->port,
+ ext_phy_type,
+ ext_phy_addr,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_8481_SIGNAL_MASK, (1<<6));
+ /* 'Interrupt Mask' */
+ bnx2x_cl45_write(bp, params->port,
+ ext_phy_type,
+ ext_phy_addr,
+ MDIO_AN_DEVAD,
+ 0xFFFB, 0xFFFD);
+}
+static void bnx2x_8481_set_legacy_led_mode(struct link_params *params,
+ u32 ext_phy_type, u8 ext_phy_addr)
+{
+ struct bnx2x *bp = params->bp;
+
+ /* LED1 (10G Link): Disable LED1 when 10/100/1000 link */
+ /* LED2 (1G/100/10 Link): Enable LED2 when 10/100/1000 link) */
+ bnx2x_cl45_write(bp, params->port,
+ ext_phy_type,
+ ext_phy_addr,
+ MDIO_AN_DEVAD,
+ MDIO_AN_REG_8481_LEGACY_SHADOW,
+ (1<<15) | (0xd << 10) | (0xc<<4) | 0xe);
+}
+
+static void bnx2x_8481_set_10G_led_mode(struct link_params *params,
+ u32 ext_phy_type, u8 ext_phy_addr)
+{
+ struct bnx2x *bp = params->bp;
+ u16 val1;
+
+ /* LED1 (10G Link) */
+ /* Enable continuse based on source 7(10G-link) */
+ bnx2x_cl45_read(bp, params->port,
+ ext_phy_type,
+ ext_phy_addr,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_8481_LINK_SIGNAL,
+ &val1);
+ /* Set bit 2 to 0, and bits [1:0] to 10 */
+ val1 &= ~((1<<0) | (1<<2)); /* Clear bits 0,2*/
+ val1 |= (1<<1); /* Set bit 1 */
+
+ bnx2x_cl45_write(bp, params->port,
+ ext_phy_type,
+ ext_phy_addr,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_8481_LINK_SIGNAL,
+ val1);
+
+ /* Unmask LED1 for 10G link */
+ bnx2x_cl45_read(bp, params->port,
+ ext_phy_type,
+ ext_phy_addr,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_8481_LED1_MASK,
+ &val1);
+ /* Set bit 2 to 0, and bits [1:0] to 10 */
+ val1 |= (1<<7);
+ bnx2x_cl45_write(bp, params->port,
+ ext_phy_type,
+ ext_phy_addr,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_8481_LED1_MASK,
+ val1);
+
+ /* LED2 (1G/100/10G Link) */
+ /* Mask LED2 for 10G link */
+ bnx2x_cl45_write(bp, params->port,
+ ext_phy_type,
+ ext_phy_addr,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_8481_LED2_MASK,
+ 0);
+
+ /* LED3 (10G/1G/100/10G Activity) */
+ bnx2x_cl45_read(bp, params->port,
+ ext_phy_type,
+ ext_phy_addr,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_8481_LINK_SIGNAL,
+ &val1);
+ /* Enable blink based on source 4(Activity) */
+ val1 &= ~((1<<7) | (1<<8)); /* Clear bits 7,8 */
+ val1 |= (1<<6); /* Set only bit 6 */
+ bnx2x_cl45_write(bp, params->port,
+ ext_phy_type,
+ ext_phy_addr,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_8481_LINK_SIGNAL,
+ val1);
+
+ bnx2x_cl45_read(bp, params->port,
+ ext_phy_type,
+ ext_phy_addr,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_8481_LED3_MASK,
+ &val1);
+ val1 |= (1<<4); /* Unmask LED3 for 10G link */
+ bnx2x_cl45_write(bp, params->port,
+ ext_phy_type,
+ ext_phy_addr,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_8481_LED3_MASK,
+ val1);
+}
+
+
static void bnx2x_init_internal_phy(struct link_params *params,
- struct link_vars *vars)
+ struct link_vars *vars,
+ u8 enable_cl73)
{
struct bnx2x *bp = params->bp;
+
if (!(vars->phy_flags & PHY_SGMII_FLAG)) {
if ((XGXS_EXT_PHY_TYPE(params->ext_phy_config) ==
PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) &&
@@ -2934,7 +3548,7 @@ static void bnx2x_init_internal_phy(struct link_params *params,
DP(NETIF_MSG_LINK, "not SGMII, no AN\n");
/* disable autoneg */
- bnx2x_set_autoneg(params, vars);
+ bnx2x_set_autoneg(params, vars, 0);
/* program speed and duplex */
bnx2x_program_serdes(params, vars);
@@ -2950,10 +3564,10 @@ static void bnx2x_init_internal_phy(struct link_params *params,
vars->ieee_fc);
/* enable autoneg */
- bnx2x_set_autoneg(params, vars);
+ bnx2x_set_autoneg(params, vars, enable_cl73);
/* enable and restart AN */
- bnx2x_restart_autoneg(params);
+ bnx2x_restart_autoneg(params, enable_cl73);
}
} else { /* SGMII mode */
@@ -2972,10 +3586,9 @@ static u8 bnx2x_ext_phy_init(struct link_params *params, struct link_vars *vars)
u16 ctrl = 0;
u16 val = 0;
u8 rc = 0;
+
if (vars->phy_flags & PHY_XGXS_FLAG) {
- ext_phy_addr = ((params->ext_phy_config &
- PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
- PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
+ ext_phy_addr = XGXS_EXT_PHY_ADDR(params->ext_phy_config);
ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
/* Make sure that the soft reset is off (expect for the 8072:
@@ -3160,6 +3773,9 @@ static u8 bnx2x_ext_phy_init(struct link_params *params, struct link_vars *vars)
driver is loaded, it reset all registers, including the
transmitter */
bnx2x_sfp_module_detection(params);
+
+ /* Set Flow control */
+ bnx2x_ext_phy_set_pause(params, vars);
if (params->req_line_speed == SPEED_1000) {
DP(NETIF_MSG_LINK, "Setting 1G force\n");
bnx2x_cl45_write(bp, params->port, ext_phy_type,
@@ -3267,14 +3883,12 @@ static u8 bnx2x_ext_phy_init(struct link_params *params, struct link_vars *vars)
bnx2x_8073_set_pause_cl37(params, vars);
if (ext_phy_type ==
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072){
+ PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072)
bnx2x_bcm8072_external_rom_boot(params);
- } else {
-
+ else
/* In case of 8073 with long xaui lines,
don't set the 8073 xaui low power*/
bnx2x_bcm8073_set_xaui_low_power_mode(params);
- }
bnx2x_cl45_read(bp, params->port,
ext_phy_type,
@@ -3339,10 +3953,8 @@ static u8 bnx2x_ext_phy_init(struct link_params *params, struct link_vars *vars)
ext_phy_addr,
MDIO_AN_DEVAD,
MDIO_AN_REG_ADV, val);
-
if (ext_phy_type ==
PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073) {
-
bnx2x_cl45_read(bp, params->port,
ext_phy_type,
ext_phy_addr,
@@ -3450,6 +4062,187 @@ static u8 bnx2x_ext_phy_init(struct link_params *params, struct link_vars *vars)
((val & (1<<7)) > 0));
break;
}
+
+ case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727:
+ {
+ u16 tmp1;
+ u16 rx_alarm_ctrl_val;
+ u16 lasi_ctrl_val;
+
+ /* Enable PMD link, MOD_ABS_FLT, and 1G link alarm */
+
+ u16 mod_abs;
+ rx_alarm_ctrl_val = (1<<2) | (1<<5) ;
+ lasi_ctrl_val = 0x0004;
+
+ DP(NETIF_MSG_LINK, "Initializing BCM8727\n");
+ /* enable LASI */
+ bnx2x_cl45_write(bp, params->port,
+ ext_phy_type,
+ ext_phy_addr,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_RX_ALARM_CTRL,
+ rx_alarm_ctrl_val);
+
+ bnx2x_cl45_write(bp, params->port,
+ ext_phy_type,
+ ext_phy_addr,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_LASI_CTRL,
+ lasi_ctrl_val);
+
+ /* Initially configure MOD_ABS to interrupt when
+ module is presence( bit 8) */
+ bnx2x_cl45_read(bp, params->port,
+ ext_phy_type,
+ ext_phy_addr,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_PHY_IDENTIFIER, &mod_abs);
+ /* Set EDC off by setting OPTXLOS signal input to low
+ (bit 9).
+ When the EDC is off it locks onto a reference clock and
+ avoids becoming 'lost'.*/
+ mod_abs &= ~((1<<8) | (1<<9));
+ bnx2x_cl45_write(bp, params->port,
+ ext_phy_type,
+ ext_phy_addr,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_PHY_IDENTIFIER, mod_abs);
+
+ /* Make MOD_ABS give interrupt on change */
+ bnx2x_cl45_read(bp, params->port,
+ ext_phy_type,
+ ext_phy_addr,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_8727_PCS_OPT_CTRL,
+ &val);
+ val |= (1<<12);
+ bnx2x_cl45_write(bp, params->port,
+ ext_phy_type,
+ ext_phy_addr,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_8727_PCS_OPT_CTRL,
+ val);
+
+ /* Set 8727 GPIOs to input to allow reading from the
+ 8727 GPIO0 status which reflect SFP+ module
+ over-current */
+
+ bnx2x_cl45_read(bp, params->port,
+ PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727,
+ ext_phy_addr,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_8727_PCS_OPT_CTRL,
+ &val);
+ val &= 0xff8f; /* Reset bits 4-6 */
+ bnx2x_cl45_write(bp, params->port,
+ PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727,
+ ext_phy_addr,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_8727_PCS_OPT_CTRL,
+ val);
+
+ bnx2x_8727_power_module(bp, params, ext_phy_addr, 1);
+ bnx2x_bcm8073_set_xaui_low_power_mode(params);
+
+ bnx2x_cl45_read(bp, params->port,
+ ext_phy_type,
+ ext_phy_addr,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_M8051_MSGOUT_REG,
+ &tmp1);
+
+ bnx2x_cl45_read(bp, params->port,
+ ext_phy_type,
+ ext_phy_addr,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_RX_ALARM, &tmp1);
+
+ /* Set option 1G speed */
+ if (params->req_line_speed == SPEED_1000) {
+
+ DP(NETIF_MSG_LINK, "Setting 1G force\n");
+ bnx2x_cl45_write(bp, params->port,
+ ext_phy_type,
+ ext_phy_addr,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_CTRL, 0x40);
+ bnx2x_cl45_write(bp, params->port,
+ ext_phy_type,
+ ext_phy_addr,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_10G_CTRL2, 0xD);
+ bnx2x_cl45_read(bp, params->port,
+ ext_phy_type,
+ ext_phy_addr,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_10G_CTRL2, &tmp1);
+ DP(NETIF_MSG_LINK, "1.7 = 0x%x \n", tmp1);
+
+ } else if ((params->req_line_speed ==
+ SPEED_AUTO_NEG) &&
+ ((params->speed_cap_mask &
+ PORT_HW_CFG_SPEED_CAPABILITY_D0_1G))) {
+
+ DP(NETIF_MSG_LINK, "Setting 1G clause37 \n");
+ bnx2x_cl45_write(bp, params->port, ext_phy_type,
+ ext_phy_addr, MDIO_AN_DEVAD,
+ MDIO_PMA_REG_8727_MISC_CTRL, 0);
+ bnx2x_cl45_write(bp, params->port, ext_phy_type,
+ ext_phy_addr, MDIO_AN_DEVAD,
+ MDIO_AN_REG_CL37_AN, 0x1300);
+ } else {
+ /* Since the 8727 has only single reset pin,
+ need to set the 10G registers although it is
+ default */
+ bnx2x_cl45_write(bp, params->port, ext_phy_type,
+ ext_phy_addr, MDIO_AN_DEVAD,
+ MDIO_AN_REG_CTRL, 0x0020);
+ bnx2x_cl45_write(bp, params->port, ext_phy_type,
+ ext_phy_addr, MDIO_AN_DEVAD,
+ 0x7, 0x0100);
+ bnx2x_cl45_write(bp, params->port, ext_phy_type,
+ ext_phy_addr, MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_CTRL, 0x2040);
+ bnx2x_cl45_write(bp, params->port, ext_phy_type,
+ ext_phy_addr, MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_10G_CTRL2, 0x0008);
+ }
+
+ /* Set 2-wire transfer rate to 400Khz since 100Khz
+ is not operational */
+ bnx2x_cl45_write(bp, params->port,
+ ext_phy_type,
+ ext_phy_addr,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_8727_TWO_WIRE_SLAVE_ADDR,
+ 0xa101);
+
+ /* Set TX PreEmphasis if needed */
+ if ((params->feature_config_flags &
+ FEATURE_CONFIG_OVERRIDE_PREEMPHASIS_ENABLED)) {
+ DP(NETIF_MSG_LINK, "Setting TX_CTRL1 0x%x,"
+ "TX_CTRL2 0x%x\n",
+ params->xgxs_config_tx[0],
+ params->xgxs_config_tx[1]);
+ bnx2x_cl45_write(bp, params->port,
+ ext_phy_type,
+ ext_phy_addr,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_8727_TX_CTRL1,
+ params->xgxs_config_tx[0]);
+
+ bnx2x_cl45_write(bp, params->port,
+ ext_phy_type,
+ ext_phy_addr,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_8727_TX_CTRL2,
+ params->xgxs_config_tx[1]);
+ }
+
+ break;
+ }
+
case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101:
{
u16 fw_ver1, fw_ver2;
@@ -3495,20 +4288,112 @@ static u8 bnx2x_ext_phy_init(struct link_params *params, struct link_vars *vars)
bnx2x_save_spirom_version(params->bp, params->port,
params->shmem_base,
(u32)(fw_ver1<<16 | fw_ver2));
-
break;
}
case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481:
- DP(NETIF_MSG_LINK,
- "Setting the BCM8481 LASI control\n");
+ /* This phy uses the NIG latch mechanism since link
+ indication arrives through its LED4 and not via
+ its LASI signal, so we get steady signal
+ instead of clear on read */
+ bnx2x_bits_en(bp, NIG_REG_LATCH_BC_0 + params->port*4,
+ 1 << NIG_LATCH_BC_ENABLE_MI_INT);
+
+ bnx2x_8481_set_led4(params, ext_phy_type, ext_phy_addr);
+ if (params->req_line_speed == SPEED_AUTO_NEG) {
+
+ u16 autoneg_val, an_1000_val, an_10_100_val;
+ /* set 1000 speed advertisement */
+ bnx2x_cl45_read(bp, params->port,
+ ext_phy_type,
+ ext_phy_addr,
+ MDIO_AN_DEVAD,
+ MDIO_AN_REG_8481_1000T_CTRL,
+ &an_1000_val);
- bnx2x_cl45_write(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_LASI_CTRL, 0x1);
+ if (params->speed_cap_mask &
+ PORT_HW_CFG_SPEED_CAPABILITY_D0_1G) {
+ an_1000_val |= (1<<8);
+ if (params->req_duplex == DUPLEX_FULL)
+ an_1000_val |= (1<<9);
+ DP(NETIF_MSG_LINK, "Advertising 1G\n");
+ } else
+ an_1000_val &= ~((1<<8) | (1<<9));
- /* Restart autoneg */
+ bnx2x_cl45_write(bp, params->port,
+ ext_phy_type,
+ ext_phy_addr,
+ MDIO_AN_DEVAD,
+ MDIO_AN_REG_8481_1000T_CTRL,
+ an_1000_val);
+
+ /* set 100 speed advertisement */
+ bnx2x_cl45_read(bp, params->port,
+ ext_phy_type,
+ ext_phy_addr,
+ MDIO_AN_DEVAD,
+ MDIO_AN_REG_8481_LEGACY_AN_ADV,
+ &an_10_100_val);
+
+ if (params->speed_cap_mask &
+ (PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_FULL |
+ PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_HALF)) {
+ an_10_100_val |= (1<<7);
+ if (params->req_duplex == DUPLEX_FULL)
+ an_10_100_val |= (1<<8);
+ DP(NETIF_MSG_LINK,
+ "Advertising 100M\n");
+ } else
+ an_10_100_val &= ~((1<<7) | (1<<8));
+
+ /* set 10 speed advertisement */
+ if (params->speed_cap_mask &
+ (PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_FULL |
+ PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_HALF)) {
+ an_10_100_val |= (1<<5);
+ if (params->req_duplex == DUPLEX_FULL)
+ an_10_100_val |= (1<<6);
+ DP(NETIF_MSG_LINK, "Advertising 10M\n");
+ }
+ else
+ an_10_100_val &= ~((1<<5) | (1<<6));
+
+ bnx2x_cl45_write(bp, params->port,
+ ext_phy_type,
+ ext_phy_addr,
+ MDIO_AN_DEVAD,
+ MDIO_AN_REG_8481_LEGACY_AN_ADV,
+ an_10_100_val);
+
+ bnx2x_cl45_read(bp, params->port,
+ ext_phy_type,
+ ext_phy_addr,
+ MDIO_AN_DEVAD,
+ MDIO_AN_REG_8481_LEGACY_MII_CTRL,
+ &autoneg_val);
+
+ /* Disable forced speed */
+ autoneg_val &= ~(1<<6|1<<13);
+
+ /* Enable autoneg and restart autoneg
+ for legacy speeds */
+ autoneg_val |= (1<<9|1<<12);
+
+ if (params->req_duplex == DUPLEX_FULL)
+ autoneg_val |= (1<<8);
+ else
+ autoneg_val &= ~(1<<8);
+
+ bnx2x_cl45_write(bp, params->port,
+ ext_phy_type,
+ ext_phy_addr,
+ MDIO_AN_DEVAD,
+ MDIO_AN_REG_8481_LEGACY_MII_CTRL,
+ autoneg_val);
+
+ if (params->speed_cap_mask &
+ PORT_HW_CFG_SPEED_CAPABILITY_D0_10G) {
+ DP(NETIF_MSG_LINK, "Advertising 10G\n");
+ /* Restart autoneg for 10G*/
bnx2x_cl45_read(bp, params->port,
ext_phy_type,
ext_phy_addr,
@@ -3520,12 +4405,81 @@ static u8 bnx2x_ext_phy_init(struct link_params *params, struct link_vars *vars)
ext_phy_addr,
MDIO_AN_DEVAD,
MDIO_AN_REG_CTRL, val);
+ }
+ } else {
+ /* Force speed */
+ u16 autoneg_ctrl, pma_ctrl;
+ bnx2x_cl45_read(bp, params->port,
+ ext_phy_type,
+ ext_phy_addr,
+ MDIO_AN_DEVAD,
+ MDIO_AN_REG_8481_LEGACY_MII_CTRL,
+ &autoneg_ctrl);
- bnx2x_save_bcm_spirom_ver(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- params->shmem_base);
+ /* Disable autoneg */
+ autoneg_ctrl &= ~(1<<12);
+
+ /* Set 1000 force */
+ switch (params->req_line_speed) {
+ case SPEED_10000:
+ DP(NETIF_MSG_LINK,
+ "Unable to set 10G force !\n");
+ break;
+ case SPEED_1000:
+ bnx2x_cl45_read(bp, params->port,
+ ext_phy_type,
+ ext_phy_addr,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_CTRL,
+ &pma_ctrl);
+ autoneg_ctrl &= ~(1<<13);
+ autoneg_ctrl |= (1<<6);
+ pma_ctrl &= ~(1<<13);
+ pma_ctrl |= (1<<6);
+ DP(NETIF_MSG_LINK,
+ "Setting 1000M force\n");
+ bnx2x_cl45_write(bp, params->port,
+ ext_phy_type,
+ ext_phy_addr,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_CTRL,
+ pma_ctrl);
+ break;
+ case SPEED_100:
+ autoneg_ctrl |= (1<<13);
+ autoneg_ctrl &= ~(1<<6);
+ DP(NETIF_MSG_LINK,
+ "Setting 100M force\n");
+ break;
+ case SPEED_10:
+ autoneg_ctrl &= ~(1<<13);
+ autoneg_ctrl &= ~(1<<6);
+ DP(NETIF_MSG_LINK,
+ "Setting 10M force\n");
+ break;
+ }
+
+ /* Duplex mode */
+ if (params->req_duplex == DUPLEX_FULL) {
+ autoneg_ctrl |= (1<<8);
+ DP(NETIF_MSG_LINK,
+ "Setting full duplex\n");
+ } else
+ autoneg_ctrl &= ~(1<<8);
+
+ /* Update autoneg ctrl and pma ctrl */
+ bnx2x_cl45_write(bp, params->port,
+ ext_phy_type,
+ ext_phy_addr,
+ MDIO_AN_DEVAD,
+ MDIO_AN_REG_8481_LEGACY_MII_CTRL,
+ autoneg_ctrl);
+ }
+ /* Save spirom version */
+ bnx2x_save_8481_spirom_version(bp, params->port,
+ ext_phy_addr,
+ params->shmem_base);
break;
case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE:
DP(NETIF_MSG_LINK,
@@ -3561,9 +4515,101 @@ static u8 bnx2x_ext_phy_init(struct link_params *params, struct link_vars *vars)
return rc;
}
+static void bnx2x_8727_handle_mod_abs(struct link_params *params)
+{
+ struct bnx2x *bp = params->bp;
+ u16 mod_abs, rx_alarm_status;
+ u8 ext_phy_addr = XGXS_EXT_PHY_ADDR(params->ext_phy_config);
+ u32 val = REG_RD(bp, params->shmem_base +
+ offsetof(struct shmem_region, dev_info.
+ port_feature_config[params->port].
+ config));
+ bnx2x_cl45_read(bp, params->port,
+ PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727,
+ ext_phy_addr,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_PHY_IDENTIFIER, &mod_abs);
+ if (mod_abs & (1<<8)) {
+
+ /* Module is absent */
+ DP(NETIF_MSG_LINK, "MOD_ABS indication "
+ "show module is absent\n");
+
+ /* 1. Set mod_abs to detect next module
+ presence event
+ 2. Set EDC off by setting OPTXLOS signal input to low
+ (bit 9).
+ When the EDC is off it locks onto a reference clock and
+ avoids becoming 'lost'.*/
+ mod_abs &= ~((1<<8)|(1<<9));
+ bnx2x_cl45_write(bp, params->port,
+ PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727,
+ ext_phy_addr,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_PHY_IDENTIFIER, mod_abs);
+
+ /* Clear RX alarm since it stays up as long as
+ the mod_abs wasn't changed */
+ bnx2x_cl45_read(bp, params->port,
+ PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727,
+ ext_phy_addr,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_RX_ALARM, &rx_alarm_status);
+
+ } else {
+ /* Module is present */
+ DP(NETIF_MSG_LINK, "MOD_ABS indication "
+ "show module is present\n");
+ /* First thing, disable transmitter,
+ and if the module is ok, the
+ module_detection will enable it*/
+
+ /* 1. Set mod_abs to detect next module
+ absent event ( bit 8)
+ 2. Restore the default polarity of the OPRXLOS signal and
+ this signal will then correctly indicate the presence or
+ absence of the Rx signal. (bit 9) */
+ mod_abs |= ((1<<8)|(1<<9));
+ bnx2x_cl45_write(bp, params->port,
+ PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727,
+ ext_phy_addr,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_PHY_IDENTIFIER, mod_abs);
+
+ /* Clear RX alarm since it stays up as long as
+ the mod_abs wasn't changed. This is need to be done
+ before calling the module detection, otherwise it will clear
+ the link update alarm */
+ bnx2x_cl45_read(bp, params->port,
+ PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727,
+ ext_phy_addr,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_RX_ALARM, &rx_alarm_status);
+
+
+ if ((val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) ==
+ PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_DISABLE_TX_LASER)
+ bnx2x_sfp_set_transmitter(bp, params->port,
+ PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727,
+ ext_phy_addr, 0);
+
+ if (bnx2x_wait_for_sfp_module_initialized(params)
+ == 0)
+ bnx2x_sfp_module_detection(params);
+ else
+ DP(NETIF_MSG_LINK, "SFP+ module is not initialized\n");
+ }
+
+ DP(NETIF_MSG_LINK, "8727 RX_ALARM_STATUS 0x%x\n",
+ rx_alarm_status);
+ /* No need to check link status in case of
+ module plugged in/out */
+}
+
static u8 bnx2x_ext_phy_is_link_up(struct link_params *params,
- struct link_vars *vars)
+ struct link_vars *vars,
+ u8 is_mi_int)
{
struct bnx2x *bp = params->bp;
u32 ext_phy_type;
@@ -3572,11 +4618,9 @@ static u8 bnx2x_ext_phy_is_link_up(struct link_params *params,
u16 rx_sd, pcs_status;
u8 ext_phy_link_up = 0;
u8 port = params->port;
- if (vars->phy_flags & PHY_XGXS_FLAG) {
- ext_phy_addr = ((params->ext_phy_config &
- PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
- PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
+ if (vars->phy_flags & PHY_XGXS_FLAG) {
+ ext_phy_addr = XGXS_EXT_PHY_ADDR(params->ext_phy_config);
ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
switch (ext_phy_type) {
case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
@@ -3602,8 +4646,19 @@ static u8 bnx2x_ext_phy_is_link_up(struct link_params *params,
ext_phy_addr,
MDIO_PMA_DEVAD,
MDIO_PMA_REG_RX_SD, &rx_sd);
- DP(NETIF_MSG_LINK, "8705 rx_sd 0x%x\n", rx_sd);
- ext_phy_link_up = (rx_sd & 0x1);
+
+ bnx2x_cl45_read(bp, params->port, ext_phy_type,
+ ext_phy_addr,
+ 1,
+ 0xc809, &val1);
+ bnx2x_cl45_read(bp, params->port, ext_phy_type,
+ ext_phy_addr,
+ 1,
+ 0xc809, &val1);
+
+ DP(NETIF_MSG_LINK, "8705 1.c809 val=0x%x\n", val1);
+ ext_phy_link_up = ((rx_sd & 0x1) && (val1 & (1<<9))
+ && ((val1 & (1<<8)) == 0));
if (ext_phy_link_up)
vars->line_speed = SPEED_10000;
break;
@@ -3672,19 +4727,172 @@ static u8 bnx2x_ext_phy_is_link_up(struct link_params *params,
break;
}
}
-
if (val2 & (1<<1))
vars->line_speed = SPEED_1000;
else
vars->line_speed = SPEED_10000;
}
+ break;
+
+ case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727:
+ {
+ u16 link_status = 0;
+ u16 rx_alarm_status;
+ /* Check the LASI */
+ bnx2x_cl45_read(bp, params->port,
+ ext_phy_type,
+ ext_phy_addr,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_RX_ALARM, &rx_alarm_status);
+
+ DP(NETIF_MSG_LINK, "8727 RX_ALARM_STATUS 0x%x\n",
+ rx_alarm_status);
+
+ bnx2x_cl45_read(bp, params->port,
+ ext_phy_type,
+ ext_phy_addr,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_LASI_STATUS, &val1);
+
+ DP(NETIF_MSG_LINK,
+ "8727 LASI status 0x%x\n",
+ val1);
+
+ /* Clear MSG-OUT */
+ bnx2x_cl45_read(bp, params->port,
+ ext_phy_type,
+ ext_phy_addr,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_M8051_MSGOUT_REG,
+ &val1);
+
+ /*
+ * If a module is present and there is need to check
+ * for over current
+ */
+ if (!(params->feature_config_flags &
+ FEATURE_CONFIG_BCM8727_NOC) &&
+ !(rx_alarm_status & (1<<5))) {
+ /* Check over-current using 8727 GPIO0 input*/
+ bnx2x_cl45_read(bp, params->port,
+ ext_phy_type,
+ ext_phy_addr,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_8727_GPIO_CTRL,
+ &val1);
+
+ if ((val1 & (1<<8)) == 0) {
+ DP(NETIF_MSG_LINK, "8727 Power fault"
+ " has been detected on "
+ "port %d\n",
+ params->port);
+ printk(KERN_ERR PFX "Error: Power"
+ " fault on %s Port %d has"
+ " been detected and the"
+ " power to that SFP+ module"
+ " has been removed to prevent"
+ " failure of the card. Please"
+ " remove the SFP+ module and"
+ " restart the system to clear"
+ " this error.\n"
+ , bp->dev->name, params->port);
+ /*
+ * Disable all RX_ALARMs except for
+ * mod_abs
+ */
+ bnx2x_cl45_write(bp, params->port,
+ ext_phy_type,
+ ext_phy_addr,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_RX_ALARM_CTRL,
+ (1<<5));
+
+ bnx2x_cl45_read(bp, params->port,
+ ext_phy_type,
+ ext_phy_addr,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_PHY_IDENTIFIER,
+ &val1);
+ /* Wait for module_absent_event */
+ val1 |= (1<<8);
+ bnx2x_cl45_write(bp, params->port,
+ ext_phy_type,
+ ext_phy_addr,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_PHY_IDENTIFIER,
+ val1);
+ /* Clear RX alarm */
+ bnx2x_cl45_read(bp, params->port,
+ ext_phy_type,
+ ext_phy_addr,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_RX_ALARM,
+ &rx_alarm_status);
+ break;
+ }
+ } /* Over current check */
+
+ /* When module absent bit is set, check module */
+ if (rx_alarm_status & (1<<5)) {
+ bnx2x_8727_handle_mod_abs(params);
+ /* Enable all mod_abs and link detection bits */
+ bnx2x_cl45_write(bp, params->port,
+ ext_phy_type,
+ ext_phy_addr,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_RX_ALARM_CTRL,
+ ((1<<5) | (1<<2)));
+ }
+
+ /* If transmitter is disabled,
+ ignore false link up indication */
+ bnx2x_cl45_read(bp, params->port,
+ ext_phy_type,
+ ext_phy_addr,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_PHY_IDENTIFIER,
+ &val1);
+ if (val1 & (1<<15)) {
+ DP(NETIF_MSG_LINK, "Tx is disabled\n");
+ ext_phy_link_up = 0;
+ break;
+ }
+ bnx2x_cl45_read(bp, params->port,
+ ext_phy_type,
+ ext_phy_addr,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_8073_SPEED_LINK_STATUS,
+ &link_status);
+
+ /* Bits 0..2 --> speed detected,
+ bits 13..15--> link is down */
+ if ((link_status & (1<<2)) &&
+ (!(link_status & (1<<15)))) {
+ ext_phy_link_up = 1;
+ vars->line_speed = SPEED_10000;
+ } else if ((link_status & (1<<0)) &&
+ (!(link_status & (1<<13)))) {
+ ext_phy_link_up = 1;
+ vars->line_speed = SPEED_1000;
+ DP(NETIF_MSG_LINK,
+ "port %x: External link"
+ " up in 1G\n", params->port);
+ } else {
+ ext_phy_link_up = 0;
+ DP(NETIF_MSG_LINK,
+ "port %x: External link"
+ " is down\n", params->port);
+ }
break;
+ }
+
case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072:
case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
{
u16 link_status = 0;
u16 an1000_status = 0;
+
if (ext_phy_type ==
PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072) {
bnx2x_cl45_read(bp, params->port,
@@ -3700,7 +4908,6 @@ static u8 bnx2x_ext_phy_is_link_up(struct link_params *params,
DP(NETIF_MSG_LINK,
"870x LASI status 0x%x->0x%x\n",
val1, val2);
-
} else {
/* In 8073, port1 is directed through emac0 and
* port0 is directed through emac1
@@ -3830,8 +5037,6 @@ static u8 bnx2x_ext_phy_is_link_up(struct link_params *params,
MDIO_PMA_DEVAD,
MDIO_PMA_REG_CDR_BANDWIDTH,
0x0333);
-
-
}
bnx2x_cl45_read(bp, params->port,
ext_phy_type,
@@ -3943,51 +5148,79 @@ static u8 bnx2x_ext_phy_is_link_up(struct link_params *params,
}
break;
case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481:
- /* Clear LASI interrupt */
- bnx2x_cl45_read(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_LASI_STATUS, &val1);
- DP(NETIF_MSG_LINK, "8481 LASI status reg = 0x%x\n",
- val1);
-
/* Check 10G-BaseT link status */
- /* Check Global PMD signal ok */
+ /* Check PMD signal ok */
bnx2x_cl45_read(bp, params->port, ext_phy_type,
- ext_phy_addr,
- MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_SD,
- &rx_sd);
- /* Check PCS block lock */
+ ext_phy_addr,
+ MDIO_AN_DEVAD,
+ 0xFFFA,
+ &val1);
bnx2x_cl45_read(bp, params->port, ext_phy_type,
ext_phy_addr,
- MDIO_PCS_DEVAD, MDIO_PCS_REG_STATUS,
- &pcs_status);
- DP(NETIF_MSG_LINK, "8481 1.a = 0x%x, 1.20 = 0x%x\n",
- rx_sd, pcs_status);
- if (rx_sd & pcs_status & 0x1) {
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_8481_PMD_SIGNAL,
+ &val2);
+ DP(NETIF_MSG_LINK, "PMD_SIGNAL 1.a811 = 0x%x\n", val2);
+
+ /* Check link 10G */
+ if (val2 & (1<<11)) {
vars->line_speed = SPEED_10000;
ext_phy_link_up = 1;
- } else {
-
- /* Check 1000-BaseT link status */
- bnx2x_cl45_read(bp, params->port, ext_phy_type,
- ext_phy_addr,
- MDIO_AN_DEVAD, 0xFFE1,
- &val1);
+ bnx2x_8481_set_10G_led_mode(params,
+ ext_phy_type,
+ ext_phy_addr);
+ } else { /* Check Legacy speed link */
+ u16 legacy_status, legacy_speed;
+
+ /* Enable expansion register 0x42
+ (Operation mode status) */
+ bnx2x_cl45_write(bp, params->port,
+ ext_phy_type,
+ ext_phy_addr,
+ MDIO_AN_DEVAD,
+ MDIO_AN_REG_8481_EXPANSION_REG_ACCESS,
+ 0xf42);
- bnx2x_cl45_read(bp, params->port, ext_phy_type,
- ext_phy_addr,
- MDIO_AN_DEVAD, 0xFFE1,
- &val2);
- DP(NETIF_MSG_LINK, "8481 7.FFE1 ="
- "0x%x-->0x%x\n", val1, val2);
- if (val2 & (1<<2)) {
- vars->line_speed = SPEED_1000;
- ext_phy_link_up = 1;
+ /* Get legacy speed operation status */
+ bnx2x_cl45_read(bp, params->port,
+ ext_phy_type,
+ ext_phy_addr,
+ MDIO_AN_DEVAD,
+ MDIO_AN_REG_8481_EXPANSION_REG_RD_RW,
+ &legacy_status);
+
+ DP(NETIF_MSG_LINK, "Legacy speed status"
+ " = 0x%x\n", legacy_status);
+ ext_phy_link_up = ((legacy_status & (1<<11))
+ == (1<<11));
+ if (ext_phy_link_up) {
+ legacy_speed = (legacy_status & (3<<9));
+ if (legacy_speed == (0<<9))
+ vars->line_speed = SPEED_10;
+ else if (legacy_speed == (1<<9))
+ vars->line_speed =
+ SPEED_100;
+ else if (legacy_speed == (2<<9))
+ vars->line_speed =
+ SPEED_1000;
+ else /* Should not happen */
+ vars->line_speed = 0;
+
+ if (legacy_status & (1<<8))
+ vars->duplex = DUPLEX_FULL;
+ else
+ vars->duplex = DUPLEX_HALF;
+
+ DP(NETIF_MSG_LINK, "Link is up "
+ "in %dMbps, is_duplex_full"
+ "= %d\n",
+ vars->line_speed,
+ (vars->duplex == DUPLEX_FULL));
+ bnx2x_8481_set_legacy_led_mode(params,
+ ext_phy_type,
+ ext_phy_addr);
}
}
-
break;
default:
DP(NETIF_MSG_LINK, "BAD XGXS ext_phy_config 0x%x\n",
@@ -3995,6 +5228,13 @@ static u8 bnx2x_ext_phy_is_link_up(struct link_params *params,
ext_phy_link_up = 0;
break;
}
+ /* Set SGMII mode for external phy */
+ if (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) {
+ if (vars->line_speed < SPEED_1000)
+ vars->phy_flags |= PHY_SGMII_FLAG;
+ else
+ vars->phy_flags &= ~PHY_SGMII_FLAG;
+ }
} else { /* SerDes */
ext_phy_type = SERDES_EXT_PHY_TYPE(params->ext_phy_config);
@@ -4027,6 +5267,7 @@ static void bnx2x_link_int_enable(struct link_params *params)
u32 ext_phy_type;
u32 mask;
struct bnx2x *bp = params->bp;
+
/* setting the status to report on link up
for either XGXS or SerDes */
@@ -4058,10 +5299,10 @@ static void bnx2x_link_int_enable(struct link_params *params)
bnx2x_bits_en(bp,
NIG_REG_MASK_INTERRUPT_PORT0 + port*4,
mask);
- DP(NETIF_MSG_LINK, "port %x, is_xgxs=%x, int_status 0x%x\n", port,
+
+ DP(NETIF_MSG_LINK, "port %x, is_xgxs %x, int_status 0x%x\n", port,
(params->switch_cfg == SWITCH_CFG_10G),
REG_RD(bp, NIG_REG_STATUS_INTERRUPT_PORT0 + port*4));
-
DP(NETIF_MSG_LINK, " int_mask 0x%x, MI_INT %x, SERDES_LINK %x\n",
REG_RD(bp, NIG_REG_MASK_INTERRUPT_PORT0 + port*4),
REG_RD(bp, NIG_REG_EMAC0_STATUS_MISC_MI_INT + port*0x18),
@@ -4071,12 +5312,47 @@ static void bnx2x_link_int_enable(struct link_params *params)
REG_RD(bp, NIG_REG_XGXS0_STATUS_LINK_STATUS + port*0x68));
}
-
+static void bnx2x_8481_rearm_latch_signal(struct bnx2x *bp, u8 port,
+ u8 is_mi_int)
+{
+ u32 latch_status = 0, is_mi_int_status;
+ /* Disable the MI INT ( external phy int )
+ * by writing 1 to the status register. Link down indication
+ * is high-active-signal, so in this case we need to write the
+ * status to clear the XOR
+ */
+ /* Read Latched signals */
+ latch_status = REG_RD(bp,
+ NIG_REG_LATCH_STATUS_0 + port*8);
+ is_mi_int_status = REG_RD(bp,
+ NIG_REG_STATUS_INTERRUPT_PORT0 + port*4);
+ DP(NETIF_MSG_LINK, "original_signal = 0x%x, nig_status = 0x%x,"
+ "latch_status = 0x%x\n",
+ is_mi_int, is_mi_int_status, latch_status);
+ /* Handle only those with latched-signal=up.*/
+ if (latch_status & 1) {
+ /* For all latched-signal=up,Write original_signal to status */
+ if (is_mi_int)
+ bnx2x_bits_en(bp,
+ NIG_REG_STATUS_INTERRUPT_PORT0
+ + port*4,
+ NIG_STATUS_EMAC0_MI_INT);
+ else
+ bnx2x_bits_dis(bp,
+ NIG_REG_STATUS_INTERRUPT_PORT0
+ + port*4,
+ NIG_STATUS_EMAC0_MI_INT);
+ /* For all latched-signal=up : Re-Arm Latch signals */
+ REG_WR(bp, NIG_REG_LATCH_STATUS_0 + port*8,
+ (latch_status & 0xfffe) | (latch_status & 1));
+ }
+}
/*
* link management
*/
static void bnx2x_link_int_ack(struct link_params *params,
- struct link_vars *vars, u8 is_10g)
+ struct link_vars *vars, u8 is_10g,
+ u8 is_mi_int)
{
struct bnx2x *bp = params->bp;
u8 port = params->port;
@@ -4087,6 +5363,10 @@ static void bnx2x_link_int_ack(struct link_params *params,
(NIG_STATUS_XGXS0_LINK10G |
NIG_STATUS_XGXS0_LINK_STATUS |
NIG_STATUS_SERDES0_LINK_STATUS));
+ if (XGXS_EXT_PHY_TYPE(params->ext_phy_config)
+ == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481) {
+ bnx2x_8481_rearm_latch_signal(bp, port, is_mi_int);
+ }
if (vars->phy_link_up) {
if (is_10g) {
/* Disable the 10G link interrupt
@@ -4106,7 +5386,8 @@ static void bnx2x_link_int_ack(struct link_params *params,
PORT_HW_CFG_LANE_SWAP_CFG_MASTER_MASK) >>
PORT_HW_CFG_LANE_SWAP_CFG_MASTER_SHIFT);
- DP(NETIF_MSG_LINK, "1G XGXS phy link up\n");
+ DP(NETIF_MSG_LINK, "%d speed XGXS phy link up\n",
+ vars->line_speed);
bnx2x_bits_en(bp,
NIG_REG_STATUS_INTERRUPT_PORT0 + port*4,
((1 << ser_lane) <<
@@ -4156,66 +5437,13 @@ static u8 bnx2x_format_ver(u32 num, u8 *str, u16 len)
return 0;
}
-
-static void bnx2x_turn_on_ef(struct bnx2x *bp, u8 port, u8 ext_phy_addr,
- u32 ext_phy_type)
-{
- u32 cnt = 0;
- u16 ctrl = 0;
- /* Enable EMAC0 in to enable MDIO */
- REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_SET,
- (MISC_REGISTERS_RESET_REG_2_RST_EMAC0_HARD_CORE << port));
- msleep(5);
-
- /* take ext phy out of reset */
- bnx2x_set_gpio(bp,
- MISC_REGISTERS_GPIO_2,
- MISC_REGISTERS_GPIO_HIGH,
- port);
-
- bnx2x_set_gpio(bp,
- MISC_REGISTERS_GPIO_1,
- MISC_REGISTERS_GPIO_HIGH,
- port);
-
- /* wait for 5ms */
- msleep(5);
-
- for (cnt = 0; cnt < 1000; cnt++) {
- msleep(1);
- bnx2x_cl45_read(bp, port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_CTRL,
- &ctrl);
- if (!(ctrl & (1<<15))) {
- DP(NETIF_MSG_LINK, "Reset completed\n\n");
- break;
- }
- }
-}
-
-static void bnx2x_turn_off_sf(struct bnx2x *bp, u8 port)
-{
- /* put sf to reset */
- bnx2x_set_gpio(bp,
- MISC_REGISTERS_GPIO_1,
- MISC_REGISTERS_GPIO_LOW,
- port);
- bnx2x_set_gpio(bp,
- MISC_REGISTERS_GPIO_2,
- MISC_REGISTERS_GPIO_LOW,
- port);
-}
-
u8 bnx2x_get_ext_phy_fw_version(struct link_params *params, u8 driver_loaded,
u8 *version, u16 len)
{
struct bnx2x *bp;
u32 ext_phy_type = 0;
u32 spirom_ver = 0;
- u8 status = 0 ;
+ u8 status;
if (version == NULL || params == NULL)
return -EINVAL;
@@ -4225,6 +5453,7 @@ u8 bnx2x_get_ext_phy_fw_version(struct link_params *params, u8 driver_loaded,
offsetof(struct shmem_region,
port_mb[params->port].ext_phy_fw_version));
+ status = 0;
/* reset the returned value to zero */
ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
switch (ext_phy_type) {
@@ -4242,13 +5471,19 @@ u8 bnx2x_get_ext_phy_fw_version(struct link_params *params, u8 driver_loaded,
break;
case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072:
case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
- case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705:
+ case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727:
case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706:
case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726:
+ status = bnx2x_format_ver(spirom_ver, version, len);
+ break;
case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481:
+ spirom_ver = ((spirom_ver & 0xF80) >> 7) << 16 |
+ (spirom_ver & 0x7F);
status = bnx2x_format_ver(spirom_ver, version, len);
break;
case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
+ case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705:
+ version[0] = '\0';
break;
case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE:
@@ -4331,10 +5566,8 @@ static void bnx2x_ext_phy_loopback(struct link_params *params)
if (params->switch_cfg == SWITCH_CFG_10G) {
ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
+ ext_phy_addr = XGXS_EXT_PHY_ADDR(params->ext_phy_config);
/* CL37 Autoneg Enabled */
- ext_phy_addr = ((params->ext_phy_config &
- PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
- PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
switch (ext_phy_type) {
case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN:
@@ -4501,6 +5734,7 @@ u8 bnx2x_set_led(struct bnx2x *bp, u8 port, u8 mode, u32 speed,
u8 rc = 0;
u32 tmp;
u32 emac_base = port ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
+
DP(NETIF_MSG_LINK, "bnx2x_set_led: port %x, mode %d\n", port, mode);
DP(NETIF_MSG_LINK, "speed 0x%x, hw_led_mode 0x%x\n",
speed, hw_led_mode);
@@ -4565,7 +5799,7 @@ u8 bnx2x_test_link(struct link_params *params, struct link_vars *vars)
&gp_status);
/* link is up only if both local phy and external phy are up */
if ((gp_status & MDIO_GP_STATUS_TOP_AN_STATUS1_LINK_STATUS) &&
- bnx2x_ext_phy_is_link_up(params, vars))
+ bnx2x_ext_phy_is_link_up(params, vars, 1))
return 0;
return -ESRCH;
@@ -4579,6 +5813,7 @@ static u8 bnx2x_link_initialize(struct link_params *params,
u8 rc = 0;
u8 non_ext_phy;
u32 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
+
/* Activate the external PHY */
bnx2x_ext_phy_reset(params, vars);
@@ -4630,11 +5865,10 @@ static u8 bnx2x_link_initialize(struct link_params *params,
if (non_ext_phy ||
(ext_phy_type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705) ||
(ext_phy_type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726) ||
- (ext_phy_type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481) ||
(params->loopback_mode == LOOPBACK_EXT_PHY)) {
if (params->req_line_speed == SPEED_AUTO_NEG)
bnx2x_set_parallel_detection(params, vars->phy_flags);
- bnx2x_init_internal_phy(params, vars);
+ bnx2x_init_internal_phy(params, vars, non_ext_phy);
}
if (!non_ext_phy)
@@ -4653,11 +5887,11 @@ static u8 bnx2x_link_initialize(struct link_params *params,
u8 bnx2x_phy_init(struct link_params *params, struct link_vars *vars)
{
struct bnx2x *bp = params->bp;
-
u32 val;
- DP(NETIF_MSG_LINK, "Phy Initialization started \n");
- DP(NETIF_MSG_LINK, "req_speed = %d, req_flowctrl=%d\n",
- params->req_line_speed, params->req_flow_ctrl);
+
+ DP(NETIF_MSG_LINK, "Phy Initialization started\n");
+ DP(NETIF_MSG_LINK, "req_speed %d, req_flowctrl %d\n",
+ params->req_line_speed, params->req_flow_ctrl);
vars->link_status = 0;
vars->phy_link_up = 0;
vars->link_up = 0;
@@ -4671,7 +5905,6 @@ u8 bnx2x_phy_init(struct link_params *params, struct link_vars *vars)
else
vars->phy_flags = PHY_XGXS_FLAG;
-
/* disable attentions */
bnx2x_bits_dis(bp, NIG_REG_MASK_INTERRUPT_PORT0 + params->port*4,
(NIG_MASK_XGXS0_LINK_STATUS |
@@ -4682,6 +5915,7 @@ u8 bnx2x_phy_init(struct link_params *params, struct link_vars *vars)
bnx2x_emac_init(params, vars);
if (CHIP_REV_IS_FPGA(bp)) {
+
vars->link_up = 1;
vars->line_speed = SPEED_10000;
vars->duplex = DUPLEX_FULL;
@@ -4690,7 +5924,8 @@ u8 bnx2x_phy_init(struct link_params *params, struct link_vars *vars)
/* enable on E1.5 FPGA */
if (CHIP_IS_E1H(bp)) {
vars->flow_ctrl |=
- (BNX2X_FLOW_CTRL_TX | BNX2X_FLOW_CTRL_RX);
+ (BNX2X_FLOW_CTRL_TX |
+ BNX2X_FLOW_CTRL_RX);
vars->link_status |=
(LINK_STATUS_TX_FLOW_CONTROL_ENABLED |
LINK_STATUS_RX_FLOW_CONTROL_ENABLED);
@@ -4699,8 +5934,7 @@ u8 bnx2x_phy_init(struct link_params *params, struct link_vars *vars)
bnx2x_emac_enable(params, vars, 0);
bnx2x_pbf_update(params, vars->flow_ctrl, vars->line_speed);
/* disable drain */
- REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE
- + params->port*4, 0);
+ REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + params->port*4, 0);
/* update shared memory */
bnx2x_update_mng(params, vars->link_status);
@@ -4730,6 +5964,7 @@ u8 bnx2x_phy_init(struct link_params *params, struct link_vars *vars)
} else
if (params->loopback_mode == LOOPBACK_BMAC) {
+
vars->link_up = 1;
vars->line_speed = SPEED_10000;
vars->duplex = DUPLEX_FULL;
@@ -4744,7 +5979,9 @@ u8 bnx2x_phy_init(struct link_params *params, struct link_vars *vars)
REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE +
params->port*4, 0);
+
} else if (params->loopback_mode == LOOPBACK_EMAC) {
+
vars->link_up = 1;
vars->line_speed = SPEED_1000;
vars->duplex = DUPLEX_FULL;
@@ -4760,8 +5997,10 @@ u8 bnx2x_phy_init(struct link_params *params, struct link_vars *vars)
vars->duplex);
REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE +
params->port*4, 0);
+
} else if ((params->loopback_mode == LOOPBACK_XGXS_10) ||
- (params->loopback_mode == LOOPBACK_EXT_PHY)) {
+ (params->loopback_mode == LOOPBACK_EXT_PHY)) {
+
vars->link_up = 1;
vars->line_speed = SPEED_10000;
vars->duplex = DUPLEX_FULL;
@@ -4790,10 +6029,14 @@ u8 bnx2x_phy_init(struct link_params *params, struct link_vars *vars)
}
REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE +
params->port*4, 0);
+
+ bnx2x_set_led(bp, params->port, LED_MODE_OPER,
+ vars->line_speed, params->hw_led_mode,
+ params->chip_id);
+
} else
/* No loopback */
{
-
bnx2x_phy_deassert(params, vars->phy_flags);
switch (params->switch_cfg) {
case SWITCH_CFG_1G:
@@ -4801,8 +6044,7 @@ u8 bnx2x_phy_init(struct link_params *params, struct link_vars *vars)
if ((params->ext_phy_config &
PORT_HW_CFG_SERDES_EXT_PHY_TYPE_MASK) ==
PORT_HW_CFG_SERDES_EXT_PHY_TYPE_BCM5482) {
- vars->phy_flags |=
- PHY_SGMII_FLAG;
+ vars->phy_flags |= PHY_SGMII_FLAG;
}
val = REG_RD(bp,
@@ -4823,7 +6065,6 @@ u8 bnx2x_phy_init(struct link_params *params, struct link_vars *vars)
default:
DP(NETIF_MSG_LINK, "Invalid switch_cfg\n");
return -EINVAL;
- break;
}
DP(NETIF_MSG_LINK, "Phy address = 0x%x\n", params->phy_addr);
@@ -4843,24 +6084,23 @@ static void bnx2x_8726_reset_phy(struct bnx2x *bp, u8 port, u8 ext_phy_addr)
PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726, ext_phy_addr,
MDIO_PMA_DEVAD,
MDIO_PMA_REG_GEN_CTRL, 0x0001);
-
- /* Disable Transmitter */
- bnx2x_bcm8726_set_transmitter(bp, port, ext_phy_addr, 0);
-
}
u8 bnx2x_link_reset(struct link_params *params, struct link_vars *vars,
u8 reset_ext_phy)
{
-
struct bnx2x *bp = params->bp;
u32 ext_phy_config = params->ext_phy_config;
u16 hw_led_mode = params->hw_led_mode;
u32 chip_id = params->chip_id;
u8 port = params->port;
u32 ext_phy_type = XGXS_EXT_PHY_TYPE(ext_phy_config);
- /* disable attentions */
+ u32 val = REG_RD(bp, params->shmem_base +
+ offsetof(struct shmem_region, dev_info.
+ port_feature_config[params->port].
+ config));
+ /* disable attentions */
vars->link_status = 0;
bnx2x_update_mng(params, vars->link_status);
bnx2x_bits_dis(bp, NIG_REG_MASK_INTERRUPT_PORT0 + port*4,
@@ -4893,6 +6133,20 @@ u8 bnx2x_link_reset(struct link_params *params, struct link_vars *vars,
case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072:
break;
+
+ case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727:
+ {
+
+ /* Disable Transmitter */
+ u8 ext_phy_addr =
+ XGXS_EXT_PHY_ADDR(params->ext_phy_config);
+ if ((val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) ==
+ PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_DISABLE_TX_LASER)
+ bnx2x_sfp_set_transmitter(bp, port,
+ PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727,
+ ext_phy_addr, 0);
+ break;
+ }
case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
DP(NETIF_MSG_LINK, "Setting 8073 port %d into "
"low power mode\n",
@@ -4903,9 +6157,8 @@ u8 bnx2x_link_reset(struct link_params *params, struct link_vars *vars,
break;
case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726:
{
- u8 ext_phy_addr = ((params->ext_phy_config &
- PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
- PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
+ u8 ext_phy_addr =
+ XGXS_EXT_PHY_ADDR(params->ext_phy_config);
/* Set soft reset */
bnx2x_8726_reset_phy(bp, params->port, ext_phy_addr);
break;
@@ -4943,6 +6196,7 @@ static u8 bnx2x_update_link_down(struct link_params *params,
{
struct bnx2x *bp = params->bp;
u8 port = params->port;
+
DP(NETIF_MSG_LINK, "Port %x: Link is down\n", port);
bnx2x_set_led(bp, port, LED_MODE_OFF,
0, params->hw_led_mode,
@@ -4979,6 +6233,7 @@ static u8 bnx2x_update_link_up(struct link_params *params,
struct bnx2x *bp = params->bp;
u8 port = params->port;
u8 rc = 0;
+
vars->link_status |= LINK_STATUS_LINK_UP;
if (link_10g) {
bnx2x_bmac_enable(params, vars, 0);
@@ -5032,16 +6287,19 @@ u8 bnx2x_link_update(struct link_params *params, struct link_vars *vars)
u8 link_10g;
u8 ext_phy_link_up, rc = 0;
u32 ext_phy_type;
+ u8 is_mi_int = 0;
DP(NETIF_MSG_LINK, "port %x, XGXS?%x, int_status 0x%x\n",
- port,
- (vars->phy_flags & PHY_XGXS_FLAG),
- REG_RD(bp, NIG_REG_STATUS_INTERRUPT_PORT0 + port*4));
+ port, (vars->phy_flags & PHY_XGXS_FLAG),
+ REG_RD(bp, NIG_REG_STATUS_INTERRUPT_PORT0 + port*4));
+ is_mi_int = (u8)(REG_RD(bp, NIG_REG_EMAC0_STATUS_MISC_MI_INT +
+ port*0x18) > 0);
DP(NETIF_MSG_LINK, "int_mask 0x%x MI_INT %x, SERDES_LINK %x\n",
- REG_RD(bp, NIG_REG_MASK_INTERRUPT_PORT0 + port*4),
- REG_RD(bp, NIG_REG_EMAC0_STATUS_MISC_MI_INT + port*0x18),
- REG_RD(bp, NIG_REG_SERDES0_STATUS_LINK_STATUS + port*0x3c));
+ REG_RD(bp, NIG_REG_MASK_INTERRUPT_PORT0 + port*4),
+ is_mi_int,
+ REG_RD(bp,
+ NIG_REG_SERDES0_STATUS_LINK_STATUS + port*0x3c));
DP(NETIF_MSG_LINK, " 10G %x, XGXS_LINK %x\n",
REG_RD(bp, NIG_REG_XGXS0_STATUS_LINK10G + port*0x68),
@@ -5053,7 +6311,7 @@ u8 bnx2x_link_update(struct link_params *params, struct link_vars *vars)
ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
/* Check external link change only for non-direct */
- ext_phy_link_up = bnx2x_ext_phy_is_link_up(params, vars);
+ ext_phy_link_up = bnx2x_ext_phy_is_link_up(params, vars, is_mi_int);
/* Read gp_status */
CL45_RD_OVER_CL22(bp, port, params->phy_addr,
@@ -5061,7 +6319,8 @@ u8 bnx2x_link_update(struct link_params *params, struct link_vars *vars)
MDIO_GP_STATUS_TOP_AN_STATUS1,
&gp_status);
- rc = bnx2x_link_settings_status(params, vars, gp_status);
+ rc = bnx2x_link_settings_status(params, vars, gp_status,
+ ext_phy_link_up);
if (rc != 0)
return rc;
@@ -5073,7 +6332,7 @@ u8 bnx2x_link_update(struct link_params *params, struct link_vars *vars)
(vars->line_speed == SPEED_15000) ||
(vars->line_speed == SPEED_16000));
- bnx2x_link_int_ack(params, vars, link_10g);
+ bnx2x_link_int_ack(params, vars, link_10g, is_mi_int);
/* In case external phy link is up, and internal link is down
( not initialized yet probably after link initialization, it needs
@@ -5086,7 +6345,7 @@ u8 bnx2x_link_update(struct link_params *params, struct link_vars *vars)
(ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705) &&
(ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726) &&
(ext_phy_link_up && !vars->phy_link_up))
- bnx2x_init_internal_phy(params, vars);
+ bnx2x_init_internal_phy(params, vars, 0);
/* link is up only if both local phy and external phy are up */
vars->link_up = (ext_phy_link_up && vars->phy_link_up);
@@ -5119,10 +6378,7 @@ static u8 bnx2x_8073_common_init_phy(struct bnx2x *bp, u32 shmem_base)
NIG_MASK_SERDES0_LINK_STATUS |
NIG_MASK_MI_INT));
- ext_phy_addr[port] =
- ((ext_phy_config &
- PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
- PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
+ ext_phy_addr[port] = XGXS_EXT_PHY_ADDR(ext_phy_config);
/* Need to take the phy out of low power mode in order
to write to access its registers */
@@ -5217,12 +6473,81 @@ static u8 bnx2x_8073_common_init_phy(struct bnx2x *bp, u32 shmem_base)
}
+static u8 bnx2x_8727_common_init_phy(struct bnx2x *bp, u32 shmem_base)
+{
+ u8 ext_phy_addr[PORT_MAX];
+ s8 port, first_port, i;
+ u32 swap_val, swap_override;
+ DP(NETIF_MSG_LINK, "Executing BCM8727 common init\n");
+ swap_val = REG_RD(bp, NIG_REG_PORT_SWAP);
+ swap_override = REG_RD(bp, NIG_REG_STRAP_OVERRIDE);
+
+ bnx2x_ext_phy_hw_reset(bp, 1 ^ (swap_val && swap_override));
+ msleep(5);
+
+ if (swap_val && swap_override)
+ first_port = PORT_0;
+ else
+ first_port = PORT_1;
+
+ /* PART1 - Reset both phys */
+ for (i = 0, port = first_port; i < PORT_MAX; i++, port = !port) {
+ /* Extract the ext phy address for the port */
+ u32 ext_phy_config = REG_RD(bp, shmem_base +
+ offsetof(struct shmem_region,
+ dev_info.port_hw_config[port].external_phy_config));
+
+ /* disable attentions */
+ bnx2x_bits_dis(bp, NIG_REG_MASK_INTERRUPT_PORT0 + port*4,
+ (NIG_MASK_XGXS0_LINK_STATUS |
+ NIG_MASK_XGXS0_LINK10G |
+ NIG_MASK_SERDES0_LINK_STATUS |
+ NIG_MASK_MI_INT));
+
+ ext_phy_addr[port] = XGXS_EXT_PHY_ADDR(ext_phy_config);
+
+ /* Reset the phy */
+ bnx2x_cl45_write(bp, port,
+ PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727,
+ ext_phy_addr[port],
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_CTRL,
+ 1<<15);
+ }
+
+ /* Add delay of 150ms after reset */
+ msleep(150);
+
+ /* PART2 - Download firmware to both phys */
+ for (i = 0, port = first_port; i < PORT_MAX; i++, port = !port) {
+ u16 fw_ver1;
+
+ bnx2x_bcm8727_external_rom_boot(bp, port,
+ ext_phy_addr[port], shmem_base);
+
+ bnx2x_cl45_read(bp, port, PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727,
+ ext_phy_addr[port],
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_ROM_VER1, &fw_ver1);
+ if (fw_ver1 == 0 || fw_ver1 == 0x4321) {
+ DP(NETIF_MSG_LINK,
+ "bnx2x_8727_common_init_phy port %x:"
+ "Download failed. fw version = 0x%x\n",
+ port, fw_ver1);
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+
static u8 bnx2x_8726_common_init_phy(struct bnx2x *bp, u32 shmem_base)
{
u8 ext_phy_addr;
u32 val;
s8 port;
+
/* Use port1 because of the static port-swap */
/* Enable the module detection interrupt */
val = REG_RD(bp, MISC_REG_GPIO_EVENT_EN);
@@ -5230,7 +6555,7 @@ static u8 bnx2x_8726_common_init_phy(struct bnx2x *bp, u32 shmem_base)
(1<<(MISC_REGISTERS_GPIO_3 + MISC_REGISTERS_GPIO_PORT_SHIFT)));
REG_WR(bp, MISC_REG_GPIO_EVENT_EN, val);
- bnx2x_hw_reset(bp, 1);
+ bnx2x_ext_phy_hw_reset(bp, 1);
msleep(5);
for (port = 0; port < PORT_MAX; port++) {
/* Extract the ext phy address for the port */
@@ -5238,10 +6563,7 @@ static u8 bnx2x_8726_common_init_phy(struct bnx2x *bp, u32 shmem_base)
offsetof(struct shmem_region,
dev_info.port_hw_config[port].external_phy_config));
- ext_phy_addr =
- ((ext_phy_config &
- PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
- PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
+ ext_phy_addr = XGXS_EXT_PHY_ADDR(ext_phy_config);
DP(NETIF_MSG_LINK, "8726_common_init : ext_phy_addr = 0x%x\n",
ext_phy_addr);
@@ -5275,6 +6597,12 @@ u8 bnx2x_common_init_phy(struct bnx2x *bp, u32 shmem_base)
rc = bnx2x_8073_common_init_phy(bp, shmem_base);
break;
}
+
+ case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727:
+ case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727_NOC:
+ rc = bnx2x_8727_common_init_phy(bp, shmem_base);
+ break;
+
case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726:
/* GPIO1 affects both ports, so there's need to pull
it for single port alone */
@@ -5291,9 +6619,7 @@ u8 bnx2x_common_init_phy(struct bnx2x *bp, u32 shmem_base)
return rc;
}
-
-
-static void bnx2x_sfx7101_sp_sw_reset(struct bnx2x *bp, u8 port, u8 phy_addr)
+void bnx2x_sfx7101_sp_sw_reset(struct bnx2x *bp, u8 port, u8 phy_addr)
{
u16 val, cnt;
@@ -5323,377 +6649,3 @@ static void bnx2x_sfx7101_sp_sw_reset(struct bnx2x *bp, u8 port, u8 phy_addr)
break;
}
}
-#define RESERVED_SIZE 256
-/* max application is 160K bytes - data at end of RAM */
-#define MAX_APP_SIZE (160*1024 - RESERVED_SIZE)
-
-/* Header is 14 bytes */
-#define HEADER_SIZE 14
-#define DATA_OFFSET HEADER_SIZE
-
-#define SPI_START_TRANSFER(bp, port, ext_phy_addr) \
- bnx2x_cl45_write(bp, port, PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101, \
- ext_phy_addr, \
- MDIO_PCS_DEVAD, \
- MDIO_PCS_REG_7101_SPI_CTRL_ADDR, 1)
-
-/* Programs an image to DSP's flash via the SPI port*/
-static u8 bnx2x_sfx7101_flash_download(struct bnx2x *bp, u8 port,
- u8 ext_phy_addr,
- char data[], u32 size)
-{
- const u16 num_trans = size/4; /* 4 bytes can be sent at a time */
- /* Doesn't include last trans!*/
- const u16 last_trans_size = size%4; /* Num bytes on last trans */
- u16 trans_cnt, byte_cnt;
- u32 data_index;
- u16 tmp;
- u16 code_started = 0;
- u16 image_revision1, image_revision2;
- u16 cnt;
-
- DP(NETIF_MSG_LINK, "bnx2x_sfx7101_flash_download file_size=%d\n", size);
- /* Going to flash*/
- if ((size-HEADER_SIZE) > MAX_APP_SIZE) {
- /* This very often will be the case, because the image is built
- with 160Kbytes size whereas the total image size must actually
- be 160Kbytes-RESERVED_SIZE */
- DP(NETIF_MSG_LINK, "Warning, file size was %d bytes "
- "truncated to %d bytes\n", size, MAX_APP_SIZE);
- size = MAX_APP_SIZE+HEADER_SIZE;
- }
- DP(NETIF_MSG_LINK, "File version is %c%c\n", data[0x14e], data[0x14f]);
- DP(NETIF_MSG_LINK, " %c%c\n", data[0x150], data[0x151]);
- /* Put the DSP in download mode by setting FLASH_CFG[2] to 1
- and issuing a reset.*/
-
- bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_0,
- MISC_REGISTERS_GPIO_HIGH, port);
-
- bnx2x_sfx7101_sp_sw_reset(bp, port, ext_phy_addr);
-
- /* wait 0.5 sec */
- for (cnt = 0; cnt < 100; cnt++)
- msleep(5);
-
- /* Make sure we can access the DSP
- And it's in the correct mode (waiting for download) */
-
- bnx2x_cl45_read(bp, port,
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
- ext_phy_addr,
- MDIO_PCS_DEVAD,
- MDIO_PCS_REG_7101_DSP_ACCESS, &tmp);
-
- if (tmp != 0x000A) {
- DP(NETIF_MSG_LINK, "DSP is not in waiting on download mode. "
- "Expected 0x000A, read 0x%04X\n", tmp);
- DP(NETIF_MSG_LINK, "Download failed\n");
- return -EINVAL;
- }
-
- /* Mux the SPI interface away from the internal processor */
- bnx2x_cl45_write(bp, port,
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
- ext_phy_addr,
- MDIO_PCS_DEVAD,
- MDIO_PCS_REG_7101_SPI_MUX, 1);
-
- /* Reset the SPI port */
- bnx2x_cl45_write(bp, port,
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
- ext_phy_addr,
- MDIO_PCS_DEVAD,
- MDIO_PCS_REG_7101_SPI_CTRL_ADDR, 0);
- bnx2x_cl45_write(bp, port,
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
- ext_phy_addr,
- MDIO_PCS_DEVAD,
- MDIO_PCS_REG_7101_SPI_CTRL_ADDR,
- (1<<MDIO_PCS_REG_7101_SPI_RESET_BIT));
- bnx2x_cl45_write(bp, port,
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
- ext_phy_addr,
- MDIO_PCS_DEVAD,
- MDIO_PCS_REG_7101_SPI_CTRL_ADDR, 0);
-
- /* Erase the flash */
- bnx2x_cl45_write(bp, port,
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
- ext_phy_addr,
- MDIO_PCS_DEVAD,
- MDIO_PCS_REG_7101_SPI_FIFO_ADDR,
- MDIO_PCS_REG_7101_SPI_FIFO_ADDR_WRITE_ENABLE_CMD);
-
- bnx2x_cl45_write(bp, port,
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
- ext_phy_addr,
- MDIO_PCS_DEVAD,
- MDIO_PCS_REG_7101_SPI_BYTES_TO_TRANSFER_ADDR,
- 1);
-
- SPI_START_TRANSFER(bp, port, ext_phy_addr);
- bnx2x_cl45_write(bp, port,
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
- ext_phy_addr,
- MDIO_PCS_DEVAD,
- MDIO_PCS_REG_7101_SPI_FIFO_ADDR,
- MDIO_PCS_REG_7101_SPI_FIFO_ADDR_BULK_ERASE_CMD);
-
- bnx2x_cl45_write(bp, port,
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
- ext_phy_addr,
- MDIO_PCS_DEVAD,
- MDIO_PCS_REG_7101_SPI_BYTES_TO_TRANSFER_ADDR,
- 1);
- SPI_START_TRANSFER(bp, port, ext_phy_addr);
-
- /* Wait 10 seconds, the maximum time for the erase to complete */
- DP(NETIF_MSG_LINK, "Erasing flash, this takes 10 seconds...\n");
- for (cnt = 0; cnt < 1000; cnt++)
- msleep(10);
-
- DP(NETIF_MSG_LINK, "Downloading flash, please wait...\n");
- data_index = 0;
- for (trans_cnt = 0; trans_cnt < num_trans; trans_cnt++) {
- bnx2x_cl45_write(bp, port,
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
- ext_phy_addr,
- MDIO_PCS_DEVAD,
- MDIO_PCS_REG_7101_SPI_FIFO_ADDR,
- MDIO_PCS_REG_7101_SPI_FIFO_ADDR_WRITE_ENABLE_CMD);
-
- bnx2x_cl45_write(bp, port,
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
- ext_phy_addr,
- MDIO_PCS_DEVAD,
- MDIO_PCS_REG_7101_SPI_BYTES_TO_TRANSFER_ADDR,
- 1);
- SPI_START_TRANSFER(bp, port, ext_phy_addr);
-
- bnx2x_cl45_write(bp, port,
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
- ext_phy_addr,
- MDIO_PCS_DEVAD,
- MDIO_PCS_REG_7101_SPI_FIFO_ADDR,
- MDIO_PCS_REG_7101_SPI_FIFO_ADDR_PAGE_PROGRAM_CMD);
-
- /* Bits 23-16 of address */
- bnx2x_cl45_write(bp, port,
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
- ext_phy_addr,
- MDIO_PCS_DEVAD,
- MDIO_PCS_REG_7101_SPI_FIFO_ADDR,
- (data_index>>16));
- /* Bits 15-8 of address */
- bnx2x_cl45_write(bp, port,
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
- ext_phy_addr,
- MDIO_PCS_DEVAD,
- MDIO_PCS_REG_7101_SPI_FIFO_ADDR,
- (data_index>>8));
-
- /* Bits 7-0 of address */
- bnx2x_cl45_write(bp, port,
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
- ext_phy_addr,
- MDIO_PCS_DEVAD,
- MDIO_PCS_REG_7101_SPI_FIFO_ADDR,
- ((u16)data_index));
-
- byte_cnt = 0;
- while (byte_cnt < 4 && data_index < size) {
- bnx2x_cl45_write(bp, port,
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
- ext_phy_addr,
- MDIO_PCS_DEVAD,
- MDIO_PCS_REG_7101_SPI_FIFO_ADDR,
- data[data_index++]);
- byte_cnt++;
- }
-
- bnx2x_cl45_write(bp, port,
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
- ext_phy_addr,
- MDIO_PCS_DEVAD,
- MDIO_PCS_REG_7101_SPI_BYTES_TO_TRANSFER_ADDR,
- byte_cnt+4);
-
- SPI_START_TRANSFER(bp, port, ext_phy_addr);
- msleep(5); /* Wait 5 ms minimum between transs */
-
- /* Let the user know something's going on.*/
- /* a pacifier ever 4K */
- if ((data_index % 1023) == 0)
- DP(NETIF_MSG_LINK, "Download %d%%\n", data_index/size);
- }
-
- DP(NETIF_MSG_LINK, "\n");
- /* Transfer the last block if there is data remaining */
- if (last_trans_size) {
- bnx2x_cl45_write(bp, port,
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
- ext_phy_addr,
- MDIO_PCS_DEVAD,
- MDIO_PCS_REG_7101_SPI_FIFO_ADDR,
- MDIO_PCS_REG_7101_SPI_FIFO_ADDR_WRITE_ENABLE_CMD);
-
- bnx2x_cl45_write(bp, port,
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
- ext_phy_addr,
- MDIO_PCS_DEVAD,
- MDIO_PCS_REG_7101_SPI_BYTES_TO_TRANSFER_ADDR,
- 1);
-
- SPI_START_TRANSFER(bp, port, ext_phy_addr);
-
- bnx2x_cl45_write(bp, port,
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
- ext_phy_addr,
- MDIO_PCS_DEVAD,
- MDIO_PCS_REG_7101_SPI_FIFO_ADDR,
- MDIO_PCS_REG_7101_SPI_FIFO_ADDR_PAGE_PROGRAM_CMD);
-
- /* Bits 23-16 of address */
- bnx2x_cl45_write(bp, port,
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
- ext_phy_addr,
- MDIO_PCS_DEVAD,
- MDIO_PCS_REG_7101_SPI_FIFO_ADDR,
- (data_index>>16));
- /* Bits 15-8 of address */
- bnx2x_cl45_write(bp, port,
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
- ext_phy_addr,
- MDIO_PCS_DEVAD,
- MDIO_PCS_REG_7101_SPI_FIFO_ADDR,
- (data_index>>8));
-
- /* Bits 7-0 of address */
- bnx2x_cl45_write(bp, port,
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
- ext_phy_addr,
- MDIO_PCS_DEVAD,
- MDIO_PCS_REG_7101_SPI_FIFO_ADDR,
- ((u16)data_index));
-
- byte_cnt = 0;
- while (byte_cnt < last_trans_size && data_index < size) {
- /* Bits 7-0 of address */
- bnx2x_cl45_write(bp, port,
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
- ext_phy_addr,
- MDIO_PCS_DEVAD,
- MDIO_PCS_REG_7101_SPI_FIFO_ADDR,
- data[data_index++]);
- byte_cnt++;
- }
-
- bnx2x_cl45_write(bp, port,
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
- ext_phy_addr,
- MDIO_PCS_DEVAD,
- MDIO_PCS_REG_7101_SPI_BYTES_TO_TRANSFER_ADDR,
- byte_cnt+4);
-
- SPI_START_TRANSFER(bp, port, ext_phy_addr);
- }
-
- /* DSP Remove Download Mode */
- bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_0,
- MISC_REGISTERS_GPIO_LOW, port);
-
- bnx2x_sfx7101_sp_sw_reset(bp, port, ext_phy_addr);
-
- /* wait 0.5 sec to allow it to run */
- for (cnt = 0; cnt < 100; cnt++)
- msleep(5);
-
- bnx2x_hw_reset(bp, port);
-
- for (cnt = 0; cnt < 100; cnt++)
- msleep(5);
-
- /* Check that the code is started. In case the download
- checksum failed, the code won't be started. */
- bnx2x_cl45_read(bp, port,
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
- ext_phy_addr,
- MDIO_PCS_DEVAD,
- MDIO_PCS_REG_7101_DSP_ACCESS,
- &tmp);
-
- code_started = (tmp & (1<<4));
- if (!code_started) {
- DP(NETIF_MSG_LINK, "Download failed. Please check file.\n");
- return -EINVAL;
- }
-
- /* Verify that the file revision is now equal to the image
- revision within the DSP */
- bnx2x_cl45_read(bp, port,
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
- ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_7101_VER1,
- &image_revision1);
-
- bnx2x_cl45_read(bp, port,
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
- ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_7101_VER2,
- &image_revision2);
-
- if (data[0x14e] != (image_revision2&0xFF) ||
- data[0x14f] != ((image_revision2&0xFF00)>>8) ||
- data[0x150] != (image_revision1&0xFF) ||
- data[0x151] != ((image_revision1&0xFF00)>>8)) {
- DP(NETIF_MSG_LINK, "Download failed.\n");
- return -EINVAL;
- }
- DP(NETIF_MSG_LINK, "Download %d%%\n", data_index/size);
- return 0;
-}
-
-u8 bnx2x_flash_download(struct bnx2x *bp, u8 port, u32 ext_phy_config,
- u8 driver_loaded, char data[], u32 size)
-{
- u8 rc = 0;
- u32 ext_phy_type;
- u8 ext_phy_addr;
- ext_phy_addr = ((ext_phy_config &
- PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
- PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
-
- ext_phy_type = XGXS_EXT_PHY_TYPE(ext_phy_config);
-
- switch (ext_phy_type) {
- case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072:
- case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
- case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705:
- case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706:
- DP(NETIF_MSG_LINK,
- "Flash download not supported for this ext phy\n");
- rc = -EINVAL;
- break;
- case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101:
- /* Take ext phy out of reset */
- if (!driver_loaded)
- bnx2x_turn_on_ef(bp, port, ext_phy_addr, ext_phy_type);
- rc = bnx2x_sfx7101_flash_download(bp, port, ext_phy_addr,
- data, size);
- if (!driver_loaded)
- bnx2x_turn_off_sf(bp, port);
- break;
- case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
- case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE:
- case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN:
- default:
- DP(NETIF_MSG_LINK, "Invalid ext phy type\n");
- rc = -EINVAL;
- break;
- }
- return rc;
-}
-
diff --git a/drivers/net/bnx2x_link.h b/drivers/net/bnx2x_link.h
index 19a866dc10e..f3e252264e1 100644
--- a/drivers/net/bnx2x_link.h
+++ b/drivers/net/bnx2x_link.h
@@ -39,7 +39,13 @@
#define SPEED_15000 15000
#define SPEED_16000 16000
-
+#define SFP_EEPROM_VENDOR_NAME_ADDR 0x14
+#define SFP_EEPROM_VENDOR_NAME_SIZE 16
+#define SFP_EEPROM_VENDOR_OUI_ADDR 0x25
+#define SFP_EEPROM_VENDOR_OUI_SIZE 3
+#define SFP_EEPROM_PART_NO_ADDR 0x28
+#define SFP_EEPROM_PART_NO_SIZE 16
+#define PWR_FLT_ERR_MSG_LEN 250
/***********************************************************/
/* Structs */
/***********************************************************/
@@ -75,47 +81,59 @@ struct link_params {
#define SWITCH_CFG_AUTO_DETECT PORT_FEATURE_CON_SWITCH_AUTO_DETECT
u16 hw_led_mode; /* part of the hw_config read from the shmem */
+
+ /* phy_addr populated by the phy_init function */
+ u8 phy_addr;
+ /*u8 reserved1;*/
+
u32 lane_config;
u32 ext_phy_config;
-#define XGXS_EXT_PHY_TYPE(ext_phy_config) (ext_phy_config & \
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_MASK)
-#define SERDES_EXT_PHY_TYPE(ext_phy_config) (ext_phy_config & \
- PORT_HW_CFG_SERDES_EXT_PHY_TYPE_MASK)
+#define XGXS_EXT_PHY_TYPE(ext_phy_config) \
+ ((ext_phy_config) & PORT_HW_CFG_XGXS_EXT_PHY_TYPE_MASK)
+#define XGXS_EXT_PHY_ADDR(ext_phy_config) \
+ (((ext_phy_config) & PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >> \
+ PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT)
+#define SERDES_EXT_PHY_TYPE(ext_phy_config) \
+ ((ext_phy_config) & PORT_HW_CFG_SERDES_EXT_PHY_TYPE_MASK)
+
/* Phy register parameter */
u32 chip_id;
- /* phy_addr populated by the CLC */
- u8 phy_addr;
u16 xgxs_config_rx[4]; /* preemphasis values for the rx side */
-
u16 xgxs_config_tx[4]; /* preemphasis values for the tx side */
+
u32 feature_config_flags;
#define FEATURE_CONFIG_OVERRIDE_PREEMPHASIS_ENABLED (1<<0)
-#define FEATURE_CONFIG_MODULE_ENFORCMENT_ENABLED (2<<0)
+#define FEATURE_CONFIG_BC_SUPPORTS_OPT_MDL_VRFY (1<<2)
+#define FEATURE_CONFIG_BCM8727_NOC (1<<3)
+
/* Device pointer passed to all callback functions */
struct bnx2x *bp;
};
/* Output parameters */
struct link_vars {
+ u8 phy_flags;
+
+ u8 mac_type;
+#define MAC_TYPE_NONE 0
+#define MAC_TYPE_EMAC 1
+#define MAC_TYPE_BMAC 2
+
u8 phy_link_up; /* internal phy link indication */
u8 link_up;
+
+ u16 line_speed;
u16 duplex;
+
u16 flow_ctrl;
- u32 ieee_fc;
- u8 mac_type;
+ u16 ieee_fc;
-#define MAC_TYPE_NONE 0
-#define MAC_TYPE_EMAC 1
-#define MAC_TYPE_BMAC 2
- u16 line_speed;
u32 autoneg;
#define AUTO_NEG_DISABLED 0x0
#define AUTO_NEG_ENABLED 0x1
#define AUTO_NEG_COMPLETE 0x2
-#define AUTO_NEG_PARALLEL_DETECTION_USED 0x3
-
- u8 phy_flags;
+#define AUTO_NEG_PARALLEL_DETECTION_USED 0x3
/* The same definitions as the shmem parameter */
u32 link_status;
@@ -167,8 +185,6 @@ u8 bnx2x_set_led(struct bnx2x *bp, u8 port, u8 mode, u32 speed,
u8 bnx2x_override_led_value(struct bnx2x *bp, u8 port, u32 led_idx, u32 value);
-u8 bnx2x_flash_download(struct bnx2x *bp, u8 port, u32 ext_phy_config,
- u8 driver_loaded, char data[], u32 size);
/* bnx2x_handle_module_detect_int should be called upon module detection
interrupt */
void bnx2x_handle_module_detect_int(struct link_params *params);
@@ -180,5 +196,12 @@ u8 bnx2x_test_link(struct link_params *input, struct link_vars *vars);
/* One-time initialization for external phy after power up */
u8 bnx2x_common_init_phy(struct bnx2x *bp, u32 shmem_base);
+/* Reset the external PHY using GPIO */
+void bnx2x_ext_phy_hw_reset(struct bnx2x *bp, u8 port);
+
+void bnx2x_sfx7101_sp_sw_reset(struct bnx2x *bp, u8 port, u8 phy_addr);
+
+u8 bnx2x_read_sfp_module_eeprom(struct link_params *params, u16 addr,
+ u8 byte_cnt, u8 *o_buf);
#endif /* BNX2X_LINK_H */
diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c
index c36a5f33739..b318d16a4d9 100644
--- a/drivers/net/bnx2x_main.c
+++ b/drivers/net/bnx2x_main.c
@@ -10,7 +10,7 @@
* Written by: Eliezer Tamir
* Based on code from Michael Chan's bnx2 driver
* UDP CSUM errata workaround by Arik Gendelman
- * Slowpath rework by Vladislav Zolotarov
+ * Slowpath and fastpath rework by Vladislav Zolotarov
* Statistics and Link management by Yitchak Gertner
*
*/
@@ -56,15 +56,15 @@
#include "bnx2x_init_ops.h"
#include "bnx2x_dump.h"
-#define DRV_MODULE_VERSION "1.48.105-1"
-#define DRV_MODULE_RELDATE "2009/04/22"
+#define DRV_MODULE_VERSION "1.52.1"
+#define DRV_MODULE_RELDATE "2009/08/12"
#define BNX2X_BC_VER 0x040200
#include <linux/firmware.h>
#include "bnx2x_fw_file_hdr.h"
/* FW files */
-#define FW_FILE_PREFIX_E1 "bnx2x-e1-"
-#define FW_FILE_PREFIX_E1H "bnx2x-e1h-"
+#define FW_FILE_PREFIX_E1 "bnx2x-e1-"
+#define FW_FILE_PREFIX_E1H "bnx2x-e1h-"
/* Time in jiffies before concluding the transmitter is hung */
#define TX_TIMEOUT (5*HZ)
@@ -80,7 +80,18 @@ MODULE_VERSION(DRV_MODULE_VERSION);
static int multi_mode = 1;
module_param(multi_mode, int, 0);
-MODULE_PARM_DESC(multi_mode, " Use per-CPU queues");
+MODULE_PARM_DESC(multi_mode, " Multi queue mode "
+ "(0 Disable; 1 Enable (default))");
+
+static int num_rx_queues;
+module_param(num_rx_queues, int, 0);
+MODULE_PARM_DESC(num_rx_queues, " Number of Rx queues for multi_mode=1"
+ " (default is half number of CPUs)");
+
+static int num_tx_queues;
+module_param(num_tx_queues, int, 0);
+MODULE_PARM_DESC(num_tx_queues, " Number of Tx queues for multi_mode=1"
+ " (default is half number of CPUs)");
static int disable_tpa;
module_param(disable_tpa, int, 0);
@@ -90,6 +101,10 @@ static int int_mode;
module_param(int_mode, int, 0);
MODULE_PARM_DESC(int_mode, " Force interrupt mode (1 INT#x; 2 MSI)");
+static int dropless_fc;
+module_param(dropless_fc, int, 0);
+MODULE_PARM_DESC(dropless_fc, " Pause on exhausted host ring");
+
static int poll;
module_param(poll, int, 0);
MODULE_PARM_DESC(poll, " Use polling (for debug)");
@@ -123,12 +138,9 @@ static struct {
static const struct pci_device_id bnx2x_pci_tbl[] = {
- { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_57710,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM57710 },
- { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_57711,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM57711 },
- { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_57711E,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM57711E },
+ { PCI_VDEVICE(BROADCOM, PCI_DEVICE_ID_NX2_57710), BCM57710 },
+ { PCI_VDEVICE(BROADCOM, PCI_DEVICE_ID_NX2_57711), BCM57711 },
+ { PCI_VDEVICE(BROADCOM, PCI_DEVICE_ID_NX2_57711E), BCM57711E },
{ 0 }
};
@@ -141,7 +153,7 @@ MODULE_DEVICE_TABLE(pci, bnx2x_pci_tbl);
/* used only at init
* locking is done by mcp
*/
-static void bnx2x_reg_wr_ind(struct bnx2x *bp, u32 addr, u32 val)
+void bnx2x_reg_wr_ind(struct bnx2x *bp, u32 addr, u32 val)
{
pci_write_config_dword(bp->pdev, PCICFG_GRC_ADDRESS, addr);
pci_write_config_dword(bp->pdev, PCICFG_GRC_DATA, val);
@@ -188,7 +200,7 @@ static void bnx2x_post_dmae(struct bnx2x *bp, struct dmae_command *dmae,
void bnx2x_write_dmae(struct bnx2x *bp, dma_addr_t dma_addr, u32 dst_addr,
u32 len32)
{
- struct dmae_command *dmae = &bp->init_dmae;
+ struct dmae_command dmae;
u32 *wb_comp = bnx2x_sp(bp, wb_comp);
int cnt = 200;
@@ -201,43 +213,43 @@ void bnx2x_write_dmae(struct bnx2x *bp, dma_addr_t dma_addr, u32 dst_addr,
return;
}
- mutex_lock(&bp->dmae_mutex);
-
- memset(dmae, 0, sizeof(struct dmae_command));
+ memset(&dmae, 0, sizeof(struct dmae_command));
- dmae->opcode = (DMAE_CMD_SRC_PCI | DMAE_CMD_DST_GRC |
- DMAE_CMD_C_DST_PCI | DMAE_CMD_C_ENABLE |
- DMAE_CMD_SRC_RESET | DMAE_CMD_DST_RESET |
+ dmae.opcode = (DMAE_CMD_SRC_PCI | DMAE_CMD_DST_GRC |
+ DMAE_CMD_C_DST_PCI | DMAE_CMD_C_ENABLE |
+ DMAE_CMD_SRC_RESET | DMAE_CMD_DST_RESET |
#ifdef __BIG_ENDIAN
- DMAE_CMD_ENDIANITY_B_DW_SWAP |
+ DMAE_CMD_ENDIANITY_B_DW_SWAP |
#else
- DMAE_CMD_ENDIANITY_DW_SWAP |
+ DMAE_CMD_ENDIANITY_DW_SWAP |
#endif
- (BP_PORT(bp) ? DMAE_CMD_PORT_1 : DMAE_CMD_PORT_0) |
- (BP_E1HVN(bp) << DMAE_CMD_E1HVN_SHIFT));
- dmae->src_addr_lo = U64_LO(dma_addr);
- dmae->src_addr_hi = U64_HI(dma_addr);
- dmae->dst_addr_lo = dst_addr >> 2;
- dmae->dst_addr_hi = 0;
- dmae->len = len32;
- dmae->comp_addr_lo = U64_LO(bnx2x_sp_mapping(bp, wb_comp));
- dmae->comp_addr_hi = U64_HI(bnx2x_sp_mapping(bp, wb_comp));
- dmae->comp_val = DMAE_COMP_VAL;
+ (BP_PORT(bp) ? DMAE_CMD_PORT_1 : DMAE_CMD_PORT_0) |
+ (BP_E1HVN(bp) << DMAE_CMD_E1HVN_SHIFT));
+ dmae.src_addr_lo = U64_LO(dma_addr);
+ dmae.src_addr_hi = U64_HI(dma_addr);
+ dmae.dst_addr_lo = dst_addr >> 2;
+ dmae.dst_addr_hi = 0;
+ dmae.len = len32;
+ dmae.comp_addr_lo = U64_LO(bnx2x_sp_mapping(bp, wb_comp));
+ dmae.comp_addr_hi = U64_HI(bnx2x_sp_mapping(bp, wb_comp));
+ dmae.comp_val = DMAE_COMP_VAL;
DP(BNX2X_MSG_OFF, "DMAE: opcode 0x%08x\n"
DP_LEVEL "src_addr [%x:%08x] len [%d *4] "
"dst_addr [%x:%08x (%08x)]\n"
DP_LEVEL "comp_addr [%x:%08x] comp_val 0x%08x\n",
- dmae->opcode, dmae->src_addr_hi, dmae->src_addr_lo,
- dmae->len, dmae->dst_addr_hi, dmae->dst_addr_lo, dst_addr,
- dmae->comp_addr_hi, dmae->comp_addr_lo, dmae->comp_val);
+ dmae.opcode, dmae.src_addr_hi, dmae.src_addr_lo,
+ dmae.len, dmae.dst_addr_hi, dmae.dst_addr_lo, dst_addr,
+ dmae.comp_addr_hi, dmae.comp_addr_lo, dmae.comp_val);
DP(BNX2X_MSG_OFF, "data [0x%08x 0x%08x 0x%08x 0x%08x]\n",
bp->slowpath->wb_data[0], bp->slowpath->wb_data[1],
bp->slowpath->wb_data[2], bp->slowpath->wb_data[3]);
+ mutex_lock(&bp->dmae_mutex);
+
*wb_comp = 0;
- bnx2x_post_dmae(bp, dmae, INIT_DMAE_C(bp));
+ bnx2x_post_dmae(bp, &dmae, INIT_DMAE_C(bp));
udelay(5);
@@ -261,7 +273,7 @@ void bnx2x_write_dmae(struct bnx2x *bp, dma_addr_t dma_addr, u32 dst_addr,
void bnx2x_read_dmae(struct bnx2x *bp, u32 src_addr, u32 len32)
{
- struct dmae_command *dmae = &bp->init_dmae;
+ struct dmae_command dmae;
u32 *wb_comp = bnx2x_sp(bp, wb_comp);
int cnt = 200;
@@ -276,41 +288,41 @@ void bnx2x_read_dmae(struct bnx2x *bp, u32 src_addr, u32 len32)
return;
}
- mutex_lock(&bp->dmae_mutex);
+ memset(&dmae, 0, sizeof(struct dmae_command));
- memset(bnx2x_sp(bp, wb_data[0]), 0, sizeof(u32) * 4);
- memset(dmae, 0, sizeof(struct dmae_command));
-
- dmae->opcode = (DMAE_CMD_SRC_GRC | DMAE_CMD_DST_PCI |
- DMAE_CMD_C_DST_PCI | DMAE_CMD_C_ENABLE |
- DMAE_CMD_SRC_RESET | DMAE_CMD_DST_RESET |
+ dmae.opcode = (DMAE_CMD_SRC_GRC | DMAE_CMD_DST_PCI |
+ DMAE_CMD_C_DST_PCI | DMAE_CMD_C_ENABLE |
+ DMAE_CMD_SRC_RESET | DMAE_CMD_DST_RESET |
#ifdef __BIG_ENDIAN
- DMAE_CMD_ENDIANITY_B_DW_SWAP |
+ DMAE_CMD_ENDIANITY_B_DW_SWAP |
#else
- DMAE_CMD_ENDIANITY_DW_SWAP |
+ DMAE_CMD_ENDIANITY_DW_SWAP |
#endif
- (BP_PORT(bp) ? DMAE_CMD_PORT_1 : DMAE_CMD_PORT_0) |
- (BP_E1HVN(bp) << DMAE_CMD_E1HVN_SHIFT));
- dmae->src_addr_lo = src_addr >> 2;
- dmae->src_addr_hi = 0;
- dmae->dst_addr_lo = U64_LO(bnx2x_sp_mapping(bp, wb_data));
- dmae->dst_addr_hi = U64_HI(bnx2x_sp_mapping(bp, wb_data));
- dmae->len = len32;
- dmae->comp_addr_lo = U64_LO(bnx2x_sp_mapping(bp, wb_comp));
- dmae->comp_addr_hi = U64_HI(bnx2x_sp_mapping(bp, wb_comp));
- dmae->comp_val = DMAE_COMP_VAL;
+ (BP_PORT(bp) ? DMAE_CMD_PORT_1 : DMAE_CMD_PORT_0) |
+ (BP_E1HVN(bp) << DMAE_CMD_E1HVN_SHIFT));
+ dmae.src_addr_lo = src_addr >> 2;
+ dmae.src_addr_hi = 0;
+ dmae.dst_addr_lo = U64_LO(bnx2x_sp_mapping(bp, wb_data));
+ dmae.dst_addr_hi = U64_HI(bnx2x_sp_mapping(bp, wb_data));
+ dmae.len = len32;
+ dmae.comp_addr_lo = U64_LO(bnx2x_sp_mapping(bp, wb_comp));
+ dmae.comp_addr_hi = U64_HI(bnx2x_sp_mapping(bp, wb_comp));
+ dmae.comp_val = DMAE_COMP_VAL;
DP(BNX2X_MSG_OFF, "DMAE: opcode 0x%08x\n"
DP_LEVEL "src_addr [%x:%08x] len [%d *4] "
"dst_addr [%x:%08x (%08x)]\n"
DP_LEVEL "comp_addr [%x:%08x] comp_val 0x%08x\n",
- dmae->opcode, dmae->src_addr_hi, dmae->src_addr_lo,
- dmae->len, dmae->dst_addr_hi, dmae->dst_addr_lo, src_addr,
- dmae->comp_addr_hi, dmae->comp_addr_lo, dmae->comp_val);
+ dmae.opcode, dmae.src_addr_hi, dmae.src_addr_lo,
+ dmae.len, dmae.dst_addr_hi, dmae.dst_addr_lo, src_addr,
+ dmae.comp_addr_hi, dmae.comp_addr_lo, dmae.comp_val);
+
+ mutex_lock(&bp->dmae_mutex);
+ memset(bnx2x_sp(bp, wb_data[0]), 0, sizeof(u32) * 4);
*wb_comp = 0;
- bnx2x_post_dmae(bp, dmae, INIT_DMAE_C(bp));
+ bnx2x_post_dmae(bp, &dmae, INIT_DMAE_C(bp));
udelay(5);
@@ -334,6 +346,21 @@ void bnx2x_read_dmae(struct bnx2x *bp, u32 src_addr, u32 len32)
mutex_unlock(&bp->dmae_mutex);
}
+void bnx2x_write_dmae_phys_len(struct bnx2x *bp, dma_addr_t phys_addr,
+ u32 addr, u32 len)
+{
+ int offset = 0;
+
+ while (len > DMAE_LEN32_WR_MAX) {
+ bnx2x_write_dmae(bp, phys_addr + offset,
+ addr + offset, DMAE_LEN32_WR_MAX);
+ offset += DMAE_LEN32_WR_MAX * 4;
+ len -= DMAE_LEN32_WR_MAX;
+ }
+
+ bnx2x_write_dmae(bp, phys_addr + offset, addr + offset, len);
+}
+
/* used only for slowpath so not inlined */
static void bnx2x_wb_wr(struct bnx2x *bp, int reg, u32 val_hi, u32 val_lo)
{
@@ -542,16 +569,15 @@ static void bnx2x_panic_dump(struct bnx2x *bp)
/* Tx */
for_each_tx_queue(bp, i) {
struct bnx2x_fastpath *fp = &bp->fp[i];
- struct eth_tx_db_data *hw_prods = fp->hw_tx_prods;
BNX2X_ERR("fp%d: tx_pkt_prod(%x) tx_pkt_cons(%x)"
" tx_bd_prod(%x) tx_bd_cons(%x) *tx_cons_sb(%x)\n",
i, fp->tx_pkt_prod, fp->tx_pkt_cons, fp->tx_bd_prod,
fp->tx_bd_cons, le16_to_cpu(*fp->tx_cons_sb));
BNX2X_ERR(" fp_c_idx(%x) *sb_c_idx(%x)"
- " bd data(%x,%x)\n", le16_to_cpu(fp->fp_c_idx),
+ " tx_db_prod(%x)\n", le16_to_cpu(fp->fp_c_idx),
fp->status_blk->c_status_block.status_block_index,
- hw_prods->packets_prod, hw_prods->bds_prod);
+ fp->tx_db.data.prod);
}
/* Rings */
@@ -653,6 +679,11 @@ static void bnx2x_int_enable(struct bnx2x *bp)
val, port, addr, (msix ? "MSI-X" : (msi ? "MSI" : "INTx")));
REG_WR(bp, addr, val);
+ /*
+ * Ensure that HC_CONFIG is written before leading/trailing edge config
+ */
+ mmiowb();
+ barrier();
if (CHIP_IS_E1H(bp)) {
/* init leading/trailing edge */
@@ -667,6 +698,9 @@ static void bnx2x_int_enable(struct bnx2x *bp)
REG_WR(bp, HC_REG_TRAILING_EDGE_0 + port*8, val);
REG_WR(bp, HC_REG_LEADING_EDGE_0 + port*8, val);
}
+
+ /* Make sure that interrupts are indeed enabled from here on */
+ mmiowb();
}
static void bnx2x_int_disable(struct bnx2x *bp)
@@ -689,7 +723,6 @@ static void bnx2x_int_disable(struct bnx2x *bp)
REG_WR(bp, addr, val);
if (REG_RD(bp, addr) != val)
BNX2X_ERR("BUG! proper val not read from IGU!\n");
-
}
static void bnx2x_int_disable_sync(struct bnx2x *bp, int disable_hw)
@@ -699,6 +732,8 @@ static void bnx2x_int_disable_sync(struct bnx2x *bp, int disable_hw)
/* disable interrupt handling */
atomic_inc(&bp->intr_sem);
+ smp_wmb(); /* Ensure that bp->intr_sem update is SMP-safe */
+
if (disable_hw)
/* prevent the HW from sending interrupts */
bnx2x_int_disable(bp);
@@ -740,6 +775,10 @@ static inline void bnx2x_ack_sb(struct bnx2x *bp, u8 sb_id,
DP(BNX2X_MSG_OFF, "write 0x%08x to HC addr 0x%x\n",
(*(u32 *)&igu_ack), hc_addr);
REG_WR(bp, hc_addr, (*(u32 *)&igu_ack));
+
+ /* Make sure that ACK is written */
+ mmiowb();
+ barrier();
}
static inline u16 bnx2x_update_fpsb_idx(struct bnx2x_fastpath *fp)
@@ -776,16 +815,6 @@ static u16 bnx2x_ack_int(struct bnx2x *bp)
* fast path service functions
*/
-static inline int bnx2x_has_tx_work(struct bnx2x_fastpath *fp)
-{
- u16 tx_cons_sb;
-
- /* Tell compiler that status block fields can change */
- barrier();
- tx_cons_sb = le16_to_cpu(*fp->tx_cons_sb);
- return (fp->tx_pkt_cons != tx_cons_sb);
-}
-
static inline int bnx2x_has_tx_work_unload(struct bnx2x_fastpath *fp)
{
/* Tell compiler that consumer and producer can change */
@@ -800,7 +829,8 @@ static u16 bnx2x_free_tx_pkt(struct bnx2x *bp, struct bnx2x_fastpath *fp,
u16 idx)
{
struct sw_tx_bd *tx_buf = &fp->tx_buf_ring[idx];
- struct eth_tx_bd *tx_bd;
+ struct eth_tx_start_bd *tx_start_bd;
+ struct eth_tx_bd *tx_data_bd;
struct sk_buff *skb = tx_buf->skb;
u16 bd_idx = TX_BD(tx_buf->first_bd), new_cons;
int nbd;
@@ -810,51 +840,46 @@ static u16 bnx2x_free_tx_pkt(struct bnx2x *bp, struct bnx2x_fastpath *fp,
/* unmap first bd */
DP(BNX2X_MSG_OFF, "free bd_idx %d\n", bd_idx);
- tx_bd = &fp->tx_desc_ring[bd_idx];
- pci_unmap_single(bp->pdev, BD_UNMAP_ADDR(tx_bd),
- BD_UNMAP_LEN(tx_bd), PCI_DMA_TODEVICE);
+ tx_start_bd = &fp->tx_desc_ring[bd_idx].start_bd;
+ pci_unmap_single(bp->pdev, BD_UNMAP_ADDR(tx_start_bd),
+ BD_UNMAP_LEN(tx_start_bd), PCI_DMA_TODEVICE);
- nbd = le16_to_cpu(tx_bd->nbd) - 1;
- new_cons = nbd + tx_buf->first_bd;
+ nbd = le16_to_cpu(tx_start_bd->nbd) - 1;
#ifdef BNX2X_STOP_ON_ERROR
- if (nbd > (MAX_SKB_FRAGS + 2)) {
+ if ((nbd - 1) > (MAX_SKB_FRAGS + 2)) {
BNX2X_ERR("BAD nbd!\n");
bnx2x_panic();
}
#endif
+ new_cons = nbd + tx_buf->first_bd;
- /* Skip a parse bd and the TSO split header bd
- since they have no mapping */
- if (nbd)
- bd_idx = TX_BD(NEXT_TX_IDX(bd_idx));
+ /* Get the next bd */
+ bd_idx = TX_BD(NEXT_TX_IDX(bd_idx));
- if (tx_bd->bd_flags.as_bitfield & (ETH_TX_BD_FLAGS_IP_CSUM |
- ETH_TX_BD_FLAGS_TCP_CSUM |
- ETH_TX_BD_FLAGS_SW_LSO)) {
- if (--nbd)
- bd_idx = TX_BD(NEXT_TX_IDX(bd_idx));
- tx_bd = &fp->tx_desc_ring[bd_idx];
- /* is this a TSO split header bd? */
- if (tx_bd->bd_flags.as_bitfield & ETH_TX_BD_FLAGS_SW_LSO) {
- if (--nbd)
- bd_idx = TX_BD(NEXT_TX_IDX(bd_idx));
- }
+ /* Skip a parse bd... */
+ --nbd;
+ bd_idx = TX_BD(NEXT_TX_IDX(bd_idx));
+
+ /* ...and the TSO split header bd since they have no mapping */
+ if (tx_buf->flags & BNX2X_TSO_SPLIT_BD) {
+ --nbd;
+ bd_idx = TX_BD(NEXT_TX_IDX(bd_idx));
}
/* now free frags */
while (nbd > 0) {
DP(BNX2X_MSG_OFF, "free frag bd_idx %d\n", bd_idx);
- tx_bd = &fp->tx_desc_ring[bd_idx];
- pci_unmap_page(bp->pdev, BD_UNMAP_ADDR(tx_bd),
- BD_UNMAP_LEN(tx_bd), PCI_DMA_TODEVICE);
+ tx_data_bd = &fp->tx_desc_ring[bd_idx].reg_bd;
+ pci_unmap_page(bp->pdev, BD_UNMAP_ADDR(tx_data_bd),
+ BD_UNMAP_LEN(tx_data_bd), PCI_DMA_TODEVICE);
if (--nbd)
bd_idx = TX_BD(NEXT_TX_IDX(bd_idx));
}
/* release skb */
WARN_ON(!skb);
- dev_kfree_skb(skb);
+ dev_kfree_skb_any(skb);
tx_buf->first_bd = 0;
tx_buf->skb = NULL;
@@ -896,7 +921,7 @@ static void bnx2x_tx_int(struct bnx2x_fastpath *fp)
return;
#endif
- txq = netdev_get_tx_queue(bp->dev, fp->index);
+ txq = netdev_get_tx_queue(bp->dev, fp->index - bp->num_rx_queues);
hw_cons = le16_to_cpu(*fp->tx_cons_sb);
sw_cons = fp->tx_pkt_cons;
@@ -926,8 +951,6 @@ static void bnx2x_tx_int(struct bnx2x_fastpath *fp)
/* TBD need a thresh? */
if (unlikely(netif_tx_queue_stopped(txq))) {
- __netif_tx_lock(txq, smp_processor_id());
-
/* Need to make the tx_bd_cons update visible to start_xmit()
* before checking for netif_tx_queue_stopped(). Without the
* memory barrier, there is a small possibility that
@@ -940,8 +963,6 @@ static void bnx2x_tx_int(struct bnx2x_fastpath *fp)
(bp->state == BNX2X_STATE_OPEN) &&
(bnx2x_tx_avail(fp) >= MAX_SKB_FRAGS + 3))
netif_tx_wake_queue(txq);
-
- __netif_tx_unlock(txq);
}
}
@@ -1009,6 +1030,7 @@ static void bnx2x_sp_event(struct bnx2x_fastpath *fp,
break;
case (RAMROD_CMD_ID_ETH_SET_MAC | BNX2X_STATE_CLOSING_WAIT4_HALT):
+ case (RAMROD_CMD_ID_ETH_SET_MAC | BNX2X_STATE_DISABLED):
DP(NETIF_MSG_IFDOWN, "got (un)set mac ramrod\n");
break;
@@ -1491,6 +1513,13 @@ static int bnx2x_rx_int(struct bnx2x_fastpath *fp, int budget)
bd_prod = RX_BD(bd_prod);
bd_cons = RX_BD(bd_cons);
+ /* Prefetch the page containing the BD descriptor
+ at producer's index. It will be needed when new skb is
+ allocated */
+ prefetch((void *)(PAGE_ALIGN((unsigned long)
+ (&fp->rx_desc_ring[bd_prod])) -
+ PAGE_SIZE + 1));
+
cqe = &fp->rx_comp_ring[comp_ring_cons];
cqe_fp_flags = cqe->fast_path_cqe.type_error_flags;
@@ -1599,7 +1628,8 @@ static int bnx2x_rx_int(struct bnx2x_fastpath *fp, int budget)
skb = new_skb;
- } else if (bnx2x_alloc_rx_skb(bp, fp, bd_prod) == 0) {
+ } else
+ if (likely(bnx2x_alloc_rx_skb(bp, fp, bd_prod) == 0)) {
pci_unmap_single(bp->pdev,
pci_unmap_addr(rx_buf, mapping),
bp->rx_buf_size,
@@ -1629,6 +1659,7 @@ reuse_rx:
}
skb_record_rx_queue(skb, fp->index);
+
#ifdef BCM_VLAN
if ((bp->vlgrp != NULL) && (bp->flags & HW_VLAN_RX_FLAG) &&
(le16_to_cpu(cqe->fast_path_cqe.pars_flags.flags) &
@@ -1674,7 +1705,6 @@ static irqreturn_t bnx2x_msix_fp_int(int irq, void *fp_cookie)
{
struct bnx2x_fastpath *fp = fp_cookie;
struct bnx2x *bp = fp->bp;
- int index = fp->index;
/* Return here if interrupt is disabled */
if (unlikely(atomic_read(&bp->intr_sem) != 0)) {
@@ -1683,20 +1713,34 @@ static irqreturn_t bnx2x_msix_fp_int(int irq, void *fp_cookie)
}
DP(BNX2X_MSG_FP, "got an MSI-X interrupt on IDX:SB [%d:%d]\n",
- index, fp->sb_id);
+ fp->index, fp->sb_id);
bnx2x_ack_sb(bp, fp->sb_id, USTORM_ID, 0, IGU_INT_DISABLE, 0);
#ifdef BNX2X_STOP_ON_ERROR
if (unlikely(bp->panic))
return IRQ_HANDLED;
#endif
+ /* Handle Rx or Tx according to MSI-X vector */
+ if (fp->is_rx_queue) {
+ prefetch(fp->rx_cons_sb);
+ prefetch(&fp->status_blk->u_status_block.status_block_index);
- prefetch(fp->rx_cons_sb);
- prefetch(fp->tx_cons_sb);
- prefetch(&fp->status_blk->c_status_block.status_block_index);
- prefetch(&fp->status_blk->u_status_block.status_block_index);
+ napi_schedule(&bnx2x_fp(bp, fp->index, napi));
- napi_schedule(&bnx2x_fp(bp, index, napi));
+ } else {
+ prefetch(fp->tx_cons_sb);
+ prefetch(&fp->status_blk->c_status_block.status_block_index);
+
+ bnx2x_update_fpsb_idx(fp);
+ rmb();
+ bnx2x_tx_int(fp);
+
+ /* Re-enable interrupts */
+ bnx2x_ack_sb(bp, fp->sb_id, USTORM_ID,
+ le16_to_cpu(fp->fp_u_idx), IGU_INT_NOP, 1);
+ bnx2x_ack_sb(bp, fp->sb_id, CSTORM_ID,
+ le16_to_cpu(fp->fp_c_idx), IGU_INT_ENABLE, 1);
+ }
return IRQ_HANDLED;
}
@@ -1706,6 +1750,7 @@ static irqreturn_t bnx2x_interrupt(int irq, void *dev_instance)
struct bnx2x *bp = netdev_priv(dev_instance);
u16 status = bnx2x_ack_int(bp);
u16 mask;
+ int i;
/* Return here if interrupt is shared and it's not for us */
if (unlikely(status == 0)) {
@@ -1725,18 +1770,38 @@ static irqreturn_t bnx2x_interrupt(int irq, void *dev_instance)
return IRQ_HANDLED;
#endif
- mask = 0x2 << bp->fp[0].sb_id;
- if (status & mask) {
- struct bnx2x_fastpath *fp = &bp->fp[0];
+ for (i = 0; i < BNX2X_NUM_QUEUES(bp); i++) {
+ struct bnx2x_fastpath *fp = &bp->fp[i];
- prefetch(fp->rx_cons_sb);
- prefetch(fp->tx_cons_sb);
- prefetch(&fp->status_blk->c_status_block.status_block_index);
- prefetch(&fp->status_blk->u_status_block.status_block_index);
+ mask = 0x2 << fp->sb_id;
+ if (status & mask) {
+ /* Handle Rx or Tx according to SB id */
+ if (fp->is_rx_queue) {
+ prefetch(fp->rx_cons_sb);
+ prefetch(&fp->status_blk->u_status_block.
+ status_block_index);
- napi_schedule(&bnx2x_fp(bp, 0, napi));
+ napi_schedule(&bnx2x_fp(bp, fp->index, napi));
- status &= ~mask;
+ } else {
+ prefetch(fp->tx_cons_sb);
+ prefetch(&fp->status_blk->c_status_block.
+ status_block_index);
+
+ bnx2x_update_fpsb_idx(fp);
+ rmb();
+ bnx2x_tx_int(fp);
+
+ /* Re-enable interrupts */
+ bnx2x_ack_sb(bp, fp->sb_id, USTORM_ID,
+ le16_to_cpu(fp->fp_u_idx),
+ IGU_INT_NOP, 1);
+ bnx2x_ack_sb(bp, fp->sb_id, CSTORM_ID,
+ le16_to_cpu(fp->fp_c_idx),
+ IGU_INT_ENABLE, 1);
+ }
+ status &= ~mask;
+ }
}
@@ -2063,6 +2128,12 @@ static void bnx2x_calc_fc_adv(struct bnx2x *bp)
static void bnx2x_link_report(struct bnx2x *bp)
{
+ if (bp->state == BNX2X_STATE_DISABLED) {
+ netif_carrier_off(bp->dev);
+ printk(KERN_ERR PFX "%s NIC Link is Down\n", bp->dev->name);
+ return;
+ }
+
if (bp->link_vars.link_up) {
if (bp->state == BNX2X_STATE_OPEN)
netif_carrier_on(bp->dev);
@@ -2102,9 +2173,7 @@ static u8 bnx2x_initial_phy_init(struct bnx2x *bp, int load_mode)
/* Initialize link parameters structure variables */
/* It is recommended to turn off RX FC for jumbo frames
for better performance */
- if (IS_E1HMF(bp))
- bp->link_params.req_fc_auto_adv = BNX2X_FLOW_CTRL_BOTH;
- else if (bp->dev->mtu > 5000)
+ if (bp->dev->mtu > 5000)
bp->link_params.req_fc_auto_adv = BNX2X_FLOW_CTRL_TX;
else
bp->link_params.req_fc_auto_adv = BNX2X_FLOW_CTRL_BOTH;
@@ -2199,6 +2268,46 @@ static void bnx2x_init_port_minmax(struct bnx2x *bp)
bp->cmng.fair_vars.fairness_timeout = fair_periodic_timeout_usec / 4;
}
+/* Calculates the sum of vn_min_rates.
+ It's needed for further normalizing of the min_rates.
+ Returns:
+ sum of vn_min_rates.
+ or
+ 0 - if all the min_rates are 0.
+ In the later case fainess algorithm should be deactivated.
+ If not all min_rates are zero then those that are zeroes will be set to 1.
+ */
+static void bnx2x_calc_vn_weight_sum(struct bnx2x *bp)
+{
+ int all_zero = 1;
+ int port = BP_PORT(bp);
+ int vn;
+
+ bp->vn_weight_sum = 0;
+ for (vn = VN_0; vn < E1HVN_MAX; vn++) {
+ int func = 2*vn + port;
+ u32 vn_cfg = SHMEM_RD(bp, mf_cfg.func_mf_config[func].config);
+ u32 vn_min_rate = ((vn_cfg & FUNC_MF_CFG_MIN_BW_MASK) >>
+ FUNC_MF_CFG_MIN_BW_SHIFT) * 100;
+
+ /* Skip hidden vns */
+ if (vn_cfg & FUNC_MF_CFG_FUNC_HIDE)
+ continue;
+
+ /* If min rate is zero - set it to 1 */
+ if (!vn_min_rate)
+ vn_min_rate = DEF_MIN_RATE;
+ else
+ all_zero = 0;
+
+ bp->vn_weight_sum += vn_min_rate;
+ }
+
+ /* ... only if all min rates are zeros - disable fairness */
+ if (all_zero)
+ bp->vn_weight_sum = 0;
+}
+
static void bnx2x_init_vn_minmax(struct bnx2x *bp, int func)
{
struct rate_shaping_vars_per_vn m_rs_vn;
@@ -2276,7 +2385,7 @@ static void bnx2x_link_attn(struct bnx2x *bp)
if (bp->link_vars.link_up) {
/* dropless flow control */
- if (CHIP_IS_E1H(bp)) {
+ if (CHIP_IS_E1H(bp) && bp->dropless_fc) {
int port = BP_PORT(bp);
u32 pause_enabled = 0;
@@ -2284,7 +2393,7 @@ static void bnx2x_link_attn(struct bnx2x *bp)
pause_enabled = 1;
REG_WR(bp, BAR_USTRORM_INTMEM +
- USTORM_PAUSE_ENABLED_OFFSET(port),
+ USTORM_ETH_PAUSE_ENABLED_OFFSET(port),
pause_enabled);
}
@@ -2309,14 +2418,12 @@ static void bnx2x_link_attn(struct bnx2x *bp)
int func;
int vn;
+ /* Set the attention towards other drivers on the same port */
for (vn = VN_0; vn < E1HVN_MAX; vn++) {
if (vn == BP_E1HVN(bp))
continue;
func = ((vn << 1) | port);
-
- /* Set the attention towards other drivers
- on the same port */
REG_WR(bp, MISC_REG_AEU_GENERAL_ATTN_0 +
(LINK_SYNC_ATTENTION_BIT_FUNC_0 + func)*4, 1);
}
@@ -2342,6 +2449,8 @@ static void bnx2x_link_attn(struct bnx2x *bp)
static void bnx2x__link_status_update(struct bnx2x *bp)
{
+ int func = BP_FUNC(bp);
+
if (bp->state != BNX2X_STATE_OPEN)
return;
@@ -2352,6 +2461,9 @@ static void bnx2x__link_status_update(struct bnx2x *bp)
else
bnx2x_stats_handle(bp, STATS_EVENT_STOP);
+ bp->mf_config = SHMEM_RD(bp, mf_cfg.func_mf_config[func].config);
+ bnx2x_calc_vn_weight_sum(bp);
+
/* indicate link status */
bnx2x_link_report(bp);
}
@@ -2380,6 +2492,152 @@ static void bnx2x_pmf_update(struct bnx2x *bp)
* General service functions
*/
+/* send the MCP a request, block until there is a reply */
+u32 bnx2x_fw_command(struct bnx2x *bp, u32 command)
+{
+ int func = BP_FUNC(bp);
+ u32 seq = ++bp->fw_seq;
+ u32 rc = 0;
+ u32 cnt = 1;
+ u8 delay = CHIP_REV_IS_SLOW(bp) ? 100 : 10;
+
+ SHMEM_WR(bp, func_mb[func].drv_mb_header, (command | seq));
+ DP(BNX2X_MSG_MCP, "wrote command (%x) to FW MB\n", (command | seq));
+
+ do {
+ /* let the FW do it's magic ... */
+ msleep(delay);
+
+ rc = SHMEM_RD(bp, func_mb[func].fw_mb_header);
+
+ /* Give the FW up to 2 second (200*10ms) */
+ } while ((seq != (rc & FW_MSG_SEQ_NUMBER_MASK)) && (cnt++ < 200));
+
+ DP(BNX2X_MSG_MCP, "[after %d ms] read (%x) seq is (%x) from FW MB\n",
+ cnt*delay, rc, seq);
+
+ /* is this a reply to our command? */
+ if (seq == (rc & FW_MSG_SEQ_NUMBER_MASK))
+ rc &= FW_MSG_CODE_MASK;
+ else {
+ /* FW BUG! */
+ BNX2X_ERR("FW failed to respond!\n");
+ bnx2x_fw_dump(bp);
+ rc = 0;
+ }
+
+ return rc;
+}
+
+static void bnx2x_set_storm_rx_mode(struct bnx2x *bp);
+static void bnx2x_set_mac_addr_e1h(struct bnx2x *bp, int set);
+static void bnx2x_set_rx_mode(struct net_device *dev);
+
+static void bnx2x_e1h_disable(struct bnx2x *bp)
+{
+ int port = BP_PORT(bp);
+ int i;
+
+ bp->rx_mode = BNX2X_RX_MODE_NONE;
+ bnx2x_set_storm_rx_mode(bp);
+
+ netif_tx_disable(bp->dev);
+ bp->dev->trans_start = jiffies; /* prevent tx timeout */
+
+ REG_WR(bp, NIG_REG_LLH0_FUNC_EN + port*8, 0);
+
+ bnx2x_set_mac_addr_e1h(bp, 0);
+
+ for (i = 0; i < MC_HASH_SIZE; i++)
+ REG_WR(bp, MC_HASH_OFFSET(bp, i), 0);
+
+ netif_carrier_off(bp->dev);
+}
+
+static void bnx2x_e1h_enable(struct bnx2x *bp)
+{
+ int port = BP_PORT(bp);
+
+ REG_WR(bp, NIG_REG_LLH0_FUNC_EN + port*8, 1);
+
+ bnx2x_set_mac_addr_e1h(bp, 1);
+
+ /* Tx queue should be only reenabled */
+ netif_tx_wake_all_queues(bp->dev);
+
+ /* Initialize the receive filter. */
+ bnx2x_set_rx_mode(bp->dev);
+}
+
+static void bnx2x_update_min_max(struct bnx2x *bp)
+{
+ int port = BP_PORT(bp);
+ int vn, i;
+
+ /* Init rate shaping and fairness contexts */
+ bnx2x_init_port_minmax(bp);
+
+ bnx2x_calc_vn_weight_sum(bp);
+
+ for (vn = VN_0; vn < E1HVN_MAX; vn++)
+ bnx2x_init_vn_minmax(bp, 2*vn + port);
+
+ if (bp->port.pmf) {
+ int func;
+
+ /* Set the attention towards other drivers on the same port */
+ for (vn = VN_0; vn < E1HVN_MAX; vn++) {
+ if (vn == BP_E1HVN(bp))
+ continue;
+
+ func = ((vn << 1) | port);
+ REG_WR(bp, MISC_REG_AEU_GENERAL_ATTN_0 +
+ (LINK_SYNC_ATTENTION_BIT_FUNC_0 + func)*4, 1);
+ }
+
+ /* Store it to internal memory */
+ for (i = 0; i < sizeof(struct cmng_struct_per_port) / 4; i++)
+ REG_WR(bp, BAR_XSTRORM_INTMEM +
+ XSTORM_CMNG_PER_PORT_VARS_OFFSET(port) + i*4,
+ ((u32 *)(&bp->cmng))[i]);
+ }
+}
+
+static void bnx2x_dcc_event(struct bnx2x *bp, u32 dcc_event)
+{
+ int func = BP_FUNC(bp);
+
+ DP(BNX2X_MSG_MCP, "dcc_event 0x%x\n", dcc_event);
+ bp->mf_config = SHMEM_RD(bp, mf_cfg.func_mf_config[func].config);
+
+ if (dcc_event & DRV_STATUS_DCC_DISABLE_ENABLE_PF) {
+
+ if (bp->mf_config & FUNC_MF_CFG_FUNC_DISABLED) {
+ DP(NETIF_MSG_IFDOWN, "mf_cfg function disabled\n");
+ bp->state = BNX2X_STATE_DISABLED;
+
+ bnx2x_e1h_disable(bp);
+ } else {
+ DP(NETIF_MSG_IFUP, "mf_cfg function enabled\n");
+ bp->state = BNX2X_STATE_OPEN;
+
+ bnx2x_e1h_enable(bp);
+ }
+ dcc_event &= ~DRV_STATUS_DCC_DISABLE_ENABLE_PF;
+ }
+ if (dcc_event & DRV_STATUS_DCC_BANDWIDTH_ALLOCATION) {
+
+ bnx2x_update_min_max(bp);
+ dcc_event &= ~DRV_STATUS_DCC_BANDWIDTH_ALLOCATION;
+ }
+
+ /* Report results to MCP */
+ if (dcc_event)
+ bnx2x_fw_command(bp, DRV_MSG_CODE_DCC_FAILURE);
+ else
+ bnx2x_fw_command(bp, DRV_MSG_CODE_DCC_OK);
+}
+
/* the slow path queue is odd since completions arrive on the fastpath ring */
static int bnx2x_sp_post(struct bnx2x *bp, int command, int cid,
u32 data_hi, u32 data_lo, int common)
@@ -2430,9 +2688,14 @@ static int bnx2x_sp_post(struct bnx2x *bp, int command, int cid,
bp->spq_prod_idx++;
}
+ /* Make sure that BD data is updated before writing the producer */
+ wmb();
+
REG_WR(bp, BAR_XSTRORM_INTMEM + XSTORM_SPQ_PROD_OFFSET(func),
bp->spq_prod_idx);
+ mmiowb();
+
spin_unlock_bh(&bp->spq_lock);
return 0;
}
@@ -2599,11 +2862,28 @@ static void bnx2x_attn_int_asserted(struct bnx2x *bp, u32 asserted)
}
}
+static inline void bnx2x_fan_failure(struct bnx2x *bp)
+{
+ int port = BP_PORT(bp);
+
+ /* mark the failure */
+ bp->link_params.ext_phy_config &= ~PORT_HW_CFG_XGXS_EXT_PHY_TYPE_MASK;
+ bp->link_params.ext_phy_config |= PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE;
+ SHMEM_WR(bp, dev_info.port_hw_config[port].external_phy_config,
+ bp->link_params.ext_phy_config);
+
+ /* log the failure */
+ printk(KERN_ERR PFX "Fan Failure on Network Controller %s has caused"
+ " the driver to shutdown the card to prevent permanent"
+ " damage. Please contact Dell Support for assistance\n",
+ bp->dev->name);
+}
+
static inline void bnx2x_attn_int_deasserted0(struct bnx2x *bp, u32 attn)
{
int port = BP_PORT(bp);
int reg_offset;
- u32 val;
+ u32 val, swap_val, swap_override;
reg_offset = (port ? MISC_REG_AEU_ENABLE1_FUNC_1_OUT_0 :
MISC_REG_AEU_ENABLE1_FUNC_0_OUT_0);
@@ -2616,36 +2896,32 @@ static inline void bnx2x_attn_int_deasserted0(struct bnx2x *bp, u32 attn)
BNX2X_ERR("SPIO5 hw attention\n");
+ /* Fan failure attention */
switch (XGXS_EXT_PHY_TYPE(bp->link_params.ext_phy_config)) {
case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101:
- /* Fan failure attention */
-
+ /* Low power mode is controlled by GPIO 2 */
+ bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
+ MISC_REGISTERS_GPIO_OUTPUT_LOW, port);
/* The PHY reset is controlled by GPIO 1 */
bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
MISC_REGISTERS_GPIO_OUTPUT_LOW, port);
- /* Low power mode is controlled by GPIO 2 */
- bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
+ break;
+
+ case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727:
+ /* The PHY reset is controlled by GPIO 1 */
+ /* fake the port number to cancel the swap done in
+ set_gpio() */
+ swap_val = REG_RD(bp, NIG_REG_PORT_SWAP);
+ swap_override = REG_RD(bp, NIG_REG_STRAP_OVERRIDE);
+ port = (swap_val && swap_override) ^ 1;
+ bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
MISC_REGISTERS_GPIO_OUTPUT_LOW, port);
- /* mark the failure */
- bp->link_params.ext_phy_config &=
- ~PORT_HW_CFG_XGXS_EXT_PHY_TYPE_MASK;
- bp->link_params.ext_phy_config |=
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE;
- SHMEM_WR(bp,
- dev_info.port_hw_config[port].
- external_phy_config,
- bp->link_params.ext_phy_config);
- /* log the failure */
- printk(KERN_ERR PFX "Fan Failure on Network"
- " Controller %s has caused the driver to"
- " shutdown the card to prevent permanent"
- " damage. Please contact Dell Support for"
- " assistance\n", bp->dev->name);
break;
default:
break;
}
+ bnx2x_fan_failure(bp);
}
if (attn & (AEU_INPUTS_ATTN_BITS_GPIO3_FUNCTION_0 |
@@ -2662,7 +2938,7 @@ static inline void bnx2x_attn_int_deasserted0(struct bnx2x *bp, u32 attn)
REG_WR(bp, reg_offset, val);
BNX2X_ERR("FATAL HW block attention set0 0x%x\n",
- (attn & HW_INTERRUT_ASSERT_SET_0));
+ (u32)(attn & HW_INTERRUT_ASSERT_SET_0));
bnx2x_panic();
}
}
@@ -2693,7 +2969,7 @@ static inline void bnx2x_attn_int_deasserted1(struct bnx2x *bp, u32 attn)
REG_WR(bp, reg_offset, val);
BNX2X_ERR("FATAL HW block attention set1 0x%x\n",
- (attn & HW_INTERRUT_ASSERT_SET_1));
+ (u32)(attn & HW_INTERRUT_ASSERT_SET_1));
bnx2x_panic();
}
}
@@ -2733,7 +3009,7 @@ static inline void bnx2x_attn_int_deasserted2(struct bnx2x *bp, u32 attn)
REG_WR(bp, reg_offset, val);
BNX2X_ERR("FATAL HW block attention set2 0x%x\n",
- (attn & HW_INTERRUT_ASSERT_SET_2));
+ (u32)(attn & HW_INTERRUT_ASSERT_SET_2));
bnx2x_panic();
}
}
@@ -2748,9 +3024,12 @@ static inline void bnx2x_attn_int_deasserted3(struct bnx2x *bp, u32 attn)
int func = BP_FUNC(bp);
REG_WR(bp, MISC_REG_AEU_GENERAL_ATTN_12 + func*4, 0);
+ val = SHMEM_RD(bp, func_mb[func].drv_status);
+ if (val & DRV_STATUS_DCC_EVENT_MASK)
+ bnx2x_dcc_event(bp,
+ (val & DRV_STATUS_DCC_EVENT_MASK));
bnx2x__link_status_update(bp);
- if (SHMEM_RD(bp, func_mb[func].drv_status) &
- DRV_STATUS_PMF)
+ if ((bp->port.pmf == 0) && (val & DRV_STATUS_PMF))
bnx2x_pmf_update(bp);
} else if (attn & BNX2X_MC_ASSERT_BITS) {
@@ -3109,53 +3388,6 @@ static void bnx2x_storm_stats_post(struct bnx2x *bp)
}
}
-static void bnx2x_stats_init(struct bnx2x *bp)
-{
- int port = BP_PORT(bp);
- int i;
-
- bp->stats_pending = 0;
- bp->executer_idx = 0;
- bp->stats_counter = 0;
-
- /* port stats */
- if (!BP_NOMCP(bp))
- bp->port.port_stx = SHMEM_RD(bp, port_mb[port].port_stx);
- else
- bp->port.port_stx = 0;
- DP(BNX2X_MSG_STATS, "port_stx 0x%x\n", bp->port.port_stx);
-
- memset(&(bp->port.old_nig_stats), 0, sizeof(struct nig_stats));
- bp->port.old_nig_stats.brb_discard =
- REG_RD(bp, NIG_REG_STAT0_BRB_DISCARD + port*0x38);
- bp->port.old_nig_stats.brb_truncate =
- REG_RD(bp, NIG_REG_STAT0_BRB_TRUNCATE + port*0x38);
- REG_RD_DMAE(bp, NIG_REG_STAT0_EGRESS_MAC_PKT0 + port*0x50,
- &(bp->port.old_nig_stats.egress_mac_pkt0_lo), 2);
- REG_RD_DMAE(bp, NIG_REG_STAT0_EGRESS_MAC_PKT1 + port*0x50,
- &(bp->port.old_nig_stats.egress_mac_pkt1_lo), 2);
-
- /* function stats */
- for_each_queue(bp, i) {
- struct bnx2x_fastpath *fp = &bp->fp[i];
-
- memset(&fp->old_tclient, 0,
- sizeof(struct tstorm_per_client_stats));
- memset(&fp->old_uclient, 0,
- sizeof(struct ustorm_per_client_stats));
- memset(&fp->old_xclient, 0,
- sizeof(struct xstorm_per_client_stats));
- memset(&fp->eth_q_stats, 0, sizeof(struct bnx2x_eth_q_stats));
- }
-
- memset(&bp->dev->stats, 0, sizeof(struct net_device_stats));
- memset(&bp->eth_stats, 0, sizeof(struct bnx2x_eth_stats));
-
- bp->stats_state = STATS_STATE_DISABLED;
- if (IS_E1HMF(bp) && bp->port.pmf && bp->port.port_stx)
- bnx2x_stats_handle(bp, STATS_EVENT_PMF);
-}
-
static void bnx2x_hw_stats_post(struct bnx2x *bp)
{
struct dmae_command *dmae = &bp->stats_dmae;
@@ -3716,7 +3948,8 @@ static int bnx2x_storm_stats_update(struct bnx2x *bp)
struct bnx2x_eth_stats *estats = &bp->eth_stats;
int i;
- memset(&(fstats->total_bytes_received_hi), 0,
+ memcpy(&(fstats->total_bytes_received_hi),
+ &(bnx2x_sp(bp, func_stats_base)->total_bytes_received_hi),
sizeof(struct host_func_stats) - 2*sizeof(u32));
estats->error_bytes_received_hi = 0;
estats->error_bytes_received_lo = 0;
@@ -3725,7 +3958,7 @@ static int bnx2x_storm_stats_update(struct bnx2x *bp)
estats->no_buff_discard_hi = 0;
estats->no_buff_discard_lo = 0;
- for_each_queue(bp, i) {
+ for_each_rx_queue(bp, i) {
struct bnx2x_fastpath *fp = &bp->fp[i];
int cl_id = fp->cl_id;
struct tstorm_per_client_stats *tclient =
@@ -3764,11 +3997,24 @@ static int bnx2x_storm_stats_update(struct bnx2x *bp)
}
qstats->total_bytes_received_hi =
- qstats->valid_bytes_received_hi =
- le32_to_cpu(tclient->total_rcv_bytes.hi);
+ le32_to_cpu(tclient->rcv_broadcast_bytes.hi);
qstats->total_bytes_received_lo =
+ le32_to_cpu(tclient->rcv_broadcast_bytes.lo);
+
+ ADD_64(qstats->total_bytes_received_hi,
+ le32_to_cpu(tclient->rcv_multicast_bytes.hi),
+ qstats->total_bytes_received_lo,
+ le32_to_cpu(tclient->rcv_multicast_bytes.lo));
+
+ ADD_64(qstats->total_bytes_received_hi,
+ le32_to_cpu(tclient->rcv_unicast_bytes.hi),
+ qstats->total_bytes_received_lo,
+ le32_to_cpu(tclient->rcv_unicast_bytes.lo));
+
+ qstats->valid_bytes_received_hi =
+ qstats->total_bytes_received_hi;
qstats->valid_bytes_received_lo =
- le32_to_cpu(tclient->total_rcv_bytes.lo);
+ qstats->total_bytes_received_lo;
qstats->error_bytes_received_hi =
le32_to_cpu(tclient->rcv_error_bytes.hi);
@@ -3801,9 +4047,19 @@ static int bnx2x_storm_stats_update(struct bnx2x *bp)
UPDATE_EXTEND_USTAT(bcast_no_buff_pkts, no_buff_discard);
qstats->total_bytes_transmitted_hi =
- le32_to_cpu(xclient->total_sent_bytes.hi);
+ le32_to_cpu(xclient->unicast_bytes_sent.hi);
qstats->total_bytes_transmitted_lo =
- le32_to_cpu(xclient->total_sent_bytes.lo);
+ le32_to_cpu(xclient->unicast_bytes_sent.lo);
+
+ ADD_64(qstats->total_bytes_transmitted_hi,
+ le32_to_cpu(xclient->multicast_bytes_sent.hi),
+ qstats->total_bytes_transmitted_lo,
+ le32_to_cpu(xclient->multicast_bytes_sent.lo));
+
+ ADD_64(qstats->total_bytes_transmitted_hi,
+ le32_to_cpu(xclient->broadcast_bytes_sent.hi),
+ qstats->total_bytes_transmitted_lo,
+ le32_to_cpu(xclient->broadcast_bytes_sent.lo));
UPDATE_EXTEND_XSTAT(unicast_pkts_sent,
total_unicast_packets_transmitted);
@@ -3919,7 +4175,7 @@ static void bnx2x_net_stats_update(struct bnx2x *bp)
nstats->tx_bytes = bnx2x_hilo(&estats->total_bytes_transmitted_hi);
nstats->rx_dropped = estats->mac_discard;
- for_each_queue(bp, i)
+ for_each_rx_queue(bp, i)
nstats->rx_dropped +=
le32_to_cpu(bp->fp[i].old_tclient.checksum_discard);
@@ -3973,7 +4229,7 @@ static void bnx2x_drv_stats_update(struct bnx2x *bp)
estats->rx_err_discard_pkt = 0;
estats->rx_skb_alloc_failed = 0;
estats->hw_csum_err = 0;
- for_each_queue(bp, i) {
+ for_each_rx_queue(bp, i) {
struct bnx2x_eth_q_stats *qstats = &bp->fp[i].eth_q_stats;
estats->driver_xoff += qstats->driver_xoff;
@@ -4003,6 +4259,8 @@ static void bnx2x_stats_update(struct bnx2x *bp)
bnx2x_drv_stats_update(bp);
if (bp->msglevel & NETIF_MSG_TIMER) {
+ struct bnx2x_fastpath *fp0_rx = bp->fp;
+ struct bnx2x_fastpath *fp0_tx = &(bp->fp[bp->num_rx_queues]);
struct tstorm_per_client_stats *old_tclient =
&bp->fp->old_tclient;
struct bnx2x_eth_q_stats *qstats = &bp->fp->eth_q_stats;
@@ -4013,13 +4271,13 @@ static void bnx2x_stats_update(struct bnx2x *bp)
printk(KERN_DEBUG "%s:\n", bp->dev->name);
printk(KERN_DEBUG " tx avail (%4x) tx hc idx (%x)"
" tx pkt (%lx)\n",
- bnx2x_tx_avail(bp->fp),
- le16_to_cpu(*bp->fp->tx_cons_sb), nstats->tx_packets);
+ bnx2x_tx_avail(fp0_tx),
+ le16_to_cpu(*fp0_tx->tx_cons_sb), nstats->tx_packets);
printk(KERN_DEBUG " rx usage (%4x) rx hc idx (%x)"
" rx pkt (%lx)\n",
- (u16)(le16_to_cpu(*bp->fp->rx_cons_sb) -
- bp->fp->rx_comp_cons),
- le16_to_cpu(*bp->fp->rx_cons_sb), nstats->rx_packets);
+ (u16)(le16_to_cpu(*fp0_rx->rx_cons_sb) -
+ fp0_rx->rx_comp_cons),
+ le16_to_cpu(*fp0_rx->rx_cons_sb), nstats->rx_packets);
printk(KERN_DEBUG " %s (Xoff events %u) brb drops %u "
"brb truncate %u\n",
(netif_queue_stopped(bp->dev) ? "Xoff" : "Xon"),
@@ -4165,11 +4423,181 @@ static void bnx2x_stats_handle(struct bnx2x *bp, enum bnx2x_stats_event event)
bnx2x_stats_stm[state][event].action(bp);
bp->stats_state = bnx2x_stats_stm[state][event].next_state;
+ /* Make sure the state has been "changed" */
+ smp_wmb();
+
if ((event != STATS_EVENT_UPDATE) || (bp->msglevel & NETIF_MSG_TIMER))
DP(BNX2X_MSG_STATS, "state %d -> event %d -> state %d\n",
state, event, bp->stats_state);
}
+static void bnx2x_port_stats_base_init(struct bnx2x *bp)
+{
+ struct dmae_command *dmae;
+ u32 *stats_comp = bnx2x_sp(bp, stats_comp);
+
+ /* sanity */
+ if (!bp->port.pmf || !bp->port.port_stx) {
+ BNX2X_ERR("BUG!\n");
+ return;
+ }
+
+ bp->executer_idx = 0;
+
+ dmae = bnx2x_sp(bp, dmae[bp->executer_idx++]);
+ dmae->opcode = (DMAE_CMD_SRC_PCI | DMAE_CMD_DST_GRC |
+ DMAE_CMD_C_DST_PCI | DMAE_CMD_C_ENABLE |
+ DMAE_CMD_SRC_RESET | DMAE_CMD_DST_RESET |
+#ifdef __BIG_ENDIAN
+ DMAE_CMD_ENDIANITY_B_DW_SWAP |
+#else
+ DMAE_CMD_ENDIANITY_DW_SWAP |
+#endif
+ (BP_PORT(bp) ? DMAE_CMD_PORT_1 : DMAE_CMD_PORT_0) |
+ (BP_E1HVN(bp) << DMAE_CMD_E1HVN_SHIFT));
+ dmae->src_addr_lo = U64_LO(bnx2x_sp_mapping(bp, port_stats));
+ dmae->src_addr_hi = U64_HI(bnx2x_sp_mapping(bp, port_stats));
+ dmae->dst_addr_lo = bp->port.port_stx >> 2;
+ dmae->dst_addr_hi = 0;
+ dmae->len = sizeof(struct host_port_stats) >> 2;
+ dmae->comp_addr_lo = U64_LO(bnx2x_sp_mapping(bp, stats_comp));
+ dmae->comp_addr_hi = U64_HI(bnx2x_sp_mapping(bp, stats_comp));
+ dmae->comp_val = DMAE_COMP_VAL;
+
+ *stats_comp = 0;
+ bnx2x_hw_stats_post(bp);
+ bnx2x_stats_comp(bp);
+}
+
+static void bnx2x_func_stats_base_init(struct bnx2x *bp)
+{
+ int vn, vn_max = IS_E1HMF(bp) ? E1HVN_MAX : E1VN_MAX;
+ int port = BP_PORT(bp);
+ int func;
+ u32 func_stx;
+
+ /* sanity */
+ if (!bp->port.pmf || !bp->func_stx) {
+ BNX2X_ERR("BUG!\n");
+ return;
+ }
+
+ /* save our func_stx */
+ func_stx = bp->func_stx;
+
+ for (vn = VN_0; vn < vn_max; vn++) {
+ func = 2*vn + port;
+
+ bp->func_stx = SHMEM_RD(bp, func_mb[func].fw_mb_param);
+ bnx2x_func_stats_init(bp);
+ bnx2x_hw_stats_post(bp);
+ bnx2x_stats_comp(bp);
+ }
+
+ /* restore our func_stx */
+ bp->func_stx = func_stx;
+}
+
+static void bnx2x_func_stats_base_update(struct bnx2x *bp)
+{
+ struct dmae_command *dmae = &bp->stats_dmae;
+ u32 *stats_comp = bnx2x_sp(bp, stats_comp);
+
+ /* sanity */
+ if (!bp->func_stx) {
+ BNX2X_ERR("BUG!\n");
+ return;
+ }
+
+ bp->executer_idx = 0;
+ memset(dmae, 0, sizeof(struct dmae_command));
+
+ dmae->opcode = (DMAE_CMD_SRC_GRC | DMAE_CMD_DST_PCI |
+ DMAE_CMD_C_DST_PCI | DMAE_CMD_C_ENABLE |
+ DMAE_CMD_SRC_RESET | DMAE_CMD_DST_RESET |
+#ifdef __BIG_ENDIAN
+ DMAE_CMD_ENDIANITY_B_DW_SWAP |
+#else
+ DMAE_CMD_ENDIANITY_DW_SWAP |
+#endif
+ (BP_PORT(bp) ? DMAE_CMD_PORT_1 : DMAE_CMD_PORT_0) |
+ (BP_E1HVN(bp) << DMAE_CMD_E1HVN_SHIFT));
+ dmae->src_addr_lo = bp->func_stx >> 2;
+ dmae->src_addr_hi = 0;
+ dmae->dst_addr_lo = U64_LO(bnx2x_sp_mapping(bp, func_stats_base));
+ dmae->dst_addr_hi = U64_HI(bnx2x_sp_mapping(bp, func_stats_base));
+ dmae->len = sizeof(struct host_func_stats) >> 2;
+ dmae->comp_addr_lo = U64_LO(bnx2x_sp_mapping(bp, stats_comp));
+ dmae->comp_addr_hi = U64_HI(bnx2x_sp_mapping(bp, stats_comp));
+ dmae->comp_val = DMAE_COMP_VAL;
+
+ *stats_comp = 0;
+ bnx2x_hw_stats_post(bp);
+ bnx2x_stats_comp(bp);
+}
+
+static void bnx2x_stats_init(struct bnx2x *bp)
+{
+ int port = BP_PORT(bp);
+ int func = BP_FUNC(bp);
+ int i;
+
+ bp->stats_pending = 0;
+ bp->executer_idx = 0;
+ bp->stats_counter = 0;
+
+ /* port and func stats for management */
+ if (!BP_NOMCP(bp)) {
+ bp->port.port_stx = SHMEM_RD(bp, port_mb[port].port_stx);
+ bp->func_stx = SHMEM_RD(bp, func_mb[func].fw_mb_param);
+
+ } else {
+ bp->port.port_stx = 0;
+ bp->func_stx = 0;
+ }
+ DP(BNX2X_MSG_STATS, "port_stx 0x%x func_stx 0x%x\n",
+ bp->port.port_stx, bp->func_stx);
+
+ /* port stats */
+ memset(&(bp->port.old_nig_stats), 0, sizeof(struct nig_stats));
+ bp->port.old_nig_stats.brb_discard =
+ REG_RD(bp, NIG_REG_STAT0_BRB_DISCARD + port*0x38);
+ bp->port.old_nig_stats.brb_truncate =
+ REG_RD(bp, NIG_REG_STAT0_BRB_TRUNCATE + port*0x38);
+ REG_RD_DMAE(bp, NIG_REG_STAT0_EGRESS_MAC_PKT0 + port*0x50,
+ &(bp->port.old_nig_stats.egress_mac_pkt0_lo), 2);
+ REG_RD_DMAE(bp, NIG_REG_STAT0_EGRESS_MAC_PKT1 + port*0x50,
+ &(bp->port.old_nig_stats.egress_mac_pkt1_lo), 2);
+
+ /* function stats */
+ for_each_queue(bp, i) {
+ struct bnx2x_fastpath *fp = &bp->fp[i];
+
+ memset(&fp->old_tclient, 0,
+ sizeof(struct tstorm_per_client_stats));
+ memset(&fp->old_uclient, 0,
+ sizeof(struct ustorm_per_client_stats));
+ memset(&fp->old_xclient, 0,
+ sizeof(struct xstorm_per_client_stats));
+ memset(&fp->eth_q_stats, 0, sizeof(struct bnx2x_eth_q_stats));
+ }
+
+ memset(&bp->dev->stats, 0, sizeof(struct net_device_stats));
+ memset(&bp->eth_stats, 0, sizeof(struct bnx2x_eth_stats));
+
+ bp->stats_state = STATS_STATE_DISABLED;
+
+ if (bp->port.pmf) {
+ if (bp->port.port_stx)
+ bnx2x_port_stats_base_init(bp);
+
+ if (bp->func_stx)
+ bnx2x_func_stats_base_init(bp);
+
+ } else if (bp->func_stx)
+ bnx2x_func_stats_base_update(bp);
+}
+
static void bnx2x_timer(unsigned long data)
{
struct bnx2x *bp = (struct bnx2x *) data;
@@ -4232,12 +4660,13 @@ static void bnx2x_zero_sb(struct bnx2x *bp, int sb_id)
{
int port = BP_PORT(bp);
- bnx2x_init_fill(bp, USTORM_INTMEM_ADDR +
- USTORM_SB_HOST_STATUS_BLOCK_OFFSET(port, sb_id), 0,
- sizeof(struct ustorm_status_block)/4);
- bnx2x_init_fill(bp, CSTORM_INTMEM_ADDR +
- CSTORM_SB_HOST_STATUS_BLOCK_OFFSET(port, sb_id), 0,
- sizeof(struct cstorm_status_block)/4);
+ /* "CSTORM" */
+ bnx2x_init_fill(bp, CSEM_REG_FAST_MEMORY +
+ CSTORM_SB_HOST_STATUS_BLOCK_U_OFFSET(port, sb_id), 0,
+ CSTORM_SB_STATUS_BLOCK_U_SIZE / 4);
+ bnx2x_init_fill(bp, CSEM_REG_FAST_MEMORY +
+ CSTORM_SB_HOST_STATUS_BLOCK_C_OFFSET(port, sb_id), 0,
+ CSTORM_SB_STATUS_BLOCK_C_SIZE / 4);
}
static void bnx2x_init_sb(struct bnx2x *bp, struct host_status_block *sb,
@@ -4253,17 +4682,17 @@ static void bnx2x_init_sb(struct bnx2x *bp, struct host_status_block *sb,
u_status_block);
sb->u_status_block.status_block_id = sb_id;
- REG_WR(bp, BAR_USTRORM_INTMEM +
- USTORM_SB_HOST_SB_ADDR_OFFSET(port, sb_id), U64_LO(section));
- REG_WR(bp, BAR_USTRORM_INTMEM +
- ((USTORM_SB_HOST_SB_ADDR_OFFSET(port, sb_id)) + 4),
+ REG_WR(bp, BAR_CSTRORM_INTMEM +
+ CSTORM_SB_HOST_SB_ADDR_U_OFFSET(port, sb_id), U64_LO(section));
+ REG_WR(bp, BAR_CSTRORM_INTMEM +
+ ((CSTORM_SB_HOST_SB_ADDR_U_OFFSET(port, sb_id)) + 4),
U64_HI(section));
- REG_WR8(bp, BAR_USTRORM_INTMEM + FP_USB_FUNC_OFF +
- USTORM_SB_HOST_STATUS_BLOCK_OFFSET(port, sb_id), func);
+ REG_WR8(bp, BAR_CSTRORM_INTMEM + FP_USB_FUNC_OFF +
+ CSTORM_SB_HOST_STATUS_BLOCK_U_OFFSET(port, sb_id), func);
for (index = 0; index < HC_USTORM_SB_NUM_INDICES; index++)
- REG_WR16(bp, BAR_USTRORM_INTMEM +
- USTORM_SB_HC_DISABLE_OFFSET(port, sb_id, index), 1);
+ REG_WR16(bp, BAR_CSTRORM_INTMEM +
+ CSTORM_SB_HC_DISABLE_U_OFFSET(port, sb_id, index), 1);
/* CSTORM */
section = ((u64)mapping) + offsetof(struct host_status_block,
@@ -4271,16 +4700,16 @@ static void bnx2x_init_sb(struct bnx2x *bp, struct host_status_block *sb,
sb->c_status_block.status_block_id = sb_id;
REG_WR(bp, BAR_CSTRORM_INTMEM +
- CSTORM_SB_HOST_SB_ADDR_OFFSET(port, sb_id), U64_LO(section));
+ CSTORM_SB_HOST_SB_ADDR_C_OFFSET(port, sb_id), U64_LO(section));
REG_WR(bp, BAR_CSTRORM_INTMEM +
- ((CSTORM_SB_HOST_SB_ADDR_OFFSET(port, sb_id)) + 4),
+ ((CSTORM_SB_HOST_SB_ADDR_C_OFFSET(port, sb_id)) + 4),
U64_HI(section));
REG_WR8(bp, BAR_CSTRORM_INTMEM + FP_CSB_FUNC_OFF +
- CSTORM_SB_HOST_STATUS_BLOCK_OFFSET(port, sb_id), func);
+ CSTORM_SB_HOST_STATUS_BLOCK_C_OFFSET(port, sb_id), func);
for (index = 0; index < HC_CSTORM_SB_NUM_INDICES; index++)
REG_WR16(bp, BAR_CSTRORM_INTMEM +
- CSTORM_SB_HC_DISABLE_OFFSET(port, sb_id, index), 1);
+ CSTORM_SB_HC_DISABLE_C_OFFSET(port, sb_id, index), 1);
bnx2x_ack_sb(bp, sb_id, CSTORM_ID, 0, IGU_INT_ENABLE, 0);
}
@@ -4289,16 +4718,16 @@ static void bnx2x_zero_def_sb(struct bnx2x *bp)
{
int func = BP_FUNC(bp);
- bnx2x_init_fill(bp, TSTORM_INTMEM_ADDR +
+ bnx2x_init_fill(bp, TSEM_REG_FAST_MEMORY +
TSTORM_DEF_SB_HOST_STATUS_BLOCK_OFFSET(func), 0,
sizeof(struct tstorm_def_status_block)/4);
- bnx2x_init_fill(bp, USTORM_INTMEM_ADDR +
- USTORM_DEF_SB_HOST_STATUS_BLOCK_OFFSET(func), 0,
- sizeof(struct ustorm_def_status_block)/4);
- bnx2x_init_fill(bp, CSTORM_INTMEM_ADDR +
- CSTORM_DEF_SB_HOST_STATUS_BLOCK_OFFSET(func), 0,
- sizeof(struct cstorm_def_status_block)/4);
- bnx2x_init_fill(bp, XSTORM_INTMEM_ADDR +
+ bnx2x_init_fill(bp, CSEM_REG_FAST_MEMORY +
+ CSTORM_DEF_SB_HOST_STATUS_BLOCK_U_OFFSET(func), 0,
+ sizeof(struct cstorm_def_status_block_u)/4);
+ bnx2x_init_fill(bp, CSEM_REG_FAST_MEMORY +
+ CSTORM_DEF_SB_HOST_STATUS_BLOCK_C_OFFSET(func), 0,
+ sizeof(struct cstorm_def_status_block_c)/4);
+ bnx2x_init_fill(bp, XSEM_REG_FAST_MEMORY +
XSTORM_DEF_SB_HOST_STATUS_BLOCK_OFFSET(func), 0,
sizeof(struct xstorm_def_status_block)/4);
}
@@ -4350,17 +4779,17 @@ static void bnx2x_init_def_sb(struct bnx2x *bp,
u_def_status_block);
def_sb->u_def_status_block.status_block_id = sb_id;
- REG_WR(bp, BAR_USTRORM_INTMEM +
- USTORM_DEF_SB_HOST_SB_ADDR_OFFSET(func), U64_LO(section));
- REG_WR(bp, BAR_USTRORM_INTMEM +
- ((USTORM_DEF_SB_HOST_SB_ADDR_OFFSET(func)) + 4),
+ REG_WR(bp, BAR_CSTRORM_INTMEM +
+ CSTORM_DEF_SB_HOST_SB_ADDR_U_OFFSET(func), U64_LO(section));
+ REG_WR(bp, BAR_CSTRORM_INTMEM +
+ ((CSTORM_DEF_SB_HOST_SB_ADDR_U_OFFSET(func)) + 4),
U64_HI(section));
- REG_WR8(bp, BAR_USTRORM_INTMEM + DEF_USB_FUNC_OFF +
- USTORM_DEF_SB_HOST_STATUS_BLOCK_OFFSET(func), func);
+ REG_WR8(bp, BAR_CSTRORM_INTMEM + DEF_USB_FUNC_OFF +
+ CSTORM_DEF_SB_HOST_STATUS_BLOCK_U_OFFSET(func), func);
for (index = 0; index < HC_USTORM_DEF_SB_NUM_INDICES; index++)
- REG_WR16(bp, BAR_USTRORM_INTMEM +
- USTORM_DEF_SB_HC_DISABLE_OFFSET(func, index), 1);
+ REG_WR16(bp, BAR_CSTRORM_INTMEM +
+ CSTORM_DEF_SB_HC_DISABLE_U_OFFSET(func, index), 1);
/* CSTORM */
section = ((u64)mapping) + offsetof(struct host_def_status_block,
@@ -4368,16 +4797,16 @@ static void bnx2x_init_def_sb(struct bnx2x *bp,
def_sb->c_def_status_block.status_block_id = sb_id;
REG_WR(bp, BAR_CSTRORM_INTMEM +
- CSTORM_DEF_SB_HOST_SB_ADDR_OFFSET(func), U64_LO(section));
+ CSTORM_DEF_SB_HOST_SB_ADDR_C_OFFSET(func), U64_LO(section));
REG_WR(bp, BAR_CSTRORM_INTMEM +
- ((CSTORM_DEF_SB_HOST_SB_ADDR_OFFSET(func)) + 4),
+ ((CSTORM_DEF_SB_HOST_SB_ADDR_C_OFFSET(func)) + 4),
U64_HI(section));
REG_WR8(bp, BAR_CSTRORM_INTMEM + DEF_CSB_FUNC_OFF +
- CSTORM_DEF_SB_HOST_STATUS_BLOCK_OFFSET(func), func);
+ CSTORM_DEF_SB_HOST_STATUS_BLOCK_C_OFFSET(func), func);
for (index = 0; index < HC_CSTORM_DEF_SB_NUM_INDICES; index++)
REG_WR16(bp, BAR_CSTRORM_INTMEM +
- CSTORM_DEF_SB_HC_DISABLE_OFFSET(func, index), 1);
+ CSTORM_DEF_SB_HC_DISABLE_C_OFFSET(func, index), 1);
/* TSTORM */
section = ((u64)mapping) + offsetof(struct host_def_status_block,
@@ -4428,23 +4857,23 @@ static void bnx2x_update_coalesce(struct bnx2x *bp)
int sb_id = bp->fp[i].sb_id;
/* HC_INDEX_U_ETH_RX_CQ_CONS */
- REG_WR8(bp, BAR_USTRORM_INTMEM +
- USTORM_SB_HC_TIMEOUT_OFFSET(port, sb_id,
- U_SB_ETH_RX_CQ_INDEX),
+ REG_WR8(bp, BAR_CSTRORM_INTMEM +
+ CSTORM_SB_HC_TIMEOUT_U_OFFSET(port, sb_id,
+ U_SB_ETH_RX_CQ_INDEX),
bp->rx_ticks/12);
- REG_WR16(bp, BAR_USTRORM_INTMEM +
- USTORM_SB_HC_DISABLE_OFFSET(port, sb_id,
- U_SB_ETH_RX_CQ_INDEX),
+ REG_WR16(bp, BAR_CSTRORM_INTMEM +
+ CSTORM_SB_HC_DISABLE_U_OFFSET(port, sb_id,
+ U_SB_ETH_RX_CQ_INDEX),
(bp->rx_ticks/12) ? 0 : 1);
/* HC_INDEX_C_ETH_TX_CQ_CONS */
REG_WR8(bp, BAR_CSTRORM_INTMEM +
- CSTORM_SB_HC_TIMEOUT_OFFSET(port, sb_id,
- C_SB_ETH_TX_CQ_INDEX),
+ CSTORM_SB_HC_TIMEOUT_C_OFFSET(port, sb_id,
+ C_SB_ETH_TX_CQ_INDEX),
bp->tx_ticks/12);
REG_WR16(bp, BAR_CSTRORM_INTMEM +
- CSTORM_SB_HC_DISABLE_OFFSET(port, sb_id,
- C_SB_ETH_TX_CQ_INDEX),
+ CSTORM_SB_HC_DISABLE_C_OFFSET(port, sb_id,
+ C_SB_ETH_TX_CQ_INDEX),
(bp->tx_ticks/12) ? 0 : 1);
}
}
@@ -4517,6 +4946,9 @@ static void bnx2x_init_rx_rings(struct bnx2x *bp)
fp->rx_cons_sb = BNX2X_RX_SB_INDEX;
fp->rx_bd_cons_sb = BNX2X_RX_SB_BD_INDEX;
+ /* Mark queue as Rx */
+ fp->is_rx_queue = 1;
+
/* "next page" elements initialization */
/* SGE ring */
for (i = 1; i <= NUM_RX_SGE_PAGES; i++) {
@@ -4626,17 +5058,21 @@ static void bnx2x_init_tx_ring(struct bnx2x *bp)
struct bnx2x_fastpath *fp = &bp->fp[j];
for (i = 1; i <= NUM_TX_RINGS; i++) {
- struct eth_tx_bd *tx_bd =
- &fp->tx_desc_ring[TX_DESC_CNT * i - 1];
+ struct eth_tx_next_bd *tx_next_bd =
+ &fp->tx_desc_ring[TX_DESC_CNT * i - 1].next_bd;
- tx_bd->addr_hi =
+ tx_next_bd->addr_hi =
cpu_to_le32(U64_HI(fp->tx_desc_mapping +
BCM_PAGE_SIZE*(i % NUM_TX_RINGS)));
- tx_bd->addr_lo =
+ tx_next_bd->addr_lo =
cpu_to_le32(U64_LO(fp->tx_desc_mapping +
BCM_PAGE_SIZE*(i % NUM_TX_RINGS)));
}
+ fp->tx_db.data.header.header = DOORBELL_HDR_DB_TYPE;
+ fp->tx_db.data.zero_fill1 = 0;
+ fp->tx_db.data.prod = 0;
+
fp->tx_pkt_prod = 0;
fp->tx_pkt_cons = 0;
fp->tx_bd_prod = 0;
@@ -4644,6 +5080,10 @@ static void bnx2x_init_tx_ring(struct bnx2x *bp)
fp->tx_cons_sb = BNX2X_TX_SB_INDEX;
fp->tx_pkt = 0;
}
+
+ /* clean tx statistics */
+ for_each_rx_queue(bp, i)
+ bnx2x_fp(bp, i, tx_pkt) = 0;
}
static void bnx2x_init_sp_ring(struct bnx2x *bp)
@@ -4672,16 +5112,15 @@ static void bnx2x_init_context(struct bnx2x *bp)
{
int i;
- for_each_queue(bp, i) {
+ for_each_rx_queue(bp, i) {
struct eth_context *context = bnx2x_sp(bp, context[i].eth);
struct bnx2x_fastpath *fp = &bp->fp[i];
u8 cl_id = fp->cl_id;
- u8 sb_id = fp->sb_id;
context->ustorm_st_context.common.sb_index_numbers =
BNX2X_RX_SB_INDEX_NUM;
context->ustorm_st_context.common.clientId = cl_id;
- context->ustorm_st_context.common.status_block_id = sb_id;
+ context->ustorm_st_context.common.status_block_id = fp->sb_id;
context->ustorm_st_context.common.flags =
(USTORM_ETH_ST_CONTEXT_CONFIG_ENABLE_MC_ALIGNMENT |
USTORM_ETH_ST_CONTEXT_CONFIG_ENABLE_STATISTICS);
@@ -4697,8 +5136,7 @@ static void bnx2x_init_context(struct bnx2x *bp)
U64_LO(fp->rx_desc_mapping);
if (!fp->disable_tpa) {
context->ustorm_st_context.common.flags |=
- (USTORM_ETH_ST_CONTEXT_CONFIG_ENABLE_TPA |
- USTORM_ETH_ST_CONTEXT_CONFIG_ENABLE_SGE_RING);
+ USTORM_ETH_ST_CONTEXT_CONFIG_ENABLE_TPA;
context->ustorm_st_context.common.sge_buff_size =
(u16)min((u32)SGE_PAGE_SIZE*PAGES_PER_SGE,
(u32)0xffff);
@@ -4706,6 +5144,13 @@ static void bnx2x_init_context(struct bnx2x *bp)
U64_HI(fp->rx_sge_mapping);
context->ustorm_st_context.common.sge_page_base_lo =
U64_LO(fp->rx_sge_mapping);
+
+ context->ustorm_st_context.common.max_sges_for_packet =
+ SGE_PAGE_ALIGN(bp->dev->mtu) >> SGE_PAGE_SHIFT;
+ context->ustorm_st_context.common.max_sges_for_packet =
+ ((context->ustorm_st_context.common.
+ max_sges_for_packet + PAGES_PER_SGE - 1) &
+ (~(PAGES_PER_SGE - 1))) >> PAGES_PER_SGE_SHIFT;
}
context->ustorm_ag_context.cdu_usage =
@@ -4713,24 +5158,27 @@ static void bnx2x_init_context(struct bnx2x *bp)
CDU_REGION_NUMBER_UCM_AG,
ETH_CONNECTION_TYPE);
+ context->xstorm_ag_context.cdu_reserved =
+ CDU_RSRVD_VALUE_TYPE_A(HW_CID(bp, i),
+ CDU_REGION_NUMBER_XCM_AG,
+ ETH_CONNECTION_TYPE);
+ }
+
+ for_each_tx_queue(bp, i) {
+ struct bnx2x_fastpath *fp = &bp->fp[i];
+ struct eth_context *context =
+ bnx2x_sp(bp, context[i - bp->num_rx_queues].eth);
+
+ context->cstorm_st_context.sb_index_number =
+ C_SB_ETH_TX_CQ_INDEX;
+ context->cstorm_st_context.status_block_id = fp->sb_id;
+
context->xstorm_st_context.tx_bd_page_base_hi =
U64_HI(fp->tx_desc_mapping);
context->xstorm_st_context.tx_bd_page_base_lo =
U64_LO(fp->tx_desc_mapping);
- context->xstorm_st_context.db_data_addr_hi =
- U64_HI(fp->tx_prods_mapping);
- context->xstorm_st_context.db_data_addr_lo =
- U64_LO(fp->tx_prods_mapping);
- context->xstorm_st_context.statistics_data = (cl_id |
+ context->xstorm_st_context.statistics_data = (fp->cl_id |
XSTORM_ETH_ST_CONTEXT_STATISTICS_ENABLE);
- context->cstorm_st_context.sb_index_number =
- C_SB_ETH_TX_CQ_INDEX;
- context->cstorm_st_context.status_block_id = sb_id;
-
- context->xstorm_ag_context.cdu_reserved =
- CDU_RSRVD_VALUE_TYPE_A(HW_CID(bp, i),
- CDU_REGION_NUMBER_XCM_AG,
- ETH_CONNECTION_TYPE);
}
}
@@ -4768,18 +5216,6 @@ static void bnx2x_set_client_config(struct bnx2x *bp)
}
#endif
- if (bp->flags & TPA_ENABLE_FLAG) {
- tstorm_client.max_sges_for_packet =
- SGE_PAGE_ALIGN(tstorm_client.mtu) >> SGE_PAGE_SHIFT;
- tstorm_client.max_sges_for_packet =
- ((tstorm_client.max_sges_for_packet +
- PAGES_PER_SGE - 1) & (~(PAGES_PER_SGE - 1))) >>
- PAGES_PER_SGE_SHIFT;
-
- tstorm_client.config_flags |=
- TSTORM_ETH_CLIENT_CONFIG_ENABLE_SGE_RING;
- }
-
for_each_queue(bp, i) {
tstorm_client.statistics_counter_id = bp->fp[i].cl_id;
@@ -4801,7 +5237,14 @@ static void bnx2x_set_storm_rx_mode(struct bnx2x *bp)
int mode = bp->rx_mode;
int mask = (1 << BP_L_ID(bp));
int func = BP_FUNC(bp);
+ int port = BP_PORT(bp);
int i;
+ /* All but management unicast packets should pass to the host as well */
+ u32 llh_mask =
+ NIG_LLH0_BRB1_DRV_MASK_REG_LLH0_BRB1_DRV_MASK_BRCST |
+ NIG_LLH0_BRB1_DRV_MASK_REG_LLH0_BRB1_DRV_MASK_MLCST |
+ NIG_LLH0_BRB1_DRV_MASK_REG_LLH0_BRB1_DRV_MASK_VLAN |
+ NIG_LLH0_BRB1_DRV_MASK_REG_LLH0_BRB1_DRV_MASK_NO_VLAN;
DP(NETIF_MSG_IFUP, "rx mode %d mask 0x%x\n", mode, mask);
@@ -4825,6 +5268,8 @@ static void bnx2x_set_storm_rx_mode(struct bnx2x *bp)
tstorm_mac_filter.ucast_accept_all = mask;
tstorm_mac_filter.mcast_accept_all = mask;
tstorm_mac_filter.bcast_accept_all = mask;
+ /* pass management unicast packets as well */
+ llh_mask |= NIG_LLH0_BRB1_DRV_MASK_REG_LLH0_BRB1_DRV_MASK_UNCST;
break;
default:
@@ -4832,6 +5277,10 @@ static void bnx2x_set_storm_rx_mode(struct bnx2x *bp)
break;
}
+ REG_WR(bp,
+ (port ? NIG_REG_LLH1_BRB1_DRV_MASK : NIG_REG_LLH0_BRB1_DRV_MASK),
+ llh_mask);
+
for (i = 0; i < sizeof(struct tstorm_eth_mac_filter_config)/4; i++) {
REG_WR(bp, BAR_TSTRORM_INTMEM +
TSTORM_MAC_FILTER_CONFIG_OFFSET(func) + i * 4,
@@ -4849,17 +5298,6 @@ static void bnx2x_init_internal_common(struct bnx2x *bp)
{
int i;
- if (bp->flags & TPA_ENABLE_FLAG) {
- struct tstorm_eth_tpa_exist tpa = {0};
-
- tpa.tpa_exist = 1;
-
- REG_WR(bp, BAR_TSTRORM_INTMEM + TSTORM_TPA_EXIST_OFFSET,
- ((u32 *)&tpa)[0]);
- REG_WR(bp, BAR_TSTRORM_INTMEM + TSTORM_TPA_EXIST_OFFSET + 4,
- ((u32 *)&tpa)[1]);
- }
-
/* Zero this manually as its initialization is
currently missing in the initTool */
for (i = 0; i < (USTORM_AGG_DATA_SIZE >> 2); i++)
@@ -4871,53 +5309,14 @@ static void bnx2x_init_internal_port(struct bnx2x *bp)
{
int port = BP_PORT(bp);
- REG_WR(bp, BAR_USTRORM_INTMEM + USTORM_HC_BTR_OFFSET(port), BNX2X_BTR);
- REG_WR(bp, BAR_CSTRORM_INTMEM + CSTORM_HC_BTR_OFFSET(port), BNX2X_BTR);
+ REG_WR(bp,
+ BAR_CSTRORM_INTMEM + CSTORM_HC_BTR_U_OFFSET(port), BNX2X_BTR);
+ REG_WR(bp,
+ BAR_CSTRORM_INTMEM + CSTORM_HC_BTR_C_OFFSET(port), BNX2X_BTR);
REG_WR(bp, BAR_TSTRORM_INTMEM + TSTORM_HC_BTR_OFFSET(port), BNX2X_BTR);
REG_WR(bp, BAR_XSTRORM_INTMEM + XSTORM_HC_BTR_OFFSET(port), BNX2X_BTR);
}
-/* Calculates the sum of vn_min_rates.
- It's needed for further normalizing of the min_rates.
- Returns:
- sum of vn_min_rates.
- or
- 0 - if all the min_rates are 0.
- In the later case fainess algorithm should be deactivated.
- If not all min_rates are zero then those that are zeroes will be set to 1.
- */
-static void bnx2x_calc_vn_weight_sum(struct bnx2x *bp)
-{
- int all_zero = 1;
- int port = BP_PORT(bp);
- int vn;
-
- bp->vn_weight_sum = 0;
- for (vn = VN_0; vn < E1HVN_MAX; vn++) {
- int func = 2*vn + port;
- u32 vn_cfg =
- SHMEM_RD(bp, mf_cfg.func_mf_config[func].config);
- u32 vn_min_rate = ((vn_cfg & FUNC_MF_CFG_MIN_BW_MASK) >>
- FUNC_MF_CFG_MIN_BW_SHIFT) * 100;
-
- /* Skip hidden vns */
- if (vn_cfg & FUNC_MF_CFG_FUNC_HIDE)
- continue;
-
- /* If min rate is zero - set it to 1 */
- if (!vn_min_rate)
- vn_min_rate = DEF_MIN_RATE;
- else
- all_zero = 0;
-
- bp->vn_weight_sum += vn_min_rate;
- }
-
- /* ... only if all min rates are zeros - disable fairness */
- if (all_zero)
- bp->vn_weight_sum = 0;
-}
-
static void bnx2x_init_internal_func(struct bnx2x *bp)
{
struct tstorm_eth_function_common_config tstorm_config = {0};
@@ -4932,6 +5331,12 @@ static void bnx2x_init_internal_func(struct bnx2x *bp)
tstorm_config.config_flags = MULTI_FLAGS(bp);
tstorm_config.rss_result_mask = MULTI_MASK;
}
+
+ /* Enable TPA if needed */
+ if (bp->flags & TPA_ENABLE_FLAG)
+ tstorm_config.config_flags |=
+ TSTORM_ETH_FUNCTION_COMMON_CONFIG_ENABLE_TPA;
+
if (IS_E1HMF(bp))
tstorm_config.config_flags |=
TSTORM_ETH_FUNCTION_COMMON_CONFIG_E1HOV_IN_CAM;
@@ -5043,6 +5448,14 @@ static void bnx2x_init_internal_func(struct bnx2x *bp)
USTORM_CQE_PAGE_BASE_OFFSET(port, fp->cl_id) + 4,
U64_HI(fp->rx_comp_mapping));
+ /* Next page */
+ REG_WR(bp, BAR_USTRORM_INTMEM +
+ USTORM_CQE_PAGE_NEXT_OFFSET(port, fp->cl_id),
+ U64_LO(fp->rx_comp_mapping + BCM_PAGE_SIZE));
+ REG_WR(bp, BAR_USTRORM_INTMEM +
+ USTORM_CQE_PAGE_NEXT_OFFSET(port, fp->cl_id) + 4,
+ U64_HI(fp->rx_comp_mapping + BCM_PAGE_SIZE));
+
REG_WR16(bp, BAR_USTRORM_INTMEM +
USTORM_MAX_AGG_SIZE_OFFSET(port, fp->cl_id),
max_agg_size);
@@ -5153,6 +5566,9 @@ static void bnx2x_nic_init(struct bnx2x *bp, u32 load_code)
fp->index = i;
fp->cl_id = BP_L_ID(bp) + i;
fp->sb_id = fp->cl_id;
+ /* Suitable Rx and Tx SBs are served by the same client */
+ if (i >= bp->num_rx_queues)
+ fp->cl_id -= bp->num_rx_queues;
DP(NETIF_MSG_IFUP,
"queue[%d]: bnx2x_init_sb(%p,%p) cl_id %d sb %d\n",
i, bp, fp->status_blk, fp->cl_id, fp->sb_id);
@@ -5185,6 +5601,11 @@ static void bnx2x_nic_init(struct bnx2x *bp, u32 load_code)
mmiowb();
bnx2x_int_enable(bp);
+
+ /* Check for SPIO5 */
+ bnx2x_attn_int_deasserted0(bp,
+ REG_RD(bp, MISC_REG_AEU_AFTER_INVERT_1_FUNC_0 + BP_PORT(bp)*4) &
+ AEU_INPUTS_ATTN_BITS_SPIO5);
}
/* end of nic init */
@@ -5510,6 +5931,78 @@ static void bnx2x_reset_common(struct bnx2x *bp)
REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR, 0x1403);
}
+static void bnx2x_init_pxp(struct bnx2x *bp)
+{
+ u16 devctl;
+ int r_order, w_order;
+
+ pci_read_config_word(bp->pdev,
+ bp->pcie_cap + PCI_EXP_DEVCTL, &devctl);
+ DP(NETIF_MSG_HW, "read 0x%x from devctl\n", devctl);
+ w_order = ((devctl & PCI_EXP_DEVCTL_PAYLOAD) >> 5);
+ if (bp->mrrs == -1)
+ r_order = ((devctl & PCI_EXP_DEVCTL_READRQ) >> 12);
+ else {
+ DP(NETIF_MSG_HW, "force read order to %d\n", bp->mrrs);
+ r_order = bp->mrrs;
+ }
+
+ bnx2x_init_pxp_arb(bp, r_order, w_order);
+}
+
+static void bnx2x_setup_fan_failure_detection(struct bnx2x *bp)
+{
+ u32 val;
+ u8 port;
+ u8 is_required = 0;
+
+ val = SHMEM_RD(bp, dev_info.shared_hw_config.config2) &
+ SHARED_HW_CFG_FAN_FAILURE_MASK;
+
+ if (val == SHARED_HW_CFG_FAN_FAILURE_ENABLED)
+ is_required = 1;
+
+ /*
+ * The fan failure mechanism is usually related to the PHY type since
+ * the power consumption of the board is affected by the PHY. Currently,
+ * fan is required for most designs with SFX7101, BCM8727 and BCM8481.
+ */
+ else if (val == SHARED_HW_CFG_FAN_FAILURE_PHY_TYPE)
+ for (port = PORT_0; port < PORT_MAX; port++) {
+ u32 phy_type =
+ SHMEM_RD(bp, dev_info.port_hw_config[port].
+ external_phy_config) &
+ PORT_HW_CFG_XGXS_EXT_PHY_TYPE_MASK;
+ is_required |=
+ ((phy_type ==
+ PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101) ||
+ (phy_type ==
+ PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727) ||
+ (phy_type ==
+ PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481));
+ }
+
+ DP(NETIF_MSG_HW, "fan detection setting: %d\n", is_required);
+
+ if (is_required == 0)
+ return;
+
+ /* Fan failure is indicated by SPIO 5 */
+ bnx2x_set_spio(bp, MISC_REGISTERS_SPIO_5,
+ MISC_REGISTERS_SPIO_INPUT_HI_Z);
+
+ /* set to active low mode */
+ val = REG_RD(bp, MISC_REG_SPIO_INT);
+ val |= ((1 << MISC_REGISTERS_SPIO_5) <<
+ MISC_REGISTERS_SPIO_INT_OLD_SET_POS);
+ REG_WR(bp, MISC_REG_SPIO_INT, val);
+
+ /* enable interrupt to signal the IGU */
+ val = REG_RD(bp, MISC_REG_SPIO_EVENT_EN);
+ val |= (1 << MISC_REGISTERS_SPIO_5);
+ REG_WR(bp, MISC_REG_SPIO_EVENT_EN, val);
+}
+
static int bnx2x_init_common(struct bnx2x *bp)
{
u32 val, i;
@@ -5626,10 +6119,10 @@ static int bnx2x_init_common(struct bnx2x *bp)
bnx2x_init_block(bp, USDM_BLOCK, COMMON_STAGE);
bnx2x_init_block(bp, XSDM_BLOCK, COMMON_STAGE);
- bnx2x_init_fill(bp, TSTORM_INTMEM_ADDR, 0, STORM_INTMEM_SIZE(bp));
- bnx2x_init_fill(bp, USTORM_INTMEM_ADDR, 0, STORM_INTMEM_SIZE(bp));
- bnx2x_init_fill(bp, CSTORM_INTMEM_ADDR, 0, STORM_INTMEM_SIZE(bp));
- bnx2x_init_fill(bp, XSTORM_INTMEM_ADDR, 0, STORM_INTMEM_SIZE(bp));
+ bnx2x_init_fill(bp, TSEM_REG_FAST_MEMORY, 0, STORM_INTMEM_SIZE(bp));
+ bnx2x_init_fill(bp, USEM_REG_FAST_MEMORY, 0, STORM_INTMEM_SIZE(bp));
+ bnx2x_init_fill(bp, CSEM_REG_FAST_MEMORY, 0, STORM_INTMEM_SIZE(bp));
+ bnx2x_init_fill(bp, XSEM_REG_FAST_MEMORY, 0, STORM_INTMEM_SIZE(bp));
bnx2x_init_block(bp, TSEM_BLOCK, COMMON_STAGE);
bnx2x_init_block(bp, USEM_BLOCK, COMMON_STAGE);
@@ -5662,11 +6155,6 @@ static int bnx2x_init_common(struct bnx2x *bp)
bnx2x_init_block(bp, CDU_BLOCK, COMMON_STAGE);
val = (4 << 24) + (0 << 12) + 1024;
REG_WR(bp, CDU_REG_CDU_GLOBAL_PARAMS, val);
- if (CHIP_IS_E1(bp)) {
- /* !!! fix pxp client crdit until excel update */
- REG_WR(bp, CDU_REG_CDU_DEBUG, 0x264);
- REG_WR(bp, CDU_REG_CDU_DEBUG, 0);
- }
bnx2x_init_block(bp, CFC_BLOCK, COMMON_STAGE);
REG_WR(bp, CFC_REG_INIT_REG, 0x7FF);
@@ -5679,19 +6167,14 @@ static int bnx2x_init_common(struct bnx2x *bp)
bnx2x_init_block(bp, HC_BLOCK, COMMON_STAGE);
bnx2x_init_block(bp, MISC_AEU_BLOCK, COMMON_STAGE);
- /* PXPCS COMMON comes here */
bnx2x_init_block(bp, PXPCS_BLOCK, COMMON_STAGE);
/* Reset PCIE errors for debug */
REG_WR(bp, 0x2814, 0xffffffff);
REG_WR(bp, 0x3820, 0xffffffff);
- /* EMAC0 COMMON comes here */
bnx2x_init_block(bp, EMAC0_BLOCK, COMMON_STAGE);
- /* EMAC1 COMMON comes here */
bnx2x_init_block(bp, EMAC1_BLOCK, COMMON_STAGE);
- /* DBU COMMON comes here */
bnx2x_init_block(bp, DBU_BLOCK, COMMON_STAGE);
- /* DBG COMMON comes here */
bnx2x_init_block(bp, DBG_BLOCK, COMMON_STAGE);
bnx2x_init_block(bp, NIG_BLOCK, COMMON_STAGE);
@@ -5736,30 +6219,16 @@ static int bnx2x_init_common(struct bnx2x *bp)
case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072:
case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726:
+ case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727:
bp->port.need_hw_lock = 1;
break;
- case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101:
- /* Fan failure is indicated by SPIO 5 */
- bnx2x_set_spio(bp, MISC_REGISTERS_SPIO_5,
- MISC_REGISTERS_SPIO_INPUT_HI_Z);
-
- /* set to active low mode */
- val = REG_RD(bp, MISC_REG_SPIO_INT);
- val |= ((1 << MISC_REGISTERS_SPIO_5) <<
- MISC_REGISTERS_SPIO_INT_OLD_SET_POS);
- REG_WR(bp, MISC_REG_SPIO_INT, val);
-
- /* enable interrupt to signal the IGU */
- val = REG_RD(bp, MISC_REG_SPIO_EVENT_EN);
- val |= (1 << MISC_REGISTERS_SPIO_5);
- REG_WR(bp, MISC_REG_SPIO_EVENT_EN, val);
- break;
-
default:
break;
}
+ bnx2x_setup_fan_failure_detection(bp);
+
/* clear PXP2 attentions */
REG_RD(bp, PXP2_REG_PXP2_INT_STS_CLR_0);
@@ -5786,10 +6255,12 @@ static int bnx2x_init_port(struct bnx2x *bp)
REG_WR(bp, NIG_REG_MASK_INTERRUPT_PORT0 + port*4, 0);
- /* Port PXP comes here */
bnx2x_init_block(bp, PXP_BLOCK, init_stage);
- /* Port PXP2 comes here */
bnx2x_init_block(bp, PXP2_BLOCK, init_stage);
+
+ bnx2x_init_block(bp, TCM_BLOCK, init_stage);
+ bnx2x_init_block(bp, UCM_BLOCK, init_stage);
+ bnx2x_init_block(bp, CCM_BLOCK, init_stage);
#ifdef BCM_ISCSI
/* Port0 1
* Port1 385 */
@@ -5815,17 +6286,14 @@ static int bnx2x_init_port(struct bnx2x *bp)
REG_WR_DMAE(bp, PXP2_REG_RQ_ONCHIP_AT + i*8, wb_write, 2);
REG_WR(bp, PXP2_REG_PSWRQ_SRC0_L2P + func*4, PXP_ONE_ILT(i));
#endif
- /* Port CMs come here */
bnx2x_init_block(bp, XCM_BLOCK, init_stage);
- /* Port QM comes here */
#ifdef BCM_ISCSI
REG_WR(bp, TM_REG_LIN0_SCAN_TIME + func*4, 1024/64*20);
REG_WR(bp, TM_REG_LIN0_MAX_ACTIVE_CID + func*4, 31);
bnx2x_init_block(bp, TIMERS_BLOCK, init_stage);
#endif
- /* Port DQ comes here */
bnx2x_init_block(bp, DQ_BLOCK, init_stage);
bnx2x_init_block(bp, BRB1_BLOCK, init_stage);
@@ -5852,15 +6320,11 @@ static int bnx2x_init_port(struct bnx2x *bp)
REG_WR(bp, BRB1_REG_PAUSE_HIGH_THRESHOLD_0 + port*4, high);
- /* Port PRS comes here */
bnx2x_init_block(bp, PRS_BLOCK, init_stage);
- /* Port TSDM comes here */
+
bnx2x_init_block(bp, TSDM_BLOCK, init_stage);
- /* Port CSDM comes here */
bnx2x_init_block(bp, CSDM_BLOCK, init_stage);
- /* Port USDM comes here */
bnx2x_init_block(bp, USDM_BLOCK, init_stage);
- /* Port XSDM comes here */
bnx2x_init_block(bp, XSDM_BLOCK, init_stage);
bnx2x_init_block(bp, TSEM_BLOCK, init_stage);
@@ -5868,9 +6332,7 @@ static int bnx2x_init_port(struct bnx2x *bp)
bnx2x_init_block(bp, CSEM_BLOCK, init_stage);
bnx2x_init_block(bp, XSEM_BLOCK, init_stage);
- /* Port UPB comes here */
bnx2x_init_block(bp, UPB_BLOCK, init_stage);
- /* Port XPB comes here */
bnx2x_init_block(bp, XPB_BLOCK, init_stage);
bnx2x_init_block(bp, PBF_BLOCK, init_stage);
@@ -5900,11 +6362,8 @@ static int bnx2x_init_port(struct bnx2x *bp)
REG_WR_DMAE(bp, SRC_REG_LASTFREE0 + func*4, wb_write, 2);
REG_WR(bp, SRC_REG_NUMBER_HASH_BITS0 + func*4, 10);
- /* Port SRCH comes here */
#endif
- /* Port CDU comes here */
bnx2x_init_block(bp, CDU_BLOCK, init_stage);
- /* Port CFC comes here */
bnx2x_init_block(bp, CFC_BLOCK, init_stage);
if (CHIP_IS_E1(bp)) {
@@ -5921,15 +6380,10 @@ static int bnx2x_init_port(struct bnx2x *bp)
REG_WR(bp, MISC_REG_AEU_MASK_ATTN_FUNC_0 + port*4,
(IS_E1HMF(bp) ? 0xF7 : 0x7));
- /* Port PXPCS comes here */
bnx2x_init_block(bp, PXPCS_BLOCK, init_stage);
- /* Port EMAC0 comes here */
bnx2x_init_block(bp, EMAC0_BLOCK, init_stage);
- /* Port EMAC1 comes here */
bnx2x_init_block(bp, EMAC1_BLOCK, init_stage);
- /* Port DBU comes here */
bnx2x_init_block(bp, DBU_BLOCK, init_stage);
- /* Port DBG comes here */
bnx2x_init_block(bp, DBG_BLOCK, init_stage);
bnx2x_init_block(bp, NIG_BLOCK, init_stage);
@@ -5941,9 +6395,6 @@ static int bnx2x_init_port(struct bnx2x *bp)
REG_WR(bp, NIG_REG_LLH0_BRB1_DRV_MASK_MF + port*4,
(IS_E1HMF(bp) ? 0x1 : 0x2));
- /* support pause requests from USDM, TSDM and BRB */
- REG_WR(bp, NIG_REG_LLFC_EGRESS_SRC_ENABLE_0 + port*4, 0x7);
-
{
REG_WR(bp, NIG_REG_LLFC_ENABLE_0 + port*4, 0);
REG_WR(bp, NIG_REG_LLFC_OUT_EN_0 + port*4, 0);
@@ -5951,9 +6402,7 @@ static int bnx2x_init_port(struct bnx2x *bp)
}
}
- /* Port MCP comes here */
bnx2x_init_block(bp, MCP_BLOCK, init_stage);
- /* Port DMAE comes here */
bnx2x_init_block(bp, DMAE_BLOCK, init_stage);
switch (XGXS_EXT_PHY_TYPE(bp->link_params.ext_phy_config)) {
@@ -5989,10 +6438,15 @@ static int bnx2x_init_port(struct bnx2x *bp)
break;
case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101:
+ case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727:
/* add SPIO 5 to group 0 */
- val = REG_RD(bp, MISC_REG_AEU_ENABLE1_FUNC_0_OUT_0);
+ {
+ u32 reg_addr = (port ? MISC_REG_AEU_ENABLE1_FUNC_1_OUT_0 :
+ MISC_REG_AEU_ENABLE1_FUNC_0_OUT_0);
+ val = REG_RD(bp, reg_addr);
val |= AEU_INPUTS_ATTN_BITS_SPIO5;
- REG_WR(bp, MISC_REG_AEU_ENABLE1_FUNC_0_OUT_0, val);
+ REG_WR(bp, reg_addr, val);
+ }
break;
default:
@@ -6057,9 +6511,15 @@ static int bnx2x_init_func(struct bnx2x *bp)
if (CHIP_IS_E1H(bp)) {
- for (i = 0; i < 9; i++)
- bnx2x_init_block(bp,
- cm_blocks[i], FUNC0_STAGE + func);
+ bnx2x_init_block(bp, MISC_BLOCK, FUNC0_STAGE + func);
+ bnx2x_init_block(bp, TCM_BLOCK, FUNC0_STAGE + func);
+ bnx2x_init_block(bp, UCM_BLOCK, FUNC0_STAGE + func);
+ bnx2x_init_block(bp, CCM_BLOCK, FUNC0_STAGE + func);
+ bnx2x_init_block(bp, XCM_BLOCK, FUNC0_STAGE + func);
+ bnx2x_init_block(bp, TSEM_BLOCK, FUNC0_STAGE + func);
+ bnx2x_init_block(bp, USEM_BLOCK, FUNC0_STAGE + func);
+ bnx2x_init_block(bp, CSEM_BLOCK, FUNC0_STAGE + func);
+ bnx2x_init_block(bp, XSEM_BLOCK, FUNC0_STAGE + func);
REG_WR(bp, NIG_REG_LLH0_FUNC_EN + port*8, 1);
REG_WR(bp, NIG_REG_LLH0_FUNC_VLAN_ID + port*8, bp->e1hov);
@@ -6090,7 +6550,9 @@ static int bnx2x_init_hw(struct bnx2x *bp, u32 load_code)
bp->dmae_ready = 0;
mutex_init(&bp->dmae_mutex);
- bnx2x_gunzip_init(bp);
+ rc = bnx2x_gunzip_init(bp);
+ if (rc)
+ return rc;
switch (load_code) {
case FW_MSG_CODE_DRV_LOAD_COMMON:
@@ -6124,11 +6586,8 @@ static int bnx2x_init_hw(struct bnx2x *bp, u32 load_code)
bp->fw_drv_pulse_wr_seq =
(SHMEM_RD(bp, func_mb[func].drv_pulse_mb) &
DRV_PULSE_SEQ_MASK);
- bp->func_stx = SHMEM_RD(bp, func_mb[func].fw_mb_param);
- DP(BNX2X_MSG_MCP, "drv_pulse 0x%x func_stx 0x%x\n",
- bp->fw_drv_pulse_wr_seq, bp->func_stx);
- } else
- bp->func_stx = 0;
+ DP(BNX2X_MSG_MCP, "drv_pulse 0x%x\n", bp->fw_drv_pulse_wr_seq);
+ }
/* this needs to be done before gunzip end */
bnx2x_zero_def_sb(bp);
@@ -6141,44 +6600,6 @@ init_hw_err:
return rc;
}
-/* send the MCP a request, block until there is a reply */
-static u32 bnx2x_fw_command(struct bnx2x *bp, u32 command)
-{
- int func = BP_FUNC(bp);
- u32 seq = ++bp->fw_seq;
- u32 rc = 0;
- u32 cnt = 1;
- u8 delay = CHIP_REV_IS_SLOW(bp) ? 100 : 10;
-
- SHMEM_WR(bp, func_mb[func].drv_mb_header, (command | seq));
- DP(BNX2X_MSG_MCP, "wrote command (%x) to FW MB\n", (command | seq));
-
- do {
- /* let the FW do it's magic ... */
- msleep(delay);
-
- rc = SHMEM_RD(bp, func_mb[func].fw_mb_header);
-
- /* Give the FW up to 2 second (200*10ms) */
- } while ((seq != (rc & FW_MSG_SEQ_NUMBER_MASK)) && (cnt++ < 200));
-
- DP(BNX2X_MSG_MCP, "[after %d ms] read (%x) seq is (%x) from FW MB\n",
- cnt*delay, rc, seq);
-
- /* is this a reply to our command? */
- if (seq == (rc & FW_MSG_SEQ_NUMBER_MASK)) {
- rc &= FW_MSG_CODE_MASK;
-
- } else {
- /* FW BUG! */
- BNX2X_ERR("FW failed to respond!\n");
- bnx2x_fw_dump(bp);
- rc = 0;
- }
-
- return rc;
-}
-
static void bnx2x_free_mem(struct bnx2x *bp)
{
@@ -6208,8 +6629,7 @@ static void bnx2x_free_mem(struct bnx2x *bp)
/* status blocks */
BNX2X_PCI_FREE(bnx2x_fp(bp, i, status_blk),
bnx2x_fp(bp, i, status_blk_mapping),
- sizeof(struct host_status_block) +
- sizeof(struct eth_tx_db_data));
+ sizeof(struct host_status_block));
}
/* Rx */
for_each_rx_queue(bp, i) {
@@ -6238,7 +6658,7 @@ static void bnx2x_free_mem(struct bnx2x *bp)
BNX2X_FREE(bnx2x_fp(bp, i, tx_buf_ring));
BNX2X_PCI_FREE(bnx2x_fp(bp, i, tx_desc_ring),
bnx2x_fp(bp, i, tx_desc_mapping),
- sizeof(struct eth_tx_bd) * NUM_TX_BD);
+ sizeof(union eth_tx_bd_types) * NUM_TX_BD);
}
/* end of fastpath */
@@ -6289,8 +6709,7 @@ static int bnx2x_alloc_mem(struct bnx2x *bp)
/* status blocks */
BNX2X_PCI_ALLOC(bnx2x_fp(bp, i, status_blk),
&bnx2x_fp(bp, i, status_blk_mapping),
- sizeof(struct host_status_block) +
- sizeof(struct eth_tx_db_data));
+ sizeof(struct host_status_block));
}
/* Rx */
for_each_rx_queue(bp, i) {
@@ -6317,19 +6736,12 @@ static int bnx2x_alloc_mem(struct bnx2x *bp)
/* Tx */
for_each_tx_queue(bp, i) {
- bnx2x_fp(bp, i, hw_tx_prods) =
- (void *)(bnx2x_fp(bp, i, status_blk) + 1);
-
- bnx2x_fp(bp, i, tx_prods_mapping) =
- bnx2x_fp(bp, i, status_blk_mapping) +
- sizeof(struct host_status_block);
-
/* fastpath tx rings: tx_buf tx_desc */
BNX2X_ALLOC(bnx2x_fp(bp, i, tx_buf_ring),
sizeof(struct sw_tx_bd) * NUM_TX_BD);
BNX2X_PCI_ALLOC(bnx2x_fp(bp, i, tx_desc_ring),
&bnx2x_fp(bp, i, tx_desc_mapping),
- sizeof(struct eth_tx_bd) * NUM_TX_BD);
+ sizeof(union eth_tx_bd_types) * NUM_TX_BD);
}
/* end of fastpath */
@@ -6506,7 +6918,12 @@ static int bnx2x_req_msix_irqs(struct bnx2x *bp)
for_each_queue(bp, i) {
struct bnx2x_fastpath *fp = &bp->fp[i];
- sprintf(fp->name, "%s.fp%d", bp->dev->name, i);
+ if (i < bp->num_rx_queues)
+ sprintf(fp->name, "%s-rx-%d", bp->dev->name, i);
+ else
+ sprintf(fp->name, "%s-tx-%d",
+ bp->dev->name, i - bp->num_rx_queues);
+
rc = request_irq(bp->msix_table[i + offset].vector,
bnx2x_msix_fp_int, 0, fp->name, fp);
if (rc) {
@@ -6519,16 +6936,11 @@ static int bnx2x_req_msix_irqs(struct bnx2x *bp)
}
i = BNX2X_NUM_QUEUES(bp);
- if (is_multi(bp))
- printk(KERN_INFO PFX
- "%s: using MSI-X IRQs: sp %d fp %d - %d\n",
- bp->dev->name, bp->msix_table[0].vector,
- bp->msix_table[offset].vector,
- bp->msix_table[offset + i - 1].vector);
- else
- printk(KERN_INFO PFX "%s: using MSI-X IRQs: sp %d fp %d\n",
- bp->dev->name, bp->msix_table[0].vector,
- bp->msix_table[offset + i - 1].vector);
+ printk(KERN_INFO PFX "%s: using MSI-X IRQs: sp %d fp[%d] %d"
+ " ... fp[%d] %d\n",
+ bp->dev->name, bp->msix_table[0].vector,
+ 0, bp->msix_table[offset].vector,
+ i - 1, bp->msix_table[offset + i - 1].vector);
return 0;
}
@@ -6583,7 +6995,12 @@ static void bnx2x_napi_disable(struct bnx2x *bp)
static void bnx2x_netif_start(struct bnx2x *bp)
{
- if (atomic_dec_and_test(&bp->intr_sem)) {
+ int intr_sem;
+
+ intr_sem = atomic_dec_and_test(&bp->intr_sem);
+ smp_wmb(); /* Ensure that bp->intr_sem update is SMP-safe */
+
+ if (intr_sem) {
if (netif_running(bp->dev)) {
bnx2x_napi_enable(bp);
bnx2x_int_enable(bp);
@@ -6631,7 +7048,8 @@ static void bnx2x_set_mac_addr_e1(struct bnx2x *bp, int set)
config->config_table[0].target_table_entry.flags = 0;
else
CAM_INVALIDATE(config->config_table[0]);
- config->config_table[0].target_table_entry.client_id = 0;
+ config->config_table[0].target_table_entry.clients_bit_vector =
+ cpu_to_le32(1 << BP_L_ID(bp));
config->config_table[0].target_table_entry.vlan_id = 0;
DP(NETIF_MSG_IFUP, "%s MAC (%04x:%04x:%04x)\n",
@@ -6650,7 +7068,8 @@ static void bnx2x_set_mac_addr_e1(struct bnx2x *bp, int set)
TSTORM_CAM_TARGET_TABLE_ENTRY_BROADCAST;
else
CAM_INVALIDATE(config->config_table[1]);
- config->config_table[1].target_table_entry.client_id = 0;
+ config->config_table[1].target_table_entry.clients_bit_vector =
+ cpu_to_le32(1 << BP_L_ID(bp));
config->config_table[1].target_table_entry.vlan_id = 0;
bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_SET_MAC, 0,
@@ -6663,11 +7082,6 @@ static void bnx2x_set_mac_addr_e1h(struct bnx2x *bp, int set)
struct mac_configuration_cmd_e1h *config =
(struct mac_configuration_cmd_e1h *)bnx2x_sp(bp, mac_config);
- if (set && (bp->state != BNX2X_STATE_OPEN)) {
- DP(NETIF_MSG_IFUP, "state is %x, returning\n", bp->state);
- return;
- }
-
/* CAM allocation for E1H
* unicasts: by func number
* multicast: 20+FUNC*20, 20 each
@@ -6684,7 +7098,8 @@ static void bnx2x_set_mac_addr_e1h(struct bnx2x *bp, int set)
swab16(*(u16 *)&bp->dev->dev_addr[2]);
config->config_table[0].lsb_mac_addr =
swab16(*(u16 *)&bp->dev->dev_addr[4]);
- config->config_table[0].client_id = BP_L_ID(bp);
+ config->config_table[0].clients_bit_vector =
+ cpu_to_le32(1 << BP_L_ID(bp));
config->config_table[0].vlan_id = 0;
config->config_table[0].e1hov_id = cpu_to_le16(bp->e1hov);
if (set)
@@ -6734,6 +7149,9 @@ static int bnx2x_wait_ramrod(struct bnx2x *bp, int state, int idx,
}
msleep(1);
+
+ if (bp->panic)
+ return -EIO;
}
/* timeout! */
@@ -6781,67 +7199,111 @@ static int bnx2x_setup_multi(struct bnx2x *bp, int index)
static int bnx2x_poll(struct napi_struct *napi, int budget);
-static void bnx2x_set_int_mode(struct bnx2x *bp)
+static void bnx2x_set_int_mode_msix(struct bnx2x *bp, int *num_rx_queues_out,
+ int *num_tx_queues_out)
+{
+ int _num_rx_queues = 0, _num_tx_queues = 0;
+
+ switch (bp->multi_mode) {
+ case ETH_RSS_MODE_DISABLED:
+ _num_rx_queues = 1;
+ _num_tx_queues = 1;
+ break;
+
+ case ETH_RSS_MODE_REGULAR:
+ if (num_rx_queues)
+ _num_rx_queues = min_t(u32, num_rx_queues,
+ BNX2X_MAX_QUEUES(bp));
+ else
+ _num_rx_queues = min_t(u32, num_online_cpus(),
+ BNX2X_MAX_QUEUES(bp));
+
+ if (num_tx_queues)
+ _num_tx_queues = min_t(u32, num_tx_queues,
+ BNX2X_MAX_QUEUES(bp));
+ else
+ _num_tx_queues = min_t(u32, num_online_cpus(),
+ BNX2X_MAX_QUEUES(bp));
+
+ /* There must be not more Tx queues than Rx queues */
+ if (_num_tx_queues > _num_rx_queues) {
+ BNX2X_ERR("number of tx queues (%d) > "
+ "number of rx queues (%d)"
+ " defaulting to %d\n",
+ _num_tx_queues, _num_rx_queues,
+ _num_rx_queues);
+ _num_tx_queues = _num_rx_queues;
+ }
+ break;
+
+
+ default:
+ _num_rx_queues = 1;
+ _num_tx_queues = 1;
+ break;
+ }
+
+ *num_rx_queues_out = _num_rx_queues;
+ *num_tx_queues_out = _num_tx_queues;
+}
+
+static int bnx2x_set_int_mode(struct bnx2x *bp)
{
- int num_queues;
+ int rc = 0;
switch (int_mode) {
case INT_MODE_INTx:
case INT_MODE_MSI:
- num_queues = 1;
- bp->num_rx_queues = num_queues;
- bp->num_tx_queues = num_queues;
- DP(NETIF_MSG_IFUP,
- "set number of queues to %d\n", num_queues);
+ bp->num_rx_queues = 1;
+ bp->num_tx_queues = 1;
+ DP(NETIF_MSG_IFUP, "set number of queues to 1\n");
break;
case INT_MODE_MSIX:
default:
- if (bp->multi_mode == ETH_RSS_MODE_REGULAR)
- num_queues = min_t(u32, num_online_cpus(),
- BNX2X_MAX_QUEUES(bp));
- else
- num_queues = 1;
- bp->num_rx_queues = num_queues;
- bp->num_tx_queues = num_queues;
- DP(NETIF_MSG_IFUP, "set number of rx queues to %d"
- " number of tx queues to %d\n",
+ /* Set interrupt mode according to bp->multi_mode value */
+ bnx2x_set_int_mode_msix(bp, &bp->num_rx_queues,
+ &bp->num_tx_queues);
+
+ DP(NETIF_MSG_IFUP, "set number of queues to: rx %d tx %d\n",
bp->num_rx_queues, bp->num_tx_queues);
+
/* if we can't use MSI-X we only need one fp,
* so try to enable MSI-X with the requested number of fp's
* and fallback to MSI or legacy INTx with one fp
*/
- if (bnx2x_enable_msix(bp)) {
+ rc = bnx2x_enable_msix(bp);
+ if (rc) {
/* failed to enable MSI-X */
- num_queues = 1;
- bp->num_rx_queues = num_queues;
- bp->num_tx_queues = num_queues;
if (bp->multi_mode)
BNX2X_ERR("Multi requested but failed to "
- "enable MSI-X set number of "
- "queues to %d\n", num_queues);
+ "enable MSI-X (rx %d tx %d), "
+ "set number of queues to 1\n",
+ bp->num_rx_queues, bp->num_tx_queues);
+ bp->num_rx_queues = 1;
+ bp->num_tx_queues = 1;
}
break;
}
bp->dev->real_num_tx_queues = bp->num_tx_queues;
+ return rc;
}
-static void bnx2x_set_rx_mode(struct net_device *dev);
/* must be called with rtnl_lock */
static int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
{
u32 load_code;
- int i, rc = 0;
+ int i, rc;
+
#ifdef BNX2X_STOP_ON_ERROR
- DP(NETIF_MSG_IFUP, "enter load_mode %d\n", load_mode);
if (unlikely(bp->panic))
return -EPERM;
#endif
bp->state = BNX2X_STATE_OPENING_WAIT4_LOAD;
- bnx2x_set_int_mode(bp);
+ rc = bnx2x_set_int_mode(bp);
if (bnx2x_alloc_mem(bp))
return -ENOMEM;
@@ -6854,17 +7316,6 @@ static int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
netif_napi_add(bp->dev, &bnx2x_fp(bp, i, napi),
bnx2x_poll, 128);
-#ifdef BNX2X_STOP_ON_ERROR
- for_each_rx_queue(bp, i) {
- struct bnx2x_fastpath *fp = &bp->fp[i];
-
- fp->poll_no_work = 0;
- fp->poll_calls = 0;
- fp->poll_max_calls = 0;
- fp->poll_complete = 0;
- fp->poll_exit = 0;
- }
-#endif
bnx2x_napi_enable(bp);
if (bp->flags & USING_MSIX_FLAG) {
@@ -6874,6 +7325,8 @@ static int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
goto load_error1;
}
} else {
+ /* Fall to INTx if failed to enable MSI-X due to lack of
+ memory (in bnx2x_set_int_mode()) */
if ((rc != -ENOMEM) && (int_mode != INT_MODE_INTx))
bnx2x_enable_msi(bp);
bnx2x_ack_int(bp);
@@ -6942,6 +7395,12 @@ static int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
/* Setup NIC internals and enable interrupts */
bnx2x_nic_init(bp, load_code);
+ if ((load_code == FW_MSG_CODE_DRV_LOAD_COMMON) &&
+ (bp->common.shmem2_base))
+ SHMEM2_WR(bp, dcc_support,
+ (SHMEM_DCC_SUPPORT_DISABLE_ENABLE_PF_TLV |
+ SHMEM_DCC_SUPPORT_BANDWIDTH_ALLOCATION_TLV));
+
/* Send LOAD_DONE command to MCP */
if (!BP_NOMCP(bp)) {
load_code = bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_DONE);
@@ -6957,7 +7416,12 @@ static int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
rc = bnx2x_setup_leading(bp);
if (rc) {
BNX2X_ERR("Setup leading failed!\n");
+#ifndef BNX2X_STOP_ON_ERROR
goto load_error3;
+#else
+ bp->panic = 1;
+ return -EBUSY;
+#endif
}
if (CHIP_IS_E1H(bp))
@@ -6966,17 +7430,18 @@ static int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
bp->state = BNX2X_STATE_DISABLED;
}
- if (bp->state == BNX2X_STATE_OPEN)
+ if (bp->state == BNX2X_STATE_OPEN) {
for_each_nondefault_queue(bp, i) {
rc = bnx2x_setup_multi(bp, i);
if (rc)
goto load_error3;
}
- if (CHIP_IS_E1(bp))
- bnx2x_set_mac_addr_e1(bp, 1);
- else
- bnx2x_set_mac_addr_e1h(bp, 1);
+ if (CHIP_IS_E1(bp))
+ bnx2x_set_mac_addr_e1(bp, 1);
+ else
+ bnx2x_set_mac_addr_e1h(bp, 1);
+ }
if (bp->port.pmf)
bnx2x_initial_phy_init(bp, load_mode);
@@ -6984,14 +7449,18 @@ static int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
/* Start fast path */
switch (load_mode) {
case LOAD_NORMAL:
- /* Tx queue should be only reenabled */
- netif_tx_wake_all_queues(bp->dev);
+ if (bp->state == BNX2X_STATE_OPEN) {
+ /* Tx queue should be only reenabled */
+ netif_tx_wake_all_queues(bp->dev);
+ }
/* Initialize the receive filter. */
bnx2x_set_rx_mode(bp->dev);
break;
case LOAD_OPEN:
netif_tx_start_all_queues(bp->dev);
+ if (bp->state != BNX2X_STATE_OPEN)
+ netif_tx_disable(bp->dev);
/* Initialize the receive filter. */
bnx2x_set_rx_mode(bp->dev);
break;
@@ -7190,9 +7659,11 @@ static int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode)
bp->state = BNX2X_STATE_CLOSING_WAIT4_HALT;
+ /* Set "drop all" */
bp->rx_mode = BNX2X_RX_MODE_NONE;
bnx2x_set_storm_rx_mode(bp);
+ /* Disable HW interrupts, NAPI and Tx */
bnx2x_netif_stop(bp, 1);
del_timer_sync(&bp->timer);
@@ -7256,17 +7727,17 @@ static int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode)
for (i = 0; i < MC_HASH_SIZE; i++)
REG_WR(bp, MC_HASH_OFFSET(bp, i), 0);
+
+ REG_WR(bp, MISC_REG_E1HMF_MODE, 0);
}
if (unload_mode == UNLOAD_NORMAL)
reset_code = DRV_MSG_CODE_UNLOAD_REQ_WOL_DIS;
- else if (bp->flags & NO_WOL_FLAG) {
+ else if (bp->flags & NO_WOL_FLAG)
reset_code = DRV_MSG_CODE_UNLOAD_REQ_WOL_MCP;
- if (CHIP_IS_E1H(bp))
- REG_WR(bp, MISC_REG_E1HMF_MODE, 0);
- } else if (bp->wol) {
+ else if (bp->wol) {
u32 emac_base = port ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
u8 *mac_addr = bp->dev->dev_addr;
u32 val;
@@ -7569,8 +8040,10 @@ static void __devinit bnx2x_get_common_hwinfo(struct bnx2x *bp)
bp->common.flash_size, bp->common.flash_size);
bp->common.shmem_base = REG_RD(bp, MISC_REG_SHARED_MEM_ADDR);
+ bp->common.shmem2_base = REG_RD(bp, MISC_REG_GENERIC_CR_0);
bp->link_params.shmem_base = bp->common.shmem_base;
- BNX2X_DEV_INFO("shmem offset is 0x%x\n", bp->common.shmem_base);
+ BNX2X_DEV_INFO("shmem offset 0x%x shmem2 offset 0x%x\n",
+ bp->common.shmem_base, bp->common.shmem2_base);
if (!bp->common.shmem_base ||
(bp->common.shmem_base < 0xA0000) ||
@@ -7610,6 +8083,9 @@ static void __devinit bnx2x_get_common_hwinfo(struct bnx2x *bp)
BNX2X_ERR("This driver needs bc_ver %X but found %X,"
" please upgrade BC\n", BNX2X_BC_VER, val);
}
+ bp->link_params.feature_config_flags |=
+ (val >= REQ_BC_VER_4_VRFY_OPT_MDL) ?
+ FEATURE_CONFIG_BC_SUPPORTS_OPT_MDL_VRFY : 0;
if (BP_E1HVN(bp) == 0) {
pci_read_config_word(bp->pdev, bp->pm_cap + PCI_PM_PMC, &pmc);
@@ -7770,6 +8246,18 @@ static void __devinit bnx2x_link_settings_supported(struct bnx2x *bp,
SUPPORTED_Asym_Pause);
break;
+ case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727:
+ BNX2X_DEV_INFO("ext_phy_type 0x%x (8727)\n",
+ ext_phy_type);
+
+ bp->port.supported |= (SUPPORTED_10000baseT_Full |
+ SUPPORTED_1000baseT_Full |
+ SUPPORTED_Autoneg |
+ SUPPORTED_FIBRE |
+ SUPPORTED_Pause |
+ SUPPORTED_Asym_Pause);
+ break;
+
case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101:
BNX2X_DEV_INFO("ext_phy_type 0x%x (SFX7101)\n",
ext_phy_type);
@@ -8024,6 +8512,7 @@ static void __devinit bnx2x_get_port_hwinfo(struct bnx2x *bp)
u32 val, val2;
u32 config;
u16 i;
+ u32 ext_phy_type;
bp->link_params.bp = bp;
bp->link_params.port = port;
@@ -8033,6 +8522,17 @@ static void __devinit bnx2x_get_port_hwinfo(struct bnx2x *bp)
bp->link_params.ext_phy_config =
SHMEM_RD(bp,
dev_info.port_hw_config[port].external_phy_config);
+ /* BCM8727_NOC => BCM8727 no over current */
+ if (XGXS_EXT_PHY_TYPE(bp->link_params.ext_phy_config) ==
+ PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727_NOC) {
+ bp->link_params.ext_phy_config &=
+ ~PORT_HW_CFG_XGXS_EXT_PHY_TYPE_MASK;
+ bp->link_params.ext_phy_config |=
+ PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727;
+ bp->link_params.feature_config_flags |=
+ FEATURE_CONFIG_BCM8727_NOC;
+ }
+
bp->link_params.speed_cap_mask =
SHMEM_RD(bp,
dev_info.port_hw_config[port].speed_capability_mask);
@@ -8053,17 +8553,10 @@ static void __devinit bnx2x_get_port_hwinfo(struct bnx2x *bp)
bp->link_params.xgxs_config_tx[(i << 1) + 1] = (val & 0xffff);
}
- config = SHMEM_RD(bp, dev_info.port_feature_config[port].config);
- if (config & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_ENABLED)
- bp->link_params.feature_config_flags |=
- FEATURE_CONFIG_MODULE_ENFORCMENT_ENABLED;
- else
- bp->link_params.feature_config_flags &=
- ~FEATURE_CONFIG_MODULE_ENFORCMENT_ENABLED;
-
/* If the device is capable of WoL, set the default state according
* to the HW
*/
+ config = SHMEM_RD(bp, dev_info.port_feature_config[port].config);
bp->wol = (!(bp->flags & NO_WOL_FLAG) &&
(config & PORT_FEATURE_WOL_ENABLED));
@@ -8073,12 +8566,25 @@ static void __devinit bnx2x_get_port_hwinfo(struct bnx2x *bp)
bp->link_params.ext_phy_config,
bp->link_params.speed_cap_mask, bp->port.link_config);
- bp->link_params.switch_cfg = (bp->port.link_config &
- PORT_FEATURE_CONNECTED_SWITCH_MASK);
+ bp->link_params.switch_cfg |= (bp->port.link_config &
+ PORT_FEATURE_CONNECTED_SWITCH_MASK);
bnx2x_link_settings_supported(bp, bp->link_params.switch_cfg);
bnx2x_link_settings_requested(bp);
+ /*
+ * If connected directly, work with the internal PHY, otherwise, work
+ * with the external PHY
+ */
+ ext_phy_type = XGXS_EXT_PHY_TYPE(bp->link_params.ext_phy_config);
+ if (ext_phy_type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT)
+ bp->mdio.prtad = bp->link_params.phy_addr;
+
+ else if ((ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE) &&
+ (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN))
+ bp->mdio.prtad =
+ XGXS_EXT_PHY_ADDR(bp->link_params.ext_phy_config);
+
val2 = SHMEM_RD(bp, dev_info.port_hw_config[port].mac_upper);
val = SHMEM_RD(bp, dev_info.port_hw_config[port].mac_lower);
bp->dev->dev_addr[0] = (u8)(val2 >> 8 & 0xff);
@@ -8105,22 +8611,33 @@ static int __devinit bnx2x_get_hwinfo(struct bnx2x *bp)
bp->mf_config =
SHMEM_RD(bp, mf_cfg.func_mf_config[func].config);
- val = (SHMEM_RD(bp, mf_cfg.func_mf_config[func].e1hov_tag) &
+ val = (SHMEM_RD(bp, mf_cfg.func_mf_config[FUNC_0].e1hov_tag) &
FUNC_MF_CFG_E1HOV_TAG_MASK);
- if (val != FUNC_MF_CFG_E1HOV_TAG_DEFAULT) {
-
- bp->e1hov = val;
+ if (val != FUNC_MF_CFG_E1HOV_TAG_DEFAULT)
bp->e1hmf = 1;
- BNX2X_DEV_INFO("MF mode E1HOV for func %d is %d "
- "(0x%04x)\n",
- func, bp->e1hov, bp->e1hov);
- } else {
- BNX2X_DEV_INFO("single function mode\n");
- if (BP_E1HVN(bp)) {
+ BNX2X_DEV_INFO("%s function mode\n",
+ IS_E1HMF(bp) ? "multi" : "single");
+
+ if (IS_E1HMF(bp)) {
+ val = (SHMEM_RD(bp, mf_cfg.func_mf_config[func].
+ e1hov_tag) &
+ FUNC_MF_CFG_E1HOV_TAG_MASK);
+ if (val != FUNC_MF_CFG_E1HOV_TAG_DEFAULT) {
+ bp->e1hov = val;
+ BNX2X_DEV_INFO("E1HOV for func %d is %d "
+ "(0x%04x)\n",
+ func, bp->e1hov, bp->e1hov);
+ } else {
BNX2X_ERR("!!! No valid E1HOV for func %d,"
" aborting\n", func);
rc = -EPERM;
}
+ } else {
+ if (BP_E1HVN(bp)) {
+ BNX2X_ERR("!!! VN %d in single function mode,"
+ " aborting\n", BP_E1HVN(bp));
+ rc = -EPERM;
+ }
}
}
@@ -8170,6 +8687,7 @@ static int __devinit bnx2x_init_bp(struct bnx2x *bp)
/* Disable interrupt handling until HW is initialized */
atomic_set(&bp->intr_sem, 1);
+ smp_wmb(); /* Ensure that bp->intr_sem update is SMP-safe */
mutex_init(&bp->port.phy_mutex);
@@ -8208,6 +8726,11 @@ static int __devinit bnx2x_init_bp(struct bnx2x *bp)
bp->dev->features |= NETIF_F_LRO;
}
+ if (CHIP_IS_E1(bp))
+ bp->dropless_fc = 0;
+ else
+ bp->dropless_fc = dropless_fc;
+
bp->mrrs = mrrs;
bp->tx_ring_size = MAX_TX_AVAIL;
@@ -8269,6 +8792,7 @@ static int bnx2x_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705:
case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706:
case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726:
+ case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727:
cmd->port = PORT_FIBRE;
break;
@@ -8290,7 +8814,7 @@ static int bnx2x_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
} else
cmd->port = PORT_TP;
- cmd->phy_address = bp->port.phy_addr;
+ cmd->phy_address = bp->mdio.prtad;
cmd->transceiver = XCVR_INTERNAL;
if (bp->link_params.req_line_speed == SPEED_AUTO_NEG)
@@ -8463,50 +8987,15 @@ static int bnx2x_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
return 0;
}
-#define PHY_FW_VER_LEN 10
-
-static void bnx2x_get_drvinfo(struct net_device *dev,
- struct ethtool_drvinfo *info)
-{
- struct bnx2x *bp = netdev_priv(dev);
- u8 phy_fw_ver[PHY_FW_VER_LEN];
-
- strcpy(info->driver, DRV_MODULE_NAME);
- strcpy(info->version, DRV_MODULE_VERSION);
-
- phy_fw_ver[0] = '\0';
- if (bp->port.pmf) {
- bnx2x_acquire_phy_lock(bp);
- bnx2x_get_ext_phy_fw_version(&bp->link_params,
- (bp->state != BNX2X_STATE_CLOSED),
- phy_fw_ver, PHY_FW_VER_LEN);
- bnx2x_release_phy_lock(bp);
- }
-
- snprintf(info->fw_version, 32, "BC:%d.%d.%d%s%s",
- (bp->common.bc_ver & 0xff0000) >> 16,
- (bp->common.bc_ver & 0xff00) >> 8,
- (bp->common.bc_ver & 0xff),
- ((phy_fw_ver[0] != '\0') ? " PHY:" : ""), phy_fw_ver);
- strcpy(info->bus_info, pci_name(bp->pdev));
- info->n_stats = BNX2X_NUM_STATS;
- info->testinfo_len = BNX2X_NUM_TESTS;
- info->eedump_len = bp->common.flash_size;
- info->regdump_len = 0;
-}
-
#define IS_E1_ONLINE(info) (((info) & RI_E1_ONLINE) == RI_E1_ONLINE)
#define IS_E1H_ONLINE(info) (((info) & RI_E1H_ONLINE) == RI_E1H_ONLINE)
static int bnx2x_get_regs_len(struct net_device *dev)
{
- static u32 regdump_len;
struct bnx2x *bp = netdev_priv(dev);
+ int regdump_len = 0;
int i;
- if (regdump_len)
- return regdump_len;
-
if (CHIP_IS_E1(bp)) {
for (i = 0; i < REGS_COUNT; i++)
if (IS_E1_ONLINE(reg_addrs[i].info))
@@ -8573,6 +9062,38 @@ static void bnx2x_get_regs(struct net_device *dev,
}
}
+#define PHY_FW_VER_LEN 10
+
+static void bnx2x_get_drvinfo(struct net_device *dev,
+ struct ethtool_drvinfo *info)
+{
+ struct bnx2x *bp = netdev_priv(dev);
+ u8 phy_fw_ver[PHY_FW_VER_LEN];
+
+ strcpy(info->driver, DRV_MODULE_NAME);
+ strcpy(info->version, DRV_MODULE_VERSION);
+
+ phy_fw_ver[0] = '\0';
+ if (bp->port.pmf) {
+ bnx2x_acquire_phy_lock(bp);
+ bnx2x_get_ext_phy_fw_version(&bp->link_params,
+ (bp->state != BNX2X_STATE_CLOSED),
+ phy_fw_ver, PHY_FW_VER_LEN);
+ bnx2x_release_phy_lock(bp);
+ }
+
+ snprintf(info->fw_version, 32, "BC:%d.%d.%d%s%s",
+ (bp->common.bc_ver & 0xff0000) >> 16,
+ (bp->common.bc_ver & 0xff00) >> 8,
+ (bp->common.bc_ver & 0xff),
+ ((phy_fw_ver[0] != '\0') ? " PHY:" : ""), phy_fw_ver);
+ strcpy(info->bus_info, pci_name(bp->pdev));
+ info->n_stats = BNX2X_NUM_STATS;
+ info->testinfo_len = BNX2X_NUM_TESTS;
+ info->eedump_len = bp->common.flash_size;
+ info->regdump_len = bnx2x_get_regs_len(dev);
+}
+
static void bnx2x_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
{
struct bnx2x *bp = netdev_priv(dev);
@@ -8638,8 +9159,7 @@ static int bnx2x_nway_reset(struct net_device *dev)
return 0;
}
-static u32
-bnx2x_get_link(struct net_device *dev)
+static u32 bnx2x_get_link(struct net_device *dev)
{
struct bnx2x *bp = netdev_priv(dev);
@@ -9013,7 +9533,8 @@ static int bnx2x_set_eeprom(struct net_device *dev,
struct ethtool_eeprom *eeprom, u8 *eebuf)
{
struct bnx2x *bp = netdev_priv(dev);
- int rc;
+ int port = BP_PORT(bp);
+ int rc = 0;
if (!netif_running(dev))
return -EAGAIN;
@@ -9025,27 +9546,60 @@ static int bnx2x_set_eeprom(struct net_device *dev,
/* parameters already validated in ethtool_set_eeprom */
- /* If the magic number is PHY (0x00504859) upgrade the PHY FW */
- if (eeprom->magic == 0x00504859)
- if (bp->port.pmf) {
+ /* PHY eeprom can be accessed only by the PMF */
+ if ((eeprom->magic >= 0x50485900) && (eeprom->magic <= 0x504859FF) &&
+ !bp->port.pmf)
+ return -EINVAL;
+ if (eeprom->magic == 0x50485950) {
+ /* 'PHYP' (0x50485950): prepare phy for FW upgrade */
+ bnx2x_stats_handle(bp, STATS_EVENT_STOP);
+
+ bnx2x_acquire_phy_lock(bp);
+ rc |= bnx2x_link_reset(&bp->link_params,
+ &bp->link_vars, 0);
+ if (XGXS_EXT_PHY_TYPE(bp->link_params.ext_phy_config) ==
+ PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101)
+ bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_0,
+ MISC_REGISTERS_GPIO_HIGH, port);
+ bnx2x_release_phy_lock(bp);
+ bnx2x_link_report(bp);
+
+ } else if (eeprom->magic == 0x50485952) {
+ /* 'PHYR' (0x50485952): re-init link after FW upgrade */
+ if ((bp->state == BNX2X_STATE_OPEN) ||
+ (bp->state == BNX2X_STATE_DISABLED)) {
bnx2x_acquire_phy_lock(bp);
- rc = bnx2x_flash_download(bp, BP_PORT(bp),
- bp->link_params.ext_phy_config,
- (bp->state != BNX2X_STATE_CLOSED),
- eebuf, eeprom->len);
- if ((bp->state == BNX2X_STATE_OPEN) ||
- (bp->state == BNX2X_STATE_DISABLED)) {
- rc |= bnx2x_link_reset(&bp->link_params,
- &bp->link_vars, 1);
- rc |= bnx2x_phy_init(&bp->link_params,
- &bp->link_vars);
- }
+ rc |= bnx2x_link_reset(&bp->link_params,
+ &bp->link_vars, 1);
+
+ rc |= bnx2x_phy_init(&bp->link_params,
+ &bp->link_vars);
bnx2x_release_phy_lock(bp);
+ bnx2x_calc_fc_adv(bp);
+ }
+ } else if (eeprom->magic == 0x53985943) {
+ /* 'PHYC' (0x53985943): PHY FW upgrade completed */
+ if (XGXS_EXT_PHY_TYPE(bp->link_params.ext_phy_config) ==
+ PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101) {
+ u8 ext_phy_addr =
+ XGXS_EXT_PHY_ADDR(bp->link_params.ext_phy_config);
- } else /* Only the PMF can access the PHY */
- return -EINVAL;
- else
+ /* DSP Remove Download Mode */
+ bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_0,
+ MISC_REGISTERS_GPIO_LOW, port);
+
+ bnx2x_acquire_phy_lock(bp);
+
+ bnx2x_sfx7101_sp_sw_reset(bp, port, ext_phy_addr);
+
+ /* wait 0.5 sec to allow it to run */
+ msleep(500);
+ bnx2x_ext_phy_hw_reset(bp, port);
+ msleep(500);
+ bnx2x_release_phy_lock(bp);
+ }
+ } else
rc = bnx2x_nvram_write(bp, eeprom->offset, eebuf, eeprom->len);
return rc;
@@ -9064,18 +9618,19 @@ static int bnx2x_get_coalesce(struct net_device *dev,
return 0;
}
+#define BNX2X_MAX_COALES_TOUT (0xf0*12) /* Maximal coalescing timeout in us */
static int bnx2x_set_coalesce(struct net_device *dev,
struct ethtool_coalesce *coal)
{
struct bnx2x *bp = netdev_priv(dev);
bp->rx_ticks = (u16) coal->rx_coalesce_usecs;
- if (bp->rx_ticks > BNX2X_MAX_COALESCE_TOUT)
- bp->rx_ticks = BNX2X_MAX_COALESCE_TOUT;
+ if (bp->rx_ticks > BNX2X_MAX_COALES_TOUT)
+ bp->rx_ticks = BNX2X_MAX_COALES_TOUT;
bp->tx_ticks = (u16) coal->tx_coalesce_usecs;
- if (bp->tx_ticks > BNX2X_MAX_COALESCE_TOUT)
- bp->tx_ticks = BNX2X_MAX_COALESCE_TOUT;
+ if (bp->tx_ticks > BNX2X_MAX_COALES_TOUT)
+ bp->tx_ticks = BNX2X_MAX_COALES_TOUT;
if (netif_running(dev))
bnx2x_update_coalesce(bp);
@@ -9296,10 +9851,9 @@ static int bnx2x_test_registers(struct bnx2x *bp)
{ XCM_REG_WU_DA_SET_TMR_CNT_FLG_CMD00, 4, 0x00000001 },
{ XCM_REG_WU_DA_CNT_CMD00, 4, 0x00000003 },
{ XCM_REG_GLB_DEL_ACK_MAX_CNT_0, 4, 0x000000ff },
- { NIG_REG_EGRESS_MNG0_FIFO, 20, 0xffffffff },
{ NIG_REG_LLH0_T_BIT, 4, 0x00000001 },
-/* 20 */ { NIG_REG_EMAC0_IN_EN, 4, 0x00000001 },
- { NIG_REG_BMAC0_IN_EN, 4, 0x00000001 },
+ { NIG_REG_EMAC0_IN_EN, 4, 0x00000001 },
+/* 20 */ { NIG_REG_BMAC0_IN_EN, 4, 0x00000001 },
{ NIG_REG_XCM0_OUT_EN, 4, 0x00000001 },
{ NIG_REG_BRB0_OUT_EN, 4, 0x00000001 },
{ NIG_REG_LLH0_XCM_MASK, 4, 0x00000007 },
@@ -9308,8 +9862,8 @@ static int bnx2x_test_registers(struct bnx2x *bp)
{ NIG_REG_LLH0_DEST_MAC_0_0, 160, 0xffffffff },
{ NIG_REG_LLH0_DEST_IP_0_1, 160, 0xffffffff },
{ NIG_REG_LLH0_IPV4_IPV6_0, 160, 0x00000001 },
-/* 30 */ { NIG_REG_LLH0_DEST_UDP_0, 160, 0x0000ffff },
- { NIG_REG_LLH0_DEST_TCP_0, 160, 0x0000ffff },
+ { NIG_REG_LLH0_DEST_UDP_0, 160, 0x0000ffff },
+/* 30 */ { NIG_REG_LLH0_DEST_TCP_0, 160, 0x0000ffff },
{ NIG_REG_LLH0_VLAN_ID_0, 160, 0x00000fff },
{ NIG_REG_XGXS_SERDES0_MODE_SEL, 4, 0x00000001 },
{ NIG_REG_LED_CONTROL_OVERRIDE_TRAFFIC_P0, 4, 0x00000001 },
@@ -9435,12 +9989,14 @@ static int bnx2x_run_loopback(struct bnx2x *bp, int loopback_mode, u8 link_up)
unsigned int pkt_size, num_pkts, i;
struct sk_buff *skb;
unsigned char *packet;
- struct bnx2x_fastpath *fp = &bp->fp[0];
+ struct bnx2x_fastpath *fp_rx = &bp->fp[0];
+ struct bnx2x_fastpath *fp_tx = &bp->fp[bp->num_rx_queues];
u16 tx_start_idx, tx_idx;
u16 rx_start_idx, rx_idx;
- u16 pkt_prod;
+ u16 pkt_prod, bd_prod;
struct sw_tx_bd *tx_buf;
- struct eth_tx_bd *tx_bd;
+ struct eth_tx_start_bd *tx_start_bd;
+ struct eth_tx_parse_bd *pbd = NULL;
dma_addr_t mapping;
union eth_rx_cqe *cqe;
u8 cqe_fp_flags;
@@ -9472,57 +10028,64 @@ static int bnx2x_run_loopback(struct bnx2x *bp, int loopback_mode, u8 link_up)
}
packet = skb_put(skb, pkt_size);
memcpy(packet, bp->dev->dev_addr, ETH_ALEN);
- memset(packet + ETH_ALEN, 0, (ETH_HLEN - ETH_ALEN));
+ memset(packet + ETH_ALEN, 0, ETH_ALEN);
+ memset(packet + 2*ETH_ALEN, 0x77, (ETH_HLEN - 2*ETH_ALEN));
for (i = ETH_HLEN; i < pkt_size; i++)
packet[i] = (unsigned char) (i & 0xff);
/* send the loopback packet */
num_pkts = 0;
- tx_start_idx = le16_to_cpu(*fp->tx_cons_sb);
- rx_start_idx = le16_to_cpu(*fp->rx_cons_sb);
+ tx_start_idx = le16_to_cpu(*fp_tx->tx_cons_sb);
+ rx_start_idx = le16_to_cpu(*fp_rx->rx_cons_sb);
- pkt_prod = fp->tx_pkt_prod++;
- tx_buf = &fp->tx_buf_ring[TX_BD(pkt_prod)];
- tx_buf->first_bd = fp->tx_bd_prod;
+ pkt_prod = fp_tx->tx_pkt_prod++;
+ tx_buf = &fp_tx->tx_buf_ring[TX_BD(pkt_prod)];
+ tx_buf->first_bd = fp_tx->tx_bd_prod;
tx_buf->skb = skb;
+ tx_buf->flags = 0;
- tx_bd = &fp->tx_desc_ring[TX_BD(fp->tx_bd_prod)];
+ bd_prod = TX_BD(fp_tx->tx_bd_prod);
+ tx_start_bd = &fp_tx->tx_desc_ring[bd_prod].start_bd;
mapping = pci_map_single(bp->pdev, skb->data,
skb_headlen(skb), PCI_DMA_TODEVICE);
- tx_bd->addr_hi = cpu_to_le32(U64_HI(mapping));
- tx_bd->addr_lo = cpu_to_le32(U64_LO(mapping));
- tx_bd->nbd = cpu_to_le16(1);
- tx_bd->nbytes = cpu_to_le16(skb_headlen(skb));
- tx_bd->vlan = cpu_to_le16(pkt_prod);
- tx_bd->bd_flags.as_bitfield = (ETH_TX_BD_FLAGS_START_BD |
- ETH_TX_BD_FLAGS_END_BD);
- tx_bd->general_data = ((UNICAST_ADDRESS <<
- ETH_TX_BD_ETH_ADDR_TYPE_SHIFT) | 1);
+ tx_start_bd->addr_hi = cpu_to_le32(U64_HI(mapping));
+ tx_start_bd->addr_lo = cpu_to_le32(U64_LO(mapping));
+ tx_start_bd->nbd = cpu_to_le16(2); /* start + pbd */
+ tx_start_bd->nbytes = cpu_to_le16(skb_headlen(skb));
+ tx_start_bd->vlan = cpu_to_le16(pkt_prod);
+ tx_start_bd->bd_flags.as_bitfield = ETH_TX_BD_FLAGS_START_BD;
+ tx_start_bd->general_data = ((UNICAST_ADDRESS <<
+ ETH_TX_START_BD_ETH_ADDR_TYPE_SHIFT) | 1);
+
+ /* turn on parsing and get a BD */
+ bd_prod = TX_BD(NEXT_TX_IDX(bd_prod));
+ pbd = &fp_tx->tx_desc_ring[bd_prod].parse_bd;
+
+ memset(pbd, 0, sizeof(struct eth_tx_parse_bd));
wmb();
- le16_add_cpu(&fp->hw_tx_prods->bds_prod, 1);
- mb(); /* FW restriction: must not reorder writing nbd and packets */
- le32_add_cpu(&fp->hw_tx_prods->packets_prod, 1);
- DOORBELL(bp, fp->index, 0);
+ fp_tx->tx_db.data.prod += 2;
+ barrier();
+ DOORBELL(bp, fp_tx->index - bp->num_rx_queues, fp_tx->tx_db.raw);
mmiowb();
num_pkts++;
- fp->tx_bd_prod++;
+ fp_tx->tx_bd_prod += 2; /* start + pbd */
bp->dev->trans_start = jiffies;
udelay(100);
- tx_idx = le16_to_cpu(*fp->tx_cons_sb);
+ tx_idx = le16_to_cpu(*fp_tx->tx_cons_sb);
if (tx_idx != tx_start_idx + num_pkts)
goto test_loopback_exit;
- rx_idx = le16_to_cpu(*fp->rx_cons_sb);
+ rx_idx = le16_to_cpu(*fp_rx->rx_cons_sb);
if (rx_idx != rx_start_idx + num_pkts)
goto test_loopback_exit;
- cqe = &fp->rx_comp_ring[RCQ_BD(fp->rx_comp_cons)];
+ cqe = &fp_rx->rx_comp_ring[RCQ_BD(fp_rx->rx_comp_cons)];
cqe_fp_flags = cqe->fast_path_cqe.type_error_flags;
if (CQE_TYPE(cqe_fp_flags) || (cqe_fp_flags & ETH_RX_ERROR_FALGS))
goto test_loopback_rx_exit;
@@ -9531,7 +10094,7 @@ static int bnx2x_run_loopback(struct bnx2x *bp, int loopback_mode, u8 link_up)
if (len != pkt_size)
goto test_loopback_rx_exit;
- rx_buf = &fp->rx_buf_ring[RX_BD(fp->rx_bd_cons)];
+ rx_buf = &fp_rx->rx_buf_ring[RX_BD(fp_rx->rx_bd_cons)];
skb = rx_buf->skb;
skb_reserve(skb, cqe->fast_path_cqe.placement_offset);
for (i = ETH_HLEN; i < pkt_size; i++)
@@ -9542,14 +10105,14 @@ static int bnx2x_run_loopback(struct bnx2x *bp, int loopback_mode, u8 link_up)
test_loopback_rx_exit:
- fp->rx_bd_cons = NEXT_RX_IDX(fp->rx_bd_cons);
- fp->rx_bd_prod = NEXT_RX_IDX(fp->rx_bd_prod);
- fp->rx_comp_cons = NEXT_RCQ_IDX(fp->rx_comp_cons);
- fp->rx_comp_prod = NEXT_RCQ_IDX(fp->rx_comp_prod);
+ fp_rx->rx_bd_cons = NEXT_RX_IDX(fp_rx->rx_bd_cons);
+ fp_rx->rx_bd_prod = NEXT_RX_IDX(fp_rx->rx_bd_prod);
+ fp_rx->rx_comp_cons = NEXT_RCQ_IDX(fp_rx->rx_comp_cons);
+ fp_rx->rx_comp_prod = NEXT_RCQ_IDX(fp_rx->rx_comp_prod);
/* Update producers */
- bnx2x_update_rx_prod(bp, fp, fp->rx_bd_prod, fp->rx_comp_prod,
- fp->rx_sge_prod);
+ bnx2x_update_rx_prod(bp, fp_rx, fp_rx->rx_bd_prod, fp_rx->rx_comp_prod,
+ fp_rx->rx_sge_prod);
test_loopback_exit:
bp->link_params.loopback_mode = LOOPBACK_NONE;
@@ -9606,7 +10169,7 @@ static int bnx2x_test_nvram(struct bnx2x *bp)
__be32 buf[0x350 / 4];
u8 *data = (u8 *)buf;
int i, rc;
- u32 magic, csum;
+ u32 magic, crc;
rc = bnx2x_nvram_read(bp, 0, data, 4);
if (rc) {
@@ -9631,10 +10194,10 @@ static int bnx2x_test_nvram(struct bnx2x *bp)
goto test_nvram_exit;
}
- csum = ether_crc_le(nvram_tbl[i].size, data);
- if (csum != CRC32_RESIDUAL) {
+ crc = ether_crc_le(nvram_tbl[i].size, data);
+ if (crc != CRC32_RESIDUAL) {
DP(NETIF_MSG_PROBE,
- "nvram_tbl[%d] csum value (0x%08x)\n", i, csum);
+ "nvram_tbl[%d] crc value (0x%08x)\n", i, crc);
rc = -ENODEV;
goto test_nvram_exit;
}
@@ -9692,8 +10255,15 @@ static void bnx2x_self_test(struct net_device *dev,
etest->flags &= ~ETH_TEST_FL_OFFLINE;
if (etest->flags & ETH_TEST_FL_OFFLINE) {
+ int port = BP_PORT(bp);
+ u32 val;
u8 link_up;
+ /* save current value of input enable for TX port IF */
+ val = REG_RD(bp, NIG_REG_EGRESS_UMP0_IN_EN + port*4);
+ /* disable input for TX port IF */
+ REG_WR(bp, NIG_REG_EGRESS_UMP0_IN_EN + port*4, 0);
+
link_up = bp->link_vars.link_up;
bnx2x_nic_unload(bp, UNLOAD_NORMAL);
bnx2x_nic_load(bp, LOAD_DIAG);
@@ -9713,6 +10283,10 @@ static void bnx2x_self_test(struct net_device *dev,
etest->flags |= ETH_TEST_FL_FAILED;
bnx2x_nic_unload(bp, UNLOAD_NORMAL);
+
+ /* restore input for TX port IF */
+ REG_WR(bp, NIG_REG_EGRESS_UMP0_IN_EN + port*4, val);
+
bnx2x_nic_load(bp, LOAD_NORMAL);
/* wait until link state is restored */
bnx2x_wait_for_link(bp, link_up);
@@ -9871,7 +10445,7 @@ static void bnx2x_get_strings(struct net_device *dev, u32 stringset, u8 *buf)
case ETH_SS_STATS:
if (is_multi(bp)) {
k = 0;
- for_each_queue(bp, i) {
+ for_each_rx_queue(bp, i) {
for (j = 0; j < BNX2X_NUM_Q_STATS; j++)
sprintf(buf + (k + j)*ETH_GSTRING_LEN,
bnx2x_q_stats_arr[j].string, i);
@@ -9905,7 +10479,7 @@ static int bnx2x_get_stats_count(struct net_device *dev)
int i, num_stats;
if (is_multi(bp)) {
- num_stats = BNX2X_NUM_Q_STATS * BNX2X_NUM_QUEUES(bp);
+ num_stats = BNX2X_NUM_Q_STATS * bp->num_rx_queues;
if (!IS_E1HMF_MODE_STAT(bp))
num_stats += BNX2X_NUM_STATS;
} else {
@@ -9930,7 +10504,7 @@ static void bnx2x_get_ethtool_stats(struct net_device *dev,
if (is_multi(bp)) {
k = 0;
- for_each_queue(bp, i) {
+ for_each_rx_queue(bp, i) {
hw_stats = (u32 *)&bp->fp[i].eth_q_stats;
for (j = 0; j < BNX2X_NUM_Q_STATS; j++) {
if (bnx2x_q_stats_arr[j].size == 0) {
@@ -10143,15 +10717,11 @@ static int bnx2x_poll(struct napi_struct *napi, int budget)
goto poll_panic;
#endif
- prefetch(fp->tx_buf_ring[TX_BD(fp->tx_pkt_cons)].skb);
prefetch(fp->rx_buf_ring[RX_BD(fp->rx_bd_cons)].skb);
prefetch((char *)(fp->rx_buf_ring[RX_BD(fp->rx_bd_cons)].skb) + 256);
bnx2x_update_fpsb_idx(fp);
- if (bnx2x_has_tx_work(fp))
- bnx2x_tx_int(fp);
-
if (bnx2x_has_rx_work(fp)) {
work_done = bnx2x_rx_int(fp, budget);
@@ -10160,11 +10730,11 @@ static int bnx2x_poll(struct napi_struct *napi, int budget)
goto poll_again;
}
- /* BNX2X_HAS_WORK() reads the status block, thus we need to
+ /* bnx2x_has_rx_work() reads the status block, thus we need to
* ensure that status block indices have been actually read
- * (bnx2x_update_fpsb_idx) prior to this check (BNX2X_HAS_WORK)
+ * (bnx2x_update_fpsb_idx) prior to this check (bnx2x_has_rx_work)
* so that we won't write the "newer" value of the status block to IGU
- * (if there was a DMA right after BNX2X_HAS_WORK and
+ * (if there was a DMA right after bnx2x_has_rx_work and
* if there is no rmb, the memory reading (bnx2x_update_fpsb_idx)
* may be postponed to right before bnx2x_ack_sb). In this case
* there will never be another interrupt until there is another update
@@ -10172,7 +10742,7 @@ static int bnx2x_poll(struct napi_struct *napi, int budget)
*/
rmb();
- if (!BNX2X_HAS_WORK(fp)) {
+ if (!bnx2x_has_rx_work(fp)) {
#ifdef BNX2X_STOP_ON_ERROR
poll_panic:
#endif
@@ -10197,10 +10767,11 @@ poll_again:
*/
static noinline u16 bnx2x_tx_split(struct bnx2x *bp,
struct bnx2x_fastpath *fp,
- struct eth_tx_bd **tx_bd, u16 hlen,
+ struct sw_tx_bd *tx_buf,
+ struct eth_tx_start_bd **tx_bd, u16 hlen,
u16 bd_prod, int nbd)
{
- struct eth_tx_bd *h_tx_bd = *tx_bd;
+ struct eth_tx_start_bd *h_tx_bd = *tx_bd;
struct eth_tx_bd *d_tx_bd;
dma_addr_t mapping;
int old_len = le16_to_cpu(h_tx_bd->nbytes);
@@ -10216,7 +10787,7 @@ static noinline u16 bnx2x_tx_split(struct bnx2x *bp,
/* now get a new data BD
* (after the pbd) and fill it */
bd_prod = TX_BD(NEXT_TX_IDX(bd_prod));
- d_tx_bd = &fp->tx_desc_ring[bd_prod];
+ d_tx_bd = &fp->tx_desc_ring[bd_prod].reg_bd;
mapping = HILO_U64(le32_to_cpu(h_tx_bd->addr_hi),
le32_to_cpu(h_tx_bd->addr_lo)) + hlen;
@@ -10224,17 +10795,16 @@ static noinline u16 bnx2x_tx_split(struct bnx2x *bp,
d_tx_bd->addr_hi = cpu_to_le32(U64_HI(mapping));
d_tx_bd->addr_lo = cpu_to_le32(U64_LO(mapping));
d_tx_bd->nbytes = cpu_to_le16(old_len - hlen);
- d_tx_bd->vlan = 0;
- /* this marks the BD as one that has no individual mapping
- * the FW ignores this flag in a BD not marked start
- */
- d_tx_bd->bd_flags.as_bitfield = ETH_TX_BD_FLAGS_SW_LSO;
+
+ /* this marks the BD as one that has no individual mapping */
+ tx_buf->flags |= BNX2X_TSO_SPLIT_BD;
+
DP(NETIF_MSG_TX_QUEUED,
"TSO split data size is %d (%x:%x)\n",
d_tx_bd->nbytes, d_tx_bd->addr_hi, d_tx_bd->addr_lo);
- /* update tx_bd for marking the last BD flag */
- *tx_bd = d_tx_bd;
+ /* update tx_bd */
+ *tx_bd = (struct eth_tx_start_bd *)d_tx_bd;
return bd_prod;
}
@@ -10369,18 +10939,19 @@ exit_lbl:
static int bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct bnx2x *bp = netdev_priv(dev);
- struct bnx2x_fastpath *fp;
+ struct bnx2x_fastpath *fp, *fp_stat;
struct netdev_queue *txq;
struct sw_tx_bd *tx_buf;
- struct eth_tx_bd *tx_bd;
+ struct eth_tx_start_bd *tx_start_bd;
+ struct eth_tx_bd *tx_data_bd, *total_pkt_bd = NULL;
struct eth_tx_parse_bd *pbd = NULL;
u16 pkt_prod, bd_prod;
int nbd, fp_index;
dma_addr_t mapping;
u32 xmit_type = bnx2x_xmit_type(bp, skb);
- int vlan_off = (bp->e1hov ? 4 : 0);
int i;
u8 hlen = 0;
+ __le16 pkt_size = 0;
#ifdef BNX2X_STOP_ON_ERROR
if (unlikely(bp->panic))
@@ -10390,10 +10961,11 @@ static int bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
fp_index = skb_get_queue_mapping(skb);
txq = netdev_get_tx_queue(dev, fp_index);
- fp = &bp->fp[fp_index];
+ fp = &bp->fp[fp_index + bp->num_rx_queues];
+ fp_stat = &bp->fp[fp_index];
if (unlikely(bnx2x_tx_avail(fp) < (skb_shinfo(skb)->nr_frags + 3))) {
- fp->eth_q_stats.driver_xoff++,
+ fp_stat->eth_q_stats.driver_xoff++;
netif_tx_stop_queue(txq);
BNX2X_ERR("BUG! Tx ring full when queue awake!\n");
return NETDEV_TX_BUSY;
@@ -10422,7 +10994,7 @@ static int bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
/*
Please read carefully. First we use one BD which we mark as start,
- then for TSO or xsum we have a parsing info BD,
+ then we have a parsing info BD (used for TSO or xsum),
and only then we have the rest of the TSO BDs.
(don't forget to mark the last one as last,
and to unmap only AFTER you write to the BD ...)
@@ -10434,42 +11006,40 @@ static int bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
/* get a tx_buf and first BD */
tx_buf = &fp->tx_buf_ring[TX_BD(pkt_prod)];
- tx_bd = &fp->tx_desc_ring[bd_prod];
+ tx_start_bd = &fp->tx_desc_ring[bd_prod].start_bd;
- tx_bd->bd_flags.as_bitfield = ETH_TX_BD_FLAGS_START_BD;
- tx_bd->general_data = (UNICAST_ADDRESS <<
- ETH_TX_BD_ETH_ADDR_TYPE_SHIFT);
+ tx_start_bd->bd_flags.as_bitfield = ETH_TX_BD_FLAGS_START_BD;
+ tx_start_bd->general_data = (UNICAST_ADDRESS <<
+ ETH_TX_START_BD_ETH_ADDR_TYPE_SHIFT);
/* header nbd */
- tx_bd->general_data |= (1 << ETH_TX_BD_HDR_NBDS_SHIFT);
+ tx_start_bd->general_data |= (1 << ETH_TX_START_BD_HDR_NBDS_SHIFT);
/* remember the first BD of the packet */
tx_buf->first_bd = fp->tx_bd_prod;
tx_buf->skb = skb;
+ tx_buf->flags = 0;
DP(NETIF_MSG_TX_QUEUED,
"sending pkt %u @%p next_idx %u bd %u @%p\n",
- pkt_prod, tx_buf, fp->tx_pkt_prod, bd_prod, tx_bd);
+ pkt_prod, tx_buf, fp->tx_pkt_prod, bd_prod, tx_start_bd);
#ifdef BCM_VLAN
if ((bp->vlgrp != NULL) && vlan_tx_tag_present(skb) &&
(bp->flags & HW_VLAN_TX_FLAG)) {
- tx_bd->vlan = cpu_to_le16(vlan_tx_tag_get(skb));
- tx_bd->bd_flags.as_bitfield |= ETH_TX_BD_FLAGS_VLAN_TAG;
- vlan_off += 4;
+ tx_start_bd->vlan = cpu_to_le16(vlan_tx_tag_get(skb));
+ tx_start_bd->bd_flags.as_bitfield |= ETH_TX_BD_FLAGS_VLAN_TAG;
} else
#endif
- tx_bd->vlan = cpu_to_le16(pkt_prod);
+ tx_start_bd->vlan = cpu_to_le16(pkt_prod);
- if (xmit_type) {
- /* turn on parsing and get a BD */
- bd_prod = TX_BD(NEXT_TX_IDX(bd_prod));
- pbd = (void *)&fp->tx_desc_ring[bd_prod];
+ /* turn on parsing and get a BD */
+ bd_prod = TX_BD(NEXT_TX_IDX(bd_prod));
+ pbd = &fp->tx_desc_ring[bd_prod].parse_bd;
- memset(pbd, 0, sizeof(struct eth_tx_parse_bd));
- }
+ memset(pbd, 0, sizeof(struct eth_tx_parse_bd));
if (xmit_type & XMIT_CSUM) {
- hlen = (skb_network_header(skb) - skb->data + vlan_off) / 2;
+ hlen = (skb_network_header(skb) - skb->data) / 2;
/* for now NS flag is not used in Linux */
pbd->global_data =
@@ -10482,15 +11052,16 @@ static int bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
hlen += pbd->ip_hlen + tcp_hdrlen(skb) / 2;
pbd->total_hlen = cpu_to_le16(hlen);
- hlen = hlen*2 - vlan_off;
+ hlen = hlen*2;
- tx_bd->bd_flags.as_bitfield |= ETH_TX_BD_FLAGS_TCP_CSUM;
+ tx_start_bd->bd_flags.as_bitfield |= ETH_TX_BD_FLAGS_L4_CSUM;
if (xmit_type & XMIT_CSUM_V4)
- tx_bd->bd_flags.as_bitfield |=
+ tx_start_bd->bd_flags.as_bitfield |=
ETH_TX_BD_FLAGS_IP_CSUM;
else
- tx_bd->bd_flags.as_bitfield |= ETH_TX_BD_FLAGS_IPV6;
+ tx_start_bd->bd_flags.as_bitfield |=
+ ETH_TX_BD_FLAGS_IPV6;
if (xmit_type & XMIT_CSUM_TCP) {
pbd->tcp_pseudo_csum = swab16(tcp_hdr(skb)->check);
@@ -10498,13 +11069,11 @@ static int bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
} else {
s8 fix = SKB_CS_OFF(skb); /* signed! */
- pbd->global_data |= ETH_TX_PARSE_BD_CS_ANY_FLG;
- pbd->cs_offset = fix / 2;
+ pbd->global_data |= ETH_TX_PARSE_BD_UDP_CS_FLG;
DP(NETIF_MSG_TX_QUEUED,
- "hlen %d offset %d fix %d csum before fix %x\n",
- le16_to_cpu(pbd->total_hlen), pbd->cs_offset, fix,
- SKB_CS(skb));
+ "hlen %d fix %d csum before fix %x\n",
+ le16_to_cpu(pbd->total_hlen), fix, SKB_CS(skb));
/* HW bug: fixup the CSUM */
pbd->tcp_pseudo_csum =
@@ -10519,17 +11088,18 @@ static int bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
mapping = pci_map_single(bp->pdev, skb->data,
skb_headlen(skb), PCI_DMA_TODEVICE);
- tx_bd->addr_hi = cpu_to_le32(U64_HI(mapping));
- tx_bd->addr_lo = cpu_to_le32(U64_LO(mapping));
- nbd = skb_shinfo(skb)->nr_frags + ((pbd == NULL) ? 1 : 2);
- tx_bd->nbd = cpu_to_le16(nbd);
- tx_bd->nbytes = cpu_to_le16(skb_headlen(skb));
+ tx_start_bd->addr_hi = cpu_to_le32(U64_HI(mapping));
+ tx_start_bd->addr_lo = cpu_to_le32(U64_LO(mapping));
+ nbd = skb_shinfo(skb)->nr_frags + 2; /* start_bd + pbd + frags */
+ tx_start_bd->nbd = cpu_to_le16(nbd);
+ tx_start_bd->nbytes = cpu_to_le16(skb_headlen(skb));
+ pkt_size = tx_start_bd->nbytes;
DP(NETIF_MSG_TX_QUEUED, "first bd @%p addr (%x:%x) nbd %d"
" nbytes %d flags %x vlan %x\n",
- tx_bd, tx_bd->addr_hi, tx_bd->addr_lo, le16_to_cpu(tx_bd->nbd),
- le16_to_cpu(tx_bd->nbytes), tx_bd->bd_flags.as_bitfield,
- le16_to_cpu(tx_bd->vlan));
+ tx_start_bd, tx_start_bd->addr_hi, tx_start_bd->addr_lo,
+ le16_to_cpu(tx_start_bd->nbd), le16_to_cpu(tx_start_bd->nbytes),
+ tx_start_bd->bd_flags.as_bitfield, le16_to_cpu(tx_start_bd->vlan));
if (xmit_type & XMIT_GSO) {
@@ -10538,11 +11108,11 @@ static int bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
skb->len, hlen, skb_headlen(skb),
skb_shinfo(skb)->gso_size);
- tx_bd->bd_flags.as_bitfield |= ETH_TX_BD_FLAGS_SW_LSO;
+ tx_start_bd->bd_flags.as_bitfield |= ETH_TX_BD_FLAGS_SW_LSO;
if (unlikely(skb_headlen(skb) > hlen))
- bd_prod = bnx2x_tx_split(bp, fp, &tx_bd, hlen,
- bd_prod, ++nbd);
+ bd_prod = bnx2x_tx_split(bp, fp, tx_buf, &tx_start_bd,
+ hlen, bd_prod, ++nbd);
pbd->lso_mss = cpu_to_le16(skb_shinfo(skb)->gso_size);
pbd->tcp_send_seq = swab32(tcp_hdr(skb)->seq);
@@ -10563,33 +11133,31 @@ static int bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
pbd->global_data |= ETH_TX_PARSE_BD_PSEUDO_CS_WITHOUT_LEN;
}
+ tx_data_bd = (struct eth_tx_bd *)tx_start_bd;
for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
bd_prod = TX_BD(NEXT_TX_IDX(bd_prod));
- tx_bd = &fp->tx_desc_ring[bd_prod];
+ tx_data_bd = &fp->tx_desc_ring[bd_prod].reg_bd;
+ if (total_pkt_bd == NULL)
+ total_pkt_bd = &fp->tx_desc_ring[bd_prod].reg_bd;
mapping = pci_map_page(bp->pdev, frag->page, frag->page_offset,
frag->size, PCI_DMA_TODEVICE);
- tx_bd->addr_hi = cpu_to_le32(U64_HI(mapping));
- tx_bd->addr_lo = cpu_to_le32(U64_LO(mapping));
- tx_bd->nbytes = cpu_to_le16(frag->size);
- tx_bd->vlan = cpu_to_le16(pkt_prod);
- tx_bd->bd_flags.as_bitfield = 0;
+ tx_data_bd->addr_hi = cpu_to_le32(U64_HI(mapping));
+ tx_data_bd->addr_lo = cpu_to_le32(U64_LO(mapping));
+ tx_data_bd->nbytes = cpu_to_le16(frag->size);
+ le16_add_cpu(&pkt_size, frag->size);
DP(NETIF_MSG_TX_QUEUED,
- "frag %d bd @%p addr (%x:%x) nbytes %d flags %x\n",
- i, tx_bd, tx_bd->addr_hi, tx_bd->addr_lo,
- le16_to_cpu(tx_bd->nbytes), tx_bd->bd_flags.as_bitfield);
+ "frag %d bd @%p addr (%x:%x) nbytes %d\n",
+ i, tx_data_bd, tx_data_bd->addr_hi, tx_data_bd->addr_lo,
+ le16_to_cpu(tx_data_bd->nbytes));
}
- /* now at last mark the BD as the last BD */
- tx_bd->bd_flags.as_bitfield |= ETH_TX_BD_FLAGS_END_BD;
-
- DP(NETIF_MSG_TX_QUEUED, "last bd @%p flags %x\n",
- tx_bd, tx_bd->bd_flags.as_bitfield);
+ DP(NETIF_MSG_TX_QUEUED, "last bd @%p\n", tx_data_bd);
bd_prod = TX_BD(NEXT_TX_IDX(bd_prod));
@@ -10599,6 +11167,9 @@ static int bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
if (TX_BD_POFF(bd_prod) < nbd)
nbd++;
+ if (total_pkt_bd != NULL)
+ total_pkt_bd->total_pkt_bytes = pkt_size;
+
if (pbd)
DP(NETIF_MSG_TX_QUEUED,
"PBD @%p ip_data %x ip_hlen %u ip_id %u lso_mss %u"
@@ -10618,25 +11189,24 @@ static int bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
*/
wmb();
- le16_add_cpu(&fp->hw_tx_prods->bds_prod, nbd);
- mb(); /* FW restriction: must not reorder writing nbd and packets */
- le32_add_cpu(&fp->hw_tx_prods->packets_prod, 1);
- DOORBELL(bp, fp->index, 0);
+ fp->tx_db.data.prod += nbd;
+ barrier();
+ DOORBELL(bp, fp->index - bp->num_rx_queues, fp->tx_db.raw);
mmiowb();
fp->tx_bd_prod += nbd;
if (unlikely(bnx2x_tx_avail(fp) < MAX_SKB_FRAGS + 3)) {
+ netif_tx_stop_queue(txq);
/* We want bnx2x_tx_int to "see" the updated tx_bd_prod
if we put Tx into XOFF state. */
smp_mb();
- netif_tx_stop_queue(txq);
- fp->eth_q_stats.driver_xoff++;
+ fp_stat->eth_q_stats.driver_xoff++;
if (bnx2x_tx_avail(fp) >= MAX_SKB_FRAGS + 3)
netif_tx_wake_queue(txq);
}
- fp->tx_pkt++;
+ fp_stat->tx_pkt++;
return NETDEV_TX_OK;
}
@@ -10712,8 +11282,9 @@ static void bnx2x_set_rx_mode(struct net_device *dev)
cpu_to_le16(port);
config->config_table[i].
target_table_entry.flags = 0;
- config->config_table[i].
- target_table_entry.client_id = 0;
+ config->config_table[i].target_table_entry.
+ clients_bit_vector =
+ cpu_to_le32(1 << BP_L_ID(bp));
config->config_table[i].
target_table_entry.vlan_id = 0;
@@ -10808,54 +11379,77 @@ static int bnx2x_change_mac_addr(struct net_device *dev, void *p)
}
/* called with rtnl_lock */
-static int bnx2x_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+static int bnx2x_mdio_read(struct net_device *netdev, int prtad,
+ int devad, u16 addr)
{
- struct mii_ioctl_data *data = if_mii(ifr);
- struct bnx2x *bp = netdev_priv(dev);
- int port = BP_PORT(bp);
- int err;
+ struct bnx2x *bp = netdev_priv(netdev);
+ u16 value;
+ int rc;
+ u32 phy_type = XGXS_EXT_PHY_TYPE(bp->link_params.ext_phy_config);
- switch (cmd) {
- case SIOCGMIIPHY:
- data->phy_id = bp->port.phy_addr;
+ DP(NETIF_MSG_LINK, "mdio_read: prtad 0x%x, devad 0x%x, addr 0x%x\n",
+ prtad, devad, addr);
- /* fallthrough */
+ if (prtad != bp->mdio.prtad) {
+ DP(NETIF_MSG_LINK, "prtad missmatch (cmd:0x%x != bp:0x%x)\n",
+ prtad, bp->mdio.prtad);
+ return -EINVAL;
+ }
- case SIOCGMIIREG: {
- u16 mii_regval;
+ /* The HW expects different devad if CL22 is used */
+ devad = (devad == MDIO_DEVAD_NONE) ? DEFAULT_PHY_DEV_ADDR : devad;
- if (!netif_running(dev))
- return -EAGAIN;
+ bnx2x_acquire_phy_lock(bp);
+ rc = bnx2x_cl45_read(bp, BP_PORT(bp), phy_type, prtad,
+ devad, addr, &value);
+ bnx2x_release_phy_lock(bp);
+ DP(NETIF_MSG_LINK, "mdio_read_val 0x%x rc = 0x%x\n", value, rc);
- mutex_lock(&bp->port.phy_mutex);
- err = bnx2x_cl45_read(bp, port, 0, bp->port.phy_addr,
- DEFAULT_PHY_DEV_ADDR,
- (data->reg_num & 0x1f), &mii_regval);
- data->val_out = mii_regval;
- mutex_unlock(&bp->port.phy_mutex);
- return err;
+ if (!rc)
+ rc = value;
+ return rc;
+}
+
+/* called with rtnl_lock */
+static int bnx2x_mdio_write(struct net_device *netdev, int prtad, int devad,
+ u16 addr, u16 value)
+{
+ struct bnx2x *bp = netdev_priv(netdev);
+ u32 ext_phy_type = XGXS_EXT_PHY_TYPE(bp->link_params.ext_phy_config);
+ int rc;
+
+ DP(NETIF_MSG_LINK, "mdio_write: prtad 0x%x, devad 0x%x, addr 0x%x,"
+ " value 0x%x\n", prtad, devad, addr, value);
+
+ if (prtad != bp->mdio.prtad) {
+ DP(NETIF_MSG_LINK, "prtad missmatch (cmd:0x%x != bp:0x%x)\n",
+ prtad, bp->mdio.prtad);
+ return -EINVAL;
}
- case SIOCSMIIREG:
- if (!capable(CAP_NET_ADMIN))
- return -EPERM;
+ /* The HW expects different devad if CL22 is used */
+ devad = (devad == MDIO_DEVAD_NONE) ? DEFAULT_PHY_DEV_ADDR : devad;
- if (!netif_running(dev))
- return -EAGAIN;
+ bnx2x_acquire_phy_lock(bp);
+ rc = bnx2x_cl45_write(bp, BP_PORT(bp), ext_phy_type, prtad,
+ devad, addr, value);
+ bnx2x_release_phy_lock(bp);
+ return rc;
+}
- mutex_lock(&bp->port.phy_mutex);
- err = bnx2x_cl45_write(bp, port, 0, bp->port.phy_addr,
- DEFAULT_PHY_DEV_ADDR,
- (data->reg_num & 0x1f), data->val_in);
- mutex_unlock(&bp->port.phy_mutex);
- return err;
+/* called with rtnl_lock */
+static int bnx2x_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+{
+ struct bnx2x *bp = netdev_priv(dev);
+ struct mii_ioctl_data *mdio = if_mii(ifr);
- default:
- /* do nothing */
- break;
- }
+ DP(NETIF_MSG_LINK, "ioctl: phy id 0x%x, reg 0x%x, val_in 0x%x\n",
+ mdio->phy_id, mdio->reg_num, mdio->val_in);
+
+ if (!netif_running(dev))
+ return -EAGAIN;
- return -EOPNOTSUPP;
+ return mdio_mii_ioctl(&bp->mdio, mdio, cmd);
}
/* called with rtnl_lock */
@@ -11065,12 +11659,27 @@ static int __devinit bnx2x_init_dev(struct pci_dev *pdev,
dev->features |= NETIF_F_HW_CSUM;
if (bp->flags & USING_DAC_FLAG)
dev->features |= NETIF_F_HIGHDMA;
+ dev->features |= (NETIF_F_TSO | NETIF_F_TSO_ECN);
+ dev->features |= NETIF_F_TSO6;
#ifdef BCM_VLAN
dev->features |= (NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX);
bp->flags |= (HW_VLAN_RX_FLAG | HW_VLAN_TX_FLAG);
+
+ dev->vlan_features |= NETIF_F_SG;
+ dev->vlan_features |= NETIF_F_HW_CSUM;
+ if (bp->flags & USING_DAC_FLAG)
+ dev->vlan_features |= NETIF_F_HIGHDMA;
+ dev->vlan_features |= (NETIF_F_TSO | NETIF_F_TSO_ECN);
+ dev->vlan_features |= NETIF_F_TSO6;
#endif
- dev->features |= (NETIF_F_TSO | NETIF_F_TSO_ECN);
- dev->features |= NETIF_F_TSO6;
+
+ /* get_port_hwinfo() will set prtad and mmds properly */
+ bp->mdio.prtad = MDIO_PRTAD_NONE;
+ bp->mdio.mmds = 0;
+ bp->mdio.mode_support = MDIO_SUPPORTS_C45 | MDIO_EMULATE_C22;
+ bp->mdio.dev = dev;
+ bp->mdio.mdio_read = bnx2x_mdio_read;
+ bp->mdio.mdio_write = bnx2x_mdio_write;
return 0;
@@ -11096,31 +11705,26 @@ err_out:
return rc;
}
-static int __devinit bnx2x_get_pcie_width(struct bnx2x *bp)
+static void __devinit bnx2x_get_pcie_width_speed(struct bnx2x *bp,
+ int *width, int *speed)
{
u32 val = REG_RD(bp, PCICFG_OFFSET + PCICFG_LINK_CONTROL);
- val = (val & PCICFG_LINK_WIDTH) >> PCICFG_LINK_WIDTH_SHIFT;
- return val;
-}
+ *width = (val & PCICFG_LINK_WIDTH) >> PCICFG_LINK_WIDTH_SHIFT;
-/* return value of 1=2.5GHz 2=5GHz */
-static int __devinit bnx2x_get_pcie_speed(struct bnx2x *bp)
-{
- u32 val = REG_RD(bp, PCICFG_OFFSET + PCICFG_LINK_CONTROL);
-
- val = (val & PCICFG_LINK_SPEED) >> PCICFG_LINK_SPEED_SHIFT;
- return val;
+ /* return value of 1=2.5GHz 2=5GHz */
+ *speed = (val & PCICFG_LINK_SPEED) >> PCICFG_LINK_SPEED_SHIFT;
}
+
static int __devinit bnx2x_check_firmware(struct bnx2x *bp)
{
+ const struct firmware *firmware = bp->firmware;
struct bnx2x_fw_file_hdr *fw_hdr;
struct bnx2x_fw_file_section *sections;
- u16 *ops_offsets;
u32 offset, len, num_ops;
+ u16 *ops_offsets;
int i;
- const struct firmware *firmware = bp->firmware;
- const u8 * fw_ver;
+ const u8 *fw_ver;
if (firmware->size < sizeof(struct bnx2x_fw_file_hdr))
return -EINVAL;
@@ -11134,7 +11738,8 @@ static int __devinit bnx2x_check_firmware(struct bnx2x *bp)
offset = be32_to_cpu(sections[i].offset);
len = be32_to_cpu(sections[i].len);
if (offset + len > firmware->size) {
- printk(KERN_ERR PFX "Section %d length is out of bounds\n", i);
+ printk(KERN_ERR PFX "Section %d length is out of "
+ "bounds\n", i);
return -EINVAL;
}
}
@@ -11146,7 +11751,8 @@ static int __devinit bnx2x_check_firmware(struct bnx2x *bp)
for (i = 0; i < be32_to_cpu(fw_hdr->init_ops_offsets.len) / 2; i++) {
if (be16_to_cpu(ops_offsets[i]) > num_ops) {
- printk(KERN_ERR PFX "Section offset %d is out of bounds\n", i);
+ printk(KERN_ERR PFX "Section offset %d is out of "
+ "bounds\n", i);
return -EINVAL;
}
}
@@ -11165,17 +11771,17 @@ static int __devinit bnx2x_check_firmware(struct bnx2x *bp)
BCM_5710_FW_MINOR_VERSION,
BCM_5710_FW_REVISION_VERSION,
BCM_5710_FW_ENGINEERING_VERSION);
- return -EINVAL;
+ return -EINVAL;
}
return 0;
}
-static void inline be32_to_cpu_n(const u8 *_source, u8 *_target, u32 n)
+static inline void be32_to_cpu_n(const u8 *_source, u8 *_target, u32 n)
{
+ const __be32 *source = (const __be32 *)_source;
+ u32 *target = (u32 *)_target;
u32 i;
- const __be32 *source = (const __be32*)_source;
- u32 *target = (u32*)_target;
for (i = 0; i < n/4; i++)
target[i] = be32_to_cpu(source[i]);
@@ -11185,66 +11791,67 @@ static void inline be32_to_cpu_n(const u8 *_source, u8 *_target, u32 n)
Ops array is stored in the following format:
{op(8bit), offset(24bit, big endian), data(32bit, big endian)}
*/
-static void inline bnx2x_prep_ops(const u8 *_source, u8 *_target, u32 n)
+static inline void bnx2x_prep_ops(const u8 *_source, u8 *_target, u32 n)
{
+ const __be32 *source = (const __be32 *)_source;
+ struct raw_op *target = (struct raw_op *)_target;
u32 i, j, tmp;
- const __be32 *source = (const __be32*)_source;
- struct raw_op *target = (struct raw_op*)_target;
- for (i = 0, j = 0; i < n/8; i++, j+=2) {
+ for (i = 0, j = 0; i < n/8; i++, j += 2) {
tmp = be32_to_cpu(source[j]);
target[i].op = (tmp >> 24) & 0xff;
target[i].offset = tmp & 0xffffff;
target[i].raw_data = be32_to_cpu(source[j+1]);
}
}
-static void inline be16_to_cpu_n(const u8 *_source, u8 *_target, u32 n)
+
+static inline void be16_to_cpu_n(const u8 *_source, u8 *_target, u32 n)
{
+ const __be16 *source = (const __be16 *)_source;
+ u16 *target = (u16 *)_target;
u32 i;
- u16 *target = (u16*)_target;
- const __be16 *source = (const __be16*)_source;
for (i = 0; i < n/2; i++)
target[i] = be16_to_cpu(source[i]);
}
#define BNX2X_ALLOC_AND_SET(arr, lbl, func) \
- do { \
- u32 len = be32_to_cpu(fw_hdr->arr.len); \
- bp->arr = kmalloc(len, GFP_KERNEL); \
+ do { \
+ u32 len = be32_to_cpu(fw_hdr->arr.len); \
+ bp->arr = kmalloc(len, GFP_KERNEL); \
if (!bp->arr) { \
- printk(KERN_ERR PFX "Failed to allocate %d bytes for "#arr"\n", len); \
+ printk(KERN_ERR PFX "Failed to allocate %d bytes " \
+ "for "#arr"\n", len); \
goto lbl; \
} \
- func(bp->firmware->data + \
- be32_to_cpu(fw_hdr->arr.offset), \
- (u8*)bp->arr, len); \
+ func(bp->firmware->data + be32_to_cpu(fw_hdr->arr.offset), \
+ (u8 *)bp->arr, len); \
} while (0)
-
static int __devinit bnx2x_init_firmware(struct bnx2x *bp, struct device *dev)
{
char fw_file_name[40] = {0};
- int rc, offset;
struct bnx2x_fw_file_hdr *fw_hdr;
+ int rc, offset;
/* Create a FW file name */
if (CHIP_IS_E1(bp))
- offset = sprintf(fw_file_name, FW_FILE_PREFIX_E1);
+ offset = sprintf(fw_file_name, FW_FILE_PREFIX_E1);
else
offset = sprintf(fw_file_name, FW_FILE_PREFIX_E1H);
sprintf(fw_file_name + offset, "%d.%d.%d.%d.fw",
BCM_5710_FW_MAJOR_VERSION,
- BCM_5710_FW_MINOR_VERSION,
- BCM_5710_FW_REVISION_VERSION,
- BCM_5710_FW_ENGINEERING_VERSION);
+ BCM_5710_FW_MINOR_VERSION,
+ BCM_5710_FW_REVISION_VERSION,
+ BCM_5710_FW_ENGINEERING_VERSION);
printk(KERN_INFO PFX "Loading %s\n", fw_file_name);
rc = request_firmware(&bp->firmware, fw_file_name, dev);
if (rc) {
- printk(KERN_ERR PFX "Can't load firmware file %s\n", fw_file_name);
+ printk(KERN_ERR PFX "Can't load firmware file %s\n",
+ fw_file_name);
goto request_firmware_exit;
}
@@ -11264,27 +11871,29 @@ static int __devinit bnx2x_init_firmware(struct bnx2x *bp, struct device *dev)
BNX2X_ALLOC_AND_SET(init_ops, init_ops_alloc_err, bnx2x_prep_ops);
/* Offsets */
- BNX2X_ALLOC_AND_SET(init_ops_offsets, init_offsets_alloc_err, be16_to_cpu_n);
+ BNX2X_ALLOC_AND_SET(init_ops_offsets, init_offsets_alloc_err,
+ be16_to_cpu_n);
/* STORMs firmware */
- bp->tsem_int_table_data = bp->firmware->data +
- be32_to_cpu(fw_hdr->tsem_int_table_data.offset);
- bp->tsem_pram_data = bp->firmware->data +
- be32_to_cpu(fw_hdr->tsem_pram_data.offset);
- bp->usem_int_table_data = bp->firmware->data +
- be32_to_cpu(fw_hdr->usem_int_table_data.offset);
- bp->usem_pram_data = bp->firmware->data +
- be32_to_cpu(fw_hdr->usem_pram_data.offset);
- bp->xsem_int_table_data = bp->firmware->data +
- be32_to_cpu(fw_hdr->xsem_int_table_data.offset);
- bp->xsem_pram_data = bp->firmware->data +
- be32_to_cpu(fw_hdr->xsem_pram_data.offset);
- bp->csem_int_table_data = bp->firmware->data +
- be32_to_cpu(fw_hdr->csem_int_table_data.offset);
- bp->csem_pram_data = bp->firmware->data +
- be32_to_cpu(fw_hdr->csem_pram_data.offset);
+ INIT_TSEM_INT_TABLE_DATA(bp) = bp->firmware->data +
+ be32_to_cpu(fw_hdr->tsem_int_table_data.offset);
+ INIT_TSEM_PRAM_DATA(bp) = bp->firmware->data +
+ be32_to_cpu(fw_hdr->tsem_pram_data.offset);
+ INIT_USEM_INT_TABLE_DATA(bp) = bp->firmware->data +
+ be32_to_cpu(fw_hdr->usem_int_table_data.offset);
+ INIT_USEM_PRAM_DATA(bp) = bp->firmware->data +
+ be32_to_cpu(fw_hdr->usem_pram_data.offset);
+ INIT_XSEM_INT_TABLE_DATA(bp) = bp->firmware->data +
+ be32_to_cpu(fw_hdr->xsem_int_table_data.offset);
+ INIT_XSEM_PRAM_DATA(bp) = bp->firmware->data +
+ be32_to_cpu(fw_hdr->xsem_pram_data.offset);
+ INIT_CSEM_INT_TABLE_DATA(bp) = bp->firmware->data +
+ be32_to_cpu(fw_hdr->csem_int_table_data.offset);
+ INIT_CSEM_PRAM_DATA(bp) = bp->firmware->data +
+ be32_to_cpu(fw_hdr->csem_pram_data.offset);
return 0;
+
init_offsets_alloc_err:
kfree(bp->init_ops);
init_ops_alloc_err:
@@ -11296,18 +11905,14 @@ request_firmware_exit:
}
-
static int __devinit bnx2x_init_one(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
- static int version_printed;
struct net_device *dev = NULL;
struct bnx2x *bp;
+ int pcie_width, pcie_speed;
int rc;
- if (version_printed++ == 0)
- printk(KERN_INFO "%s", version);
-
/* dev zeroed in init_etherdev */
dev = alloc_etherdev_mq(sizeof(*bp), MAX_CONTEXT);
if (!dev) {
@@ -11318,14 +11923,14 @@ static int __devinit bnx2x_init_one(struct pci_dev *pdev,
bp = netdev_priv(dev);
bp->msglevel = debug;
+ pci_set_drvdata(pdev, dev);
+
rc = bnx2x_init_dev(pdev, dev);
if (rc < 0) {
free_netdev(dev);
return rc;
}
- pci_set_drvdata(pdev, dev);
-
rc = bnx2x_init_bp(bp);
if (rc)
goto init_one_exit;
@@ -11343,11 +11948,11 @@ static int __devinit bnx2x_init_one(struct pci_dev *pdev,
goto init_one_exit;
}
+ bnx2x_get_pcie_width_speed(bp, &pcie_width, &pcie_speed);
printk(KERN_INFO "%s: %s (%c%d) PCI-E x%d %s found at mem %lx,"
" IRQ %d, ", dev->name, board_info[ent->driver_data].name,
(CHIP_REV(bp) >> 12) + 'A', (CHIP_METAL(bp) >> 4),
- bnx2x_get_pcie_width(bp),
- (bnx2x_get_pcie_speed(bp) == 2) ? "5GHz (Gen2)" : "2.5GHz",
+ pcie_width, (pcie_speed == 2) ? "5GHz (Gen2)" : "2.5GHz",
dev->base_addr, bp->pdev->irq);
printk(KERN_CONT "node addr %pM\n", dev->dev_addr);
@@ -11554,6 +12159,11 @@ static pci_ers_result_t bnx2x_io_error_detected(struct pci_dev *pdev,
netif_device_detach(dev);
+ if (state == pci_channel_io_perm_failure) {
+ rtnl_unlock();
+ return PCI_ERS_RESULT_DISCONNECT;
+ }
+
if (netif_running(dev))
bnx2x_eeh_nic_unload(bp);
@@ -11640,6 +12250,8 @@ static int __init bnx2x_init(void)
{
int ret;
+ printk(KERN_INFO "%s", version);
+
bnx2x_wq = create_singlethread_workqueue("bnx2x");
if (bnx2x_wq == NULL) {
printk(KERN_ERR PFX "Cannot create workqueue\n");
diff --git a/drivers/net/bnx2x_reg.h b/drivers/net/bnx2x_reg.h
index b8ce6fc927a..0695be14cf9 100644
--- a/drivers/net/bnx2x_reg.h
+++ b/drivers/net/bnx2x_reg.h
@@ -190,12 +190,6 @@
_(0..15) stands for the connection type (one of 16). */
#define CCM_REG_N_SM_CTX_LD_0 0xd004c
#define CCM_REG_N_SM_CTX_LD_1 0xd0050
-#define CCM_REG_N_SM_CTX_LD_10 0xd0074
-#define CCM_REG_N_SM_CTX_LD_11 0xd0078
-#define CCM_REG_N_SM_CTX_LD_12 0xd007c
-#define CCM_REG_N_SM_CTX_LD_13 0xd0080
-#define CCM_REG_N_SM_CTX_LD_14 0xd0084
-#define CCM_REG_N_SM_CTX_LD_15 0xd0088
#define CCM_REG_N_SM_CTX_LD_2 0xd0054
#define CCM_REG_N_SM_CTX_LD_3 0xd0058
#define CCM_REG_N_SM_CTX_LD_4 0xd005c
@@ -370,7 +364,6 @@
#define CFC_REG_NUM_LCIDS_LEAVING 0x104018
/* [RW 8] The event id for aggregated interrupt 0 */
#define CSDM_REG_AGG_INT_EVENT_0 0xc2038
-#define CSDM_REG_AGG_INT_EVENT_1 0xc203c
#define CSDM_REG_AGG_INT_EVENT_10 0xc2060
#define CSDM_REG_AGG_INT_EVENT_11 0xc2064
#define CSDM_REG_AGG_INT_EVENT_12 0xc2068
@@ -378,37 +371,27 @@
#define CSDM_REG_AGG_INT_EVENT_14 0xc2070
#define CSDM_REG_AGG_INT_EVENT_15 0xc2074
#define CSDM_REG_AGG_INT_EVENT_16 0xc2078
-#define CSDM_REG_AGG_INT_EVENT_17 0xc207c
-#define CSDM_REG_AGG_INT_EVENT_18 0xc2080
-#define CSDM_REG_AGG_INT_EVENT_19 0xc2084
#define CSDM_REG_AGG_INT_EVENT_2 0xc2040
-#define CSDM_REG_AGG_INT_EVENT_20 0xc2088
-#define CSDM_REG_AGG_INT_EVENT_21 0xc208c
-#define CSDM_REG_AGG_INT_EVENT_22 0xc2090
-#define CSDM_REG_AGG_INT_EVENT_23 0xc2094
-#define CSDM_REG_AGG_INT_EVENT_24 0xc2098
-#define CSDM_REG_AGG_INT_EVENT_25 0xc209c
-#define CSDM_REG_AGG_INT_EVENT_26 0xc20a0
-#define CSDM_REG_AGG_INT_EVENT_27 0xc20a4
-#define CSDM_REG_AGG_INT_EVENT_28 0xc20a8
-#define CSDM_REG_AGG_INT_EVENT_29 0xc20ac
#define CSDM_REG_AGG_INT_EVENT_3 0xc2044
-#define CSDM_REG_AGG_INT_EVENT_30 0xc20b0
-#define CSDM_REG_AGG_INT_EVENT_31 0xc20b4
#define CSDM_REG_AGG_INT_EVENT_4 0xc2048
-/* [RW 1] The T bit for aggregated interrupt 0 */
-#define CSDM_REG_AGG_INT_T_0 0xc20b8
-#define CSDM_REG_AGG_INT_T_1 0xc20bc
-#define CSDM_REG_AGG_INT_T_10 0xc20e0
-#define CSDM_REG_AGG_INT_T_11 0xc20e4
-#define CSDM_REG_AGG_INT_T_12 0xc20e8
-#define CSDM_REG_AGG_INT_T_13 0xc20ec
-#define CSDM_REG_AGG_INT_T_14 0xc20f0
-#define CSDM_REG_AGG_INT_T_15 0xc20f4
-#define CSDM_REG_AGG_INT_T_16 0xc20f8
-#define CSDM_REG_AGG_INT_T_17 0xc20fc
-#define CSDM_REG_AGG_INT_T_18 0xc2100
-#define CSDM_REG_AGG_INT_T_19 0xc2104
+#define CSDM_REG_AGG_INT_EVENT_5 0xc204c
+#define CSDM_REG_AGG_INT_EVENT_6 0xc2050
+#define CSDM_REG_AGG_INT_EVENT_7 0xc2054
+#define CSDM_REG_AGG_INT_EVENT_8 0xc2058
+#define CSDM_REG_AGG_INT_EVENT_9 0xc205c
+/* [RW 1] For each aggregated interrupt index whether the mode is normal (0)
+ or auto-mask-mode (1) */
+#define CSDM_REG_AGG_INT_MODE_10 0xc21e0
+#define CSDM_REG_AGG_INT_MODE_11 0xc21e4
+#define CSDM_REG_AGG_INT_MODE_12 0xc21e8
+#define CSDM_REG_AGG_INT_MODE_13 0xc21ec
+#define CSDM_REG_AGG_INT_MODE_14 0xc21f0
+#define CSDM_REG_AGG_INT_MODE_15 0xc21f4
+#define CSDM_REG_AGG_INT_MODE_16 0xc21f8
+#define CSDM_REG_AGG_INT_MODE_6 0xc21d0
+#define CSDM_REG_AGG_INT_MODE_7 0xc21d4
+#define CSDM_REG_AGG_INT_MODE_8 0xc21d8
+#define CSDM_REG_AGG_INT_MODE_9 0xc21dc
/* [RW 13] The start address in the internal RAM for the cfc_rsp lcid */
#define CSDM_REG_CFC_RSP_START_ADDR 0xc2008
/* [RW 16] The maximum value of the competion counter #0 */
@@ -633,24 +616,6 @@
#define DMAE_REG_GO_C1 0x102084
/* [RW 1] Command 10 go. */
#define DMAE_REG_GO_C10 0x102088
-#define DMAE_REG_GO_C10_SIZE 1
-/* [RW 1] Command 11 go. */
-#define DMAE_REG_GO_C11 0x10208c
-#define DMAE_REG_GO_C11_SIZE 1
-/* [RW 1] Command 12 go. */
-#define DMAE_REG_GO_C12 0x102090
-#define DMAE_REG_GO_C12_SIZE 1
-/* [RW 1] Command 13 go. */
-#define DMAE_REG_GO_C13 0x102094
-#define DMAE_REG_GO_C13_SIZE 1
-/* [RW 1] Command 14 go. */
-#define DMAE_REG_GO_C14 0x102098
-#define DMAE_REG_GO_C14_SIZE 1
-/* [RW 1] Command 15 go. */
-#define DMAE_REG_GO_C15 0x10209c
-#define DMAE_REG_GO_C15_SIZE 1
-/* [RW 1] Command 10 go. */
-#define DMAE_REG_GO_C10 0x102088
/* [RW 1] Command 11 go. */
#define DMAE_REG_GO_C11 0x10208c
/* [RW 1] Command 12 go. */
@@ -800,7 +765,6 @@
#define MCP_REG_MCPR_NVM_READ 0x86410
#define MCP_REG_MCPR_NVM_SW_ARB 0x86420
#define MCP_REG_MCPR_NVM_WRITE 0x86408
-#define MCP_REG_MCPR_NVM_WRITE1 0x86428
#define MCP_REG_MCPR_SCRATCH 0xa0000
/* [R 32] read first 32 bit after inversion of function 0. mapped as
follows: [0] NIG attention for function0; [1] NIG attention for
@@ -1186,19 +1150,7 @@
#define MISC_REG_AEU_GENERAL_ATTN_10 0xa028
#define MISC_REG_AEU_GENERAL_ATTN_11 0xa02c
#define MISC_REG_AEU_GENERAL_ATTN_12 0xa030
-#define MISC_REG_AEU_GENERAL_ATTN_13 0xa034
-#define MISC_REG_AEU_GENERAL_ATTN_14 0xa038
-#define MISC_REG_AEU_GENERAL_ATTN_15 0xa03c
-#define MISC_REG_AEU_GENERAL_ATTN_16 0xa040
-#define MISC_REG_AEU_GENERAL_ATTN_17 0xa044
-#define MISC_REG_AEU_GENERAL_ATTN_18 0xa048
-#define MISC_REG_AEU_GENERAL_ATTN_19 0xa04c
-#define MISC_REG_AEU_GENERAL_ATTN_10 0xa028
-#define MISC_REG_AEU_GENERAL_ATTN_11 0xa02c
-#define MISC_REG_AEU_GENERAL_ATTN_12 0xa030
#define MISC_REG_AEU_GENERAL_ATTN_2 0xa008
-#define MISC_REG_AEU_GENERAL_ATTN_20 0xa050
-#define MISC_REG_AEU_GENERAL_ATTN_21 0xa054
#define MISC_REG_AEU_GENERAL_ATTN_3 0xa00c
#define MISC_REG_AEU_GENERAL_ATTN_4 0xa010
#define MISC_REG_AEU_GENERAL_ATTN_5 0xa014
@@ -1290,137 +1242,13 @@
set. if the appropriate bit is clear (the driver request to free a client
it doesn't controls the ~MISC_REGISTERS_INT_STS.GENERIC_SW interrupt will
be asserted). */
-#define MISC_REG_DRIVER_CONTROL_10 0xa3e0
-#define MISC_REG_DRIVER_CONTROL_10_SIZE 2
-/* [RW 32] The following driver registers(1...16) represent 16 drivers and
- 32 clients. Each client can be controlled by one driver only. One in each
- bit represent that this driver control the appropriate client (Ex: bit 5
- is set means this driver control client number 5). addr1 = set; addr0 =
- clear; read from both addresses will give the same result = status. write
- to address 1 will set a request to control all the clients that their
- appropriate bit (in the write command) is set. if the client is free (the
- appropriate bit in all the other drivers is clear) one will be written to
- that driver register; if the client isn't free the bit will remain zero.
- if the appropriate bit is set (the driver request to gain control on a
- client it already controls the ~MISC_REGISTERS_INT_STS.GENERIC_SW
- interrupt will be asserted). write to address 0 will set a request to
- free all the clients that their appropriate bit (in the write command) is
- set. if the appropriate bit is clear (the driver request to free a client
- it doesn't controls the ~MISC_REGISTERS_INT_STS.GENERIC_SW interrupt will
- be asserted). */
-#define MISC_REG_DRIVER_CONTROL_11 0xa3e8
-#define MISC_REG_DRIVER_CONTROL_11_SIZE 2
-/* [RW 32] The following driver registers(1...16) represent 16 drivers and
- 32 clients. Each client can be controlled by one driver only. One in each
- bit represent that this driver control the appropriate client (Ex: bit 5
- is set means this driver control client number 5). addr1 = set; addr0 =
- clear; read from both addresses will give the same result = status. write
- to address 1 will set a request to control all the clients that their
- appropriate bit (in the write command) is set. if the client is free (the
- appropriate bit in all the other drivers is clear) one will be written to
- that driver register; if the client isn't free the bit will remain zero.
- if the appropriate bit is set (the driver request to gain control on a
- client it already controls the ~MISC_REGISTERS_INT_STS.GENERIC_SW
- interrupt will be asserted). write to address 0 will set a request to
- free all the clients that their appropriate bit (in the write command) is
- set. if the appropriate bit is clear (the driver request to free a client
- it doesn't controls the ~MISC_REGISTERS_INT_STS.GENERIC_SW interrupt will
- be asserted). */
-#define MISC_REG_DRIVER_CONTROL_12 0xa3f0
-#define MISC_REG_DRIVER_CONTROL_12_SIZE 2
-/* [RW 32] The following driver registers(1...16) represent 16 drivers and
- 32 clients. Each client can be controlled by one driver only. One in each
- bit represent that this driver control the appropriate client (Ex: bit 5
- is set means this driver control client number 5). addr1 = set; addr0 =
- clear; read from both addresses will give the same result = status. write
- to address 1 will set a request to control all the clients that their
- appropriate bit (in the write command) is set. if the client is free (the
- appropriate bit in all the other drivers is clear) one will be written to
- that driver register; if the client isn't free the bit will remain zero.
- if the appropriate bit is set (the driver request to gain control on a
- client it already controls the ~MISC_REGISTERS_INT_STS.GENERIC_SW
- interrupt will be asserted). write to address 0 will set a request to
- free all the clients that their appropriate bit (in the write command) is
- set. if the appropriate bit is clear (the driver request to free a client
- it doesn't controls the ~MISC_REGISTERS_INT_STS.GENERIC_SW interrupt will
- be asserted). */
-#define MISC_REG_DRIVER_CONTROL_13 0xa3f8
-#define MISC_REG_DRIVER_CONTROL_13_SIZE 2
-/* [RW 32] The following driver registers(1...16) represent 16 drivers and
- 32 clients. Each client can be controlled by one driver only. One in each
- bit represent that this driver control the appropriate client (Ex: bit 5
- is set means this driver control client number 5). addr1 = set; addr0 =
- clear; read from both addresses will give the same result = status. write
- to address 1 will set a request to control all the clients that their
- appropriate bit (in the write command) is set. if the client is free (the
- appropriate bit in all the other drivers is clear) one will be written to
- that driver register; if the client isn't free the bit will remain zero.
- if the appropriate bit is set (the driver request to gain control on a
- client it already controls the ~MISC_REGISTERS_INT_STS.GENERIC_SW
- interrupt will be asserted). write to address 0 will set a request to
- free all the clients that their appropriate bit (in the write command) is
- set. if the appropriate bit is clear (the driver request to free a client
- it doesn't controls the ~MISC_REGISTERS_INT_STS.GENERIC_SW interrupt will
- be asserted). */
#define MISC_REG_DRIVER_CONTROL_1 0xa510
-#define MISC_REG_DRIVER_CONTROL_14 0xa5e0
-#define MISC_REG_DRIVER_CONTROL_14_SIZE 2
-/* [RW 32] The following driver registers(1...16) represent 16 drivers and
- 32 clients. Each client can be controlled by one driver only. One in each
- bit represent that this driver control the appropriate client (Ex: bit 5
- is set means this driver control client number 5). addr1 = set; addr0 =
- clear; read from both addresses will give the same result = status. write
- to address 1 will set a request to control all the clients that their
- appropriate bit (in the write command) is set. if the client is free (the
- appropriate bit in all the other drivers is clear) one will be written to
- that driver register; if the client isn't free the bit will remain zero.
- if the appropriate bit is set (the driver request to gain control on a
- client it already controls the ~MISC_REGISTERS_INT_STS.GENERIC_SW
- interrupt will be asserted). write to address 0 will set a request to
- free all the clients that their appropriate bit (in the write command) is
- set. if the appropriate bit is clear (the driver request to free a client
- it doesn't controls the ~MISC_REGISTERS_INT_STS.GENERIC_SW interrupt will
- be asserted). */
-#define MISC_REG_DRIVER_CONTROL_15 0xa5e8
-#define MISC_REG_DRIVER_CONTROL_15_SIZE 2
-/* [RW 32] The following driver registers(1...16) represent 16 drivers and
- 32 clients. Each client can be controlled by one driver only. One in each
- bit represent that this driver control the appropriate client (Ex: bit 5
- is set means this driver control client number 5). addr1 = set; addr0 =
- clear; read from both addresses will give the same result = status. write
- to address 1 will set a request to control all the clients that their
- appropriate bit (in the write command) is set. if the client is free (the
- appropriate bit in all the other drivers is clear) one will be written to
- that driver register; if the client isn't free the bit will remain zero.
- if the appropriate bit is set (the driver request to gain control on a
- client it already controls the ~MISC_REGISTERS_INT_STS.GENERIC_SW
- interrupt will be asserted). write to address 0 will set a request to
- free all the clients that their appropriate bit (in the write command) is
- set. if the appropriate bit is clear (the driver request to free a client
- it doesn't controls the ~MISC_REGISTERS_INT_STS.GENERIC_SW interrupt will
- be asserted). */
-#define MISC_REG_DRIVER_CONTROL_16 0xa5f0
-#define MISC_REG_DRIVER_CONTROL_16_SIZE 2
-/* [RW 32] The following driver registers(1...16) represent 16 drivers and
- 32 clients. Each client can be controlled by one driver only. One in each
- bit represent that this driver control the appropriate client (Ex: bit 5
- is set means this driver control client number 5). addr1 = set; addr0 =
- clear; read from both addresses will give the same result = status. write
- to address 1 will set a request to control all the clients that their
- appropriate bit (in the write command) is set. if the client is free (the
- appropriate bit in all the other drivers is clear) one will be written to
- that driver register; if the client isn't free the bit will remain zero.
- if the appropriate bit is set (the driver request to gain control on a
- client it already controls the ~MISC_REGISTERS_INT_STS.GENERIC_SW
- interrupt will be asserted). write to address 0 will set a request to
- free all the clients that their appropriate bit (in the write command) is
- set. if the appropriate bit is clear (the driver request to free a client
- it doesn't controls the ~MISC_REGISTERS_INT_STS.GENERIC_SW interrupt will
- be asserted). */
#define MISC_REG_DRIVER_CONTROL_7 0xa3c8
/* [RW 1] e1hmf for WOL. If clr WOL signal o the PXP will be send on bit 0
only. */
#define MISC_REG_E1HMF_MODE 0xa5f8
+/* [RW 32] Debug only: spare RW register reset by core reset */
+#define MISC_REG_GENERIC_CR_0 0xa460
/* [RW 32] GPIO. [31-28] FLOAT port 0; [27-24] FLOAT port 0; When any of
these bits is written as a '1'; the corresponding SPIO bit will turn off
it's drivers and become an input. This is the reset state of all GPIO
@@ -1616,6 +1444,11 @@
/* [RW 1] Set by the MCP to remember if one or more of the drivers is/are
loaded; 0-prepare; -unprepare */
#define MISC_REG_UNPREPARED 0xa424
+#define NIG_LLH0_BRB1_DRV_MASK_REG_LLH0_BRB1_DRV_MASK_BRCST (0x1<<0)
+#define NIG_LLH0_BRB1_DRV_MASK_REG_LLH0_BRB1_DRV_MASK_MLCST (0x1<<1)
+#define NIG_LLH0_BRB1_DRV_MASK_REG_LLH0_BRB1_DRV_MASK_NO_VLAN (0x1<<4)
+#define NIG_LLH0_BRB1_DRV_MASK_REG_LLH0_BRB1_DRV_MASK_UNCST (0x1<<2)
+#define NIG_LLH0_BRB1_DRV_MASK_REG_LLH0_BRB1_DRV_MASK_VLAN (0x1<<3)
#define NIG_MASK_INTERRUPT_PORT0_REG_MASK_EMAC0_MISC_MI_INT (0x1<<0)
#define NIG_MASK_INTERRUPT_PORT0_REG_MASK_SERDES0_LINK_STATUS (0x1<<9)
#define NIG_MASK_INTERRUPT_PORT0_REG_MASK_XGXS0_LINK10G (0x1<<15)
@@ -1654,12 +1487,12 @@
/* [RW 1] MAC configuration for packets of port0. If 1 - all packet outputs
to emac for port0; other way to bmac for port0 */
#define NIG_REG_EGRESS_EMAC0_PORT 0x10058
-/* [RW 32] TX_MNG_FIFO in NIG_TX_PORT0; data[31:0] written in FIFO order. */
-#define NIG_REG_EGRESS_MNG0_FIFO 0x1045c
/* [RW 1] Input enable for TX PBF user packet port0 IF */
#define NIG_REG_EGRESS_PBF0_IN_EN 0x100cc
/* [RW 1] Input enable for TX PBF user packet port1 IF */
#define NIG_REG_EGRESS_PBF1_IN_EN 0x100d0
+/* [RW 1] Input enable for TX UMP management packet port0 IF */
+#define NIG_REG_EGRESS_UMP0_IN_EN 0x100d4
/* [RW 1] Input enable for RX_EMAC0 IF */
#define NIG_REG_EMAC0_IN_EN 0x100a4
/* [RW 1] output enable for TX EMAC pause port 0 IF */
@@ -1683,6 +1516,24 @@
/* [RW 17] Debug only. RX_EOP_DSCR_lb_FIFO in NIG_RX_EOP. Data
packet_length[13:0]; mac_error[14]; trunc_error[15]; parity[16] */
#define NIG_REG_INGRESS_EOP_LB_FIFO 0x104e4
+/* [RW 27] 0 - must be active for Everest A0; 1- for Everest B0 when latch
+ logic for interrupts must be used. Enable per bit of interrupt of
+ ~latch_status.latch_status */
+#define NIG_REG_LATCH_BC_0 0x16210
+/* [RW 27] Latch for each interrupt from Unicore.b[0]
+ status_emac0_misc_mi_int; b[1] status_emac0_misc_mi_complete;
+ b[2]status_emac0_misc_cfg_change; b[3]status_emac0_misc_link_status;
+ b[4]status_emac0_misc_link_change; b[5]status_emac0_misc_attn;
+ b[6]status_serdes0_mac_crs; b[7]status_serdes0_autoneg_complete;
+ b[8]status_serdes0_fiber_rxact; b[9]status_serdes0_link_status;
+ b[10]status_serdes0_mr_page_rx; b[11]status_serdes0_cl73_an_complete;
+ b[12]status_serdes0_cl73_mr_page_rx; b[13]status_serdes0_rx_sigdet;
+ b[14]status_xgxs0_remotemdioreq; b[15]status_xgxs0_link10g;
+ b[16]status_xgxs0_autoneg_complete; b[17]status_xgxs0_fiber_rxact;
+ b[21:18]status_xgxs0_link_status; b[22]status_xgxs0_mr_page_rx;
+ b[23]status_xgxs0_cl73_an_complete; b[24]status_xgxs0_cl73_mr_page_rx;
+ b[25]status_xgxs0_rx_sigdet; b[26]status_xgxs0_mac_crs */
+#define NIG_REG_LATCH_STATUS_0 0x18000
/* [RW 1] led 10g for port 0 */
#define NIG_REG_LED_10G_P0 0x10320
/* [RW 1] led 10g for port 1 */
@@ -1722,6 +1573,7 @@
/* [RW 3] for port0 enable for llfc ppp and pause. b0 - brb1 enable; b1-
tsdm enable; b2- usdm enable */
#define NIG_REG_LLFC_EGRESS_SRC_ENABLE_0 0x16070
+#define NIG_REG_LLFC_EGRESS_SRC_ENABLE_1 0x16074
/* [RW 1] SAFC enable for port0. This register may get 1 only when
~ppp_enable.ppp_enable = 0 and pause_enable.pause_enable =0 for the same
port */
@@ -1872,6 +1724,7 @@
#define NIG_REG_XGXS_LANE_SEL_P0 0x102e8
/* [RW 1] selection for port0 for NIG_MUX block : 0 = SerDes; 1 = XGXS */
#define NIG_REG_XGXS_SERDES0_MODE_SEL 0x102e0
+#define NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_EMAC0_MISC_MI_INT (0x1<<0)
#define NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_SERDES0_LINK_STATUS (0x1<<9)
#define NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_XGXS0_LINK10G (0x1<<15)
#define NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_XGXS0_LINK_STATUS (0xf<<18)
@@ -2072,6 +1925,7 @@
#define PXP2_REG_PGL_ADDR_94_F0 0x120540
#define PXP2_REG_PGL_CONTROL0 0x120490
#define PXP2_REG_PGL_CONTROL1 0x120514
+#define PXP2_REG_PGL_DEBUG 0x120520
/* [RW 32] third dword data of expansion rom request. this register is
special. reading from it provides a vector outstanding read requests. if
a bit is zero it means that a read request on the corresponding tag did
@@ -2142,11 +1996,8 @@
#define PXP2_REG_PSWRQ_BW_ADD1 0x1201c0
#define PXP2_REG_PSWRQ_BW_ADD10 0x1201e4
#define PXP2_REG_PSWRQ_BW_ADD11 0x1201e8
-#define PXP2_REG_PSWRQ_BW_ADD10 0x1201e4
-#define PXP2_REG_PSWRQ_BW_ADD11 0x1201e8
#define PXP2_REG_PSWRQ_BW_ADD2 0x1201c4
#define PXP2_REG_PSWRQ_BW_ADD28 0x120228
-#define PXP2_REG_PSWRQ_BW_ADD28 0x120228
#define PXP2_REG_PSWRQ_BW_ADD3 0x1201c8
#define PXP2_REG_PSWRQ_BW_ADD6 0x1201d4
#define PXP2_REG_PSWRQ_BW_ADD7 0x1201d8
@@ -2156,11 +2007,8 @@
#define PXP2_REG_PSWRQ_BW_L1 0x1202b0
#define PXP2_REG_PSWRQ_BW_L10 0x1202d4
#define PXP2_REG_PSWRQ_BW_L11 0x1202d8
-#define PXP2_REG_PSWRQ_BW_L10 0x1202d4
-#define PXP2_REG_PSWRQ_BW_L11 0x1202d8
#define PXP2_REG_PSWRQ_BW_L2 0x1202b4
#define PXP2_REG_PSWRQ_BW_L28 0x120318
-#define PXP2_REG_PSWRQ_BW_L28 0x120318
#define PXP2_REG_PSWRQ_BW_L3 0x1202b8
#define PXP2_REG_PSWRQ_BW_L6 0x1202c4
#define PXP2_REG_PSWRQ_BW_L7 0x1202c8
@@ -2170,11 +2018,8 @@
#define PXP2_REG_PSWRQ_BW_UB1 0x120238
#define PXP2_REG_PSWRQ_BW_UB10 0x12025c
#define PXP2_REG_PSWRQ_BW_UB11 0x120260
-#define PXP2_REG_PSWRQ_BW_UB10 0x12025c
-#define PXP2_REG_PSWRQ_BW_UB11 0x120260
#define PXP2_REG_PSWRQ_BW_UB2 0x12023c
#define PXP2_REG_PSWRQ_BW_UB28 0x1202a0
-#define PXP2_REG_PSWRQ_BW_UB28 0x1202a0
#define PXP2_REG_PSWRQ_BW_UB3 0x120240
#define PXP2_REG_PSWRQ_BW_UB6 0x12024c
#define PXP2_REG_PSWRQ_BW_UB7 0x120250
@@ -2232,6 +2077,9 @@
allocated for vq22 */
#define PXP2_REG_RD_MAX_BLKS_VQ22 0x1203d0
/* [RW 8] The maximum number of blocks in Tetris Buffer that can be
+ allocated for vq25 */
+#define PXP2_REG_RD_MAX_BLKS_VQ25 0x1203dc
+/* [RW 8] The maximum number of blocks in Tetris Buffer that can be
allocated for vq6 */
#define PXP2_REG_RD_MAX_BLKS_VQ6 0x120390
/* [RW 8] The maximum number of blocks in Tetris Buffer that can be
@@ -2762,16 +2610,6 @@
#define QM_REG_QVOQIDX_107 0x16e4b8
#define QM_REG_QVOQIDX_108 0x16e4bc
#define QM_REG_QVOQIDX_109 0x16e4c0
-#define QM_REG_QVOQIDX_100 0x16e49c
-#define QM_REG_QVOQIDX_101 0x16e4a0
-#define QM_REG_QVOQIDX_102 0x16e4a4
-#define QM_REG_QVOQIDX_103 0x16e4a8
-#define QM_REG_QVOQIDX_104 0x16e4ac
-#define QM_REG_QVOQIDX_105 0x16e4b0
-#define QM_REG_QVOQIDX_106 0x16e4b4
-#define QM_REG_QVOQIDX_107 0x16e4b8
-#define QM_REG_QVOQIDX_108 0x16e4bc
-#define QM_REG_QVOQIDX_109 0x16e4c0
#define QM_REG_QVOQIDX_11 0x168120
#define QM_REG_QVOQIDX_110 0x16e4c4
#define QM_REG_QVOQIDX_111 0x16e4c8
@@ -2783,16 +2621,6 @@
#define QM_REG_QVOQIDX_117 0x16e4e0
#define QM_REG_QVOQIDX_118 0x16e4e4
#define QM_REG_QVOQIDX_119 0x16e4e8
-#define QM_REG_QVOQIDX_110 0x16e4c4
-#define QM_REG_QVOQIDX_111 0x16e4c8
-#define QM_REG_QVOQIDX_112 0x16e4cc
-#define QM_REG_QVOQIDX_113 0x16e4d0
-#define QM_REG_QVOQIDX_114 0x16e4d4
-#define QM_REG_QVOQIDX_115 0x16e4d8
-#define QM_REG_QVOQIDX_116 0x16e4dc
-#define QM_REG_QVOQIDX_117 0x16e4e0
-#define QM_REG_QVOQIDX_118 0x16e4e4
-#define QM_REG_QVOQIDX_119 0x16e4e8
#define QM_REG_QVOQIDX_12 0x168124
#define QM_REG_QVOQIDX_120 0x16e4ec
#define QM_REG_QVOQIDX_121 0x16e4f0
@@ -2802,14 +2630,6 @@
#define QM_REG_QVOQIDX_125 0x16e500
#define QM_REG_QVOQIDX_126 0x16e504
#define QM_REG_QVOQIDX_127 0x16e508
-#define QM_REG_QVOQIDX_120 0x16e4ec
-#define QM_REG_QVOQIDX_121 0x16e4f0
-#define QM_REG_QVOQIDX_122 0x16e4f4
-#define QM_REG_QVOQIDX_123 0x16e4f8
-#define QM_REG_QVOQIDX_124 0x16e4fc
-#define QM_REG_QVOQIDX_125 0x16e500
-#define QM_REG_QVOQIDX_126 0x16e504
-#define QM_REG_QVOQIDX_127 0x16e508
#define QM_REG_QVOQIDX_13 0x168128
#define QM_REG_QVOQIDX_14 0x16812c
#define QM_REG_QVOQIDX_15 0x168130
@@ -2855,16 +2675,6 @@
#define QM_REG_QVOQIDX_57 0x1681d8
#define QM_REG_QVOQIDX_58 0x1681dc
#define QM_REG_QVOQIDX_59 0x1681e0
-#define QM_REG_QVOQIDX_50 0x1681bc
-#define QM_REG_QVOQIDX_51 0x1681c0
-#define QM_REG_QVOQIDX_52 0x1681c4
-#define QM_REG_QVOQIDX_53 0x1681c8
-#define QM_REG_QVOQIDX_54 0x1681cc
-#define QM_REG_QVOQIDX_55 0x1681d0
-#define QM_REG_QVOQIDX_56 0x1681d4
-#define QM_REG_QVOQIDX_57 0x1681d8
-#define QM_REG_QVOQIDX_58 0x1681dc
-#define QM_REG_QVOQIDX_59 0x1681e0
#define QM_REG_QVOQIDX_6 0x16810c
#define QM_REG_QVOQIDX_60 0x1681e4
#define QM_REG_QVOQIDX_61 0x1681e8
@@ -2872,16 +2682,6 @@
#define QM_REG_QVOQIDX_63 0x1681f0
#define QM_REG_QVOQIDX_64 0x16e40c
#define QM_REG_QVOQIDX_65 0x16e410
-#define QM_REG_QVOQIDX_66 0x16e414
-#define QM_REG_QVOQIDX_67 0x16e418
-#define QM_REG_QVOQIDX_68 0x16e41c
-#define QM_REG_QVOQIDX_69 0x16e420
-#define QM_REG_QVOQIDX_60 0x1681e4
-#define QM_REG_QVOQIDX_61 0x1681e8
-#define QM_REG_QVOQIDX_62 0x1681ec
-#define QM_REG_QVOQIDX_63 0x1681f0
-#define QM_REG_QVOQIDX_64 0x16e40c
-#define QM_REG_QVOQIDX_65 0x16e410
#define QM_REG_QVOQIDX_69 0x16e420
#define QM_REG_QVOQIDX_7 0x168110
#define QM_REG_QVOQIDX_70 0x16e424
@@ -2894,29 +2694,9 @@
#define QM_REG_QVOQIDX_77 0x16e440
#define QM_REG_QVOQIDX_78 0x16e444
#define QM_REG_QVOQIDX_79 0x16e448
-#define QM_REG_QVOQIDX_70 0x16e424
-#define QM_REG_QVOQIDX_71 0x16e428
-#define QM_REG_QVOQIDX_72 0x16e42c
-#define QM_REG_QVOQIDX_73 0x16e430
-#define QM_REG_QVOQIDX_74 0x16e434
-#define QM_REG_QVOQIDX_75 0x16e438
-#define QM_REG_QVOQIDX_76 0x16e43c
-#define QM_REG_QVOQIDX_77 0x16e440
-#define QM_REG_QVOQIDX_78 0x16e444
-#define QM_REG_QVOQIDX_79 0x16e448
#define QM_REG_QVOQIDX_8 0x168114
#define QM_REG_QVOQIDX_80 0x16e44c
#define QM_REG_QVOQIDX_81 0x16e450
-#define QM_REG_QVOQIDX_82 0x16e454
-#define QM_REG_QVOQIDX_83 0x16e458
-#define QM_REG_QVOQIDX_84 0x16e45c
-#define QM_REG_QVOQIDX_85 0x16e460
-#define QM_REG_QVOQIDX_86 0x16e464
-#define QM_REG_QVOQIDX_87 0x16e468
-#define QM_REG_QVOQIDX_88 0x16e46c
-#define QM_REG_QVOQIDX_89 0x16e470
-#define QM_REG_QVOQIDX_80 0x16e44c
-#define QM_REG_QVOQIDX_81 0x16e450
#define QM_REG_QVOQIDX_85 0x16e460
#define QM_REG_QVOQIDX_86 0x16e464
#define QM_REG_QVOQIDX_87 0x16e468
@@ -2933,23 +2713,11 @@
#define QM_REG_QVOQIDX_97 0x16e490
#define QM_REG_QVOQIDX_98 0x16e494
#define QM_REG_QVOQIDX_99 0x16e498
-#define QM_REG_QVOQIDX_90 0x16e474
-#define QM_REG_QVOQIDX_91 0x16e478
-#define QM_REG_QVOQIDX_92 0x16e47c
-#define QM_REG_QVOQIDX_93 0x16e480
-#define QM_REG_QVOQIDX_94 0x16e484
-#define QM_REG_QVOQIDX_95 0x16e488
-#define QM_REG_QVOQIDX_96 0x16e48c
-#define QM_REG_QVOQIDX_97 0x16e490
-#define QM_REG_QVOQIDX_98 0x16e494
-#define QM_REG_QVOQIDX_99 0x16e498
/* [RW 1] Initialization bit command */
#define QM_REG_SOFT_RESET 0x168428
/* [RW 8] The credit cost per every task in the QM. A value per each VOQ */
#define QM_REG_TASKCRDCOST_0 0x16809c
#define QM_REG_TASKCRDCOST_1 0x1680a0
-#define QM_REG_TASKCRDCOST_10 0x1680c4
-#define QM_REG_TASKCRDCOST_11 0x1680c8
#define QM_REG_TASKCRDCOST_2 0x1680a4
#define QM_REG_TASKCRDCOST_4 0x1680ac
#define QM_REG_TASKCRDCOST_5 0x1680b0
@@ -2962,24 +2730,18 @@
/* [R 16] The credit value for each VOQ */
#define QM_REG_VOQCREDIT_0 0x1682d0
#define QM_REG_VOQCREDIT_1 0x1682d4
-#define QM_REG_VOQCREDIT_10 0x1682f8
-#define QM_REG_VOQCREDIT_11 0x1682fc
#define QM_REG_VOQCREDIT_4 0x1682e0
/* [RW 16] The credit value that if above the QM is considered almost full */
#define QM_REG_VOQCREDITAFULLTHR 0x168090
/* [RW 16] The init and maximum credit for each VoQ */
#define QM_REG_VOQINITCREDIT_0 0x168060
#define QM_REG_VOQINITCREDIT_1 0x168064
-#define QM_REG_VOQINITCREDIT_10 0x168088
-#define QM_REG_VOQINITCREDIT_11 0x16808c
#define QM_REG_VOQINITCREDIT_2 0x168068
#define QM_REG_VOQINITCREDIT_4 0x168070
#define QM_REG_VOQINITCREDIT_5 0x168074
/* [RW 1] The port of which VOQ belongs */
#define QM_REG_VOQPORT_0 0x1682a0
#define QM_REG_VOQPORT_1 0x1682a4
-#define QM_REG_VOQPORT_10 0x1682c8
-#define QM_REG_VOQPORT_11 0x1682cc
#define QM_REG_VOQPORT_2 0x1682a8
/* [RW 32] The physical queue number associated with each VOQ; queues 31-0 */
#define QM_REG_VOQQMASK_0_LSB 0x168240
@@ -3077,36 +2839,6 @@
#define QM_REG_WRRWEIGHTS_0 0x16880c
#define QM_REG_WRRWEIGHTS_1 0x168810
#define QM_REG_WRRWEIGHTS_10 0x168814
-#define QM_REG_WRRWEIGHTS_10_SIZE 1
-/* [RW 32] Wrr weights */
-#define QM_REG_WRRWEIGHTS_11 0x168818
-#define QM_REG_WRRWEIGHTS_11_SIZE 1
-/* [RW 32] Wrr weights */
-#define QM_REG_WRRWEIGHTS_12 0x16881c
-#define QM_REG_WRRWEIGHTS_12_SIZE 1
-/* [RW 32] Wrr weights */
-#define QM_REG_WRRWEIGHTS_13 0x168820
-#define QM_REG_WRRWEIGHTS_13_SIZE 1
-/* [RW 32] Wrr weights */
-#define QM_REG_WRRWEIGHTS_14 0x168824
-#define QM_REG_WRRWEIGHTS_14_SIZE 1
-/* [RW 32] Wrr weights */
-#define QM_REG_WRRWEIGHTS_15 0x168828
-#define QM_REG_WRRWEIGHTS_15_SIZE 1
-/* [RW 32] Wrr weights */
-#define QM_REG_WRRWEIGHTS_16 0x16e000
-#define QM_REG_WRRWEIGHTS_16_SIZE 1
-/* [RW 32] Wrr weights */
-#define QM_REG_WRRWEIGHTS_17 0x16e004
-#define QM_REG_WRRWEIGHTS_17_SIZE 1
-/* [RW 32] Wrr weights */
-#define QM_REG_WRRWEIGHTS_18 0x16e008
-#define QM_REG_WRRWEIGHTS_18_SIZE 1
-/* [RW 32] Wrr weights */
-#define QM_REG_WRRWEIGHTS_19 0x16e00c
-#define QM_REG_WRRWEIGHTS_19_SIZE 1
-/* [RW 32] Wrr weights */
-#define QM_REG_WRRWEIGHTS_10 0x168814
#define QM_REG_WRRWEIGHTS_11 0x168818
#define QM_REG_WRRWEIGHTS_12 0x16881c
#define QM_REG_WRRWEIGHTS_13 0x168820
@@ -3118,36 +2850,6 @@
#define QM_REG_WRRWEIGHTS_19 0x16e00c
#define QM_REG_WRRWEIGHTS_2 0x16882c
#define QM_REG_WRRWEIGHTS_20 0x16e010
-#define QM_REG_WRRWEIGHTS_20_SIZE 1
-/* [RW 32] Wrr weights */
-#define QM_REG_WRRWEIGHTS_21 0x16e014
-#define QM_REG_WRRWEIGHTS_21_SIZE 1
-/* [RW 32] Wrr weights */
-#define QM_REG_WRRWEIGHTS_22 0x16e018
-#define QM_REG_WRRWEIGHTS_22_SIZE 1
-/* [RW 32] Wrr weights */
-#define QM_REG_WRRWEIGHTS_23 0x16e01c
-#define QM_REG_WRRWEIGHTS_23_SIZE 1
-/* [RW 32] Wrr weights */
-#define QM_REG_WRRWEIGHTS_24 0x16e020
-#define QM_REG_WRRWEIGHTS_24_SIZE 1
-/* [RW 32] Wrr weights */
-#define QM_REG_WRRWEIGHTS_25 0x16e024
-#define QM_REG_WRRWEIGHTS_25_SIZE 1
-/* [RW 32] Wrr weights */
-#define QM_REG_WRRWEIGHTS_26 0x16e028
-#define QM_REG_WRRWEIGHTS_26_SIZE 1
-/* [RW 32] Wrr weights */
-#define QM_REG_WRRWEIGHTS_27 0x16e02c
-#define QM_REG_WRRWEIGHTS_27_SIZE 1
-/* [RW 32] Wrr weights */
-#define QM_REG_WRRWEIGHTS_28 0x16e030
-#define QM_REG_WRRWEIGHTS_28_SIZE 1
-/* [RW 32] Wrr weights */
-#define QM_REG_WRRWEIGHTS_29 0x16e034
-#define QM_REG_WRRWEIGHTS_29_SIZE 1
-/* [RW 32] Wrr weights */
-#define QM_REG_WRRWEIGHTS_20 0x16e010
#define QM_REG_WRRWEIGHTS_21 0x16e014
#define QM_REG_WRRWEIGHTS_22 0x16e018
#define QM_REG_WRRWEIGHTS_23 0x16e01c
@@ -3159,12 +2861,6 @@
#define QM_REG_WRRWEIGHTS_29 0x16e034
#define QM_REG_WRRWEIGHTS_3 0x168830
#define QM_REG_WRRWEIGHTS_30 0x16e038
-#define QM_REG_WRRWEIGHTS_30_SIZE 1
-/* [RW 32] Wrr weights */
-#define QM_REG_WRRWEIGHTS_31 0x16e03c
-#define QM_REG_WRRWEIGHTS_31_SIZE 1
-/* [RW 32] Wrr weights */
-#define QM_REG_WRRWEIGHTS_30 0x16e038
#define QM_REG_WRRWEIGHTS_31 0x16e03c
#define QM_REG_WRRWEIGHTS_4 0x168834
#define QM_REG_WRRWEIGHTS_5 0x168838
@@ -3174,362 +2870,6 @@
#define QM_REG_WRRWEIGHTS_9 0x168848
/* [R 6] Keep the fill level of the fifo from write client 1 */
#define QM_REG_XQM_WRC_FIFOLVL 0x168000
-#define BRB1_BRB1_INT_STS_REG_ADDRESS_ERROR (0x1<<0)
-#define BRB1_BRB1_INT_STS_REG_ADDRESS_ERROR_SIZE 0
-#define BRB1_BRB1_INT_STS_CLR_REG_ADDRESS_ERROR (0x1<<0)
-#define BRB1_BRB1_INT_STS_CLR_REG_ADDRESS_ERROR_SIZE 0
-#define BRB1_BRB1_INT_STS_WR_REG_ADDRESS_ERROR (0x1<<0)
-#define BRB1_BRB1_INT_STS_WR_REG_ADDRESS_ERROR_SIZE 0
-#define BRB1_BRB1_INT_MASK_REG_ADDRESS_ERROR (0x1<<0)
-#define BRB1_BRB1_INT_MASK_REG_ADDRESS_ERROR_SIZE 0
-#define CCM_CCM_INT_STS_REG_ADDRESS_ERROR (0x1<<0)
-#define CCM_CCM_INT_STS_REG_ADDRESS_ERROR_SIZE 0
-#define CCM_CCM_INT_STS_CLR_REG_ADDRESS_ERROR (0x1<<0)
-#define CCM_CCM_INT_STS_CLR_REG_ADDRESS_ERROR_SIZE 0
-#define CCM_CCM_INT_STS_WR_REG_ADDRESS_ERROR (0x1<<0)
-#define CCM_CCM_INT_STS_WR_REG_ADDRESS_ERROR_SIZE 0
-#define CCM_CCM_INT_MASK_REG_ADDRESS_ERROR (0x1<<0)
-#define CCM_CCM_INT_MASK_REG_ADDRESS_ERROR_SIZE 0
-#define CDU_CDU_INT_STS_REG_ADDRESS_ERROR (0x1<<0)
-#define CDU_CDU_INT_STS_REG_ADDRESS_ERROR_SIZE 0
-#define CDU_CDU_INT_STS_CLR_REG_ADDRESS_ERROR (0x1<<0)
-#define CDU_CDU_INT_STS_CLR_REG_ADDRESS_ERROR_SIZE 0
-#define CDU_CDU_INT_STS_WR_REG_ADDRESS_ERROR (0x1<<0)
-#define CDU_CDU_INT_STS_WR_REG_ADDRESS_ERROR_SIZE 0
-#define CDU_CDU_INT_MASK_REG_ADDRESS_ERROR (0x1<<0)
-#define CDU_CDU_INT_MASK_REG_ADDRESS_ERROR_SIZE 0
-#define CFC_CFC_INT_STS_REG_ADDRESS_ERROR (0x1<<0)
-#define CFC_CFC_INT_STS_REG_ADDRESS_ERROR_SIZE 0
-#define CFC_CFC_INT_STS_CLR_REG_ADDRESS_ERROR (0x1<<0)
-#define CFC_CFC_INT_STS_CLR_REG_ADDRESS_ERROR_SIZE 0
-#define CFC_CFC_INT_STS_WR_REG_ADDRESS_ERROR (0x1<<0)
-#define CFC_CFC_INT_STS_WR_REG_ADDRESS_ERROR_SIZE 0
-#define CFC_CFC_INT_MASK_REG_ADDRESS_ERROR (0x1<<0)
-#define CFC_CFC_INT_MASK_REG_ADDRESS_ERROR_SIZE 0
-#define CSDM_CSDM_INT_STS_0_REG_ADDRESS_ERROR (0x1<<0)
-#define CSDM_CSDM_INT_STS_0_REG_ADDRESS_ERROR_SIZE 0
-#define CSDM_CSDM_INT_STS_CLR_0_REG_ADDRESS_ERROR (0x1<<0)
-#define CSDM_CSDM_INT_STS_CLR_0_REG_ADDRESS_ERROR_SIZE 0
-#define CSDM_CSDM_INT_STS_WR_0_REG_ADDRESS_ERROR (0x1<<0)
-#define CSDM_CSDM_INT_STS_WR_0_REG_ADDRESS_ERROR_SIZE 0
-#define CSDM_CSDM_INT_MASK_0_REG_ADDRESS_ERROR (0x1<<0)
-#define CSDM_CSDM_INT_MASK_0_REG_ADDRESS_ERROR_SIZE 0
-#define CSEM_CSEM_INT_STS_0_REG_ADDRESS_ERROR (0x1<<0)
-#define CSEM_CSEM_INT_STS_0_REG_ADDRESS_ERROR_SIZE 0
-#define CSEM_CSEM_INT_STS_CLR_0_REG_ADDRESS_ERROR (0x1<<0)
-#define CSEM_CSEM_INT_STS_CLR_0_REG_ADDRESS_ERROR_SIZE 0
-#define CSEM_CSEM_INT_STS_WR_0_REG_ADDRESS_ERROR (0x1<<0)
-#define CSEM_CSEM_INT_STS_WR_0_REG_ADDRESS_ERROR_SIZE 0
-#define CSEM_CSEM_INT_MASK_0_REG_ADDRESS_ERROR (0x1<<0)
-#define CSEM_CSEM_INT_MASK_0_REG_ADDRESS_ERROR_SIZE 0
-#define DBG_DBG_INT_STS_REG_ADDRESS_ERROR (0x1<<0)
-#define DBG_DBG_INT_STS_REG_ADDRESS_ERROR_SIZE 0
-#define DBG_DBG_INT_STS_CLR_REG_ADDRESS_ERROR (0x1<<0)
-#define DBG_DBG_INT_STS_CLR_REG_ADDRESS_ERROR_SIZE 0
-#define DBG_DBG_INT_STS_WR_REG_ADDRESS_ERROR (0x1<<0)
-#define DBG_DBG_INT_STS_WR_REG_ADDRESS_ERROR_SIZE 0
-#define DBG_DBG_INT_MASK_REG_ADDRESS_ERROR (0x1<<0)
-#define DBG_DBG_INT_MASK_REG_ADDRESS_ERROR_SIZE 0
-#define DMAE_DMAE_INT_STS_REG_ADDRESS_ERROR (0x1<<0)
-#define DMAE_DMAE_INT_STS_REG_ADDRESS_ERROR_SIZE 0
-#define DMAE_DMAE_INT_STS_CLR_REG_ADDRESS_ERROR (0x1<<0)
-#define DMAE_DMAE_INT_STS_CLR_REG_ADDRESS_ERROR_SIZE 0
-#define DMAE_DMAE_INT_STS_WR_REG_ADDRESS_ERROR (0x1<<0)
-#define DMAE_DMAE_INT_STS_WR_REG_ADDRESS_ERROR_SIZE 0
-#define DMAE_DMAE_INT_MASK_REG_ADDRESS_ERROR (0x1<<0)
-#define DMAE_DMAE_INT_MASK_REG_ADDRESS_ERROR_SIZE 0
-#define DORQ_DORQ_INT_STS_REG_ADDRESS_ERROR (0x1<<0)
-#define DORQ_DORQ_INT_STS_REG_ADDRESS_ERROR_SIZE 0
-#define DORQ_DORQ_INT_STS_CLR_REG_ADDRESS_ERROR (0x1<<0)
-#define DORQ_DORQ_INT_STS_CLR_REG_ADDRESS_ERROR_SIZE 0
-#define DORQ_DORQ_INT_STS_WR_REG_ADDRESS_ERROR (0x1<<0)
-#define DORQ_DORQ_INT_STS_WR_REG_ADDRESS_ERROR_SIZE 0
-#define DORQ_DORQ_INT_MASK_REG_ADDRESS_ERROR (0x1<<0)
-#define DORQ_DORQ_INT_MASK_REG_ADDRESS_ERROR_SIZE 0
-#define HC_HC_INT_STS_REG_ADDRESS_ERROR (0x1<<0)
-#define HC_HC_INT_STS_REG_ADDRESS_ERROR_SIZE 0
-#define HC_HC_INT_STS_CLR_REG_ADDRESS_ERROR (0x1<<0)
-#define HC_HC_INT_STS_CLR_REG_ADDRESS_ERROR_SIZE 0
-#define HC_HC_INT_STS_WR_REG_ADDRESS_ERROR (0x1<<0)
-#define HC_HC_INT_STS_WR_REG_ADDRESS_ERROR_SIZE 0
-#define HC_HC_INT_MASK_REG_ADDRESS_ERROR (0x1<<0)
-#define HC_HC_INT_MASK_REG_ADDRESS_ERROR_SIZE 0
-#define MISC_MISC_INT_STS_REG_ADDRESS_ERROR (0x1<<0)
-#define MISC_MISC_INT_STS_REG_ADDRESS_ERROR_SIZE 0
-#define MISC_MISC_INT_STS_CLR_REG_ADDRESS_ERROR (0x1<<0)
-#define MISC_MISC_INT_STS_CLR_REG_ADDRESS_ERROR_SIZE 0
-#define MISC_MISC_INT_STS_WR_REG_ADDRESS_ERROR (0x1<<0)
-#define MISC_MISC_INT_STS_WR_REG_ADDRESS_ERROR_SIZE 0
-#define MISC_MISC_INT_MASK_REG_ADDRESS_ERROR (0x1<<0)
-#define MISC_MISC_INT_MASK_REG_ADDRESS_ERROR_SIZE 0
-#define NIG_NIG_INT_STS_0_REG_ADDRESS_ERROR (0x1<<0)
-#define NIG_NIG_INT_STS_0_REG_ADDRESS_ERROR_SIZE 0
-#define NIG_NIG_INT_STS_CLR_0_REG_ADDRESS_ERROR (0x1<<0)
-#define NIG_NIG_INT_STS_CLR_0_REG_ADDRESS_ERROR_SIZE 0
-#define NIG_NIG_INT_STS_WR_0_REG_ADDRESS_ERROR (0x1<<0)
-#define NIG_NIG_INT_STS_WR_0_REG_ADDRESS_ERROR_SIZE 0
-#define NIG_NIG_INT_MASK_0_REG_ADDRESS_ERROR (0x1<<0)
-#define NIG_NIG_INT_MASK_0_REG_ADDRESS_ERROR_SIZE 0
-#define PBF_PBF_INT_STS_REG_ADDRESS_ERROR (0x1<<0)
-#define PBF_PBF_INT_STS_REG_ADDRESS_ERROR_SIZE 0
-#define PBF_PBF_INT_STS_CLR_REG_ADDRESS_ERROR (0x1<<0)
-#define PBF_PBF_INT_STS_CLR_REG_ADDRESS_ERROR_SIZE 0
-#define PBF_PBF_INT_STS_WR_REG_ADDRESS_ERROR (0x1<<0)
-#define PBF_PBF_INT_STS_WR_REG_ADDRESS_ERROR_SIZE 0
-#define PBF_PBF_INT_MASK_REG_ADDRESS_ERROR (0x1<<0)
-#define PBF_PBF_INT_MASK_REG_ADDRESS_ERROR_SIZE 0
-#define PB_PB_INT_STS_REG_ADDRESS_ERROR (0x1<<0)
-#define PB_PB_INT_STS_REG_ADDRESS_ERROR_SIZE 0
-#define PB_PB_INT_STS_CLR_REG_ADDRESS_ERROR (0x1<<0)
-#define PB_PB_INT_STS_CLR_REG_ADDRESS_ERROR_SIZE 0
-#define PB_PB_INT_STS_WR_REG_ADDRESS_ERROR (0x1<<0)
-#define PB_PB_INT_STS_WR_REG_ADDRESS_ERROR_SIZE 0
-#define PB_PB_INT_MASK_REG_ADDRESS_ERROR (0x1<<0)
-#define PB_PB_INT_MASK_REG_ADDRESS_ERROR_SIZE 0
-#define PRS_PRS_INT_STS_REG_ADDRESS_ERROR (0x1<<0)
-#define PRS_PRS_INT_STS_REG_ADDRESS_ERROR_SIZE 0
-#define PRS_PRS_INT_STS_CLR_REG_ADDRESS_ERROR (0x1<<0)
-#define PRS_PRS_INT_STS_CLR_REG_ADDRESS_ERROR_SIZE 0
-#define PRS_PRS_INT_STS_WR_REG_ADDRESS_ERROR (0x1<<0)
-#define PRS_PRS_INT_STS_WR_REG_ADDRESS_ERROR_SIZE 0
-#define PRS_PRS_INT_MASK_REG_ADDRESS_ERROR (0x1<<0)
-#define PRS_PRS_INT_MASK_REG_ADDRESS_ERROR_SIZE 0
-#define PXP2_PXP2_INT_STS_0_REG_ADDRESS_ERROR (0x1<<0)
-#define PXP2_PXP2_INT_STS_0_REG_ADDRESS_ERROR_SIZE 0
-#define PXP2_PXP2_INT_STS_CLR_0_REG_ADDRESS_ERROR (0x1<<0)
-#define PXP2_PXP2_INT_STS_CLR_0_REG_ADDRESS_ERROR_SIZE 0
-#define PXP2_PXP2_INT_STS_WR_0_REG_ADDRESS_ERROR (0x1<<0)
-#define PXP2_PXP2_INT_STS_WR_0_REG_ADDRESS_ERROR_SIZE 0
-#define PXP2_PXP2_INT_MASK_0_REG_ADDRESS_ERROR (0x1<<0)
-#define PXP2_PXP2_INT_MASK_0_REG_ADDRESS_ERROR_SIZE 0
-#define PXP_PXP_INT_STS_0_REG_ADDRESS_ERROR (0x1<<0)
-#define PXP_PXP_INT_STS_0_REG_ADDRESS_ERROR_SIZE 0
-#define PXP_PXP_INT_STS_CLR_0_REG_ADDRESS_ERROR (0x1<<0)
-#define PXP_PXP_INT_STS_CLR_0_REG_ADDRESS_ERROR_SIZE 0
-#define PXP_PXP_INT_STS_WR_0_REG_ADDRESS_ERROR (0x1<<0)
-#define PXP_PXP_INT_STS_WR_0_REG_ADDRESS_ERROR_SIZE 0
-#define PXP_PXP_INT_MASK_0_REG_ADDRESS_ERROR (0x1<<0)
-#define PXP_PXP_INT_MASK_0_REG_ADDRESS_ERROR_SIZE 0
-#define QM_QM_INT_STS_REG_ADDRESS_ERROR (0x1<<0)
-#define QM_QM_INT_STS_REG_ADDRESS_ERROR_SIZE 0
-#define QM_QM_INT_STS_CLR_REG_ADDRESS_ERROR (0x1<<0)
-#define QM_QM_INT_STS_CLR_REG_ADDRESS_ERROR_SIZE 0
-#define QM_QM_INT_STS_WR_REG_ADDRESS_ERROR (0x1<<0)
-#define QM_QM_INT_STS_WR_REG_ADDRESS_ERROR_SIZE 0
-#define QM_QM_INT_MASK_REG_ADDRESS_ERROR (0x1<<0)
-#define QM_QM_INT_MASK_REG_ADDRESS_ERROR_SIZE 0
-#define SEM_FAST_SEM_FAST_INT_STS_REG_ADDRESS_ERROR (0x1<<0)
-#define SEM_FAST_SEM_FAST_INT_STS_REG_ADDRESS_ERROR_SIZE 0
-#define SEM_FAST_SEM_FAST_INT_STS_CLR_REG_ADDRESS_ERROR (0x1<<0)
-#define SEM_FAST_SEM_FAST_INT_STS_CLR_REG_ADDRESS_ERROR_SIZE 0
-#define SEM_FAST_SEM_FAST_INT_STS_WR_REG_ADDRESS_ERROR (0x1<<0)
-#define SEM_FAST_SEM_FAST_INT_STS_WR_REG_ADDRESS_ERROR_SIZE 0
-#define SEM_FAST_SEM_FAST_INT_MASK_REG_ADDRESS_ERROR (0x1<<0)
-#define SEM_FAST_SEM_FAST_INT_MASK_REG_ADDRESS_ERROR_SIZE 0
-#define SRC_SRC_INT_STS_REG_ADDRESS_ERROR (0x1<<0)
-#define SRC_SRC_INT_STS_REG_ADDRESS_ERROR_SIZE 0
-#define SRC_SRC_INT_STS_CLR_REG_ADDRESS_ERROR (0x1<<0)
-#define SRC_SRC_INT_STS_CLR_REG_ADDRESS_ERROR_SIZE 0
-#define SRC_SRC_INT_STS_WR_REG_ADDRESS_ERROR (0x1<<0)
-#define SRC_SRC_INT_STS_WR_REG_ADDRESS_ERROR_SIZE 0
-#define SRC_SRC_INT_MASK_REG_ADDRESS_ERROR (0x1<<0)
-#define SRC_SRC_INT_MASK_REG_ADDRESS_ERROR_SIZE 0
-#define TCM_TCM_INT_STS_REG_ADDRESS_ERROR (0x1<<0)
-#define TCM_TCM_INT_STS_REG_ADDRESS_ERROR_SIZE 0
-#define TCM_TCM_INT_STS_CLR_REG_ADDRESS_ERROR (0x1<<0)
-#define TCM_TCM_INT_STS_CLR_REG_ADDRESS_ERROR_SIZE 0
-#define TCM_TCM_INT_STS_WR_REG_ADDRESS_ERROR (0x1<<0)
-#define TCM_TCM_INT_STS_WR_REG_ADDRESS_ERROR_SIZE 0
-#define TCM_TCM_INT_MASK_REG_ADDRESS_ERROR (0x1<<0)
-#define TCM_TCM_INT_MASK_REG_ADDRESS_ERROR_SIZE 0
-#define TM_TM_INT_STS_REG_ADDRESS_ERROR (0x1<<0)
-#define TM_TM_INT_STS_REG_ADDRESS_ERROR_SIZE 0
-#define TM_TM_INT_STS_CLR_REG_ADDRESS_ERROR (0x1<<0)
-#define TM_TM_INT_STS_CLR_REG_ADDRESS_ERROR_SIZE 0
-#define TM_TM_INT_STS_WR_REG_ADDRESS_ERROR (0x1<<0)
-#define TM_TM_INT_STS_WR_REG_ADDRESS_ERROR_SIZE 0
-#define TM_TM_INT_MASK_REG_ADDRESS_ERROR (0x1<<0)
-#define TM_TM_INT_MASK_REG_ADDRESS_ERROR_SIZE 0
-#define TSDM_TSDM_INT_STS_0_REG_ADDRESS_ERROR (0x1<<0)
-#define TSDM_TSDM_INT_STS_0_REG_ADDRESS_ERROR_SIZE 0
-#define TSDM_TSDM_INT_STS_CLR_0_REG_ADDRESS_ERROR (0x1<<0)
-#define TSDM_TSDM_INT_STS_CLR_0_REG_ADDRESS_ERROR_SIZE 0
-#define TSDM_TSDM_INT_STS_WR_0_REG_ADDRESS_ERROR (0x1<<0)
-#define TSDM_TSDM_INT_STS_WR_0_REG_ADDRESS_ERROR_SIZE 0
-#define TSDM_TSDM_INT_MASK_0_REG_ADDRESS_ERROR (0x1<<0)
-#define TSDM_TSDM_INT_MASK_0_REG_ADDRESS_ERROR_SIZE 0
-#define TSEM_TSEM_INT_STS_0_REG_ADDRESS_ERROR (0x1<<0)
-#define TSEM_TSEM_INT_STS_0_REG_ADDRESS_ERROR_SIZE 0
-#define TSEM_TSEM_INT_STS_CLR_0_REG_ADDRESS_ERROR (0x1<<0)
-#define TSEM_TSEM_INT_STS_CLR_0_REG_ADDRESS_ERROR_SIZE 0
-#define TSEM_TSEM_INT_STS_WR_0_REG_ADDRESS_ERROR (0x1<<0)
-#define TSEM_TSEM_INT_STS_WR_0_REG_ADDRESS_ERROR_SIZE 0
-#define TSEM_TSEM_INT_MASK_0_REG_ADDRESS_ERROR (0x1<<0)
-#define TSEM_TSEM_INT_MASK_0_REG_ADDRESS_ERROR_SIZE 0
-#define UCM_UCM_INT_STS_REG_ADDRESS_ERROR (0x1<<0)
-#define UCM_UCM_INT_STS_REG_ADDRESS_ERROR_SIZE 0
-#define UCM_UCM_INT_STS_CLR_REG_ADDRESS_ERROR (0x1<<0)
-#define UCM_UCM_INT_STS_CLR_REG_ADDRESS_ERROR_SIZE 0
-#define UCM_UCM_INT_STS_WR_REG_ADDRESS_ERROR (0x1<<0)
-#define UCM_UCM_INT_STS_WR_REG_ADDRESS_ERROR_SIZE 0
-#define UCM_UCM_INT_MASK_REG_ADDRESS_ERROR (0x1<<0)
-#define UCM_UCM_INT_MASK_REG_ADDRESS_ERROR_SIZE 0
-#define USDM_USDM_INT_STS_0_REG_ADDRESS_ERROR (0x1<<0)
-#define USDM_USDM_INT_STS_0_REG_ADDRESS_ERROR_SIZE 0
-#define USDM_USDM_INT_STS_CLR_0_REG_ADDRESS_ERROR (0x1<<0)
-#define USDM_USDM_INT_STS_CLR_0_REG_ADDRESS_ERROR_SIZE 0
-#define USDM_USDM_INT_STS_WR_0_REG_ADDRESS_ERROR (0x1<<0)
-#define USDM_USDM_INT_STS_WR_0_REG_ADDRESS_ERROR_SIZE 0
-#define USDM_USDM_INT_MASK_0_REG_ADDRESS_ERROR (0x1<<0)
-#define USDM_USDM_INT_MASK_0_REG_ADDRESS_ERROR_SIZE 0
-#define USEM_USEM_INT_STS_0_REG_ADDRESS_ERROR (0x1<<0)
-#define USEM_USEM_INT_STS_0_REG_ADDRESS_ERROR_SIZE 0
-#define USEM_USEM_INT_STS_CLR_0_REG_ADDRESS_ERROR (0x1<<0)
-#define USEM_USEM_INT_STS_CLR_0_REG_ADDRESS_ERROR_SIZE 0
-#define USEM_USEM_INT_STS_WR_0_REG_ADDRESS_ERROR (0x1<<0)
-#define USEM_USEM_INT_STS_WR_0_REG_ADDRESS_ERROR_SIZE 0
-#define USEM_USEM_INT_MASK_0_REG_ADDRESS_ERROR (0x1<<0)
-#define USEM_USEM_INT_MASK_0_REG_ADDRESS_ERROR_SIZE 0
-#define XCM_XCM_INT_STS_REG_ADDRESS_ERROR (0x1<<0)
-#define XCM_XCM_INT_STS_REG_ADDRESS_ERROR_SIZE 0
-#define XCM_XCM_INT_STS_CLR_REG_ADDRESS_ERROR (0x1<<0)
-#define XCM_XCM_INT_STS_CLR_REG_ADDRESS_ERROR_SIZE 0
-#define XCM_XCM_INT_STS_WR_REG_ADDRESS_ERROR (0x1<<0)
-#define XCM_XCM_INT_STS_WR_REG_ADDRESS_ERROR_SIZE 0
-#define XCM_XCM_INT_MASK_REG_ADDRESS_ERROR (0x1<<0)
-#define XCM_XCM_INT_MASK_REG_ADDRESS_ERROR_SIZE 0
-#define XSDM_XSDM_INT_STS_0_REG_ADDRESS_ERROR (0x1<<0)
-#define XSDM_XSDM_INT_STS_0_REG_ADDRESS_ERROR_SIZE 0
-#define XSDM_XSDM_INT_STS_CLR_0_REG_ADDRESS_ERROR (0x1<<0)
-#define XSDM_XSDM_INT_STS_CLR_0_REG_ADDRESS_ERROR_SIZE 0
-#define XSDM_XSDM_INT_STS_WR_0_REG_ADDRESS_ERROR (0x1<<0)
-#define XSDM_XSDM_INT_STS_WR_0_REG_ADDRESS_ERROR_SIZE 0
-#define XSDM_XSDM_INT_MASK_0_REG_ADDRESS_ERROR (0x1<<0)
-#define XSDM_XSDM_INT_MASK_0_REG_ADDRESS_ERROR_SIZE 0
-#define XSEM_XSEM_INT_STS_0_REG_ADDRESS_ERROR (0x1<<0)
-#define XSEM_XSEM_INT_STS_0_REG_ADDRESS_ERROR_SIZE 0
-#define XSEM_XSEM_INT_STS_CLR_0_REG_ADDRESS_ERROR (0x1<<0)
-#define XSEM_XSEM_INT_STS_CLR_0_REG_ADDRESS_ERROR_SIZE 0
-#define XSEM_XSEM_INT_STS_WR_0_REG_ADDRESS_ERROR (0x1<<0)
-#define XSEM_XSEM_INT_STS_WR_0_REG_ADDRESS_ERROR_SIZE 0
-#define XSEM_XSEM_INT_MASK_0_REG_ADDRESS_ERROR (0x1<<0)
-#define XSEM_XSEM_INT_MASK_0_REG_ADDRESS_ERROR_SIZE 0
-#define CFC_DEBUG1_REG_WRITE_AC (0x1<<4)
-#define CFC_DEBUG1_REG_WRITE_AC_SIZE 4
-/* [R 1] debug only: This bit indicates whether indicates that external
- buffer was wrapped (oldest data was thrown); Relevant only when
- ~dbg_registers_debug_target=2 (PCI) & ~dbg_registers_full_mode=1 (wrap); */
-#define DBG_REG_WRAP_ON_EXT_BUFFER 0xc124
-#define DBG_REG_WRAP_ON_EXT_BUFFER_SIZE 1
-/* [R 1] debug only: This bit indicates whether the internal buffer was
- wrapped (oldest data was thrown) Relevant only when
- ~dbg_registers_debug_target=0 (internal buffer) */
-#define DBG_REG_WRAP_ON_INT_BUFFER 0xc128
-#define DBG_REG_WRAP_ON_INT_BUFFER_SIZE 1
-#define QM_QM_PRTY_STS_REG_WRBUFF (0x1<<8)
-#define QM_QM_PRTY_STS_REG_WRBUFF_SIZE 8
-#define QM_QM_PRTY_STS_CLR_REG_WRBUFF (0x1<<8)
-#define QM_QM_PRTY_STS_CLR_REG_WRBUFF_SIZE 8
-#define QM_QM_PRTY_STS_WR_REG_WRBUFF (0x1<<8)
-#define QM_QM_PRTY_STS_WR_REG_WRBUFF_SIZE 8
-#define QM_QM_PRTY_MASK_REG_WRBUFF (0x1<<8)
-#define QM_QM_PRTY_MASK_REG_WRBUFF_SIZE 8
-/* [RW 32] Wrr weights */
-#define QM_REG_WRRWEIGHTS_0 0x16880c
-#define QM_REG_WRRWEIGHTS_0_SIZE 1
-/* [RW 32] Wrr weights */
-#define QM_REG_WRRWEIGHTS_1 0x168810
-#define QM_REG_WRRWEIGHTS_1_SIZE 1
-/* [RW 32] Wrr weights */
-#define QM_REG_WRRWEIGHTS_10 0x168814
-#define QM_REG_WRRWEIGHTS_10_SIZE 1
-/* [RW 32] Wrr weights */
-#define QM_REG_WRRWEIGHTS_11 0x168818
-#define QM_REG_WRRWEIGHTS_11_SIZE 1
-/* [RW 32] Wrr weights */
-#define QM_REG_WRRWEIGHTS_12 0x16881c
-#define QM_REG_WRRWEIGHTS_12_SIZE 1
-/* [RW 32] Wrr weights */
-#define QM_REG_WRRWEIGHTS_13 0x168820
-#define QM_REG_WRRWEIGHTS_13_SIZE 1
-/* [RW 32] Wrr weights */
-#define QM_REG_WRRWEIGHTS_14 0x168824
-#define QM_REG_WRRWEIGHTS_14_SIZE 1
-/* [RW 32] Wrr weights */
-#define QM_REG_WRRWEIGHTS_15 0x168828
-#define QM_REG_WRRWEIGHTS_15_SIZE 1
-/* [RW 32] Wrr weights */
-#define QM_REG_WRRWEIGHTS_2 0x16882c
-#define QM_REG_WRRWEIGHTS_2_SIZE 1
-/* [RW 32] Wrr weights */
-#define QM_REG_WRRWEIGHTS_3 0x168830
-#define QM_REG_WRRWEIGHTS_3_SIZE 1
-/* [RW 32] Wrr weights */
-#define QM_REG_WRRWEIGHTS_4 0x168834
-#define QM_REG_WRRWEIGHTS_4_SIZE 1
-/* [RW 32] Wrr weights */
-#define QM_REG_WRRWEIGHTS_5 0x168838
-#define QM_REG_WRRWEIGHTS_5_SIZE 1
-/* [RW 32] Wrr weights */
-#define QM_REG_WRRWEIGHTS_6 0x16883c
-#define QM_REG_WRRWEIGHTS_6_SIZE 1
-/* [RW 32] Wrr weights */
-#define QM_REG_WRRWEIGHTS_7 0x168840
-#define QM_REG_WRRWEIGHTS_7_SIZE 1
-/* [RW 32] Wrr weights */
-#define QM_REG_WRRWEIGHTS_8 0x168844
-#define QM_REG_WRRWEIGHTS_8_SIZE 1
-/* [RW 32] Wrr weights */
-#define QM_REG_WRRWEIGHTS_9 0x168848
-#define QM_REG_WRRWEIGHTS_9_SIZE 1
-/* [RW 32] Wrr weights */
-#define QM_REG_WRRWEIGHTS_16 0x16e000
-#define QM_REG_WRRWEIGHTS_16_SIZE 1
-/* [RW 32] Wrr weights */
-#define QM_REG_WRRWEIGHTS_17 0x16e004
-#define QM_REG_WRRWEIGHTS_17_SIZE 1
-/* [RW 32] Wrr weights */
-#define QM_REG_WRRWEIGHTS_18 0x16e008
-#define QM_REG_WRRWEIGHTS_18_SIZE 1
-/* [RW 32] Wrr weights */
-#define QM_REG_WRRWEIGHTS_19 0x16e00c
-#define QM_REG_WRRWEIGHTS_19_SIZE 1
-/* [RW 32] Wrr weights */
-#define QM_REG_WRRWEIGHTS_20 0x16e010
-#define QM_REG_WRRWEIGHTS_20_SIZE 1
-/* [RW 32] Wrr weights */
-#define QM_REG_WRRWEIGHTS_21 0x16e014
-#define QM_REG_WRRWEIGHTS_21_SIZE 1
-/* [RW 32] Wrr weights */
-#define QM_REG_WRRWEIGHTS_22 0x16e018
-#define QM_REG_WRRWEIGHTS_22_SIZE 1
-/* [RW 32] Wrr weights */
-#define QM_REG_WRRWEIGHTS_23 0x16e01c
-#define QM_REG_WRRWEIGHTS_23_SIZE 1
-/* [RW 32] Wrr weights */
-#define QM_REG_WRRWEIGHTS_24 0x16e020
-#define QM_REG_WRRWEIGHTS_24_SIZE 1
-/* [RW 32] Wrr weights */
-#define QM_REG_WRRWEIGHTS_25 0x16e024
-#define QM_REG_WRRWEIGHTS_25_SIZE 1
-/* [RW 32] Wrr weights */
-#define QM_REG_WRRWEIGHTS_26 0x16e028
-#define QM_REG_WRRWEIGHTS_26_SIZE 1
-/* [RW 32] Wrr weights */
-#define QM_REG_WRRWEIGHTS_27 0x16e02c
-#define QM_REG_WRRWEIGHTS_27_SIZE 1
-/* [RW 32] Wrr weights */
-#define QM_REG_WRRWEIGHTS_28 0x16e030
-#define QM_REG_WRRWEIGHTS_28_SIZE 1
-/* [RW 32] Wrr weights */
-#define QM_REG_WRRWEIGHTS_29 0x16e034
-#define QM_REG_WRRWEIGHTS_29_SIZE 1
-/* [RW 32] Wrr weights */
-#define QM_REG_WRRWEIGHTS_30 0x16e038
-#define QM_REG_WRRWEIGHTS_30_SIZE 1
-/* [RW 32] Wrr weights */
-#define QM_REG_WRRWEIGHTS_31 0x16e03c
-#define QM_REG_WRRWEIGHTS_31_SIZE 1
#define SRC_REG_COUNTFREE0 0x40500
/* [RW 1] If clr the searcher is compatible to E1 A0 - support only two
ports. If set the searcher support 8 functions. */
@@ -3629,12 +2969,6 @@
type (one of 16). */
#define TCM_REG_N_SM_CTX_LD_0 0x50050
#define TCM_REG_N_SM_CTX_LD_1 0x50054
-#define TCM_REG_N_SM_CTX_LD_10 0x50078
-#define TCM_REG_N_SM_CTX_LD_11 0x5007c
-#define TCM_REG_N_SM_CTX_LD_12 0x50080
-#define TCM_REG_N_SM_CTX_LD_13 0x50084
-#define TCM_REG_N_SM_CTX_LD_14 0x50088
-#define TCM_REG_N_SM_CTX_LD_15 0x5008c
#define TCM_REG_N_SM_CTX_LD_2 0x50058
#define TCM_REG_N_SM_CTX_LD_3 0x5005c
#define TCM_REG_N_SM_CTX_LD_4 0x50060
@@ -3828,6 +3162,7 @@
#define TM_REG_LIN0_PHY_ADDR 0x164270
/* [RW 1] Linear0 physical address valid. */
#define TM_REG_LIN0_PHY_ADDR_VALID 0x164248
+#define TM_REG_LIN0_SCAN_ON 0x1640d0
/* [RW 24] Linear0 array scan timeout. */
#define TM_REG_LIN0_SCAN_TIME 0x16403c
/* [RW 32] Linear1 logic address. */
@@ -3840,8 +3175,6 @@
#define TM_REG_LIN_SETCLR_FIFO_ALFULL_THR 0x164070
/* [RW 2] Load value for pci arbiter credit cnt. */
#define TM_REG_PCIARB_CRDCNT_VAL 0x164260
-/* [RW 1] Timer software reset - active high. */
-#define TM_REG_TIMER_SOFT_RST 0x164004
/* [RW 20] The amount of hardware cycles for each timer tick. */
#define TM_REG_TIMER_TICK_SIZE 0x16401c
/* [RW 8] Timers Context region. */
@@ -3853,44 +3186,12 @@
/* [RW 8] The event id for aggregated interrupt 0 */
#define TSDM_REG_AGG_INT_EVENT_0 0x42038
#define TSDM_REG_AGG_INT_EVENT_1 0x4203c
-#define TSDM_REG_AGG_INT_EVENT_10 0x42060
-#define TSDM_REG_AGG_INT_EVENT_11 0x42064
-#define TSDM_REG_AGG_INT_EVENT_12 0x42068
-#define TSDM_REG_AGG_INT_EVENT_13 0x4206c
-#define TSDM_REG_AGG_INT_EVENT_14 0x42070
-#define TSDM_REG_AGG_INT_EVENT_15 0x42074
-#define TSDM_REG_AGG_INT_EVENT_16 0x42078
-#define TSDM_REG_AGG_INT_EVENT_17 0x4207c
-#define TSDM_REG_AGG_INT_EVENT_18 0x42080
-#define TSDM_REG_AGG_INT_EVENT_19 0x42084
#define TSDM_REG_AGG_INT_EVENT_2 0x42040
-#define TSDM_REG_AGG_INT_EVENT_20 0x42088
-#define TSDM_REG_AGG_INT_EVENT_21 0x4208c
-#define TSDM_REG_AGG_INT_EVENT_22 0x42090
-#define TSDM_REG_AGG_INT_EVENT_23 0x42094
-#define TSDM_REG_AGG_INT_EVENT_24 0x42098
-#define TSDM_REG_AGG_INT_EVENT_25 0x4209c
-#define TSDM_REG_AGG_INT_EVENT_26 0x420a0
-#define TSDM_REG_AGG_INT_EVENT_27 0x420a4
-#define TSDM_REG_AGG_INT_EVENT_28 0x420a8
-#define TSDM_REG_AGG_INT_EVENT_29 0x420ac
#define TSDM_REG_AGG_INT_EVENT_3 0x42044
-#define TSDM_REG_AGG_INT_EVENT_30 0x420b0
-#define TSDM_REG_AGG_INT_EVENT_31 0x420b4
#define TSDM_REG_AGG_INT_EVENT_4 0x42048
/* [RW 1] The T bit for aggregated interrupt 0 */
#define TSDM_REG_AGG_INT_T_0 0x420b8
#define TSDM_REG_AGG_INT_T_1 0x420bc
-#define TSDM_REG_AGG_INT_T_10 0x420e0
-#define TSDM_REG_AGG_INT_T_11 0x420e4
-#define TSDM_REG_AGG_INT_T_12 0x420e8
-#define TSDM_REG_AGG_INT_T_13 0x420ec
-#define TSDM_REG_AGG_INT_T_14 0x420f0
-#define TSDM_REG_AGG_INT_T_15 0x420f4
-#define TSDM_REG_AGG_INT_T_16 0x420f8
-#define TSDM_REG_AGG_INT_T_17 0x420fc
-#define TSDM_REG_AGG_INT_T_18 0x42100
-#define TSDM_REG_AGG_INT_T_19 0x42104
/* [RW 13] The start address in the internal RAM for the cfc_rsp lcid */
#define TSDM_REG_CFC_RSP_START_ADDR 0x42008
/* [RW 16] The maximum value of the competion counter #0 */
@@ -4175,12 +3476,6 @@
connection type (one of 16). */
#define UCM_REG_N_SM_CTX_LD_0 0xe0054
#define UCM_REG_N_SM_CTX_LD_1 0xe0058
-#define UCM_REG_N_SM_CTX_LD_10 0xe007c
-#define UCM_REG_N_SM_CTX_LD_11 0xe0080
-#define UCM_REG_N_SM_CTX_LD_12 0xe0084
-#define UCM_REG_N_SM_CTX_LD_13 0xe0088
-#define UCM_REG_N_SM_CTX_LD_14 0xe008c
-#define UCM_REG_N_SM_CTX_LD_15 0xe0090
#define UCM_REG_N_SM_CTX_LD_2 0xe005c
#define UCM_REG_N_SM_CTX_LD_3 0xe0060
#define UCM_REG_N_SM_CTX_LD_4 0xe0064
@@ -4330,48 +3625,20 @@
/* [RW 8] The event id for aggregated interrupt 0 */
#define USDM_REG_AGG_INT_EVENT_0 0xc4038
#define USDM_REG_AGG_INT_EVENT_1 0xc403c
-#define USDM_REG_AGG_INT_EVENT_10 0xc4060
-#define USDM_REG_AGG_INT_EVENT_11 0xc4064
-#define USDM_REG_AGG_INT_EVENT_12 0xc4068
-#define USDM_REG_AGG_INT_EVENT_13 0xc406c
-#define USDM_REG_AGG_INT_EVENT_14 0xc4070
-#define USDM_REG_AGG_INT_EVENT_15 0xc4074
-#define USDM_REG_AGG_INT_EVENT_16 0xc4078
-#define USDM_REG_AGG_INT_EVENT_17 0xc407c
-#define USDM_REG_AGG_INT_EVENT_18 0xc4080
-#define USDM_REG_AGG_INT_EVENT_19 0xc4084
#define USDM_REG_AGG_INT_EVENT_2 0xc4040
-#define USDM_REG_AGG_INT_EVENT_20 0xc4088
-#define USDM_REG_AGG_INT_EVENT_21 0xc408c
-#define USDM_REG_AGG_INT_EVENT_22 0xc4090
-#define USDM_REG_AGG_INT_EVENT_23 0xc4094
-#define USDM_REG_AGG_INT_EVENT_24 0xc4098
-#define USDM_REG_AGG_INT_EVENT_25 0xc409c
-#define USDM_REG_AGG_INT_EVENT_26 0xc40a0
-#define USDM_REG_AGG_INT_EVENT_27 0xc40a4
-#define USDM_REG_AGG_INT_EVENT_28 0xc40a8
-#define USDM_REG_AGG_INT_EVENT_29 0xc40ac
-#define USDM_REG_AGG_INT_EVENT_3 0xc4044
-#define USDM_REG_AGG_INT_EVENT_30 0xc40b0
-#define USDM_REG_AGG_INT_EVENT_31 0xc40b4
#define USDM_REG_AGG_INT_EVENT_4 0xc4048
#define USDM_REG_AGG_INT_EVENT_5 0xc404c
+#define USDM_REG_AGG_INT_EVENT_6 0xc4050
/* [RW 1] For each aggregated interrupt index whether the mode is normal (0)
or auto-mask-mode (1) */
#define USDM_REG_AGG_INT_MODE_0 0xc41b8
#define USDM_REG_AGG_INT_MODE_1 0xc41bc
-#define USDM_REG_AGG_INT_MODE_10 0xc41e0
-#define USDM_REG_AGG_INT_MODE_11 0xc41e4
-#define USDM_REG_AGG_INT_MODE_12 0xc41e8
-#define USDM_REG_AGG_INT_MODE_13 0xc41ec
-#define USDM_REG_AGG_INT_MODE_14 0xc41f0
-#define USDM_REG_AGG_INT_MODE_15 0xc41f4
-#define USDM_REG_AGG_INT_MODE_16 0xc41f8
-#define USDM_REG_AGG_INT_MODE_17 0xc41fc
-#define USDM_REG_AGG_INT_MODE_18 0xc4200
-#define USDM_REG_AGG_INT_MODE_19 0xc4204
#define USDM_REG_AGG_INT_MODE_4 0xc41c8
#define USDM_REG_AGG_INT_MODE_5 0xc41cc
+#define USDM_REG_AGG_INT_MODE_6 0xc41d0
+/* [RW 1] The T bit for aggregated interrupt 5 */
+#define USDM_REG_AGG_INT_T_5 0xc40cc
+#define USDM_REG_AGG_INT_T_6 0xc40d0
/* [RW 13] The start address in the internal RAM for the cfc_rsp lcid */
#define USDM_REG_CFC_RSP_START_ADDR 0xc4008
/* [RW 16] The maximum value of the competion counter #0 */
@@ -4675,10 +3942,6 @@
/* [RC 1] Set at message length mismatch (relative to last indication) at
the nig1 interface. */
#define XCM_REG_NIG1_LENGTH_MIS 0x2023c
-/* [RW 3] The weight of the input nig1 in the WRR mechanism. 0 stands for
- weight 8 (the most prioritised); 1 stands for weight 1(least
- prioritised); 2 stands for weight 2; tc. */
-#define XCM_REG_NIG1_WEIGHT 0x200d8
/* [RW 5] The number of double REG-pairs; loaded from the STORM context and
sent to STORM; for a specific connection type. The double REG-pairs are
used in order to align to STORM context row size of 128 bits. The offset
@@ -4686,12 +3949,6 @@
connection type (one of 16). */
#define XCM_REG_N_SM_CTX_LD_0 0x20060
#define XCM_REG_N_SM_CTX_LD_1 0x20064
-#define XCM_REG_N_SM_CTX_LD_10 0x20088
-#define XCM_REG_N_SM_CTX_LD_11 0x2008c
-#define XCM_REG_N_SM_CTX_LD_12 0x20090
-#define XCM_REG_N_SM_CTX_LD_13 0x20094
-#define XCM_REG_N_SM_CTX_LD_14 0x20098
-#define XCM_REG_N_SM_CTX_LD_15 0x2009c
#define XCM_REG_N_SM_CTX_LD_2 0x20068
#define XCM_REG_N_SM_CTX_LD_3 0x2006c
#define XCM_REG_N_SM_CTX_LD_4 0x20070
@@ -4868,30 +4125,8 @@
#define XSDM_REG_AGG_INT_EVENT_12 0x166068
#define XSDM_REG_AGG_INT_EVENT_13 0x16606c
#define XSDM_REG_AGG_INT_EVENT_14 0x166070
-#define XSDM_REG_AGG_INT_EVENT_15 0x166074
-#define XSDM_REG_AGG_INT_EVENT_16 0x166078
-#define XSDM_REG_AGG_INT_EVENT_17 0x16607c
-#define XSDM_REG_AGG_INT_EVENT_18 0x166080
-#define XSDM_REG_AGG_INT_EVENT_19 0x166084
-#define XSDM_REG_AGG_INT_EVENT_10 0x166060
-#define XSDM_REG_AGG_INT_EVENT_11 0x166064
-#define XSDM_REG_AGG_INT_EVENT_12 0x166068
-#define XSDM_REG_AGG_INT_EVENT_13 0x16606c
-#define XSDM_REG_AGG_INT_EVENT_14 0x166070
#define XSDM_REG_AGG_INT_EVENT_2 0x166040
-#define XSDM_REG_AGG_INT_EVENT_20 0x166088
-#define XSDM_REG_AGG_INT_EVENT_21 0x16608c
-#define XSDM_REG_AGG_INT_EVENT_22 0x166090
-#define XSDM_REG_AGG_INT_EVENT_23 0x166094
-#define XSDM_REG_AGG_INT_EVENT_24 0x166098
-#define XSDM_REG_AGG_INT_EVENT_25 0x16609c
-#define XSDM_REG_AGG_INT_EVENT_26 0x1660a0
-#define XSDM_REG_AGG_INT_EVENT_27 0x1660a4
-#define XSDM_REG_AGG_INT_EVENT_28 0x1660a8
-#define XSDM_REG_AGG_INT_EVENT_29 0x1660ac
#define XSDM_REG_AGG_INT_EVENT_3 0x166044
-#define XSDM_REG_AGG_INT_EVENT_30 0x1660b0
-#define XSDM_REG_AGG_INT_EVENT_31 0x1660b4
#define XSDM_REG_AGG_INT_EVENT_4 0x166048
#define XSDM_REG_AGG_INT_EVENT_5 0x16604c
#define XSDM_REG_AGG_INT_EVENT_6 0x166050
@@ -4902,16 +4137,6 @@
or auto-mask-mode (1) */
#define XSDM_REG_AGG_INT_MODE_0 0x1661b8
#define XSDM_REG_AGG_INT_MODE_1 0x1661bc
-#define XSDM_REG_AGG_INT_MODE_10 0x1661e0
-#define XSDM_REG_AGG_INT_MODE_11 0x1661e4
-#define XSDM_REG_AGG_INT_MODE_12 0x1661e8
-#define XSDM_REG_AGG_INT_MODE_13 0x1661ec
-#define XSDM_REG_AGG_INT_MODE_14 0x1661f0
-#define XSDM_REG_AGG_INT_MODE_15 0x1661f4
-#define XSDM_REG_AGG_INT_MODE_16 0x1661f8
-#define XSDM_REG_AGG_INT_MODE_17 0x1661fc
-#define XSDM_REG_AGG_INT_MODE_18 0x166200
-#define XSDM_REG_AGG_INT_MODE_19 0x166204
/* [RW 13] The start address in the internal RAM for the cfc_rsp lcid */
#define XSDM_REG_CFC_RSP_START_ADDR 0x166008
/* [RW 16] The maximum value of the competion counter #0 */
@@ -5119,10 +4344,6 @@
#define MCPR_NVM_COMMAND_FIRST (1L<<7)
#define MCPR_NVM_COMMAND_LAST (1L<<8)
#define MCPR_NVM_COMMAND_WR (1L<<5)
-#define MCPR_NVM_COMMAND_WREN (1L<<16)
-#define MCPR_NVM_COMMAND_WREN_BITSHIFT 16
-#define MCPR_NVM_COMMAND_WRDI (1L<<17)
-#define MCPR_NVM_COMMAND_WRDI_BITSHIFT 17
#define MCPR_NVM_SW_ARB_ARB_ARB1 (1L<<9)
#define MCPR_NVM_SW_ARB_ARB_REQ_CLR1 (1L<<5)
#define MCPR_NVM_SW_ARB_ARB_REQ_SET1 (1L<<1)
@@ -5223,10 +4444,6 @@
#define MISC_REGISTERS_SPIO_7 7
#define MISC_REGISTERS_SPIO_CLR_POS 16
#define MISC_REGISTERS_SPIO_FLOAT (0xffL<<24)
-#define GRC_MISC_REGISTERS_SPIO_FLOAT7 0x80000000
-#define GRC_MISC_REGISTERS_SPIO_FLOAT6 0x40000000
-#define GRC_MISC_REGISTERS_SPIO_FLOAT5 0x20000000
-#define GRC_MISC_REGISTERS_SPIO_FLOAT4 0x10000000
#define MISC_REGISTERS_SPIO_FLOAT_POS 24
#define MISC_REGISTERS_SPIO_INPUT_HI_Z 2
#define MISC_REGISTERS_SPIO_INT_OLD_SET_POS 16
@@ -5344,7 +4561,8 @@
#define LATCHED_ATTN_SCPAD_PARITY_MCP 33
#define GENERAL_ATTEN_WORD(atten_name) ((94 + atten_name) / 32)
-#define GENERAL_ATTEN_OFFSET(atten_name) (1 << ((94 + atten_name) % 32))
+#define GENERAL_ATTEN_OFFSET(atten_name)\
+ (1UL << ((94 + atten_name) % 32))
/*
* This file defines GRC base address for every block.
* This file is included by chipsim, asm microcode and cpp microcode.
@@ -5568,6 +4786,9 @@
#define MDIO_CL73_IEEEB1_AN_ADV2_ADVR_10G_KR 0x0080
#define MDIO_REG_BANK_RX0 0x80b0
+#define MDIO_RX0_RX_STATUS 0x10
+#define MDIO_RX0_RX_STATUS_SIGDET 0x8000
+#define MDIO_RX0_RX_STATUS_RX_SEQ_DONE 0x1000
#define MDIO_RX0_RX_EQ_BOOST 0x1c
#define MDIO_RX0_RX_EQ_BOOST_EQUALIZER_CTRL_MASK 0x7
#define MDIO_RX0_RX_EQ_BOOST_OFFSET_CTRL 0x10
@@ -5761,12 +4982,22 @@
#define MDIO_OVER_1G_LP_UP2_PREEMPHASIS_SHIFT 7
#define MDIO_OVER_1G_LP_UP3 0x1E
+#define MDIO_REG_BANK_REMOTE_PHY 0x8330
+#define MDIO_REMOTE_PHY_MISC_RX_STATUS 0x10
+#define MDIO_REMOTE_PHY_MISC_RX_STATUS_CL37_FSM_RECEIVED_OVER1G_MSG 0x0010
+#define MDIO_REMOTE_PHY_MISC_RX_STATUS_CL37_FSM_RECEIVED_BRCM_OUI_MSG 0x0600
+
#define MDIO_REG_BANK_BAM_NEXT_PAGE 0x8350
#define MDIO_BAM_NEXT_PAGE_MP5_NEXT_PAGE_CTRL 0x10
#define MDIO_BAM_NEXT_PAGE_MP5_NEXT_PAGE_CTRL_BAM_MODE 0x0001
#define MDIO_BAM_NEXT_PAGE_MP5_NEXT_PAGE_CTRL_TETON_AN 0x0002
#define MDIO_REG_BANK_CL73_USERB0 0x8370
+#define MDIO_CL73_USERB0_CL73_UCTRL 0x10
+#define MDIO_CL73_USERB0_CL73_UCTRL_USTAT1_MUXSEL 0x0002
+#define MDIO_CL73_USERB0_CL73_USTAT1 0x11
+#define MDIO_CL73_USERB0_CL73_USTAT1_LINK_STATUS_CHECK 0x0100
+#define MDIO_CL73_USERB0_CL73_USTAT1_AN_GOOD_CHECK_BAM37 0x0400
#define MDIO_CL73_USERB0_CL73_BAM_CTRL1 0x12
#define MDIO_CL73_USERB0_CL73_BAM_CTRL1_BAM_EN 0x8000
#define MDIO_CL73_USERB0_CL73_BAM_CTRL1_BAM_STATION_MNGR_EN 0x4000
@@ -5843,25 +5074,33 @@ Theotherbitsarereservedandshouldbezero*/
#define MDIO_PMA_REG_ROM_VER2 0xca1a
#define MDIO_PMA_REG_EDC_FFE_MAIN 0xca1b
#define MDIO_PMA_REG_PLL_BANDWIDTH 0xca1d
-#define MDIO_PMA_REG_GEN_CTRL2 0xca1e
+#define MDIO_PMA_REG_PLL_CTRL 0xca1e
#define MDIO_PMA_REG_MISC_CTRL0 0xca23
#define MDIO_PMA_REG_LRM_MODE 0xca3f
#define MDIO_PMA_REG_CDR_BANDWIDTH 0xca46
#define MDIO_PMA_REG_MISC_CTRL1 0xca85
-#define MDIO_PMA_REG_8726_TWO_WIRE_CTRL 0x8000
-#define MDIO_PMA_REG_8726_TWO_WIRE_CTRL_STATUS_MASK 0x000c
-#define MDIO_PMA_REG_8726_TWO_WIRE_STATUS_IDLE 0x0000
-#define MDIO_PMA_REG_8726_TWO_WIRE_STATUS_COMPLETE 0x0004
-#define MDIO_PMA_REG_8726_TWO_WIRE_STATUS_IN_PROGRESS 0x0008
-#define MDIO_PMA_REG_8726_TWO_WIRE_STATUS_FAILED 0x000c
-#define MDIO_PMA_REG_8726_TWO_WIRE_BYTE_CNT 0x8002
-#define MDIO_PMA_REG_8726_TWO_WIRE_MEM_ADDR 0x8003
+#define MDIO_PMA_REG_SFP_TWO_WIRE_CTRL 0x8000
+#define MDIO_PMA_REG_SFP_TWO_WIRE_CTRL_STATUS_MASK 0x000c
+#define MDIO_PMA_REG_SFP_TWO_WIRE_STATUS_IDLE 0x0000
+#define MDIO_PMA_REG_SFP_TWO_WIRE_STATUS_COMPLETE 0x0004
+#define MDIO_PMA_REG_SFP_TWO_WIRE_STATUS_IN_PROGRESS 0x0008
+#define MDIO_PMA_REG_SFP_TWO_WIRE_STATUS_FAILED 0x000c
+#define MDIO_PMA_REG_SFP_TWO_WIRE_BYTE_CNT 0x8002
+#define MDIO_PMA_REG_SFP_TWO_WIRE_MEM_ADDR 0x8003
#define MDIO_PMA_REG_8726_TWO_WIRE_DATA_BUF 0xc820
#define MDIO_PMA_REG_8726_TWO_WIRE_DATA_MASK 0xff
#define MDIO_PMA_REG_8726_TX_CTRL1 0xca01
#define MDIO_PMA_REG_8726_TX_CTRL2 0xca05
+#define MDIO_PMA_REG_8727_TWO_WIRE_SLAVE_ADDR 0x8005
+#define MDIO_PMA_REG_8727_TWO_WIRE_DATA_BUF 0x8007
+#define MDIO_PMA_REG_8727_TWO_WIRE_DATA_MASK 0xff
+#define MDIO_PMA_REG_8727_MISC_CTRL 0x8309
+#define MDIO_PMA_REG_8727_TX_CTRL1 0xca02
+#define MDIO_PMA_REG_8727_TX_CTRL2 0xca05
+#define MDIO_PMA_REG_8727_PCS_OPT_CTRL 0xc808
+#define MDIO_PMA_REG_8727_GPIO_CTRL 0xc80e
#define MDIO_PMA_REG_8073_CHIP_REV 0xc801
#define MDIO_PMA_REG_8073_SPEED_LINK_STATUS 0xc820
@@ -5872,6 +5111,13 @@ Theotherbitsarereservedandshouldbezero*/
#define MDIO_PMA_REG_7101_VER1 0xc026
#define MDIO_PMA_REG_7101_VER2 0xc027
+#define MDIO_PMA_REG_8481_PMD_SIGNAL 0xa811
+#define MDIO_PMA_REG_8481_LED1_MASK 0xa82c
+#define MDIO_PMA_REG_8481_LED2_MASK 0xa82f
+#define MDIO_PMA_REG_8481_LED3_MASK 0xa832
+#define MDIO_PMA_REG_8481_SIGNAL_MASK 0xa835
+#define MDIO_PMA_REG_8481_LINK_SIGNAL 0xa83b
+
#define MDIO_WIS_DEVAD 0x2
/*bcm*/
@@ -5925,6 +5171,12 @@ Theotherbitsarereservedandshouldbezero*/
#define MDIO_AN_REG_8073_2_5G 0x8329
+#define MDIO_AN_REG_8481_LEGACY_MII_CTRL 0xffe0
+#define MDIO_AN_REG_8481_LEGACY_AN_ADV 0xffe4
+#define MDIO_AN_REG_8481_1000T_CTRL 0xffe9
+#define MDIO_AN_REG_8481_EXPANSION_REG_RD_RW 0xfff5
+#define MDIO_AN_REG_8481_EXPANSION_REG_ACCESS 0xfff7
+#define MDIO_AN_REG_8481_LEGACY_SHADOW 0xfffc
#define IGU_FUNC_BASE 0x0400
@@ -5957,3 +5209,116 @@ Theotherbitsarereservedandshouldbezero*/
#define COMMAND_REG_SIMD_NOMASK 0x1c
+#define IGU_MEM_BASE 0x0000
+
+#define IGU_MEM_MSIX_BASE 0x0000
+#define IGU_MEM_MSIX_UPPER 0x007f
+#define IGU_MEM_MSIX_RESERVED_UPPER 0x01ff
+
+#define IGU_MEM_PBA_MSIX_BASE 0x0200
+#define IGU_MEM_PBA_MSIX_UPPER 0x0200
+
+#define IGU_CMD_BACKWARD_COMP_PROD_UPD 0x0201
+#define IGU_MEM_PBA_MSIX_RESERVED_UPPER 0x03ff
+
+#define IGU_CMD_INT_ACK_BASE 0x0400
+#define IGU_CMD_INT_ACK_UPPER\
+ (IGU_CMD_INT_ACK_BASE + MAX_SB_PER_PORT * NUM_OF_PORTS_PER_PATH - 1)
+#define IGU_CMD_INT_ACK_RESERVED_UPPER 0x04ff
+
+#define IGU_CMD_E2_PROD_UPD_BASE 0x0500
+#define IGU_CMD_E2_PROD_UPD_UPPER\
+ (IGU_CMD_E2_PROD_UPD_BASE + MAX_SB_PER_PORT * NUM_OF_PORTS_PER_PATH - 1)
+#define IGU_CMD_E2_PROD_UPD_RESERVED_UPPER 0x059f
+
+#define IGU_CMD_ATTN_BIT_UPD_UPPER 0x05a0
+#define IGU_CMD_ATTN_BIT_SET_UPPER 0x05a1
+#define IGU_CMD_ATTN_BIT_CLR_UPPER 0x05a2
+
+#define IGU_REG_SISR_MDPC_WMASK_UPPER 0x05a3
+#define IGU_REG_SISR_MDPC_WMASK_LSB_UPPER 0x05a4
+#define IGU_REG_SISR_MDPC_WMASK_MSB_UPPER 0x05a5
+#define IGU_REG_SISR_MDPC_WOMASK_UPPER 0x05a6
+
+#define IGU_REG_RESERVED_UPPER 0x05ff
+
+
+#define CDU_REGION_NUMBER_XCM_AG 2
+#define CDU_REGION_NUMBER_UCM_AG 4
+
+
+/**
+ * String-to-compress [31:8] = CID (all 24 bits)
+ * String-to-compress [7:4] = Region
+ * String-to-compress [3:0] = Type
+ */
+#define CDU_VALID_DATA(_cid, _region, _type)\
+ (((_cid) << 8) | (((_region)&0xf)<<4) | (((_type)&0xf)))
+#define CDU_CRC8(_cid, _region, _type)\
+ (calc_crc8(CDU_VALID_DATA(_cid, _region, _type), 0xff))
+#define CDU_RSRVD_VALUE_TYPE_A(_cid, _region, _type)\
+ (0x80 | ((CDU_CRC8(_cid, _region, _type)) & 0x7f))
+#define CDU_RSRVD_VALUE_TYPE_B(_crc, _type)\
+ (0x80 | ((_type)&0xf << 3) | ((CDU_CRC8(_cid, _region, _type)) & 0x7))
+#define CDU_RSRVD_INVALIDATE_CONTEXT_VALUE(_val) ((_val) & ~0x80)
+
+/******************************************************************************
+ * Description:
+ * Calculates crc 8 on a word value: polynomial 0-1-2-8
+ * Code was translated from Verilog.
+ * Return:
+ *****************************************************************************/
+static inline u8 calc_crc8(u32 data, u8 crc)
+{
+ u8 D[32];
+ u8 NewCRC[8];
+ u8 C[8];
+ u8 crc_res;
+ u8 i;
+
+ /* split the data into 31 bits */
+ for (i = 0; i < 32; i++) {
+ D[i] = (u8)(data & 1);
+ data = data >> 1;
+ }
+
+ /* split the crc into 8 bits */
+ for (i = 0; i < 8; i++) {
+ C[i] = crc & 1;
+ crc = crc >> 1;
+ }
+
+ NewCRC[0] = D[31] ^ D[30] ^ D[28] ^ D[23] ^ D[21] ^ D[19] ^ D[18] ^
+ D[16] ^ D[14] ^ D[12] ^ D[8] ^ D[7] ^ D[6] ^ D[0] ^ C[4] ^
+ C[6] ^ C[7];
+ NewCRC[1] = D[30] ^ D[29] ^ D[28] ^ D[24] ^ D[23] ^ D[22] ^ D[21] ^
+ D[20] ^ D[18] ^ D[17] ^ D[16] ^ D[15] ^ D[14] ^ D[13] ^
+ D[12] ^ D[9] ^ D[6] ^ D[1] ^ D[0] ^ C[0] ^ C[4] ^ C[5] ^
+ C[6];
+ NewCRC[2] = D[29] ^ D[28] ^ D[25] ^ D[24] ^ D[22] ^ D[17] ^ D[15] ^
+ D[13] ^ D[12] ^ D[10] ^ D[8] ^ D[6] ^ D[2] ^ D[1] ^ D[0] ^
+ C[0] ^ C[1] ^ C[4] ^ C[5];
+ NewCRC[3] = D[30] ^ D[29] ^ D[26] ^ D[25] ^ D[23] ^ D[18] ^ D[16] ^
+ D[14] ^ D[13] ^ D[11] ^ D[9] ^ D[7] ^ D[3] ^ D[2] ^ D[1] ^
+ C[1] ^ C[2] ^ C[5] ^ C[6];
+ NewCRC[4] = D[31] ^ D[30] ^ D[27] ^ D[26] ^ D[24] ^ D[19] ^ D[17] ^
+ D[15] ^ D[14] ^ D[12] ^ D[10] ^ D[8] ^ D[4] ^ D[3] ^ D[2] ^
+ C[0] ^ C[2] ^ C[3] ^ C[6] ^ C[7];
+ NewCRC[5] = D[31] ^ D[28] ^ D[27] ^ D[25] ^ D[20] ^ D[18] ^ D[16] ^
+ D[15] ^ D[13] ^ D[11] ^ D[9] ^ D[5] ^ D[4] ^ D[3] ^ C[1] ^
+ C[3] ^ C[4] ^ C[7];
+ NewCRC[6] = D[29] ^ D[28] ^ D[26] ^ D[21] ^ D[19] ^ D[17] ^ D[16] ^
+ D[14] ^ D[12] ^ D[10] ^ D[6] ^ D[5] ^ D[4] ^ C[2] ^ C[4] ^
+ C[5];
+ NewCRC[7] = D[30] ^ D[29] ^ D[27] ^ D[22] ^ D[20] ^ D[18] ^ D[17] ^
+ D[15] ^ D[13] ^ D[11] ^ D[7] ^ D[6] ^ D[5] ^ C[3] ^ C[5] ^
+ C[6];
+
+ crc_res = 0;
+ for (i = 0; i < 8; i++)
+ crc_res |= (NewCRC[i] << i);
+
+ return crc_res;
+}
+
+
diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c
index d4b570886c6..cea5cfe23b7 100644
--- a/drivers/net/bonding/bond_3ad.c
+++ b/drivers/net/bonding/bond_3ad.c
@@ -1109,7 +1109,8 @@ static void ad_rx_machine(struct lacpdu *lacpdu, struct port *port)
//mux machine in case of EXPIRED even if LINK_DOWN didn't arrive for the port.
port->partner_oper.port_state &= ~AD_STATE_SYNCHRONIZATION;
port->sm_vars &= ~AD_PORT_MATCHED;
- port->partner_oper.port_state |= AD_SHORT_TIMEOUT;
+ port->partner_oper.port_state |=
+ AD_STATE_LACP_ACTIVITY;
port->sm_rx_timer_counter = __ad_timer_to_ticks(AD_CURRENT_WHILE_TIMER, (u16)(AD_SHORT_TIMEOUT));
port->actor_oper_port_state |= AD_STATE_EXPIRED;
break;
@@ -1123,7 +1124,7 @@ static void ad_rx_machine(struct lacpdu *lacpdu, struct port *port)
// detect loopback situation
if (!MAC_ADDRESS_COMPARE(&(lacpdu->actor_system), &(port->actor_system))) {
// INFO_RECEIVED_LOOPBACK_FRAMES
- printk(KERN_ERR DRV_NAME ": %s: An illegal loopback occurred on "
+ pr_err(DRV_NAME ": %s: An illegal loopback occurred on "
"adapter (%s). Check the configuration to verify that all "
"Adapters are connected to 802.3ad compliant switch ports\n",
port->slave->dev->master->name, port->slave->dev->name);
@@ -1305,11 +1306,13 @@ static void ad_port_selection_logic(struct port *port)
}
}
if (!curr_port) { // meaning: the port was related to an aggregator but was not on the aggregator port list
- printk(KERN_WARNING DRV_NAME ": %s: Warning: Port %d (on %s) was "
- "related to aggregator %d but was not on its port list\n",
- port->slave->dev->master->name,
- port->actor_port_number, port->slave->dev->name,
- port->aggregator->aggregator_identifier);
+ pr_warning(DRV_NAME ": %s: Warning: Port %d (on %s) "
+ "was related to aggregator %d but was not "
+ "on its port list\n",
+ port->slave->dev->master->name,
+ port->actor_port_number,
+ port->slave->dev->name,
+ port->aggregator->aggregator_identifier);
}
}
// search on all aggregators for a suitable aggregator for this port
@@ -1378,7 +1381,8 @@ static void ad_port_selection_logic(struct port *port)
pr_debug("Port %d joined LAG %d(new LAG)\n", port->actor_port_number, port->aggregator->aggregator_identifier);
} else {
- printk(KERN_ERR DRV_NAME ": %s: Port %d (on %s) did not find a suitable aggregator\n",
+ pr_err(DRV_NAME ": %s: Port %d (on %s) did not find "
+ "a suitable aggregator\n",
port->slave->dev->master->name,
port->actor_port_number, port->slave->dev->name);
}
@@ -1455,10 +1459,10 @@ static struct aggregator *ad_agg_selection_test(struct aggregator *best,
break;
default:
- printk(KERN_WARNING DRV_NAME
- ": %s: Impossible agg select mode %d\n",
- curr->slave->dev->master->name,
- __get_agg_selection_mode(curr->lag_ports));
+ pr_warning(DRV_NAME
+ ": %s: Impossible agg select mode %d\n",
+ curr->slave->dev->master->name,
+ __get_agg_selection_mode(curr->lag_ports));
break;
}
@@ -1561,7 +1565,7 @@ static void ad_agg_selection_logic(struct aggregator *agg)
// check if any partner replys
if (best->is_individual) {
- printk(KERN_WARNING DRV_NAME ": %s: Warning: No 802.3ad"
+ pr_warning(DRV_NAME ": %s: Warning: No 802.3ad"
" response from the link partner for any"
" adapters in the bond\n",
best->slave->dev->master->name);
@@ -1884,7 +1888,8 @@ int bond_3ad_bind_slave(struct slave *slave)
struct aggregator *aggregator;
if (bond == NULL) {
- printk(KERN_ERR DRV_NAME ": %s: The slave %s is not attached to its bond\n",
+ pr_err(DRV_NAME ": %s: The slave %s is not attached to "
+ "its bond\n",
slave->dev->master->name, slave->dev->name);
return -1;
}
@@ -1960,9 +1965,9 @@ void bond_3ad_unbind_slave(struct slave *slave)
// if slave is null, the whole port is not initialized
if (!port->slave) {
- printk(KERN_WARNING DRV_NAME ": Warning: %s: Trying to "
- "unbind an uninitialized port on %s\n",
- slave->dev->master->name, slave->dev->name);
+ pr_warning(DRV_NAME ": Warning: %s: Trying to "
+ "unbind an uninitialized port on %s\n",
+ slave->dev->master->name, slave->dev->name);
return;
}
@@ -1993,8 +1998,8 @@ void bond_3ad_unbind_slave(struct slave *slave)
pr_debug("Some port(s) related to LAG %d - replaceing with LAG %d\n", aggregator->aggregator_identifier, new_aggregator->aggregator_identifier);
if ((new_aggregator->lag_ports == port) && new_aggregator->is_active) {
- printk(KERN_INFO DRV_NAME ": %s: Removing an active aggregator\n",
- aggregator->slave->dev->master->name);
+ pr_info(DRV_NAME ": %s: Removing an active aggregator\n",
+ aggregator->slave->dev->master->name);
// select new active aggregator
select_new_active_agg = 1;
}
@@ -2024,17 +2029,17 @@ void bond_3ad_unbind_slave(struct slave *slave)
ad_agg_selection_logic(__get_first_agg(port));
}
} else {
- printk(KERN_WARNING DRV_NAME ": %s: Warning: unbinding aggregator, "
- "and could not find a new aggregator for its ports\n",
- slave->dev->master->name);
+ pr_warning(DRV_NAME ": %s: Warning: unbinding aggregator, "
+ "and could not find a new aggregator for its ports\n",
+ slave->dev->master->name);
}
} else { // in case that the only port related to this aggregator is the one we want to remove
select_new_active_agg = aggregator->is_active;
// clear the aggregator
ad_clear_agg(aggregator);
if (select_new_active_agg) {
- printk(KERN_INFO DRV_NAME ": %s: Removing an active aggregator\n",
- slave->dev->master->name);
+ pr_info(DRV_NAME ": %s: Removing an active aggregator\n",
+ slave->dev->master->name);
// select new active aggregator
ad_agg_selection_logic(__get_first_agg(port));
}
@@ -2060,8 +2065,8 @@ void bond_3ad_unbind_slave(struct slave *slave)
// clear the aggregator
ad_clear_agg(temp_aggregator);
if (select_new_active_agg) {
- printk(KERN_INFO DRV_NAME ": %s: Removing an active aggregator\n",
- slave->dev->master->name);
+ pr_info(DRV_NAME ": %s: Removing an active aggregator\n",
+ slave->dev->master->name);
// select new active aggregator
ad_agg_selection_logic(__get_first_agg(port));
}
@@ -2109,8 +2114,8 @@ void bond_3ad_state_machine_handler(struct work_struct *work)
// select the active aggregator for the bond
if ((port = __get_first_port(bond))) {
if (!port->slave) {
- printk(KERN_WARNING DRV_NAME ": %s: Warning: bond's first port is "
- "uninitialized\n", bond->dev->name);
+ pr_warning(DRV_NAME ": %s: Warning: bond's first port is "
+ "uninitialized\n", bond->dev->name);
goto re_arm;
}
@@ -2123,8 +2128,8 @@ void bond_3ad_state_machine_handler(struct work_struct *work)
// for each port run the state machines
for (port = __get_first_port(bond); port; port = __get_next_port(port)) {
if (!port->slave) {
- printk(KERN_WARNING DRV_NAME ": %s: Warning: Found an uninitialized "
- "port\n", bond->dev->name);
+ pr_warning(DRV_NAME ": %s: Warning: Found an uninitialized "
+ "port\n", bond->dev->name);
goto re_arm;
}
@@ -2165,8 +2170,9 @@ static void bond_3ad_rx_indication(struct lacpdu *lacpdu, struct slave *slave, u
port = &(SLAVE_AD_INFO(slave).port);
if (!port->slave) {
- printk(KERN_WARNING DRV_NAME ": %s: Warning: port of slave %s is "
- "uninitialized\n", slave->dev->name, slave->dev->master->name);
+ pr_warning(DRV_NAME ": %s: Warning: port of slave %s "
+ "is uninitialized\n",
+ slave->dev->name, slave->dev->master->name);
return;
}
@@ -2211,9 +2217,9 @@ void bond_3ad_adapter_speed_changed(struct slave *slave)
// if slave is null, the whole port is not initialized
if (!port->slave) {
- printk(KERN_WARNING DRV_NAME ": Warning: %s: speed "
- "changed for uninitialized port on %s\n",
- slave->dev->master->name, slave->dev->name);
+ pr_warning(DRV_NAME ": Warning: %s: speed "
+ "changed for uninitialized port on %s\n",
+ slave->dev->master->name, slave->dev->name);
return;
}
@@ -2239,9 +2245,9 @@ void bond_3ad_adapter_duplex_changed(struct slave *slave)
// if slave is null, the whole port is not initialized
if (!port->slave) {
- printk(KERN_WARNING DRV_NAME ": %s: Warning: duplex changed "
- "for uninitialized port on %s\n",
- slave->dev->master->name, slave->dev->name);
+ pr_warning(DRV_NAME ": %s: Warning: duplex changed "
+ "for uninitialized port on %s\n",
+ slave->dev->master->name, slave->dev->name);
return;
}
@@ -2268,9 +2274,9 @@ void bond_3ad_handle_link_change(struct slave *slave, char link)
// if slave is null, the whole port is not initialized
if (!port->slave) {
- printk(KERN_WARNING DRV_NAME ": Warning: %s: link status changed for "
- "uninitialized port on %s\n",
- slave->dev->master->name, slave->dev->name);
+ pr_warning(DRV_NAME ": Warning: %s: link status changed for "
+ "uninitialized port on %s\n",
+ slave->dev->master->name, slave->dev->name);
return;
}
@@ -2374,8 +2380,8 @@ int bond_3ad_xmit_xor(struct sk_buff *skb, struct net_device *dev)
}
if (bond_3ad_get_active_agg_info(bond, &ad_info)) {
- printk(KERN_DEBUG DRV_NAME ": %s: Error: "
- "bond_3ad_get_active_agg_info failed\n", dev->name);
+ pr_debug(DRV_NAME ": %s: Error: "
+ "bond_3ad_get_active_agg_info failed\n", dev->name);
goto out;
}
@@ -2384,9 +2390,8 @@ int bond_3ad_xmit_xor(struct sk_buff *skb, struct net_device *dev)
if (slaves_in_agg == 0) {
/*the aggregator is empty*/
- printk(KERN_DEBUG DRV_NAME ": %s: Error: active "
- "aggregator is empty\n",
- dev->name);
+ pr_debug(DRV_NAME ": %s: Error: active aggregator is empty\n",
+ dev->name);
goto out;
}
@@ -2404,7 +2409,7 @@ int bond_3ad_xmit_xor(struct sk_buff *skb, struct net_device *dev)
}
if (slave_agg_no >= 0) {
- printk(KERN_ERR DRV_NAME ": %s: Error: Couldn't find a slave to tx on "
+ pr_err(DRV_NAME ": %s: Error: Couldn't find a slave to tx on "
"for aggregator ID %d\n", dev->name, agg_id);
goto out;
}
@@ -2431,7 +2436,7 @@ out:
dev_kfree_skb(skb);
}
read_unlock(&bond->lock);
- return 0;
+ return NETDEV_TX_OK;
}
int bond_3ad_lacpdu_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type* ptype, struct net_device *orig_dev)
diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c
index 46d312bedfb..2108706d2f0 100644
--- a/drivers/net/bonding/bond_alb.c
+++ b/drivers/net/bonding/bond_alb.c
@@ -194,7 +194,7 @@ static int tlb_initialize(struct bonding *bond)
new_hashtbl = kzalloc(size, GFP_KERNEL);
if (!new_hashtbl) {
- printk(KERN_ERR DRV_NAME
+ pr_err(DRV_NAME
": %s: Error: Failed to allocate TLB hash table\n",
bond->dev->name);
return -1;
@@ -510,7 +510,7 @@ static void rlb_update_client(struct rlb_client_info *client_info)
client_info->slave->dev->dev_addr,
client_info->mac_dst);
if (!skb) {
- printk(KERN_ERR DRV_NAME
+ pr_err(DRV_NAME
": %s: Error: failed to create an ARP packet\n",
client_info->slave->dev->master->name);
continue;
@@ -521,7 +521,7 @@ static void rlb_update_client(struct rlb_client_info *client_info)
if (client_info->tag) {
skb = vlan_put_tag(skb, client_info->vlan_id);
if (!skb) {
- printk(KERN_ERR DRV_NAME
+ pr_err(DRV_NAME
": %s: Error: failed to insert VLAN tag\n",
client_info->slave->dev->master->name);
continue;
@@ -605,7 +605,7 @@ static void rlb_req_update_subnet_clients(struct bonding *bond, __be32 src_ip)
client_info = &(bond_info->rx_hashtbl[hash_index]);
if (!client_info->slave) {
- printk(KERN_ERR DRV_NAME
+ pr_err(DRV_NAME
": %s: Error: found a client with no channel in "
"the client's hash table\n",
bond->dev->name);
@@ -802,7 +802,7 @@ static int rlb_initialize(struct bonding *bond)
new_hashtbl = kmalloc(size, GFP_KERNEL);
if (!new_hashtbl) {
- printk(KERN_ERR DRV_NAME
+ pr_err(DRV_NAME
": %s: Error: Failed to allocate RLB hash table\n",
bond->dev->name);
return -1;
@@ -924,7 +924,7 @@ static void alb_send_learning_packets(struct slave *slave, u8 mac_addr[])
skb = vlan_put_tag(skb, vlan->vlan_id);
if (!skb) {
- printk(KERN_ERR DRV_NAME
+ pr_err(DRV_NAME
": %s: Error: failed to insert VLAN tag\n",
bond->dev->name);
continue;
@@ -954,7 +954,7 @@ static int alb_set_slave_mac_addr(struct slave *slave, u8 addr[], int hw)
memcpy(s_addr.sa_data, addr, dev->addr_len);
s_addr.sa_family = dev->type;
if (dev_set_mac_address(dev, &s_addr)) {
- printk(KERN_ERR DRV_NAME
+ pr_err(DRV_NAME
": %s: Error: dev_set_mac_address of dev %s failed! ALB "
"mode requires that the base driver support setting "
"the hw address also when the network device's "
@@ -1170,13 +1170,15 @@ static int alb_handle_addr_collision_on_attach(struct bonding *bond, struct slav
alb_set_slave_mac_addr(slave, free_mac_slave->perm_hwaddr,
bond->alb_info.rlb_enabled);
- printk(KERN_WARNING DRV_NAME
- ": %s: Warning: the hw address of slave %s is in use by "
- "the bond; giving it the hw address of %s\n",
- bond->dev->name, slave->dev->name, free_mac_slave->dev->name);
+ pr_warning(DRV_NAME
+ ": %s: Warning: the hw address of slave %s is "
+ "in use by the bond; giving it the hw address "
+ "of %s\n",
+ bond->dev->name, slave->dev->name,
+ free_mac_slave->dev->name);
} else if (has_bond_addr) {
- printk(KERN_ERR DRV_NAME
+ pr_err(DRV_NAME
": %s: Error: the hw address of slave %s is in use by the "
"bond; couldn't find a slave with a free hw address to "
"give it (this should not have happened)\n",
@@ -1413,7 +1415,7 @@ out:
}
read_unlock(&bond->curr_slave_lock);
read_unlock(&bond->lock);
- return 0;
+ return NETDEV_TX_OK;
}
void bond_alb_monitor(struct work_struct *work)
diff --git a/drivers/net/bonding/bond_ipv6.c b/drivers/net/bonding/bond_ipv6.c
index 0d73bf5ac5a..83921abae12 100644
--- a/drivers/net/bonding/bond_ipv6.c
+++ b/drivers/net/bonding/bond_ipv6.c
@@ -79,14 +79,14 @@ static void bond_na_send(struct net_device *slave_dev,
ND_OPT_TARGET_LL_ADDR);
if (!skb) {
- printk(KERN_ERR DRV_NAME ": NA packet allocation failed\n");
+ pr_err(DRV_NAME ": NA packet allocation failed\n");
return;
}
if (vlan_id) {
skb = vlan_put_tag(skb, vlan_id);
if (!skb) {
- printk(KERN_ERR DRV_NAME ": failed to insert VLAN tag\n");
+ pr_err(DRV_NAME ": failed to insert VLAN tag\n");
return;
}
}
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index aa1be1fecee..4798d30c954 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -4285,7 +4285,7 @@ out:
dev_kfree_skb(skb);
}
read_unlock(&bond->lock);
- return 0;
+ return NETDEV_TX_OK;
}
@@ -4316,7 +4316,7 @@ out:
read_unlock(&bond->curr_slave_lock);
read_unlock(&bond->lock);
- return 0;
+ return NETDEV_TX_OK;
}
/*
@@ -4362,7 +4362,7 @@ out:
dev_kfree_skb(skb);
}
read_unlock(&bond->lock);
- return 0;
+ return NETDEV_TX_OK;
}
/*
@@ -4422,7 +4422,7 @@ out:
/* frame sent to all suitable interfaces */
read_unlock(&bond->lock);
- return 0;
+ return NETDEV_TX_OK;
}
/*------------------------- Device initialization ---------------------------*/
@@ -4837,7 +4837,7 @@ static int bond_check_params(struct bond_params *params)
}
if (bond_mode == BOND_MODE_ALB) {
- printk(KERN_NOTICE DRV_NAME
+ pr_notice(DRV_NAME
": In ALB mode you might experience client "
"disconnections upon reconnection of a link if the "
"bonding module updelay parameter (%d msec) is "
@@ -4961,9 +4961,9 @@ static int bond_check_params(struct bond_params *params)
arp_ip_count);
for (i = 0; i < arp_ip_count; i++)
- printk(" %s", arp_ip_target[i]);
+ pr_info(" %s", arp_ip_target[i]);
- printk("\n");
+ pr_info("\n");
} else if (max_bonds) {
/* miimon and arp_interval not set, we need one so things
diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c
index 55bf34f59bb..6044e12ff9f 100644
--- a/drivers/net/bonding/bond_sysfs.c
+++ b/drivers/net/bonding/bond_sysfs.c
@@ -218,9 +218,8 @@ static ssize_t bonding_store_slaves(struct device *d,
/* Quick sanity check -- is the bond interface up? */
if (!(bond->dev->flags & IFF_UP)) {
- printk(KERN_WARNING DRV_NAME
- ": %s: doing slave updates when interface is down.\n",
- bond->dev->name);
+ pr_warning(DRV_NAME ": %s: doing slave updates when "
+ "interface is down.\n", bond->dev->name);
}
/* Note: We can't hold bond->lock here, as bond_create grabs it. */
@@ -778,12 +777,14 @@ static ssize_t bonding_store_downdelay(struct device *d,
goto out;
} else {
if ((new_value % bond->params.miimon) != 0) {
- printk(KERN_WARNING DRV_NAME
- ": %s: Warning: down delay (%d) is not a multiple "
- "of miimon (%d), delay rounded to %d ms\n",
- bond->dev->name, new_value, bond->params.miimon,
- (new_value / bond->params.miimon) *
- bond->params.miimon);
+ pr_warning(DRV_NAME
+ ": %s: Warning: down delay (%d) is not a "
+ "multiple of miimon (%d), delay rounded "
+ "to %d ms\n",
+ bond->dev->name, new_value,
+ bond->params.miimon,
+ (new_value / bond->params.miimon) *
+ bond->params.miimon);
}
bond->params.downdelay = new_value / bond->params.miimon;
pr_info(DRV_NAME ": %s: Setting down delay to %d.\n",
@@ -838,12 +839,14 @@ static ssize_t bonding_store_updelay(struct device *d,
goto out;
} else {
if ((new_value % bond->params.miimon) != 0) {
- printk(KERN_WARNING DRV_NAME
- ": %s: Warning: up delay (%d) is not a multiple "
- "of miimon (%d), updelay rounded to %d ms\n",
- bond->dev->name, new_value, bond->params.miimon,
- (new_value / bond->params.miimon) *
- bond->params.miimon);
+ pr_warning(DRV_NAME
+ ": %s: Warning: up delay (%d) is not a "
+ "multiple of miimon (%d), updelay rounded "
+ "to %d ms\n",
+ bond->dev->name, new_value,
+ bond->params.miimon,
+ (new_value / bond->params.miimon) *
+ bond->params.miimon);
}
bond->params.updelay = new_value / bond->params.miimon;
pr_info(DRV_NAME ": %s: Setting up delay to %d.\n",
@@ -1299,9 +1302,9 @@ static ssize_t bonding_store_active_slave(struct device *d,
new_active = slave;
if (new_active == old_active) {
/* do nothing */
- printk(KERN_INFO DRV_NAME
- ": %s: %s is already the current active slave.\n",
- bond->dev->name, slave->dev->name);
+ pr_info(DRV_NAME
+ ": %s: %s is already the current active slave.\n",
+ bond->dev->name, slave->dev->name);
goto out;
}
else {
@@ -1309,17 +1312,17 @@ static ssize_t bonding_store_active_slave(struct device *d,
(old_active) &&
(new_active->link == BOND_LINK_UP) &&
IS_UP(new_active->dev)) {
- printk(KERN_INFO DRV_NAME
- ": %s: Setting %s as active slave.\n",
- bond->dev->name, slave->dev->name);
- bond_change_active_slave(bond, new_active);
+ pr_info(DRV_NAME
+ ": %s: Setting %s as active slave.\n",
+ bond->dev->name, slave->dev->name);
+ bond_change_active_slave(bond, new_active);
}
else {
- printk(KERN_INFO DRV_NAME
- ": %s: Could not set %s as active slave; "
- "either %s is down or the link is down.\n",
- bond->dev->name, slave->dev->name,
- slave->dev->name);
+ pr_info(DRV_NAME
+ ": %s: Could not set %s as active slave; "
+ "either %s is down or the link is down.\n",
+ bond->dev->name, slave->dev->name,
+ slave->dev->name);
}
goto out;
}
@@ -1537,8 +1540,8 @@ int bond_create_sysfs(void)
/* Is someone being kinky and naming a device bonding_master? */
if (__dev_get_by_name(&init_net,
class_attr_bonding_masters.attr.name))
- printk(KERN_ERR
- "network device named %s already exists in sysfs",
+ pr_err("network device named %s already "
+ "exists in sysfs",
class_attr_bonding_masters.attr.name);
ret = 0;
}
@@ -1566,7 +1569,7 @@ int bond_create_sysfs_entry(struct bonding *bond)
err = sysfs_create_group(&(dev->dev.kobj), &bonding_group);
if (err)
- printk(KERN_EMERG "eek! didn't create group!\n");
+ pr_emerg("eek! didn't create group!\n");
return err;
}
diff --git a/drivers/net/can/Kconfig b/drivers/net/can/Kconfig
index 33821a81cbf..30ae55d7167 100644
--- a/drivers/net/can/Kconfig
+++ b/drivers/net/can/Kconfig
@@ -61,11 +61,12 @@ config CAN_SJA1000_OF_PLATFORM
you may want to enable this option.
config CAN_EMS_PCI
- tristate "EMS CPC-PCI and CPC-PCIe Card"
+ tristate "EMS CPC-PCI, CPC-PCIe and CPC-104P Card"
depends on PCI && CAN_SJA1000
---help---
- This driver is for the one or two channel CPC-PCI and CPC-PCIe
- cards from EMS Dr. Thomas Wuensche (http://www.ems-wuensche.de).
+ This driver is for the one, two or four channel CPC-PCI,
+ CPC-PCIe and CPC-104P cards from EMS Dr. Thomas Wuensche
+ (http://www.ems-wuensche.de).
config CAN_KVASER_PCI
tristate "Kvaser PCIcanx and Kvaser PCIcan PCI Cards"
diff --git a/drivers/net/can/sja1000/ems_pci.c b/drivers/net/can/sja1000/ems_pci.c
index 121b64101d7..7d84b8ac9c1 100644
--- a/drivers/net/can/sja1000/ems_pci.c
+++ b/drivers/net/can/sja1000/ems_pci.c
@@ -32,13 +32,16 @@
#define DRV_NAME "ems_pci"
MODULE_AUTHOR("Sebastian Haas <haas@ems-wuenche.com>");
-MODULE_DESCRIPTION("Socket-CAN driver for EMS CPC-PCI/PCIe CAN cards");
-MODULE_SUPPORTED_DEVICE("EMS CPC-PCI/PCIe CAN card");
+MODULE_DESCRIPTION("Socket-CAN driver for EMS CPC-PCI/PCIe/104P CAN cards");
+MODULE_SUPPORTED_DEVICE("EMS CPC-PCI/PCIe/104P CAN card");
MODULE_LICENSE("GPL v2");
-#define EMS_PCI_MAX_CHAN 2
+#define EMS_PCI_V1_MAX_CHAN 2
+#define EMS_PCI_V2_MAX_CHAN 4
+#define EMS_PCI_MAX_CHAN EMS_PCI_V2_MAX_CHAN
struct ems_pci_card {
+ int version;
int channels;
struct pci_dev *pci_dev;
@@ -63,12 +66,22 @@ struct ems_pci_card {
#define PITA2_MISC_CONFIG 0x04000000 /* Multiplexed parallel interface */
/*
+ * Register definitions for the PLX 9030
+ */
+#define PLX_ICSR 0x4c /* Interrupt Control/Status register */
+#define PLX_ICSR_LINTI1_ENA 0x0001 /* LINTi1 Enable */
+#define PLX_ICSR_PCIINT_ENA 0x0040 /* PCI Interrupt Enable */
+#define PLX_ICSR_LINTI1_CLR 0x0400 /* Local Edge Triggerable Interrupt Clear */
+#define PLX_ICSR_ENA_CLR (PLX_ICSR_LINTI1_ENA | PLX_ICSR_PCIINT_ENA | \
+ PLX_ICSR_LINTI1_CLR)
+
+/*
* The board configuration is probably following:
* RX1 is connected to ground.
* TX1 is not connected.
* CLKO is not connected.
* Setting the OCR register to 0xDA is a good idea.
- * This means normal output mode , push-pull and the correct polarity.
+ * This means normal output mode, push-pull and the correct polarity.
*/
#define EMS_PCI_OCR (OCR_TX0_PUSHPULL | OCR_TX1_PUSHPULL)
@@ -79,17 +92,21 @@ struct ems_pci_card {
* is driven by the first one CLKOUT output.
*/
#define EMS_PCI_CDR (CDR_CBP | CDR_CLKOUT_MASK)
-#define EMS_PCI_MEM_SIZE 4096 /* Size of the remapped io-memory */
+
+#define EMS_PCI_V1_BASE_BAR 1
+#define EMS_PCI_V1_MEM_SIZE 4096
+#define EMS_PCI_V2_BASE_BAR 2
+#define EMS_PCI_V2_MEM_SIZE 128
#define EMS_PCI_CAN_BASE_OFFSET 0x400 /* offset where the controllers starts */
#define EMS_PCI_CAN_CTRL_SIZE 0x200 /* memory size for each controller */
-#define EMS_PCI_PORT_BYTES 0x4 /* Each register occupies 4 bytes */
-
-#define EMS_PCI_VENDOR_ID 0x110a /* PCI device and vendor ID */
-#define EMS_PCI_DEVICE_ID 0x2104
-
static struct pci_device_id ems_pci_tbl[] = {
- {EMS_PCI_VENDOR_ID, EMS_PCI_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
+ /* CPC-PCI v1 */
+ {PCI_VENDOR_ID_SIEMENS, 0x2104, PCI_ANY_ID, PCI_ANY_ID,},
+ /* CPC-PCI v2 */
+ {PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9030, PCI_VENDOR_ID_PLX, 0x4000},
+ /* CPC-104P v2 */
+ {PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9030, PCI_VENDOR_ID_PLX, 0x4002},
{0,}
};
MODULE_DEVICE_TABLE(pci, ems_pci_tbl);
@@ -97,28 +114,47 @@ MODULE_DEVICE_TABLE(pci, ems_pci_tbl);
/*
* Helper to read internal registers from card logic (not CAN)
*/
-static u8 ems_pci_readb(struct ems_pci_card *card, unsigned int port)
+static u8 ems_pci_v1_readb(struct ems_pci_card *card, unsigned int port)
{
- return readb(card->base_addr + (port * EMS_PCI_PORT_BYTES));
+ return readb(card->base_addr + (port * 4));
}
-static u8 ems_pci_read_reg(const struct sja1000_priv *priv, int port)
+static u8 ems_pci_v1_read_reg(const struct sja1000_priv *priv, int port)
{
- return readb(priv->reg_base + (port * EMS_PCI_PORT_BYTES));
+ return readb(priv->reg_base + (port * 4));
}
-static void ems_pci_write_reg(const struct sja1000_priv *priv, int port, u8 val)
+static void ems_pci_v1_write_reg(const struct sja1000_priv *priv,
+ int port, u8 val)
{
- writeb(val, priv->reg_base + (port * EMS_PCI_PORT_BYTES));
+ writeb(val, priv->reg_base + (port * 4));
}
-static void ems_pci_post_irq(const struct sja1000_priv *priv)
+static void ems_pci_v1_post_irq(const struct sja1000_priv *priv)
{
struct ems_pci_card *card = (struct ems_pci_card *)priv->priv;
/* reset int flag of pita */
- writel(PITA2_ICR_INT0_EN | PITA2_ICR_INT0, card->conf_addr
- + PITA2_ICR);
+ writel(PITA2_ICR_INT0_EN | PITA2_ICR_INT0,
+ card->conf_addr + PITA2_ICR);
+}
+
+static u8 ems_pci_v2_read_reg(const struct sja1000_priv *priv, int port)
+{
+ return readb(priv->reg_base + port);
+}
+
+static void ems_pci_v2_write_reg(const struct sja1000_priv *priv,
+ int port, u8 val)
+{
+ writeb(val, priv->reg_base + port);
+}
+
+static void ems_pci_v2_post_irq(const struct sja1000_priv *priv)
+{
+ struct ems_pci_card *card = (struct ems_pci_card *)priv->priv;
+
+ writel(PLX_ICSR_ENA_CLR, card->conf_addr + PLX_ICSR);
}
/*
@@ -130,12 +166,12 @@ static inline int ems_pci_check_chan(const struct sja1000_priv *priv)
unsigned char res;
/* Make sure SJA1000 is in reset mode */
- ems_pci_write_reg(priv, REG_MOD, 1);
+ priv->write_reg(priv, REG_MOD, 1);
- ems_pci_write_reg(priv, REG_CDR, CDR_PELICAN);
+ priv->write_reg(priv, REG_CDR, CDR_PELICAN);
/* read reset-values */
- res = ems_pci_read_reg(priv, REG_CDR);
+ res = priv->read_reg(priv, REG_CDR);
if (res == CDR_PELICAN)
return 1;
@@ -188,6 +224,7 @@ static int __devinit ems_pci_add_card(struct pci_dev *pdev,
struct sja1000_priv *priv;
struct net_device *dev;
struct ems_pci_card *card;
+ int max_chan, mem_size, base_bar;
int err, i;
/* Enabling PCI device */
@@ -210,37 +247,52 @@ static int __devinit ems_pci_add_card(struct pci_dev *pdev,
card->channels = 0;
- /* Remap PITA configuration space, and controller memory area */
- card->conf_addr = pci_iomap(pdev, 0, EMS_PCI_MEM_SIZE);
+ if (pdev->vendor == PCI_VENDOR_ID_PLX) {
+ card->version = 2; /* CPC-PCI v2 */
+ max_chan = EMS_PCI_V2_MAX_CHAN;
+ base_bar = EMS_PCI_V2_BASE_BAR;
+ mem_size = EMS_PCI_V2_MEM_SIZE;
+ } else {
+ card->version = 1; /* CPC-PCI v1 */
+ max_chan = EMS_PCI_V1_MAX_CHAN;
+ base_bar = EMS_PCI_V1_BASE_BAR;
+ mem_size = EMS_PCI_V1_MEM_SIZE;
+ }
+
+ /* Remap configuration space and controller memory area */
+ card->conf_addr = pci_iomap(pdev, 0, mem_size);
if (card->conf_addr == NULL) {
err = -ENOMEM;
goto failure_cleanup;
}
- card->base_addr = pci_iomap(pdev, 1, EMS_PCI_MEM_SIZE);
+ card->base_addr = pci_iomap(pdev, base_bar, mem_size);
if (card->base_addr == NULL) {
err = -ENOMEM;
goto failure_cleanup;
}
- /* Configure PITA-2 parallel interface (enable MUX) */
- writel(PITA2_MISC_CONFIG, card->conf_addr + PITA2_MISC);
-
- /* Check for unique EMS CAN signature */
- if (ems_pci_readb(card, 0) != 0x55 ||
- ems_pci_readb(card, 1) != 0xAA ||
- ems_pci_readb(card, 2) != 0x01 ||
- ems_pci_readb(card, 3) != 0xCB ||
- ems_pci_readb(card, 4) != 0x11) {
- dev_err(&pdev->dev, "Not EMS Dr. Thomas Wuensche interface\n");
- err = -ENODEV;
- goto failure_cleanup;
+ if (card->version == 1) {
+ /* Configure PITA-2 parallel interface (enable MUX) */
+ writel(PITA2_MISC_CONFIG, card->conf_addr + PITA2_MISC);
+
+ /* Check for unique EMS CAN signature */
+ if (ems_pci_v1_readb(card, 0) != 0x55 ||
+ ems_pci_v1_readb(card, 1) != 0xAA ||
+ ems_pci_v1_readb(card, 2) != 0x01 ||
+ ems_pci_v1_readb(card, 3) != 0xCB ||
+ ems_pci_v1_readb(card, 4) != 0x11) {
+ dev_err(&pdev->dev,
+ "Not EMS Dr. Thomas Wuensche interface\n");
+ err = -ENODEV;
+ goto failure_cleanup;
+ }
}
ems_pci_card_reset(card);
/* Detect available channels */
- for (i = 0; i < EMS_PCI_MAX_CHAN; i++) {
+ for (i = 0; i < max_chan; i++) {
dev = alloc_sja1000dev(0);
if (dev == NULL) {
err = -ENOMEM;
@@ -255,20 +307,32 @@ static int __devinit ems_pci_add_card(struct pci_dev *pdev,
dev->irq = pdev->irq;
priv->reg_base = card->base_addr + EMS_PCI_CAN_BASE_OFFSET
+ (i * EMS_PCI_CAN_CTRL_SIZE);
+ if (card->version == 1) {
+ priv->read_reg = ems_pci_v1_read_reg;
+ priv->write_reg = ems_pci_v1_write_reg;
+ priv->post_irq = ems_pci_v1_post_irq;
+ } else {
+ priv->read_reg = ems_pci_v2_read_reg;
+ priv->write_reg = ems_pci_v2_write_reg;
+ priv->post_irq = ems_pci_v2_post_irq;
+ }
/* Check if channel is present */
if (ems_pci_check_chan(priv)) {
- priv->read_reg = ems_pci_read_reg;
- priv->write_reg = ems_pci_write_reg;
- priv->post_irq = ems_pci_post_irq;
priv->can.clock.freq = EMS_PCI_CAN_CLOCK;
priv->ocr = EMS_PCI_OCR;
priv->cdr = EMS_PCI_CDR;
SET_NETDEV_DEV(dev, &pdev->dev);
- /* Enable interrupts from card */
- writel(PITA2_ICR_INT0_EN, card->conf_addr + PITA2_ICR);
+ if (card->version == 1)
+ /* reset int flag of pita */
+ writel(PITA2_ICR_INT0_EN | PITA2_ICR_INT0,
+ card->conf_addr + PITA2_ICR);
+ else
+ /* enable IRQ in PLX 9030 */
+ writel(PLX_ICSR_ENA_CLR,
+ card->conf_addr + PLX_ICSR);
/* Register SJA1000 device */
err = register_sja1000dev(dev);
diff --git a/drivers/net/can/sja1000/sja1000.c b/drivers/net/can/sja1000/sja1000.c
index 08ebee79d8a..b3004de1e5e 100644
--- a/drivers/net/can/sja1000/sja1000.c
+++ b/drivers/net/can/sja1000/sja1000.c
@@ -282,7 +282,7 @@ static int sja1000_start_xmit(struct sk_buff *skb, struct net_device *dev)
priv->write_reg(priv, REG_CMR, CMD_TR);
- return 0;
+ return NETDEV_TX_OK;
}
static void sja1000_rx(struct net_device *dev)
diff --git a/drivers/net/cassini.c b/drivers/net/cassini.c
index eb066673c2a..299a33b914f 100644
--- a/drivers/net/cassini.c
+++ b/drivers/net/cassini.c
@@ -2928,7 +2928,7 @@ static int cas_start_xmit(struct sk_buff *skb, struct net_device *dev)
static int ring;
if (skb_padto(skb, cp->min_frame_size))
- return 0;
+ return NETDEV_TX_OK;
/* XXX: we need some higher-level QoS hooks to steer packets to
* individual queues.
@@ -2936,7 +2936,7 @@ static int cas_start_xmit(struct sk_buff *skb, struct net_device *dev)
if (cas_xmit_tx_ringN(cp, ring++ & N_TX_RINGS_MASK, skb))
return NETDEV_TX_BUSY;
dev->trans_start = jiffies;
- return 0;
+ return NETDEV_TX_OK;
}
static void cas_init_tx_dma(struct cas *cp)
diff --git a/drivers/net/cpmac.c b/drivers/net/cpmac.c
index fd5e32cbcb8..3e3fab8afb1 100644
--- a/drivers/net/cpmac.c
+++ b/drivers/net/cpmac.c
@@ -54,7 +54,7 @@ module_param(dumb_switch, int, 0444);
MODULE_PARM_DESC(debug_level, "Number of NETIF_MSG bits to enable");
MODULE_PARM_DESC(dumb_switch, "Assume switch is not connected to MDIO bus");
-#define CPMAC_VERSION "0.5.0"
+#define CPMAC_VERSION "0.5.1"
/* frame size + 802.1q tag */
#define CPMAC_SKB_SIZE (ETH_FRAME_LEN + 4)
#define CPMAC_QUEUES 8
@@ -1109,7 +1109,7 @@ static int external_switch;
static int __devinit cpmac_probe(struct platform_device *pdev)
{
int rc, phy_id;
- char *mdio_bus_id = "0";
+ char mdio_bus_id[BUS_ID_SIZE];
struct resource *mem;
struct cpmac_priv *priv;
struct net_device *dev;
@@ -1117,22 +1117,23 @@ static int __devinit cpmac_probe(struct platform_device *pdev)
pdata = pdev->dev.platform_data;
- for (phy_id = 0; phy_id < PHY_MAX_ADDR; phy_id++) {
- if (!(pdata->phy_mask & (1 << phy_id)))
- continue;
- if (!cpmac_mii->phy_map[phy_id])
- continue;
- break;
+ if (external_switch || dumb_switch) {
+ strncpy(mdio_bus_id, "0", BUS_ID_SIZE); /* fixed phys bus */
+ phy_id = pdev->id;
+ } else {
+ for (phy_id = 0; phy_id < PHY_MAX_ADDR; phy_id++) {
+ if (!(pdata->phy_mask & (1 << phy_id)))
+ continue;
+ if (!cpmac_mii->phy_map[phy_id])
+ continue;
+ strncpy(mdio_bus_id, cpmac_mii->id, BUS_ID_SIZE);
+ break;
+ }
}
if (phy_id == PHY_MAX_ADDR) {
- if (external_switch || dumb_switch) {
- mdio_bus_id = 0; /* fixed phys bus */
- phy_id = pdev->id;
- } else {
- dev_err(&pdev->dev, "no PHY present\n");
- return -ENODEV;
- }
+ dev_err(&pdev->dev, "no PHY present\n");
+ return -ENODEV;
}
dev = alloc_etherdev_mq(sizeof(*priv), CPMAC_QUEUES);
@@ -1166,8 +1167,11 @@ static int __devinit cpmac_probe(struct platform_device *pdev)
priv->msg_enable = netif_msg_init(debug_level, 0xff);
memcpy(dev->dev_addr, pdata->dev_addr, sizeof(dev->dev_addr));
- priv->phy = phy_connect(dev, dev_name(&cpmac_mii->phy_map[phy_id]->dev),
- &cpmac_adjust_link, 0, PHY_INTERFACE_MODE_MII);
+ snprintf(priv->phy_name, BUS_ID_SIZE, PHY_ID_FMT, mdio_bus_id, phy_id);
+
+ priv->phy = phy_connect(dev, priv->phy_name, &cpmac_adjust_link, 0,
+ PHY_INTERFACE_MODE_MII);
+
if (IS_ERR(priv->phy)) {
if (netif_msg_drv(priv))
printk(KERN_ERR "%s: Could not attach to PHY\n",
@@ -1241,11 +1245,11 @@ int __devinit cpmac_init(void)
cpmac_mii->reset(cpmac_mii);
- for (i = 0; i < 300000; i++)
+ for (i = 0; i < 300; i++)
if ((mask = cpmac_read(cpmac_mii->priv, CPMAC_MDIO_ALIVE)))
break;
else
- cpu_relax();
+ msleep(10);
mask &= 0x7fffffff;
if (mask & (mask - 1)) {
@@ -1254,7 +1258,7 @@ int __devinit cpmac_init(void)
}
cpmac_mii->phy_mask = ~(mask | 0x80000000);
- snprintf(cpmac_mii->id, MII_BUS_ID_SIZE, "0");
+ snprintf(cpmac_mii->id, MII_BUS_ID_SIZE, "1");
res = mdiobus_register(cpmac_mii);
if (res)
diff --git a/drivers/net/cris/eth_v10.c b/drivers/net/cris/eth_v10.c
index 7a18dc7e5c7..15c0195ebd3 100644
--- a/drivers/net/cris/eth_v10.c
+++ b/drivers/net/cris/eth_v10.c
@@ -1108,7 +1108,7 @@ e100_send_packet(struct sk_buff *skb, struct net_device *dev)
spin_unlock_irqrestore(&np->lock, flags);
- return 0;
+ return NETDEV_TX_OK;
}
/*
diff --git a/drivers/net/cs89x0.c b/drivers/net/cs89x0.c
index 55445f980f9..839cac5fd8a 100644
--- a/drivers/net/cs89x0.c
+++ b/drivers/net/cs89x0.c
@@ -177,13 +177,10 @@ static unsigned int cs8900_irq_map[] = {1,0,0,0};
#elif defined(CONFIG_MACH_IXDP2351)
static unsigned int netcard_portlist[] __used __initdata = {IXDP2351_VIRT_CS8900_BASE, 0};
static unsigned int cs8900_irq_map[] = {IRQ_IXDP2351_CS8900, 0, 0, 0};
-#include <asm/irq.h>
#elif defined(CONFIG_ARCH_IXDP2X01)
-#include <asm/irq.h>
static unsigned int netcard_portlist[] __used __initdata = {IXDP2X01_CS8900_VIRT_BASE, 0};
static unsigned int cs8900_irq_map[] = {IRQ_IXDP2X01_CS8900, 0, 0, 0};
#elif defined(CONFIG_ARCH_PNX010X)
-#include <asm/irq.h>
#include <mach/gpio.h>
#define CIRRUS_DEFAULT_BASE IO_ADDRESS(EXT_STATIC2_s0_BASE + 0x200000) /* = Physical address 0x48200000 */
#define CIRRUS_DEFAULT_IRQ VH_INTC_INT_NUM_CASCADED_INTERRUPT_1 /* Event inputs bank 1 - ID 35/bit 3 */
@@ -1367,7 +1364,7 @@ net_open(struct net_device *dev)
spin_lock_irqsave(&lp->lock, flags);
disable_dma(dev->dma);
clear_dma_ff(dev->dma);
- set_dma_mode(dev->dma, 0x14); /* auto_init as well */
+ set_dma_mode(dev->dma, DMA_RX_MODE); /* auto_init as well */
set_dma_addr(dev->dma, isa_virt_to_bus(lp->dma_buff));
set_dma_count(dev->dma, lp->dmasize*1024);
enable_dma(dev->dma);
@@ -1572,7 +1569,7 @@ static int net_send_packet(struct sk_buff *skb, struct net_device *dev)
* to restart the netdevice layer
*/
- return 0;
+ return NETDEV_TX_OK;
}
/* The typical workload of the driver:
diff --git a/drivers/net/cxgb3/adapter.h b/drivers/net/cxgb3/adapter.h
index 1694fad3872..74723f2e743 100644
--- a/drivers/net/cxgb3/adapter.h
+++ b/drivers/net/cxgb3/adapter.h
@@ -276,6 +276,14 @@ static inline struct port_info *adap2pinfo(struct adapter *adap, int idx)
return netdev_priv(adap->port[idx]);
}
+static inline int phy2portid(struct cphy *phy)
+{
+ struct adapter *adap = phy->adapter;
+ struct port_info *port0 = adap2pinfo(adap, 0);
+
+ return &port0->phy == phy ? 0 : 1;
+}
+
#define OFFLOAD_DEVMAP_BIT 15
#define tdev2adap(d) container_of(d, struct adapter, tdev)
@@ -312,4 +320,6 @@ int t3_get_desc(const struct sge_qset *qs, unsigned int qnum, unsigned int idx,
unsigned char *data);
irqreturn_t t3_sge_intr_msix(int irq, void *cookie);
+int t3_get_edc_fw(struct cphy *phy, int edc_idx, int size);
+
#endif /* __T3_ADAPTER_H__ */
diff --git a/drivers/net/cxgb3/ael1002.c b/drivers/net/cxgb3/ael1002.c
index 9fe008ec9ba..5248f9e0b2f 100644
--- a/drivers/net/cxgb3/ael1002.c
+++ b/drivers/net/cxgb3/ael1002.c
@@ -224,12 +224,6 @@ static int ael1006_reset(struct cphy *phy, int wait)
return t3_phy_reset(phy, MDIO_MMD_PMAPMD, wait);
}
-static int ael1006_power_down(struct cphy *phy, int enable)
-{
- return mdio_set_flag(&phy->mdio, phy->mdio.prtad, MDIO_MMD_PMAPMD,
- MDIO_CTRL1, MDIO_CTRL1_LPOWER, enable);
-}
-
static struct cphy_ops ael1006_ops = {
.reset = ael1006_reset,
.intr_enable = t3_phy_lasi_intr_enable,
@@ -237,7 +231,7 @@ static struct cphy_ops ael1006_ops = {
.intr_clear = t3_phy_lasi_intr_clear,
.intr_handler = t3_phy_lasi_intr_handler,
.get_link_status = get_link_status_r,
- .power_down = ael1006_power_down,
+ .power_down = ael1002_power_down,
.mmds = MDIO_DEVS_PMAPMD | MDIO_DEVS_PCS | MDIO_DEVS_PHYXS,
};
@@ -304,279 +298,7 @@ static int ael2005_setup_sr_edc(struct cphy *phy)
{ MDIO_MMD_PMAPMD, 0xc04a, 0xffff, 0x5200 },
{ 0, 0, 0, 0 }
};
- static u16 sr_edc[] = {
- 0xcc00, 0x2ff4,
- 0xcc01, 0x3cd4,
- 0xcc02, 0x2015,
- 0xcc03, 0x3105,
- 0xcc04, 0x6524,
- 0xcc05, 0x27ff,
- 0xcc06, 0x300f,
- 0xcc07, 0x2c8b,
- 0xcc08, 0x300b,
- 0xcc09, 0x4009,
- 0xcc0a, 0x400e,
- 0xcc0b, 0x2f72,
- 0xcc0c, 0x3002,
- 0xcc0d, 0x1002,
- 0xcc0e, 0x2172,
- 0xcc0f, 0x3012,
- 0xcc10, 0x1002,
- 0xcc11, 0x25d2,
- 0xcc12, 0x3012,
- 0xcc13, 0x1002,
- 0xcc14, 0xd01e,
- 0xcc15, 0x27d2,
- 0xcc16, 0x3012,
- 0xcc17, 0x1002,
- 0xcc18, 0x2004,
- 0xcc19, 0x3c84,
- 0xcc1a, 0x6436,
- 0xcc1b, 0x2007,
- 0xcc1c, 0x3f87,
- 0xcc1d, 0x8676,
- 0xcc1e, 0x40b7,
- 0xcc1f, 0xa746,
- 0xcc20, 0x4047,
- 0xcc21, 0x5673,
- 0xcc22, 0x2982,
- 0xcc23, 0x3002,
- 0xcc24, 0x13d2,
- 0xcc25, 0x8bbd,
- 0xcc26, 0x2862,
- 0xcc27, 0x3012,
- 0xcc28, 0x1002,
- 0xcc29, 0x2092,
- 0xcc2a, 0x3012,
- 0xcc2b, 0x1002,
- 0xcc2c, 0x5cc3,
- 0xcc2d, 0x314,
- 0xcc2e, 0x2942,
- 0xcc2f, 0x3002,
- 0xcc30, 0x1002,
- 0xcc31, 0xd019,
- 0xcc32, 0x2032,
- 0xcc33, 0x3012,
- 0xcc34, 0x1002,
- 0xcc35, 0x2a04,
- 0xcc36, 0x3c74,
- 0xcc37, 0x6435,
- 0xcc38, 0x2fa4,
- 0xcc39, 0x3cd4,
- 0xcc3a, 0x6624,
- 0xcc3b, 0x5563,
- 0xcc3c, 0x2d42,
- 0xcc3d, 0x3002,
- 0xcc3e, 0x13d2,
- 0xcc3f, 0x464d,
- 0xcc40, 0x2862,
- 0xcc41, 0x3012,
- 0xcc42, 0x1002,
- 0xcc43, 0x2032,
- 0xcc44, 0x3012,
- 0xcc45, 0x1002,
- 0xcc46, 0x2fb4,
- 0xcc47, 0x3cd4,
- 0xcc48, 0x6624,
- 0xcc49, 0x5563,
- 0xcc4a, 0x2d42,
- 0xcc4b, 0x3002,
- 0xcc4c, 0x13d2,
- 0xcc4d, 0x2ed2,
- 0xcc4e, 0x3002,
- 0xcc4f, 0x1002,
- 0xcc50, 0x2fd2,
- 0xcc51, 0x3002,
- 0xcc52, 0x1002,
- 0xcc53, 0x004,
- 0xcc54, 0x2942,
- 0xcc55, 0x3002,
- 0xcc56, 0x1002,
- 0xcc57, 0x2092,
- 0xcc58, 0x3012,
- 0xcc59, 0x1002,
- 0xcc5a, 0x5cc3,
- 0xcc5b, 0x317,
- 0xcc5c, 0x2f72,
- 0xcc5d, 0x3002,
- 0xcc5e, 0x1002,
- 0xcc5f, 0x2942,
- 0xcc60, 0x3002,
- 0xcc61, 0x1002,
- 0xcc62, 0x22cd,
- 0xcc63, 0x301d,
- 0xcc64, 0x2862,
- 0xcc65, 0x3012,
- 0xcc66, 0x1002,
- 0xcc67, 0x2ed2,
- 0xcc68, 0x3002,
- 0xcc69, 0x1002,
- 0xcc6a, 0x2d72,
- 0xcc6b, 0x3002,
- 0xcc6c, 0x1002,
- 0xcc6d, 0x628f,
- 0xcc6e, 0x2112,
- 0xcc6f, 0x3012,
- 0xcc70, 0x1002,
- 0xcc71, 0x5aa3,
- 0xcc72, 0x2dc2,
- 0xcc73, 0x3002,
- 0xcc74, 0x1312,
- 0xcc75, 0x6f72,
- 0xcc76, 0x1002,
- 0xcc77, 0x2807,
- 0xcc78, 0x31a7,
- 0xcc79, 0x20c4,
- 0xcc7a, 0x3c24,
- 0xcc7b, 0x6724,
- 0xcc7c, 0x1002,
- 0xcc7d, 0x2807,
- 0xcc7e, 0x3187,
- 0xcc7f, 0x20c4,
- 0xcc80, 0x3c24,
- 0xcc81, 0x6724,
- 0xcc82, 0x1002,
- 0xcc83, 0x2514,
- 0xcc84, 0x3c64,
- 0xcc85, 0x6436,
- 0xcc86, 0xdff4,
- 0xcc87, 0x6436,
- 0xcc88, 0x1002,
- 0xcc89, 0x40a4,
- 0xcc8a, 0x643c,
- 0xcc8b, 0x4016,
- 0xcc8c, 0x8c6c,
- 0xcc8d, 0x2b24,
- 0xcc8e, 0x3c24,
- 0xcc8f, 0x6435,
- 0xcc90, 0x1002,
- 0xcc91, 0x2b24,
- 0xcc92, 0x3c24,
- 0xcc93, 0x643a,
- 0xcc94, 0x4025,
- 0xcc95, 0x8a5a,
- 0xcc96, 0x1002,
- 0xcc97, 0x2731,
- 0xcc98, 0x3011,
- 0xcc99, 0x1001,
- 0xcc9a, 0xc7a0,
- 0xcc9b, 0x100,
- 0xcc9c, 0xc502,
- 0xcc9d, 0x53ac,
- 0xcc9e, 0xc503,
- 0xcc9f, 0xd5d5,
- 0xcca0, 0xc600,
- 0xcca1, 0x2a6d,
- 0xcca2, 0xc601,
- 0xcca3, 0x2a4c,
- 0xcca4, 0xc602,
- 0xcca5, 0x111,
- 0xcca6, 0xc60c,
- 0xcca7, 0x5900,
- 0xcca8, 0xc710,
- 0xcca9, 0x700,
- 0xccaa, 0xc718,
- 0xccab, 0x700,
- 0xccac, 0xc720,
- 0xccad, 0x4700,
- 0xccae, 0xc801,
- 0xccaf, 0x7f50,
- 0xccb0, 0xc802,
- 0xccb1, 0x7760,
- 0xccb2, 0xc803,
- 0xccb3, 0x7fce,
- 0xccb4, 0xc804,
- 0xccb5, 0x5700,
- 0xccb6, 0xc805,
- 0xccb7, 0x5f11,
- 0xccb8, 0xc806,
- 0xccb9, 0x4751,
- 0xccba, 0xc807,
- 0xccbb, 0x57e1,
- 0xccbc, 0xc808,
- 0xccbd, 0x2700,
- 0xccbe, 0xc809,
- 0xccbf, 0x000,
- 0xccc0, 0xc821,
- 0xccc1, 0x002,
- 0xccc2, 0xc822,
- 0xccc3, 0x014,
- 0xccc4, 0xc832,
- 0xccc5, 0x1186,
- 0xccc6, 0xc847,
- 0xccc7, 0x1e02,
- 0xccc8, 0xc013,
- 0xccc9, 0xf341,
- 0xccca, 0xc01a,
- 0xcccb, 0x446,
- 0xcccc, 0xc024,
- 0xcccd, 0x1000,
- 0xccce, 0xc025,
- 0xcccf, 0xa00,
- 0xccd0, 0xc026,
- 0xccd1, 0xc0c,
- 0xccd2, 0xc027,
- 0xccd3, 0xc0c,
- 0xccd4, 0xc029,
- 0xccd5, 0x0a0,
- 0xccd6, 0xc030,
- 0xccd7, 0xa00,
- 0xccd8, 0xc03c,
- 0xccd9, 0x01c,
- 0xccda, 0xc005,
- 0xccdb, 0x7a06,
- 0xccdc, 0x000,
- 0xccdd, 0x2731,
- 0xccde, 0x3011,
- 0xccdf, 0x1001,
- 0xcce0, 0xc620,
- 0xcce1, 0x000,
- 0xcce2, 0xc621,
- 0xcce3, 0x03f,
- 0xcce4, 0xc622,
- 0xcce5, 0x000,
- 0xcce6, 0xc623,
- 0xcce7, 0x000,
- 0xcce8, 0xc624,
- 0xcce9, 0x000,
- 0xccea, 0xc625,
- 0xcceb, 0x000,
- 0xccec, 0xc627,
- 0xcced, 0x000,
- 0xccee, 0xc628,
- 0xccef, 0x000,
- 0xccf0, 0xc62c,
- 0xccf1, 0x000,
- 0xccf2, 0x000,
- 0xccf3, 0x2806,
- 0xccf4, 0x3cb6,
- 0xccf5, 0xc161,
- 0xccf6, 0x6134,
- 0xccf7, 0x6135,
- 0xccf8, 0x5443,
- 0xccf9, 0x303,
- 0xccfa, 0x6524,
- 0xccfb, 0x00b,
- 0xccfc, 0x1002,
- 0xccfd, 0x2104,
- 0xccfe, 0x3c24,
- 0xccff, 0x2105,
- 0xcd00, 0x3805,
- 0xcd01, 0x6524,
- 0xcd02, 0xdff4,
- 0xcd03, 0x4005,
- 0xcd04, 0x6524,
- 0xcd05, 0x1002,
- 0xcd06, 0x5dd3,
- 0xcd07, 0x306,
- 0xcd08, 0x2ff7,
- 0xcd09, 0x38f7,
- 0xcd0a, 0x60b7,
- 0xcd0b, 0xdffd,
- 0xcd0c, 0x00a,
- 0xcd0d, 0x1002,
- 0xcd0e, 0
- };
+
int i, err;
err = set_phy_regs(phy, regs);
@@ -585,9 +307,16 @@ static int ael2005_setup_sr_edc(struct cphy *phy)
msleep(50);
- for (i = 0; i < ARRAY_SIZE(sr_edc) && !err; i += 2)
- err = t3_mdio_write(phy, MDIO_MMD_PMAPMD, sr_edc[i],
- sr_edc[i + 1]);
+ if (phy->priv != edc_sr)
+ err = t3_get_edc_fw(phy, EDC_OPT_AEL2005,
+ EDC_OPT_AEL2005_SIZE);
+ if (err)
+ return err;
+
+ for (i = 0; i < EDC_OPT_AEL2005_SIZE / sizeof(u16) && !err; i += 2)
+ err = t3_mdio_write(phy, MDIO_MMD_PMAPMD,
+ phy->phy_cache[i],
+ phy->phy_cache[i + 1]);
if (!err)
phy->priv = edc_sr;
return err;
@@ -604,374 +333,6 @@ static int ael2005_setup_twinax_edc(struct cphy *phy, int modtype)
{ MDIO_MMD_PMAPMD, 0xc015, 0xffff, 0xa000 },
{ 0, 0, 0, 0 }
};
- static u16 twinax_edc[] = {
- 0xcc00, 0x4009,
- 0xcc01, 0x27ff,
- 0xcc02, 0x300f,
- 0xcc03, 0x40aa,
- 0xcc04, 0x401c,
- 0xcc05, 0x401e,
- 0xcc06, 0x2ff4,
- 0xcc07, 0x3cd4,
- 0xcc08, 0x2035,
- 0xcc09, 0x3145,
- 0xcc0a, 0x6524,
- 0xcc0b, 0x26a2,
- 0xcc0c, 0x3012,
- 0xcc0d, 0x1002,
- 0xcc0e, 0x29c2,
- 0xcc0f, 0x3002,
- 0xcc10, 0x1002,
- 0xcc11, 0x2072,
- 0xcc12, 0x3012,
- 0xcc13, 0x1002,
- 0xcc14, 0x22cd,
- 0xcc15, 0x301d,
- 0xcc16, 0x2e52,
- 0xcc17, 0x3012,
- 0xcc18, 0x1002,
- 0xcc19, 0x28e2,
- 0xcc1a, 0x3002,
- 0xcc1b, 0x1002,
- 0xcc1c, 0x628f,
- 0xcc1d, 0x2ac2,
- 0xcc1e, 0x3012,
- 0xcc1f, 0x1002,
- 0xcc20, 0x5553,
- 0xcc21, 0x2ae2,
- 0xcc22, 0x3002,
- 0xcc23, 0x1302,
- 0xcc24, 0x401e,
- 0xcc25, 0x2be2,
- 0xcc26, 0x3012,
- 0xcc27, 0x1002,
- 0xcc28, 0x2da2,
- 0xcc29, 0x3012,
- 0xcc2a, 0x1002,
- 0xcc2b, 0x2ba2,
- 0xcc2c, 0x3002,
- 0xcc2d, 0x1002,
- 0xcc2e, 0x5ee3,
- 0xcc2f, 0x305,
- 0xcc30, 0x400e,
- 0xcc31, 0x2bc2,
- 0xcc32, 0x3002,
- 0xcc33, 0x1002,
- 0xcc34, 0x2b82,
- 0xcc35, 0x3012,
- 0xcc36, 0x1002,
- 0xcc37, 0x5663,
- 0xcc38, 0x302,
- 0xcc39, 0x401e,
- 0xcc3a, 0x6f72,
- 0xcc3b, 0x1002,
- 0xcc3c, 0x628f,
- 0xcc3d, 0x2be2,
- 0xcc3e, 0x3012,
- 0xcc3f, 0x1002,
- 0xcc40, 0x22cd,
- 0xcc41, 0x301d,
- 0xcc42, 0x2e52,
- 0xcc43, 0x3012,
- 0xcc44, 0x1002,
- 0xcc45, 0x2522,
- 0xcc46, 0x3012,
- 0xcc47, 0x1002,
- 0xcc48, 0x2da2,
- 0xcc49, 0x3012,
- 0xcc4a, 0x1002,
- 0xcc4b, 0x2ca2,
- 0xcc4c, 0x3012,
- 0xcc4d, 0x1002,
- 0xcc4e, 0x2fa4,
- 0xcc4f, 0x3cd4,
- 0xcc50, 0x6624,
- 0xcc51, 0x410b,
- 0xcc52, 0x56b3,
- 0xcc53, 0x3c4,
- 0xcc54, 0x2fb2,
- 0xcc55, 0x3002,
- 0xcc56, 0x1002,
- 0xcc57, 0x220b,
- 0xcc58, 0x303b,
- 0xcc59, 0x56b3,
- 0xcc5a, 0x3c3,
- 0xcc5b, 0x866b,
- 0xcc5c, 0x400c,
- 0xcc5d, 0x23a2,
- 0xcc5e, 0x3012,
- 0xcc5f, 0x1002,
- 0xcc60, 0x2da2,
- 0xcc61, 0x3012,
- 0xcc62, 0x1002,
- 0xcc63, 0x2ca2,
- 0xcc64, 0x3012,
- 0xcc65, 0x1002,
- 0xcc66, 0x2fb4,
- 0xcc67, 0x3cd4,
- 0xcc68, 0x6624,
- 0xcc69, 0x56b3,
- 0xcc6a, 0x3c3,
- 0xcc6b, 0x866b,
- 0xcc6c, 0x401c,
- 0xcc6d, 0x2205,
- 0xcc6e, 0x3035,
- 0xcc6f, 0x5b53,
- 0xcc70, 0x2c52,
- 0xcc71, 0x3002,
- 0xcc72, 0x13c2,
- 0xcc73, 0x5cc3,
- 0xcc74, 0x317,
- 0xcc75, 0x2522,
- 0xcc76, 0x3012,
- 0xcc77, 0x1002,
- 0xcc78, 0x2da2,
- 0xcc79, 0x3012,
- 0xcc7a, 0x1002,
- 0xcc7b, 0x2b82,
- 0xcc7c, 0x3012,
- 0xcc7d, 0x1002,
- 0xcc7e, 0x5663,
- 0xcc7f, 0x303,
- 0xcc80, 0x401e,
- 0xcc81, 0x004,
- 0xcc82, 0x2c42,
- 0xcc83, 0x3012,
- 0xcc84, 0x1002,
- 0xcc85, 0x6f72,
- 0xcc86, 0x1002,
- 0xcc87, 0x628f,
- 0xcc88, 0x2304,
- 0xcc89, 0x3c84,
- 0xcc8a, 0x6436,
- 0xcc8b, 0xdff4,
- 0xcc8c, 0x6436,
- 0xcc8d, 0x2ff5,
- 0xcc8e, 0x3005,
- 0xcc8f, 0x8656,
- 0xcc90, 0xdfba,
- 0xcc91, 0x56a3,
- 0xcc92, 0xd05a,
- 0xcc93, 0x21c2,
- 0xcc94, 0x3012,
- 0xcc95, 0x1392,
- 0xcc96, 0xd05a,
- 0xcc97, 0x56a3,
- 0xcc98, 0xdfba,
- 0xcc99, 0x383,
- 0xcc9a, 0x6f72,
- 0xcc9b, 0x1002,
- 0xcc9c, 0x28c5,
- 0xcc9d, 0x3005,
- 0xcc9e, 0x4178,
- 0xcc9f, 0x5653,
- 0xcca0, 0x384,
- 0xcca1, 0x22b2,
- 0xcca2, 0x3012,
- 0xcca3, 0x1002,
- 0xcca4, 0x2be5,
- 0xcca5, 0x3005,
- 0xcca6, 0x41e8,
- 0xcca7, 0x5653,
- 0xcca8, 0x382,
- 0xcca9, 0x002,
- 0xccaa, 0x4258,
- 0xccab, 0x2474,
- 0xccac, 0x3c84,
- 0xccad, 0x6437,
- 0xccae, 0xdff4,
- 0xccaf, 0x6437,
- 0xccb0, 0x2ff5,
- 0xccb1, 0x3c05,
- 0xccb2, 0x8757,
- 0xccb3, 0xb888,
- 0xccb4, 0x9787,
- 0xccb5, 0xdff4,
- 0xccb6, 0x6724,
- 0xccb7, 0x866a,
- 0xccb8, 0x6f72,
- 0xccb9, 0x1002,
- 0xccba, 0x2d01,
- 0xccbb, 0x3011,
- 0xccbc, 0x1001,
- 0xccbd, 0xc620,
- 0xccbe, 0x14e5,
- 0xccbf, 0xc621,
- 0xccc0, 0xc53d,
- 0xccc1, 0xc622,
- 0xccc2, 0x3cbe,
- 0xccc3, 0xc623,
- 0xccc4, 0x4452,
- 0xccc5, 0xc624,
- 0xccc6, 0xc5c5,
- 0xccc7, 0xc625,
- 0xccc8, 0xe01e,
- 0xccc9, 0xc627,
- 0xccca, 0x000,
- 0xcccb, 0xc628,
- 0xcccc, 0x000,
- 0xcccd, 0xc62b,
- 0xccce, 0x000,
- 0xcccf, 0xc62c,
- 0xccd0, 0x000,
- 0xccd1, 0x000,
- 0xccd2, 0x2d01,
- 0xccd3, 0x3011,
- 0xccd4, 0x1001,
- 0xccd5, 0xc620,
- 0xccd6, 0x000,
- 0xccd7, 0xc621,
- 0xccd8, 0x000,
- 0xccd9, 0xc622,
- 0xccda, 0x0ce,
- 0xccdb, 0xc623,
- 0xccdc, 0x07f,
- 0xccdd, 0xc624,
- 0xccde, 0x032,
- 0xccdf, 0xc625,
- 0xcce0, 0x000,
- 0xcce1, 0xc627,
- 0xcce2, 0x000,
- 0xcce3, 0xc628,
- 0xcce4, 0x000,
- 0xcce5, 0xc62b,
- 0xcce6, 0x000,
- 0xcce7, 0xc62c,
- 0xcce8, 0x000,
- 0xcce9, 0x000,
- 0xccea, 0x2d01,
- 0xcceb, 0x3011,
- 0xccec, 0x1001,
- 0xcced, 0xc502,
- 0xccee, 0x609f,
- 0xccef, 0xc600,
- 0xccf0, 0x2a6e,
- 0xccf1, 0xc601,
- 0xccf2, 0x2a2c,
- 0xccf3, 0xc60c,
- 0xccf4, 0x5400,
- 0xccf5, 0xc710,
- 0xccf6, 0x700,
- 0xccf7, 0xc718,
- 0xccf8, 0x700,
- 0xccf9, 0xc720,
- 0xccfa, 0x4700,
- 0xccfb, 0xc728,
- 0xccfc, 0x700,
- 0xccfd, 0xc729,
- 0xccfe, 0x1207,
- 0xccff, 0xc801,
- 0xcd00, 0x7f50,
- 0xcd01, 0xc802,
- 0xcd02, 0x7760,
- 0xcd03, 0xc803,
- 0xcd04, 0x7fce,
- 0xcd05, 0xc804,
- 0xcd06, 0x520e,
- 0xcd07, 0xc805,
- 0xcd08, 0x5c11,
- 0xcd09, 0xc806,
- 0xcd0a, 0x3c51,
- 0xcd0b, 0xc807,
- 0xcd0c, 0x4061,
- 0xcd0d, 0xc808,
- 0xcd0e, 0x49c1,
- 0xcd0f, 0xc809,
- 0xcd10, 0x3840,
- 0xcd11, 0xc80a,
- 0xcd12, 0x000,
- 0xcd13, 0xc821,
- 0xcd14, 0x002,
- 0xcd15, 0xc822,
- 0xcd16, 0x046,
- 0xcd17, 0xc844,
- 0xcd18, 0x182f,
- 0xcd19, 0xc013,
- 0xcd1a, 0xf341,
- 0xcd1b, 0xc01a,
- 0xcd1c, 0x446,
- 0xcd1d, 0xc024,
- 0xcd1e, 0x1000,
- 0xcd1f, 0xc025,
- 0xcd20, 0xa00,
- 0xcd21, 0xc026,
- 0xcd22, 0xc0c,
- 0xcd23, 0xc027,
- 0xcd24, 0xc0c,
- 0xcd25, 0xc029,
- 0xcd26, 0x0a0,
- 0xcd27, 0xc030,
- 0xcd28, 0xa00,
- 0xcd29, 0xc03c,
- 0xcd2a, 0x01c,
- 0xcd2b, 0x000,
- 0xcd2c, 0x2b84,
- 0xcd2d, 0x3c74,
- 0xcd2e, 0x6435,
- 0xcd2f, 0xdff4,
- 0xcd30, 0x6435,
- 0xcd31, 0x2806,
- 0xcd32, 0x3006,
- 0xcd33, 0x8565,
- 0xcd34, 0x2b24,
- 0xcd35, 0x3c24,
- 0xcd36, 0x6436,
- 0xcd37, 0x1002,
- 0xcd38, 0x2b24,
- 0xcd39, 0x3c24,
- 0xcd3a, 0x6436,
- 0xcd3b, 0x4045,
- 0xcd3c, 0x8656,
- 0xcd3d, 0x1002,
- 0xcd3e, 0x2807,
- 0xcd3f, 0x31a7,
- 0xcd40, 0x20c4,
- 0xcd41, 0x3c24,
- 0xcd42, 0x6724,
- 0xcd43, 0x1002,
- 0xcd44, 0x2807,
- 0xcd45, 0x3187,
- 0xcd46, 0x20c4,
- 0xcd47, 0x3c24,
- 0xcd48, 0x6724,
- 0xcd49, 0x1002,
- 0xcd4a, 0x2514,
- 0xcd4b, 0x3c64,
- 0xcd4c, 0x6436,
- 0xcd4d, 0xdff4,
- 0xcd4e, 0x6436,
- 0xcd4f, 0x1002,
- 0xcd50, 0x2806,
- 0xcd51, 0x3cb6,
- 0xcd52, 0xc161,
- 0xcd53, 0x6134,
- 0xcd54, 0x6135,
- 0xcd55, 0x5443,
- 0xcd56, 0x303,
- 0xcd57, 0x6524,
- 0xcd58, 0x00b,
- 0xcd59, 0x1002,
- 0xcd5a, 0xd019,
- 0xcd5b, 0x2104,
- 0xcd5c, 0x3c24,
- 0xcd5d, 0x2105,
- 0xcd5e, 0x3805,
- 0xcd5f, 0x6524,
- 0xcd60, 0xdff4,
- 0xcd61, 0x4005,
- 0xcd62, 0x6524,
- 0xcd63, 0x2e8d,
- 0xcd64, 0x303d,
- 0xcd65, 0x5dd3,
- 0xcd66, 0x306,
- 0xcd67, 0x2ff7,
- 0xcd68, 0x38f7,
- 0xcd69, 0x60b7,
- 0xcd6a, 0xdffd,
- 0xcd6b, 0x00a,
- 0xcd6c, 0x1002,
- 0xcd6d, 0
- };
int i, err;
err = set_phy_regs(phy, regs);
@@ -982,9 +343,16 @@ static int ael2005_setup_twinax_edc(struct cphy *phy, int modtype)
msleep(50);
- for (i = 0; i < ARRAY_SIZE(twinax_edc) && !err; i += 2)
- err = t3_mdio_write(phy, MDIO_MMD_PMAPMD, twinax_edc[i],
- twinax_edc[i + 1]);
+ if (phy->priv != edc_twinax)
+ err = t3_get_edc_fw(phy, EDC_TWX_AEL2005,
+ EDC_TWX_AEL2005_SIZE);
+ if (err)
+ return err;
+
+ for (i = 0; i < EDC_TWX_AEL2005_SIZE / sizeof(u16) && !err; i += 2)
+ err = t3_mdio_write(phy, MDIO_MMD_PMAPMD,
+ phy->phy_cache[i],
+ phy->phy_cache[i + 1]);
if (!err)
phy->priv = edc_twinax;
return err;
@@ -1201,405 +569,6 @@ static int ael2020_setup_twinax_edc(struct cphy *phy, int modtype)
{ MDIO_MMD_PMAPMD, 0xd092, 0xffff, 0x0000 },
{ 0, 0, 0, 0 }
};
-
- /* TWINAX EDC firmware */
- static u16 twinax_edc[] = {
- 0xd800, 0x4009,
- 0xd801, 0x2fff,
- 0xd802, 0x300f,
- 0xd803, 0x40aa,
- 0xd804, 0x401c,
- 0xd805, 0x401e,
- 0xd806, 0x2ff4,
- 0xd807, 0x3dc4,
- 0xd808, 0x2035,
- 0xd809, 0x3035,
- 0xd80a, 0x6524,
- 0xd80b, 0x2cb2,
- 0xd80c, 0x3012,
- 0xd80d, 0x1002,
- 0xd80e, 0x26e2,
- 0xd80f, 0x3022,
- 0xd810, 0x1002,
- 0xd811, 0x27d2,
- 0xd812, 0x3022,
- 0xd813, 0x1002,
- 0xd814, 0x2822,
- 0xd815, 0x3012,
- 0xd816, 0x1002,
- 0xd817, 0x2492,
- 0xd818, 0x3022,
- 0xd819, 0x1002,
- 0xd81a, 0x2772,
- 0xd81b, 0x3012,
- 0xd81c, 0x1002,
- 0xd81d, 0x23d2,
- 0xd81e, 0x3022,
- 0xd81f, 0x1002,
- 0xd820, 0x22cd,
- 0xd821, 0x301d,
- 0xd822, 0x27f2,
- 0xd823, 0x3022,
- 0xd824, 0x1002,
- 0xd825, 0x5553,
- 0xd826, 0x0307,
- 0xd827, 0x2522,
- 0xd828, 0x3022,
- 0xd829, 0x1002,
- 0xd82a, 0x2142,
- 0xd82b, 0x3012,
- 0xd82c, 0x1002,
- 0xd82d, 0x4016,
- 0xd82e, 0x5e63,
- 0xd82f, 0x0344,
- 0xd830, 0x2142,
- 0xd831, 0x3012,
- 0xd832, 0x1002,
- 0xd833, 0x400e,
- 0xd834, 0x2522,
- 0xd835, 0x3022,
- 0xd836, 0x1002,
- 0xd837, 0x2b52,
- 0xd838, 0x3012,
- 0xd839, 0x1002,
- 0xd83a, 0x2742,
- 0xd83b, 0x3022,
- 0xd83c, 0x1002,
- 0xd83d, 0x25e2,
- 0xd83e, 0x3022,
- 0xd83f, 0x1002,
- 0xd840, 0x2fa4,
- 0xd841, 0x3dc4,
- 0xd842, 0x6624,
- 0xd843, 0x414b,
- 0xd844, 0x56b3,
- 0xd845, 0x03c6,
- 0xd846, 0x866b,
- 0xd847, 0x400c,
- 0xd848, 0x2712,
- 0xd849, 0x3012,
- 0xd84a, 0x1002,
- 0xd84b, 0x2c4b,
- 0xd84c, 0x309b,
- 0xd84d, 0x56b3,
- 0xd84e, 0x03c3,
- 0xd84f, 0x866b,
- 0xd850, 0x400c,
- 0xd851, 0x2272,
- 0xd852, 0x3022,
- 0xd853, 0x1002,
- 0xd854, 0x2742,
- 0xd855, 0x3022,
- 0xd856, 0x1002,
- 0xd857, 0x25e2,
- 0xd858, 0x3022,
- 0xd859, 0x1002,
- 0xd85a, 0x2fb4,
- 0xd85b, 0x3dc4,
- 0xd85c, 0x6624,
- 0xd85d, 0x56b3,
- 0xd85e, 0x03c3,
- 0xd85f, 0x866b,
- 0xd860, 0x401c,
- 0xd861, 0x2c45,
- 0xd862, 0x3095,
- 0xd863, 0x5b53,
- 0xd864, 0x2372,
- 0xd865, 0x3012,
- 0xd866, 0x13c2,
- 0xd867, 0x5cc3,
- 0xd868, 0x2712,
- 0xd869, 0x3012,
- 0xd86a, 0x1312,
- 0xd86b, 0x2b52,
- 0xd86c, 0x3012,
- 0xd86d, 0x1002,
- 0xd86e, 0x2742,
- 0xd86f, 0x3022,
- 0xd870, 0x1002,
- 0xd871, 0x2582,
- 0xd872, 0x3022,
- 0xd873, 0x1002,
- 0xd874, 0x2142,
- 0xd875, 0x3012,
- 0xd876, 0x1002,
- 0xd877, 0x628f,
- 0xd878, 0x2985,
- 0xd879, 0x33a5,
- 0xd87a, 0x25e2,
- 0xd87b, 0x3022,
- 0xd87c, 0x1002,
- 0xd87d, 0x5653,
- 0xd87e, 0x03d2,
- 0xd87f, 0x401e,
- 0xd880, 0x6f72,
- 0xd881, 0x1002,
- 0xd882, 0x628f,
- 0xd883, 0x2304,
- 0xd884, 0x3c84,
- 0xd885, 0x6436,
- 0xd886, 0xdff4,
- 0xd887, 0x6436,
- 0xd888, 0x2ff5,
- 0xd889, 0x3005,
- 0xd88a, 0x8656,
- 0xd88b, 0xdfba,
- 0xd88c, 0x56a3,
- 0xd88d, 0xd05a,
- 0xd88e, 0x2972,
- 0xd88f, 0x3012,
- 0xd890, 0x1392,
- 0xd891, 0xd05a,
- 0xd892, 0x56a3,
- 0xd893, 0xdfba,
- 0xd894, 0x0383,
- 0xd895, 0x6f72,
- 0xd896, 0x1002,
- 0xd897, 0x2b45,
- 0xd898, 0x3005,
- 0xd899, 0x4178,
- 0xd89a, 0x5653,
- 0xd89b, 0x0384,
- 0xd89c, 0x2a62,
- 0xd89d, 0x3012,
- 0xd89e, 0x1002,
- 0xd89f, 0x2f05,
- 0xd8a0, 0x3005,
- 0xd8a1, 0x41c8,
- 0xd8a2, 0x5653,
- 0xd8a3, 0x0382,
- 0xd8a4, 0x0002,
- 0xd8a5, 0x4218,
- 0xd8a6, 0x2474,
- 0xd8a7, 0x3c84,
- 0xd8a8, 0x6437,
- 0xd8a9, 0xdff4,
- 0xd8aa, 0x6437,
- 0xd8ab, 0x2ff5,
- 0xd8ac, 0x3c05,
- 0xd8ad, 0x8757,
- 0xd8ae, 0xb888,
- 0xd8af, 0x9787,
- 0xd8b0, 0xdff4,
- 0xd8b1, 0x6724,
- 0xd8b2, 0x866a,
- 0xd8b3, 0x6f72,
- 0xd8b4, 0x1002,
- 0xd8b5, 0x2641,
- 0xd8b6, 0x3021,
- 0xd8b7, 0x1001,
- 0xd8b8, 0xc620,
- 0xd8b9, 0x0000,
- 0xd8ba, 0xc621,
- 0xd8bb, 0x0000,
- 0xd8bc, 0xc622,
- 0xd8bd, 0x00ce,
- 0xd8be, 0xc623,
- 0xd8bf, 0x007f,
- 0xd8c0, 0xc624,
- 0xd8c1, 0x0032,
- 0xd8c2, 0xc625,
- 0xd8c3, 0x0000,
- 0xd8c4, 0xc627,
- 0xd8c5, 0x0000,
- 0xd8c6, 0xc628,
- 0xd8c7, 0x0000,
- 0xd8c8, 0xc62c,
- 0xd8c9, 0x0000,
- 0xd8ca, 0x0000,
- 0xd8cb, 0x2641,
- 0xd8cc, 0x3021,
- 0xd8cd, 0x1001,
- 0xd8ce, 0xc502,
- 0xd8cf, 0x53ac,
- 0xd8d0, 0xc503,
- 0xd8d1, 0x2cd3,
- 0xd8d2, 0xc600,
- 0xd8d3, 0x2a6e,
- 0xd8d4, 0xc601,
- 0xd8d5, 0x2a2c,
- 0xd8d6, 0xc605,
- 0xd8d7, 0x5557,
- 0xd8d8, 0xc60c,
- 0xd8d9, 0x5400,
- 0xd8da, 0xc710,
- 0xd8db, 0x0700,
- 0xd8dc, 0xc711,
- 0xd8dd, 0x0f06,
- 0xd8de, 0xc718,
- 0xd8df, 0x0700,
- 0xd8e0, 0xc719,
- 0xd8e1, 0x0f06,
- 0xd8e2, 0xc720,
- 0xd8e3, 0x4700,
- 0xd8e4, 0xc721,
- 0xd8e5, 0x0f06,
- 0xd8e6, 0xc728,
- 0xd8e7, 0x0700,
- 0xd8e8, 0xc729,
- 0xd8e9, 0x1207,
- 0xd8ea, 0xc801,
- 0xd8eb, 0x7f50,
- 0xd8ec, 0xc802,
- 0xd8ed, 0x7760,
- 0xd8ee, 0xc803,
- 0xd8ef, 0x7fce,
- 0xd8f0, 0xc804,
- 0xd8f1, 0x520e,
- 0xd8f2, 0xc805,
- 0xd8f3, 0x5c11,
- 0xd8f4, 0xc806,
- 0xd8f5, 0x3c51,
- 0xd8f6, 0xc807,
- 0xd8f7, 0x4061,
- 0xd8f8, 0xc808,
- 0xd8f9, 0x49c1,
- 0xd8fa, 0xc809,
- 0xd8fb, 0x3840,
- 0xd8fc, 0xc80a,
- 0xd8fd, 0x0000,
- 0xd8fe, 0xc821,
- 0xd8ff, 0x0002,
- 0xd900, 0xc822,
- 0xd901, 0x0046,
- 0xd902, 0xc844,
- 0xd903, 0x182f,
- 0xd904, 0xc013,
- 0xd905, 0xf341,
- 0xd906, 0xc084,
- 0xd907, 0x0030,
- 0xd908, 0xc904,
- 0xd909, 0x1401,
- 0xd90a, 0xcb0c,
- 0xd90b, 0x0004,
- 0xd90c, 0xcb0e,
- 0xd90d, 0xa00a,
- 0xd90e, 0xcb0f,
- 0xd90f, 0xc0c0,
- 0xd910, 0xcb10,
- 0xd911, 0xc0c0,
- 0xd912, 0xcb11,
- 0xd913, 0x00a0,
- 0xd914, 0xcb12,
- 0xd915, 0x0007,
- 0xd916, 0xc241,
- 0xd917, 0xa000,
- 0xd918, 0xc243,
- 0xd919, 0x7fe0,
- 0xd91a, 0xc604,
- 0xd91b, 0x000e,
- 0xd91c, 0xc609,
- 0xd91d, 0x00f5,
- 0xd91e, 0xc611,
- 0xd91f, 0x000e,
- 0xd920, 0xc660,
- 0xd921, 0x9600,
- 0xd922, 0xc687,
- 0xd923, 0x0004,
- 0xd924, 0xc60a,
- 0xd925, 0x04f5,
- 0xd926, 0x0000,
- 0xd927, 0x2641,
- 0xd928, 0x3021,
- 0xd929, 0x1001,
- 0xd92a, 0xc620,
- 0xd92b, 0x14e5,
- 0xd92c, 0xc621,
- 0xd92d, 0xc53d,
- 0xd92e, 0xc622,
- 0xd92f, 0x3cbe,
- 0xd930, 0xc623,
- 0xd931, 0x4452,
- 0xd932, 0xc624,
- 0xd933, 0xc5c5,
- 0xd934, 0xc625,
- 0xd935, 0xe01e,
- 0xd936, 0xc627,
- 0xd937, 0x0000,
- 0xd938, 0xc628,
- 0xd939, 0x0000,
- 0xd93a, 0xc62c,
- 0xd93b, 0x0000,
- 0xd93c, 0x0000,
- 0xd93d, 0x2b84,
- 0xd93e, 0x3c74,
- 0xd93f, 0x6435,
- 0xd940, 0xdff4,
- 0xd941, 0x6435,
- 0xd942, 0x2806,
- 0xd943, 0x3006,
- 0xd944, 0x8565,
- 0xd945, 0x2b24,
- 0xd946, 0x3c24,
- 0xd947, 0x6436,
- 0xd948, 0x1002,
- 0xd949, 0x2b24,
- 0xd94a, 0x3c24,
- 0xd94b, 0x6436,
- 0xd94c, 0x4045,
- 0xd94d, 0x8656,
- 0xd94e, 0x5663,
- 0xd94f, 0x0302,
- 0xd950, 0x401e,
- 0xd951, 0x1002,
- 0xd952, 0x2807,
- 0xd953, 0x31a7,
- 0xd954, 0x20c4,
- 0xd955, 0x3c24,
- 0xd956, 0x6724,
- 0xd957, 0x1002,
- 0xd958, 0x2807,
- 0xd959, 0x3187,
- 0xd95a, 0x20c4,
- 0xd95b, 0x3c24,
- 0xd95c, 0x6724,
- 0xd95d, 0x1002,
- 0xd95e, 0x24f4,
- 0xd95f, 0x3c64,
- 0xd960, 0x6436,
- 0xd961, 0xdff4,
- 0xd962, 0x6436,
- 0xd963, 0x1002,
- 0xd964, 0x2006,
- 0xd965, 0x3d76,
- 0xd966, 0xc161,
- 0xd967, 0x6134,
- 0xd968, 0x6135,
- 0xd969, 0x5443,
- 0xd96a, 0x0303,
- 0xd96b, 0x6524,
- 0xd96c, 0x00fb,
- 0xd96d, 0x1002,
- 0xd96e, 0x20d4,
- 0xd96f, 0x3c24,
- 0xd970, 0x2025,
- 0xd971, 0x3005,
- 0xd972, 0x6524,
- 0xd973, 0x1002,
- 0xd974, 0xd019,
- 0xd975, 0x2104,
- 0xd976, 0x3c24,
- 0xd977, 0x2105,
- 0xd978, 0x3805,
- 0xd979, 0x6524,
- 0xd97a, 0xdff4,
- 0xd97b, 0x4005,
- 0xd97c, 0x6524,
- 0xd97d, 0x2e8d,
- 0xd97e, 0x303d,
- 0xd97f, 0x2408,
- 0xd980, 0x35d8,
- 0xd981, 0x5dd3,
- 0xd982, 0x0307,
- 0xd983, 0x8887,
- 0xd984, 0x63a7,
- 0xd985, 0x8887,
- 0xd986, 0x63a7,
- 0xd987, 0xdffd,
- 0xd988, 0x00f9,
- 0xd989, 0x1002,
- 0xd98a, 0x0000,
- };
int i, err;
/* set uC clock and activate it */
@@ -1612,10 +581,16 @@ static int ael2020_setup_twinax_edc(struct cphy *phy, int modtype)
if (err)
return err;
- /* write TWINAX EDC firmware into PHY */
- for (i = 0; i < ARRAY_SIZE(twinax_edc) && !err; i += 2)
- err = t3_mdio_write(phy, MDIO_MMD_PMAPMD, twinax_edc[i],
- twinax_edc[i + 1]);
+ if (phy->priv != edc_twinax)
+ err = t3_get_edc_fw(phy, EDC_TWX_AEL2020,
+ EDC_TWX_AEL2020_SIZE);
+ if (err)
+ return err;
+
+ for (i = 0; i < EDC_TWX_AEL2020_SIZE / sizeof(u16) && !err; i += 2)
+ err = t3_mdio_write(phy, MDIO_MMD_PMAPMD,
+ phy->phy_cache[i],
+ phy->phy_cache[i + 1]);
/* activate uC */
err = set_phy_regs(phy, uCactivate);
if (!err)
@@ -1649,9 +624,39 @@ static int ael2020_get_module_type(struct cphy *phy, int delay_ms)
*/
static int ael2020_intr_enable(struct cphy *phy)
{
- int err = t3_mdio_write(phy, MDIO_MMD_PMAPMD, AEL2020_GPIO_CTRL,
- 0x2 << (AEL2020_GPIO_MODDET*4));
- return err ? err : t3_phy_lasi_intr_enable(phy);
+ struct reg_val regs[] = {
+ /* output Module's Loss Of Signal (LOS) to LED */
+ { MDIO_MMD_PMAPMD, AEL2020_GPIO_CFG+AEL2020_GPIO_LSTAT,
+ 0xffff, 0x4 },
+ { MDIO_MMD_PMAPMD, AEL2020_GPIO_CTRL,
+ 0xffff, 0x8 << (AEL2020_GPIO_LSTAT*4) },
+
+ /* enable module detect status change interrupts */
+ { MDIO_MMD_PMAPMD, AEL2020_GPIO_CTRL,
+ 0xffff, 0x2 << (AEL2020_GPIO_MODDET*4) },
+
+ /* end */
+ { 0, 0, 0, 0 }
+ };
+ int err, link_ok = 0;
+
+ /* set up "link status" LED and enable module change interrupts */
+ err = set_phy_regs(phy, regs);
+ if (err)
+ return err;
+
+ err = get_link_status_r(phy, &link_ok, NULL, NULL, NULL);
+ if (err)
+ return err;
+ if (link_ok)
+ t3_link_changed(phy->adapter,
+ phy2portid(phy));
+
+ err = t3_phy_lasi_intr_enable(phy);
+ if (err)
+ return err;
+
+ return 0;
}
/*
@@ -1659,9 +664,26 @@ static int ael2020_intr_enable(struct cphy *phy)
*/
static int ael2020_intr_disable(struct cphy *phy)
{
- int err = t3_mdio_write(phy, MDIO_MMD_PMAPMD, AEL2020_GPIO_CTRL,
- 0x1 << (AEL2020_GPIO_MODDET*4));
- return err ? err : t3_phy_lasi_intr_disable(phy);
+ struct reg_val regs[] = {
+ /* reset "link status" LED to "off" */
+ { MDIO_MMD_PMAPMD, AEL2020_GPIO_CTRL,
+ 0xffff, 0xb << (AEL2020_GPIO_LSTAT*4) },
+
+ /* disable module detect status change interrupts */
+ { MDIO_MMD_PMAPMD, AEL2020_GPIO_CTRL,
+ 0xffff, 0x1 << (AEL2020_GPIO_MODDET*4) },
+
+ /* end */
+ { 0, 0, 0, 0 }
+ };
+ int err;
+
+ /* turn off "link status" LED and disable module change interrupts */
+ err = set_phy_regs(phy, regs);
+ if (err)
+ return err;
+
+ return t3_phy_lasi_intr_disable(phy);
}
/*
@@ -1679,31 +701,26 @@ static int ael2020_intr_clear(struct cphy *phy)
return err ? err : t3_phy_lasi_intr_clear(phy);
}
+static struct reg_val ael2020_reset_regs[] = {
+ /* Erratum #2: CDRLOL asserted, causing PMA link down status */
+ { MDIO_MMD_PMAPMD, 0xc003, 0xffff, 0x3101 },
+
+ /* force XAUI to send LF when RX_LOS is asserted */
+ { MDIO_MMD_PMAPMD, 0xcd40, 0xffff, 0x0001 },
+
+ /* allow writes to transceiver module EEPROM on i2c bus */
+ { MDIO_MMD_PMAPMD, 0xff02, 0xffff, 0x0023 },
+ { MDIO_MMD_PMAPMD, 0xff03, 0xffff, 0x0000 },
+ { MDIO_MMD_PMAPMD, 0xff04, 0xffff, 0x0000 },
+
+ /* end */
+ { 0, 0, 0, 0 }
+};
/*
* Reset the PHY and put it into a canonical operating state.
*/
static int ael2020_reset(struct cphy *phy, int wait)
{
- static struct reg_val regs0[] = {
- /* Erratum #2: CDRLOL asserted, causing PMA link down status */
- { MDIO_MMD_PMAPMD, 0xc003, 0xffff, 0x3101 },
-
- /* force XAUI to send LF when RX_LOS is asserted */
- { MDIO_MMD_PMAPMD, 0xcd40, 0xffff, 0x0001 },
-
- /* RX_LOS pin is active high */
- { MDIO_MMD_PMAPMD, AEL_OPT_SETTINGS,
- 0x0020, 0x0020 },
-
- /* output Module's Loss Of Signal (LOS) to LED */
- { MDIO_MMD_PMAPMD, AEL2020_GPIO_CFG+AEL2020_GPIO_LSTAT,
- 0xffff, 0x0004 },
- { MDIO_MMD_PMAPMD, AEL2020_GPIO_CTRL,
- 0xffff, 0x8 << (AEL2020_GPIO_LSTAT*4) },
-
- /* end */
- { 0, 0, 0, 0 }
- };
int err;
unsigned int lasi_ctrl;
@@ -1720,7 +737,7 @@ static int ael2020_reset(struct cphy *phy, int wait)
/* basic initialization for all module types */
phy->priv = edc_none;
- err = set_phy_regs(phy, regs0);
+ err = set_phy_regs(phy, ael2020_reset_regs);
if (err)
return err;
@@ -1798,10 +815,16 @@ static struct cphy_ops ael2020_ops = {
int t3_ael2020_phy_prep(struct cphy *phy, struct adapter *adapter, int phy_addr,
const struct mdio_ops *mdio_ops)
{
+ int err;
+
cphy_init(phy, adapter, phy_addr, &ael2020_ops, mdio_ops,
SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_FIBRE |
SUPPORTED_IRQ, "10GBASE-R");
msleep(125);
+
+ err = set_phy_regs(phy, ael2020_reset_regs);
+ if (err)
+ return err;
return 0;
}
@@ -1840,7 +863,7 @@ static struct cphy_ops qt2045_ops = {
.intr_clear = t3_phy_lasi_intr_clear,
.intr_handler = t3_phy_lasi_intr_handler,
.get_link_status = get_link_status_x,
- .power_down = ael1006_power_down,
+ .power_down = ael1002_power_down,
.mmds = MDIO_DEVS_PMAPMD | MDIO_DEVS_PCS | MDIO_DEVS_PHYXS,
};
diff --git a/drivers/net/cxgb3/aq100x.c b/drivers/net/cxgb3/aq100x.c
index b1fd5bf836e..341b7ef1508 100644
--- a/drivers/net/cxgb3/aq100x.c
+++ b/drivers/net/cxgb3/aq100x.c
@@ -271,7 +271,8 @@ int t3_aq100x_phy_prep(struct cphy *phy, struct adapter *adapter, int phy_addr,
cphy_init(phy, adapter, phy_addr, &aq100x_ops, mdio_ops,
SUPPORTED_1000baseT_Full | SUPPORTED_10000baseT_Full |
- SUPPORTED_Autoneg | SUPPORTED_AUI, "1000/10GBASE-T");
+ SUPPORTED_TP | SUPPORTED_Autoneg | SUPPORTED_AUI,
+ "1000/10GBASE-T");
/*
* The PHY has been out of reset ever since the system powered up. So
@@ -316,11 +317,9 @@ int t3_aq100x_phy_prep(struct cphy *phy, struct adapter *adapter, int phy_addr,
/* Firmware version check. */
t3_mdio_read(phy, MDIO_MMD_VEND1, AQ_FW_VERSION, &v);
- if (v != 30) {
+ if (v != 101)
CH_WARN(adapter, "PHY%d: unsupported firmware %d\n",
phy_addr, v);
- return 0; /* allow t3_prep_adapter to succeed */
- }
/*
* The PHY should start in really-low-power mode. Prepare it for normal
diff --git a/drivers/net/cxgb3/common.h b/drivers/net/cxgb3/common.h
index d21b705501a..1b2c305fb82 100644
--- a/drivers/net/cxgb3/common.h
+++ b/drivers/net/cxgb3/common.h
@@ -566,6 +566,15 @@ struct cphy_ops {
u32 mmds;
};
+enum {
+ EDC_OPT_AEL2005 = 0,
+ EDC_OPT_AEL2005_SIZE = 1084,
+ EDC_TWX_AEL2005 = 1,
+ EDC_TWX_AEL2005_SIZE = 1464,
+ EDC_TWX_AEL2020 = 2,
+ EDC_TWX_AEL2020_SIZE = 1628,
+ EDC_MAX_SIZE = EDC_TWX_AEL2020_SIZE, /* Max cache size */
+};
/* A PHY instance */
struct cphy {
@@ -577,6 +586,7 @@ struct cphy {
unsigned long fifo_errors; /* FIFO over/under-flows */
const struct cphy_ops *ops; /* PHY operations */
struct mdio_if_info mdio;
+ u16 phy_cache[EDC_MAX_SIZE]; /* EDC cache */
};
/* Convenience MDIO read/write wrappers */
diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c
index fb5df5c6203..8b3e76c1cf5 100644
--- a/drivers/net/cxgb3/cxgb3_main.c
+++ b/drivers/net/cxgb3/cxgb3_main.c
@@ -172,6 +172,23 @@ static void link_report(struct net_device *dev)
}
}
+static void enable_tx_fifo_drain(struct adapter *adapter,
+ struct port_info *pi)
+{
+ t3_set_reg_field(adapter, A_XGM_TXFIFO_CFG + pi->mac.offset, 0,
+ F_ENDROPPKT);
+ t3_write_reg(adapter, A_XGM_RX_CTRL + pi->mac.offset, 0);
+ t3_write_reg(adapter, A_XGM_TX_CTRL + pi->mac.offset, F_TXEN);
+ t3_write_reg(adapter, A_XGM_RX_CTRL + pi->mac.offset, F_RXEN);
+}
+
+static void disable_tx_fifo_drain(struct adapter *adapter,
+ struct port_info *pi)
+{
+ t3_set_reg_field(adapter, A_XGM_TXFIFO_CFG + pi->mac.offset,
+ F_ENDROPPKT, 0);
+}
+
void t3_os_link_fault(struct adapter *adap, int port_id, int state)
{
struct net_device *dev = adap->port[port_id];
@@ -185,6 +202,8 @@ void t3_os_link_fault(struct adapter *adap, int port_id, int state)
netif_carrier_on(dev);
+ disable_tx_fifo_drain(adap, pi);
+
/* Clear local faults */
t3_xgm_intr_disable(adap, pi->port_id);
t3_read_reg(adap, A_XGM_INT_STATUS +
@@ -200,9 +219,12 @@ void t3_os_link_fault(struct adapter *adap, int port_id, int state)
t3_xgm_intr_enable(adap, pi->port_id);
t3_mac_enable(mac, MAC_DIRECTION_TX);
- } else
+ } else {
netif_carrier_off(dev);
+ /* Flush TX FIFO */
+ enable_tx_fifo_drain(adap, pi);
+ }
link_report(dev);
}
@@ -232,6 +254,8 @@ void t3_os_link_changed(struct adapter *adapter, int port_id, int link_stat,
if (link_stat != netif_carrier_ok(dev)) {
if (link_stat) {
+ disable_tx_fifo_drain(adapter, pi);
+
t3_mac_enable(mac, MAC_DIRECTION_RX);
/* Clear local faults */
@@ -263,6 +287,9 @@ void t3_os_link_changed(struct adapter *adapter, int port_id, int link_stat,
t3_read_reg(adapter, A_XGM_INT_STATUS + pi->mac.offset);
t3_mac_disable(mac, MAC_DIRECTION_RX);
t3_link_start(&pi->phy, mac, &pi->link_config);
+
+ /* Flush TX FIFO */
+ enable_tx_fifo_drain(adapter, pi);
}
link_report(dev);
@@ -443,6 +470,7 @@ static int init_tp_parity(struct adapter *adap)
memset(req, 0, sizeof(*req));
req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD));
OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_SMT_WRITE_REQ, i));
+ req->mtu_idx = NMTUS - 1;
req->iff = i;
t3_mgmt_tx(adap, skb);
if (skb == adap->nofail_skb) {
@@ -963,6 +991,75 @@ static int bind_qsets(struct adapter *adap)
#define FW_FNAME "cxgb3/t3fw-%d.%d.%d.bin"
#define TPSRAM_NAME "cxgb3/t3%c_psram-%d.%d.%d.bin"
+#define AEL2005_OPT_EDC_NAME "cxgb3/ael2005_opt_edc.bin"
+#define AEL2005_TWX_EDC_NAME "cxgb3/ael2005_twx_edc.bin"
+#define AEL2020_TWX_EDC_NAME "cxgb3/ael2020_twx_edc.bin"
+
+static inline const char *get_edc_fw_name(int edc_idx)
+{
+ const char *fw_name = NULL;
+
+ switch (edc_idx) {
+ case EDC_OPT_AEL2005:
+ fw_name = AEL2005_OPT_EDC_NAME;
+ break;
+ case EDC_TWX_AEL2005:
+ fw_name = AEL2005_TWX_EDC_NAME;
+ break;
+ case EDC_TWX_AEL2020:
+ fw_name = AEL2020_TWX_EDC_NAME;
+ break;
+ }
+ return fw_name;
+}
+
+int t3_get_edc_fw(struct cphy *phy, int edc_idx, int size)
+{
+ struct adapter *adapter = phy->adapter;
+ const struct firmware *fw;
+ char buf[64];
+ u32 csum;
+ const __be32 *p;
+ u16 *cache = phy->phy_cache;
+ int i, ret;
+
+ snprintf(buf, sizeof(buf), get_edc_fw_name(edc_idx));
+
+ ret = request_firmware(&fw, buf, &adapter->pdev->dev);
+ if (ret < 0) {
+ dev_err(&adapter->pdev->dev,
+ "could not upgrade firmware: unable to load %s\n",
+ buf);
+ return ret;
+ }
+
+ /* check size, take checksum in account */
+ if (fw->size > size + 4) {
+ CH_ERR(adapter, "firmware image too large %u, expected %d\n",
+ (unsigned int)fw->size, size + 4);
+ ret = -EINVAL;
+ }
+
+ /* compute checksum */
+ p = (const __be32 *)fw->data;
+ for (csum = 0, i = 0; i < fw->size / sizeof(csum); i++)
+ csum += ntohl(p[i]);
+
+ if (csum != 0xffffffff) {
+ CH_ERR(adapter, "corrupted firmware image, checksum %u\n",
+ csum);
+ ret = -EINVAL;
+ }
+
+ for (i = 0; i < size / 4 ; i++) {
+ *cache++ = (be32_to_cpu(p[i]) & 0xffff0000) >> 16;
+ *cache++ = be32_to_cpu(p[i]) & 0xffff;
+ }
+
+ release_firmware(fw);
+
+ return ret;
+}
static int upgrade_fw(struct adapter *adap)
{
diff --git a/drivers/net/cxgb3/t3_hw.c b/drivers/net/cxgb3/t3_hw.c
index 870d44992c7..032cfe06557 100644
--- a/drivers/net/cxgb3/t3_hw.c
+++ b/drivers/net/cxgb3/t3_hw.c
@@ -3465,7 +3465,7 @@ static void config_pcie(struct adapter *adap)
{201, 321, 258, 450, 834, 1602}
};
- u16 val;
+ u16 val, devid;
unsigned int log2_width, pldsize;
unsigned int fst_trn_rx, fst_trn_tx, acklat, rpllmt;
@@ -3473,6 +3473,17 @@ static void config_pcie(struct adapter *adap)
adap->params.pci.pcie_cap_addr + PCI_EXP_DEVCTL,
&val);
pldsize = (val & PCI_EXP_DEVCTL_PAYLOAD) >> 5;
+
+ pci_read_config_word(adap->pdev, 0x2, &devid);
+ if (devid == 0x37) {
+ pci_write_config_word(adap->pdev,
+ adap->params.pci.pcie_cap_addr +
+ PCI_EXP_DEVCTL,
+ val & ~PCI_EXP_DEVCTL_READRQ &
+ ~PCI_EXP_DEVCTL_PAYLOAD);
+ pldsize = 0;
+ }
+
pci_read_config_word(adap->pdev,
adap->params.pci.pcie_cap_addr + PCI_EXP_LNKCTL,
&val);
@@ -3681,7 +3692,13 @@ static void mc7_prep(struct adapter *adapter, struct mc7 *mc7,
void mac_prep(struct cmac *mac, struct adapter *adapter, int index)
{
+ u16 devid;
+
mac->adapter = adapter;
+ pci_read_config_word(adapter->pdev, 0x2, &devid);
+
+ if (devid == 0x37 && !adapter->params.vpd.xauicfg[1])
+ index = 0;
mac->offset = (XGMAC0_1_BASE_ADDR - XGMAC0_0_BASE_ADDR) * index;
mac->nucast = 1;
diff --git a/drivers/net/cxgb3/xgmac.c b/drivers/net/cxgb3/xgmac.c
index f87f9435049..0109ee4f2f9 100644
--- a/drivers/net/cxgb3/xgmac.c
+++ b/drivers/net/cxgb3/xgmac.c
@@ -447,11 +447,12 @@ int t3_mac_set_speed_duplex_fc(struct cmac *mac, int speed, int duplex, int fc)
val = t3_read_reg(adap, A_XGM_RXFIFO_CFG + oft);
val &= ~V_RXFIFOPAUSEHWM(M_RXFIFOPAUSEHWM);
- if (fc & PAUSE_TX)
- val |= V_RXFIFOPAUSEHWM(rx_fifo_hwm(
- t3_read_reg(adap,
- A_XGM_RX_MAX_PKT_SIZE
- + oft)) / 8);
+ if (fc & PAUSE_TX) {
+ u32 rx_max_pkt_size =
+ G_RXMAXPKTSIZE(t3_read_reg(adap,
+ A_XGM_RX_MAX_PKT_SIZE + oft));
+ val |= V_RXFIFOPAUSEHWM(rx_fifo_hwm(rx_max_pkt_size) / 8);
+ }
t3_write_reg(adap, A_XGM_RXFIFO_CFG + oft, val);
t3_set_reg_field(adap, A_XGM_TX_CFG + oft, F_TXPAUSEEN,
diff --git a/drivers/net/de600.c b/drivers/net/de600.c
index e1af089064b..6b13f4fd2e9 100644
--- a/drivers/net/de600.c
+++ b/drivers/net/de600.c
@@ -226,7 +226,7 @@ static int de600_start_xmit(struct sk_buff *skb, struct net_device *dev)
}
spin_unlock_irqrestore(&de600_lock, flags);
dev_kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
}
/*
diff --git a/drivers/net/de620.c b/drivers/net/de620.c
index 55d2bb67cff..45794f6cb0f 100644
--- a/drivers/net/de620.c
+++ b/drivers/net/de620.c
@@ -542,7 +542,7 @@ static int de620_start_xmit(struct sk_buff *skb, struct net_device *dev)
dev->stats.tx_packets++;
spin_unlock_irqrestore(&de620_lock, flags);
dev_kfree_skb (skb);
- return 0;
+ return NETDEV_TX_OK;
}
/*****************************************************
diff --git a/drivers/net/declance.c b/drivers/net/declance.c
index 2b22e580c4d..a31696a3928 100644
--- a/drivers/net/declance.c
+++ b/drivers/net/declance.c
@@ -902,7 +902,7 @@ static int lance_start_xmit(struct sk_buff *skb, struct net_device *dev)
if (len < ETH_ZLEN) {
if (skb_padto(skb, ETH_ZLEN))
- return 0;
+ return NETDEV_TX_OK;
len = ETH_ZLEN;
}
@@ -933,7 +933,7 @@ static int lance_start_xmit(struct sk_buff *skb, struct net_device *dev)
dev->trans_start = jiffies;
dev_kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
}
static void lance_load_multicast(struct net_device *dev)
diff --git a/drivers/net/defxx.c b/drivers/net/defxx.c
index 102b8d43971..b2e0a8fc21d 100644
--- a/drivers/net/defxx.c
+++ b/drivers/net/defxx.c
@@ -3218,7 +3218,7 @@ static int dfx_xmt_queue_pkt(
bp->xmt_length_errors++; /* bump error counter */
netif_wake_queue(dev);
dev_kfree_skb(skb);
- return(0); /* return "success" */
+ return NETDEV_TX_OK; /* return "success" */
}
/*
* See if adapter link is available, if not, free buffer
@@ -3241,7 +3241,7 @@ static int dfx_xmt_queue_pkt(
bp->xmt_discards++; /* bump error counter */
dev_kfree_skb(skb); /* free sk_buff now */
netif_wake_queue(dev);
- return(0); /* return "success" */
+ return NETDEV_TX_OK; /* return "success" */
}
}
@@ -3345,7 +3345,7 @@ static int dfx_xmt_queue_pkt(
dfx_port_write_long(bp, PI_PDQ_K_REG_TYPE_2_PROD, bp->rcv_xmt_reg.lword);
spin_unlock_irqrestore(&bp->lock, flags);
netif_wake_queue(dev);
- return(0); /* packet queued to adapter */
+ return NETDEV_TX_OK; /* packet queued to adapter */
}
diff --git a/drivers/net/depca.c b/drivers/net/depca.c
index 97ea2d6d3fe..adb997c5bb5 100644
--- a/drivers/net/depca.c
+++ b/drivers/net/depca.c
@@ -1793,7 +1793,7 @@ static int __init get_hw_addr(struct net_device *dev)
static int load_packet(struct net_device *dev, struct sk_buff *skb)
{
struct depca_private *lp = netdev_priv(dev);
- int i, entry, end, len, status = 0;
+ int i, entry, end, len, status = NETDEV_TX_OK;
entry = lp->tx_new; /* Ring around buffer number. */
end = (entry + (skb->len - 1) / TX_BUFF_SZ) & lp->txRingMask;
diff --git a/drivers/net/dm9000.c b/drivers/net/dm9000.c
index dd771dea6ae..a2bc4158259 100644
--- a/drivers/net/dm9000.c
+++ b/drivers/net/dm9000.c
@@ -92,6 +92,7 @@ typedef struct board_info {
u16 tx_pkt_cnt;
u16 queue_pkt_len;
u16 queue_start_addr;
+ u16 queue_ip_summed;
u16 dbug_cnt;
u8 io_mode; /* 0:word, 2:byte */
u8 phy_addr;
@@ -124,6 +125,10 @@ typedef struct board_info {
struct mii_if_info mii;
u32 msg_enable;
+
+ int rx_csum;
+ int can_csum;
+ int ip_summed;
} board_info_t;
/* debug code */
@@ -460,6 +465,40 @@ static int dm9000_nway_reset(struct net_device *dev)
return mii_nway_restart(&dm->mii);
}
+static uint32_t dm9000_get_rx_csum(struct net_device *dev)
+{
+ board_info_t *dm = to_dm9000_board(dev);
+ return dm->rx_csum;
+}
+
+static int dm9000_set_rx_csum(struct net_device *dev, uint32_t data)
+{
+ board_info_t *dm = to_dm9000_board(dev);
+ unsigned long flags;
+
+ if (dm->can_csum) {
+ dm->rx_csum = data;
+
+ spin_lock_irqsave(&dm->lock, flags);
+ iow(dm, DM9000_RCSR, dm->rx_csum ? RCSR_CSUM : 0);
+ spin_unlock_irqrestore(&dm->lock, flags);
+
+ return 0;
+ }
+
+ return -EOPNOTSUPP;
+}
+
+static int dm9000_set_tx_csum(struct net_device *dev, uint32_t data)
+{
+ board_info_t *dm = to_dm9000_board(dev);
+ int ret = -EOPNOTSUPP;
+
+ if (dm->can_csum)
+ ret = ethtool_op_set_tx_csum(dev, data);
+ return ret;
+}
+
static u32 dm9000_get_link(struct net_device *dev)
{
board_info_t *dm = to_dm9000_board(dev);
@@ -540,6 +579,10 @@ static const struct ethtool_ops dm9000_ethtool_ops = {
.get_eeprom_len = dm9000_get_eeprom_len,
.get_eeprom = dm9000_get_eeprom,
.set_eeprom = dm9000_set_eeprom,
+ .get_rx_csum = dm9000_get_rx_csum,
+ .set_rx_csum = dm9000_set_rx_csum,
+ .get_tx_csum = ethtool_op_get_tx_csum,
+ .set_tx_csum = dm9000_set_tx_csum,
};
static void dm9000_show_carrier(board_info_t *db,
@@ -685,6 +728,9 @@ dm9000_init_dm9000(struct net_device *dev)
/* I/O mode */
db->io_mode = ior(db, DM9000_ISR) >> 6; /* ISR bit7:6 keeps I/O mode */
+ /* Checksum mode */
+ dm9000_set_rx_csum(dev, db->rx_csum);
+
/* GPIO0 on pre-activate PHY */
iow(db, DM9000_GPR, 0); /* REG_1F bit0 activate phyxcer */
iow(db, DM9000_GPCR, GPCR_GEP_CNTL); /* Let GPIO0 output */
@@ -743,6 +789,29 @@ static void dm9000_timeout(struct net_device *dev)
spin_unlock_irqrestore(&db->lock, flags);
}
+static void dm9000_send_packet(struct net_device *dev,
+ int ip_summed,
+ u16 pkt_len)
+{
+ board_info_t *dm = to_dm9000_board(dev);
+
+ /* The DM9000 is not smart enough to leave fragmented packets alone. */
+ if (dm->ip_summed != ip_summed) {
+ if (ip_summed == CHECKSUM_NONE)
+ iow(dm, DM9000_TCCR, 0);
+ else
+ iow(dm, DM9000_TCCR, TCCR_IP | TCCR_UDP | TCCR_TCP);
+ dm->ip_summed = ip_summed;
+ }
+
+ /* Set TX length to DM9000 */
+ iow(dm, DM9000_TXPLL, pkt_len);
+ iow(dm, DM9000_TXPLH, pkt_len >> 8);
+
+ /* Issue TX polling command */
+ iow(dm, DM9000_TCR, TCR_TXREQ); /* Cleared after TX complete */
+}
+
/*
* Hardware start transmission.
* Send a packet to media from the upper layer.
@@ -769,17 +838,11 @@ dm9000_start_xmit(struct sk_buff *skb, struct net_device *dev)
db->tx_pkt_cnt++;
/* TX control: First packet immediately send, second packet queue */
if (db->tx_pkt_cnt == 1) {
- /* Set TX length to DM9000 */
- iow(db, DM9000_TXPLL, skb->len);
- iow(db, DM9000_TXPLH, skb->len >> 8);
-
- /* Issue TX polling command */
- iow(db, DM9000_TCR, TCR_TXREQ); /* Cleared after TX complete */
-
- dev->trans_start = jiffies; /* save the time stamp */
+ dm9000_send_packet(dev, skb->ip_summed, skb->len);
} else {
/* Second packet */
db->queue_pkt_len = skb->len;
+ db->queue_ip_summed = skb->ip_summed;
netif_stop_queue(dev);
}
@@ -788,7 +851,7 @@ dm9000_start_xmit(struct sk_buff *skb, struct net_device *dev)
/* free this SKB */
dev_kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
}
/*
@@ -809,12 +872,9 @@ static void dm9000_tx_done(struct net_device *dev, board_info_t *db)
dev_dbg(db->dev, "tx done, NSR %02x\n", tx_status);
/* Queue packet check & send */
- if (db->tx_pkt_cnt > 0) {
- iow(db, DM9000_TXPLL, db->queue_pkt_len);
- iow(db, DM9000_TXPLH, db->queue_pkt_len >> 8);
- iow(db, DM9000_TCR, TCR_TXREQ);
- dev->trans_start = jiffies;
- }
+ if (db->tx_pkt_cnt > 0)
+ dm9000_send_packet(dev, db->queue_ip_summed,
+ db->queue_pkt_len);
netif_wake_queue(dev);
}
}
@@ -846,14 +906,14 @@ dm9000_rx(struct net_device *dev)
rxbyte = readb(db->io_data);
/* Status check: this byte must be 0 or 1 */
- if (rxbyte > DM9000_PKT_RDY) {
+ if (rxbyte & DM9000_PKT_ERR) {
dev_warn(db->dev, "status check fail: %d\n", rxbyte);
iow(db, DM9000_RCR, 0x00); /* Stop Device */
iow(db, DM9000_ISR, IMR_PAR); /* Stop INT request */
return;
}
- if (rxbyte != DM9000_PKT_RDY)
+ if (!(rxbyte & DM9000_PKT_RDY))
return;
/* A packet ready now & Get status/length */
@@ -914,6 +974,12 @@ dm9000_rx(struct net_device *dev)
/* Pass to upper layer */
skb->protocol = eth_type_trans(skb, dev);
+ if (db->rx_csum) {
+ if ((((rxbyte & 0x1c) << 3) & rxbyte) == 0)
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+ else
+ skb->ip_summed = CHECKSUM_NONE;
+ }
netif_rx(skb);
dev->stats.rx_packets++;
@@ -922,7 +988,7 @@ dm9000_rx(struct net_device *dev)
(db->dumpblk)(db->io_data, RxLen);
}
- } while (rxbyte == DM9000_PKT_RDY);
+ } while (rxbyte & DM9000_PKT_RDY);
}
static irqreturn_t dm9000_interrupt(int irq, void *dev_id)
@@ -1349,6 +1415,13 @@ dm9000_probe(struct platform_device *pdev)
db->type = TYPE_DM9000E;
}
+ /* dm9000a/b are capable of hardware checksum offload */
+ if (db->type == TYPE_DM9000A || db->type == TYPE_DM9000B) {
+ db->can_csum = 1;
+ db->rx_csum = 1;
+ ndev->features |= NETIF_F_IP_CSUM;
+ }
+
/* from this point we assume that we have found a DM9000 */
/* driver system function */
@@ -1410,9 +1483,10 @@ out:
}
static int
-dm9000_drv_suspend(struct platform_device *dev, pm_message_t state)
+dm9000_drv_suspend(struct device *dev)
{
- struct net_device *ndev = platform_get_drvdata(dev);
+ struct platform_device *pdev = to_platform_device(dev);
+ struct net_device *ndev = platform_get_drvdata(pdev);
board_info_t *db;
if (ndev) {
@@ -1428,9 +1502,10 @@ dm9000_drv_suspend(struct platform_device *dev, pm_message_t state)
}
static int
-dm9000_drv_resume(struct platform_device *dev)
+dm9000_drv_resume(struct device *dev)
{
- struct net_device *ndev = platform_get_drvdata(dev);
+ struct platform_device *pdev = to_platform_device(dev);
+ struct net_device *ndev = platform_get_drvdata(pdev);
board_info_t *db = netdev_priv(ndev);
if (ndev) {
@@ -1447,6 +1522,11 @@ dm9000_drv_resume(struct platform_device *dev)
return 0;
}
+static struct dev_pm_ops dm9000_drv_pm_ops = {
+ .suspend = dm9000_drv_suspend,
+ .resume = dm9000_drv_resume,
+};
+
static int __devexit
dm9000_drv_remove(struct platform_device *pdev)
{
@@ -1466,11 +1546,10 @@ static struct platform_driver dm9000_driver = {
.driver = {
.name = "dm9000",
.owner = THIS_MODULE,
+ .pm = &dm9000_drv_pm_ops,
},
.probe = dm9000_probe,
.remove = __devexit_p(dm9000_drv_remove),
- .suspend = dm9000_drv_suspend,
- .resume = dm9000_drv_resume,
};
static int __init
diff --git a/drivers/net/dm9000.h b/drivers/net/dm9000.h
index ba25cf54142..80817c2edfb 100644
--- a/drivers/net/dm9000.h
+++ b/drivers/net/dm9000.h
@@ -45,6 +45,10 @@
#define DM9000_CHIPR 0x2C
#define DM9000_SMCR 0x2F
+#define DM9000_ETXCSR 0x30
+#define DM9000_TCCR 0x31
+#define DM9000_RCSR 0x32
+
#define CHIPR_DM9000A 0x19
#define CHIPR_DM9000B 0x1B
@@ -131,7 +135,21 @@
#define GPCR_GEP_CNTL (1<<0)
+#define TCCR_IP (1<<0)
+#define TCCR_TCP (1<<1)
+#define TCCR_UDP (1<<2)
+
+#define RCSR_UDP_BAD (1<<7)
+#define RCSR_TCP_BAD (1<<6)
+#define RCSR_IP_BAD (1<<5)
+#define RCSR_UDP (1<<4)
+#define RCSR_TCP (1<<3)
+#define RCSR_IP (1<<2)
+#define RCSR_CSUM (1<<1)
+#define RCSR_DISCARD (1<<0)
+
#define DM9000_PKT_RDY 0x01 /* Packet ready to receive */
+#define DM9000_PKT_ERR 0x02
#define DM9000_PKT_MAX 1536 /* Received packet max size */
/* DM9000A / DM9000B definitions */
diff --git a/drivers/net/dnet.c b/drivers/net/dnet.c
index 33fa9eee4ca..2818d5de394 100644
--- a/drivers/net/dnet.c
+++ b/drivers/net/dnet.c
@@ -596,7 +596,7 @@ static int dnet_start_xmit(struct sk_buff *skb, struct net_device *dev)
dev->trans_start = jiffies;
- return 0;
+ return NETDEV_TX_OK;
}
static void dnet_reset_hw(struct dnet *bp)
diff --git a/drivers/net/dummy.c b/drivers/net/dummy.c
index 8ebd7d78940..713ce6c532c 100644
--- a/drivers/net/dummy.c
+++ b/drivers/net/dummy.c
@@ -85,7 +85,7 @@ static int dummy_xmit(struct sk_buff *skb, struct net_device *dev)
dev->stats.tx_bytes += skb->len;
dev_kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
}
static int dummy_validate(struct nlattr *tb[], struct nlattr *data[])
diff --git a/drivers/net/e100.c b/drivers/net/e100.c
index 41b648a67fe..569df19f0df 100644
--- a/drivers/net/e100.c
+++ b/drivers/net/e100.c
@@ -1720,7 +1720,7 @@ static int e100_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
}
netdev->trans_start = jiffies;
- return 0;
+ return NETDEV_TX_OK;
}
static int e100_tx_clean(struct nic *nic)
diff --git a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h
index e9a416f4016..1a4f89c66a2 100644
--- a/drivers/net/e1000/e1000.h
+++ b/drivers/net/e1000/e1000.h
@@ -111,6 +111,9 @@ do { \
#define E1000_MIN_RXD 80
#define E1000_MAX_82544_RXD 4096
+#define E1000_MIN_ITR_USECS 10 /* 100000 irq/sec */
+#define E1000_MAX_ITR_USECS 10000 /* 100 irq/sec */
+
/* this is the size past which hardware will drop packets when setting LPE=0 */
#define MAXIMUM_ETHERNET_VLAN_SIZE 1522
@@ -137,7 +140,7 @@ do { \
#define E1000_FC_HIGH_DIFF 0x1638 /* High: 5688 bytes below Rx FIFO size */
#define E1000_FC_LOW_DIFF 0x1640 /* Low: 5696 bytes below Rx FIFO size */
-#define E1000_FC_PAUSE_TIME 0x0680 /* 858 usec */
+#define E1000_FC_PAUSE_TIME 0xFFFF /* pause for the max or until send xon */
/* How many Tx Descriptors do we need to call netif_wake_queue ? */
#define E1000_TX_QUEUE_WAKE 16
@@ -161,6 +164,7 @@ do { \
struct e1000_buffer {
struct sk_buff *skb;
dma_addr_t dma;
+ struct page *page;
unsigned long time_stamp;
u16 length;
u16 next_to_watch;
@@ -202,6 +206,7 @@ struct e1000_rx_ring {
unsigned int next_to_clean;
/* array of buffer information structs */
struct e1000_buffer *buffer_info;
+ struct sk_buff *rx_skb_top;
/* cpu for rx queue */
int cpu;
diff --git a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c
index c854c96f5ab..27f996a2010 100644
--- a/drivers/net/e1000/e1000_ethtool.c
+++ b/drivers/net/e1000/e1000_ethtool.c
@@ -1904,6 +1904,53 @@ static int e1000_phys_id(struct net_device *netdev, u32 data)
return 0;
}
+static int e1000_get_coalesce(struct net_device *netdev,
+ struct ethtool_coalesce *ec)
+{
+ struct e1000_adapter *adapter = netdev_priv(netdev);
+
+ if (adapter->hw.mac_type < e1000_82545)
+ return -EOPNOTSUPP;
+
+ if (adapter->itr_setting <= 3)
+ ec->rx_coalesce_usecs = adapter->itr_setting;
+ else
+ ec->rx_coalesce_usecs = 1000000 / adapter->itr_setting;
+
+ return 0;
+}
+
+static int e1000_set_coalesce(struct net_device *netdev,
+ struct ethtool_coalesce *ec)
+{
+ struct e1000_adapter *adapter = netdev_priv(netdev);
+ struct e1000_hw *hw = &adapter->hw;
+
+ if (hw->mac_type < e1000_82545)
+ return -EOPNOTSUPP;
+
+ if ((ec->rx_coalesce_usecs > E1000_MAX_ITR_USECS) ||
+ ((ec->rx_coalesce_usecs > 3) &&
+ (ec->rx_coalesce_usecs < E1000_MIN_ITR_USECS)) ||
+ (ec->rx_coalesce_usecs == 2))
+ return -EINVAL;
+
+ if (ec->rx_coalesce_usecs <= 3) {
+ adapter->itr = 20000;
+ adapter->itr_setting = ec->rx_coalesce_usecs;
+ } else {
+ adapter->itr = (1000000 / ec->rx_coalesce_usecs);
+ adapter->itr_setting = adapter->itr & ~3;
+ }
+
+ if (adapter->itr_setting != 0)
+ ew32(ITR, 1000000000 / (adapter->itr * 256));
+ else
+ ew32(ITR, 0);
+
+ return 0;
+}
+
static int e1000_nway_reset(struct net_device *netdev)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
@@ -1978,7 +2025,9 @@ static const struct ethtool_ops e1000_ethtool_ops = {
.get_strings = e1000_get_strings,
.phys_id = e1000_phys_id,
.get_ethtool_stats = e1000_get_ethtool_stats,
- .get_sset_count = e1000_get_sset_count,
+ .get_sset_count = e1000_get_sset_count,
+ .get_coalesce = e1000_get_coalesce,
+ .set_coalesce = e1000_set_coalesce,
};
void e1000_set_ethtool_ops(struct net_device *netdev)
diff --git a/drivers/net/e1000/e1000_hw.c b/drivers/net/e1000/e1000_hw.c
index e1a3fc1303e..1e5ae112d57 100644
--- a/drivers/net/e1000/e1000_hw.c
+++ b/drivers/net/e1000/e1000_hw.c
@@ -1955,7 +1955,7 @@ static s32 e1000_setup_copper_link(struct e1000_hw *hw)
s32 ret_val;
u16 i;
u16 phy_data;
- u16 reg_data;
+ u16 reg_data = 0;
DEBUGFUNC("e1000_setup_copper_link");
diff --git a/drivers/net/e1000/e1000_hw.h b/drivers/net/e1000/e1000_hw.h
index 99fce2c5dd2..a8866bdbb67 100644
--- a/drivers/net/e1000/e1000_hw.h
+++ b/drivers/net/e1000/e1000_hw.h
@@ -523,11 +523,8 @@ s32 e1000_check_phy_reset_block(struct e1000_hw *hw);
/* The sizes (in bytes) of a ethernet packet */
#define ENET_HEADER_SIZE 14
-#define MAXIMUM_ETHERNET_FRAME_SIZE 1518 /* With FCS */
#define MINIMUM_ETHERNET_FRAME_SIZE 64 /* With FCS */
#define ETHERNET_FCS_SIZE 4
-#define MAXIMUM_ETHERNET_PACKET_SIZE \
- (MAXIMUM_ETHERNET_FRAME_SIZE - ETHERNET_FCS_SIZE)
#define MINIMUM_ETHERNET_PACKET_SIZE \
(MINIMUM_ETHERNET_FRAME_SIZE - ETHERNET_FCS_SIZE)
#define CRC_LENGTH ETHERNET_FCS_SIZE
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
index 5b8cbdb4b52..d7df00c2dbd 100644
--- a/drivers/net/e1000/e1000_main.c
+++ b/drivers/net/e1000/e1000_main.c
@@ -137,9 +137,15 @@ static int e1000_clean(struct napi_struct *napi, int budget);
static bool e1000_clean_rx_irq(struct e1000_adapter *adapter,
struct e1000_rx_ring *rx_ring,
int *work_done, int work_to_do);
+static bool e1000_clean_jumbo_rx_irq(struct e1000_adapter *adapter,
+ struct e1000_rx_ring *rx_ring,
+ int *work_done, int work_to_do);
static void e1000_alloc_rx_buffers(struct e1000_adapter *adapter,
- struct e1000_rx_ring *rx_ring,
+ struct e1000_rx_ring *rx_ring,
int cleaned_count);
+static void e1000_alloc_jumbo_rx_buffers(struct e1000_adapter *adapter,
+ struct e1000_rx_ring *rx_ring,
+ int cleaned_count);
static int e1000_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd);
static int e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr,
int cmd);
@@ -635,8 +641,8 @@ void e1000_reset(struct e1000_adapter *adapter)
{
struct e1000_hw *hw = &adapter->hw;
u32 pba = 0, tx_space, min_tx_space, min_rx_space;
- u16 fc_high_water_mark = E1000_FC_HIGH_DIFF;
bool legacy_pba_adjust = false;
+ u16 hwm;
/* Repartition Pba for greater than 9k mtu
* To take effect CTRL.RST is required.
@@ -680,7 +686,7 @@ void e1000_reset(struct e1000_adapter *adapter)
}
if (legacy_pba_adjust) {
- if (adapter->netdev->mtu > E1000_RXBUFFER_8192)
+ if (hw->max_frame_size > E1000_RXBUFFER_8192)
pba -= 8; /* allocate more FIFO for Tx */
if (hw->mac_type == e1000_82547) {
@@ -690,14 +696,14 @@ void e1000_reset(struct e1000_adapter *adapter)
(E1000_PBA_40K - pba) << E1000_PBA_BYTES_SHIFT;
atomic_set(&adapter->tx_fifo_stall, 0);
}
- } else if (hw->max_frame_size > MAXIMUM_ETHERNET_FRAME_SIZE) {
+ } else if (hw->max_frame_size > ETH_FRAME_LEN + ETH_FCS_LEN) {
/* adjust PBA for jumbo frames */
ew32(PBA, pba);
/* To maintain wire speed transmits, the Tx FIFO should be
- * large enough to accomodate two full transmit packets,
+ * large enough to accommodate two full transmit packets,
* rounded up to the next 1KB and expressed in KB. Likewise,
- * the Rx FIFO should be large enough to accomodate at least
+ * the Rx FIFO should be large enough to accommodate at least
* one full receive packet and is similarly rounded up and
* expressed in KB. */
pba = er32(PBA);
@@ -705,13 +711,17 @@ void e1000_reset(struct e1000_adapter *adapter)
tx_space = pba >> 16;
/* lower 16 bits has Rx packet buffer allocation size in KB */
pba &= 0xffff;
- /* don't include ethernet FCS because hardware appends/strips */
- min_rx_space = adapter->netdev->mtu + ENET_HEADER_SIZE +
- VLAN_TAG_SIZE;
- min_tx_space = min_rx_space;
- min_tx_space *= 2;
+ /*
+ * the tx fifo also stores 16 bytes of information about the tx
+ * but don't include ethernet FCS because hardware appends it
+ */
+ min_tx_space = (hw->max_frame_size +
+ sizeof(struct e1000_tx_desc) -
+ ETH_FCS_LEN) * 2;
min_tx_space = ALIGN(min_tx_space, 1024);
min_tx_space >>= 10;
+ /* software strips receive CRC, so leave room for it */
+ min_rx_space = hw->max_frame_size;
min_rx_space = ALIGN(min_rx_space, 1024);
min_rx_space >>= 10;
@@ -748,23 +758,22 @@ void e1000_reset(struct e1000_adapter *adapter)
ew32(PBA, pba);
- /* flow control settings */
- /* Set the FC high water mark to 90% of the FIFO size.
- * Required to clear last 3 LSB */
- fc_high_water_mark = ((pba * 9216)/10) & 0xFFF8;
- /* We can't use 90% on small FIFOs because the remainder
- * would be less than 1 full frame. In this case, we size
- * it to allow at least a full frame above the high water
- * mark. */
- if (pba < E1000_PBA_16K)
- fc_high_water_mark = (pba * 1024) - 1600;
-
- hw->fc_high_water = fc_high_water_mark;
- hw->fc_low_water = fc_high_water_mark - 8;
- if (hw->mac_type == e1000_80003es2lan)
- hw->fc_pause_time = 0xFFFF;
- else
- hw->fc_pause_time = E1000_FC_PAUSE_TIME;
+ /*
+ * flow control settings:
+ * The high water mark must be low enough to fit one full frame
+ * (or the size used for early receive) above it in the Rx FIFO.
+ * Set it to the lower of:
+ * - 90% of the Rx FIFO size, and
+ * - the full Rx FIFO size minus the early receive size (for parts
+ * with ERT support assuming ERT set to E1000_ERT_2048), or
+ * - the full Rx FIFO size minus one full frame
+ */
+ hwm = min(((pba << 10) * 9 / 10),
+ ((pba << 10) - hw->max_frame_size));
+
+ hw->fc_high_water = hwm & 0xFFF8; /* 8-byte granularity */
+ hw->fc_low_water = hw->fc_high_water - 8;
+ hw->fc_pause_time = E1000_FC_PAUSE_TIME;
hw->fc_send_xon = 1;
hw->fc = hw->original_fc;
@@ -1862,6 +1871,7 @@ setup_rx_desc_die:
rxdr->next_to_clean = 0;
rxdr->next_to_use = 0;
+ rxdr->rx_skb_top = NULL;
return 0;
}
@@ -1968,10 +1978,17 @@ static void e1000_configure_rx(struct e1000_adapter *adapter)
struct e1000_hw *hw = &adapter->hw;
u32 rdlen, rctl, rxcsum, ctrl_ext;
- rdlen = adapter->rx_ring[0].count *
- sizeof(struct e1000_rx_desc);
- adapter->clean_rx = e1000_clean_rx_irq;
- adapter->alloc_rx_buf = e1000_alloc_rx_buffers;
+ if (adapter->netdev->mtu > ETH_DATA_LEN) {
+ rdlen = adapter->rx_ring[0].count *
+ sizeof(struct e1000_rx_desc);
+ adapter->clean_rx = e1000_clean_jumbo_rx_irq;
+ adapter->alloc_rx_buf = e1000_alloc_jumbo_rx_buffers;
+ } else {
+ rdlen = adapter->rx_ring[0].count *
+ sizeof(struct e1000_rx_desc);
+ adapter->clean_rx = e1000_clean_rx_irq;
+ adapter->alloc_rx_buf = e1000_alloc_rx_buffers;
+ }
/* disable receives while setting up the descriptors */
rctl = er32(RCTL);
@@ -2185,26 +2202,39 @@ static void e1000_clean_rx_ring(struct e1000_adapter *adapter,
/* Free all the Rx ring sk_buffs */
for (i = 0; i < rx_ring->count; i++) {
buffer_info = &rx_ring->buffer_info[i];
- if (buffer_info->dma) {
- pci_unmap_single(pdev,
- buffer_info->dma,
- buffer_info->length,
- PCI_DMA_FROMDEVICE);
+ if (buffer_info->dma &&
+ adapter->clean_rx == e1000_clean_rx_irq) {
+ pci_unmap_single(pdev, buffer_info->dma,
+ buffer_info->length,
+ PCI_DMA_FROMDEVICE);
+ } else if (buffer_info->dma &&
+ adapter->clean_rx == e1000_clean_jumbo_rx_irq) {
+ pci_unmap_page(pdev, buffer_info->dma,
+ buffer_info->length,
+ PCI_DMA_FROMDEVICE);
}
buffer_info->dma = 0;
-
+ if (buffer_info->page) {
+ put_page(buffer_info->page);
+ buffer_info->page = NULL;
+ }
if (buffer_info->skb) {
dev_kfree_skb(buffer_info->skb);
buffer_info->skb = NULL;
}
}
+ /* there also may be some cached data from a chained receive */
+ if (rx_ring->rx_skb_top) {
+ dev_kfree_skb(rx_ring->rx_skb_top);
+ rx_ring->rx_skb_top = NULL;
+ }
+
size = sizeof(struct e1000_buffer) * rx_ring->count;
memset(rx_ring->buffer_info, 0, size);
/* Zero out the descriptor ring */
-
memset(rx_ring->desc, 0, rx_ring->size);
rx_ring->next_to_clean = 0;
@@ -3450,7 +3480,7 @@ static int e1000_change_mtu(struct net_device *netdev, int new_mtu)
switch (hw->mac_type) {
case e1000_undefined ... e1000_82542_rev2_1:
case e1000_ich8lan:
- if (max_frame > MAXIMUM_ETHERNET_FRAME_SIZE) {
+ if (max_frame > (ETH_FRAME_LEN + ETH_FCS_LEN)) {
DPRINTK(PROBE, ERR, "Jumbo Frames not supported.\n");
return -EINVAL;
}
@@ -3463,7 +3493,7 @@ static int e1000_change_mtu(struct net_device *netdev, int new_mtu)
&eeprom_data);
if ((hw->device_id != E1000_DEV_ID_82573L) ||
(eeprom_data & EEPROM_WORD1A_ASPM_MASK)) {
- if (max_frame > MAXIMUM_ETHERNET_FRAME_SIZE) {
+ if (max_frame > (ETH_FRAME_LEN + ETH_FCS_LEN)) {
DPRINTK(PROBE, ERR,
"Jumbo Frames not supported.\n");
return -EINVAL;
@@ -3489,8 +3519,10 @@ static int e1000_change_mtu(struct net_device *netdev, int new_mtu)
/* NOTE: netdev_alloc_skb reserves 16 bytes, and typically NET_IP_ALIGN
* means we reserve 2 more, this pushes us to allocate from the next
- * larger slab size
- * i.e. RXBUFFER_2048 --> size-4096 slab */
+ * larger slab size.
+ * i.e. RXBUFFER_2048 --> size-4096 slab
+ * however with the new *_jumbo_rx* routines, jumbo receives will use
+ * fragmented skbs */
if (max_frame <= E1000_RXBUFFER_256)
adapter->rx_buffer_len = E1000_RXBUFFER_256;
@@ -3500,16 +3532,16 @@ static int e1000_change_mtu(struct net_device *netdev, int new_mtu)
adapter->rx_buffer_len = E1000_RXBUFFER_1024;
else if (max_frame <= E1000_RXBUFFER_2048)
adapter->rx_buffer_len = E1000_RXBUFFER_2048;
- else if (max_frame <= E1000_RXBUFFER_4096)
- adapter->rx_buffer_len = E1000_RXBUFFER_4096;
- else if (max_frame <= E1000_RXBUFFER_8192)
- adapter->rx_buffer_len = E1000_RXBUFFER_8192;
- else if (max_frame <= E1000_RXBUFFER_16384)
+ else
+#if (PAGE_SIZE >= E1000_RXBUFFER_16384)
adapter->rx_buffer_len = E1000_RXBUFFER_16384;
+#elif (PAGE_SIZE >= E1000_RXBUFFER_4096)
+ adapter->rx_buffer_len = PAGE_SIZE;
+#endif
/* adjust allocation if LPE protects us, and we aren't using SBP */
if (!hw->tbi_compatibility_on &&
- ((max_frame == MAXIMUM_ETHERNET_FRAME_SIZE) ||
+ ((max_frame == (ETH_FRAME_LEN + ETH_FCS_LEN)) ||
(max_frame == MAXIMUM_ETHERNET_VLAN_SIZE)))
adapter->rx_buffer_len = MAXIMUM_ETHERNET_VLAN_SIZE;
@@ -3987,9 +4019,227 @@ static void e1000_rx_checksum(struct e1000_adapter *adapter, u32 status_err,
}
/**
+ * e1000_consume_page - helper function
+ **/
+static void e1000_consume_page(struct e1000_buffer *bi, struct sk_buff *skb,
+ u16 length)
+{
+ bi->page = NULL;
+ skb->len += length;
+ skb->data_len += length;
+ skb->truesize += length;
+}
+
+/**
+ * e1000_receive_skb - helper function to handle rx indications
+ * @adapter: board private structure
+ * @status: descriptor status field as written by hardware
+ * @vlan: descriptor vlan field as written by hardware (no le/be conversion)
+ * @skb: pointer to sk_buff to be indicated to stack
+ */
+static void e1000_receive_skb(struct e1000_adapter *adapter, u8 status,
+ __le16 vlan, struct sk_buff *skb)
+{
+ if (unlikely(adapter->vlgrp && (status & E1000_RXD_STAT_VP))) {
+ vlan_hwaccel_receive_skb(skb, adapter->vlgrp,
+ le16_to_cpu(vlan) &
+ E1000_RXD_SPC_VLAN_MASK);
+ } else {
+ netif_receive_skb(skb);
+ }
+}
+
+/**
+ * e1000_clean_jumbo_rx_irq - Send received data up the network stack; legacy
+ * @adapter: board private structure
+ * @rx_ring: ring to clean
+ * @work_done: amount of napi work completed this call
+ * @work_to_do: max amount of work allowed for this call to do
+ *
+ * the return value indicates whether actual cleaning was done, there
+ * is no guarantee that everything was cleaned
+ */
+static bool e1000_clean_jumbo_rx_irq(struct e1000_adapter *adapter,
+ struct e1000_rx_ring *rx_ring,
+ int *work_done, int work_to_do)
+{
+ struct e1000_hw *hw = &adapter->hw;
+ struct net_device *netdev = adapter->netdev;
+ struct pci_dev *pdev = adapter->pdev;
+ struct e1000_rx_desc *rx_desc, *next_rxd;
+ struct e1000_buffer *buffer_info, *next_buffer;
+ unsigned long irq_flags;
+ u32 length;
+ unsigned int i;
+ int cleaned_count = 0;
+ bool cleaned = false;
+ unsigned int total_rx_bytes=0, total_rx_packets=0;
+
+ i = rx_ring->next_to_clean;
+ rx_desc = E1000_RX_DESC(*rx_ring, i);
+ buffer_info = &rx_ring->buffer_info[i];
+
+ while (rx_desc->status & E1000_RXD_STAT_DD) {
+ struct sk_buff *skb;
+ u8 status;
+
+ if (*work_done >= work_to_do)
+ break;
+ (*work_done)++;
+
+ status = rx_desc->status;
+ skb = buffer_info->skb;
+ buffer_info->skb = NULL;
+
+ if (++i == rx_ring->count) i = 0;
+ next_rxd = E1000_RX_DESC(*rx_ring, i);
+ prefetch(next_rxd);
+
+ next_buffer = &rx_ring->buffer_info[i];
+
+ cleaned = true;
+ cleaned_count++;
+ pci_unmap_page(pdev, buffer_info->dma, buffer_info->length,
+ PCI_DMA_FROMDEVICE);
+ buffer_info->dma = 0;
+
+ length = le16_to_cpu(rx_desc->length);
+
+ /* errors is only valid for DD + EOP descriptors */
+ if (unlikely((status & E1000_RXD_STAT_EOP) &&
+ (rx_desc->errors & E1000_RXD_ERR_FRAME_ERR_MASK))) {
+ u8 last_byte = *(skb->data + length - 1);
+ if (TBI_ACCEPT(hw, status, rx_desc->errors, length,
+ last_byte)) {
+ spin_lock_irqsave(&adapter->stats_lock,
+ irq_flags);
+ e1000_tbi_adjust_stats(hw, &adapter->stats,
+ length, skb->data);
+ spin_unlock_irqrestore(&adapter->stats_lock,
+ irq_flags);
+ length--;
+ } else {
+ /* recycle both page and skb */
+ buffer_info->skb = skb;
+ /* an error means any chain goes out the window
+ * too */
+ if (rx_ring->rx_skb_top)
+ dev_kfree_skb(rx_ring->rx_skb_top);
+ rx_ring->rx_skb_top = NULL;
+ goto next_desc;
+ }
+ }
+
+#define rxtop rx_ring->rx_skb_top
+ if (!(status & E1000_RXD_STAT_EOP)) {
+ /* this descriptor is only the beginning (or middle) */
+ if (!rxtop) {
+ /* this is the beginning of a chain */
+ rxtop = skb;
+ skb_fill_page_desc(rxtop, 0, buffer_info->page,
+ 0, length);
+ } else {
+ /* this is the middle of a chain */
+ skb_fill_page_desc(rxtop,
+ skb_shinfo(rxtop)->nr_frags,
+ buffer_info->page, 0, length);
+ /* re-use the skb, only consumed the page */
+ buffer_info->skb = skb;
+ }
+ e1000_consume_page(buffer_info, rxtop, length);
+ goto next_desc;
+ } else {
+ if (rxtop) {
+ /* end of the chain */
+ skb_fill_page_desc(rxtop,
+ skb_shinfo(rxtop)->nr_frags,
+ buffer_info->page, 0, length);
+ /* re-use the current skb, we only consumed the
+ * page */
+ buffer_info->skb = skb;
+ skb = rxtop;
+ rxtop = NULL;
+ e1000_consume_page(buffer_info, skb, length);
+ } else {
+ /* no chain, got EOP, this buf is the packet
+ * copybreak to save the put_page/alloc_page */
+ if (length <= copybreak &&
+ skb_tailroom(skb) >= length) {
+ u8 *vaddr;
+ vaddr = kmap_atomic(buffer_info->page,
+ KM_SKB_DATA_SOFTIRQ);
+ memcpy(skb_tail_pointer(skb), vaddr, length);
+ kunmap_atomic(vaddr,
+ KM_SKB_DATA_SOFTIRQ);
+ /* re-use the page, so don't erase
+ * buffer_info->page */
+ skb_put(skb, length);
+ } else {
+ skb_fill_page_desc(skb, 0,
+ buffer_info->page, 0,
+ length);
+ e1000_consume_page(buffer_info, skb,
+ length);
+ }
+ }
+ }
+
+ /* Receive Checksum Offload XXX recompute due to CRC strip? */
+ e1000_rx_checksum(adapter,
+ (u32)(status) |
+ ((u32)(rx_desc->errors) << 24),
+ le16_to_cpu(rx_desc->csum), skb);
+
+ pskb_trim(skb, skb->len - 4);
+
+ /* probably a little skewed due to removing CRC */
+ total_rx_bytes += skb->len;
+ total_rx_packets++;
+
+ /* eth type trans needs skb->data to point to something */
+ if (!pskb_may_pull(skb, ETH_HLEN)) {
+ DPRINTK(DRV, ERR, "pskb_may_pull failed.\n");
+ dev_kfree_skb(skb);
+ goto next_desc;
+ }
+
+ skb->protocol = eth_type_trans(skb, netdev);
+
+ e1000_receive_skb(adapter, status, rx_desc->special, skb);
+
+next_desc:
+ rx_desc->status = 0;
+
+ /* return some buffers to hardware, one at a time is too slow */
+ if (unlikely(cleaned_count >= E1000_RX_BUFFER_WRITE)) {
+ adapter->alloc_rx_buf(adapter, rx_ring, cleaned_count);
+ cleaned_count = 0;
+ }
+
+ /* use prefetched values */
+ rx_desc = next_rxd;
+ buffer_info = next_buffer;
+ }
+ rx_ring->next_to_clean = i;
+
+ cleaned_count = E1000_DESC_UNUSED(rx_ring);
+ if (cleaned_count)
+ adapter->alloc_rx_buf(adapter, rx_ring, cleaned_count);
+
+ adapter->total_rx_packets += total_rx_packets;
+ adapter->total_rx_bytes += total_rx_bytes;
+ adapter->net_stats.rx_bytes += total_rx_bytes;
+ adapter->net_stats.rx_packets += total_rx_packets;
+ return cleaned;
+}
+
+/**
* e1000_clean_rx_irq - Send received data up the network stack; legacy
* @adapter: board private structure
- **/
+ * @rx_ring: ring to clean
+ * @work_done: amount of napi work completed this call
+ * @work_to_do: max amount of work allowed for this call to do
+ */
static bool e1000_clean_rx_irq(struct e1000_adapter *adapter,
struct e1000_rx_ring *rx_ring,
int *work_done, int work_to_do)
@@ -4001,7 +4251,6 @@ static bool e1000_clean_rx_irq(struct e1000_adapter *adapter,
struct e1000_buffer *buffer_info, *next_buffer;
unsigned long flags;
u32 length;
- u8 last_byte;
unsigned int i;
int cleaned_count = 0;
bool cleaned = false;
@@ -4033,9 +4282,7 @@ static bool e1000_clean_rx_irq(struct e1000_adapter *adapter,
cleaned = true;
cleaned_count++;
- pci_unmap_single(pdev,
- buffer_info->dma,
- buffer_info->length,
+ pci_unmap_single(pdev, buffer_info->dma, buffer_info->length,
PCI_DMA_FROMDEVICE);
buffer_info->dma = 0;
@@ -4052,7 +4299,7 @@ static bool e1000_clean_rx_irq(struct e1000_adapter *adapter,
}
if (unlikely(rx_desc->errors & E1000_RXD_ERR_FRAME_ERR_MASK)) {
- last_byte = *(skb->data + length - 1);
+ u8 last_byte = *(skb->data + length - 1);
if (TBI_ACCEPT(hw, status, rx_desc->errors, length,
last_byte)) {
spin_lock_irqsave(&adapter->stats_lock, flags);
@@ -4107,13 +4354,7 @@ static bool e1000_clean_rx_irq(struct e1000_adapter *adapter,
skb->protocol = eth_type_trans(skb, netdev);
- if (unlikely(adapter->vlgrp &&
- (status & E1000_RXD_STAT_VP))) {
- vlan_hwaccel_receive_skb(skb, adapter->vlgrp,
- le16_to_cpu(rx_desc->special));
- } else {
- netif_receive_skb(skb);
- }
+ e1000_receive_skb(adapter, status, rx_desc->special, skb);
next_desc:
rx_desc->status = 0;
@@ -4142,6 +4383,114 @@ next_desc:
}
/**
+ * e1000_alloc_jumbo_rx_buffers - Replace used jumbo receive buffers
+ * @adapter: address of board private structure
+ * @rx_ring: pointer to receive ring structure
+ * @cleaned_count: number of buffers to allocate this pass
+ **/
+
+static void
+e1000_alloc_jumbo_rx_buffers(struct e1000_adapter *adapter,
+ struct e1000_rx_ring *rx_ring, int cleaned_count)
+{
+ struct net_device *netdev = adapter->netdev;
+ struct pci_dev *pdev = adapter->pdev;
+ struct e1000_rx_desc *rx_desc;
+ struct e1000_buffer *buffer_info;
+ struct sk_buff *skb;
+ unsigned int i;
+ unsigned int bufsz = 256 -
+ 16 /*for skb_reserve */ -
+ NET_IP_ALIGN;
+
+ i = rx_ring->next_to_use;
+ buffer_info = &rx_ring->buffer_info[i];
+
+ while (cleaned_count--) {
+ skb = buffer_info->skb;
+ if (skb) {
+ skb_trim(skb, 0);
+ goto check_page;
+ }
+
+ skb = netdev_alloc_skb(netdev, bufsz);
+ if (unlikely(!skb)) {
+ /* Better luck next round */
+ adapter->alloc_rx_buff_failed++;
+ break;
+ }
+
+ /* Fix for errata 23, can't cross 64kB boundary */
+ if (!e1000_check_64k_bound(adapter, skb->data, bufsz)) {
+ struct sk_buff *oldskb = skb;
+ DPRINTK(PROBE, ERR, "skb align check failed: %u bytes "
+ "at %p\n", bufsz, skb->data);
+ /* Try again, without freeing the previous */
+ skb = netdev_alloc_skb(netdev, bufsz);
+ /* Failed allocation, critical failure */
+ if (!skb) {
+ dev_kfree_skb(oldskb);
+ adapter->alloc_rx_buff_failed++;
+ break;
+ }
+
+ if (!e1000_check_64k_bound(adapter, skb->data, bufsz)) {
+ /* give up */
+ dev_kfree_skb(skb);
+ dev_kfree_skb(oldskb);
+ break; /* while (cleaned_count--) */
+ }
+
+ /* Use new allocation */
+ dev_kfree_skb(oldskb);
+ }
+ /* Make buffer alignment 2 beyond a 16 byte boundary
+ * this will result in a 16 byte aligned IP header after
+ * the 14 byte MAC header is removed
+ */
+ skb_reserve(skb, NET_IP_ALIGN);
+
+ buffer_info->skb = skb;
+ buffer_info->length = adapter->rx_buffer_len;
+check_page:
+ /* allocate a new page if necessary */
+ if (!buffer_info->page) {
+ buffer_info->page = alloc_page(GFP_ATOMIC);
+ if (unlikely(!buffer_info->page)) {
+ adapter->alloc_rx_buff_failed++;
+ break;
+ }
+ }
+
+ if (!buffer_info->dma)
+ buffer_info->dma = pci_map_page(pdev,
+ buffer_info->page, 0,
+ buffer_info->length,
+ PCI_DMA_FROMDEVICE);
+
+ rx_desc = E1000_RX_DESC(*rx_ring, i);
+ rx_desc->buffer_addr = cpu_to_le64(buffer_info->dma);
+
+ if (unlikely(++i == rx_ring->count))
+ i = 0;
+ buffer_info = &rx_ring->buffer_info[i];
+ }
+
+ if (likely(rx_ring->next_to_use != i)) {
+ rx_ring->next_to_use = i;
+ if (unlikely(i-- == 0))
+ i = (rx_ring->count - 1);
+
+ /* Force memory writes to complete before letting h/w
+ * know there are new descriptors to fetch. (Only
+ * applicable for weak-ordered memory model archs,
+ * such as IA-64). */
+ wmb();
+ writel(i, adapter->hw.hw_addr + rx_ring->rdt);
+ }
+}
+
+/**
* e1000_alloc_rx_buffers - Replace used receive buffers; legacy & extended
* @adapter: address of board private structure
**/
@@ -4186,6 +4535,7 @@ static void e1000_alloc_rx_buffers(struct e1000_adapter *adapter,
/* Failed allocation, critical failure */
if (!skb) {
dev_kfree_skb(oldskb);
+ adapter->alloc_rx_buff_failed++;
break;
}
@@ -4193,6 +4543,7 @@ static void e1000_alloc_rx_buffers(struct e1000_adapter *adapter,
/* give up */
dev_kfree_skb(skb);
dev_kfree_skb(oldskb);
+ adapter->alloc_rx_buff_failed++;
break; /* while !buffer_info->skb */
}
@@ -4210,9 +4561,14 @@ static void e1000_alloc_rx_buffers(struct e1000_adapter *adapter,
map_skb:
buffer_info->dma = pci_map_single(pdev,
skb->data,
- adapter->rx_buffer_len,
+ buffer_info->length,
PCI_DMA_FROMDEVICE);
+ /*
+ * XXX if it was allocated cleanly it will never map to a
+ * boundary crossing
+ */
+
/* Fix for errata 23, can't cross 64kB boundary */
if (!e1000_check_64k_bound(adapter,
(void *)(unsigned long)buffer_info->dma,
@@ -4229,6 +4585,7 @@ map_skb:
PCI_DMA_FROMDEVICE);
buffer_info->dma = 0;
+ adapter->alloc_rx_buff_failed++;
break; /* while !buffer_info->skb */
}
rx_desc = E1000_RX_DESC(*rx_ring, i);
diff --git a/drivers/net/eepro.c b/drivers/net/eepro.c
index 4f700348534..53317a83857 100644
--- a/drivers/net/eepro.c
+++ b/drivers/net/eepro.c
@@ -1145,7 +1145,7 @@ static int eepro_send_packet(struct sk_buff *skb, struct net_device *dev)
if (length < ETH_ZLEN) {
if (skb_padto(skb, ETH_ZLEN))
- return 0;
+ return NETDEV_TX_OK;
length = ETH_ZLEN;
}
netif_stop_queue (dev);
@@ -1178,7 +1178,7 @@ static int eepro_send_packet(struct sk_buff *skb, struct net_device *dev)
eepro_en_int(ioaddr);
spin_unlock_irqrestore(&lp->lock, flags);
- return 0;
+ return NETDEV_TX_OK;
}
diff --git a/drivers/net/eexpress.c b/drivers/net/eexpress.c
index 1f016d66684..d1b6368faac 100644
--- a/drivers/net/eexpress.c
+++ b/drivers/net/eexpress.c
@@ -664,7 +664,7 @@ static int eexp_xmit(struct sk_buff *buf, struct net_device *dev)
if (buf->len < ETH_ZLEN) {
if (skb_padto(buf, ETH_ZLEN))
- return 0;
+ return NETDEV_TX_OK;
length = ETH_ZLEN;
}
@@ -691,7 +691,7 @@ static int eexp_xmit(struct sk_buff *buf, struct net_device *dev)
spin_unlock_irqrestore(&lp->lock, flags);
#endif
enable_irq(dev->irq);
- return 0;
+ return NETDEV_TX_OK;
}
/*
diff --git a/drivers/net/enc28j60.c b/drivers/net/enc28j60.c
index fc6cc038c7b..372d6c6a4e7 100644
--- a/drivers/net/enc28j60.c
+++ b/drivers/net/enc28j60.c
@@ -1299,7 +1299,7 @@ static int enc28j60_send_packet(struct sk_buff *skb, struct net_device *dev)
priv->tx_skb = skb;
schedule_work(&priv->tx_work);
- return 0;
+ return NETDEV_TX_OK;
}
static void enc28j60_tx_work_handler(struct work_struct *work)
diff --git a/drivers/net/epic100.c b/drivers/net/epic100.c
index 88d7ebf3122..d668ff2af6e 100644
--- a/drivers/net/epic100.c
+++ b/drivers/net/epic100.c
@@ -969,7 +969,7 @@ static int epic_start_xmit(struct sk_buff *skb, struct net_device *dev)
unsigned long flags;
if (skb_padto(skb, ETH_ZLEN))
- return 0;
+ return NETDEV_TX_OK;
/* Caution: the write order is important here, set the field with the
"ownership" bit last. */
@@ -1013,7 +1013,7 @@ static int epic_start_xmit(struct sk_buff *skb, struct net_device *dev)
dev->name, (int)skb->len, entry, ctrl_word,
(int)inl(dev->base_addr + TxSTAT));
- return 0;
+ return NETDEV_TX_OK;
}
static void epic_tx_error(struct net_device *dev, struct epic_private *ep,
diff --git a/drivers/net/eql.c b/drivers/net/eql.c
index 19b7dd98394..c0e69c5cae8 100644
--- a/drivers/net/eql.c
+++ b/drivers/net/eql.c
@@ -348,7 +348,7 @@ static int eql_slave_xmit(struct sk_buff *skb, struct net_device *dev)
spin_unlock(&eql->queue.lock);
- return 0;
+ return NETDEV_TX_OK;
}
/*
diff --git a/drivers/net/eth16i.c b/drivers/net/eth16i.c
index 0d8b6da046f..97d5205edc8 100644
--- a/drivers/net/eth16i.c
+++ b/drivers/net/eth16i.c
@@ -1064,7 +1064,7 @@ static int eth16i_tx(struct sk_buff *skb, struct net_device *dev)
if (length < ETH_ZLEN) {
if (skb_padto(skb, ETH_ZLEN))
- return 0;
+ return NETDEV_TX_OK;
length = ETH_ZLEN;
}
buf = skb->data;
@@ -1126,7 +1126,7 @@ static int eth16i_tx(struct sk_buff *skb, struct net_device *dev)
/* outb(TX_INTR_DONE | TX_INTR_16_COL, ioaddr + TX_INTR_REG); */
status = 0;
dev_kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
}
static void eth16i_rx(struct net_device *dev)
diff --git a/drivers/net/ethoc.c b/drivers/net/ethoc.c
index ceb6a9c357a..4dbe5f17327 100644
--- a/drivers/net/ethoc.c
+++ b/drivers/net/ethoc.c
@@ -894,7 +894,7 @@ static int ethoc_probe(struct platform_device *pdev)
mmio = devm_request_mem_region(&pdev->dev, res->start,
res->end - res->start + 1, res->name);
- if (!res) {
+ if (!mmio) {
dev_err(&pdev->dev, "cannot request I/O memory space\n");
ret = -ENXIO;
goto free;
diff --git a/drivers/net/ewrk3.c b/drivers/net/ewrk3.c
index 1e972328140..9c51bc813ad 100644
--- a/drivers/net/ewrk3.c
+++ b/drivers/net/ewrk3.c
@@ -868,7 +868,7 @@ static int ewrk3_queue_pkt (struct sk_buff *skb, struct net_device *dev)
if (inb (EWRK3_FMQC) == 0)
netif_stop_queue (dev);
- return 0;
+ return NETDEV_TX_OK;
err_out:
ENABLE_IRQs;
diff --git a/drivers/net/fealnx.c b/drivers/net/fealnx.c
index 160655d2458..f66da84a939 100644
--- a/drivers/net/fealnx.c
+++ b/drivers/net/fealnx.c
@@ -1378,7 +1378,7 @@ static int start_tx(struct sk_buff *skb, struct net_device *dev)
dev->trans_start = jiffies;
spin_unlock_irqrestore(&np->lock, flags);
- return 0;
+ return NETDEV_TX_OK;
}
diff --git a/drivers/net/fec.c b/drivers/net/fec.c
index c9fd82d3a80..967ad01b192 100644
--- a/drivers/net/fec.c
+++ b/drivers/net/fec.c
@@ -367,7 +367,7 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
spin_unlock_irqrestore(&fep->hw_lock, flags);
- return 0;
+ return NETDEV_TX_OK;
}
static void
diff --git a/drivers/net/fs_enet/mii-fec.c b/drivers/net/fs_enet/mii-fec.c
index 75a09994d66..a2d69c1cd07 100644
--- a/drivers/net/fs_enet/mii-fec.c
+++ b/drivers/net/fs_enet/mii-fec.c
@@ -36,6 +36,7 @@
#include <asm/pgtable.h>
#include <asm/irq.h>
#include <asm/uaccess.h>
+#include <asm/mpc5xxx.h>
#include "fs_enet.h"
#include "fec.h"
@@ -103,11 +104,11 @@ static int fs_enet_fec_mii_reset(struct mii_bus *bus)
static int __devinit fs_enet_mdio_probe(struct of_device *ofdev,
const struct of_device_id *match)
{
- struct device_node *np = NULL;
struct resource res;
struct mii_bus *new_bus;
struct fec_info *fec;
- int ret = -ENOMEM, i;
+ int (*get_bus_freq)(struct device_node *) = match->data;
+ int ret = -ENOMEM, clock, speed;
new_bus = mdiobus_alloc();
if (!new_bus)
@@ -133,13 +134,35 @@ static int __devinit fs_enet_mdio_probe(struct of_device *ofdev,
if (!fec->fecp)
goto out_fec;
- fec->mii_speed = ((ppc_proc_freq + 4999999) / 5000000) << 1;
+ if (get_bus_freq) {
+ clock = get_bus_freq(ofdev->node);
+ if (!clock) {
+ /* Use maximum divider if clock is unknown */
+ dev_warn(&ofdev->dev, "could not determine IPS clock\n");
+ clock = 0x3F * 5000000;
+ }
+ } else
+ clock = ppc_proc_freq;
+
+ /*
+ * Scale for a MII clock <= 2.5 MHz
+ * Note that only 6 bits (25:30) are available for MII speed.
+ */
+ speed = (clock + 4999999) / 5000000;
+ if (speed > 0x3F) {
+ speed = 0x3F;
+ dev_err(&ofdev->dev,
+ "MII clock (%d Hz) exceeds max (2.5 MHz)\n",
+ clock / speed);
+ }
+
+ fec->mii_speed = speed << 1;
setbits32(&fec->fecp->fec_r_cntrl, FEC_RCNTRL_MII_MODE);
setbits32(&fec->fecp->fec_ecntrl, FEC_ECNTRL_PINMUX |
FEC_ECNTRL_ETHER_EN);
out_be32(&fec->fecp->fec_ievent, FEC_ENET_MII);
- out_be32(&fec->fecp->fec_mii_speed, fec->mii_speed);
+ clrsetbits_be32(&fec->fecp->fec_mii_speed, 0x7E, fec->mii_speed);
new_bus->phy_mask = ~0;
new_bus->irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL);
@@ -188,6 +211,12 @@ static struct of_device_id fs_enet_mdio_fec_match[] = {
{
.compatible = "fsl,pq1-fec-mdio",
},
+#if defined(CONFIG_PPC_MPC512x)
+ {
+ .compatible = "fsl,mpc5121-fec-mdio",
+ .data = mpc5xxx_get_bus_frequency,
+ },
+#endif
{},
};
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c
index e212f2c5448..4544da4cf3c 100644
--- a/drivers/net/gianfar.c
+++ b/drivers/net/gianfar.c
@@ -297,7 +297,6 @@ static int gfar_probe(struct of_device *ofdev,
u32 tempval;
struct net_device *dev = NULL;
struct gfar_private *priv = NULL;
- DECLARE_MAC_BUF(mac);
int err = 0;
int len_devname;
diff --git a/drivers/net/hamachi.c b/drivers/net/hamachi.c
index d62378cbc14..635341d6a02 100644
--- a/drivers/net/hamachi.c
+++ b/drivers/net/hamachi.c
@@ -1372,7 +1372,7 @@ static int hamachi_start_xmit(struct sk_buff *skb, struct net_device *dev)
printk(KERN_DEBUG "%s: Hamachi transmit frame #%d queued in slot %d.\n",
dev->name, hmp->cur_tx, entry);
}
- return 0;
+ return NETDEV_TX_OK;
}
/* The interrupt handler does all of the Rx thread work and cleans up
diff --git a/drivers/net/hamradio/6pack.c b/drivers/net/hamradio/6pack.c
index 981ab530e9a..6cb2bdfd7b1 100644
--- a/drivers/net/hamradio/6pack.c
+++ b/drivers/net/hamradio/6pack.c
@@ -255,7 +255,7 @@ static int sp_xmit(struct sk_buff *skb, struct net_device *dev)
dev_kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
}
static int sp_open_dev(struct net_device *dev)
diff --git a/drivers/net/hamradio/baycom_epp.c b/drivers/net/hamradio/baycom_epp.c
index 352703255bb..7bcaf7c6624 100644
--- a/drivers/net/hamradio/baycom_epp.c
+++ b/drivers/net/hamradio/baycom_epp.c
@@ -774,18 +774,18 @@ static int baycom_send_packet(struct sk_buff *skb, struct net_device *dev)
if (skb->data[0] != 0) {
do_kiss_params(bc, skb->data, skb->len);
dev_kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
}
if (bc->skb)
return NETDEV_TX_LOCKED;
/* strip KISS byte */
if (skb->len >= HDLCDRV_MAXFLEN+1 || skb->len < 3) {
dev_kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
}
netif_stop_queue(dev);
bc->skb = skb;
- return 0;
+ return NETDEV_TX_OK;
}
/* --------------------------------------------------------------------- */
diff --git a/drivers/net/hamradio/bpqether.c b/drivers/net/hamradio/bpqether.c
index abcd19a8bff..4c5f4dfbe05 100644
--- a/drivers/net/hamradio/bpqether.c
+++ b/drivers/net/hamradio/bpqether.c
@@ -305,7 +305,7 @@ static int bpq_xmit(struct sk_buff *skb, struct net_device *dev)
dev_queue_xmit(skb);
netif_wake_queue(dev);
- return 0;
+ return NETDEV_TX_OK;
}
/*
diff --git a/drivers/net/hamradio/dmascc.c b/drivers/net/hamradio/dmascc.c
index 7459b3ac77a..950f3bb21f9 100644
--- a/drivers/net/hamradio/dmascc.c
+++ b/drivers/net/hamradio/dmascc.c
@@ -959,7 +959,7 @@ static int scc_send_packet(struct sk_buff *skb, struct net_device *dev)
spin_unlock_irqrestore(&priv->ring_lock, flags);
dev_kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
}
diff --git a/drivers/net/hamradio/hdlcdrv.c b/drivers/net/hamradio/hdlcdrv.c
index d034f8ca63c..16b060b9211 100644
--- a/drivers/net/hamradio/hdlcdrv.c
+++ b/drivers/net/hamradio/hdlcdrv.c
@@ -406,13 +406,13 @@ static int hdlcdrv_send_packet(struct sk_buff *skb, struct net_device *dev)
if (skb->data[0] != 0) {
do_kiss_params(sm, skb->data, skb->len);
dev_kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
}
if (sm->skb)
return NETDEV_TX_LOCKED;
netif_stop_queue(dev);
sm->skb = skb;
- return 0;
+ return NETDEV_TX_OK;
}
/* --------------------------------------------------------------------- */
diff --git a/drivers/net/hamradio/mkiss.c b/drivers/net/hamradio/mkiss.c
index fda2fc83e9a..ac191ef2119 100644
--- a/drivers/net/hamradio/mkiss.c
+++ b/drivers/net/hamradio/mkiss.c
@@ -560,7 +560,7 @@ static int ax_xmit(struct sk_buff *skb, struct net_device *dev)
kfree_skb(skb);
}
- return 0;
+ return NETDEV_TX_OK;
}
static int ax_open_dev(struct net_device *dev)
diff --git a/drivers/net/hamradio/scc.c b/drivers/net/hamradio/scc.c
index d712e7af780..c5406525c1a 100644
--- a/drivers/net/hamradio/scc.c
+++ b/drivers/net/hamradio/scc.c
@@ -1643,7 +1643,7 @@ static int scc_net_tx(struct sk_buff *skb, struct net_device *dev)
if (skb->len > scc->stat.bufsize || skb->len < 2) {
scc->dev_stat.tx_dropped++; /* bogus frame */
dev_kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
}
scc->dev_stat.tx_packets++;
@@ -1656,7 +1656,7 @@ static int scc_net_tx(struct sk_buff *skb, struct net_device *dev)
if (kisscmd) {
scc_set_param(scc, kisscmd, *skb->data);
dev_kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
}
spin_lock_irqsave(&scc->lock, flags);
@@ -1684,7 +1684,7 @@ static int scc_net_tx(struct sk_buff *skb, struct net_device *dev)
__scc_start_tx_timer(scc, t_dwait, 0);
}
spin_unlock_irqrestore(&scc->lock, flags);
- return 0;
+ return NETDEV_TX_OK;
}
/* ----> ioctl functions <---- */
diff --git a/drivers/net/hamradio/yam.c b/drivers/net/hamradio/yam.c
index b06691937ce..b85aa162314 100644
--- a/drivers/net/hamradio/yam.c
+++ b/drivers/net/hamradio/yam.c
@@ -600,7 +600,7 @@ static int yam_send_packet(struct sk_buff *skb, struct net_device *dev)
skb_queue_tail(&yp->send_queue, skb);
dev->trans_start = jiffies;
- return 0;
+ return NETDEV_TX_OK;
}
static void yam_start_tx(struct net_device *dev, struct yam_port *yp)
diff --git a/drivers/net/hp100.c b/drivers/net/hp100.c
index 1d3429a415e..d1b63387e9b 100644
--- a/drivers/net/hp100.c
+++ b/drivers/net/hp100.c
@@ -1499,7 +1499,7 @@ static int hp100_start_xmit_bm(struct sk_buff *skb, struct net_device *dev)
goto drop;
if (lp->chip == HP100_CHIPID_SHASTA && skb_padto(skb, ETH_ZLEN))
- return 0;
+ return NETDEV_TX_OK;
/* Get Tx ring tail pointer */
if (lp->txrtail->next == lp->txrhead) {
@@ -1585,7 +1585,7 @@ static int hp100_start_xmit_bm(struct sk_buff *skb, struct net_device *dev)
lp->stats.tx_bytes += skb->len;
dev->trans_start = jiffies;
- return 0;
+ return NETDEV_TX_OK;
drop:
dev_kfree_skb(skb);
@@ -1752,7 +1752,7 @@ static int hp100_start_xmit(struct sk_buff *skb, struct net_device *dev)
printk("hp100: %s: start_xmit: end\n", dev->name);
#endif
- return 0;
+ return NETDEV_TX_OK;
drop:
dev_kfree_skb(skb);
diff --git a/drivers/net/ibm_newemac/core.c b/drivers/net/ibm_newemac/core.c
index beb84213b67..5443558c439 100644
--- a/drivers/net/ibm_newemac/core.c
+++ b/drivers/net/ibm_newemac/core.c
@@ -1342,7 +1342,7 @@ static inline int emac_xmit_finish(struct emac_instance *dev, int len)
++dev->stats.tx_packets;
dev->stats.tx_bytes += len;
- return 0;
+ return NETDEV_TX_OK;
}
/* Tx lock BH */
diff --git a/drivers/net/ibmveth.c b/drivers/net/ibmveth.c
index 0995c438f28..76b295a1818 100644
--- a/drivers/net/ibmveth.c
+++ b/drivers/net/ibmveth.c
@@ -971,7 +971,7 @@ out: spin_lock_irqsave(&adapter->stats_lock, flags);
spin_unlock_irqrestore(&adapter->stats_lock, flags);
dev_kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
}
static int ibmveth_poll(struct napi_struct *napi, int budget)
diff --git a/drivers/net/ifb.c b/drivers/net/ifb.c
index 96713ef0629..0a79b451780 100644
--- a/drivers/net/ifb.c
+++ b/drivers/net/ifb.c
@@ -164,7 +164,7 @@ static int ifb_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct ifb_private *dp = netdev_priv(dev);
struct net_device_stats *stats = &dev->stats;
- int ret = 0;
+ int ret = NETDEV_TX_OK;
u32 from = G_TC_FROM(skb->tc_verd);
stats->rx_packets++;
diff --git a/drivers/net/igb/e1000_82575.c b/drivers/net/igb/e1000_82575.c
index ac28dd5a4fd..6158c0f3b20 100644
--- a/drivers/net/igb/e1000_82575.c
+++ b/drivers/net/igb/e1000_82575.c
@@ -53,7 +53,7 @@ static s32 igb_setup_fiber_serdes_link_82575(struct e1000_hw *);
static s32 igb_write_phy_reg_sgmii_82575(struct e1000_hw *, u32, u16);
static void igb_clear_hw_cntrs_82575(struct e1000_hw *);
static s32 igb_acquire_swfw_sync_82575(struct e1000_hw *, u16);
-static s32 igb_configure_pcs_link_82575(struct e1000_hw *);
+static void igb_configure_pcs_link_82575(struct e1000_hw *);
static s32 igb_get_pcs_speed_and_duplex_82575(struct e1000_hw *, u16 *,
u16 *);
static s32 igb_get_phy_id_82575(struct e1000_hw *);
@@ -61,6 +61,7 @@ static void igb_release_swfw_sync_82575(struct e1000_hw *, u16);
static bool igb_sgmii_active_82575(struct e1000_hw *);
static s32 igb_reset_init_script_82575(struct e1000_hw *);
static s32 igb_read_mac_addr_82575(struct e1000_hw *);
+static s32 igb_set_pcie_completion_timeout(struct e1000_hw *hw);
static s32 igb_get_invariants_82575(struct e1000_hw *hw)
{
@@ -84,6 +85,7 @@ static s32 igb_get_invariants_82575(struct e1000_hw *hw)
case E1000_DEV_ID_82576_FIBER:
case E1000_DEV_ID_82576_SERDES:
case E1000_DEV_ID_82576_QUAD_COPPER:
+ case E1000_DEV_ID_82576_SERDES_QUAD:
mac->type = e1000_82576;
break;
default:
@@ -170,6 +172,10 @@ static s32 igb_get_invariants_82575(struct e1000_hw *hw)
size = 14;
nvm->word_size = 1 << size;
+ /* if 82576 then initialize mailbox parameters */
+ if (mac->type == e1000_82576)
+ igb_init_mbx_params_pf(hw);
+
/* setup PHY parameters */
if (phy->media_type != e1000_media_type_copper) {
phy->type = e1000_phy_none;
@@ -219,10 +225,6 @@ static s32 igb_get_invariants_82575(struct e1000_hw *hw)
return -E1000_ERR_PHY;
}
- /* if 82576 then initialize mailbox parameters */
- if (mac->type == e1000_82576)
- igb_init_mbx_params_pf(hw);
-
return 0;
}
@@ -764,98 +766,6 @@ static s32 igb_get_pcs_speed_and_duplex_82575(struct e1000_hw *hw, u16 *speed,
}
/**
- * igb_init_rx_addrs_82575 - Initialize receive address's
- * @hw: pointer to the HW structure
- * @rar_count: receive address registers
- *
- * Setups the receive address registers by setting the base receive address
- * register to the devices MAC address and clearing all the other receive
- * address registers to 0.
- **/
-static void igb_init_rx_addrs_82575(struct e1000_hw *hw, u16 rar_count)
-{
- u32 i;
- u8 addr[6] = {0,0,0,0,0,0};
- /*
- * This function is essentially the same as that of
- * e1000_init_rx_addrs_generic. However it also takes care
- * of the special case where the register offset of the
- * second set of RARs begins elsewhere. This is implicitly taken care by
- * function e1000_rar_set_generic.
- */
-
- hw_dbg("e1000_init_rx_addrs_82575");
-
- /* Setup the receive address */
- hw_dbg("Programming MAC Address into RAR[0]\n");
- hw->mac.ops.rar_set(hw, hw->mac.addr, 0);
-
- /* Zero out the other (rar_entry_count - 1) receive addresses */
- hw_dbg("Clearing RAR[1-%u]\n", rar_count-1);
- for (i = 1; i < rar_count; i++)
- hw->mac.ops.rar_set(hw, addr, i);
-}
-
-/**
- * igb_update_mc_addr_list - Update Multicast addresses
- * @hw: pointer to the HW structure
- * @mc_addr_list: array of multicast addresses to program
- * @mc_addr_count: number of multicast addresses to program
- * @rar_used_count: the first RAR register free to program
- * @rar_count: total number of supported Receive Address Registers
- *
- * Updates the Receive Address Registers and Multicast Table Array.
- * The caller must have a packed mc_addr_list of multicast addresses.
- * The parameter rar_count will usually be hw->mac.rar_entry_count
- * unless there are workarounds that change this.
- **/
-void igb_update_mc_addr_list(struct e1000_hw *hw,
- u8 *mc_addr_list, u32 mc_addr_count,
- u32 rar_used_count, u32 rar_count)
-{
- u32 hash_value;
- u32 i;
- u8 addr[6] = {0,0,0,0,0,0};
- /*
- * This function is essentially the same as that of
- * igb_update_mc_addr_list_generic. However it also takes care
- * of the special case where the register offset of the
- * second set of RARs begins elsewhere. This is implicitly taken care by
- * function e1000_rar_set_generic.
- */
-
- /*
- * Load the first set of multicast addresses into the exact
- * filters (RAR). If there are not enough to fill the RAR
- * array, clear the filters.
- */
- for (i = rar_used_count; i < rar_count; i++) {
- if (mc_addr_count) {
- igb_rar_set(hw, mc_addr_list, i);
- mc_addr_count--;
- mc_addr_list += ETH_ALEN;
- } else {
- igb_rar_set(hw, addr, i);
- }
- }
-
- /* Clear the old settings from the MTA */
- hw_dbg("Clearing MTA\n");
- for (i = 0; i < hw->mac.mta_reg_count; i++) {
- array_wr32(E1000_MTA, i, 0);
- wrfl();
- }
-
- /* Load any remaining multicast addresses into the hash table. */
- for (; mc_addr_count > 0; mc_addr_count--) {
- hash_value = igb_hash_mc_addr(hw, mc_addr_list);
- hw_dbg("Hash value = 0x%03X\n", hash_value);
- igb_mta_set(hw, hash_value);
- mc_addr_list += ETH_ALEN;
- }
-}
-
-/**
* igb_shutdown_fiber_serdes_link_82575 - Remove link during power down
* @hw: pointer to the HW structure
*
@@ -866,9 +776,7 @@ void igb_shutdown_fiber_serdes_link_82575(struct e1000_hw *hw)
{
u32 reg;
- if (hw->mac.type != e1000_82576 ||
- (hw->phy.media_type != e1000_media_type_fiber &&
- hw->phy.media_type != e1000_media_type_internal_serdes))
+ if (hw->phy.media_type != e1000_media_type_internal_serdes)
return;
/* if the management interface is not enabled, then power down */
@@ -911,6 +819,12 @@ static s32 igb_reset_hw_82575(struct e1000_hw *hw)
if (ret_val)
hw_dbg("PCI-E Master disable polling has failed.\n");
+ /* set the completion timeout for interface */
+ ret_val = igb_set_pcie_completion_timeout(hw);
+ if (ret_val) {
+ hw_dbg("PCI-E Set completion timeout has failed.\n");
+ }
+
hw_dbg("Masking off all interrupts\n");
wr32(E1000_IMC, 0xffffffff);
@@ -943,7 +857,8 @@ static s32 igb_reset_hw_82575(struct e1000_hw *hw)
wr32(E1000_IMC, 0xffffffff);
icr = rd32(E1000_ICR);
- igb_check_alt_mac_addr(hw);
+ /* Install any alternate MAC address into RAR0 */
+ ret_val = igb_check_alt_mac_addr(hw);
return ret_val;
}
@@ -972,7 +887,8 @@ static s32 igb_init_hw_82575(struct e1000_hw *hw)
igb_clear_vfta(hw);
/* Setup the receive address */
- igb_init_rx_addrs_82575(hw, rar_count);
+ igb_init_rx_addrs(hw, rar_count);
+
/* Zero out the Multicast HASH table */
hw_dbg("Zeroing the MTA\n");
for (i = 0; i < mac->mta_reg_count; i++)
@@ -1002,7 +918,7 @@ static s32 igb_init_hw_82575(struct e1000_hw *hw)
**/
static s32 igb_setup_copper_link_82575(struct e1000_hw *hw)
{
- u32 ctrl, led_ctrl;
+ u32 ctrl;
s32 ret_val;
bool link;
@@ -1017,11 +933,6 @@ static s32 igb_setup_copper_link_82575(struct e1000_hw *hw)
break;
case e1000_phy_igp_3:
ret_val = igb_copper_link_setup_igp(hw);
- /* Setup activity LED */
- led_ctrl = rd32(E1000_LEDCTL);
- led_ctrl &= IGP_ACTIVITY_LED_MASK;
- led_ctrl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE);
- wr32(E1000_LEDCTL, led_ctrl);
break;
default:
ret_val = -E1000_ERR_PHY;
@@ -1052,9 +963,7 @@ static s32 igb_setup_copper_link_82575(struct e1000_hw *hw)
}
}
- ret_val = igb_configure_pcs_link_82575(hw);
- if (ret_val)
- goto out;
+ igb_configure_pcs_link_82575(hw);
/*
* Check link status. Wait up to 100 microseconds for link to become
@@ -1163,14 +1072,14 @@ static s32 igb_setup_fiber_serdes_link_82575(struct e1000_hw *hw)
* independent interface (sgmii) is being used. Configures the link
* for auto-negotiation or forces speed/duplex.
**/
-static s32 igb_configure_pcs_link_82575(struct e1000_hw *hw)
+static void igb_configure_pcs_link_82575(struct e1000_hw *hw)
{
struct e1000_mac_info *mac = &hw->mac;
u32 reg = 0;
if (hw->phy.media_type != e1000_media_type_copper ||
!(igb_sgmii_active_82575(hw)))
- goto out;
+ return;
/* For SGMII, we need to issue a PCS autoneg restart */
reg = rd32(E1000_PCS_LCTL);
@@ -1213,9 +1122,6 @@ static s32 igb_configure_pcs_link_82575(struct e1000_hw *hw)
reg);
}
wr32(E1000_PCS_LCTL, reg);
-
-out:
- return 0;
}
/**
@@ -1229,10 +1135,6 @@ out:
static bool igb_sgmii_active_82575(struct e1000_hw *hw)
{
struct e1000_dev_spec_82575 *dev_spec = &hw->dev_spec._82575;
-
- if (hw->mac.type != e1000_82575 && hw->mac.type != e1000_82576)
- return false;
-
return dev_spec->sgmii_active;
}
@@ -1424,6 +1326,57 @@ void igb_rx_fifo_flush_82575(struct e1000_hw *hw)
}
/**
+ * igb_set_pcie_completion_timeout - set pci-e completion timeout
+ * @hw: pointer to the HW structure
+ *
+ * The defaults for 82575 and 82576 should be in the range of 50us to 50ms,
+ * however the hardware default for these parts is 500us to 1ms which is less
+ * than the 10ms recommended by the pci-e spec. To address this we need to
+ * increase the value to either 10ms to 200ms for capability version 1 config,
+ * or 16ms to 55ms for version 2.
+ **/
+static s32 igb_set_pcie_completion_timeout(struct e1000_hw *hw)
+{
+ u32 gcr = rd32(E1000_GCR);
+ s32 ret_val = 0;
+ u16 pcie_devctl2;
+
+ /* only take action if timeout value is defaulted to 0 */
+ if (gcr & E1000_GCR_CMPL_TMOUT_MASK)
+ goto out;
+
+ /*
+ * if capababilities version is type 1 we can write the
+ * timeout of 10ms to 200ms through the GCR register
+ */
+ if (!(gcr & E1000_GCR_CAP_VER2)) {
+ gcr |= E1000_GCR_CMPL_TMOUT_10ms;
+ goto out;
+ }
+
+ /*
+ * for version 2 capabilities we need to write the config space
+ * directly in order to set the completion timeout value for
+ * 16ms to 55ms
+ */
+ ret_val = igb_read_pcie_cap_reg(hw, PCIE_DEVICE_CONTROL2,
+ &pcie_devctl2);
+ if (ret_val)
+ goto out;
+
+ pcie_devctl2 |= PCIE_DEVICE_CONTROL2_16ms;
+
+ ret_val = igb_write_pcie_cap_reg(hw, PCIE_DEVICE_CONTROL2,
+ &pcie_devctl2);
+out:
+ /* disable completion timeout resend */
+ gcr &= ~E1000_GCR_CMPL_TMOUT_RESEND;
+
+ wr32(E1000_GCR, gcr);
+ return ret_val;
+}
+
+/**
* igb_vmdq_set_loopback_pf - enable or disable vmdq loopback
* @hw: pointer to the hardware struct
* @enable: state to enter, either enabled or disabled
diff --git a/drivers/net/igb/e1000_82575.h b/drivers/net/igb/e1000_82575.h
index 0f16abab256..8a1e6597061 100644
--- a/drivers/net/igb/e1000_82575.h
+++ b/drivers/net/igb/e1000_82575.h
@@ -28,10 +28,14 @@
#ifndef _E1000_82575_H_
#define _E1000_82575_H_
-void igb_update_mc_addr_list(struct e1000_hw*, u8*, u32, u32, u32);
extern void igb_shutdown_fiber_serdes_link_82575(struct e1000_hw *hw);
extern void igb_rx_fifo_flush_82575(struct e1000_hw *hw);
+#define ID_LED_DEFAULT_82575_SERDES ((ID_LED_DEF1_DEF2 << 12) | \
+ (ID_LED_DEF1_DEF2 << 8) | \
+ (ID_LED_DEF1_DEF2 << 4) | \
+ (ID_LED_OFF1_ON2))
+
#define E1000_RAR_ENTRIES_82575 16
#define E1000_RAR_ENTRIES_82576 24
diff --git a/drivers/net/igb/e1000_defines.h b/drivers/net/igb/e1000_defines.h
index 3bda3db73f1..c85829355d5 100644
--- a/drivers/net/igb/e1000_defines.h
+++ b/drivers/net/igb/e1000_defines.h
@@ -435,6 +435,12 @@
/* Flow Control */
#define E1000_FCRTL_XONE 0x80000000 /* Enable XON frame transmission */
+/* PCI Express Control */
+#define E1000_GCR_CMPL_TMOUT_MASK 0x0000F000
+#define E1000_GCR_CMPL_TMOUT_10ms 0x00001000
+#define E1000_GCR_CMPL_TMOUT_RESEND 0x00010000
+#define E1000_GCR_CAP_VER2 0x00040000
+
/* PHY Control Register */
#define MII_CR_FULL_DUPLEX 0x0100 /* FDX =1, half duplex =0 */
#define MII_CR_RESTART_AUTO_NEG 0x0200 /* Restart auto negotiation */
@@ -569,9 +575,11 @@
/* PCI/PCI-X/PCI-EX Config space */
#define PCIE_LINK_STATUS 0x12
+#define PCIE_DEVICE_CONTROL2 0x28
#define PCIE_LINK_WIDTH_MASK 0x3F0
#define PCIE_LINK_WIDTH_SHIFT 4
+#define PCIE_DEVICE_CONTROL2_16ms 0x0005
#define PHY_REVISION_MASK 0xFFFFFFF0
#define MAX_PHY_REG_ADDRESS 0x1F /* 5 bit address bus (0-0x1F) */
diff --git a/drivers/net/igb/e1000_hw.h b/drivers/net/igb/e1000_hw.h
index 68aac20c31c..119869b1124 100644
--- a/drivers/net/igb/e1000_hw.h
+++ b/drivers/net/igb/e1000_hw.h
@@ -42,6 +42,7 @@ struct e1000_hw;
#define E1000_DEV_ID_82576_SERDES 0x10E7
#define E1000_DEV_ID_82576_QUAD_COPPER 0x10E8
#define E1000_DEV_ID_82576_NS 0x150A
+#define E1000_DEV_ID_82576_SERDES_QUAD 0x150D
#define E1000_DEV_ID_82575EB_COPPER 0x10A7
#define E1000_DEV_ID_82575EB_FIBER_SERDES 0x10A9
#define E1000_DEV_ID_82575GB_QUAD_COPPER 0x10D6
@@ -61,8 +62,7 @@ enum e1000_mac_type {
enum e1000_media_type {
e1000_media_type_unknown = 0,
e1000_media_type_copper = 1,
- e1000_media_type_fiber = 2,
- e1000_media_type_internal_serdes = 3,
+ e1000_media_type_internal_serdes = 2,
e1000_num_media_types
};
@@ -137,7 +137,7 @@ enum e1000_rev_polarity {
e1000_rev_polarity_undefined = 0xFF
};
-enum e1000_fc_type {
+enum e1000_fc_mode {
e1000_fc_none = 0,
e1000_fc_rx_pause,
e1000_fc_tx_pause,
@@ -339,6 +339,10 @@ struct e1000_mac_info {
u16 ifs_ratio;
u16 ifs_step_size;
u16 mta_reg_count;
+
+ /* Maximum size of the MTA register table in all supported adapters */
+ #define MAX_MTA_REG 128
+ u32 mta_shadow[MAX_MTA_REG];
u16 rar_entry_count;
u8 forced_speed_duplex;
@@ -425,8 +429,8 @@ struct e1000_fc_info {
u16 pause_time; /* Flow control pause timer */
bool send_xon; /* Flow control send XON */
bool strict_ieee; /* Strict IEEE mode */
- enum e1000_fc_type type; /* Type of flow control */
- enum e1000_fc_type original_type;
+ enum e1000_fc_mode current_mode; /* Type of flow control */
+ enum e1000_fc_mode requested_mode;
};
struct e1000_mbx_operations {
@@ -495,5 +499,7 @@ extern char *igb_get_hw_dev_name(struct e1000_hw *hw);
#else
#define hw_dbg(format, arg...)
#endif
-
#endif
+/* These functions must be implemented by drivers */
+s32 igb_read_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value);
+s32 igb_write_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value);
diff --git a/drivers/net/igb/e1000_mac.c b/drivers/net/igb/e1000_mac.c
index 472f3f12484..a0231cd079f 100644
--- a/drivers/net/igb/e1000_mac.c
+++ b/drivers/net/igb/e1000_mac.c
@@ -37,20 +37,6 @@
static s32 igb_set_default_fc(struct e1000_hw *hw);
static s32 igb_set_fc_watermarks(struct e1000_hw *hw);
-static s32 igb_read_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value)
-{
- struct igb_adapter *adapter = hw->back;
- u16 cap_offset;
-
- cap_offset = pci_find_capability(adapter->pdev, PCI_CAP_ID_EXP);
- if (!cap_offset)
- return -E1000_ERR_CONFIG;
-
- pci_read_config_word(adapter->pdev, cap_offset + reg, value);
-
- return 0;
-}
-
/**
* igb_get_bus_info_pcie - Get PCIe bus information
* @hw: pointer to the HW structure
@@ -118,6 +104,31 @@ static void igb_write_vfta(struct e1000_hw *hw, u32 offset, u32 value)
}
/**
+ * igb_init_rx_addrs - Initialize receive address's
+ * @hw: pointer to the HW structure
+ * @rar_count: receive address registers
+ *
+ * Setups the receive address registers by setting the base receive address
+ * register to the devices MAC address and clearing all the other receive
+ * address registers to 0.
+ **/
+void igb_init_rx_addrs(struct e1000_hw *hw, u16 rar_count)
+{
+ u32 i;
+ u8 mac_addr[ETH_ALEN] = {0};
+
+ /* Setup the receive address */
+ hw_dbg("Programming MAC Address into RAR[0]\n");
+
+ hw->mac.ops.rar_set(hw, hw->mac.addr, 0);
+
+ /* Zero out the other (rar_entry_count - 1) receive addresses */
+ hw_dbg("Clearing RAR[1-%u]\n", rar_count-1);
+ for (i = 1; i < rar_count; i++)
+ hw->mac.ops.rar_set(hw, mac_addr, i);
+}
+
+/**
* igb_vfta_set - enable or disable vlan in VLAN filter table
* @hw: pointer to the HW structure
* @vid: VLAN id to add or remove
@@ -275,6 +286,41 @@ void igb_mta_set(struct e1000_hw *hw, u32 hash_value)
}
/**
+ * igb_update_mc_addr_list - Update Multicast addresses
+ * @hw: pointer to the HW structure
+ * @mc_addr_list: array of multicast addresses to program
+ * @mc_addr_count: number of multicast addresses to program
+ *
+ * Updates entire Multicast Table Array.
+ * The caller must have a packed mc_addr_list of multicast addresses.
+ **/
+void igb_update_mc_addr_list(struct e1000_hw *hw,
+ u8 *mc_addr_list, u32 mc_addr_count)
+{
+ u32 hash_value, hash_bit, hash_reg;
+ int i;
+
+ /* clear mta_shadow */
+ memset(&hw->mac.mta_shadow, 0, sizeof(hw->mac.mta_shadow));
+
+ /* update mta_shadow from mc_addr_list */
+ for (i = 0; (u32) i < mc_addr_count; i++) {
+ hash_value = igb_hash_mc_addr(hw, mc_addr_list);
+
+ hash_reg = (hash_value >> 5) & (hw->mac.mta_reg_count - 1);
+ hash_bit = hash_value & 0x1F;
+
+ hw->mac.mta_shadow[hash_reg] |= (1 << hash_bit);
+ mc_addr_list += (ETH_ALEN);
+ }
+
+ /* replace the entire MTA table */
+ for (i = hw->mac.mta_reg_count - 1; i >= 0; i--)
+ array_wr32(E1000_MTA, i, hw->mac.mta_shadow[i]);
+ wrfl();
+}
+
+/**
* igb_hash_mc_addr - Generate a multicast hash value
* @hw: pointer to the HW structure
* @mc_addr: pointer to a multicast address
@@ -490,18 +536,24 @@ s32 igb_setup_link(struct e1000_hw *hw)
if (igb_check_reset_block(hw))
goto out;
- ret_val = igb_set_default_fc(hw);
- if (ret_val)
- goto out;
+ /*
+ * If requested flow control is set to default, set flow control
+ * based on the EEPROM flow control settings.
+ */
+ if (hw->fc.requested_mode == e1000_fc_default) {
+ ret_val = igb_set_default_fc(hw);
+ if (ret_val)
+ goto out;
+ }
/*
* We want to save off the original Flow Control configuration just
* in case we get disconnected and then reconnected into a different
* hub or switch with different Flow Control capabilities.
*/
- hw->fc.original_type = hw->fc.type;
+ hw->fc.current_mode = hw->fc.requested_mode;
- hw_dbg("After fix-ups FlowControl is now = %x\n", hw->fc.type);
+ hw_dbg("After fix-ups FlowControl is now = %x\n", hw->fc.current_mode);
/* Call the necessary media_type subroutine to configure the link. */
ret_val = hw->mac.ops.setup_physical_interface(hw);
@@ -568,7 +620,7 @@ static s32 igb_set_fc_watermarks(struct e1000_hw *hw)
* ability to transmit pause frames is not enabled, then these
* registers will be set to 0.
*/
- if (hw->fc.type & e1000_fc_tx_pause) {
+ if (hw->fc.current_mode & e1000_fc_tx_pause) {
/*
* We need to set up the Receive Threshold high and low water
* marks as well as (optionally) enabling the transmission of
@@ -615,12 +667,12 @@ static s32 igb_set_default_fc(struct e1000_hw *hw)
}
if ((nvm_data & NVM_WORD0F_PAUSE_MASK) == 0)
- hw->fc.type = e1000_fc_none;
+ hw->fc.requested_mode = e1000_fc_none;
else if ((nvm_data & NVM_WORD0F_PAUSE_MASK) ==
NVM_WORD0F_ASM_DIR)
- hw->fc.type = e1000_fc_tx_pause;
+ hw->fc.requested_mode = e1000_fc_tx_pause;
else
- hw->fc.type = e1000_fc_full;
+ hw->fc.requested_mode = e1000_fc_full;
out:
return ret_val;
@@ -650,7 +702,7 @@ s32 igb_force_mac_fc(struct e1000_hw *hw)
* receive flow control.
*
* The "Case" statement below enables/disable flow control
- * according to the "hw->fc.type" parameter.
+ * according to the "hw->fc.current_mode" parameter.
*
* The possible values of the "fc" parameter are:
* 0: Flow control is completely disabled
@@ -661,9 +713,9 @@ s32 igb_force_mac_fc(struct e1000_hw *hw)
* 3: Both Rx and TX flow control (symmetric) is enabled.
* other: No other values should be possible at this point.
*/
- hw_dbg("hw->fc.type = %u\n", hw->fc.type);
+ hw_dbg("hw->fc.current_mode = %u\n", hw->fc.current_mode);
- switch (hw->fc.type) {
+ switch (hw->fc.current_mode) {
case e1000_fc_none:
ctrl &= (~(E1000_CTRL_TFCE | E1000_CTRL_RFCE));
break;
@@ -713,8 +765,7 @@ s32 igb_config_fc_after_link_up(struct e1000_hw *hw)
* configuration of the MAC to match the "fc" parameter.
*/
if (mac->autoneg_failed) {
- if (hw->phy.media_type == e1000_media_type_fiber ||
- hw->phy.media_type == e1000_media_type_internal_serdes)
+ if (hw->phy.media_type == e1000_media_type_internal_serdes)
ret_val = igb_force_mac_fc(hw);
} else {
if (hw->phy.media_type == e1000_media_type_copper)
@@ -812,11 +863,11 @@ s32 igb_config_fc_after_link_up(struct e1000_hw *hw)
* ONLY. Hence, we must now check to see if we need to
* turn OFF the TRANSMISSION of PAUSE frames.
*/
- if (hw->fc.original_type == e1000_fc_full) {
- hw->fc.type = e1000_fc_full;
+ if (hw->fc.requested_mode == e1000_fc_full) {
+ hw->fc.current_mode = e1000_fc_full;
hw_dbg("Flow Control = FULL.\r\n");
} else {
- hw->fc.type = e1000_fc_rx_pause;
+ hw->fc.current_mode = e1000_fc_rx_pause;
hw_dbg("Flow Control = "
"RX PAUSE frames only.\r\n");
}
@@ -833,7 +884,7 @@ s32 igb_config_fc_after_link_up(struct e1000_hw *hw)
(mii_nway_adv_reg & NWAY_AR_ASM_DIR) &&
(mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) &&
(mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) {
- hw->fc.type = e1000_fc_tx_pause;
+ hw->fc.current_mode = e1000_fc_tx_pause;
hw_dbg("Flow Control = TX PAUSE frames only.\r\n");
}
/*
@@ -848,7 +899,7 @@ s32 igb_config_fc_after_link_up(struct e1000_hw *hw)
(mii_nway_adv_reg & NWAY_AR_ASM_DIR) &&
!(mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) &&
(mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) {
- hw->fc.type = e1000_fc_rx_pause;
+ hw->fc.current_mode = e1000_fc_rx_pause;
hw_dbg("Flow Control = RX PAUSE frames only.\r\n");
}
/*
@@ -872,13 +923,13 @@ s32 igb_config_fc_after_link_up(struct e1000_hw *hw)
* be asked to delay transmission of packets than asking
* our link partner to pause transmission of frames.
*/
- else if ((hw->fc.original_type == e1000_fc_none ||
- hw->fc.original_type == e1000_fc_tx_pause) ||
+ else if ((hw->fc.requested_mode == e1000_fc_none ||
+ hw->fc.requested_mode == e1000_fc_tx_pause) ||
hw->fc.strict_ieee) {
- hw->fc.type = e1000_fc_none;
+ hw->fc.current_mode = e1000_fc_none;
hw_dbg("Flow Control = NONE.\r\n");
} else {
- hw->fc.type = e1000_fc_rx_pause;
+ hw->fc.current_mode = e1000_fc_rx_pause;
hw_dbg("Flow Control = RX PAUSE frames only.\r\n");
}
@@ -894,7 +945,7 @@ s32 igb_config_fc_after_link_up(struct e1000_hw *hw)
}
if (duplex == HALF_DUPLEX)
- hw->fc.type = e1000_fc_none;
+ hw->fc.current_mode = e1000_fc_none;
/*
* Now we call a subroutine to actually force the MAC
@@ -1065,9 +1116,17 @@ static s32 igb_valid_led_default(struct e1000_hw *hw, u16 *data)
goto out;
}
- if (*data == ID_LED_RESERVED_0000 || *data == ID_LED_RESERVED_FFFF)
- *data = ID_LED_DEFAULT;
-
+ if (*data == ID_LED_RESERVED_0000 || *data == ID_LED_RESERVED_FFFF) {
+ switch(hw->phy.media_type) {
+ case e1000_media_type_internal_serdes:
+ *data = ID_LED_DEFAULT_82575_SERDES;
+ break;
+ case e1000_media_type_copper:
+ default:
+ *data = ID_LED_DEFAULT;
+ break;
+ }
+ }
out:
return ret_val;
}
@@ -1161,22 +1220,16 @@ s32 igb_blink_led(struct e1000_hw *hw)
u32 ledctl_blink = 0;
u32 i;
- if (hw->phy.media_type == e1000_media_type_fiber) {
- /* always blink LED0 for PCI-E fiber */
- ledctl_blink = E1000_LEDCTL_LED0_BLINK |
- (E1000_LEDCTL_MODE_LED_ON << E1000_LEDCTL_LED0_MODE_SHIFT);
- } else {
- /*
- * set the blink bit for each LED that's "on" (0x0E)
- * in ledctl_mode2
- */
- ledctl_blink = hw->mac.ledctl_mode2;
- for (i = 0; i < 4; i++)
- if (((hw->mac.ledctl_mode2 >> (i * 8)) & 0xFF) ==
- E1000_LEDCTL_MODE_LED_ON)
- ledctl_blink |= (E1000_LEDCTL_LED0_BLINK <<
- (i * 8));
- }
+ /*
+ * set the blink bit for each LED that's "on" (0x0E)
+ * in ledctl_mode2
+ */
+ ledctl_blink = hw->mac.ledctl_mode2;
+ for (i = 0; i < 4; i++)
+ if (((hw->mac.ledctl_mode2 >> (i * 8)) & 0xFF) ==
+ E1000_LEDCTL_MODE_LED_ON)
+ ledctl_blink |= (E1000_LEDCTL_LED0_BLINK <<
+ (i * 8));
wr32(E1000_LEDCTL, ledctl_blink);
@@ -1191,15 +1244,7 @@ s32 igb_blink_led(struct e1000_hw *hw)
**/
s32 igb_led_off(struct e1000_hw *hw)
{
- u32 ctrl;
-
switch (hw->phy.media_type) {
- case e1000_media_type_fiber:
- ctrl = rd32(E1000_CTRL);
- ctrl |= E1000_CTRL_SWDPIN0;
- ctrl |= E1000_CTRL_SWDPIO0;
- wr32(E1000_CTRL, ctrl);
- break;
case e1000_media_type_copper:
wr32(E1000_LEDCTL, hw->mac.ledctl_mode1);
break;
diff --git a/drivers/net/igb/e1000_mac.h b/drivers/net/igb/e1000_mac.h
index 1d690b4c9ae..7518af8cbbf 100644
--- a/drivers/net/igb/e1000_mac.h
+++ b/drivers/net/igb/e1000_mac.h
@@ -51,6 +51,8 @@ s32 igb_get_speed_and_duplex_copper(struct e1000_hw *hw, u16 *speed,
u16 *duplex);
s32 igb_id_led_init(struct e1000_hw *hw);
s32 igb_led_off(struct e1000_hw *hw);
+void igb_update_mc_addr_list(struct e1000_hw *hw,
+ u8 *mc_addr_list, u32 mc_addr_count);
s32 igb_setup_link(struct e1000_hw *hw);
s32 igb_validate_mdi_setting(struct e1000_hw *hw);
s32 igb_write_8bit_ctrl_reg(struct e1000_hw *hw, u32 reg,
@@ -60,6 +62,7 @@ void igb_clear_hw_cntrs_base(struct e1000_hw *hw);
void igb_clear_vfta(struct e1000_hw *hw);
s32 igb_vfta_set(struct e1000_hw *hw, u32 vid, bool add);
void igb_config_collision_dist(struct e1000_hw *hw);
+void igb_init_rx_addrs(struct e1000_hw *hw, u16 rar_count);
void igb_mta_set(struct e1000_hw *hw, u32 hash_value);
void igb_put_hw_semaphore(struct e1000_hw *hw);
void igb_rar_set(struct e1000_hw *hw, u8 *addr, u32 index);
diff --git a/drivers/net/igb/e1000_phy.c b/drivers/net/igb/e1000_phy.c
index f50fac25be4..c1f4da63042 100644
--- a/drivers/net/igb/e1000_phy.c
+++ b/drivers/net/igb/e1000_phy.c
@@ -735,7 +735,7 @@ static s32 igb_phy_setup_autoneg(struct e1000_hw *hw)
* other: No software override. The flow control configuration
* in the EEPROM is used.
*/
- switch (hw->fc.type) {
+ switch (hw->fc.current_mode) {
case e1000_fc_none:
/*
* Flow control (RX & TX) is completely disabled by a
@@ -992,7 +992,7 @@ static void igb_phy_force_speed_duplex_setup(struct e1000_hw *hw,
u32 ctrl;
/* Turn off flow control when forcing speed/duplex */
- hw->fc.type = e1000_fc_none;
+ hw->fc.current_mode = e1000_fc_none;
/* Force speed/duplex on the mac */
ctrl = rd32(E1000_CTRL);
diff --git a/drivers/net/igb/e1000_regs.h b/drivers/net/igb/e1000_regs.h
index 6e5924511e4..345d1442d6d 100644
--- a/drivers/net/igb/e1000_regs.h
+++ b/drivers/net/igb/e1000_regs.h
@@ -305,6 +305,7 @@ enum {
#define E1000_CCMCTL 0x05B48 /* CCM Control Register */
#define E1000_GIOCTL 0x05B44 /* GIO Analog Control Register */
#define E1000_SCCTL 0x05B4C /* PCIc PLL Configuration Register */
+#define E1000_GCR 0x05B00 /* PCI-Ex Control */
#define E1000_FACTPS 0x05B30 /* Function Active and Power State to MNG */
#define E1000_SWSM 0x05B50 /* SW Semaphore */
#define E1000_FWSM 0x05B54 /* FW Semaphore */
diff --git a/drivers/net/igb/igb_ethtool.c b/drivers/net/igb/igb_ethtool.c
index 9598ac09f4b..114ccab1f2b 100644
--- a/drivers/net/igb/igb_ethtool.c
+++ b/drivers/net/igb/igb_ethtool.c
@@ -168,8 +168,7 @@ static int igb_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
ecmd->duplex = -1;
}
- ecmd->autoneg = ((hw->phy.media_type == e1000_media_type_fiber) ||
- hw->mac.autoneg) ? AUTONEG_ENABLE : AUTONEG_DISABLE;
+ ecmd->autoneg = hw->mac.autoneg ? AUTONEG_ENABLE : AUTONEG_DISABLE;
return 0;
}
@@ -191,23 +190,20 @@ static int igb_set_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
if (ecmd->autoneg == AUTONEG_ENABLE) {
hw->mac.autoneg = 1;
- if (hw->phy.media_type == e1000_media_type_fiber)
- hw->phy.autoneg_advertised = ADVERTISED_1000baseT_Full |
- ADVERTISED_FIBRE |
- ADVERTISED_Autoneg;
- else
- hw->phy.autoneg_advertised = ecmd->advertising |
- ADVERTISED_TP |
- ADVERTISED_Autoneg;
+ hw->phy.autoneg_advertised = ecmd->advertising |
+ ADVERTISED_TP |
+ ADVERTISED_Autoneg;
ecmd->advertising = hw->phy.autoneg_advertised;
- } else
+ if (adapter->fc_autoneg)
+ hw->fc.requested_mode = e1000_fc_default;
+ } else {
if (igb_set_spd_dplx(adapter, ecmd->speed + ecmd->duplex)) {
clear_bit(__IGB_RESETTING, &adapter->state);
return -EINVAL;
}
+ }
/* reset the link */
-
if (netif_running(adapter->netdev)) {
igb_down(adapter);
igb_up(adapter);
@@ -227,11 +223,11 @@ static void igb_get_pauseparam(struct net_device *netdev,
pause->autoneg =
(adapter->fc_autoneg ? AUTONEG_ENABLE : AUTONEG_DISABLE);
- if (hw->fc.type == e1000_fc_rx_pause)
+ if (hw->fc.current_mode == e1000_fc_rx_pause)
pause->rx_pause = 1;
- else if (hw->fc.type == e1000_fc_tx_pause)
+ else if (hw->fc.current_mode == e1000_fc_tx_pause)
pause->tx_pause = 1;
- else if (hw->fc.type == e1000_fc_full) {
+ else if (hw->fc.current_mode == e1000_fc_full) {
pause->rx_pause = 1;
pause->tx_pause = 1;
}
@@ -249,26 +245,28 @@ static int igb_set_pauseparam(struct net_device *netdev,
while (test_and_set_bit(__IGB_RESETTING, &adapter->state))
msleep(1);
- if (pause->rx_pause && pause->tx_pause)
- hw->fc.type = e1000_fc_full;
- else if (pause->rx_pause && !pause->tx_pause)
- hw->fc.type = e1000_fc_rx_pause;
- else if (!pause->rx_pause && pause->tx_pause)
- hw->fc.type = e1000_fc_tx_pause;
- else if (!pause->rx_pause && !pause->tx_pause)
- hw->fc.type = e1000_fc_none;
-
- hw->fc.original_type = hw->fc.type;
-
if (adapter->fc_autoneg == AUTONEG_ENABLE) {
+ hw->fc.requested_mode = e1000_fc_default;
if (netif_running(adapter->netdev)) {
igb_down(adapter);
igb_up(adapter);
} else
igb_reset(adapter);
- } else
- retval = ((hw->phy.media_type == e1000_media_type_fiber) ?
- igb_setup_link(hw) : igb_force_mac_fc(hw));
+ } else {
+ if (pause->rx_pause && pause->tx_pause)
+ hw->fc.requested_mode = e1000_fc_full;
+ else if (pause->rx_pause && !pause->tx_pause)
+ hw->fc.requested_mode = e1000_fc_rx_pause;
+ else if (!pause->rx_pause && pause->tx_pause)
+ hw->fc.requested_mode = e1000_fc_tx_pause;
+ else if (!pause->rx_pause && !pause->tx_pause)
+ hw->fc.requested_mode = e1000_fc_none;
+
+ hw->fc.current_mode = hw->fc.requested_mode;
+
+ retval = ((hw->phy.media_type == e1000_media_type_copper) ?
+ igb_force_mac_fc(hw) : igb_setup_link(hw));
+ }
clear_bit(__IGB_RESETTING, &adapter->state);
return retval;
@@ -1483,8 +1481,7 @@ static int igb_setup_loopback_test(struct igb_adapter *adapter)
struct e1000_hw *hw = &adapter->hw;
u32 reg;
- if (hw->phy.media_type == e1000_media_type_fiber ||
- hw->phy.media_type == e1000_media_type_internal_serdes) {
+ if (hw->phy.media_type == e1000_media_type_internal_serdes) {
reg = rd32(E1000_RCTL);
reg |= E1000_RCTL_LBM_TCVR;
wr32(E1000_RCTL, reg);
@@ -1843,7 +1840,6 @@ static void igb_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
static int igb_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
{
struct igb_adapter *adapter = netdev_priv(netdev);
- struct e1000_hw *hw = &adapter->hw;
if (wol->wolopts & (WAKE_PHY | WAKE_ARP | WAKE_MAGICSECURE))
return -EOPNOTSUPP;
@@ -1852,11 +1848,6 @@ static int igb_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
!device_can_wakeup(&adapter->pdev->dev))
return wol->wolopts ? -EOPNOTSUPP : 0;
- switch (hw->device_id) {
- default:
- break;
- }
-
/* these settings will always override what we currently have */
adapter->wol = 0;
diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c
index adb09d32625..fb327351758 100644
--- a/drivers/net/igb/igb_main.c
+++ b/drivers/net/igb/igb_main.c
@@ -65,6 +65,7 @@ static struct pci_device_id igb_pci_tbl[] = {
{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82576_NS), board_82575 },
{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82576_FIBER), board_82575 },
{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82576_SERDES), board_82575 },
+ { PCI_VDEVICE(INTEL, E1000_DEV_ID_82576_SERDES_QUAD), board_82575 },
{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82576_QUAD_COPPER), board_82575 },
{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82575EB_COPPER), board_82575 },
{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82575EB_FIBER_SERDES), board_82575 },
@@ -127,7 +128,7 @@ static void igb_restore_vlan(struct igb_adapter *);
static void igb_ping_all_vfs(struct igb_adapter *);
static void igb_msg_task(struct igb_adapter *);
static int igb_rcv_msg_from_vf(struct igb_adapter *, u32);
-static void igb_set_mc_list_pools(struct igb_adapter *, int, u16);
+static inline void igb_set_rah_pool(struct e1000_hw *, int , int);
static void igb_vmm_control(struct igb_adapter *);
static int igb_set_vf_mac(struct igb_adapter *adapter, int, unsigned char *);
static void igb_restore_vf_multicasts(struct igb_adapter *adapter);
@@ -1129,7 +1130,7 @@ void igb_reset(struct igb_adapter *adapter)
}
fc->pause_time = 0xFFFF;
fc->send_xon = 1;
- fc->type = fc->original_type;
+ fc->current_mode = fc->requested_mode;
/* disable receive for all VFs and wait one second */
if (adapter->vfs_allocated_count) {
@@ -1426,8 +1427,8 @@ static int __devinit igb_probe(struct pci_dev *pdev,
hw->mac.autoneg = true;
hw->phy.autoneg_advertised = 0x2f;
- hw->fc.original_type = e1000_fc_default;
- hw->fc.type = e1000_fc_default;
+ hw->fc.requested_mode = e1000_fc_default;
+ hw->fc.current_mode = e1000_fc_default;
adapter->itr_setting = IGB_DEFAULT_ITR;
adapter->itr = IGB_START_ITR;
@@ -2535,7 +2536,6 @@ static void igb_set_multi(struct net_device *netdev)
{
struct igb_adapter *adapter = netdev_priv(netdev);
struct e1000_hw *hw = &adapter->hw;
- struct e1000_mac_info *mac = &hw->mac;
struct dev_mc_list *mc_ptr;
u8 *mta_list = NULL;
u32 rctl;
@@ -2558,13 +2558,18 @@ static void igb_set_multi(struct net_device *netdev)
}
wr32(E1000_RCTL, rctl);
- if (netdev->mc_count) {
- mta_list = kzalloc(netdev->mc_count * 6, GFP_ATOMIC);
- if (!mta_list) {
- dev_err(&adapter->pdev->dev,
- "failed to allocate multicast filter list\n");
- return;
- }
+ if (!netdev->mc_count) {
+ /* nothing to program, so clear mc list */
+ igb_update_mc_addr_list(hw, NULL, 0);
+ igb_restore_vf_multicasts(adapter);
+ return;
+ }
+
+ mta_list = kzalloc(netdev->mc_count * 6, GFP_ATOMIC);
+ if (!mta_list) {
+ dev_err(&adapter->pdev->dev,
+ "failed to allocate multicast filter list\n");
+ return;
}
/* The shared function expects a packed array of only addresses. */
@@ -2576,14 +2581,9 @@ static void igb_set_multi(struct net_device *netdev)
memcpy(mta_list + (i*ETH_ALEN), mc_ptr->dmi_addr, ETH_ALEN);
mc_ptr = mc_ptr->next;
}
- igb_update_mc_addr_list(hw, mta_list, i,
- adapter->vfs_allocated_count + 1,
- mac->rar_entry_count);
-
- igb_set_mc_list_pools(adapter, i, mac->rar_entry_count);
- igb_restore_vf_multicasts(adapter);
-
+ igb_update_mc_addr_list(hw, mta_list, i);
kfree(mta_list);
+ igb_restore_vf_multicasts(adapter);
}
/* Need to wait a few seconds after link up to get diagnostic information from
@@ -2618,10 +2618,6 @@ static bool igb_has_link(struct igb_adapter *adapter)
link_active = true;
}
break;
- case e1000_media_type_fiber:
- ret_val = hw->mac.ops.check_for_link(hw);
- link_active = !!(rd32(E1000_STATUS) & E1000_STATUS_LU);
- break;
case e1000_media_type_internal_serdes:
ret_val = hw->mac.ops.check_for_link(hw);
link_active = hw->mac.serdes_has_link;
@@ -4542,6 +4538,20 @@ static inline void igb_rx_checksum_adv(struct igb_adapter *adapter,
adapter->hw_csum_good++;
}
+static inline u16 igb_get_hlen(struct igb_adapter *adapter,
+ union e1000_adv_rx_desc *rx_desc)
+{
+ /* HW will not DMA in data larger than the given buffer, even if it
+ * parses the (NFS, of course) header to be larger. In that case, it
+ * fills the header buffer and spills the rest into the page.
+ */
+ u16 hlen = (le16_to_cpu(rx_desc->wb.lower.lo_dword.hdr_info) &
+ E1000_RXDADV_HDRBUFLEN_MASK) >> E1000_RXDADV_HDRBUFLEN_SHIFT;
+ if (hlen > adapter->rx_ps_hdr_size)
+ hlen = adapter->rx_ps_hdr_size;
+ return hlen;
+}
+
static bool igb_clean_rx_irq_adv(struct igb_ring *rx_ring,
int *work_done, int budget)
{
@@ -4556,7 +4566,8 @@ static bool igb_clean_rx_irq_adv(struct igb_ring *rx_ring,
int cleaned_count = 0;
unsigned int total_bytes = 0, total_packets = 0;
unsigned int i;
- u32 length, hlen, staterr;
+ u32 staterr;
+ u16 length;
i = rx_ring->next_to_clean;
buffer_info = &rx_ring->buffer_info[i];
@@ -4593,17 +4604,8 @@ static bool igb_clean_rx_irq_adv(struct igb_ring *rx_ring,
goto send_up;
}
- /* HW will not DMA in data larger than the given buffer, even
- * if it parses the (NFS, of course) header to be larger. In
- * that case, it fills the header buffer and spills the rest
- * into the page.
- */
- hlen = (le16_to_cpu(rx_desc->wb.lower.lo_dword.hdr_info) &
- E1000_RXDADV_HDRBUFLEN_MASK) >> E1000_RXDADV_HDRBUFLEN_SHIFT;
- if (hlen > adapter->rx_ps_hdr_size)
- hlen = adapter->rx_ps_hdr_size;
-
- if (!skb_shinfo(skb)->nr_frags) {
+ if (buffer_info->dma) {
+ u16 hlen = igb_get_hlen(adapter, rx_desc);
pci_unmap_single(pdev, buffer_info->dma,
adapter->rx_ps_hdr_size,
PCI_DMA_FROMDEVICE);
@@ -5033,6 +5035,34 @@ static int igb_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
}
}
+s32 igb_read_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value)
+{
+ struct igb_adapter *adapter = hw->back;
+ u16 cap_offset;
+
+ cap_offset = pci_find_capability(adapter->pdev, PCI_CAP_ID_EXP);
+ if (!cap_offset)
+ return -E1000_ERR_CONFIG;
+
+ pci_read_config_word(adapter->pdev, cap_offset + reg, value);
+
+ return 0;
+}
+
+s32 igb_write_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value)
+{
+ struct igb_adapter *adapter = hw->back;
+ u16 cap_offset;
+
+ cap_offset = pci_find_capability(adapter->pdev, PCI_CAP_ID_EXP);
+ if (!cap_offset)
+ return -E1000_ERR_CONFIG;
+
+ pci_write_config_word(adapter->pdev, cap_offset + reg, *value);
+
+ return 0;
+}
+
static void igb_vlan_rx_register(struct net_device *netdev,
struct vlan_group *grp)
{
@@ -5136,14 +5166,6 @@ int igb_set_spd_dplx(struct igb_adapter *adapter, u16 spddplx)
mac->autoneg = 0;
- /* Fiber NICs only allow 1000 gbps Full duplex */
- if ((adapter->hw.phy.media_type == e1000_media_type_fiber) &&
- spddplx != (SPEED_1000 + DUPLEX_FULL)) {
- dev_err(&adapter->pdev->dev,
- "Unsupported Speed/Duplex configuration\n");
- return -EINVAL;
- }
-
switch (spddplx) {
case SPEED_10 + DUPLEX_HALF:
mac->forced_speed_duplex = ADVERTISE_10_HALF;
@@ -5452,19 +5474,6 @@ static void igb_io_resume(struct pci_dev *pdev)
igb_get_hw_control(adapter);
}
-static void igb_set_mc_list_pools(struct igb_adapter *adapter,
- int entry_count, u16 total_rar_filters)
-{
- struct e1000_hw *hw = &adapter->hw;
- int i = adapter->vfs_allocated_count + 1;
-
- if ((i + entry_count) < total_rar_filters)
- total_rar_filters = i + entry_count;
-
- for (; i < total_rar_filters; i++)
- igb_set_rah_pool(hw, adapter->vfs_allocated_count, i);
-}
-
static int igb_set_vf_mac(struct igb_adapter *adapter,
int vf, unsigned char *mac_addr)
{
diff --git a/drivers/net/igbvf/netdev.c b/drivers/net/igbvf/netdev.c
index 2bc9d63027d..3f03c42ece9 100644
--- a/drivers/net/igbvf/netdev.c
+++ b/drivers/net/igbvf/netdev.c
@@ -149,7 +149,6 @@ static void igbvf_alloc_rx_buffers(struct igbvf_ring *rx_ring,
bufsz = adapter->rx_ps_hdr_size;
else
bufsz = adapter->rx_buffer_len;
- bufsz += NET_IP_ALIGN;
while (cleaned_count--) {
rx_desc = IGBVF_RX_DESC_ADV(*rx_ring, i);
@@ -173,7 +172,7 @@ static void igbvf_alloc_rx_buffers(struct igbvf_ring *rx_ring,
}
if (!buffer_info->skb) {
- skb = netdev_alloc_skb(netdev, bufsz);
+ skb = netdev_alloc_skb(netdev, bufsz + NET_IP_ALIGN);
if (!skb) {
adapter->alloc_rx_buff_failed++;
goto no_buffers;
@@ -286,7 +285,7 @@ static bool igbvf_clean_rx_irq(struct igbvf_adapter *adapter,
if (!skb_shinfo(skb)->nr_frags) {
pci_unmap_single(pdev, buffer_info->dma,
- adapter->rx_ps_hdr_size + NET_IP_ALIGN,
+ adapter->rx_ps_hdr_size,
PCI_DMA_FROMDEVICE);
skb_put(skb, hlen);
}
@@ -2512,6 +2511,9 @@ static pci_ers_result_t igbvf_io_error_detected(struct pci_dev *pdev,
netif_device_detach(netdev);
+ if (state == pci_channel_io_perm_failure)
+ return PCI_ERS_RESULT_DISCONNECT;
+
if (netif_running(netdev))
igbvf_down(adapter);
pci_disable_device(pdev);
diff --git a/drivers/net/ioc3-eth.c b/drivers/net/ioc3-eth.c
index e3cfefab670..8ec15ab8c8c 100644
--- a/drivers/net/ioc3-eth.c
+++ b/drivers/net/ioc3-eth.c
@@ -1515,7 +1515,7 @@ static int ioc3_start_xmit(struct sk_buff *skb, struct net_device *dev)
spin_unlock_irq(&ip->ioc3_lock);
- return 0;
+ return NETDEV_TX_OK;
}
static void ioc3_timeout(struct net_device *dev)
diff --git a/drivers/net/irda/ali-ircc.c b/drivers/net/irda/ali-ircc.c
index ad179558002..f0d0cea6e32 100644
--- a/drivers/net/irda/ali-ircc.c
+++ b/drivers/net/irda/ali-ircc.c
@@ -1466,7 +1466,7 @@ static int ali_ircc_fir_hard_xmit(struct sk_buff *skb, struct net_device *dev)
dev->trans_start = jiffies;
spin_unlock_irqrestore(&self->lock, flags);
dev_kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
} else
self->new_speed = speed;
}
@@ -1577,7 +1577,7 @@ static int ali_ircc_fir_hard_xmit(struct sk_buff *skb, struct net_device *dev)
dev_kfree_skb(skb);
IRDA_DEBUG(1, "%s(), ----------------- End ------------------\n", __func__ );
- return 0;
+ return NETDEV_TX_OK;
}
@@ -1966,10 +1966,10 @@ static int ali_ircc_sir_hard_xmit(struct sk_buff *skb, struct net_device *dev)
IRDA_DEBUG(2, "%s(), ---------------- Start ----------------\n", __func__ );
- IRDA_ASSERT(dev != NULL, return 0;);
+ IRDA_ASSERT(dev != NULL, return NETDEV_TX_OK;);
self = netdev_priv(dev);
- IRDA_ASSERT(self != NULL, return 0;);
+ IRDA_ASSERT(self != NULL, return NETDEV_TX_OK;);
iobase = self->io.sir_base;
@@ -1991,7 +1991,7 @@ static int ali_ircc_sir_hard_xmit(struct sk_buff *skb, struct net_device *dev)
dev->trans_start = jiffies;
spin_unlock_irqrestore(&self->lock, flags);
dev_kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
} else
self->new_speed = speed;
}
@@ -2015,7 +2015,7 @@ static int ali_ircc_sir_hard_xmit(struct sk_buff *skb, struct net_device *dev)
IRDA_DEBUG(2, "%s(), ----------------- End ------------------\n", __func__ );
- return 0;
+ return NETDEV_TX_OK;
}
diff --git a/drivers/net/irda/au1k_ir.c b/drivers/net/irda/au1k_ir.c
index c4361d46659..22baf65e156 100644
--- a/drivers/net/irda/au1k_ir.c
+++ b/drivers/net/irda/au1k_ir.c
@@ -502,7 +502,7 @@ static int au1k_irda_hard_xmit(struct sk_buff *skb, struct net_device *dev)
aup->newspeed = 0;
}
dev_kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
}
ptxd = aup->tx_ring[aup->tx_head];
@@ -555,7 +555,7 @@ static int au1k_irda_hard_xmit(struct sk_buff *skb, struct net_device *dev)
dev_kfree_skb(skb);
aup->tx_head = (aup->tx_head + 1) & (NUM_IR_DESC - 1);
dev->trans_start = jiffies;
- return 0;
+ return NETDEV_TX_OK;
}
diff --git a/drivers/net/irda/donauboe.c b/drivers/net/irda/donauboe.c
index 9a0346e751a..e4e905698dc 100644
--- a/drivers/net/irda/donauboe.c
+++ b/drivers/net/irda/donauboe.c
@@ -981,7 +981,7 @@ toshoboe_hard_xmit (struct sk_buff *skb, struct net_device *dev)
self = netdev_priv(dev);
- IRDA_ASSERT (self != NULL, return 0; );
+ IRDA_ASSERT (self != NULL, return NETDEV_TX_OK; );
IRDA_DEBUG (1, "%s.tx:%x(%x)%x\n", __func__
,skb->len,self->txpending,INB (OBOE_ENABLEH));
@@ -1021,7 +1021,7 @@ toshoboe_hard_xmit (struct sk_buff *skb, struct net_device *dev)
{
spin_unlock_irqrestore(&self->spinlock, flags);
dev_kfree_skb (skb);
- return 0;
+ return NETDEV_TX_OK;
}
/* True packet, go on, but */
/* do not accept anything before change speed execution */
@@ -1036,7 +1036,7 @@ toshoboe_hard_xmit (struct sk_buff *skb, struct net_device *dev)
toshoboe_setbaud (self);
spin_unlock_irqrestore(&self->spinlock, flags);
dev_kfree_skb (skb);
- return 0;
+ return NETDEV_TX_OK;
}
}
@@ -1143,7 +1143,7 @@ dumpbufs(skb->data,skb->len,'>');
spin_unlock_irqrestore(&self->spinlock, flags);
dev_kfree_skb (skb);
- return 0;
+ return NETDEV_TX_OK;
}
/*interrupt handler */
diff --git a/drivers/net/irda/irda-usb.c b/drivers/net/irda/irda-usb.c
index 0c0831c03f6..6a1aa7a40fe 100644
--- a/drivers/net/irda/irda-usb.c
+++ b/drivers/net/irda/irda-usb.c
@@ -534,7 +534,7 @@ static int irda_usb_hard_xmit(struct sk_buff *skb, struct net_device *netdev)
}
spin_unlock_irqrestore(&self->lock, flags);
- return 0;
+ return NETDEV_TX_OK;
drop:
/* Drop silently the skb and exit */
diff --git a/drivers/net/irda/nsc-ircc.c b/drivers/net/irda/nsc-ircc.c
index 45fd9c1eb34..51ca89c9a0b 100644
--- a/drivers/net/irda/nsc-ircc.c
+++ b/drivers/net/irda/nsc-ircc.c
@@ -1365,7 +1365,7 @@ static int nsc_ircc_hard_xmit_sir(struct sk_buff *skb, struct net_device *dev)
self = netdev_priv(dev);
- IRDA_ASSERT(self != NULL, return 0;);
+ IRDA_ASSERT(self != NULL, return NETDEV_TX_OK;);
iobase = self->io.fir_base;
@@ -1397,7 +1397,7 @@ static int nsc_ircc_hard_xmit_sir(struct sk_buff *skb, struct net_device *dev)
dev->trans_start = jiffies;
spin_unlock_irqrestore(&self->lock, flags);
dev_kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
} else
self->new_speed = speed;
}
@@ -1424,7 +1424,7 @@ static int nsc_ircc_hard_xmit_sir(struct sk_buff *skb, struct net_device *dev)
dev_kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
}
static int nsc_ircc_hard_xmit_fir(struct sk_buff *skb, struct net_device *dev)
@@ -1467,7 +1467,7 @@ static int nsc_ircc_hard_xmit_fir(struct sk_buff *skb, struct net_device *dev)
dev->trans_start = jiffies;
spin_unlock_irqrestore(&self->lock, flags);
dev_kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
} else {
/* Change speed after current frame */
self->new_speed = speed;
@@ -1554,7 +1554,7 @@ static int nsc_ircc_hard_xmit_fir(struct sk_buff *skb, struct net_device *dev)
spin_unlock_irqrestore(&self->lock, flags);
dev_kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
}
/*
diff --git a/drivers/net/irda/pxaficp_ir.c b/drivers/net/irda/pxaficp_ir.c
index 3376a4f39e0..e76a083f901 100644
--- a/drivers/net/irda/pxaficp_ir.c
+++ b/drivers/net/irda/pxaficp_ir.c
@@ -504,7 +504,7 @@ static int pxa_irda_hard_xmit(struct sk_buff *skb, struct net_device *dev)
pxa_irda_set_speed(si, speed);
}
dev_kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
}
netif_stop_queue(dev);
@@ -539,7 +539,7 @@ static int pxa_irda_hard_xmit(struct sk_buff *skb, struct net_device *dev)
dev_kfree_skb(skb);
dev->trans_start = jiffies;
- return 0;
+ return NETDEV_TX_OK;
}
static int pxa_irda_ioctl(struct net_device *dev, struct ifreq *ifreq, int cmd)
diff --git a/drivers/net/irda/sa1100_ir.c b/drivers/net/irda/sa1100_ir.c
index 2aeb2e6aec1..70e6acc597b 100644
--- a/drivers/net/irda/sa1100_ir.c
+++ b/drivers/net/irda/sa1100_ir.c
@@ -667,7 +667,7 @@ static int sa1100_irda_hard_xmit(struct sk_buff *skb, struct net_device *dev)
sa1100_irda_set_speed(si, speed);
}
dev_kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
}
if (!IS_FIR(si)) {
@@ -715,7 +715,7 @@ static int sa1100_irda_hard_xmit(struct sk_buff *skb, struct net_device *dev)
dev->trans_start = jiffies;
- return 0;
+ return NETDEV_TX_OK;
}
static int
diff --git a/drivers/net/irda/sir_dev.c b/drivers/net/irda/sir_dev.c
index fd0796c3db3..71dce20e62b 100644
--- a/drivers/net/irda/sir_dev.c
+++ b/drivers/net/irda/sir_dev.c
@@ -590,7 +590,7 @@ static int sirdev_hard_xmit(struct sk_buff *skb, struct net_device *ndev)
int err;
s32 speed;
- IRDA_ASSERT(dev != NULL, return 0;);
+ IRDA_ASSERT(dev != NULL, return NETDEV_TX_OK;);
netif_stop_queue(ndev);
@@ -621,7 +621,7 @@ static int sirdev_hard_xmit(struct sk_buff *skb, struct net_device *ndev)
*/
dev_kfree_skb_any(skb);
- return 0;
+ return NETDEV_TX_OK;
} else
dev->new_speed = speed;
}
@@ -668,7 +668,7 @@ static int sirdev_hard_xmit(struct sk_buff *skb, struct net_device *ndev)
}
spin_unlock_irqrestore(&dev->tx_lock, flags);
- return 0;
+ return NETDEV_TX_OK;
}
/* called from network layer with rtnl hold */
diff --git a/drivers/net/irda/smsc-ircc2.c b/drivers/net/irda/smsc-ircc2.c
index d0797adb5f8..15f8a7f8160 100644
--- a/drivers/net/irda/smsc-ircc2.c
+++ b/drivers/net/irda/smsc-ircc2.c
@@ -886,10 +886,10 @@ static int smsc_ircc_hard_xmit_sir(struct sk_buff *skb, struct net_device *dev)
IRDA_DEBUG(1, "%s\n", __func__);
- IRDA_ASSERT(dev != NULL, return 0;);
+ IRDA_ASSERT(dev != NULL, return NETDEV_TX_OK;);
self = netdev_priv(dev);
- IRDA_ASSERT(self != NULL, return 0;);
+ IRDA_ASSERT(self != NULL, return NETDEV_TX_OK;);
netif_stop_queue(dev);
@@ -914,7 +914,7 @@ static int smsc_ircc_hard_xmit_sir(struct sk_buff *skb, struct net_device *dev)
smsc_ircc_change_speed(self, speed);
spin_unlock_irqrestore(&self->lock, flags);
dev_kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
}
self->new_speed = speed;
}
@@ -935,7 +935,7 @@ static int smsc_ircc_hard_xmit_sir(struct sk_buff *skb, struct net_device *dev)
dev_kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
}
/*
@@ -1190,9 +1190,9 @@ static int smsc_ircc_hard_xmit_fir(struct sk_buff *skb, struct net_device *dev)
s32 speed;
int mtt;
- IRDA_ASSERT(dev != NULL, return 0;);
+ IRDA_ASSERT(dev != NULL, return NETDEV_TX_OK;);
self = netdev_priv(dev);
- IRDA_ASSERT(self != NULL, return 0;);
+ IRDA_ASSERT(self != NULL, return NETDEV_TX_OK;);
netif_stop_queue(dev);
@@ -1210,7 +1210,7 @@ static int smsc_ircc_hard_xmit_fir(struct sk_buff *skb, struct net_device *dev)
smsc_ircc_change_speed(self, speed);
spin_unlock_irqrestore(&self->lock, flags);
dev_kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
}
self->new_speed = speed;
@@ -1242,7 +1242,7 @@ static int smsc_ircc_hard_xmit_fir(struct sk_buff *skb, struct net_device *dev)
spin_unlock_irqrestore(&self->lock, flags);
dev_kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
}
/*
diff --git a/drivers/net/irda/stir4200.c b/drivers/net/irda/stir4200.c
index 8e5e45caf2f..c475b23091b 100644
--- a/drivers/net/irda/stir4200.c
+++ b/drivers/net/irda/stir4200.c
@@ -578,7 +578,7 @@ static int stir_hard_xmit(struct sk_buff *skb, struct net_device *netdev)
dev_kfree_skb(skb);
}
- return 0;
+ return NETDEV_TX_OK;
}
/*
diff --git a/drivers/net/irda/via-ircc.c b/drivers/net/irda/via-ircc.c
index 864798502ff..36a60748447 100644
--- a/drivers/net/irda/via-ircc.c
+++ b/drivers/net/irda/via-ircc.c
@@ -832,7 +832,7 @@ static int via_ircc_hard_xmit_sir(struct sk_buff *skb,
__u32 speed;
self = netdev_priv(dev);
- IRDA_ASSERT(self != NULL, return 0;);
+ IRDA_ASSERT(self != NULL, return NETDEV_TX_OK;);
iobase = self->io.fir_base;
netif_stop_queue(dev);
@@ -844,7 +844,7 @@ static int via_ircc_hard_xmit_sir(struct sk_buff *skb,
via_ircc_change_speed(self, speed);
dev->trans_start = jiffies;
dev_kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
} else
self->new_speed = speed;
}
@@ -892,7 +892,7 @@ static int via_ircc_hard_xmit_sir(struct sk_buff *skb,
dev->trans_start = jiffies;
spin_unlock_irqrestore(&self->lock, flags);
dev_kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
}
static int via_ircc_hard_xmit_fir(struct sk_buff *skb,
@@ -907,7 +907,7 @@ static int via_ircc_hard_xmit_fir(struct sk_buff *skb,
iobase = self->io.fir_base;
if (self->st_fifo.len)
- return 0;
+ return NETDEV_TX_OK;
if (self->chip_id == 0x3076)
iodelay(1500);
else
@@ -919,7 +919,7 @@ static int via_ircc_hard_xmit_fir(struct sk_buff *skb,
via_ircc_change_speed(self, speed);
dev->trans_start = jiffies;
dev_kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
} else
self->new_speed = speed;
}
@@ -940,7 +940,7 @@ static int via_ircc_hard_xmit_fir(struct sk_buff *skb,
dev->trans_start = jiffies;
dev_kfree_skb(skb);
spin_unlock_irqrestore(&self->lock, flags);
- return 0;
+ return NETDEV_TX_OK;
}
diff --git a/drivers/net/irda/vlsi_ir.c b/drivers/net/irda/vlsi_ir.c
index ac0e4b6b6b6..08e26f1297b 100644
--- a/drivers/net/irda/vlsi_ir.c
+++ b/drivers/net/irda/vlsi_ir.c
@@ -915,7 +915,7 @@ static int vlsi_hard_start_xmit(struct sk_buff *skb, struct net_device *ndev)
*/
spin_unlock_irqrestore(&idev->lock, flags);
dev_kfree_skb_any(skb);
- return 0;
+ return NETDEV_TX_OK;
}
/* sanity checks - simply drop the packet */
@@ -1044,7 +1044,7 @@ static int vlsi_hard_start_xmit(struct sk_buff *skb, struct net_device *ndev)
}
spin_unlock_irqrestore(&idev->lock, flags);
- return 0;
+ return NETDEV_TX_OK;
drop_unlock:
spin_unlock_irqrestore(&idev->lock, flags);
@@ -1058,7 +1058,7 @@ drop:
* packet for later retry of transmission - which isn't exactly
* what we want after we've just called dev_kfree_skb_any ;-)
*/
- return 0;
+ return NETDEV_TX_OK;
}
static void vlsi_tx_interrupt(struct net_device *ndev)
diff --git a/drivers/net/irda/w83977af_ir.c b/drivers/net/irda/w83977af_ir.c
index fe4f2b2bff9..462bc437080 100644
--- a/drivers/net/irda/w83977af_ir.c
+++ b/drivers/net/irda/w83977af_ir.c
@@ -516,7 +516,7 @@ static int w83977af_hard_xmit(struct sk_buff *skb, struct net_device *dev)
w83977af_change_speed(self, speed);
dev->trans_start = jiffies;
dev_kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
} else
self->new_speed = speed;
}
@@ -576,7 +576,7 @@ static int w83977af_hard_xmit(struct sk_buff *skb, struct net_device *dev)
/* Restore set register */
outb(set, iobase+SSR);
- return 0;
+ return NETDEV_TX_OK;
}
/*
diff --git a/drivers/net/isa-skeleton.c b/drivers/net/isa-skeleton.c
index d12377b8435..9706e64e367 100644
--- a/drivers/net/isa-skeleton.c
+++ b/drivers/net/isa-skeleton.c
@@ -468,7 +468,7 @@ static int net_send_packet(struct sk_buff *skb, struct net_device *dev)
dev_kfree_skb (skb);
#endif
- return 0;
+ return NETDEV_TX_OK;
}
#if TX_RING
diff --git a/drivers/net/iseries_veth.c b/drivers/net/iseries_veth.c
index e44215cb188..e36e951cbc6 100644
--- a/drivers/net/iseries_veth.c
+++ b/drivers/net/iseries_veth.c
@@ -1205,7 +1205,7 @@ static int veth_start_xmit(struct sk_buff *skb, struct net_device *dev)
if ( ! ((1 << rlp) & port->lpar_map) ) {
dev_kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
}
lpmask = 1 << rlp;
@@ -1217,7 +1217,7 @@ static int veth_start_xmit(struct sk_buff *skb, struct net_device *dev)
dev_kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
}
/* You must hold the connection's lock when you call this function. */
diff --git a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c
index 9c897cf86b9..fad08ce8a6c 100644
--- a/drivers/net/ixgb/ixgb_main.c
+++ b/drivers/net/ixgb/ixgb_main.c
@@ -1459,7 +1459,7 @@ ixgb_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
if (skb->len <= 0) {
dev_kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
}
if (unlikely(ixgb_maybe_stop_tx(netdev, &adapter->tx_ring,
@@ -2227,6 +2227,11 @@ static pci_ers_result_t ixgb_io_error_detected(struct pci_dev *pdev,
struct net_device *netdev = pci_get_drvdata(pdev);
struct ixgb_adapter *adapter = netdev_priv(netdev);
+ netif_device_detach(netdev);
+
+ if (state == pci_channel_io_perm_failure)
+ return PCI_ERS_RESULT_DISCONNECT;
+
if (netif_running(netdev))
ixgb_down(adapter, true);
diff --git a/drivers/net/ixgbe/ixgbe.h b/drivers/net/ixgbe/ixgbe.h
index 2c4dc8221dc..8f1f8bab0fd 100644
--- a/drivers/net/ixgbe/ixgbe.h
+++ b/drivers/net/ixgbe/ixgbe.h
@@ -233,10 +233,6 @@ struct ixgbe_q_vector {
#define IXGBE_TX_CTXTDESC_ADV(R, i) \
(&(((struct ixgbe_adv_tx_context_desc *)((R).desc))[i]))
-#define IXGBE_GET_DESC(R, i, type) (&(((struct type *)((R).desc))[i]))
-#define IXGBE_TX_DESC(R, i) IXGBE_GET_DESC(R, i, ixgbe_legacy_tx_desc)
-#define IXGBE_RX_DESC(R, i) IXGBE_GET_DESC(R, i, ixgbe_legacy_rx_desc)
-
#define IXGBE_MAX_JUMBO_FRAME_SIZE 16128
#ifdef IXGBE_FCOE
/* Use 3K as the baby jumbo frame size for FCoE */
diff --git a/drivers/net/ixgbe/ixgbe_82598.c b/drivers/net/ixgbe/ixgbe_82598.c
index 522c03bc1da..1c227b0777a 100644
--- a/drivers/net/ixgbe/ixgbe_82598.c
+++ b/drivers/net/ixgbe/ixgbe_82598.c
@@ -334,6 +334,7 @@ static enum ixgbe_media_type ixgbe_get_media_type_82598(struct ixgbe_hw *hw)
media_type = ixgbe_media_type_fiber;
break;
case IXGBE_DEV_ID_82598AT:
+ case IXGBE_DEV_ID_82598AT2:
media_type = ixgbe_media_type_copper;
break;
default:
diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c
index dff8dfac7ed..dd221bba54d 100644
--- a/drivers/net/ixgbe/ixgbe_ethtool.c
+++ b/drivers/net/ixgbe/ixgbe_ethtool.c
@@ -1440,7 +1440,7 @@ static int ixgbe_setup_desc_rings(struct ixgbe_adapter *adapter)
goto err_nomem;
}
- tx_ring->size = tx_ring->count * sizeof(struct ixgbe_legacy_tx_desc);
+ tx_ring->size = tx_ring->count * sizeof(union ixgbe_adv_tx_desc);
tx_ring->size = ALIGN(tx_ring->size, 4096);
if (!(tx_ring->desc = pci_alloc_consistent(pdev, tx_ring->size,
&tx_ring->dma))) {
@@ -1454,7 +1454,7 @@ static int ixgbe_setup_desc_rings(struct ixgbe_adapter *adapter)
IXGBE_WRITE_REG(&adapter->hw, IXGBE_TDBAH(0),
((u64) tx_ring->dma >> 32));
IXGBE_WRITE_REG(&adapter->hw, IXGBE_TDLEN(0),
- tx_ring->count * sizeof(struct ixgbe_legacy_tx_desc));
+ tx_ring->count * sizeof(union ixgbe_adv_tx_desc));
IXGBE_WRITE_REG(&adapter->hw, IXGBE_TDH(0), 0);
IXGBE_WRITE_REG(&adapter->hw, IXGBE_TDT(0), 0);
@@ -1472,7 +1472,7 @@ static int ixgbe_setup_desc_rings(struct ixgbe_adapter *adapter)
IXGBE_WRITE_REG(&adapter->hw, IXGBE_TXDCTL(0), reg_data);
for (i = 0; i < tx_ring->count; i++) {
- struct ixgbe_legacy_tx_desc *desc = IXGBE_TX_DESC(*tx_ring, i);
+ union ixgbe_adv_tx_desc *desc = IXGBE_TX_DESC_ADV(*tx_ring, i);
struct sk_buff *skb;
unsigned int size = 1024;
@@ -1486,13 +1486,18 @@ static int ixgbe_setup_desc_rings(struct ixgbe_adapter *adapter)
tx_ring->tx_buffer_info[i].length = skb->len;
tx_ring->tx_buffer_info[i].dma =
pci_map_single(pdev, skb->data, skb->len,
- PCI_DMA_TODEVICE);
- desc->buffer_addr = cpu_to_le64(tx_ring->tx_buffer_info[i].dma);
- desc->lower.data = cpu_to_le32(skb->len);
- desc->lower.data |= cpu_to_le32(IXGBE_TXD_CMD_EOP |
- IXGBE_TXD_CMD_IFCS |
- IXGBE_TXD_CMD_RS);
- desc->upper.data = 0;
+ PCI_DMA_TODEVICE);
+ desc->read.buffer_addr =
+ cpu_to_le64(tx_ring->tx_buffer_info[i].dma);
+ desc->read.cmd_type_len = cpu_to_le32(skb->len);
+ desc->read.cmd_type_len |= cpu_to_le32(IXGBE_TXD_CMD_EOP |
+ IXGBE_TXD_CMD_IFCS |
+ IXGBE_TXD_CMD_RS);
+ desc->read.olinfo_status = 0;
+ if (adapter->hw.mac.type == ixgbe_mac_82599EB)
+ desc->read.olinfo_status |=
+ (skb->len << IXGBE_ADVTXD_PAYLEN_SHIFT);
+
}
/* Setup Rx Descriptor ring and Rx buffers */
@@ -1508,7 +1513,7 @@ static int ixgbe_setup_desc_rings(struct ixgbe_adapter *adapter)
goto err_nomem;
}
- rx_ring->size = rx_ring->count * sizeof(struct ixgbe_legacy_rx_desc);
+ rx_ring->size = rx_ring->count * sizeof(union ixgbe_adv_rx_desc);
rx_ring->size = ALIGN(rx_ring->size, 4096);
if (!(rx_ring->desc = pci_alloc_consistent(pdev, rx_ring->size,
&rx_ring->dma))) {
@@ -1566,8 +1571,8 @@ static int ixgbe_setup_desc_rings(struct ixgbe_adapter *adapter)
IXGBE_WRITE_REG(&adapter->hw, IXGBE_RXCTRL, rctl);
for (i = 0; i < rx_ring->count; i++) {
- struct ixgbe_legacy_rx_desc *rx_desc =
- IXGBE_RX_DESC(*rx_ring, i);
+ union ixgbe_adv_rx_desc *rx_desc =
+ IXGBE_RX_DESC_ADV(*rx_ring, i);
struct sk_buff *skb;
skb = alloc_skb(IXGBE_RXBUFFER_2048 + NET_IP_ALIGN, GFP_KERNEL);
@@ -1580,7 +1585,7 @@ static int ixgbe_setup_desc_rings(struct ixgbe_adapter *adapter)
rx_ring->rx_buffer_info[i].dma =
pci_map_single(pdev, skb->data, IXGBE_RXBUFFER_2048,
PCI_DMA_FROMDEVICE);
- rx_desc->buffer_addr =
+ rx_desc->read.pkt_addr =
cpu_to_le64(rx_ring->rx_buffer_info[i].dma);
memset(skb->data, 0x00, skb->len);
}
diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c
index 77b0381a2b5..8a8518dd694 100644
--- a/drivers/net/ixgbe/ixgbe_main.c
+++ b/drivers/net/ixgbe/ixgbe_main.c
@@ -49,7 +49,7 @@ char ixgbe_driver_name[] = "ixgbe";
static const char ixgbe_driver_string[] =
"Intel(R) 10 Gigabit PCI Express Network Driver";
-#define DRV_VERSION "2.0.34-k2"
+#define DRV_VERSION "2.0.37-k2"
const char ixgbe_driver_version[] = DRV_VERSION;
static char ixgbe_copyright[] = "Copyright (c) 1999-2009 Intel Corporation.";
@@ -75,6 +75,8 @@ static struct pci_device_id ixgbe_pci_tbl[] = {
board_82598 },
{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598AT),
board_82598 },
+ {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598AT2),
+ board_82598 },
{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598EB_CX4),
board_82598 },
{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598_CX4_DUAL_PORT),
@@ -4634,13 +4636,13 @@ static void ixgbe_watchdog_task(struct work_struct *work)
if (hw->mac.type == ixgbe_mac_82599EB) {
u32 mflcn = IXGBE_READ_REG(hw, IXGBE_MFLCN);
u32 fccfg = IXGBE_READ_REG(hw, IXGBE_FCCFG);
- flow_rx = (mflcn & IXGBE_MFLCN_RFCE);
- flow_tx = (fccfg & IXGBE_FCCFG_TFCE_802_3X);
+ flow_rx = !!(mflcn & IXGBE_MFLCN_RFCE);
+ flow_tx = !!(fccfg & IXGBE_FCCFG_TFCE_802_3X);
} else {
u32 frctl = IXGBE_READ_REG(hw, IXGBE_FCTRL);
u32 rmcs = IXGBE_READ_REG(hw, IXGBE_RMCS);
- flow_rx = (frctl & IXGBE_FCTRL_RFCE);
- flow_tx = (rmcs & IXGBE_RMCS_TFCE_802_3X);
+ flow_rx = !!(frctl & IXGBE_FCTRL_RFCE);
+ flow_tx = !!(rmcs & IXGBE_RMCS_TFCE_802_3X);
}
printk(KERN_INFO "ixgbe: %s NIC Link is Up %s, "
@@ -5100,7 +5102,7 @@ static u16 ixgbe_select_queue(struct net_device *dev, struct sk_buff *skb)
return smp_processor_id();
if (adapter->flags & IXGBE_FLAG_DCB_ENABLED)
- return 0; /* All traffic should default to class 0 */
+ return (skb->vlan_tci & IXGBE_TX_FLAGS_VLAN_PRIO_MASK) >> 13;
return skb_tx_hash(dev, skb);
}
diff --git a/drivers/net/ixgbe/ixgbe_type.h b/drivers/net/ixgbe/ixgbe_type.h
index be90eb4575f..f0f3406ef00 100644
--- a/drivers/net/ixgbe/ixgbe_type.h
+++ b/drivers/net/ixgbe/ixgbe_type.h
@@ -42,6 +42,7 @@
#define IXGBE_DEV_ID_82598AF_SINGLE_PORT 0x10C7
#define IXGBE_DEV_ID_82598EB_SFP_LOM 0x10DB
#define IXGBE_DEV_ID_82598AT 0x10C8
+#define IXGBE_DEV_ID_82598AT2 0x150B
#define IXGBE_DEV_ID_82598EB_CX4 0x10DD
#define IXGBE_DEV_ID_82598_CX4_DUAL_PORT 0x10EC
#define IXGBE_DEV_ID_82598_DA_DUAL_PORT 0x10F1
@@ -1901,27 +1902,6 @@ enum ixgbe_fdir_pballoc_type {
#define IXGBE_FDIR_INIT_DONE_POLL 10
#define IXGBE_FDIRCMD_CMD_POLL 10
-/* Transmit Descriptor - Legacy */
-struct ixgbe_legacy_tx_desc {
- u64 buffer_addr; /* Address of the descriptor's data buffer */
- union {
- __le32 data;
- struct {
- __le16 length; /* Data buffer length */
- u8 cso; /* Checksum offset */
- u8 cmd; /* Descriptor control */
- } flags;
- } lower;
- union {
- __le32 data;
- struct {
- u8 status; /* Descriptor status */
- u8 css; /* Checksum start */
- __le16 vlan;
- } fields;
- } upper;
-};
-
/* Transmit Descriptor - Advanced */
union ixgbe_adv_tx_desc {
struct {
@@ -1936,16 +1916,6 @@ union ixgbe_adv_tx_desc {
} wb;
};
-/* Receive Descriptor - Legacy */
-struct ixgbe_legacy_rx_desc {
- __le64 buffer_addr; /* Address of the descriptor's data buffer */
- __le16 length; /* Length of data DMAed into data buffer */
- __le16 csum; /* Packet checksum */
- u8 status; /* Descriptor status */
- u8 errors; /* Descriptor Errors */
- __le16 vlan;
-};
-
/* Receive Descriptor - Advanced */
union ixgbe_adv_rx_desc {
struct {
diff --git a/drivers/net/ixp2000/ixpdev.c b/drivers/net/ixp2000/ixpdev.c
index 2a0174b62e9..588b44d944c 100644
--- a/drivers/net/ixp2000/ixpdev.c
+++ b/drivers/net/ixp2000/ixpdev.c
@@ -45,7 +45,7 @@ static int ixpdev_xmit(struct sk_buff *skb, struct net_device *dev)
if (unlikely(skb->len > PAGE_SIZE)) {
/* @@@ Count drops. */
dev_kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
}
entry = tx_pointer;
@@ -69,7 +69,7 @@ static int ixpdev_xmit(struct sk_buff *skb, struct net_device *dev)
netif_stop_queue(dev);
local_irq_enable();
- return 0;
+ return NETDEV_TX_OK;
}
diff --git a/drivers/net/jazzsonic.c b/drivers/net/jazzsonic.c
index 2f286091394..6e5b3f30527 100644
--- a/drivers/net/jazzsonic.c
+++ b/drivers/net/jazzsonic.c
@@ -108,7 +108,7 @@ static const struct net_device_ops sonic_netdev_ops = {
.ndo_set_mac_address = eth_mac_addr,
};
-static int __init sonic_probe1(struct net_device *dev)
+static int __devinit sonic_probe1(struct net_device *dev)
{
static unsigned version_printed;
unsigned int silicon_revision;
@@ -203,7 +203,7 @@ static int __init sonic_probe1(struct net_device *dev)
return 0;
out:
- release_region(dev->base_addr, SONIC_MEM_SIZE);
+ release_mem_region(dev->base_addr, SONIC_MEM_SIZE);
return err;
}
@@ -211,7 +211,7 @@ out:
* Probe for a SONIC ethernet controller on a Mips Jazz board.
* Actually probing is superfluous but we're paranoid.
*/
-static int __init jazz_sonic_probe(struct platform_device *pdev)
+static int __devinit jazz_sonic_probe(struct platform_device *pdev)
{
struct net_device *dev;
struct sonic_local *lp;
@@ -247,7 +247,7 @@ static int __init jazz_sonic_probe(struct platform_device *pdev)
return 0;
out1:
- release_region(dev->base_addr, SONIC_MEM_SIZE);
+ release_mem_region(dev->base_addr, SONIC_MEM_SIZE);
out:
free_netdev(dev);
@@ -269,7 +269,7 @@ static int __devexit jazz_sonic_device_remove (struct platform_device *pdev)
unregister_netdev(dev);
dma_free_coherent(lp->device, SIZEOF_SONIC_DESC * SONIC_BUS_SCALE(lp->dma_bitmode),
lp->descriptors, lp->descriptors_laddr);
- release_region (dev->base_addr, SONIC_MEM_SIZE);
+ release_mem_region(dev->base_addr, SONIC_MEM_SIZE);
free_netdev(dev);
return 0;
diff --git a/drivers/net/jme.c b/drivers/net/jme.c
index 1e3c63d67b9..e7068c7cd62 100644
--- a/drivers/net/jme.c
+++ b/drivers/net/jme.c
@@ -322,20 +322,6 @@ jme_stop_irq(struct jme_adapter *jme)
jwrite32f(jme, JME_IENC, INTR_ENABLE);
}
-static inline void
-jme_enable_shadow(struct jme_adapter *jme)
-{
- jwrite32(jme,
- JME_SHBA_LO,
- ((u32)jme->shadow_dma & ~((u32)0x1F)) | SHBA_POSTEN);
-}
-
-static inline void
-jme_disable_shadow(struct jme_adapter *jme)
-{
- jwrite32(jme, JME_SHBA_LO, 0x0);
-}
-
static u32
jme_linkstat_from_phy(struct jme_adapter *jme)
{
@@ -522,12 +508,8 @@ jme_setup_tx_resources(struct jme_adapter *jme)
&(txring->dmaalloc),
GFP_ATOMIC);
- if (!txring->alloc) {
- txring->desc = NULL;
- txring->dmaalloc = 0;
- txring->dma = 0;
- return -ENOMEM;
- }
+ if (!txring->alloc)
+ goto err_set_null;
/*
* 16 Bytes align
@@ -539,6 +521,11 @@ jme_setup_tx_resources(struct jme_adapter *jme)
atomic_set(&txring->next_to_clean, 0);
atomic_set(&txring->nr_free, jme->tx_ring_size);
+ txring->bufinf = kmalloc(sizeof(struct jme_buffer_info) *
+ jme->tx_ring_size, GFP_ATOMIC);
+ if (unlikely(!(txring->bufinf)))
+ goto err_free_txring;
+
/*
* Initialize Transmit Descriptors
*/
@@ -547,6 +534,20 @@ jme_setup_tx_resources(struct jme_adapter *jme)
sizeof(struct jme_buffer_info) * jme->tx_ring_size);
return 0;
+
+err_free_txring:
+ dma_free_coherent(&(jme->pdev->dev),
+ TX_RING_ALLOC_SIZE(jme->tx_ring_size),
+ txring->alloc,
+ txring->dmaalloc);
+
+err_set_null:
+ txring->desc = NULL;
+ txring->dmaalloc = 0;
+ txring->dma = 0;
+ txring->bufinf = NULL;
+
+ return -ENOMEM;
}
static void
@@ -554,19 +555,22 @@ jme_free_tx_resources(struct jme_adapter *jme)
{
int i;
struct jme_ring *txring = &(jme->txring[0]);
- struct jme_buffer_info *txbi = txring->bufinf;
+ struct jme_buffer_info *txbi;
if (txring->alloc) {
- for (i = 0 ; i < jme->tx_ring_size ; ++i) {
- txbi = txring->bufinf + i;
- if (txbi->skb) {
- dev_kfree_skb(txbi->skb);
- txbi->skb = NULL;
+ if (txring->bufinf) {
+ for (i = 0 ; i < jme->tx_ring_size ; ++i) {
+ txbi = txring->bufinf + i;
+ if (txbi->skb) {
+ dev_kfree_skb(txbi->skb);
+ txbi->skb = NULL;
+ }
+ txbi->mapping = 0;
+ txbi->len = 0;
+ txbi->nr_desc = 0;
+ txbi->start_xmit = 0;
}
- txbi->mapping = 0;
- txbi->len = 0;
- txbi->nr_desc = 0;
- txbi->start_xmit = 0;
+ kfree(txring->bufinf);
}
dma_free_coherent(&(jme->pdev->dev),
@@ -578,11 +582,11 @@ jme_free_tx_resources(struct jme_adapter *jme)
txring->desc = NULL;
txring->dmaalloc = 0;
txring->dma = 0;
+ txring->bufinf = NULL;
}
txring->next_to_use = 0;
atomic_set(&txring->next_to_clean, 0);
atomic_set(&txring->nr_free, 0);
-
}
static inline void
@@ -653,7 +657,7 @@ jme_disable_tx_engine(struct jme_adapter *jme)
static void
jme_set_clean_rxdesc(struct jme_adapter *jme, int i)
{
- struct jme_ring *rxring = jme->rxring;
+ struct jme_ring *rxring = &(jme->rxring[0]);
register struct rxdesc *rxdesc = rxring->desc;
struct jme_buffer_info *rxbi = rxring->bufinf;
rxdesc += i;
@@ -720,8 +724,11 @@ jme_free_rx_resources(struct jme_adapter *jme)
struct jme_ring *rxring = &(jme->rxring[0]);
if (rxring->alloc) {
- for (i = 0 ; i < jme->rx_ring_size ; ++i)
- jme_free_rx_buf(jme, i);
+ if (rxring->bufinf) {
+ for (i = 0 ; i < jme->rx_ring_size ; ++i)
+ jme_free_rx_buf(jme, i);
+ kfree(rxring->bufinf);
+ }
dma_free_coherent(&(jme->pdev->dev),
RX_RING_ALLOC_SIZE(jme->rx_ring_size),
@@ -731,6 +738,7 @@ jme_free_rx_resources(struct jme_adapter *jme)
rxring->desc = NULL;
rxring->dmaalloc = 0;
rxring->dma = 0;
+ rxring->bufinf = NULL;
}
rxring->next_to_use = 0;
atomic_set(&rxring->next_to_clean, 0);
@@ -746,12 +754,8 @@ jme_setup_rx_resources(struct jme_adapter *jme)
RX_RING_ALLOC_SIZE(jme->rx_ring_size),
&(rxring->dmaalloc),
GFP_ATOMIC);
- if (!rxring->alloc) {
- rxring->desc = NULL;
- rxring->dmaalloc = 0;
- rxring->dma = 0;
- return -ENOMEM;
- }
+ if (!rxring->alloc)
+ goto err_set_null;
/*
* 16 Bytes align
@@ -762,9 +766,16 @@ jme_setup_rx_resources(struct jme_adapter *jme)
rxring->next_to_use = 0;
atomic_set(&rxring->next_to_clean, 0);
+ rxring->bufinf = kmalloc(sizeof(struct jme_buffer_info) *
+ jme->rx_ring_size, GFP_ATOMIC);
+ if (unlikely(!(rxring->bufinf)))
+ goto err_free_rxring;
+
/*
* Initiallize Receive Descriptors
*/
+ memset(rxring->bufinf, 0,
+ sizeof(struct jme_buffer_info) * jme->rx_ring_size);
for (i = 0 ; i < jme->rx_ring_size ; ++i) {
if (unlikely(jme_make_new_rx_buf(jme, i))) {
jme_free_rx_resources(jme);
@@ -775,6 +786,19 @@ jme_setup_rx_resources(struct jme_adapter *jme)
}
return 0;
+
+err_free_rxring:
+ dma_free_coherent(&(jme->pdev->dev),
+ RX_RING_ALLOC_SIZE(jme->rx_ring_size),
+ rxring->alloc,
+ rxring->dmaalloc);
+err_set_null:
+ rxring->desc = NULL;
+ rxring->dmaalloc = 0;
+ rxring->dma = 0;
+ rxring->bufinf = NULL;
+
+ return -ENOMEM;
}
static inline void
@@ -790,9 +814,9 @@ jme_enable_rx_engine(struct jme_adapter *jme)
/*
* Setup RX DMA Bass Address
*/
- jwrite32(jme, JME_RXDBA_LO, (__u64)jme->rxring[0].dma & 0xFFFFFFFFUL);
+ jwrite32(jme, JME_RXDBA_LO, (__u64)(jme->rxring[0].dma) & 0xFFFFFFFFUL);
jwrite32(jme, JME_RXDBA_HI, (__u64)(jme->rxring[0].dma) >> 32);
- jwrite32(jme, JME_RXNDA, (__u64)jme->rxring[0].dma & 0xFFFFFFFFUL);
+ jwrite32(jme, JME_RXNDA, (__u64)(jme->rxring[0].dma) & 0xFFFFFFFFUL);
/*
* Setup RX Descriptor Count
@@ -856,27 +880,27 @@ jme_rxsum_ok(struct jme_adapter *jme, u16 flags)
if (!(flags & (RXWBFLAG_TCPON | RXWBFLAG_UDPON | RXWBFLAG_IPV4)))
return false;
- if (unlikely(!(flags & RXWBFLAG_MF) &&
- (flags & RXWBFLAG_TCPON) && !(flags & RXWBFLAG_TCPCS))) {
- msg_rx_err(jme, "TCP Checksum error.\n");
- goto out_sumerr;
+ if (unlikely((flags & (RXWBFLAG_MF | RXWBFLAG_TCPON | RXWBFLAG_TCPCS))
+ == RXWBFLAG_TCPON)) {
+ if (flags & RXWBFLAG_IPV4)
+ msg_rx_err(jme, "TCP Checksum error\n");
+ return false;
}
- if (unlikely(!(flags & RXWBFLAG_MF) &&
- (flags & RXWBFLAG_UDPON) && !(flags & RXWBFLAG_UDPCS))) {
- msg_rx_err(jme, "UDP Checksum error.\n");
- goto out_sumerr;
+ if (unlikely((flags & (RXWBFLAG_MF | RXWBFLAG_UDPON | RXWBFLAG_UDPCS))
+ == RXWBFLAG_UDPON)) {
+ if (flags & RXWBFLAG_IPV4)
+ msg_rx_err(jme, "UDP Checksum error.\n");
+ return false;
}
- if (unlikely((flags & RXWBFLAG_IPV4) && !(flags & RXWBFLAG_IPCS))) {
+ if (unlikely((flags & (RXWBFLAG_IPV4 | RXWBFLAG_IPCS))
+ == RXWBFLAG_IPV4)) {
msg_rx_err(jme, "IPv4 Checksum error.\n");
- goto out_sumerr;
+ return false;
}
return true;
-
-out_sumerr:
- return false;
}
static void
@@ -1296,7 +1320,7 @@ jme_rx_empty_tasklet(unsigned long arg)
static void
jme_wake_queue_if_stopped(struct jme_adapter *jme)
{
- struct jme_ring *txring = jme->txring;
+ struct jme_ring *txring = &(jme->txring[0]);
smp_wmb();
if (unlikely(netif_queue_stopped(jme->dev) &&
@@ -1483,12 +1507,7 @@ jme_msi(int irq, void *dev_id)
struct jme_adapter *jme = netdev_priv(netdev);
u32 intrstat;
- pci_dma_sync_single_for_cpu(jme->pdev,
- jme->shadow_dma,
- sizeof(u32) * SHADOW_REG_NR,
- PCI_DMA_FROMDEVICE);
- intrstat = jme->shadow_regs[SHADOW_IEVE];
- jme->shadow_regs[SHADOW_IEVE] = 0;
+ intrstat = jread32(jme, JME_IEVE);
jme_intr_msi(jme, intrstat);
@@ -1566,6 +1585,7 @@ jme_open(struct net_device *netdev)
jme_clear_pm(jme);
JME_NAPI_ENABLE(jme);
+ tasklet_enable(&jme->linkch_task);
tasklet_enable(&jme->txclean_task);
tasklet_hi_enable(&jme->rxclean_task);
tasklet_hi_enable(&jme->rxempty_task);
@@ -1574,7 +1594,6 @@ jme_open(struct net_device *netdev)
if (rc)
goto err_out;
- jme_enable_shadow(jme);
jme_start_irq(jme);
if (test_bit(JME_FLAG_SSET, &jme->flags))
@@ -1642,15 +1661,14 @@ jme_close(struct net_device *netdev)
netif_carrier_off(netdev);
jme_stop_irq(jme);
- jme_disable_shadow(jme);
jme_free_irq(jme);
JME_NAPI_DISABLE(jme);
- tasklet_kill(&jme->linkch_task);
- tasklet_kill(&jme->txclean_task);
- tasklet_kill(&jme->rxclean_task);
- tasklet_kill(&jme->rxempty_task);
+ tasklet_disable(&jme->linkch_task);
+ tasklet_disable(&jme->txclean_task);
+ tasklet_disable(&jme->rxclean_task);
+ tasklet_disable(&jme->rxempty_task);
jme_reset_ghc_speed(jme);
jme_disable_rx_engine(jme);
@@ -1668,7 +1686,7 @@ static int
jme_alloc_txdesc(struct jme_adapter *jme,
struct sk_buff *skb)
{
- struct jme_ring *txring = jme->txring;
+ struct jme_ring *txring = &(jme->txring[0]);
int idx, nr_alloc, mask = jme->tx_ring_mask;
idx = txring->next_to_use;
@@ -1722,7 +1740,7 @@ jme_fill_tx_map(struct pci_dev *pdev,
static void
jme_map_tx_skb(struct jme_adapter *jme, struct sk_buff *skb, int idx)
{
- struct jme_ring *txring = jme->txring;
+ struct jme_ring *txring = &(jme->txring[0]);
struct txdesc *txdesc = txring->desc, *ctxdesc;
struct jme_buffer_info *txbi = txring->bufinf, *ctxbi;
u8 hidma = jme->dev->features & NETIF_F_HIGHDMA;
@@ -1835,7 +1853,7 @@ jme_tx_vlan(struct sk_buff *skb, __le16 *vlan, u8 *flags)
static int
jme_fill_tx_desc(struct jme_adapter *jme, struct sk_buff *skb, int idx)
{
- struct jme_ring *txring = jme->txring;
+ struct jme_ring *txring = &(jme->txring[0]);
struct txdesc *txdesc;
struct jme_buffer_info *txbi;
u8 flags;
@@ -1883,7 +1901,7 @@ jme_fill_tx_desc(struct jme_adapter *jme, struct sk_buff *skb, int idx)
static void
jme_stop_queue_if_full(struct jme_adapter *jme)
{
- struct jme_ring *txring = jme->txring;
+ struct jme_ring *txring = &(jme->txring[0]);
struct jme_buffer_info *txbi = txring->bufinf;
int idx = atomic_read(&txring->next_to_clean);
@@ -2725,14 +2743,6 @@ jme_init_one(struct pci_dev *pdev,
rc = -ENOMEM;
goto err_out_free_netdev;
}
- jme->shadow_regs = pci_alloc_consistent(pdev,
- sizeof(u32) * SHADOW_REG_NR,
- &(jme->shadow_dma));
- if (!(jme->shadow_regs)) {
- jeprintk(pdev, "Allocating shadow register mapping error.\n");
- rc = -ENOMEM;
- goto err_out_unmap;
- }
if (no_pseudohp) {
apmc = jread32(jme, JME_APMC) & ~JME_APMC_PSEUDO_HP_EN;
@@ -2768,6 +2778,7 @@ jme_init_one(struct pci_dev *pdev,
tasklet_init(&jme->rxempty_task,
&jme_rx_empty_tasklet,
(unsigned long) jme);
+ tasklet_disable_nosync(&jme->linkch_task);
tasklet_disable_nosync(&jme->txclean_task);
tasklet_disable_nosync(&jme->rxclean_task);
tasklet_disable_nosync(&jme->rxempty_task);
@@ -2817,7 +2828,7 @@ jme_init_one(struct pci_dev *pdev,
if (!jme->mii_if.phy_id) {
rc = -EIO;
jeprintk(pdev, "Can not find phy_id.\n");
- goto err_out_free_shadow;
+ goto err_out_unmap;
}
jme->reg_ghc |= GHC_LINK_POLL;
@@ -2846,7 +2857,7 @@ jme_init_one(struct pci_dev *pdev,
if (rc) {
jeprintk(pdev,
"Reload eeprom for reading MAC Address error.\n");
- goto err_out_free_shadow;
+ goto err_out_unmap;
}
jme_load_macaddr(netdev);
@@ -2862,7 +2873,7 @@ jme_init_one(struct pci_dev *pdev,
rc = register_netdev(netdev);
if (rc) {
jeprintk(pdev, "Cannot register net device.\n");
- goto err_out_free_shadow;
+ goto err_out_unmap;
}
msg_probe(jme, "%s%s ver:%x rev:%x macaddr:%pM\n",
@@ -2876,11 +2887,6 @@ jme_init_one(struct pci_dev *pdev,
return 0;
-err_out_free_shadow:
- pci_free_consistent(pdev,
- sizeof(u32) * SHADOW_REG_NR,
- jme->shadow_regs,
- jme->shadow_dma);
err_out_unmap:
iounmap(jme->regs);
err_out_free_netdev:
@@ -2901,10 +2907,6 @@ jme_remove_one(struct pci_dev *pdev)
struct jme_adapter *jme = netdev_priv(netdev);
unregister_netdev(netdev);
- pci_free_consistent(pdev,
- sizeof(u32) * SHADOW_REG_NR,
- jme->shadow_regs,
- jme->shadow_dma);
iounmap(jme->regs);
pci_set_drvdata(pdev, NULL);
free_netdev(netdev);
@@ -2930,8 +2932,6 @@ jme_suspend(struct pci_dev *pdev, pm_message_t state)
tasklet_disable(&jme->rxclean_task);
tasklet_disable(&jme->rxempty_task);
- jme_disable_shadow(jme);
-
if (netif_carrier_ok(netdev)) {
if (test_bit(JME_FLAG_POLL, &jme->flags))
jme_polling_mode(jme);
@@ -2983,7 +2983,6 @@ jme_resume(struct pci_dev *pdev)
else
jme_reset_phy_processor(jme);
- jme_enable_shadow(jme);
jme_start_irq(jme);
netif_device_attach(netdev);
diff --git a/drivers/net/jme.h b/drivers/net/jme.h
index 0996a069ac7..251abed3817 100644
--- a/drivers/net/jme.h
+++ b/drivers/net/jme.h
@@ -25,7 +25,7 @@
#define __JME_H_INCLUDED__
#define DRV_NAME "jme"
-#define DRV_VERSION "1.0.4"
+#define DRV_VERSION "1.0.5"
#define PFX DRV_NAME ": "
#define PCI_DEVICE_ID_JMICRON_JMC250 0x0250
@@ -247,7 +247,7 @@ enum jme_txdesc_flags_bits {
};
#define TXDESC_MSS_SHIFT 2
-enum jme_rxdescwb_flags_bits {
+enum jme_txwbdesc_flags_bits {
TXWBFLAG_OWN = 0x80,
TXWBFLAG_INT = 0x40,
TXWBFLAG_TMOUT = 0x20,
@@ -372,7 +372,6 @@ struct jme_buffer_info {
/*
* The structure holding buffer information and ring descriptors all together.
*/
-#define MAX_RING_DESC_NR 1024
struct jme_ring {
void *alloc; /* pointer to allocated memory */
void *desc; /* pointer to ring memory */
@@ -380,7 +379,7 @@ struct jme_ring {
dma_addr_t dma; /* phys address for ring dma */
/* Buffer information corresponding to each descriptor */
- struct jme_buffer_info bufinf[MAX_RING_DESC_NR];
+ struct jme_buffer_info *bufinf;
int next_to_use;
atomic_t next_to_clean;
@@ -411,13 +410,10 @@ struct jme_ring {
/*
* Jmac Adapter Private data
*/
-#define SHADOW_REG_NR 8
struct jme_adapter {
struct pci_dev *pdev;
struct net_device *dev;
void __iomem *regs;
- dma_addr_t shadow_dma;
- u32 *shadow_regs;
struct mii_if_info mii_if;
struct jme_ring rxring[RX_RING_NR];
struct jme_ring txring[TX_RING_NR];
@@ -464,10 +460,6 @@ struct jme_adapter {
DECLARE_NET_DEVICE_STATS
};
-enum shadow_reg_val {
- SHADOW_IEVE = 0,
-};
-
enum jme_flags_bits {
JME_FLAG_MSI = 1,
JME_FLAG_SSET = 2,
@@ -1104,13 +1096,6 @@ enum jme_chipmode_shifts {
};
/*
- * Shadow base address register bits
- */
-enum jme_shadow_base_address_bits {
- SHBA_POSTEN = 0x1,
-};
-
-/*
* Aggressive Power Mode Control
*/
enum jme_apmc_bits {
diff --git a/drivers/net/korina.c b/drivers/net/korina.c
index b4cf602c32b..51ca54c8ec5 100644
--- a/drivers/net/korina.c
+++ b/drivers/net/korina.c
@@ -338,7 +338,7 @@ static irqreturn_t korina_rx_dma_interrupt(int irq, void *dev_id)
napi_schedule(&lp->napi);
if (dmas & DMA_STAT_ERR)
- printk(KERN_ERR DRV_NAME "%s: DMA error\n", dev->name);
+ printk(KERN_ERR "%s: DMA error\n", dev->name);
retval = IRQ_HANDLED;
} else
@@ -555,7 +555,7 @@ static void korina_tx(struct net_device *dev)
dev->stats.tx_dropped++;
/* Should never happen */
- printk(KERN_ERR DRV_NAME "%s: split tx ignored\n",
+ printk(KERN_ERR "%s: split tx ignored\n",
dev->name);
} else if (devcs & ETH_TX_TOK) {
dev->stats.tx_packets++;
@@ -641,7 +641,7 @@ korina_tx_dma_interrupt(int irq, void *dev_id)
dev->trans_start = jiffies;
}
if (dmas & DMA_STAT_ERR)
- printk(KERN_ERR DRV_NAME "%s: DMA error\n", dev->name);
+ printk(KERN_ERR "%s: DMA error\n", dev->name);
retval = IRQ_HANDLED;
} else
@@ -750,7 +750,7 @@ static struct ethtool_ops netdev_ethtool_ops = {
.get_link = netdev_get_link,
};
-static void korina_alloc_ring(struct net_device *dev)
+static int korina_alloc_ring(struct net_device *dev)
{
struct korina_private *lp = netdev_priv(dev);
struct sk_buff *skb;
@@ -771,7 +771,7 @@ static void korina_alloc_ring(struct net_device *dev)
for (i = 0; i < KORINA_NUM_RDS; i++) {
skb = dev_alloc_skb(KORINA_RBSIZE + 2);
if (!skb)
- break;
+ return -ENOMEM;
skb_reserve(skb, 2);
lp->rx_skb[i] = skb;
lp->rd_ring[i].control = DMA_DESC_IOD |
@@ -790,6 +790,8 @@ static void korina_alloc_ring(struct net_device *dev)
lp->rx_chain_head = 0;
lp->rx_chain_tail = 0;
lp->rx_chain_status = desc_empty;
+
+ return 0;
}
static void korina_free_ring(struct net_device *dev)
@@ -832,7 +834,11 @@ static int korina_init(struct net_device *dev)
writel(ETH_INT_FC_EN, &lp->eth_regs->ethintfc);
/* Allocate rings */
- korina_alloc_ring(dev);
+ if (korina_alloc_ring(dev)) {
+ printk(KERN_ERR "%s: descriptor allocation failed\n", dev->name);
+ korina_free_ring(dev);
+ return -ENOMEM;
+ }
writel(0, &lp->rx_dma_regs->dmas);
/* Start Rx DMA */
@@ -917,8 +923,7 @@ static int korina_restart(struct net_device *dev)
ret = korina_init(dev);
if (ret < 0) {
- printk(KERN_ERR DRV_NAME "%s: cannot restart device\n",
- dev->name);
+ printk(KERN_ERR "%s: cannot restart device\n", dev->name);
return ret;
}
korina_multicast_list(dev);
@@ -1005,7 +1010,7 @@ static int korina_open(struct net_device *dev)
/* Initialize */
ret = korina_init(dev);
if (ret < 0) {
- printk(KERN_ERR DRV_NAME "%s: cannot open device\n", dev->name);
+ printk(KERN_ERR "%s: cannot open device\n", dev->name);
goto out;
}
@@ -1015,14 +1020,14 @@ static int korina_open(struct net_device *dev)
ret = request_irq(lp->rx_irq, &korina_rx_dma_interrupt,
IRQF_DISABLED, "Korina ethernet Rx", dev);
if (ret < 0) {
- printk(KERN_ERR DRV_NAME "%s: unable to get Rx DMA IRQ %d\n",
+ printk(KERN_ERR "%s: unable to get Rx DMA IRQ %d\n",
dev->name, lp->rx_irq);
goto err_release;
}
ret = request_irq(lp->tx_irq, &korina_tx_dma_interrupt,
IRQF_DISABLED, "Korina ethernet Tx", dev);
if (ret < 0) {
- printk(KERN_ERR DRV_NAME "%s: unable to get Tx DMA IRQ %d\n",
+ printk(KERN_ERR "%s: unable to get Tx DMA IRQ %d\n",
dev->name, lp->tx_irq);
goto err_free_rx_irq;
}
@@ -1031,7 +1036,7 @@ static int korina_open(struct net_device *dev)
ret = request_irq(lp->ovr_irq, &korina_ovr_interrupt,
IRQF_DISABLED, "Ethernet Overflow", dev);
if (ret < 0) {
- printk(KERN_ERR DRV_NAME"%s: unable to get OVR IRQ %d\n",
+ printk(KERN_ERR "%s: unable to get OVR IRQ %d\n",
dev->name, lp->ovr_irq);
goto err_free_tx_irq;
}
@@ -1040,7 +1045,7 @@ static int korina_open(struct net_device *dev)
ret = request_irq(lp->und_irq, &korina_und_interrupt,
IRQF_DISABLED, "Ethernet Underflow", dev);
if (ret < 0) {
- printk(KERN_ERR DRV_NAME "%s: unable to get UND IRQ %d\n",
+ printk(KERN_ERR "%s: unable to get UND IRQ %d\n",
dev->name, lp->und_irq);
goto err_free_ovr_irq;
}
@@ -1137,7 +1142,7 @@ static int korina_probe(struct platform_device *pdev)
dev->base_addr = r->start;
lp->eth_regs = ioremap_nocache(r->start, r->end - r->start);
if (!lp->eth_regs) {
- printk(KERN_ERR DRV_NAME "cannot remap registers\n");
+ printk(KERN_ERR DRV_NAME ": cannot remap registers\n");
rc = -ENXIO;
goto probe_err_out;
}
@@ -1145,7 +1150,7 @@ static int korina_probe(struct platform_device *pdev)
r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "korina_dma_rx");
lp->rx_dma_regs = ioremap_nocache(r->start, r->end - r->start);
if (!lp->rx_dma_regs) {
- printk(KERN_ERR DRV_NAME "cannot remap Rx DMA registers\n");
+ printk(KERN_ERR DRV_NAME ": cannot remap Rx DMA registers\n");
rc = -ENXIO;
goto probe_err_dma_rx;
}
@@ -1153,14 +1158,14 @@ static int korina_probe(struct platform_device *pdev)
r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "korina_dma_tx");
lp->tx_dma_regs = ioremap_nocache(r->start, r->end - r->start);
if (!lp->tx_dma_regs) {
- printk(KERN_ERR DRV_NAME "cannot remap Tx DMA registers\n");
+ printk(KERN_ERR DRV_NAME ": cannot remap Tx DMA registers\n");
rc = -ENXIO;
goto probe_err_dma_tx;
}
lp->td_ring = kmalloc(TD_RING_SIZE + RD_RING_SIZE, GFP_KERNEL);
if (!lp->td_ring) {
- printk(KERN_ERR DRV_NAME "cannot allocate descriptors\n");
+ printk(KERN_ERR DRV_NAME ": cannot allocate descriptors\n");
rc = -ENXIO;
goto probe_err_td_ring;
}
@@ -1193,10 +1198,13 @@ static int korina_probe(struct platform_device *pdev)
rc = register_netdev(dev);
if (rc < 0) {
printk(KERN_ERR DRV_NAME
- ": cannot register net device %d\n", rc);
+ ": cannot register net device: %d\n", rc);
goto probe_err_register;
}
setup_timer(&lp->media_check_timer, korina_poll_media, (unsigned long) dev);
+
+ printk(KERN_INFO "%s: " DRV_NAME "-" DRV_VERSION " " DRV_RELDATE "\n",
+ dev->name);
out:
return rc;
diff --git a/drivers/net/lance.c b/drivers/net/lance.c
index 633808d447b..30fd4f5f1d5 100644
--- a/drivers/net/lance.c
+++ b/drivers/net/lance.c
@@ -1016,7 +1016,7 @@ static int lance_start_xmit(struct sk_buff *skb, struct net_device *dev)
out:
spin_unlock_irqrestore(&lp->devlock, flags);
- return 0;
+ return NETDEV_TX_OK;
}
/* The LANCE interrupt handler. */
diff --git a/drivers/net/lib82596.c b/drivers/net/lib82596.c
index 070fa450087..51e11c3e53e 100644
--- a/drivers/net/lib82596.c
+++ b/drivers/net/lib82596.c
@@ -983,7 +983,7 @@ static int i596_start_xmit(struct sk_buff *skb, struct net_device *dev)
if (length < ETH_ZLEN) {
if (skb_padto(skb, ETH_ZLEN))
- return 0;
+ return NETDEV_TX_OK;
length = ETH_ZLEN;
}
@@ -1028,7 +1028,7 @@ static int i596_start_xmit(struct sk_buff *skb, struct net_device *dev)
netif_start_queue(dev);
- return 0;
+ return NETDEV_TX_OK;
}
static void print_eth(unsigned char *add, char *str)
diff --git a/drivers/net/lib8390.c b/drivers/net/lib8390.c
index f28c2334300..d6be36000c5 100644
--- a/drivers/net/lib8390.c
+++ b/drivers/net/lib8390.c
@@ -414,7 +414,7 @@ static int __ei_start_xmit(struct sk_buff *skb, struct net_device *dev)
dev_kfree_skb (skb);
dev->stats.tx_bytes += send_length;
- return 0;
+ return NETDEV_TX_OK;
}
/**
diff --git a/drivers/net/ll_temac_main.c b/drivers/net/ll_temac_main.c
index 96e7248876c..da8d0a0ca94 100644
--- a/drivers/net/ll_temac_main.c
+++ b/drivers/net/ll_temac_main.c
@@ -591,7 +591,7 @@ static int temac_start_xmit(struct sk_buff *skb, struct net_device *ndev)
/* Kick off the transfer */
temac_dma_out32(lp, TX_TAILDESC_PTR, tail_p); /* DMA start */
- return 0;
+ return NETDEV_TX_OK;
}
diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c
index da472c68748..51bbce72bed 100644
--- a/drivers/net/loopback.c
+++ b/drivers/net/loopback.c
@@ -89,7 +89,7 @@ static int loopback_xmit(struct sk_buff *skb, struct net_device *dev)
} else
lb_stats->drops++;
- return 0;
+ return NETDEV_TX_OK;
}
static struct net_device_stats *loopback_get_stats(struct net_device *dev)
diff --git a/drivers/net/lp486e.c b/drivers/net/lp486e.c
index d44bddbee37..c292bad411e 100644
--- a/drivers/net/lp486e.c
+++ b/drivers/net/lp486e.c
@@ -871,7 +871,7 @@ static int i596_start_xmit (struct sk_buff *skb, struct net_device *dev) {
if (length < ETH_ZLEN) {
if (skb_padto(skb, ETH_ZLEN))
- return 0;
+ return NETDEV_TX_OK;
length = ETH_ZLEN;
}
@@ -906,7 +906,7 @@ static int i596_start_xmit (struct sk_buff *skb, struct net_device *dev) {
dev->stats.tx_packets++;
}
- return 0;
+ return NETDEV_TX_OK;
}
static void
diff --git a/drivers/net/mac89x0.c b/drivers/net/mac89x0.c
index dab45339d3a..149e0ed4a05 100644
--- a/drivers/net/mac89x0.c
+++ b/drivers/net/mac89x0.c
@@ -411,7 +411,7 @@ net_send_packet(struct sk_buff *skb, struct net_device *dev)
dev->trans_start = jiffies;
dev_kfree_skb (skb);
- return 0;
+ return NETDEV_TX_OK;
}
/* The typical workload of the driver:
diff --git a/drivers/net/macb.c b/drivers/net/macb.c
index 5b5c25368d1..d22952c78f1 100644
--- a/drivers/net/macb.c
+++ b/drivers/net/macb.c
@@ -678,7 +678,7 @@ static int macb_start_xmit(struct sk_buff *skb, struct net_device *dev)
dev->trans_start = jiffies;
- return 0;
+ return NETDEV_TX_OK;
}
static void macb_free_consistent(struct macb *bp)
diff --git a/drivers/net/mace.c b/drivers/net/mace.c
index 1427755c224..7d7577b598e 100644
--- a/drivers/net/mace.c
+++ b/drivers/net/mace.c
@@ -581,7 +581,7 @@ static int mace_xmit_start(struct sk_buff *skb, struct net_device *dev)
netif_stop_queue(dev);
spin_unlock_irqrestore(&mp->lock, flags);
- return 0;
+ return NETDEV_TX_OK;
}
static void mace_set_multicast(struct net_device *dev)
diff --git a/drivers/net/meth.c b/drivers/net/meth.c
index 5d04d94f2a2..92ceb689b4d 100644
--- a/drivers/net/meth.c
+++ b/drivers/net/meth.c
@@ -715,7 +715,7 @@ static int meth_tx(struct sk_buff *skb, struct net_device *dev)
spin_unlock_irqrestore(&priv->meth_lock, flags);
- return 0;
+ return NETDEV_TX_OK;
}
/*
@@ -784,7 +784,7 @@ static const struct net_device_ops meth_netdev_ops = {
/*
* The init function.
*/
-static int __init meth_probe(struct platform_device *pdev)
+static int __devinit meth_probe(struct platform_device *pdev)
{
struct net_device *dev;
struct meth_private *priv;
diff --git a/drivers/net/mipsnet.c b/drivers/net/mipsnet.c
index b3b9a147d09..8ea98bd89ff 100644
--- a/drivers/net/mipsnet.c
+++ b/drivers/net/mipsnet.c
@@ -141,7 +141,7 @@ static int mipsnet_xmit(struct sk_buff *skb, struct net_device *dev)
netif_stop_queue(dev);
mipsnet_put_todevice(dev, skb);
- return 0;
+ return NETDEV_TX_OK;
}
static inline ssize_t mipsnet_get_fromdev(struct net_device *dev, size_t len)
diff --git a/drivers/net/mlx4/en_main.c b/drivers/net/mlx4/en_main.c
index 9ed4a158f89..507e11fce9e 100644
--- a/drivers/net/mlx4/en_main.c
+++ b/drivers/net/mlx4/en_main.c
@@ -218,8 +218,9 @@ static void *mlx4_en_add(struct mlx4_dev *dev)
mlx4_foreach_port(i, dev, MLX4_PORT_TYPE_ETH) {
mlx4_info(mdev, "Using %d tx rings for port:%d\n",
mdev->profile.prof[i].tx_ring_num, i);
- mdev->profile.prof[i].rx_ring_num =
- min_t(int, dev->caps.num_comp_vectors, MAX_RX_RINGS);
+ mdev->profile.prof[i].rx_ring_num = min_t(int,
+ roundup_pow_of_two(dev->caps.num_comp_vectors),
+ MAX_RX_RINGS);
mlx4_info(mdev, "Defaulting to %d rx rings for port:%d\n",
mdev->profile.prof[i].rx_ring_num, i);
}
diff --git a/drivers/net/mlx4/en_netdev.c b/drivers/net/mlx4/en_netdev.c
index 93f4abd990a..c48b0f4b17b 100644
--- a/drivers/net/mlx4/en_netdev.c
+++ b/drivers/net/mlx4/en_netdev.c
@@ -414,6 +414,7 @@ static void mlx4_en_auto_moderation(struct mlx4_en_priv *priv)
unsigned long avg_pkt_size;
unsigned long rx_packets;
unsigned long rx_bytes;
+ unsigned long rx_byte_diff;
unsigned long tx_packets;
unsigned long tx_pkt_diff;
unsigned long rx_pkt_diff;
@@ -437,6 +438,8 @@ static void mlx4_en_auto_moderation(struct mlx4_en_priv *priv)
rx_pkt_diff = ((unsigned long) (rx_packets -
priv->last_moder_packets));
packets = max(tx_pkt_diff, rx_pkt_diff);
+ rx_byte_diff = rx_bytes - priv->last_moder_bytes;
+ rx_byte_diff = rx_byte_diff ? rx_byte_diff : 1;
rate = packets * HZ / period;
avg_pkt_size = packets ? ((unsigned long) (rx_bytes -
priv->last_moder_bytes)) / packets : 0;
@@ -447,10 +450,13 @@ static void mlx4_en_auto_moderation(struct mlx4_en_priv *priv)
/* If tx and rx packet rates are not balanced, assume that
* traffic is mainly BW bound and apply maximum moderation.
* Otherwise, moderate according to packet rate */
- if (2 * tx_pkt_diff > 3 * rx_pkt_diff ||
- 2 * rx_pkt_diff > 3 * tx_pkt_diff) {
+ if (2 * tx_pkt_diff > 3 * rx_pkt_diff &&
+ rx_pkt_diff / rx_byte_diff <
+ MLX4_EN_SMALL_PKT_SIZE)
+ moder_time = priv->rx_usecs_low;
+ else if (2 * rx_pkt_diff > 3 * tx_pkt_diff)
moder_time = priv->rx_usecs_high;
- } else {
+ else {
if (rate < priv->pkt_rate_low)
moder_time = priv->rx_usecs_low;
else if (rate > priv->pkt_rate_high)
@@ -616,8 +622,7 @@ int mlx4_en_start_port(struct net_device *dev)
/* Configure ring */
tx_ring = &priv->tx_ring[i];
- err = mlx4_en_activate_tx_ring(priv, tx_ring, cq->mcq.cqn,
- priv->rx_ring[0].srq.srqn);
+ err = mlx4_en_activate_tx_ring(priv, tx_ring, cq->mcq.cqn);
if (err) {
en_err(priv, "Failed allocating Tx ring\n");
mlx4_en_deactivate_cq(priv, cq);
@@ -1005,9 +1010,6 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
if (err)
goto out;
- /* Populate Rx default RSS mappings */
- mlx4_en_set_default_rss_map(priv, &priv->rss_map, priv->rx_ring_num *
- RSS_FACTOR, priv->rx_ring_num);
/* Allocate page for receive rings */
err = mlx4_alloc_hwq_res(mdev->dev, &priv->res,
MLX4_EN_PAGE_SIZE, MLX4_EN_PAGE_SIZE);
diff --git a/drivers/net/mlx4/en_resources.c b/drivers/net/mlx4/en_resources.c
index 65ca706c04b..16256784a94 100644
--- a/drivers/net/mlx4/en_resources.c
+++ b/drivers/net/mlx4/en_resources.c
@@ -37,7 +37,7 @@
#include "mlx4_en.h"
void mlx4_en_fill_qp_context(struct mlx4_en_priv *priv, int size, int stride,
- int is_tx, int rss, int qpn, int cqn, int srqn,
+ int is_tx, int rss, int qpn, int cqn,
struct mlx4_qp_context *context)
{
struct mlx4_en_dev *mdev = priv->mdev;
@@ -46,11 +46,12 @@ void mlx4_en_fill_qp_context(struct mlx4_en_priv *priv, int size, int stride,
context->flags = cpu_to_be32(7 << 16 | rss << 13);
context->pd = cpu_to_be32(mdev->priv_pdn);
context->mtu_msgmax = 0xff;
- context->rq_size_stride = 0;
+ if (!is_tx && !rss)
+ context->rq_size_stride = ilog2(size) << 3 | (ilog2(stride) - 4);
if (is_tx)
context->sq_size_stride = ilog2(size) << 3 | (ilog2(stride) - 4);
else
- context->sq_size_stride = 1;
+ context->sq_size_stride = ilog2(TXBB_SIZE) - 4;
context->usr_page = cpu_to_be32(mdev->priv_uar.index);
context->local_qpn = cpu_to_be32(qpn);
context->pri_path.ackto = 1 & 0x07;
@@ -59,8 +60,6 @@ void mlx4_en_fill_qp_context(struct mlx4_en_priv *priv, int size, int stride,
context->cqn_send = cpu_to_be32(cqn);
context->cqn_recv = cpu_to_be32(cqn);
context->db_rec_addr = cpu_to_be64(priv->res.db.dma << 2);
- if (!rss)
- context->srqn = cpu_to_be32(MLX4_EN_USE_SRQ | srqn);
}
diff --git a/drivers/net/mlx4/en_rx.c b/drivers/net/mlx4/en_rx.c
index 3ac0404d0d1..03b781a7a18 100644
--- a/drivers/net/mlx4/en_rx.c
+++ b/drivers/net/mlx4/en_rx.c
@@ -40,16 +40,6 @@
#include "mlx4_en.h"
-static void *get_wqe(struct mlx4_en_rx_ring *ring, int n)
-{
- int offset = n << ring->srq.wqe_shift;
- return ring->buf + offset;
-}
-
-static void mlx4_en_srq_event(struct mlx4_srq *srq, enum mlx4_event type)
-{
- return;
-}
static int mlx4_en_get_frag_header(struct skb_frag_struct *frags, void **mac_hdr,
void **ip_hdr, void **tcpudp_hdr,
@@ -154,9 +144,6 @@ static void mlx4_en_init_rx_desc(struct mlx4_en_priv *priv,
int possible_frags;
int i;
- /* Pre-link descriptor */
- rx_desc->next.next_wqe_index = cpu_to_be16((index + 1) & ring->size_mask);
-
/* Set size and memtype fields */
for (i = 0; i < priv->num_frags; i++) {
skb_frags[i].size = priv->frag_info[i].frag_size;
@@ -294,9 +281,6 @@ int mlx4_en_create_rx_ring(struct mlx4_en_priv *priv,
int err;
int tmp;
- /* Sanity check SRQ size before proceeding */
- if (size >= mdev->dev->caps.max_srq_wqes)
- return -EINVAL;
ring->prod = 0;
ring->cons = 0;
@@ -304,7 +288,7 @@ int mlx4_en_create_rx_ring(struct mlx4_en_priv *priv,
ring->size_mask = size - 1;
ring->stride = stride;
ring->log_stride = ffs(ring->stride) - 1;
- ring->buf_size = ring->size * ring->stride;
+ ring->buf_size = ring->size * ring->stride + TXBB_SIZE;
tmp = size * roundup_pow_of_two(MLX4_EN_MAX_RX_FRAGS *
sizeof(struct skb_frag_struct));
@@ -360,15 +344,12 @@ err_ring:
int mlx4_en_activate_rx_rings(struct mlx4_en_priv *priv)
{
- struct mlx4_en_dev *mdev = priv->mdev;
- struct mlx4_wqe_srq_next_seg *next;
struct mlx4_en_rx_ring *ring;
int i;
int ring_ind;
int err;
int stride = roundup_pow_of_two(sizeof(struct mlx4_en_rx_desc) +
DS_SIZE * priv->num_frags);
- int max_gs = (stride - sizeof(struct mlx4_wqe_srq_next_seg)) / DS_SIZE;
for (ring_ind = 0; ring_ind < priv->rx_ring_num; ring_ind++) {
ring = &priv->rx_ring[ring_ind];
@@ -379,6 +360,9 @@ int mlx4_en_activate_rx_rings(struct mlx4_en_priv *priv)
ring->cqn = priv->rx_cq[ring_ind].mcq.cqn;
ring->stride = stride;
+ if (ring->stride <= TXBB_SIZE)
+ ring->buf += TXBB_SIZE;
+
ring->log_stride = ffs(ring->stride) - 1;
ring->buf_size = ring->size * ring->stride;
@@ -405,37 +389,10 @@ int mlx4_en_activate_rx_rings(struct mlx4_en_priv *priv)
ring = &priv->rx_ring[ring_ind];
mlx4_en_update_rx_prod_db(ring);
-
- /* Configure SRQ representing the ring */
- ring->srq.max = ring->actual_size;
- ring->srq.max_gs = max_gs;
- ring->srq.wqe_shift = ilog2(ring->stride);
-
- for (i = 0; i < ring->srq.max; ++i) {
- next = get_wqe(ring, i);
- next->next_wqe_index =
- cpu_to_be16((i + 1) & (ring->srq.max - 1));
- }
-
- err = mlx4_srq_alloc(mdev->dev, mdev->priv_pdn, &ring->wqres.mtt,
- ring->wqres.db.dma, &ring->srq);
- if (err){
- en_err(priv, "Failed to allocate srq\n");
- ring_ind--;
- goto err_srq;
- }
- ring->srq.event = mlx4_en_srq_event;
}
return 0;
-err_srq:
- while (ring_ind >= 0) {
- ring = &priv->rx_ring[ring_ind];
- mlx4_srq_free(mdev->dev, &ring->srq);
- ring_ind--;
- }
-
err_buffers:
for (ring_ind = 0; ring_ind < priv->rx_ring_num; ring_ind++)
mlx4_en_free_rx_buf(priv, &priv->rx_ring[ring_ind]);
@@ -456,7 +413,7 @@ void mlx4_en_destroy_rx_ring(struct mlx4_en_priv *priv,
kfree(ring->lro.lro_arr);
mlx4_en_unmap_buffer(&ring->wqres.buf);
- mlx4_free_hwq_res(mdev->dev, &ring->wqres, ring->buf_size);
+ mlx4_free_hwq_res(mdev->dev, &ring->wqres, ring->buf_size + TXBB_SIZE);
vfree(ring->rx_info);
ring->rx_info = NULL;
}
@@ -464,10 +421,9 @@ void mlx4_en_destroy_rx_ring(struct mlx4_en_priv *priv,
void mlx4_en_deactivate_rx_ring(struct mlx4_en_priv *priv,
struct mlx4_en_rx_ring *ring)
{
- struct mlx4_en_dev *mdev = priv->mdev;
-
- mlx4_srq_free(mdev->dev, &ring->srq);
mlx4_en_free_rx_buf(priv, ring);
+ if (ring->stride <= TXBB_SIZE)
+ ring->buf -= TXBB_SIZE;
mlx4_en_destroy_allocator(priv, ring);
}
@@ -836,25 +792,8 @@ void mlx4_en_calc_rx_buf(struct net_device *dev)
/* RSS related functions */
-/* Calculate rss size and map each entry in rss table to rx ring */
-void mlx4_en_set_default_rss_map(struct mlx4_en_priv *priv,
- struct mlx4_en_rss_map *rss_map,
- int num_entries, int num_rings)
-{
- int i;
-
- rss_map->size = roundup_pow_of_two(num_entries);
- en_dbg(DRV, priv, "Setting default RSS map of %d entires\n",
- rss_map->size);
-
- for (i = 0; i < rss_map->size; i++) {
- rss_map->map[i] = i % num_rings;
- en_dbg(DRV, priv, "Entry %d ---> ring %d\n", i, rss_map->map[i]);
- }
-}
-
-static int mlx4_en_config_rss_qp(struct mlx4_en_priv *priv,
- int qpn, int srqn, int cqn,
+static int mlx4_en_config_rss_qp(struct mlx4_en_priv *priv, int qpn,
+ struct mlx4_en_rx_ring *ring,
enum mlx4_qp_state *state,
struct mlx4_qp *qp)
{
@@ -876,13 +815,16 @@ static int mlx4_en_config_rss_qp(struct mlx4_en_priv *priv,
qp->event = mlx4_en_sqp_event;
memset(context, 0, sizeof *context);
- mlx4_en_fill_qp_context(priv, 0, 0, 0, 0, qpn, cqn, srqn, context);
+ mlx4_en_fill_qp_context(priv, ring->size, ring->stride, 0, 0,
+ qpn, ring->cqn, context);
+ context->db_rec_addr = cpu_to_be64(ring->wqres.db.dma);
- err = mlx4_qp_to_ready(mdev->dev, &priv->res.mtt, context, qp, state);
+ err = mlx4_qp_to_ready(mdev->dev, &ring->wqres.mtt, context, qp, state);
if (err) {
mlx4_qp_remove(mdev->dev, qp);
mlx4_qp_free(mdev->dev, qp);
}
+ mlx4_en_update_rx_prod_db(ring);
out:
kfree(context);
return err;
@@ -898,23 +840,22 @@ int mlx4_en_config_rss_steer(struct mlx4_en_priv *priv)
void *ptr;
int rss_xor = mdev->profile.rss_xor;
u8 rss_mask = mdev->profile.rss_mask;
- int i, srqn, qpn, cqn;
+ int i, qpn;
int err = 0;
int good_qps = 0;
en_dbg(DRV, priv, "Configuring rss steering\n");
- err = mlx4_qp_reserve_range(mdev->dev, rss_map->size,
- rss_map->size, &rss_map->base_qpn);
+ err = mlx4_qp_reserve_range(mdev->dev, priv->rx_ring_num,
+ priv->rx_ring_num,
+ &rss_map->base_qpn);
if (err) {
- en_err(priv, "Failed reserving %d qps\n", rss_map->size);
+ en_err(priv, "Failed reserving %d qps\n", priv->rx_ring_num);
return err;
}
- for (i = 0; i < rss_map->size; i++) {
- cqn = priv->rx_ring[rss_map->map[i]].cqn;
- srqn = priv->rx_ring[rss_map->map[i]].srq.srqn;
+ for (i = 0; i < priv->rx_ring_num; i++) {
qpn = rss_map->base_qpn + i;
- err = mlx4_en_config_rss_qp(priv, qpn, srqn, cqn,
+ err = mlx4_en_config_rss_qp(priv, qpn, &priv->rx_ring[i],
&rss_map->state[i],
&rss_map->qps[i]);
if (err)
@@ -937,11 +878,11 @@ int mlx4_en_config_rss_steer(struct mlx4_en_priv *priv)
}
rss_map->indir_qp.event = mlx4_en_sqp_event;
mlx4_en_fill_qp_context(priv, 0, 0, 0, 1, priv->base_qpn,
- priv->rx_ring[0].cqn, 0, &context);
+ priv->rx_ring[0].cqn, &context);
ptr = ((void *) &context) + 0x3c;
rss_context = (struct mlx4_en_rss_context *) ptr;
- rss_context->base_qpn = cpu_to_be32(ilog2(rss_map->size) << 24 |
+ rss_context->base_qpn = cpu_to_be32(ilog2(priv->rx_ring_num) << 24 |
(rss_map->base_qpn));
rss_context->default_qpn = cpu_to_be32(rss_map->base_qpn);
rss_context->hash_fn = rss_xor & 0x3;
@@ -968,7 +909,7 @@ rss_err:
mlx4_qp_remove(mdev->dev, &rss_map->qps[i]);
mlx4_qp_free(mdev->dev, &rss_map->qps[i]);
}
- mlx4_qp_release_range(mdev->dev, rss_map->base_qpn, rss_map->size);
+ mlx4_qp_release_range(mdev->dev, rss_map->base_qpn, priv->rx_ring_num);
return err;
}
@@ -984,13 +925,13 @@ void mlx4_en_release_rss_steer(struct mlx4_en_priv *priv)
mlx4_qp_free(mdev->dev, &rss_map->indir_qp);
mlx4_qp_release_range(mdev->dev, priv->base_qpn, 1);
- for (i = 0; i < rss_map->size; i++) {
+ for (i = 0; i < priv->rx_ring_num; i++) {
mlx4_qp_modify(mdev->dev, NULL, rss_map->state[i],
MLX4_QP_STATE_RST, NULL, 0, 0, &rss_map->qps[i]);
mlx4_qp_remove(mdev->dev, &rss_map->qps[i]);
mlx4_qp_free(mdev->dev, &rss_map->qps[i]);
}
- mlx4_qp_release_range(mdev->dev, rss_map->base_qpn, rss_map->size);
+ mlx4_qp_release_range(mdev->dev, rss_map->base_qpn, priv->rx_ring_num);
}
diff --git a/drivers/net/mlx4/en_tx.c b/drivers/net/mlx4/en_tx.c
index 5a88b3f5769..0ecc1e1b013 100644
--- a/drivers/net/mlx4/en_tx.c
+++ b/drivers/net/mlx4/en_tx.c
@@ -150,7 +150,7 @@ void mlx4_en_destroy_tx_ring(struct mlx4_en_priv *priv,
int mlx4_en_activate_tx_ring(struct mlx4_en_priv *priv,
struct mlx4_en_tx_ring *ring,
- int cq, int srqn)
+ int cq)
{
struct mlx4_en_dev *mdev = priv->mdev;
int err;
@@ -168,7 +168,7 @@ int mlx4_en_activate_tx_ring(struct mlx4_en_priv *priv,
ring->doorbell_qpn = swab32(ring->qp.qpn << 8);
mlx4_en_fill_qp_context(priv, ring->size, ring->stride, 1, 0, ring->qpn,
- ring->cqn, srqn, &ring->context);
+ ring->cqn, &ring->context);
err = mlx4_qp_to_ready(mdev->dev, &ring->wqres.mtt, &ring->context,
&ring->qp, &ring->qp_state);
@@ -765,7 +765,7 @@ int mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev)
/* Poll CQ here */
mlx4_en_xmit_poll(priv, tx_ind);
- return 0;
+ return NETDEV_TX_OK;
tx_drop:
dev_kfree_skb_any(skb);
diff --git a/drivers/net/mlx4/mlx4_en.h b/drivers/net/mlx4/mlx4_en.h
index c7c5e86804f..4513fb4960d 100644
--- a/drivers/net/mlx4/mlx4_en.h
+++ b/drivers/net/mlx4/mlx4_en.h
@@ -95,8 +95,6 @@
#define MLX4_EN_PAGE_SIZE (1 << MLX4_EN_PAGE_SHIFT)
#define MAX_TX_RINGS 16
#define MAX_RX_RINGS 16
-#define MAX_RSS_MAP_SIZE 64
-#define RSS_FACTOR 2
#define TXBB_SIZE 64
#define HEADROOM (2048 / TXBB_SIZE + 1)
#define STAMP_STRIDE 64
@@ -276,13 +274,11 @@ struct mlx4_en_tx_ring {
};
struct mlx4_en_rx_desc {
- struct mlx4_wqe_srq_next_seg next;
/* actual number of entries depends on rx ring stride */
struct mlx4_wqe_data_seg data[0];
};
struct mlx4_en_rx_ring {
- struct mlx4_srq srq;
struct mlx4_hwq_resources wqres;
struct mlx4_en_rx_alloc page_alloc[MLX4_EN_MAX_RX_FRAGS];
struct net_lro_mgr lro;
@@ -377,11 +373,9 @@ struct mlx4_en_dev {
struct mlx4_en_rss_map {
- int size;
int base_qpn;
- u16 map[MAX_RSS_MAP_SIZE];
- struct mlx4_qp qps[MAX_RSS_MAP_SIZE];
- enum mlx4_qp_state state[MAX_RSS_MAP_SIZE];
+ struct mlx4_qp qps[MAX_RX_RINGS];
+ enum mlx4_qp_state state[MAX_RX_RINGS];
struct mlx4_qp indir_qp;
enum mlx4_qp_state indir_state;
};
@@ -531,7 +525,7 @@ int mlx4_en_create_tx_ring(struct mlx4_en_priv *priv, struct mlx4_en_tx_ring *ri
void mlx4_en_destroy_tx_ring(struct mlx4_en_priv *priv, struct mlx4_en_tx_ring *ring);
int mlx4_en_activate_tx_ring(struct mlx4_en_priv *priv,
struct mlx4_en_tx_ring *ring,
- int cq, int srqn);
+ int cq);
void mlx4_en_deactivate_tx_ring(struct mlx4_en_priv *priv,
struct mlx4_en_tx_ring *ring);
@@ -548,16 +542,13 @@ int mlx4_en_process_rx_cq(struct net_device *dev,
int budget);
int mlx4_en_poll_rx_cq(struct napi_struct *napi, int budget);
void mlx4_en_fill_qp_context(struct mlx4_en_priv *priv, int size, int stride,
- int is_tx, int rss, int qpn, int cqn, int srqn,
+ int is_tx, int rss, int qpn, int cqn,
struct mlx4_qp_context *context);
void mlx4_en_sqp_event(struct mlx4_qp *qp, enum mlx4_event event);
int mlx4_en_map_buffer(struct mlx4_buf *buf);
void mlx4_en_unmap_buffer(struct mlx4_buf *buf);
void mlx4_en_calc_rx_buf(struct net_device *dev);
-void mlx4_en_set_default_rss_map(struct mlx4_en_priv *priv,
- struct mlx4_en_rss_map *rss_map,
- int num_entries, int num_rings);
int mlx4_en_config_rss_steer(struct mlx4_en_priv *priv);
void mlx4_en_release_rss_steer(struct mlx4_en_priv *priv);
int mlx4_en_free_tx_buf(struct net_device *dev, struct mlx4_en_tx_ring *ring);
diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c
index 1f6e36ea669..75deef35b1e 100644
--- a/drivers/net/myri10ge/myri10ge.c
+++ b/drivers/net/myri10ge/myri10ge.c
@@ -75,7 +75,7 @@
#include "myri10ge_mcp.h"
#include "myri10ge_mcp_gen_header.h"
-#define MYRI10GE_VERSION_STR "1.5.0-1.418"
+#define MYRI10GE_VERSION_STR "1.5.0-1.432"
MODULE_DESCRIPTION("Myricom 10G driver (10GbE)");
MODULE_AUTHOR("Maintainer: help@myri.com");
@@ -188,6 +188,7 @@ struct myri10ge_slice_state {
dma_addr_t fw_stats_bus;
int watchdog_tx_done;
int watchdog_tx_req;
+ int watchdog_rx_done;
#ifdef CONFIG_MYRI10GE_DCA
int cached_dca_tag;
int cpu;
@@ -256,6 +257,7 @@ struct myri10ge_priv {
u32 link_changes;
u32 msg_enable;
unsigned int board_number;
+ int rebooted;
};
static char *myri10ge_fw_unaligned = "myri10ge_ethp_z8e.dat";
@@ -2552,17 +2554,22 @@ static int myri10ge_close(struct net_device *dev)
netif_carrier_off(dev);
netif_tx_stop_all_queues(dev);
- old_down_cnt = mgp->down_cnt;
- mb();
- status = myri10ge_send_cmd(mgp, MXGEFW_CMD_ETHERNET_DOWN, &cmd, 0);
- if (status)
- printk(KERN_ERR "myri10ge: %s: Couldn't bring down link\n",
- dev->name);
-
- wait_event_timeout(mgp->down_wq, old_down_cnt != mgp->down_cnt, HZ);
- if (old_down_cnt == mgp->down_cnt)
- printk(KERN_ERR "myri10ge: %s never got down irq\n", dev->name);
+ if (mgp->rebooted == 0) {
+ old_down_cnt = mgp->down_cnt;
+ mb();
+ status =
+ myri10ge_send_cmd(mgp, MXGEFW_CMD_ETHERNET_DOWN, &cmd, 0);
+ if (status)
+ printk(KERN_ERR
+ "myri10ge: %s: Couldn't bring down link\n",
+ dev->name);
+ wait_event_timeout(mgp->down_wq, old_down_cnt != mgp->down_cnt,
+ HZ);
+ if (old_down_cnt == mgp->down_cnt)
+ printk(KERN_ERR "myri10ge: %s never got down irq\n",
+ dev->name);
+ }
netif_tx_disable(dev);
myri10ge_free_irq(mgp);
for (i = 0; i < mgp->num_slices; i++)
@@ -2748,7 +2755,7 @@ again:
/* The packet is gone, so we must
* return 0 */
ss->stats.tx_dropped += 1;
- return 0;
+ return NETDEV_TX_OK;
}
/* adjust the len to account for the zero pad
* so that the nic can know how long it is */
@@ -2892,7 +2899,7 @@ again:
tx->stop_queue++;
netif_tx_stop_queue(netdev_queue);
}
- return 0;
+ return NETDEV_TX_OK;
abort_linearize:
/* Free any DMA resources we've alloced and clear out the skb
@@ -2936,7 +2943,7 @@ abort_linearize:
drop:
dev_kfree_skb_any(skb);
ss->stats.tx_dropped += 1;
- return 0;
+ return NETDEV_TX_OK;
}
@@ -2968,13 +2975,13 @@ static int myri10ge_sw_tso(struct sk_buff *skb, struct net_device *dev)
}
}
dev_kfree_skb_any(skb);
- return 0;
+ return NETDEV_TX_OK;
drop:
ss = &mgp->ss[skb_get_queue_mapping(skb)];
dev_kfree_skb_any(skb);
ss->stats.tx_dropped += 1;
- return 0;
+ return NETDEV_TX_OK;
}
static struct net_device_stats *myri10ge_get_stats(struct net_device *dev)
@@ -3427,12 +3434,13 @@ static void myri10ge_watchdog(struct work_struct *work)
container_of(work, struct myri10ge_priv, watchdog_work);
struct myri10ge_tx_buf *tx;
u32 reboot;
- int status;
+ int status, rebooted;
int i;
u16 cmd, vendor;
mgp->watchdog_resets++;
pci_read_config_word(mgp->pdev, PCI_COMMAND, &cmd);
+ rebooted = 0;
if ((cmd & PCI_COMMAND_MASTER) == 0) {
/* Bus master DMA disabled? Check to see
* if the card rebooted due to a parity error
@@ -3444,9 +3452,12 @@ static void myri10ge_watchdog(struct work_struct *work)
myri10ge_reset_recover ? " " : " not");
if (myri10ge_reset_recover == 0)
return;
-
+ rtnl_lock();
+ mgp->rebooted = 1;
+ rebooted = 1;
+ myri10ge_close(mgp->dev);
myri10ge_reset_recover--;
-
+ mgp->rebooted = 0;
/*
* A rebooted nic will come back with config space as
* it was after power was applied to PCIe bus.
@@ -3494,8 +3505,10 @@ static void myri10ge_watchdog(struct work_struct *work)
}
}
- rtnl_lock();
- myri10ge_close(mgp->dev);
+ if (!rebooted) {
+ rtnl_lock();
+ myri10ge_close(mgp->dev);
+ }
status = myri10ge_load_firmware(mgp, 1);
if (status != 0)
printk(KERN_ERR "myri10ge: %s: failed to load firmware\n",
@@ -3516,12 +3529,14 @@ static void myri10ge_watchdog_timer(unsigned long arg)
{
struct myri10ge_priv *mgp;
struct myri10ge_slice_state *ss;
- int i, reset_needed;
+ int i, reset_needed, busy_slice_cnt;
u32 rx_pause_cnt;
+ u16 cmd;
mgp = (struct myri10ge_priv *)arg;
rx_pause_cnt = ntohl(mgp->ss[0].fw_stats->dropped_pause);
+ busy_slice_cnt = 0;
for (i = 0, reset_needed = 0;
i < mgp->num_slices && reset_needed == 0; ++i) {
@@ -3559,8 +3574,22 @@ static void myri10ge_watchdog_timer(unsigned long arg)
reset_needed = 1;
}
}
+ if (ss->watchdog_tx_done != ss->tx.done ||
+ ss->watchdog_rx_done != ss->rx_done.cnt) {
+ busy_slice_cnt++;
+ }
ss->watchdog_tx_done = ss->tx.done;
ss->watchdog_tx_req = ss->tx.req;
+ ss->watchdog_rx_done = ss->rx_done.cnt;
+ }
+ /* if we've sent or received no traffic, poll the NIC to
+ * ensure it is still there. Otherwise, we risk not noticing
+ * an error in a timely fashion */
+ if (busy_slice_cnt == 0) {
+ pci_read_config_word(mgp->pdev, PCI_COMMAND, &cmd);
+ if ((cmd & PCI_COMMAND_MASTER) == 0) {
+ reset_needed = 1;
+ }
}
mgp->watchdog_pause = rx_pause_cnt;
diff --git a/drivers/net/myri_sbus.c b/drivers/net/myri_sbus.c
index 5f0758bda6b..29ebebc6a95 100644
--- a/drivers/net/myri_sbus.c
+++ b/drivers/net/myri_sbus.c
@@ -692,7 +692,7 @@ static int myri_start_xmit(struct sk_buff *skb, struct net_device *dev)
DTX(("tbusy=0, returning 0\n"));
netif_start_queue(dev);
spin_unlock_irqrestore(&mp->irq_lock, flags);
- return 0;
+ return NETDEV_TX_OK;
}
/* Create the MyriNet MAC header for an arbitrary protocol layer
diff --git a/drivers/net/natsemi.c b/drivers/net/natsemi.c
index 78c088331f5..32db12a2734 100644
--- a/drivers/net/natsemi.c
+++ b/drivers/net/natsemi.c
@@ -2125,7 +2125,7 @@ static int start_tx(struct sk_buff *skb, struct net_device *dev)
printk(KERN_DEBUG "%s: Transmit frame #%d queued in slot %d.\n",
dev->name, np->cur_tx, entry);
}
- return 0;
+ return NETDEV_TX_OK;
}
static void netdev_tx_done(struct net_device *dev)
diff --git a/drivers/net/netx-eth.c b/drivers/net/netx-eth.c
index 946366dcc99..9f4235466d5 100644
--- a/drivers/net/netx-eth.c
+++ b/drivers/net/netx-eth.c
@@ -134,7 +134,7 @@ netx_eth_hard_start_xmit(struct sk_buff *skb, struct net_device *ndev)
spin_unlock_irq(&priv->lock);
dev_kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
}
static void netx_eth_receive(struct net_device *ndev)
diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h
index a9c1fcca5e7..5abb41e2d02 100644
--- a/drivers/net/netxen/netxen_nic.h
+++ b/drivers/net/netxen/netxen_nic.h
@@ -57,8 +57,8 @@
#define _NETXEN_NIC_LINUX_MAJOR 4
#define _NETXEN_NIC_LINUX_MINOR 0
-#define _NETXEN_NIC_LINUX_SUBVERSION 30
-#define NETXEN_NIC_LINUX_VERSIONID "4.0.30"
+#define _NETXEN_NIC_LINUX_SUBVERSION 41
+#define NETXEN_NIC_LINUX_VERSIONID "4.0.41"
#define NETXEN_VERSION_CODE(a, b, c) (((a) << 24) + ((b) << 16) + (c))
#define _major(v) (((v) >> 24) & 0xff)
@@ -143,18 +143,13 @@
#define NX_ETHERMTU 1500
#define NX_MAX_ETHERHDR 32 /* This contains some padding */
-#define NX_RX_NORMAL_BUF_MAX_LEN (NX_MAX_ETHERHDR + NX_ETHERMTU)
+#define NX_P2_RX_BUF_MAX_LEN 1760
+#define NX_P3_RX_BUF_MAX_LEN (NX_MAX_ETHERHDR + NX_ETHERMTU)
#define NX_P2_RX_JUMBO_BUF_MAX_LEN (NX_MAX_ETHERHDR + P2_MAX_MTU)
#define NX_P3_RX_JUMBO_BUF_MAX_LEN (NX_MAX_ETHERHDR + P3_MAX_MTU)
#define NX_CT_DEFAULT_RX_BUF_LEN 2048
-#define MAX_RX_BUFFER_LENGTH 1760
-#define MAX_RX_JUMBO_BUFFER_LENGTH 8062
-#define MAX_RX_LRO_BUFFER_LENGTH (8062)
-#define RX_DMA_MAP_LEN (MAX_RX_BUFFER_LENGTH - 2)
-#define RX_JUMBO_DMA_MAP_LEN \
- (MAX_RX_JUMBO_BUFFER_LENGTH - 2)
-#define RX_LRO_DMA_MAP_LEN (MAX_RX_LRO_BUFFER_LENGTH - 2)
+#define NX_RX_LRO_BUFFER_LENGTH (8060)
/*
* Maximum number of ring contexts
@@ -200,13 +195,20 @@
#define RCV_RING_JUMBO 1
#define RCV_RING_LRO 2
-#define MAX_CMD_DESCRIPTORS 4096
-#define MAX_RCV_DESCRIPTORS 16384
-#define MAX_CMD_DESCRIPTORS_HOST 1024
-#define MAX_RCV_DESCRIPTORS_1G 2048
-#define MAX_RCV_DESCRIPTORS_10G 4096
-#define MAX_JUMBO_RCV_DESCRIPTORS 1024
+#define MIN_CMD_DESCRIPTORS 64
+#define MIN_RCV_DESCRIPTORS 64
+#define MIN_JUMBO_DESCRIPTORS 32
+
+#define MAX_CMD_DESCRIPTORS 1024
+#define MAX_RCV_DESCRIPTORS_1G 4096
+#define MAX_RCV_DESCRIPTORS_10G 8192
+#define MAX_JUMBO_RCV_DESCRIPTORS_1G 512
+#define MAX_JUMBO_RCV_DESCRIPTORS_10G 1024
#define MAX_LRO_RCV_DESCRIPTORS 8
+
+#define DEFAULT_RCV_DESCRIPTORS_1G 2048
+#define DEFAULT_RCV_DESCRIPTORS_10G 4096
+
#define NETXEN_CTX_SIGNATURE 0xdee0
#define NETXEN_CTX_SIGNATURE_V2 0x0002dee0
#define NETXEN_CTX_RESET 0xbad0
@@ -302,6 +304,10 @@ struct netxen_ring_ctx {
#define FLAGS_IPSEC_SA_ADD 0x04
#define FLAGS_IPSEC_SA_DELETE 0x08
#define FLAGS_VLAN_TAGGED 0x10
+#define FLAGS_VLAN_OOB 0x40
+
+#define netxen_set_tx_vlan_tci(cmd_desc, v) \
+ (cmd_desc)->vlan_TCI = cpu_to_le16(v);
#define netxen_set_cmd_desc_port(cmd_desc, var) \
((cmd_desc)->port_ctxid |= ((var) & 0x0F))
@@ -316,58 +322,33 @@ struct netxen_ring_ctx {
cpu_to_le16(((_flags) & 0x7f) | (((_opcode) & 0x3f) << 7))
#define netxen_set_tx_frags_len(_desc, _frags, _len) \
- (_desc)->num_of_buffers_total_length = \
+ (_desc)->nfrags__length = \
cpu_to_le32(((_frags) & 0xff) | (((_len) & 0xffffff) << 8))
struct cmd_desc_type0 {
u8 tcp_hdr_offset; /* For LSO only */
u8 ip_hdr_offset; /* For LSO only */
- /* Bit pattern: 0-6 flags, 7-12 opcode, 13-15 unused */
- __le16 flags_opcode;
- /* Bit pattern: 0-7 total number of segments,
- 8-31 Total size of the packet */
- __le32 num_of_buffers_total_length;
- union {
- struct {
- __le32 addr_low_part2;
- __le32 addr_high_part2;
- };
- __le64 addr_buffer2;
- };
+ __le16 flags_opcode; /* 15:13 unused, 12:7 opcode, 6:0 flags */
+ __le32 nfrags__length; /* 31:8 total len, 7:0 frag count */
+
+ __le64 addr_buffer2;
- __le16 reference_handle; /* changed to u16 to add mss */
- __le16 mss; /* passed by NDIS_PACKET for LSO */
- /* Bit pattern 0-3 port, 0-3 ctx id */
- u8 port_ctxid;
+ __le16 reference_handle;
+ __le16 mss;
+ u8 port_ctxid; /* 7:4 ctxid 3:0 port */
u8 total_hdr_length; /* LSO only : MAC+IP+TCP Hdr size */
__le16 conn_id; /* IPSec offoad only */
- union {
- struct {
- __le32 addr_low_part3;
- __le32 addr_high_part3;
- };
- __le64 addr_buffer3;
- };
- union {
- struct {
- __le32 addr_low_part1;
- __le32 addr_high_part1;
- };
- __le64 addr_buffer1;
- };
+ __le64 addr_buffer3;
+ __le64 addr_buffer1;
__le16 buffer_length[4];
- union {
- struct {
- __le32 addr_low_part4;
- __le32 addr_high_part4;
- };
- __le64 addr_buffer4;
- };
+ __le64 addr_buffer4;
- __le64 unused;
+ __le16 vlan_TCI;
+ __le16 reserved;
+ __le32 reserved2;
} __attribute__ ((aligned(64)));
@@ -380,9 +361,11 @@ struct rcv_desc {
};
/* opcode field in status_desc */
+#define NETXEN_NIC_SYN_OFFLOAD 0x03
#define NETXEN_NIC_RXPKT_DESC 0x04
#define NETXEN_OLD_RXPKT_DESC 0x3f
#define NETXEN_NIC_RESPONSE_DESC 0x05
+#define NETXEN_NIC_LRO_DESC 0x12
/* for status field in status_desc */
#define STATUS_NEED_CKSUM (1)
@@ -416,6 +399,24 @@ struct rcv_desc {
#define netxen_get_sts_opcode(sts_data) \
(((sts_data) >> 58) & 0x03F)
+#define netxen_get_lro_sts_refhandle(sts_data) \
+ ((sts_data) & 0x0FFFF)
+#define netxen_get_lro_sts_length(sts_data) \
+ (((sts_data) >> 16) & 0x0FFFF)
+#define netxen_get_lro_sts_l2_hdr_offset(sts_data) \
+ (((sts_data) >> 32) & 0x0FF)
+#define netxen_get_lro_sts_l4_hdr_offset(sts_data) \
+ (((sts_data) >> 40) & 0x0FF)
+#define netxen_get_lro_sts_timestamp(sts_data) \
+ (((sts_data) >> 48) & 0x1)
+#define netxen_get_lro_sts_type(sts_data) \
+ (((sts_data) >> 49) & 0x7)
+#define netxen_get_lro_sts_push_flag(sts_data) \
+ (((sts_data) >> 52) & 0x1)
+#define netxen_get_lro_sts_seq_number(sts_data) \
+ ((sts_data) & 0x0FFFFFFFF)
+
+
struct status_desc {
__le64 status_desc_data[2];
} __attribute__ ((aligned(16)));
@@ -459,154 +460,6 @@ struct status_desc {
#define NETXEN_BRDTYPE_P3_10G_XFP 0x0032
#define NETXEN_BRDTYPE_P3_10G_TP 0x0080
-struct netxen_board_info {
- u32 header_version;
-
- u32 board_mfg;
- u32 board_type;
- u32 board_num;
- u32 chip_id;
- u32 chip_minor;
- u32 chip_major;
- u32 chip_pkg;
- u32 chip_lot;
-
- u32 port_mask; /* available niu ports */
- u32 peg_mask; /* available pegs */
- u32 icache_ok; /* can we run with icache? */
- u32 dcache_ok; /* can we run with dcache? */
- u32 casper_ok;
-
- u32 mac_addr_lo_0;
- u32 mac_addr_lo_1;
- u32 mac_addr_lo_2;
- u32 mac_addr_lo_3;
-
- /* MN-related config */
- u32 mn_sync_mode; /* enable/ sync shift cclk/ sync shift mclk */
- u32 mn_sync_shift_cclk;
- u32 mn_sync_shift_mclk;
- u32 mn_wb_en;
- u32 mn_crystal_freq; /* in MHz */
- u32 mn_speed; /* in MHz */
- u32 mn_org;
- u32 mn_depth;
- u32 mn_ranks_0; /* ranks per slot */
- u32 mn_ranks_1; /* ranks per slot */
- u32 mn_rd_latency_0;
- u32 mn_rd_latency_1;
- u32 mn_rd_latency_2;
- u32 mn_rd_latency_3;
- u32 mn_rd_latency_4;
- u32 mn_rd_latency_5;
- u32 mn_rd_latency_6;
- u32 mn_rd_latency_7;
- u32 mn_rd_latency_8;
- u32 mn_dll_val[18];
- u32 mn_mode_reg; /* MIU DDR Mode Register */
- u32 mn_ext_mode_reg; /* MIU DDR Extended Mode Register */
- u32 mn_timing_0; /* MIU Memory Control Timing Rgister */
- u32 mn_timing_1; /* MIU Extended Memory Ctrl Timing Register */
- u32 mn_timing_2; /* MIU Extended Memory Ctrl Timing2 Register */
-
- /* SN-related config */
- u32 sn_sync_mode; /* enable/ sync shift cclk / sync shift mclk */
- u32 sn_pt_mode; /* pass through mode */
- u32 sn_ecc_en;
- u32 sn_wb_en;
- u32 sn_crystal_freq;
- u32 sn_speed;
- u32 sn_org;
- u32 sn_depth;
- u32 sn_dll_tap;
- u32 sn_rd_latency;
-
- u32 mac_addr_hi_0;
- u32 mac_addr_hi_1;
- u32 mac_addr_hi_2;
- u32 mac_addr_hi_3;
-
- u32 magic; /* indicates flash has been initialized */
-
- u32 mn_rdimm;
- u32 mn_dll_override;
-
-};
-
-#define FLASH_NUM_PORTS (4)
-
-struct netxen_flash_mac_addr {
- u32 flash_addr[32];
-};
-
-struct netxen_user_old_info {
- u8 flash_md5[16];
- u8 crbinit_md5[16];
- u8 brdcfg_md5[16];
- /* bootloader */
- u32 bootld_version;
- u32 bootld_size;
- u8 bootld_md5[16];
- /* image */
- u32 image_version;
- u32 image_size;
- u8 image_md5[16];
- /* primary image status */
- u32 primary_status;
- u32 secondary_present;
-
- /* MAC address , 4 ports */
- struct netxen_flash_mac_addr mac_addr[FLASH_NUM_PORTS];
-};
-#define FLASH_NUM_MAC_PER_PORT 32
-struct netxen_user_info {
- u8 flash_md5[16 * 64];
- /* bootloader */
- u32 bootld_version;
- u32 bootld_size;
- /* image */
- u32 image_version;
- u32 image_size;
- /* primary image status */
- u32 primary_status;
- u32 secondary_present;
-
- /* MAC address , 4 ports, 32 address per port */
- u64 mac_addr[FLASH_NUM_PORTS * FLASH_NUM_MAC_PER_PORT];
- u32 sub_sys_id;
- u8 serial_num[32];
-
- /* Any user defined data */
-};
-
-/*
- * Flash Layout - new format.
- */
-struct netxen_new_user_info {
- u8 flash_md5[16 * 64];
- /* bootloader */
- u32 bootld_version;
- u32 bootld_size;
- /* image */
- u32 image_version;
- u32 image_size;
- /* primary image status */
- u32 primary_status;
- u32 secondary_present;
-
- /* MAC address , 4 ports, 32 address per port */
- u64 mac_addr[FLASH_NUM_PORTS * FLASH_NUM_MAC_PER_PORT];
- u32 sub_sys_id;
- u8 serial_num[32];
-
- /* Any user defined data */
-};
-
-#define SECONDARY_IMAGE_PRESENT 0xb3b4b5b6
-#define SECONDARY_IMAGE_ABSENT 0xffffffff
-#define PRIMARY_IMAGE_GOOD 0x5a5a5a5a
-#define PRIMARY_IMAGE_BAD 0xffffffff
-
/* Flash memory map */
#define NETXEN_CRBINIT_START 0 /* crbinit section */
#define NETXEN_BRDCFG_START 0x4000 /* board config */
@@ -617,28 +470,25 @@ struct netxen_new_user_info {
#define NETXEN_PXE_START 0x3E0000 /* PXE boot rom */
#define NETXEN_USER_START 0x3E8000 /* Firmare info */
#define NETXEN_FIXED_START 0x3F0000 /* backup of crbinit */
+#define NETXEN_USER_START_OLD NETXEN_PXE_START /* very old flash */
+#define NX_OLD_MAC_ADDR_OFFSET (NETXEN_USER_START)
#define NX_FW_VERSION_OFFSET (NETXEN_USER_START+0x408)
#define NX_FW_SIZE_OFFSET (NETXEN_USER_START+0x40c)
+#define NX_FW_MAC_ADDR_OFFSET (NETXEN_USER_START+0x418)
+#define NX_FW_SERIAL_NUM_OFFSET (NETXEN_USER_START+0x81c)
#define NX_BIOS_VERSION_OFFSET (NETXEN_USER_START+0x83c)
+
+#define NX_HDR_VERSION_OFFSET (NETXEN_BRDCFG_START)
+#define NX_BRDTYPE_OFFSET (NETXEN_BRDCFG_START+0x8)
#define NX_FW_MAGIC_OFFSET (NETXEN_BRDCFG_START+0x128)
+
#define NX_FW_MIN_SIZE (0x3fffff)
#define NX_P2_MN_ROMIMAGE 0
#define NX_P3_CT_ROMIMAGE 1
#define NX_P3_MN_ROMIMAGE 2
#define NX_FLASH_ROMIMAGE 3
-#define NETXEN_USER_START_OLD NETXEN_PXE_START /* for backward compatibility */
-
-#define NETXEN_FLASH_START (NETXEN_CRBINIT_START)
-#define NETXEN_INIT_SECTOR (0)
-#define NETXEN_PRIMARY_START (NETXEN_BOOTLD_START)
-#define NETXEN_FLASH_CRBINIT_SIZE (0x4000)
-#define NETXEN_FLASH_BRDCFG_SIZE (sizeof(struct netxen_board_info))
-#define NETXEN_FLASH_USER_SIZE (sizeof(struct netxen_user_info)/sizeof(u32))
-#define NETXEN_FLASH_SECONDARY_SIZE (NETXEN_USER_START-NETXEN_SECONDARY_START)
-#define NETXEN_NUM_PRIMARY_SECTORS (0x20)
-#define NETXEN_NUM_CONFIG_SECTORS (1)
extern char netxen_nic_driver_name[];
/* Number of status descriptors to handle per interrupt */
@@ -881,6 +731,7 @@ struct netxen_recv_context {
#define NX_CAP0_LSO NX_CAP_BIT(0, 6)
#define NX_CAP0_JUMBO_CONTIGUOUS NX_CAP_BIT(0, 7)
#define NX_CAP0_LRO_CONTIGUOUS NX_CAP_BIT(0, 8)
+#define NX_CAP0_HW_LRO NX_CAP_BIT(0, 10)
/*
* Context state
@@ -1078,6 +929,9 @@ typedef struct {
#define NX_MAC_EVENT 0x1
+#define NX_IP_UP 2
+#define NX_IP_DOWN 3
+
/*
* Driver --> Firmware
*/
@@ -1132,6 +986,10 @@ typedef struct {
#define NX_FW_CAPABILITY_LINK_NOTIFICATION (1 << 5)
#define NX_FW_CAPABILITY_SWITCHING (1 << 6)
+#define NX_FW_CAPABILITY_PEXQ (1 << 7)
+#define NX_FW_CAPABILITY_BDG (1 << 8)
+#define NX_FW_CAPABILITY_FVLANTX (1 << 9)
+#define NX_FW_CAPABILITY_HW_LRO (1 << 10)
/* module types */
#define LINKEVENT_MODULE_NOT_PRESENT 1
@@ -1315,29 +1173,11 @@ struct netxen_adapter {
nx_nic_intr_coalesce_t coal;
- u32 fw_major;
+ u32 resv5;
u32 fw_version;
const struct firmware *fw;
};
-/*
- * NetXen dma watchdog control structure
- *
- * Bit 0 : enabled => R/O: 1 watchdog active, 0 inactive
- * Bit 1 : disable_request => 1 req disable dma watchdog
- * Bit 2 : enable_request => 1 req enable dma watchdog
- * Bit 3-31 : unused
- */
-
-#define netxen_set_dma_watchdog_disable_req(config_word) \
- _netxen_set_bits(config_word, 1, 1, 1)
-#define netxen_set_dma_watchdog_enable_req(config_word) \
- _netxen_set_bits(config_word, 2, 1, 1)
-#define netxen_get_dma_watchdog_enabled(config_word) \
- ((config_word) & 0x1)
-#define netxen_get_dma_watchdog_disabled(config_word) \
- (((config_word) >> 1) & 0x1)
-
int netxen_niu_xgbe_enable_phy_interrupts(struct netxen_adapter *adapter);
int netxen_niu_gbe_enable_phy_interrupts(struct netxen_adapter *adapter);
int netxen_niu_xgbe_disable_phy_interrupts(struct netxen_adapter *adapter);
@@ -1398,8 +1238,9 @@ unsigned long netxen_nic_pci_set_window_2M(struct netxen_adapter *adapter,
unsigned long long addr);
/* Functions from netxen_nic_init.c */
-void netxen_free_adapter_offload(struct netxen_adapter *adapter);
-int netxen_initialize_adapter_offload(struct netxen_adapter *adapter);
+int netxen_init_dummy_dma(struct netxen_adapter *adapter);
+void netxen_free_dummy_dma(struct netxen_adapter *adapter);
+
int netxen_phantom_init(struct netxen_adapter *adapter, int pegtune_val);
int netxen_load_firmware(struct netxen_adapter *adapter);
int netxen_need_fw_reset(struct netxen_adapter *adapter);
@@ -1443,6 +1284,7 @@ void netxen_p3_free_mac_list(struct netxen_adapter *adapter);
int netxen_p3_nic_set_promisc(struct netxen_adapter *adapter, u32);
int netxen_config_intr_coalesce(struct netxen_adapter *adapter);
int netxen_config_rss(struct netxen_adapter *adapter, int enable);
+int netxen_config_ipaddr(struct netxen_adapter *adapter, u32 ip, int cmd);
int netxen_linkevent_request(struct netxen_adapter *adapter, int enable);
void netxen_advert_link_change(struct netxen_adapter *adapter, int linkup);
@@ -1455,6 +1297,9 @@ struct net_device_stats *netxen_nic_get_stats(struct net_device *netdev);
void netxen_nic_update_cmd_producer(struct netxen_adapter *adapter,
struct nx_host_tx_ring *tx_ring);
+/* Functions from netxen_nic_main.c */
+int netxen_nic_reset_context(struct netxen_adapter *);
+
/*
* NetXen Board information
*/
@@ -1505,56 +1350,6 @@ static inline void get_brd_name_by_type(u32 type, char *name)
name = "Unknown";
}
-static inline int
-dma_watchdog_shutdown_request(struct netxen_adapter *adapter)
-{
- u32 ctrl;
-
- /* check if already inactive */
- ctrl = adapter->hw_read_wx(adapter,
- NETXEN_CAM_RAM(NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL));
-
- if (netxen_get_dma_watchdog_enabled(ctrl) == 0)
- return 1;
-
- /* Send the disable request */
- netxen_set_dma_watchdog_disable_req(ctrl);
- NXWR32(adapter, NETXEN_CAM_RAM(NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL), ctrl);
-
- return 0;
-}
-
-static inline int
-dma_watchdog_shutdown_poll_result(struct netxen_adapter *adapter)
-{
- u32 ctrl;
-
- ctrl = adapter->hw_read_wx(adapter,
- NETXEN_CAM_RAM(NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL));
-
- return (netxen_get_dma_watchdog_enabled(ctrl) == 0);
-}
-
-static inline int
-dma_watchdog_wakeup(struct netxen_adapter *adapter)
-{
- u32 ctrl;
-
- ctrl = adapter->hw_read_wx(adapter,
- NETXEN_CAM_RAM(NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL));
-
- if (netxen_get_dma_watchdog_enabled(ctrl))
- return 1;
-
- /* send the wakeup request */
- netxen_set_dma_watchdog_enable_req(ctrl);
-
- NXWR32(adapter, NETXEN_CAM_RAM(NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL), ctrl);
-
- return 0;
-}
-
-
static inline u32 netxen_tx_avail(struct nx_host_tx_ring *tx_ring)
{
smp_mb();
diff --git a/drivers/net/netxen/netxen_nic_ctx.c b/drivers/net/netxen/netxen_nic_ctx.c
index 9f8ae4719e2..412d65829d2 100644
--- a/drivers/net/netxen/netxen_nic_ctx.c
+++ b/drivers/net/netxen/netxen_nic_ctx.c
@@ -203,6 +203,8 @@ nx_fw_cmd_create_rx_ctx(struct netxen_adapter *adapter)
cap = (NX_CAP0_LEGACY_CONTEXT | NX_CAP0_LEGACY_MN);
cap |= (NX_CAP0_JUMBO_CONTIGUOUS | NX_CAP0_LRO_CONTIGUOUS);
+ if (adapter->capabilities & NX_FW_CAPABILITY_HW_LRO)
+ cap |= NX_CAP0_HW_LRO;
prq->capabilities[0] = cpu_to_le32(cap);
prq->host_int_crb_mode =
@@ -647,7 +649,7 @@ int netxen_alloc_hw_resources(struct netxen_adapter *adapter)
}
rds_ring->desc_head = (struct rcv_desc *)addr;
- if (adapter->fw_major < 4)
+ if (NX_IS_REVISION_P2(adapter->ahw.revision_id))
rds_ring->crb_rcv_producer =
recv_crb_registers[port].crb_rcv_producer[ring];
}
@@ -675,7 +677,7 @@ int netxen_alloc_hw_resources(struct netxen_adapter *adapter)
}
- if (adapter->fw_major >= 4) {
+ if (!NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
err = nx_fw_cmd_create_rx_ctx(adapter);
if (err)
goto err_out_free;
@@ -705,7 +707,7 @@ void netxen_free_hw_resources(struct netxen_adapter *adapter)
int port = adapter->portnum;
- if (adapter->fw_major >= 4) {
+ if (!NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
nx_fw_cmd_destroy_rx_ctx(adapter);
nx_fw_cmd_destroy_tx_ctx(adapter);
} else {
diff --git a/drivers/net/netxen/netxen_nic_ethtool.c b/drivers/net/netxen/netxen_nic_ethtool.c
index e16ea46c24b..39a308c363c 100644
--- a/drivers/net/netxen/netxen_nic_ethtool.c
+++ b/drivers/net/netxen/netxen_nic_ethtool.c
@@ -490,28 +490,86 @@ netxen_nic_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
}
static void
-netxen_nic_get_ringparam(struct net_device *dev, struct ethtool_ringparam *ring)
+netxen_nic_get_ringparam(struct net_device *dev,
+ struct ethtool_ringparam *ring)
{
struct netxen_adapter *adapter = netdev_priv(dev);
- ring->rx_pending = 0;
- ring->rx_jumbo_pending = 0;
- ring->rx_pending += adapter->recv_ctx.
- rds_rings[RCV_RING_NORMAL].num_desc;
- ring->rx_jumbo_pending += adapter->recv_ctx.
- rds_rings[RCV_RING_JUMBO].num_desc;
+ ring->rx_pending = adapter->num_rxd;
+ ring->rx_jumbo_pending = adapter->num_jumbo_rxd;
+ ring->rx_jumbo_pending += adapter->num_lro_rxd;
ring->tx_pending = adapter->num_txd;
- if (adapter->ahw.port_type == NETXEN_NIC_GBE)
+ if (adapter->ahw.port_type == NETXEN_NIC_GBE) {
ring->rx_max_pending = MAX_RCV_DESCRIPTORS_1G;
- else
+ ring->rx_jumbo_max_pending = MAX_JUMBO_RCV_DESCRIPTORS_1G;
+ } else {
ring->rx_max_pending = MAX_RCV_DESCRIPTORS_10G;
- ring->tx_max_pending = MAX_CMD_DESCRIPTORS_HOST;
- ring->rx_jumbo_max_pending = MAX_JUMBO_RCV_DESCRIPTORS;
+ ring->rx_jumbo_max_pending = MAX_JUMBO_RCV_DESCRIPTORS_10G;
+ }
+
+ ring->tx_max_pending = MAX_CMD_DESCRIPTORS;
+
ring->rx_mini_max_pending = 0;
ring->rx_mini_pending = 0;
}
+static u32
+netxen_validate_ringparam(u32 val, u32 min, u32 max, char *r_name)
+{
+ u32 num_desc;
+ num_desc = max(val, min);
+ num_desc = min(num_desc, max);
+ num_desc = roundup_pow_of_two(num_desc);
+
+ if (val != num_desc) {
+ printk(KERN_INFO "%s: setting %s ring size %d instead of %d\n",
+ netxen_nic_driver_name, r_name, num_desc, val);
+ }
+
+ return num_desc;
+}
+
+static int
+netxen_nic_set_ringparam(struct net_device *dev,
+ struct ethtool_ringparam *ring)
+{
+ struct netxen_adapter *adapter = netdev_priv(dev);
+ u16 max_rcv_desc = MAX_RCV_DESCRIPTORS_10G;
+ u16 max_jumbo_desc = MAX_JUMBO_RCV_DESCRIPTORS_10G;
+ u16 num_rxd, num_jumbo_rxd, num_txd;
+
+ if (NX_IS_REVISION_P2(adapter->ahw.revision_id))
+ return -EOPNOTSUPP;
+
+ if (ring->rx_mini_pending)
+ return -EOPNOTSUPP;
+
+ if (adapter->ahw.port_type == NETXEN_NIC_GBE) {
+ max_rcv_desc = MAX_RCV_DESCRIPTORS_1G;
+ max_jumbo_desc = MAX_JUMBO_RCV_DESCRIPTORS_10G;
+ }
+
+ num_rxd = netxen_validate_ringparam(ring->rx_pending,
+ MIN_RCV_DESCRIPTORS, max_rcv_desc, "rx");
+
+ num_jumbo_rxd = netxen_validate_ringparam(ring->rx_jumbo_pending,
+ MIN_JUMBO_DESCRIPTORS, max_jumbo_desc, "rx jumbo");
+
+ num_txd = netxen_validate_ringparam(ring->tx_pending,
+ MIN_CMD_DESCRIPTORS, MAX_CMD_DESCRIPTORS, "tx");
+
+ if (num_rxd == adapter->num_rxd && num_txd == adapter->num_txd &&
+ num_jumbo_rxd == adapter->num_jumbo_rxd)
+ return 0;
+
+ adapter->num_rxd = num_rxd;
+ adapter->num_jumbo_rxd = num_jumbo_rxd;
+ adapter->num_txd = num_txd;
+
+ return netxen_nic_reset_context(adapter);
+}
+
static void
netxen_nic_get_pauseparam(struct net_device *dev,
struct ethtool_pauseparam *pause)
@@ -893,6 +951,7 @@ struct ethtool_ops netxen_nic_ethtool_ops = {
.get_eeprom_len = netxen_nic_get_eeprom_len,
.get_eeprom = netxen_nic_get_eeprom,
.get_ringparam = netxen_nic_get_ringparam,
+ .set_ringparam = netxen_nic_set_ringparam,
.get_pauseparam = netxen_nic_get_pauseparam,
.set_pauseparam = netxen_nic_set_pauseparam,
.set_tx_csum = ethtool_op_set_tx_csum,
diff --git a/drivers/net/netxen/netxen_nic_hdr.h b/drivers/net/netxen/netxen_nic_hdr.h
index 82410367564..a7328584a21 100644
--- a/drivers/net/netxen/netxen_nic_hdr.h
+++ b/drivers/net/netxen/netxen_nic_hdr.h
@@ -852,7 +852,7 @@ enum {
#define NX_PEG_TUNE_MN_PRESENT 0x1
#define NX_PEG_TUNE_CAPABILITY (NETXEN_CAM_RAM(0x02c))
-#define NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL (0x14)
+#define NETXEN_DMA_WATCHDOG_CTRL (NETXEN_CAM_RAM(0x14))
#define NETXEN_PEG_ALIVE_COUNTER (NETXEN_CAM_RAM(0xb0))
#define ISR_MSI_INT_TRIGGER(FUNC) (NETXEN_PCIX_PS_REG(PCIX_MSI_F(FUNC)))
diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c
index b9123d445c9..673dcf5ea53 100644
--- a/drivers/net/netxen/netxen_nic_hw.c
+++ b/drivers/net/netxen/netxen_nic_hw.c
@@ -706,6 +706,30 @@ int netxen_config_rss(struct netxen_adapter *adapter, int enable)
return rv;
}
+int netxen_config_ipaddr(struct netxen_adapter *adapter, u32 ip, int cmd)
+{
+ nx_nic_req_t req;
+ u64 word;
+ int rv;
+
+ memset(&req, 0, sizeof(nx_nic_req_t));
+ req.qhdr = cpu_to_le64(NX_HOST_REQUEST << 23);
+
+ word = NX_NIC_H2C_OPCODE_CONFIG_IPADDR | ((u64)adapter->portnum << 16);
+ req.req_hdr = cpu_to_le64(word);
+
+ req.words[0] = cpu_to_le64(cmd);
+ req.words[1] = cpu_to_le64(ip);
+
+ rv = netxen_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1);
+ if (rv != 0) {
+ printk(KERN_ERR "%s: could not notify %s IP 0x%x reuqest\n",
+ adapter->netdev->name,
+ (cmd == NX_IP_UP) ? "Add" : "Remove", ip);
+ }
+ return rv;
+}
+
int netxen_linkevent_request(struct netxen_adapter *adapter, int enable)
{
nx_nic_req_t req;
@@ -792,18 +816,15 @@ int netxen_get_flash_mac_addr(struct netxen_adapter *adapter, __le64 *mac)
__le32 *pmac = (__le32 *) mac;
u32 offset;
- offset = NETXEN_USER_START +
- offsetof(struct netxen_new_user_info, mac_addr) +
- adapter->portnum * sizeof(u64);
+ offset = NX_FW_MAC_ADDR_OFFSET + (adapter->portnum * sizeof(u64));
if (netxen_get_flash_block(adapter, offset, sizeof(u64), pmac) == -1)
return -1;
if (*mac == cpu_to_le64(~0ULL)) {
- offset = NETXEN_USER_START_OLD +
- offsetof(struct netxen_user_old_info, mac_addr) +
- adapter->portnum * sizeof(u64);
+ offset = NX_OLD_MAC_ADDR_OFFSET +
+ (adapter->portnum * sizeof(u64));
if (netxen_get_flash_block(adapter,
offset, sizeof(u64), pmac) == -1)
@@ -1833,13 +1854,11 @@ int netxen_nic_get_board_info(struct netxen_adapter *adapter)
int offset, board_type, magic, header_version;
struct pci_dev *pdev = adapter->pdev;
- offset = NETXEN_BRDCFG_START +
- offsetof(struct netxen_board_info, magic);
+ offset = NX_FW_MAGIC_OFFSET;
if (netxen_rom_fast_read(adapter, offset, &magic))
return -EIO;
- offset = NETXEN_BRDCFG_START +
- offsetof(struct netxen_board_info, header_version);
+ offset = NX_HDR_VERSION_OFFSET;
if (netxen_rom_fast_read(adapter, offset, &header_version))
return -EIO;
@@ -1851,8 +1870,7 @@ int netxen_nic_get_board_info(struct netxen_adapter *adapter)
return -EIO;
}
- offset = NETXEN_BRDCFG_START +
- offsetof(struct netxen_board_info, board_type);
+ offset = NX_BRDTYPE_OFFSET;
if (netxen_rom_fast_read(adapter, offset, &board_type))
return -EIO;
@@ -1998,30 +2016,28 @@ void netxen_nic_get_firmware_info(struct netxen_adapter *adapter)
u32 fw_major, fw_minor, fw_build;
char brd_name[NETXEN_MAX_SHORT_NAME];
char serial_num[32];
- int i, addr, val;
+ int i, offset, val;
int *ptr32;
struct pci_dev *pdev = adapter->pdev;
adapter->driver_mismatch = 0;
ptr32 = (int *)&serial_num;
- addr = NETXEN_USER_START +
- offsetof(struct netxen_new_user_info, serial_num);
+ offset = NX_FW_SERIAL_NUM_OFFSET;
for (i = 0; i < 8; i++) {
- if (netxen_rom_fast_read(adapter, addr, &val) == -1) {
+ if (netxen_rom_fast_read(adapter, offset, &val) == -1) {
dev_err(&pdev->dev, "error reading board info\n");
adapter->driver_mismatch = 1;
return;
}
ptr32[i] = cpu_to_le32(val);
- addr += sizeof(u32);
+ offset += sizeof(u32);
}
fw_major = NXRD32(adapter, NETXEN_FW_VERSION_MAJOR);
fw_minor = NXRD32(adapter, NETXEN_FW_VERSION_MINOR);
fw_build = NXRD32(adapter, NETXEN_FW_VERSION_SUB);
- adapter->fw_major = fw_major;
adapter->fw_version = NETXEN_VERSION_CODE(fw_major, fw_minor, fw_build);
if (adapter->portnum == 0) {
@@ -2047,6 +2063,9 @@ void netxen_nic_get_firmware_info(struct netxen_adapter *adapter)
dev_info(&pdev->dev, "firmware running in %s mode\n",
adapter->ahw.cut_through ? "cut-through" : "legacy");
}
+
+ if (adapter->fw_version >= NETXEN_VERSION_CODE(4, 0, 222))
+ adapter->capabilities = NXRD32(adapter, CRB_FW_CAPABILITIES_1);
}
int
diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c
index 5d3343ef3d8..e8bdbf9fefb 100644
--- a/drivers/net/netxen/netxen_nic_init.c
+++ b/drivers/net/netxen/netxen_nic_init.c
@@ -247,9 +247,14 @@ int netxen_alloc_sw_resources(struct netxen_adapter *adapter)
rds_ring->skb_size =
NX_CT_DEFAULT_RX_BUF_LEN;
} else {
- rds_ring->dma_size = RX_DMA_MAP_LEN;
+ if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
+ rds_ring->dma_size =
+ NX_P3_RX_BUF_MAX_LEN;
+ else
+ rds_ring->dma_size =
+ NX_P2_RX_BUF_MAX_LEN;
rds_ring->skb_size =
- MAX_RX_BUFFER_LENGTH;
+ rds_ring->dma_size + NET_IP_ALIGN;
}
break;
@@ -267,8 +272,8 @@ int netxen_alloc_sw_resources(struct netxen_adapter *adapter)
case RCV_RING_LRO:
rds_ring->num_desc = adapter->num_lro_rxd;
- rds_ring->dma_size = RX_LRO_DMA_MAP_LEN;
- rds_ring->skb_size = MAX_RX_LRO_BUFFER_LENGTH;
+ rds_ring->dma_size = NX_RX_LRO_BUFFER_LENGTH;
+ rds_ring->skb_size = rds_ring->dma_size + NET_IP_ALIGN;
break;
}
@@ -880,22 +885,10 @@ netxen_validate_firmware(struct netxen_adapter *adapter, const char *fwname)
return 0;
}
-void netxen_request_firmware(struct netxen_adapter *adapter)
+static int
+netxen_p3_has_mn(struct netxen_adapter *adapter)
{
u32 capability, flashed_ver;
- u8 fw_type;
- struct pci_dev *pdev = adapter->pdev;
- int rc = 0;
-
- if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
- fw_type = NX_P2_MN_ROMIMAGE;
- goto request_fw;
- } else {
- fw_type = NX_P3_CT_ROMIMAGE;
- goto request_fw;
- }
-
-request_mn:
capability = 0;
netxen_rom_fast_read(adapter,
@@ -903,23 +896,35 @@ request_mn:
flashed_ver = NETXEN_DECODE_VERSION(flashed_ver);
if (flashed_ver >= NETXEN_VERSION_CODE(4, 0, 220)) {
+
capability = NXRD32(adapter, NX_PEG_TUNE_CAPABILITY);
- if (capability & NX_PEG_TUNE_MN_PRESENT) {
- fw_type = NX_P3_MN_ROMIMAGE;
- goto request_fw;
- }
+ if (capability & NX_PEG_TUNE_MN_PRESENT)
+ return 1;
}
+ return 0;
+}
- fw_type = NX_FLASH_ROMIMAGE;
- adapter->fw = NULL;
- goto done;
+void netxen_request_firmware(struct netxen_adapter *adapter)
+{
+ u8 fw_type;
+ struct pci_dev *pdev = adapter->pdev;
+ int rc = 0;
+
+ if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
+ fw_type = NX_P2_MN_ROMIMAGE;
+ goto request_fw;
+ }
+
+ fw_type = netxen_p3_has_mn(adapter) ?
+ NX_P3_MN_ROMIMAGE : NX_P3_CT_ROMIMAGE;
request_fw:
rc = request_firmware(&adapter->fw, fw_name[fw_type], &pdev->dev);
if (rc != 0) {
- if (fw_type == NX_P3_CT_ROMIMAGE) {
+ if (fw_type == NX_P3_MN_ROMIMAGE) {
msleep(1);
- goto request_mn;
+ fw_type = NX_P3_CT_ROMIMAGE;
+ goto request_fw;
}
fw_type = NX_FLASH_ROMIMAGE;
@@ -931,9 +936,10 @@ request_fw:
if (rc != 0) {
release_firmware(adapter->fw);
- if (fw_type == NX_P3_CT_ROMIMAGE) {
+ if (fw_type == NX_P3_MN_ROMIMAGE) {
msleep(1);
- goto request_mn;
+ fw_type = NX_P3_CT_ROMIMAGE;
+ goto request_fw;
}
fw_type = NX_FLASH_ROMIMAGE;
@@ -953,19 +959,20 @@ netxen_release_firmware(struct netxen_adapter *adapter)
release_firmware(adapter->fw);
}
-int netxen_initialize_adapter_offload(struct netxen_adapter *adapter)
+int netxen_init_dummy_dma(struct netxen_adapter *adapter)
{
- uint64_t addr;
- uint32_t hi;
- uint32_t lo;
+ u64 addr;
+ u32 hi, lo;
+
+ if (!NX_IS_REVISION_P2(adapter->ahw.revision_id))
+ return 0;
- adapter->dummy_dma.addr =
- pci_alloc_consistent(adapter->pdev,
+ adapter->dummy_dma.addr = pci_alloc_consistent(adapter->pdev,
NETXEN_HOST_DUMMY_DMA_SIZE,
&adapter->dummy_dma.phys_addr);
if (adapter->dummy_dma.addr == NULL) {
- printk("%s: ERROR: Could not allocate dummy DMA memory\n",
- __func__);
+ dev_err(&adapter->pdev->dev,
+ "ERROR: Could not allocate dummy DMA memory\n");
return -ENOMEM;
}
@@ -976,29 +983,41 @@ int netxen_initialize_adapter_offload(struct netxen_adapter *adapter)
NXWR32(adapter, CRB_HOST_DUMMY_BUF_ADDR_HI, hi);
NXWR32(adapter, CRB_HOST_DUMMY_BUF_ADDR_LO, lo);
- if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
- uint32_t temp = 0;
- NXWR32(adapter, CRB_HOST_DUMMY_BUF, temp);
- }
-
return 0;
}
-void netxen_free_adapter_offload(struct netxen_adapter *adapter)
+/*
+ * NetXen DMA watchdog control:
+ *
+ * Bit 0 : enabled => R/O: 1 watchdog active, 0 inactive
+ * Bit 1 : disable_request => 1 req disable dma watchdog
+ * Bit 2 : enable_request => 1 req enable dma watchdog
+ * Bit 3-31 : unused
+ */
+void netxen_free_dummy_dma(struct netxen_adapter *adapter)
{
int i = 100;
+ u32 ctrl;
+
+ if (!NX_IS_REVISION_P2(adapter->ahw.revision_id))
+ return;
if (!adapter->dummy_dma.addr)
return;
- if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
- do {
- if (dma_watchdog_shutdown_request(adapter) == 1)
- break;
+ ctrl = NXRD32(adapter, NETXEN_DMA_WATCHDOG_CTRL);
+ if ((ctrl & 0x1) != 0) {
+ NXWR32(adapter, NETXEN_DMA_WATCHDOG_CTRL, (ctrl | 0x2));
+
+ while ((ctrl & 0x1) != 0) {
+
msleep(50);
- if (dma_watchdog_shutdown_poll_result(adapter) == 1)
+
+ ctrl = NXRD32(adapter, NETXEN_DMA_WATCHDOG_CTRL);
+
+ if (--i == 0)
break;
- } while (--i);
+ };
}
if (i) {
@@ -1007,10 +1026,8 @@ void netxen_free_adapter_offload(struct netxen_adapter *adapter)
adapter->dummy_dma.addr,
adapter->dummy_dma.phys_addr);
adapter->dummy_dma.addr = NULL;
- } else {
- printk(KERN_ERR "%s: dma_watchdog_shutdown failed\n",
- adapter->netdev->name);
- }
+ } else
+ dev_err(&adapter->pdev->dev, "dma_watchdog_shutdown failed\n");
}
int netxen_phantom_init(struct netxen_adapter *adapter, int pegtune_val)
@@ -1083,10 +1100,6 @@ int netxen_init_firmware(struct netxen_adapter *adapter)
NXWR32(adapter, CRB_MPORT_MODE, MPORT_MULTI_FUNCTION_MODE);
NXWR32(adapter, CRB_CMDPEG_STATE, PHAN_INITIALIZE_ACK);
- if (adapter->fw_version >= NETXEN_VERSION_CODE(4, 0, 222)) {
- adapter->capabilities = NXRD32(adapter, CRB_FW_CAPABILITIES_1);
- }
-
return err;
}
@@ -1222,20 +1235,31 @@ no_skb:
static struct netxen_rx_buffer *
netxen_process_rcv(struct netxen_adapter *adapter,
- int ring, int index, int length, int cksum, int pkt_offset,
- struct nx_host_sds_ring *sds_ring)
+ struct nx_host_sds_ring *sds_ring,
+ int ring, u64 sts_data0)
{
struct net_device *netdev = adapter->netdev;
struct netxen_recv_context *recv_ctx = &adapter->recv_ctx;
struct netxen_rx_buffer *buffer;
struct sk_buff *skb;
- struct nx_host_rds_ring *rds_ring = &recv_ctx->rds_rings[ring];
+ struct nx_host_rds_ring *rds_ring;
+ int index, length, cksum, pkt_offset;
- if (unlikely(index > rds_ring->num_desc))
+ if (unlikely(ring >= adapter->max_rds_rings))
+ return NULL;
+
+ rds_ring = &recv_ctx->rds_rings[ring];
+
+ index = netxen_get_sts_refhandle(sts_data0);
+ if (unlikely(index >= rds_ring->num_desc))
return NULL;
buffer = &rds_ring->rx_buf_arr[index];
+ length = netxen_get_sts_totallength(sts_data0);
+ cksum = netxen_get_sts_status(sts_data0);
+ pkt_offset = netxen_get_sts_pkt_offset(sts_data0);
+
skb = netxen_process_rxbuf(adapter, rds_ring, index, cksum);
if (!skb)
return buffer;
@@ -1259,6 +1283,78 @@ netxen_process_rcv(struct netxen_adapter *adapter,
return buffer;
}
+#define TCP_HDR_SIZE 20
+#define TCP_TS_OPTION_SIZE 12
+#define TCP_TS_HDR_SIZE (TCP_HDR_SIZE + TCP_TS_OPTION_SIZE)
+
+static struct netxen_rx_buffer *
+netxen_process_lro(struct netxen_adapter *adapter,
+ struct nx_host_sds_ring *sds_ring,
+ int ring, u64 sts_data0, u64 sts_data1)
+{
+ struct net_device *netdev = adapter->netdev;
+ struct netxen_recv_context *recv_ctx = &adapter->recv_ctx;
+ struct netxen_rx_buffer *buffer;
+ struct sk_buff *skb;
+ struct nx_host_rds_ring *rds_ring;
+ struct iphdr *iph;
+ struct tcphdr *th;
+ bool push, timestamp;
+ int l2_hdr_offset, l4_hdr_offset;
+ int index;
+ u16 lro_length, length, data_offset;
+ u32 seq_number;
+
+ if (unlikely(ring > adapter->max_rds_rings))
+ return NULL;
+
+ rds_ring = &recv_ctx->rds_rings[ring];
+
+ index = netxen_get_lro_sts_refhandle(sts_data0);
+ if (unlikely(index > rds_ring->num_desc))
+ return NULL;
+
+ buffer = &rds_ring->rx_buf_arr[index];
+
+ timestamp = netxen_get_lro_sts_timestamp(sts_data0);
+ lro_length = netxen_get_lro_sts_length(sts_data0);
+ l2_hdr_offset = netxen_get_lro_sts_l2_hdr_offset(sts_data0);
+ l4_hdr_offset = netxen_get_lro_sts_l4_hdr_offset(sts_data0);
+ push = netxen_get_lro_sts_push_flag(sts_data0);
+ seq_number = netxen_get_lro_sts_seq_number(sts_data1);
+
+ skb = netxen_process_rxbuf(adapter, rds_ring, index, STATUS_CKSUM_OK);
+ if (!skb)
+ return buffer;
+
+ if (timestamp)
+ data_offset = l4_hdr_offset + TCP_TS_HDR_SIZE;
+ else
+ data_offset = l4_hdr_offset + TCP_HDR_SIZE;
+
+ skb_put(skb, lro_length + data_offset);
+
+ skb->truesize = (skb->len + sizeof(struct sk_buff) +
+ ((unsigned long)skb->data - (unsigned long)skb->head));
+
+ skb_pull(skb, l2_hdr_offset);
+ skb->protocol = eth_type_trans(skb, netdev);
+
+ iph = (struct iphdr *)skb->data;
+ th = (struct tcphdr *)(skb->data + (iph->ihl << 2));
+
+ length = (iph->ihl << 2) + (th->doff << 2) + lro_length;
+ iph->tot_len = htons(length);
+ iph->check = 0;
+ iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
+ th->psh = push;
+ th->seq = htonl(seq_number);
+
+ netif_receive_skb(skb);
+
+ return buffer;
+}
+
#define netxen_merge_rx_buffers(list, head) \
do { list_splice_tail_init(list, head); } while (0);
@@ -1275,27 +1371,33 @@ netxen_process_rcv_ring(struct nx_host_sds_ring *sds_ring, int max)
u32 consumer = sds_ring->consumer;
int count = 0;
- u64 sts_data;
- int opcode, ring, index, length, cksum, pkt_offset, desc_cnt;
+ u64 sts_data0, sts_data1;
+ int opcode, ring = 0, desc_cnt;
while (count < max) {
desc = &sds_ring->desc_head[consumer];
- sts_data = le64_to_cpu(desc->status_desc_data[0]);
+ sts_data0 = le64_to_cpu(desc->status_desc_data[0]);
- if (!(sts_data & STATUS_OWNER_HOST))
+ if (!(sts_data0 & STATUS_OWNER_HOST))
break;
- desc_cnt = netxen_get_sts_desc_cnt(sts_data);
- ring = netxen_get_sts_type(sts_data);
-
- if (ring > RCV_RING_JUMBO)
- goto skip;
+ desc_cnt = netxen_get_sts_desc_cnt(sts_data0);
- opcode = netxen_get_sts_opcode(sts_data);
+ opcode = netxen_get_sts_opcode(sts_data0);
switch (opcode) {
case NETXEN_NIC_RXPKT_DESC:
case NETXEN_OLD_RXPKT_DESC:
+ case NETXEN_NIC_SYN_OFFLOAD:
+ ring = netxen_get_sts_type(sts_data0);
+ rxbuf = netxen_process_rcv(adapter, sds_ring,
+ ring, sts_data0);
+ break;
+ case NETXEN_NIC_LRO_DESC:
+ ring = netxen_get_lro_sts_type(sts_data0);
+ sts_data1 = le64_to_cpu(desc->status_desc_data[1]);
+ rxbuf = netxen_process_lro(adapter, sds_ring,
+ ring, sts_data0, sts_data1);
break;
case NETXEN_NIC_RESPONSE_DESC:
netxen_handle_fw_message(desc_cnt, consumer, sds_ring);
@@ -1305,14 +1407,6 @@ netxen_process_rcv_ring(struct nx_host_sds_ring *sds_ring, int max)
WARN_ON(desc_cnt > 1);
- index = netxen_get_sts_refhandle(sts_data);
- length = netxen_get_sts_totallength(sts_data);
- cksum = netxen_get_sts_status(sts_data);
- pkt_offset = netxen_get_sts_pkt_offset(sts_data);
-
- rxbuf = netxen_process_rcv(adapter, ring, index,
- length, cksum, pkt_offset, sds_ring);
-
if (rxbuf)
list_add_tail(&rxbuf->list, &sds_ring->free_list[ring]);
@@ -1468,7 +1562,7 @@ netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ringid,
NXWR32(adapter, rds_ring->crb_rcv_producer,
(producer-1) & (rds_ring->num_desc-1));
- if (adapter->fw_major < 4) {
+ if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
/*
* Write a doorbell msg to tell phanmon of change in
* receive ring producer
diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c
index 28f270f5ac7..4e3fb30d66f 100644
--- a/drivers/net/netxen/netxen_nic_main.c
+++ b/drivers/net/netxen/netxen_nic_main.c
@@ -39,6 +39,7 @@
#include <linux/if_vlan.h>
#include <net/ip.h>
#include <linux/ipv6.h>
+#include <linux/inetdevice.h>
MODULE_DESCRIPTION("NetXen Multi port (1/10) Gigabit Network Driver");
MODULE_LICENSE("GPL");
@@ -65,7 +66,7 @@ static int netxen_nic_open(struct net_device *netdev);
static int netxen_nic_close(struct net_device *netdev);
static int netxen_nic_xmit_frame(struct sk_buff *, struct net_device *);
static void netxen_tx_timeout(struct net_device *netdev);
-static void netxen_tx_timeout_task(struct work_struct *work);
+static void netxen_reset_task(struct work_struct *work);
static void netxen_watchdog(unsigned long);
static int netxen_nic_poll(struct napi_struct *napi, int budget);
#ifdef CONFIG_NET_POLL_CONTROLLER
@@ -179,7 +180,7 @@ netxen_napi_add(struct netxen_adapter *adapter, struct net_device *netdev)
struct netxen_recv_context *recv_ctx = &adapter->recv_ctx;
if (netxen_alloc_sds_rings(recv_ctx, adapter->max_sds_rings))
- return 1;
+ return -ENOMEM;
for (ring = 0; ring < adapter->max_sds_rings; ring++) {
sds_ring = &recv_ctx->sds_rings[ring];
@@ -308,12 +309,16 @@ err_out:
return err;
}
-static void netxen_check_options(struct netxen_adapter *adapter)
+static void
+netxen_check_options(struct netxen_adapter *adapter)
{
- if (adapter->ahw.port_type == NETXEN_NIC_XGBE)
- adapter->num_rxd = MAX_RCV_DESCRIPTORS_10G;
- else if (adapter->ahw.port_type == NETXEN_NIC_GBE)
- adapter->num_rxd = MAX_RCV_DESCRIPTORS_1G;
+ if (adapter->ahw.port_type == NETXEN_NIC_XGBE) {
+ adapter->num_rxd = DEFAULT_RCV_DESCRIPTORS_10G;
+ adapter->num_jumbo_rxd = MAX_JUMBO_RCV_DESCRIPTORS_10G;
+ } else if (adapter->ahw.port_type == NETXEN_NIC_GBE) {
+ adapter->num_rxd = DEFAULT_RCV_DESCRIPTORS_1G;
+ adapter->num_jumbo_rxd = MAX_JUMBO_RCV_DESCRIPTORS_1G;
+ }
adapter->msix_supported = 0;
if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
@@ -331,11 +336,15 @@ static void netxen_check_options(struct netxen_adapter *adapter)
}
}
- adapter->num_txd = MAX_CMD_DESCRIPTORS_HOST;
- adapter->num_jumbo_rxd = MAX_JUMBO_RCV_DESCRIPTORS;
- adapter->num_lro_rxd = MAX_LRO_RCV_DESCRIPTORS;
+ adapter->num_txd = MAX_CMD_DESCRIPTORS;
- return;
+ if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
+ adapter->num_lro_rxd = MAX_LRO_RCV_DESCRIPTORS;
+ adapter->max_rds_rings = 3;
+ } else {
+ adapter->num_lro_rxd = 0;
+ adapter->max_rds_rings = 2;
+ }
}
static int
@@ -770,7 +779,7 @@ netxen_start_firmware(struct netxen_adapter *adapter, int request_fw)
}
- err = netxen_initialize_adapter_offload(adapter);
+ err = netxen_init_dummy_dma(adapter);
if (err)
return err;
@@ -786,10 +795,14 @@ wait_init:
/* Handshake with the card before we register the devices. */
err = netxen_phantom_init(adapter, NETXEN_NIC_PEG_TUNE);
if (err) {
- netxen_free_adapter_offload(adapter);
+ netxen_free_dummy_dma(adapter);
return err;
}
+ nx_update_dma_mask(adapter);
+
+ netxen_nic_get_firmware_info(adapter);
+
return 0;
}
@@ -840,6 +853,20 @@ netxen_nic_free_irq(struct netxen_adapter *adapter)
}
}
+static void
+netxen_nic_init_coalesce_defaults(struct netxen_adapter *adapter)
+{
+ adapter->coal.flags = NETXEN_NIC_INTR_DEFAULT;
+ adapter->coal.normal.data.rx_time_us =
+ NETXEN_DEFAULT_INTR_COALESCE_RX_TIME_US;
+ adapter->coal.normal.data.rx_packets =
+ NETXEN_DEFAULT_INTR_COALESCE_RX_PACKETS;
+ adapter->coal.normal.data.tx_time_us =
+ NETXEN_DEFAULT_INTR_COALESCE_TX_TIME_US;
+ adapter->coal.normal.data.tx_packets =
+ NETXEN_DEFAULT_INTR_COALESCE_TX_PACKETS;
+}
+
static int
netxen_nic_up(struct netxen_adapter *adapter, struct net_device *netdev)
{
@@ -862,6 +889,9 @@ netxen_nic_up(struct netxen_adapter *adapter, struct net_device *netdev)
if (adapter->max_sds_rings > 1)
netxen_config_rss(adapter, 1);
+ if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
+ netxen_config_intr_coalesce(adapter);
+
netxen_napi_enable(adapter);
if (adapter->capabilities & NX_FW_CAPABILITY_LINK_NOTIFICATION)
@@ -905,6 +935,9 @@ netxen_nic_attach(struct netxen_adapter *adapter)
struct nx_host_rds_ring *rds_ring;
struct nx_host_tx_ring *tx_ring;
+ if (adapter->is_up == NETXEN_ADAPTER_UP_MAGIC)
+ return 0;
+
err = netxen_init_firmware(adapter);
if (err)
return err;
@@ -913,11 +946,6 @@ netxen_nic_attach(struct netxen_adapter *adapter)
if (err)
return err;
- if (adapter->fw_major < 4)
- adapter->max_rds_rings = 3;
- else
- adapter->max_rds_rings = 2;
-
err = netxen_alloc_sw_resources(adapter);
if (err) {
printk(KERN_ERR "%s: Error in setting sw resources\n",
@@ -934,7 +962,7 @@ netxen_nic_attach(struct netxen_adapter *adapter)
goto err_out_free_sw;
}
- if (adapter->fw_major < 4) {
+ if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
tx_ring = adapter->tx_ring;
tx_ring->crb_cmd_producer = crb_cmd_producer[adapter->portnum];
tx_ring->crb_cmd_consumer = crb_cmd_consumer[adapter->portnum];
@@ -958,6 +986,9 @@ netxen_nic_attach(struct netxen_adapter *adapter)
goto err_out_free_rxbuf;
}
+ if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
+ netxen_nic_init_coalesce_defaults(adapter);
+
adapter->is_up = NETXEN_ADAPTER_UP_MAGIC;
return 0;
@@ -972,6 +1003,9 @@ err_out_free_sw:
static void
netxen_nic_detach(struct netxen_adapter *adapter)
{
+ if (adapter->is_up != NETXEN_ADAPTER_UP_MAGIC)
+ return;
+
netxen_free_hw_resources(adapter);
netxen_release_rx_buffers(adapter);
netxen_nic_free_irq(adapter);
@@ -981,6 +1015,95 @@ netxen_nic_detach(struct netxen_adapter *adapter)
adapter->is_up = 0;
}
+int
+netxen_nic_reset_context(struct netxen_adapter *adapter)
+{
+ int err = 0;
+ struct net_device *netdev = adapter->netdev;
+
+ if (adapter->is_up == NETXEN_ADAPTER_UP_MAGIC) {
+
+ if (netif_running(netdev))
+ netxen_nic_down(adapter, netdev);
+
+ netxen_nic_detach(adapter);
+
+ err = netxen_nic_attach(adapter);
+ if (err)
+ goto done;
+
+ if (netif_running(netdev))
+ err = netxen_nic_up(adapter, netdev);
+ }
+done:
+ return err;
+}
+
+static int
+netxen_setup_netdev(struct netxen_adapter *adapter,
+ struct net_device *netdev)
+{
+ int err = 0;
+ struct pci_dev *pdev = adapter->pdev;
+
+ adapter->rx_csum = 1;
+ adapter->mc_enabled = 0;
+ if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
+ adapter->max_mc_count = 38;
+ else
+ adapter->max_mc_count = 16;
+
+ netdev->netdev_ops = &netxen_netdev_ops;
+ netdev->watchdog_timeo = 2*HZ;
+
+ netxen_nic_change_mtu(netdev, netdev->mtu);
+
+ SET_ETHTOOL_OPS(netdev, &netxen_nic_ethtool_ops);
+
+ netdev->features |= (NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO);
+ netdev->features |= (NETIF_F_GRO);
+ netdev->vlan_features |= (NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO);
+
+ if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
+ netdev->features |= (NETIF_F_IPV6_CSUM | NETIF_F_TSO6);
+ netdev->vlan_features |= (NETIF_F_IPV6_CSUM | NETIF_F_TSO6);
+ }
+
+ if (adapter->pci_using_dac) {
+ netdev->features |= NETIF_F_HIGHDMA;
+ netdev->vlan_features |= NETIF_F_HIGHDMA;
+ }
+
+ if (adapter->capabilities & NX_FW_CAPABILITY_FVLANTX)
+ netdev->features |= (NETIF_F_HW_VLAN_TX);
+
+ netdev->irq = adapter->msix_entries[0].vector;
+
+ err = netxen_napi_add(adapter, netdev);
+ if (err)
+ return err;
+
+ init_timer(&adapter->watchdog_timer);
+ adapter->watchdog_timer.function = &netxen_watchdog;
+ adapter->watchdog_timer.data = (unsigned long)adapter;
+ INIT_WORK(&adapter->watchdog_task, netxen_watchdog_task);
+ INIT_WORK(&adapter->tx_timeout_task, netxen_reset_task);
+
+ if (netxen_read_mac_addr(adapter))
+ dev_warn(&pdev->dev, "failed to read mac addr\n");
+
+ netif_carrier_off(netdev);
+ netif_stop_queue(netdev);
+
+ err = register_netdev(netdev);
+ if (err) {
+ dev_err(&pdev->dev, "failed to register net device\n");
+ return err;
+ }
+
+ return 0;
+}
+
static int __devinit
netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
@@ -1018,9 +1141,8 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
netdev = alloc_etherdev(sizeof(struct netxen_adapter));
if(!netdev) {
- printk(KERN_ERR"%s: Failed to allocate memory for the "
- "device block.Check system memory resource"
- " usage.\n", netxen_nic_driver_name);
+ dev_err(&pdev->dev, "failed to allocate net_device\n");
+ err = -ENOMEM;
goto err_out_free_res;
}
@@ -1048,38 +1170,10 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
/* This will be reset for mezz cards */
adapter->portnum = pci_func_id;
- adapter->rx_csum = 1;
- adapter->mc_enabled = 0;
- if (NX_IS_REVISION_P3(revision_id))
- adapter->max_mc_count = 38;
- else
- adapter->max_mc_count = 16;
-
- netdev->netdev_ops = &netxen_netdev_ops;
- netdev->watchdog_timeo = 2*HZ;
- netxen_nic_change_mtu(netdev, netdev->mtu);
-
- SET_ETHTOOL_OPS(netdev, &netxen_nic_ethtool_ops);
-
- netdev->features |= (NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO);
- netdev->features |= (NETIF_F_GRO);
- netdev->vlan_features |= (NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO);
-
- if (NX_IS_REVISION_P3(revision_id)) {
- netdev->features |= (NETIF_F_IPV6_CSUM | NETIF_F_TSO6);
- netdev->vlan_features |= (NETIF_F_IPV6_CSUM | NETIF_F_TSO6);
- }
-
- if (adapter->pci_using_dac) {
- netdev->features |= NETIF_F_HIGHDMA;
- netdev->vlan_features |= NETIF_F_HIGHDMA;
- }
-
- if (netxen_nic_get_board_info(adapter) != 0) {
- printk("%s: Error getting board config info.\n",
- netxen_nic_driver_name);
- err = -EIO;
+ err = netxen_nic_get_board_info(adapter);
+ if (err) {
+ dev_err(&pdev->dev, "Error getting board config info.\n");
goto err_out_iounmap;
}
@@ -1100,15 +1194,11 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
if (err)
goto err_out_iounmap;
- nx_update_dma_mask(adapter);
-
- netxen_nic_get_firmware_info(adapter);
-
/*
* See if the firmware gave us a virtual-physical port mapping.
*/
adapter->physical_port = adapter->portnum;
- if (adapter->fw_major < 4) {
+ if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
i = NXRD32(adapter, CRB_V2P(adapter->portnum));
if (i != 0x55555555)
adapter->physical_port = i;
@@ -1118,28 +1208,9 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
netxen_setup_intr(adapter);
- netdev->irq = adapter->msix_entries[0].vector;
-
- init_timer(&adapter->watchdog_timer);
- adapter->watchdog_timer.function = &netxen_watchdog;
- adapter->watchdog_timer.data = (unsigned long)adapter;
- INIT_WORK(&adapter->watchdog_task, netxen_watchdog_task);
- INIT_WORK(&adapter->tx_timeout_task, netxen_tx_timeout_task);
-
- err = netxen_read_mac_addr(adapter);
+ err = netxen_setup_netdev(adapter, netdev);
if (err)
- dev_warn(&pdev->dev, "failed to read mac addr\n");
-
- netif_carrier_off(netdev);
- netif_stop_queue(netdev);
-
- if ((err = register_netdev(netdev))) {
- printk(KERN_ERR "%s: register_netdev failed port #%d"
- " aborting\n", netxen_nic_driver_name,
- adapter->portnum);
- err = -EIO;
goto err_out_disable_msi;
- }
pci_set_drvdata(pdev, adapter);
@@ -1159,7 +1230,7 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
err_out_disable_msi:
netxen_teardown_intr(adapter);
- netxen_free_adapter_offload(adapter);
+ netxen_free_dummy_dma(adapter);
err_out_iounmap:
netxen_cleanup_pci_map(adapter);
@@ -1192,12 +1263,10 @@ static void __devexit netxen_nic_remove(struct pci_dev *pdev)
cancel_work_sync(&adapter->watchdog_task);
cancel_work_sync(&adapter->tx_timeout_task);
- if (adapter->is_up == NETXEN_ADAPTER_UP_MAGIC) {
- netxen_nic_detach(adapter);
- }
+ netxen_nic_detach(adapter);
if (adapter->portnum == 0)
- netxen_free_adapter_offload(adapter);
+ netxen_free_dummy_dma(adapter);
netxen_teardown_intr(adapter);
@@ -1228,8 +1297,7 @@ netxen_nic_suspend(struct pci_dev *pdev, pm_message_t state)
cancel_work_sync(&adapter->watchdog_task);
cancel_work_sync(&adapter->tx_timeout_task);
- if (adapter->is_up == NETXEN_ADAPTER_UP_MAGIC)
- netxen_nic_detach(adapter);
+ netxen_nic_detach(adapter);
pci_save_state(pdev);
@@ -1290,11 +1358,9 @@ static int netxen_nic_open(struct net_device *netdev)
if (adapter->driver_mismatch)
return -EIO;
- if (adapter->is_up != NETXEN_ADAPTER_UP_MAGIC) {
- err = netxen_nic_attach(adapter);
- if (err)
- return err;
- }
+ err = netxen_nic_attach(adapter);
+ if (err)
+ return err;
err = netxen_nic_up(adapter, netdev);
if (err)
@@ -1320,30 +1386,52 @@ static int netxen_nic_close(struct net_device *netdev)
return 0;
}
-static bool netxen_tso_check(struct net_device *netdev,
- struct cmd_desc_type0 *desc, struct sk_buff *skb)
+static void
+netxen_tso_check(struct net_device *netdev,
+ struct nx_host_tx_ring *tx_ring,
+ struct cmd_desc_type0 *first_desc,
+ struct sk_buff *skb)
{
- bool tso = false;
u8 opcode = TX_ETHER_PKT;
__be16 protocol = skb->protocol;
- u16 flags = 0;
+ u16 flags = 0, vid = 0;
+ u32 producer;
+ int copied, offset, copy_len, hdr_len = 0, tso = 0, vlan_oob = 0;
+ struct cmd_desc_type0 *hwdesc;
+ struct vlan_ethhdr *vh;
if (protocol == cpu_to_be16(ETH_P_8021Q)) {
- struct vlan_ethhdr *vh = (struct vlan_ethhdr *)skb->data;
+
+ vh = (struct vlan_ethhdr *)skb->data;
protocol = vh->h_vlan_encapsulated_proto;
flags = FLAGS_VLAN_TAGGED;
+
+ } else if (vlan_tx_tag_present(skb)) {
+
+ flags = FLAGS_VLAN_OOB;
+ vid = vlan_tx_tag_get(skb);
+ netxen_set_tx_vlan_tci(first_desc, vid);
+ vlan_oob = 1;
}
if ((netdev->features & (NETIF_F_TSO | NETIF_F_TSO6)) &&
skb_shinfo(skb)->gso_size > 0) {
- desc->mss = cpu_to_le16(skb_shinfo(skb)->gso_size);
- desc->total_hdr_length =
- skb_transport_offset(skb) + tcp_hdrlen(skb);
+ hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
+
+ first_desc->mss = cpu_to_le16(skb_shinfo(skb)->gso_size);
+ first_desc->total_hdr_length = hdr_len;
+ if (vlan_oob) {
+ first_desc->total_hdr_length += VLAN_HLEN;
+ first_desc->tcp_hdr_offset = VLAN_HLEN;
+ first_desc->ip_hdr_offset = VLAN_HLEN;
+ /* Only in case of TSO on vlan device */
+ flags |= FLAGS_VLAN_TAGGED;
+ }
opcode = (protocol == cpu_to_be16(ETH_P_IPV6)) ?
TX_TCP_LSO6 : TX_TCP_LSO;
- tso = true;
+ tso = 1;
} else if (skb->ip_summed == CHECKSUM_PARTIAL) {
u8 l4proto;
@@ -1364,10 +1452,62 @@ static bool netxen_tso_check(struct net_device *netdev,
opcode = TX_UDPV6_PKT;
}
}
- desc->tcp_hdr_offset = skb_transport_offset(skb);
- desc->ip_hdr_offset = skb_network_offset(skb);
- netxen_set_tx_flags_opcode(desc, flags, opcode);
- return tso;
+
+ first_desc->tcp_hdr_offset += skb_transport_offset(skb);
+ first_desc->ip_hdr_offset += skb_network_offset(skb);
+ netxen_set_tx_flags_opcode(first_desc, flags, opcode);
+
+ if (!tso)
+ return;
+
+ /* For LSO, we need to copy the MAC/IP/TCP headers into
+ * the descriptor ring
+ */
+ producer = tx_ring->producer;
+ copied = 0;
+ offset = 2;
+
+ if (vlan_oob) {
+ /* Create a TSO vlan header template for firmware */
+
+ hwdesc = &tx_ring->desc_head[producer];
+ tx_ring->cmd_buf_arr[producer].skb = NULL;
+
+ copy_len = min((int)sizeof(struct cmd_desc_type0) - offset,
+ hdr_len + VLAN_HLEN);
+
+ vh = (struct vlan_ethhdr *)((char *)hwdesc + 2);
+ skb_copy_from_linear_data(skb, vh, 12);
+ vh->h_vlan_proto = htons(ETH_P_8021Q);
+ vh->h_vlan_TCI = htons(vid);
+ skb_copy_from_linear_data_offset(skb, 12,
+ (char *)vh + 16, copy_len - 16);
+
+ copied = copy_len - VLAN_HLEN;
+ offset = 0;
+
+ producer = get_next_index(producer, tx_ring->num_desc);
+ }
+
+ while (copied < hdr_len) {
+
+ copy_len = min((int)sizeof(struct cmd_desc_type0) - offset,
+ (hdr_len - copied));
+
+ hwdesc = &tx_ring->desc_head[producer];
+ tx_ring->cmd_buf_arr[producer].skb = NULL;
+
+ skb_copy_from_linear_data_offset(skb, copied,
+ (char *)hwdesc + offset, copy_len);
+
+ copied += copy_len;
+ offset = 0;
+
+ producer = get_next_index(producer, tx_ring->num_desc);
+ }
+
+ tx_ring->producer = producer;
+ barrier();
}
static void
@@ -1391,9 +1531,8 @@ netxen_clean_tx_dma_mapping(struct pci_dev *pdev,
static inline void
netxen_clear_cmddesc(u64 *desc)
{
- int i;
- for (i = 0; i < 8; i++)
- desc[i] = 0ULL;
+ desc[0] = 0ULL;
+ desc[2] = 0ULL;
}
static int
@@ -1401,18 +1540,18 @@ netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
{
struct netxen_adapter *adapter = netdev_priv(netdev);
struct nx_host_tx_ring *tx_ring = adapter->tx_ring;
- unsigned int first_seg_len = skb->len - skb->data_len;
+ struct skb_frag_struct *frag;
struct netxen_cmd_buffer *pbuf;
struct netxen_skb_frag *buffrag;
- struct cmd_desc_type0 *hwdesc;
- struct pci_dev *pdev = adapter->pdev;
+ struct cmd_desc_type0 *hwdesc, *first_desc;
+ struct pci_dev *pdev;
dma_addr_t temp_dma;
int i, k;
+ unsigned long offset;
u32 producer;
- int frag_count, no_of_desc;
+ int len, frag_count, no_of_desc;
u32 num_txd = tx_ring->num_desc;
- bool is_tso = false;
frag_count = skb_shinfo(skb)->nr_frags + 1;
@@ -1426,32 +1565,30 @@ netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
producer = tx_ring->producer;
- hwdesc = &tx_ring->desc_head[producer];
- netxen_clear_cmddesc((u64 *)hwdesc);
- pbuf = &tx_ring->cmd_buf_arr[producer];
+ pdev = adapter->pdev;
+ len = skb->len - skb->data_len;
- is_tso = netxen_tso_check(netdev, hwdesc, skb);
+ temp_dma = pci_map_single(pdev, skb->data, len, PCI_DMA_TODEVICE);
+ if (pci_dma_mapping_error(pdev, temp_dma))
+ goto drop_packet;
+ pbuf = &tx_ring->cmd_buf_arr[producer];
pbuf->skb = skb;
pbuf->frag_count = frag_count;
- buffrag = &pbuf->frag_array[0];
- temp_dma = pci_map_single(pdev, skb->data, first_seg_len,
- PCI_DMA_TODEVICE);
- if (pci_dma_mapping_error(pdev, temp_dma))
- goto drop_packet;
+ buffrag = &pbuf->frag_array[0];
buffrag->dma = temp_dma;
- buffrag->length = first_seg_len;
+ buffrag->length = len;
+
+ first_desc = hwdesc = &tx_ring->desc_head[producer];
+ netxen_clear_cmddesc((u64 *)hwdesc);
netxen_set_tx_frags_len(hwdesc, frag_count, skb->len);
netxen_set_tx_port(hwdesc, adapter->portnum);
- hwdesc->buffer_length[0] = cpu_to_le16(first_seg_len);
- hwdesc->addr_buffer1 = cpu_to_le64(buffrag->dma);
+ hwdesc->buffer_length[0] = cpu_to_le16(len);
+ hwdesc->addr_buffer1 = cpu_to_le64(temp_dma);
for (i = 1, k = 1; i < frag_count; i++, k++) {
- struct skb_frag_struct *frag;
- int len, temp_len;
- unsigned long offset;
/* move to next desc. if there is a need */
if ((i & 0x3) == 0) {
@@ -1462,11 +1599,11 @@ netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
pbuf = &tx_ring->cmd_buf_arr[producer];
pbuf->skb = NULL;
}
+ buffrag = &pbuf->frag_array[i];
frag = &skb_shinfo(skb)->frags[i - 1];
len = frag->size;
offset = frag->page_offset;
- temp_len = len;
temp_dma = pci_map_page(pdev, frag->page, offset,
len, PCI_DMA_TODEVICE);
if (pci_dma_mapping_error(pdev, temp_dma)) {
@@ -1474,11 +1611,10 @@ netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
goto drop_packet;
}
- buffrag++;
buffrag->dma = temp_dma;
- buffrag->length = temp_len;
+ buffrag->length = len;
- hwdesc->buffer_length[k] = cpu_to_le16(temp_len);
+ hwdesc->buffer_length[k] = cpu_to_le16(len);
switch (k) {
case 0:
hwdesc->addr_buffer1 = cpu_to_le64(temp_dma);
@@ -1493,53 +1629,14 @@ netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
hwdesc->addr_buffer4 = cpu_to_le64(temp_dma);
break;
}
- frag++;
}
- producer = get_next_index(producer, num_txd);
-
- /* For LSO, we need to copy the MAC/IP/TCP headers into
- * the descriptor ring
- */
- if (is_tso) {
- int hdr_len, first_hdr_len, more_hdr;
- hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
- if (hdr_len > (sizeof(struct cmd_desc_type0) - 2)) {
- first_hdr_len = sizeof(struct cmd_desc_type0) - 2;
- more_hdr = 1;
- } else {
- first_hdr_len = hdr_len;
- more_hdr = 0;
- }
- /* copy the MAC/IP/TCP headers to the cmd descriptor list */
- hwdesc = &tx_ring->desc_head[producer];
- pbuf = &tx_ring->cmd_buf_arr[producer];
- pbuf->skb = NULL;
+ tx_ring->producer = get_next_index(producer, num_txd);
- /* copy the first 64 bytes */
- memcpy(((void *)hwdesc) + 2,
- (void *)(skb->data), first_hdr_len);
- producer = get_next_index(producer, num_txd);
-
- if (more_hdr) {
- hwdesc = &tx_ring->desc_head[producer];
- pbuf = &tx_ring->cmd_buf_arr[producer];
- pbuf->skb = NULL;
- /* copy the next 64 bytes - should be enough except
- * for pathological case
- */
- skb_copy_from_linear_data_offset(skb, first_hdr_len,
- hwdesc,
- (hdr_len -
- first_hdr_len));
- producer = get_next_index(producer, num_txd);
- }
- }
-
- tx_ring->producer = producer;
- adapter->stats.txbytes += skb->len;
+ netxen_tso_check(netdev, tx_ring, first_desc, skb);
netxen_nic_update_cmd_producer(adapter, tx_ring);
+ adapter->stats.txbytes += skb->len;
adapter->stats.xmitcalled++;
return NETDEV_TX_OK;
@@ -1687,10 +1784,12 @@ void netxen_watchdog_task(struct work_struct *work)
static void netxen_tx_timeout(struct net_device *netdev)
{
struct netxen_adapter *adapter = netdev_priv(netdev);
+
+ dev_err(&netdev->dev, "transmit timeout, resetting.\n");
schedule_work(&adapter->tx_timeout_task);
}
-static void netxen_tx_timeout_task(struct work_struct *work)
+static void netxen_reset_task(struct work_struct *work)
{
struct netxen_adapter *adapter =
container_of(work, struct netxen_adapter, tx_timeout_task);
@@ -1698,9 +1797,6 @@ static void netxen_tx_timeout_task(struct work_struct *work)
if (!netif_running(adapter->netdev))
return;
- printk(KERN_ERR "%s %s: transmit timeout, resetting.\n",
- netxen_nic_driver_name, adapter->netdev->name);
-
netxen_napi_disable(adapter);
adapter->netdev->trans_start = jiffies;
@@ -1758,7 +1854,7 @@ static irqreturn_t netxen_intr(int irq, void *data)
}
/* clear interrupt */
- if (adapter->fw_major < 4)
+ if (NX_IS_REVISION_P2(adapter->ahw.revision_id))
netxen_nic_disable_int(sds_ring);
adapter->pci_write_immediate(adapter,
@@ -1827,6 +1923,128 @@ static void netxen_nic_poll_controller(struct net_device *netdev)
}
#endif
+#ifdef CONFIG_INET
+
+#define is_netxen_netdev(dev) (dev->netdev_ops == &netxen_netdev_ops)
+
+static int
+netxen_destip_supported(struct netxen_adapter *adapter)
+{
+ if (NX_IS_REVISION_P2(adapter->ahw.revision_id))
+ return 0;
+
+ if (adapter->ahw.cut_through)
+ return 0;
+
+ return 1;
+}
+
+static int netxen_netdev_event(struct notifier_block *this,
+ unsigned long event, void *ptr)
+{
+ struct netxen_adapter *adapter;
+ struct net_device *dev = (struct net_device *)ptr;
+ struct in_device *indev;
+
+recheck:
+ if (dev == NULL)
+ goto done;
+
+ if (dev->priv_flags & IFF_802_1Q_VLAN) {
+ dev = vlan_dev_real_dev(dev);
+ goto recheck;
+ }
+
+ if (!is_netxen_netdev(dev))
+ goto done;
+
+ adapter = netdev_priv(dev);
+
+ if (!adapter || !netxen_destip_supported(adapter))
+ goto done;
+
+ if (adapter->is_up != NETXEN_ADAPTER_UP_MAGIC)
+ goto done;
+
+ indev = in_dev_get(dev);
+ if (!indev)
+ goto done;
+
+ for_ifa(indev) {
+ switch (event) {
+ case NETDEV_UP:
+ netxen_config_ipaddr(adapter,
+ ifa->ifa_address, NX_IP_UP);
+ break;
+ case NETDEV_DOWN:
+ netxen_config_ipaddr(adapter,
+ ifa->ifa_address, NX_IP_DOWN);
+ break;
+ default:
+ break;
+ }
+ } endfor_ifa(indev);
+
+ in_dev_put(indev);
+done:
+ return NOTIFY_DONE;
+}
+
+static int
+netxen_inetaddr_event(struct notifier_block *this,
+ unsigned long event, void *ptr)
+{
+ struct netxen_adapter *adapter;
+ struct net_device *dev;
+
+ struct in_ifaddr *ifa = (struct in_ifaddr *)ptr;
+
+ dev = ifa->ifa_dev ? ifa->ifa_dev->dev : NULL;
+
+recheck:
+ if (dev == NULL || !netif_running(dev))
+ goto done;
+
+ if (dev->priv_flags & IFF_802_1Q_VLAN) {
+ dev = vlan_dev_real_dev(dev);
+ goto recheck;
+ }
+
+ if (!is_netxen_netdev(dev))
+ goto done;
+
+ adapter = netdev_priv(dev);
+
+ if (!adapter || !netxen_destip_supported(adapter))
+ goto done;
+
+ if (adapter->is_up != NETXEN_ADAPTER_UP_MAGIC)
+ goto done;
+
+ switch (event) {
+ case NETDEV_UP:
+ netxen_config_ipaddr(adapter, ifa->ifa_address, NX_IP_UP);
+ break;
+ case NETDEV_DOWN:
+ netxen_config_ipaddr(adapter, ifa->ifa_address, NX_IP_DOWN);
+ break;
+ default:
+ break;
+ }
+
+done:
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block netxen_netdev_cb = {
+ .notifier_call = netxen_netdev_event,
+};
+
+static struct notifier_block netxen_inetaddr_cb = {
+ .notifier_call = netxen_inetaddr_event,
+};
+#endif
+
static struct pci_driver netxen_driver = {
.name = netxen_nic_driver_name,
.id_table = netxen_pci_tbl,
@@ -1838,12 +2056,15 @@ static struct pci_driver netxen_driver = {
#endif
};
-/* Driver Registration on NetXen card */
-
static int __init netxen_init_module(void)
{
printk(KERN_INFO "%s\n", netxen_nic_driver_string);
+#ifdef CONFIG_INET
+ register_netdevice_notifier(&netxen_netdev_cb);
+ register_inetaddr_notifier(&netxen_inetaddr_cb);
+#endif
+
return pci_register_driver(&netxen_driver);
}
@@ -1852,6 +2073,11 @@ module_init(netxen_init_module);
static void __exit netxen_exit_module(void)
{
pci_unregister_driver(&netxen_driver);
+
+#ifdef CONFIG_INET
+ unregister_inetaddr_notifier(&netxen_inetaddr_cb);
+ unregister_netdevice_notifier(&netxen_netdev_cb);
+#endif
}
module_exit(netxen_exit_module);
diff --git a/drivers/net/ni5010.c b/drivers/net/ni5010.c
index 2a8da476ab3..462d20f2643 100644
--- a/drivers/net/ni5010.c
+++ b/drivers/net/ni5010.c
@@ -463,7 +463,7 @@ static int ni5010_send_packet(struct sk_buff *skb, struct net_device *dev)
hardware_send_packet(dev, (unsigned char *)skb->data, skb->len, length-skb->len);
dev->trans_start = jiffies;
dev_kfree_skb (skb);
- return 0;
+ return NETDEV_TX_OK;
}
/*
diff --git a/drivers/net/ni52.c b/drivers/net/ni52.c
index 77d44a06170..a0ac5d4f27d 100644
--- a/drivers/net/ni52.c
+++ b/drivers/net/ni52.c
@@ -1183,7 +1183,7 @@ static int ni52_send_packet(struct sk_buff *skb, struct net_device *dev)
if (skb->len > XMIT_BUFF_SIZE) {
printk(KERN_ERR "%s: Sorry, max. framelength is %d bytes. The length of your frame is %d bytes.\n", dev->name, XMIT_BUFF_SIZE, skb->len);
- return 0;
+ return NETDEV_TX_OK;
}
netif_stop_queue(dev);
@@ -1267,7 +1267,7 @@ static int ni52_send_packet(struct sk_buff *skb, struct net_device *dev)
}
dev_kfree_skb(skb);
#endif
- return 0;
+ return NETDEV_TX_OK;
}
/*******************************************
diff --git a/drivers/net/ni65.c b/drivers/net/ni65.c
index 1f10ed603e2..81a06178589 100644
--- a/drivers/net/ni65.c
+++ b/drivers/net/ni65.c
@@ -1216,7 +1216,7 @@ static int ni65_send_packet(struct sk_buff *skb, struct net_device *dev)
spin_unlock_irqrestore(&p->ring_lock, flags);
}
- return 0;
+ return NETDEV_TX_OK;
}
static void set_multicast_list(struct net_device *dev)
diff --git a/drivers/net/niu.c b/drivers/net/niu.c
index d2146d4a10f..3ada7ea2abc 100644
--- a/drivers/net/niu.c
+++ b/drivers/net/niu.c
@@ -4015,7 +4015,7 @@ static void niu_xmac_interrupt(struct niu *np)
mp->rx_hist_cnt6 += RXMAC_HIST_CNT6_COUNT;
if (val & XRXMAC_STATUS_RXHIST7_CNT_EXP)
mp->rx_hist_cnt7 += RXMAC_HIST_CNT7_COUNT;
- if (val & XRXMAC_STAT_MSK_RXOCTET_CNT_EXP)
+ if (val & XRXMAC_STATUS_RXOCTET_CNT_EXP)
mp->rx_octets += RXMAC_BT_CNT_COUNT;
if (val & XRXMAC_STATUS_CVIOLERR_CNT_EXP)
mp->rx_code_violations += RXMAC_CD_VIO_CNT_COUNT;
diff --git a/drivers/net/pci-skeleton.c b/drivers/net/pci-skeleton.c
index 89f7b2ad523..c47ba3610c5 100644
--- a/drivers/net/pci-skeleton.c
+++ b/drivers/net/pci-skeleton.c
@@ -1356,7 +1356,7 @@ static int netdrv_start_xmit (struct sk_buff *skb, struct net_device *dev)
DPRINTK ("%s: Queued Tx packet at %p size %u to slot %d.\n",
dev->name, skb->data, skb->len, entry);
- return 0;
+ return NETDEV_TX_OK;
}
diff --git a/drivers/net/pcmcia/3c574_cs.c b/drivers/net/pcmcia/3c574_cs.c
index f35c609ba02..a23aa872404 100644
--- a/drivers/net/pcmcia/3c574_cs.c
+++ b/drivers/net/pcmcia/3c574_cs.c
@@ -806,7 +806,7 @@ static int el3_start_xmit(struct sk_buff *skb, struct net_device *dev)
pop_tx_status(dev);
spin_unlock_irqrestore(&lp->window_lock, flags);
dev_kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
}
/* The EL3 interrupt handler. */
diff --git a/drivers/net/pcmcia/3c589_cs.c b/drivers/net/pcmcia/3c589_cs.c
index 690b9c76d34..d2156ab3da2 100644
--- a/drivers/net/pcmcia/3c589_cs.c
+++ b/drivers/net/pcmcia/3c589_cs.c
@@ -635,7 +635,7 @@ static int el3_start_xmit(struct sk_buff *skb, struct net_device *dev)
spin_unlock_irqrestore(&priv->lock, flags);
dev_kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
}
/* The EL3 interrupt handler. */
diff --git a/drivers/net/pcmcia/axnet_cs.c b/drivers/net/pcmcia/axnet_cs.c
index 0e38d80fd25..1e87d634d7b 100644
--- a/drivers/net/pcmcia/axnet_cs.c
+++ b/drivers/net/pcmcia/axnet_cs.c
@@ -893,8 +893,6 @@ static const char version_8390[] = KERN_INFO \
#include <linux/in.h>
#include <linux/interrupt.h>
-#include <linux/etherdevice.h>
-
#define BUG_83C690
/* These are the operational function interfaces to board-specific
@@ -1179,7 +1177,7 @@ static int axnet_start_xmit(struct sk_buff *skb, struct net_device *dev)
dev_kfree_skb (skb);
dev->stats.tx_bytes += send_length;
- return 0;
+ return NETDEV_TX_OK;
}
/**
diff --git a/drivers/net/pcmcia/fmvj18x_cs.c b/drivers/net/pcmcia/fmvj18x_cs.c
index 479d5b49437..434d9407bfb 100644
--- a/drivers/net/pcmcia/fmvj18x_cs.c
+++ b/drivers/net/pcmcia/fmvj18x_cs.c
@@ -865,7 +865,7 @@ static int fjn_start_xmit(struct sk_buff *skb, struct net_device *dev)
if (length < ETH_ZLEN)
{
if (skb_padto(skb, ETH_ZLEN))
- return 0;
+ return NETDEV_TX_OK;
length = ETH_ZLEN;
}
@@ -924,7 +924,7 @@ static int fjn_start_xmit(struct sk_buff *skb, struct net_device *dev)
}
dev_kfree_skb (skb);
- return 0;
+ return NETDEV_TX_OK;
} /* fjn_start_xmit */
/*====================================================================*/
diff --git a/drivers/net/pcmcia/nmclan_cs.c b/drivers/net/pcmcia/nmclan_cs.c
index 36de91baf23..dd605907670 100644
--- a/drivers/net/pcmcia/nmclan_cs.c
+++ b/drivers/net/pcmcia/nmclan_cs.c
@@ -990,7 +990,7 @@ static int mace_start_xmit(struct sk_buff *skb, struct net_device *dev)
dev_kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
} /* mace_start_xmit */
/* ----------------------------------------------------------------------------
diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c
index 37e05d3ab89..2f39244c17f 100644
--- a/drivers/net/pcmcia/smc91c92_cs.c
+++ b/drivers/net/pcmcia/smc91c92_cs.c
@@ -1399,7 +1399,7 @@ static int smc_start_xmit(struct sk_buff *skb, struct net_device *dev)
dev_kfree_skb (skb);
smc->saved_skb = NULL;
dev->stats.tx_dropped++;
- return 0; /* Do not re-queue this packet. */
+ return NETDEV_TX_OK; /* Do not re-queue this packet. */
}
/* A packet is now waiting. */
smc->packets_waiting++;
@@ -1422,7 +1422,7 @@ static int smc_start_xmit(struct sk_buff *skb, struct net_device *dev)
outw((ir&0xff00) | IM_ALLOC_INT, ioaddr + INTERRUPT);
smc_hardware_send_packet(dev); /* Send the packet now.. */
spin_unlock_irqrestore(&smc->lock, flags);
- return 0;
+ return NETDEV_TX_OK;
}
}
@@ -1431,7 +1431,7 @@ static int smc_start_xmit(struct sk_buff *skb, struct net_device *dev)
outw((IM_ALLOC_INT << 8) | (ir & 0xff00), ioaddr + INTERRUPT);
spin_unlock_irqrestore(&smc->lock, flags);
- return 0;
+ return NETDEV_TX_OK;
}
/*======================================================================
diff --git a/drivers/net/pcmcia/xirc2ps_cs.c b/drivers/net/pcmcia/xirc2ps_cs.c
index ef37d22c7e1..eda7bf6047c 100644
--- a/drivers/net/pcmcia/xirc2ps_cs.c
+++ b/drivers/net/pcmcia/xirc2ps_cs.c
@@ -1384,7 +1384,7 @@ do_start_xmit(struct sk_buff *skb, struct net_device *dev)
if (pktlen < ETH_ZLEN)
{
if (skb_padto(skb, ETH_ZLEN))
- return 0;
+ return NETDEV_TX_OK;
pktlen = ETH_ZLEN;
}
@@ -1414,7 +1414,7 @@ do_start_xmit(struct sk_buff *skb, struct net_device *dev)
dev->trans_start = jiffies;
dev->stats.tx_bytes += pktlen;
netif_start_queue(dev);
- return 0;
+ return NETDEV_TX_OK;
}
/****************
diff --git a/drivers/net/pcnet32.c b/drivers/net/pcnet32.c
index 23e1a0750fe..6859442f186 100644
--- a/drivers/net/pcnet32.c
+++ b/drivers/net/pcnet32.c
@@ -2534,7 +2534,7 @@ static int pcnet32_start_xmit(struct sk_buff *skb, struct net_device *dev)
netif_stop_queue(dev);
}
spin_unlock_irqrestore(&lp->lock, flags);
- return 0;
+ return NETDEV_TX_OK;
}
/* The PCNET32 interrupt handler. */
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index de9cf5136fd..d5d8e1c5bc9 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -56,6 +56,12 @@ config BROADCOM_PHY
Currently supports the BCM5411, BCM5421, BCM5461, BCM5464, BCM5481
and BCM5482 PHYs.
+config BCM63XX_PHY
+ tristate "Drivers for Broadcom 63xx SOCs internal PHY"
+ depends on BCM63XX
+ ---help---
+ Currently supports the 6348 and 6358 PHYs.
+
config ICPLUS_PHY
tristate "Drivers for ICPlus PHYs"
---help---
diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
index 3a1bfefefbc..edfaac48cbd 100644
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -11,6 +11,7 @@ obj-$(CONFIG_QSEMI_PHY) += qsemi.o
obj-$(CONFIG_SMSC_PHY) += smsc.o
obj-$(CONFIG_VITESSE_PHY) += vitesse.o
obj-$(CONFIG_BROADCOM_PHY) += broadcom.o
+obj-$(CONFIG_BCM63XX_PHY) += bcm63xx.o
obj-$(CONFIG_ICPLUS_PHY) += icplus.o
obj-$(CONFIG_REALTEK_PHY) += realtek.o
obj-$(CONFIG_LSI_ET1011C_PHY) += et1011c.o
diff --git a/drivers/net/phy/bcm63xx.c b/drivers/net/phy/bcm63xx.c
new file mode 100644
index 00000000000..4fed95e8350
--- /dev/null
+++ b/drivers/net/phy/bcm63xx.c
@@ -0,0 +1,132 @@
+/*
+ * Driver for Broadcom 63xx SOCs integrated PHYs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#include <linux/module.h>
+#include <linux/phy.h>
+
+#define MII_BCM63XX_IR 0x1a /* interrupt register */
+#define MII_BCM63XX_IR_EN 0x4000 /* global interrupt enable */
+#define MII_BCM63XX_IR_DUPLEX 0x0800 /* duplex changed */
+#define MII_BCM63XX_IR_SPEED 0x0400 /* speed changed */
+#define MII_BCM63XX_IR_LINK 0x0200 /* link changed */
+#define MII_BCM63XX_IR_GMASK 0x0100 /* global interrupt mask */
+
+MODULE_DESCRIPTION("Broadcom 63xx internal PHY driver");
+MODULE_AUTHOR("Maxime Bizon <mbizon@freebox.fr>");
+MODULE_LICENSE("GPL");
+
+static int bcm63xx_config_init(struct phy_device *phydev)
+{
+ int reg, err;
+
+ reg = phy_read(phydev, MII_BCM63XX_IR);
+ if (reg < 0)
+ return reg;
+
+ /* Mask interrupts globally. */
+ reg |= MII_BCM63XX_IR_GMASK;
+ err = phy_write(phydev, MII_BCM63XX_IR, reg);
+ if (err < 0)
+ return err;
+
+ /* Unmask events we are interested in */
+ reg = ~(MII_BCM63XX_IR_DUPLEX |
+ MII_BCM63XX_IR_SPEED |
+ MII_BCM63XX_IR_LINK) |
+ MII_BCM63XX_IR_EN;
+ err = phy_write(phydev, MII_BCM63XX_IR, reg);
+ if (err < 0)
+ return err;
+ return 0;
+}
+
+static int bcm63xx_ack_interrupt(struct phy_device *phydev)
+{
+ int reg;
+
+ /* Clear pending interrupts. */
+ reg = phy_read(phydev, MII_BCM63XX_IR);
+ if (reg < 0)
+ return reg;
+
+ return 0;
+}
+
+static int bcm63xx_config_intr(struct phy_device *phydev)
+{
+ int reg, err;
+
+ reg = phy_read(phydev, MII_BCM63XX_IR);
+ if (reg < 0)
+ return reg;
+
+ if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
+ reg &= ~MII_BCM63XX_IR_GMASK;
+ else
+ reg |= MII_BCM63XX_IR_GMASK;
+
+ err = phy_write(phydev, MII_BCM63XX_IR, reg);
+ return err;
+}
+
+static struct phy_driver bcm63xx_1_driver = {
+ .phy_id = 0x00406000,
+ .phy_id_mask = 0xfffffc00,
+ .name = "Broadcom BCM63XX (1)",
+ /* ASYM_PAUSE bit is marked RO in datasheet, so don't cheat */
+ .features = (PHY_BASIC_FEATURES | SUPPORTED_Pause),
+ .flags = PHY_HAS_INTERRUPT,
+ .config_init = bcm63xx_config_init,
+ .config_aneg = genphy_config_aneg,
+ .read_status = genphy_read_status,
+ .ack_interrupt = bcm63xx_ack_interrupt,
+ .config_intr = bcm63xx_config_intr,
+ .driver = { .owner = THIS_MODULE },
+};
+
+/* same phy as above, with just a different OUI */
+static struct phy_driver bcm63xx_2_driver = {
+ .phy_id = 0x002bdc00,
+ .phy_id_mask = 0xfffffc00,
+ .name = "Broadcom BCM63XX (2)",
+ .features = (PHY_BASIC_FEATURES | SUPPORTED_Pause),
+ .flags = PHY_HAS_INTERRUPT,
+ .config_init = bcm63xx_config_init,
+ .config_aneg = genphy_config_aneg,
+ .read_status = genphy_read_status,
+ .ack_interrupt = bcm63xx_ack_interrupt,
+ .config_intr = bcm63xx_config_intr,
+ .driver = { .owner = THIS_MODULE },
+};
+
+static int __init bcm63xx_phy_init(void)
+{
+ int ret;
+
+ ret = phy_driver_register(&bcm63xx_1_driver);
+ if (ret)
+ goto out_63xx_1;
+ ret = phy_driver_register(&bcm63xx_2_driver);
+ if (ret)
+ goto out_63xx_2;
+ return ret;
+
+out_63xx_2:
+ phy_driver_unregister(&bcm63xx_1_driver);
+out_63xx_1:
+ return ret;
+}
+
+static void __exit bcm63xx_phy_exit(void)
+{
+ phy_driver_unregister(&bcm63xx_1_driver);
+ phy_driver_unregister(&bcm63xx_2_driver);
+}
+
+module_init(bcm63xx_phy_init);
+module_exit(bcm63xx_phy_exit);
diff --git a/drivers/net/plip.c b/drivers/net/plip.c
index 2ca8b0d84ee..00487f569cf 100644
--- a/drivers/net/plip.c
+++ b/drivers/net/plip.c
@@ -990,7 +990,7 @@ plip_tx_packet(struct sk_buff *skb, struct net_device *dev)
schedule_work(&nl->immediate);
spin_unlock_irq(&nl->lock);
- return 0;
+ return NETDEV_TX_OK;
}
static void
diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c
index cd37d739ac7..7dd0868f983 100644
--- a/drivers/net/ppp_generic.c
+++ b/drivers/net/ppp_generic.c
@@ -988,12 +988,12 @@ ppp_start_xmit(struct sk_buff *skb, struct net_device *dev)
netif_stop_queue(dev);
skb_queue_tail(&ppp->file.xq, skb);
ppp_xmit_process(ppp);
- return 0;
+ return NETDEV_TX_OK;
outf:
kfree_skb(skb);
++dev->stats.tx_dropped;
- return 0;
+ return NETDEV_TX_OK;
}
static int
diff --git a/drivers/net/pppoe.c b/drivers/net/pppoe.c
index 5f2090233d7..7cbf6f9b51d 100644
--- a/drivers/net/pppoe.c
+++ b/drivers/net/pppoe.c
@@ -1185,17 +1185,17 @@ static int __init pppoe_init(void)
{
int err;
- err = proto_register(&pppoe_sk_proto, 0);
+ err = register_pernet_gen_device(&pppoe_net_id, &pppoe_net_ops);
if (err)
goto out;
- err = register_pppox_proto(PX_PROTO_OE, &pppoe_proto);
+ err = proto_register(&pppoe_sk_proto, 0);
if (err)
- goto out_unregister_pppoe_proto;
+ goto out_unregister_net_ops;
- err = register_pernet_gen_device(&pppoe_net_id, &pppoe_net_ops);
+ err = register_pppox_proto(PX_PROTO_OE, &pppoe_proto);
if (err)
- goto out_unregister_pppox_proto;
+ goto out_unregister_pppoe_proto;
dev_add_pack(&pppoes_ptype);
dev_add_pack(&pppoed_ptype);
@@ -1203,22 +1203,22 @@ static int __init pppoe_init(void)
return 0;
-out_unregister_pppox_proto:
- unregister_pppox_proto(PX_PROTO_OE);
out_unregister_pppoe_proto:
proto_unregister(&pppoe_sk_proto);
+out_unregister_net_ops:
+ unregister_pernet_gen_device(pppoe_net_id, &pppoe_net_ops);
out:
return err;
}
static void __exit pppoe_exit(void)
{
- unregister_pppox_proto(PX_PROTO_OE);
- dev_remove_pack(&pppoes_ptype);
- dev_remove_pack(&pppoed_ptype);
unregister_netdevice_notifier(&pppoe_notifier);
- unregister_pernet_gen_device(pppoe_net_id, &pppoe_net_ops);
+ dev_remove_pack(&pppoed_ptype);
+ dev_remove_pack(&pppoes_ptype);
+ unregister_pppox_proto(PX_PROTO_OE);
proto_unregister(&pppoe_sk_proto);
+ unregister_pernet_gen_device(pppoe_net_id, &pppoe_net_ops);
}
module_init(pppoe_init);
diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c
index 5768af17f16..3a271afdd8f 100644
--- a/drivers/net/qlge/qlge_main.c
+++ b/drivers/net/qlge/qlge_main.c
@@ -4076,6 +4076,11 @@ static pci_ers_result_t qlge_io_error_detected(struct pci_dev *pdev,
struct net_device *ndev = pci_get_drvdata(pdev);
struct ql_adapter *qdev = netdev_priv(ndev);
+ netif_device_detach(ndev);
+
+ if (state == pci_channel_io_perm_failure)
+ return PCI_ERS_RESULT_DISCONNECT;
+
if (netif_running(ndev))
ql_adapter_down(qdev);
diff --git a/drivers/net/r6040.c b/drivers/net/r6040.c
index 961b5397a53..840677f5ee8 100644
--- a/drivers/net/r6040.c
+++ b/drivers/net/r6040.c
@@ -1115,13 +1115,13 @@ static int __devinit r6040_init_one(struct pci_dev *pdev,
}
/* IO Size check */
- if (pci_resource_len(pdev, 0) < io_size) {
+ if (pci_resource_len(pdev, bar) < io_size) {
printk(KERN_ERR DRV_NAME ": Insufficient PCI resources, aborting\n");
err = -EIO;
goto err_out;
}
- pioaddr = pci_resource_start(pdev, 0); /* IO map base address */
+ pioaddr = pci_resource_start(pdev, bar); /* IO map base address */
pci_set_master(pdev);
dev = alloc_etherdev(sizeof(struct r6040_private));
diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c
index b82780d805f..8cd85309c67 100644
--- a/drivers/net/r8169.c
+++ b/drivers/net/r8169.c
@@ -1222,17 +1222,6 @@ static const struct ethtool_ops rtl8169_ethtool_ops = {
.get_ethtool_stats = rtl8169_get_ethtool_stats,
};
-static void rtl8169_write_gmii_reg_bit(void __iomem *ioaddr, int reg,
- int bitnum, int bitval)
-{
- int val;
-
- val = mdio_read(ioaddr, reg);
- val = (bitval == 1) ?
- val | (bitval << bitnum) : val & ~(0x0001 << bitnum);
- mdio_write(ioaddr, reg, val & 0xffff);
-}
-
static void rtl8169_get_mac_version(struct rtl8169_private *tp,
void __iomem *ioaddr)
{
@@ -1328,54 +1317,69 @@ static void rtl_phy_write(void __iomem *ioaddr, struct phy_reg *regs, int len)
static void rtl8169s_hw_phy_config(void __iomem *ioaddr)
{
- struct {
- u16 regs[5]; /* Beware of bit-sign propagation */
- } phy_magic[5] = { {
- { 0x0000, //w 4 15 12 0
- 0x00a1, //w 3 15 0 00a1
- 0x0008, //w 2 15 0 0008
- 0x1020, //w 1 15 0 1020
- 0x1000 } },{ //w 0 15 0 1000
- { 0x7000, //w 4 15 12 7
- 0xff41, //w 3 15 0 ff41
- 0xde60, //w 2 15 0 de60
- 0x0140, //w 1 15 0 0140
- 0x0077 } },{ //w 0 15 0 0077
- { 0xa000, //w 4 15 12 a
- 0xdf01, //w 3 15 0 df01
- 0xdf20, //w 2 15 0 df20
- 0xff95, //w 1 15 0 ff95
- 0xfa00 } },{ //w 0 15 0 fa00
- { 0xb000, //w 4 15 12 b
- 0xff41, //w 3 15 0 ff41
- 0xde20, //w 2 15 0 de20
- 0x0140, //w 1 15 0 0140
- 0x00bb } },{ //w 0 15 0 00bb
- { 0xf000, //w 4 15 12 f
- 0xdf01, //w 3 15 0 df01
- 0xdf20, //w 2 15 0 df20
- 0xff95, //w 1 15 0 ff95
- 0xbf00 } //w 0 15 0 bf00
- }
- }, *p = phy_magic;
- unsigned int i;
+ struct phy_reg phy_reg_init[] = {
+ { 0x1f, 0x0001 },
+ { 0x06, 0x006e },
+ { 0x08, 0x0708 },
+ { 0x15, 0x4000 },
+ { 0x18, 0x65c7 },
- mdio_write(ioaddr, 0x1f, 0x0001); //w 31 2 0 1
- mdio_write(ioaddr, 0x15, 0x1000); //w 21 15 0 1000
- mdio_write(ioaddr, 0x18, 0x65c7); //w 24 15 0 65c7
- rtl8169_write_gmii_reg_bit(ioaddr, 4, 11, 0); //w 4 11 11 0
+ { 0x1f, 0x0001 },
+ { 0x03, 0x00a1 },
+ { 0x02, 0x0008 },
+ { 0x01, 0x0120 },
+ { 0x00, 0x1000 },
+ { 0x04, 0x0800 },
+ { 0x04, 0x0000 },
+
+ { 0x03, 0xff41 },
+ { 0x02, 0xdf60 },
+ { 0x01, 0x0140 },
+ { 0x00, 0x0077 },
+ { 0x04, 0x7800 },
+ { 0x04, 0x7000 },
- for (i = 0; i < ARRAY_SIZE(phy_magic); i++, p++) {
- int val, pos = 4;
+ { 0x03, 0x802f },
+ { 0x02, 0x4f02 },
+ { 0x01, 0x0409 },
+ { 0x00, 0xf0f9 },
+ { 0x04, 0x9800 },
+ { 0x04, 0x9000 },
- val = (mdio_read(ioaddr, pos) & 0x0fff) | (p->regs[0] & 0xffff);
- mdio_write(ioaddr, pos, val);
- while (--pos >= 0)
- mdio_write(ioaddr, pos, p->regs[4 - pos] & 0xffff);
- rtl8169_write_gmii_reg_bit(ioaddr, 4, 11, 1); //w 4 11 11 1
- rtl8169_write_gmii_reg_bit(ioaddr, 4, 11, 0); //w 4 11 11 0
- }
- mdio_write(ioaddr, 0x1f, 0x0000); //w 31 2 0 0
+ { 0x03, 0xdf01 },
+ { 0x02, 0xdf20 },
+ { 0x01, 0xff95 },
+ { 0x00, 0xba00 },
+ { 0x04, 0xa800 },
+ { 0x04, 0xa000 },
+
+ { 0x03, 0xff41 },
+ { 0x02, 0xdf20 },
+ { 0x01, 0x0140 },
+ { 0x00, 0x00bb },
+ { 0x04, 0xb800 },
+ { 0x04, 0xb000 },
+
+ { 0x03, 0xdf41 },
+ { 0x02, 0xdc60 },
+ { 0x01, 0x6340 },
+ { 0x00, 0x007d },
+ { 0x04, 0xd800 },
+ { 0x04, 0xd000 },
+
+ { 0x03, 0xdf01 },
+ { 0x02, 0xdf20 },
+ { 0x01, 0x100a },
+ { 0x00, 0xa0ff },
+ { 0x04, 0xf800 },
+ { 0x04, 0xf000 },
+
+ { 0x1f, 0x0000 },
+ { 0x0b, 0x0000 },
+ { 0x00, 0x9200 }
+ };
+
+ rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init));
}
static void rtl8169sb_hw_phy_config(void __iomem *ioaddr)
@@ -1389,6 +1393,124 @@ static void rtl8169sb_hw_phy_config(void __iomem *ioaddr)
rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init));
}
+static void rtl8169scd_hw_phy_config_quirk(struct rtl8169_private *tp,
+ void __iomem *ioaddr)
+{
+ struct pci_dev *pdev = tp->pci_dev;
+ u16 vendor_id, device_id;
+
+ pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, &vendor_id);
+ pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, &device_id);
+
+ if ((vendor_id != PCI_VENDOR_ID_GIGABYTE) || (device_id != 0xe000))
+ return;
+
+ mdio_write(ioaddr, 0x1f, 0x0001);
+ mdio_write(ioaddr, 0x10, 0xf01b);
+ mdio_write(ioaddr, 0x1f, 0x0000);
+}
+
+static void rtl8169scd_hw_phy_config(struct rtl8169_private *tp,
+ void __iomem *ioaddr)
+{
+ struct phy_reg phy_reg_init[] = {
+ { 0x1f, 0x0001 },
+ { 0x04, 0x0000 },
+ { 0x03, 0x00a1 },
+ { 0x02, 0x0008 },
+ { 0x01, 0x0120 },
+ { 0x00, 0x1000 },
+ { 0x04, 0x0800 },
+ { 0x04, 0x9000 },
+ { 0x03, 0x802f },
+ { 0x02, 0x4f02 },
+ { 0x01, 0x0409 },
+ { 0x00, 0xf099 },
+ { 0x04, 0x9800 },
+ { 0x04, 0xa000 },
+ { 0x03, 0xdf01 },
+ { 0x02, 0xdf20 },
+ { 0x01, 0xff95 },
+ { 0x00, 0xba00 },
+ { 0x04, 0xa800 },
+ { 0x04, 0xf000 },
+ { 0x03, 0xdf01 },
+ { 0x02, 0xdf20 },
+ { 0x01, 0x101a },
+ { 0x00, 0xa0ff },
+ { 0x04, 0xf800 },
+ { 0x04, 0x0000 },
+ { 0x1f, 0x0000 },
+
+ { 0x1f, 0x0001 },
+ { 0x10, 0xf41b },
+ { 0x14, 0xfb54 },
+ { 0x18, 0xf5c7 },
+ { 0x1f, 0x0000 },
+
+ { 0x1f, 0x0001 },
+ { 0x17, 0x0cc0 },
+ { 0x1f, 0x0000 }
+ };
+
+ rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init));
+
+ rtl8169scd_hw_phy_config_quirk(tp, ioaddr);
+}
+
+static void rtl8169sce_hw_phy_config(void __iomem *ioaddr)
+{
+ struct phy_reg phy_reg_init[] = {
+ { 0x1f, 0x0001 },
+ { 0x04, 0x0000 },
+ { 0x03, 0x00a1 },
+ { 0x02, 0x0008 },
+ { 0x01, 0x0120 },
+ { 0x00, 0x1000 },
+ { 0x04, 0x0800 },
+ { 0x04, 0x9000 },
+ { 0x03, 0x802f },
+ { 0x02, 0x4f02 },
+ { 0x01, 0x0409 },
+ { 0x00, 0xf099 },
+ { 0x04, 0x9800 },
+ { 0x04, 0xa000 },
+ { 0x03, 0xdf01 },
+ { 0x02, 0xdf20 },
+ { 0x01, 0xff95 },
+ { 0x00, 0xba00 },
+ { 0x04, 0xa800 },
+ { 0x04, 0xf000 },
+ { 0x03, 0xdf01 },
+ { 0x02, 0xdf20 },
+ { 0x01, 0x101a },
+ { 0x00, 0xa0ff },
+ { 0x04, 0xf800 },
+ { 0x04, 0x0000 },
+ { 0x1f, 0x0000 },
+
+ { 0x1f, 0x0001 },
+ { 0x0b, 0x8480 },
+ { 0x1f, 0x0000 },
+
+ { 0x1f, 0x0001 },
+ { 0x18, 0x67c7 },
+ { 0x04, 0x2000 },
+ { 0x03, 0x002f },
+ { 0x02, 0x4360 },
+ { 0x01, 0x0109 },
+ { 0x00, 0x3022 },
+ { 0x04, 0x2800 },
+ { 0x1f, 0x0000 },
+
+ { 0x1f, 0x0001 },
+ { 0x17, 0x0cc0 },
+ { 0x1f, 0x0000 }
+ };
+
+ rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init));
+}
+
static void rtl8168bb_hw_phy_config(void __iomem *ioaddr)
{
struct phy_reg phy_reg_init[] = {
@@ -1607,6 +1729,7 @@ static void rtl8102e_hw_phy_config(void __iomem *ioaddr)
mdio_write(ioaddr, 0x1f, 0x0000);
mdio_patch(ioaddr, 0x11, 1 << 12);
mdio_patch(ioaddr, 0x19, 1 << 13);
+ mdio_patch(ioaddr, 0x10, 1 << 15);
rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init));
}
@@ -1628,6 +1751,12 @@ static void rtl_hw_phy_config(struct net_device *dev)
case RTL_GIGA_MAC_VER_04:
rtl8169sb_hw_phy_config(ioaddr);
break;
+ case RTL_GIGA_MAC_VER_05:
+ rtl8169scd_hw_phy_config(tp, ioaddr);
+ break;
+ case RTL_GIGA_MAC_VER_06:
+ rtl8169sce_hw_phy_config(ioaddr);
+ break;
case RTL_GIGA_MAC_VER_07:
case RTL_GIGA_MAC_VER_08:
case RTL_GIGA_MAC_VER_09:
@@ -2180,7 +2309,7 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
pci_set_drvdata(pdev, dev);
if (netif_msg_probe(tp)) {
- u32 xid = RTL_R32(TxConfig) & 0x7cf0f8ff;
+ u32 xid = RTL_R32(TxConfig) & 0x9cf0f8ff;
printk(KERN_INFO "%s: %s at 0x%lx, "
"%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x, "
@@ -2757,7 +2886,7 @@ static void rtl_hw_start_8168(struct net_device *dev)
EnableBist | \
Mac_dbgo_oe | \
Force_half_dup | \
- Force_half_dup | \
+ Force_rxflow_en | \
Force_txflow_en | \
Cxpl_dbg_sel | \
ASF | \
diff --git a/drivers/net/rionet.c b/drivers/net/rionet.c
index 8702e7acdee..bc98e7f69ee 100644
--- a/drivers/net/rionet.c
+++ b/drivers/net/rionet.c
@@ -114,11 +114,6 @@ static int rionet_rx_clean(struct net_device *ndev)
if (error == NET_RX_DROP) {
ndev->stats.rx_dropped++;
- } else if (error == NET_RX_BAD) {
- if (netif_msg_rx_err(rnet))
- printk(KERN_WARNING "%s: bad rx packet\n",
- DRV_NAME);
- ndev->stats.rx_errors++;
} else {
ndev->stats.rx_packets++;
ndev->stats.rx_bytes += RIO_MAX_MSG_SIZE;
@@ -208,7 +203,7 @@ static int rionet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
spin_unlock_irqrestore(&rnet->tx_lock, flags);
- return 0;
+ return NETDEV_TX_OK;
}
static void rionet_dbell_event(struct rio_mport *mport, void *dev_id, u16 sid, u16 tid,
diff --git a/drivers/net/rrunner.c b/drivers/net/rrunner.c
index 81dbcbb910f..d9553465591 100644
--- a/drivers/net/rrunner.c
+++ b/drivers/net/rrunner.c
@@ -1466,7 +1466,7 @@ static int rr_start_xmit(struct sk_buff *skb, struct net_device *dev)
spin_unlock_irqrestore(&rrpriv->lock, flags);
dev->trans_start = jiffies;
- return 0;
+ return NETDEV_TX_OK;
}
diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c
index 458daa06ed4..bd6d713c861 100644
--- a/drivers/net/s2io.c
+++ b/drivers/net/s2io.c
@@ -4111,14 +4111,14 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev)
if (unlikely(skb->len <= 0)) {
DBG_PRINT(TX_DBG, "%s:Buffer has no data..\n", dev->name);
dev_kfree_skb_any(skb);
- return 0;
+ return NETDEV_TX_OK;
}
if (!is_s2io_card_up(sp)) {
DBG_PRINT(TX_DBG, "%s: Card going down for reset\n",
dev->name);
dev_kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
}
queue = 0;
@@ -4192,7 +4192,7 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev)
s2io_stop_tx_queue(sp, fifo->fifo_no);
dev_kfree_skb(skb);
spin_unlock_irqrestore(&fifo->tx_lock, flags);
- return 0;
+ return NETDEV_TX_OK;
}
offload_type = s2io_offload_type(skb);
@@ -4304,14 +4304,14 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev)
if (sp->config.intr_type == MSI_X)
tx_intr_handler(fifo);
- return 0;
+ return NETDEV_TX_OK;
pci_map_failed:
stats->pci_map_fail_cnt++;
s2io_stop_tx_queue(sp, fifo->fifo_no);
stats->mem_freed += skb->truesize;
dev_kfree_skb(skb);
spin_unlock_irqrestore(&fifo->tx_lock, flags);
- return 0;
+ return NETDEV_TX_OK;
}
static void
@@ -8636,6 +8636,9 @@ static pci_ers_result_t s2io_io_error_detected(struct pci_dev *pdev,
netif_device_detach(netdev);
+ if (state == pci_channel_io_perm_failure)
+ return PCI_ERS_RESULT_DISCONNECT;
+
if (netif_running(netdev)) {
/* Bring down the card, while avoiding PCI I/O */
do_s2io_card_down(sp, 0);
diff --git a/drivers/net/sb1000.c b/drivers/net/sb1000.c
index fc0e38bddee..6a81aec645d 100644
--- a/drivers/net/sb1000.c
+++ b/drivers/net/sb1000.c
@@ -1086,7 +1086,7 @@ sb1000_start_xmit(struct sk_buff *skb, struct net_device *dev)
printk(KERN_WARNING "%s: trying to transmit!!!\n", dev->name);
/* sb1000 can't xmit datagrams */
dev_kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
}
/* SB1000 interrupt handler. */
diff --git a/drivers/net/sb1250-mac.c b/drivers/net/sb1250-mac.c
index d8c9cf1b901..508551f1b3f 100644
--- a/drivers/net/sb1250-mac.c
+++ b/drivers/net/sb1250-mac.c
@@ -2091,7 +2091,7 @@ static int sbmac_start_tx(struct sk_buff *skb, struct net_device *dev)
spin_unlock_irqrestore(&sc->sbm_lock, flags);
- return 0;
+ return NETDEV_TX_OK;
}
/**********************************************************************
@@ -2688,7 +2688,7 @@ static int sbmac_poll(struct napi_struct *napi, int budget)
}
-static int __init sbmac_probe(struct platform_device *pldev)
+static int __devinit sbmac_probe(struct platform_device *pldev)
{
struct net_device *dev;
struct sbmac_softc *sc;
diff --git a/drivers/net/seeq8005.c b/drivers/net/seeq8005.c
index ebbbe09725f..7cc8bb81413 100644
--- a/drivers/net/seeq8005.c
+++ b/drivers/net/seeq8005.c
@@ -401,7 +401,7 @@ static int seeq8005_send_packet(struct sk_buff *skb, struct net_device *dev)
if (length < ETH_ZLEN) {
if (skb_padto(skb, ETH_ZLEN))
- return 0;
+ return NETDEV_TX_OK;
length = ETH_ZLEN;
}
buf = skb->data;
@@ -415,7 +415,7 @@ static int seeq8005_send_packet(struct sk_buff *skb, struct net_device *dev)
dev_kfree_skb (skb);
/* You might need to clean up and record Tx statistics here. */
- return 0;
+ return NETDEV_TX_OK;
}
/*
diff --git a/drivers/net/sgiseeq.c b/drivers/net/sgiseeq.c
index 5fb88ca6dd7..ecf3279fbef 100644
--- a/drivers/net/sgiseeq.c
+++ b/drivers/net/sgiseeq.c
@@ -594,7 +594,7 @@ static int sgiseeq_start_xmit(struct sk_buff *skb, struct net_device *dev)
len = skb->len;
if (len < ETH_ZLEN) {
if (skb_padto(skb, ETH_ZLEN))
- return 0;
+ return NETDEV_TX_OK;
len = ETH_ZLEN;
}
@@ -642,7 +642,7 @@ static int sgiseeq_start_xmit(struct sk_buff *skb, struct net_device *dev)
netif_stop_queue(dev);
spin_unlock_irqrestore(&sp->tx_lock, flags);
- return 0;
+ return NETDEV_TX_OK;
}
static void timeout(struct net_device *dev)
@@ -720,7 +720,7 @@ static const struct net_device_ops sgiseeq_netdev_ops = {
.ndo_validate_addr = eth_validate_addr,
};
-static int __init sgiseeq_probe(struct platform_device *pdev)
+static int __devinit sgiseeq_probe(struct platform_device *pdev)
{
struct sgiseeq_platform_data *pd = pdev->dev.platform_data;
struct hpc3_regs *hpcregs = pd->hpc;
diff --git a/drivers/net/sh_eth.c b/drivers/net/sh_eth.c
index a2d82ddb3b4..4c4dcbf1902 100644
--- a/drivers/net/sh_eth.c
+++ b/drivers/net/sh_eth.c
@@ -1133,7 +1133,7 @@ static int sh_eth_start_xmit(struct sk_buff *skb, struct net_device *ndev)
ndev->trans_start = jiffies;
- return 0;
+ return NETDEV_TX_OK;
}
/* device close function */
diff --git a/drivers/net/sis900.c b/drivers/net/sis900.c
index a9a897bb42d..61ceeaaf104 100644
--- a/drivers/net/sis900.c
+++ b/drivers/net/sis900.c
@@ -1628,7 +1628,7 @@ sis900_start_xmit(struct sk_buff *skb, struct net_device *net_dev)
"to slot %d.\n",
net_dev->name, skb->data, (int)skb->len, entry);
- return 0;
+ return NETDEV_TX_OK;
}
/**
diff --git a/drivers/net/skfp/skfddi.c b/drivers/net/skfp/skfddi.c
index 088fe26484e..888a14a045e 100644
--- a/drivers/net/skfp/skfddi.c
+++ b/drivers/net/skfp/skfddi.c
@@ -1077,7 +1077,7 @@ static int skfp_send_pkt(struct sk_buff *skb, struct net_device *dev)
// dequeue packets from xmt queue and send them
netif_start_queue(dev);
dev_kfree_skb(skb);
- return (0); /* return "success" */
+ return NETDEV_TX_OK; /* return "success" */
}
if (bp->QueueSkb == 0) { // return with tbusy set: queue full
@@ -1091,7 +1091,7 @@ static int skfp_send_pkt(struct sk_buff *skb, struct net_device *dev)
netif_stop_queue(dev);
}
dev->trans_start = jiffies;
- return 0;
+ return NETDEV_TX_OK;
} // skfp_send_pkt
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c
index 0a551d8f5d9..bac187000e1 100644
--- a/drivers/net/sky2.c
+++ b/drivers/net/sky2.c
@@ -50,7 +50,7 @@
#include "sky2.h"
#define DRV_NAME "sky2"
-#define DRV_VERSION "1.23"
+#define DRV_VERSION "1.24"
#define PFX DRV_NAME " "
/*
@@ -321,7 +321,7 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port)
struct sky2_port *sky2 = netdev_priv(hw->dev[port]);
u16 ctrl, ct1000, adv, pg, ledctrl, ledover, reg;
- if (sky2->autoneg == AUTONEG_ENABLE &&
+ if ( (sky2->flags & SKY2_FLAG_AUTO_SPEED) &&
!(hw->flags & SKY2_HW_NEWER_PHY)) {
u16 ectrl = gm_phy_read(hw, port, PHY_MARV_EXT_CTRL);
@@ -363,7 +363,7 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port)
ctrl |= PHY_M_PC_MDI_XMODE(PHY_M_PC_ENA_AUTO);
/* downshift on PHY 88E1112 and 88E1149 is changed */
- if (sky2->autoneg == AUTONEG_ENABLE
+ if ( (sky2->flags & SKY2_FLAG_AUTO_SPEED)
&& (hw->flags & SKY2_HW_NEWER_PHY)) {
/* set downshift counter to 3x and enable downshift */
ctrl &= ~PHY_M_PC_DSC_MSK;
@@ -408,7 +408,7 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port)
adv = PHY_AN_CSMA;
reg = 0;
- if (sky2->autoneg == AUTONEG_ENABLE) {
+ if (sky2->flags & SKY2_FLAG_AUTO_SPEED) {
if (sky2_is_copper(hw)) {
if (sky2->advertising & ADVERTISED_1000baseT_Full)
ct1000 |= PHY_M_1000C_AFD;
@@ -423,14 +423,11 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port)
if (sky2->advertising & ADVERTISED_10baseT_Half)
adv |= PHY_M_AN_10_HD;
- adv |= copper_fc_adv[sky2->flow_mode];
} else { /* special defines for FIBER (88E1040S only) */
if (sky2->advertising & ADVERTISED_1000baseT_Full)
adv |= PHY_M_AN_1000X_AFD;
if (sky2->advertising & ADVERTISED_1000baseT_Half)
adv |= PHY_M_AN_1000X_AHD;
-
- adv |= fiber_fc_adv[sky2->flow_mode];
}
/* Restart Auto-negotiation */
@@ -439,8 +436,8 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port)
/* forced speed/duplex settings */
ct1000 = PHY_M_1000C_MSE;
- /* Disable auto update for duplex flow control and speed */
- reg |= GM_GPCR_AU_ALL_DIS;
+ /* Disable auto update for duplex flow control and duplex */
+ reg |= GM_GPCR_AU_DUP_DIS | GM_GPCR_AU_SPD_DIS;
switch (sky2->speed) {
case SPEED_1000:
@@ -458,8 +455,15 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port)
ctrl |= PHY_CT_DUP_MD;
} else if (sky2->speed < SPEED_1000)
sky2->flow_mode = FC_NONE;
+ }
-
+ if (sky2->flags & SKY2_FLAG_AUTO_PAUSE) {
+ if (sky2_is_copper(hw))
+ adv |= copper_fc_adv[sky2->flow_mode];
+ else
+ adv |= fiber_fc_adv[sky2->flow_mode];
+ } else {
+ reg |= GM_GPCR_AU_FCT_DIS;
reg |= gm_fc_disable[sky2->flow_mode];
/* Forward pause packets to GMAC? */
@@ -594,7 +598,8 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port)
/* no effect on Yukon-XL */
gm_phy_write(hw, port, PHY_MARV_LED_CTRL, ledctrl);
- if (sky2->autoneg == AUTONEG_DISABLE || sky2->speed == SPEED_100) {
+ if ( !(sky2->flags & SKY2_FLAG_AUTO_SPEED)
+ || sky2->speed == SPEED_100) {
/* turn on 100 Mbps LED (LED_LINK100) */
ledover |= PHY_M_LED_MO_100(MO_LED_ON);
}
@@ -605,7 +610,7 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port)
}
/* Enable phy interrupt on auto-negotiation complete (or link up) */
- if (sky2->autoneg == AUTONEG_ENABLE)
+ if (sky2->flags & SKY2_FLAG_AUTO_SPEED)
gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_IS_AN_COMPL);
else
gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_DEF_MSK);
@@ -661,7 +666,9 @@ static void sky2_phy_power_down(struct sky2_hw *hw, unsigned port)
/* setup General Purpose Control Register */
gma_write16(hw, port, GM_GP_CTRL,
- GM_GPCR_FL_PASS | GM_GPCR_SPEED_100 | GM_GPCR_AU_ALL_DIS);
+ GM_GPCR_FL_PASS | GM_GPCR_SPEED_100 |
+ GM_GPCR_AU_DUP_DIS | GM_GPCR_AU_FCT_DIS |
+ GM_GPCR_AU_SPD_DIS);
if (hw->chip_id != CHIP_ID_YUKON_EC) {
if (hw->chip_id == CHIP_ID_YUKON_EC_U) {
@@ -989,11 +996,11 @@ static void sky2_prefetch_init(struct sky2_hw *hw, u32 qaddr,
sky2_read32(hw, Y2_QADDR(qaddr, PREF_UNIT_CTRL));
}
-static inline struct sky2_tx_le *get_tx_le(struct sky2_port *sky2)
+static inline struct sky2_tx_le *get_tx_le(struct sky2_port *sky2, u16 *slot)
{
- struct sky2_tx_le *le = sky2->tx_le + sky2->tx_prod;
+ struct sky2_tx_le *le = sky2->tx_le + *slot;
- sky2->tx_prod = RING_NEXT(sky2->tx_prod, TX_RING_SIZE);
+ *slot = RING_NEXT(*slot, TX_RING_SIZE);
le->ctrl = 0;
return le;
}
@@ -1006,7 +1013,7 @@ static void tx_init(struct sky2_port *sky2)
sky2->tx_tcpsum = 0;
sky2->tx_last_mss = 0;
- le = get_tx_le(sky2);
+ le = get_tx_le(sky2, &sky2->tx_prod);
le->addr = 0;
le->opcode = OP_ADDR64 | HW_OWNER;
}
@@ -1117,7 +1124,8 @@ static void rx_set_checksum(struct sky2_port *sky2)
sky2_write32(sky2->hw,
Q_ADDR(rxqaddr[sky2->port], Q_CSR),
- sky2->rx_csum ? BMU_ENA_RX_CHKSUM : BMU_DIS_RX_CHKSUM);
+ (sky2->flags & SKY2_FLAG_RX_CHECKSUM)
+ ? BMU_ENA_RX_CHKSUM : BMU_DIS_RX_CHKSUM);
}
/*
@@ -1500,13 +1508,12 @@ static int sky2_up(struct net_device *dev)
sky2_write32(hw, B0_IMSK, imask);
sky2_read32(hw, B0_IMSK);
- sky2_set_multicast(dev);
-
/* wake queue incase we are restarting */
netif_wake_queue(dev);
if (netif_msg_ifup(sky2))
printk(KERN_INFO PFX "%s: enabling interface\n", dev->name);
+
return 0;
err_out:
@@ -1572,7 +1579,8 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev)
struct sky2_hw *hw = sky2->hw;
struct sky2_tx_le *le = NULL;
struct tx_ring_info *re;
- unsigned i, len, first_slot;
+ unsigned i, len;
+ u16 slot;
dma_addr_t mapping;
u16 mss;
u8 ctrl;
@@ -1586,14 +1594,14 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev)
if (pci_dma_mapping_error(hw->pdev, mapping))
goto mapping_error;
- first_slot = sky2->tx_prod;
+ slot = sky2->tx_prod;
if (unlikely(netif_msg_tx_queued(sky2)))
printk(KERN_DEBUG "%s: tx queued, slot %u, len %d\n",
- dev->name, first_slot, skb->len);
+ dev->name, slot, skb->len);
/* Send high bits if needed */
if (sizeof(dma_addr_t) > sizeof(u32)) {
- le = get_tx_le(sky2);
+ le = get_tx_le(sky2, &slot);
le->addr = cpu_to_le32(upper_32_bits(mapping));
le->opcode = OP_ADDR64 | HW_OWNER;
}
@@ -1606,7 +1614,7 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev)
mss += ETH_HLEN + ip_hdrlen(skb) + tcp_hdrlen(skb);
if (mss != sky2->tx_last_mss) {
- le = get_tx_le(sky2);
+ le = get_tx_le(sky2, &slot);
le->addr = cpu_to_le32(mss);
if (hw->flags & SKY2_HW_NEW_LE)
@@ -1622,7 +1630,7 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev)
/* Add VLAN tag, can piggyback on LRGLEN or ADDR64 */
if (sky2->vlgrp && vlan_tx_tag_present(skb)) {
if (!le) {
- le = get_tx_le(sky2);
+ le = get_tx_le(sky2, &slot);
le->addr = 0;
le->opcode = OP_VLAN|HW_OWNER;
} else
@@ -1651,7 +1659,7 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev)
if (tcpsum != sky2->tx_tcpsum) {
sky2->tx_tcpsum = tcpsum;
- le = get_tx_le(sky2);
+ le = get_tx_le(sky2, &slot);
le->addr = cpu_to_le32(tcpsum);
le->length = 0; /* initial checksum value */
le->ctrl = 1; /* one packet */
@@ -1660,7 +1668,7 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev)
}
}
- le = get_tx_le(sky2);
+ le = get_tx_le(sky2, &slot);
le->addr = cpu_to_le32((u32) mapping);
le->length = cpu_to_le16(len);
le->ctrl = ctrl;
@@ -1681,13 +1689,13 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev)
goto mapping_unwind;
if (sizeof(dma_addr_t) > sizeof(u32)) {
- le = get_tx_le(sky2);
+ le = get_tx_le(sky2, &slot);
le->addr = cpu_to_le32(upper_32_bits(mapping));
le->ctrl = 0;
le->opcode = OP_ADDR64 | HW_OWNER;
}
- le = get_tx_le(sky2);
+ le = get_tx_le(sky2, &slot);
le->addr = cpu_to_le32((u32) mapping);
le->length = cpu_to_le16(frag->size);
le->ctrl = ctrl;
@@ -1701,6 +1709,8 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev)
le->ctrl |= EOP;
+ sky2->tx_prod = slot;
+
if (tx_avail(sky2) <= MAX_SKB_TX_LE)
netif_stop_queue(dev);
@@ -1709,7 +1719,7 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev)
return NETDEV_TX_OK;
mapping_unwind:
- for (i = first_slot; i != sky2->tx_prod; i = RING_NEXT(i, TX_RING_SIZE)) {
+ for (i = sky2->tx_prod; i != slot; i = RING_NEXT(i, TX_RING_SIZE)) {
le = sky2->tx_le + i;
re = sky2->tx_ring + i;
@@ -1729,7 +1739,6 @@ mapping_unwind:
}
}
- sky2->tx_prod = first_slot;
mapping_error:
if (net_ratelimit())
dev_warn(&hw->pdev->dev, "%s: tx mapping error\n", dev->name);
@@ -1740,8 +1749,12 @@ mapping_error:
/*
* Free ring elements from starting at tx_cons until "done"
*
- * NB: the hardware will tell us about partial completion of multi-part
+ * NB:
+ * 1. The hardware will tell us about partial completion of multi-part
* buffers so make sure not to free skb to early.
+ * 2. This may run in parallel start_xmit because the it only
+ * looks at the tail of the queue of FIFO (tx_cons), not
+ * the head (tx_prod)
*/
static void sky2_tx_complete(struct sky2_port *sky2, u16 done)
{
@@ -1799,14 +1812,26 @@ static void sky2_tx_complete(struct sky2_port *sky2, u16 done)
netif_wake_queue(dev);
}
-/* Cleanup all untransmitted buffers, assume transmitter not running */
-static void sky2_tx_clean(struct net_device *dev)
+static void sky2_tx_reset(struct sky2_hw *hw, unsigned port)
{
- struct sky2_port *sky2 = netdev_priv(dev);
+ /* Disable Force Sync bit and Enable Alloc bit */
+ sky2_write8(hw, SK_REG(port, TXA_CTRL),
+ TXA_DIS_FSYNC | TXA_DIS_ALLOC | TXA_STOP_RC);
- netif_tx_lock_bh(dev);
- sky2_tx_complete(sky2, sky2->tx_prod);
- netif_tx_unlock_bh(dev);
+ /* Stop Interval Timer and Limit Counter of Tx Arbiter */
+ sky2_write32(hw, SK_REG(port, TXA_ITI_INI), 0L);
+ sky2_write32(hw, SK_REG(port, TXA_LIM_INI), 0L);
+
+ /* Reset the PCI FIFO of the async Tx queue */
+ sky2_write32(hw, Q_ADDR(txqaddr[port], Q_CSR),
+ BMU_RST_SET | BMU_FIFO_RST);
+
+ /* Reset the Tx prefetch units */
+ sky2_write32(hw, Y2_QADDR(txqaddr[port], PREF_UNIT_CTRL),
+ PREF_UNIT_RST_SET);
+
+ sky2_write32(hw, RB_ADDR(txqaddr[port], RB_CTRL), RB_RST_SET);
+ sky2_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_RST_SET);
}
/* Network shutdown */
@@ -1850,26 +1875,7 @@ static int sky2_down(struct net_device *dev)
&& port == 0 && hw->dev[1] && netif_running(hw->dev[1])))
sky2_write8(hw, SK_REG(port, GMAC_CTRL), GMC_RST_SET);
- /* Disable Force Sync bit and Enable Alloc bit */
- sky2_write8(hw, SK_REG(port, TXA_CTRL),
- TXA_DIS_FSYNC | TXA_DIS_ALLOC | TXA_STOP_RC);
-
- /* Stop Interval Timer and Limit Counter of Tx Arbiter */
- sky2_write32(hw, SK_REG(port, TXA_ITI_INI), 0L);
- sky2_write32(hw, SK_REG(port, TXA_LIM_INI), 0L);
-
- /* Reset the PCI FIFO of the async Tx queue */
- sky2_write32(hw, Q_ADDR(txqaddr[port], Q_CSR),
- BMU_RST_SET | BMU_FIFO_RST);
-
- /* Reset the Tx prefetch units */
- sky2_write32(hw, Y2_QADDR(txqaddr[port], PREF_UNIT_CTRL),
- PREF_UNIT_RST_SET);
-
- sky2_write32(hw, RB_ADDR(txqaddr[port], RB_CTRL), RB_RST_SET);
-
sky2_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_SET);
- sky2_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_RST_SET);
/* Force any delayed status interrrupt and NAPI */
sky2_write32(hw, STAT_LEV_TIMER_CNT, 0);
@@ -1888,12 +1894,18 @@ static int sky2_down(struct net_device *dev)
synchronize_irq(hw->pdev->irq);
napi_synchronize(&hw->napi);
+ spin_lock_bh(&sky2->phy_lock);
sky2_phy_power_down(hw, port);
+ spin_unlock_bh(&sky2->phy_lock);
/* turn off LED's */
sky2_write16(hw, B0_Y2LED, LED_STAT_OFF);
- sky2_tx_clean(dev);
+ sky2_tx_reset(hw, port);
+
+ /* Free any pending frames stuck in HW queue */
+ sky2_tx_complete(sky2, sky2->tx_prod);
+
sky2_rx_clean(sky2);
pci_free_consistent(hw->pdev, RX_LE_BYTES,
@@ -2083,7 +2095,7 @@ static void sky2_phy_intr(struct sky2_hw *hw, unsigned port)
printk(KERN_INFO PFX "%s: phy interrupt status 0x%x 0x%x\n",
sky2->netdev->name, istatus, phystat);
- if (sky2->autoneg == AUTONEG_ENABLE && (istatus & PHY_M_IS_AN_COMPL)) {
+ if (istatus & PHY_M_IS_AN_COMPL) {
if (sky2_autoneg_done(sky2, phystat) == 0)
sky2_link_up(sky2);
goto out;
@@ -2370,11 +2382,8 @@ static inline void sky2_tx_done(struct net_device *dev, u16 last)
{
struct sky2_port *sky2 = netdev_priv(dev);
- if (likely(netif_running(dev) && !sky2->restarting)) {
- netif_tx_lock(dev);
+ if (likely(netif_running(dev) && !sky2->restarting))
sky2_tx_complete(sky2, last);
- netif_tx_unlock(dev);
- }
}
static inline void sky2_skb_rx(const struct sky2_port *sky2,
@@ -2452,7 +2461,7 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do, u16 idx)
/* This chip reports checksum status differently */
if (hw->flags & SKY2_HW_NEW_LE) {
- if (sky2->rx_csum &&
+ if ((sky2->flags & SKY2_FLAG_RX_CHECKSUM) &&
(le->css & (CSS_ISIPV4 | CSS_ISIPV6)) &&
(le->css & CSS_TCPUDPCSOK))
skb->ip_summed = CHECKSUM_UNNECESSARY;
@@ -2479,7 +2488,7 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do, u16 idx)
/* fall through */
#endif
case OP_RXCHKS:
- if (!sky2->rx_csum)
+ if (!(sky2->flags & SKY2_FLAG_RX_CHECKSUM))
break;
/* If this happens then driver assuming wrong format */
@@ -2504,7 +2513,8 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do, u16 idx)
printk(KERN_NOTICE PFX "%s: hardware receive "
"checksum problem (status = %#x)\n",
dev->name, status);
- sky2->rx_csum = 0;
+ sky2->flags &= ~SKY2_FLAG_RX_CHECKSUM;
+
sky2_write32(sky2->hw,
Q_ADDR(rxqaddr[port], Q_CSR),
BMU_DIS_RX_CHKSUM);
@@ -3078,18 +3088,46 @@ static void sky2_reset(struct sky2_hw *hw)
sky2_write8(hw, STAT_ISR_TIMER_CTRL, TIM_START);
}
+/* Take device down (offline).
+ * Equivalent to doing dev_stop() but this does not
+ * inform upper layers of the transistion.
+ */
+static void sky2_detach(struct net_device *dev)
+{
+ if (netif_running(dev)) {
+ netif_device_detach(dev); /* stop txq */
+ sky2_down(dev);
+ }
+}
+
+/* Bring device back after doing sky2_detach */
+static int sky2_reattach(struct net_device *dev)
+{
+ int err = 0;
+
+ if (netif_running(dev)) {
+ err = sky2_up(dev);
+ if (err) {
+ printk(KERN_INFO PFX "%s: could not restart %d\n",
+ dev->name, err);
+ dev_close(dev);
+ } else {
+ netif_device_attach(dev);
+ sky2_set_multicast(dev);
+ }
+ }
+
+ return err;
+}
+
static void sky2_restart(struct work_struct *work)
{
struct sky2_hw *hw = container_of(work, struct sky2_hw, restart_work);
- struct net_device *dev;
- int i, err;
+ int i;
rtnl_lock();
- for (i = 0; i < hw->ports; i++) {
- dev = hw->dev[i];
- if (netif_running(dev))
- sky2_down(dev);
- }
+ for (i = 0; i < hw->ports; i++)
+ sky2_detach(hw->dev[i]);
napi_disable(&hw->napi);
sky2_write32(hw, B0_IMSK, 0);
@@ -3097,17 +3135,8 @@ static void sky2_restart(struct work_struct *work)
sky2_write32(hw, B0_IMSK, Y2_IS_BASE);
napi_enable(&hw->napi);
- for (i = 0; i < hw->ports; i++) {
- dev = hw->dev[i];
- if (netif_running(dev)) {
- err = sky2_up(dev);
- if (err) {
- printk(KERN_INFO PFX "%s: could not restart %d\n",
- dev->name, err);
- dev_close(dev);
- }
- }
- }
+ for (i = 0; i < hw->ports; i++)
+ sky2_reattach(hw->dev[i]);
rtnl_unlock();
}
@@ -3186,7 +3215,8 @@ static int sky2_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
}
ecmd->advertising = sky2->advertising;
- ecmd->autoneg = sky2->autoneg;
+ ecmd->autoneg = (sky2->flags & SKY2_FLAG_AUTO_SPEED)
+ ? AUTONEG_ENABLE : AUTONEG_DISABLE;
ecmd->duplex = sky2->duplex;
return 0;
}
@@ -3198,6 +3228,7 @@ static int sky2_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
u32 supported = sky2_supported_modes(hw);
if (ecmd->autoneg == AUTONEG_ENABLE) {
+ sky2->flags |= SKY2_FLAG_AUTO_SPEED;
ecmd->advertising = supported;
sky2->duplex = -1;
sky2->speed = -1;
@@ -3239,9 +3270,9 @@ static int sky2_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
sky2->speed = ecmd->speed;
sky2->duplex = ecmd->duplex;
+ sky2->flags &= ~SKY2_FLAG_AUTO_SPEED;
}
- sky2->autoneg = ecmd->autoneg;
sky2->advertising = ecmd->advertising;
if (netif_running(dev)) {
@@ -3311,14 +3342,17 @@ static u32 sky2_get_rx_csum(struct net_device *dev)
{
struct sky2_port *sky2 = netdev_priv(dev);
- return sky2->rx_csum;
+ return !!(sky2->flags & SKY2_FLAG_RX_CHECKSUM);
}
static int sky2_set_rx_csum(struct net_device *dev, u32 data)
{
struct sky2_port *sky2 = netdev_priv(dev);
- sky2->rx_csum = data;
+ if (data)
+ sky2->flags |= SKY2_FLAG_RX_CHECKSUM;
+ else
+ sky2->flags &= ~SKY2_FLAG_RX_CHECKSUM;
sky2_write32(sky2->hw, Q_ADDR(rxqaddr[sky2->port], Q_CSR),
data ? BMU_ENA_RX_CHKSUM : BMU_DIS_RX_CHKSUM);
@@ -3336,7 +3370,7 @@ static int sky2_nway_reset(struct net_device *dev)
{
struct sky2_port *sky2 = netdev_priv(dev);
- if (!netif_running(dev) || sky2->autoneg != AUTONEG_ENABLE)
+ if (!netif_running(dev) || !(sky2->flags & SKY2_FLAG_AUTO_SPEED))
return -EINVAL;
sky2_phy_reinit(sky2);
@@ -3576,7 +3610,8 @@ static void sky2_get_pauseparam(struct net_device *dev,
ecmd->tx_pause = ecmd->rx_pause = 1;
}
- ecmd->autoneg = sky2->autoneg;
+ ecmd->autoneg = (sky2->flags & SKY2_FLAG_AUTO_PAUSE)
+ ? AUTONEG_ENABLE : AUTONEG_DISABLE;
}
static int sky2_set_pauseparam(struct net_device *dev,
@@ -3584,7 +3619,11 @@ static int sky2_set_pauseparam(struct net_device *dev,
{
struct sky2_port *sky2 = netdev_priv(dev);
- sky2->autoneg = ecmd->autoneg;
+ if (ecmd->autoneg == AUTONEG_ENABLE)
+ sky2->flags |= SKY2_FLAG_AUTO_PAUSE;
+ else
+ sky2->flags &= ~SKY2_FLAG_AUTO_PAUSE;
+
sky2->flow_mode = sky2_flow(ecmd->rx_pause, ecmd->tx_pause);
if (netif_running(dev))
@@ -3696,7 +3735,6 @@ static int sky2_set_ringparam(struct net_device *dev,
struct ethtool_ringparam *ering)
{
struct sky2_port *sky2 = netdev_priv(dev);
- int err = 0;
if (ering->rx_pending > RX_MAX_PENDING ||
ering->rx_pending < 8 ||
@@ -3704,19 +3742,12 @@ static int sky2_set_ringparam(struct net_device *dev,
ering->tx_pending > TX_RING_SIZE - 1)
return -EINVAL;
- if (netif_running(dev))
- sky2_down(dev);
+ sky2_detach(dev);
sky2->rx_pending = ering->rx_pending;
sky2->tx_pending = ering->tx_pending;
- if (netif_running(dev)) {
- err = sky2_up(dev);
- if (err)
- dev_close(dev);
- }
-
- return err;
+ return sky2_reattach(dev);
}
static int sky2_get_regs_len(struct net_device *dev)
@@ -4128,7 +4159,7 @@ static int sky2_debug_show(struct seq_file *seq, void *v)
seq_printf(seq, "\nRx ring hw get=%d put=%d last=%d\n",
sky2_read16(hw, Y2_QADDR(rxqaddr[port], PREF_UNIT_GET_IDX)),
- last = sky2_read16(hw, Y2_QADDR(rxqaddr[port], PREF_UNIT_PUT_IDX)),
+ sky2_read16(hw, Y2_QADDR(rxqaddr[port], PREF_UNIT_PUT_IDX)),
sky2_read16(hw, Y2_QADDR(rxqaddr[port], PREF_UNIT_LAST_IDX)));
sky2_read32(hw, B0_Y2_SP_LISR);
@@ -4282,13 +4313,15 @@ static __devinit struct net_device *sky2_init_netdev(struct sky2_hw *hw,
sky2->msg_enable = netif_msg_init(debug, default_msg);
/* Auto speed and flow control */
- sky2->autoneg = AUTONEG_ENABLE;
+ sky2->flags = SKY2_FLAG_AUTO_SPEED | SKY2_FLAG_AUTO_PAUSE;
+ if (hw->chip_id != CHIP_ID_YUKON_XL)
+ sky2->flags |= SKY2_FLAG_RX_CHECKSUM;
+
sky2->flow_mode = FC_BOTH;
sky2->duplex = -1;
sky2->speed = -1;
sky2->advertising = sky2_supported_modes(hw);
- sky2->rx_csum = (hw->chip_id != CHIP_ID_YUKON_XL);
sky2->wol = wol;
spin_lock_init(&sky2->phy_lock);
@@ -4634,13 +4667,12 @@ static int sky2_suspend(struct pci_dev *pdev, pm_message_t state)
del_timer_sync(&hw->watchdog_timer);
cancel_work_sync(&hw->restart_work);
+ rtnl_lock();
for (i = 0; i < hw->ports; i++) {
struct net_device *dev = hw->dev[i];
struct sky2_port *sky2 = netdev_priv(dev);
- netif_device_detach(dev);
- if (netif_running(dev))
- sky2_down(dev);
+ sky2_detach(dev);
if (sky2->wol)
sky2_wol_init(sky2);
@@ -4651,6 +4683,7 @@ static int sky2_suspend(struct pci_dev *pdev, pm_message_t state)
sky2_write32(hw, B0_IMSK, 0);
napi_disable(&hw->napi);
sky2_power_aux(hw);
+ rtnl_unlock();
pci_save_state(pdev);
pci_enable_wake(pdev, pci_choose_state(pdev, state), wol);
@@ -4687,25 +4720,18 @@ static int sky2_resume(struct pci_dev *pdev)
sky2_write32(hw, B0_IMSK, Y2_IS_BASE);
napi_enable(&hw->napi);
+ rtnl_lock();
for (i = 0; i < hw->ports; i++) {
- struct net_device *dev = hw->dev[i];
-
- netif_device_attach(dev);
- if (netif_running(dev)) {
- err = sky2_up(dev);
- if (err) {
- printk(KERN_ERR PFX "%s: could not up: %d\n",
- dev->name, err);
- rtnl_lock();
- dev_close(dev);
- rtnl_unlock();
- goto out;
- }
- }
+ err = sky2_reattach(hw->dev[i]);
+ if (err)
+ goto out;
}
+ rtnl_unlock();
return 0;
out:
+ rtnl_unlock();
+
dev_err(&pdev->dev, "resume failed (%d)\n", err);
pci_disable_device(pdev);
return err;
@@ -4720,6 +4746,7 @@ static void sky2_shutdown(struct pci_dev *pdev)
if (!hw)
return;
+ rtnl_lock();
del_timer_sync(&hw->watchdog_timer);
for (i = 0; i < hw->ports; i++) {
@@ -4734,6 +4761,7 @@ static void sky2_shutdown(struct pci_dev *pdev)
if (wol)
sky2_power_aux(hw);
+ rtnl_unlock();
pci_enable_wake(pdev, PCI_D3hot, wol);
pci_enable_wake(pdev, PCI_D3cold, wol);
diff --git a/drivers/net/sky2.h b/drivers/net/sky2.h
index 4486b066b43..c9548d6d567 100644
--- a/drivers/net/sky2.h
+++ b/drivers/net/sky2.h
@@ -1583,7 +1583,6 @@ enum {
};
#define GM_GPCR_SPEED_1000 (GM_GPCR_GIGS_ENA | GM_GPCR_SPEED_100)
-#define GM_GPCR_AU_ALL_DIS (GM_GPCR_AU_DUP_DIS | GM_GPCR_AU_FCT_DIS|GM_GPCR_AU_SPD_DIS)
/* GM_TX_CTRL 16 bit r/w Transmit Control Register */
enum {
@@ -2042,15 +2041,18 @@ struct sky2_port {
u8 fifo_lev;
} check;
-
dma_addr_t rx_le_map;
dma_addr_t tx_le_map;
+
u16 advertising; /* ADVERTISED_ bits */
- u16 speed; /* SPEED_1000, SPEED_100, ... */
- u8 autoneg; /* AUTONEG_ENABLE, AUTONEG_DISABLE */
- u8 duplex; /* DUPLEX_HALF, DUPLEX_FULL */
- u8 rx_csum;
- u8 wol;
+ u16 speed; /* SPEED_1000, SPEED_100, ... */
+ u8 wol; /* WAKE_ bits */
+ u8 duplex; /* DUPLEX_HALF, DUPLEX_FULL */
+ u16 flags;
+#define SKY2_FLAG_RX_CHECKSUM 0x0001
+#define SKY2_FLAG_AUTO_SPEED 0x0002
+#define SKY2_FLAG_AUTO_PAUSE 0x0004
+
u8 restarting;
enum flow_control flow_mode;
enum flow_control flow_status;
diff --git a/drivers/net/slip.c b/drivers/net/slip.c
index 5c61d5fad90..899c4a2112c 100644
--- a/drivers/net/slip.c
+++ b/drivers/net/slip.c
@@ -484,12 +484,12 @@ sl_xmit(struct sk_buff *skb, struct net_device *dev)
spin_unlock(&sl->lock);
printk(KERN_WARNING "%s: xmit call when iface is down\n", dev->name);
dev_kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
}
if (sl->tty == NULL) {
spin_unlock(&sl->lock);
dev_kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
}
sl_lock(sl);
@@ -498,7 +498,7 @@ sl_xmit(struct sk_buff *skb, struct net_device *dev)
spin_unlock(&sl->lock);
dev_kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
}
diff --git a/drivers/net/smc911x.c b/drivers/net/smc911x.c
index bc4976ac871..2a6b6de9533 100644
--- a/drivers/net/smc911x.c
+++ b/drivers/net/smc911x.c
@@ -553,7 +553,7 @@ static int smc911x_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
dev->stats.tx_dropped++;
spin_unlock_irqrestore(&lp->lock, flags);
dev_kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
}
#ifdef SMC_USE_DMA
@@ -566,7 +566,7 @@ static int smc911x_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
lp->pending_tx_skb = skb;
netif_stop_queue(dev);
spin_unlock_irqrestore(&lp->lock, flags);
- return 0;
+ return NETDEV_TX_OK;
} else {
DBG(SMC_DEBUG_TX | SMC_DEBUG_DMA, "%s: Activating Tx DMA\n", dev->name);
lp->txdma_active = 1;
@@ -577,7 +577,7 @@ static int smc911x_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
smc911x_hardware_send_pkt(dev);
spin_unlock_irqrestore(&lp->lock, flags);
- return 0;
+ return NETDEV_TX_OK;
}
/*
diff --git a/drivers/net/smc911x.h b/drivers/net/smc911x.h
index 8140f7cb4d8..05adb6a666c 100644
--- a/drivers/net/smc911x.h
+++ b/drivers/net/smc911x.h
@@ -236,7 +236,6 @@ static inline void SMC_outsl(struct smc911x_local *lp, int reg,
* Use a DMA for RX and TX packets.
*/
#include <linux/dma-mapping.h>
-#include <mach/dma.h>
static dma_addr_t rx_dmabuf, tx_dmabuf;
static int rx_dmalen, tx_dmalen;
diff --git a/drivers/net/smc9194.c b/drivers/net/smc9194.c
index e02471b2f2b..0a1b6f40108 100644
--- a/drivers/net/smc9194.c
+++ b/drivers/net/smc9194.c
@@ -512,7 +512,7 @@ static int smc_wait_to_send_packet( struct sk_buff * skb, struct net_device * de
if (length < ETH_ZLEN) {
if (skb_padto(skb, ETH_ZLEN)) {
netif_wake_queue(dev);
- return 0;
+ return NETDEV_TX_OK;
}
length = ETH_ZLEN;
}
@@ -534,7 +534,7 @@ static int smc_wait_to_send_packet( struct sk_buff * skb, struct net_device * de
lp->saved_skb = NULL;
/* this IS an error, but, i don't want the skb saved */
netif_wake_queue(dev);
- return 0;
+ return NETDEV_TX_OK;
}
/* either way, a packet is waiting now */
lp->packets_waiting++;
@@ -571,12 +571,12 @@ static int smc_wait_to_send_packet( struct sk_buff * skb, struct net_device * de
SMC_ENABLE_INT( IM_ALLOC_INT );
PRINTK2((CARDNAME": memory allocation deferred. \n"));
/* it's deferred, but I'll handle it later */
- return 0;
+ return NETDEV_TX_OK;
}
/* or YES! I can send the packet now.. */
smc_hardware_send_packet(dev);
netif_wake_queue(dev);
- return 0;
+ return NETDEV_TX_OK;
}
/*
diff --git a/drivers/net/smc91x.c b/drivers/net/smc91x.c
index 1c70e999cc5..0f2c52c2e04 100644
--- a/drivers/net/smc91x.c
+++ b/drivers/net/smc91x.c
@@ -655,7 +655,7 @@ static int smc_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
dev->stats.tx_errors++;
dev->stats.tx_dropped++;
dev_kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
}
smc_special_lock(&lp->lock);
@@ -692,7 +692,7 @@ static int smc_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
smc_hardware_send_pkt((unsigned long)dev);
}
- return 0;
+ return NETDEV_TX_OK;
}
/*
diff --git a/drivers/net/smsc911x.c b/drivers/net/smsc911x.c
index 94b6d2658dd..c2667855a00 100644
--- a/drivers/net/smsc911x.c
+++ b/drivers/net/smsc911x.c
@@ -50,6 +50,7 @@
#include <linux/swab.h>
#include <linux/phy.h>
#include <linux/smsc911x.h>
+#include <linux/device.h>
#include "smsc911x.h"
#define SMSC_CHIPNAME "smsc911x"
@@ -2114,10 +2115,12 @@ out_0:
/* This implementation assumes the devices remains powered on its VDDVARIO
* pins during suspend. */
-static int smsc911x_suspend(struct platform_device *pdev, pm_message_t state)
+/* TODO: implement freeze/thaw callbacks for hibernation.*/
+
+static int smsc911x_suspend(struct device *dev)
{
- struct net_device *dev = platform_get_drvdata(pdev);
- struct smsc911x_data *pdata = netdev_priv(dev);
+ struct net_device *ndev = dev_get_drvdata(dev);
+ struct smsc911x_data *pdata = netdev_priv(ndev);
/* enable wake on LAN, energy detection and the external PME
* signal. */
@@ -2128,10 +2131,10 @@ static int smsc911x_suspend(struct platform_device *pdev, pm_message_t state)
return 0;
}
-static int smsc911x_resume(struct platform_device *pdev)
+static int smsc911x_resume(struct device *dev)
{
- struct net_device *dev = platform_get_drvdata(pdev);
- struct smsc911x_data *pdata = netdev_priv(dev);
+ struct net_device *ndev = dev_get_drvdata(dev);
+ struct smsc911x_data *pdata = netdev_priv(ndev);
unsigned int to = 100;
/* Note 3.11 from the datasheet:
@@ -2149,19 +2152,25 @@ static int smsc911x_resume(struct platform_device *pdev)
return (to == 0) ? -EIO : 0;
}
+static struct dev_pm_ops smsc911x_pm_ops = {
+ .suspend = smsc911x_suspend,
+ .resume = smsc911x_resume,
+};
+
+#define SMSC911X_PM_OPS (&smsc911x_pm_ops)
+
#else
-#define smsc911x_suspend NULL
-#define smsc911x_resume NULL
+#define SMSC911X_PM_OPS NULL
#endif
static struct platform_driver smsc911x_driver = {
.probe = smsc911x_drv_probe,
.remove = __devexit_p(smsc911x_drv_remove),
.driver = {
- .name = SMSC_CHIPNAME,
+ .name = SMSC_CHIPNAME,
+ .owner = THIS_MODULE,
+ .pm = SMSC911X_PM_OPS,
},
- .suspend = smsc911x_suspend,
- .resume = smsc911x_resume,
};
/* Entry point for loading the module */
diff --git a/drivers/net/sonic.c b/drivers/net/sonic.c
index 753a1fba460..9599ce77ef8 100644
--- a/drivers/net/sonic.c
+++ b/drivers/net/sonic.c
@@ -211,7 +211,7 @@ static int sonic_send_packet(struct sk_buff *skb, struct net_device *dev)
length = skb->len;
if (length < ETH_ZLEN) {
if (skb_padto(skb, ETH_ZLEN))
- return 0;
+ return NETDEV_TX_OK;
length = ETH_ZLEN;
}
@@ -265,7 +265,7 @@ static int sonic_send_packet(struct sk_buff *skb, struct net_device *dev)
dev->trans_start = jiffies;
- return 0;
+ return NETDEV_TX_OK;
}
/*
diff --git a/drivers/net/starfire.c b/drivers/net/starfire.c
index 669253c7bd4..5e7645ee8ab 100644
--- a/drivers/net/starfire.c
+++ b/drivers/net/starfire.c
@@ -1311,7 +1311,7 @@ static int start_tx(struct sk_buff *skb, struct net_device *dev)
dev->trans_start = jiffies;
- return 0;
+ return NETDEV_TX_OK;
}
diff --git a/drivers/net/sun3_82586.c b/drivers/net/sun3_82586.c
index 7bb27426dbd..2f1eaaf7a72 100644
--- a/drivers/net/sun3_82586.c
+++ b/drivers/net/sun3_82586.c
@@ -1015,7 +1015,7 @@ static int sun3_82586_send_packet(struct sk_buff *skb, struct net_device *dev)
if(skb->len > XMIT_BUFF_SIZE)
{
printk("%s: Sorry, max. framelength is %d bytes. The length of your frame is %d bytes.\n",dev->name,XMIT_BUFF_SIZE,skb->len);
- return 0;
+ return NETDEV_TX_OK;
}
netif_stop_queue(dev);
@@ -1110,7 +1110,7 @@ static int sun3_82586_send_packet(struct sk_buff *skb, struct net_device *dev)
dev_kfree_skb(skb);
#endif
}
- return 0;
+ return NETDEV_TX_OK;
}
/*******************************************
diff --git a/drivers/net/sun3lance.c b/drivers/net/sun3lance.c
index 534dfe3eef6..0ca4241b4f6 100644
--- a/drivers/net/sun3lance.c
+++ b/drivers/net/sun3lance.c
@@ -562,7 +562,7 @@ static int lance_start_xmit( struct sk_buff *skb, struct net_device *dev )
netif_start_queue(dev);
dev->trans_start = jiffies;
- return 0;
+ return NETDEV_TX_OK;
}
@@ -648,7 +648,7 @@ static int lance_start_xmit( struct sk_buff *skb, struct net_device *dev )
local_irq_restore(flags);
- return 0;
+ return NETDEV_TX_OK;
}
/* The LANCE interrupt handler. */
diff --git a/drivers/net/sunbmac.c b/drivers/net/sunbmac.c
index 5017d7fcb40..536cf7e06bf 100644
--- a/drivers/net/sunbmac.c
+++ b/drivers/net/sunbmac.c
@@ -984,7 +984,7 @@ static int bigmac_start_xmit(struct sk_buff *skb, struct net_device *dev)
dev->trans_start = jiffies;
- return 0;
+ return NETDEV_TX_OK;
}
static struct net_device_stats *bigmac_get_stats(struct net_device *dev)
diff --git a/drivers/net/sundance.c b/drivers/net/sundance.c
index d1521c3875b..d09be481bcc 100644
--- a/drivers/net/sundance.c
+++ b/drivers/net/sundance.c
@@ -1091,7 +1091,7 @@ start_tx (struct sk_buff *skb, struct net_device *dev)
"%s: Transmit frame #%d queued in slot %d.\n",
dev->name, np->cur_tx, entry);
}
- return 0;
+ return NETDEV_TX_OK;
}
/* Reset hardware tx and free all of tx buffers */
diff --git a/drivers/net/sunhme.c b/drivers/net/sunhme.c
index 4ef729198e1..008bd59fc64 100644
--- a/drivers/net/sunhme.c
+++ b/drivers/net/sunhme.c
@@ -2338,7 +2338,7 @@ static int happy_meal_start_xmit(struct sk_buff *skb, struct net_device *dev)
dev->trans_start = jiffies;
tx_add_log(hp, TXLOG_ACTION_TXMIT, 0);
- return 0;
+ return NETDEV_TX_OK;
}
static struct net_device_stats *happy_meal_get_stats(struct net_device *dev)
diff --git a/drivers/net/sunlance.c b/drivers/net/sunlance.c
index afc7b351e5e..9d6fd4760ea 100644
--- a/drivers/net/sunlance.c
+++ b/drivers/net/sunlance.c
@@ -1163,7 +1163,7 @@ static int lance_start_xmit(struct sk_buff *skb, struct net_device *dev)
dev->trans_start = jiffies;
dev_kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
}
/* taken from the depca driver */
diff --git a/drivers/net/sunqe.c b/drivers/net/sunqe.c
index c6ec61e0acc..dcefb608a9f 100644
--- a/drivers/net/sunqe.c
+++ b/drivers/net/sunqe.c
@@ -621,7 +621,7 @@ static int qe_start_xmit(struct sk_buff *skb, struct net_device *dev)
dev_kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
}
static void qe_set_multicast(struct net_device *dev)
diff --git a/drivers/net/tc35815.c b/drivers/net/tc35815.c
index d737f6b8f87..d1298e5b72c 100644
--- a/drivers/net/tc35815.c
+++ b/drivers/net/tc35815.c
@@ -23,9 +23,9 @@
*/
#ifdef TC35815_NAPI
-#define DRV_VERSION "1.37-NAPI"
+#define DRV_VERSION "1.38-NAPI"
#else
-#define DRV_VERSION "1.37"
+#define DRV_VERSION "1.38"
#endif
static const char *version = "tc35815.c:v" DRV_VERSION "\n";
#define MODNAME "tc35815"
@@ -341,8 +341,9 @@ struct BDesc {
Tx_EnExColl | Tx_EnLCarr | Tx_EnExDefer | Tx_EnUnder | \
Tx_En) /* maybe 0x7b01 */
#endif
+/* Do not use Rx_StripCRC -- it causes trouble on BLEx/FDAEx condition */
#define RX_CTL_CMD (Rx_EnGood | Rx_EnRxPar | Rx_EnLongErr | Rx_EnOver \
- | Rx_EnCRCErr | Rx_EnAlign | Rx_StripCRC | Rx_RxEn) /* maybe 0x6f11 */
+ | Rx_EnCRCErr | Rx_EnAlign | Rx_RxEn) /* maybe 0x6f01 */
#define INT_EN_CMD (Int_NRAbtEn | \
Int_DmParErrEn | Int_DParDEn | Int_DParErrEn | \
Int_SSysErrEn | Int_RMasAbtEn | Int_RTargAbtEn | \
@@ -593,9 +594,10 @@ static int tc_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
struct net_device *dev = bus->priv;
struct tc35815_regs __iomem *tr =
(struct tc35815_regs __iomem *)dev->base_addr;
- unsigned long timeout = jiffies + 10;
+ unsigned long timeout = jiffies + HZ;
tc_writel(MD_CA_Busy | (mii_id << 5) | (regnum & 0x1f), &tr->MD_CA);
+ udelay(12); /* it takes 32 x 400ns at least */
while (tc_readl(&tr->MD_CA) & MD_CA_Busy) {
if (time_after(jiffies, timeout))
return -EIO;
@@ -609,11 +611,12 @@ static int tc_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u16 val)
struct net_device *dev = bus->priv;
struct tc35815_regs __iomem *tr =
(struct tc35815_regs __iomem *)dev->base_addr;
- unsigned long timeout = jiffies + 10;
+ unsigned long timeout = jiffies + HZ;
tc_writel(val, &tr->MD_Data);
tc_writel(MD_CA_Busy | MD_CA_Wr | (mii_id << 5) | (regnum & 0x1f),
&tr->MD_CA);
+ udelay(12); /* it takes 32 x 400ns at least */
while (tc_readl(&tr->MD_CA) & MD_CA_Busy) {
if (time_after(jiffies, timeout))
return -EIO;
@@ -1509,7 +1512,7 @@ static int tc35815_send_packet(struct sk_buff *skb, struct net_device *dev)
*/
spin_unlock_irqrestore(&lp->lock, flags);
- return 0;
+ return NETDEV_TX_OK;
}
#define FATAL_ERROR_INT \
@@ -1540,8 +1543,6 @@ static int tc35815_do_interrupt(struct net_device *dev, u32 status)
#endif
{
struct tc35815_local *lp = netdev_priv(dev);
- struct tc35815_regs __iomem *tr =
- (struct tc35815_regs __iomem *)dev->base_addr;
int ret = -1;
/* Fatal errors... */
@@ -1551,27 +1552,26 @@ static int tc35815_do_interrupt(struct net_device *dev, u32 status)
}
/* recoverable errors */
if (status & Int_IntFDAEx) {
- /* disable FDAEx int. (until we make rooms...) */
- tc_writel(tc_readl(&tr->Int_En) & ~Int_FDAExEn, &tr->Int_En);
- printk(KERN_WARNING
- "%s: Free Descriptor Area Exhausted (%#x).\n",
- dev->name, status);
+ if (netif_msg_rx_err(lp))
+ dev_warn(&dev->dev,
+ "Free Descriptor Area Exhausted (%#x).\n",
+ status);
dev->stats.rx_dropped++;
ret = 0;
}
if (status & Int_IntBLEx) {
- /* disable BLEx int. (until we make rooms...) */
- tc_writel(tc_readl(&tr->Int_En) & ~Int_BLExEn, &tr->Int_En);
- printk(KERN_WARNING
- "%s: Buffer List Exhausted (%#x).\n",
- dev->name, status);
+ if (netif_msg_rx_err(lp))
+ dev_warn(&dev->dev,
+ "Buffer List Exhausted (%#x).\n",
+ status);
dev->stats.rx_dropped++;
ret = 0;
}
if (status & Int_IntExBD) {
- printk(KERN_WARNING
- "%s: Excessive Buffer Descriptiors (%#x).\n",
- dev->name, status);
+ if (netif_msg_rx_err(lp))
+ dev_warn(&dev->dev,
+ "Excessive Buffer Descriptiors (%#x).\n",
+ status);
dev->stats.rx_length_errors++;
ret = 0;
}
@@ -1630,8 +1630,12 @@ static irqreturn_t tc35815_interrupt(int irq, void *dev_id)
spin_lock(&lp->lock);
status = tc_readl(&tr->Int_Src);
- tc_writel(status, &tr->Int_Src); /* write to clear */
+ /* BLEx, FDAEx will be cleared later */
+ tc_writel(status & ~(Int_BLEx | Int_FDAEx),
+ &tr->Int_Src); /* write to clear */
handled = tc35815_do_interrupt(dev, status);
+ if (status & (Int_BLEx | Int_FDAEx))
+ tc_writel(status & (Int_BLEx | Int_FDAEx), &tr->Int_Src);
(void)tc_readl(&tr->Int_Src); /* flush */
spin_unlock(&lp->lock);
return IRQ_RETVAL(handled >= 0);
@@ -1659,8 +1663,6 @@ tc35815_rx(struct net_device *dev)
struct tc35815_local *lp = netdev_priv(dev);
unsigned int fdctl;
int i;
- int buf_free_count = 0;
- int fd_free_count = 0;
#ifdef TC35815_NAPI
int received = 0;
#endif
@@ -1769,8 +1771,9 @@ tc35815_rx(struct net_device *dev)
dev->stats.rx_bytes += pkt_len;
} else {
dev->stats.rx_errors++;
- printk(KERN_DEBUG "%s: Rx error (status %x)\n",
- dev->name, status & Rx_Stat_Mask);
+ if (netif_msg_rx_err(lp))
+ dev_info(&dev->dev, "Rx error (status %x)\n",
+ status & Rx_Stat_Mask);
/* WORKAROUND: LongErr and CRCErr means Overflow. */
if ((status & Rx_LongErr) && (status & Rx_CRCErr)) {
status &= ~(Rx_LongErr|Rx_CRCErr);
@@ -1848,7 +1851,6 @@ tc35815_rx(struct net_device *dev)
#else
lp->fbl_count++;
#endif
- buf_free_count++;
}
}
@@ -1870,7 +1872,6 @@ tc35815_rx(struct net_device *dev)
#endif
lp->rfd_cur->fd.FDCtl = cpu_to_le32(FD_CownsFD);
lp->rfd_cur++;
- fd_free_count++;
}
if (lp->rfd_cur > lp->rfd_limit)
lp->rfd_cur = lp->rfd_base;
@@ -1881,17 +1882,6 @@ tc35815_rx(struct net_device *dev)
#endif
}
- /* re-enable BL/FDA Exhaust interrupts. */
- if (fd_free_count) {
- struct tc35815_regs __iomem *tr =
- (struct tc35815_regs __iomem *)dev->base_addr;
- u32 en, en_old = tc_readl(&tr->Int_En);
- en = en_old | Int_FDAExEn;
- if (buf_free_count)
- en |= Int_BLExEn;
- if (en != en_old)
- tc_writel(en, &tr->Int_En);
- }
#ifdef TC35815_NAPI
return received;
#endif
@@ -1910,9 +1900,14 @@ static int tc35815_poll(struct napi_struct *napi, int budget)
spin_lock(&lp->lock);
status = tc_readl(&tr->Int_Src);
do {
- tc_writel(status, &tr->Int_Src); /* write to clear */
+ /* BLEx, FDAEx will be cleared later */
+ tc_writel(status & ~(Int_BLEx | Int_FDAEx),
+ &tr->Int_Src); /* write to clear */
handled = tc35815_do_interrupt(dev, status, budget - received);
+ if (status & (Int_BLEx | Int_FDAEx))
+ tc_writel(status & (Int_BLEx | Int_FDAEx),
+ &tr->Int_Src);
if (handled >= 0) {
received += handled;
if (received >= budget)
@@ -2144,7 +2139,7 @@ static struct net_device_stats *tc35815_get_stats(struct net_device *dev)
(struct tc35815_regs __iomem *)dev->base_addr;
if (netif_running(dev))
/* Update the statistics from the device registers. */
- dev->stats.rx_missed_errors = tc_readl(&tr->Miss_Cnt);
+ dev->stats.rx_missed_errors += tc_readl(&tr->Miss_Cnt);
return &dev->stats;
}
@@ -2399,8 +2394,6 @@ static void tc35815_chip_init(struct net_device *dev)
tc_writel(DMA_BURST_SIZE, &tr->DMA_Ctl);
#ifdef TC35815_USE_PACKEDBUFFER
tc_writel(RxFrag_EnPack | ETH_ZLEN, &tr->RxFragSize); /* Packing */
-#else
- tc_writel(ETH_ZLEN, &tr->RxFragSize);
#endif
tc_writel(0, &tr->TxPollCtr); /* Batch mode */
tc_writel(TX_THRESHOLD, &tr->TxThrsh);
diff --git a/drivers/net/tlan.c b/drivers/net/tlan.c
index 384cb5e2839..70c9ec45d8f 100644
--- a/drivers/net/tlan.c
+++ b/drivers/net/tlan.c
@@ -1095,11 +1095,11 @@ static int TLan_StartTx( struct sk_buff *skb, struct net_device *dev )
TLAN_DBG( TLAN_DEBUG_TX, "TRANSMIT: %s PHY is not ready\n",
dev->name );
dev_kfree_skb_any(skb);
- return 0;
+ return NETDEV_TX_OK;
}
if (skb_padto(skb, TLAN_MIN_FRAME_SIZE))
- return 0;
+ return NETDEV_TX_OK;
txlen = max(skb->len, (unsigned int)TLAN_MIN_FRAME_SIZE);
tail_list = priv->txList + priv->txTail;
@@ -1150,7 +1150,7 @@ static int TLan_StartTx( struct sk_buff *skb, struct net_device *dev )
CIRC_INC( priv->txTail, TLAN_NUM_TX_LISTS );
dev->trans_start = jiffies;
- return 0;
+ return NETDEV_TX_OK;
} /* TLan_StartTx */
diff --git a/drivers/net/tokenring/3c359.c b/drivers/net/tokenring/3c359.c
index b40b6de2d08..1787d52941b 100644
--- a/drivers/net/tokenring/3c359.c
+++ b/drivers/net/tokenring/3c359.c
@@ -1240,7 +1240,7 @@ static int xl_xmit(struct sk_buff *skb, struct net_device *dev)
spin_unlock_irqrestore(&xl_priv->xl_lock,flags) ;
- return 0;
+ return NETDEV_TX_OK;
} else {
spin_unlock_irqrestore(&xl_priv->xl_lock,flags) ;
return NETDEV_TX_BUSY;
diff --git a/drivers/net/tokenring/ibmtr.c b/drivers/net/tokenring/ibmtr.c
index 08a6c41c159..96d00c8f8d3 100644
--- a/drivers/net/tokenring/ibmtr.c
+++ b/drivers/net/tokenring/ibmtr.c
@@ -1041,7 +1041,7 @@ static int tok_send_packet(struct sk_buff *skb, struct net_device *dev)
writeb(CMD_IN_SRB, ti->mmio + ACA_OFFSET + ACA_SET + ISRA_ODD);
spin_unlock_irqrestore(&(ti->lock), flags);
dev->trans_start = jiffies;
- return 0;
+ return NETDEV_TX_OK;
}
/*****************************************************************************/
diff --git a/drivers/net/tokenring/lanstreamer.c b/drivers/net/tokenring/lanstreamer.c
index b3715efdce5..d07e61a9499 100644
--- a/drivers/net/tokenring/lanstreamer.c
+++ b/drivers/net/tokenring/lanstreamer.c
@@ -1183,7 +1183,7 @@ static int streamer_xmit(struct sk_buff *skb, struct net_device *dev)
streamer_priv->tx_ring_free = (streamer_priv->tx_ring_free + 1) & (STREAMER_TX_RING_SIZE - 1);
spin_unlock_irqrestore(&streamer_priv->streamer_lock,flags);
- return 0;
+ return NETDEV_TX_OK;
} else {
netif_stop_queue(dev);
spin_unlock_irqrestore(&streamer_priv->streamer_lock,flags);
diff --git a/drivers/net/tokenring/olympic.c b/drivers/net/tokenring/olympic.c
index 451b54136ed..f73f4e684f3 100644
--- a/drivers/net/tokenring/olympic.c
+++ b/drivers/net/tokenring/olympic.c
@@ -1052,7 +1052,7 @@ static int olympic_xmit(struct sk_buff *skb, struct net_device *dev)
writew((((readw(olympic_mmio+TXENQ_1)) & 0x8000) ^ 0x8000) | 1,olympic_mmio+TXENQ_1);
netif_wake_queue(dev);
spin_unlock_irqrestore(&olympic_priv->olympic_lock,flags);
- return 0;
+ return NETDEV_TX_OK;
} else {
spin_unlock_irqrestore(&olympic_priv->olympic_lock,flags);
return NETDEV_TX_BUSY;
diff --git a/drivers/net/tokenring/smctr.c b/drivers/net/tokenring/smctr.c
index 54ad4ed0337..23e012f5bbf 100644
--- a/drivers/net/tokenring/smctr.c
+++ b/drivers/net/tokenring/smctr.c
@@ -3091,11 +3091,7 @@ static int smctr_lobe_media_test(struct net_device *dev)
/* Setup the lobe media test. */
smctr_lobe_media_test_cmd(dev);
if(smctr_wait_cmd(dev))
- {
- smctr_reset_adapter(dev);
- tp->status = CLOSED;
- return (LOBE_MEDIA_TEST_FAILED);
- }
+ goto err;
/* Tx lobe media test frames. */
for(i = 0; i < 1500; ++i)
@@ -3103,20 +3099,12 @@ static int smctr_lobe_media_test(struct net_device *dev)
if(smctr_send_lobe_media_test(dev))
{
if(perror)
- {
- smctr_reset_adapter(dev);
- tp->state = CLOSED;
- return (LOBE_MEDIA_TEST_FAILED);
- }
+ goto err;
else
{
perror = 1;
if(smctr_lobe_media_test_cmd(dev))
- {
- smctr_reset_adapter(dev);
- tp->state = CLOSED;
- return (LOBE_MEDIA_TEST_FAILED);
- }
+ goto err;
}
}
}
@@ -3124,28 +3112,24 @@ static int smctr_lobe_media_test(struct net_device *dev)
if(smctr_send_dat(dev))
{
if(smctr_send_dat(dev))
- {
- smctr_reset_adapter(dev);
- tp->state = CLOSED;
- return (LOBE_MEDIA_TEST_FAILED);
- }
+ goto err;
}
/* Check if any frames received during test. */
if((tp->rx_fcb_curr[MAC_QUEUE]->frame_status)
|| (tp->rx_fcb_curr[NON_MAC_QUEUE]->frame_status))
- {
- smctr_reset_adapter(dev);
- tp->state = CLOSED;
- return (LOBE_MEDIA_TEST_FAILED);
- }
+ goto err;
/* Set receive mask to "Promisc" mode. */
tp->receive_mask = saved_rcv_mask;
smctr_chg_rx_mask(dev);
- return (0);
+ return 0;
+err:
+ smctr_reset_adapter(dev);
+ tp->status = CLOSED;
+ return LOBE_MEDIA_TEST_FAILED;
}
static int smctr_lobe_media_test_cmd(struct net_device *dev)
@@ -4609,7 +4593,7 @@ static int smctr_send_packet(struct sk_buff *skb, struct net_device *dev)
if(tp->QueueSkb > 0)
netif_wake_queue(dev);
- return (0);
+ return NETDEV_TX_OK;
}
static int smctr_send_lobe_media_test(struct net_device *dev)
diff --git a/drivers/net/tokenring/tms380tr.c b/drivers/net/tokenring/tms380tr.c
index a2eab72b507..07f6dfd3ba0 100644
--- a/drivers/net/tokenring/tms380tr.c
+++ b/drivers/net/tokenring/tms380tr.c
@@ -682,7 +682,7 @@ static int tms380tr_hardware_send_packet(struct sk_buff *skb, struct net_device
tms380tr_exec_sifcmd(dev, CMD_TX_VALID);
spin_unlock_irqrestore(&tp->lock, flags);
- return 0;
+ return NETDEV_TX_OK;
}
/*
diff --git a/drivers/net/tulip/de2104x.c b/drivers/net/tulip/de2104x.c
index ef49744a508..bc8a6b263b4 100644
--- a/drivers/net/tulip/de2104x.c
+++ b/drivers/net/tulip/de2104x.c
@@ -651,7 +651,7 @@ static int de_start_xmit (struct sk_buff *skb, struct net_device *dev)
dw32(TxPoll, NormalTxPoll);
dev->trans_start = jiffies;
- return 0;
+ return NETDEV_TX_OK;
}
/* Set or clear the multicast filter for this adaptor.
diff --git a/drivers/net/tulip/dmfe.c b/drivers/net/tulip/dmfe.c
index 8e78f003f08..5e15fab58c1 100644
--- a/drivers/net/tulip/dmfe.c
+++ b/drivers/net/tulip/dmfe.c
@@ -676,7 +676,7 @@ static int dmfe_start_xmit(struct sk_buff *skb, struct DEVICE *dev)
if (skb->len > MAX_PACKET_SIZE) {
printk(KERN_ERR DRV_NAME ": big packet = %d\n", (u16)skb->len);
dev_kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
}
spin_lock_irqsave(&db->lock, flags);
@@ -722,7 +722,7 @@ static int dmfe_start_xmit(struct sk_buff *skb, struct DEVICE *dev)
/* free this SKB */
dev_kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
}
diff --git a/drivers/net/tulip/tulip_core.c b/drivers/net/tulip/tulip_core.c
index 99a63649f4f..019050f273a 100644
--- a/drivers/net/tulip/tulip_core.c
+++ b/drivers/net/tulip/tulip_core.c
@@ -692,7 +692,7 @@ tulip_start_xmit(struct sk_buff *skb, struct net_device *dev)
dev->trans_start = jiffies;
- return 0;
+ return NETDEV_TX_OK;
}
static void tulip_clean_tx_ring(struct tulip_private *tp)
diff --git a/drivers/net/tulip/uli526x.c b/drivers/net/tulip/uli526x.c
index 9277ce8febe..9074a34eb81 100644
--- a/drivers/net/tulip/uli526x.c
+++ b/drivers/net/tulip/uli526x.c
@@ -582,7 +582,7 @@ static int uli526x_start_xmit(struct sk_buff *skb, struct net_device *dev)
if (skb->len > MAX_PACKET_SIZE) {
printk(KERN_ERR DRV_NAME ": big packet = %d\n", (u16)skb->len);
dev_kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
}
spin_lock_irqsave(&db->lock, flags);
@@ -624,7 +624,7 @@ static int uli526x_start_xmit(struct sk_buff *skb, struct net_device *dev)
/* free this SKB */
dev_kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
}
diff --git a/drivers/net/tulip/winbond-840.c b/drivers/net/tulip/winbond-840.c
index 0f15773dae5..1853530a32a 100644
--- a/drivers/net/tulip/winbond-840.c
+++ b/drivers/net/tulip/winbond-840.c
@@ -1058,7 +1058,7 @@ static int start_tx(struct sk_buff *skb, struct net_device *dev)
printk(KERN_DEBUG "%s: Transmit frame #%d queued in slot %d.\n",
dev->name, np->cur_tx, entry);
}
- return 0;
+ return NETDEV_TX_OK;
}
static void netdev_tx_done(struct net_device *dev)
diff --git a/drivers/net/tulip/xircom_cb.c b/drivers/net/tulip/xircom_cb.c
index c2ca9f40e40..22b6a239fb3 100644
--- a/drivers/net/tulip/xircom_cb.c
+++ b/drivers/net/tulip/xircom_cb.c
@@ -434,7 +434,7 @@ static int xircom_start_xmit(struct sk_buff *skb, struct net_device *dev)
card->transmit_used = nextdescriptor;
leave("xircom-start_xmit - sent");
spin_unlock_irqrestore(&card->lock,flags);
- return 0;
+ return NETDEV_TX_OK;
}
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index 42b6c6319bc..2533f5cf2e4 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -398,12 +398,12 @@ static int tun_net_xmit(struct sk_buff *skb, struct net_device *dev)
if (tun->flags & TUN_FASYNC)
kill_fasync(&tun->fasync, SIGIO, POLL_IN);
wake_up_interruptible(&tun->socket.wait);
- return 0;
+ return NETDEV_TX_OK;
drop:
dev->stats.tx_dropped++;
kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
}
static void tun_net_mclist(struct net_device *dev)
@@ -641,6 +641,9 @@ static __inline__ ssize_t tun_get_user(struct tun_struct *tun,
case VIRTIO_NET_HDR_GSO_TCPV6:
skb_shinfo(skb)->gso_type = SKB_GSO_TCPV6;
break;
+ case VIRTIO_NET_HDR_GSO_UDP:
+ skb_shinfo(skb)->gso_type = SKB_GSO_UDP;
+ break;
default:
tun->dev->stats.rx_frame_errors++;
kfree_skb(skb);
@@ -726,6 +729,8 @@ static __inline__ ssize_t tun_put_user(struct tun_struct *tun,
gso.gso_type = VIRTIO_NET_HDR_GSO_TCPV4;
else if (sinfo->gso_type & SKB_GSO_TCPV6)
gso.gso_type = VIRTIO_NET_HDR_GSO_TCPV6;
+ else if (sinfo->gso_type & SKB_GSO_UDP)
+ gso.gso_type = VIRTIO_NET_HDR_GSO_UDP;
else
BUG();
if (sinfo->gso_type & SKB_GSO_TCP_ECN)
@@ -997,7 +1002,6 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
goto err_free_sk;
}
- err = -EINVAL;
err = register_netdevice(tun->dev);
if (err < 0)
goto err_free_sk;
@@ -1069,7 +1073,8 @@ static int set_offload(struct net_device *dev, unsigned long arg)
old_features = dev->features;
/* Unset features, set them as we chew on the arg. */
features = (old_features & ~(NETIF_F_HW_CSUM|NETIF_F_SG|NETIF_F_FRAGLIST
- |NETIF_F_TSO_ECN|NETIF_F_TSO|NETIF_F_TSO6));
+ |NETIF_F_TSO_ECN|NETIF_F_TSO|NETIF_F_TSO6
+ |NETIF_F_UFO));
if (arg & TUN_F_CSUM) {
features |= NETIF_F_HW_CSUM|NETIF_F_SG|NETIF_F_FRAGLIST;
@@ -1086,6 +1091,11 @@ static int set_offload(struct net_device *dev, unsigned long arg)
features |= NETIF_F_TSO6;
arg &= ~(TUN_F_TSO4|TUN_F_TSO6);
}
+
+ if (arg & TUN_F_UFO) {
+ features |= NETIF_F_UFO;
+ arg &= ~TUN_F_UFO;
+ }
}
/* This gives the user a way to test for new features in future by
diff --git a/drivers/net/typhoon.c b/drivers/net/typhoon.c
index cf25eb41b1c..2c26b4577e8 100644
--- a/drivers/net/typhoon.c
+++ b/drivers/net/typhoon.c
@@ -909,7 +909,7 @@ typhoon_start_tx(struct sk_buff *skb, struct net_device *dev)
netif_wake_queue(dev);
}
- return 0;
+ return NETDEV_TX_OK;
}
static void
diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c
index 3b957e6412e..52a6750b820 100644
--- a/drivers/net/ucc_geth.c
+++ b/drivers/net/ucc_geth.c
@@ -209,9 +209,10 @@ static struct sk_buff *get_new_skb(struct ucc_geth_private *ugeth,
{
struct sk_buff *skb = NULL;
- skb = dev_alloc_skb(ugeth->ug_info->uf_info.max_rx_buf_length +
- UCC_GETH_RX_DATA_BUF_ALIGNMENT);
-
+ skb = __skb_dequeue(&ugeth->rx_recycle);
+ if (!skb)
+ skb = dev_alloc_skb(ugeth->ug_info->uf_info.max_rx_buf_length +
+ UCC_GETH_RX_DATA_BUF_ALIGNMENT);
if (skb == NULL)
return NULL;
@@ -1986,6 +1987,8 @@ static void ucc_geth_memclean(struct ucc_geth_private *ugeth)
iounmap(ugeth->ug_regs);
ugeth->ug_regs = NULL;
}
+
+ skb_queue_purge(&ugeth->rx_recycle);
}
static void ucc_geth_set_multi(struct net_device *dev)
@@ -2202,6 +2205,8 @@ static int ucc_struct_init(struct ucc_geth_private *ugeth)
return -ENOMEM;
}
+ skb_queue_head_init(&ugeth->rx_recycle);
+
return 0;
}
@@ -3173,7 +3178,7 @@ static int ucc_geth_start_xmit(struct sk_buff *skb, struct net_device *dev)
#endif
spin_unlock_irq(&ugeth->lock);
- return 0;
+ return NETDEV_TX_OK;
}
static int ucc_geth_rx(struct ucc_geth_private *ugeth, u8 rxQ, int rx_work_limit)
@@ -3208,8 +3213,10 @@ static int ucc_geth_rx(struct ucc_geth_private *ugeth, u8 rxQ, int rx_work_limit
if (netif_msg_rx_err(ugeth))
ugeth_err("%s, %d: ERROR!!! skb - 0x%08x",
__func__, __LINE__, (u32) skb);
- if (skb)
- dev_kfree_skb_any(skb);
+ if (skb) {
+ skb->data = skb->head + NET_SKB_PAD;
+ __skb_queue_head(&ugeth->rx_recycle, skb);
+ }
ugeth->rx_skbuff[rxQ][ugeth->skb_currx[rxQ]] = NULL;
dev->stats.rx_dropped++;
@@ -3267,6 +3274,8 @@ static int ucc_geth_tx(struct net_device *dev, u8 txQ)
/* Normal processing. */
while ((bd_status & T_R) == 0) {
+ struct sk_buff *skb;
+
/* BD contains already transmitted buffer. */
/* Handle the transmitted buffer and release */
/* the BD to be used with the current frame */
@@ -3276,9 +3285,16 @@ static int ucc_geth_tx(struct net_device *dev, u8 txQ)
dev->stats.tx_packets++;
- /* Free the sk buffer associated with this TxBD */
- dev_kfree_skb(ugeth->
- tx_skbuff[txQ][ugeth->skb_dirtytx[txQ]]);
+ skb = ugeth->tx_skbuff[txQ][ugeth->skb_dirtytx[txQ]];
+
+ if (skb_queue_len(&ugeth->rx_recycle) < RX_BD_RING_LEN &&
+ skb_recycle_check(skb,
+ ugeth->ug_info->uf_info.max_rx_buf_length +
+ UCC_GETH_RX_DATA_BUF_ALIGNMENT))
+ __skb_queue_head(&ugeth->rx_recycle, skb);
+ else
+ dev_kfree_skb(skb);
+
ugeth->tx_skbuff[txQ][ugeth->skb_dirtytx[txQ]] = NULL;
ugeth->skb_dirtytx[txQ] =
(ugeth->skb_dirtytx[txQ] +
@@ -3307,16 +3323,16 @@ static int ucc_geth_poll(struct napi_struct *napi, int budget)
ug_info = ugeth->ug_info;
- howmany = 0;
- for (i = 0; i < ug_info->numQueuesRx; i++)
- howmany += ucc_geth_rx(ugeth, i, budget - howmany);
-
/* Tx event processing */
spin_lock(&ugeth->lock);
for (i = 0; i < ug_info->numQueuesTx; i++)
ucc_geth_tx(ugeth->ndev, i);
spin_unlock(&ugeth->lock);
+ howmany = 0;
+ for (i = 0; i < ug_info->numQueuesRx; i++)
+ howmany += ucc_geth_rx(ugeth, i, budget - howmany);
+
if (howmany < budget) {
napi_complete(napi);
setbits32(ugeth->uccf->p_uccm, UCCE_RX_EVENTS | UCCE_TX_EVENTS);
diff --git a/drivers/net/ucc_geth.h b/drivers/net/ucc_geth.h
index 195ab267ead..cfb31afc08a 100644
--- a/drivers/net/ucc_geth.h
+++ b/drivers/net/ucc_geth.h
@@ -1212,6 +1212,8 @@ struct ucc_geth_private {
/* index of the first skb which hasn't been transmitted yet. */
u16 skb_dirtytx[NUM_TX_QUEUES];
+ struct sk_buff_head rx_recycle;
+
struct ugeth_mii_info *mii_info;
struct phy_device *phydev;
phy_interface_t phy_interface;
diff --git a/drivers/net/usb/catc.c b/drivers/net/usb/catc.c
index b9dd4257428..7abdc4abbe0 100644
--- a/drivers/net/usb/catc.c
+++ b/drivers/net/usb/catc.c
@@ -448,7 +448,7 @@ static int catc_start_xmit(struct sk_buff *skb, struct net_device *netdev)
dev_kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
}
static void catc_tx_timeout(struct net_device *netdev)
diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c
index f8c6d7ea726..ffe41063573 100644
--- a/drivers/net/usb/hso.c
+++ b/drivers/net/usb/hso.c
@@ -780,7 +780,7 @@ static int hso_net_start_xmit(struct sk_buff *skb, struct net_device *net)
netif_stop_queue(net);
if (hso_get_activity(odev->parent) == -EAGAIN) {
odev->skb_tx_buf = skb;
- return 0;
+ return NETDEV_TX_OK;
}
/* log if asked */
diff --git a/drivers/net/usb/kaweth.c b/drivers/net/usb/kaweth.c
index 1f9ec29fce5..200fe3d525c 100644
--- a/drivers/net/usb/kaweth.c
+++ b/drivers/net/usb/kaweth.c
@@ -829,7 +829,7 @@ static int kaweth_start_xmit(struct sk_buff *skb, struct net_device *net)
kaweth->stats.tx_errors++;
netif_start_queue(net);
spin_unlock_irq(&kaweth->device_lock);
- return 0;
+ return NETDEV_TX_OK;
}
}
@@ -864,7 +864,7 @@ skip:
spin_unlock_irq(&kaweth->device_lock);
- return 0;
+ return NETDEV_TX_OK;
}
/****************************************************************
diff --git a/drivers/net/usb/pegasus.c b/drivers/net/usb/pegasus.c
index 631d269ac98..69d2df95ac8 100644
--- a/drivers/net/usb/pegasus.c
+++ b/drivers/net/usb/pegasus.c
@@ -914,7 +914,7 @@ static int pegasus_start_xmit(struct sk_buff *skb, struct net_device *net)
}
dev_kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
}
static struct net_device_stats *pegasus_netdev_stats(struct net_device *dev)
diff --git a/drivers/net/usb/rndis_host.c b/drivers/net/usb/rndis_host.c
index 2232232b798..d032bba9bc4 100644
--- a/drivers/net/usb/rndis_host.c
+++ b/drivers/net/usb/rndis_host.c
@@ -65,6 +65,32 @@ void rndis_status(struct usbnet *dev, struct urb *urb)
EXPORT_SYMBOL_GPL(rndis_status);
/*
+ * RNDIS indicate messages.
+ */
+static void rndis_msg_indicate(struct usbnet *dev, struct rndis_indicate *msg,
+ int buflen)
+{
+ struct cdc_state *info = (void *)&dev->data;
+ struct device *udev = &info->control->dev;
+
+ if (dev->driver_info->indication) {
+ dev->driver_info->indication(dev, msg, buflen);
+ } else {
+ switch (msg->status) {
+ case RNDIS_STATUS_MEDIA_CONNECT:
+ dev_info(udev, "rndis media connect\n");
+ break;
+ case RNDIS_STATUS_MEDIA_DISCONNECT:
+ dev_info(udev, "rndis media disconnect\n");
+ break;
+ default:
+ dev_info(udev, "rndis indication: 0x%08x\n",
+ le32_to_cpu(msg->status));
+ }
+ }
+}
+
+/*
* RPC done RNDIS-style. Caller guarantees:
* - message is properly byteswapped
* - there's no other request pending
@@ -143,27 +169,9 @@ int rndis_command(struct usbnet *dev, struct rndis_msg_hdr *buf, int buflen)
request_id, xid);
/* then likely retry */
} else switch (buf->msg_type) {
- case RNDIS_MSG_INDICATE: { /* fault/event */
- struct rndis_indicate *msg = (void *)buf;
- int state = 0;
-
- switch (msg->status) {
- case RNDIS_STATUS_MEDIA_CONNECT:
- state = 1;
- case RNDIS_STATUS_MEDIA_DISCONNECT:
- dev_info(&info->control->dev,
- "rndis media %sconnect\n",
- !state?"dis":"");
- if (dev->driver_info->link_change)
- dev->driver_info->link_change(
- dev, state);
- break;
- default:
- dev_info(&info->control->dev,
- "rndis indication: 0x%08x\n",
- le32_to_cpu(msg->status));
- }
- }
+ case RNDIS_MSG_INDICATE: /* fault/event */
+ rndis_msg_indicate(dev, (void *)buf, buflen);
+
break;
case RNDIS_MSG_KEEPALIVE: { /* ping */
struct rndis_keepalive_c *msg = (void *)buf;
diff --git a/drivers/net/usb/rtl8150.c b/drivers/net/usb/rtl8150.c
index fcc6fa0905d..bac8b77fb25 100644
--- a/drivers/net/usb/rtl8150.c
+++ b/drivers/net/usb/rtl8150.c
@@ -753,7 +753,7 @@ static int rtl8150_start_xmit(struct sk_buff *skb, struct net_device *netdev)
netdev->trans_start = jiffies;
}
- return 0;
+ return NETDEV_TX_OK;
}
diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c
index fe045896406..09bd6351f64 100644
--- a/drivers/net/usb/smsc95xx.c
+++ b/drivers/net/usb/smsc95xx.c
@@ -220,11 +220,6 @@ static int smsc95xx_eeprom_confirm_not_busy(struct usbnet *dev)
do {
smsc95xx_read_reg(dev, E2P_CMD, &val);
- if (!(val & E2P_CMD_LOADED_)) {
- devwarn(dev, "No EEPROM present");
- return -EIO;
- }
-
if (!(val & E2P_CMD_BUSY_))
return 0;
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
index edfd9e10ceb..7d471fca274 100644
--- a/drivers/net/usb/usbnet.c
+++ b/drivers/net/usb/usbnet.c
@@ -233,6 +233,11 @@ void usbnet_skb_return (struct usbnet *dev, struct sk_buff *skb)
{
int status;
+ if (test_bit(EVENT_RX_PAUSED, &dev->flags)) {
+ skb_queue_tail(&dev->rxq_pause, skb);
+ return;
+ }
+
skb->protocol = eth_type_trans (skb, dev->net);
dev->net->stats.rx_packets++;
dev->net->stats.rx_bytes += skb->len;
@@ -526,6 +531,41 @@ static void intr_complete (struct urb *urb)
}
/*-------------------------------------------------------------------------*/
+void usbnet_pause_rx(struct usbnet *dev)
+{
+ set_bit(EVENT_RX_PAUSED, &dev->flags);
+
+ if (netif_msg_rx_status(dev))
+ devdbg(dev, "paused rx queue enabled");
+}
+EXPORT_SYMBOL_GPL(usbnet_pause_rx);
+
+void usbnet_resume_rx(struct usbnet *dev)
+{
+ struct sk_buff *skb;
+ int num = 0;
+
+ clear_bit(EVENT_RX_PAUSED, &dev->flags);
+
+ while ((skb = skb_dequeue(&dev->rxq_pause)) != NULL) {
+ usbnet_skb_return(dev, skb);
+ num++;
+ }
+
+ tasklet_schedule(&dev->bh);
+
+ if (netif_msg_rx_status(dev))
+ devdbg(dev, "paused rx queue disabled, %d skbs requeued", num);
+}
+EXPORT_SYMBOL_GPL(usbnet_resume_rx);
+
+void usbnet_purge_paused_rxq(struct usbnet *dev)
+{
+ skb_queue_purge(&dev->rxq_pause);
+}
+EXPORT_SYMBOL_GPL(usbnet_purge_paused_rxq);
+
+/*-------------------------------------------------------------------------*/
// unlink pending rx/tx; completion handlers do all other cleanup
@@ -575,7 +615,9 @@ EXPORT_SYMBOL_GPL(usbnet_unlink_rx_urbs);
int usbnet_stop (struct net_device *net)
{
struct usbnet *dev = netdev_priv(net);
+ struct driver_info *info = dev->driver_info;
int temp;
+ int retval;
DECLARE_WAIT_QUEUE_HEAD_ONSTACK (unlink_wakeup);
DECLARE_WAITQUEUE (wait, current);
@@ -587,24 +629,42 @@ int usbnet_stop (struct net_device *net)
net->stats.rx_errors, net->stats.tx_errors
);
- // ensure there are no more active urbs
- add_wait_queue (&unlink_wakeup, &wait);
- dev->wait = &unlink_wakeup;
- temp = unlink_urbs (dev, &dev->txq) + unlink_urbs (dev, &dev->rxq);
+ /* allow minidriver to stop correctly (wireless devices to turn off
+ * radio etc) */
+ if (info->stop) {
+ retval = info->stop(dev);
+ if (retval < 0 && netif_msg_ifdown(dev))
+ devinfo(dev,
+ "stop fail (%d) usbnet usb-%s-%s, %s",
+ retval,
+ dev->udev->bus->bus_name, dev->udev->devpath,
+ info->description);
+ }
- // maybe wait for deletions to finish.
- while (!skb_queue_empty(&dev->rxq)
- && !skb_queue_empty(&dev->txq)
- && !skb_queue_empty(&dev->done)) {
- msleep(UNLINK_TIMEOUT_MS);
- if (netif_msg_ifdown (dev))
- devdbg (dev, "waited for %d urb completions", temp);
+ if (!(info->flags & FLAG_AVOID_UNLINK_URBS)) {
+ /* ensure there are no more active urbs */
+ add_wait_queue(&unlink_wakeup, &wait);
+ dev->wait = &unlink_wakeup;
+ temp = unlink_urbs(dev, &dev->txq) +
+ unlink_urbs(dev, &dev->rxq);
+
+ /* maybe wait for deletions to finish. */
+ while (!skb_queue_empty(&dev->rxq)
+ && !skb_queue_empty(&dev->txq)
+ && !skb_queue_empty(&dev->done)) {
+ msleep(UNLINK_TIMEOUT_MS);
+ if (netif_msg_ifdown(dev))
+ devdbg(dev, "waited for %d urb completions",
+ temp);
+ }
+ dev->wait = NULL;
+ remove_wait_queue(&unlink_wakeup, &wait);
}
- dev->wait = NULL;
- remove_wait_queue (&unlink_wakeup, &wait);
usb_kill_urb(dev->interrupt);
+ usbnet_purge_paused_rxq(dev);
+
/* deferred work (task, timer, softirq) must also stop.
* can't flush_scheduled_work() until we drop rtnl (later),
* else workers could deadlock; so make workers a NOP.
@@ -1095,7 +1155,6 @@ static void usbnet_bh (unsigned long param)
}
-
/*-------------------------------------------------------------------------
*
* USB Device Driver support
@@ -1192,6 +1251,7 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)
skb_queue_head_init (&dev->rxq);
skb_queue_head_init (&dev->txq);
skb_queue_head_init (&dev->done);
+ skb_queue_head_init(&dev->rxq_pause);
dev->bh.func = usbnet_bh;
dev->bh.data = (unsigned long) dev;
INIT_WORK (&dev->kevent, kevent);
diff --git a/drivers/net/veth.c b/drivers/net/veth.c
index 1097c72e44d..190f784c9cf 100644
--- a/drivers/net/veth.c
+++ b/drivers/net/veth.c
@@ -171,6 +171,7 @@ static int veth_xmit(struct sk_buff *skb, struct net_device *dev)
if (skb->len > (rcv->mtu + MTU_PAD))
goto rx_drop;
+ skb->tstamp.tv64 = 0;
skb->pkt_type = PACKET_HOST;
skb->protocol = eth_type_trans(skb, rcv);
if (dev->features & NETIF_F_NO_CSUM)
@@ -189,17 +190,17 @@ static int veth_xmit(struct sk_buff *skb, struct net_device *dev)
rcv_stats->rx_packets++;
netif_rx(skb);
- return 0;
+ return NETDEV_TX_OK;
tx_drop:
kfree_skb(skb);
stats->tx_dropped++;
- return 0;
+ return NETDEV_TX_OK;
rx_drop:
kfree_skb(skb);
rcv_stats->rx_dropped++;
- return 0;
+ return NETDEV_TX_OK;
}
/*
diff --git a/drivers/net/via-rhine.c b/drivers/net/via-rhine.c
index 88c30a58b4b..46eb618bbc9 100644
--- a/drivers/net/via-rhine.c
+++ b/drivers/net/via-rhine.c
@@ -1226,7 +1226,7 @@ static int rhine_start_tx(struct sk_buff *skb, struct net_device *dev)
entry = rp->cur_tx % TX_RING_SIZE;
if (skb_padto(skb, ETH_ZLEN))
- return 0;
+ return NETDEV_TX_OK;
rp->tx_skbuff[entry] = skb;
@@ -1238,7 +1238,7 @@ static int rhine_start_tx(struct sk_buff *skb, struct net_device *dev)
dev_kfree_skb(skb);
rp->tx_skbuff[entry] = NULL;
dev->stats.tx_dropped++;
- return 0;
+ return NETDEV_TX_OK;
}
/* Padding is not copied and so must be redone. */
@@ -1286,7 +1286,7 @@ static int rhine_start_tx(struct sk_buff *skb, struct net_device *dev)
printk(KERN_DEBUG "%s: Transmit frame #%d queued in slot %d.\n",
dev->name, rp->cur_tx-1, entry);
}
- return 0;
+ return NETDEV_TX_OK;
}
/* The interrupt handler does all of the Rx thread work and cleans up
diff --git a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c
index 3ba35956327..47be41a39d3 100644
--- a/drivers/net/via-velocity.c
+++ b/drivers/net/via-velocity.c
@@ -61,9 +61,9 @@
#include <linux/interrupt.h>
#include <linux/string.h>
#include <linux/wait.h>
-#include <asm/io.h>
+#include <linux/io.h>
#include <linux/if.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
#include <linux/proc_fs.h>
#include <linux/inetdevice.h>
#include <linux/reboot.h>
@@ -81,7 +81,7 @@
#include "via-velocity.h"
-static int velocity_nics = 0;
+static int velocity_nics;
static int msglevel = MSG_LEVEL_INFO;
/**
@@ -92,8 +92,7 @@ static int msglevel = MSG_LEVEL_INFO;
* Fetch the mask bits of the selected CAM and store them into the
* provided mask buffer.
*/
-
-static void mac_get_cam_mask(struct mac_regs __iomem * regs, u8 * mask)
+static void mac_get_cam_mask(struct mac_regs __iomem *regs, u8 *mask)
{
int i;
@@ -111,7 +110,6 @@ static void mac_get_cam_mask(struct mac_regs __iomem * regs, u8 * mask)
/* Select mar */
BYTE_REG_BITS_SET(CAMCR_PS_MAR, CAMCR_PS1 | CAMCR_PS0, &regs->CAMCR);
-
}
@@ -122,8 +120,7 @@ static void mac_get_cam_mask(struct mac_regs __iomem * regs, u8 * mask)
*
* Store a new mask into a CAM
*/
-
-static void mac_set_cam_mask(struct mac_regs __iomem * regs, u8 * mask)
+static void mac_set_cam_mask(struct mac_regs __iomem *regs, u8 *mask)
{
int i;
/* Select CAM mask */
@@ -131,9 +128,9 @@ static void mac_set_cam_mask(struct mac_regs __iomem * regs, u8 * mask)
writeb(CAMADDR_CAMEN, &regs->CAMADDR);
- for (i = 0; i < 8; i++) {
+ for (i = 0; i < 8; i++)
writeb(*mask++, &(regs->MARCAM[i]));
- }
+
/* disable CAMEN */
writeb(0, &regs->CAMADDR);
@@ -141,7 +138,7 @@ static void mac_set_cam_mask(struct mac_regs __iomem * regs, u8 * mask)
BYTE_REG_BITS_SET(CAMCR_PS_MAR, CAMCR_PS1 | CAMCR_PS0, &regs->CAMCR);
}
-static void mac_set_vlan_cam_mask(struct mac_regs __iomem * regs, u8 * mask)
+static void mac_set_vlan_cam_mask(struct mac_regs __iomem *regs, u8 *mask)
{
int i;
/* Select CAM mask */
@@ -149,9 +146,9 @@ static void mac_set_vlan_cam_mask(struct mac_regs __iomem * regs, u8 * mask)
writeb(CAMADDR_CAMEN | CAMADDR_VCAMSL, &regs->CAMADDR);
- for (i = 0; i < 8; i++) {
+ for (i = 0; i < 8; i++)
writeb(*mask++, &(regs->MARCAM[i]));
- }
+
/* disable CAMEN */
writeb(0, &regs->CAMADDR);
@@ -167,8 +164,7 @@ static void mac_set_vlan_cam_mask(struct mac_regs __iomem * regs, u8 * mask)
*
* Load an address or vlan tag into a CAM
*/
-
-static void mac_set_cam(struct mac_regs __iomem * regs, int idx, const u8 *addr)
+static void mac_set_cam(struct mac_regs __iomem *regs, int idx, const u8 *addr)
{
int i;
@@ -179,9 +175,9 @@ static void mac_set_cam(struct mac_regs __iomem * regs, int idx, const u8 *addr)
writeb(CAMADDR_CAMEN | idx, &regs->CAMADDR);
- for (i = 0; i < 6; i++) {
+ for (i = 0; i < 6; i++)
writeb(*addr++, &(regs->MARCAM[i]));
- }
+
BYTE_REG_BITS_ON(CAMCR_CAMWR, &regs->CAMCR);
udelay(10);
@@ -192,7 +188,7 @@ static void mac_set_cam(struct mac_regs __iomem * regs, int idx, const u8 *addr)
BYTE_REG_BITS_SET(CAMCR_PS_MAR, CAMCR_PS1 | CAMCR_PS0, &regs->CAMCR);
}
-static void mac_set_vlan_cam(struct mac_regs __iomem * regs, int idx,
+static void mac_set_vlan_cam(struct mac_regs __iomem *regs, int idx,
const u8 *addr)
{
@@ -223,8 +219,7 @@ static void mac_set_vlan_cam(struct mac_regs __iomem * regs, int idx,
* reset the Wake on lan features. This function doesn't restore
* the rest of the logic from the result of sleep/wakeup
*/
-
-static void mac_wol_reset(struct mac_regs __iomem * regs)
+static void mac_wol_reset(struct mac_regs __iomem *regs)
{
/* Turn off SWPTAG right after leaving power mode */
@@ -242,7 +237,6 @@ static void mac_wol_reset(struct mac_regs __iomem * regs)
writew(0xFFFF, &regs->WOLSRClr);
}
-static int velocity_mii_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);
static const struct ethtool_ops velocity_ethtool_ops;
/*
@@ -253,10 +247,10 @@ MODULE_AUTHOR("VIA Networking Technologies, Inc.");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("VIA Networking Velocity Family Gigabit Ethernet Adapter Driver");
-#define VELOCITY_PARAM(N,D) \
- static int N[MAX_UNITS]=OPTION_DEFAULT;\
+#define VELOCITY_PARAM(N, D) \
+ static int N[MAX_UNITS] = OPTION_DEFAULT;\
module_param_array(N, int, NULL, 0); \
- MODULE_PARM_DESC(N, D);
+ MODULE_PARM_DESC(N, D);
#define RX_DESC_MIN 64
#define RX_DESC_MAX 255
@@ -336,8 +330,8 @@ VELOCITY_PARAM(flow_control, "Enable flow control ability");
4: indicate 10Mbps full duplex mode
Note:
- if EEPROM have been set to the force mode, this option is ignored
- by driver.
+ if EEPROM have been set to the force mode, this option is ignored
+ by driver.
*/
VELOCITY_PARAM(speed_duplex, "Setting the speed and duplex mode");
@@ -370,76 +364,14 @@ static int rx_copybreak = 200;
module_param(rx_copybreak, int, 0644);
MODULE_PARM_DESC(rx_copybreak, "Copy breakpoint for copy-only-tiny-frames");
-static void velocity_init_info(struct pci_dev *pdev, struct velocity_info *vptr,
- const struct velocity_info_tbl *info);
-static int velocity_get_pci_info(struct velocity_info *, struct pci_dev *pdev);
-static void velocity_print_info(struct velocity_info *vptr);
-static int velocity_open(struct net_device *dev);
-static int velocity_change_mtu(struct net_device *dev, int mtu);
-static int velocity_xmit(struct sk_buff *skb, struct net_device *dev);
-static irqreturn_t velocity_intr(int irq, void *dev_instance);
-static void velocity_set_multi(struct net_device *dev);
-static struct net_device_stats *velocity_get_stats(struct net_device *dev);
-static int velocity_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
-static int velocity_close(struct net_device *dev);
-static int velocity_receive_frame(struct velocity_info *, int idx);
-static int velocity_alloc_rx_buf(struct velocity_info *, int idx);
-static void velocity_free_rd_ring(struct velocity_info *vptr);
-static void velocity_free_tx_buf(struct velocity_info *vptr, struct velocity_td_info *);
-static int velocity_soft_reset(struct velocity_info *vptr);
-static void mii_init(struct velocity_info *vptr, u32 mii_status);
-static u32 velocity_get_link(struct net_device *dev);
-static u32 velocity_get_opt_media_mode(struct velocity_info *vptr);
-static void velocity_print_link_status(struct velocity_info *vptr);
-static void safe_disable_mii_autopoll(struct mac_regs __iomem * regs);
-static void velocity_shutdown(struct velocity_info *vptr);
-static void enable_flow_control_ability(struct velocity_info *vptr);
-static void enable_mii_autopoll(struct mac_regs __iomem * regs);
-static int velocity_mii_read(struct mac_regs __iomem *, u8 byIdx, u16 * pdata);
-static int velocity_mii_write(struct mac_regs __iomem *, u8 byMiiAddr, u16 data);
-static u32 mii_check_media_mode(struct mac_regs __iomem * regs);
-static u32 check_connection_type(struct mac_regs __iomem * regs);
-static int velocity_set_media_mode(struct velocity_info *vptr, u32 mii_status);
-
#ifdef CONFIG_PM
-
-static int velocity_suspend(struct pci_dev *pdev, pm_message_t state);
-static int velocity_resume(struct pci_dev *pdev);
-
static DEFINE_SPINLOCK(velocity_dev_list_lock);
static LIST_HEAD(velocity_dev_list);
-
-#endif
-
-#if defined(CONFIG_PM) && defined(CONFIG_INET)
-
-static int velocity_netdev_event(struct notifier_block *nb, unsigned long notification, void *ptr);
-
-static struct notifier_block velocity_inetaddr_notifier = {
- .notifier_call = velocity_netdev_event,
-};
-
-static void velocity_register_notifier(void)
-{
- register_inetaddr_notifier(&velocity_inetaddr_notifier);
-}
-
-static void velocity_unregister_notifier(void)
-{
- unregister_inetaddr_notifier(&velocity_inetaddr_notifier);
-}
-
-#else
-
-#define velocity_register_notifier() do {} while (0)
-#define velocity_unregister_notifier() do {} while (0)
-
#endif
/*
* Internal board variants. At the moment we have only one
*/
-
static struct velocity_info_tbl chip_info_table[] = {
{CHIP_TYPE_VT6110, "VIA Networking Velocity Family Gigabit Ethernet Adapter", 1, 0x00FFFFFFUL},
{ }
@@ -449,7 +381,6 @@ static struct velocity_info_tbl chip_info_table[] = {
* Describe the PCI device identifiers that we support in this
* device driver. Used for hotplug autoloading.
*/
-
static const struct pci_device_id velocity_id_table[] __devinitdata = {
{ PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_612X) },
{ }
@@ -464,7 +395,6 @@ MODULE_DEVICE_TABLE(pci, velocity_id_table);
* Given a chip identifier return a suitable description. Returns
* a pointer a static string valid while the driver is loaded.
*/
-
static const char __devinit *get_chip_name(enum chip_type chip_id)
{
int i;
@@ -482,7 +412,6 @@ static const char __devinit *get_chip_name(enum chip_type chip_id)
* unload for each active device that is present. Disconnects
* the device from the network layer and frees all the resources
*/
-
static void __devexit velocity_remove1(struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata(pdev);
@@ -520,7 +449,6 @@ static void __devexit velocity_remove1(struct pci_dev *pdev)
* all the verification and checking as well as reporting so that
* we don't duplicate code for each option.
*/
-
static void __devinit velocity_set_int_opt(int *opt, int val, int min, int max, int def, char *name, const char *devname)
{
if (val == -1)
@@ -549,8 +477,7 @@ static void __devinit velocity_set_int_opt(int *opt, int val, int min, int max,
* all the verification and checking as well as reporting so that
* we don't duplicate code for each option.
*/
-
-static void __devinit velocity_set_bool_opt(u32 * opt, int val, int def, u32 flag, char *name, const char *devname)
+static void __devinit velocity_set_bool_opt(u32 *opt, int val, int def, u32 flag, char *name, const char *devname)
{
(*opt) &= (~flag);
if (val == -1)
@@ -575,7 +502,6 @@ static void __devinit velocity_set_bool_opt(u32 * opt, int val, int def, u32 fla
* Turn the module and command options into a single structure
* for the current device
*/
-
static void __devinit velocity_get_options(struct velocity_opt *opts, int index, const char *devname)
{
@@ -601,10 +527,9 @@ static void __devinit velocity_get_options(struct velocity_opt *opts, int index,
* Initialize the content addressable memory used for filters. Load
* appropriately according to the presence of VLAN
*/
-
static void velocity_init_cam_filter(struct velocity_info *vptr)
{
- struct mac_regs __iomem * regs = vptr->mac_regs;
+ struct mac_regs __iomem *regs = vptr->mac_regs;
/* Turn on MCFG_PQEN, turn off MCFG_RTGOPT */
WORD_REG_BITS_SET(MCFG_PQEN, MCFG_RTGOPT, &regs->MCFG);
@@ -647,19 +572,19 @@ static void velocity_vlan_rx_add_vid(struct net_device *dev, unsigned short vid)
{
struct velocity_info *vptr = netdev_priv(dev);
- spin_lock_irq(&vptr->lock);
+ spin_lock_irq(&vptr->lock);
velocity_init_cam_filter(vptr);
- spin_unlock_irq(&vptr->lock);
+ spin_unlock_irq(&vptr->lock);
}
static void velocity_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
{
struct velocity_info *vptr = netdev_priv(dev);
- spin_lock_irq(&vptr->lock);
+ spin_lock_irq(&vptr->lock);
vlan_group_set_device(vptr->vlgrp, vid, NULL);
velocity_init_cam_filter(vptr);
- spin_unlock_irq(&vptr->lock);
+ spin_unlock_irq(&vptr->lock);
}
static void velocity_init_rx_ring_indexes(struct velocity_info *vptr)
@@ -674,11 +599,10 @@ static void velocity_init_rx_ring_indexes(struct velocity_info *vptr)
* Reset the ownership and status for the receive ring side.
* Hand all the receive queue to the NIC.
*/
-
static void velocity_rx_reset(struct velocity_info *vptr)
{
- struct mac_regs __iomem * regs = vptr->mac_regs;
+ struct mac_regs __iomem *regs = vptr->mac_regs;
int i;
velocity_init_rx_ring_indexes(vptr);
@@ -696,6 +620,647 @@ static void velocity_rx_reset(struct velocity_info *vptr)
}
/**
+ * velocity_get_opt_media_mode - get media selection
+ * @vptr: velocity adapter
+ *
+ * Get the media mode stored in EEPROM or module options and load
+ * mii_status accordingly. The requested link state information
+ * is also returned.
+ */
+static u32 velocity_get_opt_media_mode(struct velocity_info *vptr)
+{
+ u32 status = 0;
+
+ switch (vptr->options.spd_dpx) {
+ case SPD_DPX_AUTO:
+ status = VELOCITY_AUTONEG_ENABLE;
+ break;
+ case SPD_DPX_100_FULL:
+ status = VELOCITY_SPEED_100 | VELOCITY_DUPLEX_FULL;
+ break;
+ case SPD_DPX_10_FULL:
+ status = VELOCITY_SPEED_10 | VELOCITY_DUPLEX_FULL;
+ break;
+ case SPD_DPX_100_HALF:
+ status = VELOCITY_SPEED_100;
+ break;
+ case SPD_DPX_10_HALF:
+ status = VELOCITY_SPEED_10;
+ break;
+ }
+ vptr->mii_status = status;
+ return status;
+}
+
+/**
+ * safe_disable_mii_autopoll - autopoll off
+ * @regs: velocity registers
+ *
+ * Turn off the autopoll and wait for it to disable on the chip
+ */
+static void safe_disable_mii_autopoll(struct mac_regs __iomem *regs)
+{
+ u16 ww;
+
+ /* turn off MAUTO */
+ writeb(0, &regs->MIICR);
+ for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
+ udelay(1);
+ if (BYTE_REG_BITS_IS_ON(MIISR_MIDLE, &regs->MIISR))
+ break;
+ }
+}
+
+/**
+ * enable_mii_autopoll - turn on autopolling
+ * @regs: velocity registers
+ *
+ * Enable the MII link status autopoll feature on the Velocity
+ * hardware. Wait for it to enable.
+ */
+static void enable_mii_autopoll(struct mac_regs __iomem *regs)
+{
+ int ii;
+
+ writeb(0, &(regs->MIICR));
+ writeb(MIIADR_SWMPL, &regs->MIIADR);
+
+ for (ii = 0; ii < W_MAX_TIMEOUT; ii++) {
+ udelay(1);
+ if (BYTE_REG_BITS_IS_ON(MIISR_MIDLE, &regs->MIISR))
+ break;
+ }
+
+ writeb(MIICR_MAUTO, &regs->MIICR);
+
+ for (ii = 0; ii < W_MAX_TIMEOUT; ii++) {
+ udelay(1);
+ if (!BYTE_REG_BITS_IS_ON(MIISR_MIDLE, &regs->MIISR))
+ break;
+ }
+
+}
+
+/**
+ * velocity_mii_read - read MII data
+ * @regs: velocity registers
+ * @index: MII register index
+ * @data: buffer for received data
+ *
+ * Perform a single read of an MII 16bit register. Returns zero
+ * on success or -ETIMEDOUT if the PHY did not respond.
+ */
+static int velocity_mii_read(struct mac_regs __iomem *regs, u8 index, u16 *data)
+{
+ u16 ww;
+
+ /*
+ * Disable MIICR_MAUTO, so that mii addr can be set normally
+ */
+ safe_disable_mii_autopoll(regs);
+
+ writeb(index, &regs->MIIADR);
+
+ BYTE_REG_BITS_ON(MIICR_RCMD, &regs->MIICR);
+
+ for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
+ if (!(readb(&regs->MIICR) & MIICR_RCMD))
+ break;
+ }
+
+ *data = readw(&regs->MIIDATA);
+
+ enable_mii_autopoll(regs);
+ if (ww == W_MAX_TIMEOUT)
+ return -ETIMEDOUT;
+ return 0;
+}
+
+
+/**
+ * mii_check_media_mode - check media state
+ * @regs: velocity registers
+ *
+ * Check the current MII status and determine the link status
+ * accordingly
+ */
+static u32 mii_check_media_mode(struct mac_regs __iomem *regs)
+{
+ u32 status = 0;
+ u16 ANAR;
+
+ if (!MII_REG_BITS_IS_ON(BMSR_LNK, MII_REG_BMSR, regs))
+ status |= VELOCITY_LINK_FAIL;
+
+ if (MII_REG_BITS_IS_ON(G1000CR_1000FD, MII_REG_G1000CR, regs))
+ status |= VELOCITY_SPEED_1000 | VELOCITY_DUPLEX_FULL;
+ else if (MII_REG_BITS_IS_ON(G1000CR_1000, MII_REG_G1000CR, regs))
+ status |= (VELOCITY_SPEED_1000);
+ else {
+ velocity_mii_read(regs, MII_REG_ANAR, &ANAR);
+ if (ANAR & ANAR_TXFD)
+ status |= (VELOCITY_SPEED_100 | VELOCITY_DUPLEX_FULL);
+ else if (ANAR & ANAR_TX)
+ status |= VELOCITY_SPEED_100;
+ else if (ANAR & ANAR_10FD)
+ status |= (VELOCITY_SPEED_10 | VELOCITY_DUPLEX_FULL);
+ else
+ status |= (VELOCITY_SPEED_10);
+ }
+
+ if (MII_REG_BITS_IS_ON(BMCR_AUTO, MII_REG_BMCR, regs)) {
+ velocity_mii_read(regs, MII_REG_ANAR, &ANAR);
+ if ((ANAR & (ANAR_TXFD | ANAR_TX | ANAR_10FD | ANAR_10))
+ == (ANAR_TXFD | ANAR_TX | ANAR_10FD | ANAR_10)) {
+ if (MII_REG_BITS_IS_ON(G1000CR_1000 | G1000CR_1000FD, MII_REG_G1000CR, regs))
+ status |= VELOCITY_AUTONEG_ENABLE;
+ }
+ }
+
+ return status;
+}
+
+/**
+ * velocity_mii_write - write MII data
+ * @regs: velocity registers
+ * @index: MII register index
+ * @data: 16bit data for the MII register
+ *
+ * Perform a single write to an MII 16bit register. Returns zero
+ * on success or -ETIMEDOUT if the PHY did not respond.
+ */
+static int velocity_mii_write(struct mac_regs __iomem *regs, u8 mii_addr, u16 data)
+{
+ u16 ww;
+
+ /*
+ * Disable MIICR_MAUTO, so that mii addr can be set normally
+ */
+ safe_disable_mii_autopoll(regs);
+
+ /* MII reg offset */
+ writeb(mii_addr, &regs->MIIADR);
+ /* set MII data */
+ writew(data, &regs->MIIDATA);
+
+ /* turn on MIICR_WCMD */
+ BYTE_REG_BITS_ON(MIICR_WCMD, &regs->MIICR);
+
+ /* W_MAX_TIMEOUT is the timeout period */
+ for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
+ udelay(5);
+ if (!(readb(&regs->MIICR) & MIICR_WCMD))
+ break;
+ }
+ enable_mii_autopoll(regs);
+
+ if (ww == W_MAX_TIMEOUT)
+ return -ETIMEDOUT;
+ return 0;
+}
+
+/**
+ * set_mii_flow_control - flow control setup
+ * @vptr: velocity interface
+ *
+ * Set up the flow control on this interface according to
+ * the supplied user/eeprom options.
+ */
+static void set_mii_flow_control(struct velocity_info *vptr)
+{
+ /*Enable or Disable PAUSE in ANAR */
+ switch (vptr->options.flow_cntl) {
+ case FLOW_CNTL_TX:
+ MII_REG_BITS_OFF(ANAR_PAUSE, MII_REG_ANAR, vptr->mac_regs);
+ MII_REG_BITS_ON(ANAR_ASMDIR, MII_REG_ANAR, vptr->mac_regs);
+ break;
+
+ case FLOW_CNTL_RX:
+ MII_REG_BITS_ON(ANAR_PAUSE, MII_REG_ANAR, vptr->mac_regs);
+ MII_REG_BITS_ON(ANAR_ASMDIR, MII_REG_ANAR, vptr->mac_regs);
+ break;
+
+ case FLOW_CNTL_TX_RX:
+ MII_REG_BITS_ON(ANAR_PAUSE, MII_REG_ANAR, vptr->mac_regs);
+ MII_REG_BITS_ON(ANAR_ASMDIR, MII_REG_ANAR, vptr->mac_regs);
+ break;
+
+ case FLOW_CNTL_DISABLE:
+ MII_REG_BITS_OFF(ANAR_PAUSE, MII_REG_ANAR, vptr->mac_regs);
+ MII_REG_BITS_OFF(ANAR_ASMDIR, MII_REG_ANAR, vptr->mac_regs);
+ break;
+ default:
+ break;
+ }
+}
+
+/**
+ * mii_set_auto_on - autonegotiate on
+ * @vptr: velocity
+ *
+ * Enable autonegotation on this interface
+ */
+static void mii_set_auto_on(struct velocity_info *vptr)
+{
+ if (MII_REG_BITS_IS_ON(BMCR_AUTO, MII_REG_BMCR, vptr->mac_regs))
+ MII_REG_BITS_ON(BMCR_REAUTO, MII_REG_BMCR, vptr->mac_regs);
+ else
+ MII_REG_BITS_ON(BMCR_AUTO, MII_REG_BMCR, vptr->mac_regs);
+}
+
+static u32 check_connection_type(struct mac_regs __iomem *regs)
+{
+ u32 status = 0;
+ u8 PHYSR0;
+ u16 ANAR;
+ PHYSR0 = readb(&regs->PHYSR0);
+
+ /*
+ if (!(PHYSR0 & PHYSR0_LINKGD))
+ status|=VELOCITY_LINK_FAIL;
+ */
+
+ if (PHYSR0 & PHYSR0_FDPX)
+ status |= VELOCITY_DUPLEX_FULL;
+
+ if (PHYSR0 & PHYSR0_SPDG)
+ status |= VELOCITY_SPEED_1000;
+ else if (PHYSR0 & PHYSR0_SPD10)
+ status |= VELOCITY_SPEED_10;
+ else
+ status |= VELOCITY_SPEED_100;
+
+ if (MII_REG_BITS_IS_ON(BMCR_AUTO, MII_REG_BMCR, regs)) {
+ velocity_mii_read(regs, MII_REG_ANAR, &ANAR);
+ if ((ANAR & (ANAR_TXFD | ANAR_TX | ANAR_10FD | ANAR_10))
+ == (ANAR_TXFD | ANAR_TX | ANAR_10FD | ANAR_10)) {
+ if (MII_REG_BITS_IS_ON(G1000CR_1000 | G1000CR_1000FD, MII_REG_G1000CR, regs))
+ status |= VELOCITY_AUTONEG_ENABLE;
+ }
+ }
+
+ return status;
+}
+
+
+
+/**
+ * velocity_set_media_mode - set media mode
+ * @mii_status: old MII link state
+ *
+ * Check the media link state and configure the flow control
+ * PHY and also velocity hardware setup accordingly. In particular
+ * we need to set up CD polling and frame bursting.
+ */
+static int velocity_set_media_mode(struct velocity_info *vptr, u32 mii_status)
+{
+ u32 curr_status;
+ struct mac_regs __iomem *regs = vptr->mac_regs;
+
+ vptr->mii_status = mii_check_media_mode(vptr->mac_regs);
+ curr_status = vptr->mii_status & (~VELOCITY_LINK_FAIL);
+
+ /* Set mii link status */
+ set_mii_flow_control(vptr);
+
+ /*
+ Check if new status is consisent with current status
+ if (((mii_status & curr_status) & VELOCITY_AUTONEG_ENABLE)
+ || (mii_status==curr_status)) {
+ vptr->mii_status=mii_check_media_mode(vptr->mac_regs);
+ vptr->mii_status=check_connection_type(vptr->mac_regs);
+ VELOCITY_PRT(MSG_LEVEL_INFO, "Velocity link no change\n");
+ return 0;
+ }
+ */
+
+ if (PHYID_GET_PHY_ID(vptr->phy_id) == PHYID_CICADA_CS8201)
+ MII_REG_BITS_ON(AUXCR_MDPPS, MII_REG_AUXCR, vptr->mac_regs);
+
+ /*
+ * If connection type is AUTO
+ */
+ if (mii_status & VELOCITY_AUTONEG_ENABLE) {
+ VELOCITY_PRT(MSG_LEVEL_INFO, "Velocity is AUTO mode\n");
+ /* clear force MAC mode bit */
+ BYTE_REG_BITS_OFF(CHIPGCR_FCMODE, &regs->CHIPGCR);
+ /* set duplex mode of MAC according to duplex mode of MII */
+ MII_REG_BITS_ON(ANAR_TXFD | ANAR_TX | ANAR_10FD | ANAR_10, MII_REG_ANAR, vptr->mac_regs);
+ MII_REG_BITS_ON(G1000CR_1000FD | G1000CR_1000, MII_REG_G1000CR, vptr->mac_regs);
+ MII_REG_BITS_ON(BMCR_SPEED1G, MII_REG_BMCR, vptr->mac_regs);
+
+ /* enable AUTO-NEGO mode */
+ mii_set_auto_on(vptr);
+ } else {
+ u16 ANAR;
+ u8 CHIPGCR;
+
+ /*
+ * 1. if it's 3119, disable frame bursting in halfduplex mode
+ * and enable it in fullduplex mode
+ * 2. set correct MII/GMII and half/full duplex mode in CHIPGCR
+ * 3. only enable CD heart beat counter in 10HD mode
+ */
+
+ /* set force MAC mode bit */
+ BYTE_REG_BITS_ON(CHIPGCR_FCMODE, &regs->CHIPGCR);
+
+ CHIPGCR = readb(&regs->CHIPGCR);
+ CHIPGCR &= ~CHIPGCR_FCGMII;
+
+ if (mii_status & VELOCITY_DUPLEX_FULL) {
+ CHIPGCR |= CHIPGCR_FCFDX;
+ writeb(CHIPGCR, &regs->CHIPGCR);
+ VELOCITY_PRT(MSG_LEVEL_INFO, "set Velocity to forced full mode\n");
+ if (vptr->rev_id < REV_ID_VT3216_A0)
+ BYTE_REG_BITS_OFF(TCR_TB2BDIS, &regs->TCR);
+ } else {
+ CHIPGCR &= ~CHIPGCR_FCFDX;
+ VELOCITY_PRT(MSG_LEVEL_INFO, "set Velocity to forced half mode\n");
+ writeb(CHIPGCR, &regs->CHIPGCR);
+ if (vptr->rev_id < REV_ID_VT3216_A0)
+ BYTE_REG_BITS_ON(TCR_TB2BDIS, &regs->TCR);
+ }
+
+ MII_REG_BITS_OFF(G1000CR_1000FD | G1000CR_1000, MII_REG_G1000CR, vptr->mac_regs);
+
+ if (!(mii_status & VELOCITY_DUPLEX_FULL) && (mii_status & VELOCITY_SPEED_10))
+ BYTE_REG_BITS_OFF(TESTCFG_HBDIS, &regs->TESTCFG);
+ else
+ BYTE_REG_BITS_ON(TESTCFG_HBDIS, &regs->TESTCFG);
+
+ /* MII_REG_BITS_OFF(BMCR_SPEED1G, MII_REG_BMCR, vptr->mac_regs); */
+ velocity_mii_read(vptr->mac_regs, MII_REG_ANAR, &ANAR);
+ ANAR &= (~(ANAR_TXFD | ANAR_TX | ANAR_10FD | ANAR_10));
+ if (mii_status & VELOCITY_SPEED_100) {
+ if (mii_status & VELOCITY_DUPLEX_FULL)
+ ANAR |= ANAR_TXFD;
+ else
+ ANAR |= ANAR_TX;
+ } else {
+ if (mii_status & VELOCITY_DUPLEX_FULL)
+ ANAR |= ANAR_10FD;
+ else
+ ANAR |= ANAR_10;
+ }
+ velocity_mii_write(vptr->mac_regs, MII_REG_ANAR, ANAR);
+ /* enable AUTO-NEGO mode */
+ mii_set_auto_on(vptr);
+ /* MII_REG_BITS_ON(BMCR_AUTO, MII_REG_BMCR, vptr->mac_regs); */
+ }
+ /* vptr->mii_status=mii_check_media_mode(vptr->mac_regs); */
+ /* vptr->mii_status=check_connection_type(vptr->mac_regs); */
+ return VELOCITY_LINK_CHANGE;
+}
+
+/**
+ * velocity_print_link_status - link status reporting
+ * @vptr: velocity to report on
+ *
+ * Turn the link status of the velocity card into a kernel log
+ * description of the new link state, detailing speed and duplex
+ * status
+ */
+static void velocity_print_link_status(struct velocity_info *vptr)
+{
+
+ if (vptr->mii_status & VELOCITY_LINK_FAIL) {
+ VELOCITY_PRT(MSG_LEVEL_INFO, KERN_NOTICE "%s: failed to detect cable link\n", vptr->dev->name);
+ } else if (vptr->options.spd_dpx == SPD_DPX_AUTO) {
+ VELOCITY_PRT(MSG_LEVEL_INFO, KERN_NOTICE "%s: Link auto-negotiation", vptr->dev->name);
+
+ if (vptr->mii_status & VELOCITY_SPEED_1000)
+ VELOCITY_PRT(MSG_LEVEL_INFO, " speed 1000M bps");
+ else if (vptr->mii_status & VELOCITY_SPEED_100)
+ VELOCITY_PRT(MSG_LEVEL_INFO, " speed 100M bps");
+ else
+ VELOCITY_PRT(MSG_LEVEL_INFO, " speed 10M bps");
+
+ if (vptr->mii_status & VELOCITY_DUPLEX_FULL)
+ VELOCITY_PRT(MSG_LEVEL_INFO, " full duplex\n");
+ else
+ VELOCITY_PRT(MSG_LEVEL_INFO, " half duplex\n");
+ } else {
+ VELOCITY_PRT(MSG_LEVEL_INFO, KERN_NOTICE "%s: Link forced", vptr->dev->name);
+ switch (vptr->options.spd_dpx) {
+ case SPD_DPX_100_HALF:
+ VELOCITY_PRT(MSG_LEVEL_INFO, " speed 100M bps half duplex\n");
+ break;
+ case SPD_DPX_100_FULL:
+ VELOCITY_PRT(MSG_LEVEL_INFO, " speed 100M bps full duplex\n");
+ break;
+ case SPD_DPX_10_HALF:
+ VELOCITY_PRT(MSG_LEVEL_INFO, " speed 10M bps half duplex\n");
+ break;
+ case SPD_DPX_10_FULL:
+ VELOCITY_PRT(MSG_LEVEL_INFO, " speed 10M bps full duplex\n");
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+/**
+ * enable_flow_control_ability - flow control
+ * @vptr: veloity to configure
+ *
+ * Set up flow control according to the flow control options
+ * determined by the eeprom/configuration.
+ */
+static void enable_flow_control_ability(struct velocity_info *vptr)
+{
+
+ struct mac_regs __iomem *regs = vptr->mac_regs;
+
+ switch (vptr->options.flow_cntl) {
+
+ case FLOW_CNTL_DEFAULT:
+ if (BYTE_REG_BITS_IS_ON(PHYSR0_RXFLC, &regs->PHYSR0))
+ writel(CR0_FDXRFCEN, &regs->CR0Set);
+ else
+ writel(CR0_FDXRFCEN, &regs->CR0Clr);
+
+ if (BYTE_REG_BITS_IS_ON(PHYSR0_TXFLC, &regs->PHYSR0))
+ writel(CR0_FDXTFCEN, &regs->CR0Set);
+ else
+ writel(CR0_FDXTFCEN, &regs->CR0Clr);
+ break;
+
+ case FLOW_CNTL_TX:
+ writel(CR0_FDXTFCEN, &regs->CR0Set);
+ writel(CR0_FDXRFCEN, &regs->CR0Clr);
+ break;
+
+ case FLOW_CNTL_RX:
+ writel(CR0_FDXRFCEN, &regs->CR0Set);
+ writel(CR0_FDXTFCEN, &regs->CR0Clr);
+ break;
+
+ case FLOW_CNTL_TX_RX:
+ writel(CR0_FDXTFCEN, &regs->CR0Set);
+ writel(CR0_FDXRFCEN, &regs->CR0Set);
+ break;
+
+ case FLOW_CNTL_DISABLE:
+ writel(CR0_FDXRFCEN, &regs->CR0Clr);
+ writel(CR0_FDXTFCEN, &regs->CR0Clr);
+ break;
+
+ default:
+ break;
+ }
+
+}
+
+/**
+ * velocity_soft_reset - soft reset
+ * @vptr: velocity to reset
+ *
+ * Kick off a soft reset of the velocity adapter and then poll
+ * until the reset sequence has completed before returning.
+ */
+static int velocity_soft_reset(struct velocity_info *vptr)
+{
+ struct mac_regs __iomem *regs = vptr->mac_regs;
+ int i = 0;
+
+ writel(CR0_SFRST, &regs->CR0Set);
+
+ for (i = 0; i < W_MAX_TIMEOUT; i++) {
+ udelay(5);
+ if (!DWORD_REG_BITS_IS_ON(CR0_SFRST, &regs->CR0Set))
+ break;
+ }
+
+ if (i == W_MAX_TIMEOUT) {
+ writel(CR0_FORSRST, &regs->CR0Set);
+ /* FIXME: PCI POSTING */
+ /* delay 2ms */
+ mdelay(2);
+ }
+ return 0;
+}
+
+/**
+ * velocity_set_multi - filter list change callback
+ * @dev: network device
+ *
+ * Called by the network layer when the filter lists need to change
+ * for a velocity adapter. Reload the CAMs with the new address
+ * filter ruleset.
+ */
+static void velocity_set_multi(struct net_device *dev)
+{
+ struct velocity_info *vptr = netdev_priv(dev);
+ struct mac_regs __iomem *regs = vptr->mac_regs;
+ u8 rx_mode;
+ int i;
+ struct dev_mc_list *mclist;
+
+ if (dev->flags & IFF_PROMISC) { /* Set promiscuous. */
+ writel(0xffffffff, &regs->MARCAM[0]);
+ writel(0xffffffff, &regs->MARCAM[4]);
+ rx_mode = (RCR_AM | RCR_AB | RCR_PROM);
+ } else if ((dev->mc_count > vptr->multicast_limit)
+ || (dev->flags & IFF_ALLMULTI)) {
+ writel(0xffffffff, &regs->MARCAM[0]);
+ writel(0xffffffff, &regs->MARCAM[4]);
+ rx_mode = (RCR_AM | RCR_AB);
+ } else {
+ int offset = MCAM_SIZE - vptr->multicast_limit;
+ mac_get_cam_mask(regs, vptr->mCAMmask);
+
+ for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; i++, mclist = mclist->next) {
+ mac_set_cam(regs, i + offset, mclist->dmi_addr);
+ vptr->mCAMmask[(offset + i) / 8] |= 1 << ((offset + i) & 7);
+ }
+
+ mac_set_cam_mask(regs, vptr->mCAMmask);
+ rx_mode = RCR_AM | RCR_AB | RCR_AP;
+ }
+ if (dev->mtu > 1500)
+ rx_mode |= RCR_AL;
+
+ BYTE_REG_BITS_ON(rx_mode, &regs->RCR);
+
+}
+
+/*
+ * MII access , media link mode setting functions
+ */
+
+/**
+ * mii_init - set up MII
+ * @vptr: velocity adapter
+ * @mii_status: links tatus
+ *
+ * Set up the PHY for the current link state.
+ */
+static void mii_init(struct velocity_info *vptr, u32 mii_status)
+{
+ u16 BMCR;
+
+ switch (PHYID_GET_PHY_ID(vptr->phy_id)) {
+ case PHYID_CICADA_CS8201:
+ /*
+ * Reset to hardware default
+ */
+ MII_REG_BITS_OFF((ANAR_ASMDIR | ANAR_PAUSE), MII_REG_ANAR, vptr->mac_regs);
+ /*
+ * Turn on ECHODIS bit in NWay-forced full mode and turn it
+ * off it in NWay-forced half mode for NWay-forced v.s.
+ * legacy-forced issue.
+ */
+ if (vptr->mii_status & VELOCITY_DUPLEX_FULL)
+ MII_REG_BITS_ON(TCSR_ECHODIS, MII_REG_TCSR, vptr->mac_regs);
+ else
+ MII_REG_BITS_OFF(TCSR_ECHODIS, MII_REG_TCSR, vptr->mac_regs);
+ /*
+ * Turn on Link/Activity LED enable bit for CIS8201
+ */
+ MII_REG_BITS_ON(PLED_LALBE, MII_REG_PLED, vptr->mac_regs);
+ break;
+ case PHYID_VT3216_32BIT:
+ case PHYID_VT3216_64BIT:
+ /*
+ * Reset to hardware default
+ */
+ MII_REG_BITS_ON((ANAR_ASMDIR | ANAR_PAUSE), MII_REG_ANAR, vptr->mac_regs);
+ /*
+ * Turn on ECHODIS bit in NWay-forced full mode and turn it
+ * off it in NWay-forced half mode for NWay-forced v.s.
+ * legacy-forced issue
+ */
+ if (vptr->mii_status & VELOCITY_DUPLEX_FULL)
+ MII_REG_BITS_ON(TCSR_ECHODIS, MII_REG_TCSR, vptr->mac_regs);
+ else
+ MII_REG_BITS_OFF(TCSR_ECHODIS, MII_REG_TCSR, vptr->mac_regs);
+ break;
+
+ case PHYID_MARVELL_1000:
+ case PHYID_MARVELL_1000S:
+ /*
+ * Assert CRS on Transmit
+ */
+ MII_REG_BITS_ON(PSCR_ACRSTX, MII_REG_PSCR, vptr->mac_regs);
+ /*
+ * Reset to hardware default
+ */
+ MII_REG_BITS_ON((ANAR_ASMDIR | ANAR_PAUSE), MII_REG_ANAR, vptr->mac_regs);
+ break;
+ default:
+ ;
+ }
+ velocity_mii_read(vptr->mac_regs, MII_REG_BMCR, &BMCR);
+ if (BMCR & BMCR_ISO) {
+ BMCR &= ~BMCR_ISO;
+ velocity_mii_write(vptr->mac_regs, MII_REG_BMCR, BMCR);
+ }
+}
+
+
+/**
* velocity_init_registers - initialise MAC registers
* @vptr: velocity to init
* @type: type of initialisation (hot or cold)
@@ -703,11 +1268,10 @@ static void velocity_rx_reset(struct velocity_info *vptr)
* Initialise the MAC on a reset or on first set up on the
* hardware.
*/
-
static void velocity_init_registers(struct velocity_info *vptr,
enum velocity_init_type type)
{
- struct mac_regs __iomem * regs = vptr->mac_regs;
+ struct mac_regs __iomem *regs = vptr->mac_regs;
int i, mii_status;
mac_wol_reset(regs);
@@ -750,9 +1314,9 @@ static void velocity_init_registers(struct velocity_info *vptr,
mdelay(5);
mac_eeprom_reload(regs);
- for (i = 0; i < 6; i++) {
+ for (i = 0; i < 6; i++)
writeb(vptr->dev->dev_addr[i], &(regs->PAR[i]));
- }
+
/*
* clear Pre_ACPI bit.
*/
@@ -819,291 +1383,29 @@ static void velocity_init_registers(struct velocity_info *vptr,
}
}
-/**
- * velocity_soft_reset - soft reset
- * @vptr: velocity to reset
- *
- * Kick off a soft reset of the velocity adapter and then poll
- * until the reset sequence has completed before returning.
- */
-
-static int velocity_soft_reset(struct velocity_info *vptr)
-{
- struct mac_regs __iomem * regs = vptr->mac_regs;
- int i = 0;
-
- writel(CR0_SFRST, &regs->CR0Set);
-
- for (i = 0; i < W_MAX_TIMEOUT; i++) {
- udelay(5);
- if (!DWORD_REG_BITS_IS_ON(CR0_SFRST, &regs->CR0Set))
- break;
- }
-
- if (i == W_MAX_TIMEOUT) {
- writel(CR0_FORSRST, &regs->CR0Set);
- /* FIXME: PCI POSTING */
- /* delay 2ms */
- mdelay(2);
- }
- return 0;
-}
-
-static const struct net_device_ops velocity_netdev_ops = {
- .ndo_open = velocity_open,
- .ndo_stop = velocity_close,
- .ndo_start_xmit = velocity_xmit,
- .ndo_get_stats = velocity_get_stats,
- .ndo_validate_addr = eth_validate_addr,
- .ndo_set_mac_address = eth_mac_addr,
- .ndo_set_multicast_list = velocity_set_multi,
- .ndo_change_mtu = velocity_change_mtu,
- .ndo_do_ioctl = velocity_ioctl,
- .ndo_vlan_rx_add_vid = velocity_vlan_rx_add_vid,
- .ndo_vlan_rx_kill_vid = velocity_vlan_rx_kill_vid,
- .ndo_vlan_rx_register = velocity_vlan_rx_register,
-};
-
-/**
- * velocity_found1 - set up discovered velocity card
- * @pdev: PCI device
- * @ent: PCI device table entry that matched
- *
- * Configure a discovered adapter from scratch. Return a negative
- * errno error code on failure paths.
- */
-
-static int __devinit velocity_found1(struct pci_dev *pdev, const struct pci_device_id *ent)
+static void velocity_give_many_rx_descs(struct velocity_info *vptr)
{
- static int first = 1;
- struct net_device *dev;
- int i;
- const char *drv_string;
- const struct velocity_info_tbl *info = &chip_info_table[ent->driver_data];
- struct velocity_info *vptr;
- struct mac_regs __iomem * regs;
- int ret = -ENOMEM;
-
- /* FIXME: this driver, like almost all other ethernet drivers,
- * can support more than MAX_UNITS.
- */
- if (velocity_nics >= MAX_UNITS) {
- dev_notice(&pdev->dev, "already found %d NICs.\n",
- velocity_nics);
- return -ENODEV;
- }
-
- dev = alloc_etherdev(sizeof(struct velocity_info));
- if (!dev) {
- dev_err(&pdev->dev, "allocate net device failed.\n");
- goto out;
- }
-
- /* Chain it all together */
-
- SET_NETDEV_DEV(dev, &pdev->dev);
- vptr = netdev_priv(dev);
-
-
- if (first) {
- printk(KERN_INFO "%s Ver. %s\n",
- VELOCITY_FULL_DRV_NAM, VELOCITY_VERSION);
- printk(KERN_INFO "Copyright (c) 2002, 2003 VIA Networking Technologies, Inc.\n");
- printk(KERN_INFO "Copyright (c) 2004 Red Hat Inc.\n");
- first = 0;
- }
-
- velocity_init_info(pdev, vptr, info);
-
- vptr->dev = dev;
-
- dev->irq = pdev->irq;
-
- ret = pci_enable_device(pdev);
- if (ret < 0)
- goto err_free_dev;
-
- ret = velocity_get_pci_info(vptr, pdev);
- if (ret < 0) {
- /* error message already printed */
- goto err_disable;
- }
-
- ret = pci_request_regions(pdev, VELOCITY_NAME);
- if (ret < 0) {
- dev_err(&pdev->dev, "No PCI resources.\n");
- goto err_disable;
- }
-
- regs = ioremap(vptr->memaddr, VELOCITY_IO_SIZE);
- if (regs == NULL) {
- ret = -EIO;
- goto err_release_res;
- }
-
- vptr->mac_regs = regs;
-
- mac_wol_reset(regs);
-
- dev->base_addr = vptr->ioaddr;
-
- for (i = 0; i < 6; i++)
- dev->dev_addr[i] = readb(&regs->PAR[i]);
-
-
- drv_string = dev_driver_string(&pdev->dev);
-
- velocity_get_options(&vptr->options, velocity_nics, drv_string);
-
- /*
- * Mask out the options cannot be set to the chip
- */
-
- vptr->options.flags &= info->flags;
+ struct mac_regs __iomem *regs = vptr->mac_regs;
+ int avail, dirty, unusable;
/*
- * Enable the chip specified capbilities
+ * RD number must be equal to 4X per hardware spec
+ * (programming guide rev 1.20, p.13)
*/
+ if (vptr->rx.filled < 4)
+ return;
- vptr->flags = vptr->options.flags | (info->flags & 0xFF000000UL);
-
- vptr->wol_opts = vptr->options.wol_opts;
- vptr->flags |= VELOCITY_FLAGS_WOL_ENABLED;
-
- vptr->phy_id = MII_GET_PHY_ID(vptr->mac_regs);
-
- dev->irq = pdev->irq;
- dev->netdev_ops = &velocity_netdev_ops;
- dev->ethtool_ops = &velocity_ethtool_ops;
-
-#ifdef VELOCITY_ZERO_COPY_SUPPORT
- dev->features |= NETIF_F_SG;
-#endif
- dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_FILTER |
- NETIF_F_HW_VLAN_RX;
-
- if (vptr->flags & VELOCITY_FLAGS_TX_CSUM)
- dev->features |= NETIF_F_IP_CSUM;
-
- ret = register_netdev(dev);
- if (ret < 0)
- goto err_iounmap;
-
- if (!velocity_get_link(dev)) {
- netif_carrier_off(dev);
- vptr->mii_status |= VELOCITY_LINK_FAIL;
- }
-
- velocity_print_info(vptr);
- pci_set_drvdata(pdev, dev);
-
- /* and leave the chip powered down */
-
- pci_set_power_state(pdev, PCI_D3hot);
-#ifdef CONFIG_PM
- {
- unsigned long flags;
-
- spin_lock_irqsave(&velocity_dev_list_lock, flags);
- list_add(&vptr->list, &velocity_dev_list);
- spin_unlock_irqrestore(&velocity_dev_list_lock, flags);
- }
-#endif
- velocity_nics++;
-out:
- return ret;
-
-err_iounmap:
- iounmap(regs);
-err_release_res:
- pci_release_regions(pdev);
-err_disable:
- pci_disable_device(pdev);
-err_free_dev:
- free_netdev(dev);
- goto out;
-}
-
-/**
- * velocity_print_info - per driver data
- * @vptr: velocity
- *
- * Print per driver data as the kernel driver finds Velocity
- * hardware
- */
-
-static void __devinit velocity_print_info(struct velocity_info *vptr)
-{
- struct net_device *dev = vptr->dev;
-
- printk(KERN_INFO "%s: %s\n", dev->name, get_chip_name(vptr->chip_id));
- printk(KERN_INFO "%s: Ethernet Address: %2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X\n",
- dev->name,
- dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
- dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]);
-}
-
-/**
- * velocity_init_info - init private data
- * @pdev: PCI device
- * @vptr: Velocity info
- * @info: Board type
- *
- * Set up the initial velocity_info struct for the device that has been
- * discovered.
- */
-
-static void __devinit velocity_init_info(struct pci_dev *pdev,
- struct velocity_info *vptr,
- const struct velocity_info_tbl *info)
-{
- memset(vptr, 0, sizeof(struct velocity_info));
-
- vptr->pdev = pdev;
- vptr->chip_id = info->chip_id;
- vptr->tx.numq = info->txqueue;
- vptr->multicast_limit = MCAM_SIZE;
- spin_lock_init(&vptr->lock);
- INIT_LIST_HEAD(&vptr->list);
-}
-
-/**
- * velocity_get_pci_info - retrieve PCI info for device
- * @vptr: velocity device
- * @pdev: PCI device it matches
- *
- * Retrieve the PCI configuration space data that interests us from
- * the kernel PCI layer
- */
-
-static int __devinit velocity_get_pci_info(struct velocity_info *vptr, struct pci_dev *pdev)
-{
- vptr->rev_id = pdev->revision;
-
- pci_set_master(pdev);
-
- vptr->ioaddr = pci_resource_start(pdev, 0);
- vptr->memaddr = pci_resource_start(pdev, 1);
-
- if (!(pci_resource_flags(pdev, 0) & IORESOURCE_IO)) {
- dev_err(&pdev->dev,
- "region #0 is not an I/O resource, aborting.\n");
- return -EINVAL;
- }
-
- if ((pci_resource_flags(pdev, 1) & IORESOURCE_IO)) {
- dev_err(&pdev->dev,
- "region #1 is an I/O resource, aborting.\n");
- return -EINVAL;
- }
+ wmb();
- if (pci_resource_len(pdev, 1) < VELOCITY_IO_SIZE) {
- dev_err(&pdev->dev, "region #1 is too small.\n");
- return -EINVAL;
+ unusable = vptr->rx.filled & 0x0003;
+ dirty = vptr->rx.dirty - unusable;
+ for (avail = vptr->rx.filled & 0xfffc; avail; avail--) {
+ dirty = (dirty > 0) ? dirty - 1 : vptr->options.numrx - 1;
+ vptr->rx.ring[dirty].rdesc0.len |= OWNED_BY_NIC;
}
- vptr->pdev = pdev;
- return 0;
+ writew(vptr->rx.filled & 0xfffc, &regs->RBRDU);
+ vptr->rx.filled = unusable;
}
/**
@@ -1113,7 +1415,6 @@ static int __devinit velocity_get_pci_info(struct velocity_info *vptr, struct pc
* Allocate PCI mapped DMA rings for the receive and transmit layer
* to use.
*/
-
static int velocity_init_dma_rings(struct velocity_info *vptr)
{
struct velocity_opt *opt = &vptr->options;
@@ -1154,46 +1455,50 @@ static int velocity_init_dma_rings(struct velocity_info *vptr)
return 0;
}
+static void velocity_set_rxbufsize(struct velocity_info *vptr, int mtu)
+{
+ vptr->rx.buf_sz = (mtu <= ETH_DATA_LEN) ? PKT_BUF_SZ : mtu + 32;
+}
+
/**
- * velocity_free_dma_rings - free PCI ring pointers
- * @vptr: Velocity to free from
+ * velocity_alloc_rx_buf - allocate aligned receive buffer
+ * @vptr: velocity
+ * @idx: ring index
*
- * Clean up the PCI ring buffers allocated to this velocity.
+ * Allocate a new full sized buffer for the reception of a frame and
+ * map it into PCI space for the hardware to use. The hardware
+ * requires *64* byte alignment of the buffer which makes life
+ * less fun than would be ideal.
*/
-
-static void velocity_free_dma_rings(struct velocity_info *vptr)
+static int velocity_alloc_rx_buf(struct velocity_info *vptr, int idx)
{
- const int size = vptr->options.numrx * sizeof(struct rx_desc) +
- vptr->options.numtx * sizeof(struct tx_desc) * vptr->tx.numq;
-
- pci_free_consistent(vptr->pdev, size, vptr->rx.ring, vptr->rx.pool_dma);
-}
+ struct rx_desc *rd = &(vptr->rx.ring[idx]);
+ struct velocity_rd_info *rd_info = &(vptr->rx.info[idx]);
-static void velocity_give_many_rx_descs(struct velocity_info *vptr)
-{
- struct mac_regs __iomem *regs = vptr->mac_regs;
- int avail, dirty, unusable;
+ rd_info->skb = dev_alloc_skb(vptr->rx.buf_sz + 64);
+ if (rd_info->skb == NULL)
+ return -ENOMEM;
/*
- * RD number must be equal to 4X per hardware spec
- * (programming guide rev 1.20, p.13)
+ * Do the gymnastics to get the buffer head for data at
+ * 64byte alignment.
*/
- if (vptr->rx.filled < 4)
- return;
-
- wmb();
+ skb_reserve(rd_info->skb, (unsigned long) rd_info->skb->data & 63);
+ rd_info->skb_dma = pci_map_single(vptr->pdev, rd_info->skb->data,
+ vptr->rx.buf_sz, PCI_DMA_FROMDEVICE);
- unusable = vptr->rx.filled & 0x0003;
- dirty = vptr->rx.dirty - unusable;
- for (avail = vptr->rx.filled & 0xfffc; avail; avail--) {
- dirty = (dirty > 0) ? dirty - 1 : vptr->options.numrx - 1;
- vptr->rx.ring[dirty].rdesc0.len |= OWNED_BY_NIC;
- }
+ /*
+ * Fill in the descriptor to match
+ */
- writew(vptr->rx.filled & 0xfffc, &regs->RBRDU);
- vptr->rx.filled = unusable;
+ *((u32 *) & (rd->rdesc0)) = 0;
+ rd->size = cpu_to_le16(vptr->rx.buf_sz) | RX_INTEN;
+ rd->pa_low = cpu_to_le32(rd_info->skb_dma);
+ rd->pa_high = 0;
+ return 0;
}
+
static int velocity_rx_refill(struct velocity_info *vptr)
{
int dirty = vptr->rx.dirty, done = 0;
@@ -1221,42 +1526,6 @@ static int velocity_rx_refill(struct velocity_info *vptr)
return done;
}
-static void velocity_set_rxbufsize(struct velocity_info *vptr, int mtu)
-{
- vptr->rx.buf_sz = (mtu <= ETH_DATA_LEN) ? PKT_BUF_SZ : mtu + 32;
-}
-
-/**
- * velocity_init_rd_ring - set up receive ring
- * @vptr: velocity to configure
- *
- * Allocate and set up the receive buffers for each ring slot and
- * assign them to the network adapter.
- */
-
-static int velocity_init_rd_ring(struct velocity_info *vptr)
-{
- int ret = -ENOMEM;
-
- vptr->rx.info = kcalloc(vptr->options.numrx,
- sizeof(struct velocity_rd_info), GFP_KERNEL);
- if (!vptr->rx.info)
- goto out;
-
- velocity_init_rx_ring_indexes(vptr);
-
- if (velocity_rx_refill(vptr) != vptr->options.numrx) {
- VELOCITY_PRT(MSG_LEVEL_ERR, KERN_ERR
- "%s: failed to allocate RX buffer.\n", vptr->dev->name);
- velocity_free_rd_ring(vptr);
- goto out;
- }
-
- ret = 0;
-out:
- return ret;
-}
-
/**
* velocity_free_rd_ring - free receive ring
* @vptr: velocity to clean up
@@ -1264,7 +1533,6 @@ out:
* Free the receive buffers for each ring slot and any
* attached socket buffers that need to go away.
*/
-
static void velocity_free_rd_ring(struct velocity_info *vptr)
{
int i;
@@ -1292,6 +1560,38 @@ static void velocity_free_rd_ring(struct velocity_info *vptr)
vptr->rx.info = NULL;
}
+
+
+/**
+ * velocity_init_rd_ring - set up receive ring
+ * @vptr: velocity to configure
+ *
+ * Allocate and set up the receive buffers for each ring slot and
+ * assign them to the network adapter.
+ */
+static int velocity_init_rd_ring(struct velocity_info *vptr)
+{
+ int ret = -ENOMEM;
+
+ vptr->rx.info = kcalloc(vptr->options.numrx,
+ sizeof(struct velocity_rd_info), GFP_KERNEL);
+ if (!vptr->rx.info)
+ goto out;
+
+ velocity_init_rx_ring_indexes(vptr);
+
+ if (velocity_rx_refill(vptr) != vptr->options.numrx) {
+ VELOCITY_PRT(MSG_LEVEL_ERR, KERN_ERR
+ "%s: failed to allocate RX buffer.\n", vptr->dev->name);
+ velocity_free_rd_ring(vptr);
+ goto out;
+ }
+
+ ret = 0;
+out:
+ return ret;
+}
+
/**
* velocity_init_td_ring - set up transmit ring
* @vptr: velocity
@@ -1300,7 +1600,6 @@ static void velocity_free_rd_ring(struct velocity_info *vptr)
* Returns zero on success or a negative posix errno code for
* failure.
*/
-
static int velocity_init_td_ring(struct velocity_info *vptr)
{
dma_addr_t curr;
@@ -1314,7 +1613,7 @@ static int velocity_init_td_ring(struct velocity_info *vptr)
sizeof(struct velocity_td_info),
GFP_KERNEL);
if (!vptr->tx.infos[j]) {
- while(--j >= 0)
+ while (--j >= 0)
kfree(vptr->tx.infos[j]);
return -ENOMEM;
}
@@ -1324,22 +1623,92 @@ static int velocity_init_td_ring(struct velocity_info *vptr)
return 0;
}
+/**
+ * velocity_free_dma_rings - free PCI ring pointers
+ * @vptr: Velocity to free from
+ *
+ * Clean up the PCI ring buffers allocated to this velocity.
+ */
+static void velocity_free_dma_rings(struct velocity_info *vptr)
+{
+ const int size = vptr->options.numrx * sizeof(struct rx_desc) +
+ vptr->options.numtx * sizeof(struct tx_desc) * vptr->tx.numq;
+
+ pci_free_consistent(vptr->pdev, size, vptr->rx.ring, vptr->rx.pool_dma);
+}
+
+
+static int velocity_init_rings(struct velocity_info *vptr, int mtu)
+{
+ int ret;
+
+ velocity_set_rxbufsize(vptr, mtu);
+
+ ret = velocity_init_dma_rings(vptr);
+ if (ret < 0)
+ goto out;
+
+ ret = velocity_init_rd_ring(vptr);
+ if (ret < 0)
+ goto err_free_dma_rings_0;
+
+ ret = velocity_init_td_ring(vptr);
+ if (ret < 0)
+ goto err_free_rd_ring_1;
+out:
+ return ret;
+
+err_free_rd_ring_1:
+ velocity_free_rd_ring(vptr);
+err_free_dma_rings_0:
+ velocity_free_dma_rings(vptr);
+ goto out;
+}
+
+/**
+ * velocity_free_tx_buf - free transmit buffer
+ * @vptr: velocity
+ * @tdinfo: buffer
+ *
+ * Release an transmit buffer. If the buffer was preallocated then
+ * recycle it, if not then unmap the buffer.
+ */
+static void velocity_free_tx_buf(struct velocity_info *vptr, struct velocity_td_info *tdinfo)
+{
+ struct sk_buff *skb = tdinfo->skb;
+ int i;
+ int pktlen;
+
+ /*
+ * Don't unmap the pre-allocated tx_bufs
+ */
+ if (tdinfo->skb_dma) {
+
+ pktlen = max_t(unsigned int, skb->len, ETH_ZLEN);
+ for (i = 0; i < tdinfo->nskb_dma; i++) {
+ pci_unmap_single(vptr->pdev, tdinfo->skb_dma[i], pktlen, PCI_DMA_TODEVICE);
+ tdinfo->skb_dma[i] = 0;
+ }
+ }
+ dev_kfree_skb_irq(skb);
+ tdinfo->skb = NULL;
+}
+
+
/*
* FIXME: could we merge this with velocity_free_tx_buf ?
*/
-
static void velocity_free_td_ring_entry(struct velocity_info *vptr,
int q, int n)
{
- struct velocity_td_info * td_info = &(vptr->tx.infos[q][n]);
+ struct velocity_td_info *td_info = &(vptr->tx.infos[q][n]);
int i;
if (td_info == NULL)
return;
if (td_info->skb) {
- for (i = 0; i < td_info->nskb_dma; i++)
- {
+ for (i = 0; i < td_info->nskb_dma; i++) {
if (td_info->skb_dma[i]) {
pci_unmap_single(vptr->pdev, td_info->skb_dma[i],
td_info->skb->len, PCI_DMA_TODEVICE);
@@ -1358,7 +1727,6 @@ static void velocity_free_td_ring_entry(struct velocity_info *vptr,
* Free up the transmit ring for this particular velocity adapter.
* We free the ring contents but not the ring itself.
*/
-
static void velocity_free_td_ring(struct velocity_info *vptr)
{
int i, j;
@@ -1366,70 +1734,175 @@ static void velocity_free_td_ring(struct velocity_info *vptr)
for (j = 0; j < vptr->tx.numq; j++) {
if (vptr->tx.infos[j] == NULL)
continue;
- for (i = 0; i < vptr->options.numtx; i++) {
+ for (i = 0; i < vptr->options.numtx; i++)
velocity_free_td_ring_entry(vptr, j, i);
- }
kfree(vptr->tx.infos[j]);
vptr->tx.infos[j] = NULL;
}
}
+
+static void velocity_free_rings(struct velocity_info *vptr)
+{
+ velocity_free_td_ring(vptr);
+ velocity_free_rd_ring(vptr);
+ velocity_free_dma_rings(vptr);
+}
+
/**
- * velocity_rx_srv - service RX interrupt
+ * velocity_error - handle error from controller
* @vptr: velocity
- * @status: adapter status (unused)
+ * @status: card status
+ *
+ * Process an error report from the hardware and attempt to recover
+ * the card itself. At the moment we cannot recover from some
+ * theoretically impossible errors but this could be fixed using
+ * the pci_device_failed logic to bounce the hardware
*
- * Walk the receive ring of the velocity adapter and remove
- * any received packets from the receive queue. Hand the ring
- * slots back to the adapter for reuse.
*/
-
-static int velocity_rx_srv(struct velocity_info *vptr, int status)
+static void velocity_error(struct velocity_info *vptr, int status)
{
- struct net_device_stats *stats = &vptr->dev->stats;
- int rd_curr = vptr->rx.curr;
- int works = 0;
- do {
- struct rx_desc *rd = vptr->rx.ring + rd_curr;
+ if (status & ISR_TXSTLI) {
+ struct mac_regs __iomem *regs = vptr->mac_regs;
- if (!vptr->rx.info[rd_curr].skb)
- break;
+ printk(KERN_ERR "TD structure error TDindex=%hx\n", readw(&regs->TDIdx[0]));
+ BYTE_REG_BITS_ON(TXESR_TDSTR, &regs->TXESR);
+ writew(TRDCSR_RUN, &regs->TDCSRClr);
+ netif_stop_queue(vptr->dev);
- if (rd->rdesc0.len & OWNED_BY_NIC)
- break;
+ /* FIXME: port over the pci_device_failed code and use it
+ here */
+ }
- rmb();
+ if (status & ISR_SRCI) {
+ struct mac_regs __iomem *regs = vptr->mac_regs;
+ int linked;
+
+ if (vptr->options.spd_dpx == SPD_DPX_AUTO) {
+ vptr->mii_status = check_connection_type(regs);
+ /*
+ * If it is a 3119, disable frame bursting in
+ * halfduplex mode and enable it in fullduplex
+ * mode
+ */
+ if (vptr->rev_id < REV_ID_VT3216_A0) {
+ if (vptr->mii_status | VELOCITY_DUPLEX_FULL)
+ BYTE_REG_BITS_ON(TCR_TB2BDIS, &regs->TCR);
+ else
+ BYTE_REG_BITS_OFF(TCR_TB2BDIS, &regs->TCR);
+ }
+ /*
+ * Only enable CD heart beat counter in 10HD mode
+ */
+ if (!(vptr->mii_status & VELOCITY_DUPLEX_FULL) && (vptr->mii_status & VELOCITY_SPEED_10))
+ BYTE_REG_BITS_OFF(TESTCFG_HBDIS, &regs->TESTCFG);
+ else
+ BYTE_REG_BITS_ON(TESTCFG_HBDIS, &regs->TESTCFG);
+ }
/*
- * Don't drop CE or RL error frame although RXOK is off
+ * Get link status from PHYSR0
*/
- if (rd->rdesc0.RSR & (RSR_RXOK | RSR_CE | RSR_RL)) {
- if (velocity_receive_frame(vptr, rd_curr) < 0)
- stats->rx_dropped++;
- } else {
- if (rd->rdesc0.RSR & RSR_CRC)
- stats->rx_crc_errors++;
- if (rd->rdesc0.RSR & RSR_FAE)
- stats->rx_frame_errors++;
+ linked = readb(&regs->PHYSR0) & PHYSR0_LINKGD;
- stats->rx_dropped++;
+ if (linked) {
+ vptr->mii_status &= ~VELOCITY_LINK_FAIL;
+ netif_carrier_on(vptr->dev);
+ } else {
+ vptr->mii_status |= VELOCITY_LINK_FAIL;
+ netif_carrier_off(vptr->dev);
}
- rd->size |= RX_INTEN;
+ velocity_print_link_status(vptr);
+ enable_flow_control_ability(vptr);
- rd_curr++;
- if (rd_curr >= vptr->options.numrx)
- rd_curr = 0;
- } while (++works <= 15);
+ /*
+ * Re-enable auto-polling because SRCI will disable
+ * auto-polling
+ */
- vptr->rx.curr = rd_curr;
+ enable_mii_autopoll(regs);
- if ((works > 0) && (velocity_rx_refill(vptr) > 0))
- velocity_give_many_rx_descs(vptr);
+ if (vptr->mii_status & VELOCITY_LINK_FAIL)
+ netif_stop_queue(vptr->dev);
+ else
+ netif_wake_queue(vptr->dev);
- VAR_USED(stats);
+ };
+ if (status & ISR_MIBFI)
+ velocity_update_hw_mibs(vptr);
+ if (status & ISR_LSTEI)
+ mac_rx_queue_wake(vptr->mac_regs);
+}
+
+/**
+ * tx_srv - transmit interrupt service
+ * @vptr; Velocity
+ * @status:
+ *
+ * Scan the queues looking for transmitted packets that
+ * we can complete and clean up. Update any statistics as
+ * necessary/
+ */
+static int velocity_tx_srv(struct velocity_info *vptr, u32 status)
+{
+ struct tx_desc *td;
+ int qnum;
+ int full = 0;
+ int idx;
+ int works = 0;
+ struct velocity_td_info *tdinfo;
+ struct net_device_stats *stats = &vptr->dev->stats;
+
+ for (qnum = 0; qnum < vptr->tx.numq; qnum++) {
+ for (idx = vptr->tx.tail[qnum]; vptr->tx.used[qnum] > 0;
+ idx = (idx + 1) % vptr->options.numtx) {
+
+ /*
+ * Get Tx Descriptor
+ */
+ td = &(vptr->tx.rings[qnum][idx]);
+ tdinfo = &(vptr->tx.infos[qnum][idx]);
+
+ if (td->tdesc0.len & OWNED_BY_NIC)
+ break;
+
+ if ((works++ > 15))
+ break;
+
+ if (td->tdesc0.TSR & TSR0_TERR) {
+ stats->tx_errors++;
+ stats->tx_dropped++;
+ if (td->tdesc0.TSR & TSR0_CDH)
+ stats->tx_heartbeat_errors++;
+ if (td->tdesc0.TSR & TSR0_CRS)
+ stats->tx_carrier_errors++;
+ if (td->tdesc0.TSR & TSR0_ABT)
+ stats->tx_aborted_errors++;
+ if (td->tdesc0.TSR & TSR0_OWC)
+ stats->tx_window_errors++;
+ } else {
+ stats->tx_packets++;
+ stats->tx_bytes += tdinfo->skb->len;
+ }
+ velocity_free_tx_buf(vptr, tdinfo);
+ vptr->tx.used[qnum]--;
+ }
+ vptr->tx.tail[qnum] = idx;
+
+ if (AVAIL_TD(vptr, qnum) < 1)
+ full = 1;
+ }
+ /*
+ * Look to see if we should kick the transmit network
+ * layer for more work.
+ */
+ if (netif_queue_stopped(vptr->dev) && (full == 0)
+ && (!(vptr->mii_status & VELOCITY_LINK_FAIL))) {
+ netif_wake_queue(vptr->dev);
+ }
return works;
}
@@ -1441,7 +1914,6 @@ static int velocity_rx_srv(struct velocity_info *vptr, int status)
* Process the status bits for the received packet and determine
* if the checksum was computed and verified by the hardware
*/
-
static inline void velocity_rx_csum(struct rx_desc *rd, struct sk_buff *skb)
{
skb->ip_summed = CHECKSUM_NONE;
@@ -1450,9 +1922,8 @@ static inline void velocity_rx_csum(struct rx_desc *rd, struct sk_buff *skb)
if (rd->rdesc1.CSM & CSM_IPOK) {
if ((rd->rdesc1.CSM & CSM_TCPKT) ||
(rd->rdesc1.CSM & CSM_UDPKT)) {
- if (!(rd->rdesc1.CSM & CSM_TUPOK)) {
+ if (!(rd->rdesc1.CSM & CSM_TUPOK))
return;
- }
}
skb->ip_summed = CHECKSUM_UNNECESSARY;
}
@@ -1509,6 +1980,7 @@ static inline void velocity_iph_realign(struct velocity_info *vptr,
}
}
+
/**
* velocity_receive_frame - received packet processor
* @vptr: velocity we are handling
@@ -1517,7 +1989,6 @@ static inline void velocity_iph_realign(struct velocity_info *vptr,
* A packet has arrived. We process the packet and if appropriate
* pass the frame up the network stack
*/
-
static int velocity_receive_frame(struct velocity_info *vptr, int idx)
{
void (*pci_action)(struct pci_dev *, dma_addr_t, size_t, int);
@@ -1579,320 +2050,118 @@ static int velocity_receive_frame(struct velocity_info *vptr, int idx)
return 0;
}
-/**
- * velocity_alloc_rx_buf - allocate aligned receive buffer
- * @vptr: velocity
- * @idx: ring index
- *
- * Allocate a new full sized buffer for the reception of a frame and
- * map it into PCI space for the hardware to use. The hardware
- * requires *64* byte alignment of the buffer which makes life
- * less fun than would be ideal.
- */
-
-static int velocity_alloc_rx_buf(struct velocity_info *vptr, int idx)
-{
- struct rx_desc *rd = &(vptr->rx.ring[idx]);
- struct velocity_rd_info *rd_info = &(vptr->rx.info[idx]);
-
- rd_info->skb = dev_alloc_skb(vptr->rx.buf_sz + 64);
- if (rd_info->skb == NULL)
- return -ENOMEM;
-
- /*
- * Do the gymnastics to get the buffer head for data at
- * 64byte alignment.
- */
- skb_reserve(rd_info->skb, (unsigned long) rd_info->skb->data & 63);
- rd_info->skb_dma = pci_map_single(vptr->pdev, rd_info->skb->data,
- vptr->rx.buf_sz, PCI_DMA_FROMDEVICE);
-
- /*
- * Fill in the descriptor to match
- */
-
- *((u32 *) & (rd->rdesc0)) = 0;
- rd->size = cpu_to_le16(vptr->rx.buf_sz) | RX_INTEN;
- rd->pa_low = cpu_to_le32(rd_info->skb_dma);
- rd->pa_high = 0;
- return 0;
-}
/**
- * tx_srv - transmit interrupt service
- * @vptr; Velocity
- * @status:
+ * velocity_rx_srv - service RX interrupt
+ * @vptr: velocity
+ * @status: adapter status (unused)
*
- * Scan the queues looking for transmitted packets that
- * we can complete and clean up. Update any statistics as
- * necessary/
+ * Walk the receive ring of the velocity adapter and remove
+ * any received packets from the receive queue. Hand the ring
+ * slots back to the adapter for reuse.
*/
-
-static int velocity_tx_srv(struct velocity_info *vptr, u32 status)
+static int velocity_rx_srv(struct velocity_info *vptr, int status)
{
- struct tx_desc *td;
- int qnum;
- int full = 0;
- int idx;
- int works = 0;
- struct velocity_td_info *tdinfo;
struct net_device_stats *stats = &vptr->dev->stats;
+ int rd_curr = vptr->rx.curr;
+ int works = 0;
- for (qnum = 0; qnum < vptr->tx.numq; qnum++) {
- for (idx = vptr->tx.tail[qnum]; vptr->tx.used[qnum] > 0;
- idx = (idx + 1) % vptr->options.numtx) {
+ do {
+ struct rx_desc *rd = vptr->rx.ring + rd_curr;
- /*
- * Get Tx Descriptor
- */
- td = &(vptr->tx.rings[qnum][idx]);
- tdinfo = &(vptr->tx.infos[qnum][idx]);
+ if (!vptr->rx.info[rd_curr].skb)
+ break;
- if (td->tdesc0.len & OWNED_BY_NIC)
- break;
+ if (rd->rdesc0.len & OWNED_BY_NIC)
+ break;
- if ((works++ > 15))
- break;
+ rmb();
- if (td->tdesc0.TSR & TSR0_TERR) {
- stats->tx_errors++;
- stats->tx_dropped++;
- if (td->tdesc0.TSR & TSR0_CDH)
- stats->tx_heartbeat_errors++;
- if (td->tdesc0.TSR & TSR0_CRS)
- stats->tx_carrier_errors++;
- if (td->tdesc0.TSR & TSR0_ABT)
- stats->tx_aborted_errors++;
- if (td->tdesc0.TSR & TSR0_OWC)
- stats->tx_window_errors++;
- } else {
- stats->tx_packets++;
- stats->tx_bytes += tdinfo->skb->len;
- }
- velocity_free_tx_buf(vptr, tdinfo);
- vptr->tx.used[qnum]--;
- }
- vptr->tx.tail[qnum] = idx;
+ /*
+ * Don't drop CE or RL error frame although RXOK is off
+ */
+ if (rd->rdesc0.RSR & (RSR_RXOK | RSR_CE | RSR_RL)) {
+ if (velocity_receive_frame(vptr, rd_curr) < 0)
+ stats->rx_dropped++;
+ } else {
+ if (rd->rdesc0.RSR & RSR_CRC)
+ stats->rx_crc_errors++;
+ if (rd->rdesc0.RSR & RSR_FAE)
+ stats->rx_frame_errors++;
- if (AVAIL_TD(vptr, qnum) < 1) {
- full = 1;
+ stats->rx_dropped++;
}
- }
- /*
- * Look to see if we should kick the transmit network
- * layer for more work.
- */
- if (netif_queue_stopped(vptr->dev) && (full == 0)
- && (!(vptr->mii_status & VELOCITY_LINK_FAIL))) {
- netif_wake_queue(vptr->dev);
- }
- return works;
-}
-/**
- * velocity_print_link_status - link status reporting
- * @vptr: velocity to report on
- *
- * Turn the link status of the velocity card into a kernel log
- * description of the new link state, detailing speed and duplex
- * status
- */
+ rd->size |= RX_INTEN;
-static void velocity_print_link_status(struct velocity_info *vptr)
-{
+ rd_curr++;
+ if (rd_curr >= vptr->options.numrx)
+ rd_curr = 0;
+ } while (++works <= 15);
- if (vptr->mii_status & VELOCITY_LINK_FAIL) {
- VELOCITY_PRT(MSG_LEVEL_INFO, KERN_NOTICE "%s: failed to detect cable link\n", vptr->dev->name);
- } else if (vptr->options.spd_dpx == SPD_DPX_AUTO) {
- VELOCITY_PRT(MSG_LEVEL_INFO, KERN_NOTICE "%s: Link auto-negotiation", vptr->dev->name);
+ vptr->rx.curr = rd_curr;
- if (vptr->mii_status & VELOCITY_SPEED_1000)
- VELOCITY_PRT(MSG_LEVEL_INFO, " speed 1000M bps");
- else if (vptr->mii_status & VELOCITY_SPEED_100)
- VELOCITY_PRT(MSG_LEVEL_INFO, " speed 100M bps");
- else
- VELOCITY_PRT(MSG_LEVEL_INFO, " speed 10M bps");
+ if ((works > 0) && (velocity_rx_refill(vptr) > 0))
+ velocity_give_many_rx_descs(vptr);
- if (vptr->mii_status & VELOCITY_DUPLEX_FULL)
- VELOCITY_PRT(MSG_LEVEL_INFO, " full duplex\n");
- else
- VELOCITY_PRT(MSG_LEVEL_INFO, " half duplex\n");
- } else {
- VELOCITY_PRT(MSG_LEVEL_INFO, KERN_NOTICE "%s: Link forced", vptr->dev->name);
- switch (vptr->options.spd_dpx) {
- case SPD_DPX_100_HALF:
- VELOCITY_PRT(MSG_LEVEL_INFO, " speed 100M bps half duplex\n");
- break;
- case SPD_DPX_100_FULL:
- VELOCITY_PRT(MSG_LEVEL_INFO, " speed 100M bps full duplex\n");
- break;
- case SPD_DPX_10_HALF:
- VELOCITY_PRT(MSG_LEVEL_INFO, " speed 10M bps half duplex\n");
- break;
- case SPD_DPX_10_FULL:
- VELOCITY_PRT(MSG_LEVEL_INFO, " speed 10M bps full duplex\n");
- break;
- default:
- break;
- }
- }
+ VAR_USED(stats);
+ return works;
}
+
/**
- * velocity_error - handle error from controller
- * @vptr: velocity
- * @status: card status
- *
- * Process an error report from the hardware and attempt to recover
- * the card itself. At the moment we cannot recover from some
- * theoretically impossible errors but this could be fixed using
- * the pci_device_failed logic to bounce the hardware
+ * velocity_intr - interrupt callback
+ * @irq: interrupt number
+ * @dev_instance: interrupting device
*
+ * Called whenever an interrupt is generated by the velocity
+ * adapter IRQ line. We may not be the source of the interrupt
+ * and need to identify initially if we are, and if not exit as
+ * efficiently as possible.
*/
-
-static void velocity_error(struct velocity_info *vptr, int status)
+static irqreturn_t velocity_intr(int irq, void *dev_instance)
{
+ struct net_device *dev = dev_instance;
+ struct velocity_info *vptr = netdev_priv(dev);
+ u32 isr_status;
+ int max_count = 0;
- if (status & ISR_TXSTLI) {
- struct mac_regs __iomem * regs = vptr->mac_regs;
- printk(KERN_ERR "TD structure error TDindex=%hx\n", readw(&regs->TDIdx[0]));
- BYTE_REG_BITS_ON(TXESR_TDSTR, &regs->TXESR);
- writew(TRDCSR_RUN, &regs->TDCSRClr);
- netif_stop_queue(vptr->dev);
+ spin_lock(&vptr->lock);
+ isr_status = mac_read_isr(vptr->mac_regs);
- /* FIXME: port over the pci_device_failed code and use it
- here */
+ /* Not us ? */
+ if (isr_status == 0) {
+ spin_unlock(&vptr->lock);
+ return IRQ_NONE;
}
- if (status & ISR_SRCI) {
- struct mac_regs __iomem * regs = vptr->mac_regs;
- int linked;
-
- if (vptr->options.spd_dpx == SPD_DPX_AUTO) {
- vptr->mii_status = check_connection_type(regs);
-
- /*
- * If it is a 3119, disable frame bursting in
- * halfduplex mode and enable it in fullduplex
- * mode
- */
- if (vptr->rev_id < REV_ID_VT3216_A0) {
- if (vptr->mii_status | VELOCITY_DUPLEX_FULL)
- BYTE_REG_BITS_ON(TCR_TB2BDIS, &regs->TCR);
- else
- BYTE_REG_BITS_OFF(TCR_TB2BDIS, &regs->TCR);
- }
- /*
- * Only enable CD heart beat counter in 10HD mode
- */
- if (!(vptr->mii_status & VELOCITY_DUPLEX_FULL) && (vptr->mii_status & VELOCITY_SPEED_10)) {
- BYTE_REG_BITS_OFF(TESTCFG_HBDIS, &regs->TESTCFG);
- } else {
- BYTE_REG_BITS_ON(TESTCFG_HBDIS, &regs->TESTCFG);
- }
- }
- /*
- * Get link status from PHYSR0
- */
- linked = readb(&regs->PHYSR0) & PHYSR0_LINKGD;
-
- if (linked) {
- vptr->mii_status &= ~VELOCITY_LINK_FAIL;
- netif_carrier_on(vptr->dev);
- } else {
- vptr->mii_status |= VELOCITY_LINK_FAIL;
- netif_carrier_off(vptr->dev);
- }
-
- velocity_print_link_status(vptr);
- enable_flow_control_ability(vptr);
-
- /*
- * Re-enable auto-polling because SRCI will disable
- * auto-polling
- */
-
- enable_mii_autopoll(regs);
-
- if (vptr->mii_status & VELOCITY_LINK_FAIL)
- netif_stop_queue(vptr->dev);
- else
- netif_wake_queue(vptr->dev);
-
- };
- if (status & ISR_MIBFI)
- velocity_update_hw_mibs(vptr);
- if (status & ISR_LSTEI)
- mac_rx_queue_wake(vptr->mac_regs);
-}
-
-/**
- * velocity_free_tx_buf - free transmit buffer
- * @vptr: velocity
- * @tdinfo: buffer
- *
- * Release an transmit buffer. If the buffer was preallocated then
- * recycle it, if not then unmap the buffer.
- */
-
-static void velocity_free_tx_buf(struct velocity_info *vptr, struct velocity_td_info *tdinfo)
-{
- struct sk_buff *skb = tdinfo->skb;
- int i;
- int pktlen;
+ mac_disable_int(vptr->mac_regs);
/*
- * Don't unmap the pre-allocated tx_bufs
+ * Keep processing the ISR until we have completed
+ * processing and the isr_status becomes zero
*/
- if (tdinfo->skb_dma) {
- pktlen = max_t(unsigned int, skb->len, ETH_ZLEN);
- for (i = 0; i < tdinfo->nskb_dma; i++) {
-#ifdef VELOCITY_ZERO_COPY_SUPPORT
- pci_unmap_single(vptr->pdev, tdinfo->skb_dma[i], le16_to_cpu(td->tdesc1.len), PCI_DMA_TODEVICE);
-#else
- pci_unmap_single(vptr->pdev, tdinfo->skb_dma[i], pktlen, PCI_DMA_TODEVICE);
-#endif
- tdinfo->skb_dma[i] = 0;
+ while (isr_status != 0) {
+ mac_write_isr(vptr->mac_regs, isr_status);
+ if (isr_status & (~(ISR_PRXI | ISR_PPRXI | ISR_PTXI | ISR_PPTXI)))
+ velocity_error(vptr, isr_status);
+ if (isr_status & (ISR_PRXI | ISR_PPRXI))
+ max_count += velocity_rx_srv(vptr, isr_status);
+ if (isr_status & (ISR_PTXI | ISR_PPTXI))
+ max_count += velocity_tx_srv(vptr, isr_status);
+ isr_status = mac_read_isr(vptr->mac_regs);
+ if (max_count > vptr->options.int_works) {
+ printk(KERN_WARNING "%s: excessive work at interrupt.\n",
+ dev->name);
+ max_count = 0;
}
}
- dev_kfree_skb_irq(skb);
- tdinfo->skb = NULL;
-}
-
-static int velocity_init_rings(struct velocity_info *vptr, int mtu)
-{
- int ret;
-
- velocity_set_rxbufsize(vptr, mtu);
-
- ret = velocity_init_dma_rings(vptr);
- if (ret < 0)
- goto out;
-
- ret = velocity_init_rd_ring(vptr);
- if (ret < 0)
- goto err_free_dma_rings_0;
-
- ret = velocity_init_td_ring(vptr);
- if (ret < 0)
- goto err_free_rd_ring_1;
-out:
- return ret;
-
-err_free_rd_ring_1:
- velocity_free_rd_ring(vptr);
-err_free_dma_rings_0:
- velocity_free_dma_rings(vptr);
- goto out;
-}
+ spin_unlock(&vptr->lock);
+ mac_enable_int(vptr->mac_regs);
+ return IRQ_HANDLED;
-static void velocity_free_rings(struct velocity_info *vptr)
-{
- velocity_free_td_ring(vptr);
- velocity_free_rd_ring(vptr);
- velocity_free_dma_rings(vptr);
}
/**
@@ -1905,7 +2174,6 @@ static void velocity_free_rings(struct velocity_info *vptr)
* All the ring allocation and set up is done on open for this
* adapter to minimise memory usage when inactive
*/
-
static int velocity_open(struct net_device *dev)
{
struct velocity_info *vptr = netdev_priv(dev);
@@ -1939,6 +2207,24 @@ out:
}
/**
+ * velocity_shutdown - shut down the chip
+ * @vptr: velocity to deactivate
+ *
+ * Shuts down the internal operations of the velocity and
+ * disables interrupts, autopolling, transmit and receive
+ */
+static void velocity_shutdown(struct velocity_info *vptr)
+{
+ struct mac_regs __iomem *regs = vptr->mac_regs;
+ mac_disable_int(regs);
+ writel(CR0_STOP, &regs->CR0Set);
+ writew(0xFFFF, &regs->TDCSRClr);
+ writeb(0xFF, &regs->RDCSRClr);
+ safe_disable_mii_autopoll(regs);
+ mac_clear_isr(regs);
+}
+
+/**
* velocity_change_mtu - MTU change callback
* @dev: network device
* @new_mtu: desired MTU
@@ -1947,7 +2233,6 @@ out:
* this interface. It gets called on a change by the network layer.
* Return zero for success or negative posix error code.
*/
-
static int velocity_change_mtu(struct net_device *dev, int new_mtu)
{
struct velocity_info *vptr = netdev_priv(dev);
@@ -2021,22 +2306,127 @@ out_0:
}
/**
- * velocity_shutdown - shut down the chip
- * @vptr: velocity to deactivate
+ * velocity_mii_ioctl - MII ioctl handler
+ * @dev: network device
+ * @ifr: the ifreq block for the ioctl
+ * @cmd: the command
*
- * Shuts down the internal operations of the velocity and
- * disables interrupts, autopolling, transmit and receive
+ * Process MII requests made via ioctl from the network layer. These
+ * are used by tools like kudzu to interrogate the link state of the
+ * hardware
*/
+static int velocity_mii_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+{
+ struct velocity_info *vptr = netdev_priv(dev);
+ struct mac_regs __iomem *regs = vptr->mac_regs;
+ unsigned long flags;
+ struct mii_ioctl_data *miidata = if_mii(ifr);
+ int err;
-static void velocity_shutdown(struct velocity_info *vptr)
+ switch (cmd) {
+ case SIOCGMIIPHY:
+ miidata->phy_id = readb(&regs->MIIADR) & 0x1f;
+ break;
+ case SIOCGMIIREG:
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
+ if (velocity_mii_read(vptr->mac_regs, miidata->reg_num & 0x1f, &(miidata->val_out)) < 0)
+ return -ETIMEDOUT;
+ break;
+ case SIOCSMIIREG:
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
+ spin_lock_irqsave(&vptr->lock, flags);
+ err = velocity_mii_write(vptr->mac_regs, miidata->reg_num & 0x1f, miidata->val_in);
+ spin_unlock_irqrestore(&vptr->lock, flags);
+ check_connection_type(vptr->mac_regs);
+ if (err)
+ return err;
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+ return 0;
+}
+
+
+/**
+ * velocity_ioctl - ioctl entry point
+ * @dev: network device
+ * @rq: interface request ioctl
+ * @cmd: command code
+ *
+ * Called when the user issues an ioctl request to the network
+ * device in question. The velocity interface supports MII.
+ */
+static int velocity_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
{
- struct mac_regs __iomem * regs = vptr->mac_regs;
- mac_disable_int(regs);
- writel(CR0_STOP, &regs->CR0Set);
- writew(0xFFFF, &regs->TDCSRClr);
- writeb(0xFF, &regs->RDCSRClr);
- safe_disable_mii_autopoll(regs);
- mac_clear_isr(regs);
+ struct velocity_info *vptr = netdev_priv(dev);
+ int ret;
+
+ /* If we are asked for information and the device is power
+ saving then we need to bring the device back up to talk to it */
+
+ if (!netif_running(dev))
+ pci_set_power_state(vptr->pdev, PCI_D0);
+
+ switch (cmd) {
+ case SIOCGMIIPHY: /* Get address of MII PHY in use. */
+ case SIOCGMIIREG: /* Read MII PHY register. */
+ case SIOCSMIIREG: /* Write to MII PHY register. */
+ ret = velocity_mii_ioctl(dev, rq, cmd);
+ break;
+
+ default:
+ ret = -EOPNOTSUPP;
+ }
+ if (!netif_running(dev))
+ pci_set_power_state(vptr->pdev, PCI_D3hot);
+
+
+ return ret;
+}
+
+/**
+ * velocity_get_status - statistics callback
+ * @dev: network device
+ *
+ * Callback from the network layer to allow driver statistics
+ * to be resynchronized with hardware collected state. In the
+ * case of the velocity we need to pull the MIB counters from
+ * the hardware into the counters before letting the network
+ * layer display them.
+ */
+static struct net_device_stats *velocity_get_stats(struct net_device *dev)
+{
+ struct velocity_info *vptr = netdev_priv(dev);
+
+ /* If the hardware is down, don't touch MII */
+ if (!netif_running(dev))
+ return &dev->stats;
+
+ spin_lock_irq(&vptr->lock);
+ velocity_update_hw_mibs(vptr);
+ spin_unlock_irq(&vptr->lock);
+
+ dev->stats.rx_packets = vptr->mib_counter[HW_MIB_ifRxAllPkts];
+ dev->stats.rx_errors = vptr->mib_counter[HW_MIB_ifRxErrorPkts];
+ dev->stats.rx_length_errors = vptr->mib_counter[HW_MIB_ifInRangeLengthErrors];
+
+// unsigned long rx_dropped; /* no space in linux buffers */
+ dev->stats.collisions = vptr->mib_counter[HW_MIB_ifTxEtherCollisions];
+ /* detailed rx_errors: */
+// unsigned long rx_length_errors;
+// unsigned long rx_over_errors; /* receiver ring buff overflow */
+ dev->stats.rx_crc_errors = vptr->mib_counter[HW_MIB_ifRxPktCRCE];
+// unsigned long rx_frame_errors; /* recv'd frame alignment error */
+// unsigned long rx_fifo_errors; /* recv'r fifo overrun */
+// unsigned long rx_missed_errors; /* receiver missed packet */
+
+ /* detailed tx_errors */
+// unsigned long tx_fifo_errors;
+
+ return &dev->stats;
}
/**
@@ -2046,7 +2436,6 @@ static void velocity_shutdown(struct velocity_info *vptr)
* Callback from the network layer when the velocity is being
* deactivated by the network layer
*/
-
static int velocity_close(struct net_device *dev)
{
struct velocity_info *vptr = netdev_priv(dev);
@@ -2076,7 +2465,6 @@ static int velocity_close(struct net_device *dev)
* Called by the networ layer to request a packet is queued to
* the velocity. Returns zero on success.
*/
-
static int velocity_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct velocity_info *vptr = netdev_priv(dev);
@@ -2088,20 +2476,12 @@ static int velocity_xmit(struct sk_buff *skb, struct net_device *dev)
__le16 len;
int index;
-
if (skb_padto(skb, ETH_ZLEN))
goto out;
pktlen = max_t(unsigned int, skb->len, ETH_ZLEN);
len = cpu_to_le16(pktlen);
-#ifdef VELOCITY_ZERO_COPY_SUPPORT
- if (skb_shinfo(skb)->nr_frags > 6 && __skb_linearize(skb)) {
- kfree_skb(skb);
- return 0;
- }
-#endif
-
spin_lock_irqsave(&vptr->lock, flags);
index = vptr->tx.curr[qnum];
@@ -2111,59 +2491,18 @@ static int velocity_xmit(struct sk_buff *skb, struct net_device *dev)
td_ptr->tdesc1.TCR = TCR0_TIC;
td_ptr->td_buf[0].size &= ~TD_QUEUE;
-#ifdef VELOCITY_ZERO_COPY_SUPPORT
- if (skb_shinfo(skb)->nr_frags > 0) {
- int nfrags = skb_shinfo(skb)->nr_frags;
- tdinfo->skb = skb;
- if (nfrags > 6) {
- skb_copy_from_linear_data(skb, tdinfo->buf, skb->len);
- tdinfo->skb_dma[0] = tdinfo->buf_dma;
- td_ptr->tdesc0.len = len;
- td_ptr->tx.buf[0].pa_low = cpu_to_le32(tdinfo->skb_dma[0]);
- td_ptr->tx.buf[0].pa_high = 0;
- td_ptr->tx.buf[0].size = len; /* queue is 0 anyway */
- tdinfo->nskb_dma = 1;
- } else {
- int i = 0;
- tdinfo->nskb_dma = 0;
- tdinfo->skb_dma[i] = pci_map_single(vptr->pdev, skb->data,
- skb_headlen(skb), PCI_DMA_TODEVICE);
-
- td_ptr->tdesc0.len = len;
-
- /* FIXME: support 48bit DMA later */
- td_ptr->tx.buf[i].pa_low = cpu_to_le32(tdinfo->skb_dma);
- td_ptr->tx.buf[i].pa_high = 0;
- td_ptr->tx.buf[i].size = cpu_to_le16(skb_headlen(skb));
-
- for (i = 0; i < nfrags; i++) {
- skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
- void *addr = (void *)page_address(frag->page) + frag->page_offset;
-
- tdinfo->skb_dma[i + 1] = pci_map_single(vptr->pdev, addr, frag->size, PCI_DMA_TODEVICE);
-
- td_ptr->tx.buf[i + 1].pa_low = cpu_to_le32(tdinfo->skb_dma[i + 1]);
- td_ptr->tx.buf[i + 1].pa_high = 0;
- td_ptr->tx.buf[i + 1].size = cpu_to_le16(frag->size);
- }
- tdinfo->nskb_dma = i - 1;
- }
+ /*
+ * Map the linear network buffer into PCI space and
+ * add it to the transmit ring.
+ */
+ tdinfo->skb = skb;
+ tdinfo->skb_dma[0] = pci_map_single(vptr->pdev, skb->data, pktlen, PCI_DMA_TODEVICE);
+ td_ptr->tdesc0.len = len;
+ td_ptr->td_buf[0].pa_low = cpu_to_le32(tdinfo->skb_dma[0]);
+ td_ptr->td_buf[0].pa_high = 0;
+ td_ptr->td_buf[0].size = len;
+ tdinfo->nskb_dma = 1;
- } else
-#endif
- {
- /*
- * Map the linear network buffer into PCI space and
- * add it to the transmit ring.
- */
- tdinfo->skb = skb;
- tdinfo->skb_dma[0] = pci_map_single(vptr->pdev, skb->data, pktlen, PCI_DMA_TODEVICE);
- td_ptr->tdesc0.len = len;
- td_ptr->td_buf[0].pa_low = cpu_to_le32(tdinfo->skb_dma[0]);
- td_ptr->td_buf[0].pa_high = 0;
- td_ptr->td_buf[0].size = len;
- tdinfo->nskb_dma = 1;
- }
td_ptr->tdesc1.cmd = TCPLS_NORMAL + (tdinfo->nskb_dma + 1) * 16;
if (vptr->vlgrp && vlan_tx_tag_present(skb)) {
@@ -2206,782 +2545,533 @@ out:
return NETDEV_TX_OK;
}
+
+static const struct net_device_ops velocity_netdev_ops = {
+ .ndo_open = velocity_open,
+ .ndo_stop = velocity_close,
+ .ndo_start_xmit = velocity_xmit,
+ .ndo_get_stats = velocity_get_stats,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_set_mac_address = eth_mac_addr,
+ .ndo_set_multicast_list = velocity_set_multi,
+ .ndo_change_mtu = velocity_change_mtu,
+ .ndo_do_ioctl = velocity_ioctl,
+ .ndo_vlan_rx_add_vid = velocity_vlan_rx_add_vid,
+ .ndo_vlan_rx_kill_vid = velocity_vlan_rx_kill_vid,
+ .ndo_vlan_rx_register = velocity_vlan_rx_register,
+};
+
/**
- * velocity_intr - interrupt callback
- * @irq: interrupt number
- * @dev_instance: interrupting device
+ * velocity_init_info - init private data
+ * @pdev: PCI device
+ * @vptr: Velocity info
+ * @info: Board type
*
- * Called whenever an interrupt is generated by the velocity
- * adapter IRQ line. We may not be the source of the interrupt
- * and need to identify initially if we are, and if not exit as
- * efficiently as possible.
+ * Set up the initial velocity_info struct for the device that has been
+ * discovered.
*/
-
-static irqreturn_t velocity_intr(int irq, void *dev_instance)
+static void __devinit velocity_init_info(struct pci_dev *pdev,
+ struct velocity_info *vptr,
+ const struct velocity_info_tbl *info)
{
- struct net_device *dev = dev_instance;
- struct velocity_info *vptr = netdev_priv(dev);
- u32 isr_status;
- int max_count = 0;
-
-
- spin_lock(&vptr->lock);
- isr_status = mac_read_isr(vptr->mac_regs);
-
- /* Not us ? */
- if (isr_status == 0) {
- spin_unlock(&vptr->lock);
- return IRQ_NONE;
- }
-
- mac_disable_int(vptr->mac_regs);
-
- /*
- * Keep processing the ISR until we have completed
- * processing and the isr_status becomes zero
- */
-
- while (isr_status != 0) {
- mac_write_isr(vptr->mac_regs, isr_status);
- if (isr_status & (~(ISR_PRXI | ISR_PPRXI | ISR_PTXI | ISR_PPTXI)))
- velocity_error(vptr, isr_status);
- if (isr_status & (ISR_PRXI | ISR_PPRXI))
- max_count += velocity_rx_srv(vptr, isr_status);
- if (isr_status & (ISR_PTXI | ISR_PPTXI))
- max_count += velocity_tx_srv(vptr, isr_status);
- isr_status = mac_read_isr(vptr->mac_regs);
- if (max_count > vptr->options.int_works)
- {
- printk(KERN_WARNING "%s: excessive work at interrupt.\n",
- dev->name);
- max_count = 0;
- }
- }
- spin_unlock(&vptr->lock);
- mac_enable_int(vptr->mac_regs);
- return IRQ_HANDLED;
+ memset(vptr, 0, sizeof(struct velocity_info));
+ vptr->pdev = pdev;
+ vptr->chip_id = info->chip_id;
+ vptr->tx.numq = info->txqueue;
+ vptr->multicast_limit = MCAM_SIZE;
+ spin_lock_init(&vptr->lock);
+ INIT_LIST_HEAD(&vptr->list);
}
-
/**
- * velocity_set_multi - filter list change callback
- * @dev: network device
+ * velocity_get_pci_info - retrieve PCI info for device
+ * @vptr: velocity device
+ * @pdev: PCI device it matches
*
- * Called by the network layer when the filter lists need to change
- * for a velocity adapter. Reload the CAMs with the new address
- * filter ruleset.
+ * Retrieve the PCI configuration space data that interests us from
+ * the kernel PCI layer
*/
-
-static void velocity_set_multi(struct net_device *dev)
+static int __devinit velocity_get_pci_info(struct velocity_info *vptr, struct pci_dev *pdev)
{
- struct velocity_info *vptr = netdev_priv(dev);
- struct mac_regs __iomem * regs = vptr->mac_regs;
- u8 rx_mode;
- int i;
- struct dev_mc_list *mclist;
+ vptr->rev_id = pdev->revision;
- if (dev->flags & IFF_PROMISC) { /* Set promiscuous. */
- writel(0xffffffff, &regs->MARCAM[0]);
- writel(0xffffffff, &regs->MARCAM[4]);
- rx_mode = (RCR_AM | RCR_AB | RCR_PROM);
- } else if ((dev->mc_count > vptr->multicast_limit)
- || (dev->flags & IFF_ALLMULTI)) {
- writel(0xffffffff, &regs->MARCAM[0]);
- writel(0xffffffff, &regs->MARCAM[4]);
- rx_mode = (RCR_AM | RCR_AB);
- } else {
- int offset = MCAM_SIZE - vptr->multicast_limit;
- mac_get_cam_mask(regs, vptr->mCAMmask);
+ pci_set_master(pdev);
- for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; i++, mclist = mclist->next) {
- mac_set_cam(regs, i + offset, mclist->dmi_addr);
- vptr->mCAMmask[(offset + i) / 8] |= 1 << ((offset + i) & 7);
- }
+ vptr->ioaddr = pci_resource_start(pdev, 0);
+ vptr->memaddr = pci_resource_start(pdev, 1);
- mac_set_cam_mask(regs, vptr->mCAMmask);
- rx_mode = RCR_AM | RCR_AB | RCR_AP;
+ if (!(pci_resource_flags(pdev, 0) & IORESOURCE_IO)) {
+ dev_err(&pdev->dev,
+ "region #0 is not an I/O resource, aborting.\n");
+ return -EINVAL;
}
- if (dev->mtu > 1500)
- rx_mode |= RCR_AL;
- BYTE_REG_BITS_ON(rx_mode, &regs->RCR);
+ if ((pci_resource_flags(pdev, 1) & IORESOURCE_IO)) {
+ dev_err(&pdev->dev,
+ "region #1 is an I/O resource, aborting.\n");
+ return -EINVAL;
+ }
+ if (pci_resource_len(pdev, 1) < VELOCITY_IO_SIZE) {
+ dev_err(&pdev->dev, "region #1 is too small.\n");
+ return -EINVAL;
+ }
+ vptr->pdev = pdev;
+
+ return 0;
}
/**
- * velocity_get_status - statistics callback
- * @dev: network device
+ * velocity_print_info - per driver data
+ * @vptr: velocity
*
- * Callback from the network layer to allow driver statistics
- * to be resynchronized with hardware collected state. In the
- * case of the velocity we need to pull the MIB counters from
- * the hardware into the counters before letting the network
- * layer display them.
+ * Print per driver data as the kernel driver finds Velocity
+ * hardware
*/
-
-static struct net_device_stats *velocity_get_stats(struct net_device *dev)
+static void __devinit velocity_print_info(struct velocity_info *vptr)
{
- struct velocity_info *vptr = netdev_priv(dev);
-
- /* If the hardware is down, don't touch MII */
- if(!netif_running(dev))
- return &dev->stats;
-
- spin_lock_irq(&vptr->lock);
- velocity_update_hw_mibs(vptr);
- spin_unlock_irq(&vptr->lock);
-
- dev->stats.rx_packets = vptr->mib_counter[HW_MIB_ifRxAllPkts];
- dev->stats.rx_errors = vptr->mib_counter[HW_MIB_ifRxErrorPkts];
- dev->stats.rx_length_errors = vptr->mib_counter[HW_MIB_ifInRangeLengthErrors];
-
-// unsigned long rx_dropped; /* no space in linux buffers */
- dev->stats.collisions = vptr->mib_counter[HW_MIB_ifTxEtherCollisions];
- /* detailed rx_errors: */
-// unsigned long rx_length_errors;
-// unsigned long rx_over_errors; /* receiver ring buff overflow */
- dev->stats.rx_crc_errors = vptr->mib_counter[HW_MIB_ifRxPktCRCE];
-// unsigned long rx_frame_errors; /* recv'd frame alignment error */
-// unsigned long rx_fifo_errors; /* recv'r fifo overrun */
-// unsigned long rx_missed_errors; /* receiver missed packet */
-
- /* detailed tx_errors */
-// unsigned long tx_fifo_errors;
+ struct net_device *dev = vptr->dev;
- return &dev->stats;
+ printk(KERN_INFO "%s: %s\n", dev->name, get_chip_name(vptr->chip_id));
+ printk(KERN_INFO "%s: Ethernet Address: %2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X\n",
+ dev->name,
+ dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
+ dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]);
}
-
-/**
- * velocity_ioctl - ioctl entry point
- * @dev: network device
- * @rq: interface request ioctl
- * @cmd: command code
- *
- * Called when the user issues an ioctl request to the network
- * device in question. The velocity interface supports MII.
- */
-
-static int velocity_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+static u32 velocity_get_link(struct net_device *dev)
{
struct velocity_info *vptr = netdev_priv(dev);
- int ret;
-
- /* If we are asked for information and the device is power
- saving then we need to bring the device back up to talk to it */
-
- if (!netif_running(dev))
- pci_set_power_state(vptr->pdev, PCI_D0);
-
- switch (cmd) {
- case SIOCGMIIPHY: /* Get address of MII PHY in use. */
- case SIOCGMIIREG: /* Read MII PHY register. */
- case SIOCSMIIREG: /* Write to MII PHY register. */
- ret = velocity_mii_ioctl(dev, rq, cmd);
- break;
-
- default:
- ret = -EOPNOTSUPP;
- }
- if (!netif_running(dev))
- pci_set_power_state(vptr->pdev, PCI_D3hot);
-
-
- return ret;
+ struct mac_regs __iomem *regs = vptr->mac_regs;
+ return BYTE_REG_BITS_IS_ON(PHYSR0_LINKGD, &regs->PHYSR0) ? 1 : 0;
}
-/*
- * Definition for our device driver. The PCI layer interface
- * uses this to handle all our card discover and plugging
- */
-
-static struct pci_driver velocity_driver = {
- .name = VELOCITY_NAME,
- .id_table = velocity_id_table,
- .probe = velocity_found1,
- .remove = __devexit_p(velocity_remove1),
-#ifdef CONFIG_PM
- .suspend = velocity_suspend,
- .resume = velocity_resume,
-#endif
-};
/**
- * velocity_init_module - load time function
+ * velocity_found1 - set up discovered velocity card
+ * @pdev: PCI device
+ * @ent: PCI device table entry that matched
*
- * Called when the velocity module is loaded. The PCI driver
- * is registered with the PCI layer, and in turn will call
- * the probe functions for each velocity adapter installed
- * in the system.
+ * Configure a discovered adapter from scratch. Return a negative
+ * errno error code on failure paths.
*/
-
-static int __init velocity_init_module(void)
+static int __devinit velocity_found1(struct pci_dev *pdev, const struct pci_device_id *ent)
{
- int ret;
+ static int first = 1;
+ struct net_device *dev;
+ int i;
+ const char *drv_string;
+ const struct velocity_info_tbl *info = &chip_info_table[ent->driver_data];
+ struct velocity_info *vptr;
+ struct mac_regs __iomem *regs;
+ int ret = -ENOMEM;
- velocity_register_notifier();
- ret = pci_register_driver(&velocity_driver);
- if (ret < 0)
- velocity_unregister_notifier();
- return ret;
-}
+ /* FIXME: this driver, like almost all other ethernet drivers,
+ * can support more than MAX_UNITS.
+ */
+ if (velocity_nics >= MAX_UNITS) {
+ dev_notice(&pdev->dev, "already found %d NICs.\n",
+ velocity_nics);
+ return -ENODEV;
+ }
-/**
- * velocity_cleanup - module unload
- *
- * When the velocity hardware is unloaded this function is called.
- * It will clean up the notifiers and the unregister the PCI
- * driver interface for this hardware. This in turn cleans up
- * all discovered interfaces before returning from the function
- */
+ dev = alloc_etherdev(sizeof(struct velocity_info));
+ if (!dev) {
+ dev_err(&pdev->dev, "allocate net device failed.\n");
+ goto out;
+ }
-static void __exit velocity_cleanup_module(void)
-{
- velocity_unregister_notifier();
- pci_unregister_driver(&velocity_driver);
-}
+ /* Chain it all together */
-module_init(velocity_init_module);
-module_exit(velocity_cleanup_module);
+ SET_NETDEV_DEV(dev, &pdev->dev);
+ vptr = netdev_priv(dev);
-/*
- * MII access , media link mode setting functions
- */
+ if (first) {
+ printk(KERN_INFO "%s Ver. %s\n",
+ VELOCITY_FULL_DRV_NAM, VELOCITY_VERSION);
+ printk(KERN_INFO "Copyright (c) 2002, 2003 VIA Networking Technologies, Inc.\n");
+ printk(KERN_INFO "Copyright (c) 2004 Red Hat Inc.\n");
+ first = 0;
+ }
+ velocity_init_info(pdev, vptr, info);
-/**
- * mii_init - set up MII
- * @vptr: velocity adapter
- * @mii_status: links tatus
- *
- * Set up the PHY for the current link state.
- */
+ vptr->dev = dev;
-static void mii_init(struct velocity_info *vptr, u32 mii_status)
-{
- u16 BMCR;
+ dev->irq = pdev->irq;
- switch (PHYID_GET_PHY_ID(vptr->phy_id)) {
- case PHYID_CICADA_CS8201:
- /*
- * Reset to hardware default
- */
- MII_REG_BITS_OFF((ANAR_ASMDIR | ANAR_PAUSE), MII_REG_ANAR, vptr->mac_regs);
- /*
- * Turn on ECHODIS bit in NWay-forced full mode and turn it
- * off it in NWay-forced half mode for NWay-forced v.s.
- * legacy-forced issue.
- */
- if (vptr->mii_status & VELOCITY_DUPLEX_FULL)
- MII_REG_BITS_ON(TCSR_ECHODIS, MII_REG_TCSR, vptr->mac_regs);
- else
- MII_REG_BITS_OFF(TCSR_ECHODIS, MII_REG_TCSR, vptr->mac_regs);
- /*
- * Turn on Link/Activity LED enable bit for CIS8201
- */
- MII_REG_BITS_ON(PLED_LALBE, MII_REG_PLED, vptr->mac_regs);
- break;
- case PHYID_VT3216_32BIT:
- case PHYID_VT3216_64BIT:
- /*
- * Reset to hardware default
- */
- MII_REG_BITS_ON((ANAR_ASMDIR | ANAR_PAUSE), MII_REG_ANAR, vptr->mac_regs);
- /*
- * Turn on ECHODIS bit in NWay-forced full mode and turn it
- * off it in NWay-forced half mode for NWay-forced v.s.
- * legacy-forced issue
- */
- if (vptr->mii_status & VELOCITY_DUPLEX_FULL)
- MII_REG_BITS_ON(TCSR_ECHODIS, MII_REG_TCSR, vptr->mac_regs);
- else
- MII_REG_BITS_OFF(TCSR_ECHODIS, MII_REG_TCSR, vptr->mac_regs);
- break;
+ ret = pci_enable_device(pdev);
+ if (ret < 0)
+ goto err_free_dev;
- case PHYID_MARVELL_1000:
- case PHYID_MARVELL_1000S:
- /*
- * Assert CRS on Transmit
- */
- MII_REG_BITS_ON(PSCR_ACRSTX, MII_REG_PSCR, vptr->mac_regs);
- /*
- * Reset to hardware default
- */
- MII_REG_BITS_ON((ANAR_ASMDIR | ANAR_PAUSE), MII_REG_ANAR, vptr->mac_regs);
- break;
- default:
- ;
- }
- velocity_mii_read(vptr->mac_regs, MII_REG_BMCR, &BMCR);
- if (BMCR & BMCR_ISO) {
- BMCR &= ~BMCR_ISO;
- velocity_mii_write(vptr->mac_regs, MII_REG_BMCR, BMCR);
+ ret = velocity_get_pci_info(vptr, pdev);
+ if (ret < 0) {
+ /* error message already printed */
+ goto err_disable;
}
-}
-/**
- * safe_disable_mii_autopoll - autopoll off
- * @regs: velocity registers
- *
- * Turn off the autopoll and wait for it to disable on the chip
- */
-
-static void safe_disable_mii_autopoll(struct mac_regs __iomem * regs)
-{
- u16 ww;
-
- /* turn off MAUTO */
- writeb(0, &regs->MIICR);
- for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
- udelay(1);
- if (BYTE_REG_BITS_IS_ON(MIISR_MIDLE, &regs->MIISR))
- break;
+ ret = pci_request_regions(pdev, VELOCITY_NAME);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "No PCI resources.\n");
+ goto err_disable;
}
-}
-
-/**
- * enable_mii_autopoll - turn on autopolling
- * @regs: velocity registers
- *
- * Enable the MII link status autopoll feature on the Velocity
- * hardware. Wait for it to enable.
- */
-static void enable_mii_autopoll(struct mac_regs __iomem * regs)
-{
- int ii;
+ regs = ioremap(vptr->memaddr, VELOCITY_IO_SIZE);
+ if (regs == NULL) {
+ ret = -EIO;
+ goto err_release_res;
+ }
- writeb(0, &(regs->MIICR));
- writeb(MIIADR_SWMPL, &regs->MIIADR);
+ vptr->mac_regs = regs;
- for (ii = 0; ii < W_MAX_TIMEOUT; ii++) {
- udelay(1);
- if (BYTE_REG_BITS_IS_ON(MIISR_MIDLE, &regs->MIISR))
- break;
- }
+ mac_wol_reset(regs);
- writeb(MIICR_MAUTO, &regs->MIICR);
+ dev->base_addr = vptr->ioaddr;
- for (ii = 0; ii < W_MAX_TIMEOUT; ii++) {
- udelay(1);
- if (!BYTE_REG_BITS_IS_ON(MIISR_MIDLE, &regs->MIISR))
- break;
- }
+ for (i = 0; i < 6; i++)
+ dev->dev_addr[i] = readb(&regs->PAR[i]);
-}
-/**
- * velocity_mii_read - read MII data
- * @regs: velocity registers
- * @index: MII register index
- * @data: buffer for received data
- *
- * Perform a single read of an MII 16bit register. Returns zero
- * on success or -ETIMEDOUT if the PHY did not respond.
- */
+ drv_string = dev_driver_string(&pdev->dev);
-static int velocity_mii_read(struct mac_regs __iomem *regs, u8 index, u16 *data)
-{
- u16 ww;
+ velocity_get_options(&vptr->options, velocity_nics, drv_string);
/*
- * Disable MIICR_MAUTO, so that mii addr can be set normally
+ * Mask out the options cannot be set to the chip
*/
- safe_disable_mii_autopoll(regs);
-
- writeb(index, &regs->MIIADR);
- BYTE_REG_BITS_ON(MIICR_RCMD, &regs->MIICR);
+ vptr->options.flags &= info->flags;
- for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
- if (!(readb(&regs->MIICR) & MIICR_RCMD))
- break;
- }
+ /*
+ * Enable the chip specified capbilities
+ */
- *data = readw(&regs->MIIDATA);
+ vptr->flags = vptr->options.flags | (info->flags & 0xFF000000UL);
- enable_mii_autopoll(regs);
- if (ww == W_MAX_TIMEOUT)
- return -ETIMEDOUT;
- return 0;
-}
+ vptr->wol_opts = vptr->options.wol_opts;
+ vptr->flags |= VELOCITY_FLAGS_WOL_ENABLED;
-/**
- * velocity_mii_write - write MII data
- * @regs: velocity registers
- * @index: MII register index
- * @data: 16bit data for the MII register
- *
- * Perform a single write to an MII 16bit register. Returns zero
- * on success or -ETIMEDOUT if the PHY did not respond.
- */
+ vptr->phy_id = MII_GET_PHY_ID(vptr->mac_regs);
-static int velocity_mii_write(struct mac_regs __iomem *regs, u8 mii_addr, u16 data)
-{
- u16 ww;
+ dev->irq = pdev->irq;
+ dev->netdev_ops = &velocity_netdev_ops;
+ dev->ethtool_ops = &velocity_ethtool_ops;
- /*
- * Disable MIICR_MAUTO, so that mii addr can be set normally
- */
- safe_disable_mii_autopoll(regs);
+ dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_FILTER |
+ NETIF_F_HW_VLAN_RX;
- /* MII reg offset */
- writeb(mii_addr, &regs->MIIADR);
- /* set MII data */
- writew(data, &regs->MIIDATA);
+ if (vptr->flags & VELOCITY_FLAGS_TX_CSUM)
+ dev->features |= NETIF_F_IP_CSUM;
- /* turn on MIICR_WCMD */
- BYTE_REG_BITS_ON(MIICR_WCMD, &regs->MIICR);
+ ret = register_netdev(dev);
+ if (ret < 0)
+ goto err_iounmap;
- /* W_MAX_TIMEOUT is the timeout period */
- for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
- udelay(5);
- if (!(readb(&regs->MIICR) & MIICR_WCMD))
- break;
+ if (!velocity_get_link(dev)) {
+ netif_carrier_off(dev);
+ vptr->mii_status |= VELOCITY_LINK_FAIL;
}
- enable_mii_autopoll(regs);
- if (ww == W_MAX_TIMEOUT)
- return -ETIMEDOUT;
- return 0;
-}
+ velocity_print_info(vptr);
+ pci_set_drvdata(pdev, dev);
-/**
- * velocity_get_opt_media_mode - get media selection
- * @vptr: velocity adapter
- *
- * Get the media mode stored in EEPROM or module options and load
- * mii_status accordingly. The requested link state information
- * is also returned.
- */
+ /* and leave the chip powered down */
-static u32 velocity_get_opt_media_mode(struct velocity_info *vptr)
-{
- u32 status = 0;
+ pci_set_power_state(pdev, PCI_D3hot);
+#ifdef CONFIG_PM
+ {
+ unsigned long flags;
- switch (vptr->options.spd_dpx) {
- case SPD_DPX_AUTO:
- status = VELOCITY_AUTONEG_ENABLE;
- break;
- case SPD_DPX_100_FULL:
- status = VELOCITY_SPEED_100 | VELOCITY_DUPLEX_FULL;
- break;
- case SPD_DPX_10_FULL:
- status = VELOCITY_SPEED_10 | VELOCITY_DUPLEX_FULL;
- break;
- case SPD_DPX_100_HALF:
- status = VELOCITY_SPEED_100;
- break;
- case SPD_DPX_10_HALF:
- status = VELOCITY_SPEED_10;
- break;
+ spin_lock_irqsave(&velocity_dev_list_lock, flags);
+ list_add(&vptr->list, &velocity_dev_list);
+ spin_unlock_irqrestore(&velocity_dev_list_lock, flags);
}
- vptr->mii_status = status;
- return status;
-}
-
-/**
- * mii_set_auto_on - autonegotiate on
- * @vptr: velocity
- *
- * Enable autonegotation on this interface
- */
+#endif
+ velocity_nics++;
+out:
+ return ret;
-static void mii_set_auto_on(struct velocity_info *vptr)
-{
- if (MII_REG_BITS_IS_ON(BMCR_AUTO, MII_REG_BMCR, vptr->mac_regs))
- MII_REG_BITS_ON(BMCR_REAUTO, MII_REG_BMCR, vptr->mac_regs);
- else
- MII_REG_BITS_ON(BMCR_AUTO, MII_REG_BMCR, vptr->mac_regs);
+err_iounmap:
+ iounmap(regs);
+err_release_res:
+ pci_release_regions(pdev);
+err_disable:
+ pci_disable_device(pdev);
+err_free_dev:
+ free_netdev(dev);
+ goto out;
}
-/*
-static void mii_set_auto_off(struct velocity_info * vptr)
-{
- MII_REG_BITS_OFF(BMCR_AUTO, MII_REG_BMCR, vptr->mac_regs);
-}
-*/
-
+#ifdef CONFIG_PM
/**
- * set_mii_flow_control - flow control setup
- * @vptr: velocity interface
+ * wol_calc_crc - WOL CRC
+ * @pattern: data pattern
+ * @mask_pattern: mask
*
- * Set up the flow control on this interface according to
- * the supplied user/eeprom options.
+ * Compute the wake on lan crc hashes for the packet header
+ * we are interested in.
*/
-
-static void set_mii_flow_control(struct velocity_info *vptr)
+static u16 wol_calc_crc(int size, u8 *pattern, u8 *mask_pattern)
{
- /*Enable or Disable PAUSE in ANAR */
- switch (vptr->options.flow_cntl) {
- case FLOW_CNTL_TX:
- MII_REG_BITS_OFF(ANAR_PAUSE, MII_REG_ANAR, vptr->mac_regs);
- MII_REG_BITS_ON(ANAR_ASMDIR, MII_REG_ANAR, vptr->mac_regs);
- break;
+ u16 crc = 0xFFFF;
+ u8 mask;
+ int i, j;
- case FLOW_CNTL_RX:
- MII_REG_BITS_ON(ANAR_PAUSE, MII_REG_ANAR, vptr->mac_regs);
- MII_REG_BITS_ON(ANAR_ASMDIR, MII_REG_ANAR, vptr->mac_regs);
- break;
+ for (i = 0; i < size; i++) {
+ mask = mask_pattern[i];
- case FLOW_CNTL_TX_RX:
- MII_REG_BITS_ON(ANAR_PAUSE, MII_REG_ANAR, vptr->mac_regs);
- MII_REG_BITS_ON(ANAR_ASMDIR, MII_REG_ANAR, vptr->mac_regs);
- break;
+ /* Skip this loop if the mask equals to zero */
+ if (mask == 0x00)
+ continue;
- case FLOW_CNTL_DISABLE:
- MII_REG_BITS_OFF(ANAR_PAUSE, MII_REG_ANAR, vptr->mac_regs);
- MII_REG_BITS_OFF(ANAR_ASMDIR, MII_REG_ANAR, vptr->mac_regs);
- break;
- default:
- break;
+ for (j = 0; j < 8; j++) {
+ if ((mask & 0x01) == 0) {
+ mask >>= 1;
+ continue;
+ }
+ mask >>= 1;
+ crc = crc_ccitt(crc, &(pattern[i * 8 + j]), 1);
+ }
}
+ /* Finally, invert the result once to get the correct data */
+ crc = ~crc;
+ return bitrev32(crc) >> 16;
}
/**
- * velocity_set_media_mode - set media mode
- * @mii_status: old MII link state
+ * velocity_set_wol - set up for wake on lan
+ * @vptr: velocity to set WOL status on
*
- * Check the media link state and configure the flow control
- * PHY and also velocity hardware setup accordingly. In particular
- * we need to set up CD polling and frame bursting.
+ * Set a card up for wake on lan either by unicast or by
+ * ARP packet.
+ *
+ * FIXME: check static buffer is safe here
*/
-
-static int velocity_set_media_mode(struct velocity_info *vptr, u32 mii_status)
+static int velocity_set_wol(struct velocity_info *vptr)
{
- u32 curr_status;
- struct mac_regs __iomem * regs = vptr->mac_regs;
+ struct mac_regs __iomem *regs = vptr->mac_regs;
+ static u8 buf[256];
+ int i;
- vptr->mii_status = mii_check_media_mode(vptr->mac_regs);
- curr_status = vptr->mii_status & (~VELOCITY_LINK_FAIL);
+ static u32 mask_pattern[2][4] = {
+ {0x00203000, 0x000003C0, 0x00000000, 0x0000000}, /* ARP */
+ {0xfffff000, 0xffffffff, 0xffffffff, 0x000ffff} /* Magic Packet */
+ };
- /* Set mii link status */
- set_mii_flow_control(vptr);
+ writew(0xFFFF, &regs->WOLCRClr);
+ writeb(WOLCFG_SAB | WOLCFG_SAM, &regs->WOLCFGSet);
+ writew(WOLCR_MAGIC_EN, &regs->WOLCRSet);
/*
- Check if new status is consisent with current status
- if (((mii_status & curr_status) & VELOCITY_AUTONEG_ENABLE)
- || (mii_status==curr_status)) {
- vptr->mii_status=mii_check_media_mode(vptr->mac_regs);
- vptr->mii_status=check_connection_type(vptr->mac_regs);
- VELOCITY_PRT(MSG_LEVEL_INFO, "Velocity link no change\n");
- return 0;
- }
+ if (vptr->wol_opts & VELOCITY_WOL_PHY)
+ writew((WOLCR_LINKON_EN|WOLCR_LINKOFF_EN), &regs->WOLCRSet);
*/
- if (PHYID_GET_PHY_ID(vptr->phy_id) == PHYID_CICADA_CS8201) {
- MII_REG_BITS_ON(AUXCR_MDPPS, MII_REG_AUXCR, vptr->mac_regs);
- }
+ if (vptr->wol_opts & VELOCITY_WOL_UCAST)
+ writew(WOLCR_UNICAST_EN, &regs->WOLCRSet);
- /*
- * If connection type is AUTO
- */
- if (mii_status & VELOCITY_AUTONEG_ENABLE) {
- VELOCITY_PRT(MSG_LEVEL_INFO, "Velocity is AUTO mode\n");
- /* clear force MAC mode bit */
- BYTE_REG_BITS_OFF(CHIPGCR_FCMODE, &regs->CHIPGCR);
- /* set duplex mode of MAC according to duplex mode of MII */
- MII_REG_BITS_ON(ANAR_TXFD | ANAR_TX | ANAR_10FD | ANAR_10, MII_REG_ANAR, vptr->mac_regs);
- MII_REG_BITS_ON(G1000CR_1000FD | G1000CR_1000, MII_REG_G1000CR, vptr->mac_regs);
- MII_REG_BITS_ON(BMCR_SPEED1G, MII_REG_BMCR, vptr->mac_regs);
+ if (vptr->wol_opts & VELOCITY_WOL_ARP) {
+ struct arp_packet *arp = (struct arp_packet *) buf;
+ u16 crc;
+ memset(buf, 0, sizeof(struct arp_packet) + 7);
- /* enable AUTO-NEGO mode */
- mii_set_auto_on(vptr);
- } else {
- u16 ANAR;
- u8 CHIPGCR;
+ for (i = 0; i < 4; i++)
+ writel(mask_pattern[0][i], &regs->ByteMask[0][i]);
- /*
- * 1. if it's 3119, disable frame bursting in halfduplex mode
- * and enable it in fullduplex mode
- * 2. set correct MII/GMII and half/full duplex mode in CHIPGCR
- * 3. only enable CD heart beat counter in 10HD mode
- */
+ arp->type = htons(ETH_P_ARP);
+ arp->ar_op = htons(1);
- /* set force MAC mode bit */
- BYTE_REG_BITS_ON(CHIPGCR_FCMODE, &regs->CHIPGCR);
+ memcpy(arp->ar_tip, vptr->ip_addr, 4);
- CHIPGCR = readb(&regs->CHIPGCR);
- CHIPGCR &= ~CHIPGCR_FCGMII;
+ crc = wol_calc_crc((sizeof(struct arp_packet) + 7) / 8, buf,
+ (u8 *) & mask_pattern[0][0]);
- if (mii_status & VELOCITY_DUPLEX_FULL) {
- CHIPGCR |= CHIPGCR_FCFDX;
- writeb(CHIPGCR, &regs->CHIPGCR);
- VELOCITY_PRT(MSG_LEVEL_INFO, "set Velocity to forced full mode\n");
- if (vptr->rev_id < REV_ID_VT3216_A0)
- BYTE_REG_BITS_OFF(TCR_TB2BDIS, &regs->TCR);
- } else {
- CHIPGCR &= ~CHIPGCR_FCFDX;
- VELOCITY_PRT(MSG_LEVEL_INFO, "set Velocity to forced half mode\n");
- writeb(CHIPGCR, &regs->CHIPGCR);
- if (vptr->rev_id < REV_ID_VT3216_A0)
- BYTE_REG_BITS_ON(TCR_TB2BDIS, &regs->TCR);
- }
+ writew(crc, &regs->PatternCRC[0]);
+ writew(WOLCR_ARP_EN, &regs->WOLCRSet);
+ }
+
+ BYTE_REG_BITS_ON(PWCFG_WOLTYPE, &regs->PWCFGSet);
+ BYTE_REG_BITS_ON(PWCFG_LEGACY_WOLEN, &regs->PWCFGSet);
+
+ writew(0x0FFF, &regs->WOLSRClr);
+
+ if (vptr->mii_status & VELOCITY_AUTONEG_ENABLE) {
+ if (PHYID_GET_PHY_ID(vptr->phy_id) == PHYID_CICADA_CS8201)
+ MII_REG_BITS_ON(AUXCR_MDPPS, MII_REG_AUXCR, vptr->mac_regs);
MII_REG_BITS_OFF(G1000CR_1000FD | G1000CR_1000, MII_REG_G1000CR, vptr->mac_regs);
+ }
- if (!(mii_status & VELOCITY_DUPLEX_FULL) && (mii_status & VELOCITY_SPEED_10)) {
- BYTE_REG_BITS_OFF(TESTCFG_HBDIS, &regs->TESTCFG);
- } else {
- BYTE_REG_BITS_ON(TESTCFG_HBDIS, &regs->TESTCFG);
- }
- /* MII_REG_BITS_OFF(BMCR_SPEED1G, MII_REG_BMCR, vptr->mac_regs); */
- velocity_mii_read(vptr->mac_regs, MII_REG_ANAR, &ANAR);
- ANAR &= (~(ANAR_TXFD | ANAR_TX | ANAR_10FD | ANAR_10));
- if (mii_status & VELOCITY_SPEED_100) {
- if (mii_status & VELOCITY_DUPLEX_FULL)
- ANAR |= ANAR_TXFD;
- else
- ANAR |= ANAR_TX;
- } else {
- if (mii_status & VELOCITY_DUPLEX_FULL)
- ANAR |= ANAR_10FD;
- else
- ANAR |= ANAR_10;
- }
- velocity_mii_write(vptr->mac_regs, MII_REG_ANAR, ANAR);
- /* enable AUTO-NEGO mode */
- mii_set_auto_on(vptr);
- /* MII_REG_BITS_ON(BMCR_AUTO, MII_REG_BMCR, vptr->mac_regs); */
+ if (vptr->mii_status & VELOCITY_SPEED_1000)
+ MII_REG_BITS_ON(BMCR_REAUTO, MII_REG_BMCR, vptr->mac_regs);
+
+ BYTE_REG_BITS_ON(CHIPGCR_FCMODE, &regs->CHIPGCR);
+
+ {
+ u8 GCR;
+ GCR = readb(&regs->CHIPGCR);
+ GCR = (GCR & ~CHIPGCR_FCGMII) | CHIPGCR_FCFDX;
+ writeb(GCR, &regs->CHIPGCR);
}
- /* vptr->mii_status=mii_check_media_mode(vptr->mac_regs); */
- /* vptr->mii_status=check_connection_type(vptr->mac_regs); */
- return VELOCITY_LINK_CHANGE;
+
+ BYTE_REG_BITS_OFF(ISR_PWEI, &regs->ISR);
+ /* Turn on SWPTAG just before entering power mode */
+ BYTE_REG_BITS_ON(STICKHW_SWPTAG, &regs->STICKHW);
+ /* Go to bed ..... */
+ BYTE_REG_BITS_ON((STICKHW_DS1 | STICKHW_DS0), &regs->STICKHW);
+
+ return 0;
}
/**
- * mii_check_media_mode - check media state
- * @regs: velocity registers
+ * velocity_save_context - save registers
+ * @vptr: velocity
+ * @context: buffer for stored context
*
- * Check the current MII status and determine the link status
- * accordingly
+ * Retrieve the current configuration from the velocity hardware
+ * and stash it in the context structure, for use by the context
+ * restore functions. This allows us to save things we need across
+ * power down states
*/
-
-static u32 mii_check_media_mode(struct mac_regs __iomem * regs)
+static void velocity_save_context(struct velocity_info *vptr, struct velocity_context *context)
{
- u32 status = 0;
- u16 ANAR;
+ struct mac_regs __iomem *regs = vptr->mac_regs;
+ u16 i;
+ u8 __iomem *ptr = (u8 __iomem *)regs;
- if (!MII_REG_BITS_IS_ON(BMSR_LNK, MII_REG_BMSR, regs))
- status |= VELOCITY_LINK_FAIL;
+ for (i = MAC_REG_PAR; i < MAC_REG_CR0_CLR; i += 4)
+ *((u32 *) (context->mac_reg + i)) = readl(ptr + i);
- if (MII_REG_BITS_IS_ON(G1000CR_1000FD, MII_REG_G1000CR, regs))
- status |= VELOCITY_SPEED_1000 | VELOCITY_DUPLEX_FULL;
- else if (MII_REG_BITS_IS_ON(G1000CR_1000, MII_REG_G1000CR, regs))
- status |= (VELOCITY_SPEED_1000);
- else {
- velocity_mii_read(regs, MII_REG_ANAR, &ANAR);
- if (ANAR & ANAR_TXFD)
- status |= (VELOCITY_SPEED_100 | VELOCITY_DUPLEX_FULL);
- else if (ANAR & ANAR_TX)
- status |= VELOCITY_SPEED_100;
- else if (ANAR & ANAR_10FD)
- status |= (VELOCITY_SPEED_10 | VELOCITY_DUPLEX_FULL);
- else
- status |= (VELOCITY_SPEED_10);
- }
+ for (i = MAC_REG_MAR; i < MAC_REG_TDCSR_CLR; i += 4)
+ *((u32 *) (context->mac_reg + i)) = readl(ptr + i);
- if (MII_REG_BITS_IS_ON(BMCR_AUTO, MII_REG_BMCR, regs)) {
- velocity_mii_read(regs, MII_REG_ANAR, &ANAR);
- if ((ANAR & (ANAR_TXFD | ANAR_TX | ANAR_10FD | ANAR_10))
- == (ANAR_TXFD | ANAR_TX | ANAR_10FD | ANAR_10)) {
- if (MII_REG_BITS_IS_ON(G1000CR_1000 | G1000CR_1000FD, MII_REG_G1000CR, regs))
- status |= VELOCITY_AUTONEG_ENABLE;
- }
- }
+ for (i = MAC_REG_RDBASE_LO; i < MAC_REG_FIFO_TEST0; i += 4)
+ *((u32 *) (context->mac_reg + i)) = readl(ptr + i);
- return status;
}
-static u32 check_connection_type(struct mac_regs __iomem * regs)
+static int velocity_suspend(struct pci_dev *pdev, pm_message_t state)
{
- u32 status = 0;
- u8 PHYSR0;
- u16 ANAR;
- PHYSR0 = readb(&regs->PHYSR0);
-
- /*
- if (!(PHYSR0 & PHYSR0_LINKGD))
- status|=VELOCITY_LINK_FAIL;
- */
+ struct net_device *dev = pci_get_drvdata(pdev);
+ struct velocity_info *vptr = netdev_priv(dev);
+ unsigned long flags;
- if (PHYSR0 & PHYSR0_FDPX)
- status |= VELOCITY_DUPLEX_FULL;
+ if (!netif_running(vptr->dev))
+ return 0;
- if (PHYSR0 & PHYSR0_SPDG)
- status |= VELOCITY_SPEED_1000;
- else if (PHYSR0 & PHYSR0_SPD10)
- status |= VELOCITY_SPEED_10;
- else
- status |= VELOCITY_SPEED_100;
+ netif_device_detach(vptr->dev);
- if (MII_REG_BITS_IS_ON(BMCR_AUTO, MII_REG_BMCR, regs)) {
- velocity_mii_read(regs, MII_REG_ANAR, &ANAR);
- if ((ANAR & (ANAR_TXFD | ANAR_TX | ANAR_10FD | ANAR_10))
- == (ANAR_TXFD | ANAR_TX | ANAR_10FD | ANAR_10)) {
- if (MII_REG_BITS_IS_ON(G1000CR_1000 | G1000CR_1000FD, MII_REG_G1000CR, regs))
- status |= VELOCITY_AUTONEG_ENABLE;
- }
+ spin_lock_irqsave(&vptr->lock, flags);
+ pci_save_state(pdev);
+#ifdef ETHTOOL_GWOL
+ if (vptr->flags & VELOCITY_FLAGS_WOL_ENABLED) {
+ velocity_get_ip(vptr);
+ velocity_save_context(vptr, &vptr->context);
+ velocity_shutdown(vptr);
+ velocity_set_wol(vptr);
+ pci_enable_wake(pdev, PCI_D3hot, 1);
+ pci_set_power_state(pdev, PCI_D3hot);
+ } else {
+ velocity_save_context(vptr, &vptr->context);
+ velocity_shutdown(vptr);
+ pci_disable_device(pdev);
+ pci_set_power_state(pdev, pci_choose_state(pdev, state));
}
-
- return status;
+#else
+ pci_set_power_state(pdev, pci_choose_state(pdev, state));
+#endif
+ spin_unlock_irqrestore(&vptr->lock, flags);
+ return 0;
}
/**
- * enable_flow_control_ability - flow control
- * @vptr: veloity to configure
+ * velocity_restore_context - restore registers
+ * @vptr: velocity
+ * @context: buffer for stored context
*
- * Set up flow control according to the flow control options
- * determined by the eeprom/configuration.
+ * Reload the register configuration from the velocity context
+ * created by velocity_save_context.
*/
-
-static void enable_flow_control_ability(struct velocity_info *vptr)
+static void velocity_restore_context(struct velocity_info *vptr, struct velocity_context *context)
{
+ struct mac_regs __iomem *regs = vptr->mac_regs;
+ int i;
+ u8 __iomem *ptr = (u8 __iomem *)regs;
- struct mac_regs __iomem * regs = vptr->mac_regs;
+ for (i = MAC_REG_PAR; i < MAC_REG_CR0_SET; i += 4)
+ writel(*((u32 *) (context->mac_reg + i)), ptr + i);
- switch (vptr->options.flow_cntl) {
+ /* Just skip cr0 */
+ for (i = MAC_REG_CR1_SET; i < MAC_REG_CR0_CLR; i++) {
+ /* Clear */
+ writeb(~(*((u8 *) (context->mac_reg + i))), ptr + i + 4);
+ /* Set */
+ writeb(*((u8 *) (context->mac_reg + i)), ptr + i);
+ }
- case FLOW_CNTL_DEFAULT:
- if (BYTE_REG_BITS_IS_ON(PHYSR0_RXFLC, &regs->PHYSR0))
- writel(CR0_FDXRFCEN, &regs->CR0Set);
- else
- writel(CR0_FDXRFCEN, &regs->CR0Clr);
+ for (i = MAC_REG_MAR; i < MAC_REG_IMR; i += 4)
+ writel(*((u32 *) (context->mac_reg + i)), ptr + i);
- if (BYTE_REG_BITS_IS_ON(PHYSR0_TXFLC, &regs->PHYSR0))
- writel(CR0_FDXTFCEN, &regs->CR0Set);
- else
- writel(CR0_FDXTFCEN, &regs->CR0Clr);
- break;
+ for (i = MAC_REG_RDBASE_LO; i < MAC_REG_FIFO_TEST0; i += 4)
+ writel(*((u32 *) (context->mac_reg + i)), ptr + i);
- case FLOW_CNTL_TX:
- writel(CR0_FDXTFCEN, &regs->CR0Set);
- writel(CR0_FDXRFCEN, &regs->CR0Clr);
- break;
+ for (i = MAC_REG_TDCSR_SET; i <= MAC_REG_RDCSR_SET; i++)
+ writeb(*((u8 *) (context->mac_reg + i)), ptr + i);
+}
- case FLOW_CNTL_RX:
- writel(CR0_FDXRFCEN, &regs->CR0Set);
- writel(CR0_FDXTFCEN, &regs->CR0Clr);
- break;
+static int velocity_resume(struct pci_dev *pdev)
+{
+ struct net_device *dev = pci_get_drvdata(pdev);
+ struct velocity_info *vptr = netdev_priv(dev);
+ unsigned long flags;
+ int i;
- case FLOW_CNTL_TX_RX:
- writel(CR0_FDXTFCEN, &regs->CR0Set);
- writel(CR0_FDXRFCEN, &regs->CR0Set);
- break;
+ if (!netif_running(vptr->dev))
+ return 0;
- case FLOW_CNTL_DISABLE:
- writel(CR0_FDXRFCEN, &regs->CR0Clr);
- writel(CR0_FDXTFCEN, &regs->CR0Clr);
- break;
+ pci_set_power_state(pdev, PCI_D0);
+ pci_enable_wake(pdev, 0, 0);
+ pci_restore_state(pdev);
- default:
- break;
+ mac_wol_reset(vptr->mac_regs);
+
+ spin_lock_irqsave(&vptr->lock, flags);
+ velocity_restore_context(vptr, &vptr->context);
+ velocity_init_registers(vptr, VELOCITY_INIT_WOL);
+ mac_disable_int(vptr->mac_regs);
+
+ velocity_tx_srv(vptr, 0);
+
+ for (i = 0; i < vptr->tx.numq; i++) {
+ if (vptr->tx.used[i])
+ mac_tx_queue_wake(vptr->mac_regs, i);
}
+ mac_enable_int(vptr->mac_regs);
+ spin_unlock_irqrestore(&vptr->lock, flags);
+ netif_device_attach(vptr->dev);
+
+ return 0;
}
+#endif
+
+/*
+ * Definition for our device driver. The PCI layer interface
+ * uses this to handle all our card discover and plugging
+ */
+static struct pci_driver velocity_driver = {
+ .name = VELOCITY_NAME,
+ .id_table = velocity_id_table,
+ .probe = velocity_found1,
+ .remove = __devexit_p(velocity_remove1),
+#ifdef CONFIG_PM
+ .suspend = velocity_suspend,
+ .resume = velocity_resume,
+#endif
+};
/**
@@ -2991,7 +3081,6 @@ static void enable_flow_control_ability(struct velocity_info *vptr)
* Called before an ethtool operation. We need to make sure the
* chip is out of D3 state before we poke at it.
*/
-
static int velocity_ethtool_up(struct net_device *dev)
{
struct velocity_info *vptr = netdev_priv(dev);
@@ -3007,7 +3096,6 @@ static int velocity_ethtool_up(struct net_device *dev)
* Called after an ethtool operation. Restore the chip back to D3
* state if it isn't running.
*/
-
static void velocity_ethtool_down(struct net_device *dev)
{
struct velocity_info *vptr = netdev_priv(dev);
@@ -3018,7 +3106,7 @@ static void velocity_ethtool_down(struct net_device *dev)
static int velocity_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
{
struct velocity_info *vptr = netdev_priv(dev);
- struct mac_regs __iomem * regs = vptr->mac_regs;
+ struct mac_regs __iomem *regs = vptr->mac_regs;
u32 status;
status = check_connection_type(vptr->mac_regs);
@@ -3072,13 +3160,6 @@ static int velocity_set_settings(struct net_device *dev, struct ethtool_cmd *cmd
return ret;
}
-static u32 velocity_get_link(struct net_device *dev)
-{
- struct velocity_info *vptr = netdev_priv(dev);
- struct mac_regs __iomem * regs = vptr->mac_regs;
- return BYTE_REG_BITS_IS_ON(PHYSR0_LINKGD, &regs->PHYSR0) ? 1 : 0;
-}
-
static void velocity_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
{
struct velocity_info *vptr = netdev_priv(dev);
@@ -3157,338 +3238,86 @@ static const struct ethtool_ops velocity_ethtool_ops = {
.complete = velocity_ethtool_down
};
-/**
- * velocity_mii_ioctl - MII ioctl handler
- * @dev: network device
- * @ifr: the ifreq block for the ioctl
- * @cmd: the command
- *
- * Process MII requests made via ioctl from the network layer. These
- * are used by tools like kudzu to interrogate the link state of the
- * hardware
- */
-
-static int velocity_mii_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+#ifdef CONFIG_PM
+#ifdef CONFIG_INET
+static int velocity_netdev_event(struct notifier_block *nb, unsigned long notification, void *ptr)
{
- struct velocity_info *vptr = netdev_priv(dev);
- struct mac_regs __iomem * regs = vptr->mac_regs;
+ struct in_ifaddr *ifa = (struct in_ifaddr *) ptr;
+ struct net_device *dev = ifa->ifa_dev->dev;
+ struct velocity_info *vptr;
unsigned long flags;
- struct mii_ioctl_data *miidata = if_mii(ifr);
- int err;
- switch (cmd) {
- case SIOCGMIIPHY:
- miidata->phy_id = readb(&regs->MIIADR) & 0x1f;
- break;
- case SIOCGMIIREG:
- if (!capable(CAP_NET_ADMIN))
- return -EPERM;
- if(velocity_mii_read(vptr->mac_regs, miidata->reg_num & 0x1f, &(miidata->val_out)) < 0)
- return -ETIMEDOUT;
- break;
- case SIOCSMIIREG:
- if (!capable(CAP_NET_ADMIN))
- return -EPERM;
- spin_lock_irqsave(&vptr->lock, flags);
- err = velocity_mii_write(vptr->mac_regs, miidata->reg_num & 0x1f, miidata->val_in);
- spin_unlock_irqrestore(&vptr->lock, flags);
- check_connection_type(vptr->mac_regs);
- if(err)
- return err;
- break;
- default:
- return -EOPNOTSUPP;
+ if (dev_net(dev) != &init_net)
+ return NOTIFY_DONE;
+
+ spin_lock_irqsave(&velocity_dev_list_lock, flags);
+ list_for_each_entry(vptr, &velocity_dev_list, list) {
+ if (vptr->dev == dev) {
+ velocity_get_ip(vptr);
+ break;
+ }
}
- return 0;
-}
+ spin_unlock_irqrestore(&velocity_dev_list_lock, flags);
-#ifdef CONFIG_PM
+ return NOTIFY_DONE;
+}
+#endif /* CONFIG_INET */
+#endif /* CONFIG_PM */
-/**
- * velocity_save_context - save registers
- * @vptr: velocity
- * @context: buffer for stored context
- *
- * Retrieve the current configuration from the velocity hardware
- * and stash it in the context structure, for use by the context
- * restore functions. This allows us to save things we need across
- * power down states
- */
+#if defined(CONFIG_PM) && defined(CONFIG_INET)
+static struct notifier_block velocity_inetaddr_notifier = {
+ .notifier_call = velocity_netdev_event,
+};
-static void velocity_save_context(struct velocity_info *vptr, struct velocity_context * context)
+static void velocity_register_notifier(void)
{
- struct mac_regs __iomem * regs = vptr->mac_regs;
- u16 i;
- u8 __iomem *ptr = (u8 __iomem *)regs;
-
- for (i = MAC_REG_PAR; i < MAC_REG_CR0_CLR; i += 4)
- *((u32 *) (context->mac_reg + i)) = readl(ptr + i);
-
- for (i = MAC_REG_MAR; i < MAC_REG_TDCSR_CLR; i += 4)
- *((u32 *) (context->mac_reg + i)) = readl(ptr + i);
-
- for (i = MAC_REG_RDBASE_LO; i < MAC_REG_FIFO_TEST0; i += 4)
- *((u32 *) (context->mac_reg + i)) = readl(ptr + i);
-
+ register_inetaddr_notifier(&velocity_inetaddr_notifier);
}
-/**
- * velocity_restore_context - restore registers
- * @vptr: velocity
- * @context: buffer for stored context
- *
- * Reload the register configuration from the velocity context
- * created by velocity_save_context.
- */
-
-static void velocity_restore_context(struct velocity_info *vptr, struct velocity_context *context)
+static void velocity_unregister_notifier(void)
{
- struct mac_regs __iomem * regs = vptr->mac_regs;
- int i;
- u8 __iomem *ptr = (u8 __iomem *)regs;
-
- for (i = MAC_REG_PAR; i < MAC_REG_CR0_SET; i += 4) {
- writel(*((u32 *) (context->mac_reg + i)), ptr + i);
- }
-
- /* Just skip cr0 */
- for (i = MAC_REG_CR1_SET; i < MAC_REG_CR0_CLR; i++) {
- /* Clear */
- writeb(~(*((u8 *) (context->mac_reg + i))), ptr + i + 4);
- /* Set */
- writeb(*((u8 *) (context->mac_reg + i)), ptr + i);
- }
-
- for (i = MAC_REG_MAR; i < MAC_REG_IMR; i += 4) {
- writel(*((u32 *) (context->mac_reg + i)), ptr + i);
- }
+ unregister_inetaddr_notifier(&velocity_inetaddr_notifier);
+}
- for (i = MAC_REG_RDBASE_LO; i < MAC_REG_FIFO_TEST0; i += 4) {
- writel(*((u32 *) (context->mac_reg + i)), ptr + i);
- }
+#else
- for (i = MAC_REG_TDCSR_SET; i <= MAC_REG_RDCSR_SET; i++) {
- writeb(*((u8 *) (context->mac_reg + i)), ptr + i);
- }
+#define velocity_register_notifier() do {} while (0)
+#define velocity_unregister_notifier() do {} while (0)
-}
+#endif /* defined(CONFIG_PM) && defined(CONFIG_INET) */
/**
- * wol_calc_crc - WOL CRC
- * @pattern: data pattern
- * @mask_pattern: mask
+ * velocity_init_module - load time function
*
- * Compute the wake on lan crc hashes for the packet header
- * we are interested in.
+ * Called when the velocity module is loaded. The PCI driver
+ * is registered with the PCI layer, and in turn will call
+ * the probe functions for each velocity adapter installed
+ * in the system.
*/
-
-static u16 wol_calc_crc(int size, u8 * pattern, u8 *mask_pattern)
+static int __init velocity_init_module(void)
{
- u16 crc = 0xFFFF;
- u8 mask;
- int i, j;
-
- for (i = 0; i < size; i++) {
- mask = mask_pattern[i];
-
- /* Skip this loop if the mask equals to zero */
- if (mask == 0x00)
- continue;
+ int ret;
- for (j = 0; j < 8; j++) {
- if ((mask & 0x01) == 0) {
- mask >>= 1;
- continue;
- }
- mask >>= 1;
- crc = crc_ccitt(crc, &(pattern[i * 8 + j]), 1);
- }
- }
- /* Finally, invert the result once to get the correct data */
- crc = ~crc;
- return bitrev32(crc) >> 16;
+ velocity_register_notifier();
+ ret = pci_register_driver(&velocity_driver);
+ if (ret < 0)
+ velocity_unregister_notifier();
+ return ret;
}
/**
- * velocity_set_wol - set up for wake on lan
- * @vptr: velocity to set WOL status on
- *
- * Set a card up for wake on lan either by unicast or by
- * ARP packet.
+ * velocity_cleanup - module unload
*
- * FIXME: check static buffer is safe here
+ * When the velocity hardware is unloaded this function is called.
+ * It will clean up the notifiers and the unregister the PCI
+ * driver interface for this hardware. This in turn cleans up
+ * all discovered interfaces before returning from the function
*/
-
-static int velocity_set_wol(struct velocity_info *vptr)
-{
- struct mac_regs __iomem * regs = vptr->mac_regs;
- static u8 buf[256];
- int i;
-
- static u32 mask_pattern[2][4] = {
- {0x00203000, 0x000003C0, 0x00000000, 0x0000000}, /* ARP */
- {0xfffff000, 0xffffffff, 0xffffffff, 0x000ffff} /* Magic Packet */
- };
-
- writew(0xFFFF, &regs->WOLCRClr);
- writeb(WOLCFG_SAB | WOLCFG_SAM, &regs->WOLCFGSet);
- writew(WOLCR_MAGIC_EN, &regs->WOLCRSet);
-
- /*
- if (vptr->wol_opts & VELOCITY_WOL_PHY)
- writew((WOLCR_LINKON_EN|WOLCR_LINKOFF_EN), &regs->WOLCRSet);
- */
-
- if (vptr->wol_opts & VELOCITY_WOL_UCAST) {
- writew(WOLCR_UNICAST_EN, &regs->WOLCRSet);
- }
-
- if (vptr->wol_opts & VELOCITY_WOL_ARP) {
- struct arp_packet *arp = (struct arp_packet *) buf;
- u16 crc;
- memset(buf, 0, sizeof(struct arp_packet) + 7);
-
- for (i = 0; i < 4; i++)
- writel(mask_pattern[0][i], &regs->ByteMask[0][i]);
-
- arp->type = htons(ETH_P_ARP);
- arp->ar_op = htons(1);
-
- memcpy(arp->ar_tip, vptr->ip_addr, 4);
-
- crc = wol_calc_crc((sizeof(struct arp_packet) + 7) / 8, buf,
- (u8 *) & mask_pattern[0][0]);
-
- writew(crc, &regs->PatternCRC[0]);
- writew(WOLCR_ARP_EN, &regs->WOLCRSet);
- }
-
- BYTE_REG_BITS_ON(PWCFG_WOLTYPE, &regs->PWCFGSet);
- BYTE_REG_BITS_ON(PWCFG_LEGACY_WOLEN, &regs->PWCFGSet);
-
- writew(0x0FFF, &regs->WOLSRClr);
-
- if (vptr->mii_status & VELOCITY_AUTONEG_ENABLE) {
- if (PHYID_GET_PHY_ID(vptr->phy_id) == PHYID_CICADA_CS8201)
- MII_REG_BITS_ON(AUXCR_MDPPS, MII_REG_AUXCR, vptr->mac_regs);
-
- MII_REG_BITS_OFF(G1000CR_1000FD | G1000CR_1000, MII_REG_G1000CR, vptr->mac_regs);
- }
-
- if (vptr->mii_status & VELOCITY_SPEED_1000)
- MII_REG_BITS_ON(BMCR_REAUTO, MII_REG_BMCR, vptr->mac_regs);
-
- BYTE_REG_BITS_ON(CHIPGCR_FCMODE, &regs->CHIPGCR);
-
- {
- u8 GCR;
- GCR = readb(&regs->CHIPGCR);
- GCR = (GCR & ~CHIPGCR_FCGMII) | CHIPGCR_FCFDX;
- writeb(GCR, &regs->CHIPGCR);
- }
-
- BYTE_REG_BITS_OFF(ISR_PWEI, &regs->ISR);
- /* Turn on SWPTAG just before entering power mode */
- BYTE_REG_BITS_ON(STICKHW_SWPTAG, &regs->STICKHW);
- /* Go to bed ..... */
- BYTE_REG_BITS_ON((STICKHW_DS1 | STICKHW_DS0), &regs->STICKHW);
-
- return 0;
-}
-
-static int velocity_suspend(struct pci_dev *pdev, pm_message_t state)
-{
- struct net_device *dev = pci_get_drvdata(pdev);
- struct velocity_info *vptr = netdev_priv(dev);
- unsigned long flags;
-
- if(!netif_running(vptr->dev))
- return 0;
-
- netif_device_detach(vptr->dev);
-
- spin_lock_irqsave(&vptr->lock, flags);
- pci_save_state(pdev);
-#ifdef ETHTOOL_GWOL
- if (vptr->flags & VELOCITY_FLAGS_WOL_ENABLED) {
- velocity_get_ip(vptr);
- velocity_save_context(vptr, &vptr->context);
- velocity_shutdown(vptr);
- velocity_set_wol(vptr);
- pci_enable_wake(pdev, PCI_D3hot, 1);
- pci_set_power_state(pdev, PCI_D3hot);
- } else {
- velocity_save_context(vptr, &vptr->context);
- velocity_shutdown(vptr);
- pci_disable_device(pdev);
- pci_set_power_state(pdev, pci_choose_state(pdev, state));
- }
-#else
- pci_set_power_state(pdev, pci_choose_state(pdev, state));
-#endif
- spin_unlock_irqrestore(&vptr->lock, flags);
- return 0;
-}
-
-static int velocity_resume(struct pci_dev *pdev)
-{
- struct net_device *dev = pci_get_drvdata(pdev);
- struct velocity_info *vptr = netdev_priv(dev);
- unsigned long flags;
- int i;
-
- if(!netif_running(vptr->dev))
- return 0;
-
- pci_set_power_state(pdev, PCI_D0);
- pci_enable_wake(pdev, 0, 0);
- pci_restore_state(pdev);
-
- mac_wol_reset(vptr->mac_regs);
-
- spin_lock_irqsave(&vptr->lock, flags);
- velocity_restore_context(vptr, &vptr->context);
- velocity_init_registers(vptr, VELOCITY_INIT_WOL);
- mac_disable_int(vptr->mac_regs);
-
- velocity_tx_srv(vptr, 0);
-
- for (i = 0; i < vptr->tx.numq; i++) {
- if (vptr->tx.used[i]) {
- mac_tx_queue_wake(vptr->mac_regs, i);
- }
- }
-
- mac_enable_int(vptr->mac_regs);
- spin_unlock_irqrestore(&vptr->lock, flags);
- netif_device_attach(vptr->dev);
-
- return 0;
-}
-
-#ifdef CONFIG_INET
-
-static int velocity_netdev_event(struct notifier_block *nb, unsigned long notification, void *ptr)
+static void __exit velocity_cleanup_module(void)
{
- struct in_ifaddr *ifa = (struct in_ifaddr *) ptr;
- struct net_device *dev = ifa->ifa_dev->dev;
- struct velocity_info *vptr;
- unsigned long flags;
-
- if (dev_net(dev) != &init_net)
- return NOTIFY_DONE;
-
- spin_lock_irqsave(&velocity_dev_list_lock, flags);
- list_for_each_entry(vptr, &velocity_dev_list, list) {
- if (vptr->dev == dev) {
- velocity_get_ip(vptr);
- break;
- }
- }
- spin_unlock_irqrestore(&velocity_dev_list_lock, flags);
-
- return NOTIFY_DONE;
+ velocity_unregister_notifier();
+ pci_unregister_driver(&velocity_driver);
}
-#endif
-#endif
+module_init(velocity_init_module);
+module_exit(velocity_cleanup_module);
diff --git a/drivers/net/via-velocity.h b/drivers/net/via-velocity.h
index 4cd3f6c9737..2f00c13ab50 100644
--- a/drivers/net/via-velocity.h
+++ b/drivers/net/via-velocity.h
@@ -96,8 +96,8 @@
* Bits in the CSM register
*/
-#define CSM_IPOK 0x40 //IP Checkusm validatiaon ok
-#define CSM_TUPOK 0x20 //TCP/UDP Checkusm validatiaon ok
+#define CSM_IPOK 0x40 //IP Checksum validation ok
+#define CSM_TUPOK 0x20 //TCP/UDP Checksum validation ok
#define CSM_FRAG 0x10 //Fragment IP datagram
#define CSM_IPKT 0x04 //Received an IP packet
#define CSM_TCPKT 0x02 //Received a TCP packet
@@ -819,7 +819,7 @@ enum velocity_owner {
* Bits in the EECSR register
*/
-#define EECSR_EMBP 0x40 /* eeprom embeded programming */
+#define EECSR_EMBP 0x40 /* eeprom embedded programming */
#define EECSR_RELOAD 0x20 /* eeprom content reload */
#define EECSR_DPM 0x10 /* eeprom direct programming */
#define EECSR_ECS 0x08 /* eeprom CS pin */
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index 2a6e81d5b57..a6f903f0092 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -774,6 +774,7 @@ static struct ethtool_ops virtnet_ethtool_ops = {
.set_tx_csum = virtnet_set_tx_csum,
.set_sg = ethtool_op_set_sg,
.set_tso = ethtool_op_set_tso,
+ .set_ufo = ethtool_op_set_ufo,
.get_link = ethtool_op_get_link,
};
@@ -1005,7 +1006,7 @@ static unsigned int features[] = {
VIRTIO_NET_F_GSO, VIRTIO_NET_F_MAC,
VIRTIO_NET_F_HOST_TSO4, VIRTIO_NET_F_HOST_UFO, VIRTIO_NET_F_HOST_TSO6,
VIRTIO_NET_F_HOST_ECN, VIRTIO_NET_F_GUEST_TSO4, VIRTIO_NET_F_GUEST_TSO6,
- VIRTIO_NET_F_GUEST_ECN, /* We don't yet handle UFO input. */
+ VIRTIO_NET_F_GUEST_ECN, VIRTIO_NET_F_GUEST_UFO,
VIRTIO_NET_F_MRG_RXBUF, VIRTIO_NET_F_STATUS, VIRTIO_NET_F_CTRL_VQ,
VIRTIO_NET_F_CTRL_RX, VIRTIO_NET_F_CTRL_VLAN,
VIRTIO_F_NOTIFY_ON_EMPTY,
diff --git a/drivers/net/vxge/vxge-config.c b/drivers/net/vxge/vxge-config.c
index 58d2551c78e..9e94c4b0fb1 100644
--- a/drivers/net/vxge/vxge-config.c
+++ b/drivers/net/vxge/vxge-config.c
@@ -313,14 +313,6 @@ __vxge_hw_device_reg_addr_get(struct __vxge_hw_device *hldev)
hldev->kdfc = (u8 __iomem *)(hldev->bar0 +
VXGE_HW_TOC_GET_KDFC_INITIAL_OFFSET(val64));
break;
- case 2:
- hldev->kdfc = (u8 __iomem *)(hldev->bar1 +
- VXGE_HW_TOC_GET_KDFC_INITIAL_OFFSET(val64));
- break;
- case 4:
- hldev->kdfc = (u8 __iomem *)(hldev->bar2 +
- VXGE_HW_TOC_GET_KDFC_INITIAL_OFFSET(val64));
- break;
default:
break;
}
@@ -831,8 +823,6 @@ vxge_hw_device_initialize(
sizeof(struct vxge_hw_device_config));
hldev->bar0 = attr->bar0;
- hldev->bar1 = attr->bar1;
- hldev->bar2 = attr->bar2;
hldev->pdev = attr->pdev;
hldev->uld_callbacks.link_up = attr->uld_callbacks.link_up;
diff --git a/drivers/net/vxge/vxge-config.h b/drivers/net/vxge/vxge-config.h
index afbdf6f4d22..62779a520ca 100644
--- a/drivers/net/vxge/vxge-config.h
+++ b/drivers/net/vxge/vxge-config.h
@@ -682,8 +682,6 @@ struct __vxge_hw_vpath_handle{
* @major_revision: PCI Device major revision
* @minor_revision: PCI Device minor revision
* @bar0: BAR0 virtual address.
- * @bar1: BAR1 virtual address.
- * @bar2: BAR2 virtual address.
* @pdev: Physical device handle
* @config: Confguration passed by the LL driver at initialization
* @link_state: Link state
@@ -698,8 +696,6 @@ struct __vxge_hw_device {
u8 major_revision;
u8 minor_revision;
void __iomem *bar0;
- void __iomem *bar1;
- void __iomem *bar2;
struct pci_dev *pdev;
struct net_device *ndev;
struct vxge_hw_device_config config;
@@ -788,17 +784,13 @@ struct vxge_hw_device_hw_info {
/**
* struct vxge_hw_device_attr - Device memory spaces.
* @bar0: BAR0 virtual address.
- * @bar1: BAR1 virtual address.
- * @bar2: BAR2 virtual address.
* @pdev: PCI device object.
*
- * Device memory spaces. Includes configuration, BAR0, BAR1, etc. per device
+ * Device memory spaces. Includes configuration, BAR0 etc. per device
* mapped memories. Also, includes a pointer to OS-specific PCI device object.
*/
struct vxge_hw_device_attr {
void __iomem *bar0;
- void __iomem *bar1;
- void __iomem *bar2;
struct pci_dev *pdev;
struct vxge_hw_uld_cbs uld_callbacks;
};
@@ -986,7 +978,9 @@ struct __vxge_hw_fifo {
void *txdlh,
enum vxge_hw_fifo_tcode t_code,
void *userdata,
- void **skb_ptr);
+ struct sk_buff ***skb_ptr,
+ int nr_skb,
+ int *more);
void (*txdl_term)(
void *txdlh,
@@ -1787,7 +1781,8 @@ struct vxge_hw_fifo_attr {
void *txdlh,
enum vxge_hw_fifo_tcode t_code,
void *userdata,
- void **skb_ptr);
+ struct sk_buff ***skb_ptr,
+ int nr_skb, int *more);
void (*txdl_term)(
void *txdlh,
diff --git a/drivers/net/vxge/vxge-main.c b/drivers/net/vxge/vxge-main.c
index 6034497536a..094d15548a2 100644
--- a/drivers/net/vxge/vxge-main.c
+++ b/drivers/net/vxge/vxge-main.c
@@ -87,22 +87,25 @@ static inline int is_vxge_card_up(struct vxgedev *vdev)
static inline void VXGE_COMPLETE_VPATH_TX(struct vxge_fifo *fifo)
{
unsigned long flags = 0;
- struct sk_buff *skb_ptr = NULL;
- struct sk_buff **temp, *head, *skb;
-
- if (spin_trylock_irqsave(&fifo->tx_lock, flags)) {
- vxge_hw_vpath_poll_tx(fifo->handle, (void **)&skb_ptr);
- spin_unlock_irqrestore(&fifo->tx_lock, flags);
- }
- /* free SKBs */
- head = skb_ptr;
- while (head) {
- skb = head;
- temp = (struct sk_buff **)&skb->cb;
- head = *temp;
- *temp = NULL;
- dev_kfree_skb_irq(skb);
- }
+ struct sk_buff **skb_ptr = NULL;
+ struct sk_buff **temp;
+#define NR_SKB_COMPLETED 128
+ struct sk_buff *completed[NR_SKB_COMPLETED];
+ int more;
+
+ do {
+ more = 0;
+ skb_ptr = completed;
+
+ if (spin_trylock_irqsave(&fifo->tx_lock, flags)) {
+ vxge_hw_vpath_poll_tx(fifo->handle, &skb_ptr,
+ NR_SKB_COMPLETED, &more);
+ spin_unlock_irqrestore(&fifo->tx_lock, flags);
+ }
+ /* free SKBs */
+ for (temp = completed; temp != skb_ptr; temp++)
+ dev_kfree_skb_irq(*temp);
+ } while (more) ;
}
static inline void VXGE_COMPLETE_ALL_TX(struct vxgedev *vdev)
@@ -283,6 +286,7 @@ vxge_rx_alloc(void *dtrh, struct vxge_ring *ring, const int skb_size)
skb_reserve(skb, VXGE_HW_HEADER_ETHERNET_II_802_3_ALIGN);
rx_priv->skb = skb;
+ rx_priv->skb_data = NULL;
rx_priv->data_size = skb_size;
vxge_debug_entryexit(VXGE_TRACE,
"%s: %s:%d Exiting...", ring->ndev->name, __func__, __LINE__);
@@ -302,7 +306,8 @@ static int vxge_rx_map(void *dtrh, struct vxge_ring *ring)
ring->ndev->name, __func__, __LINE__);
rx_priv = vxge_hw_ring_rxd_private_get(dtrh);
- dma_addr = pci_map_single(ring->pdev, rx_priv->skb->data,
+ rx_priv->skb_data = rx_priv->skb->data;
+ dma_addr = pci_map_single(ring->pdev, rx_priv->skb_data,
rx_priv->data_size, PCI_DMA_FROMDEVICE);
if (dma_addr == 0) {
@@ -374,10 +379,10 @@ vxge_rx_complete(struct vxge_ring *ring, struct sk_buff *skb, u16 vlan,
if (ring->vlgrp && ext_info->vlan &&
(ring->vlan_tag_strip ==
VXGE_HW_VPATH_RPA_STRIP_VLAN_TAG_ENABLE))
- vlan_gro_receive(&ring->napi, ring->vlgrp,
+ vlan_gro_receive(ring->napi_p, ring->vlgrp,
ext_info->vlan, skb);
else
- napi_gro_receive(&ring->napi, skb);
+ napi_gro_receive(ring->napi_p, skb);
} else {
if (ring->vlgrp && vlan &&
(ring->vlan_tag_strip ==
@@ -442,10 +447,12 @@ vxge_rx_1b_compl(struct __vxge_hw_ring *ringh, void *dtr,
vxge_hw_ring_replenish(ringh, 0);
do {
+ prefetch((char *)dtr + L1_CACHE_BYTES);
rx_priv = vxge_hw_ring_rxd_private_get(dtr);
skb = rx_priv->skb;
data_size = rx_priv->data_size;
data_dma = rx_priv->data_dma;
+ prefetch(rx_priv->skb_data);
vxge_debug_rx(VXGE_TRACE,
"%s: %s:%d skb = 0x%p",
@@ -454,6 +461,8 @@ vxge_rx_1b_compl(struct __vxge_hw_ring *ringh, void *dtr,
vxge_hw_ring_rxd_1b_get(ringh, dtr, &dma_sizes);
pkt_length = dma_sizes;
+ pkt_length -= ETH_FCS_LEN;
+
vxge_debug_rx(VXGE_TRACE,
"%s: %s:%d Packet Length = %d",
ring->ndev->name, __func__, __LINE__, pkt_length);
@@ -598,11 +607,10 @@ vxge_rx_1b_compl(struct __vxge_hw_ring *ringh, void *dtr,
enum vxge_hw_status
vxge_xmit_compl(struct __vxge_hw_fifo *fifo_hw, void *dtr,
enum vxge_hw_fifo_tcode t_code, void *userdata,
- void **skb_ptr)
+ struct sk_buff ***skb_ptr, int nr_skb, int *more)
{
struct vxge_fifo *fifo = (struct vxge_fifo *)userdata;
- struct sk_buff *skb, *head = NULL;
- struct sk_buff **temp;
+ struct sk_buff *skb, **done_skb = *skb_ptr;
int pkt_cnt = 0;
vxge_debug_entryexit(VXGE_TRACE,
@@ -655,9 +663,12 @@ vxge_xmit_compl(struct __vxge_hw_fifo *fifo_hw, void *dtr,
fifo->stats.tx_frms++;
fifo->stats.tx_bytes += skb->len;
- temp = (struct sk_buff **)&skb->cb;
- *temp = head;
- head = skb;
+ *done_skb++ = skb;
+
+ if (--nr_skb <= 0) {
+ *more = 1;
+ break;
+ }
pkt_cnt++;
if (pkt_cnt > fifo->indicate_max_pkts)
@@ -666,11 +677,9 @@ vxge_xmit_compl(struct __vxge_hw_fifo *fifo_hw, void *dtr,
} while (vxge_hw_fifo_txdl_next_completed(fifo_hw,
&dtr, &t_code) == VXGE_HW_OK);
+ *skb_ptr = done_skb;
vxge_wake_tx_queue(fifo, skb);
- if (skb_ptr)
- *skb_ptr = (void *) head;
-
vxge_debug_entryexit(VXGE_TRACE,
"%s: %s:%d Exiting...",
fifo->ndev->name, __func__, __LINE__);
@@ -817,7 +826,6 @@ vxge_xmit(struct sk_buff *skb, struct net_device *dev)
u64 dma_pointer;
struct vxge_tx_priv *txdl_priv = NULL;
struct __vxge_hw_fifo *fifo_hw;
- u32 max_mss = 0x0;
int offload_type;
unsigned long flags = 0;
int vpath_no = 0;
@@ -894,6 +902,12 @@ vxge_xmit(struct sk_buff *skb, struct net_device *dev)
goto _exit2;
}
+ /* Last TXD? Stop tx queue to avoid dropping packets. TX
+ * completion will resume the queue.
+ */
+ if (avail == 1)
+ vxge_stop_tx_queue(fifo);
+
status = vxge_hw_fifo_txdl_reserve(fifo_hw, &dtr, &dtr_priv);
if (unlikely(status != VXGE_HW_OK)) {
vxge_debug_tx(VXGE_ERR,
@@ -969,10 +983,6 @@ vxge_xmit(struct sk_buff *skb, struct net_device *dev)
int mss = vxge_tcp_mss(skb);
if (mss) {
- max_mss = dev->mtu + ETH_HLEN -
- VXGE_HW_TCPIP_HEADER_MAX_SIZE;
- if (mss > max_mss)
- mss = max_mss;
vxge_debug_tx(VXGE_TRACE,
"%s: %s:%d mss = %d",
dev->name, __func__, __LINE__, mss);
@@ -1000,7 +1010,7 @@ vxge_xmit(struct sk_buff *skb, struct net_device *dev)
VXGE_COMPLETE_VPATH_TX(fifo);
vxge_debug_entryexit(VXGE_TRACE, "%s: %s:%d Exiting...",
dev->name, __func__, __LINE__);
- return 0;
+ return NETDEV_TX_OK;
_exit0:
vxge_debug_tx(VXGE_TRACE, "%s: pci_map_page failed", dev->name);
@@ -1024,7 +1034,7 @@ _exit2:
spin_unlock_irqrestore(&fifo->tx_lock, flags);
VXGE_COMPLETE_VPATH_TX(fifo);
- return 0;
+ return NETDEV_TX_OK;
}
/*
@@ -1049,6 +1059,7 @@ vxge_rx_term(void *dtrh, enum vxge_hw_rxd_state state, void *userdata)
rx_priv->data_size, PCI_DMA_FROMDEVICE);
dev_kfree_skb(rx_priv->skb);
+ rx_priv->skb_data = NULL;
vxge_debug_entryexit(VXGE_TRACE,
"%s: %s:%d Exiting...",
@@ -2137,16 +2148,16 @@ int vxge_open_vpaths(struct vxgedev *vdev)
*/
static irqreturn_t vxge_isr_napi(int irq, void *dev_id)
{
- struct __vxge_hw_device *hldev = (struct __vxge_hw_device *)dev_id;
- struct vxgedev *vdev;
struct net_device *dev;
+ struct __vxge_hw_device *hldev;
u64 reason;
enum vxge_hw_status status;
+ struct vxgedev *vdev = (struct vxgedev *) dev_id;;
vxge_debug_intr(VXGE_TRACE, "%s:%d", __func__, __LINE__);
- dev = hldev->ndev;
- vdev = netdev_priv(dev);
+ dev = vdev->ndev;
+ hldev = (struct __vxge_hw_device *)pci_get_drvdata(vdev->pdev);
if (pci_channel_offline(vdev->pdev))
return IRQ_NONE;
@@ -2417,15 +2428,13 @@ static void vxge_rem_isr(struct vxgedev *vdev)
#endif
if (vdev->config.intr_type == INTA) {
synchronize_irq(vdev->pdev->irq);
- free_irq(vdev->pdev->irq, hldev);
+ free_irq(vdev->pdev->irq, vdev);
}
}
static int vxge_add_isr(struct vxgedev *vdev)
{
int ret = 0;
- struct __vxge_hw_device *hldev =
- (struct __vxge_hw_device *) pci_get_drvdata(vdev->pdev);
#ifdef CONFIG_PCI_MSI
int vp_idx = 0, intr_idx = 0, intr_cnt = 0, msix_idx = 0, irq_req = 0;
u64 function_mode = vdev->config.device_hw_info.function_mode;
@@ -2579,7 +2588,7 @@ INTA_MODE:
if (vdev->config.intr_type == INTA) {
ret = request_irq((int) vdev->pdev->irq,
vxge_isr_napi,
- IRQF_SHARED, vdev->desc[0], hldev);
+ IRQF_SHARED, vdev->desc[0], vdev);
if (ret) {
vxge_debug_init(VXGE_ERR,
"%s %s-%d: ISR registration failed",
@@ -2712,11 +2721,15 @@ vxge_open(struct net_device *dev)
netif_napi_add(dev, &vdev->napi, vxge_poll_inta,
vdev->config.napi_weight);
napi_enable(&vdev->napi);
+ for (i = 0; i < vdev->no_of_vpath; i++)
+ vdev->vpaths[i].ring.napi_p = &vdev->napi;
} else {
for (i = 0; i < vdev->no_of_vpath; i++) {
netif_napi_add(dev, &vdev->vpaths[i].ring.napi,
vxge_poll_msix, vdev->config.napi_weight);
napi_enable(&vdev->vpaths[i].ring.napi);
+ vdev->vpaths[i].ring.napi_p =
+ &vdev->vpaths[i].ring.napi;
}
}
@@ -2890,6 +2903,9 @@ int do_vxge_close(struct net_device *dev, int do_io)
vdev = (struct vxgedev *)netdev_priv(dev);
hldev = (struct __vxge_hw_device *) pci_get_drvdata(vdev->pdev);
+ if (unlikely(!is_vxge_card_up(vdev)))
+ return 0;
+
/* If vxge_handle_crit_err task is executing,
* wait till it completes. */
while (test_and_set_bit(__VXGE_STATE_RESET_CARD, &vdev->state))
@@ -3954,6 +3970,9 @@ static pci_ers_result_t vxge_io_error_detected(struct pci_dev *pdev,
netif_device_detach(netdev);
+ if (state == pci_channel_io_perm_failure)
+ return PCI_ERS_RESULT_DISCONNECT;
+
if (netif_running(netdev)) {
/* Bring down the card, while avoiding PCI I/O */
do_vxge_close(netdev, 0);
@@ -4152,18 +4171,6 @@ vxge_probe(struct pci_dev *pdev, const struct pci_device_id *pre)
attr.bar0,
(unsigned long long)pci_resource_start(pdev, 0));
- attr.bar1 = pci_ioremap_bar(pdev, 2);
- if (!attr.bar1) {
- vxge_debug_init(VXGE_ERR,
- "%s : cannot remap io memory bar2", __func__);
- ret = -ENODEV;
- goto _exit3;
- }
- vxge_debug_ll_config(VXGE_TRACE,
- "pci ioremap bar1: %p:0x%llx",
- attr.bar1,
- (unsigned long long)pci_resource_start(pdev, 2));
-
status = vxge_hw_device_hw_info_get(attr.bar0,
&ll_config.device_hw_info);
if (status != VXGE_HW_OK) {
@@ -4171,17 +4178,17 @@ vxge_probe(struct pci_dev *pdev, const struct pci_device_id *pre)
"%s: Reading of hardware info failed."
"Please try upgrading the firmware.", VXGE_DRIVER_NAME);
ret = -EINVAL;
- goto _exit4;
+ goto _exit3;
}
if (ll_config.device_hw_info.fw_version.major !=
- VXGE_DRIVER_VERSION_MAJOR) {
+ VXGE_DRIVER_FW_VERSION_MAJOR) {
vxge_debug_init(VXGE_ERR,
- "FW Ver.(maj): %d not driver's expected version: %d",
- ll_config.device_hw_info.fw_version.major,
- VXGE_DRIVER_VERSION_MAJOR);
+ "%s: Incorrect firmware version."
+ "Please upgrade the firmware to version 1.x.x",
+ VXGE_DRIVER_NAME);
ret = -EINVAL;
- goto _exit4;
+ goto _exit3;
}
vpath_mask = ll_config.device_hw_info.vpath_mask;
@@ -4189,7 +4196,7 @@ vxge_probe(struct pci_dev *pdev, const struct pci_device_id *pre)
vxge_debug_ll_config(VXGE_TRACE,
"%s: No vpaths available in device", VXGE_DRIVER_NAME);
ret = -EINVAL;
- goto _exit4;
+ goto _exit3;
}
vxge_debug_ll_config(VXGE_TRACE,
@@ -4222,7 +4229,7 @@ vxge_probe(struct pci_dev *pdev, const struct pci_device_id *pre)
vxge_debug_ll_config(VXGE_ERR,
"%s: No more vpaths to configure", VXGE_DRIVER_NAME);
ret = 0;
- goto _exit4;
+ goto _exit3;
}
/* Setting driver callbacks */
@@ -4235,7 +4242,7 @@ vxge_probe(struct pci_dev *pdev, const struct pci_device_id *pre)
vxge_debug_init(VXGE_ERR,
"Failed to initialize device (%d)", status);
ret = -EINVAL;
- goto _exit4;
+ goto _exit3;
}
vxge_hw_device_debug_set(hldev, VXGE_ERR, VXGE_COMPONENT_LL);
@@ -4260,7 +4267,7 @@ vxge_probe(struct pci_dev *pdev, const struct pci_device_id *pre)
if (vxge_device_register(hldev, &ll_config, high_dma, no_of_vpath,
&vdev)) {
ret = -EINVAL;
- goto _exit5;
+ goto _exit4;
}
vxge_hw_device_debug_set(hldev, VXGE_TRACE, VXGE_COMPONENT_LL);
@@ -4271,7 +4278,6 @@ vxge_probe(struct pci_dev *pdev, const struct pci_device_id *pre)
hldev->ndev = vdev->ndev;
vdev->mtu = VXGE_HW_DEFAULT_MTU;
vdev->bar0 = attr.bar0;
- vdev->bar1 = attr.bar1;
vdev->max_vpath_supported = max_vpath_supported;
vdev->no_of_vpath = no_of_vpath;
@@ -4336,6 +4342,27 @@ vxge_probe(struct pci_dev *pdev, const struct pci_device_id *pre)
ll_config.device_hw_info.fw_version.version,
ll_config.device_hw_info.fw_date.date);
+ if (new_device) {
+ switch (ll_config.device_hw_info.function_mode) {
+ case VXGE_HW_FUNCTION_MODE_SINGLE_FUNCTION:
+ vxge_debug_init(VXGE_TRACE,
+ "%s: Single Function Mode Enabled", vdev->ndev->name);
+ break;
+ case VXGE_HW_FUNCTION_MODE_MULTI_FUNCTION:
+ vxge_debug_init(VXGE_TRACE,
+ "%s: Multi Function Mode Enabled", vdev->ndev->name);
+ break;
+ case VXGE_HW_FUNCTION_MODE_SRIOV:
+ vxge_debug_init(VXGE_TRACE,
+ "%s: Single Root IOV Mode Enabled", vdev->ndev->name);
+ break;
+ case VXGE_HW_FUNCTION_MODE_MRIOV:
+ vxge_debug_init(VXGE_TRACE,
+ "%s: Multi Root IOV Mode Enabled", vdev->ndev->name);
+ break;
+ }
+ }
+
vxge_print_parm(vdev, vpath_mask);
/* Store the fw version for ethttool option */
@@ -4353,7 +4380,7 @@ vxge_probe(struct pci_dev *pdev, const struct pci_device_id *pre)
"%s: mac_addr_list : memory allocation failed",
vdev->ndev->name);
ret = -EPERM;
- goto _exit6;
+ goto _exit5;
}
macaddr = (u8 *)&entry->macaddr;
memcpy(macaddr, vdev->ndev->dev_addr, ETH_ALEN);
@@ -4361,6 +4388,7 @@ vxge_probe(struct pci_dev *pdev, const struct pci_device_id *pre)
vdev->vpaths[i].mac_addr_cnt = 1;
}
+ kfree(device_config);
vxge_debug_entryexit(VXGE_TRACE, "%s: %s:%d Exiting...",
vdev->ndev->name, __func__, __LINE__);
@@ -4370,16 +4398,14 @@ vxge_probe(struct pci_dev *pdev, const struct pci_device_id *pre)
return 0;
-_exit6:
+_exit5:
for (i = 0; i < vdev->no_of_vpath; i++)
vxge_free_mac_add_list(&vdev->vpaths[i]);
vxge_device_unregister(hldev);
-_exit5:
+_exit4:
pci_disable_sriov(pdev);
vxge_hw_device_terminate(hldev);
-_exit4:
- iounmap(attr.bar1);
_exit3:
iounmap(attr.bar0);
_exit2:
@@ -4438,7 +4464,6 @@ vxge_remove(struct pci_dev *pdev)
kfree(vdev->vpaths);
iounmap(vdev->bar0);
- iounmap(vdev->bar1);
pci_disable_sriov(pdev);
diff --git a/drivers/net/vxge/vxge-main.h b/drivers/net/vxge/vxge-main.h
index 9704b2bd432..9c36b3a9a63 100644
--- a/drivers/net/vxge/vxge-main.h
+++ b/drivers/net/vxge/vxge-main.h
@@ -21,7 +21,7 @@
#define VXGE_DRIVER_NAME "vxge"
#define VXGE_DRIVER_VENDOR "Neterion, Inc"
-#define VXGE_DRIVER_VERSION_MAJOR 0
+#define VXGE_DRIVER_FW_VERSION_MAJOR 1
#define DRV_VERSION VXGE_VERSION_MAJOR"."VXGE_VERSION_MINOR"."\
VXGE_VERSION_FIX"."VXGE_VERSION_BUILD"-"\
@@ -260,6 +260,7 @@ struct vxge_ring {
int gro_enable;
struct napi_struct napi;
+ struct napi_struct *napi_p;
#define VXGE_MAX_MAC_ADDR_COUNT 30
@@ -363,7 +364,6 @@ struct vxgedev {
struct __vxge_hw_vpath_handle *vp_handles[VXGE_HW_MAX_VIRTUAL_PATHS];
void __iomem *bar0;
- void __iomem *bar1;
struct vxge_sw_stats stats;
int mtu;
/* Below variables are used for vpath selection to transmit a packet */
@@ -378,6 +378,7 @@ struct vxgedev {
struct vxge_rx_priv {
struct sk_buff *skb;
+ unsigned char *skb_data;
dma_addr_t data_dma;
dma_addr_t data_size;
};
@@ -428,7 +429,8 @@ vxge_rx_1b_compl(struct __vxge_hw_ring *ringh, void *dtr,
enum vxge_hw_status
vxge_xmit_compl(struct __vxge_hw_fifo *fifo_hw, void *dtr,
- enum vxge_hw_fifo_tcode t_code, void *userdata, void **skb_ptr);
+ enum vxge_hw_fifo_tcode t_code, void *userdata,
+ struct sk_buff ***skb_ptr, int nr_skbs, int *more);
int vxge_close(struct net_device *dev);
diff --git a/drivers/net/vxge/vxge-reg.h b/drivers/net/vxge/vxge-reg.h
index 10f4da32929..9a3b823e08d 100644
--- a/drivers/net/vxge/vxge-reg.h
+++ b/drivers/net/vxge/vxge-reg.h
@@ -1784,7 +1784,7 @@ struct vxge_hw_mrpcim_reg {
#define VXGE_HW_XMAC_GEN_ERR_REG_XMACJ_XMAC_FSM_ERR vxge_mBIT(63)
/*0x01e18*/ u64 xmac_gen_err_mask;
/*0x01e20*/ u64 xmac_gen_err_alarm;
-/*0x01e28*/ u64 xmac_link_err_port_reg[2];
+/*0x01e28*/ u64 xmac_link_err_port0_reg;
#define VXGE_HW_XMAC_LINK_ERR_PORT_REG_XMACJ_PORT_DOWN vxge_mBIT(3)
#define VXGE_HW_XMAC_LINK_ERR_PORT_REG_XMACJ_PORT_UP vxge_mBIT(7)
#define VXGE_HW_XMAC_LINK_ERR_PORT_REG_XMACJ_PORT_WENT_DOWN vxge_mBIT(11)
@@ -1798,8 +1798,11 @@ struct vxge_hw_mrpcim_reg {
#define VXGE_HW_XMAC_LINK_ERR_PORT_REG_RATEMGMT_LASI_INV vxge_mBIT(39)
#define VXGE_HW_XMAC_LINK_ERR_PORT_REG_XMDIO_MDIO_MGR_ACCESS_COMPLETE \
vxge_mBIT(47)
-/*0x01e30*/ u64 xmac_link_err_port_mask[2];
-/*0x01e38*/ u64 xmac_link_err_port_alarm[2];
+/*0x01e30*/ u64 xmac_link_err_port0_mask;
+/*0x01e38*/ u64 xmac_link_err_port0_alarm;
+/*0x01e40*/ u64 xmac_link_err_port1_reg;
+/*0x01e48*/ u64 xmac_link_err_port1_mask;
+/*0x01e50*/ u64 xmac_link_err_port1_alarm;
/*0x01e58*/ u64 xgxs_gen_err_reg;
#define VXGE_HW_XGXS_GEN_ERR_REG_XGXS_XGXS_FSM_ERR vxge_mBIT(63)
/*0x01e60*/ u64 xgxs_gen_err_mask;
diff --git a/drivers/net/vxge/vxge-traffic.c b/drivers/net/vxge/vxge-traffic.c
index 370f55cbbad..fe3ae518c69 100644
--- a/drivers/net/vxge/vxge-traffic.c
+++ b/drivers/net/vxge/vxge-traffic.c
@@ -731,6 +731,7 @@ vxge_hw_channel_dtr_try_complete(struct __vxge_hw_channel *channel, void **dtrh)
vxge_assert(channel->compl_index < channel->length);
*dtrh = channel->work_arr[channel->compl_index];
+ prefetch(*dtrh);
}
/*
@@ -1070,11 +1071,11 @@ static void __vxge_hw_non_offload_db_post(struct __vxge_hw_fifo *fifo,
VXGE_HW_NODBW_GET_NO_SNOOP(no_snoop),
&fifo->nofl_db->control_0);
- wmb();
+ mmiowb();
writeq(txdl_ptr, &fifo->nofl_db->txdl_ptr);
- wmb();
+ mmiowb();
}
/**
@@ -2508,7 +2509,8 @@ enum vxge_hw_status vxge_hw_vpath_poll_rx(struct __vxge_hw_ring *ring)
* See also: vxge_hw_vpath_poll_tx().
*/
enum vxge_hw_status vxge_hw_vpath_poll_tx(struct __vxge_hw_fifo *fifo,
- void **skb_ptr)
+ struct sk_buff ***skb_ptr, int nr_skb,
+ int *more)
{
enum vxge_hw_fifo_tcode t_code;
void *first_txdlh;
@@ -2520,8 +2522,8 @@ enum vxge_hw_status vxge_hw_vpath_poll_tx(struct __vxge_hw_fifo *fifo,
status = vxge_hw_fifo_txdl_next_completed(fifo,
&first_txdlh, &t_code);
if (status == VXGE_HW_OK)
- if (fifo->callback(fifo, first_txdlh,
- t_code, channel->userdata, skb_ptr) != VXGE_HW_OK)
+ if (fifo->callback(fifo, first_txdlh, t_code,
+ channel->userdata, skb_ptr, nr_skb, more) != VXGE_HW_OK)
status = VXGE_HW_COMPLETIONS_REMAIN;
return status;
diff --git a/drivers/net/vxge/vxge-traffic.h b/drivers/net/vxge/vxge-traffic.h
index 7567a1140d0..461742b4442 100644
--- a/drivers/net/vxge/vxge-traffic.h
+++ b/drivers/net/vxge/vxge-traffic.h
@@ -35,8 +35,6 @@
VXGE_HW_HEADER_VLAN_SIZE + \
VXGE_HW_HEADER_SNAP_SIZE)
-#define VXGE_HW_TCPIP_HEADER_MAX_SIZE (64 + 64)
-
/* 32bit alignments */
#define VXGE_HW_HEADER_ETHERNET_II_802_3_ALIGN 2
#define VXGE_HW_HEADER_802_2_SNAP_ALIGN 2
@@ -2328,7 +2326,7 @@ enum vxge_hw_status vxge_hw_vpath_poll_rx(
enum vxge_hw_status vxge_hw_vpath_poll_tx(
struct __vxge_hw_fifo *fifoh,
- void **skb_ptr);
+ struct sk_buff ***skb_ptr, int nr_skb, int *more);
enum vxge_hw_status vxge_hw_vpath_alarm_process(
struct __vxge_hw_vpath_handle *vpath_handle,
diff --git a/drivers/net/vxge/vxge-version.h b/drivers/net/vxge/vxge-version.h
index 82786ffb7dd..8fbce755203 100644
--- a/drivers/net/vxge/vxge-version.h
+++ b/drivers/net/vxge/vxge-version.h
@@ -17,7 +17,7 @@
#define VXGE_VERSION_MAJOR "2"
#define VXGE_VERSION_MINOR "0"
-#define VXGE_VERSION_FIX "4"
-#define VXGE_VERSION_BUILD "17795"
+#define VXGE_VERSION_FIX "5"
+#define VXGE_VERSION_BUILD "18053"
#define VXGE_VERSION_FOR "k"
#endif
diff --git a/drivers/net/wan/cycx_x25.c b/drivers/net/wan/cycx_x25.c
index f525f9fe74d..4ae9bd297cc 100644
--- a/drivers/net/wan/cycx_x25.c
+++ b/drivers/net/wan/cycx_x25.c
@@ -663,7 +663,7 @@ static int cycx_netdevice_hard_start_xmit(struct sk_buff *skb,
free_packet:
dev_kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
}
/* Get Ethernet-style interface statistics.
diff --git a/drivers/net/wan/dlci.c b/drivers/net/wan/dlci.c
index 2fa275a58f9..8526b6d1ee4 100644
--- a/drivers/net/wan/dlci.c
+++ b/drivers/net/wan/dlci.c
@@ -194,7 +194,7 @@ static int dlci_transmit(struct sk_buff *skb, struct net_device *dev)
ret = 0;
if (!skb || !dev)
- return(0);
+ return NETDEV_TX_OK;
dlp = netdev_priv(dev);
@@ -219,7 +219,7 @@ static int dlci_transmit(struct sk_buff *skb, struct net_device *dev)
/* Alan Cox recommends always returning 0, and always freeing the packet */
/* experience suggest a slightly more conservative approach */
- if (!ret)
+ if (ret == NETDEV_TX_OK)
{
dev_kfree_skb(skb);
netif_wake_queue(dev);
diff --git a/drivers/net/wan/dscc4.c b/drivers/net/wan/dscc4.c
index 8face5db8f3..e81946d9854 100644
--- a/drivers/net/wan/dscc4.c
+++ b/drivers/net/wan/dscc4.c
@@ -1182,7 +1182,7 @@ static int dscc4_start_xmit(struct sk_buff *skb, struct net_device *dev)
if (dscc4_tx_quiescent(dpriv, dev))
dscc4_do_tx(dpriv, dev);
- return 0;
+ return NETDEV_TX_OK;
}
static int dscc4_close(struct net_device *dev)
diff --git a/drivers/net/wan/farsync.c b/drivers/net/wan/farsync.c
index 25c9ef6a181..20a1237a3d7 100644
--- a/drivers/net/wan/farsync.c
+++ b/drivers/net/wan/farsync.c
@@ -792,25 +792,6 @@ fst_process_rx_status(int rx_status, char *name)
*/
break;
}
-
- case NET_RX_CN_LOW:
- {
- dbg(DBG_ASS, "%s: Receive Low Congestion\n", name);
- break;
- }
-
- case NET_RX_CN_MOD:
- {
- dbg(DBG_ASS, "%s: Receive Moderate Congestion\n", name);
- break;
- }
-
- case NET_RX_CN_HIGH:
- {
- dbg(DBG_ASS, "%s: Receive High Congestion\n", name);
- break;
- }
-
case NET_RX_DROP:
{
dbg(DBG_ASS, "%s: Received packet dropped\n", name);
@@ -2313,7 +2294,7 @@ fst_start_xmit(struct sk_buff *skb, struct net_device *dev)
dbg(DBG_ASS,
"Tried to transmit but no carrier on card %d port %d\n",
card->card_no, port->index);
- return 0;
+ return NETDEV_TX_OK;
}
/* Drop it if it's too big! MTU failure ? */
@@ -2322,7 +2303,7 @@ fst_start_xmit(struct sk_buff *skb, struct net_device *dev)
LEN_TX_BUFFER);
dev_kfree_skb(skb);
dev->stats.tx_errors++;
- return 0;
+ return NETDEV_TX_OK;
}
/*
@@ -2356,7 +2337,7 @@ fst_start_xmit(struct sk_buff *skb, struct net_device *dev)
dev->stats.tx_errors++;
dbg(DBG_ASS, "Tx queue overflow card %d port %d\n",
card->card_no, port->index);
- return 0;
+ return NETDEV_TX_OK;
}
/*
@@ -2373,7 +2354,7 @@ fst_start_xmit(struct sk_buff *skb, struct net_device *dev)
fst_q_work_item(&fst_work_txq, card->card_no);
tasklet_schedule(&fst_tx_task);
- return 0;
+ return NETDEV_TX_OK;
}
/*
diff --git a/drivers/net/wan/hdlc_fr.c b/drivers/net/wan/hdlc_fr.c
index bfa0161a02d..52438c76bf8 100644
--- a/drivers/net/wan/hdlc_fr.c
+++ b/drivers/net/wan/hdlc_fr.c
@@ -421,7 +421,7 @@ static int pvc_xmit(struct sk_buff *skb, struct net_device *dev)
GFP_ATOMIC)) {
dev->stats.tx_dropped++;
dev_kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
}
skb_put(skb, pad);
memset(skb->data + len, 0, pad);
@@ -435,13 +435,13 @@ static int pvc_xmit(struct sk_buff *skb, struct net_device *dev)
dev->stats.tx_compressed++;
skb->dev = pvc->frad;
dev_queue_xmit(skb);
- return 0;
+ return NETDEV_TX_OK;
}
}
dev->stats.tx_dropped++;
dev_kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
}
static inline void fr_log_dlci_active(pvc_device *pvc)
diff --git a/drivers/net/wan/lmc/lmc_main.c b/drivers/net/wan/lmc/lmc_main.c
index 45b1822c962..6e6b08c3a1e 100644
--- a/drivers/net/wan/lmc/lmc_main.c
+++ b/drivers/net/wan/lmc/lmc_main.c
@@ -1428,7 +1428,7 @@ static int lmc_start_xmit(struct sk_buff *skb, struct net_device *dev)
lmc_softc_t *sc = dev_to_sc(dev);
u32 flag;
int entry;
- int ret = 0;
+ int ret = NETDEV_TX_OK;
unsigned long flags;
lmc_trace(dev, "lmc_start_xmit in");
@@ -1897,11 +1897,12 @@ static void lmc_softreset (lmc_softc_t * const sc) /*fold00*/
/*
* Sets end of ring
*/
- sc->lmc_rxring[i - 1].length |= 0x02000000; /* Set end of buffers flag */
- sc->lmc_rxring[i - 1].buffer2 = virt_to_bus (&sc->lmc_rxring[0]); /* Point back to the start */
+ if (i != 0) {
+ sc->lmc_rxring[i - 1].length |= 0x02000000; /* Set end of buffers flag */
+ sc->lmc_rxring[i - 1].buffer2 = virt_to_bus(&sc->lmc_rxring[0]); /* Point back to the start */
+ }
LMC_CSR_WRITE (sc, csr_rxlist, virt_to_bus (sc->lmc_rxring)); /* write base address */
-
/* Initialize the transmit rings and buffers */
for (i = 0; i < LMC_TXDESCS; i++)
{
diff --git a/drivers/net/wan/sbni.c b/drivers/net/wan/sbni.c
index d14e95a08d6..85c02a2ec2e 100644
--- a/drivers/net/wan/sbni.c
+++ b/drivers/net/wan/sbni.c
@@ -463,7 +463,7 @@ sbni_start_xmit( struct sk_buff *skb, struct net_device *dev )
prepare_to_send( skb, p );
spin_unlock( &nl->lock );
netif_start_queue( dev );
- return 0;
+ return NETDEV_TX_OK;
}
}
@@ -483,7 +483,7 @@ sbni_start_xmit( struct sk_buff *skb, struct net_device *dev )
prepare_to_send( skb, dev );
spin_unlock( &nl->lock );
- return 0;
+ return NETDEV_TX_OK;
}
#endif /* CONFIG_SBNI_MULTILINE */
diff --git a/drivers/net/wan/wanxl.c b/drivers/net/wan/wanxl.c
index e4ad7b6b52e..03b76adbe5f 100644
--- a/drivers/net/wan/wanxl.c
+++ b/drivers/net/wan/wanxl.c
@@ -310,7 +310,7 @@ static int wanxl_xmit(struct sk_buff *skb, struct net_device *dev)
}
spin_unlock(&port->lock);
- return 0;
+ return NETDEV_TX_OK;
}
diff --git a/drivers/net/wan/x25_asy.c b/drivers/net/wan/x25_asy.c
index d67e208ab37..1047920e742 100644
--- a/drivers/net/wan/x25_asy.c
+++ b/drivers/net/wan/x25_asy.c
@@ -308,7 +308,7 @@ static int x25_asy_xmit(struct sk_buff *skb, struct net_device *dev)
printk(KERN_ERR "%s: xmit call when iface is down\n",
dev->name);
kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
}
switch (skb->data[0]) {
@@ -319,14 +319,14 @@ static int x25_asy_xmit(struct sk_buff *skb, struct net_device *dev)
if (err != LAPB_OK)
printk(KERN_ERR "x25_asy: lapb_connect_request error - %d\n", err);
kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
case 0x02: /* Disconnect request .. do nothing - hang up ?? */
err = lapb_disconnect_request(dev);
if (err != LAPB_OK)
printk(KERN_ERR "x25_asy: lapb_disconnect_request error - %d\n", err);
default:
kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
}
skb_pull(skb, 1); /* Remove control byte */
/*
@@ -344,9 +344,9 @@ static int x25_asy_xmit(struct sk_buff *skb, struct net_device *dev)
if (err != LAPB_OK) {
printk(KERN_ERR "x25_asy: lapb_data_request error - %d\n", err);
kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
}
- return 0;
+ return NETDEV_TX_OK;
}
diff --git a/drivers/net/wimax/i2400m/sdio.c b/drivers/net/wimax/i2400m/sdio.c
index 2538825d1c6..ea7b29034aa 100644
--- a/drivers/net/wimax/i2400m/sdio.c
+++ b/drivers/net/wimax/i2400m/sdio.c
@@ -58,6 +58,7 @@
*/
#include <linux/debugfs.h>
+#include <linux/mmc/sdio_ids.h>
#include <linux/mmc/sdio.h>
#include <linux/mmc/sdio_func.h>
#include "i2400m-sdio.h"
@@ -501,15 +502,12 @@ void i2400ms_remove(struct sdio_func *func)
d_fnend(3, dev, "SDIO func %p\n", func);
}
-enum {
- I2400MS_INTEL_VID = 0x89,
-};
-
static
const struct sdio_device_id i2400ms_sdio_ids[] = {
- /* Intel: i2400m WiMAX over SDIO */
- { SDIO_DEVICE(I2400MS_INTEL_VID, 0x1402) },
- { }, /* end: all zeroes */
+ /* Intel: i2400m WiMAX (iwmc3200) over SDIO */
+ { SDIO_DEVICE(SDIO_VENDOR_ID_INTEL,
+ SDIO_DEVICE_ID_INTEL_IWMC3200WIMAX) },
+ { /* end: all zeroes */ },
};
MODULE_DEVICE_TABLE(sdio, i2400ms_sdio_ids);
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig
index 5bc00db21b2..dda7cc2e1f5 100644
--- a/drivers/net/wireless/Kconfig
+++ b/drivers/net/wireless/Kconfig
@@ -5,7 +5,7 @@
menu "Wireless LAN"
depends on !S390
-config WLAN_PRE80211
+menuconfig WLAN_PRE80211
bool "Wireless LAN (pre-802.11)"
depends on NETDEVICES
---help---
@@ -101,7 +101,7 @@ config PCMCIA_NETWAVE
called netwave_cs. If unsure, say N.
-config WLAN_80211
+menuconfig WLAN_80211
bool "Wireless LAN (IEEE 802.11)"
depends on NETDEVICES
---help---
@@ -428,10 +428,12 @@ config RTL8187
Micronet SP907GK V5
Encore ENUWI-G2
Trendnet TEW-424UB
- ASUS P5B Deluxe
+ ASUS P5B Deluxe/P5K Premium motherboards
Toshiba Satellite Pro series of laptops
Asus Wireless Link
- Linksys WUSB54GC-EU
+ Linksys WUSB54GC-EU v2
+ (v1 = rt73usb; v3 is rt2070-based,
+ use staging/rt3070 or try rt2800usb)
Thanks to Realtek for their support!
diff --git a/drivers/net/wireless/adm8211.c b/drivers/net/wireless/adm8211.c
index 2b9e379994a..5695911bc60 100644
--- a/drivers/net/wireless/adm8211.c
+++ b/drivers/net/wireless/adm8211.c
@@ -452,7 +452,8 @@ static void adm8211_interrupt_rci(struct ieee80211_hw *dev)
rx_status.freq = adm8211_channels[priv->channel - 1].center_freq;
rx_status.band = IEEE80211_BAND_2GHZ;
- ieee80211_rx_irqsafe(dev, skb, &rx_status);
+ memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status));
+ ieee80211_rx_irqsafe(dev, skb);
}
entry = (++priv->cur_rx) % priv->rx_ring_size;
@@ -1963,14 +1964,6 @@ static void __devexit adm8211_remove(struct pci_dev *pdev)
#ifdef CONFIG_PM
static int adm8211_suspend(struct pci_dev *pdev, pm_message_t state)
{
- struct ieee80211_hw *dev = pci_get_drvdata(pdev);
- struct adm8211_priv *priv = dev->priv;
-
- if (priv->mode != NL80211_IFTYPE_UNSPECIFIED) {
- ieee80211_stop_queues(dev);
- adm8211_stop(dev);
- }
-
pci_save_state(pdev);
pci_set_power_state(pdev, pci_choose_state(pdev, state));
return 0;
@@ -1978,17 +1971,8 @@ static int adm8211_suspend(struct pci_dev *pdev, pm_message_t state)
static int adm8211_resume(struct pci_dev *pdev)
{
- struct ieee80211_hw *dev = pci_get_drvdata(pdev);
- struct adm8211_priv *priv = dev->priv;
-
pci_set_power_state(pdev, PCI_D0);
pci_restore_state(pdev);
-
- if (priv->mode != NL80211_IFTYPE_UNSPECIFIED) {
- adm8211_start(dev);
- ieee80211_wake_queues(dev);
- }
-
return 0;
}
#endif /* CONFIG_PM */
diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c
index 8ce5e4cee16..c150c485857 100644
--- a/drivers/net/wireless/airo.c
+++ b/drivers/net/wireless/airo.c
@@ -1927,7 +1927,7 @@ static int mpi_start_xmit(struct sk_buff *skb, struct net_device *dev) {
if (!skb) {
airo_print_err(dev->name, "%s: skb == NULL!",__func__);
- return 0;
+ return NETDEV_TX_OK;
}
npacks = skb_queue_len (&ai->txq);
@@ -1938,7 +1938,7 @@ static int mpi_start_xmit(struct sk_buff *skb, struct net_device *dev) {
return NETDEV_TX_BUSY;
}
skb_queue_tail (&ai->txq, skb);
- return 0;
+ return NETDEV_TX_OK;
}
spin_lock_irqsave(&ai->aux_lock, flags);
@@ -1951,7 +1951,7 @@ static int mpi_start_xmit(struct sk_buff *skb, struct net_device *dev) {
set_bit(FLAG_PENDING_XMIT, &ai->flags);
mpi_send_packet (dev);
}
- return 0;
+ return NETDEV_TX_OK;
}
/*
@@ -2127,7 +2127,7 @@ static int airo_start_xmit(struct sk_buff *skb, struct net_device *dev) {
if ( skb == NULL ) {
airo_print_err(dev->name, "%s: skb == NULL!", __func__);
- return 0;
+ return NETDEV_TX_OK;
}
/* Find a vacant FID */
@@ -2155,7 +2155,7 @@ static int airo_start_xmit(struct sk_buff *skb, struct net_device *dev) {
wake_up_interruptible(&priv->thr_wait);
} else
airo_end_xmit(dev);
- return 0;
+ return NETDEV_TX_OK;
}
static void airo_end_xmit11(struct net_device *dev) {
@@ -2199,7 +2199,7 @@ static int airo_start_xmit11(struct sk_buff *skb, struct net_device *dev) {
if ( skb == NULL ) {
airo_print_err(dev->name, "%s: skb == NULL!", __func__);
- return 0;
+ return NETDEV_TX_OK;
}
/* Find a vacant FID */
@@ -2227,7 +2227,7 @@ static int airo_start_xmit11(struct sk_buff *skb, struct net_device *dev) {
wake_up_interruptible(&priv->thr_wait);
} else
airo_end_xmit11(dev);
- return 0;
+ return NETDEV_TX_OK;
}
static void airo_read_stats(struct net_device *dev)
diff --git a/drivers/net/wireless/arlan-main.c b/drivers/net/wireless/arlan-main.c
index d84caf198a2..f96c634e2d3 100644
--- a/drivers/net/wireless/arlan-main.c
+++ b/drivers/net/wireless/arlan-main.c
@@ -1022,7 +1022,7 @@ static int arlan_mac_addr(struct net_device *dev, void *p)
ARLAN_DEBUG_ENTRY("arlan_mac_addr");
return -EINVAL;
- if (!netif_running(dev))
+ if (netif_running(dev))
return -EBUSY;
memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
@@ -1193,7 +1193,7 @@ static int arlan_tx(struct sk_buff *skb, struct net_device *dev)
arlan_process_interrupt(dev);
ARLAN_DEBUG_EXIT("arlan_tx");
- return 0;
+ return NETDEV_TX_OK;
bad_end:
arlan_process_interrupt(dev);
diff --git a/drivers/net/wireless/at76c50x-usb.c b/drivers/net/wireless/at76c50x-usb.c
index 4efbdbe6d6b..7218dbabad3 100644
--- a/drivers/net/wireless/at76c50x-usb.c
+++ b/drivers/net/wireless/at76c50x-usb.c
@@ -1568,7 +1568,8 @@ static void at76_rx_tasklet(unsigned long param)
at76_dbg(DBG_MAC80211, "calling ieee80211_rx_irqsafe(): %d/%d",
priv->rx_skb->len, priv->rx_skb->data_len);
- ieee80211_rx_irqsafe(priv->hw, priv->rx_skb, &rx_status);
+ memcpy(IEEE80211_SKB_RXCB(priv->rx_skb), &rx_status, sizeof(rx_status));
+ ieee80211_rx_irqsafe(priv->hw, priv->rx_skb);
/* Use a new skb for the next receive */
priv->rx_skb = NULL;
@@ -1772,6 +1773,9 @@ static void at76_mac80211_stop(struct ieee80211_hw *hw)
at76_dbg(DBG_MAC80211, "%s()", __func__);
+ cancel_delayed_work(&priv->dwork_hw_scan);
+ cancel_work_sync(&priv->work_set_promisc);
+
mutex_lock(&priv->mtx);
if (!priv->device_unplugged) {
@@ -1871,8 +1875,8 @@ static void at76_dwork_hw_scan(struct work_struct *work)
/* FIXME: add maximum time for scan to complete */
if (ret != CMD_STATUS_COMPLETE) {
- queue_delayed_work(priv->hw->workqueue, &priv->dwork_hw_scan,
- SCAN_POLL_INTERVAL);
+ ieee80211_queue_delayed_work(priv->hw, &priv->dwork_hw_scan,
+ SCAN_POLL_INTERVAL);
mutex_unlock(&priv->mtx);
return;
}
@@ -1933,8 +1937,8 @@ static int at76_hw_scan(struct ieee80211_hw *hw,
goto exit;
}
- queue_delayed_work(priv->hw->workqueue, &priv->dwork_hw_scan,
- SCAN_POLL_INTERVAL);
+ ieee80211_queue_delayed_work(priv->hw, &priv->dwork_hw_scan,
+ SCAN_POLL_INTERVAL);
exit:
mutex_unlock(&priv->mtx);
@@ -2023,7 +2027,7 @@ static void at76_configure_filter(struct ieee80211_hw *hw,
} else
return;
- queue_work(hw->workqueue, &priv->work_set_promisc);
+ ieee80211_queue_work(hw, &priv->work_set_promisc);
}
static int at76_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
@@ -2294,11 +2298,8 @@ static void at76_delete_device(struct at76_priv *priv)
tasklet_kill(&priv->rx_tasklet);
- if (priv->mac80211_registered) {
- cancel_delayed_work(&priv->dwork_hw_scan);
- flush_workqueue(priv->hw->workqueue);
+ if (priv->mac80211_registered)
ieee80211_unregister_hw(priv->hw);
- }
if (priv->tx_urb) {
usb_kill_urb(priv->tx_urb);
diff --git a/drivers/net/wireless/ath/Kconfig b/drivers/net/wireless/ath/Kconfig
index eb0337c4954..11ded150b93 100644
--- a/drivers/net/wireless/ath/Kconfig
+++ b/drivers/net/wireless/ath/Kconfig
@@ -1,9 +1,22 @@
-config ATH_COMMON
+menuconfig ATH_COMMON
tristate "Atheros Wireless Cards"
depends on WLAN_80211
- depends on ATH5K || ATH9K || AR9170_USB
+ depends on CFG80211
+ ---help---
+ This will enable the support for the Atheros wireless drivers.
+ ath5k, ath9k and ar9170 drivers share some common code, this option
+ enables the common ath.ko module which shares common helpers.
+ For more information and documentation on this module you can visit:
+
+ http://wireless.kernel.org/en/users/Drivers/ath
+
+ For information on all Atheros wireless drivers visit:
+
+ http://wireless.kernel.org/en/users/Drivers/Atheros
+
+if ATH_COMMON
source "drivers/net/wireless/ath/ath5k/Kconfig"
source "drivers/net/wireless/ath/ath9k/Kconfig"
source "drivers/net/wireless/ath/ar9170/Kconfig"
-
+endif
diff --git a/drivers/net/wireless/ath/ar9170/Kconfig b/drivers/net/wireless/ath/ar9170/Kconfig
index b99e3263ee6..05918f1e685 100644
--- a/drivers/net/wireless/ath/ar9170/Kconfig
+++ b/drivers/net/wireless/ath/ar9170/Kconfig
@@ -1,13 +1,13 @@
config AR9170_USB
tristate "Atheros AR9170 802.11n USB support"
- depends on USB && MAC80211 && WLAN_80211 && EXPERIMENTAL
+ depends on USB && MAC80211 && WLAN_80211
select FW_LOADER
- select ATH_COMMON
help
This is a driver for the Atheros "otus" 802.11n USB devices.
These devices require additional firmware (2 files).
For now, these files can be downloaded from here:
+
http://wireless.kernel.org/en/users/Drivers/ar9170
If you choose to build a module, it'll be called ar9170usb.
diff --git a/drivers/net/wireless/ath/ar9170/ar9170.h b/drivers/net/wireless/ath/ar9170/ar9170.h
index bb97981fb24..e6c3ee3e058 100644
--- a/drivers/net/wireless/ath/ar9170/ar9170.h
+++ b/drivers/net/wireless/ath/ar9170/ar9170.h
@@ -109,11 +109,52 @@ struct ar9170_rxstream_mpdu_merge {
bool has_plcp;
};
+#define AR9170_NUM_MAX_BA_RETRY 5
+#define AR9170_NUM_TID 16
+#define WME_BA_BMP_SIZE 64
+#define AR9170_NUM_MAX_AGG_LEN (2 * WME_BA_BMP_SIZE)
+
+#define WME_AC_BE 2
+#define WME_AC_BK 3
+#define WME_AC_VI 1
+#define WME_AC_VO 0
+
+#define TID_TO_WME_AC(_tid) \
+ ((((_tid) == 0) || ((_tid) == 3)) ? WME_AC_BE : \
+ (((_tid) == 1) || ((_tid) == 2)) ? WME_AC_BK : \
+ (((_tid) == 4) || ((_tid) == 5)) ? WME_AC_VI : \
+ WME_AC_VO)
+
+#define BAW_WITHIN(_start, _bawsz, _seqno) \
+ ((((_seqno) - (_start)) & 0xfff) < (_bawsz))
+
+enum ar9170_tid_state {
+ AR9170_TID_STATE_INVALID,
+ AR9170_TID_STATE_SHUTDOWN,
+ AR9170_TID_STATE_PROGRESS,
+ AR9170_TID_STATE_COMPLETE,
+};
+
+struct ar9170_sta_tid {
+ struct list_head list;
+ struct sk_buff_head queue;
+ u8 addr[ETH_ALEN];
+ u16 ssn;
+ u16 tid;
+ enum ar9170_tid_state state;
+ bool active;
+ u8 retry;
+};
+
#define AR9170_QUEUE_TIMEOUT 64
#define AR9170_TX_TIMEOUT 8
+#define AR9170_BA_TIMEOUT 4
#define AR9170_JANITOR_DELAY 128
#define AR9170_TX_INVALID_RATE 0xffffffff
+#define AR9170_NUM_TX_STATUS 128
+#define AR9170_NUM_TX_AGG_MAX 30
+
struct ar9170 {
struct ieee80211_hw *hw;
struct mutex mutex;
@@ -187,14 +228,25 @@ struct ar9170 {
struct sk_buff_head tx_pending[__AR9170_NUM_TXQ];
struct sk_buff_head tx_status[__AR9170_NUM_TXQ];
struct delayed_work tx_janitor;
+ /* tx ampdu */
+ struct sk_buff_head tx_status_ampdu;
+ spinlock_t tx_ampdu_list_lock;
+ struct list_head tx_ampdu_list;
+ unsigned int tx_ampdu_pending;
/* rxstream mpdu merge */
struct ar9170_rxstream_mpdu_merge rx_mpdu;
struct sk_buff *rx_failover;
int rx_failover_missing;
+
+ /* (cached) HW A-MPDU settings */
+ u8 global_ampdu_density;
+ u8 global_ampdu_factor;
};
struct ar9170_sta_info {
+ struct ar9170_sta_tid agg[AR9170_NUM_TID];
+ unsigned int ampdu_max_len;
};
#define AR9170_TX_FLAG_WAIT_FOR_ACK BIT(0)
diff --git a/drivers/net/wireless/ath/ar9170/led.c b/drivers/net/wireless/ath/ar9170/led.c
index 63fda6cd210..86c4e79f6bc 100644
--- a/drivers/net/wireless/ath/ar9170/led.c
+++ b/drivers/net/wireless/ath/ar9170/led.c
@@ -90,9 +90,12 @@ static void ar9170_update_leds(struct work_struct *work)
ar9170_set_leds_state(ar, led_val);
mutex_unlock(&ar->mutex);
- if (rerun)
- queue_delayed_work(ar->hw->workqueue, &ar->led_work,
- msecs_to_jiffies(blink_delay));
+ if (!rerun)
+ return;
+
+ ieee80211_queue_delayed_work(ar->hw,
+ &ar->led_work,
+ msecs_to_jiffies(blink_delay));
}
static void ar9170_led_brightness_set(struct led_classdev *led,
@@ -110,7 +113,7 @@ static void ar9170_led_brightness_set(struct led_classdev *led,
}
if (likely(IS_ACCEPTING_CMD(ar) && arl->toggled))
- queue_delayed_work(ar->hw->workqueue, &ar->led_work, HZ/10);
+ ieee80211_queue_delayed_work(ar->hw, &ar->led_work, HZ/10);
}
static int ar9170_register_led(struct ar9170 *ar, int i, char *name,
diff --git a/drivers/net/wireless/ath/ar9170/main.c b/drivers/net/wireless/ath/ar9170/main.c
index 88c3d857386..ea8c9419336 100644
--- a/drivers/net/wireless/ath/ar9170/main.c
+++ b/drivers/net/wireless/ath/ar9170/main.c
@@ -49,6 +49,10 @@ static int modparam_nohwcrypt;
module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO);
MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption.");
+static int modparam_ht;
+module_param_named(ht, modparam_ht, bool, S_IRUGO);
+MODULE_PARM_DESC(ht, "enable MPDU aggregation.");
+
#define RATE(_bitrate, _hw_rate, _txpidx, _flags) { \
.bitrate = (_bitrate), \
.flags = (_flags), \
@@ -148,12 +152,15 @@ static struct ieee80211_channel ar9170_5ghz_chantable[] = {
.cap = IEEE80211_HT_CAP_MAX_AMSDU | \
IEEE80211_HT_CAP_SUP_WIDTH_20_40 | \
IEEE80211_HT_CAP_SGI_40 | \
+ IEEE80211_HT_CAP_GRN_FLD | \
IEEE80211_HT_CAP_DSSSCCK40 | \
IEEE80211_HT_CAP_SM_PS, \
.ampdu_factor = 3, \
.ampdu_density = 6, \
.mcs = { \
- .rx_mask = { 0xFF, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0, }, \
+ .rx_mask = { 0xff, 0xff, 0, 0, 0x1, 0, 0, 0, 0, 0, }, \
+ .rx_highest = cpu_to_le16(300), \
+ .tx_params = IEEE80211_HT_MCS_TX_DEFINED, \
}, \
}
@@ -174,8 +181,31 @@ static struct ieee80211_supported_band ar9170_band_5GHz = {
};
static void ar9170_tx(struct ar9170 *ar);
+static bool ar9170_tx_ampdu(struct ar9170 *ar);
-#ifdef AR9170_QUEUE_DEBUG
+static inline u16 ar9170_get_seq_h(struct ieee80211_hdr *hdr)
+{
+ return le16_to_cpu(hdr->seq_ctrl) >> 4;
+}
+
+static inline u16 ar9170_get_seq(struct sk_buff *skb)
+{
+ struct ar9170_tx_control *txc = (void *) skb->data;
+ return ar9170_get_seq_h((void *) txc->frame_data);
+}
+
+static inline u16 ar9170_get_tid(struct sk_buff *skb)
+{
+ struct ar9170_tx_control *txc = (void *) skb->data;
+ struct ieee80211_hdr *hdr = (void *) txc->frame_data;
+
+ return (ieee80211_get_qos_ctl(hdr))[0] & IEEE80211_QOS_CTL_TID_MASK;
+}
+
+#define GET_NEXT_SEQ(seq) ((seq + 1) & 0x0fff)
+#define GET_NEXT_SEQ_FROM_SKB(skb) (GET_NEXT_SEQ(ar9170_get_seq(skb)))
+
+#if (defined AR9170_QUEUE_DEBUG) || (defined AR9170_TXAGG_DEBUG)
static void ar9170_print_txheader(struct ar9170 *ar, struct sk_buff *skb)
{
struct ar9170_tx_control *txc = (void *) skb->data;
@@ -183,10 +213,10 @@ static void ar9170_print_txheader(struct ar9170 *ar, struct sk_buff *skb)
struct ar9170_tx_info *arinfo = (void *) txinfo->rate_driver_data;
struct ieee80211_hdr *hdr = (void *) txc->frame_data;
- printk(KERN_DEBUG "%s: => FRAME [skb:%p, q:%d, DA:[%pM] flags:%x "
+ printk(KERN_DEBUG "%s: => FRAME [skb:%p, q:%d, DA:[%pM] flags:%x s:%d "
"mac_ctrl:%04x, phy_ctrl:%08x, timeout:[%d ms]]\n",
wiphy_name(ar->hw->wiphy), skb, skb_get_queue_mapping(skb),
- ieee80211_get_DA(hdr), arinfo->flags,
+ ieee80211_get_DA(hdr), arinfo->flags, ar9170_get_seq_h(hdr),
le16_to_cpu(txc->mac_control), le32_to_cpu(txc->phy_control),
jiffies_to_msecs(arinfo->timeout - jiffies));
}
@@ -210,7 +240,9 @@ static void __ar9170_dump_txqueue(struct ar9170 *ar,
"mismatch %d != %d\n", skb_queue_len(queue), i);
printk(KERN_DEBUG "---[ end ]---\n");
}
+#endif /* AR9170_QUEUE_DEBUG || AR9170_TXAGG_DEBUG */
+#ifdef AR9170_QUEUE_DEBUG
static void ar9170_dump_txqueue(struct ar9170 *ar,
struct sk_buff_head *queue)
{
@@ -220,7 +252,9 @@ static void ar9170_dump_txqueue(struct ar9170 *ar,
__ar9170_dump_txqueue(ar, queue);
spin_unlock_irqrestore(&queue->lock, flags);
}
+#endif /* AR9170_QUEUE_DEBUG */
+#ifdef AR9170_QUEUE_STOP_DEBUG
static void __ar9170_dump_txstats(struct ar9170 *ar)
{
int i;
@@ -229,20 +263,27 @@ static void __ar9170_dump_txstats(struct ar9170 *ar)
wiphy_name(ar->hw->wiphy));
for (i = 0; i < __AR9170_NUM_TXQ; i++)
- printk(KERN_DEBUG "%s: queue:%d limit:%d len:%d waitack:%d\n",
- wiphy_name(ar->hw->wiphy), i, ar->tx_stats[i].limit,
- ar->tx_stats[i].len, skb_queue_len(&ar->tx_status[i]));
+ printk(KERN_DEBUG "%s: queue:%d limit:%d len:%d waitack:%d "
+ " stopped:%d\n", wiphy_name(ar->hw->wiphy), i,
+ ar->tx_stats[i].limit, ar->tx_stats[i].len,
+ skb_queue_len(&ar->tx_status[i]),
+ ieee80211_queue_stopped(ar->hw, i));
}
+#endif /* AR9170_QUEUE_STOP_DEBUG */
-static void ar9170_dump_txstats(struct ar9170 *ar)
+#ifdef AR9170_TXAGG_DEBUG
+static void ar9170_dump_tx_status_ampdu(struct ar9170 *ar)
{
unsigned long flags;
- spin_lock_irqsave(&ar->tx_stats_lock, flags);
- __ar9170_dump_txstats(ar);
- spin_unlock_irqrestore(&ar->tx_stats_lock, flags);
+ spin_lock_irqsave(&ar->tx_status_ampdu.lock, flags);
+ printk(KERN_DEBUG "%s: A-MPDU tx_status queue => \n",
+ wiphy_name(ar->hw->wiphy));
+ __ar9170_dump_txqueue(ar, &ar->tx_status_ampdu);
+ spin_unlock_irqrestore(&ar->tx_status_ampdu.lock, flags);
}
-#endif /* AR9170_QUEUE_DEBUG */
+
+#endif /* AR9170_TXAGG_DEBUG */
/* caller must guarantee exclusive access for _bin_ queue. */
static void ar9170_recycle_expired(struct ar9170 *ar,
@@ -315,6 +356,70 @@ static void ar9170_tx_status(struct ar9170 *ar, struct sk_buff *skb,
ieee80211_tx_status_irqsafe(ar->hw, skb);
}
+static void ar9170_tx_fake_ampdu_status(struct ar9170 *ar)
+{
+ struct sk_buff_head success;
+ struct sk_buff *skb;
+ unsigned int i;
+ unsigned long queue_bitmap = 0;
+
+ skb_queue_head_init(&success);
+
+ while (skb_queue_len(&ar->tx_status_ampdu) > AR9170_NUM_TX_STATUS)
+ __skb_queue_tail(&success, skb_dequeue(&ar->tx_status_ampdu));
+
+ ar9170_recycle_expired(ar, &ar->tx_status_ampdu, &success);
+
+#ifdef AR9170_TXAGG_DEBUG
+ printk(KERN_DEBUG "%s: collected %d A-MPDU frames.\n",
+ wiphy_name(ar->hw->wiphy), skb_queue_len(&success));
+ __ar9170_dump_txqueue(ar, &success);
+#endif /* AR9170_TXAGG_DEBUG */
+
+ while ((skb = __skb_dequeue(&success))) {
+ struct ieee80211_tx_info *txinfo;
+
+ queue_bitmap |= BIT(skb_get_queue_mapping(skb));
+
+ txinfo = IEEE80211_SKB_CB(skb);
+ ieee80211_tx_info_clear_status(txinfo);
+
+ txinfo->flags |= IEEE80211_TX_STAT_ACK;
+ txinfo->status.rates[0].count = 1;
+
+ skb_pull(skb, sizeof(struct ar9170_tx_control));
+ ieee80211_tx_status_irqsafe(ar->hw, skb);
+ }
+
+ for_each_bit(i, &queue_bitmap, BITS_PER_BYTE) {
+#ifdef AR9170_QUEUE_STOP_DEBUG
+ printk(KERN_DEBUG "%s: wake queue %d\n",
+ wiphy_name(ar->hw->wiphy), i);
+ __ar9170_dump_txstats(ar);
+#endif /* AR9170_QUEUE_STOP_DEBUG */
+ ieee80211_wake_queue(ar->hw, i);
+ }
+
+ if (queue_bitmap)
+ ar9170_tx(ar);
+}
+
+static void ar9170_tx_ampdu_callback(struct ar9170 *ar, struct sk_buff *skb)
+{
+ struct ieee80211_tx_info *txinfo = IEEE80211_SKB_CB(skb);
+ struct ar9170_tx_info *arinfo = (void *) txinfo->rate_driver_data;
+
+ arinfo->timeout = jiffies +
+ msecs_to_jiffies(AR9170_BA_TIMEOUT);
+
+ skb_queue_tail(&ar->tx_status_ampdu, skb);
+ ar9170_tx_fake_ampdu_status(ar);
+ ar->tx_ampdu_pending--;
+
+ if (!list_empty(&ar->tx_ampdu_list) && !ar->tx_ampdu_pending)
+ ar9170_tx_ampdu(ar);
+}
+
void ar9170_tx_callback(struct ar9170 *ar, struct sk_buff *skb)
{
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
@@ -336,7 +441,7 @@ void ar9170_tx_callback(struct ar9170 *ar, struct sk_buff *skb)
spin_unlock_irqrestore(&ar->tx_stats_lock, flags);
if (arinfo->flags & AR9170_TX_FLAG_BLOCK_ACK) {
- dev_kfree_skb_any(skb);
+ ar9170_tx_ampdu_callback(ar, skb);
} else if (arinfo->flags & AR9170_TX_FLAG_WAIT_FOR_ACK) {
arinfo->timeout = jiffies +
msecs_to_jiffies(AR9170_TX_TIMEOUT);
@@ -420,6 +525,38 @@ static struct sk_buff *ar9170_get_queued_skb(struct ar9170 *ar,
return NULL;
}
+static void ar9170_handle_block_ack(struct ar9170 *ar, u16 count, u16 r)
+{
+ struct sk_buff *skb;
+ struct ieee80211_tx_info *txinfo;
+
+ while (count) {
+ skb = ar9170_get_queued_skb(ar, NULL, &ar->tx_status_ampdu, r);
+ if (!skb)
+ break;
+
+ txinfo = IEEE80211_SKB_CB(skb);
+ ieee80211_tx_info_clear_status(txinfo);
+
+ /* FIXME: maybe more ? */
+ txinfo->status.rates[0].count = 1;
+
+ skb_pull(skb, sizeof(struct ar9170_tx_control));
+ ieee80211_tx_status_irqsafe(ar->hw, skb);
+ count--;
+ }
+
+#ifdef AR9170_TXAGG_DEBUG
+ if (count) {
+ printk(KERN_DEBUG "%s: got %d more failed mpdus, but no more "
+ "suitable frames left in tx_status queue.\n",
+ wiphy_name(ar->hw->wiphy), count);
+
+ ar9170_dump_tx_status_ampdu(ar);
+ }
+#endif /* AR9170_TXAGG_DEBUG */
+}
+
/*
* This worker tries to keeps an maintain tx_status queues.
* So we can guarantee that incoming tx_status reports are
@@ -456,10 +593,14 @@ static void ar9170_tx_janitor(struct work_struct *work)
resched = true;
}
- if (resched)
- queue_delayed_work(ar->hw->workqueue,
- &ar->tx_janitor,
- msecs_to_jiffies(AR9170_JANITOR_DELAY));
+ ar9170_tx_fake_ampdu_status(ar);
+
+ if (!resched)
+ return;
+
+ ieee80211_queue_delayed_work(ar->hw,
+ &ar->tx_janitor,
+ msecs_to_jiffies(AR9170_JANITOR_DELAY));
}
void ar9170_handle_command_response(struct ar9170 *ar, void *buf, u32 len)
@@ -509,7 +650,7 @@ void ar9170_handle_command_response(struct ar9170 *ar, void *buf, u32 len)
* pre-TBTT event
*/
if (ar->vif && ar->vif->type == NL80211_IFTYPE_AP)
- queue_work(ar->hw->workqueue, &ar->beacon_work);
+ ieee80211_queue_work(ar->hw, &ar->beacon_work);
break;
case 0xc2:
@@ -528,8 +669,15 @@ void ar9170_handle_command_response(struct ar9170 *ar, void *buf, u32 len)
break;
case 0xc4:
+ /* BlockACK bitmap */
+ break;
+
case 0xc5:
/* BlockACK events */
+ ar9170_handle_block_ack(ar,
+ le16_to_cpu(cmd->ba_fail_cnt.failed),
+ le16_to_cpu(cmd->ba_fail_cnt.rate));
+ ar9170_tx_fake_ampdu_status(ar);
break;
case 0xc6:
@@ -917,8 +1065,10 @@ static void ar9170_handle_mpdu(struct ar9170 *ar, u8 *buf, int len)
ar9170_rx_phy_status(ar, phy, &status);
skb = ar9170_rx_copy_data(buf, mpdu_len);
- if (likely(skb))
- ieee80211_rx_irqsafe(ar->hw, skb, &status);
+ if (likely(skb)) {
+ memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status));
+ ieee80211_rx_irqsafe(ar->hw, skb);
+ }
}
void ar9170_rx(struct ar9170 *ar, struct sk_buff *skb)
@@ -1096,6 +1246,10 @@ static int ar9170_op_start(struct ieee80211_hw *hw)
AR9170_FILL_QUEUE(ar->edcf[3], 2, 3, 7, 47); /* VOICE */
AR9170_FILL_QUEUE(ar->edcf[4], 2, 3, 7, 0); /* SPECIAL */
+ /* set sane AMPDU defaults */
+ ar->global_ampdu_density = 6;
+ ar->global_ampdu_factor = 3;
+
ar->bad_hw_nagger = jiffies;
err = ar->open(ar);
@@ -1138,11 +1292,13 @@ static void ar9170_op_stop(struct ieee80211_hw *hw)
if (IS_STARTED(ar))
ar->state = AR9170_IDLE;
- flush_workqueue(ar->hw->workqueue);
-
cancel_delayed_work_sync(&ar->tx_janitor);
+#ifdef CONFIG_AR9170_LEDS
+ cancel_delayed_work_sync(&ar->led_work);
+#endif
cancel_work_sync(&ar->filter_config_work);
cancel_work_sync(&ar->beacon_work);
+
mutex_lock(&ar->mutex);
if (IS_ACCEPTING_CMD(ar)) {
@@ -1157,9 +1313,40 @@ static void ar9170_op_stop(struct ieee80211_hw *hw)
skb_queue_purge(&ar->tx_pending[i]);
skb_queue_purge(&ar->tx_status[i]);
}
+ skb_queue_purge(&ar->tx_status_ampdu);
+
mutex_unlock(&ar->mutex);
}
+static void ar9170_tx_indicate_immba(struct ar9170 *ar, struct sk_buff *skb)
+{
+ struct ar9170_tx_control *txc = (void *) skb->data;
+
+ txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_IMM_AMPDU);
+}
+
+static void ar9170_tx_copy_phy(struct ar9170 *ar, struct sk_buff *dst,
+ struct sk_buff *src)
+{
+ struct ar9170_tx_control *dst_txc, *src_txc;
+ struct ieee80211_tx_info *dst_info, *src_info;
+ struct ar9170_tx_info *dst_arinfo, *src_arinfo;
+
+ src_txc = (void *) src->data;
+ src_info = IEEE80211_SKB_CB(src);
+ src_arinfo = (void *) src_info->rate_driver_data;
+
+ dst_txc = (void *) dst->data;
+ dst_info = IEEE80211_SKB_CB(dst);
+ dst_arinfo = (void *) dst_info->rate_driver_data;
+
+ dst_txc->phy_control = src_txc->phy_control;
+
+ /* same MCS for the whole aggregate */
+ memcpy(dst_info->driver_rates, src_info->driver_rates,
+ sizeof(dst_info->driver_rates));
+}
+
static int ar9170_tx_prepare(struct ar9170 *ar, struct sk_buff *skb)
{
struct ieee80211_hdr *hdr;
@@ -1228,6 +1415,7 @@ static int ar9170_tx_prepare(struct ar9170 *ar, struct sk_buff *skb)
txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_AGGR);
arinfo->flags = AR9170_TX_FLAG_BLOCK_ACK;
+
goto out;
}
@@ -1358,6 +1546,159 @@ static void ar9170_tx_prepare_phy(struct ar9170 *ar, struct sk_buff *skb)
txc->phy_control |= cpu_to_le32(chains << AR9170_TX_PHY_TXCHAIN_SHIFT);
}
+static bool ar9170_tx_ampdu(struct ar9170 *ar)
+{
+ struct sk_buff_head agg;
+ struct ar9170_sta_tid *tid_info = NULL, *tmp;
+ struct sk_buff *skb, *first = NULL;
+ unsigned long flags, f2;
+ unsigned int i = 0;
+ u16 seq, queue, tmpssn;
+ bool run = false;
+
+ skb_queue_head_init(&agg);
+
+ spin_lock_irqsave(&ar->tx_ampdu_list_lock, flags);
+ if (list_empty(&ar->tx_ampdu_list)) {
+#ifdef AR9170_TXAGG_DEBUG
+ printk(KERN_DEBUG "%s: aggregation list is empty.\n",
+ wiphy_name(ar->hw->wiphy));
+#endif /* AR9170_TXAGG_DEBUG */
+ goto out_unlock;
+ }
+
+ list_for_each_entry_safe(tid_info, tmp, &ar->tx_ampdu_list, list) {
+ if (tid_info->state != AR9170_TID_STATE_COMPLETE) {
+#ifdef AR9170_TXAGG_DEBUG
+ printk(KERN_DEBUG "%s: dangling aggregation entry!\n",
+ wiphy_name(ar->hw->wiphy));
+#endif /* AR9170_TXAGG_DEBUG */
+ continue;
+ }
+
+ if (++i > 64) {
+#ifdef AR9170_TXAGG_DEBUG
+ printk(KERN_DEBUG "%s: enough frames aggregated.\n",
+ wiphy_name(ar->hw->wiphy));
+#endif /* AR9170_TXAGG_DEBUG */
+ break;
+ }
+
+ queue = TID_TO_WME_AC(tid_info->tid);
+
+ if (skb_queue_len(&ar->tx_pending[queue]) >=
+ AR9170_NUM_TX_AGG_MAX) {
+#ifdef AR9170_TXAGG_DEBUG
+ printk(KERN_DEBUG "%s: queue %d full.\n",
+ wiphy_name(ar->hw->wiphy), queue);
+#endif /* AR9170_TXAGG_DEBUG */
+ continue;
+ }
+
+ list_del_init(&tid_info->list);
+
+ spin_lock_irqsave(&tid_info->queue.lock, f2);
+ tmpssn = seq = tid_info->ssn;
+ first = skb_peek(&tid_info->queue);
+
+ if (likely(first))
+ tmpssn = ar9170_get_seq(first);
+
+ if (unlikely(tmpssn != seq)) {
+#ifdef AR9170_TXAGG_DEBUG
+ printk(KERN_DEBUG "%s: ssn mismatch [%d != %d]\n.",
+ wiphy_name(ar->hw->wiphy), seq, tmpssn);
+#endif /* AR9170_TXAGG_DEBUG */
+ tid_info->ssn = tmpssn;
+ }
+
+#ifdef AR9170_TXAGG_DEBUG
+ printk(KERN_DEBUG "%s: generate A-MPDU for tid:%d ssn:%d with "
+ "%d queued frames.\n", wiphy_name(ar->hw->wiphy),
+ tid_info->tid, tid_info->ssn,
+ skb_queue_len(&tid_info->queue));
+ __ar9170_dump_txqueue(ar, &tid_info->queue);
+#endif /* AR9170_TXAGG_DEBUG */
+
+ while ((skb = skb_peek(&tid_info->queue))) {
+ if (unlikely(ar9170_get_seq(skb) != seq))
+ break;
+
+ __skb_unlink(skb, &tid_info->queue);
+ tid_info->ssn = seq = GET_NEXT_SEQ(seq);
+
+ if (unlikely(skb_get_queue_mapping(skb) != queue)) {
+#ifdef AR9170_TXAGG_DEBUG
+ printk(KERN_DEBUG "%s: tid:%d(q:%d) queue:%d "
+ "!match.\n", wiphy_name(ar->hw->wiphy),
+ tid_info->tid,
+ TID_TO_WME_AC(tid_info->tid),
+ skb_get_queue_mapping(skb));
+#endif /* AR9170_TXAGG_DEBUG */
+ dev_kfree_skb_any(skb);
+ continue;
+ }
+
+ if (unlikely(first == skb)) {
+ ar9170_tx_prepare_phy(ar, skb);
+ __skb_queue_tail(&agg, skb);
+ first = skb;
+ } else {
+ ar9170_tx_copy_phy(ar, skb, first);
+ __skb_queue_tail(&agg, skb);
+ }
+
+ if (unlikely(skb_queue_len(&agg) ==
+ AR9170_NUM_TX_AGG_MAX))
+ break;
+ }
+
+ if (skb_queue_empty(&tid_info->queue))
+ tid_info->active = false;
+ else
+ list_add_tail(&tid_info->list,
+ &ar->tx_ampdu_list);
+
+ spin_unlock_irqrestore(&tid_info->queue.lock, f2);
+
+ if (unlikely(skb_queue_empty(&agg))) {
+#ifdef AR9170_TXAGG_DEBUG
+ printk(KERN_DEBUG "%s: queued empty list!\n",
+ wiphy_name(ar->hw->wiphy));
+#endif /* AR9170_TXAGG_DEBUG */
+ continue;
+ }
+
+ /*
+ * tell the FW/HW that this is the last frame,
+ * that way it will wait for the immediate block ack.
+ */
+ if (likely(skb_peek_tail(&agg)))
+ ar9170_tx_indicate_immba(ar, skb_peek_tail(&agg));
+
+#ifdef AR9170_TXAGG_DEBUG
+ printk(KERN_DEBUG "%s: generated A-MPDU looks like this:\n",
+ wiphy_name(ar->hw->wiphy));
+ __ar9170_dump_txqueue(ar, &agg);
+#endif /* AR9170_TXAGG_DEBUG */
+
+ spin_unlock_irqrestore(&ar->tx_ampdu_list_lock, flags);
+
+ spin_lock_irqsave(&ar->tx_pending[queue].lock, flags);
+ skb_queue_splice_tail_init(&agg, &ar->tx_pending[queue]);
+ spin_unlock_irqrestore(&ar->tx_pending[queue].lock, flags);
+ run = true;
+
+ spin_lock_irqsave(&ar->tx_ampdu_list_lock, flags);
+ }
+
+out_unlock:
+ spin_unlock_irqrestore(&ar->tx_ampdu_list_lock, flags);
+ __skb_queue_purge(&agg);
+
+ return run;
+}
+
static void ar9170_tx(struct ar9170 *ar)
{
struct sk_buff *skb;
@@ -1382,11 +1723,17 @@ static void ar9170_tx(struct ar9170 *ar)
printk(KERN_DEBUG "%s: queue %d full\n",
wiphy_name(ar->hw->wiphy), i);
- __ar9170_dump_txstats(ar);
- printk(KERN_DEBUG "stuck frames: ===> \n");
+ printk(KERN_DEBUG "%s: stuck frames: ===> \n",
+ wiphy_name(ar->hw->wiphy));
ar9170_dump_txqueue(ar, &ar->tx_pending[i]);
ar9170_dump_txqueue(ar, &ar->tx_status[i]);
#endif /* AR9170_QUEUE_DEBUG */
+
+#ifdef AR9170_QUEUE_STOP_DEBUG
+ printk(KERN_DEBUG "%s: stop queue %d\n",
+ wiphy_name(ar->hw->wiphy), i);
+ __ar9170_dump_txstats(ar);
+#endif /* AR9170_QUEUE_STOP_DEBUG */
ieee80211_stop_queue(ar->hw, i);
spin_unlock_irqrestore(&ar->tx_stats_lock, flags);
continue;
@@ -1401,8 +1748,6 @@ static void ar9170_tx(struct ar9170 *ar)
"remaining slots:%d, needed:%d\n",
wiphy_name(ar->hw->wiphy), i, remaining_space,
frames);
-
- ar9170_dump_txstats(ar);
#endif /* AR9170_QUEUE_DEBUG */
frames = remaining_space;
}
@@ -1430,6 +1775,9 @@ static void ar9170_tx(struct ar9170 *ar)
arinfo->timeout = jiffies +
msecs_to_jiffies(AR9170_TX_TIMEOUT);
+ if (arinfo->flags == AR9170_TX_FLAG_BLOCK_ACK)
+ ar->tx_ampdu_pending++;
+
#ifdef AR9170_QUEUE_DEBUG
printk(KERN_DEBUG "%s: send frame q:%d =>\n",
wiphy_name(ar->hw->wiphy), i);
@@ -1438,6 +1786,9 @@ static void ar9170_tx(struct ar9170 *ar)
err = ar->tx(ar, skb);
if (unlikely(err)) {
+ if (arinfo->flags == AR9170_TX_FLAG_BLOCK_ACK)
+ ar->tx_ampdu_pending--;
+
frames_failed++;
dev_kfree_skb_any(skb);
} else {
@@ -1459,22 +1810,113 @@ static void ar9170_tx(struct ar9170 *ar)
if (unlikely(frames_failed)) {
#ifdef AR9170_QUEUE_DEBUG
- printk(KERN_DEBUG "%s: frames failed =>\n",
+ printk(KERN_DEBUG "%s: frames failed %d =>\n",
wiphy_name(ar->hw->wiphy), frames_failed);
#endif /* AR9170_QUEUE_DEBUG */
spin_lock_irqsave(&ar->tx_stats_lock, flags);
ar->tx_stats[i].len -= frames_failed;
ar->tx_stats[i].count -= frames_failed;
+#ifdef AR9170_QUEUE_STOP_DEBUG
+ printk(KERN_DEBUG "%s: wake queue %d\n",
+ wiphy_name(ar->hw->wiphy), i);
+ __ar9170_dump_txstats(ar);
+#endif /* AR9170_QUEUE_STOP_DEBUG */
ieee80211_wake_queue(ar->hw, i);
spin_unlock_irqrestore(&ar->tx_stats_lock, flags);
}
}
- if (schedule_garbagecollector)
- queue_delayed_work(ar->hw->workqueue,
- &ar->tx_janitor,
- msecs_to_jiffies(AR9170_JANITOR_DELAY));
+ if (!schedule_garbagecollector)
+ return;
+
+ ieee80211_queue_delayed_work(ar->hw,
+ &ar->tx_janitor,
+ msecs_to_jiffies(AR9170_JANITOR_DELAY));
+}
+
+static bool ar9170_tx_ampdu_queue(struct ar9170 *ar, struct sk_buff *skb)
+{
+ struct ieee80211_tx_info *txinfo;
+ struct ar9170_sta_info *sta_info;
+ struct ar9170_sta_tid *agg;
+ struct sk_buff *iter;
+ unsigned long flags, f2;
+ unsigned int max;
+ u16 tid, seq, qseq;
+ bool run = false, queue = false;
+
+ tid = ar9170_get_tid(skb);
+ seq = ar9170_get_seq(skb);
+ txinfo = IEEE80211_SKB_CB(skb);
+ sta_info = (void *) txinfo->control.sta->drv_priv;
+ agg = &sta_info->agg[tid];
+ max = sta_info->ampdu_max_len;
+
+ spin_lock_irqsave(&ar->tx_ampdu_list_lock, flags);
+
+ if (unlikely(agg->state != AR9170_TID_STATE_COMPLETE)) {
+#ifdef AR9170_TXAGG_DEBUG
+ printk(KERN_DEBUG "%s: BlockACK session not fully initialized "
+ "for ESS:%pM tid:%d state:%d.\n",
+ wiphy_name(ar->hw->wiphy), agg->addr, agg->tid,
+ agg->state);
+#endif /* AR9170_TXAGG_DEBUG */
+ goto err_unlock;
+ }
+
+ if (!agg->active) {
+ agg->active = true;
+ agg->ssn = seq;
+ queue = true;
+ }
+
+ /* check if seq is within the BA window */
+ if (unlikely(!BAW_WITHIN(agg->ssn, max, seq))) {
+#ifdef AR9170_TXAGG_DEBUG
+ printk(KERN_DEBUG "%s: frame with tid:%d seq:%d does not "
+ "fit into BA window (%d - %d)\n",
+ wiphy_name(ar->hw->wiphy), tid, seq, agg->ssn,
+ (agg->ssn + max) & 0xfff);
+#endif /* AR9170_TXAGG_DEBUG */
+ goto err_unlock;
+ }
+
+ spin_lock_irqsave(&agg->queue.lock, f2);
+
+ skb_queue_reverse_walk(&agg->queue, iter) {
+ qseq = ar9170_get_seq(iter);
+
+ if (GET_NEXT_SEQ(qseq) == seq) {
+ __skb_queue_after(&agg->queue, iter, skb);
+ goto queued;
+ }
+ }
+
+ __skb_queue_head(&agg->queue, skb);
+
+queued:
+ spin_unlock_irqrestore(&agg->queue.lock, f2);
+
+#ifdef AR9170_TXAGG_DEBUG
+ printk(KERN_DEBUG "%s: new aggregate %p queued.\n",
+ wiphy_name(ar->hw->wiphy), skb);
+ __ar9170_dump_txqueue(ar, &agg->queue);
+#endif /* AR9170_TXAGG_DEBUG */
+
+ if (skb_queue_len(&agg->queue) >= AR9170_NUM_TX_AGG_MAX)
+ run = true;
+
+ if (queue)
+ list_add_tail(&agg->list, &ar->tx_ampdu_list);
+
+ spin_unlock_irqrestore(&ar->tx_ampdu_list_lock, flags);
+ return run;
+
+err_unlock:
+ spin_unlock_irqrestore(&ar->tx_ampdu_list_lock, flags);
+ dev_kfree_skb_irq(skb);
+ return false;
}
int ar9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
@@ -1490,8 +1932,10 @@ int ar9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
info = IEEE80211_SKB_CB(skb);
if (info->flags & IEEE80211_TX_CTL_AMPDU) {
- /* drop frame, we do not allow TX A-MPDU aggregation yet. */
- goto err_free;
+ bool run = ar9170_tx_ampdu_queue(ar, skb);
+
+ if (run || !ar->tx_ampdu_pending)
+ ar9170_tx_ampdu(ar);
} else {
unsigned int queue = skb_get_queue_mapping(skb);
@@ -1717,7 +2161,7 @@ static void ar9170_op_configure_filter(struct ieee80211_hw *hw,
}
if (likely(IS_STARTED(ar)))
- queue_work(ar->hw->workqueue, &ar->filter_config_work);
+ ieee80211_queue_work(ar->hw, &ar->filter_config_work);
}
static void ar9170_op_bss_info_changed(struct ieee80211_hw *hw,
@@ -1929,6 +2373,53 @@ static void ar9170_sta_notify(struct ieee80211_hw *hw,
enum sta_notify_cmd cmd,
struct ieee80211_sta *sta)
{
+ struct ar9170 *ar = hw->priv;
+ struct ar9170_sta_info *sta_info = (void *) sta->drv_priv;
+ unsigned int i;
+
+ switch (cmd) {
+ case STA_NOTIFY_ADD:
+ memset(sta_info, 0, sizeof(*sta_info));
+
+ if (!sta->ht_cap.ht_supported)
+ break;
+
+ if (sta->ht_cap.ampdu_density > ar->global_ampdu_density)
+ ar->global_ampdu_density = sta->ht_cap.ampdu_density;
+
+ if (sta->ht_cap.ampdu_factor < ar->global_ampdu_factor)
+ ar->global_ampdu_factor = sta->ht_cap.ampdu_factor;
+
+ for (i = 0; i < AR9170_NUM_TID; i++) {
+ sta_info->agg[i].state = AR9170_TID_STATE_SHUTDOWN;
+ sta_info->agg[i].active = false;
+ sta_info->agg[i].ssn = 0;
+ sta_info->agg[i].retry = 0;
+ sta_info->agg[i].tid = i;
+ INIT_LIST_HEAD(&sta_info->agg[i].list);
+ skb_queue_head_init(&sta_info->agg[i].queue);
+ }
+
+ sta_info->ampdu_max_len = 1 << (3 + sta->ht_cap.ampdu_factor);
+ break;
+
+ case STA_NOTIFY_REMOVE:
+ if (!sta->ht_cap.ht_supported)
+ break;
+
+ for (i = 0; i < AR9170_NUM_TID; i++) {
+ sta_info->agg[i].state = AR9170_TID_STATE_INVALID;
+ skb_queue_purge(&sta_info->agg[i].queue);
+ }
+
+ break;
+
+ default:
+ break;
+ }
+
+ if (IS_STARTED(ar) && ar->filter_changed)
+ ieee80211_queue_work(ar->hw, &ar->filter_config_work);
}
static int ar9170_get_stats(struct ieee80211_hw *hw,
@@ -1984,18 +2475,65 @@ static int ar9170_ampdu_action(struct ieee80211_hw *hw,
enum ieee80211_ampdu_mlme_action action,
struct ieee80211_sta *sta, u16 tid, u16 *ssn)
{
+ struct ar9170 *ar = hw->priv;
+ struct ar9170_sta_info *sta_info = (void *) sta->drv_priv;
+ struct ar9170_sta_tid *tid_info = &sta_info->agg[tid];
+ unsigned long flags;
+
+ if (!modparam_ht)
+ return -EOPNOTSUPP;
+
switch (action) {
+ case IEEE80211_AMPDU_TX_START:
+ spin_lock_irqsave(&ar->tx_ampdu_list_lock, flags);
+ if (tid_info->state != AR9170_TID_STATE_SHUTDOWN ||
+ !list_empty(&tid_info->list)) {
+ spin_unlock_irqrestore(&ar->tx_ampdu_list_lock, flags);
+#ifdef AR9170_TXAGG_DEBUG
+ printk(KERN_INFO "%s: A-MPDU [ESS:[%pM] tid:[%d]] "
+ "is in a very bad state!\n",
+ wiphy_name(hw->wiphy), sta->addr, tid);
+#endif /* AR9170_TXAGG_DEBUG */
+ return -EBUSY;
+ }
+
+ *ssn = tid_info->ssn;
+ tid_info->state = AR9170_TID_STATE_PROGRESS;
+ tid_info->active = false;
+ spin_unlock_irqrestore(&ar->tx_ampdu_list_lock, flags);
+ ieee80211_start_tx_ba_cb_irqsafe(hw, sta->addr, tid);
+ break;
+
+ case IEEE80211_AMPDU_TX_STOP:
+ spin_lock_irqsave(&ar->tx_ampdu_list_lock, flags);
+ tid_info->state = AR9170_TID_STATE_SHUTDOWN;
+ list_del_init(&tid_info->list);
+ tid_info->active = false;
+ skb_queue_purge(&tid_info->queue);
+ spin_unlock_irqrestore(&ar->tx_ampdu_list_lock, flags);
+ ieee80211_stop_tx_ba_cb_irqsafe(hw, sta->addr, tid);
+ break;
+
+ case IEEE80211_AMPDU_TX_OPERATIONAL:
+#ifdef AR9170_TXAGG_DEBUG
+ printk(KERN_INFO "%s: A-MPDU for %pM [tid:%d] Operational.\n",
+ wiphy_name(hw->wiphy), sta->addr, tid);
+#endif /* AR9170_TXAGG_DEBUG */
+ spin_lock_irqsave(&ar->tx_ampdu_list_lock, flags);
+ sta_info->agg[tid].state = AR9170_TID_STATE_COMPLETE;
+ spin_unlock_irqrestore(&ar->tx_ampdu_list_lock, flags);
+ break;
+
case IEEE80211_AMPDU_RX_START:
case IEEE80211_AMPDU_RX_STOP:
- /*
- * Something goes wrong -- RX locks up
- * after a while of receiving aggregated
- * frames -- not enabling for now.
- */
- return -EOPNOTSUPP;
+ /* Handled by firmware */
+ break;
+
default:
return -EOPNOTSUPP;
}
+
+ return 0;
}
static const struct ieee80211_ops ar9170_ops = {
@@ -2044,6 +2582,8 @@ void *ar9170_alloc(size_t priv_size)
mutex_init(&ar->mutex);
spin_lock_init(&ar->cmdlock);
spin_lock_init(&ar->tx_stats_lock);
+ spin_lock_init(&ar->tx_ampdu_list_lock);
+ skb_queue_head_init(&ar->tx_status_ampdu);
for (i = 0; i < __AR9170_NUM_TXQ; i++) {
skb_queue_head_init(&ar->tx_status[i]);
skb_queue_head_init(&ar->tx_pending[i]);
@@ -2052,6 +2592,7 @@ void *ar9170_alloc(size_t priv_size)
INIT_WORK(&ar->filter_config_work, ar9170_set_filters);
INIT_WORK(&ar->beacon_work, ar9170_new_beacon);
INIT_DELAYED_WORK(&ar->tx_janitor, ar9170_tx_janitor);
+ INIT_LIST_HEAD(&ar->tx_ampdu_list);
/* all hw supports 2.4 GHz, so set channel to 1 by default */
ar->channel = &ar9170_2ghz_chantable[0];
@@ -2065,6 +2606,13 @@ void *ar9170_alloc(size_t priv_size)
IEEE80211_HW_SIGNAL_DBM |
IEEE80211_HW_NOISE_DBM;
+ if (modparam_ht) {
+ ar->hw->flags |= IEEE80211_HW_AMPDU_AGGREGATION;
+ } else {
+ ar9170_band_2GHz.ht_cap.ht_supported = false;
+ ar9170_band_5GHz.ht_cap.ht_supported = false;
+ }
+
ar->hw->queues = __AR9170_NUM_TXQ;
ar->hw->extra_tx_headroom = 8;
ar->hw->sta_data_size = sizeof(struct ar9170_sta_info);
@@ -2086,10 +2634,10 @@ static int ar9170_read_eeprom(struct ar9170 *ar)
{
#define RW 8 /* number of words to read at once */
#define RB (sizeof(u32) * RW)
- DECLARE_MAC_BUF(mbuf);
u8 *eeprom = (void *)&ar->eeprom;
u8 *addr = ar->eeprom.mac_address;
__le32 offsets[RW];
+ unsigned int rx_streams, tx_streams, tx_params = 0;
int i, j, err, bands = 0;
BUILD_BUG_ON(sizeof(ar->eeprom) & 3);
@@ -2126,6 +2674,20 @@ static int ar9170_read_eeprom(struct ar9170 *ar)
ar->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &ar9170_band_5GHz;
bands++;
}
+
+ rx_streams = hweight8(ar->eeprom.rx_mask);
+ tx_streams = hweight8(ar->eeprom.tx_mask);
+
+ if (rx_streams != tx_streams)
+ tx_params = IEEE80211_HT_MCS_TX_RX_DIFF;
+
+ if (tx_streams >= 1 && tx_streams <= IEEE80211_HT_MCS_TX_MAX_STREAMS)
+ tx_params = (tx_streams - 1) <<
+ IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT;
+
+ ar9170_band_2GHz.ht_cap.mcs.tx_params |= tx_params;
+ ar9170_band_5GHz.ht_cap.mcs.tx_params |= tx_params;
+
/*
* I measured this, a bandswitch takes roughly
* 135 ms and a frequency switch about 80.
diff --git a/drivers/net/wireless/ath/ar9170/usb.c b/drivers/net/wireless/ath/ar9170/usb.c
index 007eb85fc67..e0138ac8bf5 100644
--- a/drivers/net/wireless/ath/ar9170/usb.c
+++ b/drivers/net/wireless/ath/ar9170/usb.c
@@ -783,7 +783,7 @@ static int ar9170_usb_probe(struct usb_interface *intf,
aru->req_one_stage_fw = ar9170_requires_one_stage(id);
usb_set_intfdata(intf, aru);
- SET_IEEE80211_DEV(ar->hw, &udev->dev);
+ SET_IEEE80211_DEV(ar->hw, &intf->dev);
init_usb_anchor(&aru->rx_submitted);
init_usb_anchor(&aru->tx_pending);
diff --git a/drivers/net/wireless/ath/ath.h b/drivers/net/wireless/ath/ath.h
new file mode 100644
index 00000000000..e284cd3ac6d
--- /dev/null
+++ b/drivers/net/wireless/ath/ath.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2008-2009 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef ATH_H
+#define ATH_H
+
+#include <linux/skbuff.h>
+
+struct ath_common {
+ u16 cachelsz;
+};
+
+struct sk_buff *ath_rxbuf_alloc(struct ath_common *common,
+ u32 len,
+ gfp_t gfp_mask);
+
+#endif /* ATH_H */
diff --git a/drivers/net/wireless/ath/ath5k/Kconfig b/drivers/net/wireless/ath/ath5k/Kconfig
index daf0c83527d..06d006675d7 100644
--- a/drivers/net/wireless/ath/ath5k/Kconfig
+++ b/drivers/net/wireless/ath/ath5k/Kconfig
@@ -1,7 +1,6 @@
config ATH5K
tristate "Atheros 5xxx wireless cards support"
- depends on PCI && MAC80211 && WLAN_80211 && EXPERIMENTAL
- select ATH_COMMON
+ depends on PCI && MAC80211 && WLAN_80211
select MAC80211_LEDS
select LEDS_CLASS
select NEW_LEDS
diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h
index 6358233bac9..c09402eea7f 100644
--- a/drivers/net/wireless/ath/ath5k/ath5k.h
+++ b/drivers/net/wireless/ath/ath5k/ath5k.h
@@ -713,8 +713,8 @@ struct ath5k_gain {
* Used internaly for reset_tx_queue).
* Also see struct struct ieee80211_channel.
*/
-#define IS_CHAN_XR(_c) ((_c.hw_value & CHANNEL_XR) != 0)
-#define IS_CHAN_B(_c) ((_c.hw_value & CHANNEL_B) != 0)
+#define IS_CHAN_XR(_c) ((_c->hw_value & CHANNEL_XR) != 0)
+#define IS_CHAN_B(_c) ((_c->hw_value & CHANNEL_B) != 0)
/*
* The following structure is used to map 2GHz channels to
@@ -919,6 +919,12 @@ enum ath5k_int {
AR5K_INT_NOCARD = 0xffffffff
};
+/* Software interrupts used for calibration */
+enum ath5k_software_interrupt {
+ AR5K_SWI_FULL_CALIBRATION = 0x01,
+ AR5K_SWI_SHORT_CALIBRATION = 0x02,
+};
+
/*
* Power management
*/
@@ -1029,14 +1035,15 @@ struct ath5k_hw {
enum ath5k_int ah_imr;
enum nl80211_iftype ah_op_mode;
- enum ath5k_power_mode ah_power_mode;
- struct ieee80211_channel ah_current_channel;
+ struct ieee80211_channel *ah_current_channel;
bool ah_turbo;
bool ah_calibration;
- bool ah_running;
bool ah_single_chip;
bool ah_combined_mic;
+ enum ath5k_version ah_version;
+ enum ath5k_radio ah_radio;
+ u32 ah_phy;
u32 ah_mac_srev;
u16 ah_mac_version;
u16 ah_mac_revision;
@@ -1044,13 +1051,6 @@ struct ath5k_hw {
u16 ah_radio_5ghz_revision;
u16 ah_radio_2ghz_revision;
- enum ath5k_version ah_version;
- enum ath5k_radio ah_radio;
- u32 ah_phy;
-
- bool ah_5ghz;
- bool ah_2ghz;
-
#define ah_modes ah_capabilities.cap_mode
#define ah_ee_version ah_capabilities.cap_eeprom.ee_version
@@ -1058,7 +1058,6 @@ struct ath5k_hw {
u32 ah_aifs;
u32 ah_cw_min;
u32 ah_cw_max;
- bool ah_software_retry;
u32 ah_limit_tx_retries;
/* Antenna Control */
@@ -1066,6 +1065,7 @@ struct ath5k_hw {
u8 ah_ant_mode;
u8 ah_tx_ant;
u8 ah_def_ant;
+ bool ah_software_retry;
u8 ah_sta_id[ETH_ALEN];
@@ -1075,7 +1075,6 @@ struct ath5k_hw {
u8 ah_bssid[ETH_ALEN];
u8 ah_bssid_mask[ETH_ALEN];
- u32 ah_gpio[AR5K_MAX_GPIO];
int ah_gpio_npins;
struct ath_regulatory ah_regulatory;
@@ -1130,6 +1129,15 @@ struct ath5k_hw {
/* noise floor from last periodic calibration */
s32 ah_noise_floor;
+ /* Calibration timestamp */
+ unsigned long ah_cal_tstamp;
+
+ /* Calibration interval (secs) */
+ u8 ah_cal_intval;
+
+ /* Software interrupt mask */
+ u8 ah_swi_mask;
+
/*
* Function pointers
*/
@@ -1164,6 +1172,7 @@ extern void ath5k_unregister_leds(struct ath5k_softc *sc);
/* Reset Functions */
extern int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial);
+extern int ath5k_hw_on_hold(struct ath5k_hw *ah);
extern int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, struct ieee80211_channel *channel, bool change_channel);
/* Power management functions */
extern int ath5k_hw_set_power(struct ath5k_hw *ah, enum ath5k_power_mode mode, bool set_chip, u16 sleep_duration);
@@ -1282,6 +1291,7 @@ extern int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *chann
/* PHY calibration */
extern int ath5k_hw_phy_calibrate(struct ath5k_hw *ah, struct ieee80211_channel *channel);
extern int ath5k_hw_noise_floor_calibration(struct ath5k_hw *ah, short freq);
+extern void ath5k_hw_calibration_poll(struct ath5k_hw *ah);
/* Spur mitigation */
bool ath5k_hw_chan_has_spur_noise(struct ath5k_hw *ah,
struct ieee80211_channel *channel);
diff --git a/drivers/net/wireless/ath/ath5k/attach.c b/drivers/net/wireless/ath/ath5k/attach.c
index c41ef58393e..65d438b59f6 100644
--- a/drivers/net/wireless/ath/ath5k/attach.c
+++ b/drivers/net/wireless/ath/ath5k/attach.c
@@ -145,7 +145,7 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version)
goto err_free;
/* Bring device out of sleep and reset it's units */
- ret = ath5k_hw_nic_wakeup(ah, CHANNEL_B, true);
+ ret = ath5k_hw_nic_wakeup(ah, 0, true);
if (ret)
goto err_free;
@@ -253,28 +253,6 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version)
}
/*
- * Write PCI-E power save settings
- */
- if ((ah->ah_version == AR5K_AR5212) && (pdev->is_pcie)) {
- ath5k_hw_reg_write(ah, 0x9248fc00, AR5K_PCIE_SERDES);
- ath5k_hw_reg_write(ah, 0x24924924, AR5K_PCIE_SERDES);
- /* Shut off RX when elecidle is asserted */
- ath5k_hw_reg_write(ah, 0x28000039, AR5K_PCIE_SERDES);
- ath5k_hw_reg_write(ah, 0x53160824, AR5K_PCIE_SERDES);
- /* TODO: EEPROM work */
- ath5k_hw_reg_write(ah, 0xe5980579, AR5K_PCIE_SERDES);
- /* Shut off PLL and CLKREQ active in L1 */
- ath5k_hw_reg_write(ah, 0x001defff, AR5K_PCIE_SERDES);
- /* Preserce other settings */
- ath5k_hw_reg_write(ah, 0x1aaabe40, AR5K_PCIE_SERDES);
- ath5k_hw_reg_write(ah, 0xbe105554, AR5K_PCIE_SERDES);
- ath5k_hw_reg_write(ah, 0x000e3007, AR5K_PCIE_SERDES);
- /* Reset SERDES to load new settings */
- ath5k_hw_reg_write(ah, 0x00000000, AR5K_PCIE_SERDES_RESET);
- mdelay(1);
- }
-
- /*
* POST
*/
ret = ath5k_hw_post(ah);
@@ -283,7 +261,7 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version)
/* Enable pci core retry fix on Hainan (5213A) and later chips */
if (srev >= AR5K_SREV_AR5213A)
- ath5k_hw_reg_write(ah, AR5K_PCICFG_RETRY_FIX, AR5K_PCICFG);
+ AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, AR5K_PCICFG_RETRY_FIX);
/*
* Get card capabilities, calibration values etc
@@ -295,6 +273,40 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version)
goto err_free;
}
+ /*
+ * Write PCI-E power save settings
+ */
+ if ((ah->ah_version == AR5K_AR5212) && (pdev->is_pcie)) {
+ struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+
+ ath5k_hw_reg_write(ah, 0x9248fc00, AR5K_PCIE_SERDES);
+ ath5k_hw_reg_write(ah, 0x24924924, AR5K_PCIE_SERDES);
+
+ /* Shut off RX when elecidle is asserted */
+ ath5k_hw_reg_write(ah, 0x28000039, AR5K_PCIE_SERDES);
+ ath5k_hw_reg_write(ah, 0x53160824, AR5K_PCIE_SERDES);
+
+ /* If serdes programing is enabled, increase PCI-E
+ * tx power for systems with long trace from host
+ * to minicard connector. */
+ if (ee->ee_serdes)
+ ath5k_hw_reg_write(ah, 0xe5980579, AR5K_PCIE_SERDES);
+ else
+ ath5k_hw_reg_write(ah, 0xf6800579, AR5K_PCIE_SERDES);
+
+ /* Shut off PLL and CLKREQ active in L1 */
+ ath5k_hw_reg_write(ah, 0x001defff, AR5K_PCIE_SERDES);
+
+ /* Preserve other settings */
+ ath5k_hw_reg_write(ah, 0x1aaabe40, AR5K_PCIE_SERDES);
+ ath5k_hw_reg_write(ah, 0xbe105554, AR5K_PCIE_SERDES);
+ ath5k_hw_reg_write(ah, 0x000e3007, AR5K_PCIE_SERDES);
+
+ /* Reset SERDES to load new settings */
+ ath5k_hw_reg_write(ah, 0x00000000, AR5K_PCIE_SERDES_RESET);
+ mdelay(1);
+ }
+
/* Get misc capabilities */
ret = ath5k_hw_set_capabilities(ah);
if (ret) {
@@ -319,6 +331,9 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version)
ath5k_hw_rfgain_opt_init(ah);
+ /* turn on HW LEDs */
+ ath5k_hw_set_ledstate(ah, AR5K_LED_INIT);
+
return ah;
err_free:
kfree(ah);
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c
index 029c1bc7468..2b3cf39dd4b 100644
--- a/drivers/net/wireless/ath/ath5k/base.c
+++ b/drivers/net/wireless/ath/ath5k/base.c
@@ -59,7 +59,7 @@
#include "reg.h"
#include "debug.h"
-static int ath5k_calinterval = 10; /* Calibrate PHY every 10 secs (TODO: Fixme) */
+static u8 ath5k_calinterval = 10; /* Calibrate PHY every 10 secs (TODO: Fixme) */
static int modparam_nohwcrypt;
module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO);
MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption.");
@@ -218,6 +218,8 @@ static struct pci_driver ath5k_pci_driver = {
* Prototypes - MAC 802.11 stack related functions
*/
static int ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb);
+static int ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb,
+ struct ath5k_txq *txq);
static int ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan);
static int ath5k_reset_wake(struct ath5k_softc *sc);
static int ath5k_start(struct ieee80211_hw *hw);
@@ -248,6 +250,8 @@ static void ath5k_bss_info_changed(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_bss_conf *bss_conf,
u32 changes);
+static void ath5k_sw_scan_start(struct ieee80211_hw *hw);
+static void ath5k_sw_scan_complete(struct ieee80211_hw *hw);
static const struct ieee80211_ops ath5k_hw_ops = {
.tx = ath5k_tx,
@@ -265,6 +269,8 @@ static const struct ieee80211_ops ath5k_hw_ops = {
.set_tsf = ath5k_set_tsf,
.reset_tsf = ath5k_reset_tsf,
.bss_info_changed = ath5k_bss_info_changed,
+ .sw_scan_start = ath5k_sw_scan_start,
+ .sw_scan_complete = ath5k_sw_scan_complete,
};
/*
@@ -297,7 +303,8 @@ static void ath5k_desc_free(struct ath5k_softc *sc,
static int ath5k_rxbuf_setup(struct ath5k_softc *sc,
struct ath5k_buf *bf);
static int ath5k_txbuf_setup(struct ath5k_softc *sc,
- struct ath5k_buf *bf);
+ struct ath5k_buf *bf,
+ struct ath5k_txq *txq);
static inline void ath5k_txbuf_free(struct ath5k_softc *sc,
struct ath5k_buf *bf)
{
@@ -369,7 +376,7 @@ static int ath5k_stop_hw(struct ath5k_softc *sc);
static irqreturn_t ath5k_intr(int irq, void *dev_id);
static void ath5k_tasklet_reset(unsigned long data);
-static void ath5k_calibrate(unsigned long data);
+static void ath5k_tasklet_calibrate(unsigned long data);
/*
* Module init/exit functions
@@ -464,7 +471,7 @@ ath5k_pci_probe(struct pci_dev *pdev,
* DMA to work so force a reasonable value here if it
* comes up zero.
*/
- csz = L1_CACHE_BYTES / sizeof(u32);
+ csz = L1_CACHE_BYTES >> 2;
pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, csz);
}
/*
@@ -512,6 +519,7 @@ ath5k_pci_probe(struct pci_dev *pdev,
/* Initialize driver private data */
SET_IEEE80211_DEV(hw, &pdev->dev);
hw->flags = IEEE80211_HW_RX_INCLUDES_FCS |
+ IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
IEEE80211_HW_SIGNAL_DBM |
IEEE80211_HW_NOISE_DBM;
@@ -536,7 +544,7 @@ ath5k_pci_probe(struct pci_dev *pdev,
__set_bit(ATH_STAT_INVALID, sc->status);
sc->iobase = mem; /* So we can unmap it on detach */
- sc->cachelsz = csz * sizeof(u32); /* convert to bytes */
+ sc->common.cachelsz = csz << 2; /* convert to bytes */
sc->opmode = NL80211_IFTYPE_STATION;
sc->bintval = 1000;
mutex_init(&sc->lock);
@@ -666,7 +674,6 @@ ath5k_pci_suspend(struct pci_dev *pdev, pm_message_t state)
ath5k_led_off(sc);
- free_irq(pdev->irq, sc);
pci_save_state(pdev);
pci_disable_device(pdev);
pci_set_power_state(pdev, PCI_D3hot);
@@ -694,18 +701,8 @@ ath5k_pci_resume(struct pci_dev *pdev)
*/
pci_write_config_byte(pdev, 0x41, 0);
- err = request_irq(pdev->irq, ath5k_intr, IRQF_SHARED, "ath", sc);
- if (err) {
- ATH5K_ERR(sc, "request_irq failed\n");
- goto err_no_irq;
- }
-
ath5k_led_enable(sc);
return 0;
-
-err_no_irq:
- pci_disable_device(pdev);
- return err;
}
#endif /* CONFIG_PM */
@@ -785,19 +782,25 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw)
goto err_desc;
}
sc->bhalq = ret;
+ sc->cabq = ath5k_txq_setup(sc, AR5K_TX_QUEUE_CAB, 0);
+ if (IS_ERR(sc->cabq)) {
+ ATH5K_ERR(sc, "can't setup cab queue\n");
+ ret = PTR_ERR(sc->cabq);
+ goto err_bhal;
+ }
sc->txq = ath5k_txq_setup(sc, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_BK);
if (IS_ERR(sc->txq)) {
ATH5K_ERR(sc, "can't setup xmit queue\n");
ret = PTR_ERR(sc->txq);
- goto err_bhal;
+ goto err_queues;
}
tasklet_init(&sc->rxtq, ath5k_tasklet_rx, (unsigned long)sc);
tasklet_init(&sc->txtq, ath5k_tasklet_tx, (unsigned long)sc);
tasklet_init(&sc->restq, ath5k_tasklet_reset, (unsigned long)sc);
+ tasklet_init(&sc->calib, ath5k_tasklet_calibrate, (unsigned long)sc);
tasklet_init(&sc->beacontq, ath5k_tasklet_beacon, (unsigned long)sc);
- setup_timer(&sc->calib_tim, ath5k_calibrate, (unsigned long)sc);
ret = ath5k_eeprom_read_mac(ah, mac);
if (ret) {
@@ -1068,10 +1071,9 @@ ath5k_setup_bands(struct ieee80211_hw *hw)
}
/*
- * Set/change channels. If the channel is really being changed,
- * it's done by reseting the chip. To accomplish this we must
- * first cleanup any pending DMA, then restart stuff after a la
- * ath5k_init.
+ * Set/change channels. We always reset the chip.
+ * To accomplish this we must first cleanup any pending DMA,
+ * then restart stuff after a la ath5k_init.
*
* Called with sc->lock.
*/
@@ -1081,19 +1083,13 @@ ath5k_chan_set(struct ath5k_softc *sc, struct ieee80211_channel *chan)
ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "(%u MHz) -> (%u MHz)\n",
sc->curchan->center_freq, chan->center_freq);
- if (chan->center_freq != sc->curchan->center_freq ||
- chan->hw_value != sc->curchan->hw_value) {
-
- /*
- * To switch channels clear any pending DMA operations;
- * wait long enough for the RX fifo to drain, reset the
- * hardware at the new frequency, and then re-enable
- * the relevant bits of the h/w.
- */
- return ath5k_reset(sc, chan);
- }
-
- return 0;
+ /*
+ * To switch channels clear any pending DMA operations;
+ * wait long enough for the RX fifo to drain, reset the
+ * hardware at the new frequency, and then re-enable
+ * the relevant bits of the h/w.
+ */
+ return ath5k_reset(sc, chan);
}
static void
@@ -1114,6 +1110,8 @@ ath5k_mode_setup(struct ath5k_softc *sc)
struct ath5k_hw *ah = sc->ah;
u32 rfilt;
+ ah->ah_op_mode = sc->opmode;
+
/* configure rx filter */
rfilt = sc->filter_flags;
ath5k_hw_set_rx_filter(ah, rfilt);
@@ -1153,27 +1151,20 @@ static
struct sk_buff *ath5k_rx_skb_alloc(struct ath5k_softc *sc, dma_addr_t *skb_addr)
{
struct sk_buff *skb;
- unsigned int off;
/*
* Allocate buffer with headroom_needed space for the
* fake physical layer header at the start.
*/
- skb = dev_alloc_skb(sc->rxbufsize + sc->cachelsz - 1);
+ skb = ath_rxbuf_alloc(&sc->common,
+ sc->rxbufsize + sc->common.cachelsz - 1,
+ GFP_ATOMIC);
if (!skb) {
ATH5K_ERR(sc, "can't alloc skbuff of size %u\n",
- sc->rxbufsize + sc->cachelsz - 1);
+ sc->rxbufsize + sc->common.cachelsz - 1);
return NULL;
}
- /*
- * Cache-line-align. This is important (for the
- * 5210 at least) as not doing so causes bogus data
- * in rx'd frames.
- */
- off = ((unsigned long)skb->data) % sc->cachelsz;
- if (off != 0)
- skb_reserve(skb, sc->cachelsz - off);
*skb_addr = pci_map_single(sc->pdev,
skb->data, sc->rxbufsize, PCI_DMA_FROMDEVICE);
@@ -1228,10 +1219,10 @@ ath5k_rxbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
}
static int
-ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
+ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf,
+ struct ath5k_txq *txq)
{
struct ath5k_hw *ah = sc->ah;
- struct ath5k_txq *txq = sc->txq;
struct ath5k_desc *ds = bf->desc;
struct sk_buff *skb = bf->skb;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
@@ -1615,10 +1606,10 @@ ath5k_rx_start(struct ath5k_softc *sc)
struct ath5k_buf *bf;
int ret;
- sc->rxbufsize = roundup(IEEE80211_MAX_LEN, sc->cachelsz);
+ sc->rxbufsize = roundup(IEEE80211_MAX_LEN, sc->common.cachelsz);
ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "cachelsz %u rxbufsize %u\n",
- sc->cachelsz, sc->rxbufsize);
+ sc->common.cachelsz, sc->rxbufsize);
spin_lock_bh(&sc->rxbuflock);
sc->rxlink = NULL;
@@ -1901,7 +1892,8 @@ accept:
if (sc->opmode == NL80211_IFTYPE_ADHOC)
ath5k_check_ibss_tsf(sc, skb, &rxs);
- __ieee80211_rx(sc->hw, skb, &rxs);
+ memcpy(IEEE80211_SKB_RXCB(skb), &rxs, sizeof(rxs));
+ ieee80211_rx(sc->hw, skb);
bf->skb = next_skb;
bf->skbaddr = next_skb_addr;
@@ -1994,9 +1986,12 @@ ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq)
static void
ath5k_tasklet_tx(unsigned long data)
{
+ int i;
struct ath5k_softc *sc = (void *)data;
- ath5k_tx_processq(sc, sc->txq);
+ for (i=0; i < AR5K_NUM_TX_QUEUES; i++)
+ if (sc->txqs[i].setup && (sc->ah->ah_txq_isr & BIT(i)))
+ ath5k_tx_processq(sc, &sc->txqs[i]);
}
@@ -2078,13 +2073,6 @@ err_unmap:
return ret;
}
-static void ath5k_beacon_disable(struct ath5k_softc *sc)
-{
- sc->imask &= ~(AR5K_INT_BMISS | AR5K_INT_SWBA);
- ath5k_hw_set_imr(sc->ah, sc->imask);
- ath5k_hw_stop_tx_dma(sc->ah, sc->bhalq);
-}
-
/*
* Transmit a beacon frame at SWBA. Dynamic updates to the
* frame contents are done as needed and the slot time is
@@ -2098,6 +2086,7 @@ ath5k_beacon_send(struct ath5k_softc *sc)
{
struct ath5k_buf *bf = sc->bbuf;
struct ath5k_hw *ah = sc->ah;
+ struct sk_buff *skb;
ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON, "in beacon_send\n");
@@ -2151,6 +2140,12 @@ ath5k_beacon_send(struct ath5k_softc *sc)
ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, "TXDP[%u] = %llx (%p)\n",
sc->bhalq, (unsigned long long)bf->daddr, bf->desc);
+ skb = ieee80211_get_buffered_bc(sc->hw, sc->vif);
+ while (skb) {
+ ath5k_tx_queue(sc->hw, skb, sc->cabq);
+ skb = ieee80211_get_buffered_bc(sc->hw, sc->vif);
+ }
+
sc->bsent++;
}
@@ -2271,13 +2266,11 @@ ath5k_beacon_config(struct ath5k_softc *sc)
struct ath5k_hw *ah = sc->ah;
unsigned long flags;
- ath5k_hw_set_imr(ah, 0);
+ spin_lock_irqsave(&sc->block, flags);
sc->bmisscount = 0;
sc->imask &= ~(AR5K_INT_BMISS | AR5K_INT_SWBA);
- if (sc->opmode == NL80211_IFTYPE_ADHOC ||
- sc->opmode == NL80211_IFTYPE_MESH_POINT ||
- sc->opmode == NL80211_IFTYPE_AP) {
+ if (sc->enable_beacon) {
/*
* In IBSS mode we use a self-linked tx descriptor and let the
* hardware send the beacons automatically. We have to load it
@@ -2290,16 +2283,17 @@ ath5k_beacon_config(struct ath5k_softc *sc)
sc->imask |= AR5K_INT_SWBA;
if (sc->opmode == NL80211_IFTYPE_ADHOC) {
- if (ath5k_hw_hasveol(ah)) {
- spin_lock_irqsave(&sc->block, flags);
+ if (ath5k_hw_hasveol(ah))
ath5k_beacon_send(sc);
- spin_unlock_irqrestore(&sc->block, flags);
- }
} else
ath5k_beacon_update_timers(sc, -1);
+ } else {
+ ath5k_hw_stop_tx_dma(sc->ah, sc->bhalq);
}
ath5k_hw_set_imr(ah, sc->imask);
+ mmiowb();
+ spin_unlock_irqrestore(&sc->block, flags);
}
static void ath5k_tasklet_beacon(unsigned long data)
@@ -2363,7 +2357,7 @@ ath5k_init(struct ath5k_softc *sc)
sc->curband = &sc->sbands[sc->curchan->band];
sc->imask = AR5K_INT_RXOK | AR5K_INT_RXERR | AR5K_INT_RXEOL |
AR5K_INT_RXORN | AR5K_INT_TXDESC | AR5K_INT_TXEOL |
- AR5K_INT_FATAL | AR5K_INT_GLOBAL;
+ AR5K_INT_FATAL | AR5K_INT_GLOBAL | AR5K_INT_SWI;
ret = ath5k_reset(sc, NULL);
if (ret)
goto done;
@@ -2380,8 +2374,8 @@ ath5k_init(struct ath5k_softc *sc)
/* Set ack to be sent at low bit-rates */
ath5k_hw_set_ack_bitrate_high(ah, false);
- mod_timer(&sc->calib_tim, round_jiffies(jiffies +
- msecs_to_jiffies(ath5k_calinterval * 1000)));
+ /* Set PHY calibration inteval */
+ ah->ah_cal_intval = ath5k_calinterval;
ret = 0;
done:
@@ -2445,37 +2439,39 @@ ath5k_stop_hw(struct ath5k_softc *sc)
ret = ath5k_stop_locked(sc);
if (ret == 0 && !test_bit(ATH_STAT_INVALID, sc->status)) {
/*
- * Set the chip in full sleep mode. Note that we are
- * careful to do this only when bringing the interface
- * completely to a stop. When the chip is in this state
- * it must be carefully woken up or references to
- * registers in the PCI clock domain may freeze the bus
- * (and system). This varies by chip and is mostly an
- * issue with newer parts that go to sleep more quickly.
- */
- if (sc->ah->ah_mac_srev >= 0x78) {
- /*
- * XXX
- * don't put newer MAC revisions > 7.8 to sleep because
- * of the above mentioned problems
- */
- ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "mac version > 7.8, "
- "not putting device to sleep\n");
- } else {
- ATH5K_DBG(sc, ATH5K_DEBUG_RESET,
- "putting device to full sleep\n");
- ath5k_hw_set_power(sc->ah, AR5K_PM_FULL_SLEEP, true, 0);
- }
+ * Don't set the card in full sleep mode!
+ *
+ * a) When the device is in this state it must be carefully
+ * woken up or references to registers in the PCI clock
+ * domain may freeze the bus (and system). This varies
+ * by chip and is mostly an issue with newer parts
+ * (madwifi sources mentioned srev >= 0x78) that go to
+ * sleep more quickly.
+ *
+ * b) On older chips full sleep results a weird behaviour
+ * during wakeup. I tested various cards with srev < 0x78
+ * and they don't wake up after module reload, a second
+ * module reload is needed to bring the card up again.
+ *
+ * Until we figure out what's going on don't enable
+ * full chip reset on any chip (this is what Legacy HAL
+ * and Sam's HAL do anyway). Instead Perform a full reset
+ * on the device (same as initial state after attach) and
+ * leave it idle (keep MAC/BB on warm reset) */
+ ret = ath5k_hw_on_hold(sc->ah);
+
+ ATH5K_DBG(sc, ATH5K_DEBUG_RESET,
+ "putting device to sleep\n");
}
ath5k_txbuf_free(sc, sc->bbuf);
mmiowb();
mutex_unlock(&sc->lock);
- del_timer_sync(&sc->calib_tim);
tasklet_kill(&sc->rxtq);
tasklet_kill(&sc->txtq);
tasklet_kill(&sc->restq);
+ tasklet_kill(&sc->calib);
tasklet_kill(&sc->beacontq);
ath5k_rfkill_hw_stop(sc->ah);
@@ -2531,6 +2527,9 @@ ath5k_intr(int irq, void *dev_id)
if (status & AR5K_INT_BMISS) {
/* TODO */
}
+ if (status & AR5K_INT_SWI) {
+ tasklet_schedule(&sc->calib);
+ }
if (status & AR5K_INT_MIB) {
/*
* These stats are also used for ANI i think
@@ -2547,6 +2546,8 @@ ath5k_intr(int irq, void *dev_id)
if (unlikely(!counter))
ATH5K_WARN(sc, "too many interrupts, giving up for now\n");
+ ath5k_hw_calibration_poll(ah);
+
return IRQ_HANDLED;
}
@@ -2563,11 +2564,19 @@ ath5k_tasklet_reset(unsigned long data)
* for temperature/environment changes.
*/
static void
-ath5k_calibrate(unsigned long data)
+ath5k_tasklet_calibrate(unsigned long data)
{
struct ath5k_softc *sc = (void *)data;
struct ath5k_hw *ah = sc->ah;
+ /* Only full calibration for now */
+ if (ah->ah_swi_mask != AR5K_SWI_FULL_CALIBRATION)
+ return;
+
+ /* Stop queues so that calibration
+ * doesn't interfere with tx */
+ ieee80211_stop_queues(sc->hw);
+
ATH5K_DBG(sc, ATH5K_DEBUG_CALIBRATE, "channel %u/%x\n",
ieee80211_frequency_to_channel(sc->curchan->center_freq),
sc->curchan->hw_value);
@@ -2585,8 +2594,11 @@ ath5k_calibrate(unsigned long data)
ieee80211_frequency_to_channel(
sc->curchan->center_freq));
- mod_timer(&sc->calib_tim, round_jiffies(jiffies +
- msecs_to_jiffies(ath5k_calinterval * 1000)));
+ ah->ah_swi_mask = 0;
+
+ /* Wake queues */
+ ieee80211_wake_queues(sc->hw);
+
}
@@ -2598,6 +2610,14 @@ static int
ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
{
struct ath5k_softc *sc = hw->priv;
+
+ return ath5k_tx_queue(hw, skb, sc->txq);
+}
+
+static int ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb,
+ struct ath5k_txq *txq)
+{
+ struct ath5k_softc *sc = hw->priv;
struct ath5k_buf *bf;
unsigned long flags;
int hdrlen;
@@ -2641,7 +2661,7 @@ ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
bf->skb = skb;
- if (ath5k_txbuf_setup(sc, bf)) {
+ if (ath5k_txbuf_setup(sc, bf, txq)) {
bf->skb = NULL;
spin_lock_irqsave(&sc->txbuflock, flags);
list_add_tail(&bf->list, &sc->txbuf);
@@ -2676,7 +2696,7 @@ ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan)
sc->curchan = chan;
sc->curband = &sc->sbands[chan->band];
}
- ret = ath5k_hw_reset(ah, sc->opmode, sc->curchan, true);
+ ret = ath5k_hw_reset(ah, sc->opmode, sc->curchan, chan != NULL);
if (ret) {
ATH5K_ERR(sc, "can't reset hardware (%d)\n", ret);
goto err;
@@ -2757,6 +2777,7 @@ static int ath5k_add_interface(struct ieee80211_hw *hw,
}
ath5k_hw_set_lladdr(sc->ah, conf->mac_addr);
+ ath5k_mode_setup(sc);
ret = 0;
end:
@@ -2776,7 +2797,6 @@ ath5k_remove_interface(struct ieee80211_hw *hw,
goto end;
ath5k_hw_set_lladdr(sc->ah, mac);
- ath5k_beacon_disable(sc);
sc->vif = NULL;
end:
mutex_unlock(&sc->lock);
@@ -2795,9 +2815,11 @@ ath5k_config(struct ieee80211_hw *hw, u32 changed)
mutex_lock(&sc->lock);
- ret = ath5k_chan_set(sc, conf->channel);
- if (ret < 0)
- goto unlock;
+ if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
+ ret = ath5k_chan_set(sc, conf->channel);
+ if (ret < 0)
+ goto unlock;
+ }
if ((changed & IEEE80211_CONF_CHANGE_POWER) &&
(sc->power_level != conf->power_level)) {
@@ -3108,25 +3130,6 @@ out:
return ret;
}
-/*
- * Update the beacon and reconfigure the beacon queues.
- */
-static void
-ath5k_beacon_reconfig(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
-{
- int ret;
- unsigned long flags;
- struct ath5k_softc *sc = hw->priv;
-
- spin_lock_irqsave(&sc->block, flags);
- ret = ath5k_beacon_update(hw, vif);
- spin_unlock_irqrestore(&sc->block, flags);
- if (ret == 0) {
- ath5k_beacon_config(sc);
- mmiowb();
- }
-}
-
static void
set_beacon_filter(struct ieee80211_hw *hw, bool enable)
{
@@ -3149,6 +3152,7 @@ static void ath5k_bss_info_changed(struct ieee80211_hw *hw,
{
struct ath5k_softc *sc = hw->priv;
struct ath5k_hw *ah = sc->ah;
+ unsigned long flags;
mutex_lock(&sc->lock);
if (WARN_ON(sc->vif != vif))
@@ -3170,15 +3174,37 @@ static void ath5k_bss_info_changed(struct ieee80211_hw *hw,
sc->assoc = bss_conf->assoc;
if (sc->opmode == NL80211_IFTYPE_STATION)
set_beacon_filter(hw, sc->assoc);
+ ath5k_hw_set_ledstate(sc->ah, sc->assoc ?
+ AR5K_LED_ASSOC : AR5K_LED_INIT);
}
- if (changes & BSS_CHANGED_BEACON &&
- (vif->type == NL80211_IFTYPE_ADHOC ||
- vif->type == NL80211_IFTYPE_MESH_POINT ||
- vif->type == NL80211_IFTYPE_AP)) {
- ath5k_beacon_reconfig(hw, vif);
+ if (changes & BSS_CHANGED_BEACON) {
+ spin_lock_irqsave(&sc->block, flags);
+ ath5k_beacon_update(hw, vif);
+ spin_unlock_irqrestore(&sc->block, flags);
}
+ if (changes & BSS_CHANGED_BEACON_ENABLED)
+ sc->enable_beacon = bss_conf->enable_beacon;
+
+ if (changes & (BSS_CHANGED_BEACON | BSS_CHANGED_BEACON_ENABLED |
+ BSS_CHANGED_BEACON_INT))
+ ath5k_beacon_config(sc);
+
unlock:
mutex_unlock(&sc->lock);
}
+
+static void ath5k_sw_scan_start(struct ieee80211_hw *hw)
+{
+ struct ath5k_softc *sc = hw->priv;
+ if (!sc->assoc)
+ ath5k_hw_set_ledstate(sc->ah, AR5K_LED_SCAN);
+}
+
+static void ath5k_sw_scan_complete(struct ieee80211_hw *hw)
+{
+ struct ath5k_softc *sc = hw->priv;
+ ath5k_hw_set_ledstate(sc->ah, sc->assoc ?
+ AR5K_LED_ASSOC : AR5K_LED_INIT);
+}
diff --git a/drivers/net/wireless/ath/ath5k/base.h b/drivers/net/wireless/ath/ath5k/base.h
index f9b7f2f819b..25a72a85aaa 100644
--- a/drivers/net/wireless/ath/ath5k/base.h
+++ b/drivers/net/wireless/ath/ath5k/base.h
@@ -50,6 +50,7 @@
#include "ath5k.h"
#include "debug.h"
+#include "../ath.h"
#define ATH_RXBUF 40 /* number of RX buffers */
#define ATH_TXBUF 200 /* number of TX buffers */
@@ -112,10 +113,10 @@ struct ath5k_rfkill {
* associated with an instance of a device */
struct ath5k_softc {
struct pci_dev *pdev; /* for dma mapping */
+ struct ath_common common;
void __iomem *iobase; /* address of the device */
struct mutex lock; /* dev-level lock */
- /* FIXME: how many does it really need? */
- struct ieee80211_tx_queue_stats tx_stats[16];
+ struct ieee80211_tx_queue_stats tx_stats[AR5K_NUM_TX_QUEUES];
struct ieee80211_low_level_stats ll_stats;
struct ieee80211_hw *hw; /* IEEE 802.11 common */
struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS];
@@ -135,7 +136,6 @@ struct ath5k_softc {
struct ath5k_desc *desc; /* TX/RX descriptors */
dma_addr_t desc_daddr; /* DMA (physical) address */
size_t desc_len; /* size of TX/RX descriptors */
- u16 cachelsz; /* cache line size */
DECLARE_BITMAP(status, 5);
#define ATH_STAT_INVALID 0 /* disable hardware accesses */
@@ -171,14 +171,15 @@ struct ath5k_softc {
struct list_head txbuf; /* transmit buffer */
spinlock_t txbuflock;
unsigned int txbuf_len; /* buf count in txbuf list */
- struct ath5k_txq txqs[2]; /* beacon and tx */
-
- struct ath5k_txq *txq; /* beacon and tx*/
+ struct ath5k_txq txqs[AR5K_NUM_TX_QUEUES]; /* tx queues */
+ struct ath5k_txq *txq; /* main tx queue */
struct tasklet_struct txtq; /* tx intr tasklet */
struct ath5k_led tx_led; /* tx led */
struct ath5k_rfkill rf_kill;
+ struct tasklet_struct calib; /* calibration tasklet */
+
spinlock_t block; /* protects beacon */
struct tasklet_struct beacontq; /* beacon intr tasklet */
struct ath5k_buf *bbuf; /* beacon buffer */
@@ -187,10 +188,11 @@ struct ath5k_softc {
bintval, /* beacon interval in TU */
bsent;
unsigned int nexttbtt; /* next beacon time in TU */
+ struct ath5k_txq *cabq; /* content after beacon */
- struct timer_list calib_tim; /* calibration timer */
int power_level; /* Requested tx power in dbm */
bool assoc; /* assocate state */
+ bool enable_beacon; /* true if beacons are on */
};
#define ath5k_hw_hasbssidmask(_ah) \
diff --git a/drivers/net/wireless/ath/ath5k/debug.c b/drivers/net/wireless/ath/ath5k/debug.c
index 4904a07e4b5..747508c15d3 100644
--- a/drivers/net/wireless/ath/ath5k/debug.c
+++ b/drivers/net/wireless/ath/ath5k/debug.c
@@ -380,13 +380,15 @@ ath5k_debug_init_device(struct ath5k_softc *sc)
sc->debug.debugfs_phydir = debugfs_create_dir(wiphy_name(sc->hw->wiphy),
ath5k_global_debugfs);
- sc->debug.debugfs_debug = debugfs_create_file("debug", S_IWUSR | S_IRUGO,
+ sc->debug.debugfs_debug = debugfs_create_file("debug",
+ S_IWUSR | S_IRUSR,
sc->debug.debugfs_phydir, sc, &fops_debug);
- sc->debug.debugfs_registers = debugfs_create_file("registers", S_IRUGO,
+ sc->debug.debugfs_registers = debugfs_create_file("registers", S_IRUSR,
sc->debug.debugfs_phydir, sc, &fops_registers);
- sc->debug.debugfs_beacon = debugfs_create_file("beacon", S_IWUSR | S_IRUGO,
+ sc->debug.debugfs_beacon = debugfs_create_file("beacon",
+ S_IWUSR | S_IRUSR,
sc->debug.debugfs_phydir, sc, &fops_beacon);
sc->debug.debugfs_reset = debugfs_create_file("reset", S_IWUSR,
diff --git a/drivers/net/wireless/ath/ath5k/eeprom.c b/drivers/net/wireless/ath/ath5k/eeprom.c
index c56b494d417..8af477dd6fc 100644
--- a/drivers/net/wireless/ath/ath5k/eeprom.c
+++ b/drivers/net/wireless/ath/ath5k/eeprom.c
@@ -167,6 +167,16 @@ ath5k_eeprom_init_header(struct ath5k_hw *ah)
ee->ee_rfkill_pin = (u8) AR5K_REG_MS(val, AR5K_EEPROM_RFKILL_GPIO_SEL);
ee->ee_rfkill_pol = val & AR5K_EEPROM_RFKILL_POLARITY ? true : false;
+ /* Check if PCIE_OFFSET points to PCIE_SERDES_SECTION
+ * and enable serdes programming if needed.
+ *
+ * XXX: Serdes values seem to be fixed so
+ * no need to read them here, we write them
+ * during ath5k_hw_attach */
+ AR5K_EEPROM_READ(AR5K_EEPROM_PCIE_OFFSET, val);
+ ee->ee_serdes = (val == AR5K_EEPROM_PCIE_SERDES_SECTION) ?
+ true : false;
+
return 0;
}
diff --git a/drivers/net/wireless/ath/ath5k/eeprom.h b/drivers/net/wireless/ath/ath5k/eeprom.h
index 64be73a5eda..0123f3521a0 100644
--- a/drivers/net/wireless/ath/ath5k/eeprom.h
+++ b/drivers/net/wireless/ath/ath5k/eeprom.h
@@ -19,6 +19,9 @@
/*
* Common ar5xxx EEPROM data offsets (set these on AR5K_EEPROM_BASE)
*/
+#define AR5K_EEPROM_PCIE_OFFSET 0x02 /* Contains offset to PCI-E infos */
+#define AR5K_EEPROM_PCIE_SERDES_SECTION 0x40 /* PCIE_OFFSET points here when
+ * SERDES infos are present */
#define AR5K_EEPROM_MAGIC 0x003d /* EEPROM Magic number */
#define AR5K_EEPROM_MAGIC_VALUE 0x5aa5 /* Default - found on EEPROM */
#define AR5K_EEPROM_MAGIC_5212 0x0000145c /* 5212 */
@@ -391,6 +394,7 @@ struct ath5k_eeprom_info {
u8 ee_rfkill_pin;
bool ee_rfkill_pol;
bool ee_is_hb63;
+ bool ee_serdes;
u16 ee_misc0;
u16 ee_misc1;
u16 ee_misc2;
diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c
index a876ca8d69e..298fcf01522 100644
--- a/drivers/net/wireless/ath/ath5k/phy.c
+++ b/drivers/net/wireless/ath/ath5k/phy.c
@@ -740,13 +740,22 @@ int ath5k_hw_rfregs_init(struct ath5k_hw *ah, struct ieee80211_channel *channel,
AR5K_RF_XPD_GAIN, true);
} else {
- /* TODO: Set high and low gain bits */
- ath5k_hw_rfb_op(ah, rf_regs,
- ee->ee_x_gain[ee_mode],
+ u8 *pdg_curve_to_idx = ee->ee_pdc_to_idx[ee_mode];
+ if (ee->ee_pd_gains[ee_mode] > 1) {
+ ath5k_hw_rfb_op(ah, rf_regs,
+ pdg_curve_to_idx[0],
AR5K_RF_PD_GAIN_LO, true);
- ath5k_hw_rfb_op(ah, rf_regs,
- ee->ee_x_gain[ee_mode],
+ ath5k_hw_rfb_op(ah, rf_regs,
+ pdg_curve_to_idx[1],
AR5K_RF_PD_GAIN_HI, true);
+ } else {
+ ath5k_hw_rfb_op(ah, rf_regs,
+ pdg_curve_to_idx[0],
+ AR5K_RF_PD_GAIN_LO, true);
+ ath5k_hw_rfb_op(ah, rf_regs,
+ pdg_curve_to_idx[0],
+ AR5K_RF_PD_GAIN_HI, true);
+ }
/* Lower synth voltage on Rev 2 */
ath5k_hw_rfb_op(ah, rf_regs, 2,
@@ -1085,8 +1094,7 @@ int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel)
AR5K_PHY_CCKTXCTL_WORLD);
}
- ah->ah_current_channel.center_freq = channel->center_freq;
- ah->ah_current_channel.hw_value = channel->hw_value;
+ ah->ah_current_channel = channel;
ah->ah_turbo = channel->hw_value == CHANNEL_T ? true : false;
return 0;
@@ -1096,6 +1104,29 @@ int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel)
PHY calibration
\*****************/
+void
+ath5k_hw_calibration_poll(struct ath5k_hw *ah)
+{
+ /* Calibration interval in jiffies */
+ unsigned long cal_intval;
+
+ cal_intval = msecs_to_jiffies(ah->ah_cal_intval * 1000);
+
+ /* Initialize timestamp if needed */
+ if (!ah->ah_cal_tstamp)
+ ah->ah_cal_tstamp = jiffies;
+
+ /* For now we always do full calibration
+ * Mark software interrupt mask and fire software
+ * interrupt (bit gets auto-cleared) */
+ if (time_is_before_eq_jiffies(ah->ah_cal_tstamp + cal_intval)) {
+ ah->ah_cal_tstamp = jiffies;
+ ah->ah_swi_mask = AR5K_SWI_FULL_CALIBRATION;
+ AR5K_REG_ENABLE_BITS(ah, AR5K_CR, AR5K_CR_SWI);
+ }
+
+}
+
/**
* ath5k_hw_noise_floor_calibration - perform PHY noise floor calibration
*
@@ -1731,7 +1762,7 @@ ath5k_hw_set_fast_div(struct ath5k_hw *ah, u8 ee_mode, bool enable)
void
ath5k_hw_set_antenna_mode(struct ath5k_hw *ah, u8 ant_mode)
{
- struct ieee80211_channel *channel = &ah->ah_current_channel;
+ struct ieee80211_channel *channel = ah->ah_current_channel;
bool use_def_for_tx, update_def_on_tx, use_def_for_rts, fast_div;
bool use_def_for_sg;
u8 def_ant, tx_ant, ee_mode;
@@ -1897,8 +1928,9 @@ ath5k_get_linear_pcdac_min(const u8 *stepL, const u8 *stepR,
s16 min_pwrL, min_pwrR;
s16 pwr_i;
- if (WARN_ON(stepL[0] == stepL[1] || stepR[0] == stepR[1]))
- return 0;
+ /* Some vendors write the same pcdac value twice !!! */
+ if (stepL[0] == stepL[1] || stepR[0] == stepR[1])
+ return max(pwrL[0], pwrR[0]);
if (pwrL[0] == pwrL[1])
min_pwrL = pwrL[0];
@@ -3011,7 +3043,7 @@ ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel,
int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 txpower)
{
/*Just a try M.F.*/
- struct ieee80211_channel *channel = &ah->ah_current_channel;
+ struct ieee80211_channel *channel = ah->ah_current_channel;
u8 ee_mode;
ATH5K_TRACE(ah->ah_sc);
diff --git a/drivers/net/wireless/ath/ath5k/qcu.c b/drivers/net/wireless/ath/ath5k/qcu.c
index 73407b3f53e..eeebb9aef20 100644
--- a/drivers/net/wireless/ath/ath5k/qcu.c
+++ b/drivers/net/wireless/ath/ath5k/qcu.c
@@ -362,7 +362,7 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue)
}
if (tq->tqi_ready_time &&
- (tq->tqi_type != AR5K_TX_QUEUE_ID_CAB))
+ (tq->tqi_type != AR5K_TX_QUEUE_CAB))
ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_ready_time,
AR5K_QCU_RDYTIMECFG_INTVAL) |
AR5K_QCU_RDYTIMECFG_ENABLE,
@@ -411,7 +411,6 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue)
AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
AR5K_QCU_MISC_FRSHED_BCN_SENT_GT |
AR5K_QCU_MISC_CBREXP_DIS |
- AR5K_QCU_MISC_RDY_VEOL_POLICY |
AR5K_QCU_MISC_CBREXP_BCN_DIS);
ath5k_hw_reg_write(ah, ((AR5K_TUNE_BEACON_INTERVAL -
diff --git a/drivers/net/wireless/ath/ath5k/reg.h b/drivers/net/wireless/ath/ath5k/reg.h
index 6809b54a2ad..debad07d990 100644
--- a/drivers/net/wireless/ath/ath5k/reg.h
+++ b/drivers/net/wireless/ath/ath5k/reg.h
@@ -339,9 +339,9 @@
#define AR5K_SISR2 0x008c /* Register Address [5211+] */
#define AR5K_SISR2_QCU_TXURN 0x000003ff /* Mask for QCU_TXURN */
#define AR5K_SISR2_QCU_TXURN_S 0
-#define AR5K_SISR2_MCABT 0x00100000 /* Master Cycle Abort */
-#define AR5K_SISR2_SSERR 0x00200000 /* Signaled System Error */
-#define AR5K_SISR2_DPERR 0x00400000 /* Bus parity error */
+#define AR5K_SISR2_MCABT 0x00010000 /* Master Cycle Abort */
+#define AR5K_SISR2_SSERR 0x00020000 /* Signaled System Error */
+#define AR5K_SISR2_DPERR 0x00040000 /* Bus parity error */
#define AR5K_SISR2_TIM 0x01000000 /* [5212+] */
#define AR5K_SISR2_CAB_END 0x02000000 /* [5212+] */
#define AR5K_SISR2_DTIM_SYNC 0x04000000 /* DTIM sync lost [5212+] */
@@ -430,9 +430,9 @@
#define AR5K_SIMR2 0x00ac /* Register Address [5211+] */
#define AR5K_SIMR2_QCU_TXURN 0x000003ff /* Mask for QCU_TXURN */
#define AR5K_SIMR2_QCU_TXURN_S 0
-#define AR5K_SIMR2_MCABT 0x00100000 /* Master Cycle Abort */
-#define AR5K_SIMR2_SSERR 0x00200000 /* Signaled System Error */
-#define AR5K_SIMR2_DPERR 0x00400000 /* Bus parity error */
+#define AR5K_SIMR2_MCABT 0x00010000 /* Master Cycle Abort */
+#define AR5K_SIMR2_SSERR 0x00020000 /* Signaled System Error */
+#define AR5K_SIMR2_DPERR 0x00040000 /* Bus parity error */
#define AR5K_SIMR2_TIM 0x01000000 /* [5212+] */
#define AR5K_SIMR2_CAB_END 0x02000000 /* [5212+] */
#define AR5K_SIMR2_DTIM_SYNC 0x04000000 /* DTIM Sync lost [5212+] */
diff --git a/drivers/net/wireless/ath/ath5k/reset.c b/drivers/net/wireless/ath/ath5k/reset.c
index bd0a97a38d3..34e13c70084 100644
--- a/drivers/net/wireless/ath/ath5k/reset.c
+++ b/drivers/net/wireless/ath/ath5k/reset.c
@@ -258,29 +258,35 @@ int ath5k_hw_set_power(struct ath5k_hw *ah, enum ath5k_power_mode mode,
if (!set_chip)
goto commit;
- /* Preserve sleep duration */
data = ath5k_hw_reg_read(ah, AR5K_SLEEP_CTL);
+
+ /* If card is down we 'll get 0xffff... so we
+ * need to clean this up before we write the register
+ */
if (data & 0xffc00000)
data = 0;
else
- data = data & 0xfffcffff;
+ /* Preserve sleep duration etc */
+ data = data & ~AR5K_SLEEP_CTL_SLE;
- ath5k_hw_reg_write(ah, data, AR5K_SLEEP_CTL);
+ ath5k_hw_reg_write(ah, data | AR5K_SLEEP_CTL_SLE_WAKE,
+ AR5K_SLEEP_CTL);
udelay(15);
- for (i = 50; i > 0; i--) {
+ for (i = 200; i > 0; i--) {
/* Check if the chip did wake up */
if ((ath5k_hw_reg_read(ah, AR5K_PCICFG) &
AR5K_PCICFG_SPWR_DN) == 0)
break;
/* Wait a bit and retry */
- udelay(200);
- ath5k_hw_reg_write(ah, data, AR5K_SLEEP_CTL);
+ udelay(50);
+ ath5k_hw_reg_write(ah, data | AR5K_SLEEP_CTL_SLE_WAKE,
+ AR5K_SLEEP_CTL);
}
/* Fail if the chip didn't wake up */
- if (i <= 0)
+ if (i == 0)
return -EIO;
break;
@@ -290,13 +296,70 @@ int ath5k_hw_set_power(struct ath5k_hw *ah, enum ath5k_power_mode mode,
}
commit:
- ah->ah_power_mode = mode;
ath5k_hw_reg_write(ah, staid, AR5K_STA_ID1);
return 0;
}
/*
+ * Put device on hold
+ *
+ * Put MAC and Baseband on warm reset and
+ * keep that state (don't clean sleep control
+ * register). After this MAC and Baseband are
+ * disabled and a full reset is needed to come
+ * back. This way we save as much power as possible
+ * without puting the card on full sleep.
+ */
+int ath5k_hw_on_hold(struct ath5k_hw *ah)
+{
+ struct pci_dev *pdev = ah->ah_sc->pdev;
+ u32 bus_flags;
+ int ret;
+
+ /* Make sure device is awake */
+ ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0);
+ if (ret) {
+ ATH5K_ERR(ah->ah_sc, "failed to wakeup the MAC Chip\n");
+ return ret;
+ }
+
+ /*
+ * Put chipset on warm reset...
+ *
+ * Note: puting PCI core on warm reset on PCI-E cards
+ * results card to hang and always return 0xffff... so
+ * we ingore that flag for PCI-E cards. On PCI cards
+ * this flag gets cleared after 64 PCI clocks.
+ */
+ bus_flags = (pdev->is_pcie) ? 0 : AR5K_RESET_CTL_PCI;
+
+ if (ah->ah_version == AR5K_AR5210) {
+ ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU |
+ AR5K_RESET_CTL_MAC | AR5K_RESET_CTL_DMA |
+ AR5K_RESET_CTL_PHY | AR5K_RESET_CTL_PCI);
+ mdelay(2);
+ } else {
+ ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU |
+ AR5K_RESET_CTL_BASEBAND | bus_flags);
+ }
+
+ if (ret) {
+ ATH5K_ERR(ah->ah_sc, "failed to put device on warm reset\n");
+ return -EIO;
+ }
+
+ /* ...wakeup again!*/
+ ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0);
+ if (ret) {
+ ATH5K_ERR(ah->ah_sc, "failed to put device on hold\n");
+ return ret;
+ }
+
+ return ret;
+}
+
+/*
* Bring up MAC + PHY Chips and program PLL
* TODO: Half/Quarter rate support
*/
@@ -319,6 +382,50 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial)
return ret;
}
+ /*
+ * Put chipset on warm reset...
+ *
+ * Note: puting PCI core on warm reset on PCI-E cards
+ * results card to hang and always return 0xffff... so
+ * we ingore that flag for PCI-E cards. On PCI cards
+ * this flag gets cleared after 64 PCI clocks.
+ */
+ bus_flags = (pdev->is_pcie) ? 0 : AR5K_RESET_CTL_PCI;
+
+ if (ah->ah_version == AR5K_AR5210) {
+ ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU |
+ AR5K_RESET_CTL_MAC | AR5K_RESET_CTL_DMA |
+ AR5K_RESET_CTL_PHY | AR5K_RESET_CTL_PCI);
+ mdelay(2);
+ } else {
+ ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU |
+ AR5K_RESET_CTL_BASEBAND | bus_flags);
+ }
+
+ if (ret) {
+ ATH5K_ERR(ah->ah_sc, "failed to reset the MAC Chip\n");
+ return -EIO;
+ }
+
+ /* ...wakeup again!...*/
+ ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0);
+ if (ret) {
+ ATH5K_ERR(ah->ah_sc, "failed to resume the MAC Chip\n");
+ return ret;
+ }
+
+ /* ...clear reset control register and pull device out of
+ * warm reset */
+ if (ath5k_hw_nic_reset(ah, 0)) {
+ ATH5K_ERR(ah->ah_sc, "failed to warm reset the MAC Chip\n");
+ return -EIO;
+ }
+
+ /* On initialization skip PLL programming since we don't have
+ * a channel / mode set yet */
+ if (initial)
+ return 0;
+
if (ah->ah_version != AR5K_AR5210) {
/*
* Get channel mode flags
@@ -384,39 +491,6 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial)
AR5K_PHY_TURBO);
}
- /* reseting PCI on PCI-E cards results card to hang
- * and always return 0xffff... so we ingore that flag
- * for PCI-E cards */
- bus_flags = (pdev->is_pcie) ? 0 : AR5K_RESET_CTL_PCI;
-
- /* Reset chipset */
- if (ah->ah_version == AR5K_AR5210) {
- ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU |
- AR5K_RESET_CTL_MAC | AR5K_RESET_CTL_DMA |
- AR5K_RESET_CTL_PHY | AR5K_RESET_CTL_PCI);
- mdelay(2);
- } else {
- ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU |
- AR5K_RESET_CTL_BASEBAND | bus_flags);
- }
- if (ret) {
- ATH5K_ERR(ah->ah_sc, "failed to reset the MAC Chip\n");
- return -EIO;
- }
-
- /* ...wakeup again!*/
- ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0);
- if (ret) {
- ATH5K_ERR(ah->ah_sc, "failed to resume the MAC Chip\n");
- return ret;
- }
-
- /* ...final warm reset */
- if (ath5k_hw_nic_reset(ah, 0)) {
- ATH5K_ERR(ah->ah_sc, "failed to warm reset the MAC Chip\n");
- return -EIO;
- }
-
if (ah->ah_version != AR5K_AR5210) {
/* ...update PLL if needed */
diff --git a/drivers/net/wireless/ath/ath9k/Kconfig b/drivers/net/wireless/ath/ath9k/Kconfig
index 2d79610bce1..ef5f59c4dd8 100644
--- a/drivers/net/wireless/ath/ath9k/Kconfig
+++ b/drivers/net/wireless/ath/ath9k/Kconfig
@@ -1,13 +1,18 @@
config ATH9K
tristate "Atheros 802.11n wireless cards support"
depends on PCI && MAC80211 && WLAN_80211
- select ATH_COMMON
select MAC80211_LEDS
select LEDS_CLASS
select NEW_LEDS
---help---
This module adds support for wireless adapters based on
- Atheros IEEE 802.11n AR5008 and AR9001 family of chipsets.
+ Atheros IEEE 802.11n AR5008, AR9001 and AR9002 family
+ of chipsets. For a specific list of supported external
+ cards, laptops that already ship with these cards and
+ APs that come with these cards refer to to ath9k wiki
+ products page:
+
+ http://wireless.kernel.org/en/users/Drivers/ath9k/products
If you choose to build a module, it'll be called ath9k.
@@ -18,6 +23,6 @@ config ATH9K_DEBUG
Say Y, if you need ath9k to display debug messages.
Pass the debug mask as a module parameter:
- modprobe ath9k debug=0x00002000
+ modprobe ath9k debug=0x00000200
- Look in ath9k/core.h for possible debug masks
+ Look in ath9k/debug.h for possible debug masks
diff --git a/drivers/net/wireless/ath/ath9k/Makefile b/drivers/net/wireless/ath/ath9k/Makefile
index 783bc39eb2f..28443e05ec1 100644
--- a/drivers/net/wireless/ath/ath9k/Makefile
+++ b/drivers/net/wireless/ath/ath9k/Makefile
@@ -1,5 +1,8 @@
ath9k-y += hw.o \
eeprom.o \
+ eeprom_def.o \
+ eeprom_4k.o \
+ eeprom_9287.o \
mac.o \
calib.o \
ani.o \
diff --git a/drivers/net/wireless/ath/ath9k/ahb.c b/drivers/net/wireless/ath/ath9k/ahb.c
index 0e65c51ba17..5618fc25d52 100644
--- a/drivers/net/wireless/ath/ath9k/ahb.c
+++ b/drivers/net/wireless/ath/ath9k/ahb.c
@@ -119,7 +119,7 @@ static int ath_ahb_probe(struct platform_device *pdev)
sc->bus_ops = &ath_ahb_bus_ops;
sc->irq = irq;
- ret = ath_attach(AR5416_AR9100_DEVID, sc);
+ ret = ath_init_device(AR5416_AR9100_DEVID, sc);
if (ret != 0) {
dev_err(&pdev->dev, "failed to attach device, err=%d\n", ret);
ret = -ENODEV;
diff --git a/drivers/net/wireless/ath/ath9k/ani.c b/drivers/net/wireless/ath/ath9k/ani.c
index aad259b4c19..f264097a2f4 100644
--- a/drivers/net/wireless/ath/ath9k/ani.c
+++ b/drivers/net/wireless/ath/ath9k/ani.c
@@ -236,36 +236,35 @@ static void ath9k_ani_restart(struct ath_hw *ah)
return;
aniState = ah->curani;
-
aniState->listenTime = 0;
- if (ah->has_hw_phycounters) {
- if (aniState->ofdmTrigHigh > AR_PHY_COUNTMAX) {
- aniState->ofdmPhyErrBase = 0;
- DPRINTF(ah->ah_sc, ATH_DBG_ANI,
- "OFDM Trigger is too high for hw counters\n");
- } else {
- aniState->ofdmPhyErrBase =
- AR_PHY_COUNTMAX - aniState->ofdmTrigHigh;
- }
- if (aniState->cckTrigHigh > AR_PHY_COUNTMAX) {
- aniState->cckPhyErrBase = 0;
- DPRINTF(ah->ah_sc, ATH_DBG_ANI,
- "CCK Trigger is too high for hw counters\n");
- } else {
- aniState->cckPhyErrBase =
- AR_PHY_COUNTMAX - aniState->cckTrigHigh;
- }
+
+ if (aniState->ofdmTrigHigh > AR_PHY_COUNTMAX) {
+ aniState->ofdmPhyErrBase = 0;
DPRINTF(ah->ah_sc, ATH_DBG_ANI,
- "Writing ofdmbase=%u cckbase=%u\n",
- aniState->ofdmPhyErrBase,
- aniState->cckPhyErrBase);
- REG_WRITE(ah, AR_PHY_ERR_1, aniState->ofdmPhyErrBase);
- REG_WRITE(ah, AR_PHY_ERR_2, aniState->cckPhyErrBase);
- REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
- REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
-
- ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
+ "OFDM Trigger is too high for hw counters\n");
+ } else {
+ aniState->ofdmPhyErrBase =
+ AR_PHY_COUNTMAX - aniState->ofdmTrigHigh;
+ }
+ if (aniState->cckTrigHigh > AR_PHY_COUNTMAX) {
+ aniState->cckPhyErrBase = 0;
+ DPRINTF(ah->ah_sc, ATH_DBG_ANI,
+ "CCK Trigger is too high for hw counters\n");
+ } else {
+ aniState->cckPhyErrBase =
+ AR_PHY_COUNTMAX - aniState->cckTrigHigh;
}
+ DPRINTF(ah->ah_sc, ATH_DBG_ANI,
+ "Writing ofdmbase=%u cckbase=%u\n",
+ aniState->ofdmPhyErrBase,
+ aniState->cckPhyErrBase);
+ REG_WRITE(ah, AR_PHY_ERR_1, aniState->ofdmPhyErrBase);
+ REG_WRITE(ah, AR_PHY_ERR_2, aniState->cckPhyErrBase);
+ REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
+ REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
+
+ ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
+
aniState->ofdmPhyErrCount = 0;
aniState->cckPhyErrCount = 0;
}
@@ -530,18 +529,12 @@ void ath9k_ani_reset(struct ath_hw *ah)
if (aniState->firstepLevel != 0)
ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
aniState->firstepLevel);
- if (ah->has_hw_phycounters) {
- ath9k_hw_setrxfilter(ah, ath9k_hw_getrxfilter(ah) &
- ~ATH9K_RX_FILTER_PHYERR);
- ath9k_ani_restart(ah);
- REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
- REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
- } else {
- ath9k_ani_restart(ah);
- ath9k_hw_setrxfilter(ah, ath9k_hw_getrxfilter(ah) |
- ATH9K_RX_FILTER_PHYERR);
- }
+ ath9k_hw_setrxfilter(ah, ath9k_hw_getrxfilter(ah) &
+ ~ATH9K_RX_FILTER_PHYERR);
+ ath9k_ani_restart(ah);
+ REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
+ REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
}
void ath9k_hw_ani_monitor(struct ath_hw *ah,
@@ -550,6 +543,8 @@ void ath9k_hw_ani_monitor(struct ath_hw *ah,
{
struct ar5416AniState *aniState;
int32_t listenTime;
+ u32 phyCnt1, phyCnt2;
+ u32 ofdmPhyErrCnt, cckPhyErrCnt;
if (!DO_ANI(ah))
return;
@@ -566,50 +561,45 @@ void ath9k_hw_ani_monitor(struct ath_hw *ah,
aniState->listenTime += listenTime;
- if (ah->has_hw_phycounters) {
- u32 phyCnt1, phyCnt2;
- u32 ofdmPhyErrCnt, cckPhyErrCnt;
+ ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
- ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
-
- phyCnt1 = REG_READ(ah, AR_PHY_ERR_1);
- phyCnt2 = REG_READ(ah, AR_PHY_ERR_2);
-
- if (phyCnt1 < aniState->ofdmPhyErrBase ||
- phyCnt2 < aniState->cckPhyErrBase) {
- if (phyCnt1 < aniState->ofdmPhyErrBase) {
- DPRINTF(ah->ah_sc, ATH_DBG_ANI,
- "phyCnt1 0x%x, resetting "
- "counter value to 0x%x\n",
- phyCnt1, aniState->ofdmPhyErrBase);
- REG_WRITE(ah, AR_PHY_ERR_1,
- aniState->ofdmPhyErrBase);
- REG_WRITE(ah, AR_PHY_ERR_MASK_1,
- AR_PHY_ERR_OFDM_TIMING);
- }
- if (phyCnt2 < aniState->cckPhyErrBase) {
- DPRINTF(ah->ah_sc, ATH_DBG_ANI,
- "phyCnt2 0x%x, resetting "
- "counter value to 0x%x\n",
- phyCnt2, aniState->cckPhyErrBase);
- REG_WRITE(ah, AR_PHY_ERR_2,
- aniState->cckPhyErrBase);
- REG_WRITE(ah, AR_PHY_ERR_MASK_2,
- AR_PHY_ERR_CCK_TIMING);
- }
- return;
+ phyCnt1 = REG_READ(ah, AR_PHY_ERR_1);
+ phyCnt2 = REG_READ(ah, AR_PHY_ERR_2);
+
+ if (phyCnt1 < aniState->ofdmPhyErrBase ||
+ phyCnt2 < aniState->cckPhyErrBase) {
+ if (phyCnt1 < aniState->ofdmPhyErrBase) {
+ DPRINTF(ah->ah_sc, ATH_DBG_ANI,
+ "phyCnt1 0x%x, resetting "
+ "counter value to 0x%x\n",
+ phyCnt1, aniState->ofdmPhyErrBase);
+ REG_WRITE(ah, AR_PHY_ERR_1,
+ aniState->ofdmPhyErrBase);
+ REG_WRITE(ah, AR_PHY_ERR_MASK_1,
+ AR_PHY_ERR_OFDM_TIMING);
+ }
+ if (phyCnt2 < aniState->cckPhyErrBase) {
+ DPRINTF(ah->ah_sc, ATH_DBG_ANI,
+ "phyCnt2 0x%x, resetting "
+ "counter value to 0x%x\n",
+ phyCnt2, aniState->cckPhyErrBase);
+ REG_WRITE(ah, AR_PHY_ERR_2,
+ aniState->cckPhyErrBase);
+ REG_WRITE(ah, AR_PHY_ERR_MASK_2,
+ AR_PHY_ERR_CCK_TIMING);
}
+ return;
+ }
- ofdmPhyErrCnt = phyCnt1 - aniState->ofdmPhyErrBase;
- ah->stats.ast_ani_ofdmerrs +=
- ofdmPhyErrCnt - aniState->ofdmPhyErrCount;
- aniState->ofdmPhyErrCount = ofdmPhyErrCnt;
+ ofdmPhyErrCnt = phyCnt1 - aniState->ofdmPhyErrBase;
+ ah->stats.ast_ani_ofdmerrs +=
+ ofdmPhyErrCnt - aniState->ofdmPhyErrCount;
+ aniState->ofdmPhyErrCount = ofdmPhyErrCnt;
- cckPhyErrCnt = phyCnt2 - aniState->cckPhyErrBase;
- ah->stats.ast_ani_cckerrs +=
- cckPhyErrCnt - aniState->cckPhyErrCount;
- aniState->cckPhyErrCount = cckPhyErrCnt;
- }
+ cckPhyErrCnt = phyCnt2 - aniState->cckPhyErrBase;
+ ah->stats.ast_ani_cckerrs +=
+ cckPhyErrCnt - aniState->cckPhyErrCount;
+ aniState->cckPhyErrCount = cckPhyErrCnt;
if (aniState->listenTime > 5 * ah->aniperiod) {
if (aniState->ofdmPhyErrCount <= aniState->listenTime *
@@ -632,11 +622,6 @@ void ath9k_hw_ani_monitor(struct ath_hw *ah,
}
}
-bool ath9k_hw_phycounters(struct ath_hw *ah)
-{
- return ah->has_hw_phycounters ? true : false;
-}
-
void ath9k_enable_mib_counters(struct ath_hw *ah)
{
DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Enable MIB counters\n");
@@ -777,13 +762,11 @@ void ath9k_hw_ani_setup(struct ath_hw *ah)
}
}
-void ath9k_hw_ani_attach(struct ath_hw *ah)
+void ath9k_hw_ani_init(struct ath_hw *ah)
{
int i;
- DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Attach ANI\n");
-
- ah->has_hw_phycounters = 1;
+ DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Initialize ANI\n");
memset(ah->ani, 0, sizeof(ah->ani));
for (i = 0; i < ARRAY_SIZE(ah->ani); i++) {
@@ -799,36 +782,32 @@ void ath9k_hw_ani_attach(struct ath_hw *ah)
ATH9K_ANI_CCK_WEAK_SIG_THR;
ah->ani[i].spurImmunityLevel = ATH9K_ANI_SPUR_IMMUNE_LVL;
ah->ani[i].firstepLevel = ATH9K_ANI_FIRSTEP_LVL;
- if (ah->has_hw_phycounters) {
- ah->ani[i].ofdmPhyErrBase =
- AR_PHY_COUNTMAX - ATH9K_ANI_OFDM_TRIG_HIGH;
- ah->ani[i].cckPhyErrBase =
- AR_PHY_COUNTMAX - ATH9K_ANI_CCK_TRIG_HIGH;
- }
- }
- if (ah->has_hw_phycounters) {
- DPRINTF(ah->ah_sc, ATH_DBG_ANI,
- "Setting OfdmErrBase = 0x%08x\n",
- ah->ani[0].ofdmPhyErrBase);
- DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Setting cckErrBase = 0x%08x\n",
- ah->ani[0].cckPhyErrBase);
-
- REG_WRITE(ah, AR_PHY_ERR_1, ah->ani[0].ofdmPhyErrBase);
- REG_WRITE(ah, AR_PHY_ERR_2, ah->ani[0].cckPhyErrBase);
- ath9k_enable_mib_counters(ah);
+ ah->ani[i].ofdmPhyErrBase =
+ AR_PHY_COUNTMAX - ATH9K_ANI_OFDM_TRIG_HIGH;
+ ah->ani[i].cckPhyErrBase =
+ AR_PHY_COUNTMAX - ATH9K_ANI_CCK_TRIG_HIGH;
}
+
+ DPRINTF(ah->ah_sc, ATH_DBG_ANI,
+ "Setting OfdmErrBase = 0x%08x\n",
+ ah->ani[0].ofdmPhyErrBase);
+ DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Setting cckErrBase = 0x%08x\n",
+ ah->ani[0].cckPhyErrBase);
+
+ REG_WRITE(ah, AR_PHY_ERR_1, ah->ani[0].ofdmPhyErrBase);
+ REG_WRITE(ah, AR_PHY_ERR_2, ah->ani[0].cckPhyErrBase);
+ ath9k_enable_mib_counters(ah);
+
ah->aniperiod = ATH9K_ANI_PERIOD;
if (ah->config.enable_ani)
ah->proc_phyerr |= HAL_PROCESS_ANI;
}
-void ath9k_hw_ani_detach(struct ath_hw *ah)
+void ath9k_hw_ani_disable(struct ath_hw *ah)
{
- DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Detach ANI\n");
+ DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Disabling ANI\n");
- if (ah->has_hw_phycounters) {
- ath9k_hw_disable_mib_counters(ah);
- REG_WRITE(ah, AR_PHY_ERR_1, 0);
- REG_WRITE(ah, AR_PHY_ERR_2, 0);
- }
+ ath9k_hw_disable_mib_counters(ah);
+ REG_WRITE(ah, AR_PHY_ERR_1, 0);
+ REG_WRITE(ah, AR_PHY_ERR_2, 0);
}
diff --git a/drivers/net/wireless/ath/ath9k/ani.h b/drivers/net/wireless/ath/ath9k/ani.h
index 08b4e7ed5ff..119924511f8 100644
--- a/drivers/net/wireless/ath/ath9k/ani.h
+++ b/drivers/net/wireless/ath/ath9k/ani.h
@@ -124,7 +124,6 @@ void ath9k_ani_reset(struct ath_hw *ah);
void ath9k_hw_ani_monitor(struct ath_hw *ah,
const struct ath9k_node_stats *stats,
struct ath9k_channel *chan);
-bool ath9k_hw_phycounters(struct ath_hw *ah);
void ath9k_enable_mib_counters(struct ath_hw *ah);
void ath9k_hw_disable_mib_counters(struct ath_hw *ah);
u32 ath9k_hw_GetMibCycleCountsPct(struct ath_hw *ah, u32 *rxc_pcnt,
@@ -132,7 +131,7 @@ u32 ath9k_hw_GetMibCycleCountsPct(struct ath_hw *ah, u32 *rxc_pcnt,
void ath9k_hw_procmibevent(struct ath_hw *ah,
const struct ath9k_node_stats *stats);
void ath9k_hw_ani_setup(struct ath_hw *ah);
-void ath9k_hw_ani_attach(struct ath_hw *ah);
-void ath9k_hw_ani_detach(struct ath_hw *ah);
+void ath9k_hw_ani_init(struct ath_hw *ah);
+void ath9k_hw_ani_disable(struct ath_hw *ah);
#endif /* ANI_H */
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index 5efc9345ca0..2fd663c01b8 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -25,6 +25,7 @@
#include "hw.h"
#include "rc.h"
#include "debug.h"
+#include "../ath.h"
struct ath_node;
@@ -164,7 +165,6 @@ void ath_descdma_cleanup(struct ath_softc *sc, struct ath_descdma *dd,
#define WME_NUM_TID 16
#define ATH_TXBUF 512
#define ATH_TXMAXTRY 13
-#define ATH_11N_TXMAXTRY 10
#define ATH_MGT_TXMAXTRY 4
#define WME_BA_BMP_SIZE 64
#define WME_MAX_BA WME_BA_BMP_SIZE
@@ -191,12 +191,9 @@ void ath_descdma_cleanup(struct ath_softc *sc, struct ath_descdma *dd,
#define ATH_AGGR_MIN_QDEPTH 2
#define ATH_AMPDU_SUBFRAME_DEFAULT 32
#define ATH_AMPDU_LIMIT_MAX (64 * 1024 - 1)
-#define ATH_AMPDU_LIMIT_DEFAULT ATH_AMPDU_LIMIT_MAX
#define IEEE80211_SEQ_SEQ_SHIFT 4
#define IEEE80211_SEQ_MAX 4096
-#define IEEE80211_MIN_AMPDU_BUF 0x8
-#define IEEE80211_HTCAP_MAXRXAMPDU_FACTOR 13
#define IEEE80211_WEP_IVLEN 3
#define IEEE80211_WEP_KIDLEN 1
#define IEEE80211_WEP_CRCLEN 4
@@ -226,6 +223,8 @@ void ath_descdma_cleanup(struct ath_softc *sc, struct ath_descdma *dd,
#define ATH_DS_TX_BA(_ds) ((_ds)->ds_us.tx.ts_flags & ATH9K_TX_BA)
#define ATH_AN_2_TID(_an, _tidno) (&(_an)->tid[(_tidno)])
+#define ATH_TX_COMPLETE_POLL_INT 1000
+
enum ATH_AGGR_STATUS {
ATH_AGGR_DONE,
ATH_AGGR_BAW_CLOSED,
@@ -239,8 +238,8 @@ struct ath_txq {
spinlock_t axq_lock;
u32 axq_depth;
u8 axq_aggr_depth;
- u32 axq_totalqueued;
bool stopped;
+ bool axq_tx_inprogress;
struct ath_buf *axq_linkbuf;
/* first desc of the last descriptor that contains CTS */
@@ -272,7 +271,6 @@ struct ath_atx_tid {
int sched;
int paused;
u8 state;
- int addba_exchangeattempts;
};
struct ath_atx_ac {
@@ -292,12 +290,28 @@ struct ath_tx_control {
#define ATH_TX_XRETRY 0x02
#define ATH_TX_BAR 0x04
+#define ATH_RSSI_LPF_LEN 10
+#define RSSI_LPF_THRESHOLD -20
+#define ATH9K_RSSI_BAD 0x80
+#define ATH_RSSI_EP_MULTIPLIER (1<<7)
+#define ATH_EP_MUL(x, mul) ((x) * (mul))
+#define ATH_RSSI_IN(x) (ATH_EP_MUL((x), ATH_RSSI_EP_MULTIPLIER))
+#define ATH_LPF_RSSI(x, y, len) \
+ ((x != ATH_RSSI_DUMMY_MARKER) ? (((x) * ((len) - 1) + (y)) / (len)) : (y))
+#define ATH_RSSI_LPF(x, y) do { \
+ if ((y) >= RSSI_LPF_THRESHOLD) \
+ x = ATH_LPF_RSSI((x), ATH_RSSI_IN((y)), ATH_RSSI_LPF_LEN); \
+} while (0)
+#define ATH_EP_RND(x, mul) \
+ ((((x)%(mul)) >= ((mul)/2)) ? ((x) + ((mul) - 1)) / (mul) : (x)/(mul))
+
struct ath_node {
struct ath_softc *an_sc;
struct ath_atx_tid tid[WME_NUM_TID];
struct ath_atx_ac ac[WME_NUM_AC];
u16 maxampdu;
u8 mpdudensity;
+ int last_rssi;
};
struct ath_tx {
@@ -348,9 +362,9 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
void ath_tx_tasklet(struct ath_softc *sc);
void ath_tx_cabq(struct ieee80211_hw *hw, struct sk_buff *skb);
bool ath_tx_aggr_check(struct ath_softc *sc, struct ath_node *an, u8 tidno);
-int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
- u16 tid, u16 *ssn);
-int ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid);
+void ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
+ u16 tid, u16 *ssn);
+void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid);
void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid);
/********/
@@ -519,6 +533,8 @@ struct ath_softc {
struct ieee80211_hw *hw;
struct device *dev;
+ struct ath_common common;
+
spinlock_t wiphy_lock; /* spinlock to protect ath_wiphy data */
struct ath_wiphy *pri_wiphy;
struct ath_wiphy **sec_wiphy; /* secondary wiphys (virtual radios); may
@@ -541,6 +557,8 @@ struct ath_softc {
int irq;
spinlock_t sc_resetlock;
spinlock_t sc_serial_rw;
+ spinlock_t ani_lock;
+ spinlock_t sc_pm_lock;
struct mutex mutex;
u8 curbssid[ETH_ALEN];
@@ -549,7 +567,6 @@ struct ath_softc {
u32 sc_flags; /* SC_OP_* */
u16 curtxpow;
u16 curaid;
- u16 cachelsz;
u8 nbcnvifs;
u16 nvifs;
u8 tx_chainmask;
@@ -557,7 +574,8 @@ struct ath_softc {
u32 keymax;
DECLARE_BITMAP(keymap, ATH_KEYMAX);
u8 splitmic;
- atomic_t ps_usecount;
+ bool ps_enabled;
+ unsigned long ps_usecount;
enum ath9k_int imask;
enum ath9k_ht_extprotspacing ht_extprotspacing;
enum ath9k_ht_macmode tx_chan_width;
@@ -590,6 +608,7 @@ struct ath_softc {
#endif
struct ath_bus_ops *bus_ops;
struct ath_beacon_config cur_beacon_conf;
+ struct delayed_work tx_complete_work;
};
struct ath_wiphy {
@@ -625,7 +644,7 @@ extern struct ieee80211_ops ath9k_ops;
irqreturn_t ath_isr(int irq, void *dev);
void ath_cleanup(struct ath_softc *sc);
-int ath_attach(u16 devid, struct ath_softc *sc);
+int ath_init_device(u16 devid, struct ath_softc *sc);
void ath_detach(struct ath_softc *sc);
const char *ath_mac_bb_name(u32 mac_bb_version);
const char *ath_rf_name(u16 rf_version);
@@ -654,27 +673,8 @@ static inline int ath_ahb_init(void) { return 0; };
static inline void ath_ahb_exit(void) {};
#endif
-static inline void ath9k_ps_wakeup(struct ath_softc *sc)
-{
- if (atomic_inc_return(&sc->ps_usecount) == 1)
- if (sc->sc_ah->power_mode != ATH9K_PM_AWAKE) {
- sc->sc_ah->restore_mode = sc->sc_ah->power_mode;
- ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_AWAKE);
- }
-}
-
-static inline void ath9k_ps_restore(struct ath_softc *sc)
-{
- if (atomic_dec_and_test(&sc->ps_usecount))
- if ((sc->hw->conf.flags & IEEE80211_CONF_PS) &&
- !(sc->sc_flags & (SC_OP_WAIT_FOR_BEACON |
- SC_OP_WAIT_FOR_CAB |
- SC_OP_WAIT_FOR_PSPOLL_DATA |
- SC_OP_WAIT_FOR_TX_ACK)))
- ath9k_hw_setpower(sc->sc_ah,
- sc->sc_ah->restore_mode);
-}
-
+void ath9k_ps_wakeup(struct ath_softc *sc);
+void ath9k_ps_restore(struct ath_softc *sc);
void ath9k_set_bssid_mask(struct ieee80211_hw *hw);
int ath9k_wiphy_add(struct ath_softc *sc);
@@ -690,6 +690,7 @@ void ath9k_wiphy_pause_all_forced(struct ath_softc *sc,
struct ath_wiphy *selected);
bool ath9k_wiphy_scanning(struct ath_softc *sc);
void ath9k_wiphy_work(struct work_struct *work);
+bool ath9k_all_wiphys_idle(struct ath_softc *sc);
void ath9k_iowrite32(struct ath_hw *ah, u32 reg_offset, u32 val);
unsigned int ath9k_ioread32(struct ath_hw *ah, u32 reg_offset);
diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c
index 3639a2e6987..45c4ea57616 100644
--- a/drivers/net/wireless/ath/ath9k/beacon.c
+++ b/drivers/net/wireless/ath/ath9k/beacon.c
@@ -674,13 +674,6 @@ static void ath_beacon_config_adhoc(struct ath_softc *sc,
intval = conf->beacon_interval & ATH9K_BEACON_PERIOD;
- /*
- * It looks like mac80211 may end up using beacon interval of zero in
- * some cases (at least for mesh point). Avoid getting into an
- * infinite loop by using a bit safer value instead..
- */
- if (intval == 0)
- intval = 100;
/* Pull nexttbtt forward to reflect the current TSF */
@@ -745,6 +738,14 @@ void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif)
iftype = sc->sc_ah->opmode;
}
+ /*
+ * It looks like mac80211 may end up using beacon interval of zero in
+ * some cases (at least for mesh point). Avoid getting into an
+ * infinite loop by using a bit safer value instead. To be safe,
+ * do sanity check on beacon interval for all operating modes.
+ */
+ if (cur_conf->beacon_interval == 0)
+ cur_conf->beacon_interval = 100;
switch (iftype) {
case NL80211_IFTYPE_AP:
diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c
index a32d7e7fecb..26d87527acb 100644
--- a/drivers/net/wireless/ath/ath9k/calib.c
+++ b/drivers/net/wireless/ath/ath9k/calib.c
@@ -116,7 +116,7 @@ static void ath9k_hw_do_getnf(struct ath_hw *ah,
"NF calibrated [ctl] [chain 1] is %d\n", nf);
nfarray[1] = nf;
- if (!AR_SREV_9280(ah)) {
+ if (!AR_SREV_9280(ah) && !AR_SREV_9287(ah)) {
nf = MS(REG_READ(ah, AR_PHY_CH2_CCA),
AR_PHY_CH2_MINCCA_PWR);
if (nf & 0x100)
@@ -154,7 +154,7 @@ static void ath9k_hw_do_getnf(struct ath_hw *ah,
"NF calibrated [ext] [chain 1] is %d\n", nf);
nfarray[4] = nf;
- if (!AR_SREV_9280(ah)) {
+ if (!AR_SREV_9280(ah) && !AR_SREV_9287(ah)) {
nf = MS(REG_READ(ah, AR_PHY_CH2_EXT_CCA),
AR_PHY_CH2_EXT_MINCCA_PWR);
if (nf & 0x100)
@@ -613,7 +613,7 @@ void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan)
if (AR_SREV_9285(ah))
chainmask = 0x9;
- else if (AR_SREV_9280(ah))
+ else if (AR_SREV_9280(ah) || AR_SREV_9287(ah))
chainmask = 0x1B;
else
chainmask = 0x3F;
@@ -691,15 +691,22 @@ int16_t ath9k_hw_getnf(struct ath_hw *ah,
void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah)
{
int i, j;
+ s16 noise_floor;
+
+ if (AR_SREV_9280(ah))
+ noise_floor = AR_PHY_CCA_MAX_AR9280_GOOD_VALUE;
+ else if (AR_SREV_9285(ah))
+ noise_floor = AR_PHY_CCA_MAX_AR9285_GOOD_VALUE;
+ else
+ noise_floor = AR_PHY_CCA_MAX_AR5416_GOOD_VALUE;
for (i = 0; i < NUM_NF_READINGS; i++) {
ah->nfCalHist[i].currIndex = 0;
- ah->nfCalHist[i].privNF = AR_PHY_CCA_MAX_GOOD_VALUE;
+ ah->nfCalHist[i].privNF = noise_floor;
ah->nfCalHist[i].invalidNFcount =
AR_PHY_CCA_FILTERWINDOW_LENGTH;
for (j = 0; j < ATH9K_NF_CAL_HIST_MAX; j++) {
- ah->nfCalHist[i].nfCalBuffer[j] =
- AR_PHY_CCA_MAX_GOOD_VALUE;
+ ah->nfCalHist[i].nfCalBuffer[j] = noise_floor;
}
}
}
@@ -746,6 +753,98 @@ static void ath9k_olc_temp_compensation(struct ath_hw *ah)
}
}
+static void ath9k_hw_9271_pa_cal(struct ath_hw *ah)
+{
+ u32 regVal;
+ unsigned int i;
+ u32 regList [][2] = {
+ { 0x786c, 0 },
+ { 0x7854, 0 },
+ { 0x7820, 0 },
+ { 0x7824, 0 },
+ { 0x7868, 0 },
+ { 0x783c, 0 },
+ { 0x7838, 0 } ,
+ { 0x7828, 0 } ,
+ };
+
+ for (i = 0; i < ARRAY_SIZE(regList); i++)
+ regList[i][1] = REG_READ(ah, regList[i][0]);
+
+ regVal = REG_READ(ah, 0x7834);
+ regVal &= (~(0x1));
+ REG_WRITE(ah, 0x7834, regVal);
+ regVal = REG_READ(ah, 0x9808);
+ regVal |= (0x1 << 27);
+ REG_WRITE(ah, 0x9808, regVal);
+
+ /* 786c,b23,1, pwddac=1 */
+ REG_RMW_FIELD(ah, AR9285_AN_TOP3, AR9285_AN_TOP3_PWDDAC, 1);
+ /* 7854, b5,1, pdrxtxbb=1 */
+ REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDRXTXBB1, 1);
+ /* 7854, b7,1, pdv2i=1 */
+ REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDV2I, 1);
+ /* 7854, b8,1, pddacinterface=1 */
+ REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDDACIF, 1);
+ /* 7824,b12,0, offcal=0 */
+ REG_RMW_FIELD(ah, AR9285_AN_RF2G2, AR9285_AN_RF2G2_OFFCAL, 0);
+ /* 7838, b1,0, pwddb=0 */
+ REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PWDDB, 0);
+ /* 7820,b11,0, enpacal=0 */
+ REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_ENPACAL, 0);
+ /* 7820,b25,1, pdpadrv1=0 */
+ REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV1, 0);
+ /* 7820,b24,0, pdpadrv2=0 */
+ REG_RMW_FIELD(ah, AR9285_AN_RF2G1,AR9285_AN_RF2G1_PDPADRV2,0);
+ /* 7820,b23,0, pdpaout=0 */
+ REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPAOUT, 0);
+ /* 783c,b14-16,7, padrvgn2tab_0=7 */
+ REG_RMW_FIELD(ah, AR9285_AN_RF2G8,AR9285_AN_RF2G8_PADRVGN2TAB0, 7);
+ /*
+ * 7838,b29-31,0, padrvgn1tab_0=0
+ * does not matter since we turn it off
+ */
+ REG_RMW_FIELD(ah, AR9285_AN_RF2G7,AR9285_AN_RF2G7_PADRVGN2TAB0, 0);
+
+ REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9271_AN_RF2G3_CCOMP, 0xfff);
+
+ /* Set:
+ * localmode=1,bmode=1,bmoderxtx=1,synthon=1,
+ * txon=1,paon=1,oscon=1,synthon_force=1
+ */
+ REG_WRITE(ah, AR9285_AN_TOP2, 0xca0358a0);
+ udelay(30);
+ REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9271_AN_RF2G6_OFFS, 0);
+
+ /* find off_6_1; */
+ for (i = 6; i >= 0; i--) {
+ regVal = REG_READ(ah, 0x7834);
+ regVal |= (1 << (20 + i));
+ REG_WRITE(ah, 0x7834, regVal);
+ udelay(1);
+ //regVal = REG_READ(ah, 0x7834);
+ regVal &= (~(0x1 << (20 + i)));
+ regVal |= (MS(REG_READ(ah, 0x7840), AR9285_AN_RXTXBB1_SPARE9)
+ << (20 + i));
+ REG_WRITE(ah, 0x7834, regVal);
+ }
+
+ /* Empirical offset correction */
+#if 0
+ REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9271_AN_RF2G6_OFFS, 0x20);
+#endif
+
+ regVal = REG_READ(ah, 0x7834);
+ regVal |= 0x1;
+ REG_WRITE(ah, 0x7834, regVal);
+ regVal = REG_READ(ah, 0x9808);
+ regVal &= (~(0x1 << 27));
+ REG_WRITE(ah, 0x9808, regVal);
+
+ for (i = 0; i < ARRAY_SIZE(regList); i++)
+ REG_WRITE(ah, regList[i][0], regList[i][1]);
+}
+
static inline void ath9k_hw_9285_pa_cal(struct ath_hw *ah)
{
@@ -862,14 +961,26 @@ bool ath9k_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan,
}
}
+ /* Do NF cal only at longer intervals */
if (longcal) {
- if (AR_SREV_9285_11_OR_LATER(ah))
+ /* Do periodic PAOffset Cal */
+ if (AR_SREV_9271(ah))
+ ath9k_hw_9271_pa_cal(ah);
+ else if (AR_SREV_9285_11_OR_LATER(ah))
ath9k_hw_9285_pa_cal(ah);
- if (OLC_FOR_AR9280_20_LATER)
+ if (OLC_FOR_AR9280_20_LATER || OLC_FOR_AR9287_10_LATER)
ath9k_olc_temp_compensation(ah);
+
+ /* Get the value from the previous NF cal and update history buffer */
ath9k_hw_getnf(ah, chan);
+
+ /*
+ * Load the NF from history buffer of the current channel.
+ * NF is slow time-variant, so it is OK to use a historical value.
+ */
ath9k_hw_loadnf(ah, ah->curchan);
+
ath9k_hw_start_nfcal(ah);
}
@@ -922,8 +1033,11 @@ bool ath9k_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan)
return false;
} else {
if (AR_SREV_9280_10_OR_LATER(ah)) {
- REG_CLR_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC);
- REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL);
+ if (!AR_SREV_9287_10_OR_LATER(ah))
+ REG_CLR_BIT(ah, AR_PHY_ADC_CTL,
+ AR_PHY_ADC_CTL_OFF_PWDADC);
+ REG_SET_BIT(ah, AR_PHY_AGC_CONTROL,
+ AR_PHY_AGC_CONTROL_FLTR_CAL);
}
/* Calibrate the AGC */
@@ -941,8 +1055,11 @@ bool ath9k_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan)
}
if (AR_SREV_9280_10_OR_LATER(ah)) {
- REG_SET_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC);
- REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL);
+ if (!AR_SREV_9287_10_OR_LATER(ah))
+ REG_SET_BIT(ah, AR_PHY_ADC_CTL,
+ AR_PHY_ADC_CTL_OFF_PWDADC);
+ REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
+ AR_PHY_AGC_CONTROL_FLTR_CAL);
}
}
diff --git a/drivers/net/wireless/ath/ath9k/calib.h b/drivers/net/wireless/ath/ath9k/calib.h
index fe5367f1414..547e697b905 100644
--- a/drivers/net/wireless/ath/ath9k/calib.h
+++ b/drivers/net/wireless/ath/ath9k/calib.h
@@ -25,7 +25,9 @@ extern const struct ath9k_percal_data adc_dc_cal_multi_sample;
extern const struct ath9k_percal_data adc_dc_cal_single_sample;
extern const struct ath9k_percal_data adc_init_dc_cal;
-#define AR_PHY_CCA_MAX_GOOD_VALUE -85
+#define AR_PHY_CCA_MAX_AR5416_GOOD_VALUE -85
+#define AR_PHY_CCA_MAX_AR9280_GOOD_VALUE -112
+#define AR_PHY_CCA_MAX_AR9285_GOOD_VALUE -118
#define AR_PHY_CCA_MAX_HIGH_VALUE -62
#define AR_PHY_CCA_MIN_BAD_VALUE -140
#define AR_PHY_CCA_FILTERWINDOW_LENGTH_INIT 3
diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c
index 6d20725d645..9e369208f7d 100644
--- a/drivers/net/wireless/ath/ath9k/debug.c
+++ b/drivers/net/wireless/ath/ath9k/debug.c
@@ -486,6 +486,83 @@ static const struct file_operations fops_wiphy = {
.owner = THIS_MODULE
};
+#define PR(str, elem) \
+ do { \
+ len += snprintf(buf + len, size - len, \
+ "%s%13u%11u%10u%10u\n", str, \
+ sc->debug.stats.txstats[sc->tx.hwq_map[ATH9K_WME_AC_BE]].elem, \
+ sc->debug.stats.txstats[sc->tx.hwq_map[ATH9K_WME_AC_BK]].elem, \
+ sc->debug.stats.txstats[sc->tx.hwq_map[ATH9K_WME_AC_VI]].elem, \
+ sc->debug.stats.txstats[sc->tx.hwq_map[ATH9K_WME_AC_VO]].elem); \
+} while(0)
+
+static ssize_t read_file_xmit(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct ath_softc *sc = file->private_data;
+ char *buf;
+ unsigned int len = 0, size = 2048;
+ ssize_t retval = 0;
+
+ buf = kzalloc(size, GFP_KERNEL);
+ if (buf == NULL)
+ return 0;
+
+ len += sprintf(buf, "%30s %10s%10s%10s\n\n", "BE", "BK", "VI", "VO");
+
+ PR("MPDUs Queued: ", queued);
+ PR("MPDUs Completed: ", completed);
+ PR("Aggregates: ", a_aggr);
+ PR("AMPDUs Queued: ", a_queued);
+ PR("AMPDUs Completed:", a_completed);
+ PR("AMPDUs Retried: ", a_retries);
+ PR("AMPDUs XRetried: ", a_xretries);
+ PR("FIFO Underrun: ", fifo_underrun);
+ PR("TXOP Exceeded: ", xtxop);
+ PR("TXTIMER Expiry: ", timer_exp);
+ PR("DESC CFG Error: ", desc_cfg_err);
+ PR("DATA Underrun: ", data_underrun);
+ PR("DELIM Underrun: ", delim_underrun);
+
+ retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
+ kfree(buf);
+
+ return retval;
+}
+
+void ath_debug_stat_tx(struct ath_softc *sc, struct ath_txq *txq,
+ struct ath_buf *bf)
+{
+ struct ath_desc *ds = bf->bf_desc;
+
+ if (bf_isampdu(bf)) {
+ if (bf_isxretried(bf))
+ TX_STAT_INC(txq->axq_qnum, a_xretries);
+ else
+ TX_STAT_INC(txq->axq_qnum, a_completed);
+ } else {
+ TX_STAT_INC(txq->axq_qnum, completed);
+ }
+
+ if (ds->ds_txstat.ts_status & ATH9K_TXERR_FIFO)
+ TX_STAT_INC(txq->axq_qnum, fifo_underrun);
+ if (ds->ds_txstat.ts_status & ATH9K_TXERR_XTXOP)
+ TX_STAT_INC(txq->axq_qnum, xtxop);
+ if (ds->ds_txstat.ts_status & ATH9K_TXERR_TIMER_EXPIRED)
+ TX_STAT_INC(txq->axq_qnum, timer_exp);
+ if (ds->ds_txstat.ts_flags & ATH9K_TX_DESC_CFG_ERR)
+ TX_STAT_INC(txq->axq_qnum, desc_cfg_err);
+ if (ds->ds_txstat.ts_flags & ATH9K_TX_DATA_UNDERRUN)
+ TX_STAT_INC(txq->axq_qnum, data_underrun);
+ if (ds->ds_txstat.ts_flags & ATH9K_TX_DELIM_UNDERRUN)
+ TX_STAT_INC(txq->axq_qnum, delim_underrun);
+}
+
+static const struct file_operations fops_xmit = {
+ .read = read_file_xmit,
+ .open = ath9k_debugfs_open,
+ .owner = THIS_MODULE
+};
int ath9k_init_debug(struct ath_softc *sc)
{
@@ -500,35 +577,42 @@ int ath9k_init_debug(struct ath_softc *sc)
goto err;
sc->debug.debugfs_debug = debugfs_create_file("debug",
- S_IRUGO | S_IWUSR, sc->debug.debugfs_phy, sc, &fops_debug);
+ S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, sc, &fops_debug);
if (!sc->debug.debugfs_debug)
goto err;
- sc->debug.debugfs_dma = debugfs_create_file("dma", S_IRUGO,
+ sc->debug.debugfs_dma = debugfs_create_file("dma", S_IRUSR,
sc->debug.debugfs_phy, sc, &fops_dma);
if (!sc->debug.debugfs_dma)
goto err;
sc->debug.debugfs_interrupt = debugfs_create_file("interrupt",
- S_IRUGO,
+ S_IRUSR,
sc->debug.debugfs_phy,
sc, &fops_interrupt);
if (!sc->debug.debugfs_interrupt)
goto err;
sc->debug.debugfs_rcstat = debugfs_create_file("rcstat",
- S_IRUGO,
+ S_IRUSR,
sc->debug.debugfs_phy,
sc, &fops_rcstat);
if (!sc->debug.debugfs_rcstat)
goto err;
sc->debug.debugfs_wiphy = debugfs_create_file(
- "wiphy", S_IRUGO | S_IWUSR, sc->debug.debugfs_phy, sc,
+ "wiphy", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, sc,
&fops_wiphy);
if (!sc->debug.debugfs_wiphy)
goto err;
+ sc->debug.debugfs_xmit = debugfs_create_file("xmit",
+ S_IRUSR,
+ sc->debug.debugfs_phy,
+ sc, &fops_xmit);
+ if (!sc->debug.debugfs_xmit)
+ goto err;
+
return 0;
err:
ath9k_exit_debug(sc);
@@ -537,6 +621,7 @@ err:
void ath9k_exit_debug(struct ath_softc *sc)
{
+ debugfs_remove(sc->debug.debugfs_xmit);
debugfs_remove(sc->debug.debugfs_wiphy);
debugfs_remove(sc->debug.debugfs_rcstat);
debugfs_remove(sc->debug.debugfs_interrupt);
diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h
index edda15bf2c1..5e56b79d0cb 100644
--- a/drivers/net/wireless/ath/ath9k/debug.h
+++ b/drivers/net/wireless/ath/ath9k/debug.h
@@ -35,6 +35,15 @@ enum ATH_DEBUG {
#define DBG_DEFAULT (ATH_DBG_FATAL)
+struct ath_txq;
+struct ath_buf;
+
+#ifdef CONFIG_ATH9K_DEBUG
+#define TX_STAT_INC(q, c) sc->debug.stats.txstats[q].c++
+#else
+#define TX_STAT_INC(q, c) do { } while (0)
+#endif
+
#ifdef CONFIG_ATH9K_DEBUG
/**
@@ -87,9 +96,45 @@ struct ath_rc_stats {
u8 per;
};
+/**
+ * struct ath_tx_stats - Statistics about TX
+ * @queued: Total MPDUs (non-aggr) queued
+ * @completed: Total MPDUs (non-aggr) completed
+ * @a_aggr: Total no. of aggregates queued
+ * @a_queued: Total AMPDUs queued
+ * @a_completed: Total AMPDUs completed
+ * @a_retries: No. of AMPDUs retried (SW)
+ * @a_xretries: No. of AMPDUs dropped due to xretries
+ * @fifo_underrun: FIFO underrun occurrences
+ Valid only for:
+ - non-aggregate condition.
+ - first packet of aggregate.
+ * @xtxop: No. of frames filtered because of TXOP limit
+ * @timer_exp: Transmit timer expiry
+ * @desc_cfg_err: Descriptor configuration errors
+ * @data_urn: TX data underrun errors
+ * @delim_urn: TX delimiter underrun errors
+ */
+struct ath_tx_stats {
+ u32 queued;
+ u32 completed;
+ u32 a_aggr;
+ u32 a_queued;
+ u32 a_completed;
+ u32 a_retries;
+ u32 a_xretries;
+ u32 fifo_underrun;
+ u32 xtxop;
+ u32 timer_exp;
+ u32 desc_cfg_err;
+ u32 data_underrun;
+ u32 delim_underrun;
+};
+
struct ath_stats {
struct ath_interrupt_stats istats;
struct ath_rc_stats rcstats[RATE_TABLE_SIZE];
+ struct ath_tx_stats txstats[ATH9K_NUM_TX_QUEUES];
};
struct ath9k_debug {
@@ -100,6 +145,7 @@ struct ath9k_debug {
struct dentry *debugfs_interrupt;
struct dentry *debugfs_rcstat;
struct dentry *debugfs_wiphy;
+ struct dentry *debugfs_xmit;
struct ath_stats stats;
};
@@ -110,6 +156,8 @@ int ath9k_debug_create_root(void);
void ath9k_debug_remove_root(void);
void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status);
void ath_debug_stat_rc(struct ath_softc *sc, struct sk_buff *skb);
+void ath_debug_stat_tx(struct ath_softc *sc, struct ath_txq *txq,
+ struct ath_buf *bf);
void ath_debug_stat_retries(struct ath_softc *sc, int rix,
int xretries, int retries, u8 per);
@@ -148,6 +196,12 @@ static inline void ath_debug_stat_rc(struct ath_softc *sc,
{
}
+static inline void ath_debug_stat_tx(struct ath_softc *sc,
+ struct ath_txq *txq,
+ struct ath_buf *bf)
+{
+}
+
static inline void ath_debug_stat_retries(struct ath_softc *sc, int rix,
int xretries, int retries, u8 per)
{
diff --git a/drivers/net/wireless/ath/ath9k/eeprom.c b/drivers/net/wireless/ath/ath9k/eeprom.c
index ce0e86c36a8..958948bc73f 100644
--- a/drivers/net/wireless/ath/ath9k/eeprom.c
+++ b/drivers/net/wireless/ath/ath9k/eeprom.c
@@ -16,9 +16,16 @@
#include "ath9k.h"
-static void ath9k_hw_analog_shift_rmw(struct ath_hw *ah,
- u32 reg, u32 mask,
- u32 shift, u32 val)
+static inline u16 ath9k_hw_fbin2freq(u8 fbin, bool is2GHz)
+{
+ if (fbin == AR5416_BCHAN_UNUSED)
+ return fbin;
+
+ return (u16) ((is2GHz) ? (2300 + fbin) : (4800 + 5 * fbin));
+}
+
+void ath9k_hw_analog_shift_rmw(struct ath_hw *ah, u32 reg, u32 mask,
+ u32 shift, u32 val)
{
u32 regVal;
@@ -33,19 +40,8 @@ static void ath9k_hw_analog_shift_rmw(struct ath_hw *ah,
return;
}
-static inline u16 ath9k_hw_fbin2freq(u8 fbin, bool is2GHz)
-{
-
- if (fbin == AR5416_BCHAN_UNUSED)
- return fbin;
-
- return (u16) ((is2GHz) ? (2300 + fbin) : (4800 + 5 * fbin));
-}
-
-static inline int16_t ath9k_hw_interpolate(u16 target,
- u16 srcLeft, u16 srcRight,
- int16_t targetLeft,
- int16_t targetRight)
+int16_t ath9k_hw_interpolate(u16 target, u16 srcLeft, u16 srcRight,
+ int16_t targetLeft, int16_t targetRight)
{
int16_t rv;
@@ -59,9 +55,8 @@ static inline int16_t ath9k_hw_interpolate(u16 target,
return rv;
}
-static inline bool ath9k_hw_get_lower_upper_index(u8 target, u8 *pList,
- u16 listSize, u16 *indexL,
- u16 *indexR)
+bool ath9k_hw_get_lower_upper_index(u8 target, u8 *pList, u16 listSize,
+ u16 *indexL, u16 *indexR)
{
u16 i;
@@ -88,16 +83,16 @@ static inline bool ath9k_hw_get_lower_upper_index(u8 target, u8 *pList,
return false;
}
-static inline bool ath9k_hw_nvram_read(struct ath_hw *ah, u32 off, u16 *data)
+bool ath9k_hw_nvram_read(struct ath_hw *ah, u32 off, u16 *data)
{
struct ath_softc *sc = ah->ah_sc;
return sc->bus_ops->eeprom_read(ah, off, data);
}
-static inline bool ath9k_hw_fill_vpd_table(u8 pwrMin, u8 pwrMax, u8 *pPwrList,
- u8 *pVpdList, u16 numIntercepts,
- u8 *pRetVpdList)
+void ath9k_hw_fill_vpd_table(u8 pwrMin, u8 pwrMax, u8 *pPwrList,
+ u8 *pVpdList, u16 numIntercepts,
+ u8 *pRetVpdList)
{
u16 i, k;
u8 currPwr = pwrMin;
@@ -120,16 +115,14 @@ static inline bool ath9k_hw_fill_vpd_table(u8 pwrMin, u8 pwrMax, u8 *pPwrList,
pRetVpdList[i] = (u8) k;
currPwr += 2;
}
-
- return true;
}
-static void ath9k_hw_get_legacy_target_powers(struct ath_hw *ah,
- struct ath9k_channel *chan,
- struct cal_target_power_leg *powInfo,
- u16 numChannels,
- struct cal_target_power_leg *pNewPower,
- u16 numRates, bool isExtTarget)
+void ath9k_hw_get_legacy_target_powers(struct ath_hw *ah,
+ struct ath9k_channel *chan,
+ struct cal_target_power_leg *powInfo,
+ u16 numChannels,
+ struct cal_target_power_leg *pNewPower,
+ u16 numRates, bool isExtTarget)
{
struct chan_centers centers;
u16 clo, chi;
@@ -179,75 +172,12 @@ static void ath9k_hw_get_legacy_target_powers(struct ath_hw *ah,
}
}
-static void ath9k_get_txgain_index(struct ath_hw *ah,
- struct ath9k_channel *chan,
- struct calDataPerFreqOpLoop *rawDatasetOpLoop,
- u8 *calChans, u16 availPiers, u8 *pwr, u8 *pcdacIdx)
-{
- u8 pcdac, i = 0;
- u16 idxL = 0, idxR = 0, numPiers;
- bool match;
- struct chan_centers centers;
-
- ath9k_hw_get_channel_centers(ah, chan, &centers);
-
- for (numPiers = 0; numPiers < availPiers; numPiers++)
- if (calChans[numPiers] == AR5416_BCHAN_UNUSED)
- break;
-
- match = ath9k_hw_get_lower_upper_index(
- (u8)FREQ2FBIN(centers.synth_center, IS_CHAN_2GHZ(chan)),
- calChans, numPiers, &idxL, &idxR);
- if (match) {
- pcdac = rawDatasetOpLoop[idxL].pcdac[0][0];
- *pwr = rawDatasetOpLoop[idxL].pwrPdg[0][0];
- } else {
- pcdac = rawDatasetOpLoop[idxR].pcdac[0][0];
- *pwr = (rawDatasetOpLoop[idxL].pwrPdg[0][0] +
- rawDatasetOpLoop[idxR].pwrPdg[0][0])/2;
- }
-
- while (pcdac > ah->originalGain[i] &&
- i < (AR9280_TX_GAIN_TABLE_SIZE - 1))
- i++;
-
- *pcdacIdx = i;
- return;
-}
-
-static void ath9k_olc_get_pdadcs(struct ath_hw *ah,
- u32 initTxGain,
- int txPower,
- u8 *pPDADCValues)
-{
- u32 i;
- u32 offset;
-
- REG_RMW_FIELD(ah, AR_PHY_TX_PWRCTRL6_0,
- AR_PHY_TX_PWRCTRL_ERR_EST_MODE, 3);
- REG_RMW_FIELD(ah, AR_PHY_TX_PWRCTRL6_1,
- AR_PHY_TX_PWRCTRL_ERR_EST_MODE, 3);
-
- REG_RMW_FIELD(ah, AR_PHY_TX_PWRCTRL7,
- AR_PHY_TX_PWRCTRL_INIT_TX_GAIN, initTxGain);
-
- offset = txPower;
- for (i = 0; i < AR5416_NUM_PDADC_VALUES; i++)
- if (i < offset)
- pPDADCValues[i] = 0x0;
- else
- pPDADCValues[i] = 0xFF;
-}
-
-
-
-
-static void ath9k_hw_get_target_powers(struct ath_hw *ah,
- struct ath9k_channel *chan,
- struct cal_target_power_ht *powInfo,
- u16 numChannels,
- struct cal_target_power_ht *pNewPower,
- u16 numRates, bool isHt40Target)
+void ath9k_hw_get_target_powers(struct ath_hw *ah,
+ struct ath9k_channel *chan,
+ struct cal_target_power_ht *powInfo,
+ u16 numChannels,
+ struct cal_target_power_ht *pNewPower,
+ u16 numRates, bool isHt40Target)
{
struct chan_centers centers;
u16 clo, chi;
@@ -297,9 +227,8 @@ static void ath9k_hw_get_target_powers(struct ath_hw *ah,
}
}
-static u16 ath9k_hw_get_max_edge_power(u16 freq,
- struct cal_ctl_edges *pRdEdgesPower,
- bool is2GHz, int num_band_edges)
+u16 ath9k_hw_get_max_edge_power(u16 freq, struct cal_ctl_edges *pRdEdgesPower,
+ bool is2GHz, int num_band_edges)
{
u16 twiceMaxEdgePower = AR5416_MAX_RATE_POWER;
int i;
@@ -325,2451 +254,14 @@ static u16 ath9k_hw_get_max_edge_power(u16 freq,
return twiceMaxEdgePower;
}
-/****************************************/
-/* EEPROM Operations for 4K sized cards */
-/****************************************/
-
-static int ath9k_hw_4k_get_eeprom_ver(struct ath_hw *ah)
-{
- return ((ah->eeprom.map4k.baseEepHeader.version >> 12) & 0xF);
-}
-
-static int ath9k_hw_4k_get_eeprom_rev(struct ath_hw *ah)
-{
- return ((ah->eeprom.map4k.baseEepHeader.version) & 0xFFF);
-}
-
-static bool ath9k_hw_4k_fill_eeprom(struct ath_hw *ah)
-{
-#define SIZE_EEPROM_4K (sizeof(struct ar5416_eeprom_4k) / sizeof(u16))
- u16 *eep_data = (u16 *)&ah->eeprom.map4k;
- int addr, eep_start_loc = 0;
-
- eep_start_loc = 64;
-
- if (!ath9k_hw_use_flash(ah)) {
- DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
- "Reading from EEPROM, not flash\n");
- }
-
- for (addr = 0; addr < SIZE_EEPROM_4K; addr++) {
- if (!ath9k_hw_nvram_read(ah, addr + eep_start_loc, eep_data)) {
- DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
- "Unable to read eeprom region \n");
- return false;
- }
- eep_data++;
- }
-
- return true;
-#undef SIZE_EEPROM_4K
-}
-
-static int ath9k_hw_4k_check_eeprom(struct ath_hw *ah)
-{
-#define EEPROM_4K_SIZE (sizeof(struct ar5416_eeprom_4k) / sizeof(u16))
- struct ar5416_eeprom_4k *eep =
- (struct ar5416_eeprom_4k *) &ah->eeprom.map4k;
- u16 *eepdata, temp, magic, magic2;
- u32 sum = 0, el;
- bool need_swap = false;
- int i, addr;
-
-
- if (!ath9k_hw_use_flash(ah)) {
- if (!ath9k_hw_nvram_read(ah, AR5416_EEPROM_MAGIC_OFFSET,
- &magic)) {
- DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
- "Reading Magic # failed\n");
- return false;
- }
-
- DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
- "Read Magic = 0x%04X\n", magic);
-
- if (magic != AR5416_EEPROM_MAGIC) {
- magic2 = swab16(magic);
-
- if (magic2 == AR5416_EEPROM_MAGIC) {
- need_swap = true;
- eepdata = (u16 *) (&ah->eeprom);
-
- for (addr = 0; addr < EEPROM_4K_SIZE; addr++) {
- temp = swab16(*eepdata);
- *eepdata = temp;
- eepdata++;
- }
- } else {
- DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
- "Invalid EEPROM Magic. "
- "endianness mismatch.\n");
- return -EINVAL;
- }
- }
- }
-
- DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, "need_swap = %s.\n",
- need_swap ? "True" : "False");
-
- if (need_swap)
- el = swab16(ah->eeprom.map4k.baseEepHeader.length);
- else
- el = ah->eeprom.map4k.baseEepHeader.length;
-
- if (el > sizeof(struct ar5416_eeprom_4k))
- el = sizeof(struct ar5416_eeprom_4k) / sizeof(u16);
- else
- el = el / sizeof(u16);
-
- eepdata = (u16 *)(&ah->eeprom);
-
- for (i = 0; i < el; i++)
- sum ^= *eepdata++;
-
- if (need_swap) {
- u32 integer;
- u16 word;
-
- DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
- "EEPROM Endianness is not native.. Changing\n");
-
- word = swab16(eep->baseEepHeader.length);
- eep->baseEepHeader.length = word;
-
- word = swab16(eep->baseEepHeader.checksum);
- eep->baseEepHeader.checksum = word;
-
- word = swab16(eep->baseEepHeader.version);
- eep->baseEepHeader.version = word;
-
- word = swab16(eep->baseEepHeader.regDmn[0]);
- eep->baseEepHeader.regDmn[0] = word;
-
- word = swab16(eep->baseEepHeader.regDmn[1]);
- eep->baseEepHeader.regDmn[1] = word;
-
- word = swab16(eep->baseEepHeader.rfSilent);
- eep->baseEepHeader.rfSilent = word;
-
- word = swab16(eep->baseEepHeader.blueToothOptions);
- eep->baseEepHeader.blueToothOptions = word;
-
- word = swab16(eep->baseEepHeader.deviceCap);
- eep->baseEepHeader.deviceCap = word;
-
- integer = swab32(eep->modalHeader.antCtrlCommon);
- eep->modalHeader.antCtrlCommon = integer;
-
- for (i = 0; i < AR5416_EEP4K_MAX_CHAINS; i++) {
- integer = swab32(eep->modalHeader.antCtrlChain[i]);
- eep->modalHeader.antCtrlChain[i] = integer;
- }
-
- for (i = 0; i < AR5416_EEPROM_MODAL_SPURS; i++) {
- word = swab16(eep->modalHeader.spurChans[i].spurChan);
- eep->modalHeader.spurChans[i].spurChan = word;
- }
- }
-
- if (sum != 0xffff || ah->eep_ops->get_eeprom_ver(ah) != AR5416_EEP_VER ||
- ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_NO_BACK_VER) {
- DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
- "Bad EEPROM checksum 0x%x or revision 0x%04x\n",
- sum, ah->eep_ops->get_eeprom_ver(ah));
- return -EINVAL;
- }
-
- return 0;
-#undef EEPROM_4K_SIZE
-}
-
-static u32 ath9k_hw_4k_get_eeprom(struct ath_hw *ah,
- enum eeprom_param param)
-{
- struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k;
- struct modal_eep_4k_header *pModal = &eep->modalHeader;
- struct base_eep_header_4k *pBase = &eep->baseEepHeader;
-
- switch (param) {
- case EEP_NFTHRESH_2:
- return pModal->noiseFloorThreshCh[0];
- case AR_EEPROM_MAC(0):
- return pBase->macAddr[0] << 8 | pBase->macAddr[1];
- case AR_EEPROM_MAC(1):
- return pBase->macAddr[2] << 8 | pBase->macAddr[3];
- case AR_EEPROM_MAC(2):
- return pBase->macAddr[4] << 8 | pBase->macAddr[5];
- case EEP_REG_0:
- return pBase->regDmn[0];
- case EEP_REG_1:
- return pBase->regDmn[1];
- case EEP_OP_CAP:
- return pBase->deviceCap;
- case EEP_OP_MODE:
- return pBase->opCapFlags;
- case EEP_RF_SILENT:
- return pBase->rfSilent;
- case EEP_OB_2:
- return pModal->ob_01;
- case EEP_DB_2:
- return pModal->db1_01;
- case EEP_MINOR_REV:
- return pBase->version & AR5416_EEP_VER_MINOR_MASK;
- case EEP_TX_MASK:
- return pBase->txMask;
- case EEP_RX_MASK:
- return pBase->rxMask;
- case EEP_FRAC_N_5G:
- return 0;
- default:
- return 0;
- }
-}
-
-static void ath9k_hw_get_4k_gain_boundaries_pdadcs(struct ath_hw *ah,
- struct ath9k_channel *chan,
- struct cal_data_per_freq_4k *pRawDataSet,
- u8 *bChans, u16 availPiers,
- u16 tPdGainOverlap, int16_t *pMinCalPower,
- u16 *pPdGainBoundaries, u8 *pPDADCValues,
- u16 numXpdGains)
-{
-#define TMP_VAL_VPD_TABLE \
- ((vpdTableI[i][sizeCurrVpdTable - 1] + (ss - maxIndex + 1) * vpdStep));
- int i, j, k;
- int16_t ss;
- u16 idxL = 0, idxR = 0, numPiers;
- static u8 vpdTableL[AR5416_EEP4K_NUM_PD_GAINS]
- [AR5416_MAX_PWR_RANGE_IN_HALF_DB];
- static u8 vpdTableR[AR5416_EEP4K_NUM_PD_GAINS]
- [AR5416_MAX_PWR_RANGE_IN_HALF_DB];
- static u8 vpdTableI[AR5416_EEP4K_NUM_PD_GAINS]
- [AR5416_MAX_PWR_RANGE_IN_HALF_DB];
-
- u8 *pVpdL, *pVpdR, *pPwrL, *pPwrR;
- u8 minPwrT4[AR5416_EEP4K_NUM_PD_GAINS];
- u8 maxPwrT4[AR5416_EEP4K_NUM_PD_GAINS];
- int16_t vpdStep;
- int16_t tmpVal;
- u16 sizeCurrVpdTable, maxIndex, tgtIndex;
- bool match;
- int16_t minDelta = 0;
- struct chan_centers centers;
-#define PD_GAIN_BOUNDARY_DEFAULT 58;
-
- ath9k_hw_get_channel_centers(ah, chan, &centers);
-
- for (numPiers = 0; numPiers < availPiers; numPiers++) {
- if (bChans[numPiers] == AR5416_BCHAN_UNUSED)
- break;
- }
-
- match = ath9k_hw_get_lower_upper_index(
- (u8)FREQ2FBIN(centers.synth_center,
- IS_CHAN_2GHZ(chan)), bChans, numPiers,
- &idxL, &idxR);
-
- if (match) {
- for (i = 0; i < numXpdGains; i++) {
- minPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][0];
- maxPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][4];
- ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
- pRawDataSet[idxL].pwrPdg[i],
- pRawDataSet[idxL].vpdPdg[i],
- AR5416_EEP4K_PD_GAIN_ICEPTS,
- vpdTableI[i]);
- }
- } else {
- for (i = 0; i < numXpdGains; i++) {
- pVpdL = pRawDataSet[idxL].vpdPdg[i];
- pPwrL = pRawDataSet[idxL].pwrPdg[i];
- pVpdR = pRawDataSet[idxR].vpdPdg[i];
- pPwrR = pRawDataSet[idxR].pwrPdg[i];
-
- minPwrT4[i] = max(pPwrL[0], pPwrR[0]);
-
- maxPwrT4[i] =
- min(pPwrL[AR5416_EEP4K_PD_GAIN_ICEPTS - 1],
- pPwrR[AR5416_EEP4K_PD_GAIN_ICEPTS - 1]);
-
-
- ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
- pPwrL, pVpdL,
- AR5416_EEP4K_PD_GAIN_ICEPTS,
- vpdTableL[i]);
- ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
- pPwrR, pVpdR,
- AR5416_EEP4K_PD_GAIN_ICEPTS,
- vpdTableR[i]);
-
- for (j = 0; j <= (maxPwrT4[i] - minPwrT4[i]) / 2; j++) {
- vpdTableI[i][j] =
- (u8)(ath9k_hw_interpolate((u16)
- FREQ2FBIN(centers.
- synth_center,
- IS_CHAN_2GHZ
- (chan)),
- bChans[idxL], bChans[idxR],
- vpdTableL[i][j], vpdTableR[i][j]));
- }
- }
- }
-
- *pMinCalPower = (int16_t)(minPwrT4[0] / 2);
-
- k = 0;
-
- for (i = 0; i < numXpdGains; i++) {
- if (i == (numXpdGains - 1))
- pPdGainBoundaries[i] =
- (u16)(maxPwrT4[i] / 2);
- else
- pPdGainBoundaries[i] =
- (u16)((maxPwrT4[i] + minPwrT4[i + 1]) / 4);
-
- pPdGainBoundaries[i] =
- min((u16)AR5416_MAX_RATE_POWER, pPdGainBoundaries[i]);
-
- if ((i == 0) && !AR_SREV_5416_20_OR_LATER(ah)) {
- minDelta = pPdGainBoundaries[0] - 23;
- pPdGainBoundaries[0] = 23;
- } else {
- minDelta = 0;
- }
-
- if (i == 0) {
- if (AR_SREV_9280_10_OR_LATER(ah))
- ss = (int16_t)(0 - (minPwrT4[i] / 2));
- else
- ss = 0;
- } else {
- ss = (int16_t)((pPdGainBoundaries[i - 1] -
- (minPwrT4[i] / 2)) -
- tPdGainOverlap + 1 + minDelta);
- }
- vpdStep = (int16_t)(vpdTableI[i][1] - vpdTableI[i][0]);
- vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep);
-
- while ((ss < 0) && (k < (AR5416_NUM_PDADC_VALUES - 1))) {
- tmpVal = (int16_t)(vpdTableI[i][0] + ss * vpdStep);
- pPDADCValues[k++] = (u8)((tmpVal < 0) ? 0 : tmpVal);
- ss++;
- }
-
- sizeCurrVpdTable = (u8) ((maxPwrT4[i] - minPwrT4[i]) / 2 + 1);
- tgtIndex = (u8)(pPdGainBoundaries[i] + tPdGainOverlap -
- (minPwrT4[i] / 2));
- maxIndex = (tgtIndex < sizeCurrVpdTable) ?
- tgtIndex : sizeCurrVpdTable;
-
- while ((ss < maxIndex) && (k < (AR5416_NUM_PDADC_VALUES - 1)))
- pPDADCValues[k++] = vpdTableI[i][ss++];
-
- vpdStep = (int16_t)(vpdTableI[i][sizeCurrVpdTable - 1] -
- vpdTableI[i][sizeCurrVpdTable - 2]);
- vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep);
-
- if (tgtIndex >= maxIndex) {
- while ((ss <= tgtIndex) &&
- (k < (AR5416_NUM_PDADC_VALUES - 1))) {
- tmpVal = (int16_t) TMP_VAL_VPD_TABLE;
- pPDADCValues[k++] = (u8)((tmpVal > 255) ?
- 255 : tmpVal);
- ss++;
- }
- }
- }
-
- while (i < AR5416_EEP4K_PD_GAINS_IN_MASK) {
- pPdGainBoundaries[i] = PD_GAIN_BOUNDARY_DEFAULT;
- i++;
- }
-
- while (k < AR5416_NUM_PDADC_VALUES) {
- pPDADCValues[k] = pPDADCValues[k - 1];
- k++;
- }
-
- return;
-#undef TMP_VAL_VPD_TABLE
-}
-
-static void ath9k_hw_set_4k_power_cal_table(struct ath_hw *ah,
- struct ath9k_channel *chan,
- int16_t *pTxPowerIndexOffset)
-{
- struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k;
- struct cal_data_per_freq_4k *pRawDataset;
- u8 *pCalBChans = NULL;
- u16 pdGainOverlap_t2;
- static u8 pdadcValues[AR5416_NUM_PDADC_VALUES];
- u16 gainBoundaries[AR5416_EEP4K_PD_GAINS_IN_MASK];
- u16 numPiers, i, j;
- int16_t tMinCalPower;
- u16 numXpdGain, xpdMask;
- u16 xpdGainValues[AR5416_EEP4K_NUM_PD_GAINS] = { 0, 0 };
- u32 reg32, regOffset, regChainOffset;
-
- xpdMask = pEepData->modalHeader.xpdGain;
-
- if ((pEepData->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
- AR5416_EEP_MINOR_VER_2) {
- pdGainOverlap_t2 =
- pEepData->modalHeader.pdGainOverlap;
- } else {
- pdGainOverlap_t2 = (u16)(MS(REG_READ(ah, AR_PHY_TPCRG5),
- AR_PHY_TPCRG5_PD_GAIN_OVERLAP));
- }
-
- pCalBChans = pEepData->calFreqPier2G;
- numPiers = AR5416_EEP4K_NUM_2G_CAL_PIERS;
-
- numXpdGain = 0;
-
- for (i = 1; i <= AR5416_EEP4K_PD_GAINS_IN_MASK; i++) {
- if ((xpdMask >> (AR5416_EEP4K_PD_GAINS_IN_MASK - i)) & 1) {
- if (numXpdGain >= AR5416_EEP4K_NUM_PD_GAINS)
- break;
- xpdGainValues[numXpdGain] =
- (u16)(AR5416_EEP4K_PD_GAINS_IN_MASK - i);
- numXpdGain++;
- }
- }
-
- REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_NUM_PD_GAIN,
- (numXpdGain - 1) & 0x3);
- REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_1,
- xpdGainValues[0]);
- REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_2,
- xpdGainValues[1]);
- REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_3, 0);
-
- for (i = 0; i < AR5416_EEP4K_MAX_CHAINS; i++) {
- if (AR_SREV_5416_20_OR_LATER(ah) &&
- (ah->rxchainmask == 5 || ah->txchainmask == 5) &&
- (i != 0)) {
- regChainOffset = (i == 1) ? 0x2000 : 0x1000;
- } else
- regChainOffset = i * 0x1000;
-
- if (pEepData->baseEepHeader.txMask & (1 << i)) {
- pRawDataset = pEepData->calPierData2G[i];
-
- ath9k_hw_get_4k_gain_boundaries_pdadcs(ah, chan,
- pRawDataset, pCalBChans,
- numPiers, pdGainOverlap_t2,
- &tMinCalPower, gainBoundaries,
- pdadcValues, numXpdGain);
-
- if ((i == 0) || AR_SREV_5416_20_OR_LATER(ah)) {
- REG_WRITE(ah, AR_PHY_TPCRG5 + regChainOffset,
- SM(pdGainOverlap_t2,
- AR_PHY_TPCRG5_PD_GAIN_OVERLAP)
- | SM(gainBoundaries[0],
- AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1)
- | SM(gainBoundaries[1],
- AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2)
- | SM(gainBoundaries[2],
- AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3)
- | SM(gainBoundaries[3],
- AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4));
- }
-
- regOffset = AR_PHY_BASE + (672 << 2) + regChainOffset;
- for (j = 0; j < 32; j++) {
- reg32 = ((pdadcValues[4 * j + 0] & 0xFF) << 0) |
- ((pdadcValues[4 * j + 1] & 0xFF) << 8) |
- ((pdadcValues[4 * j + 2] & 0xFF) << 16)|
- ((pdadcValues[4 * j + 3] & 0xFF) << 24);
- REG_WRITE(ah, regOffset, reg32);
-
- DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
- "PDADC (%d,%4x): %4.4x %8.8x\n",
- i, regChainOffset, regOffset,
- reg32);
- DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
- "PDADC: Chain %d | "
- "PDADC %3d Value %3d | "
- "PDADC %3d Value %3d | "
- "PDADC %3d Value %3d | "
- "PDADC %3d Value %3d |\n",
- i, 4 * j, pdadcValues[4 * j],
- 4 * j + 1, pdadcValues[4 * j + 1],
- 4 * j + 2, pdadcValues[4 * j + 2],
- 4 * j + 3,
- pdadcValues[4 * j + 3]);
-
- regOffset += 4;
- }
- }
- }
-
- *pTxPowerIndexOffset = 0;
-}
-
-static void ath9k_hw_set_4k_power_per_rate_table(struct ath_hw *ah,
- struct ath9k_channel *chan,
- int16_t *ratesArray,
- u16 cfgCtl,
- u16 AntennaReduction,
- u16 twiceMaxRegulatoryPower,
- u16 powerLimit)
-{
- struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k;
- u16 twiceMaxEdgePower = AR5416_MAX_RATE_POWER;
- static const u16 tpScaleReductionTable[5] =
- { 0, 3, 6, 9, AR5416_MAX_RATE_POWER };
-
- int i;
- int16_t twiceLargestAntenna;
- struct cal_ctl_data_4k *rep;
- struct cal_target_power_leg targetPowerOfdm, targetPowerCck = {
- 0, { 0, 0, 0, 0}
- };
- struct cal_target_power_leg targetPowerOfdmExt = {
- 0, { 0, 0, 0, 0} }, targetPowerCckExt = {
- 0, { 0, 0, 0, 0 }
- };
- struct cal_target_power_ht targetPowerHt20, targetPowerHt40 = {
- 0, {0, 0, 0, 0}
- };
- u16 scaledPower = 0, minCtlPower, maxRegAllowedPower;
- u16 ctlModesFor11g[] =
- { CTL_11B, CTL_11G, CTL_2GHT20, CTL_11B_EXT, CTL_11G_EXT,
- CTL_2GHT40
- };
- u16 numCtlModes, *pCtlMode, ctlMode, freq;
- struct chan_centers centers;
- int tx_chainmask;
- u16 twiceMinEdgePower;
-
- tx_chainmask = ah->txchainmask;
-
- ath9k_hw_get_channel_centers(ah, chan, &centers);
-
- twiceLargestAntenna = pEepData->modalHeader.antennaGainCh[0];
-
- twiceLargestAntenna = (int16_t)min(AntennaReduction -
- twiceLargestAntenna, 0);
-
- maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna;
-
- if (ah->regulatory.tp_scale != ATH9K_TP_SCALE_MAX) {
- maxRegAllowedPower -=
- (tpScaleReductionTable[(ah->regulatory.tp_scale)] * 2);
- }
-
- scaledPower = min(powerLimit, maxRegAllowedPower);
- scaledPower = max((u16)0, scaledPower);
-
- numCtlModes = ARRAY_SIZE(ctlModesFor11g) - SUB_NUM_CTL_MODES_AT_2G_40;
- pCtlMode = ctlModesFor11g;
-
- ath9k_hw_get_legacy_target_powers(ah, chan,
- pEepData->calTargetPowerCck,
- AR5416_NUM_2G_CCK_TARGET_POWERS,
- &targetPowerCck, 4, false);
- ath9k_hw_get_legacy_target_powers(ah, chan,
- pEepData->calTargetPower2G,
- AR5416_NUM_2G_20_TARGET_POWERS,
- &targetPowerOfdm, 4, false);
- ath9k_hw_get_target_powers(ah, chan,
- pEepData->calTargetPower2GHT20,
- AR5416_NUM_2G_20_TARGET_POWERS,
- &targetPowerHt20, 8, false);
-
- if (IS_CHAN_HT40(chan)) {
- numCtlModes = ARRAY_SIZE(ctlModesFor11g);
- ath9k_hw_get_target_powers(ah, chan,
- pEepData->calTargetPower2GHT40,
- AR5416_NUM_2G_40_TARGET_POWERS,
- &targetPowerHt40, 8, true);
- ath9k_hw_get_legacy_target_powers(ah, chan,
- pEepData->calTargetPowerCck,
- AR5416_NUM_2G_CCK_TARGET_POWERS,
- &targetPowerCckExt, 4, true);
- ath9k_hw_get_legacy_target_powers(ah, chan,
- pEepData->calTargetPower2G,
- AR5416_NUM_2G_20_TARGET_POWERS,
- &targetPowerOfdmExt, 4, true);
- }
-
- for (ctlMode = 0; ctlMode < numCtlModes; ctlMode++) {
- bool isHt40CtlMode = (pCtlMode[ctlMode] == CTL_5GHT40) ||
- (pCtlMode[ctlMode] == CTL_2GHT40);
- if (isHt40CtlMode)
- freq = centers.synth_center;
- else if (pCtlMode[ctlMode] & EXT_ADDITIVE)
- freq = centers.ext_center;
- else
- freq = centers.ctl_center;
-
- if (ah->eep_ops->get_eeprom_ver(ah) == 14 &&
- ah->eep_ops->get_eeprom_rev(ah) <= 2)
- twiceMaxEdgePower = AR5416_MAX_RATE_POWER;
-
- DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
- "LOOP-Mode ctlMode %d < %d, isHt40CtlMode %d, "
- "EXT_ADDITIVE %d\n",
- ctlMode, numCtlModes, isHt40CtlMode,
- (pCtlMode[ctlMode] & EXT_ADDITIVE));
-
- for (i = 0; (i < AR5416_EEP4K_NUM_CTLS) &&
- pEepData->ctlIndex[i]; i++) {
- DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
- " LOOP-Ctlidx %d: cfgCtl 0x%2.2x "
- "pCtlMode 0x%2.2x ctlIndex 0x%2.2x "
- "chan %d\n",
- i, cfgCtl, pCtlMode[ctlMode],
- pEepData->ctlIndex[i], chan->channel);
-
- if ((((cfgCtl & ~CTL_MODE_M) |
- (pCtlMode[ctlMode] & CTL_MODE_M)) ==
- pEepData->ctlIndex[i]) ||
- (((cfgCtl & ~CTL_MODE_M) |
- (pCtlMode[ctlMode] & CTL_MODE_M)) ==
- ((pEepData->ctlIndex[i] & CTL_MODE_M) |
- SD_NO_CTL))) {
- rep = &(pEepData->ctlData[i]);
-
- twiceMinEdgePower =
- ath9k_hw_get_max_edge_power(freq,
- rep->ctlEdges[ar5416_get_ntxchains
- (tx_chainmask) - 1],
- IS_CHAN_2GHZ(chan),
- AR5416_EEP4K_NUM_BAND_EDGES);
-
- DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
- " MATCH-EE_IDX %d: ch %d is2 %d "
- "2xMinEdge %d chainmask %d chains %d\n",
- i, freq, IS_CHAN_2GHZ(chan),
- twiceMinEdgePower, tx_chainmask,
- ar5416_get_ntxchains
- (tx_chainmask));
- if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL) {
- twiceMaxEdgePower =
- min(twiceMaxEdgePower,
- twiceMinEdgePower);
- } else {
- twiceMaxEdgePower = twiceMinEdgePower;
- break;
- }
- }
- }
-
- minCtlPower = (u8)min(twiceMaxEdgePower, scaledPower);
-
- DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
- " SEL-Min ctlMode %d pCtlMode %d "
- "2xMaxEdge %d sP %d minCtlPwr %d\n",
- ctlMode, pCtlMode[ctlMode], twiceMaxEdgePower,
- scaledPower, minCtlPower);
-
- switch (pCtlMode[ctlMode]) {
- case CTL_11B:
- for (i = 0; i < ARRAY_SIZE(targetPowerCck.tPow2x);
- i++) {
- targetPowerCck.tPow2x[i] =
- min((u16)targetPowerCck.tPow2x[i],
- minCtlPower);
- }
- break;
- case CTL_11G:
- for (i = 0; i < ARRAY_SIZE(targetPowerOfdm.tPow2x);
- i++) {
- targetPowerOfdm.tPow2x[i] =
- min((u16)targetPowerOfdm.tPow2x[i],
- minCtlPower);
- }
- break;
- case CTL_2GHT20:
- for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x);
- i++) {
- targetPowerHt20.tPow2x[i] =
- min((u16)targetPowerHt20.tPow2x[i],
- minCtlPower);
- }
- break;
- case CTL_11B_EXT:
- targetPowerCckExt.tPow2x[0] = min((u16)
- targetPowerCckExt.tPow2x[0],
- minCtlPower);
- break;
- case CTL_11G_EXT:
- targetPowerOfdmExt.tPow2x[0] = min((u16)
- targetPowerOfdmExt.tPow2x[0],
- minCtlPower);
- break;
- case CTL_2GHT40:
- for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x);
- i++) {
- targetPowerHt40.tPow2x[i] =
- min((u16)targetPowerHt40.tPow2x[i],
- minCtlPower);
- }
- break;
- default:
- break;
- }
- }
-
- ratesArray[rate6mb] = ratesArray[rate9mb] = ratesArray[rate12mb] =
- ratesArray[rate18mb] = ratesArray[rate24mb] =
- targetPowerOfdm.tPow2x[0];
- ratesArray[rate36mb] = targetPowerOfdm.tPow2x[1];
- ratesArray[rate48mb] = targetPowerOfdm.tPow2x[2];
- ratesArray[rate54mb] = targetPowerOfdm.tPow2x[3];
- ratesArray[rateXr] = targetPowerOfdm.tPow2x[0];
-
- for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); i++)
- ratesArray[rateHt20_0 + i] = targetPowerHt20.tPow2x[i];
-
- ratesArray[rate1l] = targetPowerCck.tPow2x[0];
- ratesArray[rate2s] = ratesArray[rate2l] = targetPowerCck.tPow2x[1];
- ratesArray[rate5_5s] = ratesArray[rate5_5l] = targetPowerCck.tPow2x[2];
- ratesArray[rate11s] = ratesArray[rate11l] = targetPowerCck.tPow2x[3];
-
- if (IS_CHAN_HT40(chan)) {
- for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++) {
- ratesArray[rateHt40_0 + i] =
- targetPowerHt40.tPow2x[i];
- }
- ratesArray[rateDupOfdm] = targetPowerHt40.tPow2x[0];
- ratesArray[rateDupCck] = targetPowerHt40.tPow2x[0];
- ratesArray[rateExtOfdm] = targetPowerOfdmExt.tPow2x[0];
- ratesArray[rateExtCck] = targetPowerCckExt.tPow2x[0];
- }
-}
-
-static void ath9k_hw_4k_set_txpower(struct ath_hw *ah,
- struct ath9k_channel *chan,
- u16 cfgCtl,
- u8 twiceAntennaReduction,
- u8 twiceMaxRegulatoryPower,
- u8 powerLimit)
-{
- struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k;
- struct modal_eep_4k_header *pModal = &pEepData->modalHeader;
- int16_t ratesArray[Ar5416RateSize];
- int16_t txPowerIndexOffset = 0;
- u8 ht40PowerIncForPdadc = 2;
- int i;
-
- memset(ratesArray, 0, sizeof(ratesArray));
-
- if ((pEepData->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
- AR5416_EEP_MINOR_VER_2) {
- ht40PowerIncForPdadc = pModal->ht40PowerIncForPdadc;
- }
-
- ath9k_hw_set_4k_power_per_rate_table(ah, chan,
- &ratesArray[0], cfgCtl,
- twiceAntennaReduction,
- twiceMaxRegulatoryPower,
- powerLimit);
-
- ath9k_hw_set_4k_power_cal_table(ah, chan, &txPowerIndexOffset);
-
- for (i = 0; i < ARRAY_SIZE(ratesArray); i++) {
- ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]);
- if (ratesArray[i] > AR5416_MAX_RATE_POWER)
- ratesArray[i] = AR5416_MAX_RATE_POWER;
- }
-
- if (AR_SREV_9280_10_OR_LATER(ah)) {
- for (i = 0; i < Ar5416RateSize; i++)
- ratesArray[i] -= AR5416_PWR_TABLE_OFFSET * 2;
- }
-
- REG_WRITE(ah, AR_PHY_POWER_TX_RATE1,
- ATH9K_POW_SM(ratesArray[rate18mb], 24)
- | ATH9K_POW_SM(ratesArray[rate12mb], 16)
- | ATH9K_POW_SM(ratesArray[rate9mb], 8)
- | ATH9K_POW_SM(ratesArray[rate6mb], 0));
- REG_WRITE(ah, AR_PHY_POWER_TX_RATE2,
- ATH9K_POW_SM(ratesArray[rate54mb], 24)
- | ATH9K_POW_SM(ratesArray[rate48mb], 16)
- | ATH9K_POW_SM(ratesArray[rate36mb], 8)
- | ATH9K_POW_SM(ratesArray[rate24mb], 0));
-
- if (IS_CHAN_2GHZ(chan)) {
- REG_WRITE(ah, AR_PHY_POWER_TX_RATE3,
- ATH9K_POW_SM(ratesArray[rate2s], 24)
- | ATH9K_POW_SM(ratesArray[rate2l], 16)
- | ATH9K_POW_SM(ratesArray[rateXr], 8)
- | ATH9K_POW_SM(ratesArray[rate1l], 0));
- REG_WRITE(ah, AR_PHY_POWER_TX_RATE4,
- ATH9K_POW_SM(ratesArray[rate11s], 24)
- | ATH9K_POW_SM(ratesArray[rate11l], 16)
- | ATH9K_POW_SM(ratesArray[rate5_5s], 8)
- | ATH9K_POW_SM(ratesArray[rate5_5l], 0));
- }
-
- REG_WRITE(ah, AR_PHY_POWER_TX_RATE5,
- ATH9K_POW_SM(ratesArray[rateHt20_3], 24)
- | ATH9K_POW_SM(ratesArray[rateHt20_2], 16)
- | ATH9K_POW_SM(ratesArray[rateHt20_1], 8)
- | ATH9K_POW_SM(ratesArray[rateHt20_0], 0));
- REG_WRITE(ah, AR_PHY_POWER_TX_RATE6,
- ATH9K_POW_SM(ratesArray[rateHt20_7], 24)
- | ATH9K_POW_SM(ratesArray[rateHt20_6], 16)
- | ATH9K_POW_SM(ratesArray[rateHt20_5], 8)
- | ATH9K_POW_SM(ratesArray[rateHt20_4], 0));
-
- if (IS_CHAN_HT40(chan)) {
- REG_WRITE(ah, AR_PHY_POWER_TX_RATE7,
- ATH9K_POW_SM(ratesArray[rateHt40_3] +
- ht40PowerIncForPdadc, 24)
- | ATH9K_POW_SM(ratesArray[rateHt40_2] +
- ht40PowerIncForPdadc, 16)
- | ATH9K_POW_SM(ratesArray[rateHt40_1] +
- ht40PowerIncForPdadc, 8)
- | ATH9K_POW_SM(ratesArray[rateHt40_0] +
- ht40PowerIncForPdadc, 0));
- REG_WRITE(ah, AR_PHY_POWER_TX_RATE8,
- ATH9K_POW_SM(ratesArray[rateHt40_7] +
- ht40PowerIncForPdadc, 24)
- | ATH9K_POW_SM(ratesArray[rateHt40_6] +
- ht40PowerIncForPdadc, 16)
- | ATH9K_POW_SM(ratesArray[rateHt40_5] +
- ht40PowerIncForPdadc, 8)
- | ATH9K_POW_SM(ratesArray[rateHt40_4] +
- ht40PowerIncForPdadc, 0));
-
- REG_WRITE(ah, AR_PHY_POWER_TX_RATE9,
- ATH9K_POW_SM(ratesArray[rateExtOfdm], 24)
- | ATH9K_POW_SM(ratesArray[rateExtCck], 16)
- | ATH9K_POW_SM(ratesArray[rateDupOfdm], 8)
- | ATH9K_POW_SM(ratesArray[rateDupCck], 0));
- }
-
- i = rate6mb;
-
- if (IS_CHAN_HT40(chan))
- i = rateHt40_0;
- else if (IS_CHAN_HT20(chan))
- i = rateHt20_0;
-
- if (AR_SREV_9280_10_OR_LATER(ah))
- ah->regulatory.max_power_level =
- ratesArray[i] + AR5416_PWR_TABLE_OFFSET * 2;
- else
- ah->regulatory.max_power_level = ratesArray[i];
-
-}
-
-static void ath9k_hw_4k_set_addac(struct ath_hw *ah,
- struct ath9k_channel *chan)
-{
- struct modal_eep_4k_header *pModal;
- struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k;
- u8 biaslevel;
-
- if (ah->hw_version.macVersion != AR_SREV_VERSION_9160)
- return;
-
- if (ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_MINOR_VER_7)
- return;
-
- pModal = &eep->modalHeader;
-
- if (pModal->xpaBiasLvl != 0xff) {
- biaslevel = pModal->xpaBiasLvl;
- INI_RA(&ah->iniAddac, 7, 1) =
- (INI_RA(&ah->iniAddac, 7, 1) & (~0x18)) | biaslevel << 3;
- }
-}
-
-static void ath9k_hw_4k_set_gain(struct ath_hw *ah,
- struct modal_eep_4k_header *pModal,
- struct ar5416_eeprom_4k *eep,
- u8 txRxAttenLocal, int regChainOffset)
-{
- REG_WRITE(ah, AR_PHY_SWITCH_CHAIN_0 + regChainOffset,
- pModal->antCtrlChain[0]);
-
- REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset,
- (REG_READ(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset) &
- ~(AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF |
- AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF)) |
- SM(pModal->iqCalICh[0], AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF) |
- SM(pModal->iqCalQCh[0], AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF));
-
- if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
- AR5416_EEP_MINOR_VER_3) {
- txRxAttenLocal = pModal->txRxAttenCh[0];
-
- REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
- AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN, pModal->bswMargin[0]);
- REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
- AR_PHY_GAIN_2GHZ_XATTEN1_DB, pModal->bswAtten[0]);
- REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
- AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN,
- pModal->xatten2Margin[0]);
- REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
- AR_PHY_GAIN_2GHZ_XATTEN2_DB, pModal->xatten2Db[0]);
- }
-
- REG_RMW_FIELD(ah, AR_PHY_RXGAIN + regChainOffset,
- AR9280_PHY_RXGAIN_TXRX_ATTEN, txRxAttenLocal);
- REG_RMW_FIELD(ah, AR_PHY_RXGAIN + regChainOffset,
- AR9280_PHY_RXGAIN_TXRX_MARGIN, pModal->rxTxMarginCh[0]);
-
- if (AR_SREV_9285_11(ah))
- REG_WRITE(ah, AR9285_AN_TOP4, (AR9285_AN_TOP4_DEFAULT | 0x14));
-}
-
-static void ath9k_hw_4k_set_board_values(struct ath_hw *ah,
- struct ath9k_channel *chan)
-{
- struct modal_eep_4k_header *pModal;
- struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k;
- u8 txRxAttenLocal;
- u8 ob[5], db1[5], db2[5];
- u8 ant_div_control1, ant_div_control2;
- u32 regVal;
-
- pModal = &eep->modalHeader;
- txRxAttenLocal = 23;
-
- REG_WRITE(ah, AR_PHY_SWITCH_COM,
- ah->eep_ops->get_eeprom_antenna_cfg(ah, chan));
-
- /* Single chain for 4K EEPROM*/
- ath9k_hw_4k_set_gain(ah, pModal, eep, txRxAttenLocal, 0);
-
- /* Initialize Ant Diversity settings from EEPROM */
- if (pModal->version == 3) {
- ant_div_control1 = ((pModal->ob_234 >> 12) & 0xf);
- ant_div_control2 = ((pModal->db1_234 >> 12) & 0xf);
- regVal = REG_READ(ah, 0x99ac);
- regVal &= (~(0x7f000000));
- regVal |= ((ant_div_control1 & 0x1) << 24);
- regVal |= (((ant_div_control1 >> 1) & 0x1) << 29);
- regVal |= (((ant_div_control1 >> 2) & 0x1) << 30);
- regVal |= ((ant_div_control2 & 0x3) << 25);
- regVal |= (((ant_div_control2 >> 2) & 0x3) << 27);
- REG_WRITE(ah, 0x99ac, regVal);
- regVal = REG_READ(ah, 0x99ac);
- regVal = REG_READ(ah, 0xa208);
- regVal &= (~(0x1 << 13));
- regVal |= (((ant_div_control1 >> 3) & 0x1) << 13);
- REG_WRITE(ah, 0xa208, regVal);
- regVal = REG_READ(ah, 0xa208);
- }
-
- if (pModal->version >= 2) {
- ob[0] = (pModal->ob_01 & 0xf);
- ob[1] = (pModal->ob_01 >> 4) & 0xf;
- ob[2] = (pModal->ob_234 & 0xf);
- ob[3] = ((pModal->ob_234 >> 4) & 0xf);
- ob[4] = ((pModal->ob_234 >> 8) & 0xf);
-
- db1[0] = (pModal->db1_01 & 0xf);
- db1[1] = ((pModal->db1_01 >> 4) & 0xf);
- db1[2] = (pModal->db1_234 & 0xf);
- db1[3] = ((pModal->db1_234 >> 4) & 0xf);
- db1[4] = ((pModal->db1_234 >> 8) & 0xf);
-
- db2[0] = (pModal->db2_01 & 0xf);
- db2[1] = ((pModal->db2_01 >> 4) & 0xf);
- db2[2] = (pModal->db2_234 & 0xf);
- db2[3] = ((pModal->db2_234 >> 4) & 0xf);
- db2[4] = ((pModal->db2_234 >> 8) & 0xf);
-
- } else if (pModal->version == 1) {
- ob[0] = (pModal->ob_01 & 0xf);
- ob[1] = ob[2] = ob[3] = ob[4] = (pModal->ob_01 >> 4) & 0xf;
- db1[0] = (pModal->db1_01 & 0xf);
- db1[1] = db1[2] = db1[3] =
- db1[4] = ((pModal->db1_01 >> 4) & 0xf);
- db2[0] = (pModal->db2_01 & 0xf);
- db2[1] = db2[2] = db2[3] =
- db2[4] = ((pModal->db2_01 >> 4) & 0xf);
- } else {
- int i;
- for (i = 0; i < 5; i++) {
- ob[i] = pModal->ob_01;
- db1[i] = pModal->db1_01;
- db2[i] = pModal->db1_01;
- }
- }
-
- ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G3,
- AR9285_AN_RF2G3_OB_0, AR9285_AN_RF2G3_OB_0_S, ob[0]);
- ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G3,
- AR9285_AN_RF2G3_OB_1, AR9285_AN_RF2G3_OB_1_S, ob[1]);
- ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G3,
- AR9285_AN_RF2G3_OB_2, AR9285_AN_RF2G3_OB_2_S, ob[2]);
- ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G3,
- AR9285_AN_RF2G3_OB_3, AR9285_AN_RF2G3_OB_3_S, ob[3]);
- ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G3,
- AR9285_AN_RF2G3_OB_4, AR9285_AN_RF2G3_OB_4_S, ob[4]);
-
- ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G3,
- AR9285_AN_RF2G3_DB1_0, AR9285_AN_RF2G3_DB1_0_S, db1[0]);
- ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G3,
- AR9285_AN_RF2G3_DB1_1, AR9285_AN_RF2G3_DB1_1_S, db1[1]);
- ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G3,
- AR9285_AN_RF2G3_DB1_2, AR9285_AN_RF2G3_DB1_2_S, db1[2]);
- ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G4,
- AR9285_AN_RF2G4_DB1_3, AR9285_AN_RF2G4_DB1_3_S, db1[3]);
- ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G4,
- AR9285_AN_RF2G4_DB1_4, AR9285_AN_RF2G4_DB1_4_S, db1[4]);
-
- ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G4,
- AR9285_AN_RF2G4_DB2_0, AR9285_AN_RF2G4_DB2_0_S, db2[0]);
- ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G4,
- AR9285_AN_RF2G4_DB2_1, AR9285_AN_RF2G4_DB2_1_S, db2[1]);
- ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G4,
- AR9285_AN_RF2G4_DB2_2, AR9285_AN_RF2G4_DB2_2_S, db2[2]);
- ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G4,
- AR9285_AN_RF2G4_DB2_3, AR9285_AN_RF2G4_DB2_3_S, db2[3]);
- ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G4,
- AR9285_AN_RF2G4_DB2_4, AR9285_AN_RF2G4_DB2_4_S, db2[4]);
-
-
- if (AR_SREV_9285_11(ah))
- REG_WRITE(ah, AR9285_AN_TOP4, AR9285_AN_TOP4_DEFAULT);
-
- REG_RMW_FIELD(ah, AR_PHY_SETTLING, AR_PHY_SETTLING_SWITCH,
- pModal->switchSettling);
- REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, AR_PHY_DESIRED_SZ_ADC,
- pModal->adcDesiredSize);
-
- REG_WRITE(ah, AR_PHY_RF_CTL4,
- SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAA_OFF) |
- SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAB_OFF) |
- SM(pModal->txFrameToXpaOn, AR_PHY_RF_CTL4_FRAME_XPAA_ON) |
- SM(pModal->txFrameToXpaOn, AR_PHY_RF_CTL4_FRAME_XPAB_ON));
-
- REG_RMW_FIELD(ah, AR_PHY_RF_CTL3, AR_PHY_TX_END_TO_A2_RX_ON,
- pModal->txEndToRxOn);
- REG_RMW_FIELD(ah, AR_PHY_CCA, AR9280_PHY_CCA_THRESH62,
- pModal->thresh62);
- REG_RMW_FIELD(ah, AR_PHY_EXT_CCA0, AR_PHY_EXT_CCA0_THRESH62,
- pModal->thresh62);
-
- if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
- AR5416_EEP_MINOR_VER_2) {
- REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, AR_PHY_TX_END_DATA_START,
- pModal->txFrameToDataStart);
- REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, AR_PHY_TX_END_PA_ON,
- pModal->txFrameToPaOn);
- }
-
- if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
- AR5416_EEP_MINOR_VER_3) {
- if (IS_CHAN_HT40(chan))
- REG_RMW_FIELD(ah, AR_PHY_SETTLING,
- AR_PHY_SETTLING_SWITCH,
- pModal->swSettleHt40);
- }
-}
-
-static u16 ath9k_hw_4k_get_eeprom_antenna_cfg(struct ath_hw *ah,
- struct ath9k_channel *chan)
-{
- struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k;
- struct modal_eep_4k_header *pModal = &eep->modalHeader;
-
- return pModal->antCtrlCommon & 0xFFFF;
-}
-
-static u8 ath9k_hw_4k_get_num_ant_config(struct ath_hw *ah,
- enum ieee80211_band freq_band)
-{
- return 1;
-}
-
-static u16 ath9k_hw_4k_get_spur_channel(struct ath_hw *ah, u16 i, bool is2GHz)
-{
-#define EEP_MAP4K_SPURCHAN \
- (ah->eeprom.map4k.modalHeader.spurChans[i].spurChan)
-
- u16 spur_val = AR_NO_SPUR;
-
- DPRINTF(ah->ah_sc, ATH_DBG_ANI,
- "Getting spur idx %d is2Ghz. %d val %x\n",
- i, is2GHz, ah->config.spurchans[i][is2GHz]);
-
- switch (ah->config.spurmode) {
- case SPUR_DISABLE:
- break;
- case SPUR_ENABLE_IOCTL:
- spur_val = ah->config.spurchans[i][is2GHz];
- DPRINTF(ah->ah_sc, ATH_DBG_ANI,
- "Getting spur val from new loc. %d\n", spur_val);
- break;
- case SPUR_ENABLE_EEPROM:
- spur_val = EEP_MAP4K_SPURCHAN;
- break;
- }
-
- return spur_val;
-
-#undef EEP_MAP4K_SPURCHAN
-}
-
-static struct eeprom_ops eep_4k_ops = {
- .check_eeprom = ath9k_hw_4k_check_eeprom,
- .get_eeprom = ath9k_hw_4k_get_eeprom,
- .fill_eeprom = ath9k_hw_4k_fill_eeprom,
- .get_eeprom_ver = ath9k_hw_4k_get_eeprom_ver,
- .get_eeprom_rev = ath9k_hw_4k_get_eeprom_rev,
- .get_num_ant_config = ath9k_hw_4k_get_num_ant_config,
- .get_eeprom_antenna_cfg = ath9k_hw_4k_get_eeprom_antenna_cfg,
- .set_board_values = ath9k_hw_4k_set_board_values,
- .set_addac = ath9k_hw_4k_set_addac,
- .set_txpower = ath9k_hw_4k_set_txpower,
- .get_spur_channel = ath9k_hw_4k_get_spur_channel
-};
-
-/************************************************/
-/* EEPROM Operations for non-4K (Default) cards */
-/************************************************/
-
-static int ath9k_hw_def_get_eeprom_ver(struct ath_hw *ah)
-{
- return ((ah->eeprom.def.baseEepHeader.version >> 12) & 0xF);
-}
-
-static int ath9k_hw_def_get_eeprom_rev(struct ath_hw *ah)
-{
- return ((ah->eeprom.def.baseEepHeader.version) & 0xFFF);
-}
-
-static bool ath9k_hw_def_fill_eeprom(struct ath_hw *ah)
-{
-#define SIZE_EEPROM_DEF (sizeof(struct ar5416_eeprom_def) / sizeof(u16))
- u16 *eep_data = (u16 *)&ah->eeprom.def;
- int addr, ar5416_eep_start_loc = 0x100;
-
- for (addr = 0; addr < SIZE_EEPROM_DEF; addr++) {
- if (!ath9k_hw_nvram_read(ah, addr + ar5416_eep_start_loc,
- eep_data)) {
- DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
- "Unable to read eeprom region\n");
- return false;
- }
- eep_data++;
- }
- return true;
-#undef SIZE_EEPROM_DEF
-}
-
-static int ath9k_hw_def_check_eeprom(struct ath_hw *ah)
-{
- struct ar5416_eeprom_def *eep =
- (struct ar5416_eeprom_def *) &ah->eeprom.def;
- u16 *eepdata, temp, magic, magic2;
- u32 sum = 0, el;
- bool need_swap = false;
- int i, addr, size;
-
- if (!ath9k_hw_nvram_read(ah, AR5416_EEPROM_MAGIC_OFFSET, &magic)) {
- DPRINTF(ah->ah_sc, ATH_DBG_FATAL, "Reading Magic # failed\n");
- return false;
- }
-
- if (!ath9k_hw_use_flash(ah)) {
- DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
- "Read Magic = 0x%04X\n", magic);
-
- if (magic != AR5416_EEPROM_MAGIC) {
- magic2 = swab16(magic);
-
- if (magic2 == AR5416_EEPROM_MAGIC) {
- size = sizeof(struct ar5416_eeprom_def);
- need_swap = true;
- eepdata = (u16 *) (&ah->eeprom);
-
- for (addr = 0; addr < size / sizeof(u16); addr++) {
- temp = swab16(*eepdata);
- *eepdata = temp;
- eepdata++;
- }
- } else {
- DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
- "Invalid EEPROM Magic. "
- "Endianness mismatch.\n");
- return -EINVAL;
- }
- }
- }
-
- DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, "need_swap = %s.\n",
- need_swap ? "True" : "False");
-
- if (need_swap)
- el = swab16(ah->eeprom.def.baseEepHeader.length);
- else
- el = ah->eeprom.def.baseEepHeader.length;
-
- if (el > sizeof(struct ar5416_eeprom_def))
- el = sizeof(struct ar5416_eeprom_def) / sizeof(u16);
- else
- el = el / sizeof(u16);
-
- eepdata = (u16 *)(&ah->eeprom);
-
- for (i = 0; i < el; i++)
- sum ^= *eepdata++;
-
- if (need_swap) {
- u32 integer, j;
- u16 word;
-
- DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
- "EEPROM Endianness is not native.. Changing.\n");
-
- word = swab16(eep->baseEepHeader.length);
- eep->baseEepHeader.length = word;
-
- word = swab16(eep->baseEepHeader.checksum);
- eep->baseEepHeader.checksum = word;
-
- word = swab16(eep->baseEepHeader.version);
- eep->baseEepHeader.version = word;
-
- word = swab16(eep->baseEepHeader.regDmn[0]);
- eep->baseEepHeader.regDmn[0] = word;
-
- word = swab16(eep->baseEepHeader.regDmn[1]);
- eep->baseEepHeader.regDmn[1] = word;
-
- word = swab16(eep->baseEepHeader.rfSilent);
- eep->baseEepHeader.rfSilent = word;
-
- word = swab16(eep->baseEepHeader.blueToothOptions);
- eep->baseEepHeader.blueToothOptions = word;
-
- word = swab16(eep->baseEepHeader.deviceCap);
- eep->baseEepHeader.deviceCap = word;
-
- for (j = 0; j < ARRAY_SIZE(eep->modalHeader); j++) {
- struct modal_eep_header *pModal =
- &eep->modalHeader[j];
- integer = swab32(pModal->antCtrlCommon);
- pModal->antCtrlCommon = integer;
-
- for (i = 0; i < AR5416_MAX_CHAINS; i++) {
- integer = swab32(pModal->antCtrlChain[i]);
- pModal->antCtrlChain[i] = integer;
- }
-
- for (i = 0; i < AR5416_EEPROM_MODAL_SPURS; i++) {
- word = swab16(pModal->spurChans[i].spurChan);
- pModal->spurChans[i].spurChan = word;
- }
- }
- }
-
- if (sum != 0xffff || ah->eep_ops->get_eeprom_ver(ah) != AR5416_EEP_VER ||
- ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_NO_BACK_VER) {
- DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
- "Bad EEPROM checksum 0x%x or revision 0x%04x\n",
- sum, ah->eep_ops->get_eeprom_ver(ah));
- return -EINVAL;
- }
-
- return 0;
-}
-
-static u32 ath9k_hw_def_get_eeprom(struct ath_hw *ah,
- enum eeprom_param param)
-{
- struct ar5416_eeprom_def *eep = &ah->eeprom.def;
- struct modal_eep_header *pModal = eep->modalHeader;
- struct base_eep_header *pBase = &eep->baseEepHeader;
-
- switch (param) {
- case EEP_NFTHRESH_5:
- return pModal[0].noiseFloorThreshCh[0];
- case EEP_NFTHRESH_2:
- return pModal[1].noiseFloorThreshCh[0];
- case AR_EEPROM_MAC(0):
- return pBase->macAddr[0] << 8 | pBase->macAddr[1];
- case AR_EEPROM_MAC(1):
- return pBase->macAddr[2] << 8 | pBase->macAddr[3];
- case AR_EEPROM_MAC(2):
- return pBase->macAddr[4] << 8 | pBase->macAddr[5];
- case EEP_REG_0:
- return pBase->regDmn[0];
- case EEP_REG_1:
- return pBase->regDmn[1];
- case EEP_OP_CAP:
- return pBase->deviceCap;
- case EEP_OP_MODE:
- return pBase->opCapFlags;
- case EEP_RF_SILENT:
- return pBase->rfSilent;
- case EEP_OB_5:
- return pModal[0].ob;
- case EEP_DB_5:
- return pModal[0].db;
- case EEP_OB_2:
- return pModal[1].ob;
- case EEP_DB_2:
- return pModal[1].db;
- case EEP_MINOR_REV:
- return AR5416_VER_MASK;
- case EEP_TX_MASK:
- return pBase->txMask;
- case EEP_RX_MASK:
- return pBase->rxMask;
- case EEP_RXGAIN_TYPE:
- return pBase->rxGainType;
- case EEP_TXGAIN_TYPE:
- return pBase->txGainType;
- case EEP_OL_PWRCTRL:
- if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_19)
- return pBase->openLoopPwrCntl ? true : false;
- else
- return false;
- case EEP_RC_CHAIN_MASK:
- if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_19)
- return pBase->rcChainMask;
- else
- return 0;
- case EEP_DAC_HPWR_5G:
- if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_20)
- return pBase->dacHiPwrMode_5G;
- else
- return 0;
- case EEP_FRAC_N_5G:
- if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_22)
- return pBase->frac_n_5g;
- else
- return 0;
- default:
- return 0;
- }
-}
-
-static void ath9k_hw_def_set_gain(struct ath_hw *ah,
- struct modal_eep_header *pModal,
- struct ar5416_eeprom_def *eep,
- u8 txRxAttenLocal, int regChainOffset, int i)
-{
- if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_3) {
- txRxAttenLocal = pModal->txRxAttenCh[i];
-
- if (AR_SREV_9280_10_OR_LATER(ah)) {
- REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
- AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN,
- pModal->bswMargin[i]);
- REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
- AR_PHY_GAIN_2GHZ_XATTEN1_DB,
- pModal->bswAtten[i]);
- REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
- AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN,
- pModal->xatten2Margin[i]);
- REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
- AR_PHY_GAIN_2GHZ_XATTEN2_DB,
- pModal->xatten2Db[i]);
- } else {
- REG_WRITE(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
- (REG_READ(ah, AR_PHY_GAIN_2GHZ + regChainOffset) &
- ~AR_PHY_GAIN_2GHZ_BSW_MARGIN)
- | SM(pModal-> bswMargin[i],
- AR_PHY_GAIN_2GHZ_BSW_MARGIN));
- REG_WRITE(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
- (REG_READ(ah, AR_PHY_GAIN_2GHZ + regChainOffset) &
- ~AR_PHY_GAIN_2GHZ_BSW_ATTEN)
- | SM(pModal->bswAtten[i],
- AR_PHY_GAIN_2GHZ_BSW_ATTEN));
- }
- }
-
- if (AR_SREV_9280_10_OR_LATER(ah)) {
- REG_RMW_FIELD(ah,
- AR_PHY_RXGAIN + regChainOffset,
- AR9280_PHY_RXGAIN_TXRX_ATTEN, txRxAttenLocal);
- REG_RMW_FIELD(ah,
- AR_PHY_RXGAIN + regChainOffset,
- AR9280_PHY_RXGAIN_TXRX_MARGIN, pModal->rxTxMarginCh[i]);
- } else {
- REG_WRITE(ah,
- AR_PHY_RXGAIN + regChainOffset,
- (REG_READ(ah, AR_PHY_RXGAIN + regChainOffset) &
- ~AR_PHY_RXGAIN_TXRX_ATTEN)
- | SM(txRxAttenLocal, AR_PHY_RXGAIN_TXRX_ATTEN));
- REG_WRITE(ah,
- AR_PHY_GAIN_2GHZ + regChainOffset,
- (REG_READ(ah, AR_PHY_GAIN_2GHZ + regChainOffset) &
- ~AR_PHY_GAIN_2GHZ_RXTX_MARGIN) |
- SM(pModal->rxTxMarginCh[i], AR_PHY_GAIN_2GHZ_RXTX_MARGIN));
- }
-}
-
-static void ath9k_hw_def_set_board_values(struct ath_hw *ah,
- struct ath9k_channel *chan)
-{
- struct modal_eep_header *pModal;
- struct ar5416_eeprom_def *eep = &ah->eeprom.def;
- int i, regChainOffset;
- u8 txRxAttenLocal;
-
- pModal = &(eep->modalHeader[IS_CHAN_2GHZ(chan)]);
- txRxAttenLocal = IS_CHAN_2GHZ(chan) ? 23 : 44;
-
- REG_WRITE(ah, AR_PHY_SWITCH_COM,
- ah->eep_ops->get_eeprom_antenna_cfg(ah, chan));
-
- for (i = 0; i < AR5416_MAX_CHAINS; i++) {
- if (AR_SREV_9280(ah)) {
- if (i >= 2)
- break;
- }
-
- if (AR_SREV_5416_20_OR_LATER(ah) &&
- (ah->rxchainmask == 5 || ah->txchainmask == 5) && (i != 0))
- regChainOffset = (i == 1) ? 0x2000 : 0x1000;
- else
- regChainOffset = i * 0x1000;
-
- REG_WRITE(ah, AR_PHY_SWITCH_CHAIN_0 + regChainOffset,
- pModal->antCtrlChain[i]);
-
- REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset,
- (REG_READ(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset) &
- ~(AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF |
- AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF)) |
- SM(pModal->iqCalICh[i],
- AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF) |
- SM(pModal->iqCalQCh[i],
- AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF));
-
- if ((i == 0) || AR_SREV_5416_20_OR_LATER(ah))
- ath9k_hw_def_set_gain(ah, pModal, eep, txRxAttenLocal,
- regChainOffset, i);
- }
-
- if (AR_SREV_9280_10_OR_LATER(ah)) {
- if (IS_CHAN_2GHZ(chan)) {
- ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH0,
- AR_AN_RF2G1_CH0_OB,
- AR_AN_RF2G1_CH0_OB_S,
- pModal->ob);
- ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH0,
- AR_AN_RF2G1_CH0_DB,
- AR_AN_RF2G1_CH0_DB_S,
- pModal->db);
- ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH1,
- AR_AN_RF2G1_CH1_OB,
- AR_AN_RF2G1_CH1_OB_S,
- pModal->ob_ch1);
- ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH1,
- AR_AN_RF2G1_CH1_DB,
- AR_AN_RF2G1_CH1_DB_S,
- pModal->db_ch1);
- } else {
- ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH0,
- AR_AN_RF5G1_CH0_OB5,
- AR_AN_RF5G1_CH0_OB5_S,
- pModal->ob);
- ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH0,
- AR_AN_RF5G1_CH0_DB5,
- AR_AN_RF5G1_CH0_DB5_S,
- pModal->db);
- ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH1,
- AR_AN_RF5G1_CH1_OB5,
- AR_AN_RF5G1_CH1_OB5_S,
- pModal->ob_ch1);
- ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH1,
- AR_AN_RF5G1_CH1_DB5,
- AR_AN_RF5G1_CH1_DB5_S,
- pModal->db_ch1);
- }
- ath9k_hw_analog_shift_rmw(ah, AR_AN_TOP2,
- AR_AN_TOP2_XPABIAS_LVL,
- AR_AN_TOP2_XPABIAS_LVL_S,
- pModal->xpaBiasLvl);
- ath9k_hw_analog_shift_rmw(ah, AR_AN_TOP2,
- AR_AN_TOP2_LOCALBIAS,
- AR_AN_TOP2_LOCALBIAS_S,
- pModal->local_bias);
- REG_RMW_FIELD(ah, AR_PHY_XPA_CFG, AR_PHY_FORCE_XPA_CFG,
- pModal->force_xpaon);
- }
-
- REG_RMW_FIELD(ah, AR_PHY_SETTLING, AR_PHY_SETTLING_SWITCH,
- pModal->switchSettling);
- REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, AR_PHY_DESIRED_SZ_ADC,
- pModal->adcDesiredSize);
-
- if (!AR_SREV_9280_10_OR_LATER(ah))
- REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ,
- AR_PHY_DESIRED_SZ_PGA,
- pModal->pgaDesiredSize);
-
- REG_WRITE(ah, AR_PHY_RF_CTL4,
- SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAA_OFF)
- | SM(pModal->txEndToXpaOff,
- AR_PHY_RF_CTL4_TX_END_XPAB_OFF)
- | SM(pModal->txFrameToXpaOn,
- AR_PHY_RF_CTL4_FRAME_XPAA_ON)
- | SM(pModal->txFrameToXpaOn,
- AR_PHY_RF_CTL4_FRAME_XPAB_ON));
-
- REG_RMW_FIELD(ah, AR_PHY_RF_CTL3, AR_PHY_TX_END_TO_A2_RX_ON,
- pModal->txEndToRxOn);
-
- if (AR_SREV_9280_10_OR_LATER(ah)) {
- REG_RMW_FIELD(ah, AR_PHY_CCA, AR9280_PHY_CCA_THRESH62,
- pModal->thresh62);
- REG_RMW_FIELD(ah, AR_PHY_EXT_CCA0,
- AR_PHY_EXT_CCA0_THRESH62,
- pModal->thresh62);
- } else {
- REG_RMW_FIELD(ah, AR_PHY_CCA, AR_PHY_CCA_THRESH62,
- pModal->thresh62);
- REG_RMW_FIELD(ah, AR_PHY_EXT_CCA,
- AR_PHY_EXT_CCA_THRESH62,
- pModal->thresh62);
- }
-
- if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_2) {
- REG_RMW_FIELD(ah, AR_PHY_RF_CTL2,
- AR_PHY_TX_END_DATA_START,
- pModal->txFrameToDataStart);
- REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, AR_PHY_TX_END_PA_ON,
- pModal->txFrameToPaOn);
- }
-
- if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_3) {
- if (IS_CHAN_HT40(chan))
- REG_RMW_FIELD(ah, AR_PHY_SETTLING,
- AR_PHY_SETTLING_SWITCH,
- pModal->swSettleHt40);
- }
-
- if (AR_SREV_9280_20_OR_LATER(ah) &&
- AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_19)
- REG_RMW_FIELD(ah, AR_PHY_CCK_TX_CTRL,
- AR_PHY_CCK_TX_CTRL_TX_DAC_SCALE_CCK,
- pModal->miscBits);
-
-
- if (AR_SREV_9280_20(ah) && AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_20) {
- if (IS_CHAN_2GHZ(chan))
- REG_RMW_FIELD(ah, AR_AN_TOP1, AR_AN_TOP1_DACIPMODE,
- eep->baseEepHeader.dacLpMode);
- else if (eep->baseEepHeader.dacHiPwrMode_5G)
- REG_RMW_FIELD(ah, AR_AN_TOP1, AR_AN_TOP1_DACIPMODE, 0);
- else
- REG_RMW_FIELD(ah, AR_AN_TOP1, AR_AN_TOP1_DACIPMODE,
- eep->baseEepHeader.dacLpMode);
-
- REG_RMW_FIELD(ah, AR_PHY_FRAME_CTL, AR_PHY_FRAME_CTL_TX_CLIP,
- pModal->miscBits >> 2);
-
- REG_RMW_FIELD(ah, AR_PHY_TX_PWRCTRL9,
- AR_PHY_TX_DESIRED_SCALE_CCK,
- eep->baseEepHeader.desiredScaleCCK);
- }
-}
-
-static void ath9k_hw_def_set_addac(struct ath_hw *ah,
- struct ath9k_channel *chan)
-{
-#define XPA_LVL_FREQ(cnt) (pModal->xpaBiasLvlFreq[cnt])
- struct modal_eep_header *pModal;
- struct ar5416_eeprom_def *eep = &ah->eeprom.def;
- u8 biaslevel;
-
- if (ah->hw_version.macVersion != AR_SREV_VERSION_9160)
- return;
-
- if (ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_MINOR_VER_7)
- return;
-
- pModal = &(eep->modalHeader[IS_CHAN_2GHZ(chan)]);
-
- if (pModal->xpaBiasLvl != 0xff) {
- biaslevel = pModal->xpaBiasLvl;
- } else {
- u16 resetFreqBin, freqBin, freqCount = 0;
- struct chan_centers centers;
-
- ath9k_hw_get_channel_centers(ah, chan, &centers);
-
- resetFreqBin = FREQ2FBIN(centers.synth_center,
- IS_CHAN_2GHZ(chan));
- freqBin = XPA_LVL_FREQ(0) & 0xff;
- biaslevel = (u8) (XPA_LVL_FREQ(0) >> 14);
-
- freqCount++;
-
- while (freqCount < 3) {
- if (XPA_LVL_FREQ(freqCount) == 0x0)
- break;
-
- freqBin = XPA_LVL_FREQ(freqCount) & 0xff;
- if (resetFreqBin >= freqBin)
- biaslevel = (u8)(XPA_LVL_FREQ(freqCount) >> 14);
- else
- break;
- freqCount++;
- }
- }
-
- if (IS_CHAN_2GHZ(chan)) {
- INI_RA(&ah->iniAddac, 7, 1) = (INI_RA(&ah->iniAddac,
- 7, 1) & (~0x18)) | biaslevel << 3;
- } else {
- INI_RA(&ah->iniAddac, 6, 1) = (INI_RA(&ah->iniAddac,
- 6, 1) & (~0xc0)) | biaslevel << 6;
- }
-#undef XPA_LVL_FREQ
-}
-
-static void ath9k_hw_get_def_gain_boundaries_pdadcs(struct ath_hw *ah,
- struct ath9k_channel *chan,
- struct cal_data_per_freq *pRawDataSet,
- u8 *bChans, u16 availPiers,
- u16 tPdGainOverlap, int16_t *pMinCalPower,
- u16 *pPdGainBoundaries, u8 *pPDADCValues,
- u16 numXpdGains)
-{
- int i, j, k;
- int16_t ss;
- u16 idxL = 0, idxR = 0, numPiers;
- static u8 vpdTableL[AR5416_NUM_PD_GAINS]
- [AR5416_MAX_PWR_RANGE_IN_HALF_DB];
- static u8 vpdTableR[AR5416_NUM_PD_GAINS]
- [AR5416_MAX_PWR_RANGE_IN_HALF_DB];
- static u8 vpdTableI[AR5416_NUM_PD_GAINS]
- [AR5416_MAX_PWR_RANGE_IN_HALF_DB];
-
- u8 *pVpdL, *pVpdR, *pPwrL, *pPwrR;
- u8 minPwrT4[AR5416_NUM_PD_GAINS];
- u8 maxPwrT4[AR5416_NUM_PD_GAINS];
- int16_t vpdStep;
- int16_t tmpVal;
- u16 sizeCurrVpdTable, maxIndex, tgtIndex;
- bool match;
- int16_t minDelta = 0;
- struct chan_centers centers;
-
- ath9k_hw_get_channel_centers(ah, chan, &centers);
-
- for (numPiers = 0; numPiers < availPiers; numPiers++) {
- if (bChans[numPiers] == AR5416_BCHAN_UNUSED)
- break;
- }
-
- match = ath9k_hw_get_lower_upper_index((u8)FREQ2FBIN(centers.synth_center,
- IS_CHAN_2GHZ(chan)),
- bChans, numPiers, &idxL, &idxR);
-
- if (match) {
- for (i = 0; i < numXpdGains; i++) {
- minPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][0];
- maxPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][4];
- ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
- pRawDataSet[idxL].pwrPdg[i],
- pRawDataSet[idxL].vpdPdg[i],
- AR5416_PD_GAIN_ICEPTS,
- vpdTableI[i]);
- }
- } else {
- for (i = 0; i < numXpdGains; i++) {
- pVpdL = pRawDataSet[idxL].vpdPdg[i];
- pPwrL = pRawDataSet[idxL].pwrPdg[i];
- pVpdR = pRawDataSet[idxR].vpdPdg[i];
- pPwrR = pRawDataSet[idxR].pwrPdg[i];
-
- minPwrT4[i] = max(pPwrL[0], pPwrR[0]);
-
- maxPwrT4[i] =
- min(pPwrL[AR5416_PD_GAIN_ICEPTS - 1],
- pPwrR[AR5416_PD_GAIN_ICEPTS - 1]);
-
-
- ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
- pPwrL, pVpdL,
- AR5416_PD_GAIN_ICEPTS,
- vpdTableL[i]);
- ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
- pPwrR, pVpdR,
- AR5416_PD_GAIN_ICEPTS,
- vpdTableR[i]);
-
- for (j = 0; j <= (maxPwrT4[i] - minPwrT4[i]) / 2; j++) {
- vpdTableI[i][j] =
- (u8)(ath9k_hw_interpolate((u16)
- FREQ2FBIN(centers.
- synth_center,
- IS_CHAN_2GHZ
- (chan)),
- bChans[idxL], bChans[idxR],
- vpdTableL[i][j], vpdTableR[i][j]));
- }
- }
- }
-
- *pMinCalPower = (int16_t)(minPwrT4[0] / 2);
-
- k = 0;
-
- for (i = 0; i < numXpdGains; i++) {
- if (i == (numXpdGains - 1))
- pPdGainBoundaries[i] =
- (u16)(maxPwrT4[i] / 2);
- else
- pPdGainBoundaries[i] =
- (u16)((maxPwrT4[i] + minPwrT4[i + 1]) / 4);
-
- pPdGainBoundaries[i] =
- min((u16)AR5416_MAX_RATE_POWER, pPdGainBoundaries[i]);
-
- if ((i == 0) && !AR_SREV_5416_20_OR_LATER(ah)) {
- minDelta = pPdGainBoundaries[0] - 23;
- pPdGainBoundaries[0] = 23;
- } else {
- minDelta = 0;
- }
-
- if (i == 0) {
- if (AR_SREV_9280_10_OR_LATER(ah))
- ss = (int16_t)(0 - (minPwrT4[i] / 2));
- else
- ss = 0;
- } else {
- ss = (int16_t)((pPdGainBoundaries[i - 1] -
- (minPwrT4[i] / 2)) -
- tPdGainOverlap + 1 + minDelta);
- }
- vpdStep = (int16_t)(vpdTableI[i][1] - vpdTableI[i][0]);
- vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep);
-
- while ((ss < 0) && (k < (AR5416_NUM_PDADC_VALUES - 1))) {
- tmpVal = (int16_t)(vpdTableI[i][0] + ss * vpdStep);
- pPDADCValues[k++] = (u8)((tmpVal < 0) ? 0 : tmpVal);
- ss++;
- }
-
- sizeCurrVpdTable = (u8) ((maxPwrT4[i] - minPwrT4[i]) / 2 + 1);
- tgtIndex = (u8)(pPdGainBoundaries[i] + tPdGainOverlap -
- (minPwrT4[i] / 2));
- maxIndex = (tgtIndex < sizeCurrVpdTable) ?
- tgtIndex : sizeCurrVpdTable;
-
- while ((ss < maxIndex) && (k < (AR5416_NUM_PDADC_VALUES - 1))) {
- pPDADCValues[k++] = vpdTableI[i][ss++];
- }
-
- vpdStep = (int16_t)(vpdTableI[i][sizeCurrVpdTable - 1] -
- vpdTableI[i][sizeCurrVpdTable - 2]);
- vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep);
-
- if (tgtIndex > maxIndex) {
- while ((ss <= tgtIndex) &&
- (k < (AR5416_NUM_PDADC_VALUES - 1))) {
- tmpVal = (int16_t)((vpdTableI[i][sizeCurrVpdTable - 1] +
- (ss - maxIndex + 1) * vpdStep));
- pPDADCValues[k++] = (u8)((tmpVal > 255) ?
- 255 : tmpVal);
- ss++;
- }
- }
- }
-
- while (i < AR5416_PD_GAINS_IN_MASK) {
- pPdGainBoundaries[i] = pPdGainBoundaries[i - 1];
- i++;
- }
-
- while (k < AR5416_NUM_PDADC_VALUES) {
- pPDADCValues[k] = pPDADCValues[k - 1];
- k++;
- }
-
- return;
-}
-
-static void ath9k_hw_set_def_power_cal_table(struct ath_hw *ah,
- struct ath9k_channel *chan,
- int16_t *pTxPowerIndexOffset)
-{
-#define SM_PD_GAIN(x) SM(0x38, AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_##x)
-#define SM_PDGAIN_B(x, y) \
- SM((gainBoundaries[x]), AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_##y)
-
- struct ar5416_eeprom_def *pEepData = &ah->eeprom.def;
- struct cal_data_per_freq *pRawDataset;
- u8 *pCalBChans = NULL;
- u16 pdGainOverlap_t2;
- static u8 pdadcValues[AR5416_NUM_PDADC_VALUES];
- u16 gainBoundaries[AR5416_PD_GAINS_IN_MASK];
- u16 numPiers, i, j;
- int16_t tMinCalPower;
- u16 numXpdGain, xpdMask;
- u16 xpdGainValues[AR5416_NUM_PD_GAINS] = { 0, 0, 0, 0 };
- u32 reg32, regOffset, regChainOffset;
- int16_t modalIdx;
-
- modalIdx = IS_CHAN_2GHZ(chan) ? 1 : 0;
- xpdMask = pEepData->modalHeader[modalIdx].xpdGain;
-
- if ((pEepData->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
- AR5416_EEP_MINOR_VER_2) {
- pdGainOverlap_t2 =
- pEepData->modalHeader[modalIdx].pdGainOverlap;
- } else {
- pdGainOverlap_t2 = (u16)(MS(REG_READ(ah, AR_PHY_TPCRG5),
- AR_PHY_TPCRG5_PD_GAIN_OVERLAP));
- }
-
- if (IS_CHAN_2GHZ(chan)) {
- pCalBChans = pEepData->calFreqPier2G;
- numPiers = AR5416_NUM_2G_CAL_PIERS;
- } else {
- pCalBChans = pEepData->calFreqPier5G;
- numPiers = AR5416_NUM_5G_CAL_PIERS;
- }
-
- if (OLC_FOR_AR9280_20_LATER && IS_CHAN_2GHZ(chan)) {
- pRawDataset = pEepData->calPierData2G[0];
- ah->initPDADC = ((struct calDataPerFreqOpLoop *)
- pRawDataset)->vpdPdg[0][0];
- }
-
- numXpdGain = 0;
-
- for (i = 1; i <= AR5416_PD_GAINS_IN_MASK; i++) {
- if ((xpdMask >> (AR5416_PD_GAINS_IN_MASK - i)) & 1) {
- if (numXpdGain >= AR5416_NUM_PD_GAINS)
- break;
- xpdGainValues[numXpdGain] =
- (u16)(AR5416_PD_GAINS_IN_MASK - i);
- numXpdGain++;
- }
- }
-
- REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_NUM_PD_GAIN,
- (numXpdGain - 1) & 0x3);
- REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_1,
- xpdGainValues[0]);
- REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_2,
- xpdGainValues[1]);
- REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_3,
- xpdGainValues[2]);
-
- for (i = 0; i < AR5416_MAX_CHAINS; i++) {
- if (AR_SREV_5416_20_OR_LATER(ah) &&
- (ah->rxchainmask == 5 || ah->txchainmask == 5) &&
- (i != 0)) {
- regChainOffset = (i == 1) ? 0x2000 : 0x1000;
- } else
- regChainOffset = i * 0x1000;
-
- if (pEepData->baseEepHeader.txMask & (1 << i)) {
- if (IS_CHAN_2GHZ(chan))
- pRawDataset = pEepData->calPierData2G[i];
- else
- pRawDataset = pEepData->calPierData5G[i];
-
-
- if (OLC_FOR_AR9280_20_LATER) {
- u8 pcdacIdx;
- u8 txPower;
-
- ath9k_get_txgain_index(ah, chan,
- (struct calDataPerFreqOpLoop *)pRawDataset,
- pCalBChans, numPiers, &txPower, &pcdacIdx);
- ath9k_olc_get_pdadcs(ah, pcdacIdx,
- txPower/2, pdadcValues);
- } else {
- ath9k_hw_get_def_gain_boundaries_pdadcs(ah,
- chan, pRawDataset,
- pCalBChans, numPiers,
- pdGainOverlap_t2,
- &tMinCalPower,
- gainBoundaries,
- pdadcValues,
- numXpdGain);
- }
-
- if ((i == 0) || AR_SREV_5416_20_OR_LATER(ah)) {
- if (OLC_FOR_AR9280_20_LATER) {
- REG_WRITE(ah,
- AR_PHY_TPCRG5 + regChainOffset,
- SM(0x6,
- AR_PHY_TPCRG5_PD_GAIN_OVERLAP) |
- SM_PD_GAIN(1) | SM_PD_GAIN(2) |
- SM_PD_GAIN(3) | SM_PD_GAIN(4));
- } else {
- REG_WRITE(ah,
- AR_PHY_TPCRG5 + regChainOffset,
- SM(pdGainOverlap_t2,
- AR_PHY_TPCRG5_PD_GAIN_OVERLAP)|
- SM_PDGAIN_B(0, 1) |
- SM_PDGAIN_B(1, 2) |
- SM_PDGAIN_B(2, 3) |
- SM_PDGAIN_B(3, 4));
- }
- }
-
- regOffset = AR_PHY_BASE + (672 << 2) + regChainOffset;
- for (j = 0; j < 32; j++) {
- reg32 = ((pdadcValues[4 * j + 0] & 0xFF) << 0) |
- ((pdadcValues[4 * j + 1] & 0xFF) << 8) |
- ((pdadcValues[4 * j + 2] & 0xFF) << 16)|
- ((pdadcValues[4 * j + 3] & 0xFF) << 24);
- REG_WRITE(ah, regOffset, reg32);
-
- DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
- "PDADC (%d,%4x): %4.4x %8.8x\n",
- i, regChainOffset, regOffset,
- reg32);
- DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
- "PDADC: Chain %d | PDADC %3d "
- "Value %3d | PDADC %3d Value %3d | "
- "PDADC %3d Value %3d | PDADC %3d "
- "Value %3d |\n",
- i, 4 * j, pdadcValues[4 * j],
- 4 * j + 1, pdadcValues[4 * j + 1],
- 4 * j + 2, pdadcValues[4 * j + 2],
- 4 * j + 3,
- pdadcValues[4 * j + 3]);
-
- regOffset += 4;
- }
- }
- }
-
- *pTxPowerIndexOffset = 0;
-#undef SM_PD_GAIN
-#undef SM_PDGAIN_B
-}
-
-static void ath9k_hw_set_def_power_per_rate_table(struct ath_hw *ah,
- struct ath9k_channel *chan,
- int16_t *ratesArray,
- u16 cfgCtl,
- u16 AntennaReduction,
- u16 twiceMaxRegulatoryPower,
- u16 powerLimit)
-{
-#define REDUCE_SCALED_POWER_BY_TWO_CHAIN 6 /* 10*log10(2)*2 */
-#define REDUCE_SCALED_POWER_BY_THREE_CHAIN 10 /* 10*log10(3)*2 */
-
- struct ar5416_eeprom_def *pEepData = &ah->eeprom.def;
- u16 twiceMaxEdgePower = AR5416_MAX_RATE_POWER;
- static const u16 tpScaleReductionTable[5] =
- { 0, 3, 6, 9, AR5416_MAX_RATE_POWER };
-
- int i;
- int16_t twiceLargestAntenna;
- struct cal_ctl_data *rep;
- struct cal_target_power_leg targetPowerOfdm, targetPowerCck = {
- 0, { 0, 0, 0, 0}
- };
- struct cal_target_power_leg targetPowerOfdmExt = {
- 0, { 0, 0, 0, 0} }, targetPowerCckExt = {
- 0, { 0, 0, 0, 0 }
- };
- struct cal_target_power_ht targetPowerHt20, targetPowerHt40 = {
- 0, {0, 0, 0, 0}
- };
- u16 scaledPower = 0, minCtlPower, maxRegAllowedPower;
- u16 ctlModesFor11a[] =
- { CTL_11A, CTL_5GHT20, CTL_11A_EXT, CTL_5GHT40 };
- u16 ctlModesFor11g[] =
- { CTL_11B, CTL_11G, CTL_2GHT20, CTL_11B_EXT, CTL_11G_EXT,
- CTL_2GHT40
- };
- u16 numCtlModes, *pCtlMode, ctlMode, freq;
- struct chan_centers centers;
- int tx_chainmask;
- u16 twiceMinEdgePower;
-
- tx_chainmask = ah->txchainmask;
-
- ath9k_hw_get_channel_centers(ah, chan, &centers);
-
- twiceLargestAntenna = max(
- pEepData->modalHeader
- [IS_CHAN_2GHZ(chan)].antennaGainCh[0],
- pEepData->modalHeader
- [IS_CHAN_2GHZ(chan)].antennaGainCh[1]);
-
- twiceLargestAntenna = max((u8)twiceLargestAntenna,
- pEepData->modalHeader
- [IS_CHAN_2GHZ(chan)].antennaGainCh[2]);
-
- twiceLargestAntenna = (int16_t)min(AntennaReduction -
- twiceLargestAntenna, 0);
-
- maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna;
-
- if (ah->regulatory.tp_scale != ATH9K_TP_SCALE_MAX) {
- maxRegAllowedPower -=
- (tpScaleReductionTable[(ah->regulatory.tp_scale)] * 2);
- }
-
- scaledPower = min(powerLimit, maxRegAllowedPower);
-
- switch (ar5416_get_ntxchains(tx_chainmask)) {
- case 1:
- break;
- case 2:
- scaledPower -= REDUCE_SCALED_POWER_BY_TWO_CHAIN;
- break;
- case 3:
- scaledPower -= REDUCE_SCALED_POWER_BY_THREE_CHAIN;
- break;
- }
-
- scaledPower = max((u16)0, scaledPower);
-
- if (IS_CHAN_2GHZ(chan)) {
- numCtlModes = ARRAY_SIZE(ctlModesFor11g) -
- SUB_NUM_CTL_MODES_AT_2G_40;
- pCtlMode = ctlModesFor11g;
-
- ath9k_hw_get_legacy_target_powers(ah, chan,
- pEepData->calTargetPowerCck,
- AR5416_NUM_2G_CCK_TARGET_POWERS,
- &targetPowerCck, 4, false);
- ath9k_hw_get_legacy_target_powers(ah, chan,
- pEepData->calTargetPower2G,
- AR5416_NUM_2G_20_TARGET_POWERS,
- &targetPowerOfdm, 4, false);
- ath9k_hw_get_target_powers(ah, chan,
- pEepData->calTargetPower2GHT20,
- AR5416_NUM_2G_20_TARGET_POWERS,
- &targetPowerHt20, 8, false);
-
- if (IS_CHAN_HT40(chan)) {
- numCtlModes = ARRAY_SIZE(ctlModesFor11g);
- ath9k_hw_get_target_powers(ah, chan,
- pEepData->calTargetPower2GHT40,
- AR5416_NUM_2G_40_TARGET_POWERS,
- &targetPowerHt40, 8, true);
- ath9k_hw_get_legacy_target_powers(ah, chan,
- pEepData->calTargetPowerCck,
- AR5416_NUM_2G_CCK_TARGET_POWERS,
- &targetPowerCckExt, 4, true);
- ath9k_hw_get_legacy_target_powers(ah, chan,
- pEepData->calTargetPower2G,
- AR5416_NUM_2G_20_TARGET_POWERS,
- &targetPowerOfdmExt, 4, true);
- }
- } else {
- numCtlModes = ARRAY_SIZE(ctlModesFor11a) -
- SUB_NUM_CTL_MODES_AT_5G_40;
- pCtlMode = ctlModesFor11a;
-
- ath9k_hw_get_legacy_target_powers(ah, chan,
- pEepData->calTargetPower5G,
- AR5416_NUM_5G_20_TARGET_POWERS,
- &targetPowerOfdm, 4, false);
- ath9k_hw_get_target_powers(ah, chan,
- pEepData->calTargetPower5GHT20,
- AR5416_NUM_5G_20_TARGET_POWERS,
- &targetPowerHt20, 8, false);
-
- if (IS_CHAN_HT40(chan)) {
- numCtlModes = ARRAY_SIZE(ctlModesFor11a);
- ath9k_hw_get_target_powers(ah, chan,
- pEepData->calTargetPower5GHT40,
- AR5416_NUM_5G_40_TARGET_POWERS,
- &targetPowerHt40, 8, true);
- ath9k_hw_get_legacy_target_powers(ah, chan,
- pEepData->calTargetPower5G,
- AR5416_NUM_5G_20_TARGET_POWERS,
- &targetPowerOfdmExt, 4, true);
- }
- }
-
- for (ctlMode = 0; ctlMode < numCtlModes; ctlMode++) {
- bool isHt40CtlMode = (pCtlMode[ctlMode] == CTL_5GHT40) ||
- (pCtlMode[ctlMode] == CTL_2GHT40);
- if (isHt40CtlMode)
- freq = centers.synth_center;
- else if (pCtlMode[ctlMode] & EXT_ADDITIVE)
- freq = centers.ext_center;
- else
- freq = centers.ctl_center;
-
- if (ah->eep_ops->get_eeprom_ver(ah) == 14 &&
- ah->eep_ops->get_eeprom_rev(ah) <= 2)
- twiceMaxEdgePower = AR5416_MAX_RATE_POWER;
-
- DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
- "LOOP-Mode ctlMode %d < %d, isHt40CtlMode %d, "
- "EXT_ADDITIVE %d\n",
- ctlMode, numCtlModes, isHt40CtlMode,
- (pCtlMode[ctlMode] & EXT_ADDITIVE));
-
- for (i = 0; (i < AR5416_NUM_CTLS) && pEepData->ctlIndex[i]; i++) {
- DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
- " LOOP-Ctlidx %d: cfgCtl 0x%2.2x "
- "pCtlMode 0x%2.2x ctlIndex 0x%2.2x "
- "chan %d\n",
- i, cfgCtl, pCtlMode[ctlMode],
- pEepData->ctlIndex[i], chan->channel);
-
- if ((((cfgCtl & ~CTL_MODE_M) |
- (pCtlMode[ctlMode] & CTL_MODE_M)) ==
- pEepData->ctlIndex[i]) ||
- (((cfgCtl & ~CTL_MODE_M) |
- (pCtlMode[ctlMode] & CTL_MODE_M)) ==
- ((pEepData->ctlIndex[i] & CTL_MODE_M) | SD_NO_CTL))) {
- rep = &(pEepData->ctlData[i]);
-
- twiceMinEdgePower = ath9k_hw_get_max_edge_power(freq,
- rep->ctlEdges[ar5416_get_ntxchains(tx_chainmask) - 1],
- IS_CHAN_2GHZ(chan), AR5416_NUM_BAND_EDGES);
-
- DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
- " MATCH-EE_IDX %d: ch %d is2 %d "
- "2xMinEdge %d chainmask %d chains %d\n",
- i, freq, IS_CHAN_2GHZ(chan),
- twiceMinEdgePower, tx_chainmask,
- ar5416_get_ntxchains
- (tx_chainmask));
- if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL) {
- twiceMaxEdgePower = min(twiceMaxEdgePower,
- twiceMinEdgePower);
- } else {
- twiceMaxEdgePower = twiceMinEdgePower;
- break;
- }
- }
- }
-
- minCtlPower = min(twiceMaxEdgePower, scaledPower);
-
- DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
- " SEL-Min ctlMode %d pCtlMode %d "
- "2xMaxEdge %d sP %d minCtlPwr %d\n",
- ctlMode, pCtlMode[ctlMode], twiceMaxEdgePower,
- scaledPower, minCtlPower);
-
- switch (pCtlMode[ctlMode]) {
- case CTL_11B:
- for (i = 0; i < ARRAY_SIZE(targetPowerCck.tPow2x); i++) {
- targetPowerCck.tPow2x[i] =
- min((u16)targetPowerCck.tPow2x[i],
- minCtlPower);
- }
- break;
- case CTL_11A:
- case CTL_11G:
- for (i = 0; i < ARRAY_SIZE(targetPowerOfdm.tPow2x); i++) {
- targetPowerOfdm.tPow2x[i] =
- min((u16)targetPowerOfdm.tPow2x[i],
- minCtlPower);
- }
- break;
- case CTL_5GHT20:
- case CTL_2GHT20:
- for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); i++) {
- targetPowerHt20.tPow2x[i] =
- min((u16)targetPowerHt20.tPow2x[i],
- minCtlPower);
- }
- break;
- case CTL_11B_EXT:
- targetPowerCckExt.tPow2x[0] = min((u16)
- targetPowerCckExt.tPow2x[0],
- minCtlPower);
- break;
- case CTL_11A_EXT:
- case CTL_11G_EXT:
- targetPowerOfdmExt.tPow2x[0] = min((u16)
- targetPowerOfdmExt.tPow2x[0],
- minCtlPower);
- break;
- case CTL_5GHT40:
- case CTL_2GHT40:
- for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++) {
- targetPowerHt40.tPow2x[i] =
- min((u16)targetPowerHt40.tPow2x[i],
- minCtlPower);
- }
- break;
- default:
- break;
- }
- }
-
- ratesArray[rate6mb] = ratesArray[rate9mb] = ratesArray[rate12mb] =
- ratesArray[rate18mb] = ratesArray[rate24mb] =
- targetPowerOfdm.tPow2x[0];
- ratesArray[rate36mb] = targetPowerOfdm.tPow2x[1];
- ratesArray[rate48mb] = targetPowerOfdm.tPow2x[2];
- ratesArray[rate54mb] = targetPowerOfdm.tPow2x[3];
- ratesArray[rateXr] = targetPowerOfdm.tPow2x[0];
-
- for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); i++)
- ratesArray[rateHt20_0 + i] = targetPowerHt20.tPow2x[i];
-
- if (IS_CHAN_2GHZ(chan)) {
- ratesArray[rate1l] = targetPowerCck.tPow2x[0];
- ratesArray[rate2s] = ratesArray[rate2l] =
- targetPowerCck.tPow2x[1];
- ratesArray[rate5_5s] = ratesArray[rate5_5l] =
- targetPowerCck.tPow2x[2];
- ;
- ratesArray[rate11s] = ratesArray[rate11l] =
- targetPowerCck.tPow2x[3];
- ;
- }
- if (IS_CHAN_HT40(chan)) {
- for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++) {
- ratesArray[rateHt40_0 + i] =
- targetPowerHt40.tPow2x[i];
- }
- ratesArray[rateDupOfdm] = targetPowerHt40.tPow2x[0];
- ratesArray[rateDupCck] = targetPowerHt40.tPow2x[0];
- ratesArray[rateExtOfdm] = targetPowerOfdmExt.tPow2x[0];
- if (IS_CHAN_2GHZ(chan)) {
- ratesArray[rateExtCck] =
- targetPowerCckExt.tPow2x[0];
- }
- }
-}
-
-static void ath9k_hw_def_set_txpower(struct ath_hw *ah,
- struct ath9k_channel *chan,
- u16 cfgCtl,
- u8 twiceAntennaReduction,
- u8 twiceMaxRegulatoryPower,
- u8 powerLimit)
-{
-#define RT_AR_DELTA(x) (ratesArray[x] - cck_ofdm_delta)
- struct ar5416_eeprom_def *pEepData = &ah->eeprom.def;
- struct modal_eep_header *pModal =
- &(pEepData->modalHeader[IS_CHAN_2GHZ(chan)]);
- int16_t ratesArray[Ar5416RateSize];
- int16_t txPowerIndexOffset = 0;
- u8 ht40PowerIncForPdadc = 2;
- int i, cck_ofdm_delta = 0;
-
- memset(ratesArray, 0, sizeof(ratesArray));
-
- if ((pEepData->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
- AR5416_EEP_MINOR_VER_2) {
- ht40PowerIncForPdadc = pModal->ht40PowerIncForPdadc;
- }
-
- ath9k_hw_set_def_power_per_rate_table(ah, chan,
- &ratesArray[0], cfgCtl,
- twiceAntennaReduction,
- twiceMaxRegulatoryPower,
- powerLimit);
-
- ath9k_hw_set_def_power_cal_table(ah, chan, &txPowerIndexOffset);
-
- for (i = 0; i < ARRAY_SIZE(ratesArray); i++) {
- ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]);
- if (ratesArray[i] > AR5416_MAX_RATE_POWER)
- ratesArray[i] = AR5416_MAX_RATE_POWER;
- }
-
- if (AR_SREV_9280_10_OR_LATER(ah)) {
- for (i = 0; i < Ar5416RateSize; i++)
- ratesArray[i] -= AR5416_PWR_TABLE_OFFSET * 2;
- }
-
- REG_WRITE(ah, AR_PHY_POWER_TX_RATE1,
- ATH9K_POW_SM(ratesArray[rate18mb], 24)
- | ATH9K_POW_SM(ratesArray[rate12mb], 16)
- | ATH9K_POW_SM(ratesArray[rate9mb], 8)
- | ATH9K_POW_SM(ratesArray[rate6mb], 0));
- REG_WRITE(ah, AR_PHY_POWER_TX_RATE2,
- ATH9K_POW_SM(ratesArray[rate54mb], 24)
- | ATH9K_POW_SM(ratesArray[rate48mb], 16)
- | ATH9K_POW_SM(ratesArray[rate36mb], 8)
- | ATH9K_POW_SM(ratesArray[rate24mb], 0));
-
- if (IS_CHAN_2GHZ(chan)) {
- if (OLC_FOR_AR9280_20_LATER) {
- cck_ofdm_delta = 2;
- REG_WRITE(ah, AR_PHY_POWER_TX_RATE3,
- ATH9K_POW_SM(RT_AR_DELTA(rate2s), 24)
- | ATH9K_POW_SM(RT_AR_DELTA(rate2l), 16)
- | ATH9K_POW_SM(ratesArray[rateXr], 8)
- | ATH9K_POW_SM(RT_AR_DELTA(rate1l), 0));
- REG_WRITE(ah, AR_PHY_POWER_TX_RATE4,
- ATH9K_POW_SM(RT_AR_DELTA(rate11s), 24)
- | ATH9K_POW_SM(RT_AR_DELTA(rate11l), 16)
- | ATH9K_POW_SM(RT_AR_DELTA(rate5_5s), 8)
- | ATH9K_POW_SM(RT_AR_DELTA(rate5_5l), 0));
- } else {
- REG_WRITE(ah, AR_PHY_POWER_TX_RATE3,
- ATH9K_POW_SM(ratesArray[rate2s], 24)
- | ATH9K_POW_SM(ratesArray[rate2l], 16)
- | ATH9K_POW_SM(ratesArray[rateXr], 8)
- | ATH9K_POW_SM(ratesArray[rate1l], 0));
- REG_WRITE(ah, AR_PHY_POWER_TX_RATE4,
- ATH9K_POW_SM(ratesArray[rate11s], 24)
- | ATH9K_POW_SM(ratesArray[rate11l], 16)
- | ATH9K_POW_SM(ratesArray[rate5_5s], 8)
- | ATH9K_POW_SM(ratesArray[rate5_5l], 0));
- }
- }
-
- REG_WRITE(ah, AR_PHY_POWER_TX_RATE5,
- ATH9K_POW_SM(ratesArray[rateHt20_3], 24)
- | ATH9K_POW_SM(ratesArray[rateHt20_2], 16)
- | ATH9K_POW_SM(ratesArray[rateHt20_1], 8)
- | ATH9K_POW_SM(ratesArray[rateHt20_0], 0));
- REG_WRITE(ah, AR_PHY_POWER_TX_RATE6,
- ATH9K_POW_SM(ratesArray[rateHt20_7], 24)
- | ATH9K_POW_SM(ratesArray[rateHt20_6], 16)
- | ATH9K_POW_SM(ratesArray[rateHt20_5], 8)
- | ATH9K_POW_SM(ratesArray[rateHt20_4], 0));
-
- if (IS_CHAN_HT40(chan)) {
- REG_WRITE(ah, AR_PHY_POWER_TX_RATE7,
- ATH9K_POW_SM(ratesArray[rateHt40_3] +
- ht40PowerIncForPdadc, 24)
- | ATH9K_POW_SM(ratesArray[rateHt40_2] +
- ht40PowerIncForPdadc, 16)
- | ATH9K_POW_SM(ratesArray[rateHt40_1] +
- ht40PowerIncForPdadc, 8)
- | ATH9K_POW_SM(ratesArray[rateHt40_0] +
- ht40PowerIncForPdadc, 0));
- REG_WRITE(ah, AR_PHY_POWER_TX_RATE8,
- ATH9K_POW_SM(ratesArray[rateHt40_7] +
- ht40PowerIncForPdadc, 24)
- | ATH9K_POW_SM(ratesArray[rateHt40_6] +
- ht40PowerIncForPdadc, 16)
- | ATH9K_POW_SM(ratesArray[rateHt40_5] +
- ht40PowerIncForPdadc, 8)
- | ATH9K_POW_SM(ratesArray[rateHt40_4] +
- ht40PowerIncForPdadc, 0));
- if (OLC_FOR_AR9280_20_LATER) {
- REG_WRITE(ah, AR_PHY_POWER_TX_RATE9,
- ATH9K_POW_SM(ratesArray[rateExtOfdm], 24)
- | ATH9K_POW_SM(RT_AR_DELTA(rateExtCck), 16)
- | ATH9K_POW_SM(ratesArray[rateDupOfdm], 8)
- | ATH9K_POW_SM(RT_AR_DELTA(rateDupCck), 0));
- } else {
- REG_WRITE(ah, AR_PHY_POWER_TX_RATE9,
- ATH9K_POW_SM(ratesArray[rateExtOfdm], 24)
- | ATH9K_POW_SM(ratesArray[rateExtCck], 16)
- | ATH9K_POW_SM(ratesArray[rateDupOfdm], 8)
- | ATH9K_POW_SM(ratesArray[rateDupCck], 0));
- }
- }
-
- REG_WRITE(ah, AR_PHY_POWER_TX_SUB,
- ATH9K_POW_SM(pModal->pwrDecreaseFor3Chain, 6)
- | ATH9K_POW_SM(pModal->pwrDecreaseFor2Chain, 0));
-
- i = rate6mb;
-
- if (IS_CHAN_HT40(chan))
- i = rateHt40_0;
- else if (IS_CHAN_HT20(chan))
- i = rateHt20_0;
-
- if (AR_SREV_9280_10_OR_LATER(ah))
- ah->regulatory.max_power_level =
- ratesArray[i] + AR5416_PWR_TABLE_OFFSET * 2;
- else
- ah->regulatory.max_power_level = ratesArray[i];
-
- switch(ar5416_get_ntxchains(ah->txchainmask)) {
- case 1:
- break;
- case 2:
- ah->regulatory.max_power_level += INCREASE_MAXPOW_BY_TWO_CHAIN;
- break;
- case 3:
- ah->regulatory.max_power_level += INCREASE_MAXPOW_BY_THREE_CHAIN;
- break;
- default:
- DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
- "Invalid chainmask configuration\n");
- break;
- }
-}
-
-static u8 ath9k_hw_def_get_num_ant_config(struct ath_hw *ah,
- enum ieee80211_band freq_band)
-{
- struct ar5416_eeprom_def *eep = &ah->eeprom.def;
- struct modal_eep_header *pModal =
- &(eep->modalHeader[ATH9K_HAL_FREQ_BAND_2GHZ == freq_band]);
- struct base_eep_header *pBase = &eep->baseEepHeader;
- u8 num_ant_config;
-
- num_ant_config = 1;
-
- if (pBase->version >= 0x0E0D)
- if (pModal->useAnt1)
- num_ant_config += 1;
-
- return num_ant_config;
-}
-
-static u16 ath9k_hw_def_get_eeprom_antenna_cfg(struct ath_hw *ah,
- struct ath9k_channel *chan)
-{
- struct ar5416_eeprom_def *eep = &ah->eeprom.def;
- struct modal_eep_header *pModal =
- &(eep->modalHeader[IS_CHAN_2GHZ(chan)]);
-
- return pModal->antCtrlCommon & 0xFFFF;
-}
-
-static u16 ath9k_hw_def_get_spur_channel(struct ath_hw *ah, u16 i, bool is2GHz)
-{
-#define EEP_DEF_SPURCHAN \
- (ah->eeprom.def.modalHeader[is2GHz].spurChans[i].spurChan)
-
- u16 spur_val = AR_NO_SPUR;
-
- DPRINTF(ah->ah_sc, ATH_DBG_ANI,
- "Getting spur idx %d is2Ghz. %d val %x\n",
- i, is2GHz, ah->config.spurchans[i][is2GHz]);
-
- switch (ah->config.spurmode) {
- case SPUR_DISABLE:
- break;
- case SPUR_ENABLE_IOCTL:
- spur_val = ah->config.spurchans[i][is2GHz];
- DPRINTF(ah->ah_sc, ATH_DBG_ANI,
- "Getting spur val from new loc. %d\n", spur_val);
- break;
- case SPUR_ENABLE_EEPROM:
- spur_val = EEP_DEF_SPURCHAN;
- break;
- }
-
- return spur_val;
-
-#undef EEP_DEF_SPURCHAN
-}
-
-static struct eeprom_ops eep_def_ops = {
- .check_eeprom = ath9k_hw_def_check_eeprom,
- .get_eeprom = ath9k_hw_def_get_eeprom,
- .fill_eeprom = ath9k_hw_def_fill_eeprom,
- .get_eeprom_ver = ath9k_hw_def_get_eeprom_ver,
- .get_eeprom_rev = ath9k_hw_def_get_eeprom_rev,
- .get_num_ant_config = ath9k_hw_def_get_num_ant_config,
- .get_eeprom_antenna_cfg = ath9k_hw_def_get_eeprom_antenna_cfg,
- .set_board_values = ath9k_hw_def_set_board_values,
- .set_addac = ath9k_hw_def_set_addac,
- .set_txpower = ath9k_hw_def_set_txpower,
- .get_spur_channel = ath9k_hw_def_get_spur_channel
-};
-
-int ath9k_hw_eeprom_attach(struct ath_hw *ah)
+int ath9k_hw_eeprom_init(struct ath_hw *ah)
{
int status;
- if (AR_SREV_9285(ah)) {
+ if (AR_SREV_9287(ah)) {
+ ah->eep_map = EEP_MAP_AR9287;
+ ah->eep_ops = &eep_AR9287_ops;
+ } else if (AR_SREV_9285(ah) || AR_SREV_9271(ah)) {
ah->eep_map = EEP_MAP_4KBITS;
ah->eep_ops = &eep_4k_ops;
} else {
diff --git a/drivers/net/wireless/ath/ath9k/eeprom.h b/drivers/net/wireless/ath/ath9k/eeprom.h
index 67b8bd12941..4fe33f7eee9 100644
--- a/drivers/net/wireless/ath/ath9k/eeprom.h
+++ b/drivers/net/wireless/ath/ath9k/eeprom.h
@@ -100,6 +100,8 @@
#define AR5416_VER_MASK (eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK)
#define OLC_FOR_AR9280_20_LATER (AR_SREV_9280_20_OR_LATER(ah) && \
ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL))
+#define OLC_FOR_AR9287_10_LATER (AR_SREV_9287_10_OR_LATER(ah) && \
+ ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL))
#define AR_EEPROM_RFSILENT_GPIO_SEL 0x001c
#define AR_EEPROM_RFSILENT_GPIO_SEL_S 2
@@ -176,6 +178,57 @@
#define AR9280_TX_GAIN_TABLE_SIZE 22
+#define AR9287_EEP_VER 0xE
+#define AR9287_EEP_VER_MINOR_MASK 0xFFF
+#define AR9287_EEP_MINOR_VER_1 0x1
+#define AR9287_EEP_MINOR_VER_2 0x2
+#define AR9287_EEP_MINOR_VER_3 0x3
+#define AR9287_EEP_MINOR_VER AR9287_EEP_MINOR_VER_3
+#define AR9287_EEP_MINOR_VER_b AR9287_EEP_MINOR_VER
+#define AR9287_EEP_NO_BACK_VER AR9287_EEP_MINOR_VER_1
+
+#define AR9287_EEP_START_LOC 128
+#define AR9287_NUM_2G_CAL_PIERS 3
+#define AR9287_NUM_2G_CCK_TARGET_POWERS 3
+#define AR9287_NUM_2G_20_TARGET_POWERS 3
+#define AR9287_NUM_2G_40_TARGET_POWERS 3
+#define AR9287_NUM_CTLS 12
+#define AR9287_NUM_BAND_EDGES 4
+#define AR9287_NUM_PD_GAINS 4
+#define AR9287_PD_GAINS_IN_MASK 4
+#define AR9287_PD_GAIN_ICEPTS 1
+#define AR9287_EEPROM_MODAL_SPURS 5
+#define AR9287_MAX_RATE_POWER 63
+#define AR9287_NUM_PDADC_VALUES 128
+#define AR9287_NUM_RATES 16
+#define AR9287_BCHAN_UNUSED 0xFF
+#define AR9287_MAX_PWR_RANGE_IN_HALF_DB 64
+#define AR9287_OPFLAGS_11A 0x01
+#define AR9287_OPFLAGS_11G 0x02
+#define AR9287_OPFLAGS_2G_HT40 0x08
+#define AR9287_OPFLAGS_2G_HT20 0x20
+#define AR9287_OPFLAGS_5G_HT40 0x04
+#define AR9287_OPFLAGS_5G_HT20 0x10
+#define AR9287_EEPMISC_BIG_ENDIAN 0x01
+#define AR9287_EEPMISC_WOW 0x02
+#define AR9287_MAX_CHAINS 2
+#define AR9287_ANT_16S 32
+#define AR9287_custdatasize 20
+
+#define AR9287_NUM_ANT_CHAIN_FIELDS 6
+#define AR9287_NUM_ANT_COMMON_FIELDS 4
+#define AR9287_SIZE_ANT_CHAIN_FIELD 2
+#define AR9287_SIZE_ANT_COMMON_FIELD 4
+#define AR9287_ANT_CHAIN_MASK 0x3
+#define AR9287_ANT_COMMON_MASK 0xf
+#define AR9287_CHAIN_0_IDX 0
+#define AR9287_CHAIN_1_IDX 1
+#define AR9287_DATA_SZ 32
+
+#define AR9287_PWR_TABLE_OFFSET_DB -5
+
+#define AR9287_CHECKSUM_LOCATION (AR9287_EEP_START_LOC + 1)
+
enum eeprom_param {
EEP_NFTHRESH_5,
EEP_NFTHRESH_2,
@@ -199,7 +252,11 @@ enum eeprom_param {
EEP_OL_PWRCTRL,
EEP_RC_CHAIN_MASK,
EEP_DAC_HPWR_5G,
- EEP_FRAC_N_5G
+ EEP_FRAC_N_5G,
+ EEP_DEV_TYPE,
+ EEP_TEMPSENSE_SLOPE,
+ EEP_TEMPSENSE_SLOPE_PAL_ON,
+ EEP_PWR_TABLE_OFFSET
};
enum ar5416_rates {
@@ -328,46 +385,123 @@ struct calDataPerFreqOpLoop {
} __packed;
struct modal_eep_4k_header {
- u32 antCtrlChain[AR5416_EEP4K_MAX_CHAINS];
- u32 antCtrlCommon;
- u8 antennaGainCh[AR5416_EEP4K_MAX_CHAINS];
- u8 switchSettling;
- u8 txRxAttenCh[AR5416_EEP4K_MAX_CHAINS];
- u8 rxTxMarginCh[AR5416_EEP4K_MAX_CHAINS];
- u8 adcDesiredSize;
- u8 pgaDesiredSize;
- u8 xlnaGainCh[AR5416_EEP4K_MAX_CHAINS];
- u8 txEndToXpaOff;
- u8 txEndToRxOn;
- u8 txFrameToXpaOn;
- u8 thresh62;
- u8 noiseFloorThreshCh[AR5416_EEP4K_MAX_CHAINS];
- u8 xpdGain;
- u8 xpd;
- u8 iqCalICh[AR5416_EEP4K_MAX_CHAINS];
- u8 iqCalQCh[AR5416_EEP4K_MAX_CHAINS];
- u8 pdGainOverlap;
- u8 ob_01;
- u8 db1_01;
- u8 xpaBiasLvl;
- u8 txFrameToDataStart;
- u8 txFrameToPaOn;
- u8 ht40PowerIncForPdadc;
- u8 bswAtten[AR5416_EEP4K_MAX_CHAINS];
- u8 bswMargin[AR5416_EEP4K_MAX_CHAINS];
- u8 swSettleHt40;
- u8 xatten2Db[AR5416_EEP4K_MAX_CHAINS];
- u8 xatten2Margin[AR5416_EEP4K_MAX_CHAINS];
- u8 db2_01;
- u8 version;
- u16 ob_234;
- u16 db1_234;
- u16 db2_234;
- u8 futureModal[4];
-
+ u32 antCtrlChain[AR5416_EEP4K_MAX_CHAINS];
+ u32 antCtrlCommon;
+ u8 antennaGainCh[AR5416_EEP4K_MAX_CHAINS];
+ u8 switchSettling;
+ u8 txRxAttenCh[AR5416_EEP4K_MAX_CHAINS];
+ u8 rxTxMarginCh[AR5416_EEP4K_MAX_CHAINS];
+ u8 adcDesiredSize;
+ u8 pgaDesiredSize;
+ u8 xlnaGainCh[AR5416_EEP4K_MAX_CHAINS];
+ u8 txEndToXpaOff;
+ u8 txEndToRxOn;
+ u8 txFrameToXpaOn;
+ u8 thresh62;
+ u8 noiseFloorThreshCh[AR5416_EEP4K_MAX_CHAINS];
+ u8 xpdGain;
+ u8 xpd;
+ u8 iqCalICh[AR5416_EEP4K_MAX_CHAINS];
+ u8 iqCalQCh[AR5416_EEP4K_MAX_CHAINS];
+ u8 pdGainOverlap;
+#ifdef __BIG_ENDIAN_BITFIELD
+ u8 ob_1:4, ob_0:4;
+ u8 db1_1:4, db1_0:4;
+#else
+ u8 ob_0:4, ob_1:4;
+ u8 db1_0:4, db1_1:4;
+#endif
+ u8 xpaBiasLvl;
+ u8 txFrameToDataStart;
+ u8 txFrameToPaOn;
+ u8 ht40PowerIncForPdadc;
+ u8 bswAtten[AR5416_EEP4K_MAX_CHAINS];
+ u8 bswMargin[AR5416_EEP4K_MAX_CHAINS];
+ u8 swSettleHt40;
+ u8 xatten2Db[AR5416_EEP4K_MAX_CHAINS];
+ u8 xatten2Margin[AR5416_EEP4K_MAX_CHAINS];
+#ifdef __BIG_ENDIAN_BITFIELD
+ u8 db2_1:4, db2_0:4;
+#else
+ u8 db2_0:4, db2_1:4;
+#endif
+ u8 version;
+#ifdef __BIG_ENDIAN_BITFIELD
+ u8 ob_3:4, ob_2:4;
+ u8 antdiv_ctl1:4, ob_4:4;
+ u8 db1_3:4, db1_2:4;
+ u8 antdiv_ctl2:4, db1_4:4;
+ u8 db2_2:4, db2_3:4;
+ u8 reserved:4, db2_4:4;
+#else
+ u8 ob_2:4, ob_3:4;
+ u8 ob_4:4, antdiv_ctl1:4;
+ u8 db1_2:4, db1_3:4;
+ u8 db1_4:4, antdiv_ctl2:4;
+ u8 db2_2:4, db2_3:4;
+ u8 db2_4:4, reserved:4;
+#endif
+ u8 futureModal[4];
struct spur_chan spurChans[AR5416_EEPROM_MODAL_SPURS];
} __packed;
+struct base_eep_ar9287_header {
+ u16 length;
+ u16 checksum;
+ u16 version;
+ u8 opCapFlags;
+ u8 eepMisc;
+ u16 regDmn[2];
+ u8 macAddr[6];
+ u8 rxMask;
+ u8 txMask;
+ u16 rfSilent;
+ u16 blueToothOptions;
+ u16 deviceCap;
+ u32 binBuildNumber;
+ u8 deviceType;
+ u8 openLoopPwrCntl;
+ int8_t pwrTableOffset;
+ int8_t tempSensSlope;
+ int8_t tempSensSlopePalOn;
+ u8 futureBase[29];
+} __packed;
+
+struct modal_eep_ar9287_header {
+ u32 antCtrlChain[AR9287_MAX_CHAINS];
+ u32 antCtrlCommon;
+ int8_t antennaGainCh[AR9287_MAX_CHAINS];
+ u8 switchSettling;
+ u8 txRxAttenCh[AR9287_MAX_CHAINS];
+ u8 rxTxMarginCh[AR9287_MAX_CHAINS];
+ int8_t adcDesiredSize;
+ u8 txEndToXpaOff;
+ u8 txEndToRxOn;
+ u8 txFrameToXpaOn;
+ u8 thresh62;
+ int8_t noiseFloorThreshCh[AR9287_MAX_CHAINS];
+ u8 xpdGain;
+ u8 xpd;
+ int8_t iqCalICh[AR9287_MAX_CHAINS];
+ int8_t iqCalQCh[AR9287_MAX_CHAINS];
+ u8 pdGainOverlap;
+ u8 xpaBiasLvl;
+ u8 txFrameToDataStart;
+ u8 txFrameToPaOn;
+ u8 ht40PowerIncForPdadc;
+ u8 bswAtten[AR9287_MAX_CHAINS];
+ u8 bswMargin[AR9287_MAX_CHAINS];
+ u8 swSettleHt40;
+ u8 version;
+ u8 db1;
+ u8 db2;
+ u8 ob_cck;
+ u8 ob_psk;
+ u8 ob_qam;
+ u8 ob_pal_off;
+ u8 futureModal[30];
+ struct spur_chan spurChans[AR9287_EEPROM_MODAL_SPURS];
+} __packed;
struct cal_data_per_freq {
u8 pwrPdg[AR5416_NUM_PD_GAINS][AR5416_PD_GAIN_ICEPTS];
@@ -402,6 +536,28 @@ struct cal_ctl_edges {
} __packed;
#endif
+struct cal_data_op_loop_ar9287 {
+ u8 pwrPdg[2][5];
+ u8 vpdPdg[2][5];
+ u8 pcdac[2][5];
+ u8 empty[2][5];
+} __packed;
+
+struct cal_data_per_freq_ar9287 {
+ u8 pwrPdg[AR9287_NUM_PD_GAINS][AR9287_PD_GAIN_ICEPTS];
+ u8 vpdPdg[AR9287_NUM_PD_GAINS][AR9287_PD_GAIN_ICEPTS];
+} __packed;
+
+union cal_data_per_freq_ar9287_u {
+ struct cal_data_op_loop_ar9287 calDataOpen;
+ struct cal_data_per_freq_ar9287 calDataClose;
+} __packed;
+
+struct cal_ctl_data_ar9287 {
+ struct cal_ctl_edges
+ ctlEdges[AR9287_MAX_CHAINS][AR9287_NUM_BAND_EDGES];
+} __packed;
+
struct cal_ctl_data {
struct cal_ctl_edges
ctlEdges[AR5416_MAX_CHAINS][AR5416_NUM_BAND_EDGES];
@@ -461,6 +617,26 @@ struct ar5416_eeprom_4k {
u8 padding;
} __packed;
+struct ar9287_eeprom {
+ struct base_eep_ar9287_header baseEepHeader;
+ u8 custData[AR9287_DATA_SZ];
+ struct modal_eep_ar9287_header modalHeader;
+ u8 calFreqPier2G[AR9287_NUM_2G_CAL_PIERS];
+ union cal_data_per_freq_ar9287_u
+ calPierData2G[AR9287_MAX_CHAINS][AR9287_NUM_2G_CAL_PIERS];
+ struct cal_target_power_leg
+ calTargetPowerCck[AR9287_NUM_2G_CCK_TARGET_POWERS];
+ struct cal_target_power_leg
+ calTargetPower2G[AR9287_NUM_2G_20_TARGET_POWERS];
+ struct cal_target_power_ht
+ calTargetPower2GHT20[AR9287_NUM_2G_20_TARGET_POWERS];
+ struct cal_target_power_ht
+ calTargetPower2GHT40[AR9287_NUM_2G_40_TARGET_POWERS];
+ u8 ctlIndex[AR9287_NUM_CTLS];
+ struct cal_ctl_data_ar9287 ctlData[AR9287_NUM_CTLS];
+ u8 padding;
+} __packed;
+
enum reg_ext_bitmap {
REG_EXT_JAPAN_MIDBAND = 1,
REG_EXT_FCC_DFS_HT40 = 2,
@@ -480,6 +656,7 @@ struct ath9k_country_entry {
enum ath9k_eep_map {
EEP_MAP_DEFAULT = 0x0,
EEP_MAP_4KBITS,
+ EEP_MAP_AR9287,
EEP_MAP_MAX
};
@@ -500,10 +677,39 @@ struct eeprom_ops {
u16 (*get_spur_channel)(struct ath_hw *ah, u16 i, bool is2GHz);
};
+void ath9k_hw_analog_shift_rmw(struct ath_hw *ah, u32 reg, u32 mask,
+ u32 shift, u32 val);
+int16_t ath9k_hw_interpolate(u16 target, u16 srcLeft, u16 srcRight,
+ int16_t targetLeft,
+ int16_t targetRight);
+bool ath9k_hw_get_lower_upper_index(u8 target, u8 *pList, u16 listSize,
+ u16 *indexL, u16 *indexR);
+bool ath9k_hw_nvram_read(struct ath_hw *ah, u32 off, u16 *data);
+void ath9k_hw_fill_vpd_table(u8 pwrMin, u8 pwrMax, u8 *pPwrList,
+ u8 *pVpdList, u16 numIntercepts,
+ u8 *pRetVpdList);
+void ath9k_hw_get_legacy_target_powers(struct ath_hw *ah,
+ struct ath9k_channel *chan,
+ struct cal_target_power_leg *powInfo,
+ u16 numChannels,
+ struct cal_target_power_leg *pNewPower,
+ u16 numRates, bool isExtTarget);
+void ath9k_hw_get_target_powers(struct ath_hw *ah,
+ struct ath9k_channel *chan,
+ struct cal_target_power_ht *powInfo,
+ u16 numChannels,
+ struct cal_target_power_ht *pNewPower,
+ u16 numRates, bool isHt40Target);
+u16 ath9k_hw_get_max_edge_power(u16 freq, struct cal_ctl_edges *pRdEdgesPower,
+ bool is2GHz, int num_band_edges);
+int ath9k_hw_eeprom_init(struct ath_hw *ah);
+
#define ar5416_get_ntxchains(_txchainmask) \
(((_txchainmask >> 2) & 1) + \
((_txchainmask >> 1) & 1) + (_txchainmask & 1))
-int ath9k_hw_eeprom_attach(struct ath_hw *ah);
+extern const struct eeprom_ops eep_def_ops;
+extern const struct eeprom_ops eep_4k_ops;
+extern const struct eeprom_ops eep_AR9287_ops;
#endif /* EEPROM_H */
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_4k.c b/drivers/net/wireless/ath/ath9k/eeprom_4k.c
new file mode 100644
index 00000000000..d34dd23e806
--- /dev/null
+++ b/drivers/net/wireless/ath/ath9k/eeprom_4k.c
@@ -0,0 +1,1186 @@
+/*
+ * Copyright (c) 2008-2009 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "ath9k.h"
+
+static int ath9k_hw_4k_get_eeprom_ver(struct ath_hw *ah)
+{
+ return ((ah->eeprom.map4k.baseEepHeader.version >> 12) & 0xF);
+}
+
+static int ath9k_hw_4k_get_eeprom_rev(struct ath_hw *ah)
+{
+ return ((ah->eeprom.map4k.baseEepHeader.version) & 0xFFF);
+}
+
+static bool ath9k_hw_4k_fill_eeprom(struct ath_hw *ah)
+{
+#define SIZE_EEPROM_4K (sizeof(struct ar5416_eeprom_4k) / sizeof(u16))
+ u16 *eep_data = (u16 *)&ah->eeprom.map4k;
+ int addr, eep_start_loc = 0;
+
+ eep_start_loc = 64;
+
+ if (!ath9k_hw_use_flash(ah)) {
+ DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
+ "Reading from EEPROM, not flash\n");
+ }
+
+ for (addr = 0; addr < SIZE_EEPROM_4K; addr++) {
+ if (!ath9k_hw_nvram_read(ah, addr + eep_start_loc, eep_data)) {
+ DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
+ "Unable to read eeprom region \n");
+ return false;
+ }
+ eep_data++;
+ }
+
+ return true;
+#undef SIZE_EEPROM_4K
+}
+
+static int ath9k_hw_4k_check_eeprom(struct ath_hw *ah)
+{
+#define EEPROM_4K_SIZE (sizeof(struct ar5416_eeprom_4k) / sizeof(u16))
+ struct ar5416_eeprom_4k *eep =
+ (struct ar5416_eeprom_4k *) &ah->eeprom.map4k;
+ u16 *eepdata, temp, magic, magic2;
+ u32 sum = 0, el;
+ bool need_swap = false;
+ int i, addr;
+
+
+ if (!ath9k_hw_use_flash(ah)) {
+ if (!ath9k_hw_nvram_read(ah, AR5416_EEPROM_MAGIC_OFFSET,
+ &magic)) {
+ DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
+ "Reading Magic # failed\n");
+ return false;
+ }
+
+ DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
+ "Read Magic = 0x%04X\n", magic);
+
+ if (magic != AR5416_EEPROM_MAGIC) {
+ magic2 = swab16(magic);
+
+ if (magic2 == AR5416_EEPROM_MAGIC) {
+ need_swap = true;
+ eepdata = (u16 *) (&ah->eeprom);
+
+ for (addr = 0; addr < EEPROM_4K_SIZE; addr++) {
+ temp = swab16(*eepdata);
+ *eepdata = temp;
+ eepdata++;
+ }
+ } else {
+ DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
+ "Invalid EEPROM Magic. "
+ "endianness mismatch.\n");
+ return -EINVAL;
+ }
+ }
+ }
+
+ DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, "need_swap = %s.\n",
+ need_swap ? "True" : "False");
+
+ if (need_swap)
+ el = swab16(ah->eeprom.map4k.baseEepHeader.length);
+ else
+ el = ah->eeprom.map4k.baseEepHeader.length;
+
+ if (el > sizeof(struct ar5416_eeprom_4k))
+ el = sizeof(struct ar5416_eeprom_4k) / sizeof(u16);
+ else
+ el = el / sizeof(u16);
+
+ eepdata = (u16 *)(&ah->eeprom);
+
+ for (i = 0; i < el; i++)
+ sum ^= *eepdata++;
+
+ if (need_swap) {
+ u32 integer;
+ u16 word;
+
+ DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
+ "EEPROM Endianness is not native.. Changing\n");
+
+ word = swab16(eep->baseEepHeader.length);
+ eep->baseEepHeader.length = word;
+
+ word = swab16(eep->baseEepHeader.checksum);
+ eep->baseEepHeader.checksum = word;
+
+ word = swab16(eep->baseEepHeader.version);
+ eep->baseEepHeader.version = word;
+
+ word = swab16(eep->baseEepHeader.regDmn[0]);
+ eep->baseEepHeader.regDmn[0] = word;
+
+ word = swab16(eep->baseEepHeader.regDmn[1]);
+ eep->baseEepHeader.regDmn[1] = word;
+
+ word = swab16(eep->baseEepHeader.rfSilent);
+ eep->baseEepHeader.rfSilent = word;
+
+ word = swab16(eep->baseEepHeader.blueToothOptions);
+ eep->baseEepHeader.blueToothOptions = word;
+
+ word = swab16(eep->baseEepHeader.deviceCap);
+ eep->baseEepHeader.deviceCap = word;
+
+ integer = swab32(eep->modalHeader.antCtrlCommon);
+ eep->modalHeader.antCtrlCommon = integer;
+
+ for (i = 0; i < AR5416_EEP4K_MAX_CHAINS; i++) {
+ integer = swab32(eep->modalHeader.antCtrlChain[i]);
+ eep->modalHeader.antCtrlChain[i] = integer;
+ }
+
+ for (i = 0; i < AR5416_EEPROM_MODAL_SPURS; i++) {
+ word = swab16(eep->modalHeader.spurChans[i].spurChan);
+ eep->modalHeader.spurChans[i].spurChan = word;
+ }
+ }
+
+ if (sum != 0xffff || ah->eep_ops->get_eeprom_ver(ah) != AR5416_EEP_VER ||
+ ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_NO_BACK_VER) {
+ DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
+ "Bad EEPROM checksum 0x%x or revision 0x%04x\n",
+ sum, ah->eep_ops->get_eeprom_ver(ah));
+ return -EINVAL;
+ }
+
+ return 0;
+#undef EEPROM_4K_SIZE
+}
+
+static u32 ath9k_hw_4k_get_eeprom(struct ath_hw *ah,
+ enum eeprom_param param)
+{
+ struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k;
+ struct modal_eep_4k_header *pModal = &eep->modalHeader;
+ struct base_eep_header_4k *pBase = &eep->baseEepHeader;
+
+ switch (param) {
+ case EEP_NFTHRESH_2:
+ return pModal->noiseFloorThreshCh[0];
+ case AR_EEPROM_MAC(0):
+ return pBase->macAddr[0] << 8 | pBase->macAddr[1];
+ case AR_EEPROM_MAC(1):
+ return pBase->macAddr[2] << 8 | pBase->macAddr[3];
+ case AR_EEPROM_MAC(2):
+ return pBase->macAddr[4] << 8 | pBase->macAddr[5];
+ case EEP_REG_0:
+ return pBase->regDmn[0];
+ case EEP_REG_1:
+ return pBase->regDmn[1];
+ case EEP_OP_CAP:
+ return pBase->deviceCap;
+ case EEP_OP_MODE:
+ return pBase->opCapFlags;
+ case EEP_RF_SILENT:
+ return pBase->rfSilent;
+ case EEP_OB_2:
+ return pModal->ob_0;
+ case EEP_DB_2:
+ return pModal->db1_1;
+ case EEP_MINOR_REV:
+ return pBase->version & AR5416_EEP_VER_MINOR_MASK;
+ case EEP_TX_MASK:
+ return pBase->txMask;
+ case EEP_RX_MASK:
+ return pBase->rxMask;
+ case EEP_FRAC_N_5G:
+ return 0;
+ default:
+ return 0;
+ }
+}
+
+static void ath9k_hw_get_4k_gain_boundaries_pdadcs(struct ath_hw *ah,
+ struct ath9k_channel *chan,
+ struct cal_data_per_freq_4k *pRawDataSet,
+ u8 *bChans, u16 availPiers,
+ u16 tPdGainOverlap, int16_t *pMinCalPower,
+ u16 *pPdGainBoundaries, u8 *pPDADCValues,
+ u16 numXpdGains)
+{
+#define TMP_VAL_VPD_TABLE \
+ ((vpdTableI[i][sizeCurrVpdTable - 1] + (ss - maxIndex + 1) * vpdStep));
+ int i, j, k;
+ int16_t ss;
+ u16 idxL = 0, idxR = 0, numPiers;
+ static u8 vpdTableL[AR5416_EEP4K_NUM_PD_GAINS]
+ [AR5416_MAX_PWR_RANGE_IN_HALF_DB];
+ static u8 vpdTableR[AR5416_EEP4K_NUM_PD_GAINS]
+ [AR5416_MAX_PWR_RANGE_IN_HALF_DB];
+ static u8 vpdTableI[AR5416_EEP4K_NUM_PD_GAINS]
+ [AR5416_MAX_PWR_RANGE_IN_HALF_DB];
+
+ u8 *pVpdL, *pVpdR, *pPwrL, *pPwrR;
+ u8 minPwrT4[AR5416_EEP4K_NUM_PD_GAINS];
+ u8 maxPwrT4[AR5416_EEP4K_NUM_PD_GAINS];
+ int16_t vpdStep;
+ int16_t tmpVal;
+ u16 sizeCurrVpdTable, maxIndex, tgtIndex;
+ bool match;
+ int16_t minDelta = 0;
+ struct chan_centers centers;
+#define PD_GAIN_BOUNDARY_DEFAULT 58;
+
+ ath9k_hw_get_channel_centers(ah, chan, &centers);
+
+ for (numPiers = 0; numPiers < availPiers; numPiers++) {
+ if (bChans[numPiers] == AR5416_BCHAN_UNUSED)
+ break;
+ }
+
+ match = ath9k_hw_get_lower_upper_index(
+ (u8)FREQ2FBIN(centers.synth_center,
+ IS_CHAN_2GHZ(chan)), bChans, numPiers,
+ &idxL, &idxR);
+
+ if (match) {
+ for (i = 0; i < numXpdGains; i++) {
+ minPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][0];
+ maxPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][4];
+ ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
+ pRawDataSet[idxL].pwrPdg[i],
+ pRawDataSet[idxL].vpdPdg[i],
+ AR5416_EEP4K_PD_GAIN_ICEPTS,
+ vpdTableI[i]);
+ }
+ } else {
+ for (i = 0; i < numXpdGains; i++) {
+ pVpdL = pRawDataSet[idxL].vpdPdg[i];
+ pPwrL = pRawDataSet[idxL].pwrPdg[i];
+ pVpdR = pRawDataSet[idxR].vpdPdg[i];
+ pPwrR = pRawDataSet[idxR].pwrPdg[i];
+
+ minPwrT4[i] = max(pPwrL[0], pPwrR[0]);
+
+ maxPwrT4[i] =
+ min(pPwrL[AR5416_EEP4K_PD_GAIN_ICEPTS - 1],
+ pPwrR[AR5416_EEP4K_PD_GAIN_ICEPTS - 1]);
+
+
+ ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
+ pPwrL, pVpdL,
+ AR5416_EEP4K_PD_GAIN_ICEPTS,
+ vpdTableL[i]);
+ ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
+ pPwrR, pVpdR,
+ AR5416_EEP4K_PD_GAIN_ICEPTS,
+ vpdTableR[i]);
+
+ for (j = 0; j <= (maxPwrT4[i] - minPwrT4[i]) / 2; j++) {
+ vpdTableI[i][j] =
+ (u8)(ath9k_hw_interpolate((u16)
+ FREQ2FBIN(centers.
+ synth_center,
+ IS_CHAN_2GHZ
+ (chan)),
+ bChans[idxL], bChans[idxR],
+ vpdTableL[i][j], vpdTableR[i][j]));
+ }
+ }
+ }
+
+ *pMinCalPower = (int16_t)(minPwrT4[0] / 2);
+
+ k = 0;
+
+ for (i = 0; i < numXpdGains; i++) {
+ if (i == (numXpdGains - 1))
+ pPdGainBoundaries[i] =
+ (u16)(maxPwrT4[i] / 2);
+ else
+ pPdGainBoundaries[i] =
+ (u16)((maxPwrT4[i] + minPwrT4[i + 1]) / 4);
+
+ pPdGainBoundaries[i] =
+ min((u16)AR5416_MAX_RATE_POWER, pPdGainBoundaries[i]);
+
+ if ((i == 0) && !AR_SREV_5416_20_OR_LATER(ah)) {
+ minDelta = pPdGainBoundaries[0] - 23;
+ pPdGainBoundaries[0] = 23;
+ } else {
+ minDelta = 0;
+ }
+
+ if (i == 0) {
+ if (AR_SREV_9280_10_OR_LATER(ah))
+ ss = (int16_t)(0 - (minPwrT4[i] / 2));
+ else
+ ss = 0;
+ } else {
+ ss = (int16_t)((pPdGainBoundaries[i - 1] -
+ (minPwrT4[i] / 2)) -
+ tPdGainOverlap + 1 + minDelta);
+ }
+ vpdStep = (int16_t)(vpdTableI[i][1] - vpdTableI[i][0]);
+ vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep);
+
+ while ((ss < 0) && (k < (AR5416_NUM_PDADC_VALUES - 1))) {
+ tmpVal = (int16_t)(vpdTableI[i][0] + ss * vpdStep);
+ pPDADCValues[k++] = (u8)((tmpVal < 0) ? 0 : tmpVal);
+ ss++;
+ }
+
+ sizeCurrVpdTable = (u8) ((maxPwrT4[i] - minPwrT4[i]) / 2 + 1);
+ tgtIndex = (u8)(pPdGainBoundaries[i] + tPdGainOverlap -
+ (minPwrT4[i] / 2));
+ maxIndex = (tgtIndex < sizeCurrVpdTable) ?
+ tgtIndex : sizeCurrVpdTable;
+
+ while ((ss < maxIndex) && (k < (AR5416_NUM_PDADC_VALUES - 1)))
+ pPDADCValues[k++] = vpdTableI[i][ss++];
+
+ vpdStep = (int16_t)(vpdTableI[i][sizeCurrVpdTable - 1] -
+ vpdTableI[i][sizeCurrVpdTable - 2]);
+ vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep);
+
+ if (tgtIndex >= maxIndex) {
+ while ((ss <= tgtIndex) &&
+ (k < (AR5416_NUM_PDADC_VALUES - 1))) {
+ tmpVal = (int16_t) TMP_VAL_VPD_TABLE;
+ pPDADCValues[k++] = (u8)((tmpVal > 255) ?
+ 255 : tmpVal);
+ ss++;
+ }
+ }
+ }
+
+ while (i < AR5416_EEP4K_PD_GAINS_IN_MASK) {
+ pPdGainBoundaries[i] = PD_GAIN_BOUNDARY_DEFAULT;
+ i++;
+ }
+
+ while (k < AR5416_NUM_PDADC_VALUES) {
+ pPDADCValues[k] = pPDADCValues[k - 1];
+ k++;
+ }
+
+ return;
+#undef TMP_VAL_VPD_TABLE
+}
+
+static void ath9k_hw_set_4k_power_cal_table(struct ath_hw *ah,
+ struct ath9k_channel *chan,
+ int16_t *pTxPowerIndexOffset)
+{
+ struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k;
+ struct cal_data_per_freq_4k *pRawDataset;
+ u8 *pCalBChans = NULL;
+ u16 pdGainOverlap_t2;
+ static u8 pdadcValues[AR5416_NUM_PDADC_VALUES];
+ u16 gainBoundaries[AR5416_EEP4K_PD_GAINS_IN_MASK];
+ u16 numPiers, i, j;
+ int16_t tMinCalPower;
+ u16 numXpdGain, xpdMask;
+ u16 xpdGainValues[AR5416_EEP4K_NUM_PD_GAINS] = { 0, 0 };
+ u32 reg32, regOffset, regChainOffset;
+
+ xpdMask = pEepData->modalHeader.xpdGain;
+
+ if ((pEepData->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
+ AR5416_EEP_MINOR_VER_2) {
+ pdGainOverlap_t2 =
+ pEepData->modalHeader.pdGainOverlap;
+ } else {
+ pdGainOverlap_t2 = (u16)(MS(REG_READ(ah, AR_PHY_TPCRG5),
+ AR_PHY_TPCRG5_PD_GAIN_OVERLAP));
+ }
+
+ pCalBChans = pEepData->calFreqPier2G;
+ numPiers = AR5416_EEP4K_NUM_2G_CAL_PIERS;
+
+ numXpdGain = 0;
+
+ for (i = 1; i <= AR5416_EEP4K_PD_GAINS_IN_MASK; i++) {
+ if ((xpdMask >> (AR5416_EEP4K_PD_GAINS_IN_MASK - i)) & 1) {
+ if (numXpdGain >= AR5416_EEP4K_NUM_PD_GAINS)
+ break;
+ xpdGainValues[numXpdGain] =
+ (u16)(AR5416_EEP4K_PD_GAINS_IN_MASK - i);
+ numXpdGain++;
+ }
+ }
+
+ REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_NUM_PD_GAIN,
+ (numXpdGain - 1) & 0x3);
+ REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_1,
+ xpdGainValues[0]);
+ REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_2,
+ xpdGainValues[1]);
+ REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_3, 0);
+
+ for (i = 0; i < AR5416_EEP4K_MAX_CHAINS; i++) {
+ if (AR_SREV_5416_20_OR_LATER(ah) &&
+ (ah->rxchainmask == 5 || ah->txchainmask == 5) &&
+ (i != 0)) {
+ regChainOffset = (i == 1) ? 0x2000 : 0x1000;
+ } else
+ regChainOffset = i * 0x1000;
+
+ if (pEepData->baseEepHeader.txMask & (1 << i)) {
+ pRawDataset = pEepData->calPierData2G[i];
+
+ ath9k_hw_get_4k_gain_boundaries_pdadcs(ah, chan,
+ pRawDataset, pCalBChans,
+ numPiers, pdGainOverlap_t2,
+ &tMinCalPower, gainBoundaries,
+ pdadcValues, numXpdGain);
+
+ if ((i == 0) || AR_SREV_5416_20_OR_LATER(ah)) {
+ REG_WRITE(ah, AR_PHY_TPCRG5 + regChainOffset,
+ SM(pdGainOverlap_t2,
+ AR_PHY_TPCRG5_PD_GAIN_OVERLAP)
+ | SM(gainBoundaries[0],
+ AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1)
+ | SM(gainBoundaries[1],
+ AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2)
+ | SM(gainBoundaries[2],
+ AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3)
+ | SM(gainBoundaries[3],
+ AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4));
+ }
+
+ regOffset = AR_PHY_BASE + (672 << 2) + regChainOffset;
+ for (j = 0; j < 32; j++) {
+ reg32 = ((pdadcValues[4 * j + 0] & 0xFF) << 0) |
+ ((pdadcValues[4 * j + 1] & 0xFF) << 8) |
+ ((pdadcValues[4 * j + 2] & 0xFF) << 16)|
+ ((pdadcValues[4 * j + 3] & 0xFF) << 24);
+ REG_WRITE(ah, regOffset, reg32);
+
+ DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
+ "PDADC (%d,%4x): %4.4x %8.8x\n",
+ i, regChainOffset, regOffset,
+ reg32);
+ DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
+ "PDADC: Chain %d | "
+ "PDADC %3d Value %3d | "
+ "PDADC %3d Value %3d | "
+ "PDADC %3d Value %3d | "
+ "PDADC %3d Value %3d |\n",
+ i, 4 * j, pdadcValues[4 * j],
+ 4 * j + 1, pdadcValues[4 * j + 1],
+ 4 * j + 2, pdadcValues[4 * j + 2],
+ 4 * j + 3,
+ pdadcValues[4 * j + 3]);
+
+ regOffset += 4;
+ }
+ }
+ }
+
+ *pTxPowerIndexOffset = 0;
+}
+
+static void ath9k_hw_set_4k_power_per_rate_table(struct ath_hw *ah,
+ struct ath9k_channel *chan,
+ int16_t *ratesArray,
+ u16 cfgCtl,
+ u16 AntennaReduction,
+ u16 twiceMaxRegulatoryPower,
+ u16 powerLimit)
+{
+#define CMP_TEST_GRP \
+ (((cfgCtl & ~CTL_MODE_M)| (pCtlMode[ctlMode] & CTL_MODE_M)) == \
+ pEepData->ctlIndex[i]) \
+ || (((cfgCtl & ~CTL_MODE_M) | (pCtlMode[ctlMode] & CTL_MODE_M)) == \
+ ((pEepData->ctlIndex[i] & CTL_MODE_M) | SD_NO_CTL))
+
+ int i;
+ int16_t twiceLargestAntenna;
+ u16 twiceMinEdgePower;
+ u16 twiceMaxEdgePower = AR5416_MAX_RATE_POWER;
+ u16 scaledPower = 0, minCtlPower, maxRegAllowedPower;
+ u16 numCtlModes, *pCtlMode, ctlMode, freq;
+ struct chan_centers centers;
+ struct cal_ctl_data_4k *rep;
+ struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k;
+ static const u16 tpScaleReductionTable[5] =
+ { 0, 3, 6, 9, AR5416_MAX_RATE_POWER };
+ struct cal_target_power_leg targetPowerOfdm, targetPowerCck = {
+ 0, { 0, 0, 0, 0}
+ };
+ struct cal_target_power_leg targetPowerOfdmExt = {
+ 0, { 0, 0, 0, 0} }, targetPowerCckExt = {
+ 0, { 0, 0, 0, 0 }
+ };
+ struct cal_target_power_ht targetPowerHt20, targetPowerHt40 = {
+ 0, {0, 0, 0, 0}
+ };
+ u16 ctlModesFor11g[] =
+ { CTL_11B, CTL_11G, CTL_2GHT20, CTL_11B_EXT, CTL_11G_EXT,
+ CTL_2GHT40
+ };
+
+ ath9k_hw_get_channel_centers(ah, chan, &centers);
+
+ twiceLargestAntenna = pEepData->modalHeader.antennaGainCh[0];
+ twiceLargestAntenna = (int16_t)min(AntennaReduction -
+ twiceLargestAntenna, 0);
+
+ maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna;
+ if (ah->regulatory.tp_scale != ATH9K_TP_SCALE_MAX) {
+ maxRegAllowedPower -=
+ (tpScaleReductionTable[(ah->regulatory.tp_scale)] * 2);
+ }
+
+ scaledPower = min(powerLimit, maxRegAllowedPower);
+ scaledPower = max((u16)0, scaledPower);
+
+ numCtlModes = ARRAY_SIZE(ctlModesFor11g) - SUB_NUM_CTL_MODES_AT_2G_40;
+ pCtlMode = ctlModesFor11g;
+
+ ath9k_hw_get_legacy_target_powers(ah, chan,
+ pEepData->calTargetPowerCck,
+ AR5416_NUM_2G_CCK_TARGET_POWERS,
+ &targetPowerCck, 4, false);
+ ath9k_hw_get_legacy_target_powers(ah, chan,
+ pEepData->calTargetPower2G,
+ AR5416_NUM_2G_20_TARGET_POWERS,
+ &targetPowerOfdm, 4, false);
+ ath9k_hw_get_target_powers(ah, chan,
+ pEepData->calTargetPower2GHT20,
+ AR5416_NUM_2G_20_TARGET_POWERS,
+ &targetPowerHt20, 8, false);
+
+ if (IS_CHAN_HT40(chan)) {
+ numCtlModes = ARRAY_SIZE(ctlModesFor11g);
+ ath9k_hw_get_target_powers(ah, chan,
+ pEepData->calTargetPower2GHT40,
+ AR5416_NUM_2G_40_TARGET_POWERS,
+ &targetPowerHt40, 8, true);
+ ath9k_hw_get_legacy_target_powers(ah, chan,
+ pEepData->calTargetPowerCck,
+ AR5416_NUM_2G_CCK_TARGET_POWERS,
+ &targetPowerCckExt, 4, true);
+ ath9k_hw_get_legacy_target_powers(ah, chan,
+ pEepData->calTargetPower2G,
+ AR5416_NUM_2G_20_TARGET_POWERS,
+ &targetPowerOfdmExt, 4, true);
+ }
+
+ for (ctlMode = 0; ctlMode < numCtlModes; ctlMode++) {
+ bool isHt40CtlMode = (pCtlMode[ctlMode] == CTL_5GHT40) ||
+ (pCtlMode[ctlMode] == CTL_2GHT40);
+
+ if (isHt40CtlMode)
+ freq = centers.synth_center;
+ else if (pCtlMode[ctlMode] & EXT_ADDITIVE)
+ freq = centers.ext_center;
+ else
+ freq = centers.ctl_center;
+
+ if (ah->eep_ops->get_eeprom_ver(ah) == 14 &&
+ ah->eep_ops->get_eeprom_rev(ah) <= 2)
+ twiceMaxEdgePower = AR5416_MAX_RATE_POWER;
+
+ for (i = 0; (i < AR5416_EEP4K_NUM_CTLS) &&
+ pEepData->ctlIndex[i]; i++) {
+
+ if (CMP_TEST_GRP) {
+ rep = &(pEepData->ctlData[i]);
+
+ twiceMinEdgePower = ath9k_hw_get_max_edge_power(
+ freq,
+ rep->ctlEdges[
+ ar5416_get_ntxchains(ah->txchainmask) - 1],
+ IS_CHAN_2GHZ(chan),
+ AR5416_EEP4K_NUM_BAND_EDGES);
+
+ if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL) {
+ twiceMaxEdgePower =
+ min(twiceMaxEdgePower,
+ twiceMinEdgePower);
+ } else {
+ twiceMaxEdgePower = twiceMinEdgePower;
+ break;
+ }
+ }
+ }
+
+ minCtlPower = (u8)min(twiceMaxEdgePower, scaledPower);
+
+ switch (pCtlMode[ctlMode]) {
+ case CTL_11B:
+ for (i = 0; i < ARRAY_SIZE(targetPowerCck.tPow2x); i++) {
+ targetPowerCck.tPow2x[i] =
+ min((u16)targetPowerCck.tPow2x[i],
+ minCtlPower);
+ }
+ break;
+ case CTL_11G:
+ for (i = 0; i < ARRAY_SIZE(targetPowerOfdm.tPow2x); i++) {
+ targetPowerOfdm.tPow2x[i] =
+ min((u16)targetPowerOfdm.tPow2x[i],
+ minCtlPower);
+ }
+ break;
+ case CTL_2GHT20:
+ for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); i++) {
+ targetPowerHt20.tPow2x[i] =
+ min((u16)targetPowerHt20.tPow2x[i],
+ minCtlPower);
+ }
+ break;
+ case CTL_11B_EXT:
+ targetPowerCckExt.tPow2x[0] =
+ min((u16)targetPowerCckExt.tPow2x[0],
+ minCtlPower);
+ break;
+ case CTL_11G_EXT:
+ targetPowerOfdmExt.tPow2x[0] =
+ min((u16)targetPowerOfdmExt.tPow2x[0],
+ minCtlPower);
+ break;
+ case CTL_2GHT40:
+ for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++) {
+ targetPowerHt40.tPow2x[i] =
+ min((u16)targetPowerHt40.tPow2x[i],
+ minCtlPower);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ ratesArray[rate6mb] =
+ ratesArray[rate9mb] =
+ ratesArray[rate12mb] =
+ ratesArray[rate18mb] =
+ ratesArray[rate24mb] =
+ targetPowerOfdm.tPow2x[0];
+
+ ratesArray[rate36mb] = targetPowerOfdm.tPow2x[1];
+ ratesArray[rate48mb] = targetPowerOfdm.tPow2x[2];
+ ratesArray[rate54mb] = targetPowerOfdm.tPow2x[3];
+ ratesArray[rateXr] = targetPowerOfdm.tPow2x[0];
+
+ for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); i++)
+ ratesArray[rateHt20_0 + i] = targetPowerHt20.tPow2x[i];
+
+ ratesArray[rate1l] = targetPowerCck.tPow2x[0];
+ ratesArray[rate2s] = ratesArray[rate2l] = targetPowerCck.tPow2x[1];
+ ratesArray[rate5_5s] = ratesArray[rate5_5l] = targetPowerCck.tPow2x[2];
+ ratesArray[rate11s] = ratesArray[rate11l] = targetPowerCck.tPow2x[3];
+
+ if (IS_CHAN_HT40(chan)) {
+ for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++) {
+ ratesArray[rateHt40_0 + i] =
+ targetPowerHt40.tPow2x[i];
+ }
+ ratesArray[rateDupOfdm] = targetPowerHt40.tPow2x[0];
+ ratesArray[rateDupCck] = targetPowerHt40.tPow2x[0];
+ ratesArray[rateExtOfdm] = targetPowerOfdmExt.tPow2x[0];
+ ratesArray[rateExtCck] = targetPowerCckExt.tPow2x[0];
+ }
+
+#undef CMP_TEST_GRP
+}
+
+static void ath9k_hw_4k_set_txpower(struct ath_hw *ah,
+ struct ath9k_channel *chan,
+ u16 cfgCtl,
+ u8 twiceAntennaReduction,
+ u8 twiceMaxRegulatoryPower,
+ u8 powerLimit)
+{
+ struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k;
+ struct modal_eep_4k_header *pModal = &pEepData->modalHeader;
+ int16_t ratesArray[Ar5416RateSize];
+ int16_t txPowerIndexOffset = 0;
+ u8 ht40PowerIncForPdadc = 2;
+ int i;
+
+ memset(ratesArray, 0, sizeof(ratesArray));
+
+ if ((pEepData->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
+ AR5416_EEP_MINOR_VER_2) {
+ ht40PowerIncForPdadc = pModal->ht40PowerIncForPdadc;
+ }
+
+ ath9k_hw_set_4k_power_per_rate_table(ah, chan,
+ &ratesArray[0], cfgCtl,
+ twiceAntennaReduction,
+ twiceMaxRegulatoryPower,
+ powerLimit);
+
+ ath9k_hw_set_4k_power_cal_table(ah, chan, &txPowerIndexOffset);
+
+ for (i = 0; i < ARRAY_SIZE(ratesArray); i++) {
+ ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]);
+ if (ratesArray[i] > AR5416_MAX_RATE_POWER)
+ ratesArray[i] = AR5416_MAX_RATE_POWER;
+ }
+
+
+ /* Update regulatory */
+
+ i = rate6mb;
+ if (IS_CHAN_HT40(chan))
+ i = rateHt40_0;
+ else if (IS_CHAN_HT20(chan))
+ i = rateHt20_0;
+
+ ah->regulatory.max_power_level = ratesArray[i];
+
+ if (AR_SREV_9280_10_OR_LATER(ah)) {
+ for (i = 0; i < Ar5416RateSize; i++)
+ ratesArray[i] -= AR5416_PWR_TABLE_OFFSET * 2;
+ }
+
+ /* OFDM power per rate */
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE1,
+ ATH9K_POW_SM(ratesArray[rate18mb], 24)
+ | ATH9K_POW_SM(ratesArray[rate12mb], 16)
+ | ATH9K_POW_SM(ratesArray[rate9mb], 8)
+ | ATH9K_POW_SM(ratesArray[rate6mb], 0));
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE2,
+ ATH9K_POW_SM(ratesArray[rate54mb], 24)
+ | ATH9K_POW_SM(ratesArray[rate48mb], 16)
+ | ATH9K_POW_SM(ratesArray[rate36mb], 8)
+ | ATH9K_POW_SM(ratesArray[rate24mb], 0));
+
+ /* CCK power per rate */
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE3,
+ ATH9K_POW_SM(ratesArray[rate2s], 24)
+ | ATH9K_POW_SM(ratesArray[rate2l], 16)
+ | ATH9K_POW_SM(ratesArray[rateXr], 8)
+ | ATH9K_POW_SM(ratesArray[rate1l], 0));
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE4,
+ ATH9K_POW_SM(ratesArray[rate11s], 24)
+ | ATH9K_POW_SM(ratesArray[rate11l], 16)
+ | ATH9K_POW_SM(ratesArray[rate5_5s], 8)
+ | ATH9K_POW_SM(ratesArray[rate5_5l], 0));
+
+ /* HT20 power per rate */
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE5,
+ ATH9K_POW_SM(ratesArray[rateHt20_3], 24)
+ | ATH9K_POW_SM(ratesArray[rateHt20_2], 16)
+ | ATH9K_POW_SM(ratesArray[rateHt20_1], 8)
+ | ATH9K_POW_SM(ratesArray[rateHt20_0], 0));
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE6,
+ ATH9K_POW_SM(ratesArray[rateHt20_7], 24)
+ | ATH9K_POW_SM(ratesArray[rateHt20_6], 16)
+ | ATH9K_POW_SM(ratesArray[rateHt20_5], 8)
+ | ATH9K_POW_SM(ratesArray[rateHt20_4], 0));
+
+ /* HT40 power per rate */
+ if (IS_CHAN_HT40(chan)) {
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE7,
+ ATH9K_POW_SM(ratesArray[rateHt40_3] +
+ ht40PowerIncForPdadc, 24)
+ | ATH9K_POW_SM(ratesArray[rateHt40_2] +
+ ht40PowerIncForPdadc, 16)
+ | ATH9K_POW_SM(ratesArray[rateHt40_1] +
+ ht40PowerIncForPdadc, 8)
+ | ATH9K_POW_SM(ratesArray[rateHt40_0] +
+ ht40PowerIncForPdadc, 0));
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE8,
+ ATH9K_POW_SM(ratesArray[rateHt40_7] +
+ ht40PowerIncForPdadc, 24)
+ | ATH9K_POW_SM(ratesArray[rateHt40_6] +
+ ht40PowerIncForPdadc, 16)
+ | ATH9K_POW_SM(ratesArray[rateHt40_5] +
+ ht40PowerIncForPdadc, 8)
+ | ATH9K_POW_SM(ratesArray[rateHt40_4] +
+ ht40PowerIncForPdadc, 0));
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE9,
+ ATH9K_POW_SM(ratesArray[rateExtOfdm], 24)
+ | ATH9K_POW_SM(ratesArray[rateExtCck], 16)
+ | ATH9K_POW_SM(ratesArray[rateDupOfdm], 8)
+ | ATH9K_POW_SM(ratesArray[rateDupCck], 0));
+ }
+}
+
+static void ath9k_hw_4k_set_addac(struct ath_hw *ah,
+ struct ath9k_channel *chan)
+{
+ struct modal_eep_4k_header *pModal;
+ struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k;
+ u8 biaslevel;
+
+ if (ah->hw_version.macVersion != AR_SREV_VERSION_9160)
+ return;
+
+ if (ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_MINOR_VER_7)
+ return;
+
+ pModal = &eep->modalHeader;
+
+ if (pModal->xpaBiasLvl != 0xff) {
+ biaslevel = pModal->xpaBiasLvl;
+ INI_RA(&ah->iniAddac, 7, 1) =
+ (INI_RA(&ah->iniAddac, 7, 1) & (~0x18)) | biaslevel << 3;
+ }
+}
+
+static void ath9k_hw_4k_set_gain(struct ath_hw *ah,
+ struct modal_eep_4k_header *pModal,
+ struct ar5416_eeprom_4k *eep,
+ u8 txRxAttenLocal)
+{
+ REG_WRITE(ah, AR_PHY_SWITCH_CHAIN_0,
+ pModal->antCtrlChain[0]);
+
+ REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0),
+ (REG_READ(ah, AR_PHY_TIMING_CTRL4(0)) &
+ ~(AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF |
+ AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF)) |
+ SM(pModal->iqCalICh[0], AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF) |
+ SM(pModal->iqCalQCh[0], AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF));
+
+ if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
+ AR5416_EEP_MINOR_VER_3) {
+ txRxAttenLocal = pModal->txRxAttenCh[0];
+
+ REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ,
+ AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN, pModal->bswMargin[0]);
+ REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ,
+ AR_PHY_GAIN_2GHZ_XATTEN1_DB, pModal->bswAtten[0]);
+ REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ,
+ AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN,
+ pModal->xatten2Margin[0]);
+ REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ,
+ AR_PHY_GAIN_2GHZ_XATTEN2_DB, pModal->xatten2Db[0]);
+
+ /* Set the block 1 value to block 0 value */
+ REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + 0x1000,
+ AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN,
+ pModal->bswMargin[0]);
+ REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + 0x1000,
+ AR_PHY_GAIN_2GHZ_XATTEN1_DB, pModal->bswAtten[0]);
+ REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + 0x1000,
+ AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN,
+ pModal->xatten2Margin[0]);
+ REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + 0x1000,
+ AR_PHY_GAIN_2GHZ_XATTEN2_DB,
+ pModal->xatten2Db[0]);
+ }
+
+ REG_RMW_FIELD(ah, AR_PHY_RXGAIN,
+ AR9280_PHY_RXGAIN_TXRX_ATTEN, txRxAttenLocal);
+ REG_RMW_FIELD(ah, AR_PHY_RXGAIN,
+ AR9280_PHY_RXGAIN_TXRX_MARGIN, pModal->rxTxMarginCh[0]);
+
+ REG_RMW_FIELD(ah, AR_PHY_RXGAIN + 0x1000,
+ AR9280_PHY_RXGAIN_TXRX_ATTEN, txRxAttenLocal);
+ REG_RMW_FIELD(ah, AR_PHY_RXGAIN + 0x1000,
+ AR9280_PHY_RXGAIN_TXRX_MARGIN, pModal->rxTxMarginCh[0]);
+
+ if (AR_SREV_9285_11(ah))
+ REG_WRITE(ah, AR9285_AN_TOP4, (AR9285_AN_TOP4_DEFAULT | 0x14));
+}
+
+/*
+ * Read EEPROM header info and program the device for correct operation
+ * given the channel value.
+ */
+static void ath9k_hw_4k_set_board_values(struct ath_hw *ah,
+ struct ath9k_channel *chan)
+{
+ struct modal_eep_4k_header *pModal;
+ struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k;
+ u8 txRxAttenLocal;
+ u8 ob[5], db1[5], db2[5];
+ u8 ant_div_control1, ant_div_control2;
+ u32 regVal;
+
+ pModal = &eep->modalHeader;
+ txRxAttenLocal = 23;
+
+ REG_WRITE(ah, AR_PHY_SWITCH_COM,
+ ah->eep_ops->get_eeprom_antenna_cfg(ah, chan));
+
+ /* Single chain for 4K EEPROM*/
+ ath9k_hw_4k_set_gain(ah, pModal, eep, txRxAttenLocal);
+
+ /* Initialize Ant Diversity settings from EEPROM */
+ if (pModal->version >= 3) {
+ ant_div_control1 = pModal->antdiv_ctl1;
+ ant_div_control2 = pModal->antdiv_ctl2;
+
+ regVal = REG_READ(ah, AR_PHY_MULTICHAIN_GAIN_CTL);
+ regVal &= (~(AR_PHY_9285_ANT_DIV_CTL_ALL));
+
+ regVal |= SM(ant_div_control1,
+ AR_PHY_9285_ANT_DIV_CTL);
+ regVal |= SM(ant_div_control2,
+ AR_PHY_9285_ANT_DIV_ALT_LNACONF);
+ regVal |= SM((ant_div_control2 >> 2),
+ AR_PHY_9285_ANT_DIV_MAIN_LNACONF);
+ regVal |= SM((ant_div_control1 >> 1),
+ AR_PHY_9285_ANT_DIV_ALT_GAINTB);
+ regVal |= SM((ant_div_control1 >> 2),
+ AR_PHY_9285_ANT_DIV_MAIN_GAINTB);
+
+
+ REG_WRITE(ah, AR_PHY_MULTICHAIN_GAIN_CTL, regVal);
+ regVal = REG_READ(ah, AR_PHY_MULTICHAIN_GAIN_CTL);
+ regVal = REG_READ(ah, AR_PHY_CCK_DETECT);
+ regVal &= (~AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV);
+ regVal |= SM((ant_div_control1 >> 3),
+ AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV);
+
+ REG_WRITE(ah, AR_PHY_CCK_DETECT, regVal);
+ regVal = REG_READ(ah, AR_PHY_CCK_DETECT);
+ }
+
+ if (pModal->version >= 2) {
+ ob[0] = pModal->ob_0;
+ ob[1] = pModal->ob_1;
+ ob[2] = pModal->ob_2;
+ ob[3] = pModal->ob_3;
+ ob[4] = pModal->ob_4;
+
+ db1[0] = pModal->db1_0;
+ db1[1] = pModal->db1_1;
+ db1[2] = pModal->db1_2;
+ db1[3] = pModal->db1_3;
+ db1[4] = pModal->db1_4;
+
+ db2[0] = pModal->db2_0;
+ db2[1] = pModal->db2_1;
+ db2[2] = pModal->db2_2;
+ db2[3] = pModal->db2_3;
+ db2[4] = pModal->db2_4;
+ } else if (pModal->version == 1) {
+ ob[0] = pModal->ob_0;
+ ob[1] = ob[2] = ob[3] = ob[4] = pModal->ob_1;
+ db1[0] = pModal->db1_0;
+ db1[1] = db1[2] = db1[3] = db1[4] = pModal->db1_1;
+ db2[0] = pModal->db2_0;
+ db2[1] = db2[2] = db2[3] = db2[4] = pModal->db2_1;
+ } else {
+ int i;
+
+ for (i = 0; i < 5; i++) {
+ ob[i] = pModal->ob_0;
+ db1[i] = pModal->db1_0;
+ db2[i] = pModal->db1_0;
+ }
+ }
+
+ if (AR_SREV_9271(ah)) {
+ ath9k_hw_analog_shift_rmw(ah,
+ AR9285_AN_RF2G3,
+ AR9271_AN_RF2G3_OB_cck,
+ AR9271_AN_RF2G3_OB_cck_S,
+ ob[0]);
+ ath9k_hw_analog_shift_rmw(ah,
+ AR9285_AN_RF2G3,
+ AR9271_AN_RF2G3_OB_psk,
+ AR9271_AN_RF2G3_OB_psk_S,
+ ob[1]);
+ ath9k_hw_analog_shift_rmw(ah,
+ AR9285_AN_RF2G3,
+ AR9271_AN_RF2G3_OB_qam,
+ AR9271_AN_RF2G3_OB_qam_S,
+ ob[2]);
+ ath9k_hw_analog_shift_rmw(ah,
+ AR9285_AN_RF2G3,
+ AR9271_AN_RF2G3_DB_1,
+ AR9271_AN_RF2G3_DB_1_S,
+ db1[0]);
+ ath9k_hw_analog_shift_rmw(ah,
+ AR9285_AN_RF2G4,
+ AR9271_AN_RF2G4_DB_2,
+ AR9271_AN_RF2G4_DB_2_S,
+ db2[0]);
+ } else {
+ ath9k_hw_analog_shift_rmw(ah,
+ AR9285_AN_RF2G3,
+ AR9285_AN_RF2G3_OB_0,
+ AR9285_AN_RF2G3_OB_0_S,
+ ob[0]);
+ ath9k_hw_analog_shift_rmw(ah,
+ AR9285_AN_RF2G3,
+ AR9285_AN_RF2G3_OB_1,
+ AR9285_AN_RF2G3_OB_1_S,
+ ob[1]);
+ ath9k_hw_analog_shift_rmw(ah,
+ AR9285_AN_RF2G3,
+ AR9285_AN_RF2G3_OB_2,
+ AR9285_AN_RF2G3_OB_2_S,
+ ob[2]);
+ ath9k_hw_analog_shift_rmw(ah,
+ AR9285_AN_RF2G3,
+ AR9285_AN_RF2G3_OB_3,
+ AR9285_AN_RF2G3_OB_3_S,
+ ob[3]);
+ ath9k_hw_analog_shift_rmw(ah,
+ AR9285_AN_RF2G3,
+ AR9285_AN_RF2G3_OB_4,
+ AR9285_AN_RF2G3_OB_4_S,
+ ob[4]);
+
+ ath9k_hw_analog_shift_rmw(ah,
+ AR9285_AN_RF2G3,
+ AR9285_AN_RF2G3_DB1_0,
+ AR9285_AN_RF2G3_DB1_0_S,
+ db1[0]);
+ ath9k_hw_analog_shift_rmw(ah,
+ AR9285_AN_RF2G3,
+ AR9285_AN_RF2G3_DB1_1,
+ AR9285_AN_RF2G3_DB1_1_S,
+ db1[1]);
+ ath9k_hw_analog_shift_rmw(ah,
+ AR9285_AN_RF2G3,
+ AR9285_AN_RF2G3_DB1_2,
+ AR9285_AN_RF2G3_DB1_2_S,
+ db1[2]);
+ ath9k_hw_analog_shift_rmw(ah,
+ AR9285_AN_RF2G4,
+ AR9285_AN_RF2G4_DB1_3,
+ AR9285_AN_RF2G4_DB1_3_S,
+ db1[3]);
+ ath9k_hw_analog_shift_rmw(ah,
+ AR9285_AN_RF2G4,
+ AR9285_AN_RF2G4_DB1_4,
+ AR9285_AN_RF2G4_DB1_4_S, db1[4]);
+
+ ath9k_hw_analog_shift_rmw(ah,
+ AR9285_AN_RF2G4,
+ AR9285_AN_RF2G4_DB2_0,
+ AR9285_AN_RF2G4_DB2_0_S,
+ db2[0]);
+ ath9k_hw_analog_shift_rmw(ah,
+ AR9285_AN_RF2G4,
+ AR9285_AN_RF2G4_DB2_1,
+ AR9285_AN_RF2G4_DB2_1_S,
+ db2[1]);
+ ath9k_hw_analog_shift_rmw(ah,
+ AR9285_AN_RF2G4,
+ AR9285_AN_RF2G4_DB2_2,
+ AR9285_AN_RF2G4_DB2_2_S,
+ db2[2]);
+ ath9k_hw_analog_shift_rmw(ah,
+ AR9285_AN_RF2G4,
+ AR9285_AN_RF2G4_DB2_3,
+ AR9285_AN_RF2G4_DB2_3_S,
+ db2[3]);
+ ath9k_hw_analog_shift_rmw(ah,
+ AR9285_AN_RF2G4,
+ AR9285_AN_RF2G4_DB2_4,
+ AR9285_AN_RF2G4_DB2_4_S,
+ db2[4]);
+ }
+
+
+ if (AR_SREV_9285_11(ah))
+ REG_WRITE(ah, AR9285_AN_TOP4, AR9285_AN_TOP4_DEFAULT);
+
+ REG_RMW_FIELD(ah, AR_PHY_SETTLING, AR_PHY_SETTLING_SWITCH,
+ pModal->switchSettling);
+ REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, AR_PHY_DESIRED_SZ_ADC,
+ pModal->adcDesiredSize);
+
+ REG_WRITE(ah, AR_PHY_RF_CTL4,
+ SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAA_OFF) |
+ SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAB_OFF) |
+ SM(pModal->txFrameToXpaOn, AR_PHY_RF_CTL4_FRAME_XPAA_ON) |
+ SM(pModal->txFrameToXpaOn, AR_PHY_RF_CTL4_FRAME_XPAB_ON));
+
+ REG_RMW_FIELD(ah, AR_PHY_RF_CTL3, AR_PHY_TX_END_TO_A2_RX_ON,
+ pModal->txEndToRxOn);
+ REG_RMW_FIELD(ah, AR_PHY_CCA, AR9280_PHY_CCA_THRESH62,
+ pModal->thresh62);
+ REG_RMW_FIELD(ah, AR_PHY_EXT_CCA0, AR_PHY_EXT_CCA0_THRESH62,
+ pModal->thresh62);
+
+ if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
+ AR5416_EEP_MINOR_VER_2) {
+ REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, AR_PHY_TX_END_DATA_START,
+ pModal->txFrameToDataStart);
+ REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, AR_PHY_TX_END_PA_ON,
+ pModal->txFrameToPaOn);
+ }
+
+ if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
+ AR5416_EEP_MINOR_VER_3) {
+ if (IS_CHAN_HT40(chan))
+ REG_RMW_FIELD(ah, AR_PHY_SETTLING,
+ AR_PHY_SETTLING_SWITCH,
+ pModal->swSettleHt40);
+ }
+}
+
+static u16 ath9k_hw_4k_get_eeprom_antenna_cfg(struct ath_hw *ah,
+ struct ath9k_channel *chan)
+{
+ struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k;
+ struct modal_eep_4k_header *pModal = &eep->modalHeader;
+
+ return pModal->antCtrlCommon & 0xFFFF;
+}
+
+static u8 ath9k_hw_4k_get_num_ant_config(struct ath_hw *ah,
+ enum ieee80211_band freq_band)
+{
+ return 1;
+}
+
+static u16 ath9k_hw_4k_get_spur_channel(struct ath_hw *ah, u16 i, bool is2GHz)
+{
+#define EEP_MAP4K_SPURCHAN \
+ (ah->eeprom.map4k.modalHeader.spurChans[i].spurChan)
+
+ u16 spur_val = AR_NO_SPUR;
+
+ DPRINTF(ah->ah_sc, ATH_DBG_ANI,
+ "Getting spur idx %d is2Ghz. %d val %x\n",
+ i, is2GHz, ah->config.spurchans[i][is2GHz]);
+
+ switch (ah->config.spurmode) {
+ case SPUR_DISABLE:
+ break;
+ case SPUR_ENABLE_IOCTL:
+ spur_val = ah->config.spurchans[i][is2GHz];
+ DPRINTF(ah->ah_sc, ATH_DBG_ANI,
+ "Getting spur val from new loc. %d\n", spur_val);
+ break;
+ case SPUR_ENABLE_EEPROM:
+ spur_val = EEP_MAP4K_SPURCHAN;
+ break;
+ }
+
+ return spur_val;
+
+#undef EEP_MAP4K_SPURCHAN
+}
+
+const struct eeprom_ops eep_4k_ops = {
+ .check_eeprom = ath9k_hw_4k_check_eeprom,
+ .get_eeprom = ath9k_hw_4k_get_eeprom,
+ .fill_eeprom = ath9k_hw_4k_fill_eeprom,
+ .get_eeprom_ver = ath9k_hw_4k_get_eeprom_ver,
+ .get_eeprom_rev = ath9k_hw_4k_get_eeprom_rev,
+ .get_num_ant_config = ath9k_hw_4k_get_num_ant_config,
+ .get_eeprom_antenna_cfg = ath9k_hw_4k_get_eeprom_antenna_cfg,
+ .set_board_values = ath9k_hw_4k_set_board_values,
+ .set_addac = ath9k_hw_4k_set_addac,
+ .set_txpower = ath9k_hw_4k_set_txpower,
+ .get_spur_channel = ath9k_hw_4k_get_spur_channel
+};
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_9287.c b/drivers/net/wireless/ath/ath9k/eeprom_9287.c
new file mode 100644
index 00000000000..aeb7f484b6e
--- /dev/null
+++ b/drivers/net/wireless/ath/ath9k/eeprom_9287.c
@@ -0,0 +1,1183 @@
+/*
+ * Copyright (c) 2008-2009 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "ath9k.h"
+
+static int ath9k_hw_AR9287_get_eeprom_ver(struct ath_hw *ah)
+{
+ return (ah->eeprom.map9287.baseEepHeader.version >> 12) & 0xF;
+}
+
+static int ath9k_hw_AR9287_get_eeprom_rev(struct ath_hw *ah)
+{
+ return (ah->eeprom.map9287.baseEepHeader.version) & 0xFFF;
+}
+
+static bool ath9k_hw_AR9287_fill_eeprom(struct ath_hw *ah)
+{
+ struct ar9287_eeprom *eep = &ah->eeprom.map9287;
+ u16 *eep_data;
+ int addr, eep_start_loc = AR9287_EEP_START_LOC;
+ eep_data = (u16 *)eep;
+
+ if (!ath9k_hw_use_flash(ah)) {
+ DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
+ "Reading from EEPROM, not flash\n");
+ }
+
+ for (addr = 0; addr < sizeof(struct ar9287_eeprom) / sizeof(u16);
+ addr++) {
+ if (!ath9k_hw_nvram_read(ah, addr + eep_start_loc, eep_data)) {
+ DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
+ "Unable to read eeprom region \n");
+ return false;
+ }
+ eep_data++;
+ }
+ return true;
+}
+
+static int ath9k_hw_AR9287_check_eeprom(struct ath_hw *ah)
+{
+ u32 sum = 0, el, integer;
+ u16 temp, word, magic, magic2, *eepdata;
+ int i, addr;
+ bool need_swap = false;
+ struct ar9287_eeprom *eep = &ah->eeprom.map9287;
+
+ if (!ath9k_hw_use_flash(ah)) {
+ if (!ath9k_hw_nvram_read
+ (ah, AR5416_EEPROM_MAGIC_OFFSET, &magic)) {
+ DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
+ "Reading Magic # failed\n");
+ return false;
+ }
+
+ DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
+ "Read Magic = 0x%04X\n", magic);
+ if (magic != AR5416_EEPROM_MAGIC) {
+ magic2 = swab16(magic);
+
+ if (magic2 == AR5416_EEPROM_MAGIC) {
+ need_swap = true;
+ eepdata = (u16 *)(&ah->eeprom);
+
+ for (addr = 0;
+ addr < sizeof(struct ar9287_eeprom) / sizeof(u16);
+ addr++) {
+ temp = swab16(*eepdata);
+ *eepdata = temp;
+ eepdata++;
+ }
+ } else {
+ DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
+ "Invalid EEPROM Magic. "
+ "endianness mismatch.\n");
+ return -EINVAL;
+ }
+ }
+ }
+ DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, "need_swap = %s.\n", need_swap ?
+ "True" : "False");
+
+ if (need_swap)
+ el = swab16(ah->eeprom.map9287.baseEepHeader.length);
+ else
+ el = ah->eeprom.map9287.baseEepHeader.length;
+
+ if (el > sizeof(struct ar9287_eeprom))
+ el = sizeof(struct ar9287_eeprom) / sizeof(u16);
+ else
+ el = el / sizeof(u16);
+
+ eepdata = (u16 *)(&ah->eeprom);
+ for (i = 0; i < el; i++)
+ sum ^= *eepdata++;
+
+ if (need_swap) {
+ word = swab16(eep->baseEepHeader.length);
+ eep->baseEepHeader.length = word;
+
+ word = swab16(eep->baseEepHeader.checksum);
+ eep->baseEepHeader.checksum = word;
+
+ word = swab16(eep->baseEepHeader.version);
+ eep->baseEepHeader.version = word;
+
+ word = swab16(eep->baseEepHeader.regDmn[0]);
+ eep->baseEepHeader.regDmn[0] = word;
+
+ word = swab16(eep->baseEepHeader.regDmn[1]);
+ eep->baseEepHeader.regDmn[1] = word;
+
+ word = swab16(eep->baseEepHeader.rfSilent);
+ eep->baseEepHeader.rfSilent = word;
+
+ word = swab16(eep->baseEepHeader.blueToothOptions);
+ eep->baseEepHeader.blueToothOptions = word;
+
+ word = swab16(eep->baseEepHeader.deviceCap);
+ eep->baseEepHeader.deviceCap = word;
+
+ integer = swab32(eep->modalHeader.antCtrlCommon);
+ eep->modalHeader.antCtrlCommon = integer;
+
+ for (i = 0; i < AR9287_MAX_CHAINS; i++) {
+ integer = swab32(eep->modalHeader.antCtrlChain[i]);
+ eep->modalHeader.antCtrlChain[i] = integer;
+ }
+
+ for (i = 0; i < AR9287_EEPROM_MODAL_SPURS; i++) {
+ word = swab16(eep->modalHeader.spurChans[i].spurChan);
+ eep->modalHeader.spurChans[i].spurChan = word;
+ }
+ }
+
+ if (sum != 0xffff || ah->eep_ops->get_eeprom_ver(ah) != AR9287_EEP_VER
+ || ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_NO_BACK_VER) {
+ DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
+ "Bad EEPROM checksum 0x%x or revision 0x%04x\n",
+ sum, ah->eep_ops->get_eeprom_ver(ah));
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static u32 ath9k_hw_AR9287_get_eeprom(struct ath_hw *ah,
+ enum eeprom_param param)
+{
+ struct ar9287_eeprom *eep = &ah->eeprom.map9287;
+ struct modal_eep_ar9287_header *pModal = &eep->modalHeader;
+ struct base_eep_ar9287_header *pBase = &eep->baseEepHeader;
+ u16 ver_minor;
+
+ ver_minor = pBase->version & AR9287_EEP_VER_MINOR_MASK;
+ switch (param) {
+ case EEP_NFTHRESH_2:
+ return pModal->noiseFloorThreshCh[0];
+ case AR_EEPROM_MAC(0):
+ return pBase->macAddr[0] << 8 | pBase->macAddr[1];
+ case AR_EEPROM_MAC(1):
+ return pBase->macAddr[2] << 8 | pBase->macAddr[3];
+ case AR_EEPROM_MAC(2):
+ return pBase->macAddr[4] << 8 | pBase->macAddr[5];
+ case EEP_REG_0:
+ return pBase->regDmn[0];
+ case EEP_REG_1:
+ return pBase->regDmn[1];
+ case EEP_OP_CAP:
+ return pBase->deviceCap;
+ case EEP_OP_MODE:
+ return pBase->opCapFlags;
+ case EEP_RF_SILENT:
+ return pBase->rfSilent;
+ case EEP_MINOR_REV:
+ return ver_minor;
+ case EEP_TX_MASK:
+ return pBase->txMask;
+ case EEP_RX_MASK:
+ return pBase->rxMask;
+ case EEP_DEV_TYPE:
+ return pBase->deviceType;
+ case EEP_OL_PWRCTRL:
+ return pBase->openLoopPwrCntl;
+ case EEP_TEMPSENSE_SLOPE:
+ if (ver_minor >= AR9287_EEP_MINOR_VER_2)
+ return pBase->tempSensSlope;
+ else
+ return 0;
+ case EEP_TEMPSENSE_SLOPE_PAL_ON:
+ if (ver_minor >= AR9287_EEP_MINOR_VER_3)
+ return pBase->tempSensSlopePalOn;
+ else
+ return 0;
+ default:
+ return 0;
+ }
+}
+
+
+static void ath9k_hw_get_AR9287_gain_boundaries_pdadcs(struct ath_hw *ah,
+ struct ath9k_channel *chan,
+ struct cal_data_per_freq_ar9287 *pRawDataSet,
+ u8 *bChans, u16 availPiers,
+ u16 tPdGainOverlap, int16_t *pMinCalPower,
+ u16 *pPdGainBoundaries, u8 *pPDADCValues,
+ u16 numXpdGains)
+{
+#define TMP_VAL_VPD_TABLE \
+ ((vpdTableI[i][sizeCurrVpdTable - 1] + (ss - maxIndex + 1) * vpdStep));
+
+ int i, j, k;
+ int16_t ss;
+ u16 idxL = 0, idxR = 0, numPiers;
+ u8 *pVpdL, *pVpdR, *pPwrL, *pPwrR;
+ u8 minPwrT4[AR9287_NUM_PD_GAINS];
+ u8 maxPwrT4[AR9287_NUM_PD_GAINS];
+ int16_t vpdStep;
+ int16_t tmpVal;
+ u16 sizeCurrVpdTable, maxIndex, tgtIndex;
+ bool match;
+ int16_t minDelta = 0;
+ struct chan_centers centers;
+ static u8 vpdTableL[AR5416_EEP4K_NUM_PD_GAINS]
+ [AR5416_MAX_PWR_RANGE_IN_HALF_DB];
+ static u8 vpdTableR[AR5416_EEP4K_NUM_PD_GAINS]
+ [AR5416_MAX_PWR_RANGE_IN_HALF_DB];
+ static u8 vpdTableI[AR5416_EEP4K_NUM_PD_GAINS]
+ [AR5416_MAX_PWR_RANGE_IN_HALF_DB];
+
+ ath9k_hw_get_channel_centers(ah, chan, &centers);
+
+ for (numPiers = 0; numPiers < availPiers; numPiers++) {
+ if (bChans[numPiers] == AR9287_BCHAN_UNUSED)
+ break;
+ }
+
+ match = ath9k_hw_get_lower_upper_index(
+ (u8)FREQ2FBIN(centers.synth_center,
+ IS_CHAN_2GHZ(chan)), bChans, numPiers,
+ &idxL, &idxR);
+
+ if (match) {
+ for (i = 0; i < numXpdGains; i++) {
+ minPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][0];
+ maxPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][4];
+ ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
+ pRawDataSet[idxL].pwrPdg[i],
+ pRawDataSet[idxL].vpdPdg[i],
+ AR9287_PD_GAIN_ICEPTS, vpdTableI[i]);
+ }
+ } else {
+ for (i = 0; i < numXpdGains; i++) {
+ pVpdL = pRawDataSet[idxL].vpdPdg[i];
+ pPwrL = pRawDataSet[idxL].pwrPdg[i];
+ pVpdR = pRawDataSet[idxR].vpdPdg[i];
+ pPwrR = pRawDataSet[idxR].pwrPdg[i];
+
+ minPwrT4[i] = max(pPwrL[0], pPwrR[0]);
+
+ maxPwrT4[i] =
+ min(pPwrL[AR9287_PD_GAIN_ICEPTS - 1],
+ pPwrR[AR9287_PD_GAIN_ICEPTS - 1]);
+
+ ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
+ pPwrL, pVpdL,
+ AR9287_PD_GAIN_ICEPTS,
+ vpdTableL[i]);
+ ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
+ pPwrR, pVpdR,
+ AR9287_PD_GAIN_ICEPTS,
+ vpdTableR[i]);
+
+ for (j = 0; j <= (maxPwrT4[i] - minPwrT4[i]) / 2; j++) {
+ vpdTableI[i][j] =
+ (u8)(ath9k_hw_interpolate((u16)
+ FREQ2FBIN(centers. synth_center,
+ IS_CHAN_2GHZ(chan)),
+ bChans[idxL], bChans[idxR],
+ vpdTableL[i][j], vpdTableR[i][j]));
+ }
+ }
+ }
+ *pMinCalPower = (int16_t)(minPwrT4[0] / 2);
+
+ k = 0;
+ for (i = 0; i < numXpdGains; i++) {
+ if (i == (numXpdGains - 1))
+ pPdGainBoundaries[i] = (u16)(maxPwrT4[i] / 2);
+ else
+ pPdGainBoundaries[i] = (u16)((maxPwrT4[i] +
+ minPwrT4[i+1]) / 4);
+
+ pPdGainBoundaries[i] = min((u16)AR5416_MAX_RATE_POWER,
+ pPdGainBoundaries[i]);
+
+
+ if ((i == 0) && !AR_SREV_5416_20_OR_LATER(ah)) {
+ minDelta = pPdGainBoundaries[0] - 23;
+ pPdGainBoundaries[0] = 23;
+ } else
+ minDelta = 0;
+
+ if (i == 0) {
+ if (AR_SREV_9280_10_OR_LATER(ah))
+ ss = (int16_t)(0 - (minPwrT4[i] / 2));
+ else
+ ss = 0;
+ } else
+ ss = (int16_t)((pPdGainBoundaries[i-1] -
+ (minPwrT4[i] / 2)) -
+ tPdGainOverlap + 1 + minDelta);
+
+ vpdStep = (int16_t)(vpdTableI[i][1] - vpdTableI[i][0]);
+ vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep);
+ while ((ss < 0) && (k < (AR9287_NUM_PDADC_VALUES - 1))) {
+ tmpVal = (int16_t)(vpdTableI[i][0] + ss * vpdStep);
+ pPDADCValues[k++] = (u8)((tmpVal < 0) ? 0 : tmpVal);
+ ss++;
+ }
+
+ sizeCurrVpdTable = (u8)((maxPwrT4[i] - minPwrT4[i]) / 2 + 1);
+ tgtIndex = (u8)(pPdGainBoundaries[i] +
+ tPdGainOverlap - (minPwrT4[i] / 2));
+ maxIndex = (tgtIndex < sizeCurrVpdTable) ?
+ tgtIndex : sizeCurrVpdTable;
+
+ while ((ss < maxIndex) && (k < (AR9287_NUM_PDADC_VALUES - 1)))
+ pPDADCValues[k++] = vpdTableI[i][ss++];
+
+ vpdStep = (int16_t)(vpdTableI[i][sizeCurrVpdTable - 1] -
+ vpdTableI[i][sizeCurrVpdTable - 2]);
+ vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep);
+ if (tgtIndex > maxIndex) {
+ while ((ss <= tgtIndex) &&
+ (k < (AR9287_NUM_PDADC_VALUES - 1))) {
+ tmpVal = (int16_t) TMP_VAL_VPD_TABLE;
+ pPDADCValues[k++] = (u8)((tmpVal > 255) ?
+ 255 : tmpVal);
+ ss++;
+ }
+ }
+ }
+
+ while (i < AR9287_PD_GAINS_IN_MASK) {
+ pPdGainBoundaries[i] = pPdGainBoundaries[i-1];
+ i++;
+ }
+
+ while (k < AR9287_NUM_PDADC_VALUES) {
+ pPDADCValues[k] = pPDADCValues[k-1];
+ k++;
+ }
+
+#undef TMP_VAL_VPD_TABLE
+}
+
+static void ar9287_eeprom_get_tx_gain_index(struct ath_hw *ah,
+ struct ath9k_channel *chan,
+ struct cal_data_op_loop_ar9287 *pRawDatasetOpLoop,
+ u8 *pCalChans, u16 availPiers,
+ int8_t *pPwr)
+{
+ u8 pcdac, i = 0;
+ u16 idxL = 0, idxR = 0, numPiers;
+ bool match;
+ struct chan_centers centers;
+
+ ath9k_hw_get_channel_centers(ah, chan, &centers);
+
+ for (numPiers = 0; numPiers < availPiers; numPiers++) {
+ if (pCalChans[numPiers] == AR9287_BCHAN_UNUSED)
+ break;
+ }
+
+ match = ath9k_hw_get_lower_upper_index(
+ (u8)FREQ2FBIN(centers.synth_center, IS_CHAN_2GHZ(chan)),
+ pCalChans, numPiers,
+ &idxL, &idxR);
+
+ if (match) {
+ pcdac = pRawDatasetOpLoop[idxL].pcdac[0][0];
+ *pPwr = pRawDatasetOpLoop[idxL].pwrPdg[0][0];
+ } else {
+ pcdac = pRawDatasetOpLoop[idxR].pcdac[0][0];
+ *pPwr = (pRawDatasetOpLoop[idxL].pwrPdg[0][0] +
+ pRawDatasetOpLoop[idxR].pwrPdg[0][0])/2;
+ }
+
+ while ((pcdac > ah->originalGain[i]) &&
+ (i < (AR9280_TX_GAIN_TABLE_SIZE - 1)))
+ i++;
+}
+
+static void ar9287_eeprom_olpc_set_pdadcs(struct ath_hw *ah,
+ int32_t txPower, u16 chain)
+{
+ u32 tmpVal;
+ u32 a;
+
+ tmpVal = REG_READ(ah, 0xa270);
+ tmpVal = tmpVal & 0xFCFFFFFF;
+ tmpVal = tmpVal | (0x3 << 24);
+ REG_WRITE(ah, 0xa270, tmpVal);
+
+ tmpVal = REG_READ(ah, 0xb270);
+ tmpVal = tmpVal & 0xFCFFFFFF;
+ tmpVal = tmpVal | (0x3 << 24);
+ REG_WRITE(ah, 0xb270, tmpVal);
+
+ if (chain == 0) {
+ tmpVal = REG_READ(ah, 0xa398);
+ tmpVal = tmpVal & 0xff00ffff;
+ a = (txPower)&0xff;
+ tmpVal = tmpVal | (a << 16);
+ REG_WRITE(ah, 0xa398, tmpVal);
+ }
+
+ if (chain == 1) {
+ tmpVal = REG_READ(ah, 0xb398);
+ tmpVal = tmpVal & 0xff00ffff;
+ a = (txPower)&0xff;
+ tmpVal = tmpVal | (a << 16);
+ REG_WRITE(ah, 0xb398, tmpVal);
+ }
+}
+
+static void ath9k_hw_set_AR9287_power_cal_table(struct ath_hw *ah,
+ struct ath9k_channel *chan,
+ int16_t *pTxPowerIndexOffset)
+{
+ struct cal_data_per_freq_ar9287 *pRawDataset;
+ struct cal_data_op_loop_ar9287 *pRawDatasetOpenLoop;
+ u8 *pCalBChans = NULL;
+ u16 pdGainOverlap_t2;
+ u8 pdadcValues[AR9287_NUM_PDADC_VALUES];
+ u16 gainBoundaries[AR9287_PD_GAINS_IN_MASK];
+ u16 numPiers = 0, i, j;
+ int16_t tMinCalPower;
+ u16 numXpdGain, xpdMask;
+ u16 xpdGainValues[AR9287_NUM_PD_GAINS] = {0, 0, 0, 0};
+ u32 reg32, regOffset, regChainOffset;
+ int16_t modalIdx, diff = 0;
+ struct ar9287_eeprom *pEepData = &ah->eeprom.map9287;
+ modalIdx = IS_CHAN_2GHZ(chan) ? 1 : 0;
+ xpdMask = pEepData->modalHeader.xpdGain;
+ if ((pEepData->baseEepHeader.version & AR9287_EEP_VER_MINOR_MASK) >=
+ AR9287_EEP_MINOR_VER_2)
+ pdGainOverlap_t2 = pEepData->modalHeader.pdGainOverlap;
+ else
+ pdGainOverlap_t2 = (u16)(MS(REG_READ(ah, AR_PHY_TPCRG5),
+ AR_PHY_TPCRG5_PD_GAIN_OVERLAP));
+
+ if (IS_CHAN_2GHZ(chan)) {
+ pCalBChans = pEepData->calFreqPier2G;
+ numPiers = AR9287_NUM_2G_CAL_PIERS;
+ if (ath9k_hw_AR9287_get_eeprom(ah, EEP_OL_PWRCTRL)) {
+ pRawDatasetOpenLoop =
+ (struct cal_data_op_loop_ar9287 *)
+ pEepData->calPierData2G[0];
+ ah->initPDADC = pRawDatasetOpenLoop->vpdPdg[0][0];
+ }
+ }
+
+ numXpdGain = 0;
+ for (i = 1; i <= AR9287_PD_GAINS_IN_MASK; i++) {
+ if ((xpdMask >> (AR9287_PD_GAINS_IN_MASK - i)) & 1) {
+ if (numXpdGain >= AR9287_NUM_PD_GAINS)
+ break;
+ xpdGainValues[numXpdGain] =
+ (u16)(AR9287_PD_GAINS_IN_MASK-i);
+ numXpdGain++;
+ }
+ }
+
+ REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_NUM_PD_GAIN,
+ (numXpdGain - 1) & 0x3);
+ REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_1,
+ xpdGainValues[0]);
+ REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_2,
+ xpdGainValues[1]);
+ REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_3,
+ xpdGainValues[2]);
+
+ for (i = 0; i < AR9287_MAX_CHAINS; i++) {
+ regChainOffset = i * 0x1000;
+ if (pEepData->baseEepHeader.txMask & (1 << i)) {
+ pRawDatasetOpenLoop = (struct cal_data_op_loop_ar9287 *)
+ pEepData->calPierData2G[i];
+ if (ath9k_hw_AR9287_get_eeprom(ah, EEP_OL_PWRCTRL)) {
+ int8_t txPower;
+ ar9287_eeprom_get_tx_gain_index(ah, chan,
+ pRawDatasetOpenLoop,
+ pCalBChans, numPiers,
+ &txPower);
+ ar9287_eeprom_olpc_set_pdadcs(ah, txPower, i);
+ } else {
+ pRawDataset =
+ (struct cal_data_per_freq_ar9287 *)
+ pEepData->calPierData2G[i];
+ ath9k_hw_get_AR9287_gain_boundaries_pdadcs(
+ ah, chan, pRawDataset,
+ pCalBChans, numPiers,
+ pdGainOverlap_t2,
+ &tMinCalPower, gainBoundaries,
+ pdadcValues, numXpdGain);
+ }
+
+ if (i == 0) {
+ if (!ath9k_hw_AR9287_get_eeprom(
+ ah, EEP_OL_PWRCTRL)) {
+ REG_WRITE(ah, AR_PHY_TPCRG5 +
+ regChainOffset,
+ SM(pdGainOverlap_t2,
+ AR_PHY_TPCRG5_PD_GAIN_OVERLAP) |
+ SM(gainBoundaries[0],
+ AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1)
+ | SM(gainBoundaries[1],
+ AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2)
+ | SM(gainBoundaries[2],
+ AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3)
+ | SM(gainBoundaries[3],
+ AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4));
+ }
+ }
+
+ if ((int32_t)AR9287_PWR_TABLE_OFFSET_DB !=
+ pEepData->baseEepHeader.pwrTableOffset) {
+ diff = (u16)
+ (pEepData->baseEepHeader.pwrTableOffset
+ - (int32_t)AR9287_PWR_TABLE_OFFSET_DB);
+ diff *= 2;
+
+ for (j = 0;
+ j < ((u16)AR9287_NUM_PDADC_VALUES-diff);
+ j++)
+ pdadcValues[j] = pdadcValues[j+diff];
+
+ for (j = (u16)(AR9287_NUM_PDADC_VALUES-diff);
+ j < AR9287_NUM_PDADC_VALUES; j++)
+ pdadcValues[j] =
+ pdadcValues[
+ AR9287_NUM_PDADC_VALUES-diff];
+ }
+
+ if (!ath9k_hw_AR9287_get_eeprom(ah, EEP_OL_PWRCTRL)) {
+ regOffset = AR_PHY_BASE + (672 << 2) +
+ regChainOffset;
+ for (j = 0; j < 32; j++) {
+ reg32 = ((pdadcValues[4*j + 0]
+ & 0xFF) << 0) |
+ ((pdadcValues[4*j + 1]
+ & 0xFF) << 8) |
+ ((pdadcValues[4*j + 2]
+ & 0xFF) << 16) |
+ ((pdadcValues[4*j + 3]
+ & 0xFF) << 24) ;
+ REG_WRITE(ah, regOffset, reg32);
+
+ DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
+ "PDADC (%d,%4x): %4.4x %8.8x\n",
+ i, regChainOffset, regOffset,
+ reg32);
+
+ DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
+ "PDADC: Chain %d | "
+ "PDADC %3d Value %3d | "
+ "PDADC %3d Value %3d | "
+ "PDADC %3d Value %3d | "
+ "PDADC %3d Value %3d |\n",
+ i, 4 * j, pdadcValues[4 * j],
+ 4 * j + 1,
+ pdadcValues[4 * j + 1],
+ 4 * j + 2,
+ pdadcValues[4 * j + 2],
+ 4 * j + 3,
+ pdadcValues[4 * j + 3]);
+
+ regOffset += 4;
+ }
+ }
+ }
+ }
+
+ *pTxPowerIndexOffset = 0;
+}
+
+static void ath9k_hw_set_AR9287_power_per_rate_table(struct ath_hw *ah,
+ struct ath9k_channel *chan, int16_t *ratesArray, u16 cfgCtl,
+ u16 AntennaReduction, u16 twiceMaxRegulatoryPower,
+ u16 powerLimit)
+{
+#define REDUCE_SCALED_POWER_BY_TWO_CHAIN 6
+#define REDUCE_SCALED_POWER_BY_THREE_CHAIN 10
+
+ u16 twiceMaxEdgePower = AR5416_MAX_RATE_POWER;
+ static const u16 tpScaleReductionTable[5] =
+ { 0, 3, 6, 9, AR5416_MAX_RATE_POWER };
+ int i;
+ int16_t twiceLargestAntenna;
+ struct cal_ctl_data_ar9287 *rep;
+ struct cal_target_power_leg targetPowerOfdm = {0, {0, 0, 0, 0} },
+ targetPowerCck = {0, {0, 0, 0, 0} };
+ struct cal_target_power_leg targetPowerOfdmExt = {0, {0, 0, 0, 0} },
+ targetPowerCckExt = {0, {0, 0, 0, 0} };
+ struct cal_target_power_ht targetPowerHt20,
+ targetPowerHt40 = {0, {0, 0, 0, 0} };
+ u16 scaledPower = 0, minCtlPower, maxRegAllowedPower;
+ u16 ctlModesFor11g[] =
+ {CTL_11B, CTL_11G, CTL_2GHT20,
+ CTL_11B_EXT, CTL_11G_EXT, CTL_2GHT40};
+ u16 numCtlModes = 0, *pCtlMode = NULL, ctlMode, freq;
+ struct chan_centers centers;
+ int tx_chainmask;
+ u16 twiceMinEdgePower;
+ struct ar9287_eeprom *pEepData = &ah->eeprom.map9287;
+ tx_chainmask = ah->txchainmask;
+
+ ath9k_hw_get_channel_centers(ah, chan, &centers);
+
+ twiceLargestAntenna = max(pEepData->modalHeader.antennaGainCh[0],
+ pEepData->modalHeader.antennaGainCh[1]);
+
+ twiceLargestAntenna = (int16_t)min((AntennaReduction) -
+ twiceLargestAntenna, 0);
+
+ maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna;
+ if (ah->regulatory.tp_scale != ATH9K_TP_SCALE_MAX)
+ maxRegAllowedPower -=
+ (tpScaleReductionTable[(ah->regulatory.tp_scale)] * 2);
+
+ scaledPower = min(powerLimit, maxRegAllowedPower);
+
+ switch (ar5416_get_ntxchains(tx_chainmask)) {
+ case 1:
+ break;
+ case 2:
+ scaledPower -= REDUCE_SCALED_POWER_BY_TWO_CHAIN;
+ break;
+ case 3:
+ scaledPower -= REDUCE_SCALED_POWER_BY_THREE_CHAIN;
+ break;
+ }
+ scaledPower = max((u16)0, scaledPower);
+
+ if (IS_CHAN_2GHZ(chan)) {
+ numCtlModes =
+ ARRAY_SIZE(ctlModesFor11g) - SUB_NUM_CTL_MODES_AT_2G_40;
+ pCtlMode = ctlModesFor11g;
+
+ ath9k_hw_get_legacy_target_powers(ah, chan,
+ pEepData->calTargetPowerCck,
+ AR9287_NUM_2G_CCK_TARGET_POWERS,
+ &targetPowerCck, 4, false);
+ ath9k_hw_get_legacy_target_powers(ah, chan,
+ pEepData->calTargetPower2G,
+ AR9287_NUM_2G_20_TARGET_POWERS,
+ &targetPowerOfdm, 4, false);
+ ath9k_hw_get_target_powers(ah, chan,
+ pEepData->calTargetPower2GHT20,
+ AR9287_NUM_2G_20_TARGET_POWERS,
+ &targetPowerHt20, 8, false);
+
+ if (IS_CHAN_HT40(chan)) {
+ numCtlModes = ARRAY_SIZE(ctlModesFor11g);
+ ath9k_hw_get_target_powers(ah, chan,
+ pEepData->calTargetPower2GHT40,
+ AR9287_NUM_2G_40_TARGET_POWERS,
+ &targetPowerHt40, 8, true);
+ ath9k_hw_get_legacy_target_powers(ah, chan,
+ pEepData->calTargetPowerCck,
+ AR9287_NUM_2G_CCK_TARGET_POWERS,
+ &targetPowerCckExt, 4, true);
+ ath9k_hw_get_legacy_target_powers(ah, chan,
+ pEepData->calTargetPower2G,
+ AR9287_NUM_2G_20_TARGET_POWERS,
+ &targetPowerOfdmExt, 4, true);
+ }
+ }
+
+ for (ctlMode = 0; ctlMode < numCtlModes; ctlMode++) {
+ bool isHt40CtlMode = (pCtlMode[ctlMode] == CTL_5GHT40) ||
+ (pCtlMode[ctlMode] == CTL_2GHT40);
+ if (isHt40CtlMode)
+ freq = centers.synth_center;
+ else if (pCtlMode[ctlMode] & EXT_ADDITIVE)
+ freq = centers.ext_center;
+ else
+ freq = centers.ctl_center;
+
+ if (ah->eep_ops->get_eeprom_ver(ah) == 14 &&
+ ah->eep_ops->get_eeprom_rev(ah) <= 2)
+ twiceMaxEdgePower = AR5416_MAX_RATE_POWER;
+
+ for (i = 0; (i < AR9287_NUM_CTLS) && pEepData->ctlIndex[i]; i++) {
+ if ((((cfgCtl & ~CTL_MODE_M) |
+ (pCtlMode[ctlMode] & CTL_MODE_M)) ==
+ pEepData->ctlIndex[i]) ||
+ (((cfgCtl & ~CTL_MODE_M) |
+ (pCtlMode[ctlMode] & CTL_MODE_M)) ==
+ ((pEepData->ctlIndex[i] &
+ CTL_MODE_M) | SD_NO_CTL))) {
+
+ rep = &(pEepData->ctlData[i]);
+ twiceMinEdgePower = ath9k_hw_get_max_edge_power(
+ freq,
+ rep->ctlEdges[ar5416_get_ntxchains(
+ tx_chainmask) - 1],
+ IS_CHAN_2GHZ(chan), AR5416_NUM_BAND_EDGES);
+
+ if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL)
+ twiceMaxEdgePower = min(
+ twiceMaxEdgePower,
+ twiceMinEdgePower);
+ else {
+ twiceMaxEdgePower = twiceMinEdgePower;
+ break;
+ }
+ }
+ }
+
+ minCtlPower = (u8)min(twiceMaxEdgePower, scaledPower);
+
+ switch (pCtlMode[ctlMode]) {
+ case CTL_11B:
+ for (i = 0;
+ i < ARRAY_SIZE(targetPowerCck.tPow2x);
+ i++) {
+ targetPowerCck.tPow2x[i] = (u8)min(
+ (u16)targetPowerCck.tPow2x[i],
+ minCtlPower);
+ }
+ break;
+ case CTL_11A:
+ case CTL_11G:
+ for (i = 0;
+ i < ARRAY_SIZE(targetPowerOfdm.tPow2x);
+ i++) {
+ targetPowerOfdm.tPow2x[i] = (u8)min(
+ (u16)targetPowerOfdm.tPow2x[i],
+ minCtlPower);
+ }
+ break;
+ case CTL_5GHT20:
+ case CTL_2GHT20:
+ for (i = 0;
+ i < ARRAY_SIZE(targetPowerHt20.tPow2x);
+ i++) {
+ targetPowerHt20.tPow2x[i] = (u8)min(
+ (u16)targetPowerHt20.tPow2x[i],
+ minCtlPower);
+ }
+ break;
+ case CTL_11B_EXT:
+ targetPowerCckExt.tPow2x[0] = (u8)min(
+ (u16)targetPowerCckExt.tPow2x[0],
+ minCtlPower);
+ break;
+ case CTL_11A_EXT:
+ case CTL_11G_EXT:
+ targetPowerOfdmExt.tPow2x[0] = (u8)min(
+ (u16)targetPowerOfdmExt.tPow2x[0],
+ minCtlPower);
+ break;
+ case CTL_5GHT40:
+ case CTL_2GHT40:
+ for (i = 0;
+ i < ARRAY_SIZE(targetPowerHt40.tPow2x);
+ i++) {
+ targetPowerHt40.tPow2x[i] = (u8)min(
+ (u16)targetPowerHt40.tPow2x[i],
+ minCtlPower);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ ratesArray[rate6mb] =
+ ratesArray[rate9mb] =
+ ratesArray[rate12mb] =
+ ratesArray[rate18mb] =
+ ratesArray[rate24mb] =
+ targetPowerOfdm.tPow2x[0];
+
+ ratesArray[rate36mb] = targetPowerOfdm.tPow2x[1];
+ ratesArray[rate48mb] = targetPowerOfdm.tPow2x[2];
+ ratesArray[rate54mb] = targetPowerOfdm.tPow2x[3];
+ ratesArray[rateXr] = targetPowerOfdm.tPow2x[0];
+
+ for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); i++)
+ ratesArray[rateHt20_0 + i] = targetPowerHt20.tPow2x[i];
+
+ if (IS_CHAN_2GHZ(chan)) {
+ ratesArray[rate1l] = targetPowerCck.tPow2x[0];
+ ratesArray[rate2s] = ratesArray[rate2l] =
+ targetPowerCck.tPow2x[1];
+ ratesArray[rate5_5s] = ratesArray[rate5_5l] =
+ targetPowerCck.tPow2x[2];
+ ratesArray[rate11s] = ratesArray[rate11l] =
+ targetPowerCck.tPow2x[3];
+ }
+ if (IS_CHAN_HT40(chan)) {
+ for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++)
+ ratesArray[rateHt40_0 + i] = targetPowerHt40.tPow2x[i];
+
+ ratesArray[rateDupOfdm] = targetPowerHt40.tPow2x[0];
+ ratesArray[rateDupCck] = targetPowerHt40.tPow2x[0];
+ ratesArray[rateExtOfdm] = targetPowerOfdmExt.tPow2x[0];
+ if (IS_CHAN_2GHZ(chan))
+ ratesArray[rateExtCck] = targetPowerCckExt.tPow2x[0];
+ }
+
+#undef REDUCE_SCALED_POWER_BY_TWO_CHAIN
+#undef REDUCE_SCALED_POWER_BY_THREE_CHAIN
+}
+
+static void ath9k_hw_AR9287_set_txpower(struct ath_hw *ah,
+ struct ath9k_channel *chan, u16 cfgCtl,
+ u8 twiceAntennaReduction,
+ u8 twiceMaxRegulatoryPower,
+ u8 powerLimit)
+{
+#define INCREASE_MAXPOW_BY_TWO_CHAIN 6
+#define INCREASE_MAXPOW_BY_THREE_CHAIN 10
+
+ struct ar9287_eeprom *pEepData = &ah->eeprom.map9287;
+ struct modal_eep_ar9287_header *pModal = &pEepData->modalHeader;
+ int16_t ratesArray[Ar5416RateSize];
+ int16_t txPowerIndexOffset = 0;
+ u8 ht40PowerIncForPdadc = 2;
+ int i;
+
+ memset(ratesArray, 0, sizeof(ratesArray));
+
+ if ((pEepData->baseEepHeader.version & AR9287_EEP_VER_MINOR_MASK) >=
+ AR9287_EEP_MINOR_VER_2)
+ ht40PowerIncForPdadc = pModal->ht40PowerIncForPdadc;
+
+ ath9k_hw_set_AR9287_power_per_rate_table(ah, chan,
+ &ratesArray[0], cfgCtl,
+ twiceAntennaReduction,
+ twiceMaxRegulatoryPower,
+ powerLimit);
+
+ ath9k_hw_set_AR9287_power_cal_table(ah, chan, &txPowerIndexOffset);
+
+ for (i = 0; i < ARRAY_SIZE(ratesArray); i++) {
+ ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]);
+ if (ratesArray[i] > AR9287_MAX_RATE_POWER)
+ ratesArray[i] = AR9287_MAX_RATE_POWER;
+ }
+
+ if (AR_SREV_9280_10_OR_LATER(ah)) {
+ for (i = 0; i < Ar5416RateSize; i++)
+ ratesArray[i] -= AR9287_PWR_TABLE_OFFSET_DB * 2;
+ }
+
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE1,
+ ATH9K_POW_SM(ratesArray[rate18mb], 24)
+ | ATH9K_POW_SM(ratesArray[rate12mb], 16)
+ | ATH9K_POW_SM(ratesArray[rate9mb], 8)
+ | ATH9K_POW_SM(ratesArray[rate6mb], 0));
+
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE2,
+ ATH9K_POW_SM(ratesArray[rate54mb], 24)
+ | ATH9K_POW_SM(ratesArray[rate48mb], 16)
+ | ATH9K_POW_SM(ratesArray[rate36mb], 8)
+ | ATH9K_POW_SM(ratesArray[rate24mb], 0));
+
+ if (IS_CHAN_2GHZ(chan)) {
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE3,
+ ATH9K_POW_SM(ratesArray[rate2s], 24)
+ | ATH9K_POW_SM(ratesArray[rate2l], 16)
+ | ATH9K_POW_SM(ratesArray[rateXr], 8)
+ | ATH9K_POW_SM(ratesArray[rate1l], 0));
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE4,
+ ATH9K_POW_SM(ratesArray[rate11s], 24)
+ | ATH9K_POW_SM(ratesArray[rate11l], 16)
+ | ATH9K_POW_SM(ratesArray[rate5_5s], 8)
+ | ATH9K_POW_SM(ratesArray[rate5_5l], 0));
+ }
+
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE5,
+ ATH9K_POW_SM(ratesArray[rateHt20_3], 24)
+ | ATH9K_POW_SM(ratesArray[rateHt20_2], 16)
+ | ATH9K_POW_SM(ratesArray[rateHt20_1], 8)
+ | ATH9K_POW_SM(ratesArray[rateHt20_0], 0));
+
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE6,
+ ATH9K_POW_SM(ratesArray[rateHt20_7], 24)
+ | ATH9K_POW_SM(ratesArray[rateHt20_6], 16)
+ | ATH9K_POW_SM(ratesArray[rateHt20_5], 8)
+ | ATH9K_POW_SM(ratesArray[rateHt20_4], 0));
+
+ if (IS_CHAN_HT40(chan)) {
+ if (ath9k_hw_AR9287_get_eeprom(ah, EEP_OL_PWRCTRL)) {
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE7,
+ ATH9K_POW_SM(ratesArray[rateHt40_3], 24)
+ | ATH9K_POW_SM(ratesArray[rateHt40_2], 16)
+ | ATH9K_POW_SM(ratesArray[rateHt40_1], 8)
+ | ATH9K_POW_SM(ratesArray[rateHt40_0], 0));
+
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE8,
+ ATH9K_POW_SM(ratesArray[rateHt40_7], 24)
+ | ATH9K_POW_SM(ratesArray[rateHt40_6], 16)
+ | ATH9K_POW_SM(ratesArray[rateHt40_5], 8)
+ | ATH9K_POW_SM(ratesArray[rateHt40_4], 0));
+ } else {
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE7,
+ ATH9K_POW_SM(ratesArray[rateHt40_3] +
+ ht40PowerIncForPdadc, 24)
+ | ATH9K_POW_SM(ratesArray[rateHt40_2] +
+ ht40PowerIncForPdadc, 16)
+ | ATH9K_POW_SM(ratesArray[rateHt40_1] +
+ ht40PowerIncForPdadc, 8)
+ | ATH9K_POW_SM(ratesArray[rateHt40_0] +
+ ht40PowerIncForPdadc, 0));
+
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE8,
+ ATH9K_POW_SM(ratesArray[rateHt40_7] +
+ ht40PowerIncForPdadc, 24)
+ | ATH9K_POW_SM(ratesArray[rateHt40_6] +
+ ht40PowerIncForPdadc, 16)
+ | ATH9K_POW_SM(ratesArray[rateHt40_5] +
+ ht40PowerIncForPdadc, 8)
+ | ATH9K_POW_SM(ratesArray[rateHt40_4] +
+ ht40PowerIncForPdadc, 0));
+ }
+
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE9,
+ ATH9K_POW_SM(ratesArray[rateExtOfdm], 24)
+ | ATH9K_POW_SM(ratesArray[rateExtCck], 16)
+ | ATH9K_POW_SM(ratesArray[rateDupOfdm], 8)
+ | ATH9K_POW_SM(ratesArray[rateDupCck], 0));
+ }
+
+ if (IS_CHAN_2GHZ(chan))
+ i = rate1l;
+ else
+ i = rate6mb;
+
+ if (AR_SREV_9280_10_OR_LATER(ah))
+ ah->regulatory.max_power_level =
+ ratesArray[i] + AR9287_PWR_TABLE_OFFSET_DB * 2;
+ else
+ ah->regulatory.max_power_level = ratesArray[i];
+
+ switch (ar5416_get_ntxchains(ah->txchainmask)) {
+ case 1:
+ break;
+ case 2:
+ ah->regulatory.max_power_level +=
+ INCREASE_MAXPOW_BY_TWO_CHAIN;
+ break;
+ case 3:
+ ah->regulatory.max_power_level +=
+ INCREASE_MAXPOW_BY_THREE_CHAIN;
+ break;
+ default:
+ DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
+ "Invalid chainmask configuration\n");
+ break;
+ }
+}
+
+static void ath9k_hw_AR9287_set_addac(struct ath_hw *ah,
+ struct ath9k_channel *chan)
+{
+}
+
+static void ath9k_hw_AR9287_set_board_values(struct ath_hw *ah,
+ struct ath9k_channel *chan)
+{
+ struct ar9287_eeprom *eep = &ah->eeprom.map9287;
+ struct modal_eep_ar9287_header *pModal = &eep->modalHeader;
+ u16 antWrites[AR9287_ANT_16S];
+ u32 regChainOffset;
+ u8 txRxAttenLocal;
+ int i, j, offset_num;
+
+ pModal = &eep->modalHeader;
+
+ antWrites[0] = (u16)((pModal->antCtrlCommon >> 28) & 0xF);
+ antWrites[1] = (u16)((pModal->antCtrlCommon >> 24) & 0xF);
+ antWrites[2] = (u16)((pModal->antCtrlCommon >> 20) & 0xF);
+ antWrites[3] = (u16)((pModal->antCtrlCommon >> 16) & 0xF);
+ antWrites[4] = (u16)((pModal->antCtrlCommon >> 12) & 0xF);
+ antWrites[5] = (u16)((pModal->antCtrlCommon >> 8) & 0xF);
+ antWrites[6] = (u16)((pModal->antCtrlCommon >> 4) & 0xF);
+ antWrites[7] = (u16)(pModal->antCtrlCommon & 0xF);
+
+ offset_num = 8;
+
+ for (i = 0, j = offset_num; i < AR9287_MAX_CHAINS; i++) {
+ antWrites[j++] = (u16)((pModal->antCtrlChain[i] >> 28) & 0xf);
+ antWrites[j++] = (u16)((pModal->antCtrlChain[i] >> 10) & 0x3);
+ antWrites[j++] = (u16)((pModal->antCtrlChain[i] >> 8) & 0x3);
+ antWrites[j++] = 0;
+ antWrites[j++] = (u16)((pModal->antCtrlChain[i] >> 6) & 0x3);
+ antWrites[j++] = (u16)((pModal->antCtrlChain[i] >> 4) & 0x3);
+ antWrites[j++] = (u16)((pModal->antCtrlChain[i] >> 2) & 0x3);
+ antWrites[j++] = (u16)(pModal->antCtrlChain[i] & 0x3);
+ }
+
+ REG_WRITE(ah, AR_PHY_SWITCH_COM,
+ ah->eep_ops->get_eeprom_antenna_cfg(ah, chan));
+
+ for (i = 0; i < AR9287_MAX_CHAINS; i++) {
+ regChainOffset = i * 0x1000;
+
+ REG_WRITE(ah, AR_PHY_SWITCH_CHAIN_0 + regChainOffset,
+ pModal->antCtrlChain[i]);
+
+ REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset,
+ (REG_READ(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset)
+ & ~(AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF |
+ AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF)) |
+ SM(pModal->iqCalICh[i],
+ AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF) |
+ SM(pModal->iqCalQCh[i],
+ AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF));
+
+ txRxAttenLocal = pModal->txRxAttenCh[i];
+
+ REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
+ AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN,
+ pModal->bswMargin[i]);
+ REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
+ AR_PHY_GAIN_2GHZ_XATTEN1_DB,
+ pModal->bswAtten[i]);
+ REG_RMW_FIELD(ah, AR_PHY_RXGAIN + regChainOffset,
+ AR9280_PHY_RXGAIN_TXRX_ATTEN,
+ txRxAttenLocal);
+ REG_RMW_FIELD(ah, AR_PHY_RXGAIN + regChainOffset,
+ AR9280_PHY_RXGAIN_TXRX_MARGIN,
+ pModal->rxTxMarginCh[i]);
+ }
+
+
+ if (IS_CHAN_HT40(chan))
+ REG_RMW_FIELD(ah, AR_PHY_SETTLING,
+ AR_PHY_SETTLING_SWITCH, pModal->swSettleHt40);
+ else
+ REG_RMW_FIELD(ah, AR_PHY_SETTLING,
+ AR_PHY_SETTLING_SWITCH, pModal->switchSettling);
+
+ REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ,
+ AR_PHY_DESIRED_SZ_ADC, pModal->adcDesiredSize);
+
+ REG_WRITE(ah, AR_PHY_RF_CTL4,
+ SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAA_OFF)
+ | SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAB_OFF)
+ | SM(pModal->txFrameToXpaOn, AR_PHY_RF_CTL4_FRAME_XPAA_ON)
+ | SM(pModal->txFrameToXpaOn, AR_PHY_RF_CTL4_FRAME_XPAB_ON));
+
+ REG_RMW_FIELD(ah, AR_PHY_RF_CTL3,
+ AR_PHY_TX_END_TO_A2_RX_ON, pModal->txEndToRxOn);
+
+ REG_RMW_FIELD(ah, AR_PHY_CCA,
+ AR9280_PHY_CCA_THRESH62, pModal->thresh62);
+ REG_RMW_FIELD(ah, AR_PHY_EXT_CCA0,
+ AR_PHY_EXT_CCA0_THRESH62, pModal->thresh62);
+
+ ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH0, AR9287_AN_RF2G3_DB1,
+ AR9287_AN_RF2G3_DB1_S, pModal->db1);
+ ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH0, AR9287_AN_RF2G3_DB2,
+ AR9287_AN_RF2G3_DB2_S, pModal->db2);
+ ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH0,
+ AR9287_AN_RF2G3_OB_CCK,
+ AR9287_AN_RF2G3_OB_CCK_S, pModal->ob_cck);
+ ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH0,
+ AR9287_AN_RF2G3_OB_PSK,
+ AR9287_AN_RF2G3_OB_PSK_S, pModal->ob_psk);
+ ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH0,
+ AR9287_AN_RF2G3_OB_QAM,
+ AR9287_AN_RF2G3_OB_QAM_S, pModal->ob_qam);
+ ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH0,
+ AR9287_AN_RF2G3_OB_PAL_OFF,
+ AR9287_AN_RF2G3_OB_PAL_OFF_S,
+ pModal->ob_pal_off);
+
+ ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH1,
+ AR9287_AN_RF2G3_DB1, AR9287_AN_RF2G3_DB1_S,
+ pModal->db1);
+ ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH1, AR9287_AN_RF2G3_DB2,
+ AR9287_AN_RF2G3_DB2_S, pModal->db2);
+ ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH1,
+ AR9287_AN_RF2G3_OB_CCK,
+ AR9287_AN_RF2G3_OB_CCK_S, pModal->ob_cck);
+ ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH1,
+ AR9287_AN_RF2G3_OB_PSK,
+ AR9287_AN_RF2G3_OB_PSK_S, pModal->ob_psk);
+ ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH1,
+ AR9287_AN_RF2G3_OB_QAM,
+ AR9287_AN_RF2G3_OB_QAM_S, pModal->ob_qam);
+ ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH1,
+ AR9287_AN_RF2G3_OB_PAL_OFF,
+ AR9287_AN_RF2G3_OB_PAL_OFF_S,
+ pModal->ob_pal_off);
+
+ REG_RMW_FIELD(ah, AR_PHY_RF_CTL2,
+ AR_PHY_TX_END_DATA_START, pModal->txFrameToDataStart);
+ REG_RMW_FIELD(ah, AR_PHY_RF_CTL2,
+ AR_PHY_TX_END_PA_ON, pModal->txFrameToPaOn);
+
+ ath9k_hw_analog_shift_rmw(ah, AR9287_AN_TOP2,
+ AR9287_AN_TOP2_XPABIAS_LVL,
+ AR9287_AN_TOP2_XPABIAS_LVL_S,
+ pModal->xpaBiasLvl);
+}
+
+static u8 ath9k_hw_AR9287_get_num_ant_config(struct ath_hw *ah,
+ enum ieee80211_band freq_band)
+{
+ return 1;
+}
+
+static u16 ath9k_hw_AR9287_get_eeprom_antenna_cfg(struct ath_hw *ah,
+ struct ath9k_channel *chan)
+{
+ struct ar9287_eeprom *eep = &ah->eeprom.map9287;
+ struct modal_eep_ar9287_header *pModal = &eep->modalHeader;
+
+ return pModal->antCtrlCommon & 0xFFFF;
+}
+
+static u16 ath9k_hw_AR9287_get_spur_channel(struct ath_hw *ah,
+ u16 i, bool is2GHz)
+{
+#define EEP_MAP9287_SPURCHAN \
+ (ah->eeprom.map9287.modalHeader.spurChans[i].spurChan)
+ u16 spur_val = AR_NO_SPUR;
+
+ DPRINTF(ah->ah_sc, ATH_DBG_ANI,
+ "Getting spur idx %d is2Ghz. %d val %x\n",
+ i, is2GHz, ah->config.spurchans[i][is2GHz]);
+
+ switch (ah->config.spurmode) {
+ case SPUR_DISABLE:
+ break;
+ case SPUR_ENABLE_IOCTL:
+ spur_val = ah->config.spurchans[i][is2GHz];
+ DPRINTF(ah->ah_sc, ATH_DBG_ANI,
+ "Getting spur val from new loc. %d\n", spur_val);
+ break;
+ case SPUR_ENABLE_EEPROM:
+ spur_val = EEP_MAP9287_SPURCHAN;
+ break;
+ }
+
+ return spur_val;
+
+#undef EEP_MAP9287_SPURCHAN
+}
+
+const struct eeprom_ops eep_AR9287_ops = {
+ .check_eeprom = ath9k_hw_AR9287_check_eeprom,
+ .get_eeprom = ath9k_hw_AR9287_get_eeprom,
+ .fill_eeprom = ath9k_hw_AR9287_fill_eeprom,
+ .get_eeprom_ver = ath9k_hw_AR9287_get_eeprom_ver,
+ .get_eeprom_rev = ath9k_hw_AR9287_get_eeprom_rev,
+ .get_num_ant_config = ath9k_hw_AR9287_get_num_ant_config,
+ .get_eeprom_antenna_cfg = ath9k_hw_AR9287_get_eeprom_antenna_cfg,
+ .set_board_values = ath9k_hw_AR9287_set_board_values,
+ .set_addac = ath9k_hw_AR9287_set_addac,
+ .set_txpower = ath9k_hw_AR9287_set_txpower,
+ .get_spur_channel = ath9k_hw_AR9287_get_spur_channel
+};
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_def.c b/drivers/net/wireless/ath/ath9k/eeprom_def.c
new file mode 100644
index 00000000000..5211ad94c8f
--- /dev/null
+++ b/drivers/net/wireless/ath/ath9k/eeprom_def.c
@@ -0,0 +1,1385 @@
+/*
+ * Copyright (c) 2008-2009 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "ath9k.h"
+
+static void ath9k_get_txgain_index(struct ath_hw *ah,
+ struct ath9k_channel *chan,
+ struct calDataPerFreqOpLoop *rawDatasetOpLoop,
+ u8 *calChans, u16 availPiers, u8 *pwr, u8 *pcdacIdx)
+{
+ u8 pcdac, i = 0;
+ u16 idxL = 0, idxR = 0, numPiers;
+ bool match;
+ struct chan_centers centers;
+
+ ath9k_hw_get_channel_centers(ah, chan, &centers);
+
+ for (numPiers = 0; numPiers < availPiers; numPiers++)
+ if (calChans[numPiers] == AR5416_BCHAN_UNUSED)
+ break;
+
+ match = ath9k_hw_get_lower_upper_index(
+ (u8)FREQ2FBIN(centers.synth_center, IS_CHAN_2GHZ(chan)),
+ calChans, numPiers, &idxL, &idxR);
+ if (match) {
+ pcdac = rawDatasetOpLoop[idxL].pcdac[0][0];
+ *pwr = rawDatasetOpLoop[idxL].pwrPdg[0][0];
+ } else {
+ pcdac = rawDatasetOpLoop[idxR].pcdac[0][0];
+ *pwr = (rawDatasetOpLoop[idxL].pwrPdg[0][0] +
+ rawDatasetOpLoop[idxR].pwrPdg[0][0])/2;
+ }
+
+ while (pcdac > ah->originalGain[i] &&
+ i < (AR9280_TX_GAIN_TABLE_SIZE - 1))
+ i++;
+
+ *pcdacIdx = i;
+ return;
+}
+
+static void ath9k_olc_get_pdadcs(struct ath_hw *ah,
+ u32 initTxGain,
+ int txPower,
+ u8 *pPDADCValues)
+{
+ u32 i;
+ u32 offset;
+
+ REG_RMW_FIELD(ah, AR_PHY_TX_PWRCTRL6_0,
+ AR_PHY_TX_PWRCTRL_ERR_EST_MODE, 3);
+ REG_RMW_FIELD(ah, AR_PHY_TX_PWRCTRL6_1,
+ AR_PHY_TX_PWRCTRL_ERR_EST_MODE, 3);
+
+ REG_RMW_FIELD(ah, AR_PHY_TX_PWRCTRL7,
+ AR_PHY_TX_PWRCTRL_INIT_TX_GAIN, initTxGain);
+
+ offset = txPower;
+ for (i = 0; i < AR5416_NUM_PDADC_VALUES; i++)
+ if (i < offset)
+ pPDADCValues[i] = 0x0;
+ else
+ pPDADCValues[i] = 0xFF;
+}
+
+static int ath9k_hw_def_get_eeprom_ver(struct ath_hw *ah)
+{
+ return ((ah->eeprom.def.baseEepHeader.version >> 12) & 0xF);
+}
+
+static int ath9k_hw_def_get_eeprom_rev(struct ath_hw *ah)
+{
+ return ((ah->eeprom.def.baseEepHeader.version) & 0xFFF);
+}
+
+static bool ath9k_hw_def_fill_eeprom(struct ath_hw *ah)
+{
+#define SIZE_EEPROM_DEF (sizeof(struct ar5416_eeprom_def) / sizeof(u16))
+ u16 *eep_data = (u16 *)&ah->eeprom.def;
+ int addr, ar5416_eep_start_loc = 0x100;
+
+ for (addr = 0; addr < SIZE_EEPROM_DEF; addr++) {
+ if (!ath9k_hw_nvram_read(ah, addr + ar5416_eep_start_loc,
+ eep_data)) {
+ DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
+ "Unable to read eeprom region\n");
+ return false;
+ }
+ eep_data++;
+ }
+ return true;
+#undef SIZE_EEPROM_DEF
+}
+
+static int ath9k_hw_def_check_eeprom(struct ath_hw *ah)
+{
+ struct ar5416_eeprom_def *eep =
+ (struct ar5416_eeprom_def *) &ah->eeprom.def;
+ u16 *eepdata, temp, magic, magic2;
+ u32 sum = 0, el;
+ bool need_swap = false;
+ int i, addr, size;
+
+ if (!ath9k_hw_nvram_read(ah, AR5416_EEPROM_MAGIC_OFFSET, &magic)) {
+ DPRINTF(ah->ah_sc, ATH_DBG_FATAL, "Reading Magic # failed\n");
+ return false;
+ }
+
+ if (!ath9k_hw_use_flash(ah)) {
+ DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
+ "Read Magic = 0x%04X\n", magic);
+
+ if (magic != AR5416_EEPROM_MAGIC) {
+ magic2 = swab16(magic);
+
+ if (magic2 == AR5416_EEPROM_MAGIC) {
+ size = sizeof(struct ar5416_eeprom_def);
+ need_swap = true;
+ eepdata = (u16 *) (&ah->eeprom);
+
+ for (addr = 0; addr < size / sizeof(u16); addr++) {
+ temp = swab16(*eepdata);
+ *eepdata = temp;
+ eepdata++;
+ }
+ } else {
+ DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
+ "Invalid EEPROM Magic. "
+ "Endianness mismatch.\n");
+ return -EINVAL;
+ }
+ }
+ }
+
+ DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, "need_swap = %s.\n",
+ need_swap ? "True" : "False");
+
+ if (need_swap)
+ el = swab16(ah->eeprom.def.baseEepHeader.length);
+ else
+ el = ah->eeprom.def.baseEepHeader.length;
+
+ if (el > sizeof(struct ar5416_eeprom_def))
+ el = sizeof(struct ar5416_eeprom_def) / sizeof(u16);
+ else
+ el = el / sizeof(u16);
+
+ eepdata = (u16 *)(&ah->eeprom);
+
+ for (i = 0; i < el; i++)
+ sum ^= *eepdata++;
+
+ if (need_swap) {
+ u32 integer, j;
+ u16 word;
+
+ DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
+ "EEPROM Endianness is not native.. Changing.\n");
+
+ word = swab16(eep->baseEepHeader.length);
+ eep->baseEepHeader.length = word;
+
+ word = swab16(eep->baseEepHeader.checksum);
+ eep->baseEepHeader.checksum = word;
+
+ word = swab16(eep->baseEepHeader.version);
+ eep->baseEepHeader.version = word;
+
+ word = swab16(eep->baseEepHeader.regDmn[0]);
+ eep->baseEepHeader.regDmn[0] = word;
+
+ word = swab16(eep->baseEepHeader.regDmn[1]);
+ eep->baseEepHeader.regDmn[1] = word;
+
+ word = swab16(eep->baseEepHeader.rfSilent);
+ eep->baseEepHeader.rfSilent = word;
+
+ word = swab16(eep->baseEepHeader.blueToothOptions);
+ eep->baseEepHeader.blueToothOptions = word;
+
+ word = swab16(eep->baseEepHeader.deviceCap);
+ eep->baseEepHeader.deviceCap = word;
+
+ for (j = 0; j < ARRAY_SIZE(eep->modalHeader); j++) {
+ struct modal_eep_header *pModal =
+ &eep->modalHeader[j];
+ integer = swab32(pModal->antCtrlCommon);
+ pModal->antCtrlCommon = integer;
+
+ for (i = 0; i < AR5416_MAX_CHAINS; i++) {
+ integer = swab32(pModal->antCtrlChain[i]);
+ pModal->antCtrlChain[i] = integer;
+ }
+
+ for (i = 0; i < AR5416_EEPROM_MODAL_SPURS; i++) {
+ word = swab16(pModal->spurChans[i].spurChan);
+ pModal->spurChans[i].spurChan = word;
+ }
+ }
+ }
+
+ if (sum != 0xffff || ah->eep_ops->get_eeprom_ver(ah) != AR5416_EEP_VER ||
+ ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_NO_BACK_VER) {
+ DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
+ "Bad EEPROM checksum 0x%x or revision 0x%04x\n",
+ sum, ah->eep_ops->get_eeprom_ver(ah));
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static u32 ath9k_hw_def_get_eeprom(struct ath_hw *ah,
+ enum eeprom_param param)
+{
+ struct ar5416_eeprom_def *eep = &ah->eeprom.def;
+ struct modal_eep_header *pModal = eep->modalHeader;
+ struct base_eep_header *pBase = &eep->baseEepHeader;
+
+ switch (param) {
+ case EEP_NFTHRESH_5:
+ return pModal[0].noiseFloorThreshCh[0];
+ case EEP_NFTHRESH_2:
+ return pModal[1].noiseFloorThreshCh[0];
+ case AR_EEPROM_MAC(0):
+ return pBase->macAddr[0] << 8 | pBase->macAddr[1];
+ case AR_EEPROM_MAC(1):
+ return pBase->macAddr[2] << 8 | pBase->macAddr[3];
+ case AR_EEPROM_MAC(2):
+ return pBase->macAddr[4] << 8 | pBase->macAddr[5];
+ case EEP_REG_0:
+ return pBase->regDmn[0];
+ case EEP_REG_1:
+ return pBase->regDmn[1];
+ case EEP_OP_CAP:
+ return pBase->deviceCap;
+ case EEP_OP_MODE:
+ return pBase->opCapFlags;
+ case EEP_RF_SILENT:
+ return pBase->rfSilent;
+ case EEP_OB_5:
+ return pModal[0].ob;
+ case EEP_DB_5:
+ return pModal[0].db;
+ case EEP_OB_2:
+ return pModal[1].ob;
+ case EEP_DB_2:
+ return pModal[1].db;
+ case EEP_MINOR_REV:
+ return AR5416_VER_MASK;
+ case EEP_TX_MASK:
+ return pBase->txMask;
+ case EEP_RX_MASK:
+ return pBase->rxMask;
+ case EEP_RXGAIN_TYPE:
+ return pBase->rxGainType;
+ case EEP_TXGAIN_TYPE:
+ return pBase->txGainType;
+ case EEP_OL_PWRCTRL:
+ if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_19)
+ return pBase->openLoopPwrCntl ? true : false;
+ else
+ return false;
+ case EEP_RC_CHAIN_MASK:
+ if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_19)
+ return pBase->rcChainMask;
+ else
+ return 0;
+ case EEP_DAC_HPWR_5G:
+ if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_20)
+ return pBase->dacHiPwrMode_5G;
+ else
+ return 0;
+ case EEP_FRAC_N_5G:
+ if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_22)
+ return pBase->frac_n_5g;
+ else
+ return 0;
+ default:
+ return 0;
+ }
+}
+
+static void ath9k_hw_def_set_gain(struct ath_hw *ah,
+ struct modal_eep_header *pModal,
+ struct ar5416_eeprom_def *eep,
+ u8 txRxAttenLocal, int regChainOffset, int i)
+{
+ if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_3) {
+ txRxAttenLocal = pModal->txRxAttenCh[i];
+
+ if (AR_SREV_9280_10_OR_LATER(ah)) {
+ REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
+ AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN,
+ pModal->bswMargin[i]);
+ REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
+ AR_PHY_GAIN_2GHZ_XATTEN1_DB,
+ pModal->bswAtten[i]);
+ REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
+ AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN,
+ pModal->xatten2Margin[i]);
+ REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
+ AR_PHY_GAIN_2GHZ_XATTEN2_DB,
+ pModal->xatten2Db[i]);
+ } else {
+ REG_WRITE(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
+ (REG_READ(ah, AR_PHY_GAIN_2GHZ + regChainOffset) &
+ ~AR_PHY_GAIN_2GHZ_BSW_MARGIN)
+ | SM(pModal-> bswMargin[i],
+ AR_PHY_GAIN_2GHZ_BSW_MARGIN));
+ REG_WRITE(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
+ (REG_READ(ah, AR_PHY_GAIN_2GHZ + regChainOffset) &
+ ~AR_PHY_GAIN_2GHZ_BSW_ATTEN)
+ | SM(pModal->bswAtten[i],
+ AR_PHY_GAIN_2GHZ_BSW_ATTEN));
+ }
+ }
+
+ if (AR_SREV_9280_10_OR_LATER(ah)) {
+ REG_RMW_FIELD(ah,
+ AR_PHY_RXGAIN + regChainOffset,
+ AR9280_PHY_RXGAIN_TXRX_ATTEN, txRxAttenLocal);
+ REG_RMW_FIELD(ah,
+ AR_PHY_RXGAIN + regChainOffset,
+ AR9280_PHY_RXGAIN_TXRX_MARGIN, pModal->rxTxMarginCh[i]);
+ } else {
+ REG_WRITE(ah,
+ AR_PHY_RXGAIN + regChainOffset,
+ (REG_READ(ah, AR_PHY_RXGAIN + regChainOffset) &
+ ~AR_PHY_RXGAIN_TXRX_ATTEN)
+ | SM(txRxAttenLocal, AR_PHY_RXGAIN_TXRX_ATTEN));
+ REG_WRITE(ah,
+ AR_PHY_GAIN_2GHZ + regChainOffset,
+ (REG_READ(ah, AR_PHY_GAIN_2GHZ + regChainOffset) &
+ ~AR_PHY_GAIN_2GHZ_RXTX_MARGIN) |
+ SM(pModal->rxTxMarginCh[i], AR_PHY_GAIN_2GHZ_RXTX_MARGIN));
+ }
+}
+
+static void ath9k_hw_def_set_board_values(struct ath_hw *ah,
+ struct ath9k_channel *chan)
+{
+ struct modal_eep_header *pModal;
+ struct ar5416_eeprom_def *eep = &ah->eeprom.def;
+ int i, regChainOffset;
+ u8 txRxAttenLocal;
+
+ pModal = &(eep->modalHeader[IS_CHAN_2GHZ(chan)]);
+ txRxAttenLocal = IS_CHAN_2GHZ(chan) ? 23 : 44;
+
+ REG_WRITE(ah, AR_PHY_SWITCH_COM,
+ ah->eep_ops->get_eeprom_antenna_cfg(ah, chan));
+
+ for (i = 0; i < AR5416_MAX_CHAINS; i++) {
+ if (AR_SREV_9280(ah)) {
+ if (i >= 2)
+ break;
+ }
+
+ if (AR_SREV_5416_20_OR_LATER(ah) &&
+ (ah->rxchainmask == 5 || ah->txchainmask == 5) && (i != 0))
+ regChainOffset = (i == 1) ? 0x2000 : 0x1000;
+ else
+ regChainOffset = i * 0x1000;
+
+ REG_WRITE(ah, AR_PHY_SWITCH_CHAIN_0 + regChainOffset,
+ pModal->antCtrlChain[i]);
+
+ REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset,
+ (REG_READ(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset) &
+ ~(AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF |
+ AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF)) |
+ SM(pModal->iqCalICh[i],
+ AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF) |
+ SM(pModal->iqCalQCh[i],
+ AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF));
+
+ if ((i == 0) || AR_SREV_5416_20_OR_LATER(ah))
+ ath9k_hw_def_set_gain(ah, pModal, eep, txRxAttenLocal,
+ regChainOffset, i);
+ }
+
+ if (AR_SREV_9280_10_OR_LATER(ah)) {
+ if (IS_CHAN_2GHZ(chan)) {
+ ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH0,
+ AR_AN_RF2G1_CH0_OB,
+ AR_AN_RF2G1_CH0_OB_S,
+ pModal->ob);
+ ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH0,
+ AR_AN_RF2G1_CH0_DB,
+ AR_AN_RF2G1_CH0_DB_S,
+ pModal->db);
+ ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH1,
+ AR_AN_RF2G1_CH1_OB,
+ AR_AN_RF2G1_CH1_OB_S,
+ pModal->ob_ch1);
+ ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH1,
+ AR_AN_RF2G1_CH1_DB,
+ AR_AN_RF2G1_CH1_DB_S,
+ pModal->db_ch1);
+ } else {
+ ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH0,
+ AR_AN_RF5G1_CH0_OB5,
+ AR_AN_RF5G1_CH0_OB5_S,
+ pModal->ob);
+ ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH0,
+ AR_AN_RF5G1_CH0_DB5,
+ AR_AN_RF5G1_CH0_DB5_S,
+ pModal->db);
+ ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH1,
+ AR_AN_RF5G1_CH1_OB5,
+ AR_AN_RF5G1_CH1_OB5_S,
+ pModal->ob_ch1);
+ ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH1,
+ AR_AN_RF5G1_CH1_DB5,
+ AR_AN_RF5G1_CH1_DB5_S,
+ pModal->db_ch1);
+ }
+ ath9k_hw_analog_shift_rmw(ah, AR_AN_TOP2,
+ AR_AN_TOP2_XPABIAS_LVL,
+ AR_AN_TOP2_XPABIAS_LVL_S,
+ pModal->xpaBiasLvl);
+ ath9k_hw_analog_shift_rmw(ah, AR_AN_TOP2,
+ AR_AN_TOP2_LOCALBIAS,
+ AR_AN_TOP2_LOCALBIAS_S,
+ pModal->local_bias);
+ REG_RMW_FIELD(ah, AR_PHY_XPA_CFG, AR_PHY_FORCE_XPA_CFG,
+ pModal->force_xpaon);
+ }
+
+ REG_RMW_FIELD(ah, AR_PHY_SETTLING, AR_PHY_SETTLING_SWITCH,
+ pModal->switchSettling);
+ REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, AR_PHY_DESIRED_SZ_ADC,
+ pModal->adcDesiredSize);
+
+ if (!AR_SREV_9280_10_OR_LATER(ah))
+ REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ,
+ AR_PHY_DESIRED_SZ_PGA,
+ pModal->pgaDesiredSize);
+
+ REG_WRITE(ah, AR_PHY_RF_CTL4,
+ SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAA_OFF)
+ | SM(pModal->txEndToXpaOff,
+ AR_PHY_RF_CTL4_TX_END_XPAB_OFF)
+ | SM(pModal->txFrameToXpaOn,
+ AR_PHY_RF_CTL4_FRAME_XPAA_ON)
+ | SM(pModal->txFrameToXpaOn,
+ AR_PHY_RF_CTL4_FRAME_XPAB_ON));
+
+ REG_RMW_FIELD(ah, AR_PHY_RF_CTL3, AR_PHY_TX_END_TO_A2_RX_ON,
+ pModal->txEndToRxOn);
+
+ if (AR_SREV_9280_10_OR_LATER(ah)) {
+ REG_RMW_FIELD(ah, AR_PHY_CCA, AR9280_PHY_CCA_THRESH62,
+ pModal->thresh62);
+ REG_RMW_FIELD(ah, AR_PHY_EXT_CCA0,
+ AR_PHY_EXT_CCA0_THRESH62,
+ pModal->thresh62);
+ } else {
+ REG_RMW_FIELD(ah, AR_PHY_CCA, AR_PHY_CCA_THRESH62,
+ pModal->thresh62);
+ REG_RMW_FIELD(ah, AR_PHY_EXT_CCA,
+ AR_PHY_EXT_CCA_THRESH62,
+ pModal->thresh62);
+ }
+
+ if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_2) {
+ REG_RMW_FIELD(ah, AR_PHY_RF_CTL2,
+ AR_PHY_TX_END_DATA_START,
+ pModal->txFrameToDataStart);
+ REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, AR_PHY_TX_END_PA_ON,
+ pModal->txFrameToPaOn);
+ }
+
+ if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_3) {
+ if (IS_CHAN_HT40(chan))
+ REG_RMW_FIELD(ah, AR_PHY_SETTLING,
+ AR_PHY_SETTLING_SWITCH,
+ pModal->swSettleHt40);
+ }
+
+ if (AR_SREV_9280_20_OR_LATER(ah) &&
+ AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_19)
+ REG_RMW_FIELD(ah, AR_PHY_CCK_TX_CTRL,
+ AR_PHY_CCK_TX_CTRL_TX_DAC_SCALE_CCK,
+ pModal->miscBits);
+
+
+ if (AR_SREV_9280_20(ah) && AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_20) {
+ if (IS_CHAN_2GHZ(chan))
+ REG_RMW_FIELD(ah, AR_AN_TOP1, AR_AN_TOP1_DACIPMODE,
+ eep->baseEepHeader.dacLpMode);
+ else if (eep->baseEepHeader.dacHiPwrMode_5G)
+ REG_RMW_FIELD(ah, AR_AN_TOP1, AR_AN_TOP1_DACIPMODE, 0);
+ else
+ REG_RMW_FIELD(ah, AR_AN_TOP1, AR_AN_TOP1_DACIPMODE,
+ eep->baseEepHeader.dacLpMode);
+
+ REG_RMW_FIELD(ah, AR_PHY_FRAME_CTL, AR_PHY_FRAME_CTL_TX_CLIP,
+ pModal->miscBits >> 2);
+
+ REG_RMW_FIELD(ah, AR_PHY_TX_PWRCTRL9,
+ AR_PHY_TX_DESIRED_SCALE_CCK,
+ eep->baseEepHeader.desiredScaleCCK);
+ }
+}
+
+static void ath9k_hw_def_set_addac(struct ath_hw *ah,
+ struct ath9k_channel *chan)
+{
+#define XPA_LVL_FREQ(cnt) (pModal->xpaBiasLvlFreq[cnt])
+ struct modal_eep_header *pModal;
+ struct ar5416_eeprom_def *eep = &ah->eeprom.def;
+ u8 biaslevel;
+
+ if (ah->hw_version.macVersion != AR_SREV_VERSION_9160)
+ return;
+
+ if (ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_MINOR_VER_7)
+ return;
+
+ pModal = &(eep->modalHeader[IS_CHAN_2GHZ(chan)]);
+
+ if (pModal->xpaBiasLvl != 0xff) {
+ biaslevel = pModal->xpaBiasLvl;
+ } else {
+ u16 resetFreqBin, freqBin, freqCount = 0;
+ struct chan_centers centers;
+
+ ath9k_hw_get_channel_centers(ah, chan, &centers);
+
+ resetFreqBin = FREQ2FBIN(centers.synth_center,
+ IS_CHAN_2GHZ(chan));
+ freqBin = XPA_LVL_FREQ(0) & 0xff;
+ biaslevel = (u8) (XPA_LVL_FREQ(0) >> 14);
+
+ freqCount++;
+
+ while (freqCount < 3) {
+ if (XPA_LVL_FREQ(freqCount) == 0x0)
+ break;
+
+ freqBin = XPA_LVL_FREQ(freqCount) & 0xff;
+ if (resetFreqBin >= freqBin)
+ biaslevel = (u8)(XPA_LVL_FREQ(freqCount) >> 14);
+ else
+ break;
+ freqCount++;
+ }
+ }
+
+ if (IS_CHAN_2GHZ(chan)) {
+ INI_RA(&ah->iniAddac, 7, 1) = (INI_RA(&ah->iniAddac,
+ 7, 1) & (~0x18)) | biaslevel << 3;
+ } else {
+ INI_RA(&ah->iniAddac, 6, 1) = (INI_RA(&ah->iniAddac,
+ 6, 1) & (~0xc0)) | biaslevel << 6;
+ }
+#undef XPA_LVL_FREQ
+}
+
+static void ath9k_hw_get_def_gain_boundaries_pdadcs(struct ath_hw *ah,
+ struct ath9k_channel *chan,
+ struct cal_data_per_freq *pRawDataSet,
+ u8 *bChans, u16 availPiers,
+ u16 tPdGainOverlap, int16_t *pMinCalPower,
+ u16 *pPdGainBoundaries, u8 *pPDADCValues,
+ u16 numXpdGains)
+{
+ int i, j, k;
+ int16_t ss;
+ u16 idxL = 0, idxR = 0, numPiers;
+ static u8 vpdTableL[AR5416_NUM_PD_GAINS]
+ [AR5416_MAX_PWR_RANGE_IN_HALF_DB];
+ static u8 vpdTableR[AR5416_NUM_PD_GAINS]
+ [AR5416_MAX_PWR_RANGE_IN_HALF_DB];
+ static u8 vpdTableI[AR5416_NUM_PD_GAINS]
+ [AR5416_MAX_PWR_RANGE_IN_HALF_DB];
+
+ u8 *pVpdL, *pVpdR, *pPwrL, *pPwrR;
+ u8 minPwrT4[AR5416_NUM_PD_GAINS];
+ u8 maxPwrT4[AR5416_NUM_PD_GAINS];
+ int16_t vpdStep;
+ int16_t tmpVal;
+ u16 sizeCurrVpdTable, maxIndex, tgtIndex;
+ bool match;
+ int16_t minDelta = 0;
+ struct chan_centers centers;
+
+ ath9k_hw_get_channel_centers(ah, chan, &centers);
+
+ for (numPiers = 0; numPiers < availPiers; numPiers++) {
+ if (bChans[numPiers] == AR5416_BCHAN_UNUSED)
+ break;
+ }
+
+ match = ath9k_hw_get_lower_upper_index((u8)FREQ2FBIN(centers.synth_center,
+ IS_CHAN_2GHZ(chan)),
+ bChans, numPiers, &idxL, &idxR);
+
+ if (match) {
+ for (i = 0; i < numXpdGains; i++) {
+ minPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][0];
+ maxPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][4];
+ ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
+ pRawDataSet[idxL].pwrPdg[i],
+ pRawDataSet[idxL].vpdPdg[i],
+ AR5416_PD_GAIN_ICEPTS,
+ vpdTableI[i]);
+ }
+ } else {
+ for (i = 0; i < numXpdGains; i++) {
+ pVpdL = pRawDataSet[idxL].vpdPdg[i];
+ pPwrL = pRawDataSet[idxL].pwrPdg[i];
+ pVpdR = pRawDataSet[idxR].vpdPdg[i];
+ pPwrR = pRawDataSet[idxR].pwrPdg[i];
+
+ minPwrT4[i] = max(pPwrL[0], pPwrR[0]);
+
+ maxPwrT4[i] =
+ min(pPwrL[AR5416_PD_GAIN_ICEPTS - 1],
+ pPwrR[AR5416_PD_GAIN_ICEPTS - 1]);
+
+
+ ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
+ pPwrL, pVpdL,
+ AR5416_PD_GAIN_ICEPTS,
+ vpdTableL[i]);
+ ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
+ pPwrR, pVpdR,
+ AR5416_PD_GAIN_ICEPTS,
+ vpdTableR[i]);
+
+ for (j = 0; j <= (maxPwrT4[i] - minPwrT4[i]) / 2; j++) {
+ vpdTableI[i][j] =
+ (u8)(ath9k_hw_interpolate((u16)
+ FREQ2FBIN(centers.
+ synth_center,
+ IS_CHAN_2GHZ
+ (chan)),
+ bChans[idxL], bChans[idxR],
+ vpdTableL[i][j], vpdTableR[i][j]));
+ }
+ }
+ }
+
+ *pMinCalPower = (int16_t)(minPwrT4[0] / 2);
+
+ k = 0;
+
+ for (i = 0; i < numXpdGains; i++) {
+ if (i == (numXpdGains - 1))
+ pPdGainBoundaries[i] =
+ (u16)(maxPwrT4[i] / 2);
+ else
+ pPdGainBoundaries[i] =
+ (u16)((maxPwrT4[i] + minPwrT4[i + 1]) / 4);
+
+ pPdGainBoundaries[i] =
+ min((u16)AR5416_MAX_RATE_POWER, pPdGainBoundaries[i]);
+
+ if ((i == 0) && !AR_SREV_5416_20_OR_LATER(ah)) {
+ minDelta = pPdGainBoundaries[0] - 23;
+ pPdGainBoundaries[0] = 23;
+ } else {
+ minDelta = 0;
+ }
+
+ if (i == 0) {
+ if (AR_SREV_9280_10_OR_LATER(ah))
+ ss = (int16_t)(0 - (minPwrT4[i] / 2));
+ else
+ ss = 0;
+ } else {
+ ss = (int16_t)((pPdGainBoundaries[i - 1] -
+ (minPwrT4[i] / 2)) -
+ tPdGainOverlap + 1 + minDelta);
+ }
+ vpdStep = (int16_t)(vpdTableI[i][1] - vpdTableI[i][0]);
+ vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep);
+
+ while ((ss < 0) && (k < (AR5416_NUM_PDADC_VALUES - 1))) {
+ tmpVal = (int16_t)(vpdTableI[i][0] + ss * vpdStep);
+ pPDADCValues[k++] = (u8)((tmpVal < 0) ? 0 : tmpVal);
+ ss++;
+ }
+
+ sizeCurrVpdTable = (u8) ((maxPwrT4[i] - minPwrT4[i]) / 2 + 1);
+ tgtIndex = (u8)(pPdGainBoundaries[i] + tPdGainOverlap -
+ (minPwrT4[i] / 2));
+ maxIndex = (tgtIndex < sizeCurrVpdTable) ?
+ tgtIndex : sizeCurrVpdTable;
+
+ while ((ss < maxIndex) && (k < (AR5416_NUM_PDADC_VALUES - 1))) {
+ pPDADCValues[k++] = vpdTableI[i][ss++];
+ }
+
+ vpdStep = (int16_t)(vpdTableI[i][sizeCurrVpdTable - 1] -
+ vpdTableI[i][sizeCurrVpdTable - 2]);
+ vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep);
+
+ if (tgtIndex > maxIndex) {
+ while ((ss <= tgtIndex) &&
+ (k < (AR5416_NUM_PDADC_VALUES - 1))) {
+ tmpVal = (int16_t)((vpdTableI[i][sizeCurrVpdTable - 1] +
+ (ss - maxIndex + 1) * vpdStep));
+ pPDADCValues[k++] = (u8)((tmpVal > 255) ?
+ 255 : tmpVal);
+ ss++;
+ }
+ }
+ }
+
+ while (i < AR5416_PD_GAINS_IN_MASK) {
+ pPdGainBoundaries[i] = pPdGainBoundaries[i - 1];
+ i++;
+ }
+
+ while (k < AR5416_NUM_PDADC_VALUES) {
+ pPDADCValues[k] = pPDADCValues[k - 1];
+ k++;
+ }
+
+ return;
+}
+
+static void ath9k_hw_set_def_power_cal_table(struct ath_hw *ah,
+ struct ath9k_channel *chan,
+ int16_t *pTxPowerIndexOffset)
+{
+#define SM_PD_GAIN(x) SM(0x38, AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_##x)
+#define SM_PDGAIN_B(x, y) \
+ SM((gainBoundaries[x]), AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_##y)
+
+ struct ar5416_eeprom_def *pEepData = &ah->eeprom.def;
+ struct cal_data_per_freq *pRawDataset;
+ u8 *pCalBChans = NULL;
+ u16 pdGainOverlap_t2;
+ static u8 pdadcValues[AR5416_NUM_PDADC_VALUES];
+ u16 gainBoundaries[AR5416_PD_GAINS_IN_MASK];
+ u16 numPiers, i, j;
+ int16_t tMinCalPower;
+ u16 numXpdGain, xpdMask;
+ u16 xpdGainValues[AR5416_NUM_PD_GAINS] = { 0, 0, 0, 0 };
+ u32 reg32, regOffset, regChainOffset;
+ int16_t modalIdx;
+
+ modalIdx = IS_CHAN_2GHZ(chan) ? 1 : 0;
+ xpdMask = pEepData->modalHeader[modalIdx].xpdGain;
+
+ if ((pEepData->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
+ AR5416_EEP_MINOR_VER_2) {
+ pdGainOverlap_t2 =
+ pEepData->modalHeader[modalIdx].pdGainOverlap;
+ } else {
+ pdGainOverlap_t2 = (u16)(MS(REG_READ(ah, AR_PHY_TPCRG5),
+ AR_PHY_TPCRG5_PD_GAIN_OVERLAP));
+ }
+
+ if (IS_CHAN_2GHZ(chan)) {
+ pCalBChans = pEepData->calFreqPier2G;
+ numPiers = AR5416_NUM_2G_CAL_PIERS;
+ } else {
+ pCalBChans = pEepData->calFreqPier5G;
+ numPiers = AR5416_NUM_5G_CAL_PIERS;
+ }
+
+ if (OLC_FOR_AR9280_20_LATER && IS_CHAN_2GHZ(chan)) {
+ pRawDataset = pEepData->calPierData2G[0];
+ ah->initPDADC = ((struct calDataPerFreqOpLoop *)
+ pRawDataset)->vpdPdg[0][0];
+ }
+
+ numXpdGain = 0;
+
+ for (i = 1; i <= AR5416_PD_GAINS_IN_MASK; i++) {
+ if ((xpdMask >> (AR5416_PD_GAINS_IN_MASK - i)) & 1) {
+ if (numXpdGain >= AR5416_NUM_PD_GAINS)
+ break;
+ xpdGainValues[numXpdGain] =
+ (u16)(AR5416_PD_GAINS_IN_MASK - i);
+ numXpdGain++;
+ }
+ }
+
+ REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_NUM_PD_GAIN,
+ (numXpdGain - 1) & 0x3);
+ REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_1,
+ xpdGainValues[0]);
+ REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_2,
+ xpdGainValues[1]);
+ REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_3,
+ xpdGainValues[2]);
+
+ for (i = 0; i < AR5416_MAX_CHAINS; i++) {
+ if (AR_SREV_5416_20_OR_LATER(ah) &&
+ (ah->rxchainmask == 5 || ah->txchainmask == 5) &&
+ (i != 0)) {
+ regChainOffset = (i == 1) ? 0x2000 : 0x1000;
+ } else
+ regChainOffset = i * 0x1000;
+
+ if (pEepData->baseEepHeader.txMask & (1 << i)) {
+ if (IS_CHAN_2GHZ(chan))
+ pRawDataset = pEepData->calPierData2G[i];
+ else
+ pRawDataset = pEepData->calPierData5G[i];
+
+
+ if (OLC_FOR_AR9280_20_LATER) {
+ u8 pcdacIdx;
+ u8 txPower;
+
+ ath9k_get_txgain_index(ah, chan,
+ (struct calDataPerFreqOpLoop *)pRawDataset,
+ pCalBChans, numPiers, &txPower, &pcdacIdx);
+ ath9k_olc_get_pdadcs(ah, pcdacIdx,
+ txPower/2, pdadcValues);
+ } else {
+ ath9k_hw_get_def_gain_boundaries_pdadcs(ah,
+ chan, pRawDataset,
+ pCalBChans, numPiers,
+ pdGainOverlap_t2,
+ &tMinCalPower,
+ gainBoundaries,
+ pdadcValues,
+ numXpdGain);
+ }
+
+ if ((i == 0) || AR_SREV_5416_20_OR_LATER(ah)) {
+ if (OLC_FOR_AR9280_20_LATER) {
+ REG_WRITE(ah,
+ AR_PHY_TPCRG5 + regChainOffset,
+ SM(0x6,
+ AR_PHY_TPCRG5_PD_GAIN_OVERLAP) |
+ SM_PD_GAIN(1) | SM_PD_GAIN(2) |
+ SM_PD_GAIN(3) | SM_PD_GAIN(4));
+ } else {
+ REG_WRITE(ah,
+ AR_PHY_TPCRG5 + regChainOffset,
+ SM(pdGainOverlap_t2,
+ AR_PHY_TPCRG5_PD_GAIN_OVERLAP)|
+ SM_PDGAIN_B(0, 1) |
+ SM_PDGAIN_B(1, 2) |
+ SM_PDGAIN_B(2, 3) |
+ SM_PDGAIN_B(3, 4));
+ }
+ }
+
+ regOffset = AR_PHY_BASE + (672 << 2) + regChainOffset;
+ for (j = 0; j < 32; j++) {
+ reg32 = ((pdadcValues[4 * j + 0] & 0xFF) << 0) |
+ ((pdadcValues[4 * j + 1] & 0xFF) << 8) |
+ ((pdadcValues[4 * j + 2] & 0xFF) << 16)|
+ ((pdadcValues[4 * j + 3] & 0xFF) << 24);
+ REG_WRITE(ah, regOffset, reg32);
+
+ DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
+ "PDADC (%d,%4x): %4.4x %8.8x\n",
+ i, regChainOffset, regOffset,
+ reg32);
+ DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
+ "PDADC: Chain %d | PDADC %3d "
+ "Value %3d | PDADC %3d Value %3d | "
+ "PDADC %3d Value %3d | PDADC %3d "
+ "Value %3d |\n",
+ i, 4 * j, pdadcValues[4 * j],
+ 4 * j + 1, pdadcValues[4 * j + 1],
+ 4 * j + 2, pdadcValues[4 * j + 2],
+ 4 * j + 3,
+ pdadcValues[4 * j + 3]);
+
+ regOffset += 4;
+ }
+ }
+ }
+
+ *pTxPowerIndexOffset = 0;
+#undef SM_PD_GAIN
+#undef SM_PDGAIN_B
+}
+
+static void ath9k_hw_set_def_power_per_rate_table(struct ath_hw *ah,
+ struct ath9k_channel *chan,
+ int16_t *ratesArray,
+ u16 cfgCtl,
+ u16 AntennaReduction,
+ u16 twiceMaxRegulatoryPower,
+ u16 powerLimit)
+{
+#define REDUCE_SCALED_POWER_BY_TWO_CHAIN 6 /* 10*log10(2)*2 */
+#define REDUCE_SCALED_POWER_BY_THREE_CHAIN 10 /* 10*log10(3)*2 */
+
+ struct ar5416_eeprom_def *pEepData = &ah->eeprom.def;
+ u16 twiceMaxEdgePower = AR5416_MAX_RATE_POWER;
+ static const u16 tpScaleReductionTable[5] =
+ { 0, 3, 6, 9, AR5416_MAX_RATE_POWER };
+
+ int i;
+ int16_t twiceLargestAntenna;
+ struct cal_ctl_data *rep;
+ struct cal_target_power_leg targetPowerOfdm, targetPowerCck = {
+ 0, { 0, 0, 0, 0}
+ };
+ struct cal_target_power_leg targetPowerOfdmExt = {
+ 0, { 0, 0, 0, 0} }, targetPowerCckExt = {
+ 0, { 0, 0, 0, 0 }
+ };
+ struct cal_target_power_ht targetPowerHt20, targetPowerHt40 = {
+ 0, {0, 0, 0, 0}
+ };
+ u16 scaledPower = 0, minCtlPower, maxRegAllowedPower;
+ u16 ctlModesFor11a[] =
+ { CTL_11A, CTL_5GHT20, CTL_11A_EXT, CTL_5GHT40 };
+ u16 ctlModesFor11g[] =
+ { CTL_11B, CTL_11G, CTL_2GHT20, CTL_11B_EXT, CTL_11G_EXT,
+ CTL_2GHT40
+ };
+ u16 numCtlModes, *pCtlMode, ctlMode, freq;
+ struct chan_centers centers;
+ int tx_chainmask;
+ u16 twiceMinEdgePower;
+
+ tx_chainmask = ah->txchainmask;
+
+ ath9k_hw_get_channel_centers(ah, chan, &centers);
+
+ twiceLargestAntenna = max(
+ pEepData->modalHeader
+ [IS_CHAN_2GHZ(chan)].antennaGainCh[0],
+ pEepData->modalHeader
+ [IS_CHAN_2GHZ(chan)].antennaGainCh[1]);
+
+ twiceLargestAntenna = max((u8)twiceLargestAntenna,
+ pEepData->modalHeader
+ [IS_CHAN_2GHZ(chan)].antennaGainCh[2]);
+
+ twiceLargestAntenna = (int16_t)min(AntennaReduction -
+ twiceLargestAntenna, 0);
+
+ maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna;
+
+ if (ah->regulatory.tp_scale != ATH9K_TP_SCALE_MAX) {
+ maxRegAllowedPower -=
+ (tpScaleReductionTable[(ah->regulatory.tp_scale)] * 2);
+ }
+
+ scaledPower = min(powerLimit, maxRegAllowedPower);
+
+ switch (ar5416_get_ntxchains(tx_chainmask)) {
+ case 1:
+ break;
+ case 2:
+ scaledPower -= REDUCE_SCALED_POWER_BY_TWO_CHAIN;
+ break;
+ case 3:
+ scaledPower -= REDUCE_SCALED_POWER_BY_THREE_CHAIN;
+ break;
+ }
+
+ scaledPower = max((u16)0, scaledPower);
+
+ if (IS_CHAN_2GHZ(chan)) {
+ numCtlModes = ARRAY_SIZE(ctlModesFor11g) -
+ SUB_NUM_CTL_MODES_AT_2G_40;
+ pCtlMode = ctlModesFor11g;
+
+ ath9k_hw_get_legacy_target_powers(ah, chan,
+ pEepData->calTargetPowerCck,
+ AR5416_NUM_2G_CCK_TARGET_POWERS,
+ &targetPowerCck, 4, false);
+ ath9k_hw_get_legacy_target_powers(ah, chan,
+ pEepData->calTargetPower2G,
+ AR5416_NUM_2G_20_TARGET_POWERS,
+ &targetPowerOfdm, 4, false);
+ ath9k_hw_get_target_powers(ah, chan,
+ pEepData->calTargetPower2GHT20,
+ AR5416_NUM_2G_20_TARGET_POWERS,
+ &targetPowerHt20, 8, false);
+
+ if (IS_CHAN_HT40(chan)) {
+ numCtlModes = ARRAY_SIZE(ctlModesFor11g);
+ ath9k_hw_get_target_powers(ah, chan,
+ pEepData->calTargetPower2GHT40,
+ AR5416_NUM_2G_40_TARGET_POWERS,
+ &targetPowerHt40, 8, true);
+ ath9k_hw_get_legacy_target_powers(ah, chan,
+ pEepData->calTargetPowerCck,
+ AR5416_NUM_2G_CCK_TARGET_POWERS,
+ &targetPowerCckExt, 4, true);
+ ath9k_hw_get_legacy_target_powers(ah, chan,
+ pEepData->calTargetPower2G,
+ AR5416_NUM_2G_20_TARGET_POWERS,
+ &targetPowerOfdmExt, 4, true);
+ }
+ } else {
+ numCtlModes = ARRAY_SIZE(ctlModesFor11a) -
+ SUB_NUM_CTL_MODES_AT_5G_40;
+ pCtlMode = ctlModesFor11a;
+
+ ath9k_hw_get_legacy_target_powers(ah, chan,
+ pEepData->calTargetPower5G,
+ AR5416_NUM_5G_20_TARGET_POWERS,
+ &targetPowerOfdm, 4, false);
+ ath9k_hw_get_target_powers(ah, chan,
+ pEepData->calTargetPower5GHT20,
+ AR5416_NUM_5G_20_TARGET_POWERS,
+ &targetPowerHt20, 8, false);
+
+ if (IS_CHAN_HT40(chan)) {
+ numCtlModes = ARRAY_SIZE(ctlModesFor11a);
+ ath9k_hw_get_target_powers(ah, chan,
+ pEepData->calTargetPower5GHT40,
+ AR5416_NUM_5G_40_TARGET_POWERS,
+ &targetPowerHt40, 8, true);
+ ath9k_hw_get_legacy_target_powers(ah, chan,
+ pEepData->calTargetPower5G,
+ AR5416_NUM_5G_20_TARGET_POWERS,
+ &targetPowerOfdmExt, 4, true);
+ }
+ }
+
+ for (ctlMode = 0; ctlMode < numCtlModes; ctlMode++) {
+ bool isHt40CtlMode = (pCtlMode[ctlMode] == CTL_5GHT40) ||
+ (pCtlMode[ctlMode] == CTL_2GHT40);
+ if (isHt40CtlMode)
+ freq = centers.synth_center;
+ else if (pCtlMode[ctlMode] & EXT_ADDITIVE)
+ freq = centers.ext_center;
+ else
+ freq = centers.ctl_center;
+
+ if (ah->eep_ops->get_eeprom_ver(ah) == 14 &&
+ ah->eep_ops->get_eeprom_rev(ah) <= 2)
+ twiceMaxEdgePower = AR5416_MAX_RATE_POWER;
+
+ for (i = 0; (i < AR5416_NUM_CTLS) && pEepData->ctlIndex[i]; i++) {
+ if ((((cfgCtl & ~CTL_MODE_M) |
+ (pCtlMode[ctlMode] & CTL_MODE_M)) ==
+ pEepData->ctlIndex[i]) ||
+ (((cfgCtl & ~CTL_MODE_M) |
+ (pCtlMode[ctlMode] & CTL_MODE_M)) ==
+ ((pEepData->ctlIndex[i] & CTL_MODE_M) | SD_NO_CTL))) {
+ rep = &(pEepData->ctlData[i]);
+
+ twiceMinEdgePower = ath9k_hw_get_max_edge_power(freq,
+ rep->ctlEdges[ar5416_get_ntxchains(tx_chainmask) - 1],
+ IS_CHAN_2GHZ(chan), AR5416_NUM_BAND_EDGES);
+
+ if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL) {
+ twiceMaxEdgePower = min(twiceMaxEdgePower,
+ twiceMinEdgePower);
+ } else {
+ twiceMaxEdgePower = twiceMinEdgePower;
+ break;
+ }
+ }
+ }
+
+ minCtlPower = min(twiceMaxEdgePower, scaledPower);
+
+ switch (pCtlMode[ctlMode]) {
+ case CTL_11B:
+ for (i = 0; i < ARRAY_SIZE(targetPowerCck.tPow2x); i++) {
+ targetPowerCck.tPow2x[i] =
+ min((u16)targetPowerCck.tPow2x[i],
+ minCtlPower);
+ }
+ break;
+ case CTL_11A:
+ case CTL_11G:
+ for (i = 0; i < ARRAY_SIZE(targetPowerOfdm.tPow2x); i++) {
+ targetPowerOfdm.tPow2x[i] =
+ min((u16)targetPowerOfdm.tPow2x[i],
+ minCtlPower);
+ }
+ break;
+ case CTL_5GHT20:
+ case CTL_2GHT20:
+ for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); i++) {
+ targetPowerHt20.tPow2x[i] =
+ min((u16)targetPowerHt20.tPow2x[i],
+ minCtlPower);
+ }
+ break;
+ case CTL_11B_EXT:
+ targetPowerCckExt.tPow2x[0] = min((u16)
+ targetPowerCckExt.tPow2x[0],
+ minCtlPower);
+ break;
+ case CTL_11A_EXT:
+ case CTL_11G_EXT:
+ targetPowerOfdmExt.tPow2x[0] = min((u16)
+ targetPowerOfdmExt.tPow2x[0],
+ minCtlPower);
+ break;
+ case CTL_5GHT40:
+ case CTL_2GHT40:
+ for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++) {
+ targetPowerHt40.tPow2x[i] =
+ min((u16)targetPowerHt40.tPow2x[i],
+ minCtlPower);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ ratesArray[rate6mb] = ratesArray[rate9mb] = ratesArray[rate12mb] =
+ ratesArray[rate18mb] = ratesArray[rate24mb] =
+ targetPowerOfdm.tPow2x[0];
+ ratesArray[rate36mb] = targetPowerOfdm.tPow2x[1];
+ ratesArray[rate48mb] = targetPowerOfdm.tPow2x[2];
+ ratesArray[rate54mb] = targetPowerOfdm.tPow2x[3];
+ ratesArray[rateXr] = targetPowerOfdm.tPow2x[0];
+
+ for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); i++)
+ ratesArray[rateHt20_0 + i] = targetPowerHt20.tPow2x[i];
+
+ if (IS_CHAN_2GHZ(chan)) {
+ ratesArray[rate1l] = targetPowerCck.tPow2x[0];
+ ratesArray[rate2s] = ratesArray[rate2l] =
+ targetPowerCck.tPow2x[1];
+ ratesArray[rate5_5s] = ratesArray[rate5_5l] =
+ targetPowerCck.tPow2x[2];
+ ratesArray[rate11s] = ratesArray[rate11l] =
+ targetPowerCck.tPow2x[3];
+ }
+ if (IS_CHAN_HT40(chan)) {
+ for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++) {
+ ratesArray[rateHt40_0 + i] =
+ targetPowerHt40.tPow2x[i];
+ }
+ ratesArray[rateDupOfdm] = targetPowerHt40.tPow2x[0];
+ ratesArray[rateDupCck] = targetPowerHt40.tPow2x[0];
+ ratesArray[rateExtOfdm] = targetPowerOfdmExt.tPow2x[0];
+ if (IS_CHAN_2GHZ(chan)) {
+ ratesArray[rateExtCck] =
+ targetPowerCckExt.tPow2x[0];
+ }
+ }
+}
+
+static void ath9k_hw_def_set_txpower(struct ath_hw *ah,
+ struct ath9k_channel *chan,
+ u16 cfgCtl,
+ u8 twiceAntennaReduction,
+ u8 twiceMaxRegulatoryPower,
+ u8 powerLimit)
+{
+#define RT_AR_DELTA(x) (ratesArray[x] - cck_ofdm_delta)
+ struct ar5416_eeprom_def *pEepData = &ah->eeprom.def;
+ struct modal_eep_header *pModal =
+ &(pEepData->modalHeader[IS_CHAN_2GHZ(chan)]);
+ int16_t ratesArray[Ar5416RateSize];
+ int16_t txPowerIndexOffset = 0;
+ u8 ht40PowerIncForPdadc = 2;
+ int i, cck_ofdm_delta = 0;
+
+ memset(ratesArray, 0, sizeof(ratesArray));
+
+ if ((pEepData->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
+ AR5416_EEP_MINOR_VER_2) {
+ ht40PowerIncForPdadc = pModal->ht40PowerIncForPdadc;
+ }
+
+ ath9k_hw_set_def_power_per_rate_table(ah, chan,
+ &ratesArray[0], cfgCtl,
+ twiceAntennaReduction,
+ twiceMaxRegulatoryPower,
+ powerLimit);
+
+ ath9k_hw_set_def_power_cal_table(ah, chan, &txPowerIndexOffset);
+
+ for (i = 0; i < ARRAY_SIZE(ratesArray); i++) {
+ ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]);
+ if (ratesArray[i] > AR5416_MAX_RATE_POWER)
+ ratesArray[i] = AR5416_MAX_RATE_POWER;
+ }
+
+ if (AR_SREV_9280_10_OR_LATER(ah)) {
+ for (i = 0; i < Ar5416RateSize; i++)
+ ratesArray[i] -= AR5416_PWR_TABLE_OFFSET * 2;
+ }
+
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE1,
+ ATH9K_POW_SM(ratesArray[rate18mb], 24)
+ | ATH9K_POW_SM(ratesArray[rate12mb], 16)
+ | ATH9K_POW_SM(ratesArray[rate9mb], 8)
+ | ATH9K_POW_SM(ratesArray[rate6mb], 0));
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE2,
+ ATH9K_POW_SM(ratesArray[rate54mb], 24)
+ | ATH9K_POW_SM(ratesArray[rate48mb], 16)
+ | ATH9K_POW_SM(ratesArray[rate36mb], 8)
+ | ATH9K_POW_SM(ratesArray[rate24mb], 0));
+
+ if (IS_CHAN_2GHZ(chan)) {
+ if (OLC_FOR_AR9280_20_LATER) {
+ cck_ofdm_delta = 2;
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE3,
+ ATH9K_POW_SM(RT_AR_DELTA(rate2s), 24)
+ | ATH9K_POW_SM(RT_AR_DELTA(rate2l), 16)
+ | ATH9K_POW_SM(ratesArray[rateXr], 8)
+ | ATH9K_POW_SM(RT_AR_DELTA(rate1l), 0));
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE4,
+ ATH9K_POW_SM(RT_AR_DELTA(rate11s), 24)
+ | ATH9K_POW_SM(RT_AR_DELTA(rate11l), 16)
+ | ATH9K_POW_SM(RT_AR_DELTA(rate5_5s), 8)
+ | ATH9K_POW_SM(RT_AR_DELTA(rate5_5l), 0));
+ } else {
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE3,
+ ATH9K_POW_SM(ratesArray[rate2s], 24)
+ | ATH9K_POW_SM(ratesArray[rate2l], 16)
+ | ATH9K_POW_SM(ratesArray[rateXr], 8)
+ | ATH9K_POW_SM(ratesArray[rate1l], 0));
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE4,
+ ATH9K_POW_SM(ratesArray[rate11s], 24)
+ | ATH9K_POW_SM(ratesArray[rate11l], 16)
+ | ATH9K_POW_SM(ratesArray[rate5_5s], 8)
+ | ATH9K_POW_SM(ratesArray[rate5_5l], 0));
+ }
+ }
+
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE5,
+ ATH9K_POW_SM(ratesArray[rateHt20_3], 24)
+ | ATH9K_POW_SM(ratesArray[rateHt20_2], 16)
+ | ATH9K_POW_SM(ratesArray[rateHt20_1], 8)
+ | ATH9K_POW_SM(ratesArray[rateHt20_0], 0));
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE6,
+ ATH9K_POW_SM(ratesArray[rateHt20_7], 24)
+ | ATH9K_POW_SM(ratesArray[rateHt20_6], 16)
+ | ATH9K_POW_SM(ratesArray[rateHt20_5], 8)
+ | ATH9K_POW_SM(ratesArray[rateHt20_4], 0));
+
+ if (IS_CHAN_HT40(chan)) {
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE7,
+ ATH9K_POW_SM(ratesArray[rateHt40_3] +
+ ht40PowerIncForPdadc, 24)
+ | ATH9K_POW_SM(ratesArray[rateHt40_2] +
+ ht40PowerIncForPdadc, 16)
+ | ATH9K_POW_SM(ratesArray[rateHt40_1] +
+ ht40PowerIncForPdadc, 8)
+ | ATH9K_POW_SM(ratesArray[rateHt40_0] +
+ ht40PowerIncForPdadc, 0));
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE8,
+ ATH9K_POW_SM(ratesArray[rateHt40_7] +
+ ht40PowerIncForPdadc, 24)
+ | ATH9K_POW_SM(ratesArray[rateHt40_6] +
+ ht40PowerIncForPdadc, 16)
+ | ATH9K_POW_SM(ratesArray[rateHt40_5] +
+ ht40PowerIncForPdadc, 8)
+ | ATH9K_POW_SM(ratesArray[rateHt40_4] +
+ ht40PowerIncForPdadc, 0));
+ if (OLC_FOR_AR9280_20_LATER) {
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE9,
+ ATH9K_POW_SM(ratesArray[rateExtOfdm], 24)
+ | ATH9K_POW_SM(RT_AR_DELTA(rateExtCck), 16)
+ | ATH9K_POW_SM(ratesArray[rateDupOfdm], 8)
+ | ATH9K_POW_SM(RT_AR_DELTA(rateDupCck), 0));
+ } else {
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE9,
+ ATH9K_POW_SM(ratesArray[rateExtOfdm], 24)
+ | ATH9K_POW_SM(ratesArray[rateExtCck], 16)
+ | ATH9K_POW_SM(ratesArray[rateDupOfdm], 8)
+ | ATH9K_POW_SM(ratesArray[rateDupCck], 0));
+ }
+ }
+
+ REG_WRITE(ah, AR_PHY_POWER_TX_SUB,
+ ATH9K_POW_SM(pModal->pwrDecreaseFor3Chain, 6)
+ | ATH9K_POW_SM(pModal->pwrDecreaseFor2Chain, 0));
+
+ i = rate6mb;
+
+ if (IS_CHAN_HT40(chan))
+ i = rateHt40_0;
+ else if (IS_CHAN_HT20(chan))
+ i = rateHt20_0;
+
+ if (AR_SREV_9280_10_OR_LATER(ah))
+ ah->regulatory.max_power_level =
+ ratesArray[i] + AR5416_PWR_TABLE_OFFSET * 2;
+ else
+ ah->regulatory.max_power_level = ratesArray[i];
+
+ switch(ar5416_get_ntxchains(ah->txchainmask)) {
+ case 1:
+ break;
+ case 2:
+ ah->regulatory.max_power_level += INCREASE_MAXPOW_BY_TWO_CHAIN;
+ break;
+ case 3:
+ ah->regulatory.max_power_level += INCREASE_MAXPOW_BY_THREE_CHAIN;
+ break;
+ default:
+ DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
+ "Invalid chainmask configuration\n");
+ break;
+ }
+}
+
+static u8 ath9k_hw_def_get_num_ant_config(struct ath_hw *ah,
+ enum ieee80211_band freq_band)
+{
+ struct ar5416_eeprom_def *eep = &ah->eeprom.def;
+ struct modal_eep_header *pModal =
+ &(eep->modalHeader[ATH9K_HAL_FREQ_BAND_2GHZ == freq_band]);
+ struct base_eep_header *pBase = &eep->baseEepHeader;
+ u8 num_ant_config;
+
+ num_ant_config = 1;
+
+ if (pBase->version >= 0x0E0D)
+ if (pModal->useAnt1)
+ num_ant_config += 1;
+
+ return num_ant_config;
+}
+
+static u16 ath9k_hw_def_get_eeprom_antenna_cfg(struct ath_hw *ah,
+ struct ath9k_channel *chan)
+{
+ struct ar5416_eeprom_def *eep = &ah->eeprom.def;
+ struct modal_eep_header *pModal =
+ &(eep->modalHeader[IS_CHAN_2GHZ(chan)]);
+
+ return pModal->antCtrlCommon & 0xFFFF;
+}
+
+static u16 ath9k_hw_def_get_spur_channel(struct ath_hw *ah, u16 i, bool is2GHz)
+{
+#define EEP_DEF_SPURCHAN \
+ (ah->eeprom.def.modalHeader[is2GHz].spurChans[i].spurChan)
+
+ u16 spur_val = AR_NO_SPUR;
+
+ DPRINTF(ah->ah_sc, ATH_DBG_ANI,
+ "Getting spur idx %d is2Ghz. %d val %x\n",
+ i, is2GHz, ah->config.spurchans[i][is2GHz]);
+
+ switch (ah->config.spurmode) {
+ case SPUR_DISABLE:
+ break;
+ case SPUR_ENABLE_IOCTL:
+ spur_val = ah->config.spurchans[i][is2GHz];
+ DPRINTF(ah->ah_sc, ATH_DBG_ANI,
+ "Getting spur val from new loc. %d\n", spur_val);
+ break;
+ case SPUR_ENABLE_EEPROM:
+ spur_val = EEP_DEF_SPURCHAN;
+ break;
+ }
+
+ return spur_val;
+
+#undef EEP_DEF_SPURCHAN
+}
+
+const struct eeprom_ops eep_def_ops = {
+ .check_eeprom = ath9k_hw_def_check_eeprom,
+ .get_eeprom = ath9k_hw_def_get_eeprom,
+ .fill_eeprom = ath9k_hw_def_fill_eeprom,
+ .get_eeprom_ver = ath9k_hw_def_get_eeprom_ver,
+ .get_eeprom_rev = ath9k_hw_def_get_eeprom_rev,
+ .get_num_ant_config = ath9k_hw_def_get_num_ant_config,
+ .get_eeprom_antenna_cfg = ath9k_hw_def_get_eeprom_antenna_cfg,
+ .set_board_values = ath9k_hw_def_set_board_values,
+ .set_addac = ath9k_hw_def_set_addac,
+ .set_txpower = ath9k_hw_def_set_txpower,
+ .get_spur_channel = ath9k_hw_def_get_spur_channel
+};
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index 34935a8ee59..9f1b34d9861 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -380,12 +380,15 @@ static const char *ath9k_hw_devname(u16 devid)
return "Atheros 9280";
case AR9285_DEVID_PCIE:
return "Atheros 9285";
+ case AR5416_DEVID_AR9287_PCI:
+ case AR5416_DEVID_AR9287_PCIE:
+ return "Atheros 9287";
}
return NULL;
}
-static void ath9k_hw_set_defaults(struct ath_hw *ah)
+static void ath9k_hw_init_config(struct ath_hw *ah)
{
int i;
@@ -404,7 +407,7 @@ static void ath9k_hw_set_defaults(struct ath_hw *ah)
ah->config.cck_trig_high = 200;
ah->config.cck_trig_low = 100;
ah->config.enable_ani = 1;
- ah->config.diversity_control = 0;
+ ah->config.diversity_control = ATH9K_ANT_VARIABLE;
ah->config.antenna_switch_swap = 0;
for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) {
@@ -434,27 +437,14 @@ static void ath9k_hw_set_defaults(struct ath_hw *ah)
ah->config.serialize_regmode = SER_REG_MODE_AUTO;
}
-static struct ath_hw *ath9k_hw_newstate(u16 devid, struct ath_softc *sc,
- int *status)
+static void ath9k_hw_init_defaults(struct ath_hw *ah)
{
- struct ath_hw *ah;
-
- ah = kzalloc(sizeof(struct ath_hw), GFP_KERNEL);
- if (ah == NULL) {
- DPRINTF(sc, ATH_DBG_FATAL,
- "Cannot allocate memory for state block\n");
- *status = -ENOMEM;
- return NULL;
- }
-
- ah->ah_sc = sc;
ah->hw_version.magic = AR5416_MAGIC;
ah->regulatory.country_code = CTRY_DEFAULT;
- ah->hw_version.devid = devid;
ah->hw_version.subvendorid = 0;
ah->ah_flags = 0;
- if ((devid == AR5416_AR9100_DEVID))
+ if (ah->hw_version.devid == AR5416_AR9100_DEVID)
ah->hw_version.macVersion = AR_SREV_VERSION_9100;
if (!AR_SREV_9100(ah))
ah->ah_flags = AH_USE_EEPROM;
@@ -462,9 +452,6 @@ static struct ath_hw *ath9k_hw_newstate(u16 devid, struct ath_softc *sc,
ah->regulatory.power_limit = MAX_RATE_POWER;
ah->regulatory.tp_scale = ATH9K_TP_SCALE_MAX;
ah->atim_window = 0;
- ah->diversity_control = ah->config.diversity_control;
- ah->antenna_switch_swap =
- ah->config.antenna_switch_swap;
ah->sta_id1_defaults = AR_STA_ID1_CRPT_MIC_ENABLE;
ah->beacon_interval = 100;
ah->enable_32kHz_clock = DONT_USE_32KHZ;
@@ -475,7 +462,7 @@ static struct ath_hw *ath9k_hw_newstate(u16 devid, struct ath_softc *sc,
ah->gbeacon_rate = 0;
- return ah;
+ ah->power_mode = ATH9K_PM_UNDEFINED;
}
static int ath9k_hw_rfattach(struct ath_hw *ah)
@@ -588,7 +575,7 @@ static void ath9k_hw_init_txgain_ini(struct ath_hw *ah)
}
}
-static int ath9k_hw_post_attach(struct ath_hw *ah)
+static int ath9k_hw_post_init(struct ath_hw *ah)
{
int ecode;
@@ -599,7 +586,7 @@ static int ath9k_hw_post_attach(struct ath_hw *ah)
if (ecode != 0)
return ecode;
- ecode = ath9k_hw_eeprom_attach(ah);
+ ecode = ath9k_hw_eeprom_init(ah);
if (ecode != 0)
return ecode;
@@ -612,70 +599,52 @@ static int ath9k_hw_post_attach(struct ath_hw *ah)
if (!AR_SREV_9100(ah)) {
ath9k_hw_ani_setup(ah);
- ath9k_hw_ani_attach(ah);
+ ath9k_hw_ani_init(ah);
}
return 0;
}
-static struct ath_hw *ath9k_hw_do_attach(u16 devid, struct ath_softc *sc,
- int *status)
+static bool ath9k_hw_devid_supported(u16 devid)
{
- struct ath_hw *ah;
- int ecode;
- u32 i, j;
-
- ah = ath9k_hw_newstate(devid, sc, status);
- if (ah == NULL)
- return NULL;
-
- ath9k_hw_set_defaults(ah);
-
- if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_POWER_ON)) {
- DPRINTF(sc, ATH_DBG_FATAL, "Couldn't reset chip\n");
- ecode = -EIO;
- goto bad;
- }
-
- if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) {
- DPRINTF(sc, ATH_DBG_FATAL, "Couldn't wakeup chip\n");
- ecode = -EIO;
- goto bad;
- }
-
- if (ah->config.serialize_regmode == SER_REG_MODE_AUTO) {
- if (ah->hw_version.macVersion == AR_SREV_VERSION_5416_PCI ||
- (AR_SREV_9280(ah) && !ah->is_pciexpress)) {
- ah->config.serialize_regmode =
- SER_REG_MODE_ON;
- } else {
- ah->config.serialize_regmode =
- SER_REG_MODE_OFF;
- }
- }
-
- DPRINTF(sc, ATH_DBG_RESET, "serialize_regmode is %d\n",
- ah->config.serialize_regmode);
-
- if ((ah->hw_version.macVersion != AR_SREV_VERSION_5416_PCI) &&
- (ah->hw_version.macVersion != AR_SREV_VERSION_5416_PCIE) &&
- (ah->hw_version.macVersion != AR_SREV_VERSION_9160) &&
- (!AR_SREV_9100(ah)) && (!AR_SREV_9280(ah)) && (!AR_SREV_9285(ah))) {
- DPRINTF(sc, ATH_DBG_FATAL,
- "Mac Chip Rev 0x%02x.%x is not supported by "
- "this driver\n", ah->hw_version.macVersion,
- ah->hw_version.macRev);
- ecode = -EOPNOTSUPP;
- goto bad;
+ switch (devid) {
+ case AR5416_DEVID_PCI:
+ case AR5416_DEVID_PCIE:
+ case AR5416_AR9100_DEVID:
+ case AR9160_DEVID_PCI:
+ case AR9280_DEVID_PCI:
+ case AR9280_DEVID_PCIE:
+ case AR9285_DEVID_PCIE:
+ case AR5416_DEVID_AR9287_PCI:
+ case AR5416_DEVID_AR9287_PCIE:
+ return true;
+ default:
+ break;
}
+ return false;
+}
- if (AR_SREV_9100(ah)) {
- ah->iq_caldata.calData = &iq_cal_multi_sample;
- ah->supp_cals = IQ_MISMATCH_CAL;
- ah->is_pciexpress = false;
+static bool ath9k_hw_macversion_supported(u32 macversion)
+{
+ switch (macversion) {
+ case AR_SREV_VERSION_5416_PCI:
+ case AR_SREV_VERSION_5416_PCIE:
+ case AR_SREV_VERSION_9160:
+ case AR_SREV_VERSION_9100:
+ case AR_SREV_VERSION_9280:
+ case AR_SREV_VERSION_9285:
+ case AR_SREV_VERSION_9287:
+ return true;
+ /* Not yet */
+ case AR_SREV_VERSION_9271:
+ default:
+ break;
}
- ah->hw_version.phyRev = REG_READ(ah, AR_PHY_CHIP_ID);
+ return false;
+}
+static void ath9k_hw_init_cal_settings(struct ath_hw *ah)
+{
if (AR_SREV_9160_10_OR_LATER(ah)) {
if (AR_SREV_9280_10_OR_LATER(ah)) {
ah->iq_caldata.calData = &iq_cal_single_sample;
@@ -696,12 +665,49 @@ static struct ath_hw *ath9k_hw_do_attach(u16 devid, struct ath_softc *sc,
}
ah->supp_cals = ADC_GAIN_CAL | ADC_DC_CAL | IQ_MISMATCH_CAL;
}
+}
- ah->ani_function = ATH9K_ANI_ALL;
- if (AR_SREV_9280_10_OR_LATER(ah))
- ah->ani_function &= ~ATH9K_ANI_NOISE_IMMUNITY_LEVEL;
+static void ath9k_hw_init_mode_regs(struct ath_hw *ah)
+{
+ if (AR_SREV_9271(ah)) {
+ INIT_INI_ARRAY(&ah->iniModes, ar9271Modes_9271_1_0,
+ ARRAY_SIZE(ar9271Modes_9271_1_0), 6);
+ INIT_INI_ARRAY(&ah->iniCommon, ar9271Common_9271_1_0,
+ ARRAY_SIZE(ar9271Common_9271_1_0), 2);
+ return;
+ }
+
+ if (AR_SREV_9287_11_OR_LATER(ah)) {
+ INIT_INI_ARRAY(&ah->iniModes, ar9287Modes_9287_1_1,
+ ARRAY_SIZE(ar9287Modes_9287_1_1), 6);
+ INIT_INI_ARRAY(&ah->iniCommon, ar9287Common_9287_1_1,
+ ARRAY_SIZE(ar9287Common_9287_1_1), 2);
+ if (ah->config.pcie_clock_req)
+ INIT_INI_ARRAY(&ah->iniPcieSerdes,
+ ar9287PciePhy_clkreq_off_L1_9287_1_1,
+ ARRAY_SIZE(ar9287PciePhy_clkreq_off_L1_9287_1_1), 2);
+ else
+ INIT_INI_ARRAY(&ah->iniPcieSerdes,
+ ar9287PciePhy_clkreq_always_on_L1_9287_1_1,
+ ARRAY_SIZE(ar9287PciePhy_clkreq_always_on_L1_9287_1_1),
+ 2);
+ } else if (AR_SREV_9287_10_OR_LATER(ah)) {
+ INIT_INI_ARRAY(&ah->iniModes, ar9287Modes_9287_1_0,
+ ARRAY_SIZE(ar9287Modes_9287_1_0), 6);
+ INIT_INI_ARRAY(&ah->iniCommon, ar9287Common_9287_1_0,
+ ARRAY_SIZE(ar9287Common_9287_1_0), 2);
+
+ if (ah->config.pcie_clock_req)
+ INIT_INI_ARRAY(&ah->iniPcieSerdes,
+ ar9287PciePhy_clkreq_off_L1_9287_1_0,
+ ARRAY_SIZE(ar9287PciePhy_clkreq_off_L1_9287_1_0), 2);
+ else
+ INIT_INI_ARRAY(&ah->iniPcieSerdes,
+ ar9287PciePhy_clkreq_always_on_L1_9287_1_0,
+ ARRAY_SIZE(ar9287PciePhy_clkreq_always_on_L1_9287_1_0),
+ 2);
+ } else if (AR_SREV_9285_12_OR_LATER(ah)) {
- if (AR_SREV_9285_12_OR_LATER(ah)) {
INIT_INI_ARRAY(&ah->iniModes, ar9285Modes_9285_1_2,
ARRAY_SIZE(ar9285Modes_9285_1_2), 6);
@@ -832,17 +838,32 @@ static struct ath_hw *ath9k_hw_do_attach(u16 devid, struct ath_softc *sc,
INIT_INI_ARRAY(&ah->iniAddac, ar5416Addac,
ARRAY_SIZE(ar5416Addac), 2);
}
+}
- if (ah->is_pciexpress)
- ath9k_hw_configpcipowersave(ah, 0);
- else
- ath9k_hw_disablepcie(ah);
-
- ecode = ath9k_hw_post_attach(ah);
- if (ecode != 0)
- goto bad;
+static void ath9k_hw_init_mode_gain_regs(struct ath_hw *ah)
+{
+ if (AR_SREV_9287_11(ah))
+ INIT_INI_ARRAY(&ah->iniModesRxGain,
+ ar9287Modes_rx_gain_9287_1_1,
+ ARRAY_SIZE(ar9287Modes_rx_gain_9287_1_1), 6);
+ else if (AR_SREV_9287_10(ah))
+ INIT_INI_ARRAY(&ah->iniModesRxGain,
+ ar9287Modes_rx_gain_9287_1_0,
+ ARRAY_SIZE(ar9287Modes_rx_gain_9287_1_0), 6);
+ else if (AR_SREV_9280_20(ah))
+ ath9k_hw_init_rxgain_ini(ah);
- if (AR_SREV_9285_12_OR_LATER(ah)) {
+ if (AR_SREV_9287_11(ah)) {
+ INIT_INI_ARRAY(&ah->iniModesTxGain,
+ ar9287Modes_tx_gain_9287_1_1,
+ ARRAY_SIZE(ar9287Modes_tx_gain_9287_1_1), 6);
+ } else if (AR_SREV_9287_10(ah)) {
+ INIT_INI_ARRAY(&ah->iniModesTxGain,
+ ar9287Modes_tx_gain_9287_1_0,
+ ARRAY_SIZE(ar9287Modes_tx_gain_9287_1_0), 6);
+ } else if (AR_SREV_9280_20(ah)) {
+ ath9k_hw_init_txgain_ini(ah);
+ } else if (AR_SREV_9285_12_OR_LATER(ah)) {
u32 txgain_type = ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE);
/* txgain table */
@@ -857,16 +878,11 @@ static struct ath_hw *ath9k_hw_do_attach(u16 devid, struct ath_softc *sc,
}
}
+}
- /* rxgain table */
- if (AR_SREV_9280_20(ah))
- ath9k_hw_init_rxgain_ini(ah);
-
- /* txgain table */
- if (AR_SREV_9280_20(ah))
- ath9k_hw_init_txgain_ini(ah);
-
- ath9k_hw_fill_cap_info(ah);
+static void ath9k_hw_init_11a_eeprom_fix(struct ath_hw *ah)
+{
+ u32 i, j;
if ((ah->hw_version.devid == AR9280_DEVID_PCI) &&
test_bit(ATH9K_MODE_11A, ah->caps.wireless_modes)) {
@@ -885,29 +901,97 @@ static struct ath_hw *ath9k_hw_do_attach(u16 devid, struct ath_softc *sc,
}
}
}
+}
+
+int ath9k_hw_init(struct ath_hw *ah)
+{
+ int r = 0;
+
+ if (!ath9k_hw_devid_supported(ah->hw_version.devid))
+ return -EOPNOTSUPP;
+
+ ath9k_hw_init_defaults(ah);
+ ath9k_hw_init_config(ah);
+
+ if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_POWER_ON)) {
+ DPRINTF(ah->ah_sc, ATH_DBG_FATAL, "Couldn't reset chip\n");
+ return -EIO;
+ }
+
+ if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) {
+ DPRINTF(ah->ah_sc, ATH_DBG_FATAL, "Couldn't wakeup chip\n");
+ return -EIO;
+ }
+
+ if (ah->config.serialize_regmode == SER_REG_MODE_AUTO) {
+ if (ah->hw_version.macVersion == AR_SREV_VERSION_5416_PCI ||
+ (AR_SREV_9280(ah) && !ah->is_pciexpress)) {
+ ah->config.serialize_regmode =
+ SER_REG_MODE_ON;
+ } else {
+ ah->config.serialize_regmode =
+ SER_REG_MODE_OFF;
+ }
+ }
+
+ DPRINTF(ah->ah_sc, ATH_DBG_RESET, "serialize_regmode is %d\n",
+ ah->config.serialize_regmode);
+
+ if (!ath9k_hw_macversion_supported(ah->hw_version.macVersion)) {
+ DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
+ "Mac Chip Rev 0x%02x.%x is not supported by "
+ "this driver\n", ah->hw_version.macVersion,
+ ah->hw_version.macRev);
+ return -EOPNOTSUPP;
+ }
+
+ if (AR_SREV_9100(ah)) {
+ ah->iq_caldata.calData = &iq_cal_multi_sample;
+ ah->supp_cals = IQ_MISMATCH_CAL;
+ ah->is_pciexpress = false;
+ }
+
+ if (AR_SREV_9271(ah))
+ ah->is_pciexpress = false;
+
+ ah->hw_version.phyRev = REG_READ(ah, AR_PHY_CHIP_ID);
+
+ ath9k_hw_init_cal_settings(ah);
+
+ ah->ani_function = ATH9K_ANI_ALL;
+ if (AR_SREV_9280_10_OR_LATER(ah))
+ ah->ani_function &= ~ATH9K_ANI_NOISE_IMMUNITY_LEVEL;
+
+ ath9k_hw_init_mode_regs(ah);
+
+ if (ah->is_pciexpress)
+ ath9k_hw_configpcipowersave(ah, 0);
+ else
+ ath9k_hw_disablepcie(ah);
+
+ r = ath9k_hw_post_init(ah);
+ if (r)
+ return r;
+
+ ath9k_hw_init_mode_gain_regs(ah);
+ ath9k_hw_fill_cap_info(ah);
+ ath9k_hw_init_11a_eeprom_fix(ah);
- ecode = ath9k_hw_init_macaddr(ah);
- if (ecode != 0) {
- DPRINTF(sc, ATH_DBG_FATAL,
+ r = ath9k_hw_init_macaddr(ah);
+ if (r) {
+ DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
"Failed to initialize MAC address\n");
- goto bad;
+ return r;
}
- if (AR_SREV_9285(ah))
+ if (AR_SREV_9285(ah) || AR_SREV_9271(ah))
ah->tx_trig_level = (AR_FTRIG_256B >> AR_FTRIG_S);
else
ah->tx_trig_level = (AR_FTRIG_512B >> AR_FTRIG_S);
ath9k_init_nfcal_hist_buffer(ah);
- return ah;
-bad:
- if (ah)
- ath9k_hw_detach(ah);
- if (status)
- *status = ecode;
-
- return NULL;
+ return 0;
}
static void ath9k_hw_init_bb(struct ath_hw *ah,
@@ -1146,33 +1230,12 @@ const char *ath9k_hw_probe(u16 vendorid, u16 devid)
void ath9k_hw_detach(struct ath_hw *ah)
{
if (!AR_SREV_9100(ah))
- ath9k_hw_ani_detach(ah);
+ ath9k_hw_ani_disable(ah);
- ath9k_hw_rfdetach(ah);
+ ath9k_hw_rf_free(ah);
ath9k_hw_setpower(ah, ATH9K_PM_FULL_SLEEP);
kfree(ah);
-}
-
-struct ath_hw *ath9k_hw_attach(u16 devid, struct ath_softc *sc, int *error)
-{
- struct ath_hw *ah = NULL;
-
- switch (devid) {
- case AR5416_DEVID_PCI:
- case AR5416_DEVID_PCIE:
- case AR5416_AR9100_DEVID:
- case AR9160_DEVID_PCI:
- case AR9280_DEVID_PCI:
- case AR9280_DEVID_PCIE:
- case AR9285_DEVID_PCIE:
- ah = ath9k_hw_do_attach(devid, sc, error);
- break;
- default:
- *error = -ENXIO;
- break;
- }
-
- return ah;
+ ah = NULL;
}
/*******/
@@ -1182,6 +1245,27 @@ struct ath_hw *ath9k_hw_attach(u16 devid, struct ath_softc *sc, int *error)
static void ath9k_hw_override_ini(struct ath_hw *ah,
struct ath9k_channel *chan)
{
+ u32 val;
+
+ if (AR_SREV_9271(ah)) {
+ /*
+ * Enable spectral scan to solution for issues with stuck
+ * beacons on AR9271 1.0. The beacon stuck issue is not seeon on
+ * AR9271 1.1
+ */
+ if (AR_SREV_9271_10(ah)) {
+ val = REG_READ(ah, AR_PHY_SPECTRAL_SCAN) | AR_PHY_SPECTRAL_SCAN_ENABLE;
+ REG_WRITE(ah, AR_PHY_SPECTRAL_SCAN, val);
+ }
+ else if (AR_SREV_9271_11(ah))
+ /*
+ * change AR_PHY_RF_CTL3 setting to fix MAC issue
+ * present on AR9271 1.1
+ */
+ REG_WRITE(ah, AR_PHY_RF_CTL3, 0x3a020001);
+ return;
+ }
+
/*
* Set the RX_ABORT and RX_DIS and clear if off only after
* RXE is set for MAC. This prevents frames with corrupted
@@ -1193,7 +1277,10 @@ static void ath9k_hw_override_ini(struct ath_hw *ah,
if (!AR_SREV_5416_20_OR_LATER(ah) ||
AR_SREV_9280_10_OR_LATER(ah))
return;
-
+ /*
+ * Disable BB clock gating
+ * Necessary to avoid issues on AR5416 2.0
+ */
REG_WRITE(ah, 0x9800 + (651 << 2), 0x11);
}
@@ -1341,10 +1428,11 @@ static int ath9k_hw_process_ini(struct ath_hw *ah,
DO_DELAY(regWrites);
}
- if (AR_SREV_9280(ah))
+ if (AR_SREV_9280(ah) || AR_SREV_9287_10_OR_LATER(ah))
REG_WRITE_ARRAY(&ah->iniModesRxGain, modesIndex, regWrites);
- if (AR_SREV_9280(ah) || AR_SREV_9285_12_OR_LATER(ah))
+ if (AR_SREV_9280(ah) || AR_SREV_9285_12_OR_LATER(ah) ||
+ AR_SREV_9287_10_OR_LATER(ah))
REG_WRITE_ARRAY(&ah->iniModesTxGain, modesIndex, regWrites);
for (i = 0; i < ah->iniCommon.ia_rows; i++) {
@@ -1424,23 +1512,48 @@ static inline void ath9k_hw_set_dma(struct ath_hw *ah)
{
u32 regval;
+ /*
+ * set AHB_MODE not to do cacheline prefetches
+ */
regval = REG_READ(ah, AR_AHB_MODE);
REG_WRITE(ah, AR_AHB_MODE, regval | AR_AHB_PREFETCH_RD_EN);
+ /*
+ * let mac dma reads be in 128 byte chunks
+ */
regval = REG_READ(ah, AR_TXCFG) & ~AR_TXCFG_DMASZ_MASK;
REG_WRITE(ah, AR_TXCFG, regval | AR_TXCFG_DMASZ_128B);
+ /*
+ * Restore TX Trigger Level to its pre-reset value.
+ * The initial value depends on whether aggregation is enabled, and is
+ * adjusted whenever underruns are detected.
+ */
REG_RMW_FIELD(ah, AR_TXCFG, AR_FTRIG, ah->tx_trig_level);
+ /*
+ * let mac dma writes be in 128 byte chunks
+ */
regval = REG_READ(ah, AR_RXCFG) & ~AR_RXCFG_DMASZ_MASK;
REG_WRITE(ah, AR_RXCFG, regval | AR_RXCFG_DMASZ_128B);
+ /*
+ * Setup receive FIFO threshold to hold off TX activities
+ */
REG_WRITE(ah, AR_RXFIFO_CFG, 0x200);
+ /*
+ * reduce the number of usable entries in PCU TXBUF to avoid
+ * wrap around issues.
+ */
if (AR_SREV_9285(ah)) {
+ /* For AR9285 the number of Fifos are reduced to half.
+ * So set the usable tx buf size also to half to
+ * avoid data/delimiter underruns
+ */
REG_WRITE(ah, AR_PCU_TXBUF_CTRL,
AR_9285_PCU_TXBUF_CTRL_USABLE_SIZE);
- } else {
+ } else if (!AR_SREV_9271(ah)) {
REG_WRITE(ah, AR_PCU_TXBUF_CTRL,
AR_PCU_TXBUF_CTRL_USABLE_SIZE);
}
@@ -2246,14 +2359,39 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
ath9k_hw_mark_phy_inactive(ah);
+ if (AR_SREV_9271(ah) && ah->htc_reset_init) {
+ REG_WRITE(ah,
+ AR9271_RESET_POWER_DOWN_CONTROL,
+ AR9271_RADIO_RF_RST);
+ udelay(50);
+ }
+
if (!ath9k_hw_chip_reset(ah, chan)) {
DPRINTF(ah->ah_sc, ATH_DBG_FATAL, "Chip reset failed\n");
return -EINVAL;
}
+ if (AR_SREV_9271(ah) && ah->htc_reset_init) {
+ ah->htc_reset_init = false;
+ REG_WRITE(ah,
+ AR9271_RESET_POWER_DOWN_CONTROL,
+ AR9271_GATE_MAC_CTL);
+ udelay(50);
+ }
+
if (AR_SREV_9280_10_OR_LATER(ah))
REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, AR_GPIO_JTAG_DISABLE);
+ if (AR_SREV_9287_10_OR_LATER(ah)) {
+ /* Enable ASYNC FIFO */
+ REG_SET_BIT(ah, AR_MAC_PCU_ASYNC_FIFO_REG3,
+ AR_MAC_PCU_ASYNC_FIFO_REG3_DATAPATH_SEL);
+ REG_SET_BIT(ah, AR_PHY_MODE, AR_PHY_MODE_ASYNCFIFO);
+ REG_CLR_BIT(ah, AR_MAC_PCU_ASYNC_FIFO_REG3,
+ AR_MAC_PCU_ASYNC_FIFO_REG3_SOFT_RESET);
+ REG_SET_BIT(ah, AR_MAC_PCU_ASYNC_FIFO_REG3,
+ AR_MAC_PCU_ASYNC_FIFO_REG3_SOFT_RESET);
+ }
r = ath9k_hw_process_ini(ah, chan, sc->tx_chan_width);
if (r)
return r;
@@ -2330,6 +2468,27 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
ath9k_hw_init_user_settings(ah);
+ if (AR_SREV_9287_10_OR_LATER(ah)) {
+ REG_WRITE(ah, AR_D_GBL_IFS_SIFS,
+ AR_D_GBL_IFS_SIFS_ASYNC_FIFO_DUR);
+ REG_WRITE(ah, AR_D_GBL_IFS_SLOT,
+ AR_D_GBL_IFS_SLOT_ASYNC_FIFO_DUR);
+ REG_WRITE(ah, AR_D_GBL_IFS_EIFS,
+ AR_D_GBL_IFS_EIFS_ASYNC_FIFO_DUR);
+
+ REG_WRITE(ah, AR_TIME_OUT, AR_TIME_OUT_ACK_CTS_ASYNC_FIFO_DUR);
+ REG_WRITE(ah, AR_USEC, AR_USEC_ASYNC_FIFO_DUR);
+
+ REG_SET_BIT(ah, AR_MAC_PCU_LOGIC_ANALYZER,
+ AR_MAC_PCU_LOGIC_ANALYZER_DISBUG20768);
+ REG_RMW_FIELD(ah, AR_AHB_MODE, AR_AHB_CUSTOM_BURST_EN,
+ AR_AHB_CUSTOM_BURST_ASYNC_FIFO_VAL);
+ }
+ if (AR_SREV_9287_10_OR_LATER(ah)) {
+ REG_SET_BIT(ah, AR_PCU_MISC_MODE2,
+ AR_PCU_MISC_MODE2_ENABLE_AGGWEP);
+ }
+
REG_WRITE(ah, AR_STA_ID1,
REG_READ(ah, AR_STA_ID1) | AR_STA_ID1_PRESERVE_SEQNUM);
@@ -2345,7 +2504,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
ath9k_hw_init_bb(ah, chan);
if (!ath9k_hw_init_cal(ah, chan))
- return -EIO;;
+ return -EIO;
rx_chainmask = ah->rxchainmask;
if ((rx_chainmask == 0x5) || (rx_chainmask == 0x3)) {
@@ -2355,6 +2514,9 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
REG_WRITE(ah, AR_CFG_LED, saveLedState | AR_CFG_SCLK_32KHZ);
+ /*
+ * For big endian systems turn on swapping for descriptors
+ */
if (AR_SREV_9100(ah)) {
u32 mask;
mask = REG_READ(ah, AR_CFG);
@@ -2369,8 +2531,12 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
"Setting CFG 0x%x\n", REG_READ(ah, AR_CFG));
}
} else {
+ /* Configure AR9271 target WLAN */
+ if (AR_SREV_9271(ah))
+ REG_WRITE(ah, AR_CFG, AR_CFG_SWRB | AR_CFG_SWTB);
#ifdef __BIG_ENDIAN
- REG_WRITE(ah, AR_CFG, AR_CFG_SWTD | AR_CFG_SWRD);
+ else
+ REG_WRITE(ah, AR_CFG, AR_CFG_SWTD | AR_CFG_SWRD);
#endif
}
@@ -2412,9 +2578,6 @@ bool ath9k_hw_keyreset(struct ath_hw *ah, u16 entry)
}
- if (ah->curchan == NULL)
- return true;
-
return true;
}
@@ -2728,7 +2891,8 @@ static bool ath9k_hw_set_power_awake(struct ath_hw *ah, int setChip)
return true;
}
-bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode)
+static bool ath9k_hw_setpower_nolock(struct ath_hw *ah,
+ enum ath9k_power_mode mode)
{
int status = true, setChip = true;
static const char *modes[] = {
@@ -2738,6 +2902,9 @@ bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode)
"UNDEFINED"
};
+ if (ah->power_mode == mode)
+ return status;
+
DPRINTF(ah->ah_sc, ATH_DBG_RESET, "%s -> %s\n",
modes[ah->power_mode], modes[mode]);
@@ -2762,6 +2929,51 @@ bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode)
return status;
}
+bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode)
+{
+ unsigned long flags;
+ bool ret;
+
+ spin_lock_irqsave(&ah->ah_sc->sc_pm_lock, flags);
+ ret = ath9k_hw_setpower_nolock(ah, mode);
+ spin_unlock_irqrestore(&ah->ah_sc->sc_pm_lock, flags);
+
+ return ret;
+}
+
+void ath9k_ps_wakeup(struct ath_softc *sc)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&sc->sc_pm_lock, flags);
+ if (++sc->ps_usecount != 1)
+ goto unlock;
+
+ ath9k_hw_setpower_nolock(sc->sc_ah, ATH9K_PM_AWAKE);
+
+ unlock:
+ spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
+}
+
+void ath9k_ps_restore(struct ath_softc *sc)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&sc->sc_pm_lock, flags);
+ if (--sc->ps_usecount != 0)
+ goto unlock;
+
+ if (sc->ps_enabled &&
+ !(sc->sc_flags & (SC_OP_WAIT_FOR_BEACON |
+ SC_OP_WAIT_FOR_CAB |
+ SC_OP_WAIT_FOR_PSPOLL_DATA |
+ SC_OP_WAIT_FOR_TX_ACK)))
+ ath9k_hw_setpower_nolock(sc->sc_ah, ATH9K_PM_NETWORK_SLEEP);
+
+ unlock:
+ spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
+}
+
/*
* Helper for ASPM support.
*
@@ -2790,7 +3002,7 @@ void ath9k_hw_configpcipowersave(struct ath_hw *ah, int restore)
/*
* AR9280 2.0 or later chips use SerDes values from the
* initvals.h initialized depending on chipset during
- * ath9k_hw_do_attach()
+ * ath9k_hw_init()
*/
for (i = 0; i < ah->iniPcieSerdes.ia_rows; i++) {
REG_WRITE(ah, INI_RA(&ah->iniPcieSerdes, i, 0),
@@ -2851,7 +3063,7 @@ void ath9k_hw_configpcipowersave(struct ath_hw *ah, int restore)
if (ah->config.pcie_waen) {
REG_WRITE(ah, AR_WA, ah->config.pcie_waen);
} else {
- if (AR_SREV_9285(ah))
+ if (AR_SREV_9285(ah) || AR_SREV_9271(ah))
REG_WRITE(ah, AR_WA, AR9285_WA_DEFAULT);
/*
* On AR9280 chips bit 22 of 0x4004 needs to be set to
@@ -3021,11 +3233,6 @@ bool ath9k_hw_getisr(struct ath_hw *ah, enum ath9k_int *masked)
return true;
}
-enum ath9k_int ath9k_hw_intrget(struct ath_hw *ah)
-{
- return ah->mask_reg;
-}
-
enum ath9k_int ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints)
{
u32 omask = ah->mask_reg;
@@ -3305,7 +3512,6 @@ void ath9k_hw_fill_cap_info(struct ath_hw *ah)
}
if (eeval & AR5416_OPFLAGS_11G) {
- set_bit(ATH9K_MODE_11B, pCap->wireless_modes);
set_bit(ATH9K_MODE_11G, pCap->wireless_modes);
if (ah->config.ht_enable) {
if (!(eeval & AR5416_OPFLAGS_N_2G_HT20))
@@ -3321,10 +3527,17 @@ void ath9k_hw_fill_cap_info(struct ath_hw *ah)
}
pCap->tx_chainmask = ah->eep_ops->get_eeprom(ah, EEP_TX_MASK);
+ /*
+ * For AR9271 we will temporarilly uses the rx chainmax as read from
+ * the EEPROM.
+ */
if ((ah->hw_version.devid == AR5416_DEVID_PCI) &&
- !(eeval & AR5416_OPFLAGS_11A))
+ !(eeval & AR5416_OPFLAGS_11A) &&
+ !(AR_SREV_9271(ah)))
+ /* CB71: GPIO 0 is pulled down to indicate 3 rx chains */
pCap->rx_chainmask = ath9k_hw_gpio_get(ah, 0) ? 0x5 : 0x7;
else
+ /* Use rx_chainmask from EEPROM. */
pCap->rx_chainmask = ah->eep_ops->get_eeprom(ah, EEP_RX_MASK);
if (!(AR_SREV_9280(ah) && (ah->hw_version.macRev == 0)))
@@ -3595,7 +3808,9 @@ u32 ath9k_hw_gpio_get(struct ath_hw *ah, u32 gpio)
if (gpio >= ah->caps.num_gpio_pins)
return 0xffffffff;
- if (AR_SREV_9285_10_OR_LATER(ah))
+ if (AR_SREV_9287_10_OR_LATER(ah))
+ return MS_REG_READ(AR9287, gpio) != 0;
+ else if (AR_SREV_9285_10_OR_LATER(ah))
return MS_REG_READ(AR9285, gpio) != 0;
else if (AR_SREV_9280_10_OR_LATER(ah))
return MS_REG_READ(AR928X, gpio) != 0;
@@ -3673,7 +3888,7 @@ bool ath9k_hw_setantennaswitch(struct ath_hw *ah,
break;
}
} else {
- ah->diversity_control = settings;
+ ah->config.diversity_control = settings;
}
return true;
@@ -3791,29 +4006,22 @@ void ath9k_hw_settsf64(struct ath_hw *ah, u64 tsf64)
void ath9k_hw_reset_tsf(struct ath_hw *ah)
{
- int count;
+ ath9k_ps_wakeup(ah->ah_sc);
+ if (!ath9k_hw_wait(ah, AR_SLP32_MODE, AR_SLP32_TSF_WRITE_STATUS, 0,
+ AH_TSF_WRITE_TIMEOUT))
+ DPRINTF(ah->ah_sc, ATH_DBG_RESET,
+ "AR_SLP32_TSF_WRITE_STATUS limit exceeded\n");
- count = 0;
- while (REG_READ(ah, AR_SLP32_MODE) & AR_SLP32_TSF_WRITE_STATUS) {
- count++;
- if (count > 10) {
- DPRINTF(ah->ah_sc, ATH_DBG_RESET,
- "AR_SLP32_TSF_WRITE_STATUS limit exceeded\n");
- break;
- }
- udelay(10);
- }
REG_WRITE(ah, AR_RESET_TSF, AR_RESET_TSF_ONCE);
+ ath9k_ps_restore(ah->ah_sc);
}
-bool ath9k_hw_set_tsfadjust(struct ath_hw *ah, u32 setting)
+void ath9k_hw_set_tsfadjust(struct ath_hw *ah, u32 setting)
{
if (setting)
ah->misc_mode |= AR_PCU_TX_ADD_TSF;
else
ah->misc_mode &= ~AR_PCU_TX_ADD_TSF;
-
- return true;
}
bool ath9k_hw_setslottime(struct ath_hw *ah, u32 us)
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h
index 9d0b31ad460..0336981a70e 100644
--- a/drivers/net/wireless/ath/ath9k/hw.h
+++ b/drivers/net/wireless/ath/ath9k/hw.h
@@ -42,6 +42,9 @@
#define AR_SUBVENDOR_ID_NEW_A 0x7065
#define AR5416_MAGIC 0x19641014
+#define AR5416_DEVID_AR9287_PCI 0x002D
+#define AR5416_DEVID_AR9287_PCIE 0x002E
+
/* Register read/write primitives */
#define REG_WRITE(_ah, _reg, _val) ath9k_iowrite32((_ah), (_reg), (_val))
#define REG_READ(_ah, _reg) ath9k_ioread32((_ah), (_reg))
@@ -95,6 +98,7 @@
#define MAX_RATE_POWER 63
#define AH_WAIT_TIMEOUT 100000 /* (us) */
+#define AH_TSF_WRITE_TIMEOUT 100 /* (us) */
#define AH_TIME_QUANTUM 10
#define AR_KEYTABLE_SIZE 128
#define POWER_UP_TIME 200000
@@ -113,15 +117,20 @@
enum wireless_mode {
ATH9K_MODE_11A = 0,
- ATH9K_MODE_11B = 2,
- ATH9K_MODE_11G = 3,
- ATH9K_MODE_11NA_HT20 = 6,
- ATH9K_MODE_11NG_HT20 = 7,
- ATH9K_MODE_11NA_HT40PLUS = 8,
- ATH9K_MODE_11NA_HT40MINUS = 9,
- ATH9K_MODE_11NG_HT40PLUS = 10,
- ATH9K_MODE_11NG_HT40MINUS = 11,
- ATH9K_MODE_MAX
+ ATH9K_MODE_11G,
+ ATH9K_MODE_11NA_HT20,
+ ATH9K_MODE_11NG_HT20,
+ ATH9K_MODE_11NA_HT40PLUS,
+ ATH9K_MODE_11NA_HT40MINUS,
+ ATH9K_MODE_11NG_HT40PLUS,
+ ATH9K_MODE_11NG_HT40MINUS,
+ ATH9K_MODE_MAX,
+};
+
+enum ath9k_ant_setting {
+ ATH9K_ANT_VARIABLE = 0,
+ ATH9K_ANT_FIXED_A,
+ ATH9K_ANT_FIXED_B
};
enum ath9k_hw_caps {
@@ -188,7 +197,7 @@ struct ath9k_ops_config {
u32 cck_trig_high;
u32 cck_trig_low;
u32 enable_ani;
- u16 diversity_control;
+ enum ath9k_ant_setting diversity_control;
u16 antenna_switch_swap;
int serialize_regmode;
bool intr_mitigation;
@@ -327,12 +336,6 @@ enum ath9k_power_mode {
ATH9K_PM_UNDEFINED
};
-enum ath9k_ant_setting {
- ATH9K_ANT_VARIABLE = 0,
- ATH9K_ANT_FIXED_A,
- ATH9K_ANT_FIXED_B
-};
-
enum ath9k_tp_scale {
ATH9K_TP_SCALE_MAX = 0,
ATH9K_TP_SCALE_50,
@@ -400,6 +403,7 @@ struct ath_hw {
union {
struct ar5416_eeprom_def def;
struct ar5416_eeprom_4k map4k;
+ struct ar9287_eeprom map9287;
} eeprom;
const struct eeprom_ops *eep_ops;
enum ath9k_eep_map eep_map;
@@ -415,9 +419,10 @@ struct ath_hw {
u32 wlanactive_gpio;
u32 ah_flags;
+ bool htc_reset_init;
+
enum nl80211_iftype opmode;
enum ath9k_power_mode power_mode;
- enum ath9k_power_mode restore_mode;
struct ath9k_nfcal_hist nfCalHist[NUM_NF_READINGS];
struct ar5416Stats stats;
@@ -432,8 +437,6 @@ struct ath_hw {
u32 txurn_interrupt_mask;
bool chip_fullsleep;
u32 atim_window;
- u16 antenna_switch_swap;
- enum ath9k_ant_setting diversity_control;
/* Calibration */
enum ath9k_cal_types supp_cals;
@@ -502,7 +505,6 @@ struct ath_hw {
/* ANI */
u32 proc_phyerr;
- bool has_hw_phycounters;
u32 aniperiod;
struct ar5416AniState *curani;
struct ar5416AniState ani[255];
@@ -538,11 +540,11 @@ struct ath_hw {
struct ar5416IniArray iniModesTxGain;
};
-/* Attach, Detach, Reset */
+/* Initialization, Detach, Reset */
const char *ath9k_hw_probe(u16 vendorid, u16 devid);
void ath9k_hw_detach(struct ath_hw *ah);
-struct ath_hw *ath9k_hw_attach(u16 devid, struct ath_softc *sc, int *error);
-void ath9k_hw_rfdetach(struct ath_hw *ah);
+int ath9k_hw_init(struct ath_hw *ah);
+void ath9k_hw_rf_free(struct ath_hw *ah);
int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
bool bChannelChange);
void ath9k_hw_fill_cap_info(struct ath_hw *ah);
@@ -596,7 +598,7 @@ void ath9k_hw_write_associd(struct ath_softc *sc);
u64 ath9k_hw_gettsf64(struct ath_hw *ah);
void ath9k_hw_settsf64(struct ath_hw *ah, u64 tsf64);
void ath9k_hw_reset_tsf(struct ath_hw *ah);
-bool ath9k_hw_set_tsfadjust(struct ath_hw *ah, u32 setting);
+void ath9k_hw_set_tsfadjust(struct ath_hw *ah, u32 setting);
bool ath9k_hw_setslottime(struct ath_hw *ah, u32 us);
void ath9k_hw_set11nmac2040(struct ath_hw *ah, enum ath9k_ht_macmode mode);
void ath9k_hw_beaconinit(struct ath_hw *ah, u32 next_beacon, u32 beacon_period);
@@ -609,7 +611,6 @@ void ath9k_hw_configpcipowersave(struct ath_hw *ah, int restore);
/* Interrupt Handling */
bool ath9k_hw_intrpend(struct ath_hw *ah);
bool ath9k_hw_getisr(struct ath_hw *ah, enum ath9k_int *masked);
-enum ath9k_int ath9k_hw_intrget(struct ath_hw *ah);
enum ath9k_int ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints);
void ath9k_hw_btcoex_enable(struct ath_hw *ah);
diff --git a/drivers/net/wireless/ath/ath9k/initvals.h b/drivers/net/wireless/ath/ath9k/initvals.h
index e2f0a34b79a..27a86bb7c4c 100644
--- a/drivers/net/wireless/ath/ath9k/initvals.h
+++ b/drivers/net/wireless/ath/ath9k/initvals.h
@@ -2782,7 +2782,7 @@ static const u32 ar9280Common_9280_2[][2] = {
{ 0x00008338, 0x00ff0000 },
{ 0x0000833c, 0x00000000 },
{ 0x00008340, 0x000107ff },
- { 0x00008344, 0x00581043 },
+ { 0x00008344, 0x00481043 },
{ 0x00009808, 0x00000000 },
{ 0x0000980c, 0xafa68e30 },
{ 0x00009810, 0xfd14e000 },
@@ -3439,7 +3439,7 @@ static const u32 ar9280PciePhy_clkreq_always_on_L1_9280[][2] = {
{0x00004044, 0x00000000 },
};
-/* AR9285 */
+/* AR9285 Revsion 10*/
static const u_int32_t ar9285Modes_9285[][6] = {
{ 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 },
{ 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 },
@@ -3955,7 +3955,7 @@ static const u_int32_t ar9285Common_9285[][2] = {
{ 0x00008338, 0x00000000 },
{ 0x0000833c, 0x00000000 },
{ 0x00008340, 0x00010380 },
- { 0x00008344, 0x00581043 },
+ { 0x00008344, 0x00481043 },
{ 0x00009808, 0x00000000 },
{ 0x0000980c, 0xafe68e30 },
{ 0x00009810, 0xfd14e000 },
@@ -4121,8 +4121,9 @@ static const u_int32_t ar9285PciePhy_clkreq_off_L1_9285[][2] = {
{0x00004044, 0x00000000 },
};
-/* AR9285 v1_2 PCI Register Writes. Created: 03/04/09 */
+/* AR9285 v1_2 PCI Register Writes. Created: 04/13/09 */
static const u_int32_t ar9285Modes_9285_1_2[][6] = {
+ /* Address 5G-HT20 5G-HT40 2G-HT40 2G-HT20 Turbo */
{ 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 },
{ 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 },
{ 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 },
@@ -4139,6 +4140,7 @@ static const u_int32_t ar9285Modes_9285_1_2[][6] = {
{ 0x00009840, 0x206a012e, 0x206a012e, 0x206a012e, 0x206a012e, 0x206a012e },
{ 0x00009844, 0x0372161e, 0x0372161e, 0x03721620, 0x03721620, 0x037216a0 },
{ 0x00009848, 0x00001066, 0x00001066, 0x00001053, 0x00001053, 0x00001059 },
+ { 0x0000a848, 0x00001066, 0x00001066, 0x00001053, 0x00001053, 0x00001059 },
{ 0x00009850, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2 },
{ 0x00009858, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e },
{ 0x0000985c, 0x3139605e, 0x3139605e, 0x3137605e, 0x3137605e, 0x3139605e },
@@ -4419,6 +4421,7 @@ static const u_int32_t ar9285Modes_9285_1_2[][6] = {
{ 0x0000abfc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
{ 0x0000a204, 0x00000004, 0x00000004, 0x00000004, 0x00000004, 0x00000004 },
{ 0x0000a20c, 0x00000014, 0x00000014, 0x0001f000, 0x0001f000, 0x0001f000 },
+ { 0x0000b20c, 0x00000014, 0x00000014, 0x0001f000, 0x0001f000, 0x0001f000 },
{ 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a },
{ 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 },
{ 0x0000a250, 0x0004f000, 0x0004f000, 0x0004a000, 0x0004a000, 0x0004a000 },
@@ -4618,7 +4621,7 @@ static const u_int32_t ar9285Common_9285_1_2[][2] = {
{ 0x00008338, 0x00ff0000 },
{ 0x0000833c, 0x00000000 },
{ 0x00008340, 0x00010380 },
- { 0x00008344, 0x00581043 },
+ { 0x00008344, 0x00481043 },
{ 0x00009808, 0x00000000 },
{ 0x0000980c, 0xafe68e30 },
{ 0x00009810, 0xfd14e000 },
@@ -4752,18 +4755,18 @@ static const u_int32_t ar9285Common_9285_1_2[][2] = {
static const u_int32_t ar9285Modes_high_power_tx_gain_9285_1_2[][6] = {
/* Address 5G-HT20 5G-HT40 2G-HT40 2G-HT20 Turbo */
{ 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
- { 0x0000a304, 0x00000000, 0x00000000, 0x00005200, 0x00005200, 0x00000000 },
- { 0x0000a308, 0x00000000, 0x00000000, 0x00007201, 0x00007201, 0x00000000 },
+ { 0x0000a304, 0x00000000, 0x00000000, 0x00006200, 0x00006200, 0x00000000 },
+ { 0x0000a308, 0x00000000, 0x00000000, 0x00008201, 0x00008201, 0x00000000 },
{ 0x0000a30c, 0x00000000, 0x00000000, 0x0000b240, 0x0000b240, 0x00000000 },
{ 0x0000a310, 0x00000000, 0x00000000, 0x0000d241, 0x0000d241, 0x00000000 },
- { 0x0000a314, 0x00000000, 0x00000000, 0x0000f440, 0x0000f440, 0x00000000 },
- { 0x0000a318, 0x00000000, 0x00000000, 0x00014640, 0x00014640, 0x00000000 },
- { 0x0000a31c, 0x00000000, 0x00000000, 0x00018680, 0x00018680, 0x00000000 },
- { 0x0000a320, 0x00000000, 0x00000000, 0x00019841, 0x00019841, 0x00000000 },
- { 0x0000a324, 0x00000000, 0x00000000, 0x0001ca40, 0x0001ca40, 0x00000000 },
- { 0x0000a328, 0x00000000, 0x00000000, 0x0001fa80, 0x0001fa80, 0x00000000 },
- { 0x0000a32c, 0x00000000, 0x00000000, 0x00023ac0, 0x00023ac0, 0x00000000 },
- { 0x0000a330, 0x00000000, 0x00000000, 0x0002ab40, 0x0002ab40, 0x00000000 },
+ { 0x0000a314, 0x00000000, 0x00000000, 0x0000f600, 0x0000f600, 0x00000000 },
+ { 0x0000a318, 0x00000000, 0x00000000, 0x00012800, 0x00012800, 0x00000000 },
+ { 0x0000a31c, 0x00000000, 0x00000000, 0x00016802, 0x00016802, 0x00000000 },
+ { 0x0000a320, 0x00000000, 0x00000000, 0x0001b805, 0x0001b805, 0x00000000 },
+ { 0x0000a324, 0x00000000, 0x00000000, 0x00021a80, 0x00021a80, 0x00000000 },
+ { 0x0000a328, 0x00000000, 0x00000000, 0x00028b00, 0x00028b00, 0x00000000 },
+ { 0x0000a32c, 0x00000000, 0x00000000, 0x0002ab40, 0x0002ab40, 0x00000000 },
+ { 0x0000a330, 0x00000000, 0x00000000, 0x0002cd80, 0x0002cd80, 0x00000000 },
{ 0x0000a334, 0x00000000, 0x00000000, 0x00033d82, 0x00033d82, 0x00000000 },
{ 0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e, 0x00000000 },
{ 0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x00000000 },
@@ -4776,13 +4779,13 @@ static const u_int32_t ar9285Modes_high_power_tx_gain_9285_1_2[][6] = {
{ 0x00007838, 0xfac68803, 0xfac68803, 0xfac68803, 0xfac68803, 0xfac68803 },
{ 0x0000786c, 0x08609ebe, 0x08609ebe, 0x08609ebe, 0x08609ebe, 0x08609ebe },
{ 0x00007820, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00 },
- { 0x0000a274, 0x0a22a652, 0x0a22a652, 0x0a21a652, 0x0a21a652, 0x0a22a652 },
- { 0x0000a278, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce },
- { 0x0000a27c, 0x050701ce, 0x050701ce, 0x050701ce, 0x050701ce, 0x050701ce },
- { 0x0000a394, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce },
- { 0x0000a398, 0x000001ce, 0x000001ce, 0x000001ce, 0x000001ce, 0x000001ce },
- { 0x0000a3dc, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce },
- { 0x0000a3e0, 0x000001ce, 0x000001ce, 0x000001ce, 0x000001ce, 0x000001ce },
+ { 0x0000a274, 0x0a22a652, 0x0a22a652, 0x0a216652, 0x0a216652, 0x0a22a652 },
+ { 0x0000a278, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7 },
+ { 0x0000a27c, 0x050380e7, 0x050380e7, 0x050380e7, 0x050380e7, 0x050380e7 },
+ { 0x0000a394, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7 },
+ { 0x0000a398, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7 },
+ { 0x0000a3dc, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7 },
+ { 0x0000a3e0, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7 },
};
static const u_int32_t ar9285Modes_original_tx_gain_9285_1_2[][6] = {
@@ -4846,3 +4849,2185 @@ static const u_int32_t ar9285PciePhy_clkreq_off_L1_9285_1_2[][2] = {
{0x00004040, 0x00043007 },
{0x00004044, 0x00000000 },
};
+
+/* AR9287 Revision 10 */
+static const u_int32_t ar9287Modes_9287_1_0[][6] = {
+ /* Address 5G-HT20 5G-HT40 2G-HT40 2G-HT20 Turbo */
+ { 0x00001030, 0x00000000, 0x00000000, 0x000002c0, 0x00000160, 0x000001e0 },
+ { 0x00001070, 0x00000000, 0x00000000, 0x00000318, 0x0000018c, 0x000001e0 },
+ { 0x000010b0, 0x00000000, 0x00000000, 0x00007c70, 0x00003e38, 0x00001180 },
+ { 0x000010f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000008 },
+ { 0x00008014, 0x00000000, 0x00000000, 0x10801600, 0x08400b00, 0x06e006e0 },
+ { 0x0000801c, 0x00000000, 0x00000000, 0x12e00057, 0x12e0002b, 0x0988004f },
+ { 0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810, 0x08f04810 },
+ { 0x000081d0, 0x00003200, 0x00003200, 0x0000320a, 0x0000320a, 0x0000320a },
+ { 0x00008318, 0x00000000, 0x00000000, 0x00006880, 0x00003440, 0x00006880 },
+ { 0x00009804, 0x00000000, 0x00000000, 0x000003c4, 0x00000300, 0x00000303 },
+ { 0x00009820, 0x00000000, 0x00000000, 0x02020200, 0x02020200, 0x02020200 },
+ { 0x00009824, 0x00000000, 0x00000000, 0x01000e0e, 0x01000e0e, 0x01000e0e },
+ { 0x00009828, 0x00000000, 0x00000000, 0x0a020001, 0x0a020001, 0x0a020001 },
+ { 0x00009834, 0x00000000, 0x00000000, 0x00000e0e, 0x00000e0e, 0x00000e0e },
+ { 0x00009838, 0x00000003, 0x00000003, 0x00000007, 0x00000007, 0x00000007 },
+ { 0x00009840, 0x206a002e, 0x206a002e, 0x206a012e, 0x206a012e, 0x206a012e },
+ { 0x00009844, 0x03720000, 0x03720000, 0x037216a0, 0x037216a0, 0x037216a0 },
+ { 0x00009850, 0x60000000, 0x60000000, 0x6d4000e2, 0x6c4000e2, 0x6c4000e2 },
+ { 0x00009858, 0x7c000d00, 0x7c000d00, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e },
+ { 0x0000985c, 0x3100005e, 0x3100005e, 0x3139605e, 0x31395d5e, 0x31395d5e },
+ { 0x00009860, 0x00058d00, 0x00058d00, 0x00058d20, 0x00058d20, 0x00058d18 },
+ { 0x00009864, 0x00000e00, 0x00000e00, 0x0001ce00, 0x0001ce00, 0x0001ce00 },
+ { 0x00009868, 0x000040c0, 0x000040c0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0 },
+ { 0x0000986c, 0x00000080, 0x00000080, 0x06903881, 0x06903881, 0x06903881 },
+ { 0x00009914, 0x00000000, 0x00000000, 0x00001130, 0x00000898, 0x000007d0 },
+ { 0x00009918, 0x00000000, 0x00000000, 0x00000016, 0x0000000b, 0x00000016 },
+ { 0x00009924, 0xd00a8a01, 0xd00a8a01, 0xd00a8a0d, 0xd00a8a0d, 0xd00a8a0d },
+ { 0x00009944, 0xefbc0000, 0xefbc0000, 0xefbc1010, 0xefbc1010, 0xefbc1010 },
+ { 0x00009960, 0x00000000, 0x00000000, 0x00000010, 0x00000010, 0x00000010 },
+ { 0x0000a960, 0x00000000, 0x00000000, 0x00000010, 0x00000010, 0x00000010 },
+ { 0x00009964, 0x00000000, 0x00000000, 0x00000210, 0x00000210, 0x00000210 },
+ { 0x0000c968, 0x00000200, 0x00000200, 0x000003ce, 0x000003ce, 0x000003ce },
+ { 0x000099b8, 0x00000000, 0x00000000, 0x0000001c, 0x0000001c, 0x0000001c },
+ { 0x000099bc, 0x00000000, 0x00000000, 0x00000c00, 0x00000c00, 0x00000c00 },
+ { 0x000099c0, 0x00000000, 0x00000000, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4 },
+ { 0x0000a204, 0x00000440, 0x00000440, 0x00000444, 0x00000444, 0x00000444 },
+ { 0x0000a20c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x0000b20c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x0000a21c, 0x1803800a, 0x1803800a, 0x1883800a, 0x1883800a, 0x1883800a },
+ { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 },
+ { 0x0000a250, 0x00000000, 0x00000000, 0x0004a000, 0x0004a000, 0x0004a000 },
+ { 0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e, 0x7999aa0e },
+ { 0x0000a3d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+};
+
+static const u_int32_t ar9287Common_9287_1_0[][2] = {
+ { 0x0000000c, 0x00000000 },
+ { 0x00000030, 0x00020015 },
+ { 0x00000034, 0x00000005 },
+ { 0x00000040, 0x00000000 },
+ { 0x00000044, 0x00000008 },
+ { 0x00000048, 0x00000008 },
+ { 0x0000004c, 0x00000010 },
+ { 0x00000050, 0x00000000 },
+ { 0x00000054, 0x0000001f },
+ { 0x00000800, 0x00000000 },
+ { 0x00000804, 0x00000000 },
+ { 0x00000808, 0x00000000 },
+ { 0x0000080c, 0x00000000 },
+ { 0x00000810, 0x00000000 },
+ { 0x00000814, 0x00000000 },
+ { 0x00000818, 0x00000000 },
+ { 0x0000081c, 0x00000000 },
+ { 0x00000820, 0x00000000 },
+ { 0x00000824, 0x00000000 },
+ { 0x00001040, 0x002ffc0f },
+ { 0x00001044, 0x002ffc0f },
+ { 0x00001048, 0x002ffc0f },
+ { 0x0000104c, 0x002ffc0f },
+ { 0x00001050, 0x002ffc0f },
+ { 0x00001054, 0x002ffc0f },
+ { 0x00001058, 0x002ffc0f },
+ { 0x0000105c, 0x002ffc0f },
+ { 0x00001060, 0x002ffc0f },
+ { 0x00001064, 0x002ffc0f },
+ { 0x00001230, 0x00000000 },
+ { 0x00001270, 0x00000000 },
+ { 0x00001038, 0x00000000 },
+ { 0x00001078, 0x00000000 },
+ { 0x000010b8, 0x00000000 },
+ { 0x000010f8, 0x00000000 },
+ { 0x00001138, 0x00000000 },
+ { 0x00001178, 0x00000000 },
+ { 0x000011b8, 0x00000000 },
+ { 0x000011f8, 0x00000000 },
+ { 0x00001238, 0x00000000 },
+ { 0x00001278, 0x00000000 },
+ { 0x000012b8, 0x00000000 },
+ { 0x000012f8, 0x00000000 },
+ { 0x00001338, 0x00000000 },
+ { 0x00001378, 0x00000000 },
+ { 0x000013b8, 0x00000000 },
+ { 0x000013f8, 0x00000000 },
+ { 0x00001438, 0x00000000 },
+ { 0x00001478, 0x00000000 },
+ { 0x000014b8, 0x00000000 },
+ { 0x000014f8, 0x00000000 },
+ { 0x00001538, 0x00000000 },
+ { 0x00001578, 0x00000000 },
+ { 0x000015b8, 0x00000000 },
+ { 0x000015f8, 0x00000000 },
+ { 0x00001638, 0x00000000 },
+ { 0x00001678, 0x00000000 },
+ { 0x000016b8, 0x00000000 },
+ { 0x000016f8, 0x00000000 },
+ { 0x00001738, 0x00000000 },
+ { 0x00001778, 0x00000000 },
+ { 0x000017b8, 0x00000000 },
+ { 0x000017f8, 0x00000000 },
+ { 0x0000103c, 0x00000000 },
+ { 0x0000107c, 0x00000000 },
+ { 0x000010bc, 0x00000000 },
+ { 0x000010fc, 0x00000000 },
+ { 0x0000113c, 0x00000000 },
+ { 0x0000117c, 0x00000000 },
+ { 0x000011bc, 0x00000000 },
+ { 0x000011fc, 0x00000000 },
+ { 0x0000123c, 0x00000000 },
+ { 0x0000127c, 0x00000000 },
+ { 0x000012bc, 0x00000000 },
+ { 0x000012fc, 0x00000000 },
+ { 0x0000133c, 0x00000000 },
+ { 0x0000137c, 0x00000000 },
+ { 0x000013bc, 0x00000000 },
+ { 0x000013fc, 0x00000000 },
+ { 0x0000143c, 0x00000000 },
+ { 0x0000147c, 0x00000000 },
+ { 0x00004030, 0x00000002 },
+ { 0x0000403c, 0x00000002 },
+ { 0x00004024, 0x0000001f },
+ { 0x00004060, 0x00000000 },
+ { 0x00004064, 0x00000000 },
+ { 0x00007010, 0x00000033 },
+ { 0x00007020, 0x00000000 },
+ { 0x00007034, 0x00000002 },
+ { 0x00007038, 0x000004c2 },
+ { 0x00008004, 0x00000000 },
+ { 0x00008008, 0x00000000 },
+ { 0x0000800c, 0x00000000 },
+ { 0x00008018, 0x00000700 },
+ { 0x00008020, 0x00000000 },
+ { 0x00008038, 0x00000000 },
+ { 0x0000803c, 0x00000000 },
+ { 0x00008048, 0x40000000 },
+ { 0x00008054, 0x00000000 },
+ { 0x00008058, 0x00000000 },
+ { 0x0000805c, 0x000fc78f },
+ { 0x00008060, 0x0000000f },
+ { 0x00008064, 0x00000000 },
+ { 0x00008070, 0x00000000 },
+ { 0x000080c0, 0x2a80001a },
+ { 0x000080c4, 0x05dc01e0 },
+ { 0x000080c8, 0x1f402710 },
+ { 0x000080cc, 0x01f40000 },
+ { 0x000080d0, 0x00001e00 },
+ { 0x000080d4, 0x00000000 },
+ { 0x000080d8, 0x00400000 },
+ { 0x000080e0, 0xffffffff },
+ { 0x000080e4, 0x0000ffff },
+ { 0x000080e8, 0x003f3f3f },
+ { 0x000080ec, 0x00000000 },
+ { 0x000080f0, 0x00000000 },
+ { 0x000080f4, 0x00000000 },
+ { 0x000080f8, 0x00000000 },
+ { 0x000080fc, 0x00020000 },
+ { 0x00008100, 0x00020000 },
+ { 0x00008104, 0x00000001 },
+ { 0x00008108, 0x00000052 },
+ { 0x0000810c, 0x00000000 },
+ { 0x00008110, 0x00000168 },
+ { 0x00008118, 0x000100aa },
+ { 0x0000811c, 0x00003210 },
+ { 0x00008124, 0x00000000 },
+ { 0x00008128, 0x00000000 },
+ { 0x0000812c, 0x00000000 },
+ { 0x00008130, 0x00000000 },
+ { 0x00008134, 0x00000000 },
+ { 0x00008138, 0x00000000 },
+ { 0x0000813c, 0x00000000 },
+ { 0x00008144, 0xffffffff },
+ { 0x00008168, 0x00000000 },
+ { 0x0000816c, 0x00000000 },
+ { 0x00008170, 0x18487320 },
+ { 0x00008174, 0xfaa4fa50 },
+ { 0x00008178, 0x00000100 },
+ { 0x0000817c, 0x00000000 },
+ { 0x000081c0, 0x00000000 },
+ { 0x000081c4, 0x00000000 },
+ { 0x000081d4, 0x00000000 },
+ { 0x000081ec, 0x00000000 },
+ { 0x000081f0, 0x00000000 },
+ { 0x000081f4, 0x00000000 },
+ { 0x000081f8, 0x00000000 },
+ { 0x000081fc, 0x00000000 },
+ { 0x00008200, 0x00000000 },
+ { 0x00008204, 0x00000000 },
+ { 0x00008208, 0x00000000 },
+ { 0x0000820c, 0x00000000 },
+ { 0x00008210, 0x00000000 },
+ { 0x00008214, 0x00000000 },
+ { 0x00008218, 0x00000000 },
+ { 0x0000821c, 0x00000000 },
+ { 0x00008220, 0x00000000 },
+ { 0x00008224, 0x00000000 },
+ { 0x00008228, 0x00000000 },
+ { 0x0000822c, 0x00000000 },
+ { 0x00008230, 0x00000000 },
+ { 0x00008234, 0x00000000 },
+ { 0x00008238, 0x00000000 },
+ { 0x0000823c, 0x00000000 },
+ { 0x00008240, 0x00100000 },
+ { 0x00008244, 0x0010f400 },
+ { 0x00008248, 0x00000100 },
+ { 0x0000824c, 0x0001e800 },
+ { 0x00008250, 0x00000000 },
+ { 0x00008254, 0x00000000 },
+ { 0x00008258, 0x00000000 },
+ { 0x0000825c, 0x400000ff },
+ { 0x00008260, 0x00080922 },
+ { 0x00008264, 0xa8a00010 },
+ { 0x00008270, 0x00000000 },
+ { 0x00008274, 0x40000000 },
+ { 0x00008278, 0x003e4180 },
+ { 0x0000827c, 0x00000000 },
+ { 0x00008284, 0x0000002c },
+ { 0x00008288, 0x0000002c },
+ { 0x0000828c, 0x000000ff },
+ { 0x00008294, 0x00000000 },
+ { 0x00008298, 0x00000000 },
+ { 0x0000829c, 0x00000000 },
+ { 0x00008300, 0x00000040 },
+ { 0x00008314, 0x00000000 },
+ { 0x00008328, 0x00000000 },
+ { 0x0000832c, 0x00000007 },
+ { 0x00008330, 0x00000302 },
+ { 0x00008334, 0x00000e00 },
+ { 0x00008338, 0x00ff0000 },
+ { 0x0000833c, 0x00000000 },
+ { 0x00008340, 0x000107ff },
+ { 0x00008344, 0x01c81043 },
+ { 0x00008360, 0xffffffff },
+ { 0x00008364, 0xffffffff },
+ { 0x00008368, 0x00000000 },
+ { 0x00008370, 0x00000000 },
+ { 0x00008374, 0x000000ff },
+ { 0x00008378, 0x00000000 },
+ { 0x0000837c, 0x00000000 },
+ { 0x00008380, 0xffffffff },
+ { 0x00008384, 0xffffffff },
+ { 0x00008390, 0x0fffffff },
+ { 0x00008394, 0x0fffffff },
+ { 0x00008398, 0x00000000 },
+ { 0x0000839c, 0x00000000 },
+ { 0x000083a0, 0x00000000 },
+ { 0x00009808, 0x00000000 },
+ { 0x0000980c, 0xafe68e30 },
+ { 0x00009810, 0xfd14e000 },
+ { 0x00009814, 0x9c0a9f6b },
+ { 0x0000981c, 0x00000000 },
+ { 0x0000982c, 0x0000a000 },
+ { 0x00009830, 0x00000000 },
+ { 0x0000983c, 0x00200400 },
+ { 0x0000984c, 0x0040233c },
+ { 0x0000a84c, 0x0040233c },
+ { 0x00009854, 0x00000044 },
+ { 0x00009900, 0x00000000 },
+ { 0x00009904, 0x00000000 },
+ { 0x00009908, 0x00000000 },
+ { 0x0000990c, 0x00000000 },
+ { 0x00009910, 0x10002310 },
+ { 0x0000991c, 0x10000fff },
+ { 0x00009920, 0x04900000 },
+ { 0x0000a920, 0x04900000 },
+ { 0x00009928, 0x00000001 },
+ { 0x0000992c, 0x00000004 },
+ { 0x00009930, 0x00000000 },
+ { 0x0000a930, 0x00000000 },
+ { 0x00009934, 0x1e1f2022 },
+ { 0x00009938, 0x0a0b0c0d },
+ { 0x0000993c, 0x00000000 },
+ { 0x00009948, 0x9280c00a },
+ { 0x0000994c, 0x00020028 },
+ { 0x00009954, 0x5f3ca3de },
+ { 0x00009958, 0x0108ecff },
+ { 0x00009940, 0x14750604 },
+ { 0x0000c95c, 0x004b6a8e },
+ { 0x00009970, 0x990bb515 },
+ { 0x00009974, 0x00000000 },
+ { 0x00009978, 0x00000001 },
+ { 0x0000997c, 0x00000000 },
+ { 0x000099a0, 0x00000000 },
+ { 0x000099a4, 0x00000001 },
+ { 0x000099a8, 0x201fff00 },
+ { 0x000099ac, 0x0c6f0000 },
+ { 0x000099b0, 0x03051000 },
+ { 0x000099b4, 0x00000820 },
+ { 0x000099c4, 0x06336f77 },
+ { 0x000099c8, 0x6af65329 },
+ { 0x000099cc, 0x08f186c8 },
+ { 0x000099d0, 0x00046384 },
+ { 0x000099dc, 0x00000000 },
+ { 0x000099e0, 0x00000000 },
+ { 0x000099e4, 0xaaaaaaaa },
+ { 0x000099e8, 0x3c466478 },
+ { 0x000099ec, 0x0cc80caa },
+ { 0x000099f0, 0x00000000 },
+ { 0x000099fc, 0x00001042 },
+ { 0x0000a1f4, 0x00fffeff },
+ { 0x0000a1f8, 0x00f5f9ff },
+ { 0x0000a1fc, 0xb79f6427 },
+ { 0x0000a208, 0x803e4788 },
+ { 0x0000a210, 0x4080a333 },
+ { 0x0000a214, 0x40206c10 },
+ { 0x0000a218, 0x009c4060 },
+ { 0x0000a220, 0x01834061 },
+ { 0x0000a224, 0x00000400 },
+ { 0x0000a228, 0x000003b5 },
+ { 0x0000a22c, 0x233f7180 },
+ { 0x0000a234, 0x20202020 },
+ { 0x0000a238, 0x20202020 },
+ { 0x0000a23c, 0x13c889af },
+ { 0x0000a240, 0x38490a20 },
+ { 0x0000a244, 0x00000000 },
+ { 0x0000a248, 0xfffffffc },
+ { 0x0000a24c, 0x00000000 },
+ { 0x0000a254, 0x00000000 },
+ { 0x0000a258, 0x0cdbd380 },
+ { 0x0000a25c, 0x0f0f0f01 },
+ { 0x0000a260, 0xdfa91f01 },
+ { 0x0000a264, 0x00418a11 },
+ { 0x0000b264, 0x00418a11 },
+ { 0x0000a268, 0x00000000 },
+ { 0x0000a26c, 0x0e79e5c6 },
+ { 0x0000b26c, 0x0e79e5c6 },
+ { 0x0000d270, 0x00820820 },
+ { 0x0000a278, 0x1ce739ce },
+ { 0x0000a27c, 0x050701ce },
+ { 0x0000d35c, 0x07ffffef },
+ { 0x0000d360, 0x0fffffe7 },
+ { 0x0000d364, 0x17ffffe5 },
+ { 0x0000d368, 0x1fffffe4 },
+ { 0x0000d36c, 0x37ffffe3 },
+ { 0x0000d370, 0x3fffffe3 },
+ { 0x0000d374, 0x57ffffe3 },
+ { 0x0000d378, 0x5fffffe2 },
+ { 0x0000d37c, 0x7fffffe2 },
+ { 0x0000d380, 0x7f3c7bba },
+ { 0x0000d384, 0xf3307ff0 },
+ { 0x0000a388, 0x0c000000 },
+ { 0x0000a38c, 0x20202020 },
+ { 0x0000a390, 0x20202020 },
+ { 0x0000a394, 0x1ce739ce },
+ { 0x0000a398, 0x000001ce },
+ { 0x0000b398, 0x000001ce },
+ { 0x0000a39c, 0x00000001 },
+ { 0x0000a3c8, 0x00000246 },
+ { 0x0000a3cc, 0x20202020 },
+ { 0x0000a3d0, 0x20202020 },
+ { 0x0000a3d4, 0x20202020 },
+ { 0x0000a3dc, 0x1ce739ce },
+ { 0x0000a3e0, 0x000001ce },
+ { 0x0000a3e4, 0x00000000 },
+ { 0x0000a3e8, 0x18c43433 },
+ { 0x0000a3ec, 0x00f70081 },
+ { 0x0000a3f0, 0x01036a1e },
+ { 0x0000a3f4, 0x00000000 },
+ { 0x0000b3f4, 0x00000000 },
+ { 0x0000a7d8, 0x00000001 },
+ { 0x00007800, 0x00000800 },
+ { 0x00007804, 0x6c35ffb0 },
+ { 0x00007808, 0x6db6c000 },
+ { 0x0000780c, 0x6db6cb30 },
+ { 0x00007810, 0x6db6cb6c },
+ { 0x00007814, 0x0501e200 },
+ { 0x00007818, 0x0094128d },
+ { 0x0000781c, 0x976ee392 },
+ { 0x00007820, 0xf75ff6fc },
+ { 0x00007824, 0x00040000 },
+ { 0x00007828, 0xdb003012 },
+ { 0x0000782c, 0x04924914 },
+ { 0x00007830, 0x21084210 },
+ { 0x00007834, 0x00140000 },
+ { 0x00007838, 0x0e4548d8 },
+ { 0x0000783c, 0x54214514 },
+ { 0x00007840, 0x02025820 },
+ { 0x00007844, 0x71c0d388 },
+ { 0x00007848, 0x934934a8 },
+ { 0x00007850, 0x00000000 },
+ { 0x00007854, 0x00000800 },
+ { 0x00007858, 0x6c35ffb0 },
+ { 0x0000785c, 0x6db6c000 },
+ { 0x00007860, 0x6db6cb2c },
+ { 0x00007864, 0x6db6cb6c },
+ { 0x00007868, 0x0501e200 },
+ { 0x0000786c, 0x0094128d },
+ { 0x00007870, 0x976ee392 },
+ { 0x00007874, 0xf75ff6fc },
+ { 0x00007878, 0x00040000 },
+ { 0x0000787c, 0xdb003012 },
+ { 0x00007880, 0x04924914 },
+ { 0x00007884, 0x21084210 },
+ { 0x00007888, 0x001b6db0 },
+ { 0x0000788c, 0x00376b63 },
+ { 0x00007890, 0x06db6db6 },
+ { 0x00007894, 0x006d8000 },
+ { 0x00007898, 0x48100000 },
+ { 0x0000789c, 0x00000000 },
+ { 0x000078a0, 0x08000000 },
+ { 0x000078a4, 0x0007ffd8 },
+ { 0x000078a8, 0x0007ffd8 },
+ { 0x000078ac, 0x001c0020 },
+ { 0x000078b0, 0x000611eb },
+ { 0x000078b4, 0x40008080 },
+ { 0x000078b8, 0x2a850160 },
+};
+
+static const u_int32_t ar9287Modes_tx_gain_9287_1_0[][6] = {
+ /* Address 5G-HT20 5G-HT40 2G-HT40 2G-HT20 Turbo */
+ { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x0000a304, 0x00000000, 0x00000000, 0x00004002, 0x00004002, 0x00004002 },
+ { 0x0000a308, 0x00000000, 0x00000000, 0x00008004, 0x00008004, 0x00008004 },
+ { 0x0000a30c, 0x00000000, 0x00000000, 0x0000c00a, 0x0000c00a, 0x0000c00a },
+ { 0x0000a310, 0x00000000, 0x00000000, 0x0001000c, 0x0001000c, 0x0001000c },
+ { 0x0000a314, 0x00000000, 0x00000000, 0x0001420b, 0x0001420b, 0x0001420b },
+ { 0x0000a318, 0x00000000, 0x00000000, 0x0001824a, 0x0001824a, 0x0001824a },
+ { 0x0000a31c, 0x00000000, 0x00000000, 0x0001c44a, 0x0001c44a, 0x0001c44a },
+ { 0x0000a320, 0x00000000, 0x00000000, 0x0002064a, 0x0002064a, 0x0002064a },
+ { 0x0000a324, 0x00000000, 0x00000000, 0x0002484a, 0x0002484a, 0x0002484a },
+ { 0x0000a328, 0x00000000, 0x00000000, 0x00028a4a, 0x00028a4a, 0x00028a4a },
+ { 0x0000a32c, 0x00000000, 0x00000000, 0x0002cc4a, 0x0002cc4a, 0x0002cc4a },
+ { 0x0000a330, 0x00000000, 0x00000000, 0x00030e4a, 0x00030e4a, 0x00030e4a },
+ { 0x0000a334, 0x00000000, 0x00000000, 0x00034e8a, 0x00034e8a, 0x00034e8a },
+ { 0x0000a338, 0x00000000, 0x00000000, 0x00038e8c, 0x00038e8c, 0x00038e8c },
+ { 0x0000a33c, 0x00000000, 0x00000000, 0x0003cecc, 0x0003cecc, 0x0003cecc },
+ { 0x0000a340, 0x00000000, 0x00000000, 0x00040ed4, 0x00040ed4, 0x00040ed4 },
+ { 0x0000a344, 0x00000000, 0x00000000, 0x00044edc, 0x00044edc, 0x00044edc },
+ { 0x0000a348, 0x00000000, 0x00000000, 0x00048ede, 0x00048ede, 0x00048ede },
+ { 0x0000a34c, 0x00000000, 0x00000000, 0x0004cf1e, 0x0004cf1e, 0x0004cf1e },
+ { 0x0000a350, 0x00000000, 0x00000000, 0x00050f5e, 0x00050f5e, 0x00050f5e },
+ { 0x0000a354, 0x00000000, 0x00000000, 0x00054f9e, 0x00054f9e, 0x00054f9e },
+ { 0x0000a780, 0x00000000, 0x00000000, 0x00000060, 0x00000060, 0x00000060 },
+ { 0x0000a784, 0x00000000, 0x00000000, 0x00004062, 0x00004062, 0x00004062 },
+ { 0x0000a788, 0x00000000, 0x00000000, 0x00008064, 0x00008064, 0x00008064 },
+ { 0x0000a78c, 0x00000000, 0x00000000, 0x0000c0a4, 0x0000c0a4, 0x0000c0a4 },
+ { 0x0000a790, 0x00000000, 0x00000000, 0x000100b0, 0x000100b0, 0x000100b0 },
+ { 0x0000a794, 0x00000000, 0x00000000, 0x000140b2, 0x000140b2, 0x000140b2 },
+ { 0x0000a798, 0x00000000, 0x00000000, 0x000180b4, 0x000180b4, 0x000180b4 },
+ { 0x0000a79c, 0x00000000, 0x00000000, 0x0001c0f4, 0x0001c0f4, 0x0001c0f4 },
+ { 0x0000a7a0, 0x00000000, 0x00000000, 0x00020134, 0x00020134, 0x00020134 },
+ { 0x0000a7a4, 0x00000000, 0x00000000, 0x000240fe, 0x000240fe, 0x000240fe },
+ { 0x0000a7a8, 0x00000000, 0x00000000, 0x0002813e, 0x0002813e, 0x0002813e },
+ { 0x0000a7ac, 0x00000000, 0x00000000, 0x0002c17e, 0x0002c17e, 0x0002c17e },
+ { 0x0000a7b0, 0x00000000, 0x00000000, 0x000301be, 0x000301be, 0x000301be },
+ { 0x0000a7b4, 0x00000000, 0x00000000, 0x000341fe, 0x000341fe, 0x000341fe },
+ { 0x0000a7b8, 0x00000000, 0x00000000, 0x000341fe, 0x000341fe, 0x000341fe },
+ { 0x0000a7bc, 0x00000000, 0x00000000, 0x000341fe, 0x000341fe, 0x000341fe },
+ { 0x0000a7c0, 0x00000000, 0x00000000, 0x000341fe, 0x000341fe, 0x000341fe },
+ { 0x0000a7c4, 0x00000000, 0x00000000, 0x000341fe, 0x000341fe, 0x000341fe },
+ { 0x0000a7c8, 0x00000000, 0x00000000, 0x000341fe, 0x000341fe, 0x000341fe },
+ { 0x0000a7cc, 0x00000000, 0x00000000, 0x000341fe, 0x000341fe, 0x000341fe },
+ { 0x0000a7d0, 0x00000000, 0x00000000, 0x000341fe, 0x000341fe, 0x000341fe },
+ { 0x0000a7d4, 0x00000000, 0x00000000, 0x000341fe, 0x000341fe, 0x000341fe },
+ { 0x0000a274, 0x0a180000, 0x0a180000, 0x0a1aa000, 0x0a1aa000, 0x0a1aa000 },
+};
+
+
+static const u_int32_t ar9287Modes_rx_gain_9287_1_0[][6] = {
+ /* Address 5G-HT20 5G-HT40 2G-HT40 2G-HT20 Turbo */
+ { 0x00009a00, 0x00000000, 0x00000000, 0x0000a120, 0x0000a120, 0x0000a120 },
+ { 0x00009a04, 0x00000000, 0x00000000, 0x0000a124, 0x0000a124, 0x0000a124 },
+ { 0x00009a08, 0x00000000, 0x00000000, 0x0000a128, 0x0000a128, 0x0000a128 },
+ { 0x00009a0c, 0x00000000, 0x00000000, 0x0000a12c, 0x0000a12c, 0x0000a12c },
+ { 0x00009a10, 0x00000000, 0x00000000, 0x0000a130, 0x0000a130, 0x0000a130 },
+ { 0x00009a14, 0x00000000, 0x00000000, 0x0000a194, 0x0000a194, 0x0000a194 },
+ { 0x00009a18, 0x00000000, 0x00000000, 0x0000a198, 0x0000a198, 0x0000a198 },
+ { 0x00009a1c, 0x00000000, 0x00000000, 0x0000a20c, 0x0000a20c, 0x0000a20c },
+ { 0x00009a20, 0x00000000, 0x00000000, 0x0000a210, 0x0000a210, 0x0000a210 },
+ { 0x00009a24, 0x00000000, 0x00000000, 0x0000a284, 0x0000a284, 0x0000a284 },
+ { 0x00009a28, 0x00000000, 0x00000000, 0x0000a288, 0x0000a288, 0x0000a288 },
+ { 0x00009a2c, 0x00000000, 0x00000000, 0x0000a28c, 0x0000a28c, 0x0000a28c },
+ { 0x00009a30, 0x00000000, 0x00000000, 0x0000a290, 0x0000a290, 0x0000a290 },
+ { 0x00009a34, 0x00000000, 0x00000000, 0x0000a294, 0x0000a294, 0x0000a294 },
+ { 0x00009a38, 0x00000000, 0x00000000, 0x0000a2a0, 0x0000a2a0, 0x0000a2a0 },
+ { 0x00009a3c, 0x00000000, 0x00000000, 0x0000a2a4, 0x0000a2a4, 0x0000a2a4 },
+ { 0x00009a40, 0x00000000, 0x00000000, 0x0000a2a8, 0x0000a2a8, 0x0000a2a8 },
+ { 0x00009a44, 0x00000000, 0x00000000, 0x0000a2ac, 0x0000a2ac, 0x0000a2ac },
+ { 0x00009a48, 0x00000000, 0x00000000, 0x0000a2b0, 0x0000a2b0, 0x0000a2b0 },
+ { 0x00009a4c, 0x00000000, 0x00000000, 0x0000a2b4, 0x0000a2b4, 0x0000a2b4 },
+ { 0x00009a50, 0x00000000, 0x00000000, 0x0000a2b8, 0x0000a2b8, 0x0000a2b8 },
+ { 0x00009a54, 0x00000000, 0x00000000, 0x0000a2c4, 0x0000a2c4, 0x0000a2c4 },
+ { 0x00009a58, 0x00000000, 0x00000000, 0x0000a708, 0x0000a708, 0x0000a708 },
+ { 0x00009a5c, 0x00000000, 0x00000000, 0x0000a70c, 0x0000a70c, 0x0000a70c },
+ { 0x00009a60, 0x00000000, 0x00000000, 0x0000a710, 0x0000a710, 0x0000a710 },
+ { 0x00009a64, 0x00000000, 0x00000000, 0x0000ab04, 0x0000ab04, 0x0000ab04 },
+ { 0x00009a68, 0x00000000, 0x00000000, 0x0000ab08, 0x0000ab08, 0x0000ab08 },
+ { 0x00009a6c, 0x00000000, 0x00000000, 0x0000ab0c, 0x0000ab0c, 0x0000ab0c },
+ { 0x00009a70, 0x00000000, 0x00000000, 0x0000ab10, 0x0000ab10, 0x0000ab10 },
+ { 0x00009a74, 0x00000000, 0x00000000, 0x0000ab14, 0x0000ab14, 0x0000ab14 },
+ { 0x00009a78, 0x00000000, 0x00000000, 0x0000ab18, 0x0000ab18, 0x0000ab18 },
+ { 0x00009a7c, 0x00000000, 0x00000000, 0x0000ab8c, 0x0000ab8c, 0x0000ab8c },
+ { 0x00009a80, 0x00000000, 0x00000000, 0x0000ab90, 0x0000ab90, 0x0000ab90 },
+ { 0x00009a84, 0x00000000, 0x00000000, 0x0000ab94, 0x0000ab94, 0x0000ab94 },
+ { 0x00009a88, 0x00000000, 0x00000000, 0x0000ab98, 0x0000ab98, 0x0000ab98 },
+ { 0x00009a8c, 0x00000000, 0x00000000, 0x0000aba4, 0x0000aba4, 0x0000aba4 },
+ { 0x00009a90, 0x00000000, 0x00000000, 0x0000aba8, 0x0000aba8, 0x0000aba8 },
+ { 0x00009a94, 0x00000000, 0x00000000, 0x0000cb04, 0x0000cb04, 0x0000cb04 },
+ { 0x00009a98, 0x00000000, 0x00000000, 0x0000cb08, 0x0000cb08, 0x0000cb08 },
+ { 0x00009a9c, 0x00000000, 0x00000000, 0x0000cb0c, 0x0000cb0c, 0x0000cb0c },
+ { 0x00009aa0, 0x00000000, 0x00000000, 0x0000cb10, 0x0000cb10, 0x0000cb10 },
+ { 0x00009aa4, 0x00000000, 0x00000000, 0x0000cb14, 0x0000cb14, 0x0000cb14 },
+ { 0x00009aa8, 0x00000000, 0x00000000, 0x0000cb18, 0x0000cb18, 0x0000cb18 },
+ { 0x00009aac, 0x00000000, 0x00000000, 0x0000cb8c, 0x0000cb8c, 0x0000cb8c },
+ { 0x00009ab0, 0x00000000, 0x00000000, 0x0000cb90, 0x0000cb90, 0x0000cb90 },
+ { 0x00009ab4, 0x00000000, 0x00000000, 0x0000cf18, 0x0000cf18, 0x0000cf18 },
+ { 0x00009ab8, 0x00000000, 0x00000000, 0x0000cf24, 0x0000cf24, 0x0000cf24 },
+ { 0x00009abc, 0x00000000, 0x00000000, 0x0000cf28, 0x0000cf28, 0x0000cf28 },
+ { 0x00009ac0, 0x00000000, 0x00000000, 0x0000d314, 0x0000d314, 0x0000d314 },
+ { 0x00009ac4, 0x00000000, 0x00000000, 0x0000d318, 0x0000d318, 0x0000d318 },
+ { 0x00009ac8, 0x00000000, 0x00000000, 0x0000d38c, 0x0000d38c, 0x0000d38c },
+ { 0x00009acc, 0x00000000, 0x00000000, 0x0000d390, 0x0000d390, 0x0000d390 },
+ { 0x00009ad0, 0x00000000, 0x00000000, 0x0000d394, 0x0000d394, 0x0000d394 },
+ { 0x00009ad4, 0x00000000, 0x00000000, 0x0000d398, 0x0000d398, 0x0000d398 },
+ { 0x00009ad8, 0x00000000, 0x00000000, 0x0000d3a4, 0x0000d3a4, 0x0000d3a4 },
+ { 0x00009adc, 0x00000000, 0x00000000, 0x0000d3a8, 0x0000d3a8, 0x0000d3a8 },
+ { 0x00009ae0, 0x00000000, 0x00000000, 0x0000d3ac, 0x0000d3ac, 0x0000d3ac },
+ { 0x00009ae4, 0x00000000, 0x00000000, 0x0000d3b0, 0x0000d3b0, 0x0000d3b0 },
+ { 0x00009ae8, 0x00000000, 0x00000000, 0x0000f380, 0x0000f380, 0x0000f380 },
+ { 0x00009aec, 0x00000000, 0x00000000, 0x0000f384, 0x0000f384, 0x0000f384 },
+ { 0x00009af0, 0x00000000, 0x00000000, 0x0000f388, 0x0000f388, 0x0000f388 },
+ { 0x00009af4, 0x00000000, 0x00000000, 0x0000f710, 0x0000f710, 0x0000f710 },
+ { 0x00009af8, 0x00000000, 0x00000000, 0x0000f714, 0x0000f714, 0x0000f714 },
+ { 0x00009afc, 0x00000000, 0x00000000, 0x0000f718, 0x0000f718, 0x0000f718 },
+ { 0x00009b00, 0x00000000, 0x00000000, 0x0000fb10, 0x0000fb10, 0x0000fb10 },
+ { 0x00009b04, 0x00000000, 0x00000000, 0x0000fb14, 0x0000fb14, 0x0000fb14 },
+ { 0x00009b08, 0x00000000, 0x00000000, 0x0000fb18, 0x0000fb18, 0x0000fb18 },
+ { 0x00009b0c, 0x00000000, 0x00000000, 0x0000fb8c, 0x0000fb8c, 0x0000fb8c },
+ { 0x00009b10, 0x00000000, 0x00000000, 0x0000fb90, 0x0000fb90, 0x0000fb90 },
+ { 0x00009b14, 0x00000000, 0x00000000, 0x0000fb94, 0x0000fb94, 0x0000fb94 },
+ { 0x00009b18, 0x00000000, 0x00000000, 0x0000ff8c, 0x0000ff8c, 0x0000ff8c },
+ { 0x00009b1c, 0x00000000, 0x00000000, 0x0000ff90, 0x0000ff90, 0x0000ff90 },
+ { 0x00009b20, 0x00000000, 0x00000000, 0x0000ff94, 0x0000ff94, 0x0000ff94 },
+ { 0x00009b24, 0x00000000, 0x00000000, 0x0000ffa0, 0x0000ffa0, 0x0000ffa0 },
+ { 0x00009b28, 0x00000000, 0x00000000, 0x0000ffa4, 0x0000ffa4, 0x0000ffa4 },
+ { 0x00009b2c, 0x00000000, 0x00000000, 0x0000ffa8, 0x0000ffa8, 0x0000ffa8 },
+ { 0x00009b30, 0x00000000, 0x00000000, 0x0000ffac, 0x0000ffac, 0x0000ffac },
+ { 0x00009b34, 0x00000000, 0x00000000, 0x0000ffb0, 0x0000ffb0, 0x0000ffb0 },
+ { 0x00009b38, 0x00000000, 0x00000000, 0x0000ffb4, 0x0000ffb4, 0x0000ffb4 },
+ { 0x00009b3c, 0x00000000, 0x00000000, 0x0000ffa1, 0x0000ffa1, 0x0000ffa1 },
+ { 0x00009b40, 0x00000000, 0x00000000, 0x0000ffa5, 0x0000ffa5, 0x0000ffa5 },
+ { 0x00009b44, 0x00000000, 0x00000000, 0x0000ffa9, 0x0000ffa9, 0x0000ffa9 },
+ { 0x00009b48, 0x00000000, 0x00000000, 0x0000ffad, 0x0000ffad, 0x0000ffad },
+ { 0x00009b4c, 0x00000000, 0x00000000, 0x0000ffb1, 0x0000ffb1, 0x0000ffb1 },
+ { 0x00009b50, 0x00000000, 0x00000000, 0x0000ffb5, 0x0000ffb5, 0x0000ffb5 },
+ { 0x00009b54, 0x00000000, 0x00000000, 0x0000ffb9, 0x0000ffb9, 0x0000ffb9 },
+ { 0x00009b58, 0x00000000, 0x00000000, 0x0000ffc5, 0x0000ffc5, 0x0000ffc5 },
+ { 0x00009b5c, 0x00000000, 0x00000000, 0x0000ffc9, 0x0000ffc9, 0x0000ffc9 },
+ { 0x00009b60, 0x00000000, 0x00000000, 0x0000ffcd, 0x0000ffcd, 0x0000ffcd },
+ { 0x00009b64, 0x00000000, 0x00000000, 0x0000ffd1, 0x0000ffd1, 0x0000ffd1 },
+ { 0x00009b68, 0x00000000, 0x00000000, 0x0000ffd5, 0x0000ffd5, 0x0000ffd5 },
+ { 0x00009b6c, 0x00000000, 0x00000000, 0x0000ffc2, 0x0000ffc2, 0x0000ffc2 },
+ { 0x00009b70, 0x00000000, 0x00000000, 0x0000ffc6, 0x0000ffc6, 0x0000ffc6 },
+ { 0x00009b74, 0x00000000, 0x00000000, 0x0000ffca, 0x0000ffca, 0x0000ffca },
+ { 0x00009b78, 0x00000000, 0x00000000, 0x0000ffce, 0x0000ffce, 0x0000ffce },
+ { 0x00009b7c, 0x00000000, 0x00000000, 0x0000ffd2, 0x0000ffd2, 0x0000ffd2 },
+ { 0x00009b80, 0x00000000, 0x00000000, 0x0000ffd6, 0x0000ffd6, 0x0000ffd6 },
+ { 0x00009b84, 0x00000000, 0x00000000, 0x0000ffda, 0x0000ffda, 0x0000ffda },
+ { 0x00009b88, 0x00000000, 0x00000000, 0x0000ffc7, 0x0000ffc7, 0x0000ffc7 },
+ { 0x00009b8c, 0x00000000, 0x00000000, 0x0000ffcb, 0x0000ffcb, 0x0000ffcb },
+ { 0x00009b90, 0x00000000, 0x00000000, 0x0000ffcf, 0x0000ffcf, 0x0000ffcf },
+ { 0x00009b94, 0x00000000, 0x00000000, 0x0000ffd3, 0x0000ffd3, 0x0000ffd3 },
+ { 0x00009b98, 0x00000000, 0x00000000, 0x0000ffd7, 0x0000ffd7, 0x0000ffd7 },
+ { 0x00009b9c, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb },
+ { 0x00009ba0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb },
+ { 0x00009ba4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb },
+ { 0x00009ba8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb },
+ { 0x00009bac, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb },
+ { 0x00009bb0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb },
+ { 0x00009bb4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb },
+ { 0x00009bb8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb },
+ { 0x00009bbc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb },
+ { 0x00009bc0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb },
+ { 0x00009bc4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb },
+ { 0x00009bc8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb },
+ { 0x00009bcc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb },
+ { 0x00009bd0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb },
+ { 0x00009bd4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb },
+ { 0x00009bd8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb },
+ { 0x00009bdc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb },
+ { 0x00009be0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb },
+ { 0x00009be4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb },
+ { 0x00009be8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb },
+ { 0x00009bec, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb },
+ { 0x00009bf0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb },
+ { 0x00009bf4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb },
+ { 0x00009bf8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb },
+ { 0x00009bfc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb },
+ { 0x0000aa00, 0x00000000, 0x00000000, 0x0000a120, 0x0000a120, 0x0000a120 },
+ { 0x0000aa04, 0x00000000, 0x00000000, 0x0000a124, 0x0000a124, 0x0000a124 },
+ { 0x0000aa08, 0x00000000, 0x00000000, 0x0000a128, 0x0000a128, 0x0000a128 },
+ { 0x0000aa0c, 0x00000000, 0x00000000, 0x0000a12c, 0x0000a12c, 0x0000a12c },
+ { 0x0000aa10, 0x00000000, 0x00000000, 0x0000a130, 0x0000a130, 0x0000a130 },
+ { 0x0000aa14, 0x00000000, 0x00000000, 0x0000a194, 0x0000a194, 0x0000a194 },
+ { 0x0000aa18, 0x00000000, 0x00000000, 0x0000a198, 0x0000a198, 0x0000a198 },
+ { 0x0000aa1c, 0x00000000, 0x00000000, 0x0000a20c, 0x0000a20c, 0x0000a20c },
+ { 0x0000aa20, 0x00000000, 0x00000000, 0x0000a210, 0x0000a210, 0x0000a210 },
+ { 0x0000aa24, 0x00000000, 0x00000000, 0x0000a284, 0x0000a284, 0x0000a284 },
+ { 0x0000aa28, 0x00000000, 0x00000000, 0x0000a288, 0x0000a288, 0x0000a288 },
+ { 0x0000aa2c, 0x00000000, 0x00000000, 0x0000a28c, 0x0000a28c, 0x0000a28c },
+ { 0x0000aa30, 0x00000000, 0x00000000, 0x0000a290, 0x0000a290, 0x0000a290 },
+ { 0x0000aa34, 0x00000000, 0x00000000, 0x0000a294, 0x0000a294, 0x0000a294 },
+ { 0x0000aa38, 0x00000000, 0x00000000, 0x0000a2a0, 0x0000a2a0, 0x0000a2a0 },
+ { 0x0000aa3c, 0x00000000, 0x00000000, 0x0000a2a4, 0x0000a2a4, 0x0000a2a4 },
+ { 0x0000aa40, 0x00000000, 0x00000000, 0x0000a2a8, 0x0000a2a8, 0x0000a2a8 },
+ { 0x0000aa44, 0x00000000, 0x00000000, 0x0000a2ac, 0x0000a2ac, 0x0000a2ac },
+ { 0x0000aa48, 0x00000000, 0x00000000, 0x0000a2b0, 0x0000a2b0, 0x0000a2b0 },
+ { 0x0000aa4c, 0x00000000, 0x00000000, 0x0000a2b4, 0x0000a2b4, 0x0000a2b4 },
+ { 0x0000aa50, 0x00000000, 0x00000000, 0x0000a2b8, 0x0000a2b8, 0x0000a2b8 },
+ { 0x0000aa54, 0x00000000, 0x00000000, 0x0000a2c4, 0x0000a2c4, 0x0000a2c4 },
+ { 0x0000aa58, 0x00000000, 0x00000000, 0x0000a708, 0x0000a708, 0x0000a708 },
+ { 0x0000aa5c, 0x00000000, 0x00000000, 0x0000a70c, 0x0000a70c, 0x0000a70c },
+ { 0x0000aa60, 0x00000000, 0x00000000, 0x0000a710, 0x0000a710, 0x0000a710 },
+ { 0x0000aa64, 0x00000000, 0x00000000, 0x0000ab04, 0x0000ab04, 0x0000ab04 },
+ { 0x0000aa68, 0x00000000, 0x00000000, 0x0000ab08, 0x0000ab08, 0x0000ab08 },
+ { 0x0000aa6c, 0x00000000, 0x00000000, 0x0000ab0c, 0x0000ab0c, 0x0000ab0c },
+ { 0x0000aa70, 0x00000000, 0x00000000, 0x0000ab10, 0x0000ab10, 0x0000ab10 },
+ { 0x0000aa74, 0x00000000, 0x00000000, 0x0000ab14, 0x0000ab14, 0x0000ab14 },
+ { 0x0000aa78, 0x00000000, 0x00000000, 0x0000ab18, 0x0000ab18, 0x0000ab18 },
+ { 0x0000aa7c, 0x00000000, 0x00000000, 0x0000ab8c, 0x0000ab8c, 0x0000ab8c },
+ { 0x0000aa80, 0x00000000, 0x00000000, 0x0000ab90, 0x0000ab90, 0x0000ab90 },
+ { 0x0000aa84, 0x00000000, 0x00000000, 0x0000ab94, 0x0000ab94, 0x0000ab94 },
+ { 0x0000aa88, 0x00000000, 0x00000000, 0x0000ab98, 0x0000ab98, 0x0000ab98 },
+ { 0x0000aa8c, 0x00000000, 0x00000000, 0x0000aba4, 0x0000aba4, 0x0000aba4 },
+ { 0x0000aa90, 0x00000000, 0x00000000, 0x0000aba8, 0x0000aba8, 0x0000aba8 },
+ { 0x0000aa94, 0x00000000, 0x00000000, 0x0000cb04, 0x0000cb04, 0x0000cb04 },
+ { 0x0000aa98, 0x00000000, 0x00000000, 0x0000cb08, 0x0000cb08, 0x0000cb08 },
+ { 0x0000aa9c, 0x00000000, 0x00000000, 0x0000cb0c, 0x0000cb0c, 0x0000cb0c },
+ { 0x0000aaa0, 0x00000000, 0x00000000, 0x0000cb10, 0x0000cb10, 0x0000cb10 },
+ { 0x0000aaa4, 0x00000000, 0x00000000, 0x0000cb14, 0x0000cb14, 0x0000cb14 },
+ { 0x0000aaa8, 0x00000000, 0x00000000, 0x0000cb18, 0x0000cb18, 0x0000cb18 },
+ { 0x0000aaac, 0x00000000, 0x00000000, 0x0000cb8c, 0x0000cb8c, 0x0000cb8c },
+ { 0x0000aab0, 0x00000000, 0x00000000, 0x0000cb90, 0x0000cb90, 0x0000cb90 },
+ { 0x0000aab4, 0x00000000, 0x00000000, 0x0000cf18, 0x0000cf18, 0x0000cf18 },
+ { 0x0000aab8, 0x00000000, 0x00000000, 0x0000cf24, 0x0000cf24, 0x0000cf24 },
+ { 0x0000aabc, 0x00000000, 0x00000000, 0x0000cf28, 0x0000cf28, 0x0000cf28 },
+ { 0x0000aac0, 0x00000000, 0x00000000, 0x0000d314, 0x0000d314, 0x0000d314 },
+ { 0x0000aac4, 0x00000000, 0x00000000, 0x0000d318, 0x0000d318, 0x0000d318 },
+ { 0x0000aac8, 0x00000000, 0x00000000, 0x0000d38c, 0x0000d38c, 0x0000d38c },
+ { 0x0000aacc, 0x00000000, 0x00000000, 0x0000d390, 0x0000d390, 0x0000d390 },
+ { 0x0000aad0, 0x00000000, 0x00000000, 0x0000d394, 0x0000d394, 0x0000d394 },
+ { 0x0000aad4, 0x00000000, 0x00000000, 0x0000d398, 0x0000d398, 0x0000d398 },
+ { 0x0000aad8, 0x00000000, 0x00000000, 0x0000d3a4, 0x0000d3a4, 0x0000d3a4 },
+ { 0x0000aadc, 0x00000000, 0x00000000, 0x0000d3a8, 0x0000d3a8, 0x0000d3a8 },
+ { 0x0000aae0, 0x00000000, 0x00000000, 0x0000d3ac, 0x0000d3ac, 0x0000d3ac },
+ { 0x0000aae4, 0x00000000, 0x00000000, 0x0000d3b0, 0x0000d3b0, 0x0000d3b0 },
+ { 0x0000aae8, 0x00000000, 0x00000000, 0x0000f380, 0x0000f380, 0x0000f380 },
+ { 0x0000aaec, 0x00000000, 0x00000000, 0x0000f384, 0x0000f384, 0x0000f384 },
+ { 0x0000aaf0, 0x00000000, 0x00000000, 0x0000f388, 0x0000f388, 0x0000f388 },
+ { 0x0000aaf4, 0x00000000, 0x00000000, 0x0000f710, 0x0000f710, 0x0000f710 },
+ { 0x0000aaf8, 0x00000000, 0x00000000, 0x0000f714, 0x0000f714, 0x0000f714 },
+ { 0x0000aafc, 0x00000000, 0x00000000, 0x0000f718, 0x0000f718, 0x0000f718 },
+ { 0x0000ab00, 0x00000000, 0x00000000, 0x0000fb10, 0x0000fb10, 0x0000fb10 },
+ { 0x0000ab04, 0x00000000, 0x00000000, 0x0000fb14, 0x0000fb14, 0x0000fb14 },
+ { 0x0000ab08, 0x00000000, 0x00000000, 0x0000fb18, 0x0000fb18, 0x0000fb18 },
+ { 0x0000ab0c, 0x00000000, 0x00000000, 0x0000fb8c, 0x0000fb8c, 0x0000fb8c },
+ { 0x0000ab10, 0x00000000, 0x00000000, 0x0000fb90, 0x0000fb90, 0x0000fb90 },
+ { 0x0000ab14, 0x00000000, 0x00000000, 0x0000fb94, 0x0000fb94, 0x0000fb94 },
+ { 0x0000ab18, 0x00000000, 0x00000000, 0x0000ff8c, 0x0000ff8c, 0x0000ff8c },
+ { 0x0000ab1c, 0x00000000, 0x00000000, 0x0000ff90, 0x0000ff90, 0x0000ff90 },
+ { 0x0000ab20, 0x00000000, 0x00000000, 0x0000ff94, 0x0000ff94, 0x0000ff94 },
+ { 0x0000ab24, 0x00000000, 0x00000000, 0x0000ffa0, 0x0000ffa0, 0x0000ffa0 },
+ { 0x0000ab28, 0x00000000, 0x00000000, 0x0000ffa4, 0x0000ffa4, 0x0000ffa4 },
+ { 0x0000ab2c, 0x00000000, 0x00000000, 0x0000ffa8, 0x0000ffa8, 0x0000ffa8 },
+ { 0x0000ab30, 0x00000000, 0x00000000, 0x0000ffac, 0x0000ffac, 0x0000ffac },
+ { 0x0000ab34, 0x00000000, 0x00000000, 0x0000ffb0, 0x0000ffb0, 0x0000ffb0 },
+ { 0x0000ab38, 0x00000000, 0x00000000, 0x0000ffb4, 0x0000ffb4, 0x0000ffb4 },
+ { 0x0000ab3c, 0x00000000, 0x00000000, 0x0000ffa1, 0x0000ffa1, 0x0000ffa1 },
+ { 0x0000ab40, 0x00000000, 0x00000000, 0x0000ffa5, 0x0000ffa5, 0x0000ffa5 },
+ { 0x0000ab44, 0x00000000, 0x00000000, 0x0000ffa9, 0x0000ffa9, 0x0000ffa9 },
+ { 0x0000ab48, 0x00000000, 0x00000000, 0x0000ffad, 0x0000ffad, 0x0000ffad },
+ { 0x0000ab4c, 0x00000000, 0x00000000, 0x0000ffb1, 0x0000ffb1, 0x0000ffb1 },
+ { 0x0000ab50, 0x00000000, 0x00000000, 0x0000ffb5, 0x0000ffb5, 0x0000ffb5 },
+ { 0x0000ab54, 0x00000000, 0x00000000, 0x0000ffb9, 0x0000ffb9, 0x0000ffb9 },
+ { 0x0000ab58, 0x00000000, 0x00000000, 0x0000ffc5, 0x0000ffc5, 0x0000ffc5 },
+ { 0x0000ab5c, 0x00000000, 0x00000000, 0x0000ffc9, 0x0000ffc9, 0x0000ffc9 },
+ { 0x0000ab60, 0x00000000, 0x00000000, 0x0000ffcd, 0x0000ffcd, 0x0000ffcd },
+ { 0x0000ab64, 0x00000000, 0x00000000, 0x0000ffd1, 0x0000ffd1, 0x0000ffd1 },
+ { 0x0000ab68, 0x00000000, 0x00000000, 0x0000ffd5, 0x0000ffd5, 0x0000ffd5 },
+ { 0x0000ab6c, 0x00000000, 0x00000000, 0x0000ffc2, 0x0000ffc2, 0x0000ffc2 },
+ { 0x0000ab70, 0x00000000, 0x00000000, 0x0000ffc6, 0x0000ffc6, 0x0000ffc6 },
+ { 0x0000ab74, 0x00000000, 0x00000000, 0x0000ffca, 0x0000ffca, 0x0000ffca },
+ { 0x0000ab78, 0x00000000, 0x00000000, 0x0000ffce, 0x0000ffce, 0x0000ffce },
+ { 0x0000ab7c, 0x00000000, 0x00000000, 0x0000ffd2, 0x0000ffd2, 0x0000ffd2 },
+ { 0x0000ab80, 0x00000000, 0x00000000, 0x0000ffd6, 0x0000ffd6, 0x0000ffd6 },
+ { 0x0000ab84, 0x00000000, 0x00000000, 0x0000ffda, 0x0000ffda, 0x0000ffda },
+ { 0x0000ab88, 0x00000000, 0x00000000, 0x0000ffc7, 0x0000ffc7, 0x0000ffc7 },
+ { 0x0000ab8c, 0x00000000, 0x00000000, 0x0000ffcb, 0x0000ffcb, 0x0000ffcb },
+ { 0x0000ab90, 0x00000000, 0x00000000, 0x0000ffcf, 0x0000ffcf, 0x0000ffcf },
+ { 0x0000ab94, 0x00000000, 0x00000000, 0x0000ffd3, 0x0000ffd3, 0x0000ffd3 },
+ { 0x0000ab98, 0x00000000, 0x00000000, 0x0000ffd7, 0x0000ffd7, 0x0000ffd7 },
+ { 0x0000ab9c, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb },
+ { 0x0000aba0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb },
+ { 0x0000aba4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb },
+ { 0x0000aba8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb },
+ { 0x0000abac, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb },
+ { 0x0000abb0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb },
+ { 0x0000abb4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb },
+ { 0x0000abb8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb },
+ { 0x0000abbc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb },
+ { 0x0000abc0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb },
+ { 0x0000abc4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb },
+ { 0x0000abc8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb },
+ { 0x0000abcc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb },
+ { 0x0000abd0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb },
+ { 0x0000abd4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb },
+ { 0x0000abd8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb },
+ { 0x0000abdc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb },
+ { 0x0000abe0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb },
+ { 0x0000abe4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb },
+ { 0x0000abe8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb },
+ { 0x0000abec, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb },
+ { 0x0000abf0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb },
+ { 0x0000abf4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb },
+ { 0x0000abf8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb },
+ { 0x0000abfc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb },
+ { 0x00009848, 0x00000000, 0x00000000, 0x00001067, 0x00001067, 0x00001067 },
+ { 0x0000a848, 0x00000000, 0x00000000, 0x00001067, 0x00001067, 0x00001067 },
+};
+
+static const u_int32_t ar9287PciePhy_clkreq_always_on_L1_9287_1_0[][2] = {
+ {0x00004040, 0x9248fd00 },
+ {0x00004040, 0x24924924 },
+ {0x00004040, 0xa8000019 },
+ {0x00004040, 0x13160820 },
+ {0x00004040, 0xe5980560 },
+ {0x00004040, 0xc01dcffd },
+ {0x00004040, 0x1aaabe41 },
+ {0x00004040, 0xbe105554 },
+ {0x00004040, 0x00043007 },
+ {0x00004044, 0x00000000 },
+};
+
+static const u_int32_t ar9287PciePhy_clkreq_off_L1_9287_1_0[][2] = {
+ {0x00004040, 0x9248fd00 },
+ {0x00004040, 0x24924924 },
+ {0x00004040, 0xa8000019 },
+ {0x00004040, 0x13160820 },
+ {0x00004040, 0xe5980560 },
+ {0x00004040, 0xc01dcffc },
+ {0x00004040, 0x1aaabe41 },
+ {0x00004040, 0xbe105554 },
+ {0x00004040, 0x00043007 },
+ {0x00004044, 0x00000000 },
+};
+
+/* AR9287 Revision 11 */
+
+static const u_int32_t ar9287Modes_9287_1_1[][6] = {
+ /* Address 5G-HT20 5G-HT40 2G-HT40 2G-HT20 Turbo */
+ { 0x00001030, 0x00000000, 0x00000000, 0x000002c0, 0x00000160, 0x000001e0 },
+ { 0x00001070, 0x00000000, 0x00000000, 0x00000318, 0x0000018c, 0x000001e0 },
+ { 0x000010b0, 0x00000000, 0x00000000, 0x00007c70, 0x00003e38, 0x00001180 },
+ { 0x000010f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000008 },
+ { 0x00008014, 0x00000000, 0x00000000, 0x10801600, 0x08400b00, 0x06e006e0 },
+ { 0x0000801c, 0x00000000, 0x00000000, 0x12e00057, 0x12e0002b, 0x0988004f },
+ { 0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810, 0x08f04810 },
+ { 0x000081d0, 0x00003200, 0x00003200, 0x0000320a, 0x0000320a, 0x0000320a },
+ { 0x00008318, 0x00000000, 0x00000000, 0x00006880, 0x00003440, 0x00006880 },
+ { 0x00009804, 0x00000000, 0x00000000, 0x000003c4, 0x00000300, 0x00000303 },
+ { 0x00009820, 0x00000000, 0x00000000, 0x02020200, 0x02020200, 0x02020200 },
+ { 0x00009824, 0x00000000, 0x00000000, 0x01000e0e, 0x01000e0e, 0x01000e0e },
+ { 0x00009828, 0x00000000, 0x00000000, 0x3a020001, 0x3a020001, 0x3a020001 },
+ { 0x00009834, 0x00000000, 0x00000000, 0x00000e0e, 0x00000e0e, 0x00000e0e },
+ { 0x00009838, 0x00000003, 0x00000003, 0x00000007, 0x00000007, 0x00000007 },
+ { 0x00009840, 0x206a002e, 0x206a002e, 0x206a012e, 0x206a012e, 0x206a012e },
+ { 0x00009844, 0x03720000, 0x03720000, 0x037216a0, 0x037216a0, 0x037216a0 },
+ { 0x00009850, 0x60000000, 0x60000000, 0x6d4000e2, 0x6c4000e2, 0x6c4000e2 },
+ { 0x00009858, 0x7c000d00, 0x7c000d00, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e },
+ { 0x0000985c, 0x3100005e, 0x3100005e, 0x3139605e, 0x31395d5e, 0x31395d5e },
+ { 0x00009860, 0x00058d00, 0x00058d00, 0x00058d20, 0x00058d20, 0x00058d18 },
+ { 0x00009864, 0x00000e00, 0x00000e00, 0x0001ce00, 0x0001ce00, 0x0001ce00 },
+ { 0x00009868, 0x000040c0, 0x000040c0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0 },
+ { 0x0000986c, 0x00000080, 0x00000080, 0x06903881, 0x06903881, 0x06903881 },
+ { 0x00009914, 0x00000000, 0x00000000, 0x00001130, 0x00000898, 0x000007d0 },
+ { 0x00009918, 0x00000000, 0x00000000, 0x00000016, 0x0000000b, 0x00000016 },
+ { 0x00009924, 0xd00a8a01, 0xd00a8a01, 0xd00a8a0d, 0xd00a8a0d, 0xd00a8a0d },
+ { 0x00009944, 0xefbc0000, 0xefbc0000, 0xefbc1010, 0xefbc1010, 0xefbc1010 },
+ { 0x00009960, 0x00000000, 0x00000000, 0x00000010, 0x00000010, 0x00000010 },
+ { 0x0000a960, 0x00000000, 0x00000000, 0x00000010, 0x00000010, 0x00000010 },
+ { 0x00009964, 0x00000000, 0x00000000, 0x00000210, 0x00000210, 0x00000210 },
+ { 0x0000c968, 0x00000200, 0x00000200, 0x000003ce, 0x000003ce, 0x000003ce },
+ { 0x000099b8, 0x00000000, 0x00000000, 0x0000001c, 0x0000001c, 0x0000001c },
+ { 0x000099bc, 0x00000000, 0x00000000, 0x00000c00, 0x00000c00, 0x00000c00 },
+ { 0x000099c0, 0x00000000, 0x00000000, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4 },
+ { 0x0000a204, 0x00000440, 0x00000440, 0x00000444, 0x00000444, 0x00000444 },
+ { 0x0000a20c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x0000b20c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x0000a21c, 0x1803800a, 0x1803800a, 0x1883800a, 0x1883800a, 0x1883800a },
+ { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 },
+ { 0x0000a250, 0x00000000, 0x00000000, 0x0004a000, 0x0004a000, 0x0004a000 },
+ { 0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e, 0x7999aa0e },
+ { 0x0000a3d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+};
+
+static const u_int32_t ar9287Common_9287_1_1[][2] = {
+ { 0x0000000c, 0x00000000 },
+ { 0x00000030, 0x00020015 },
+ { 0x00000034, 0x00000005 },
+ { 0x00000040, 0x00000000 },
+ { 0x00000044, 0x00000008 },
+ { 0x00000048, 0x00000008 },
+ { 0x0000004c, 0x00000010 },
+ { 0x00000050, 0x00000000 },
+ { 0x00000054, 0x0000001f },
+ { 0x00000800, 0x00000000 },
+ { 0x00000804, 0x00000000 },
+ { 0x00000808, 0x00000000 },
+ { 0x0000080c, 0x00000000 },
+ { 0x00000810, 0x00000000 },
+ { 0x00000814, 0x00000000 },
+ { 0x00000818, 0x00000000 },
+ { 0x0000081c, 0x00000000 },
+ { 0x00000820, 0x00000000 },
+ { 0x00000824, 0x00000000 },
+ { 0x00001040, 0x002ffc0f },
+ { 0x00001044, 0x002ffc0f },
+ { 0x00001048, 0x002ffc0f },
+ { 0x0000104c, 0x002ffc0f },
+ { 0x00001050, 0x002ffc0f },
+ { 0x00001054, 0x002ffc0f },
+ { 0x00001058, 0x002ffc0f },
+ { 0x0000105c, 0x002ffc0f },
+ { 0x00001060, 0x002ffc0f },
+ { 0x00001064, 0x002ffc0f },
+ { 0x00001230, 0x00000000 },
+ { 0x00001270, 0x00000000 },
+ { 0x00001038, 0x00000000 },
+ { 0x00001078, 0x00000000 },
+ { 0x000010b8, 0x00000000 },
+ { 0x000010f8, 0x00000000 },
+ { 0x00001138, 0x00000000 },
+ { 0x00001178, 0x00000000 },
+ { 0x000011b8, 0x00000000 },
+ { 0x000011f8, 0x00000000 },
+ { 0x00001238, 0x00000000 },
+ { 0x00001278, 0x00000000 },
+ { 0x000012b8, 0x00000000 },
+ { 0x000012f8, 0x00000000 },
+ { 0x00001338, 0x00000000 },
+ { 0x00001378, 0x00000000 },
+ { 0x000013b8, 0x00000000 },
+ { 0x000013f8, 0x00000000 },
+ { 0x00001438, 0x00000000 },
+ { 0x00001478, 0x00000000 },
+ { 0x000014b8, 0x00000000 },
+ { 0x000014f8, 0x00000000 },
+ { 0x00001538, 0x00000000 },
+ { 0x00001578, 0x00000000 },
+ { 0x000015b8, 0x00000000 },
+ { 0x000015f8, 0x00000000 },
+ { 0x00001638, 0x00000000 },
+ { 0x00001678, 0x00000000 },
+ { 0x000016b8, 0x00000000 },
+ { 0x000016f8, 0x00000000 },
+ { 0x00001738, 0x00000000 },
+ { 0x00001778, 0x00000000 },
+ { 0x000017b8, 0x00000000 },
+ { 0x000017f8, 0x00000000 },
+ { 0x0000103c, 0x00000000 },
+ { 0x0000107c, 0x00000000 },
+ { 0x000010bc, 0x00000000 },
+ { 0x000010fc, 0x00000000 },
+ { 0x0000113c, 0x00000000 },
+ { 0x0000117c, 0x00000000 },
+ { 0x000011bc, 0x00000000 },
+ { 0x000011fc, 0x00000000 },
+ { 0x0000123c, 0x00000000 },
+ { 0x0000127c, 0x00000000 },
+ { 0x000012bc, 0x00000000 },
+ { 0x000012fc, 0x00000000 },
+ { 0x0000133c, 0x00000000 },
+ { 0x0000137c, 0x00000000 },
+ { 0x000013bc, 0x00000000 },
+ { 0x000013fc, 0x00000000 },
+ { 0x0000143c, 0x00000000 },
+ { 0x0000147c, 0x00000000 },
+ { 0x00004030, 0x00000002 },
+ { 0x0000403c, 0x00000002 },
+ { 0x00004024, 0x0000001f },
+ { 0x00004060, 0x00000000 },
+ { 0x00004064, 0x00000000 },
+ { 0x00007010, 0x00000033 },
+ { 0x00007020, 0x00000000 },
+ { 0x00007034, 0x00000002 },
+ { 0x00007038, 0x000004c2 },
+ { 0x00008004, 0x00000000 },
+ { 0x00008008, 0x00000000 },
+ { 0x0000800c, 0x00000000 },
+ { 0x00008018, 0x00000700 },
+ { 0x00008020, 0x00000000 },
+ { 0x00008038, 0x00000000 },
+ { 0x0000803c, 0x00000000 },
+ { 0x00008048, 0x40000000 },
+ { 0x00008054, 0x00000000 },
+ { 0x00008058, 0x00000000 },
+ { 0x0000805c, 0x000fc78f },
+ { 0x00008060, 0x0000000f },
+ { 0x00008064, 0x00000000 },
+ { 0x00008070, 0x00000000 },
+ { 0x000080c0, 0x2a80001a },
+ { 0x000080c4, 0x05dc01e0 },
+ { 0x000080c8, 0x1f402710 },
+ { 0x000080cc, 0x01f40000 },
+ { 0x000080d0, 0x00001e00 },
+ { 0x000080d4, 0x00000000 },
+ { 0x000080d8, 0x00400000 },
+ { 0x000080e0, 0xffffffff },
+ { 0x000080e4, 0x0000ffff },
+ { 0x000080e8, 0x003f3f3f },
+ { 0x000080ec, 0x00000000 },
+ { 0x000080f0, 0x00000000 },
+ { 0x000080f4, 0x00000000 },
+ { 0x000080f8, 0x00000000 },
+ { 0x000080fc, 0x00020000 },
+ { 0x00008100, 0x00020000 },
+ { 0x00008104, 0x00000001 },
+ { 0x00008108, 0x00000052 },
+ { 0x0000810c, 0x00000000 },
+ { 0x00008110, 0x00000168 },
+ { 0x00008118, 0x000100aa },
+ { 0x0000811c, 0x00003210 },
+ { 0x00008124, 0x00000000 },
+ { 0x00008128, 0x00000000 },
+ { 0x0000812c, 0x00000000 },
+ { 0x00008130, 0x00000000 },
+ { 0x00008134, 0x00000000 },
+ { 0x00008138, 0x00000000 },
+ { 0x0000813c, 0x00000000 },
+ { 0x00008144, 0xffffffff },
+ { 0x00008168, 0x00000000 },
+ { 0x0000816c, 0x00000000 },
+ { 0x00008170, 0x18487320 },
+ { 0x00008174, 0xfaa4fa50 },
+ { 0x00008178, 0x00000100 },
+ { 0x0000817c, 0x00000000 },
+ { 0x000081c0, 0x00000000 },
+ { 0x000081c4, 0x00000000 },
+ { 0x000081d4, 0x00000000 },
+ { 0x000081ec, 0x00000000 },
+ { 0x000081f0, 0x00000000 },
+ { 0x000081f4, 0x00000000 },
+ { 0x000081f8, 0x00000000 },
+ { 0x000081fc, 0x00000000 },
+ { 0x00008200, 0x00000000 },
+ { 0x00008204, 0x00000000 },
+ { 0x00008208, 0x00000000 },
+ { 0x0000820c, 0x00000000 },
+ { 0x00008210, 0x00000000 },
+ { 0x00008214, 0x00000000 },
+ { 0x00008218, 0x00000000 },
+ { 0x0000821c, 0x00000000 },
+ { 0x00008220, 0x00000000 },
+ { 0x00008224, 0x00000000 },
+ { 0x00008228, 0x00000000 },
+ { 0x0000822c, 0x00000000 },
+ { 0x00008230, 0x00000000 },
+ { 0x00008234, 0x00000000 },
+ { 0x00008238, 0x00000000 },
+ { 0x0000823c, 0x00000000 },
+ { 0x00008240, 0x00100000 },
+ { 0x00008244, 0x0010f400 },
+ { 0x00008248, 0x00000100 },
+ { 0x0000824c, 0x0001e800 },
+ { 0x00008250, 0x00000000 },
+ { 0x00008254, 0x00000000 },
+ { 0x00008258, 0x00000000 },
+ { 0x0000825c, 0x400000ff },
+ { 0x00008260, 0x00080922 },
+ { 0x00008264, 0x88a00010 },
+ { 0x00008270, 0x00000000 },
+ { 0x00008274, 0x40000000 },
+ { 0x00008278, 0x003e4180 },
+ { 0x0000827c, 0x00000000 },
+ { 0x00008284, 0x0000002c },
+ { 0x00008288, 0x0000002c },
+ { 0x0000828c, 0x000000ff },
+ { 0x00008294, 0x00000000 },
+ { 0x00008298, 0x00000000 },
+ { 0x0000829c, 0x00000000 },
+ { 0x00008300, 0x00000040 },
+ { 0x00008314, 0x00000000 },
+ { 0x00008328, 0x00000000 },
+ { 0x0000832c, 0x00000007 },
+ { 0x00008330, 0x00000302 },
+ { 0x00008334, 0x00000e00 },
+ { 0x00008338, 0x00ff0000 },
+ { 0x0000833c, 0x00000000 },
+ { 0x00008340, 0x000107ff },
+ { 0x00008344, 0x01c81043 },
+ { 0x00008360, 0xffffffff },
+ { 0x00008364, 0xffffffff },
+ { 0x00008368, 0x00000000 },
+ { 0x00008370, 0x00000000 },
+ { 0x00008374, 0x000000ff },
+ { 0x00008378, 0x00000000 },
+ { 0x0000837c, 0x00000000 },
+ { 0x00008380, 0xffffffff },
+ { 0x00008384, 0xffffffff },
+ { 0x00008390, 0x0fffffff },
+ { 0x00008394, 0x0fffffff },
+ { 0x00008398, 0x00000000 },
+ { 0x0000839c, 0x00000000 },
+ { 0x000083a0, 0x00000000 },
+ { 0x00009808, 0x00000000 },
+ { 0x0000980c, 0xafe68e30 },
+ { 0x00009810, 0xfd14e000 },
+ { 0x00009814, 0x9c0a9f6b },
+ { 0x0000981c, 0x00000000 },
+ { 0x0000982c, 0x0000a000 },
+ { 0x00009830, 0x00000000 },
+ { 0x0000983c, 0x00200400 },
+ { 0x0000984c, 0x0040233c },
+ { 0x0000a84c, 0x0040233c },
+ { 0x00009854, 0x00000044 },
+ { 0x00009900, 0x00000000 },
+ { 0x00009904, 0x00000000 },
+ { 0x00009908, 0x00000000 },
+ { 0x0000990c, 0x00000000 },
+ { 0x00009910, 0x10002310 },
+ { 0x0000991c, 0x10000fff },
+ { 0x00009920, 0x04900000 },
+ { 0x0000a920, 0x04900000 },
+ { 0x00009928, 0x00000001 },
+ { 0x0000992c, 0x00000004 },
+ { 0x00009930, 0x00000000 },
+ { 0x0000a930, 0x00000000 },
+ { 0x00009934, 0x1e1f2022 },
+ { 0x00009938, 0x0a0b0c0d },
+ { 0x0000993c, 0x00000000 },
+ { 0x00009948, 0x9280c00a },
+ { 0x0000994c, 0x00020028 },
+ { 0x00009954, 0x5f3ca3de },
+ { 0x00009958, 0x0108ecff },
+ { 0x00009940, 0x14750604 },
+ { 0x0000c95c, 0x004b6a8e },
+ { 0x00009970, 0x990bb514 },
+ { 0x00009974, 0x00000000 },
+ { 0x00009978, 0x00000001 },
+ { 0x0000997c, 0x00000000 },
+ { 0x000099a0, 0x00000000 },
+ { 0x000099a4, 0x00000001 },
+ { 0x000099a8, 0x201fff00 },
+ { 0x000099ac, 0x0c6f0000 },
+ { 0x000099b0, 0x03051000 },
+ { 0x000099b4, 0x00000820 },
+ { 0x000099c4, 0x06336f77 },
+ { 0x000099c8, 0x6af6532f },
+ { 0x000099cc, 0x08f186c8 },
+ { 0x000099d0, 0x00046384 },
+ { 0x000099dc, 0x00000000 },
+ { 0x000099e0, 0x00000000 },
+ { 0x000099e4, 0xaaaaaaaa },
+ { 0x000099e8, 0x3c466478 },
+ { 0x000099ec, 0x0cc80caa },
+ { 0x000099f0, 0x00000000 },
+ { 0x000099fc, 0x00001042 },
+ { 0x0000a1f4, 0x00fffeff },
+ { 0x0000a1f8, 0x00f5f9ff },
+ { 0x0000a1fc, 0xb79f6427 },
+ { 0x0000a208, 0x803e4788 },
+ { 0x0000a210, 0x4080a333 },
+ { 0x0000a214, 0x40206c10 },
+ { 0x0000a218, 0x009c4060 },
+ { 0x0000a220, 0x01834061 },
+ { 0x0000a224, 0x00000400 },
+ { 0x0000a228, 0x000003b5 },
+ { 0x0000a22c, 0x233f7180 },
+ { 0x0000a234, 0x20202020 },
+ { 0x0000a238, 0x20202020 },
+ { 0x0000a23c, 0x13c889af },
+ { 0x0000a240, 0x38490a20 },
+ { 0x0000a244, 0x00000000 },
+ { 0x0000a248, 0xfffffffc },
+ { 0x0000a24c, 0x00000000 },
+ { 0x0000a254, 0x00000000 },
+ { 0x0000a258, 0x0cdbd380 },
+ { 0x0000a25c, 0x0f0f0f01 },
+ { 0x0000a260, 0xdfa91f01 },
+ { 0x0000a264, 0x00418a11 },
+ { 0x0000b264, 0x00418a11 },
+ { 0x0000a268, 0x00000000 },
+ { 0x0000a26c, 0x0e79e5c6 },
+ { 0x0000b26c, 0x0e79e5c6 },
+ { 0x0000d270, 0x00820820 },
+ { 0x0000a278, 0x1ce739ce },
+ { 0x0000a27c, 0x050701ce },
+ { 0x0000d35c, 0x07ffffef },
+ { 0x0000d360, 0x0fffffe7 },
+ { 0x0000d364, 0x17ffffe5 },
+ { 0x0000d368, 0x1fffffe4 },
+ { 0x0000d36c, 0x37ffffe3 },
+ { 0x0000d370, 0x3fffffe3 },
+ { 0x0000d374, 0x57ffffe3 },
+ { 0x0000d378, 0x5fffffe2 },
+ { 0x0000d37c, 0x7fffffe2 },
+ { 0x0000d380, 0x7f3c7bba },
+ { 0x0000d384, 0xf3307ff0 },
+ { 0x0000a388, 0x0c000000 },
+ { 0x0000a38c, 0x20202020 },
+ { 0x0000a390, 0x20202020 },
+ { 0x0000a394, 0x1ce739ce },
+ { 0x0000a398, 0x000001ce },
+ { 0x0000b398, 0x000001ce },
+ { 0x0000a39c, 0x00000001 },
+ { 0x0000a3c8, 0x00000246 },
+ { 0x0000a3cc, 0x20202020 },
+ { 0x0000a3d0, 0x20202020 },
+ { 0x0000a3d4, 0x20202020 },
+ { 0x0000a3dc, 0x1ce739ce },
+ { 0x0000a3e0, 0x000001ce },
+ { 0x0000a3e4, 0x00000000 },
+ { 0x0000a3e8, 0x18c43433 },
+ { 0x0000a3ec, 0x00f70081 },
+ { 0x0000a3f0, 0x01036a1e },
+ { 0x0000a3f4, 0x00000000 },
+ { 0x0000b3f4, 0x00000000 },
+ { 0x0000a7d8, 0x000003f1 },
+ { 0x00007800, 0x00000800 },
+ { 0x00007804, 0x6c35ffc2 },
+ { 0x00007808, 0x6db6c000 },
+ { 0x0000780c, 0x6db6cb30 },
+ { 0x00007810, 0x6db6cb6c },
+ { 0x00007814, 0x0501e200 },
+ { 0x00007818, 0x0094128d },
+ { 0x0000781c, 0x976ee392 },
+ { 0x00007820, 0xf75ff6fc },
+ { 0x00007824, 0x00040000 },
+ { 0x00007828, 0xdb003012 },
+ { 0x0000782c, 0x04924914 },
+ { 0x00007830, 0x21084210 },
+ { 0x00007834, 0x00140000 },
+ { 0x00007838, 0x0e4548d8 },
+ { 0x0000783c, 0x54214514 },
+ { 0x00007840, 0x02025830 },
+ { 0x00007844, 0x71c0d388 },
+ { 0x00007848, 0x934934a8 },
+ { 0x00007850, 0x00000000 },
+ { 0x00007854, 0x00000800 },
+ { 0x00007858, 0x6c35ffc2 },
+ { 0x0000785c, 0x6db6c000 },
+ { 0x00007860, 0x6db6cb30 },
+ { 0x00007864, 0x6db6cb6c },
+ { 0x00007868, 0x0501e200 },
+ { 0x0000786c, 0x0094128d },
+ { 0x00007870, 0x976ee392 },
+ { 0x00007874, 0xf75ff6fc },
+ { 0x00007878, 0x00040000 },
+ { 0x0000787c, 0xdb003012 },
+ { 0x00007880, 0x04924914 },
+ { 0x00007884, 0x21084210 },
+ { 0x00007888, 0x001b6db0 },
+ { 0x0000788c, 0x00376b63 },
+ { 0x00007890, 0x06db6db6 },
+ { 0x00007894, 0x006d8000 },
+ { 0x00007898, 0x48100000 },
+ { 0x0000789c, 0x00000000 },
+ { 0x000078a0, 0x08000000 },
+ { 0x000078a4, 0x0007ffd8 },
+ { 0x000078a8, 0x0007ffd8 },
+ { 0x000078ac, 0x001c0020 },
+ { 0x000078b0, 0x00060aeb },
+ { 0x000078b4, 0x40008080 },
+ { 0x000078b8, 0x2a850160 },
+};
+
+static const u_int32_t ar9287Modes_tx_gain_9287_1_1[][6] = {
+ /* Address 5G-HT20 5G-HT40 2G-HT40 2G-HT20 Turbo */
+ { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x0000a304, 0x00000000, 0x00000000, 0x00004002, 0x00004002, 0x00004002 },
+ { 0x0000a308, 0x00000000, 0x00000000, 0x00008004, 0x00008004, 0x00008004 },
+ { 0x0000a30c, 0x00000000, 0x00000000, 0x0000c00a, 0x0000c00a, 0x0000c00a },
+ { 0x0000a310, 0x00000000, 0x00000000, 0x0001000c, 0x0001000c, 0x0001000c },
+ { 0x0000a314, 0x00000000, 0x00000000, 0x0001420b, 0x0001420b, 0x0001420b },
+ { 0x0000a318, 0x00000000, 0x00000000, 0x0001824a, 0x0001824a, 0x0001824a },
+ { 0x0000a31c, 0x00000000, 0x00000000, 0x0001c44a, 0x0001c44a, 0x0001c44a },
+ { 0x0000a320, 0x00000000, 0x00000000, 0x0002064a, 0x0002064a, 0x0002064a },
+ { 0x0000a324, 0x00000000, 0x00000000, 0x0002484a, 0x0002484a, 0x0002484a },
+ { 0x0000a328, 0x00000000, 0x00000000, 0x00028a4a, 0x00028a4a, 0x00028a4a },
+ { 0x0000a32c, 0x00000000, 0x00000000, 0x0002cc4a, 0x0002cc4a, 0x0002cc4a },
+ { 0x0000a330, 0x00000000, 0x00000000, 0x00030e4a, 0x00030e4a, 0x00030e4a },
+ { 0x0000a334, 0x00000000, 0x00000000, 0x00034e8a, 0x00034e8a, 0x00034e8a },
+ { 0x0000a338, 0x00000000, 0x00000000, 0x00038e8c, 0x00038e8c, 0x00038e8c },
+ { 0x0000a33c, 0x00000000, 0x00000000, 0x0003cecc, 0x0003cecc, 0x0003cecc },
+ { 0x0000a340, 0x00000000, 0x00000000, 0x00040ed4, 0x00040ed4, 0x00040ed4 },
+ { 0x0000a344, 0x00000000, 0x00000000, 0x00044edc, 0x00044edc, 0x00044edc },
+ { 0x0000a348, 0x00000000, 0x00000000, 0x00048ede, 0x00048ede, 0x00048ede },
+ { 0x0000a34c, 0x00000000, 0x00000000, 0x0004cf1e, 0x0004cf1e, 0x0004cf1e },
+ { 0x0000a350, 0x00000000, 0x00000000, 0x00050f5e, 0x00050f5e, 0x00050f5e },
+ { 0x0000a354, 0x00000000, 0x00000000, 0x00054f9e, 0x00054f9e, 0x00054f9e },
+ { 0x0000a780, 0x00000000, 0x00000000, 0x00000062, 0x00000062, 0x00000062 },
+ { 0x0000a784, 0x00000000, 0x00000000, 0x00004064, 0x00004064, 0x00004064 },
+ { 0x0000a788, 0x00000000, 0x00000000, 0x000080a4, 0x000080a4, 0x000080a4 },
+ { 0x0000a78c, 0x00000000, 0x00000000, 0x0000c0aa, 0x0000c0aa, 0x0000c0aa },
+ { 0x0000a790, 0x00000000, 0x00000000, 0x000100ac, 0x000100ac, 0x000100ac },
+ { 0x0000a794, 0x00000000, 0x00000000, 0x000140b4, 0x000140b4, 0x000140b4 },
+ { 0x0000a798, 0x00000000, 0x00000000, 0x000180f4, 0x000180f4, 0x000180f4 },
+ { 0x0000a79c, 0x00000000, 0x00000000, 0x0001c134, 0x0001c134, 0x0001c134 },
+ { 0x0000a7a0, 0x00000000, 0x00000000, 0x00020174, 0x00020174, 0x00020174 },
+ { 0x0000a7a4, 0x00000000, 0x00000000, 0x0002417c, 0x0002417c, 0x0002417c },
+ { 0x0000a7a8, 0x00000000, 0x00000000, 0x0002817e, 0x0002817e, 0x0002817e },
+ { 0x0000a7ac, 0x00000000, 0x00000000, 0x0002c1be, 0x0002c1be, 0x0002c1be },
+ { 0x0000a7b0, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe },
+ { 0x0000a7b4, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe },
+ { 0x0000a7b8, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe },
+ { 0x0000a7bc, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe },
+ { 0x0000a7c0, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe },
+ { 0x0000a7c4, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe },
+ { 0x0000a7c8, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe },
+ { 0x0000a7cc, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe },
+ { 0x0000a7d0, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe },
+ { 0x0000a7d4, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe },
+ { 0x0000a274, 0x0a180000, 0x0a180000, 0x0a1aa000, 0x0a1aa000, 0x0a1aa000 },
+};
+
+static const u_int32_t ar9287Modes_rx_gain_9287_1_1[][6] = {
+ /* Address 5G-HT20 5G-HT40 2G-HT40 2G-HT20 Turbo */
+ { 0x00009a00, 0x00000000, 0x00000000, 0x0000a120, 0x0000a120, 0x0000a120 },
+ { 0x00009a04, 0x00000000, 0x00000000, 0x0000a124, 0x0000a124, 0x0000a124 },
+ { 0x00009a08, 0x00000000, 0x00000000, 0x0000a128, 0x0000a128, 0x0000a128 },
+ { 0x00009a0c, 0x00000000, 0x00000000, 0x0000a12c, 0x0000a12c, 0x0000a12c },
+ { 0x00009a10, 0x00000000, 0x00000000, 0x0000a130, 0x0000a130, 0x0000a130 },
+ { 0x00009a14, 0x00000000, 0x00000000, 0x0000a194, 0x0000a194, 0x0000a194 },
+ { 0x00009a18, 0x00000000, 0x00000000, 0x0000a198, 0x0000a198, 0x0000a198 },
+ { 0x00009a1c, 0x00000000, 0x00000000, 0x0000a20c, 0x0000a20c, 0x0000a20c },
+ { 0x00009a20, 0x00000000, 0x00000000, 0x0000a210, 0x0000a210, 0x0000a210 },
+ { 0x00009a24, 0x00000000, 0x00000000, 0x0000a284, 0x0000a284, 0x0000a284 },
+ { 0x00009a28, 0x00000000, 0x00000000, 0x0000a288, 0x0000a288, 0x0000a288 },
+ { 0x00009a2c, 0x00000000, 0x00000000, 0x0000a28c, 0x0000a28c, 0x0000a28c },
+ { 0x00009a30, 0x00000000, 0x00000000, 0x0000a290, 0x0000a290, 0x0000a290 },
+ { 0x00009a34, 0x00000000, 0x00000000, 0x0000a294, 0x0000a294, 0x0000a294 },
+ { 0x00009a38, 0x00000000, 0x00000000, 0x0000a2a0, 0x0000a2a0, 0x0000a2a0 },
+ { 0x00009a3c, 0x00000000, 0x00000000, 0x0000a2a4, 0x0000a2a4, 0x0000a2a4 },
+ { 0x00009a40, 0x00000000, 0x00000000, 0x0000a2a8, 0x0000a2a8, 0x0000a2a8 },
+ { 0x00009a44, 0x00000000, 0x00000000, 0x0000a2ac, 0x0000a2ac, 0x0000a2ac },
+ { 0x00009a48, 0x00000000, 0x00000000, 0x0000a2b0, 0x0000a2b0, 0x0000a2b0 },
+ { 0x00009a4c, 0x00000000, 0x00000000, 0x0000a2b4, 0x0000a2b4, 0x0000a2b4 },
+ { 0x00009a50, 0x00000000, 0x00000000, 0x0000a2b8, 0x0000a2b8, 0x0000a2b8 },
+ { 0x00009a54, 0x00000000, 0x00000000, 0x0000a2c4, 0x0000a2c4, 0x0000a2c4 },
+ { 0x00009a58, 0x00000000, 0x00000000, 0x0000a708, 0x0000a708, 0x0000a708 },
+ { 0x00009a5c, 0x00000000, 0x00000000, 0x0000a70c, 0x0000a70c, 0x0000a70c },
+ { 0x00009a60, 0x00000000, 0x00000000, 0x0000a710, 0x0000a710, 0x0000a710 },
+ { 0x00009a64, 0x00000000, 0x00000000, 0x0000ab04, 0x0000ab04, 0x0000ab04 },
+ { 0x00009a68, 0x00000000, 0x00000000, 0x0000ab08, 0x0000ab08, 0x0000ab08 },
+ { 0x00009a6c, 0x00000000, 0x00000000, 0x0000ab0c, 0x0000ab0c, 0x0000ab0c },
+ { 0x00009a70, 0x00000000, 0x00000000, 0x0000ab10, 0x0000ab10, 0x0000ab10 },
+ { 0x00009a74, 0x00000000, 0x00000000, 0x0000ab14, 0x0000ab14, 0x0000ab14 },
+ { 0x00009a78, 0x00000000, 0x00000000, 0x0000ab18, 0x0000ab18, 0x0000ab18 },
+ { 0x00009a7c, 0x00000000, 0x00000000, 0x0000ab8c, 0x0000ab8c, 0x0000ab8c },
+ { 0x00009a80, 0x00000000, 0x00000000, 0x0000ab90, 0x0000ab90, 0x0000ab90 },
+ { 0x00009a84, 0x00000000, 0x00000000, 0x0000ab94, 0x0000ab94, 0x0000ab94 },
+ { 0x00009a88, 0x00000000, 0x00000000, 0x0000ab98, 0x0000ab98, 0x0000ab98 },
+ { 0x00009a8c, 0x00000000, 0x00000000, 0x0000aba4, 0x0000aba4, 0x0000aba4 },
+ { 0x00009a90, 0x00000000, 0x00000000, 0x0000aba8, 0x0000aba8, 0x0000aba8 },
+ { 0x00009a94, 0x00000000, 0x00000000, 0x0000cb04, 0x0000cb04, 0x0000cb04 },
+ { 0x00009a98, 0x00000000, 0x00000000, 0x0000cb08, 0x0000cb08, 0x0000cb08 },
+ { 0x00009a9c, 0x00000000, 0x00000000, 0x0000cb0c, 0x0000cb0c, 0x0000cb0c },
+ { 0x00009aa0, 0x00000000, 0x00000000, 0x0000cb10, 0x0000cb10, 0x0000cb10 },
+ { 0x00009aa4, 0x00000000, 0x00000000, 0x0000cb14, 0x0000cb14, 0x0000cb14 },
+ { 0x00009aa8, 0x00000000, 0x00000000, 0x0000cb18, 0x0000cb18, 0x0000cb18 },
+ { 0x00009aac, 0x00000000, 0x00000000, 0x0000cb8c, 0x0000cb8c, 0x0000cb8c },
+ { 0x00009ab0, 0x00000000, 0x00000000, 0x0000cb90, 0x0000cb90, 0x0000cb90 },
+ { 0x00009ab4, 0x00000000, 0x00000000, 0x0000cf18, 0x0000cf18, 0x0000cf18 },
+ { 0x00009ab8, 0x00000000, 0x00000000, 0x0000cf24, 0x0000cf24, 0x0000cf24 },
+ { 0x00009abc, 0x00000000, 0x00000000, 0x0000cf28, 0x0000cf28, 0x0000cf28 },
+ { 0x00009ac0, 0x00000000, 0x00000000, 0x0000d314, 0x0000d314, 0x0000d314 },
+ { 0x00009ac4, 0x00000000, 0x00000000, 0x0000d318, 0x0000d318, 0x0000d318 },
+ { 0x00009ac8, 0x00000000, 0x00000000, 0x0000d38c, 0x0000d38c, 0x0000d38c },
+ { 0x00009acc, 0x00000000, 0x00000000, 0x0000d390, 0x0000d390, 0x0000d390 },
+ { 0x00009ad0, 0x00000000, 0x00000000, 0x0000d394, 0x0000d394, 0x0000d394 },
+ { 0x00009ad4, 0x00000000, 0x00000000, 0x0000d398, 0x0000d398, 0x0000d398 },
+ { 0x00009ad8, 0x00000000, 0x00000000, 0x0000d3a4, 0x0000d3a4, 0x0000d3a4 },
+ { 0x00009adc, 0x00000000, 0x00000000, 0x0000d3a8, 0x0000d3a8, 0x0000d3a8 },
+ { 0x00009ae0, 0x00000000, 0x00000000, 0x0000d3ac, 0x0000d3ac, 0x0000d3ac },
+ { 0x00009ae4, 0x00000000, 0x00000000, 0x0000d3b0, 0x0000d3b0, 0x0000d3b0 },
+ { 0x00009ae8, 0x00000000, 0x00000000, 0x0000f380, 0x0000f380, 0x0000f380 },
+ { 0x00009aec, 0x00000000, 0x00000000, 0x0000f384, 0x0000f384, 0x0000f384 },
+ { 0x00009af0, 0x00000000, 0x00000000, 0x0000f388, 0x0000f388, 0x0000f388 },
+ { 0x00009af4, 0x00000000, 0x00000000, 0x0000f710, 0x0000f710, 0x0000f710 },
+ { 0x00009af8, 0x00000000, 0x00000000, 0x0000f714, 0x0000f714, 0x0000f714 },
+ { 0x00009afc, 0x00000000, 0x00000000, 0x0000f718, 0x0000f718, 0x0000f718 },
+ { 0x00009b00, 0x00000000, 0x00000000, 0x0000fb10, 0x0000fb10, 0x0000fb10 },
+ { 0x00009b04, 0x00000000, 0x00000000, 0x0000fb14, 0x0000fb14, 0x0000fb14 },
+ { 0x00009b08, 0x00000000, 0x00000000, 0x0000fb18, 0x0000fb18, 0x0000fb18 },
+ { 0x00009b0c, 0x00000000, 0x00000000, 0x0000fb8c, 0x0000fb8c, 0x0000fb8c },
+ { 0x00009b10, 0x00000000, 0x00000000, 0x0000fb90, 0x0000fb90, 0x0000fb90 },
+ { 0x00009b14, 0x00000000, 0x00000000, 0x0000fb94, 0x0000fb94, 0x0000fb94 },
+ { 0x00009b18, 0x00000000, 0x00000000, 0x0000ff8c, 0x0000ff8c, 0x0000ff8c },
+ { 0x00009b1c, 0x00000000, 0x00000000, 0x0000ff90, 0x0000ff90, 0x0000ff90 },
+ { 0x00009b20, 0x00000000, 0x00000000, 0x0000ff94, 0x0000ff94, 0x0000ff94 },
+ { 0x00009b24, 0x00000000, 0x00000000, 0x0000ffa0, 0x0000ffa0, 0x0000ffa0 },
+ { 0x00009b28, 0x00000000, 0x00000000, 0x0000ffa4, 0x0000ffa4, 0x0000ffa4 },
+ { 0x00009b2c, 0x00000000, 0x00000000, 0x0000ffa8, 0x0000ffa8, 0x0000ffa8 },
+ { 0x00009b30, 0x00000000, 0x00000000, 0x0000ffac, 0x0000ffac, 0x0000ffac },
+ { 0x00009b34, 0x00000000, 0x00000000, 0x0000ffb0, 0x0000ffb0, 0x0000ffb0 },
+ { 0x00009b38, 0x00000000, 0x00000000, 0x0000ffb4, 0x0000ffb4, 0x0000ffb4 },
+ { 0x00009b3c, 0x00000000, 0x00000000, 0x0000ffa1, 0x0000ffa1, 0x0000ffa1 },
+ { 0x00009b40, 0x00000000, 0x00000000, 0x0000ffa5, 0x0000ffa5, 0x0000ffa5 },
+ { 0x00009b44, 0x00000000, 0x00000000, 0x0000ffa9, 0x0000ffa9, 0x0000ffa9 },
+ { 0x00009b48, 0x00000000, 0x00000000, 0x0000ffad, 0x0000ffad, 0x0000ffad },
+ { 0x00009b4c, 0x00000000, 0x00000000, 0x0000ffb1, 0x0000ffb1, 0x0000ffb1 },
+ { 0x00009b50, 0x00000000, 0x00000000, 0x0000ffb5, 0x0000ffb5, 0x0000ffb5 },
+ { 0x00009b54, 0x00000000, 0x00000000, 0x0000ffb9, 0x0000ffb9, 0x0000ffb9 },
+ { 0x00009b58, 0x00000000, 0x00000000, 0x0000ffc5, 0x0000ffc5, 0x0000ffc5 },
+ { 0x00009b5c, 0x00000000, 0x00000000, 0x0000ffc9, 0x0000ffc9, 0x0000ffc9 },
+ { 0x00009b60, 0x00000000, 0x00000000, 0x0000ffcd, 0x0000ffcd, 0x0000ffcd },
+ { 0x00009b64, 0x00000000, 0x00000000, 0x0000ffd1, 0x0000ffd1, 0x0000ffd1 },
+ { 0x00009b68, 0x00000000, 0x00000000, 0x0000ffd5, 0x0000ffd5, 0x0000ffd5 },
+ { 0x00009b6c, 0x00000000, 0x00000000, 0x0000ffc2, 0x0000ffc2, 0x0000ffc2 },
+ { 0x00009b70, 0x00000000, 0x00000000, 0x0000ffc6, 0x0000ffc6, 0x0000ffc6 },
+ { 0x00009b74, 0x00000000, 0x00000000, 0x0000ffca, 0x0000ffca, 0x0000ffca },
+ { 0x00009b78, 0x00000000, 0x00000000, 0x0000ffce, 0x0000ffce, 0x0000ffce },
+ { 0x00009b7c, 0x00000000, 0x00000000, 0x0000ffd2, 0x0000ffd2, 0x0000ffd2 },
+ { 0x00009b80, 0x00000000, 0x00000000, 0x0000ffd6, 0x0000ffd6, 0x0000ffd6 },
+ { 0x00009b84, 0x00000000, 0x00000000, 0x0000ffda, 0x0000ffda, 0x0000ffda },
+ { 0x00009b88, 0x00000000, 0x00000000, 0x0000ffc7, 0x0000ffc7, 0x0000ffc7 },
+ { 0x00009b8c, 0x00000000, 0x00000000, 0x0000ffcb, 0x0000ffcb, 0x0000ffcb },
+ { 0x00009b90, 0x00000000, 0x00000000, 0x0000ffcf, 0x0000ffcf, 0x0000ffcf },
+ { 0x00009b94, 0x00000000, 0x00000000, 0x0000ffd3, 0x0000ffd3, 0x0000ffd3 },
+ { 0x00009b98, 0x00000000, 0x00000000, 0x0000ffd7, 0x0000ffd7, 0x0000ffd7 },
+ { 0x00009b9c, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb },
+ { 0x00009ba0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb },
+ { 0x00009ba4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb },
+ { 0x00009ba8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb },
+ { 0x00009bac, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb },
+ { 0x00009bb0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb },
+ { 0x00009bb4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb },
+ { 0x00009bb8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb },
+ { 0x00009bbc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb },
+ { 0x00009bc0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb },
+ { 0x00009bc4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb },
+ { 0x00009bc8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb },
+ { 0x00009bcc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb },
+ { 0x00009bd0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb },
+ { 0x00009bd4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb },
+ { 0x00009bd8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb },
+ { 0x00009bdc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb },
+ { 0x00009be0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb },
+ { 0x00009be4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb },
+ { 0x00009be8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb },
+ { 0x00009bec, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb },
+ { 0x00009bf0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb },
+ { 0x00009bf4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb },
+ { 0x00009bf8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb },
+ { 0x00009bfc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb },
+ { 0x0000aa00, 0x00000000, 0x00000000, 0x0000a120, 0x0000a120, 0x0000a120 },
+ { 0x0000aa04, 0x00000000, 0x00000000, 0x0000a124, 0x0000a124, 0x0000a124 },
+ { 0x0000aa08, 0x00000000, 0x00000000, 0x0000a128, 0x0000a128, 0x0000a128 },
+ { 0x0000aa0c, 0x00000000, 0x00000000, 0x0000a12c, 0x0000a12c, 0x0000a12c },
+ { 0x0000aa10, 0x00000000, 0x00000000, 0x0000a130, 0x0000a130, 0x0000a130 },
+ { 0x0000aa14, 0x00000000, 0x00000000, 0x0000a194, 0x0000a194, 0x0000a194 },
+ { 0x0000aa18, 0x00000000, 0x00000000, 0x0000a198, 0x0000a198, 0x0000a198 },
+ { 0x0000aa1c, 0x00000000, 0x00000000, 0x0000a20c, 0x0000a20c, 0x0000a20c },
+ { 0x0000aa20, 0x00000000, 0x00000000, 0x0000a210, 0x0000a210, 0x0000a210 },
+ { 0x0000aa24, 0x00000000, 0x00000000, 0x0000a284, 0x0000a284, 0x0000a284 },
+ { 0x0000aa28, 0x00000000, 0x00000000, 0x0000a288, 0x0000a288, 0x0000a288 },
+ { 0x0000aa2c, 0x00000000, 0x00000000, 0x0000a28c, 0x0000a28c, 0x0000a28c },
+ { 0x0000aa30, 0x00000000, 0x00000000, 0x0000a290, 0x0000a290, 0x0000a290 },
+ { 0x0000aa34, 0x00000000, 0x00000000, 0x0000a294, 0x0000a294, 0x0000a294 },
+ { 0x0000aa38, 0x00000000, 0x00000000, 0x0000a2a0, 0x0000a2a0, 0x0000a2a0 },
+ { 0x0000aa3c, 0x00000000, 0x00000000, 0x0000a2a4, 0x0000a2a4, 0x0000a2a4 },
+ { 0x0000aa40, 0x00000000, 0x00000000, 0x0000a2a8, 0x0000a2a8, 0x0000a2a8 },
+ { 0x0000aa44, 0x00000000, 0x00000000, 0x0000a2ac, 0x0000a2ac, 0x0000a2ac },
+ { 0x0000aa48, 0x00000000, 0x00000000, 0x0000a2b0, 0x0000a2b0, 0x0000a2b0 },
+ { 0x0000aa4c, 0x00000000, 0x00000000, 0x0000a2b4, 0x0000a2b4, 0x0000a2b4 },
+ { 0x0000aa50, 0x00000000, 0x00000000, 0x0000a2b8, 0x0000a2b8, 0x0000a2b8 },
+ { 0x0000aa54, 0x00000000, 0x00000000, 0x0000a2c4, 0x0000a2c4, 0x0000a2c4 },
+ { 0x0000aa58, 0x00000000, 0x00000000, 0x0000a708, 0x0000a708, 0x0000a708 },
+ { 0x0000aa5c, 0x00000000, 0x00000000, 0x0000a70c, 0x0000a70c, 0x0000a70c },
+ { 0x0000aa60, 0x00000000, 0x00000000, 0x0000a710, 0x0000a710, 0x0000a710 },
+ { 0x0000aa64, 0x00000000, 0x00000000, 0x0000ab04, 0x0000ab04, 0x0000ab04 },
+ { 0x0000aa68, 0x00000000, 0x00000000, 0x0000ab08, 0x0000ab08, 0x0000ab08 },
+ { 0x0000aa6c, 0x00000000, 0x00000000, 0x0000ab0c, 0x0000ab0c, 0x0000ab0c },
+ { 0x0000aa70, 0x00000000, 0x00000000, 0x0000ab10, 0x0000ab10, 0x0000ab10 },
+ { 0x0000aa74, 0x00000000, 0x00000000, 0x0000ab14, 0x0000ab14, 0x0000ab14 },
+ { 0x0000aa78, 0x00000000, 0x00000000, 0x0000ab18, 0x0000ab18, 0x0000ab18 },
+ { 0x0000aa7c, 0x00000000, 0x00000000, 0x0000ab8c, 0x0000ab8c, 0x0000ab8c },
+ { 0x0000aa80, 0x00000000, 0x00000000, 0x0000ab90, 0x0000ab90, 0x0000ab90 },
+ { 0x0000aa84, 0x00000000, 0x00000000, 0x0000ab94, 0x0000ab94, 0x0000ab94 },
+ { 0x0000aa88, 0x00000000, 0x00000000, 0x0000ab98, 0x0000ab98, 0x0000ab98 },
+ { 0x0000aa8c, 0x00000000, 0x00000000, 0x0000aba4, 0x0000aba4, 0x0000aba4 },
+ { 0x0000aa90, 0x00000000, 0x00000000, 0x0000aba8, 0x0000aba8, 0x0000aba8 },
+ { 0x0000aa94, 0x00000000, 0x00000000, 0x0000cb04, 0x0000cb04, 0x0000cb04 },
+ { 0x0000aa98, 0x00000000, 0x00000000, 0x0000cb08, 0x0000cb08, 0x0000cb08 },
+ { 0x0000aa9c, 0x00000000, 0x00000000, 0x0000cb0c, 0x0000cb0c, 0x0000cb0c },
+ { 0x0000aaa0, 0x00000000, 0x00000000, 0x0000cb10, 0x0000cb10, 0x0000cb10 },
+ { 0x0000aaa4, 0x00000000, 0x00000000, 0x0000cb14, 0x0000cb14, 0x0000cb14 },
+ { 0x0000aaa8, 0x00000000, 0x00000000, 0x0000cb18, 0x0000cb18, 0x0000cb18 },
+ { 0x0000aaac, 0x00000000, 0x00000000, 0x0000cb8c, 0x0000cb8c, 0x0000cb8c },
+ { 0x0000aab0, 0x00000000, 0x00000000, 0x0000cb90, 0x0000cb90, 0x0000cb90 },
+ { 0x0000aab4, 0x00000000, 0x00000000, 0x0000cf18, 0x0000cf18, 0x0000cf18 },
+ { 0x0000aab8, 0x00000000, 0x00000000, 0x0000cf24, 0x0000cf24, 0x0000cf24 },
+ { 0x0000aabc, 0x00000000, 0x00000000, 0x0000cf28, 0x0000cf28, 0x0000cf28 },
+ { 0x0000aac0, 0x00000000, 0x00000000, 0x0000d314, 0x0000d314, 0x0000d314 },
+ { 0x0000aac4, 0x00000000, 0x00000000, 0x0000d318, 0x0000d318, 0x0000d318 },
+ { 0x0000aac8, 0x00000000, 0x00000000, 0x0000d38c, 0x0000d38c, 0x0000d38c },
+ { 0x0000aacc, 0x00000000, 0x00000000, 0x0000d390, 0x0000d390, 0x0000d390 },
+ { 0x0000aad0, 0x00000000, 0x00000000, 0x0000d394, 0x0000d394, 0x0000d394 },
+ { 0x0000aad4, 0x00000000, 0x00000000, 0x0000d398, 0x0000d398, 0x0000d398 },
+ { 0x0000aad8, 0x00000000, 0x00000000, 0x0000d3a4, 0x0000d3a4, 0x0000d3a4 },
+ { 0x0000aadc, 0x00000000, 0x00000000, 0x0000d3a8, 0x0000d3a8, 0x0000d3a8 },
+ { 0x0000aae0, 0x00000000, 0x00000000, 0x0000d3ac, 0x0000d3ac, 0x0000d3ac },
+ { 0x0000aae4, 0x00000000, 0x00000000, 0x0000d3b0, 0x0000d3b0, 0x0000d3b0 },
+ { 0x0000aae8, 0x00000000, 0x00000000, 0x0000f380, 0x0000f380, 0x0000f380 },
+ { 0x0000aaec, 0x00000000, 0x00000000, 0x0000f384, 0x0000f384, 0x0000f384 },
+ { 0x0000aaf0, 0x00000000, 0x00000000, 0x0000f388, 0x0000f388, 0x0000f388 },
+ { 0x0000aaf4, 0x00000000, 0x00000000, 0x0000f710, 0x0000f710, 0x0000f710 },
+ { 0x0000aaf8, 0x00000000, 0x00000000, 0x0000f714, 0x0000f714, 0x0000f714 },
+ { 0x0000aafc, 0x00000000, 0x00000000, 0x0000f718, 0x0000f718, 0x0000f718 },
+ { 0x0000ab00, 0x00000000, 0x00000000, 0x0000fb10, 0x0000fb10, 0x0000fb10 },
+ { 0x0000ab04, 0x00000000, 0x00000000, 0x0000fb14, 0x0000fb14, 0x0000fb14 },
+ { 0x0000ab08, 0x00000000, 0x00000000, 0x0000fb18, 0x0000fb18, 0x0000fb18 },
+ { 0x0000ab0c, 0x00000000, 0x00000000, 0x0000fb8c, 0x0000fb8c, 0x0000fb8c },
+ { 0x0000ab10, 0x00000000, 0x00000000, 0x0000fb90, 0x0000fb90, 0x0000fb90 },
+ { 0x0000ab14, 0x00000000, 0x00000000, 0x0000fb94, 0x0000fb94, 0x0000fb94 },
+ { 0x0000ab18, 0x00000000, 0x00000000, 0x0000ff8c, 0x0000ff8c, 0x0000ff8c },
+ { 0x0000ab1c, 0x00000000, 0x00000000, 0x0000ff90, 0x0000ff90, 0x0000ff90 },
+ { 0x0000ab20, 0x00000000, 0x00000000, 0x0000ff94, 0x0000ff94, 0x0000ff94 },
+ { 0x0000ab24, 0x00000000, 0x00000000, 0x0000ffa0, 0x0000ffa0, 0x0000ffa0 },
+ { 0x0000ab28, 0x00000000, 0x00000000, 0x0000ffa4, 0x0000ffa4, 0x0000ffa4 },
+ { 0x0000ab2c, 0x00000000, 0x00000000, 0x0000ffa8, 0x0000ffa8, 0x0000ffa8 },
+ { 0x0000ab30, 0x00000000, 0x00000000, 0x0000ffac, 0x0000ffac, 0x0000ffac },
+ { 0x0000ab34, 0x00000000, 0x00000000, 0x0000ffb0, 0x0000ffb0, 0x0000ffb0 },
+ { 0x0000ab38, 0x00000000, 0x00000000, 0x0000ffb4, 0x0000ffb4, 0x0000ffb4 },
+ { 0x0000ab3c, 0x00000000, 0x00000000, 0x0000ffa1, 0x0000ffa1, 0x0000ffa1 },
+ { 0x0000ab40, 0x00000000, 0x00000000, 0x0000ffa5, 0x0000ffa5, 0x0000ffa5 },
+ { 0x0000ab44, 0x00000000, 0x00000000, 0x0000ffa9, 0x0000ffa9, 0x0000ffa9 },
+ { 0x0000ab48, 0x00000000, 0x00000000, 0x0000ffad, 0x0000ffad, 0x0000ffad },
+ { 0x0000ab4c, 0x00000000, 0x00000000, 0x0000ffb1, 0x0000ffb1, 0x0000ffb1 },
+ { 0x0000ab50, 0x00000000, 0x00000000, 0x0000ffb5, 0x0000ffb5, 0x0000ffb5 },
+ { 0x0000ab54, 0x00000000, 0x00000000, 0x0000ffb9, 0x0000ffb9, 0x0000ffb9 },
+ { 0x0000ab58, 0x00000000, 0x00000000, 0x0000ffc5, 0x0000ffc5, 0x0000ffc5 },
+ { 0x0000ab5c, 0x00000000, 0x00000000, 0x0000ffc9, 0x0000ffc9, 0x0000ffc9 },
+ { 0x0000ab60, 0x00000000, 0x00000000, 0x0000ffcd, 0x0000ffcd, 0x0000ffcd },
+ { 0x0000ab64, 0x00000000, 0x00000000, 0x0000ffd1, 0x0000ffd1, 0x0000ffd1 },
+ { 0x0000ab68, 0x00000000, 0x00000000, 0x0000ffd5, 0x0000ffd5, 0x0000ffd5 },
+ { 0x0000ab6c, 0x00000000, 0x00000000, 0x0000ffc2, 0x0000ffc2, 0x0000ffc2 },
+ { 0x0000ab70, 0x00000000, 0x00000000, 0x0000ffc6, 0x0000ffc6, 0x0000ffc6 },
+ { 0x0000ab74, 0x00000000, 0x00000000, 0x0000ffca, 0x0000ffca, 0x0000ffca },
+ { 0x0000ab78, 0x00000000, 0x00000000, 0x0000ffce, 0x0000ffce, 0x0000ffce },
+ { 0x0000ab7c, 0x00000000, 0x00000000, 0x0000ffd2, 0x0000ffd2, 0x0000ffd2 },
+ { 0x0000ab80, 0x00000000, 0x00000000, 0x0000ffd6, 0x0000ffd6, 0x0000ffd6 },
+ { 0x0000ab84, 0x00000000, 0x00000000, 0x0000ffda, 0x0000ffda, 0x0000ffda },
+ { 0x0000ab88, 0x00000000, 0x00000000, 0x0000ffc7, 0x0000ffc7, 0x0000ffc7 },
+ { 0x0000ab8c, 0x00000000, 0x00000000, 0x0000ffcb, 0x0000ffcb, 0x0000ffcb },
+ { 0x0000ab90, 0x00000000, 0x00000000, 0x0000ffcf, 0x0000ffcf, 0x0000ffcf },
+ { 0x0000ab94, 0x00000000, 0x00000000, 0x0000ffd3, 0x0000ffd3, 0x0000ffd3 },
+ { 0x0000ab98, 0x00000000, 0x00000000, 0x0000ffd7, 0x0000ffd7, 0x0000ffd7 },
+ { 0x0000ab9c, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb },
+ { 0x0000aba0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb },
+ { 0x0000aba4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb },
+ { 0x0000aba8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb },
+ { 0x0000abac, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb },
+ { 0x0000abb0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb },
+ { 0x0000abb4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb },
+ { 0x0000abb8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb },
+ { 0x0000abbc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb },
+ { 0x0000abc0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb },
+ { 0x0000abc4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb },
+ { 0x0000abc8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb },
+ { 0x0000abcc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb },
+ { 0x0000abd0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb },
+ { 0x0000abd4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb },
+ { 0x0000abd8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb },
+ { 0x0000abdc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb },
+ { 0x0000abe0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb },
+ { 0x0000abe4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb },
+ { 0x0000abe8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb },
+ { 0x0000abec, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb },
+ { 0x0000abf0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb },
+ { 0x0000abf4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb },
+ { 0x0000abf8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb },
+ { 0x0000abfc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb },
+ { 0x00009848, 0x00000000, 0x00000000, 0x00001067, 0x00001067, 0x00001067 },
+ { 0x0000a848, 0x00000000, 0x00000000, 0x00001067, 0x00001067, 0x00001067 },
+};
+
+static const u_int32_t ar9287PciePhy_clkreq_always_on_L1_9287_1_1[][2] = {
+ {0x00004040, 0x9248fd00 },
+ {0x00004040, 0x24924924 },
+ {0x00004040, 0xa8000019 },
+ {0x00004040, 0x13160820 },
+ {0x00004040, 0xe5980560 },
+ {0x00004040, 0xc01dcffd },
+ {0x00004040, 0x1aaabe41 },
+ {0x00004040, 0xbe105554 },
+ {0x00004040, 0x00043007 },
+ {0x00004044, 0x00000000 },
+};
+
+static const u_int32_t ar9287PciePhy_clkreq_off_L1_9287_1_1[][2] = {
+ {0x00004040, 0x9248fd00 },
+ {0x00004040, 0x24924924 },
+ {0x00004040, 0xa8000019 },
+ {0x00004040, 0x13160820 },
+ {0x00004040, 0xe5980560 },
+ {0x00004040, 0xc01dcffc },
+ {0x00004040, 0x1aaabe41 },
+ {0x00004040, 0xbe105554 },
+ {0x00004040, 0x00043007 },
+ {0x00004044, 0x00000000 },
+};
+
+
+/* AR9271 initialization values automaticaly created: 03/23/09 */
+static const u_int32_t ar9271Modes_9271_1_0[][6] = {
+ { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 },
+ { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 },
+ { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 },
+ { 0x000010f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000008 },
+ { 0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0 },
+ { 0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b, 0x0988004f },
+ { 0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440, 0x00006880 },
+ { 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303 },
+ { 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200 },
+ { 0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e },
+ { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 },
+ { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e },
+ { 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 },
+ { 0x00009840, 0x206a012e, 0x206a012e, 0x206a012e, 0x206a012e, 0x206a012e },
+ { 0x00009844, 0x0372161e, 0x0372161e, 0x03721620, 0x03721620, 0x037216a0 },
+ { 0x00009848, 0x00001066, 0x00001066, 0x00001053, 0x00001053, 0x00001059 },
+ { 0x0000a848, 0x00001066, 0x00001066, 0x00001053, 0x00001053, 0x00001059 },
+ { 0x00009850, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2 },
+ { 0x00009858, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e },
+ { 0x0000985c, 0x3139605e, 0x3139605e, 0x3137605e, 0x3137605e, 0x3139605e },
+ { 0x00009860, 0x00058d18, 0x00058d18, 0x00058d18, 0x00058d18, 0x00058d18 },
+ { 0x00009864, 0x0000fe00, 0x0000fe00, 0x0001ce00, 0x0001ce00, 0x0001ce00 },
+ { 0x00009868, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0 },
+ { 0x0000986c, 0x06903081, 0x06903081, 0x06903881, 0x06903881, 0x06903881 },
+ { 0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0 },
+ { 0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016 },
+ { 0x00009924, 0xd00a8007, 0xd00a8007, 0xd00a800d, 0xd00a800d, 0xd00a800d },
+ { 0x00009944, 0xffbc1010, 0xffbc1010, 0xffbc1020, 0xffbc1020, 0xffbc1010 },
+ { 0x00009960, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x00009964, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x000099b8, 0x0000421c, 0x0000421c, 0x0000421c, 0x0000421c, 0x0000421c },
+ { 0x000099bc, 0x00000600, 0x00000600, 0x00000c00, 0x00000c00, 0x00000c00 },
+ { 0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4 },
+ { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 },
+ { 0x000099c8, 0x6af65329, 0x6af65329, 0x6af65329, 0x6af65329, 0x6af65329 },
+ { 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8 },
+ { 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 },
+ { 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x00009a00, 0x00000000, 0x00000000, 0x00058084, 0x00058084, 0x00000000 },
+ { 0x00009a04, 0x00000000, 0x00000000, 0x00058088, 0x00058088, 0x00000000 },
+ { 0x00009a08, 0x00000000, 0x00000000, 0x0005808c, 0x0005808c, 0x00000000 },
+ { 0x00009a0c, 0x00000000, 0x00000000, 0x00058100, 0x00058100, 0x00000000 },
+ { 0x00009a10, 0x00000000, 0x00000000, 0x00058104, 0x00058104, 0x00000000 },
+ { 0x00009a14, 0x00000000, 0x00000000, 0x00058108, 0x00058108, 0x00000000 },
+ { 0x00009a18, 0x00000000, 0x00000000, 0x0005810c, 0x0005810c, 0x00000000 },
+ { 0x00009a1c, 0x00000000, 0x00000000, 0x00058110, 0x00058110, 0x00000000 },
+ { 0x00009a20, 0x00000000, 0x00000000, 0x00058114, 0x00058114, 0x00000000 },
+ { 0x00009a24, 0x00000000, 0x00000000, 0x00058180, 0x00058180, 0x00000000 },
+ { 0x00009a28, 0x00000000, 0x00000000, 0x00058184, 0x00058184, 0x00000000 },
+ { 0x00009a2c, 0x00000000, 0x00000000, 0x00058188, 0x00058188, 0x00000000 },
+ { 0x00009a30, 0x00000000, 0x00000000, 0x0005818c, 0x0005818c, 0x00000000 },
+ { 0x00009a34, 0x00000000, 0x00000000, 0x00058190, 0x00058190, 0x00000000 },
+ { 0x00009a38, 0x00000000, 0x00000000, 0x00058194, 0x00058194, 0x00000000 },
+ { 0x00009a3c, 0x00000000, 0x00000000, 0x000581a0, 0x000581a0, 0x00000000 },
+ { 0x00009a40, 0x00000000, 0x00000000, 0x0005820c, 0x0005820c, 0x00000000 },
+ { 0x00009a44, 0x00000000, 0x00000000, 0x000581a8, 0x000581a8, 0x00000000 },
+ { 0x00009a48, 0x00000000, 0x00000000, 0x00058284, 0x00058284, 0x00000000 },
+ { 0x00009a4c, 0x00000000, 0x00000000, 0x00058288, 0x00058288, 0x00000000 },
+ { 0x00009a50, 0x00000000, 0x00000000, 0x00058220, 0x00058220, 0x00000000 },
+ { 0x00009a54, 0x00000000, 0x00000000, 0x00058290, 0x00058290, 0x00000000 },
+ { 0x00009a58, 0x00000000, 0x00000000, 0x00058300, 0x00058300, 0x00000000 },
+ { 0x00009a5c, 0x00000000, 0x00000000, 0x00058304, 0x00058304, 0x00000000 },
+ { 0x00009a60, 0x00000000, 0x00000000, 0x00058308, 0x00058308, 0x00000000 },
+ { 0x00009a64, 0x00000000, 0x00000000, 0x0005830c, 0x0005830c, 0x00000000 },
+ { 0x00009a68, 0x00000000, 0x00000000, 0x00058380, 0x00058380, 0x00000000 },
+ { 0x00009a6c, 0x00000000, 0x00000000, 0x00058384, 0x00058384, 0x00000000 },
+ { 0x00009a70, 0x00000000, 0x00000000, 0x00068700, 0x00068700, 0x00000000 },
+ { 0x00009a74, 0x00000000, 0x00000000, 0x00068704, 0x00068704, 0x00000000 },
+ { 0x00009a78, 0x00000000, 0x00000000, 0x00068708, 0x00068708, 0x00000000 },
+ { 0x00009a7c, 0x00000000, 0x00000000, 0x0006870c, 0x0006870c, 0x00000000 },
+ { 0x00009a80, 0x00000000, 0x00000000, 0x00068780, 0x00068780, 0x00000000 },
+ { 0x00009a84, 0x00000000, 0x00000000, 0x00068784, 0x00068784, 0x00000000 },
+ { 0x00009a88, 0x00000000, 0x00000000, 0x00078b04, 0x00078b04, 0x00000000 },
+ { 0x00009a8c, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000 },
+ { 0x00009a90, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000 },
+ { 0x00009a94, 0x00000000, 0x00000000, 0x00078b0c, 0x00078b0c, 0x00000000 },
+ { 0x00009a98, 0x00000000, 0x00000000, 0x00078b80, 0x00078b80, 0x00000000 },
+ { 0x00009a9c, 0x00000000, 0x00000000, 0x00078b84, 0x00078b84, 0x00000000 },
+ { 0x00009aa0, 0x00000000, 0x00000000, 0x00078b88, 0x00078b88, 0x00000000 },
+ { 0x00009aa4, 0x00000000, 0x00000000, 0x00078b8c, 0x00078b8c, 0x00000000 },
+ { 0x00009aa8, 0x00000000, 0x00000000, 0x00078b90, 0x00078b90, 0x00000000 },
+ { 0x00009aac, 0x00000000, 0x00000000, 0x000caf80, 0x000caf80, 0x00000000 },
+ { 0x00009ab0, 0x00000000, 0x00000000, 0x000caf84, 0x000caf84, 0x00000000 },
+ { 0x00009ab4, 0x00000000, 0x00000000, 0x000caf88, 0x000caf88, 0x00000000 },
+ { 0x00009ab8, 0x00000000, 0x00000000, 0x000caf8c, 0x000caf8c, 0x00000000 },
+ { 0x00009abc, 0x00000000, 0x00000000, 0x000caf90, 0x000caf90, 0x00000000 },
+ { 0x00009ac0, 0x00000000, 0x00000000, 0x000db30c, 0x000db30c, 0x00000000 },
+ { 0x00009ac4, 0x00000000, 0x00000000, 0x000db310, 0x000db310, 0x00000000 },
+ { 0x00009ac8, 0x00000000, 0x00000000, 0x000db384, 0x000db384, 0x00000000 },
+ { 0x00009acc, 0x00000000, 0x00000000, 0x000db388, 0x000db388, 0x00000000 },
+ { 0x00009ad0, 0x00000000, 0x00000000, 0x000db324, 0x000db324, 0x00000000 },
+ { 0x00009ad4, 0x00000000, 0x00000000, 0x000eb704, 0x000eb704, 0x00000000 },
+ { 0x00009ad8, 0x00000000, 0x00000000, 0x000eb6a4, 0x000eb6a4, 0x00000000 },
+ { 0x00009adc, 0x00000000, 0x00000000, 0x000eb6a8, 0x000eb6a8, 0x00000000 },
+ { 0x00009ae0, 0x00000000, 0x00000000, 0x000eb710, 0x000eb710, 0x00000000 },
+ { 0x00009ae4, 0x00000000, 0x00000000, 0x000eb714, 0x000eb714, 0x00000000 },
+ { 0x00009ae8, 0x00000000, 0x00000000, 0x000eb720, 0x000eb720, 0x00000000 },
+ { 0x00009aec, 0x00000000, 0x00000000, 0x000eb724, 0x000eb724, 0x00000000 },
+ { 0x00009af0, 0x00000000, 0x00000000, 0x000eb728, 0x000eb728, 0x00000000 },
+ { 0x00009af4, 0x00000000, 0x00000000, 0x000eb72c, 0x000eb72c, 0x00000000 },
+ { 0x00009af8, 0x00000000, 0x00000000, 0x000eb7a0, 0x000eb7a0, 0x00000000 },
+ { 0x00009afc, 0x00000000, 0x00000000, 0x000eb7a4, 0x000eb7a4, 0x00000000 },
+ { 0x00009b00, 0x00000000, 0x00000000, 0x000eb7a8, 0x000eb7a8, 0x00000000 },
+ { 0x00009b04, 0x00000000, 0x00000000, 0x000eb7b0, 0x000eb7b0, 0x00000000 },
+ { 0x00009b08, 0x00000000, 0x00000000, 0x000eb7b4, 0x000eb7b4, 0x00000000 },
+ { 0x00009b0c, 0x00000000, 0x00000000, 0x000eb7b8, 0x000eb7b8, 0x00000000 },
+ { 0x00009b10, 0x00000000, 0x00000000, 0x000eb7a5, 0x000eb7a5, 0x00000000 },
+ { 0x00009b14, 0x00000000, 0x00000000, 0x000eb7a9, 0x000eb7a9, 0x00000000 },
+ { 0x00009b18, 0x00000000, 0x00000000, 0x000eb7ad, 0x000eb7ad, 0x00000000 },
+ { 0x00009b1c, 0x00000000, 0x00000000, 0x000eb7b1, 0x000eb7b1, 0x00000000 },
+ { 0x00009b20, 0x00000000, 0x00000000, 0x000eb7b5, 0x000eb7b5, 0x00000000 },
+ { 0x00009b24, 0x00000000, 0x00000000, 0x000eb7b9, 0x000eb7b9, 0x00000000 },
+ { 0x00009b28, 0x00000000, 0x00000000, 0x000eb7c5, 0x000eb7c5, 0x00000000 },
+ { 0x00009b2c, 0x00000000, 0x00000000, 0x000eb7c9, 0x000eb7c9, 0x00000000 },
+ { 0x00009b30, 0x00000000, 0x00000000, 0x000eb7d1, 0x000eb7d1, 0x00000000 },
+ { 0x00009b34, 0x00000000, 0x00000000, 0x000eb7d5, 0x000eb7d5, 0x00000000 },
+ { 0x00009b38, 0x00000000, 0x00000000, 0x000eb7d9, 0x000eb7d9, 0x00000000 },
+ { 0x00009b3c, 0x00000000, 0x00000000, 0x000eb7c6, 0x000eb7c6, 0x00000000 },
+ { 0x00009b40, 0x00000000, 0x00000000, 0x000eb7ca, 0x000eb7ca, 0x00000000 },
+ { 0x00009b44, 0x00000000, 0x00000000, 0x000eb7ce, 0x000eb7ce, 0x00000000 },
+ { 0x00009b48, 0x00000000, 0x00000000, 0x000eb7d2, 0x000eb7d2, 0x00000000 },
+ { 0x00009b4c, 0x00000000, 0x00000000, 0x000eb7d6, 0x000eb7d6, 0x00000000 },
+ { 0x00009b50, 0x00000000, 0x00000000, 0x000eb7c3, 0x000eb7c3, 0x00000000 },
+ { 0x00009b54, 0x00000000, 0x00000000, 0x000eb7c7, 0x000eb7c7, 0x00000000 },
+ { 0x00009b58, 0x00000000, 0x00000000, 0x000eb7cb, 0x000eb7cb, 0x00000000 },
+ { 0x00009b5c, 0x00000000, 0x00000000, 0x000eb7cf, 0x000eb7cf, 0x00000000 },
+ { 0x00009b60, 0x00000000, 0x00000000, 0x000eb7d7, 0x000eb7d7, 0x00000000 },
+ { 0x00009b64, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+ { 0x00009b68, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+ { 0x00009b6c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+ { 0x00009b70, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+ { 0x00009b74, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+ { 0x00009b78, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+ { 0x00009b7c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+ { 0x00009b80, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+ { 0x00009b84, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+ { 0x00009b88, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+ { 0x00009b8c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+ { 0x00009b90, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+ { 0x00009b94, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+ { 0x00009b98, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+ { 0x00009b9c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+ { 0x00009ba0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+ { 0x00009ba4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+ { 0x00009ba8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+ { 0x00009bac, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+ { 0x00009bb0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+ { 0x00009bb4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+ { 0x00009bb8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+ { 0x00009bbc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+ { 0x00009bc0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+ { 0x00009bc4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+ { 0x00009bc8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+ { 0x00009bcc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+ { 0x00009bd0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+ { 0x00009bd4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+ { 0x00009bd8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+ { 0x00009bdc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+ { 0x00009be0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+ { 0x00009be4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+ { 0x00009be8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+ { 0x00009bec, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+ { 0x00009bf0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+ { 0x00009bf4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+ { 0x00009bf8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+ { 0x00009bfc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+ { 0x0000aa00, 0x00000000, 0x00000000, 0x00058084, 0x00058084, 0x00000000 },
+ { 0x0000aa04, 0x00000000, 0x00000000, 0x00058088, 0x00058088, 0x00000000 },
+ { 0x0000aa08, 0x00000000, 0x00000000, 0x0005808c, 0x0005808c, 0x00000000 },
+ { 0x0000aa0c, 0x00000000, 0x00000000, 0x00058100, 0x00058100, 0x00000000 },
+ { 0x0000aa10, 0x00000000, 0x00000000, 0x00058104, 0x00058104, 0x00000000 },
+ { 0x0000aa14, 0x00000000, 0x00000000, 0x00058108, 0x00058108, 0x00000000 },
+ { 0x0000aa18, 0x00000000, 0x00000000, 0x0005810c, 0x0005810c, 0x00000000 },
+ { 0x0000aa1c, 0x00000000, 0x00000000, 0x00058110, 0x00058110, 0x00000000 },
+ { 0x0000aa20, 0x00000000, 0x00000000, 0x00058114, 0x00058114, 0x00000000 },
+ { 0x0000aa24, 0x00000000, 0x00000000, 0x00058180, 0x00058180, 0x00000000 },
+ { 0x0000aa28, 0x00000000, 0x00000000, 0x00058184, 0x00058184, 0x00000000 },
+ { 0x0000aa2c, 0x00000000, 0x00000000, 0x00058188, 0x00058188, 0x00000000 },
+ { 0x0000aa30, 0x00000000, 0x00000000, 0x0005818c, 0x0005818c, 0x00000000 },
+ { 0x0000aa34, 0x00000000, 0x00000000, 0x00058190, 0x00058190, 0x00000000 },
+ { 0x0000aa38, 0x00000000, 0x00000000, 0x00058194, 0x00058194, 0x00000000 },
+ { 0x0000aa3c, 0x00000000, 0x00000000, 0x000581a0, 0x000581a0, 0x00000000 },
+ { 0x0000aa40, 0x00000000, 0x00000000, 0x0005820c, 0x0005820c, 0x00000000 },
+ { 0x0000aa44, 0x00000000, 0x00000000, 0x000581a8, 0x000581a8, 0x00000000 },
+ { 0x0000aa48, 0x00000000, 0x00000000, 0x00058284, 0x00058284, 0x00000000 },
+ { 0x0000aa4c, 0x00000000, 0x00000000, 0x00058288, 0x00058288, 0x00000000 },
+ { 0x0000aa50, 0x00000000, 0x00000000, 0x00058220, 0x00058220, 0x00000000 },
+ { 0x0000aa54, 0x00000000, 0x00000000, 0x00058290, 0x00058290, 0x00000000 },
+ { 0x0000aa58, 0x00000000, 0x00000000, 0x00058300, 0x00058300, 0x00000000 },
+ { 0x0000aa5c, 0x00000000, 0x00000000, 0x00058304, 0x00058304, 0x00000000 },
+ { 0x0000aa60, 0x00000000, 0x00000000, 0x00058308, 0x00058308, 0x00000000 },
+ { 0x0000aa64, 0x00000000, 0x00000000, 0x0005830c, 0x0005830c, 0x00000000 },
+ { 0x0000aa68, 0x00000000, 0x00000000, 0x00058380, 0x00058380, 0x00000000 },
+ { 0x0000aa6c, 0x00000000, 0x00000000, 0x00058384, 0x00058384, 0x00000000 },
+ { 0x0000aa70, 0x00000000, 0x00000000, 0x00068700, 0x00068700, 0x00000000 },
+ { 0x0000aa74, 0x00000000, 0x00000000, 0x00068704, 0x00068704, 0x00000000 },
+ { 0x0000aa78, 0x00000000, 0x00000000, 0x00068708, 0x00068708, 0x00000000 },
+ { 0x0000aa7c, 0x00000000, 0x00000000, 0x0006870c, 0x0006870c, 0x00000000 },
+ { 0x0000aa80, 0x00000000, 0x00000000, 0x00068780, 0x00068780, 0x00000000 },
+ { 0x0000aa84, 0x00000000, 0x00000000, 0x00068784, 0x00068784, 0x00000000 },
+ { 0x0000aa88, 0x00000000, 0x00000000, 0x00078b04, 0x00078b04, 0x00000000 },
+ { 0x0000aa8c, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000 },
+ { 0x0000aa90, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000 },
+ { 0x0000aa94, 0x00000000, 0x00000000, 0x00078b0c, 0x00078b0c, 0x00000000 },
+ { 0x0000aa98, 0x00000000, 0x00000000, 0x00078b80, 0x00078b80, 0x00000000 },
+ { 0x0000aa9c, 0x00000000, 0x00000000, 0x00078b84, 0x00078b84, 0x00000000 },
+ { 0x0000aaa0, 0x00000000, 0x00000000, 0x00078b88, 0x00078b88, 0x00000000 },
+ { 0x0000aaa4, 0x00000000, 0x00000000, 0x00078b8c, 0x00078b8c, 0x00000000 },
+ { 0x0000aaa8, 0x00000000, 0x00000000, 0x00078b90, 0x00078b90, 0x00000000 },
+ { 0x0000aaac, 0x00000000, 0x00000000, 0x000caf80, 0x000caf80, 0x00000000 },
+ { 0x0000aab0, 0x00000000, 0x00000000, 0x000caf84, 0x000caf84, 0x00000000 },
+ { 0x0000aab4, 0x00000000, 0x00000000, 0x000caf88, 0x000caf88, 0x00000000 },
+ { 0x0000aab8, 0x00000000, 0x00000000, 0x000caf8c, 0x000caf8c, 0x00000000 },
+ { 0x0000aabc, 0x00000000, 0x00000000, 0x000caf90, 0x000caf90, 0x00000000 },
+ { 0x0000aac0, 0x00000000, 0x00000000, 0x000db30c, 0x000db30c, 0x00000000 },
+ { 0x0000aac4, 0x00000000, 0x00000000, 0x000db310, 0x000db310, 0x00000000 },
+ { 0x0000aac8, 0x00000000, 0x00000000, 0x000db384, 0x000db384, 0x00000000 },
+ { 0x0000aacc, 0x00000000, 0x00000000, 0x000db388, 0x000db388, 0x00000000 },
+ { 0x0000aad0, 0x00000000, 0x00000000, 0x000db324, 0x000db324, 0x00000000 },
+ { 0x0000aad4, 0x00000000, 0x00000000, 0x000eb704, 0x000eb704, 0x00000000 },
+ { 0x0000aad8, 0x00000000, 0x00000000, 0x000eb6a4, 0x000eb6a4, 0x00000000 },
+ { 0x0000aadc, 0x00000000, 0x00000000, 0x000eb6a8, 0x000eb6a8, 0x00000000 },
+ { 0x0000aae0, 0x00000000, 0x00000000, 0x000eb710, 0x000eb710, 0x00000000 },
+ { 0x0000aae4, 0x00000000, 0x00000000, 0x000eb714, 0x000eb714, 0x00000000 },
+ { 0x0000aae8, 0x00000000, 0x00000000, 0x000eb720, 0x000eb720, 0x00000000 },
+ { 0x0000aaec, 0x00000000, 0x00000000, 0x000eb724, 0x000eb724, 0x00000000 },
+ { 0x0000aaf0, 0x00000000, 0x00000000, 0x000eb728, 0x000eb728, 0x00000000 },
+ { 0x0000aaf4, 0x00000000, 0x00000000, 0x000eb72c, 0x000eb72c, 0x00000000 },
+ { 0x0000aaf8, 0x00000000, 0x00000000, 0x000eb7a0, 0x000eb7a0, 0x00000000 },
+ { 0x0000aafc, 0x00000000, 0x00000000, 0x000eb7a4, 0x000eb7a4, 0x00000000 },
+ { 0x0000ab00, 0x00000000, 0x00000000, 0x000eb7a8, 0x000eb7a8, 0x00000000 },
+ { 0x0000ab04, 0x00000000, 0x00000000, 0x000eb7b0, 0x000eb7b0, 0x00000000 },
+ { 0x0000ab08, 0x00000000, 0x00000000, 0x000eb7b4, 0x000eb7b4, 0x00000000 },
+ { 0x0000ab0c, 0x00000000, 0x00000000, 0x000eb7b8, 0x000eb7b8, 0x00000000 },
+ { 0x0000ab10, 0x00000000, 0x00000000, 0x000eb7a5, 0x000eb7a5, 0x00000000 },
+ { 0x0000ab14, 0x00000000, 0x00000000, 0x000eb7a9, 0x000eb7a9, 0x00000000 },
+ { 0x0000ab18, 0x00000000, 0x00000000, 0x000eb7ad, 0x000eb7ad, 0x00000000 },
+ { 0x0000ab1c, 0x00000000, 0x00000000, 0x000eb7b1, 0x000eb7b1, 0x00000000 },
+ { 0x0000ab20, 0x00000000, 0x00000000, 0x000eb7b5, 0x000eb7b5, 0x00000000 },
+ { 0x0000ab24, 0x00000000, 0x00000000, 0x000eb7b9, 0x000eb7b9, 0x00000000 },
+ { 0x0000ab28, 0x00000000, 0x00000000, 0x000eb7c5, 0x000eb7c5, 0x00000000 },
+ { 0x0000ab2c, 0x00000000, 0x00000000, 0x000eb7c9, 0x000eb7c9, 0x00000000 },
+ { 0x0000ab30, 0x00000000, 0x00000000, 0x000eb7d1, 0x000eb7d1, 0x00000000 },
+ { 0x0000ab34, 0x00000000, 0x00000000, 0x000eb7d5, 0x000eb7d5, 0x00000000 },
+ { 0x0000ab38, 0x00000000, 0x00000000, 0x000eb7d9, 0x000eb7d9, 0x00000000 },
+ { 0x0000ab3c, 0x00000000, 0x00000000, 0x000eb7c6, 0x000eb7c6, 0x00000000 },
+ { 0x0000ab40, 0x00000000, 0x00000000, 0x000eb7ca, 0x000eb7ca, 0x00000000 },
+ { 0x0000ab44, 0x00000000, 0x00000000, 0x000eb7ce, 0x000eb7ce, 0x00000000 },
+ { 0x0000ab48, 0x00000000, 0x00000000, 0x000eb7d2, 0x000eb7d2, 0x00000000 },
+ { 0x0000ab4c, 0x00000000, 0x00000000, 0x000eb7d6, 0x000eb7d6, 0x00000000 },
+ { 0x0000ab50, 0x00000000, 0x00000000, 0x000eb7c3, 0x000eb7c3, 0x00000000 },
+ { 0x0000ab54, 0x00000000, 0x00000000, 0x000eb7c7, 0x000eb7c7, 0x00000000 },
+ { 0x0000ab58, 0x00000000, 0x00000000, 0x000eb7cb, 0x000eb7cb, 0x00000000 },
+ { 0x0000ab5c, 0x00000000, 0x00000000, 0x000eb7cf, 0x000eb7cf, 0x00000000 },
+ { 0x0000ab60, 0x00000000, 0x00000000, 0x000eb7d7, 0x000eb7d7, 0x00000000 },
+ { 0x0000ab64, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+ { 0x0000ab68, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+ { 0x0000ab6c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+ { 0x0000ab70, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+ { 0x0000ab74, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+ { 0x0000ab78, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+ { 0x0000ab7c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+ { 0x0000ab80, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+ { 0x0000ab84, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+ { 0x0000ab88, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+ { 0x0000ab8c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+ { 0x0000ab90, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+ { 0x0000ab94, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+ { 0x0000ab98, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+ { 0x0000ab9c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+ { 0x0000aba0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+ { 0x0000aba4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+ { 0x0000aba8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+ { 0x0000abac, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+ { 0x0000abb0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+ { 0x0000abb4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+ { 0x0000abb8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+ { 0x0000abbc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+ { 0x0000abc0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+ { 0x0000abc4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+ { 0x0000abc8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+ { 0x0000abcc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+ { 0x0000abd0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+ { 0x0000abd4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+ { 0x0000abd8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+ { 0x0000abdc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+ { 0x0000abe0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+ { 0x0000abe4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+ { 0x0000abe8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+ { 0x0000abec, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+ { 0x0000abf0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+ { 0x0000abf4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+ { 0x0000abf8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+ { 0x0000abfc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+ { 0x0000a204, 0x00000004, 0x00000004, 0x00000004, 0x00000004, 0x00000004 },
+ { 0x0000a20c, 0x00000014, 0x00000014, 0x0001f000, 0x0001f000, 0x0001f000 },
+ { 0x0000b20c, 0x00000014, 0x00000014, 0x0001f000, 0x0001f000, 0x0001f000 },
+ { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a },
+ { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 },
+ { 0x0000a250, 0x0004f000, 0x0004f000, 0x0004a000, 0x0004a000, 0x0004a000 },
+ { 0x0000a274, 0x0a21c652, 0x0a21c652, 0x0a218652, 0x0a218652, 0x0a22a652 },
+ { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x0000a304, 0x00000000, 0x00000000, 0x00009200, 0x00009200, 0x00000000 },
+ { 0x0000a308, 0x00000000, 0x00000000, 0x00010208, 0x00010208, 0x00000000 },
+ { 0x0000a30c, 0x00000000, 0x00000000, 0x00019608, 0x00019608, 0x00000000 },
+ { 0x0000a310, 0x00000000, 0x00000000, 0x0001e610, 0x0001e610, 0x00000000 },
+ { 0x0000a314, 0x00000000, 0x00000000, 0x0002d6d0, 0x0002d6d0, 0x00000000 },
+ { 0x0000a318, 0x00000000, 0x00000000, 0x00039758, 0x00039758, 0x00000000 },
+ { 0x0000a31c, 0x00000000, 0x00000000, 0x0003b759, 0x0003b759, 0x00000000 },
+ { 0x0000a320, 0x00000000, 0x00000000, 0x0003d75a, 0x0003d75a, 0x00000000 },
+ { 0x0000a324, 0x00000000, 0x00000000, 0x0004175c, 0x0004175c, 0x00000000 },
+ { 0x0000a328, 0x00000000, 0x00000000, 0x0004575e, 0x0004575e, 0x00000000 },
+ { 0x0000a32c, 0x00000000, 0x00000000, 0x0004979f, 0x0004979f, 0x00000000 },
+ { 0x0000a330, 0x00000000, 0x00000000, 0x0004d7df, 0x0004d7df, 0x00000000 },
+ { 0x0000a334, 0x000368de, 0x000368de, 0x000368de, 0x000368de, 0x00000000 },
+ { 0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e, 0x00000000 },
+ { 0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x00000000 },
+ { 0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 },
+ { 0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 },
+ { 0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e, 0x7999aa0e },
+};
+
+static const u_int32_t ar9271Common_9271_1_0[][2] = {
+ { 0x0000000c, 0x00000000 },
+ { 0x00000030, 0x00020045 },
+ { 0x00000034, 0x00000005 },
+ { 0x00000040, 0x00000000 },
+ { 0x00000044, 0x00000008 },
+ { 0x00000048, 0x00000008 },
+ { 0x0000004c, 0x00000010 },
+ { 0x00000050, 0x00000000 },
+ { 0x00000054, 0x0000001f },
+ { 0x00000800, 0x00000000 },
+ { 0x00000804, 0x00000000 },
+ { 0x00000808, 0x00000000 },
+ { 0x0000080c, 0x00000000 },
+ { 0x00000810, 0x00000000 },
+ { 0x00000814, 0x00000000 },
+ { 0x00000818, 0x00000000 },
+ { 0x0000081c, 0x00000000 },
+ { 0x00000820, 0x00000000 },
+ { 0x00000824, 0x00000000 },
+ { 0x00001040, 0x002ffc0f },
+ { 0x00001044, 0x002ffc0f },
+ { 0x00001048, 0x002ffc0f },
+ { 0x0000104c, 0x002ffc0f },
+ { 0x00001050, 0x002ffc0f },
+ { 0x00001054, 0x002ffc0f },
+ { 0x00001058, 0x002ffc0f },
+ { 0x0000105c, 0x002ffc0f },
+ { 0x00001060, 0x002ffc0f },
+ { 0x00001064, 0x002ffc0f },
+ { 0x00001230, 0x00000000 },
+ { 0x00001270, 0x00000000 },
+ { 0x00001038, 0x00000000 },
+ { 0x00001078, 0x00000000 },
+ { 0x000010b8, 0x00000000 },
+ { 0x000010f8, 0x00000000 },
+ { 0x00001138, 0x00000000 },
+ { 0x00001178, 0x00000000 },
+ { 0x000011b8, 0x00000000 },
+ { 0x000011f8, 0x00000000 },
+ { 0x00001238, 0x00000000 },
+ { 0x00001278, 0x00000000 },
+ { 0x000012b8, 0x00000000 },
+ { 0x000012f8, 0x00000000 },
+ { 0x00001338, 0x00000000 },
+ { 0x00001378, 0x00000000 },
+ { 0x000013b8, 0x00000000 },
+ { 0x000013f8, 0x00000000 },
+ { 0x00001438, 0x00000000 },
+ { 0x00001478, 0x00000000 },
+ { 0x000014b8, 0x00000000 },
+ { 0x000014f8, 0x00000000 },
+ { 0x00001538, 0x00000000 },
+ { 0x00001578, 0x00000000 },
+ { 0x000015b8, 0x00000000 },
+ { 0x000015f8, 0x00000000 },
+ { 0x00001638, 0x00000000 },
+ { 0x00001678, 0x00000000 },
+ { 0x000016b8, 0x00000000 },
+ { 0x000016f8, 0x00000000 },
+ { 0x00001738, 0x00000000 },
+ { 0x00001778, 0x00000000 },
+ { 0x000017b8, 0x00000000 },
+ { 0x000017f8, 0x00000000 },
+ { 0x0000103c, 0x00000000 },
+ { 0x0000107c, 0x00000000 },
+ { 0x000010bc, 0x00000000 },
+ { 0x000010fc, 0x00000000 },
+ { 0x0000113c, 0x00000000 },
+ { 0x0000117c, 0x00000000 },
+ { 0x000011bc, 0x00000000 },
+ { 0x000011fc, 0x00000000 },
+ { 0x0000123c, 0x00000000 },
+ { 0x0000127c, 0x00000000 },
+ { 0x000012bc, 0x00000000 },
+ { 0x000012fc, 0x00000000 },
+ { 0x0000133c, 0x00000000 },
+ { 0x0000137c, 0x00000000 },
+ { 0x000013bc, 0x00000000 },
+ { 0x000013fc, 0x00000000 },
+ { 0x0000143c, 0x00000000 },
+ { 0x0000147c, 0x00000000 },
+ { 0x00004030, 0x00000002 },
+ { 0x0000403c, 0x00000002 },
+ { 0x00004024, 0x0000001f },
+ { 0x00004060, 0x00000000 },
+ { 0x00004064, 0x00000000 },
+ { 0x00008004, 0x00000000 },
+ { 0x00008008, 0x00000000 },
+ { 0x0000800c, 0x00000000 },
+ { 0x00008018, 0x00000700 },
+ { 0x00008020, 0x00000000 },
+ { 0x00008038, 0x00000000 },
+ { 0x0000803c, 0x00000000 },
+ { 0x00008048, 0x00000000 },
+ { 0x00008054, 0x00000000 },
+ { 0x00008058, 0x02000000 },
+ { 0x0000805c, 0x000fc78f },
+ { 0x00008060, 0x0000000f },
+ { 0x00008064, 0x00000000 },
+ { 0x00008070, 0x00000000 },
+ { 0x000080b0, 0x00000000 },
+ { 0x000080b4, 0x00000000 },
+ { 0x000080b8, 0x00000000 },
+ { 0x000080bc, 0x00000000 },
+ { 0x000080c0, 0x2a80001a },
+ { 0x000080c4, 0x05dc01e0 },
+ { 0x000080c8, 0x1f402710 },
+ { 0x000080cc, 0x01f40000 },
+ { 0x000080d0, 0x00001e00 },
+ { 0x000080d4, 0x00000000 },
+ { 0x000080d8, 0x00400000 },
+ { 0x000080e0, 0xffffffff },
+ { 0x000080e4, 0x0000ffff },
+ { 0x000080e8, 0x003f3f3f },
+ { 0x000080ec, 0x00000000 },
+ { 0x000080f0, 0x00000000 },
+ { 0x000080f4, 0x00000000 },
+ { 0x000080f8, 0x00000000 },
+ { 0x000080fc, 0x00020000 },
+ { 0x00008100, 0x00020000 },
+ { 0x00008104, 0x00000001 },
+ { 0x00008108, 0x00000052 },
+ { 0x0000810c, 0x00000000 },
+ { 0x00008110, 0x00000168 },
+ { 0x00008118, 0x000100aa },
+ { 0x0000811c, 0x00003210 },
+ { 0x00008120, 0x08f04814 },
+ { 0x00008124, 0x00000000 },
+ { 0x00008128, 0x00000000 },
+ { 0x0000812c, 0x00000000 },
+ { 0x00008130, 0x00000000 },
+ { 0x00008134, 0x00000000 },
+ { 0x00008138, 0x00000000 },
+ { 0x0000813c, 0x00000000 },
+ { 0x00008144, 0xffffffff },
+ { 0x00008168, 0x00000000 },
+ { 0x0000816c, 0x00000000 },
+ { 0x00008170, 0x32143320 },
+ { 0x00008174, 0xfaa4fa50 },
+ { 0x00008178, 0x00000100 },
+ { 0x0000817c, 0x00000000 },
+ { 0x000081c0, 0x00000000 },
+ { 0x000081d0, 0x0000320a },
+ { 0x000081ec, 0x00000000 },
+ { 0x000081f0, 0x00000000 },
+ { 0x000081f4, 0x00000000 },
+ { 0x000081f8, 0x00000000 },
+ { 0x000081fc, 0x00000000 },
+ { 0x00008200, 0x00000000 },
+ { 0x00008204, 0x00000000 },
+ { 0x00008208, 0x00000000 },
+ { 0x0000820c, 0x00000000 },
+ { 0x00008210, 0x00000000 },
+ { 0x00008214, 0x00000000 },
+ { 0x00008218, 0x00000000 },
+ { 0x0000821c, 0x00000000 },
+ { 0x00008220, 0x00000000 },
+ { 0x00008224, 0x00000000 },
+ { 0x00008228, 0x00000000 },
+ { 0x0000822c, 0x00000000 },
+ { 0x00008230, 0x00000000 },
+ { 0x00008234, 0x00000000 },
+ { 0x00008238, 0x00000000 },
+ { 0x0000823c, 0x00000000 },
+ { 0x00008240, 0x00100000 },
+ { 0x00008244, 0x0010f400 },
+ { 0x00008248, 0x00000100 },
+ { 0x0000824c, 0x0001e800 },
+ { 0x00008250, 0x00000000 },
+ { 0x00008254, 0x00000000 },
+ { 0x00008258, 0x00000000 },
+ { 0x0000825c, 0x400000ff },
+ { 0x00008260, 0x00080922 },
+ { 0x00008264, 0xa8a00010 },
+ { 0x00008270, 0x00000000 },
+ { 0x00008274, 0x40000000 },
+ { 0x00008278, 0x003e4180 },
+ { 0x0000827c, 0x00000000 },
+ { 0x00008284, 0x0000002c },
+ { 0x00008288, 0x0000002c },
+ { 0x0000828c, 0x00000000 },
+ { 0x00008294, 0x00000000 },
+ { 0x00008298, 0x00000000 },
+ { 0x0000829c, 0x00000000 },
+ { 0x00008300, 0x00000040 },
+ { 0x00008314, 0x00000000 },
+ { 0x00008328, 0x00000000 },
+ { 0x0000832c, 0x00000001 },
+ { 0x00008330, 0x00000302 },
+ { 0x00008334, 0x00000e00 },
+ { 0x00008338, 0x00ff0000 },
+ { 0x0000833c, 0x00000000 },
+ { 0x00008340, 0x00010380 },
+ { 0x00008344, 0x00581043 },
+ { 0x00007010, 0x00000030 },
+ { 0x00007034, 0x00000002 },
+ { 0x00007038, 0x000004c2 },
+ { 0x00007800, 0x00140000 },
+ { 0x00007804, 0x0e4548d8 },
+ { 0x00007808, 0x54214514 },
+ { 0x0000780c, 0x02025820 },
+ { 0x00007810, 0x71c0d388 },
+ { 0x00007814, 0x924934a8 },
+ { 0x0000781c, 0x00000000 },
+ { 0x00007820, 0x00000c04 },
+ { 0x00007824, 0x00d86bff },
+ { 0x00007828, 0x66964300 },
+ { 0x0000782c, 0x8db6d961 },
+ { 0x00007830, 0x8db6d96c },
+ { 0x00007834, 0x6140008b },
+ { 0x00007838, 0x00000029 },
+ { 0x0000783c, 0x72ee0a72 },
+ { 0x00007840, 0xbbfffffc },
+ { 0x00007844, 0x000c0db6 },
+ { 0x00007848, 0x6db61b6f },
+ { 0x0000784c, 0x6d9b66db },
+ { 0x00007850, 0x6d8c6dba },
+ { 0x00007854, 0x00040000 },
+ { 0x00007858, 0xdb003012 },
+ { 0x0000785c, 0x04924914 },
+ { 0x00007860, 0x21084210 },
+ { 0x00007864, 0xf7d7ffde },
+ { 0x00007868, 0xc2034080 },
+ { 0x0000786c, 0x48609eb4 },
+ { 0x00007870, 0x10142c00 },
+ { 0x00009808, 0x00000000 },
+ { 0x0000980c, 0xafe68e30 },
+ { 0x00009810, 0xfd14e000 },
+ { 0x00009814, 0x9c0a9f6b },
+ { 0x0000981c, 0x00000000 },
+ { 0x0000982c, 0x0000a000 },
+ { 0x00009830, 0x00000000 },
+ { 0x0000983c, 0x00200400 },
+ { 0x0000984c, 0x0040233c },
+ { 0x00009854, 0x00000044 },
+ { 0x00009900, 0x00000000 },
+ { 0x00009904, 0x00000000 },
+ { 0x00009908, 0x00000000 },
+ { 0x0000990c, 0x00000000 },
+ { 0x00009910, 0x30002310 },
+ { 0x0000991c, 0x10000fff },
+ { 0x00009920, 0x04900000 },
+ { 0x00009928, 0x00000001 },
+ { 0x0000992c, 0x00000004 },
+ { 0x00009934, 0x1e1f2022 },
+ { 0x00009938, 0x0a0b0c0d },
+ { 0x0000993c, 0x00000000 },
+ { 0x00009940, 0x14750604 },
+ { 0x00009948, 0x9280c00a },
+ { 0x0000994c, 0x00020028 },
+ { 0x00009954, 0x5f3ca3de },
+ { 0x00009958, 0x0108ecff },
+ { 0x00009968, 0x000003ce },
+ { 0x00009970, 0x192bb515 },
+ { 0x00009974, 0x00000000 },
+ { 0x00009978, 0x00000001 },
+ { 0x0000997c, 0x00000000 },
+ { 0x00009980, 0x00000000 },
+ { 0x00009984, 0x00000000 },
+ { 0x00009988, 0x00000000 },
+ { 0x0000998c, 0x00000000 },
+ { 0x00009990, 0x00000000 },
+ { 0x00009994, 0x00000000 },
+ { 0x00009998, 0x00000000 },
+ { 0x0000999c, 0x00000000 },
+ { 0x000099a0, 0x00000000 },
+ { 0x000099a4, 0x00000001 },
+ { 0x000099a8, 0x201fff00 },
+ { 0x000099ac, 0x2def0400 },
+ { 0x000099b0, 0x03051000 },
+ { 0x000099b4, 0x00000820 },
+ { 0x000099dc, 0x00000000 },
+ { 0x000099e0, 0x00000000 },
+ { 0x000099e4, 0xaaaaaaaa },
+ { 0x000099e8, 0x3c466478 },
+ { 0x000099ec, 0x0cc80caa },
+ { 0x000099f0, 0x00000000 },
+ { 0x0000a1f4, 0x00000000 },
+ { 0x0000a1f8, 0x71733d01 },
+ { 0x0000a1fc, 0xd0ad5c12 },
+ { 0x0000a208, 0x803e68c8 },
+ { 0x0000a210, 0x4080a333 },
+ { 0x0000a214, 0x00206c10 },
+ { 0x0000a218, 0x009c4060 },
+ { 0x0000a220, 0x01834061 },
+ { 0x0000a224, 0x00000400 },
+ { 0x0000a228, 0x000003b5 },
+ { 0x0000a22c, 0x00000000 },
+ { 0x0000a234, 0x20202020 },
+ { 0x0000a238, 0x20202020 },
+ { 0x0000a244, 0x00000000 },
+ { 0x0000a248, 0xfffffffc },
+ { 0x0000a24c, 0x00000000 },
+ { 0x0000a254, 0x00000000 },
+ { 0x0000a258, 0x0ccb5380 },
+ { 0x0000a25c, 0x15151501 },
+ { 0x0000a260, 0xdfa90f01 },
+ { 0x0000a268, 0x00000000 },
+ { 0x0000a26c, 0x0ebae9e6 },
+ { 0x0000a278, 0x3bdef7bd },
+ { 0x0000a27c, 0x050e83bd },
+ { 0x0000a388, 0x0c000000 },
+ { 0x0000a38c, 0x20202020 },
+ { 0x0000a390, 0x20202020 },
+ { 0x0000a394, 0x3bdef7bd },
+ { 0x0000a398, 0x000003bd },
+ { 0x0000a39c, 0x00000001 },
+ { 0x0000a3a0, 0x00000000 },
+ { 0x0000a3a4, 0x00000000 },
+ { 0x0000a3a8, 0x00000000 },
+ { 0x0000a3ac, 0x00000000 },
+ { 0x0000a3b0, 0x00000000 },
+ { 0x0000a3b4, 0x00000000 },
+ { 0x0000a3b8, 0x00000000 },
+ { 0x0000a3bc, 0x00000000 },
+ { 0x0000a3c0, 0x00000000 },
+ { 0x0000a3c4, 0x00000000 },
+ { 0x0000a3cc, 0x20202020 },
+ { 0x0000a3d0, 0x20202020 },
+ { 0x0000a3d4, 0x20202020 },
+ { 0x0000a3dc, 0x3bdef7bd },
+ { 0x0000a3e0, 0x000003bd },
+ { 0x0000a3e4, 0x00000000 },
+ { 0x0000a3e8, 0x18c43433 },
+ { 0x0000a3ec, 0x00f70081 },
+ { 0x0000a3f0, 0x01036a2f },
+ { 0x0000a3f4, 0x00000000 },
+ { 0x0000d270, 0x0d820820 },
+ { 0x0000d35c, 0x07ffffef },
+ { 0x0000d360, 0x0fffffe7 },
+ { 0x0000d364, 0x17ffffe5 },
+ { 0x0000d368, 0x1fffffe4 },
+ { 0x0000d36c, 0x37ffffe3 },
+ { 0x0000d370, 0x3fffffe3 },
+ { 0x0000d374, 0x57ffffe3 },
+ { 0x0000d378, 0x5fffffe2 },
+ { 0x0000d37c, 0x7fffffe2 },
+ { 0x0000d380, 0x7f3c7bba },
+ { 0x0000d384, 0xf3307ff0 },
+};
diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c
index 8ae4ec21667..800bfab9463 100644
--- a/drivers/net/wireless/ath/ath9k/mac.c
+++ b/drivers/net/wireless/ath/ath9k/mac.c
@@ -40,20 +40,15 @@ u32 ath9k_hw_gettxbuf(struct ath_hw *ah, u32 q)
return REG_READ(ah, AR_QTXDP(q));
}
-bool ath9k_hw_puttxbuf(struct ath_hw *ah, u32 q, u32 txdp)
+void ath9k_hw_puttxbuf(struct ath_hw *ah, u32 q, u32 txdp)
{
REG_WRITE(ah, AR_QTXDP(q), txdp);
-
- return true;
}
-bool ath9k_hw_txstart(struct ath_hw *ah, u32 q)
+void ath9k_hw_txstart(struct ath_hw *ah, u32 q)
{
DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Enable TXE on queue: %u\n", q);
-
REG_WRITE(ah, AR_Q_TXE, 1 << q);
-
- return true;
}
u32 ath9k_hw_numtxpending(struct ath_hw *ah, u32 q)
@@ -178,7 +173,7 @@ bool ath9k_hw_stoptxdma(struct ath_hw *ah, u32 q)
#undef ATH9K_TIME_QUANTUM
}
-bool ath9k_hw_filltxdesc(struct ath_hw *ah, struct ath_desc *ds,
+void ath9k_hw_filltxdesc(struct ath_hw *ah, struct ath_desc *ds,
u32 segLen, bool firstSeg,
bool lastSeg, const struct ath_desc *ds0)
{
@@ -202,8 +197,6 @@ bool ath9k_hw_filltxdesc(struct ath_hw *ah, struct ath_desc *ds,
ads->ds_txstatus4 = ads->ds_txstatus5 = 0;
ads->ds_txstatus6 = ads->ds_txstatus7 = 0;
ads->ds_txstatus8 = ads->ds_txstatus9 = 0;
-
- return true;
}
void ath9k_hw_cleartxdesc(struct ath_hw *ah, struct ath_desc *ds)
@@ -825,13 +818,29 @@ int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds,
ds->ds_rxstat.rs_datalen = ads.ds_rxstatus1 & AR_DataLen;
ds->ds_rxstat.rs_tstamp = ads.AR_RcvTimestamp;
- ds->ds_rxstat.rs_rssi = MS(ads.ds_rxstatus4, AR_RxRSSICombined);
- ds->ds_rxstat.rs_rssi_ctl0 = MS(ads.ds_rxstatus0, AR_RxRSSIAnt00);
- ds->ds_rxstat.rs_rssi_ctl1 = MS(ads.ds_rxstatus0, AR_RxRSSIAnt01);
- ds->ds_rxstat.rs_rssi_ctl2 = MS(ads.ds_rxstatus0, AR_RxRSSIAnt02);
- ds->ds_rxstat.rs_rssi_ext0 = MS(ads.ds_rxstatus4, AR_RxRSSIAnt10);
- ds->ds_rxstat.rs_rssi_ext1 = MS(ads.ds_rxstatus4, AR_RxRSSIAnt11);
- ds->ds_rxstat.rs_rssi_ext2 = MS(ads.ds_rxstatus4, AR_RxRSSIAnt12);
+ if (ads.ds_rxstatus8 & AR_PostDelimCRCErr) {
+ ds->ds_rxstat.rs_rssi = ATH9K_RSSI_BAD;
+ ds->ds_rxstat.rs_rssi_ctl0 = ATH9K_RSSI_BAD;
+ ds->ds_rxstat.rs_rssi_ctl1 = ATH9K_RSSI_BAD;
+ ds->ds_rxstat.rs_rssi_ctl2 = ATH9K_RSSI_BAD;
+ ds->ds_rxstat.rs_rssi_ext0 = ATH9K_RSSI_BAD;
+ ds->ds_rxstat.rs_rssi_ext1 = ATH9K_RSSI_BAD;
+ ds->ds_rxstat.rs_rssi_ext2 = ATH9K_RSSI_BAD;
+ } else {
+ ds->ds_rxstat.rs_rssi = MS(ads.ds_rxstatus4, AR_RxRSSICombined);
+ ds->ds_rxstat.rs_rssi_ctl0 = MS(ads.ds_rxstatus0,
+ AR_RxRSSIAnt00);
+ ds->ds_rxstat.rs_rssi_ctl1 = MS(ads.ds_rxstatus0,
+ AR_RxRSSIAnt01);
+ ds->ds_rxstat.rs_rssi_ctl2 = MS(ads.ds_rxstatus0,
+ AR_RxRSSIAnt02);
+ ds->ds_rxstat.rs_rssi_ext0 = MS(ads.ds_rxstatus4,
+ AR_RxRSSIAnt10);
+ ds->ds_rxstat.rs_rssi_ext1 = MS(ads.ds_rxstatus4,
+ AR_RxRSSIAnt11);
+ ds->ds_rxstat.rs_rssi_ext2 = MS(ads.ds_rxstatus4,
+ AR_RxRSSIAnt12);
+ }
if (ads.ds_rxstatus8 & AR_RxKeyIdxValid)
ds->ds_rxstat.rs_keyix = MS(ads.ds_rxstatus8, AR_KeyIdx);
else
@@ -872,7 +881,7 @@ int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds,
return 0;
}
-bool ath9k_hw_setuprxdesc(struct ath_hw *ah, struct ath_desc *ds,
+void ath9k_hw_setuprxdesc(struct ath_hw *ah, struct ath_desc *ds,
u32 size, u32 flags)
{
struct ar5416_desc *ads = AR5416DESC(ds);
@@ -885,8 +894,6 @@ bool ath9k_hw_setuprxdesc(struct ath_hw *ah, struct ath_desc *ds,
ads->ds_rxstatus8 &= ~AR_RxDone;
if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP))
memset(&(ads->u), 0, sizeof(ads->u));
-
- return true;
}
bool ath9k_hw_setrxabort(struct ath_hw *ah, bool set)
diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h
index 1176bce8b76..7b3982295a4 100644
--- a/drivers/net/wireless/ath/ath9k/mac.h
+++ b/drivers/net/wireless/ath/ath9k/mac.h
@@ -628,12 +628,12 @@ struct ath9k_channel;
struct ath_rate_table;
u32 ath9k_hw_gettxbuf(struct ath_hw *ah, u32 q);
-bool ath9k_hw_puttxbuf(struct ath_hw *ah, u32 q, u32 txdp);
-bool ath9k_hw_txstart(struct ath_hw *ah, u32 q);
+void ath9k_hw_puttxbuf(struct ath_hw *ah, u32 q, u32 txdp);
+void ath9k_hw_txstart(struct ath_hw *ah, u32 q);
u32 ath9k_hw_numtxpending(struct ath_hw *ah, u32 q);
bool ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel);
bool ath9k_hw_stoptxdma(struct ath_hw *ah, u32 q);
-bool ath9k_hw_filltxdesc(struct ath_hw *ah, struct ath_desc *ds,
+void ath9k_hw_filltxdesc(struct ath_hw *ah, struct ath_desc *ds,
u32 segLen, bool firstSeg,
bool lastSeg, const struct ath_desc *ds0);
void ath9k_hw_cleartxdesc(struct ath_hw *ah, struct ath_desc *ds);
@@ -668,7 +668,7 @@ bool ath9k_hw_releasetxqueue(struct ath_hw *ah, u32 q);
bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q);
int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds,
u32 pa, struct ath_desc *nds, u64 tsf);
-bool ath9k_hw_setuprxdesc(struct ath_hw *ah, struct ath_desc *ds,
+void ath9k_hw_setuprxdesc(struct ath_hw *ah, struct ath_desc *ds,
u32 size, u32 flags);
bool ath9k_hw_setrxabort(struct ath_hw *ah, bool set);
void ath9k_hw_putrxbuf(struct ath_hw *ah, u32 rxdp);
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index 66a6c1f5022..fa4c6e74f97 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -17,8 +17,6 @@
#include <linux/nl80211.h>
#include "ath9k.h"
-#define ATH_PCI_VERSION "0.1"
-
static char *dev_info = "ath9k";
MODULE_AUTHOR("Atheros Communications");
@@ -342,6 +340,7 @@ static void ath_ani_calibrate(unsigned long data)
* don't calibrate when we're scanning.
* we are most likely not on our home channel.
*/
+ spin_lock(&sc->ani_lock);
if (sc->sc_flags & SC_OP_SCANNING)
goto set_timer;
@@ -405,6 +404,7 @@ static void ath_ani_calibrate(unsigned long data)
ath9k_ps_restore(sc);
set_timer:
+ spin_unlock(&sc->ani_lock);
/*
* Set timer interval based on previous results.
* The interval must be the shortest necessary to satisfy ANI,
@@ -460,9 +460,10 @@ static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta)
if (sc->sc_flags & SC_OP_TXAGGR) {
ath_tx_node_init(sc, an);
- an->maxampdu = 1 << (IEEE80211_HTCAP_MAXRXAMPDU_FACTOR +
+ an->maxampdu = 1 << (IEEE80211_HT_MAX_AMPDU_FACTOR +
sta->ht_cap.ampdu_factor);
an->mpdudensity = parse_mpdudensity(sta->ht_cap.ampdu_density);
+ an->last_rssi = ATH_RSSI_DUMMY_MARKER;
}
}
@@ -496,8 +497,7 @@ static void ath9k_tasklet(unsigned long data)
if (status & ATH9K_INT_TX)
ath_tx_tasklet(sc);
- if ((status & ATH9K_INT_TSFOOR) &&
- (sc->hw->conf.flags & IEEE80211_CONF_PS)) {
+ if ((status & ATH9K_INT_TSFOOR) && sc->ps_enabled) {
/*
* TSF sync does not look correct; remain awake to sync with
* the next Beacon.
@@ -885,8 +885,7 @@ static void ath_key_delete(struct ath_softc *sc, struct ieee80211_key_conf *key)
static void setup_ht_cap(struct ath_softc *sc,
struct ieee80211_sta_ht_cap *ht_info)
{
-#define ATH9K_HT_CAP_MAXRXAMPDU_65536 0x3 /* 2 ^ 16 */
-#define ATH9K_HT_CAP_MPDUDENSITY_8 0x6 /* 8 usec */
+ u8 tx_streams, rx_streams;
ht_info->ht_supported = true;
ht_info->cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
@@ -894,50 +893,48 @@ static void setup_ht_cap(struct ath_softc *sc,
IEEE80211_HT_CAP_SGI_40 |
IEEE80211_HT_CAP_DSSSCCK40;
- ht_info->ampdu_factor = ATH9K_HT_CAP_MAXRXAMPDU_65536;
- ht_info->ampdu_density = ATH9K_HT_CAP_MPDUDENSITY_8;
+ ht_info->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
+ ht_info->ampdu_density = IEEE80211_HT_MPDU_DENSITY_8;
/* set up supported mcs set */
memset(&ht_info->mcs, 0, sizeof(ht_info->mcs));
+ tx_streams = !(sc->tx_chainmask & (sc->tx_chainmask - 1)) ? 1 : 2;
+ rx_streams = !(sc->rx_chainmask & (sc->rx_chainmask - 1)) ? 1 : 2;
- switch(sc->rx_chainmask) {
- case 1:
- ht_info->mcs.rx_mask[0] = 0xff;
- break;
- case 3:
- case 5:
- case 7:
- default:
- ht_info->mcs.rx_mask[0] = 0xff;
- ht_info->mcs.rx_mask[1] = 0xff;
- break;
+ if (tx_streams != rx_streams) {
+ DPRINTF(sc, ATH_DBG_CONFIG, "TX streams %d, RX streams: %d\n",
+ tx_streams, rx_streams);
+ ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_RX_DIFF;
+ ht_info->mcs.tx_params |= ((tx_streams - 1) <<
+ IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT);
}
- ht_info->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;
+ ht_info->mcs.rx_mask[0] = 0xff;
+ if (rx_streams >= 2)
+ ht_info->mcs.rx_mask[1] = 0xff;
+
+ ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_DEFINED;
}
static void ath9k_bss_assoc_info(struct ath_softc *sc,
struct ieee80211_vif *vif,
struct ieee80211_bss_conf *bss_conf)
{
- struct ath_vif *avp = (void *)vif->drv_priv;
if (bss_conf->assoc) {
DPRINTF(sc, ATH_DBG_CONFIG, "Bss Info ASSOC %d, bssid: %pM\n",
bss_conf->aid, sc->curbssid);
/* New association, store aid */
- if (avp->av_opmode == NL80211_IFTYPE_STATION) {
- sc->curaid = bss_conf->aid;
- ath9k_hw_write_associd(sc);
+ sc->curaid = bss_conf->aid;
+ ath9k_hw_write_associd(sc);
- /*
- * Request a re-configuration of Beacon related timers
- * on the receipt of the first Beacon frame (i.e.,
- * after time sync with the AP).
- */
- sc->sc_flags |= SC_OP_BEACON_SYNC;
- }
+ /*
+ * Request a re-configuration of Beacon related timers
+ * on the receipt of the first Beacon frame (i.e.,
+ * after time sync with the AP).
+ */
+ sc->sc_flags |= SC_OP_BEACON_SYNC;
/* Configure the beacon */
ath_beacon_config(sc, vif);
@@ -952,6 +949,8 @@ static void ath9k_bss_assoc_info(struct ath_softc *sc,
} else {
DPRINTF(sc, ATH_DBG_CONFIG, "Bss Info DISASSOC\n");
sc->curaid = 0;
+ /* Stop ANI */
+ del_timer_sync(&sc->ani.timer);
}
}
@@ -974,10 +973,11 @@ static void ath_led_blink_work(struct work_struct *work)
ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN,
(sc->sc_flags & SC_OP_LED_ON) ? 1 : 0);
- queue_delayed_work(sc->hw->workqueue, &sc->ath_led_blink_work,
- (sc->sc_flags & SC_OP_LED_ON) ?
- msecs_to_jiffies(sc->led_off_duration) :
- msecs_to_jiffies(sc->led_on_duration));
+ ieee80211_queue_delayed_work(sc->hw,
+ &sc->ath_led_blink_work,
+ (sc->sc_flags & SC_OP_LED_ON) ?
+ msecs_to_jiffies(sc->led_off_duration) :
+ msecs_to_jiffies(sc->led_on_duration));
sc->led_on_duration = sc->led_on_cnt ?
max((ATH_LED_ON_DURATION_IDLE - sc->led_on_cnt), 25) :
@@ -1014,8 +1014,8 @@ static void ath_led_brightness(struct led_classdev *led_cdev,
case LED_FULL:
if (led->led_type == ATH_LED_ASSOC) {
sc->sc_flags |= SC_OP_LED_ASSOCIATED;
- queue_delayed_work(sc->hw->workqueue,
- &sc->ath_led_blink_work, 0);
+ ieee80211_queue_delayed_work(sc->hw,
+ &sc->ath_led_blink_work, 0);
} else if (led->led_type == ATH_LED_RADIO) {
ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 0);
sc->sc_flags |= SC_OP_LED_ON;
@@ -1057,7 +1057,6 @@ static void ath_unregister_led(struct ath_led *led)
static void ath_deinit_leds(struct ath_softc *sc)
{
- cancel_delayed_work_sync(&sc->ath_led_blink_work);
ath_unregister_led(&sc->assoc_led);
sc->sc_flags &= ~SC_OP_LED_ASSOCIATED;
ath_unregister_led(&sc->tx_led);
@@ -1114,6 +1113,7 @@ static void ath_init_leds(struct ath_softc *sc)
return;
fail:
+ cancel_delayed_work_sync(&sc->ath_led_blink_work);
ath_deinit_leds(sc);
}
@@ -1253,8 +1253,6 @@ void ath_detach(struct ath_softc *sc)
DPRINTF(sc, ATH_DBG_CONFIG, "Detach ATH hw\n");
ath_deinit_leds(sc);
- cancel_work_sync(&sc->chan_work);
- cancel_delayed_work_sync(&sc->wiphy_work);
for (i = 0; i < sc->num_sec_wiphy; i++) {
struct ath_wiphy *aphy = sc->sec_wiphy[i];
@@ -1280,8 +1278,8 @@ void ath_detach(struct ath_softc *sc)
ath_tx_cleanupq(sc, &sc->tx.txq[i]);
ath9k_hw_detach(sc->sc_ah);
+ sc->sc_ah = NULL;
ath9k_exit_debug(sc);
- ath9k_ps_restore(sc);
}
static int ath9k_reg_notifier(struct wiphy *wiphy,
@@ -1295,11 +1293,16 @@ static int ath9k_reg_notifier(struct wiphy *wiphy,
return ath_reg_notifier_apply(wiphy, request, reg);
}
-static int ath_init(u16 devid, struct ath_softc *sc)
+/*
+ * Initialize and fill ath_softc, ath_sofct is the
+ * "Software Carrier" struct. Historically it has existed
+ * to allow the separation between hardware specific
+ * variables (now in ath_hw) and driver specific variables.
+ */
+static int ath_init_softc(u16 devid, struct ath_softc *sc)
{
struct ath_hw *ah = NULL;
- int status;
- int error = 0, i;
+ int r = 0, i;
int csz = 0;
/* XXX: hardware will not be ready until ath_open() being called */
@@ -1311,6 +1314,8 @@ static int ath_init(u16 devid, struct ath_softc *sc)
spin_lock_init(&sc->wiphy_lock);
spin_lock_init(&sc->sc_resetlock);
spin_lock_init(&sc->sc_serial_rw);
+ spin_lock_init(&sc->ani_lock);
+ spin_lock_init(&sc->sc_pm_lock);
mutex_init(&sc->mutex);
tasklet_init(&sc->intr_tq, ath9k_tasklet, (unsigned long)sc);
tasklet_init(&sc->bcon_tasklet, ath_beacon_tasklet,
@@ -1322,16 +1327,25 @@ static int ath_init(u16 devid, struct ath_softc *sc)
*/
ath_read_cachesize(sc, &csz);
/* XXX assert csz is non-zero */
- sc->cachelsz = csz << 2; /* convert to bytes */
+ sc->common.cachelsz = csz << 2; /* convert to bytes */
+
+ ah = kzalloc(sizeof(struct ath_hw), GFP_KERNEL);
+ if (!ah) {
+ r = -ENOMEM;
+ goto bad_no_ah;
+ }
+
+ ah->ah_sc = sc;
+ ah->hw_version.devid = devid;
+ sc->sc_ah = ah;
- ah = ath9k_hw_attach(devid, sc, &status);
- if (ah == NULL) {
+ r = ath9k_hw_init(ah);
+ if (r) {
DPRINTF(sc, ATH_DBG_FATAL,
- "Unable to attach hardware; HAL status %d\n", status);
- error = -ENXIO;
+ "Unable to initialize hardware; "
+ "initialization status: %d\n", r);
goto bad;
}
- sc->sc_ah = ah;
/* Get the hardware key cache size. */
sc->keymax = ah->caps.keycache_size;
@@ -1349,9 +1363,6 @@ static int ath_init(u16 devid, struct ath_softc *sc)
for (i = 0; i < sc->keymax; i++)
ath9k_hw_keyreset(ah, (u16) i);
- if (error)
- goto bad;
-
/* default to MONITOR mode */
sc->sc_ah->opmode = NL80211_IFTYPE_MONITOR;
@@ -1371,14 +1382,14 @@ static int ath_init(u16 devid, struct ath_softc *sc)
if (sc->beacon.beaconq == -1) {
DPRINTF(sc, ATH_DBG_FATAL,
"Unable to setup a beacon xmit queue\n");
- error = -EIO;
+ r = -EIO;
goto bad2;
}
sc->beacon.cabq = ath_txq_setup(sc, ATH9K_TX_QUEUE_CAB, 0);
if (sc->beacon.cabq == NULL) {
DPRINTF(sc, ATH_DBG_FATAL,
"Unable to setup CAB xmit queue\n");
- error = -EIO;
+ r = -EIO;
goto bad2;
}
@@ -1393,26 +1404,26 @@ static int ath_init(u16 devid, struct ath_softc *sc)
if (!ath_tx_setup(sc, ATH9K_WME_AC_BK)) {
DPRINTF(sc, ATH_DBG_FATAL,
"Unable to setup xmit queue for BK traffic\n");
- error = -EIO;
+ r = -EIO;
goto bad2;
}
if (!ath_tx_setup(sc, ATH9K_WME_AC_BE)) {
DPRINTF(sc, ATH_DBG_FATAL,
"Unable to setup xmit queue for BE traffic\n");
- error = -EIO;
+ r = -EIO;
goto bad2;
}
if (!ath_tx_setup(sc, ATH9K_WME_AC_VI)) {
DPRINTF(sc, ATH_DBG_FATAL,
"Unable to setup xmit queue for VI traffic\n");
- error = -EIO;
+ r = -EIO;
goto bad2;
}
if (!ath_tx_setup(sc, ATH9K_WME_AC_VO)) {
DPRINTF(sc, ATH_DBG_FATAL,
"Unable to setup xmit queue for VO traffic\n");
- error = -EIO;
+ r = -EIO;
goto bad2;
}
@@ -1506,11 +1517,12 @@ bad2:
if (ATH_TXQ_SETUP(sc, i))
ath_tx_cleanupq(sc, &sc->tx.txq[i]);
bad:
- if (ah)
- ath9k_hw_detach(ah);
+ ath9k_hw_detach(ah);
+ sc->sc_ah = NULL;
+bad_no_ah:
ath9k_exit_debug(sc);
- return error;
+ return r;
}
void ath_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
@@ -1536,7 +1548,8 @@ void ath_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
hw->max_rates = 4;
hw->channel_change_time = 5000;
hw->max_listen_interval = 10;
- hw->max_rate_tries = ATH_11N_TXMAXTRY;
+ /* Hardware supports 10 but we use 4 */
+ hw->max_rate_tries = 4;
hw->sta_data_size = sizeof(struct ath_node);
hw->vif_data_size = sizeof(struct ath_vif);
@@ -1549,7 +1562,8 @@ void ath_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
&sc->sbands[IEEE80211_BAND_5GHZ];
}
-int ath_attach(u16 devid, struct ath_softc *sc)
+/* Device driver core initialization */
+int ath_init_device(u16 devid, struct ath_softc *sc)
{
struct ieee80211_hw *hw = sc->hw;
int error = 0, i;
@@ -1557,7 +1571,7 @@ int ath_attach(u16 devid, struct ath_softc *sc)
DPRINTF(sc, ATH_DBG_CONFIG, "Attach ATH hw\n");
- error = ath_init(devid, sc);
+ error = ath_init_softc(devid, sc);
if (error != 0)
return error;
@@ -1615,6 +1629,7 @@ error_attach:
ath_tx_cleanupq(sc, &sc->tx.txq[i]);
ath9k_hw_detach(sc->sc_ah);
+ sc->sc_ah = NULL;
ath9k_exit_debug(sc);
return error;
@@ -1973,6 +1988,8 @@ static int ath9k_start(struct ieee80211_hw *hw)
ieee80211_wake_queues(hw);
+ ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0);
+
mutex_unlock:
mutex_unlock(&sc->mutex);
@@ -1994,7 +2011,7 @@ static int ath9k_tx(struct ieee80211_hw *hw,
goto exit;
}
- if (sc->hw->conf.flags & IEEE80211_CONF_PS) {
+ if (sc->ps_enabled) {
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
/*
* mac80211 does not set PM field for normal data frames, so we
@@ -2085,6 +2102,14 @@ static void ath9k_stop(struct ieee80211_hw *hw)
aphy->state = ATH_WIPHY_INACTIVE;
+ cancel_delayed_work_sync(&sc->ath_led_blink_work);
+ cancel_delayed_work_sync(&sc->tx_complete_work);
+
+ if (!sc->num_sec_wiphy) {
+ cancel_delayed_work_sync(&sc->wiphy_work);
+ cancel_work_sync(&sc->chan_work);
+ }
+
if (sc->sc_flags & SC_OP_INVALID) {
DPRINTF(sc, ATH_DBG_ANY, "Device not present\n");
return;
@@ -2092,7 +2117,7 @@ static void ath9k_stop(struct ieee80211_hw *hw)
mutex_lock(&sc->mutex);
- ieee80211_stop_queues(hw);
+ cancel_delayed_work_sync(&sc->tx_complete_work);
if (ath9k_wiphy_started(sc)) {
mutex_unlock(&sc->mutex);
@@ -2115,6 +2140,7 @@ static void ath9k_stop(struct ieee80211_hw *hw)
/* disable HAL and put h/w to sleep */
ath9k_hw_disable(sc->sc_ah);
ath9k_hw_configpcipowersave(sc->sc_ah, 1);
+ ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_FULL_SLEEP);
sc->sc_flags |= SC_OP_INVALID;
@@ -2189,14 +2215,15 @@ static int ath9k_add_interface(struct ieee80211_hw *hw,
if ((conf->type == NL80211_IFTYPE_STATION) ||
(conf->type == NL80211_IFTYPE_ADHOC) ||
(conf->type == NL80211_IFTYPE_MESH_POINT)) {
- if (ath9k_hw_phycounters(sc->sc_ah))
- sc->imask |= ATH9K_INT_MIB;
+ sc->imask |= ATH9K_INT_MIB;
sc->imask |= ATH9K_INT_TSFOOR;
}
ath9k_hw_set_interrupts(sc->sc_ah, sc->imask);
- if (conf->type == NL80211_IFTYPE_AP)
+ if (conf->type == NL80211_IFTYPE_AP ||
+ conf->type == NL80211_IFTYPE_ADHOC ||
+ conf->type == NL80211_IFTYPE_MONITOR)
ath_start_ani(sc);
out:
@@ -2249,9 +2276,28 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
struct ath_softc *sc = aphy->sc;
struct ieee80211_conf *conf = &hw->conf;
struct ath_hw *ah = sc->sc_ah;
+ bool all_wiphys_idle = false, disable_radio = false;
mutex_lock(&sc->mutex);
+ /* Leave this as the first check */
+ if (changed & IEEE80211_CONF_CHANGE_IDLE) {
+
+ spin_lock_bh(&sc->wiphy_lock);
+ all_wiphys_idle = ath9k_all_wiphys_idle(sc);
+ spin_unlock_bh(&sc->wiphy_lock);
+
+ if (conf->flags & IEEE80211_CONF_IDLE){
+ if (all_wiphys_idle)
+ disable_radio = true;
+ }
+ else if (all_wiphys_idle) {
+ ath_radio_enable(sc);
+ DPRINTF(sc, ATH_DBG_CONFIG,
+ "not-idle: enabling radio\n");
+ }
+ }
+
if (changed & IEEE80211_CONF_CHANGE_PS) {
if (conf->flags & IEEE80211_CONF_PS) {
if (!(ah->caps.hw_caps &
@@ -2263,8 +2309,9 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
}
ath9k_hw_setrxabort(sc->sc_ah, 1);
}
- ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_NETWORK_SLEEP);
+ sc->ps_enabled = true;
} else {
+ sc->ps_enabled = false;
ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_AWAKE);
if (!(ah->caps.hw_caps &
ATH9K_HW_CAP_AUTOSLEEP)) {
@@ -2319,6 +2366,11 @@ skip_chan_change:
if (changed & IEEE80211_CONF_CHANGE_POWER)
sc->config.txpowlimit = 2 * conf->power_level;
+ if (disable_radio) {
+ DPRINTF(sc, ATH_DBG_CONFIG, "idle: disabling radio\n");
+ ath_radio_disable(sc);
+ }
+
mutex_unlock(&sc->mutex);
return 0;
@@ -2328,6 +2380,7 @@ skip_chan_change:
(FIF_PROMISC_IN_BSS | \
FIF_ALLMULTI | \
FIF_CONTROL | \
+ FIF_PSPOLL | \
FIF_OTHER_BSS | \
FIF_BCN_PRBRESP_PROMISC | \
FIF_FCSFAIL)
@@ -2638,19 +2691,11 @@ static int ath9k_ampdu_action(struct ieee80211_hw *hw,
case IEEE80211_AMPDU_RX_STOP:
break;
case IEEE80211_AMPDU_TX_START:
- ret = ath_tx_aggr_start(sc, sta, tid, ssn);
- if (ret < 0)
- DPRINTF(sc, ATH_DBG_FATAL,
- "Unable to start TX aggregation\n");
- else
- ieee80211_start_tx_ba_cb_irqsafe(hw, sta->addr, tid);
+ ath_tx_aggr_start(sc, sta, tid, ssn);
+ ieee80211_start_tx_ba_cb_irqsafe(hw, sta->addr, tid);
break;
case IEEE80211_AMPDU_TX_STOP:
- ret = ath_tx_aggr_stop(sc, sta, tid);
- if (ret < 0)
- DPRINTF(sc, ATH_DBG_FATAL,
- "Unable to stop TX aggregation\n");
-
+ ath_tx_aggr_stop(sc, sta, tid);
ieee80211_stop_tx_ba_cb_irqsafe(hw, sta->addr, tid);
break;
case IEEE80211_AMPDU_TX_OPERATIONAL:
@@ -2681,9 +2726,9 @@ static void ath9k_sw_scan_start(struct ieee80211_hw *hw)
aphy->state = ATH_WIPHY_SCAN;
ath9k_wiphy_pause_all_forced(sc, aphy);
- mutex_lock(&sc->mutex);
+ spin_lock_bh(&sc->ani_lock);
sc->sc_flags |= SC_OP_SCANNING;
- mutex_unlock(&sc->mutex);
+ spin_unlock_bh(&sc->ani_lock);
}
static void ath9k_sw_scan_complete(struct ieee80211_hw *hw)
@@ -2691,11 +2736,11 @@ static void ath9k_sw_scan_complete(struct ieee80211_hw *hw)
struct ath_wiphy *aphy = hw->priv;
struct ath_softc *sc = aphy->sc;
- mutex_lock(&sc->mutex);
+ spin_lock_bh(&sc->ani_lock);
aphy->state = ATH_WIPHY_ACTIVE;
sc->sc_flags &= ~SC_OP_SCANNING;
sc->sc_flags |= SC_OP_FULL_RESET;
- mutex_unlock(&sc->mutex);
+ spin_unlock_bh(&sc->ani_lock);
}
struct ieee80211_ops ath9k_ops = {
@@ -2728,7 +2773,8 @@ static struct {
{ AR_SREV_VERSION_9100, "9100" },
{ AR_SREV_VERSION_9160, "9160" },
{ AR_SREV_VERSION_9280, "9280" },
- { AR_SREV_VERSION_9285, "9285" }
+ { AR_SREV_VERSION_9285, "9285" },
+ { AR_SREV_VERSION_9287, "9287" }
};
static struct {
diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c
index 170c5b32e49..616bdff2b6a 100644
--- a/drivers/net/wireless/ath/ath9k/pci.c
+++ b/drivers/net/wireless/ath/ath9k/pci.c
@@ -25,6 +25,8 @@ static struct pci_device_id ath_pci_id_table[] __devinitdata = {
{ PCI_VDEVICE(ATHEROS, 0x0029) }, /* PCI */
{ PCI_VDEVICE(ATHEROS, 0x002A) }, /* PCI-E */
{ PCI_VDEVICE(ATHEROS, 0x002B) }, /* PCI-E */
+ { PCI_VDEVICE(ATHEROS, 0x002D) }, /* PCI */
+ { PCI_VDEVICE(ATHEROS, 0x002E) }, /* PCI-E */
{ 0 }
};
@@ -176,7 +178,7 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
sc->mem = mem;
sc->bus_ops = &ath_pci_bus_ops;
- if (ath_attach(id->device, sc) != 0) {
+ if (ath_init_device(id->device, sc) != 0) {
ret = -ENODEV;
goto bad3;
}
@@ -251,10 +253,12 @@ static int ath_pci_resume(struct pci_dev *pdev)
u32 val;
int err;
+ pci_restore_state(pdev);
+
err = pci_enable_device(pdev);
if (err)
return err;
- pci_restore_state(pdev);
+
/*
* Suspend/Resume resets the PCI configuration space, so we have to
* re-disable the RETRY_TIMEOUT register (0x41) to keep
diff --git a/drivers/net/wireless/ath/ath9k/phy.c b/drivers/net/wireless/ath/ath9k/phy.c
index aaa941561c3..63bf9a307c6 100644
--- a/drivers/net/wireless/ath/ath9k/phy.c
+++ b/drivers/net/wireless/ath/ath9k/phy.c
@@ -264,44 +264,23 @@ ath9k_hw_set_rf_regs(struct ath_hw *ah, struct ath9k_channel *chan,
}
void
-ath9k_hw_rfdetach(struct ath_hw *ah)
+ath9k_hw_rf_free(struct ath_hw *ah)
{
- if (ah->analogBank0Data != NULL) {
- kfree(ah->analogBank0Data);
- ah->analogBank0Data = NULL;
- }
- if (ah->analogBank1Data != NULL) {
- kfree(ah->analogBank1Data);
- ah->analogBank1Data = NULL;
- }
- if (ah->analogBank2Data != NULL) {
- kfree(ah->analogBank2Data);
- ah->analogBank2Data = NULL;
- }
- if (ah->analogBank3Data != NULL) {
- kfree(ah->analogBank3Data);
- ah->analogBank3Data = NULL;
- }
- if (ah->analogBank6Data != NULL) {
- kfree(ah->analogBank6Data);
- ah->analogBank6Data = NULL;
- }
- if (ah->analogBank6TPCData != NULL) {
- kfree(ah->analogBank6TPCData);
- ah->analogBank6TPCData = NULL;
- }
- if (ah->analogBank7Data != NULL) {
- kfree(ah->analogBank7Data);
- ah->analogBank7Data = NULL;
- }
- if (ah->addac5416_21 != NULL) {
- kfree(ah->addac5416_21);
- ah->addac5416_21 = NULL;
- }
- if (ah->bank6Temp != NULL) {
- kfree(ah->bank6Temp);
- ah->bank6Temp = NULL;
- }
+#define ATH_FREE_BANK(bank) do { \
+ kfree(bank); \
+ bank = NULL; \
+ } while (0);
+
+ ATH_FREE_BANK(ah->analogBank0Data);
+ ATH_FREE_BANK(ah->analogBank1Data);
+ ATH_FREE_BANK(ah->analogBank2Data);
+ ATH_FREE_BANK(ah->analogBank3Data);
+ ATH_FREE_BANK(ah->analogBank6Data);
+ ATH_FREE_BANK(ah->analogBank6TPCData);
+ ATH_FREE_BANK(ah->analogBank7Data);
+ ATH_FREE_BANK(ah->addac5416_21);
+ ATH_FREE_BANK(ah->bank6Temp);
+#undef ATH_FREE_BANK
}
bool ath9k_hw_init_rf(struct ath_hw *ah, int *status)
@@ -374,18 +353,16 @@ ath9k_hw_decrease_chain_power(struct ath_hw *ah, struct ath9k_channel *chan)
u32 bank6SelMask;
u32 *bank6Temp = ah->bank6Temp;
- switch (ah->diversity_control) {
+ switch (ah->config.diversity_control) {
case ATH9K_ANT_FIXED_A:
bank6SelMask =
- (ah->
- antenna_switch_swap & ANTSWAP_AB) ? REDUCE_CHAIN_0 :
- REDUCE_CHAIN_1;
+ (ah->config.antenna_switch_swap & ANTSWAP_AB) ?
+ REDUCE_CHAIN_0 : REDUCE_CHAIN_1;
break;
case ATH9K_ANT_FIXED_B:
bank6SelMask =
- (ah->
- antenna_switch_swap & ANTSWAP_AB) ? REDUCE_CHAIN_1 :
- REDUCE_CHAIN_0;
+ (ah->config.antenna_switch_swap & ANTSWAP_AB) ?
+ REDUCE_CHAIN_1 : REDUCE_CHAIN_0;
break;
case ATH9K_ANT_VARIABLE:
return;
diff --git a/drivers/net/wireless/ath/ath9k/phy.h b/drivers/net/wireless/ath/ath9k/phy.h
index c70f530642f..e83cd4ab87f 100644
--- a/drivers/net/wireless/ath/ath9k/phy.h
+++ b/drivers/net/wireless/ath/ath9k/phy.h
@@ -185,6 +185,9 @@ bool ath9k_hw_init_rf(struct ath_hw *ah,
#define AR_PHY_PLL_CTL_44_2133 0xeb
#define AR_PHY_PLL_CTL_40_2133 0xea
+#define AR_PHY_SPECTRAL_SCAN 0x9912
+#define AR_PHY_SPECTRAL_SCAN_ENABLE 0x1
+
#define AR_PHY_RX_DELAY 0x9914
#define AR_PHY_SEARCH_START_DELAY 0x9918
#define AR_PHY_RX_DELAY_DELAY 0x00003FFF
@@ -309,7 +312,25 @@ bool ath9k_hw_init_rf(struct ath_hw *ah,
#define AR_PHY_NEW_ADC_DC_GAIN_CORR(_i) (0x99b4 + ((_i) << 12))
#define AR_PHY_NEW_ADC_GAIN_CORR_ENABLE 0x40000000
#define AR_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE 0x80000000
-#define AR_PHY_MULTICHAIN_GAIN_CTL 0x99ac
+
+#define AR_PHY_MULTICHAIN_GAIN_CTL 0x99ac
+#define AR_PHY_9285_ANT_DIV_CTL_ALL 0x7f000000
+#define AR_PHY_9285_ANT_DIV_CTL 0x01000000
+#define AR_PHY_9285_ANT_DIV_CTL_S 24
+#define AR_PHY_9285_ANT_DIV_ALT_LNACONF 0x06000000
+#define AR_PHY_9285_ANT_DIV_ALT_LNACONF_S 25
+#define AR_PHY_9285_ANT_DIV_MAIN_LNACONF 0x18000000
+#define AR_PHY_9285_ANT_DIV_MAIN_LNACONF_S 27
+#define AR_PHY_9285_ANT_DIV_ALT_GAINTB 0x20000000
+#define AR_PHY_9285_ANT_DIV_ALT_GAINTB_S 29
+#define AR_PHY_9285_ANT_DIV_MAIN_GAINTB 0x40000000
+#define AR_PHY_9285_ANT_DIV_MAIN_GAINTB_S 30
+#define AR_PHY_9285_ANT_DIV_LNA1 2
+#define AR_PHY_9285_ANT_DIV_LNA2 1
+#define AR_PHY_9285_ANT_DIV_LNA1_PLUS_LNA2 3
+#define AR_PHY_9285_ANT_DIV_LNA1_MINUS_LNA2 0
+#define AR_PHY_9285_ANT_DIV_GAINTB_0 0
+#define AR_PHY_9285_ANT_DIV_GAINTB_1 1
#define AR_PHY_EXT_CCA0 0x99b8
#define AR_PHY_EXT_CCA0_THRESH62 0x000000FF
@@ -375,6 +396,7 @@ bool ath9k_hw_init_rf(struct ath_hw *ah,
#define AR_PHY_CHAN_INFO_GAIN 0x9CFC
#define AR_PHY_MODE 0xA200
+#define AR_PHY_MODE_ASYNCFIFO 0x80
#define AR_PHY_MODE_AR2133 0x08
#define AR_PHY_MODE_AR5111 0x00
#define AR_PHY_MODE_AR5112 0x08
@@ -397,6 +419,7 @@ bool ath9k_hw_init_rf(struct ath_hw *ah,
#define AR_PHY_CCK_DETECT_ANT_SWITCH_TIME 0x00001FC0
#define AR_PHY_CCK_DETECT_ANT_SWITCH_TIME_S 6
#define AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV 0x2000
+#define AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV_S 13
#define AR_PHY_GAIN_2GHZ 0xA20C
#define AR_PHY_GAIN_2GHZ_RXTX_MARGIN 0x00FC0000
diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c
index ba06e78b2f5..16a271787b8 100644
--- a/drivers/net/wireless/ath/ath9k/rc.c
+++ b/drivers/net/wireless/ath/ath9k/rc.c
@@ -22,133 +22,132 @@ static const struct ath_rate_table ar5416_11na_ratetable = {
{
{ VALID, VALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */
5400, 0x0b, 0x00, 12,
- 0, 2, 1, 0, 0, 0, 0, 0 },
+ 0, 0, 0, 0, 0, 0 },
{ VALID, VALID, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */
7800, 0x0f, 0x00, 18,
- 0, 3, 1, 1, 1, 1, 1, 0 },
+ 0, 1, 1, 1, 1, 0 },
{ VALID, VALID, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */
10000, 0x0a, 0x00, 24,
- 2, 4, 2, 2, 2, 2, 2, 0 },
+ 2, 2, 2, 2, 2, 0 },
{ VALID, VALID, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */
13900, 0x0e, 0x00, 36,
- 2, 6, 2, 3, 3, 3, 3, 0 },
+ 2, 3, 3, 3, 3, 0 },
{ VALID, VALID, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */
17300, 0x09, 0x00, 48,
- 4, 10, 3, 4, 4, 4, 4, 0 },
+ 4, 4, 4, 4, 4, 0 },
{ VALID, VALID, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */
23000, 0x0d, 0x00, 72,
- 4, 14, 3, 5, 5, 5, 5, 0 },
+ 4, 5, 5, 5, 5, 0 },
{ VALID, VALID, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */
27400, 0x08, 0x00, 96,
- 4, 20, 3, 6, 6, 6, 6, 0 },
+ 4, 6, 6, 6, 6, 0 },
{ VALID, VALID, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */
29300, 0x0c, 0x00, 108,
- 4, 23, 3, 7, 7, 7, 7, 0 },
- { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 6500, /* 6.5 Mb */
+ 4, 7, 7, 7, 7, 0 },
+ { VALID_2040, VALID_2040, WLAN_RC_PHY_HT_20_SS, 6500, /* 6.5 Mb */
6400, 0x80, 0x00, 0,
- 0, 2, 3, 8, 24, 8, 24, 3216 },
+ 0, 8, 24, 8, 24, 3216 },
{ VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 13000, /* 13 Mb */
12700, 0x81, 0x00, 1,
- 2, 4, 3, 9, 25, 9, 25, 6434 },
+ 2, 9, 25, 9, 25, 6434 },
{ VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 19500, /* 19.5 Mb */
18800, 0x82, 0x00, 2,
- 2, 6, 3, 10, 26, 10, 26, 9650 },
+ 2, 10, 26, 10, 26, 9650 },
{ VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 26000, /* 26 Mb */
25000, 0x83, 0x00, 3,
- 4, 10, 3, 11, 27, 11, 27, 12868 },
+ 4, 11, 27, 11, 27, 12868 },
{ VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 39000, /* 39 Mb */
36700, 0x84, 0x00, 4,
- 4, 14, 3, 12, 28, 12, 28, 19304 },
+ 4, 12, 28, 12, 28, 19304 },
{ INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 52000, /* 52 Mb */
48100, 0x85, 0x00, 5,
- 4, 20, 3, 13, 29, 13, 29, 25740 },
+ 4, 13, 29, 13, 29, 25740 },
{ INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 58500, /* 58.5 Mb */
53500, 0x86, 0x00, 6,
- 4, 23, 3, 14, 30, 14, 30, 28956 },
+ 4, 14, 30, 14, 30, 28956 },
{ INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 65000, /* 65 Mb */
59000, 0x87, 0x00, 7,
- 4, 25, 3, 15, 31, 15, 32, 32180 },
+ 4, 15, 31, 15, 32, 32180 },
{ INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 13000, /* 13 Mb */
12700, 0x88, 0x00,
- 8, 0, 2, 3, 16, 33, 16, 33, 6430 },
+ 8, 3, 16, 33, 16, 33, 6430 },
{ INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 26000, /* 26 Mb */
24800, 0x89, 0x00, 9,
- 2, 4, 3, 17, 34, 17, 34, 12860 },
+ 2, 17, 34, 17, 34, 12860 },
{ INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 39000, /* 39 Mb */
36600, 0x8a, 0x00, 10,
- 2, 6, 3, 18, 35, 18, 35, 19300 },
+ 2, 18, 35, 18, 35, 19300 },
{ VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 52000, /* 52 Mb */
48100, 0x8b, 0x00, 11,
- 4, 10, 3, 19, 36, 19, 36, 25736 },
+ 4, 19, 36, 19, 36, 25736 },
{ VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 78000, /* 78 Mb */
69500, 0x8c, 0x00, 12,
- 4, 14, 3, 20, 37, 20, 37, 38600 },
+ 4, 20, 37, 20, 37, 38600 },
{ VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 104000, /* 104 Mb */
89500, 0x8d, 0x00, 13,
- 4, 20, 3, 21, 38, 21, 38, 51472 },
+ 4, 21, 38, 21, 38, 51472 },
{ VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 117000, /* 117 Mb */
98900, 0x8e, 0x00, 14,
- 4, 23, 3, 22, 39, 22, 39, 57890 },
+ 4, 22, 39, 22, 39, 57890 },
{ VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 130000, /* 130 Mb */
108300, 0x8f, 0x00, 15,
- 4, 25, 3, 23, 40, 23, 41, 64320 },
+ 4, 23, 40, 23, 41, 64320 },
{ VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 13500, /* 13.5 Mb */
13200, 0x80, 0x00, 0,
- 0, 2, 3, 8, 24, 24, 24, 6684 },
+ 0, 8, 24, 24, 24, 6684 },
{ VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 27500, /* 27.0 Mb */
25900, 0x81, 0x00, 1,
- 2, 4, 3, 9, 25, 25, 25, 13368 },
+ 2, 9, 25, 25, 25, 13368 },
{ VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 40500, /* 40.5 Mb */
38600, 0x82, 0x00, 2,
- 2, 6, 3, 10, 26, 26, 26, 20052 },
+ 2, 10, 26, 26, 26, 20052 },
{ VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 54000, /* 54 Mb */
49800, 0x83, 0x00, 3,
- 4, 10, 3, 11, 27, 27, 27, 26738 },
+ 4, 11, 27, 27, 27, 26738 },
{ VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 81500, /* 81 Mb */
72200, 0x84, 0x00, 4,
- 4, 14, 3, 12, 28, 28, 28, 40104 },
+ 4, 12, 28, 28, 28, 40104 },
{ INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 108000, /* 108 Mb */
92900, 0x85, 0x00, 5,
- 4, 20, 3, 13, 29, 29, 29, 53476 },
+ 4, 13, 29, 29, 29, 53476 },
{ INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 121500, /* 121.5 Mb */
102700, 0x86, 0x00, 6,
- 4, 23, 3, 14, 30, 30, 30, 60156 },
+ 4, 14, 30, 30, 30, 60156 },
{ INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 135000, /* 135 Mb */
112000, 0x87, 0x00, 7,
- 4, 25, 3, 15, 31, 32, 32, 66840 },
+ 4, 15, 31, 32, 32, 66840 },
{ INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS_HGI, 150000, /* 150 Mb */
122000, 0x87, 0x00, 7,
- 4, 25, 3, 15, 31, 32, 32, 74200 },
+ 4, 15, 31, 32, 32, 74200 },
{ INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 27000, /* 27 Mb */
25800, 0x88, 0x00, 8,
- 0, 2, 3, 16, 33, 33, 33, 13360 },
+ 0, 16, 33, 33, 33, 13360 },
{ INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 54000, /* 54 Mb */
49800, 0x89, 0x00, 9,
- 2, 4, 3, 17, 34, 34, 34, 26720 },
+ 2, 17, 34, 34, 34, 26720 },
{ INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 81000, /* 81 Mb */
71900, 0x8a, 0x00, 10,
- 2, 6, 3, 18, 35, 35, 35, 40080 },
+ 2, 18, 35, 35, 35, 40080 },
{ VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 108000, /* 108 Mb */
92500, 0x8b, 0x00, 11,
- 4, 10, 3, 19, 36, 36, 36, 53440 },
+ 4, 19, 36, 36, 36, 53440 },
{ VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 162000, /* 162 Mb */
130300, 0x8c, 0x00, 12,
- 4, 14, 3, 20, 37, 37, 37, 80160 },
+ 4, 20, 37, 37, 37, 80160 },
{ VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 216000, /* 216 Mb */
162800, 0x8d, 0x00, 13,
- 4, 20, 3, 21, 38, 38, 38, 106880 },
+ 4, 21, 38, 38, 38, 106880 },
{ VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 243000, /* 243 Mb */
178200, 0x8e, 0x00, 14,
- 4, 23, 3, 22, 39, 39, 39, 120240 },
+ 4, 22, 39, 39, 39, 120240 },
{ VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 270000, /* 270 Mb */
192100, 0x8f, 0x00, 15,
- 4, 25, 3, 23, 40, 41, 41, 133600 },
+ 4, 23, 40, 41, 41, 133600 },
{ VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS_HGI, 300000, /* 300 Mb */
207000, 0x8f, 0x00, 15,
- 4, 25, 3, 23, 40, 41, 41, 148400 },
+ 4, 23, 40, 41, 41, 148400 },
},
50, /* probe interval */
- 50, /* rssi reduce interval */
WLAN_RC_HT_FLAG, /* Phy rates allowed initially */
};
@@ -160,145 +159,144 @@ static const struct ath_rate_table ar5416_11ng_ratetable = {
{
{ VALID_ALL, VALID_ALL, WLAN_RC_PHY_CCK, 1000, /* 1 Mb */
900, 0x1b, 0x00, 2,
- 0, 0, 1, 0, 0, 0, 0, 0 },
+ 0, 0, 0, 0, 0, 0 },
{ VALID_ALL, VALID_ALL, WLAN_RC_PHY_CCK, 2000, /* 2 Mb */
1900, 0x1a, 0x04, 4,
- 1, 1, 1, 1, 1, 1, 1, 0 },
+ 1, 1, 1, 1, 1, 0 },
{ VALID_ALL, VALID_ALL, WLAN_RC_PHY_CCK, 5500, /* 5.5 Mb */
4900, 0x19, 0x04, 11,
- 2, 2, 2, 2, 2, 2, 2, 0 },
+ 2, 2, 2, 2, 2, 0 },
{ VALID_ALL, VALID_ALL, WLAN_RC_PHY_CCK, 11000, /* 11 Mb */
8100, 0x18, 0x04, 22,
- 3, 3, 2, 3, 3, 3, 3, 0 },
+ 3, 3, 3, 3, 3, 0 },
{ INVALID, INVALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */
5400, 0x0b, 0x00, 12,
- 4, 2, 1, 4, 4, 4, 4, 0 },
+ 4, 4, 4, 4, 4, 0 },
{ INVALID, INVALID, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */
7800, 0x0f, 0x00, 18,
- 4, 3, 1, 5, 5, 5, 5, 0 },
+ 4, 5, 5, 5, 5, 0 },
{ VALID, VALID, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */
10100, 0x0a, 0x00, 24,
- 6, 4, 1, 6, 6, 6, 6, 0 },
+ 6, 6, 6, 6, 6, 0 },
{ VALID, VALID, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */
14100, 0x0e, 0x00, 36,
- 6, 6, 2, 7, 7, 7, 7, 0 },
+ 6, 7, 7, 7, 7, 0 },
{ VALID, VALID, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */
17700, 0x09, 0x00, 48,
- 8, 10, 3, 8, 8, 8, 8, 0 },
+ 8, 8, 8, 8, 8, 0 },
{ VALID, VALID, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */
23700, 0x0d, 0x00, 72,
- 8, 14, 3, 9, 9, 9, 9, 0 },
+ 8, 9, 9, 9, 9, 0 },
{ VALID, VALID, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */
27400, 0x08, 0x00, 96,
- 8, 20, 3, 10, 10, 10, 10, 0 },
+ 8, 10, 10, 10, 10, 0 },
{ VALID, VALID, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */
30900, 0x0c, 0x00, 108,
- 8, 23, 3, 11, 11, 11, 11, 0 },
+ 8, 11, 11, 11, 11, 0 },
{ INVALID, INVALID, WLAN_RC_PHY_HT_20_SS, 6500, /* 6.5 Mb */
6400, 0x80, 0x00, 0,
- 4, 2, 3, 12, 28, 12, 28, 3216 },
+ 4, 12, 28, 12, 28, 3216 },
{ VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 13000, /* 13 Mb */
12700, 0x81, 0x00, 1,
- 6, 4, 3, 13, 29, 13, 29, 6434 },
+ 6, 13, 29, 13, 29, 6434 },
{ VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 19500, /* 19.5 Mb */
18800, 0x82, 0x00, 2,
- 6, 6, 3, 14, 30, 14, 30, 9650 },
+ 6, 14, 30, 14, 30, 9650 },
{ VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 26000, /* 26 Mb */
25000, 0x83, 0x00, 3,
- 8, 10, 3, 15, 31, 15, 31, 12868 },
+ 8, 15, 31, 15, 31, 12868 },
{ VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 39000, /* 39 Mb */
36700, 0x84, 0x00, 4,
- 8, 14, 3, 16, 32, 16, 32, 19304 },
+ 8, 16, 32, 16, 32, 19304 },
{ INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 52000, /* 52 Mb */
48100, 0x85, 0x00, 5,
- 8, 20, 3, 17, 33, 17, 33, 25740 },
+ 8, 17, 33, 17, 33, 25740 },
{ INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 58500, /* 58.5 Mb */
53500, 0x86, 0x00, 6,
- 8, 23, 3, 18, 34, 18, 34, 28956 },
+ 8, 18, 34, 18, 34, 28956 },
{ INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 65000, /* 65 Mb */
59000, 0x87, 0x00, 7,
- 8, 25, 3, 19, 35, 19, 36, 32180 },
+ 8, 19, 35, 19, 36, 32180 },
{ INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 13000, /* 13 Mb */
12700, 0x88, 0x00, 8,
- 4, 2, 3, 20, 37, 20, 37, 6430 },
+ 4, 20, 37, 20, 37, 6430 },
{ INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 26000, /* 26 Mb */
24800, 0x89, 0x00, 9,
- 6, 4, 3, 21, 38, 21, 38, 12860 },
+ 6, 21, 38, 21, 38, 12860 },
{ INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 39000, /* 39 Mb */
36600, 0x8a, 0x00, 10,
- 6, 6, 3, 22, 39, 22, 39, 19300 },
+ 6, 22, 39, 22, 39, 19300 },
{ VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 52000, /* 52 Mb */
48100, 0x8b, 0x00, 11,
- 8, 10, 3, 23, 40, 23, 40, 25736 },
+ 8, 23, 40, 23, 40, 25736 },
{ VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 78000, /* 78 Mb */
69500, 0x8c, 0x00, 12,
- 8, 14, 3, 24, 41, 24, 41, 38600 },
+ 8, 24, 41, 24, 41, 38600 },
{ VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 104000, /* 104 Mb */
89500, 0x8d, 0x00, 13,
- 8, 20, 3, 25, 42, 25, 42, 51472 },
+ 8, 25, 42, 25, 42, 51472 },
{ VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 117000, /* 117 Mb */
98900, 0x8e, 0x00, 14,
- 8, 23, 3, 26, 43, 26, 44, 57890 },
+ 8, 26, 43, 26, 44, 57890 },
{ VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 130000, /* 130 Mb */
108300, 0x8f, 0x00, 15,
- 8, 25, 3, 27, 44, 27, 45, 64320 },
+ 8, 27, 44, 27, 45, 64320 },
{ VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 13500, /* 13.5 Mb */
13200, 0x80, 0x00, 0,
- 8, 2, 3, 12, 28, 28, 28, 6684 },
+ 8, 12, 28, 28, 28, 6684 },
{ VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 27500, /* 27.0 Mb */
25900, 0x81, 0x00, 1,
- 8, 4, 3, 13, 29, 29, 29, 13368 },
+ 8, 13, 29, 29, 29, 13368 },
{ VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 40500, /* 40.5 Mb */
38600, 0x82, 0x00, 2,
- 8, 6, 3, 14, 30, 30, 30, 20052 },
+ 8, 14, 30, 30, 30, 20052 },
{ VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 54000, /* 54 Mb */
49800, 0x83, 0x00, 3,
- 8, 10, 3, 15, 31, 31, 31, 26738 },
+ 8, 15, 31, 31, 31, 26738 },
{ VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 81500, /* 81 Mb */
72200, 0x84, 0x00, 4,
- 8, 14, 3, 16, 32, 32, 32, 40104 },
+ 8, 16, 32, 32, 32, 40104 },
{ INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 108000, /* 108 Mb */
92900, 0x85, 0x00, 5,
- 8, 20, 3, 17, 33, 33, 33, 53476 },
+ 8, 17, 33, 33, 33, 53476 },
{ INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 121500, /* 121.5 Mb */
102700, 0x86, 0x00, 6,
- 8, 23, 3, 18, 34, 34, 34, 60156 },
+ 8, 18, 34, 34, 34, 60156 },
{ INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 135000, /* 135 Mb */
112000, 0x87, 0x00, 7,
- 8, 23, 3, 19, 35, 36, 36, 66840 },
+ 8, 19, 35, 36, 36, 66840 },
{ INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS_HGI, 150000, /* 150 Mb */
122000, 0x87, 0x00, 7,
- 8, 25, 3, 19, 35, 36, 36, 74200 },
+ 8, 19, 35, 36, 36, 74200 },
{ INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 27000, /* 27 Mb */
25800, 0x88, 0x00, 8,
- 8, 2, 3, 20, 37, 37, 37, 13360 },
+ 8, 20, 37, 37, 37, 13360 },
{ INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 54000, /* 54 Mb */
49800, 0x89, 0x00, 9,
- 8, 4, 3, 21, 38, 38, 38, 26720 },
+ 8, 21, 38, 38, 38, 26720 },
{ INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 81000, /* 81 Mb */
71900, 0x8a, 0x00, 10,
- 8, 6, 3, 22, 39, 39, 39, 40080 },
+ 8, 22, 39, 39, 39, 40080 },
{ VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 108000, /* 108 Mb */
92500, 0x8b, 0x00, 11,
- 8, 10, 3, 23, 40, 40, 40, 53440 },
+ 8, 23, 40, 40, 40, 53440 },
{ VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 162000, /* 162 Mb */
130300, 0x8c, 0x00, 12,
- 8, 14, 3, 24, 41, 41, 41, 80160 },
+ 8, 24, 41, 41, 41, 80160 },
{ VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 216000, /* 216 Mb */
162800, 0x8d, 0x00, 13,
- 8, 20, 3, 25, 42, 42, 42, 106880 },
+ 8, 25, 42, 42, 42, 106880 },
{ VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 243000, /* 243 Mb */
178200, 0x8e, 0x00, 14,
- 8, 23, 3, 26, 43, 43, 43, 120240 },
+ 8, 26, 43, 43, 43, 120240 },
{ VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 270000, /* 270 Mb */
192100, 0x8f, 0x00, 15,
- 8, 23, 3, 27, 44, 45, 45, 133600 },
+ 8, 27, 44, 45, 45, 133600 },
{ VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS_HGI, 300000, /* 300 Mb */
207000, 0x8f, 0x00, 15,
- 8, 25, 3, 27, 44, 45, 45, 148400 },
+ 8, 27, 44, 45, 45, 148400 },
},
50, /* probe interval */
- 50, /* rssi reduce interval */
WLAN_RC_HT_FLAG, /* Phy rates allowed initially */
};
@@ -307,31 +305,30 @@ static const struct ath_rate_table ar5416_11a_ratetable = {
{
{ VALID, VALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */
5400, 0x0b, 0x00, (0x80|12),
- 0, 2, 1, 0, 0 },
+ 0, 0, 0 },
{ VALID, VALID, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */
7800, 0x0f, 0x00, 18,
- 0, 3, 1, 1, 0 },
+ 0, 1, 0 },
{ VALID, VALID, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */
10000, 0x0a, 0x00, (0x80|24),
- 2, 4, 2, 2, 0 },
+ 2, 2, 0 },
{ VALID, VALID, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */
13900, 0x0e, 0x00, 36,
- 2, 6, 2, 3, 0 },
+ 2, 3, 0 },
{ VALID, VALID, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */
17300, 0x09, 0x00, (0x80|48),
- 4, 10, 3, 4, 0 },
+ 4, 4, 0 },
{ VALID, VALID, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */
23000, 0x0d, 0x00, 72,
- 4, 14, 3, 5, 0 },
+ 4, 5, 0 },
{ VALID, VALID, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */
27400, 0x08, 0x00, 96,
- 4, 19, 3, 6, 0 },
+ 4, 6, 0 },
{ VALID, VALID, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */
29300, 0x0c, 0x00, 108,
- 4, 23, 3, 7, 0 },
+ 4, 7, 0 },
},
50, /* probe interval */
- 50, /* rssi reduce interval */
0, /* Phy rates allowed initially */
};
@@ -340,64 +337,42 @@ static const struct ath_rate_table ar5416_11g_ratetable = {
{
{ VALID, VALID, WLAN_RC_PHY_CCK, 1000, /* 1 Mb */
900, 0x1b, 0x00, 2,
- 0, 0, 1, 0, 0 },
+ 0, 0, 0 },
{ VALID, VALID, WLAN_RC_PHY_CCK, 2000, /* 2 Mb */
1900, 0x1a, 0x04, 4,
- 1, 1, 1, 1, 0 },
+ 1, 1, 0 },
{ VALID, VALID, WLAN_RC_PHY_CCK, 5500, /* 5.5 Mb */
4900, 0x19, 0x04, 11,
- 2, 2, 2, 2, 0 },
+ 2, 2, 0 },
{ VALID, VALID, WLAN_RC_PHY_CCK, 11000, /* 11 Mb */
8100, 0x18, 0x04, 22,
- 3, 3, 2, 3, 0 },
+ 3, 3, 0 },
{ INVALID, INVALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */
5400, 0x0b, 0x00, 12,
- 4, 2, 1, 4, 0 },
+ 4, 4, 0 },
{ INVALID, INVALID, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */
7800, 0x0f, 0x00, 18,
- 4, 3, 1, 5, 0 },
+ 4, 5, 0 },
{ VALID, VALID, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */
10000, 0x0a, 0x00, 24,
- 6, 4, 1, 6, 0 },
+ 6, 6, 0 },
{ VALID, VALID, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */
13900, 0x0e, 0x00, 36,
- 6, 6, 2, 7, 0 },
+ 6, 7, 0 },
{ VALID, VALID, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */
17300, 0x09, 0x00, 48,
- 8, 10, 3, 8, 0 },
+ 8, 8, 0 },
{ VALID, VALID, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */
23000, 0x0d, 0x00, 72,
- 8, 14, 3, 9, 0 },
+ 8, 9, 0 },
{ VALID, VALID, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */
27400, 0x08, 0x00, 96,
- 8, 19, 3, 10, 0 },
+ 8, 10, 0 },
{ VALID, VALID, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */
29300, 0x0c, 0x00, 108,
- 8, 23, 3, 11, 0 },
+ 8, 11, 0 },
},
50, /* probe interval */
- 50, /* rssi reduce interval */
- 0, /* Phy rates allowed initially */
-};
-
-static const struct ath_rate_table ar5416_11b_ratetable = {
- 4,
- {
- { VALID, VALID, WLAN_RC_PHY_CCK, 1000, /* 1 Mb */
- 900, 0x1b, 0x00, (0x80|2),
- 0, 0, 1, 0, 0 },
- { VALID, VALID, WLAN_RC_PHY_CCK, 2000, /* 2 Mb */
- 1800, 0x1a, 0x04, (0x80|4),
- 1, 1, 1, 1, 0 },
- { VALID, VALID, WLAN_RC_PHY_CCK, 5500, /* 5.5 Mb */
- 4300, 0x19, 0x04, (0x80|11),
- 1, 2, 2, 2, 0 },
- { VALID, VALID, WLAN_RC_PHY_CCK, 11000, /* 11 Mb */
- 7100, 0x18, 0x04, (0x80|22),
- 1, 4, 100, 3, 0 },
- },
- 100, /* probe interval */
- 100, /* rssi reduce interval */
0, /* Phy rates allowed initially */
};
@@ -454,13 +429,6 @@ static inline void ath_rc_set_valid_txmask(struct ath_rate_priv *ath_rc_priv,
ath_rc_priv->valid_rate_index[index] = valid_tx_rate ? 1 : 0;
}
-static inline int ath_rc_isvalid_txmask(struct ath_rate_priv *ath_rc_priv,
- u8 index)
-{
- ASSERT(index <= ath_rc_priv->rate_table_size);
- return ath_rc_priv->valid_rate_index[index];
-}
-
static inline
int ath_rc_get_nextvalid_txrate(const struct ath_rate_table *rate_table,
struct ath_rate_priv *ath_rc_priv,
@@ -495,15 +463,13 @@ static int ath_rc_valid_phyrate(u32 phy, u32 capflag, int ignore_cw)
if (!ignore_cw && WLAN_RC_PHY_HT(phy))
if (WLAN_RC_PHY_40(phy) && !(capflag & WLAN_RC_40_FLAG))
return 0;
- if (!WLAN_RC_PHY_40(phy) && (capflag & WLAN_RC_40_FLAG))
- return 0;
return 1;
}
static inline int
-ath_rc_get_nextlowervalid_txrate(const struct ath_rate_table *rate_table,
- struct ath_rate_priv *ath_rc_priv,
- u8 cur_valid_txrate, u8 *next_idx)
+ath_rc_get_lower_rix(const struct ath_rate_table *rate_table,
+ struct ath_rate_priv *ath_rc_priv,
+ u8 cur_valid_txrate, u8 *next_idx)
{
int8_t i;
@@ -629,52 +595,20 @@ static u8 ath_rc_setvalid_htrates(struct ath_rate_priv *ath_rc_priv,
return hi;
}
-static u8 ath_rc_ratefind_ht(struct ath_softc *sc,
- struct ath_rate_priv *ath_rc_priv,
- const struct ath_rate_table *rate_table,
- int *is_probing)
+/* Finds the highest rate index we can use */
+static u8 ath_rc_get_highest_rix(struct ath_softc *sc,
+ struct ath_rate_priv *ath_rc_priv,
+ const struct ath_rate_table *rate_table,
+ int *is_probing)
{
- u32 dt, best_thruput, this_thruput, now_msec;
+ u32 best_thruput, this_thruput, now_msec;
u8 rate, next_rate, best_rate, maxindex, minindex;
- int8_t rssi_last, rssi_reduce = 0, index = 0;
-
- *is_probing = 0;
-
- rssi_last = median(ath_rc_priv->rssi_last,
- ath_rc_priv->rssi_last_prev,
- ath_rc_priv->rssi_last_prev2);
-
- /*
- * Age (reduce) last ack rssi based on how old it is.
- * The bizarre numbers are so the delta is 160msec,
- * meaning we divide by 16.
- * 0msec <= dt <= 25msec: don't derate
- * 25msec <= dt <= 185msec: derate linearly from 0 to 10dB
- * 185msec <= dt: derate by 10dB
- */
+ int8_t index = 0;
now_msec = jiffies_to_msecs(jiffies);
- dt = now_msec - ath_rc_priv->rssi_time;
-
- if (dt >= 185)
- rssi_reduce = 10;
- else if (dt >= 25)
- rssi_reduce = (u8)((dt - 25) >> 4);
-
- /* Now reduce rssi_last by rssi_reduce */
- if (rssi_last < rssi_reduce)
- rssi_last = 0;
- else
- rssi_last -= rssi_reduce;
-
- /*
- * Now look up the rate in the rssi table and return it.
- * If no rates match then we return 0 (lowest rate)
- */
-
+ *is_probing = 0;
best_thruput = 0;
maxindex = ath_rc_priv->max_valid_rate-1;
-
minindex = 0;
best_rate = minindex;
@@ -700,7 +634,7 @@ static u8 ath_rc_ratefind_ht(struct ath_softc *sc,
* 10-15 and we would be worse off then staying
* at the current rate.
*/
- per_thres = ath_rc_priv->state[rate].per;
+ per_thres = ath_rc_priv->per[rate];
if (per_thres < 12)
per_thres = 12;
@@ -714,7 +648,6 @@ static u8 ath_rc_ratefind_ht(struct ath_softc *sc,
}
rate = best_rate;
- ath_rc_priv->rssi_last_lookup = rssi_last;
/*
* Must check the actual rate (ratekbps) to account for
@@ -741,10 +674,18 @@ static u8 ath_rc_ratefind_ht(struct ath_softc *sc,
if (rate > (ath_rc_priv->rate_table_size - 1))
rate = ath_rc_priv->rate_table_size - 1;
- ASSERT((rate_table->info[rate].valid &&
- (ath_rc_priv->ht_cap & WLAN_RC_DS_FLAG)) ||
- (rate_table->info[rate].valid_single_stream &&
- !(ath_rc_priv->ht_cap & WLAN_RC_DS_FLAG)));
+ if (rate_table->info[rate].valid &&
+ (ath_rc_priv->ht_cap & WLAN_RC_DS_FLAG))
+ return rate;
+
+ if (rate_table->info[rate].valid_single_stream &&
+ !(ath_rc_priv->ht_cap & WLAN_RC_DS_FLAG));
+ return rate;
+
+ /* This should not happen */
+ WARN_ON(1);
+
+ rate = ath_rc_priv->valid_rate_index[0];
return rate;
}
@@ -796,7 +737,6 @@ static void ath_rc_rate_set_rtscts(struct ath_softc *sc,
* just CTS. Note that this is only done for OFDM/HT unicast frames.
*/
if ((sc->sc_flags & SC_OP_PROTECT_ENABLE) &&
- !(tx_info->flags & IEEE80211_TX_CTL_NO_ACK) &&
(rate_table->info[rix].phy == WLAN_RC_PHY_OFDM ||
WLAN_RC_PHY_HT(rate_table->info[rix].phy))) {
rates[0].flags |= IEEE80211_TX_RC_USE_CTS_PROTECT;
@@ -806,50 +746,37 @@ static void ath_rc_rate_set_rtscts(struct ath_softc *sc,
tx_info->control.rts_cts_rate_idx = cix;
}
-static u8 ath_rc_rate_getidx(struct ath_softc *sc,
- struct ath_rate_priv *ath_rc_priv,
- const struct ath_rate_table *rate_table,
- u8 rix, u16 stepdown,
- u16 min_rate)
-{
- u32 j;
- u8 nextindex = 0;
-
- if (min_rate) {
- for (j = RATE_TABLE_SIZE; j > 0; j--) {
- if (ath_rc_get_nextlowervalid_txrate(rate_table,
- ath_rc_priv, rix, &nextindex))
- rix = nextindex;
- else
- break;
- }
- } else {
- for (j = stepdown; j > 0; j--) {
- if (ath_rc_get_nextlowervalid_txrate(rate_table,
- ath_rc_priv, rix, &nextindex))
- rix = nextindex;
- else
- break;
- }
- }
- return rix;
-}
-
-static void ath_rc_ratefind(struct ath_softc *sc,
- struct ath_rate_priv *ath_rc_priv,
- struct ieee80211_tx_rate_control *txrc)
+static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta,
+ struct ieee80211_tx_rate_control *txrc)
{
+ struct ath_softc *sc = priv;
+ struct ath_rate_priv *ath_rc_priv = priv_sta;
const struct ath_rate_table *rate_table;
struct sk_buff *skb = txrc->skb;
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
struct ieee80211_tx_rate *rates = tx_info->control.rates;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
__le16 fc = hdr->frame_control;
- u8 try_per_rate = 0, i = 0, rix, nrix;
+ u8 try_per_rate, i = 0, rix, nrix;
int is_probe = 0;
+ if (rate_control_send_low(sta, priv_sta, txrc))
+ return;
+
+ /*
+ * For Multi Rate Retry we use a different number of
+ * retry attempt counts. This ends up looking like this:
+ *
+ * MRR[0] = 2
+ * MRR[1] = 2
+ * MRR[2] = 2
+ * MRR[3] = 4
+ *
+ */
+ try_per_rate = sc->hw->max_rate_tries;
+
rate_table = sc->cur_rate_table;
- rix = ath_rc_ratefind_ht(sc, ath_rc_priv, rate_table, &is_probe);
+ rix = ath_rc_get_highest_rix(sc, ath_rc_priv, rate_table, &is_probe);
nrix = rix;
if (is_probe) {
@@ -858,18 +785,15 @@ static void ath_rc_ratefind(struct ath_softc *sc,
ath_rc_rate_set_series(rate_table, &rates[i++], txrc,
1, nrix, 0);
- try_per_rate = (ATH_11N_TXMAXTRY/4);
/* Get the next tried/allowed rate. No RTS for the next series
* after the probe rate
*/
- nrix = ath_rc_rate_getidx(sc, ath_rc_priv,
- rate_table, nrix, 1, 0);
+ ath_rc_get_lower_rix(rate_table, ath_rc_priv, rix, &nrix);
ath_rc_rate_set_series(rate_table, &rates[i++], txrc,
try_per_rate, nrix, 0);
tx_info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE;
} else {
- try_per_rate = (ATH_11N_TXMAXTRY/4);
/* Set the choosen rate. No RTS for first series entry. */
ath_rc_rate_set_series(rate_table, &rates[i++], txrc,
try_per_rate, nrix, 0);
@@ -877,18 +801,14 @@ static void ath_rc_ratefind(struct ath_softc *sc,
/* Fill in the other rates for multirate retry */
for ( ; i < 4; i++) {
- u8 try_num;
- u8 min_rate;
+ /* Use twice the number of tries for the last MRR segment. */
+ if (i + 1 == 4)
+ try_per_rate = 4;
- try_num = ((i + 1) == 4) ?
- ATH_11N_TXMAXTRY - (try_per_rate * i) : try_per_rate ;
- min_rate = (((i + 1) == 4) && 0);
-
- nrix = ath_rc_rate_getidx(sc, ath_rc_priv,
- rate_table, nrix, 1, min_rate);
+ ath_rc_get_lower_rix(rate_table, ath_rc_priv, rix, &nrix);
/* All other rates in the series have RTS enabled */
ath_rc_rate_set_series(rate_table, &rates[i], txrc,
- try_num, nrix, 1);
+ try_per_rate, nrix, 1);
}
/*
@@ -925,9 +845,8 @@ static void ath_rc_ratefind(struct ath_softc *sc,
*
* FIXME: Fix duration
*/
- if (!(tx_info->flags & IEEE80211_TX_CTL_NO_ACK) &&
- (ieee80211_has_morefrags(fc) ||
- (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG))) {
+ if (ieee80211_has_morefrags(fc) ||
+ (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG)) {
rates[1].count = rates[2].count = rates[3].count = 0;
rates[1].idx = rates[2].idx = rates[3].idx = 0;
rates[0].count = ATH_TXMAXTRY;
@@ -960,13 +879,13 @@ static bool ath_rc_update_per(struct ath_softc *sc,
100 * 9 / 10
};
- last_per = ath_rc_priv->state[tx_rate].per;
+ last_per = ath_rc_priv->per[tx_rate];
if (xretries) {
if (xretries == 1) {
- ath_rc_priv->state[tx_rate].per += 30;
- if (ath_rc_priv->state[tx_rate].per > 100)
- ath_rc_priv->state[tx_rate].per = 100;
+ ath_rc_priv->per[tx_rate] += 30;
+ if (ath_rc_priv->per[tx_rate] > 100)
+ ath_rc_priv->per[tx_rate] = 100;
} else {
/* xretries == 2 */
count = ARRAY_SIZE(nretry_to_per_lookup);
@@ -974,7 +893,7 @@ static bool ath_rc_update_per(struct ath_softc *sc,
retries = count - 1;
/* new_PER = 7/8*old_PER + 1/8*(currentPER) */
- ath_rc_priv->state[tx_rate].per =
+ ath_rc_priv->per[tx_rate] =
(u8)(last_per - (last_per >> 3) + (100 >> 3));
}
@@ -1010,18 +929,14 @@ static bool ath_rc_update_per(struct ath_softc *sc,
n_frames = tx_info_priv->n_frames * (retries + 1);
cur_per = (100 * n_bad_frames / n_frames) >> 3;
new_per = (u8)(last_per - (last_per >> 3) + cur_per);
- ath_rc_priv->state[tx_rate].per = new_per;
+ ath_rc_priv->per[tx_rate] = new_per;
}
} else {
- ath_rc_priv->state[tx_rate].per =
+ ath_rc_priv->per[tx_rate] =
(u8)(last_per - (last_per >> 3) +
(nretry_to_per_lookup[retries] >> 3));
}
- ath_rc_priv->rssi_last_prev2 = ath_rc_priv->rssi_last_prev;
- ath_rc_priv->rssi_last_prev = ath_rc_priv->rssi_last;
- ath_rc_priv->rssi_last = tx_info_priv->tx.ts_rssi;
- ath_rc_priv->rssi_time = now_msec;
/*
* If we got at most one retry then increase the max rate if
@@ -1045,8 +960,8 @@ static bool ath_rc_update_per(struct ath_softc *sc,
ath_rc_priv->probe_rate;
probe_rate = ath_rc_priv->probe_rate;
- if (ath_rc_priv->state[probe_rate].per > 30)
- ath_rc_priv->state[probe_rate].per = 20;
+ if (ath_rc_priv->per[probe_rate] > 30)
+ ath_rc_priv->per[probe_rate] = 20;
ath_rc_priv->probe_rate = 0;
@@ -1065,18 +980,9 @@ static bool ath_rc_update_per(struct ath_softc *sc,
/*
* Don't update anything. We don't know if
* this was because of collisions or poor signal.
- *
- * Later: if rssi_ack is close to
- * ath_rc_priv->state[txRate].rssi_thres and we see lots
- * of retries, then we could increase
- * ath_rc_priv->state[txRate].rssi_thres.
*/
ath_rc_priv->hw_maxretry_pktcnt = 0;
} else {
- int32_t rssi_ackAvg;
- int8_t rssi_thres;
- int8_t rssi_ack_vmin;
-
/*
* It worked with no retries. First ignore bogus (small)
* rssi_ack values.
@@ -1086,43 +992,9 @@ static bool ath_rc_update_per(struct ath_softc *sc,
ath_rc_priv->hw_maxretry_pktcnt++;
}
- if (tx_info_priv->tx.ts_rssi <
- rate_table->info[tx_rate].rssi_ack_validmin)
- goto exit;
-
- /* Average the rssi */
- if (tx_rate != ath_rc_priv->rssi_sum_rate) {
- ath_rc_priv->rssi_sum_rate = tx_rate;
- ath_rc_priv->rssi_sum =
- ath_rc_priv->rssi_sum_cnt = 0;
- }
-
- ath_rc_priv->rssi_sum += tx_info_priv->tx.ts_rssi;
- ath_rc_priv->rssi_sum_cnt++;
-
- if (ath_rc_priv->rssi_sum_cnt < 4)
- goto exit;
-
- rssi_ackAvg =
- (ath_rc_priv->rssi_sum + 2) / 4;
- rssi_thres =
- ath_rc_priv->state[tx_rate].rssi_thres;
- rssi_ack_vmin =
- rate_table->info[tx_rate].rssi_ack_validmin;
-
- ath_rc_priv->rssi_sum =
- ath_rc_priv->rssi_sum_cnt = 0;
-
- /* Now reduce the current rssi threshold */
- if ((rssi_ackAvg < rssi_thres + 2) &&
- (rssi_thres > rssi_ack_vmin)) {
- ath_rc_priv->state[tx_rate].rssi_thres--;
- }
-
- state_change = true;
}
}
-exit:
+
return state_change;
}
@@ -1134,11 +1006,6 @@ static void ath_rc_update_ht(struct ath_softc *sc,
struct ath_tx_info_priv *tx_info_priv,
int tx_rate, int xretries, int retries)
{
-#define CHK_RSSI(rate) \
- ((ath_rc_priv->state[(rate)].rssi_thres + \
- rate_table->info[(rate)].rssi_ack_deltamin) > \
- ath_rc_priv->state[(rate)+1].rssi_thres)
-
u32 now_msec = jiffies_to_msecs(jiffies);
int rate;
u8 last_per;
@@ -1149,14 +1016,7 @@ static void ath_rc_update_ht(struct ath_softc *sc,
if ((tx_rate < 0) || (tx_rate > rate_table->rate_cnt))
return;
- /* To compensate for some imbalance between ctrl and ext. channel */
-
- if (WLAN_RC_PHY_40(rate_table->info[tx_rate].phy))
- tx_info_priv->tx.ts_rssi =
- tx_info_priv->tx.ts_rssi < 3 ? 0 :
- tx_info_priv->tx.ts_rssi - 3;
-
- last_per = ath_rc_priv->state[tx_rate].per;
+ last_per = ath_rc_priv->per[tx_rate];
/* Update PER first */
state_change = ath_rc_update_per(sc, rate_table, ath_rc_priv,
@@ -1167,114 +1027,52 @@ static void ath_rc_update_ht(struct ath_softc *sc,
* If this rate looks bad (high PER) then stop using it for
* a while (except if we are probing).
*/
- if (ath_rc_priv->state[tx_rate].per >= 55 && tx_rate > 0 &&
+ if (ath_rc_priv->per[tx_rate] >= 55 && tx_rate > 0 &&
rate_table->info[tx_rate].ratekbps <=
rate_table->info[ath_rc_priv->rate_max_phy].ratekbps) {
- ath_rc_get_nextlowervalid_txrate(rate_table, ath_rc_priv,
- (u8)tx_rate, &ath_rc_priv->rate_max_phy);
+ ath_rc_get_lower_rix(rate_table, ath_rc_priv,
+ (u8)tx_rate, &ath_rc_priv->rate_max_phy);
/* Don't probe for a little while. */
ath_rc_priv->probe_time = now_msec;
}
- if (state_change) {
- /*
- * Make sure the rates above this have higher rssi thresholds.
- * (Note: Monotonicity is kept within the OFDM rates and
- * within the CCK rates. However, no adjustment is
- * made to keep the rssi thresholds monotonically
- * increasing between the CCK and OFDM rates.)
- */
- for (rate = tx_rate; rate < size - 1; rate++) {
- if (rate_table->info[rate+1].phy !=
- rate_table->info[tx_rate].phy)
- break;
-
- if (CHK_RSSI(rate)) {
- ath_rc_priv->state[rate+1].rssi_thres =
- ath_rc_priv->state[rate].rssi_thres +
- rate_table->info[rate].rssi_ack_deltamin;
- }
- }
-
- /* Make sure the rates below this have lower rssi thresholds. */
- for (rate = tx_rate - 1; rate >= 0; rate--) {
- if (rate_table->info[rate].phy !=
- rate_table->info[tx_rate].phy)
- break;
-
- if (CHK_RSSI(rate)) {
- if (ath_rc_priv->state[rate+1].rssi_thres <
- rate_table->info[rate].rssi_ack_deltamin)
- ath_rc_priv->state[rate].rssi_thres = 0;
- else {
- ath_rc_priv->state[rate].rssi_thres =
- ath_rc_priv->state[rate+1].rssi_thres -
- rate_table->info[rate].rssi_ack_deltamin;
- }
-
- if (ath_rc_priv->state[rate].rssi_thres <
- rate_table->info[rate].rssi_ack_validmin) {
- ath_rc_priv->state[rate].rssi_thres =
- rate_table->info[rate].rssi_ack_validmin;
- }
- }
- }
- }
-
/* Make sure the rates below this have lower PER */
/* Monotonicity is kept only for rates below the current rate. */
- if (ath_rc_priv->state[tx_rate].per < last_per) {
+ if (ath_rc_priv->per[tx_rate] < last_per) {
for (rate = tx_rate - 1; rate >= 0; rate--) {
- if (rate_table->info[rate].phy !=
- rate_table->info[tx_rate].phy)
- break;
- if (ath_rc_priv->state[rate].per >
- ath_rc_priv->state[rate+1].per) {
- ath_rc_priv->state[rate].per =
- ath_rc_priv->state[rate+1].per;
+ if (ath_rc_priv->per[rate] >
+ ath_rc_priv->per[rate+1]) {
+ ath_rc_priv->per[rate] =
+ ath_rc_priv->per[rate+1];
}
}
}
/* Maintain monotonicity for rates above the current rate */
for (rate = tx_rate; rate < size - 1; rate++) {
- if (ath_rc_priv->state[rate+1].per <
- ath_rc_priv->state[rate].per)
- ath_rc_priv->state[rate+1].per =
- ath_rc_priv->state[rate].per;
- }
-
- /* Every so often, we reduce the thresholds and
- * PER (different for CCK and OFDM). */
- if (now_msec - ath_rc_priv->rssi_down_time >=
- rate_table->rssi_reduce_interval) {
-
- for (rate = 0; rate < size; rate++) {
- if (ath_rc_priv->state[rate].rssi_thres >
- rate_table->info[rate].rssi_ack_validmin)
- ath_rc_priv->state[rate].rssi_thres -= 1;
- }
- ath_rc_priv->rssi_down_time = now_msec;
+ if (ath_rc_priv->per[rate+1] <
+ ath_rc_priv->per[rate])
+ ath_rc_priv->per[rate+1] =
+ ath_rc_priv->per[rate];
}
/* Every so often, we reduce the thresholds
* and PER (different for CCK and OFDM). */
if (now_msec - ath_rc_priv->per_down_time >=
- rate_table->rssi_reduce_interval) {
+ rate_table->probe_interval) {
for (rate = 0; rate < size; rate++) {
- ath_rc_priv->state[rate].per =
- 7 * ath_rc_priv->state[rate].per / 8;
+ ath_rc_priv->per[rate] =
+ 7 * ath_rc_priv->per[rate] / 8;
}
ath_rc_priv->per_down_time = now_msec;
}
ath_debug_stat_retries(sc, tx_rate, xretries, retries,
- ath_rc_priv->state[tx_rate].per);
+ ath_rc_priv->per[tx_rate]);
-#undef CHK_RSSI
}
static int ath_rc_get_rateindex(const struct ath_rate_table *rate_table,
@@ -1410,9 +1208,7 @@ static void ath_rc_init(struct ath_softc *sc,
/* Initialize thresholds according to the global rate table */
for (i = 0 ; i < ath_rc_priv->rate_table_size; i++) {
- ath_rc_priv->state[i].rssi_thres =
- rate_table->info[i].rssi_ack_validmin;
- ath_rc_priv->state[i].per = 0;
+ ath_rc_priv->per[i] = 0;
}
/* Determine the valid rates */
@@ -1521,7 +1317,7 @@ static void ath_tx_status(void *priv, struct ieee80211_supported_band *sband,
/*
* If underrun error is seen assume it as an excessive retry only
* if prefetch trigger level have reached the max (0x3f for 5416)
- * Adjust the long retry as if the frame was tried ATH_11N_TXMAXTRY
+ * Adjust the long retry as if the frame was tried hw->max_rate_tries
* times. This affects how ratectrl updates PER for the failed rate.
*/
if (tx_info_priv->tx.ts_flags &
@@ -1536,7 +1332,7 @@ static void ath_tx_status(void *priv, struct ieee80211_supported_band *sband,
tx_status = 1;
ath_rc_tx_status(sc, ath_rc_priv, tx_info, final_ts_idx, tx_status,
- (is_underrun) ? ATH_11N_TXMAXTRY :
+ (is_underrun) ? sc->hw->max_rate_tries :
tx_info_priv->tx.ts_longretry);
/* Check if aggregation has to be enabled for this tid */
@@ -1560,31 +1356,6 @@ exit:
kfree(tx_info_priv);
}
-static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta,
- struct ieee80211_tx_rate_control *txrc)
-{
- struct ieee80211_supported_band *sband = txrc->sband;
- struct sk_buff *skb = txrc->skb;
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
- struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
- struct ath_softc *sc = priv;
- struct ath_rate_priv *ath_rc_priv = priv_sta;
- __le16 fc = hdr->frame_control;
-
- /* lowest rate for management and NO_ACK frames */
- if (!ieee80211_is_data(fc) ||
- tx_info->flags & IEEE80211_TX_CTL_NO_ACK || !sta) {
- tx_info->control.rates[0].idx = rate_lowest_index(sband, sta);
- tx_info->control.rates[0].count =
- (tx_info->flags & IEEE80211_TX_CTL_NO_ACK) ?
- 1 : ATH_MGT_TXMAXTRY;
- return;
- }
-
- /* Find tx rate for unicast frames */
- ath_rc_ratefind(sc, ath_rc_priv, txrc);
-}
-
static void ath_rate_init(void *priv, struct ieee80211_supported_band *sband,
struct ieee80211_sta *sta, void *priv_sta)
{
@@ -1697,7 +1468,6 @@ static void *ath_rate_alloc_sta(void *priv, struct ieee80211_sta *sta, gfp_t gfp
return NULL;
}
- rate_priv->rssi_down_time = jiffies_to_msecs(jiffies);
rate_priv->tx_triglevel_max = sc->sc_ah->caps.tx_triglevel_max;
return rate_priv;
@@ -1725,8 +1495,6 @@ static struct rate_control_ops ath_rate_ops = {
void ath_rate_attach(struct ath_softc *sc)
{
- sc->hw_rate_table[ATH9K_MODE_11B] =
- &ar5416_11b_ratetable;
sc->hw_rate_table[ATH9K_MODE_11A] =
&ar5416_11a_ratetable;
sc->hw_rate_table[ATH9K_MODE_11G] =
diff --git a/drivers/net/wireless/ath/ath9k/rc.h b/drivers/net/wireless/ath/ath9k/rc.h
index e3abd76103f..fa21a628ddd 100644
--- a/drivers/net/wireless/ath/ath9k/rc.h
+++ b/drivers/net/wireless/ath/ath9k/rc.h
@@ -112,8 +112,6 @@ struct ath_rate_table {
u8 short_preamble;
u8 dot11rate;
u8 ctrl_rate;
- int8_t rssi_ack_validmin;
- int8_t rssi_ack_deltamin;
u8 base_index;
u8 cw40index;
u8 sgi_index;
@@ -121,15 +119,9 @@ struct ath_rate_table {
u32 max_4ms_framelen;
} info[RATE_TABLE_SIZE];
u32 probe_interval;
- u32 rssi_reduce_interval;
u8 initial_ratemax;
};
-struct ath_tx_ratectrl_state {
- int8_t rssi_thres; /* required rssi for this rate (dB) */
- u8 per; /* recent estimate of packet error rate (%) */
-};
-
struct ath_rateset {
u8 rs_nrates;
u8 rs_rates[ATH_RATE_MAX];
@@ -138,22 +130,14 @@ struct ath_rateset {
/**
* struct ath_rate_priv - Rate Control priv data
* @state: RC state
- * @rssi_last: last ACK rssi
- * @rssi_last_lookup: last ACK rssi used for lookup
- * @rssi_last_prev: previous last ACK rssi
- * @rssi_last_prev2: 2nd previous last ACK rssi
- * @rssi_sum_cnt: count of rssi_sum for averaging
- * @rssi_sum_rate: rate that we are averaging
- * @rssi_sum: running sum of rssi for averaging
* @probe_rate: rate we are probing at
- * @rssi_time: msec timestamp for last ack rssi
- * @rssi_down_time: msec timestamp for last down step
* @probe_time: msec timestamp for last probe
* @hw_maxretry_pktcnt: num of packets since we got HW max retry error
* @max_valid_rate: maximum number of valid rate
* @per_down_time: msec timestamp for last PER down step
* @valid_phy_ratecnt: valid rate count
* @rate_max_phy: phy index for the max rate
+ * @per: PER for every valid rate in %
* @probe_interval: interval for ratectrl to probe for other rates
* @prev_data_rix: rate idx of last data frame
* @ht_cap: HT capabilities
@@ -161,13 +145,6 @@ struct ath_rateset {
* @neg_ht_rates: Negotiated HT rates
*/
struct ath_rate_priv {
- int8_t rssi_last;
- int8_t rssi_last_lookup;
- int8_t rssi_last_prev;
- int8_t rssi_last_prev2;
- int32_t rssi_sum_cnt;
- int32_t rssi_sum_rate;
- int32_t rssi_sum;
u8 rate_table_size;
u8 probe_rate;
u8 hw_maxretry_pktcnt;
@@ -177,14 +154,12 @@ struct ath_rate_priv {
u8 valid_phy_ratecnt[WLAN_RC_PHY_MAX];
u8 valid_phy_rateidx[WLAN_RC_PHY_MAX][RATE_TABLE_SIZE];
u8 rate_max_phy;
- u32 rssi_time;
- u32 rssi_down_time;
+ u8 per[RATE_TABLE_SIZE];
u32 probe_time;
u32 per_down_time;
u32 probe_interval;
u32 prev_data_rix;
u32 tx_triglevel_max;
- struct ath_tx_ratectrl_state state[RATE_TABLE_SIZE];
struct ath_rateset neg_rates;
struct ath_rateset neg_ht_rates;
struct ath_rate_softc *asc;
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c
index cece1c4c6bd..61dbdd22744 100644
--- a/drivers/net/wireless/ath/ath9k/recv.c
+++ b/drivers/net/wireless/ath/ath9k/recv.c
@@ -100,38 +100,6 @@ static u64 ath_extend_tsf(struct ath_softc *sc, u32 rstamp)
return (tsf & ~0x7fff) | rstamp;
}
-static struct sk_buff *ath_rxbuf_alloc(struct ath_softc *sc, u32 len, gfp_t gfp_mask)
-{
- struct sk_buff *skb;
- u32 off;
-
- /*
- * Cache-line-align. This is important (for the
- * 5210 at least) as not doing so causes bogus data
- * in rx'd frames.
- */
-
- /* Note: the kernel can allocate a value greater than
- * what we ask it to give us. We really only need 4 KB as that
- * is this hardware supports and in fact we need at least 3849
- * as that is the MAX AMSDU size this hardware supports.
- * Unfortunately this means we may get 8 KB here from the
- * kernel... and that is actually what is observed on some
- * systems :( */
- skb = __dev_alloc_skb(len + sc->cachelsz - 1, gfp_mask);
- if (skb != NULL) {
- off = ((unsigned long) skb->data) % sc->cachelsz;
- if (off != 0)
- skb_reserve(skb, sc->cachelsz - off);
- } else {
- DPRINTF(sc, ATH_DBG_FATAL,
- "skbuff alloc of size %u failed\n", len);
- return NULL;
- }
-
- return skb;
-}
-
/*
* For Decrypt or Demic errors, we only mark packet status here and always push
* up the frame up to let mac80211 handle the actual error case, be it no
@@ -145,6 +113,10 @@ static int ath_rx_prepare(struct sk_buff *skb, struct ath_desc *ds,
u8 ratecode;
__le16 fc;
struct ieee80211_hw *hw;
+ struct ieee80211_sta *sta;
+ struct ath_node *an;
+ int last_rssi = ATH_RSSI_DUMMY_MARKER;
+
hdr = (struct ieee80211_hdr *)skb->data;
fc = hdr->frame_control;
@@ -229,17 +201,61 @@ static int ath_rx_prepare(struct sk_buff *skb, struct ath_desc *ds,
}
}
+ rcu_read_lock();
+ sta = ieee80211_find_sta(sc->hw, hdr->addr2);
+ if (sta) {
+ an = (struct ath_node *) sta->drv_priv;
+ if (ds->ds_rxstat.rs_rssi != ATH9K_RSSI_BAD &&
+ !ds->ds_rxstat.rs_moreaggr)
+ ATH_RSSI_LPF(an->last_rssi, ds->ds_rxstat.rs_rssi);
+ last_rssi = an->last_rssi;
+ }
+ rcu_read_unlock();
+
+ if (likely(last_rssi != ATH_RSSI_DUMMY_MARKER))
+ ds->ds_rxstat.rs_rssi = ATH_EP_RND(last_rssi,
+ ATH_RSSI_EP_MULTIPLIER);
+ if (ds->ds_rxstat.rs_rssi < 0)
+ ds->ds_rxstat.rs_rssi = 0;
+ else if (ds->ds_rxstat.rs_rssi > 127)
+ ds->ds_rxstat.rs_rssi = 127;
+
+ /* Update Beacon RSSI, this is used by ANI. */
+ if (ieee80211_is_beacon(fc))
+ sc->nodestats.ns_avgbrssi = ds->ds_rxstat.rs_rssi;
+
rx_status->mactime = ath_extend_tsf(sc, ds->ds_rxstat.rs_tstamp);
rx_status->band = hw->conf.channel->band;
rx_status->freq = hw->conf.channel->center_freq;
rx_status->noise = sc->ani.noise_floor;
- rx_status->signal = rx_status->noise + ds->ds_rxstat.rs_rssi;
+ rx_status->signal = ATH_DEFAULT_NOISE_FLOOR + ds->ds_rxstat.rs_rssi;
rx_status->antenna = ds->ds_rxstat.rs_antenna;
- /* at 45 you will be able to use MCS 15 reliably. A more elaborate
- * scheme can be used here but it requires tables of SNR/throughput for
- * each possible mode used. */
- rx_status->qual = ds->ds_rxstat.rs_rssi * 100 / 45;
+ /*
+ * Theory for reporting quality:
+ *
+ * At a hardware RSSI of 45 you will be able to use MCS 7 reliably.
+ * At a hardware RSSI of 45 you will be able to use MCS 15 reliably.
+ * At a hardware RSSI of 35 you should be able use 54 Mbps reliably.
+ *
+ * MCS 7 is the highets MCS index usable by a 1-stream device.
+ * MCS 15 is the highest MCS index usable by a 2-stream device.
+ *
+ * All ath9k devices are either 1-stream or 2-stream.
+ *
+ * How many bars you see is derived from the qual reporting.
+ *
+ * A more elaborate scheme can be used here but it requires tables
+ * of SNR/throughput for each possible mode used. For the MCS table
+ * you can refer to the wireless wiki:
+ *
+ * http://wireless.kernel.org/en/developers/Documentation/ieee80211/802.11n
+ *
+ */
+ if (conf_is_ht(&hw->conf))
+ rx_status->qual = ds->ds_rxstat.rs_rssi * 100 / 45;
+ else
+ rx_status->qual = ds->ds_rxstat.rs_rssi * 100 / 35;
/* rssi can be more than 45 though, anything above that
* should be considered at 100% */
@@ -288,10 +304,10 @@ int ath_rx_init(struct ath_softc *sc, int nbufs)
spin_lock_init(&sc->rx.rxbuflock);
sc->rx.bufsize = roundup(IEEE80211_MAX_MPDU_LEN,
- min(sc->cachelsz, (u16)64));
+ min(sc->common.cachelsz, (u16)64));
DPRINTF(sc, ATH_DBG_CONFIG, "cachelsz %u rxbufsize %u\n",
- sc->cachelsz, sc->rx.bufsize);
+ sc->common.cachelsz, sc->rx.bufsize);
/* Initialize rx descriptors */
@@ -304,7 +320,7 @@ int ath_rx_init(struct ath_softc *sc, int nbufs)
}
list_for_each_entry(bf, &sc->rx.rxbuf, list) {
- skb = ath_rxbuf_alloc(sc, sc->rx.bufsize, GFP_KERNEL);
+ skb = ath_rxbuf_alloc(&sc->common, sc->rx.bufsize, GFP_KERNEL);
if (skb == NULL) {
error = -ENOMEM;
goto err;
@@ -404,8 +420,7 @@ u32 ath_calcrxfilter(struct ath_softc *sc)
else
rfilt |= ATH9K_RX_FILTER_BEACON;
- /* If in HOSTAP mode, want to enable reception of PSPOLL frames */
- if (sc->sc_ah->opmode == NL80211_IFTYPE_AP)
+ if (sc->rx.rxfilter & FIF_PSPOLL)
rfilt |= ATH9K_RX_FILTER_PSPOLL;
if (sc->sec_wiphy) {
@@ -505,11 +520,6 @@ static bool ath_beacon_dtim_pending_cab(struct sk_buff *skb)
return false;
}
-static void ath_rx_ps_back_to_sleep(struct ath_softc *sc)
-{
- sc->sc_flags &= ~(SC_OP_WAIT_FOR_BEACON | SC_OP_WAIT_FOR_CAB);
-}
-
static void ath_rx_ps_beacon(struct ath_softc *sc, struct sk_buff *skb)
{
struct ieee80211_mgmt *mgmt;
@@ -521,6 +531,8 @@ static void ath_rx_ps_beacon(struct ath_softc *sc, struct sk_buff *skb)
if (memcmp(sc->curbssid, mgmt->bssid, ETH_ALEN) != 0)
return; /* not from our current AP */
+ sc->sc_flags &= ~SC_OP_WAIT_FOR_BEACON;
+
if (sc->sc_flags & SC_OP_BEACON_SYNC) {
sc->sc_flags &= ~SC_OP_BEACON_SYNC;
DPRINTF(sc, ATH_DBG_PS, "Reconfigure Beacon timers based on "
@@ -528,14 +540,6 @@ static void ath_rx_ps_beacon(struct ath_softc *sc, struct sk_buff *skb)
ath_beacon_config(sc, NULL);
}
- if (!(sc->hw->conf.flags & IEEE80211_CONF_PS)) {
- /* We are not in PS mode anymore; remain awake */
- DPRINTF(sc, ATH_DBG_PS, "Not in PS mode anymore, remain "
- "awake\n");
- sc->sc_flags &= ~(SC_OP_WAIT_FOR_BEACON | SC_OP_WAIT_FOR_CAB);
- return;
- }
-
if (ath_beacon_dtim_pending_cab(skb)) {
/*
* Remain awake waiting for buffered broadcast/multicast
@@ -556,11 +560,9 @@ static void ath_rx_ps_beacon(struct ath_softc *sc, struct sk_buff *skb)
* fails to send a frame indicating that all CAB frames have
* been delivered.
*/
+ sc->sc_flags &= ~SC_OP_WAIT_FOR_CAB;
DPRINTF(sc, ATH_DBG_PS, "PS wait for CAB frames timed out\n");
}
-
- /* No more broadcast/multicast frames to be received at this point. */
- ath_rx_ps_back_to_sleep(sc);
}
static void ath_rx_ps(struct ath_softc *sc, struct sk_buff *skb)
@@ -578,13 +580,13 @@ static void ath_rx_ps(struct ath_softc *sc, struct sk_buff *skb)
ieee80211_is_action(hdr->frame_control)) &&
is_multicast_ether_addr(hdr->addr1) &&
!ieee80211_has_moredata(hdr->frame_control)) {
- DPRINTF(sc, ATH_DBG_PS, "All PS CAB frames received, back to "
- "sleep\n");
/*
* No more broadcast/multicast frames to be received at this
* point.
*/
- ath_rx_ps_back_to_sleep(sc);
+ sc->sc_flags &= ~SC_OP_WAIT_FOR_CAB;
+ DPRINTF(sc, ATH_DBG_PS, "All PS CAB frames received, back to "
+ "sleep\n");
} else if ((sc->sc_flags & SC_OP_WAIT_FOR_PSPOLL_DATA) &&
!is_multicast_ether_addr(hdr->addr1) &&
!ieee80211_has_morefrags(hdr->frame_control)) {
@@ -619,13 +621,18 @@ static void ath_rx_send_to_mac80211(struct ath_softc *sc, struct sk_buff *skb,
if (aphy == NULL)
continue;
nskb = skb_copy(skb, GFP_ATOMIC);
- if (nskb)
- __ieee80211_rx(aphy->hw, nskb, rx_status);
+ if (nskb) {
+ memcpy(IEEE80211_SKB_RXCB(nskb), rx_status,
+ sizeof(*rx_status));
+ ieee80211_rx(aphy->hw, nskb);
+ }
}
- __ieee80211_rx(sc->hw, skb, rx_status);
+ memcpy(IEEE80211_SKB_RXCB(skb), rx_status, sizeof(*rx_status));
+ ieee80211_rx(sc->hw, skb);
} else {
/* Deliver unicast frames based on receiver address */
- __ieee80211_rx(ath_get_virt_hw(sc, hdr), skb, rx_status);
+ memcpy(IEEE80211_SKB_RXCB(skb), rx_status, sizeof(*rx_status));
+ ieee80211_rx(ath_get_virt_hw(sc, hdr), skb);
}
}
@@ -738,7 +745,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush)
/* Ensure we always have an skb to requeue once we are done
* processing the current buffer's skb */
- requeue_skb = ath_rxbuf_alloc(sc, sc->rx.bufsize, GFP_ATOMIC);
+ requeue_skb = ath_rxbuf_alloc(&sc->common, sc->rx.bufsize, GFP_ATOMIC);
/* If there is no memory we ignore the current RX'd frame,
* tell hardware it can give us a new frame using the old
@@ -753,7 +760,6 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush)
DMA_FROM_DEVICE);
skb_put(skb, ds->ds_rxstat.rs_datalen);
- skb->protocol = cpu_to_be16(ETH_P_CONTROL);
/* see if any padding is done by the hw and remove it */
hdr = (struct ieee80211_hdr *)skb->data;
diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h
index 52605246679..13fd658b5d3 100644
--- a/drivers/net/wireless/ath/ath9k/reg.h
+++ b/drivers/net/wireless/ath/ath9k/reg.h
@@ -574,6 +574,7 @@
#define AR_D_GBL_IFS_SIFS 0x1030
#define AR_D_GBL_IFS_SIFS_M 0x0000FFFF
+#define AR_D_GBL_IFS_SIFS_ASYNC_FIFO_DUR 0x000003AB
#define AR_D_GBL_IFS_SIFS_RESV0 0xFFFFFFFF
#define AR_D_TXBLK_BASE 0x1038
@@ -589,10 +590,12 @@
#define AR_D_GBL_IFS_SLOT 0x1070
#define AR_D_GBL_IFS_SLOT_M 0x0000FFFF
#define AR_D_GBL_IFS_SLOT_RESV0 0xFFFF0000
+#define AR_D_GBL_IFS_SLOT_ASYNC_FIFO_DUR 0x00000420
#define AR_D_GBL_IFS_EIFS 0x10b0
#define AR_D_GBL_IFS_EIFS_M 0x0000FFFF
#define AR_D_GBL_IFS_EIFS_RESV0 0xFFFF0000
+#define AR_D_GBL_IFS_EIFS_ASYNC_FIFO_DUR 0x0000A5EB
#define AR_D_GBL_IFS_MISC 0x10f0
#define AR_D_GBL_IFS_MISC_LFSR_SLICE_SEL 0x00000007
@@ -738,6 +741,12 @@
#define AR_SREV_REVISION_9285_10 0
#define AR_SREV_REVISION_9285_11 1
#define AR_SREV_REVISION_9285_12 2
+#define AR_SREV_VERSION_9287 0x180
+#define AR_SREV_REVISION_9287_10 0
+#define AR_SREV_REVISION_9287_11 1
+#define AR_SREV_VERSION_9271 0x140
+#define AR_SREV_REVISION_9271_10 0
+#define AR_SREV_REVISION_9271_11 1
#define AR_SREV_5416(_ah) \
(((_ah)->hw_version.macVersion == AR_SREV_VERSION_5416_PCI) || \
@@ -794,6 +803,30 @@
(AR_SREV_9285(ah) && ((_ah)->hw_version.macRev >= \
AR_SREV_REVISION_9285_12)))
+#define AR_SREV_9287(_ah) \
+ (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9287))
+#define AR_SREV_9287_10_OR_LATER(_ah) \
+ (((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9287))
+#define AR_SREV_9287_10(_ah) \
+ (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9287) && \
+ ((_ah)->hw_version.macRev == AR_SREV_REVISION_9287_10))
+#define AR_SREV_9287_11(_ah) \
+ (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9287) && \
+ ((_ah)->hw_version.macRev == AR_SREV_REVISION_9287_11))
+#define AR_SREV_9287_11_OR_LATER(_ah) \
+ (((_ah)->hw_version.macVersion > AR_SREV_VERSION_9287) || \
+ (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9287) && \
+ ((_ah)->hw_version.macRev >= AR_SREV_REVISION_9287_11)))
+
+#define AR_SREV_9271(_ah) \
+ (((_ah))->hw_version.macVersion == AR_SREV_VERSION_9271)
+#define AR_SREV_9271_10(_ah) \
+ (AR_SREV_9271(_ah) && \
+ ((_ah)->hw_version.macRev == AR_SREV_REVISION_9271_10))
+#define AR_SREV_9271_11(_ah) \
+ (AR_SREV_9271(_ah) && \
+ ((_ah)->hw_version.macRev == AR_SREV_REVISION_9271_11))
+
#define AR_RADIO_SREV_MAJOR 0xf0
#define AR_RAD5133_SREV_MAJOR 0xc0
#define AR_RAD2133_SREV_MAJOR 0xd0
@@ -809,6 +842,9 @@
#define AR_AHB_PAGE_SIZE_1K 0x00000000
#define AR_AHB_PAGE_SIZE_2K 0x00000008
#define AR_AHB_PAGE_SIZE_4K 0x00000010
+#define AR_AHB_CUSTOM_BURST_EN 0x000000C0
+#define AR_AHB_CUSTOM_BURST_EN_S 6
+#define AR_AHB_CUSTOM_BURST_ASYNC_FIFO_VAL 3
#define AR_INTR_RTC_IRQ 0x00000001
#define AR_INTR_MAC_IRQ 0x00000002
@@ -885,6 +921,7 @@ enum {
#define AR_NUM_GPIO 14
#define AR928X_NUM_GPIO 10
#define AR9285_NUM_GPIO 12
+#define AR9287_NUM_GPIO 11
#define AR_GPIO_IN_OUT 0x4048
#define AR_GPIO_IN_VAL 0x0FFFC000
@@ -893,6 +930,8 @@ enum {
#define AR928X_GPIO_IN_VAL_S 10
#define AR9285_GPIO_IN_VAL 0x00FFF000
#define AR9285_GPIO_IN_VAL_S 12
+#define AR9287_GPIO_IN_VAL 0x003FF800
+#define AR9287_GPIO_IN_VAL_S 11
#define AR_GPIO_OE_OUT 0x404c
#define AR_GPIO_OE_OUT_DRV 0x3
@@ -1115,12 +1154,32 @@ enum {
#define AR9285_AN_RF2G4_DB2_4 0x00003800
#define AR9285_AN_RF2G4_DB2_4_S 11
+/* AR9271 : 0x7828, 0x782c different setting from AR9285 */
+#define AR9271_AN_RF2G3_OB_cck 0x001C0000
+#define AR9271_AN_RF2G3_OB_cck_S 18
+#define AR9271_AN_RF2G3_OB_psk 0x00038000
+#define AR9271_AN_RF2G3_OB_psk_S 15
+#define AR9271_AN_RF2G3_OB_qam 0x00007000
+#define AR9271_AN_RF2G3_OB_qam_S 12
+
+#define AR9271_AN_RF2G3_DB_1 0x00E00000
+#define AR9271_AN_RF2G3_DB_1_S 21
+
+#define AR9271_AN_RF2G3_CCOMP 0xFFF
+#define AR9271_AN_RF2G3_CCOMP_S 0
+
+#define AR9271_AN_RF2G4_DB_2 0xE0000000
+#define AR9271_AN_RF2G4_DB_2_S 29
+
#define AR9285_AN_RF2G6 0x7834
#define AR9285_AN_RF2G6_CCOMP 0x00007800
#define AR9285_AN_RF2G6_CCOMP_S 11
#define AR9285_AN_RF2G6_OFFS 0x03f00000
#define AR9285_AN_RF2G6_OFFS_S 20
+#define AR9271_AN_RF2G6_OFFS 0x07f00000
+#define AR9271_AN_RF2G6_OFFS_S 20
+
#define AR9285_AN_RF2G7 0x7838
#define AR9285_AN_RF2G7_PWDDB 0x00000002
#define AR9285_AN_RF2G7_PWDDB_S 1
@@ -1154,6 +1213,38 @@ enum {
#define AR9285_AN_TOP4 0x7870
#define AR9285_AN_TOP4_DEFAULT 0x10142c00
+#define AR9287_AN_RF2G3_CH0 0x7808
+#define AR9287_AN_RF2G3_CH1 0x785c
+#define AR9287_AN_RF2G3_DB1 0xE0000000
+#define AR9287_AN_RF2G3_DB1_S 29
+#define AR9287_AN_RF2G3_DB2 0x1C000000
+#define AR9287_AN_RF2G3_DB2_S 26
+#define AR9287_AN_RF2G3_OB_CCK 0x03800000
+#define AR9287_AN_RF2G3_OB_CCK_S 23
+#define AR9287_AN_RF2G3_OB_PSK 0x00700000
+#define AR9287_AN_RF2G3_OB_PSK_S 20
+#define AR9287_AN_RF2G3_OB_QAM 0x000E0000
+#define AR9287_AN_RF2G3_OB_QAM_S 17
+#define AR9287_AN_RF2G3_OB_PAL_OFF 0x0001C000
+#define AR9287_AN_RF2G3_OB_PAL_OFF_S 14
+
+#define AR9287_AN_TXPC0 0x7898
+#define AR9287_AN_TXPC0_TXPCMODE 0x0000C000
+#define AR9287_AN_TXPC0_TXPCMODE_S 14
+#define AR9287_AN_TXPC0_TXPCMODE_NORMAL 0
+#define AR9287_AN_TXPC0_TXPCMODE_TEST 1
+#define AR9287_AN_TXPC0_TXPCMODE_TEMPSENSE 2
+#define AR9287_AN_TXPC0_TXPCMODE_ATBTEST 3
+
+#define AR9287_AN_TOP2 0x78b4
+#define AR9287_AN_TOP2_XPABIAS_LVL 0xC0000000
+#define AR9287_AN_TOP2_XPABIAS_LVL_S 30
+
+/* AR9271 specific stuff */
+#define AR9271_RESET_POWER_DOWN_CONTROL 0x50044
+#define AR9271_RADIO_RF_RST 0x20
+#define AR9271_GATE_MAC_CTL 0x4000
+
#define AR_STA_ID0 0x8000
#define AR_STA_ID1 0x8004
#define AR_STA_ID1_SADH_MASK 0x0000FFFF
@@ -1188,6 +1279,7 @@ enum {
#define AR_TIME_OUT_ACK_S 0
#define AR_TIME_OUT_CTS 0x3FFF0000
#define AR_TIME_OUT_CTS_S 16
+#define AR_TIME_OUT_ACK_CTS_ASYNC_FIFO_DUR 0x16001D56
#define AR_RSSI_THR 0x8018
#define AR_RSSI_THR_MASK 0x000000FF
@@ -1203,6 +1295,7 @@ enum {
#define AR_USEC_TX_LAT_S 14
#define AR_USEC_RX_LAT 0x1F800000
#define AR_USEC_RX_LAT_S 23
+#define AR_USEC_ASYNC_FIFO_DUR 0x12e00074
#define AR_RESET_TSF 0x8020
#define AR_RESET_TSF_ONCE 0x01000000
@@ -1468,6 +1561,10 @@ enum {
#define AR_SLP_MIB_CLEAR 0x00000001
#define AR_SLP_MIB_PENDING 0x00000002
+#define AR_MAC_PCU_LOGIC_ANALYZER 0x8264
+#define AR_MAC_PCU_LOGIC_ANALYZER_DISBUG20768 0x20000000
+
+
#define AR_2040_MODE 0x8318
#define AR_2040_JOINED_RX_CLEAR 0x00000001
@@ -1485,6 +1582,39 @@ enum {
#define AR_PCU_MISC_MODE2_MGMT_CRYPTO_ENABLE 0x00000002
#define AR_PCU_MISC_MODE2_NO_CRYPTO_FOR_NON_DATA_PKT 0x00000004
+#define AR_PCU_MISC_MODE2_RESERVED 0x00000038
+#define AR_PCU_MISC_MODE2_ADHOC_MCAST_KEYID_ENABLE 0x00000040
+#define AR_PCU_MISC_MODE2_CFP_IGNORE 0x00000080
+#define AR_PCU_MISC_MODE2_MGMT_QOS 0x0000FF00
+#define AR_PCU_MISC_MODE2_MGMT_QOS_S 8
+#define AR_PCU_MISC_MODE2_ENABLE_LOAD_NAV_BEACON_DURATION 0x00010000
+#define AR_PCU_MISC_MODE2_ENABLE_AGGWEP 0x00020000
+#define AR_PCU_MISC_MODE2_HWWAR1 0x00100000
+#define AR_PCU_MISC_MODE2_HWWAR2 0x02000000
+#define AR_PCU_MISC_MODE2_RESERVED2 0xFFFE0000
+
+#define AR_MAC_PCU_ASYNC_FIFO_REG3 0x8358
+#define AR_MAC_PCU_ASYNC_FIFO_REG3_DATAPATH_SEL 0x00000400
+#define AR_MAC_PCU_ASYNC_FIFO_REG3_SOFT_RESET 0x80000000
+
+
+#define AR_AES_MUTE_MASK0 0x805c
+#define AR_AES_MUTE_MASK0_FC 0x0000FFFF
+#define AR_AES_MUTE_MASK0_QOS 0xFFFF0000
+#define AR_AES_MUTE_MASK0_QOS_S 16
+
+#define AR_AES_MUTE_MASK1 0x8060
+#define AR_AES_MUTE_MASK1_SEQ 0x0000FFFF
+#define AR_AES_MUTE_MASK1_SEQ_S 0
+#define AR_AES_MUTE_MASK1_FC_MGMT 0xFFFF0000
+#define AR_AES_MUTE_MASK1_FC_MGMT_S 16
+
+#define AR_RATE_DURATION_0 0x8700
+#define AR_RATE_DURATION_31 0x87CC
+#define AR_RATE_DURATION_32 0x8780
+#define AR_RATE_DURATION(_n) (AR_RATE_DURATION_0 + ((_n)<<2))
+
+
#define AR_KEYTABLE_0 0x8800
#define AR_KEYTABLE(_n) (AR_KEYTABLE_0 + ((_n)*32))
#define AR_KEY_CACHE_SIZE 128
diff --git a/drivers/net/wireless/ath/ath9k/virtual.c b/drivers/net/wireless/ath/ath9k/virtual.c
index 1ff429b027d..19b88f8177f 100644
--- a/drivers/net/wireless/ath/ath9k/virtual.c
+++ b/drivers/net/wireless/ath/ath9k/virtual.c
@@ -351,7 +351,7 @@ void ath9k_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
* Drop from tasklet to work to allow mutex for channel
* change.
*/
- queue_work(aphy->sc->hw->workqueue,
+ ieee80211_queue_work(aphy->sc->hw,
&aphy->sc->chan_work);
}
}
@@ -367,7 +367,7 @@ static void ath9k_mark_paused(struct ath_wiphy *aphy)
struct ath_softc *sc = aphy->sc;
aphy->state = ATH_WIPHY_PAUSED;
if (!__ath9k_wiphy_pausing(sc))
- queue_work(sc->hw->workqueue, &sc->chan_work);
+ ieee80211_queue_work(sc->hw, &sc->chan_work);
}
static void ath9k_pause_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
@@ -521,7 +521,7 @@ int ath9k_wiphy_select(struct ath_wiphy *aphy)
spin_unlock_bh(&sc->wiphy_lock);
ath_radio_disable(sc);
ath_radio_enable(sc);
- queue_work(aphy->sc->hw->workqueue,
+ ieee80211_queue_work(aphy->sc->hw,
&aphy->sc->chan_work);
return -EBUSY; /* previous select still in progress */
}
@@ -541,7 +541,7 @@ int ath9k_wiphy_select(struct ath_wiphy *aphy)
if (now) {
/* Ready to request channel change immediately */
- queue_work(aphy->sc->hw->workqueue, &aphy->sc->chan_work);
+ ieee80211_queue_work(aphy->sc->hw, &aphy->sc->chan_work);
}
/*
@@ -648,8 +648,9 @@ try_again:
"change\n");
}
- queue_delayed_work(sc->hw->workqueue, &sc->wiphy_work,
- sc->wiphy_scheduler_int);
+ ieee80211_queue_delayed_work(sc->hw,
+ &sc->wiphy_work,
+ sc->wiphy_scheduler_int);
}
void ath9k_wiphy_set_scheduler(struct ath_softc *sc, unsigned int msec_int)
@@ -657,6 +658,23 @@ void ath9k_wiphy_set_scheduler(struct ath_softc *sc, unsigned int msec_int)
cancel_delayed_work_sync(&sc->wiphy_work);
sc->wiphy_scheduler_int = msecs_to_jiffies(msec_int);
if (sc->wiphy_scheduler_int)
- queue_delayed_work(sc->hw->workqueue, &sc->wiphy_work,
- sc->wiphy_scheduler_int);
+ ieee80211_queue_delayed_work(sc->hw, &sc->wiphy_work,
+ sc->wiphy_scheduler_int);
+}
+
+/* caller must hold wiphy_lock */
+bool ath9k_all_wiphys_idle(struct ath_softc *sc)
+{
+ unsigned int i;
+ if (sc->pri_wiphy->state != ATH_WIPHY_INACTIVE) {
+ return false;
+ }
+ for (i = 0; i < sc->num_sec_wiphy; i++) {
+ struct ath_wiphy *aphy = sc->sec_wiphy[i];
+ if (!aphy)
+ continue;
+ if (aphy->state != ATH_WIPHY_INACTIVE)
+ return false;
+ }
+ return true;
}
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
index 4ccf48e396d..87762da0383 100644
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -59,6 +59,7 @@ static void ath_tx_send_ht_normal(struct ath_softc *sc, struct ath_txq *txq,
struct ath_atx_tid *tid,
struct list_head *bf_head);
static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
+ struct ath_txq *txq,
struct list_head *bf_q,
int txok, int sendbar);
static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq,
@@ -73,18 +74,6 @@ static void ath_tx_rc_status(struct ath_buf *bf, struct ath_desc *ds,
/* Aggregation logic */
/*********************/
-static int ath_aggr_query(struct ath_softc *sc, struct ath_node *an, u8 tidno)
-{
- struct ath_atx_tid *tid;
- tid = ATH_AN_2_TID(an, tidno);
-
- if (tid->state & AGGR_ADDBA_COMPLETE ||
- tid->state & AGGR_ADDBA_PROGRESS)
- return 1;
- else
- return 0;
-}
-
static void ath_tx_queue_tid(struct ath_txq *txq, struct ath_atx_tid *tid)
{
struct ath_atx_ac *ac = tid->ac;
@@ -224,7 +213,7 @@ static void ath_tid_drain(struct ath_softc *sc, struct ath_txq *txq,
ath_tx_update_baw(sc, tid, bf->bf_seqno);
spin_unlock(&txq->axq_lock);
- ath_tx_complete_buf(sc, bf, &bf_head, 0, 0);
+ ath_tx_complete_buf(sc, bf, txq, &bf_head, 0, 0);
spin_lock(&txq->axq_lock);
}
@@ -232,13 +221,15 @@ static void ath_tid_drain(struct ath_softc *sc, struct ath_txq *txq,
tid->baw_tail = tid->baw_head;
}
-static void ath_tx_set_retry(struct ath_softc *sc, struct ath_buf *bf)
+static void ath_tx_set_retry(struct ath_softc *sc, struct ath_txq *txq,
+ struct ath_buf *bf)
{
struct sk_buff *skb;
struct ieee80211_hdr *hdr;
bf->bf_state.bf_type |= BUF_RETRY;
bf->bf_retries++;
+ TX_STAT_INC(txq->axq_qnum, a_retries);
skb = bf->bf_mpdu;
hdr = (struct ieee80211_hdr *)skb->data;
@@ -250,7 +241,10 @@ static struct ath_buf* ath_clone_txbuf(struct ath_softc *sc, struct ath_buf *bf)
struct ath_buf *tbf;
spin_lock_bh(&sc->tx.txbuflock);
- ASSERT(!list_empty((&sc->tx.txbuf)));
+ if (WARN_ON(list_empty(&sc->tx.txbuf))) {
+ spin_unlock_bh(&sc->tx.txbuflock);
+ return NULL;
+ }
tbf = list_first_entry(&sc->tx.txbuf, struct ath_buf, list);
list_del(&tbf->list);
spin_unlock_bh(&sc->tx.txbuflock);
@@ -337,7 +331,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
if (!(tid->state & AGGR_CLEANUP) &&
ds->ds_txstat.ts_flags != ATH9K_TX_SW_ABORTED) {
if (bf->bf_retries < ATH_MAX_SW_RETRIES) {
- ath_tx_set_retry(sc, bf);
+ ath_tx_set_retry(sc, txq, bf);
txpending = 1;
} else {
bf->bf_state.bf_type |= BUF_XRETRY;
@@ -384,13 +378,31 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
ath_tx_rc_status(bf, ds, nbad, txok, false);
}
- ath_tx_complete_buf(sc, bf, &bf_head, !txfail, sendbar);
+ ath_tx_complete_buf(sc, bf, txq, &bf_head, !txfail, sendbar);
} else {
/* retry the un-acked ones */
if (bf->bf_next == NULL && bf_last->bf_stale) {
struct ath_buf *tbf;
tbf = ath_clone_txbuf(sc, bf_last);
+ /*
+ * Update tx baw and complete the frame with
+ * failed status if we run out of tx buf
+ */
+ if (!tbf) {
+ spin_lock_bh(&txq->axq_lock);
+ ath_tx_update_baw(sc, tid,
+ bf->bf_seqno);
+ spin_unlock_bh(&txq->axq_lock);
+
+ bf->bf_state.bf_type |= BUF_XRETRY;
+ ath_tx_rc_status(bf, ds, nbad,
+ 0, false);
+ ath_tx_complete_buf(sc, bf, txq,
+ &bf_head, 0, 0);
+ break;
+ }
+
ath9k_hw_cleartxdesc(sc->sc_ah, tbf->bf_desc);
list_add_tail(&tbf->list, &bf_head);
} else {
@@ -414,7 +426,6 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
if (tid->state & AGGR_CLEANUP) {
if (tid->baw_head == tid->baw_tail) {
tid->state &= ~AGGR_ADDBA_COMPLETE;
- tid->addba_exchangeattempts = 0;
tid->state &= ~AGGR_CLEANUP;
/* send buffered frames as singles */
@@ -447,7 +458,7 @@ static u32 ath_lookup_rate(struct ath_softc *sc, struct ath_buf *bf,
struct ieee80211_tx_rate *rates;
struct ath_tx_info_priv *tx_info_priv;
u32 max_4ms_framelen, frmlen;
- u16 aggr_limit, legacy = 0, maxampdu;
+ u16 aggr_limit, legacy = 0;
int i;
skb = bf->bf_mpdu;
@@ -482,16 +493,15 @@ static u32 ath_lookup_rate(struct ath_softc *sc, struct ath_buf *bf,
if (tx_info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE || legacy)
return 0;
- aggr_limit = min(max_4ms_framelen, (u32)ATH_AMPDU_LIMIT_DEFAULT);
+ aggr_limit = min(max_4ms_framelen, (u32)ATH_AMPDU_LIMIT_MAX);
/*
* h/w can accept aggregates upto 16 bit lengths (65535).
* The IE, however can hold upto 65536, which shows up here
* as zero. Ignore 65536 since we are constrained by hw.
*/
- maxampdu = tid->an->maxampdu;
- if (maxampdu)
- aggr_limit = min(aggr_limit, maxampdu);
+ if (tid->an->maxampdu)
+ aggr_limit = min(aggr_limit, tid->an->maxampdu);
return aggr_limit;
}
@@ -499,7 +509,6 @@ static u32 ath_lookup_rate(struct ath_softc *sc, struct ath_buf *bf,
/*
* Returns the number of delimiters to be added to
* meet the minimum required mpdudensity.
- * caller should make sure that the rate is HT rate .
*/
static int ath_compute_num_delims(struct ath_softc *sc, struct ath_atx_tid *tid,
struct ath_buf *bf, u16 frmlen)
@@ -507,7 +516,7 @@ static int ath_compute_num_delims(struct ath_softc *sc, struct ath_atx_tid *tid,
const struct ath_rate_table *rt = sc->cur_rate_table;
struct sk_buff *skb = bf->bf_mpdu;
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
- u32 nsymbits, nsymbols, mpdudensity;
+ u32 nsymbits, nsymbols;
u16 minlen;
u8 rc, flags, rix;
int width, half_gi, ndelim, mindelim;
@@ -529,14 +538,12 @@ static int ath_compute_num_delims(struct ath_softc *sc, struct ath_atx_tid *tid,
* on highest rate in rate series (i.e. first rate) to determine
* required minimum length for subframe. Take into account
* whether high rate is 20 or 40Mhz and half or full GI.
- */
- mpdudensity = tid->an->mpdudensity;
-
- /*
+ *
* If there is no mpdu density restriction, no further calculation
* is needed.
*/
- if (mpdudensity == 0)
+
+ if (tid->an->mpdudensity == 0)
return ndelim;
rix = tx_info->control.rates[0].idx;
@@ -546,9 +553,9 @@ static int ath_compute_num_delims(struct ath_softc *sc, struct ath_atx_tid *tid,
half_gi = (flags & IEEE80211_TX_RC_SHORT_GI) ? 1 : 0;
if (half_gi)
- nsymbols = NUM_SYMBOLS_PER_USEC_HALFGI(mpdudensity);
+ nsymbols = NUM_SYMBOLS_PER_USEC_HALFGI(tid->an->mpdudensity);
else
- nsymbols = NUM_SYMBOLS_PER_USEC(mpdudensity);
+ nsymbols = NUM_SYMBOLS_PER_USEC(tid->an->mpdudensity);
if (nsymbols == 0)
nsymbols = 1;
@@ -565,6 +572,7 @@ static int ath_compute_num_delims(struct ath_softc *sc, struct ath_atx_tid *tid,
}
static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc,
+ struct ath_txq *txq,
struct ath_atx_tid *tid,
struct list_head *bf_q)
{
@@ -629,6 +637,7 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc,
bf_prev->bf_desc->ds_link = bf->bf_daddr;
}
bf_prev = bf;
+
} while (!list_empty(&tid->buf_q));
bf_first->bf_al = al;
@@ -651,7 +660,7 @@ static void ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq,
INIT_LIST_HEAD(&bf_q);
- status = ath_tx_form_aggr(sc, tid, &bf_q);
+ status = ath_tx_form_aggr(sc, txq, tid, &bf_q);
/*
* no frames picked up to be aggregated;
@@ -682,30 +691,26 @@ static void ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq,
txq->axq_aggr_depth++;
ath_tx_txqaddbuf(sc, txq, &bf_q);
+ TX_STAT_INC(txq->axq_qnum, a_aggr);
} while (txq->axq_depth < ATH_AGGR_MIN_QDEPTH &&
status != ATH_AGGR_BAW_CLOSED);
}
-int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
- u16 tid, u16 *ssn)
+void ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
+ u16 tid, u16 *ssn)
{
struct ath_atx_tid *txtid;
struct ath_node *an;
an = (struct ath_node *)sta->drv_priv;
-
- if (sc->sc_flags & SC_OP_TXAGGR) {
- txtid = ATH_AN_2_TID(an, tid);
- txtid->state |= AGGR_ADDBA_PROGRESS;
- ath_tx_pause_tid(sc, txtid);
- *ssn = txtid->seq_start;
- }
-
- return 0;
+ txtid = ATH_AN_2_TID(an, tid);
+ txtid->state |= AGGR_ADDBA_PROGRESS;
+ ath_tx_pause_tid(sc, txtid);
+ *ssn = txtid->seq_start;
}
-int ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid)
+void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid)
{
struct ath_node *an = (struct ath_node *)sta->drv_priv;
struct ath_atx_tid *txtid = ATH_AN_2_TID(an, tid);
@@ -715,12 +720,11 @@ int ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid)
INIT_LIST_HEAD(&bf_head);
if (txtid->state & AGGR_CLEANUP)
- return 0;
+ return;
if (!(txtid->state & AGGR_ADDBA_COMPLETE)) {
txtid->state &= ~AGGR_ADDBA_PROGRESS;
- txtid->addba_exchangeattempts = 0;
- return 0;
+ return;
}
ath_tx_pause_tid(sc, txtid);
@@ -739,7 +743,7 @@ int ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid)
}
list_move_tail(&bf->list, &bf_head);
ath_tx_update_baw(sc, txtid, bf->bf_seqno);
- ath_tx_complete_buf(sc, bf, &bf_head, 0, 0);
+ ath_tx_complete_buf(sc, bf, txq, &bf_head, 0, 0);
}
spin_unlock_bh(&txq->axq_lock);
@@ -747,11 +751,8 @@ int ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid)
txtid->state |= AGGR_CLEANUP;
} else {
txtid->state &= ~AGGR_ADDBA_COMPLETE;
- txtid->addba_exchangeattempts = 0;
ath_tx_flush_tid(sc, txtid);
}
-
- return 0;
}
void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid)
@@ -780,14 +781,8 @@ bool ath_tx_aggr_check(struct ath_softc *sc, struct ath_node *an, u8 tidno)
txtid = ATH_AN_2_TID(an, tidno);
- if (!(txtid->state & AGGR_ADDBA_COMPLETE)) {
- if (!(txtid->state & AGGR_ADDBA_PROGRESS) &&
- (txtid->addba_exchangeattempts < ADDBA_EXCHANGE_ATTEMPTS)) {
- txtid->addba_exchangeattempts++;
+ if (!(txtid->state & (AGGR_ADDBA_COMPLETE | AGGR_ADDBA_PROGRESS)))
return true;
- }
- }
-
return false;
}
@@ -870,8 +865,8 @@ struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype)
spin_lock_init(&txq->axq_lock);
txq->axq_depth = 0;
txq->axq_aggr_depth = 0;
- txq->axq_totalqueued = 0;
txq->axq_linkbuf = NULL;
+ txq->axq_tx_inprogress = false;
sc->tx.txqsetup |= 1<<qnum;
}
return &sc->tx.txq[qnum];
@@ -1035,9 +1030,13 @@ void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx)
if (bf_isampdu(bf))
ath_tx_complete_aggr(sc, txq, bf, &bf_head, 0);
else
- ath_tx_complete_buf(sc, bf, &bf_head, 0, 0);
+ ath_tx_complete_buf(sc, bf, txq, &bf_head, 0, 0);
}
+ spin_lock_bh(&txq->axq_lock);
+ txq->axq_tx_inprogress = false;
+ spin_unlock_bh(&txq->axq_lock);
+
/* flush any pending frames if aggregation is enabled */
if (sc->sc_flags & SC_OP_TXAGGR) {
if (!retry_tx) {
@@ -1118,8 +1117,7 @@ void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq)
if (tid->paused)
continue;
- if ((txq->axq_depth % 2) == 0)
- ath_tx_sched_aggr(sc, txq, tid);
+ ath_tx_sched_aggr(sc, txq, tid);
/*
* add tid to round-robin queue if more frames
@@ -1183,7 +1181,6 @@ static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq,
list_splice_tail_init(head, &txq->axq_q);
txq->axq_depth++;
- txq->axq_totalqueued++;
txq->axq_linkbuf = list_entry(txq->axq_q.prev, struct ath_buf, list);
DPRINTF(sc, ATH_DBG_QUEUE,
@@ -1231,6 +1228,7 @@ static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_atx_tid *tid,
bf = list_first_entry(bf_head, struct ath_buf, list);
bf->bf_state.bf_type |= BUF_AMPDU;
+ TX_STAT_INC(txctl->txq->axq_qnum, a_queued);
/*
* Do not queue to h/w when any of the following conditions is true:
@@ -1277,6 +1275,7 @@ static void ath_tx_send_ht_normal(struct ath_softc *sc, struct ath_txq *txq,
bf->bf_lastbf = bf;
ath_buf_set_rate(sc, bf);
ath_tx_txqaddbuf(sc, txq, bf_head);
+ TX_STAT_INC(txq->axq_qnum, queued);
}
static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq,
@@ -1290,6 +1289,7 @@ static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq,
bf->bf_nframes = 1;
ath_buf_set_rate(sc, bf);
ath_tx_txqaddbuf(sc, txq, bf_head);
+ TX_STAT_INC(txq->axq_qnum, queued);
}
static enum ath9k_pkt_type get_hw_packet_type(struct sk_buff *skb)
@@ -1636,7 +1636,7 @@ static void ath_tx_start_dma(struct ath_softc *sc, struct ath_buf *bf,
goto tx_done;
}
- if (ath_aggr_query(sc, an, bf->bf_tidno)) {
+ if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) {
/*
* Try aggregation if it's a unicast data frame
* and the destination is HT capable.
@@ -1815,6 +1815,7 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
}
static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
+ struct ath_txq *txq,
struct list_head *bf_q,
int txok, int sendbar)
{
@@ -1822,7 +1823,6 @@ static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
unsigned long flags;
int tx_flags = 0;
-
if (sendbar)
tx_flags = ATH_TX_BAR;
@@ -1835,6 +1835,7 @@ static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
dma_unmap_single(sc->dev, bf->bf_dmacontext, skb->len, DMA_TO_DEVICE);
ath_tx_complete(sc, skb, tx_flags);
+ ath_debug_stat_tx(sc, txq, bf);
/*
* Return the list of ath_buf of this mpdu to free queue
@@ -1962,19 +1963,7 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
if (bf->bf_stale) {
bf_held = bf;
if (list_is_last(&bf_held->list, &txq->axq_q)) {
- txq->axq_link = NULL;
- txq->axq_linkbuf = NULL;
spin_unlock_bh(&txq->axq_lock);
-
- /*
- * The holding descriptor is the last
- * descriptor in queue. It's safe to remove
- * the last holding descriptor in BH context.
- */
- spin_lock_bh(&sc->tx.txbuflock);
- list_move_tail(&bf_held->list, &sc->tx.txbuf);
- spin_unlock_bh(&sc->tx.txbuflock);
-
break;
} else {
bf = list_entry(bf_held->list.next,
@@ -2011,6 +2000,7 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
txq->axq_aggr_depth--;
txok = (ds->ds_txstat.ts_status == 0);
+ txq->axq_tx_inprogress = false;
spin_unlock_bh(&txq->axq_lock);
if (bf_held) {
@@ -2033,7 +2023,7 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
if (bf_isampdu(bf))
ath_tx_complete_aggr(sc, txq, bf, &bf_head, txok);
else
- ath_tx_complete_buf(sc, bf, &bf_head, txok, 0);
+ ath_tx_complete_buf(sc, bf, txq, &bf_head, txok, 0);
ath_wake_mac80211_queue(sc, txq);
@@ -2044,6 +2034,40 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
}
}
+static void ath_tx_complete_poll_work(struct work_struct *work)
+{
+ struct ath_softc *sc = container_of(work, struct ath_softc,
+ tx_complete_work.work);
+ struct ath_txq *txq;
+ int i;
+ bool needreset = false;
+
+ for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++)
+ if (ATH_TXQ_SETUP(sc, i)) {
+ txq = &sc->tx.txq[i];
+ spin_lock_bh(&txq->axq_lock);
+ if (txq->axq_depth) {
+ if (txq->axq_tx_inprogress) {
+ needreset = true;
+ spin_unlock_bh(&txq->axq_lock);
+ break;
+ } else {
+ txq->axq_tx_inprogress = true;
+ }
+ }
+ spin_unlock_bh(&txq->axq_lock);
+ }
+
+ if (needreset) {
+ DPRINTF(sc, ATH_DBG_RESET, "tx hung, resetting the chip\n");
+ ath_reset(sc, false);
+ }
+
+ ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work,
+ msecs_to_jiffies(ATH_TX_COMPLETE_POLL_INT));
+}
+
+
void ath_tx_tasklet(struct ath_softc *sc)
{
@@ -2084,6 +2108,8 @@ int ath_tx_init(struct ath_softc *sc, int nbufs)
goto err;
}
+ INIT_DELAYED_WORK(&sc->tx_complete_work, ath_tx_complete_poll_work);
+
err:
if (error != 0)
ath_tx_cleanup(sc);
@@ -2122,7 +2148,6 @@ void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an)
tid->ac = &an->ac[acno];
tid->state &= ~AGGR_ADDBA_COMPLETE;
tid->state &= ~AGGR_ADDBA_PROGRESS;
- tid->addba_exchangeattempts = 0;
}
for (acno = 0, ac = &an->ac[acno];
@@ -2179,7 +2204,6 @@ void ath_tx_node_cleanup(struct ath_softc *sc, struct ath_node *an)
tid->sched = false;
ath_tid_drain(sc, txq, tid);
tid->state &= ~AGGR_ADDBA_COMPLETE;
- tid->addba_exchangeattempts = 0;
tid->state &= ~AGGR_CLEANUP;
}
}
diff --git a/drivers/net/wireless/ath/main.c b/drivers/net/wireless/ath/main.c
index 9949b11cb15..487193f1de1 100644
--- a/drivers/net/wireless/ath/main.c
+++ b/drivers/net/wireless/ath/main.c
@@ -17,6 +17,42 @@
#include <linux/kernel.h>
#include <linux/module.h>
+#include "ath.h"
+
MODULE_AUTHOR("Atheros Communications");
MODULE_DESCRIPTION("Shared library for Atheros wireless LAN cards.");
MODULE_LICENSE("Dual BSD/GPL");
+
+struct sk_buff *ath_rxbuf_alloc(struct ath_common *common,
+ u32 len,
+ gfp_t gfp_mask)
+{
+ struct sk_buff *skb;
+ u32 off;
+
+ /*
+ * Cache-line-align. This is important (for the
+ * 5210 at least) as not doing so causes bogus data
+ * in rx'd frames.
+ */
+
+ /* Note: the kernel can allocate a value greater than
+ * what we ask it to give us. We really only need 4 KB as that
+ * is this hardware supports and in fact we need at least 3849
+ * as that is the MAX AMSDU size this hardware supports.
+ * Unfortunately this means we may get 8 KB here from the
+ * kernel... and that is actually what is observed on some
+ * systems :( */
+ skb = __dev_alloc_skb(len + common->cachelsz - 1, gfp_mask);
+ if (skb != NULL) {
+ off = ((unsigned long) skb->data) % common->cachelsz;
+ if (off != 0)
+ skb_reserve(skb, common->cachelsz - off);
+ } else {
+ printk(KERN_ERR "skbuff alloc of size %u failed\n", len);
+ return NULL;
+ }
+
+ return skb;
+}
+EXPORT_SYMBOL(ath_rxbuf_alloc);
diff --git a/drivers/net/wireless/ath/regd.c b/drivers/net/wireless/ath/regd.c
index bf3d25ba7be..077bcc142cd 100644
--- a/drivers/net/wireless/ath/regd.c
+++ b/drivers/net/wireless/ath/regd.c
@@ -586,7 +586,5 @@ u32 ath_regd_get_band_ctl(struct ath_regulatory *reg,
default:
return NO_CTL;
}
-
- return NO_CTL;
}
EXPORT_SYMBOL(ath_regd_get_band_ctl);
diff --git a/drivers/net/wireless/ath/regd_common.h b/drivers/net/wireless/ath/regd_common.h
index 4d0e298cd1c..ad6d938d3cf 100644
--- a/drivers/net/wireless/ath/regd_common.h
+++ b/drivers/net/wireless/ath/regd_common.h
@@ -450,7 +450,7 @@ static struct country_code_to_enum_rd allCountries[] = {
{CTRY_SWITZERLAND, ETSI1_WORLD, "CH"},
{CTRY_SYRIA, NULL1_WORLD, "SY"},
{CTRY_TAIWAN, APL3_FCCA, "TW"},
- {CTRY_THAILAND, NULL1_WORLD, "TH"},
+ {CTRY_THAILAND, FCC3_WORLD, "TH"},
{CTRY_TRINIDAD_Y_TOBAGO, ETSI4_WORLD, "TT"},
{CTRY_TUNISIA, ETSI3_WORLD, "TN"},
{CTRY_TURKEY, ETSI3_WORLD, "TR"},
diff --git a/drivers/net/wireless/atmel.c b/drivers/net/wireless/atmel.c
index 291a94bd46f..05813bc3e30 100644
--- a/drivers/net/wireless/atmel.c
+++ b/drivers/net/wireless/atmel.c
@@ -793,13 +793,13 @@ static int start_tx(struct sk_buff *skb, struct net_device *dev)
!(*priv->present_callback)(priv->card)) {
dev->stats.tx_errors++;
dev_kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
}
if (priv->station_state != STATION_STATE_READY) {
dev->stats.tx_errors++;
dev_kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
}
/* first ensure the timer func cannot run */
@@ -856,7 +856,7 @@ static int start_tx(struct sk_buff *skb, struct net_device *dev)
spin_unlock_bh(&priv->timerlock);
dev_kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
}
static void atmel_transmit_management_frame(struct atmel_private *priv,
diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h
index 40448067e4c..a1b3b731935 100644
--- a/drivers/net/wireless/b43/b43.h
+++ b/drivers/net/wireless/b43/b43.h
@@ -142,6 +142,17 @@
#define B43_BFL_BTCMOD 0x4000 /* BFL_BTCOEXIST is given in alternate GPIOs */
#define B43_BFL_ALTIQ 0x8000 /* alternate I/Q settings */
+/* SPROM boardflags_hi values */
+#define B43_BFH_NOPA 0x0001 /* has no PA */
+#define B43_BFH_RSSIINV 0x0002 /* RSSI uses positive slope (not TSSI) */
+#define B43_BFH_PAREF 0x0004 /* uses the PARef LDO */
+#define B43_BFH_3TSWITCH 0x0008 /* uses a triple throw switch shared
+ * with bluetooth */
+#define B43_BFH_PHASESHIFT 0x0010 /* can support phase shifter */
+#define B43_BFH_BUCKBOOST 0x0020 /* has buck/booster */
+#define B43_BFH_FEM_BT 0x0040 /* has FEM and switch to share antenna
+ * with bluetooth */
+
/* GPIO register offset, in both ChipCommon and PCI core. */
#define B43_GPIO_CONTROL 0x6c
@@ -482,6 +493,10 @@ enum {
/* Max size of a security key */
#define B43_SEC_KEYSIZE 16
+/* Max number of group keys */
+#define B43_NR_GROUP_KEYS 4
+/* Max number of pairwise keys */
+#define B43_NR_PAIRWISE_KEYS 50
/* Security algorithms. */
enum {
B43_SEC_ALGO_NONE = 0, /* unencrypted, as of TX header. */
@@ -628,7 +643,7 @@ struct b43_wl {
u8 mac_addr[ETH_ALEN];
/* Current BSSID */
u8 bssid[ETH_ALEN];
- /* Interface type. (IEEE80211_IF_TYPE_XXX) */
+ /* Interface type. (NL80211_IFTYPE_XXX) */
int if_type;
/* Is the card operating in AP, STA or IBSS mode? */
bool operating;
@@ -808,8 +823,7 @@ struct b43_wldev {
/* encryption/decryption */
u16 ktp; /* Key table pointer */
- u8 max_nr_keys;
- struct b43_key key[58];
+ struct b43_key key[B43_NR_GROUP_KEYS * 2 + B43_NR_PAIRWISE_KEYS];
/* Firmware data */
struct b43_firmware fw;
@@ -834,7 +848,7 @@ static inline struct b43_wldev *dev_to_b43_wldev(struct device *dev)
return ssb_get_drvdata(ssb_dev);
}
-/* Is the device operating in a specified mode (IEEE80211_IF_TYPE_XXX). */
+/* Is the device operating in a specified mode (NL80211_IFTYPE_XXX). */
static inline int b43_is_mode(struct b43_wl *wl, int type)
{
return (wl->operating && wl->if_type == type);
diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c
index 7964cc32b25..41a0e9c2b33 100644
--- a/drivers/net/wireless/b43/dma.c
+++ b/drivers/net/wireless/b43/dma.c
@@ -1334,13 +1334,22 @@ int b43_dma_tx(struct b43_wldev *dev, struct sk_buff *skb)
spin_lock_irqsave(&ring->lock, flags);
B43_WARN_ON(!ring->tx);
- /* Check if the queue was stopped in mac80211,
- * but we got called nevertheless.
- * That would be a mac80211 bug. */
- B43_WARN_ON(ring->stopped);
- if (unlikely(free_slots(ring) < TX_SLOTS_PER_FRAME)) {
- b43warn(dev->wl, "DMA queue overflow\n");
+ if (unlikely(ring->stopped)) {
+ /* We get here only because of a bug in mac80211.
+ * Because of a race, one packet may be queued after
+ * the queue is stopped, thus we got called when we shouldn't.
+ * For now, just refuse the transmit. */
+ if (b43_debug(dev, B43_DBG_DMAVERBOSE))
+ b43err(dev->wl, "Packet after queue stopped\n");
+ err = -ENOSPC;
+ goto out_unlock;
+ }
+
+ if (unlikely(WARN_ON(free_slots(ring) < TX_SLOTS_PER_FRAME))) {
+ /* If we get here, we have a real error with the queue
+ * full, but queues not stopped. */
+ b43err(dev->wl, "DMA queue overflow\n");
err = -ENOSPC;
goto out_unlock;
}
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c
index e71c8d9cd70..950beefbeae 100644
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
@@ -395,9 +395,8 @@ u32 __b43_shm_read32(struct b43_wldev *dev, u16 routing, u16 offset)
/* Unaligned access */
b43_shm_control_word(dev, routing, offset >> 2);
ret = b43_read16(dev, B43_MMIO_SHM_DATA_UNALIGNED);
- ret <<= 16;
b43_shm_control_word(dev, routing, (offset >> 2) + 1);
- ret |= b43_read16(dev, B43_MMIO_SHM_DATA);
+ ret |= ((u32)b43_read16(dev, B43_MMIO_SHM_DATA)) << 16;
goto out;
}
@@ -464,9 +463,10 @@ void __b43_shm_write32(struct b43_wldev *dev, u16 routing, u16 offset, u32 value
/* Unaligned access */
b43_shm_control_word(dev, routing, offset >> 2);
b43_write16(dev, B43_MMIO_SHM_DATA_UNALIGNED,
- (value >> 16) & 0xffff);
+ value & 0xFFFF);
b43_shm_control_word(dev, routing, (offset >> 2) + 1);
- b43_write16(dev, B43_MMIO_SHM_DATA, value & 0xffff);
+ b43_write16(dev, B43_MMIO_SHM_DATA,
+ (value >> 16) & 0xFFFF);
return;
}
offset >>= 2;
@@ -796,18 +796,19 @@ static void key_write(struct b43_wldev *dev,
static void keymac_write(struct b43_wldev *dev, u8 index, const u8 *addr)
{
u32 addrtmp[2] = { 0, 0, };
- u8 per_sta_keys_start = 8;
+ u8 pairwise_keys_start = B43_NR_GROUP_KEYS * 2;
if (b43_new_kidx_api(dev))
- per_sta_keys_start = 4;
+ pairwise_keys_start = B43_NR_GROUP_KEYS;
- B43_WARN_ON(index < per_sta_keys_start);
- /* We have two default TX keys and possibly two default RX keys.
+ B43_WARN_ON(index < pairwise_keys_start);
+ /* We have four default TX keys and possibly four default RX keys.
* Physical mac 0 is mapped to physical key 4 or 8, depending
* on the firmware version.
* So we must adjust the index here.
*/
- index -= per_sta_keys_start;
+ index -= pairwise_keys_start;
+ B43_WARN_ON(index >= B43_NR_PAIRWISE_KEYS);
if (addr) {
addrtmp[0] = addr[0];
@@ -818,27 +819,11 @@ static void keymac_write(struct b43_wldev *dev, u8 index, const u8 *addr)
addrtmp[1] |= ((u32) (addr[5]) << 8);
}
- if (dev->dev->id.revision >= 5) {
- /* Receive match transmitter address mechanism */
- b43_shm_write32(dev, B43_SHM_RCMTA,
- (index * 2) + 0, addrtmp[0]);
- b43_shm_write16(dev, B43_SHM_RCMTA,
- (index * 2) + 1, addrtmp[1]);
- } else {
- /* RXE (Receive Engine) and
- * PSM (Programmable State Machine) mechanism
- */
- if (index < 8) {
- /* TODO write to RCM 16, 19, 22 and 25 */
- } else {
- b43_shm_write32(dev, B43_SHM_SHARED,
- B43_SHM_SH_PSM + (index * 6) + 0,
- addrtmp[0]);
- b43_shm_write16(dev, B43_SHM_SHARED,
- B43_SHM_SH_PSM + (index * 6) + 4,
- addrtmp[1]);
- }
- }
+ /* Receive match transmitter address (RCMTA) mechanism */
+ b43_shm_write32(dev, B43_SHM_RCMTA,
+ (index * 2) + 0, addrtmp[0]);
+ b43_shm_write16(dev, B43_SHM_RCMTA,
+ (index * 2) + 1, addrtmp[1]);
}
static void do_key_write(struct b43_wldev *dev,
@@ -846,20 +831,20 @@ static void do_key_write(struct b43_wldev *dev,
const u8 *key, size_t key_len, const u8 *mac_addr)
{
u8 buf[B43_SEC_KEYSIZE] = { 0, };
- u8 per_sta_keys_start = 8;
+ u8 pairwise_keys_start = B43_NR_GROUP_KEYS * 2;
if (b43_new_kidx_api(dev))
- per_sta_keys_start = 4;
+ pairwise_keys_start = B43_NR_GROUP_KEYS;
- B43_WARN_ON(index >= dev->max_nr_keys);
+ B43_WARN_ON(index >= ARRAY_SIZE(dev->key));
B43_WARN_ON(key_len > B43_SEC_KEYSIZE);
- if (index >= per_sta_keys_start)
+ if (index >= pairwise_keys_start)
keymac_write(dev, index, NULL); /* First zero out mac. */
if (key)
memcpy(buf, key, key_len);
key_write(dev, index, algorithm, buf);
- if (index >= per_sta_keys_start)
+ if (index >= pairwise_keys_start)
keymac_write(dev, index, mac_addr);
dev->key[index].algorithm = algorithm;
@@ -872,21 +857,24 @@ static int b43_key_write(struct b43_wldev *dev,
struct ieee80211_key_conf *keyconf)
{
int i;
- int sta_keys_start;
+ int pairwise_keys_start;
if (key_len > B43_SEC_KEYSIZE)
return -EINVAL;
- for (i = 0; i < dev->max_nr_keys; i++) {
+ for (i = 0; i < ARRAY_SIZE(dev->key); i++) {
/* Check that we don't already have this key. */
B43_WARN_ON(dev->key[i].keyconf == keyconf);
}
if (index < 0) {
/* Pairwise key. Get an empty slot for the key. */
if (b43_new_kidx_api(dev))
- sta_keys_start = 4;
+ pairwise_keys_start = B43_NR_GROUP_KEYS;
else
- sta_keys_start = 8;
- for (i = sta_keys_start; i < dev->max_nr_keys; i++) {
+ pairwise_keys_start = B43_NR_GROUP_KEYS * 2;
+ for (i = pairwise_keys_start;
+ i < pairwise_keys_start + B43_NR_PAIRWISE_KEYS;
+ i++) {
+ B43_WARN_ON(i >= ARRAY_SIZE(dev->key));
if (!dev->key[i].keyconf) {
/* found empty */
index = i;
@@ -914,7 +902,7 @@ static int b43_key_write(struct b43_wldev *dev,
static int b43_key_clear(struct b43_wldev *dev, int index)
{
- if (B43_WARN_ON((index < 0) || (index >= dev->max_nr_keys)))
+ if (B43_WARN_ON((index < 0) || (index >= ARRAY_SIZE(dev->key))))
return -EINVAL;
do_key_write(dev, index, B43_SEC_ALGO_NONE,
NULL, B43_SEC_KEYSIZE, NULL);
@@ -929,16 +917,19 @@ static int b43_key_clear(struct b43_wldev *dev, int index)
static void b43_clear_keys(struct b43_wldev *dev)
{
- int i;
+ int i, count;
- for (i = 0; i < dev->max_nr_keys; i++)
+ if (b43_new_kidx_api(dev))
+ count = B43_NR_GROUP_KEYS + B43_NR_PAIRWISE_KEYS;
+ else
+ count = B43_NR_GROUP_KEYS * 2 + B43_NR_PAIRWISE_KEYS;
+ for (i = 0; i < count; i++)
b43_key_clear(dev, i);
}
static void b43_dump_keymemory(struct b43_wldev *dev)
{
- unsigned int i, index, offset;
- DECLARE_MAC_BUF(macbuf);
+ unsigned int i, index, count, offset, pairwise_keys_start;
u8 mac[ETH_ALEN];
u16 algo;
u32 rcmta0;
@@ -952,7 +943,14 @@ static void b43_dump_keymemory(struct b43_wldev *dev)
hf = b43_hf_read(dev);
b43dbg(dev->wl, "Hardware key memory dump: USEDEFKEYS=%u\n",
!!(hf & B43_HF_USEDEFKEYS));
- for (index = 0; index < dev->max_nr_keys; index++) {
+ if (b43_new_kidx_api(dev)) {
+ pairwise_keys_start = B43_NR_GROUP_KEYS;
+ count = B43_NR_GROUP_KEYS + B43_NR_PAIRWISE_KEYS;
+ } else {
+ pairwise_keys_start = B43_NR_GROUP_KEYS * 2;
+ count = B43_NR_GROUP_KEYS * 2 + B43_NR_PAIRWISE_KEYS;
+ }
+ for (index = 0; index < count; index++) {
key = &(dev->key[index]);
printk(KERN_DEBUG "Key slot %02u: %s",
index, (key->keyconf == NULL) ? " " : "*");
@@ -966,15 +964,14 @@ static void b43_dump_keymemory(struct b43_wldev *dev)
B43_SHM_SH_KEYIDXBLOCK + (index * 2));
printk(" Algo: %04X/%02X", algo, key->algorithm);
- if (index >= 4) {
+ if (index >= pairwise_keys_start) {
rcmta0 = b43_shm_read32(dev, B43_SHM_RCMTA,
- ((index - 4) * 2) + 0);
+ ((index - pairwise_keys_start) * 2) + 0);
rcmta1 = b43_shm_read16(dev, B43_SHM_RCMTA,
- ((index - 4) * 2) + 1);
+ ((index - pairwise_keys_start) * 2) + 1);
*((__le32 *)(&mac[0])) = cpu_to_le32(rcmta0);
*((__le16 *)(&mac[4])) = cpu_to_le16(rcmta1);
- printk(" MAC: %s",
- print_mac(macbuf, mac));
+ printk(" MAC: %pM", mac);
} else
printk(" DEFAULT KEY");
printk("\n");
@@ -1431,113 +1428,6 @@ static void b43_write_beacon_template(struct b43_wldev *dev,
b43dbg(dev->wl, "Updated beacon template at 0x%x\n", ram_offset);
}
-static void b43_write_probe_resp_plcp(struct b43_wldev *dev,
- u16 shm_offset, u16 size,
- struct ieee80211_rate *rate)
-{
- struct b43_plcp_hdr4 plcp;
- u32 tmp;
- __le16 dur;
-
- plcp.data = 0;
- b43_generate_plcp_hdr(&plcp, size + FCS_LEN, rate->hw_value);
- dur = ieee80211_generic_frame_duration(dev->wl->hw,
- dev->wl->vif, size,
- rate);
- /* Write PLCP in two parts and timing for packet transfer */
- tmp = le32_to_cpu(plcp.data);
- b43_shm_write16(dev, B43_SHM_SHARED, shm_offset, tmp & 0xFFFF);
- b43_shm_write16(dev, B43_SHM_SHARED, shm_offset + 2, tmp >> 16);
- b43_shm_write16(dev, B43_SHM_SHARED, shm_offset + 6, le16_to_cpu(dur));
-}
-
-/* Instead of using custom probe response template, this function
- * just patches custom beacon template by:
- * 1) Changing packet type
- * 2) Patching duration field
- * 3) Stripping TIM
- */
-static const u8 *b43_generate_probe_resp(struct b43_wldev *dev,
- u16 *dest_size,
- struct ieee80211_rate *rate)
-{
- const u8 *src_data;
- u8 *dest_data;
- u16 src_size, elem_size, src_pos, dest_pos;
- __le16 dur;
- struct ieee80211_hdr *hdr;
- size_t ie_start;
-
- src_size = dev->wl->current_beacon->len;
- src_data = (const u8 *)dev->wl->current_beacon->data;
-
- /* Get the start offset of the variable IEs in the packet. */
- ie_start = offsetof(struct ieee80211_mgmt, u.probe_resp.variable);
- B43_WARN_ON(ie_start != offsetof(struct ieee80211_mgmt, u.beacon.variable));
-
- if (B43_WARN_ON(src_size < ie_start))
- return NULL;
-
- dest_data = kmalloc(src_size, GFP_ATOMIC);
- if (unlikely(!dest_data))
- return NULL;
-
- /* Copy the static data and all Information Elements, except the TIM. */
- memcpy(dest_data, src_data, ie_start);
- src_pos = ie_start;
- dest_pos = ie_start;
- for ( ; src_pos < src_size - 2; src_pos += elem_size) {
- elem_size = src_data[src_pos + 1] + 2;
- if (src_data[src_pos] == 5) {
- /* This is the TIM. */
- continue;
- }
- memcpy(dest_data + dest_pos, src_data + src_pos,
- elem_size);
- dest_pos += elem_size;
- }
- *dest_size = dest_pos;
- hdr = (struct ieee80211_hdr *)dest_data;
-
- /* Set the frame control. */
- hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
- IEEE80211_STYPE_PROBE_RESP);
- dur = ieee80211_generic_frame_duration(dev->wl->hw,
- dev->wl->vif, *dest_size,
- rate);
- hdr->duration_id = dur;
-
- return dest_data;
-}
-
-static void b43_write_probe_resp_template(struct b43_wldev *dev,
- u16 ram_offset,
- u16 shm_size_offset,
- struct ieee80211_rate *rate)
-{
- const u8 *probe_resp_data;
- u16 size;
-
- size = dev->wl->current_beacon->len;
- probe_resp_data = b43_generate_probe_resp(dev, &size, rate);
- if (unlikely(!probe_resp_data))
- return;
-
- /* Looks like PLCP headers plus packet timings are stored for
- * all possible basic rates
- */
- b43_write_probe_resp_plcp(dev, 0x31A, size, &b43_b_ratetable[0]);
- b43_write_probe_resp_plcp(dev, 0x32C, size, &b43_b_ratetable[1]);
- b43_write_probe_resp_plcp(dev, 0x33E, size, &b43_b_ratetable[2]);
- b43_write_probe_resp_plcp(dev, 0x350, size, &b43_b_ratetable[3]);
-
- size = min((size_t) size, 0x200 - sizeof(struct b43_plcp_hdr6));
- b43_write_template_common(dev, probe_resp_data,
- size, ram_offset, shm_size_offset,
- rate->hw_value);
- kfree(probe_resp_data);
-}
-
static void b43_upload_beacon0(struct b43_wldev *dev)
{
struct b43_wl *wl = dev->wl;
@@ -1545,10 +1435,6 @@ static void b43_upload_beacon0(struct b43_wldev *dev)
if (wl->beacon0_uploaded)
return;
b43_write_beacon_template(dev, 0x68, 0x18);
- /* FIXME: Probe resp upload doesn't really belong here,
- * but we don't use that feature anyway. */
- b43_write_probe_resp_template(dev, 0x268, 0x4A,
- &__b43_ratetable[3]);
wl->beacon0_uploaded = 1;
}
@@ -1656,7 +1542,7 @@ static void b43_update_templates(struct b43_wl *wl)
wl->current_beacon = beacon;
wl->beacon0_uploaded = 0;
wl->beacon1_uploaded = 0;
- queue_work(wl->hw->workqueue, &wl->beacon_update_trigger);
+ ieee80211_queue_work(wl->hw, &wl->beacon_update_trigger);
}
static void b43_set_beacon_int(struct b43_wldev *dev, u16 beacon_int)
@@ -2916,7 +2802,7 @@ out_requeue:
delay = msecs_to_jiffies(50);
else
delay = round_jiffies_relative(HZ * 15);
- queue_delayed_work(wl->hw->workqueue, &dev->periodic_work, delay);
+ ieee80211_queue_delayed_work(wl->hw, &dev->periodic_work, delay);
out:
mutex_unlock(&wl->mutex);
}
@@ -2927,15 +2813,16 @@ static void b43_periodic_tasks_setup(struct b43_wldev *dev)
dev->periodic_state = 0;
INIT_DELAYED_WORK(work, b43_periodic_work_handler);
- queue_delayed_work(dev->wl->hw->workqueue, work, 0);
+ ieee80211_queue_delayed_work(dev->wl->hw, work, 0);
}
/* Check if communication with the device works correctly. */
static int b43_validate_chipaccess(struct b43_wldev *dev)
{
- u32 v, backup;
+ u32 v, backup0, backup4;
- backup = b43_shm_read32(dev, B43_SHM_SHARED, 0);
+ backup0 = b43_shm_read32(dev, B43_SHM_SHARED, 0);
+ backup4 = b43_shm_read32(dev, B43_SHM_SHARED, 4);
/* Check for read/write and endianness problems. */
b43_shm_write32(dev, B43_SHM_SHARED, 0, 0x55AAAA55);
@@ -2945,7 +2832,23 @@ static int b43_validate_chipaccess(struct b43_wldev *dev)
if (b43_shm_read32(dev, B43_SHM_SHARED, 0) != 0xAA5555AA)
goto error;
- b43_shm_write32(dev, B43_SHM_SHARED, 0, backup);
+ /* Check if unaligned 32bit SHM_SHARED access works properly.
+ * However, don't bail out on failure, because it's noncritical. */
+ b43_shm_write16(dev, B43_SHM_SHARED, 0, 0x1122);
+ b43_shm_write16(dev, B43_SHM_SHARED, 2, 0x3344);
+ b43_shm_write16(dev, B43_SHM_SHARED, 4, 0x5566);
+ b43_shm_write16(dev, B43_SHM_SHARED, 6, 0x7788);
+ if (b43_shm_read32(dev, B43_SHM_SHARED, 2) != 0x55663344)
+ b43warn(dev->wl, "Unaligned 32bit SHM read access is broken\n");
+ b43_shm_write32(dev, B43_SHM_SHARED, 2, 0xAABBCCDD);
+ if (b43_shm_read16(dev, B43_SHM_SHARED, 0) != 0x1122 ||
+ b43_shm_read16(dev, B43_SHM_SHARED, 2) != 0xCCDD ||
+ b43_shm_read16(dev, B43_SHM_SHARED, 4) != 0xAABB ||
+ b43_shm_read16(dev, B43_SHM_SHARED, 6) != 0x7788)
+ b43warn(dev->wl, "Unaligned 32bit SHM write access is broken\n");
+
+ b43_shm_write32(dev, B43_SHM_SHARED, 0, backup0);
+ b43_shm_write32(dev, B43_SHM_SHARED, 4, backup4);
if ((dev->dev->id.revision >= 3) && (dev->dev->id.revision <= 10)) {
/* The 32bit register shadows the two 16bit registers
@@ -2972,17 +2875,14 @@ error:
static void b43_security_init(struct b43_wldev *dev)
{
- dev->max_nr_keys = (dev->dev->id.revision >= 5) ? 58 : 20;
- B43_WARN_ON(dev->max_nr_keys > ARRAY_SIZE(dev->key));
dev->ktp = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_KTP);
/* KTP is a word address, but we address SHM bytewise.
* So multiply by two.
*/
dev->ktp *= 2;
- if (dev->dev->id.revision >= 5) {
- /* Number of RCMTA address slots */
- b43_write16(dev, B43_MMIO_RCMTA_COUNT, dev->max_nr_keys - 8);
- }
+ /* Number of RCMTA address slots */
+ b43_write16(dev, B43_MMIO_RCMTA_COUNT, B43_NR_PAIRWISE_KEYS);
+ /* Clear the key memory. */
b43_clear_keys(dev);
}
@@ -4873,7 +4773,7 @@ void b43_controller_restart(struct b43_wldev *dev, const char *reason)
if (b43_status(dev) < B43_STAT_INITIALIZED)
return;
b43info(dev->wl, "Controller RESET (%s) ...\n", reason);
- queue_work(dev->wl->hw->workqueue, &dev->restart_work);
+ ieee80211_queue_work(dev->wl->hw, &dev->restart_work);
}
#ifdef CONFIG_PM
diff --git a/drivers/net/wireless/b43/phy_common.c b/drivers/net/wireless/b43/phy_common.c
index 6d241622210..51686ec9698 100644
--- a/drivers/net/wireless/b43/phy_common.c
+++ b/drivers/net/wireless/b43/phy_common.c
@@ -240,6 +240,13 @@ void b43_phy_write(struct b43_wldev *dev, u16 reg, u16 value)
dev->phy.ops->phy_write(dev, reg, value);
}
+void b43_phy_copy(struct b43_wldev *dev, u16 destreg, u16 srcreg)
+{
+ assert_mac_suspended(dev);
+ dev->phy.ops->phy_write(dev, destreg,
+ dev->phy.ops->phy_read(dev, srcreg));
+}
+
void b43_phy_mask(struct b43_wldev *dev, u16 offset, u16 mask)
{
b43_phy_write(dev, offset,
@@ -352,7 +359,7 @@ void b43_phy_txpower_check(struct b43_wldev *dev, unsigned int flags)
/* We must adjust the transmission power in hardware.
* Schedule b43_phy_txpower_adjust_work(). */
- queue_work(dev->wl->hw->workqueue, &dev->wl->txpower_adjust_work);
+ ieee80211_queue_work(dev->wl->hw, &dev->wl->txpower_adjust_work);
}
int b43_phy_shm_tssi_read(struct b43_wldev *dev, u16 shm_offset)
diff --git a/drivers/net/wireless/b43/phy_common.h b/drivers/net/wireless/b43/phy_common.h
index 44cc918e4fc..9f9f23cab72 100644
--- a/drivers/net/wireless/b43/phy_common.h
+++ b/drivers/net/wireless/b43/phy_common.h
@@ -291,6 +291,11 @@ u16 b43_phy_read(struct b43_wldev *dev, u16 reg);
void b43_phy_write(struct b43_wldev *dev, u16 reg, u16 value);
/**
+ * b43_phy_copy - copy contents of 16bit PHY register to another
+ */
+void b43_phy_copy(struct b43_wldev *dev, u16 destreg, u16 srcreg);
+
+/**
* b43_phy_mask - Mask a PHY register with a mask
*/
void b43_phy_mask(struct b43_wldev *dev, u16 offset, u16 mask);
diff --git a/drivers/net/wireless/b43/phy_lp.c b/drivers/net/wireless/b43/phy_lp.c
index ea0d3a3a6a6..cfb8337d385 100644
--- a/drivers/net/wireless/b43/phy_lp.c
+++ b/drivers/net/wireless/b43/phy_lp.c
@@ -59,14 +59,273 @@ static void b43_lpphy_op_free(struct b43_wldev *dev)
dev->phy.lp = NULL;
}
+static void lpphy_read_band_sprom(struct b43_wldev *dev)
+{
+ struct b43_phy_lp *lpphy = dev->phy.lp;
+ struct ssb_bus *bus = dev->dev->bus;
+ u16 cckpo, maxpwr;
+ u32 ofdmpo;
+ int i;
+
+ if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
+ lpphy->tx_isolation_med_band = bus->sprom.tri2g;
+ lpphy->bx_arch = bus->sprom.bxa2g;
+ lpphy->rx_pwr_offset = bus->sprom.rxpo2g;
+ lpphy->rssi_vf = bus->sprom.rssismf2g;
+ lpphy->rssi_vc = bus->sprom.rssismc2g;
+ lpphy->rssi_gs = bus->sprom.rssisav2g;
+ lpphy->txpa[0] = bus->sprom.pa0b0;
+ lpphy->txpa[1] = bus->sprom.pa0b1;
+ lpphy->txpa[2] = bus->sprom.pa0b2;
+ maxpwr = bus->sprom.maxpwr_bg;
+ lpphy->max_tx_pwr_med_band = maxpwr;
+ cckpo = bus->sprom.cck2gpo;
+ ofdmpo = bus->sprom.ofdm2gpo;
+ if (cckpo) {
+ for (i = 0; i < 4; i++) {
+ lpphy->tx_max_rate[i] =
+ maxpwr - (ofdmpo & 0xF) * 2;
+ ofdmpo >>= 4;
+ }
+ ofdmpo = bus->sprom.ofdm2gpo;
+ for (i = 4; i < 15; i++) {
+ lpphy->tx_max_rate[i] =
+ maxpwr - (ofdmpo & 0xF) * 2;
+ ofdmpo >>= 4;
+ }
+ } else {
+ ofdmpo &= 0xFF;
+ for (i = 0; i < 4; i++)
+ lpphy->tx_max_rate[i] = maxpwr;
+ for (i = 4; i < 15; i++)
+ lpphy->tx_max_rate[i] = maxpwr - ofdmpo;
+ }
+ } else { /* 5GHz */
+ lpphy->tx_isolation_low_band = bus->sprom.tri5gl;
+ lpphy->tx_isolation_med_band = bus->sprom.tri5g;
+ lpphy->tx_isolation_hi_band = bus->sprom.tri5gh;
+ lpphy->bx_arch = bus->sprom.bxa5g;
+ lpphy->rx_pwr_offset = bus->sprom.rxpo5g;
+ lpphy->rssi_vf = bus->sprom.rssismf5g;
+ lpphy->rssi_vc = bus->sprom.rssismc5g;
+ lpphy->rssi_gs = bus->sprom.rssisav5g;
+ lpphy->txpa[0] = bus->sprom.pa1b0;
+ lpphy->txpa[1] = bus->sprom.pa1b1;
+ lpphy->txpa[2] = bus->sprom.pa1b2;
+ lpphy->txpal[0] = bus->sprom.pa1lob0;
+ lpphy->txpal[1] = bus->sprom.pa1lob1;
+ lpphy->txpal[2] = bus->sprom.pa1lob2;
+ lpphy->txpah[0] = bus->sprom.pa1hib0;
+ lpphy->txpah[1] = bus->sprom.pa1hib1;
+ lpphy->txpah[2] = bus->sprom.pa1hib2;
+ maxpwr = bus->sprom.maxpwr_al;
+ ofdmpo = bus->sprom.ofdm5glpo;
+ lpphy->max_tx_pwr_low_band = maxpwr;
+ for (i = 4; i < 12; i++) {
+ lpphy->tx_max_ratel[i] = maxpwr - (ofdmpo & 0xF) * 2;
+ ofdmpo >>= 4;
+ }
+ maxpwr = bus->sprom.maxpwr_a;
+ ofdmpo = bus->sprom.ofdm5gpo;
+ lpphy->max_tx_pwr_med_band = maxpwr;
+ for (i = 4; i < 12; i++) {
+ lpphy->tx_max_rate[i] = maxpwr - (ofdmpo & 0xF) * 2;
+ ofdmpo >>= 4;
+ }
+ maxpwr = bus->sprom.maxpwr_ah;
+ ofdmpo = bus->sprom.ofdm5ghpo;
+ lpphy->max_tx_pwr_hi_band = maxpwr;
+ for (i = 4; i < 12; i++) {
+ lpphy->tx_max_rateh[i] = maxpwr - (ofdmpo & 0xF) * 2;
+ ofdmpo >>= 4;
+ }
+ }
+}
+
+static void lpphy_adjust_gain_table(struct b43_wldev *dev)
+{
+ struct b43_phy_lp *lpphy = dev->phy.lp;
+ u32 freq = dev->wl->hw->conf.channel->center_freq;
+ u16 temp[3];
+ u16 isolation;
+
+ B43_WARN_ON(dev->phy.rev >= 2);
+
+ if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
+ isolation = lpphy->tx_isolation_med_band;
+ else if (freq <= 5320)
+ isolation = lpphy->tx_isolation_low_band;
+ else if (freq <= 5700)
+ isolation = lpphy->tx_isolation_med_band;
+ else
+ isolation = lpphy->tx_isolation_hi_band;
+
+ temp[0] = ((isolation - 26) / 12) << 12;
+ temp[1] = temp[0] + 0x1000;
+ temp[2] = temp[0] + 0x2000;
+
+ b43_lptab_write_bulk(dev, B43_LPTAB16(12, 0), 3, temp);
+ b43_lptab_write_bulk(dev, B43_LPTAB16(13, 0), 3, temp);
+}
+
static void lpphy_table_init(struct b43_wldev *dev)
{
- //TODO
+ if (dev->phy.rev < 2)
+ lpphy_rev0_1_table_init(dev);
+ else
+ lpphy_rev2plus_table_init(dev);
+
+ lpphy_init_tx_gain_table(dev);
+
+ if (dev->phy.rev < 2)
+ lpphy_adjust_gain_table(dev);
}
static void lpphy_baseband_rev0_1_init(struct b43_wldev *dev)
{
- B43_WARN_ON(1);//TODO rev < 2 not supported, yet.
+ struct ssb_bus *bus = dev->dev->bus;
+ u16 tmp, tmp2;
+
+ if (dev->phy.rev == 1 &&
+ (bus->sprom.boardflags_hi & B43_BFH_FEM_BT)) {
+ b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_1, 0xFFC0, 0x000A);
+ b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_1, 0x3F00, 0x0900);
+ b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_2, 0xFFC0, 0x000A);
+ b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_2, 0xC0FF, 0x0B00);
+ b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_3, 0xFFC0, 0x000A);
+ b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_3, 0xC0FF, 0x0400);
+ b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_4, 0xFFC0, 0x000A);
+ b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_4, 0xC0FF, 0x0B00);
+ b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_5, 0xFFC0, 0x000A);
+ b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_5, 0xC0FF, 0x0900);
+ b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_6, 0xFFC0, 0x000A);
+ b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_6, 0xC0FF, 0x0B00);
+ b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_7, 0xFFC0, 0x000A);
+ b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_7, 0xC0FF, 0x0900);
+ b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_8, 0xFFC0, 0x000A);
+ b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_8, 0xC0FF, 0x0B00);
+ } else if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ ||
+ (bus->boardinfo.type == 0x048A) || ((dev->phy.rev == 0) &&
+ (bus->sprom.boardflags_lo & B43_BFL_FEM))) {
+ b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_1, 0xFFC0, 0x0001);
+ b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_1, 0xC0FF, 0x0400);
+ b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_2, 0xFFC0, 0x0001);
+ b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_2, 0xC0FF, 0x0500);
+ b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_3, 0xFFC0, 0x0002);
+ b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_3, 0xC0FF, 0x0800);
+ b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_4, 0xFFC0, 0x0002);
+ b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_4, 0xC0FF, 0x0A00);
+ } else if (dev->phy.rev == 1 ||
+ (bus->sprom.boardflags_lo & B43_BFL_FEM)) {
+ b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_1, 0xFFC0, 0x0004);
+ b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_1, 0xC0FF, 0x0800);
+ b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_2, 0xFFC0, 0x0004);
+ b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_2, 0xC0FF, 0x0C00);
+ b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_3, 0xFFC0, 0x0002);
+ b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_3, 0xC0FF, 0x0100);
+ b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_4, 0xFFC0, 0x0002);
+ b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_4, 0xC0FF, 0x0300);
+ } else {
+ b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_1, 0xFFC0, 0x000A);
+ b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_1, 0xC0FF, 0x0900);
+ b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_2, 0xFFC0, 0x000A);
+ b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_2, 0xC0FF, 0x0B00);
+ b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_3, 0xFFC0, 0x0006);
+ b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_3, 0xC0FF, 0x0500);
+ b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_4, 0xFFC0, 0x0006);
+ b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_4, 0xC0FF, 0x0700);
+ }
+ if (dev->phy.rev == 1) {
+ b43_phy_copy(dev, B43_LPPHY_TR_LOOKUP_5, B43_LPPHY_TR_LOOKUP_1);
+ b43_phy_copy(dev, B43_LPPHY_TR_LOOKUP_6, B43_LPPHY_TR_LOOKUP_2);
+ b43_phy_copy(dev, B43_LPPHY_TR_LOOKUP_7, B43_LPPHY_TR_LOOKUP_3);
+ b43_phy_copy(dev, B43_LPPHY_TR_LOOKUP_8, B43_LPPHY_TR_LOOKUP_4);
+ }
+ if ((bus->sprom.boardflags_hi & B43_BFH_FEM_BT) &&
+ (bus->chip_id == 0x5354) &&
+ (bus->chip_package == SSB_CHIPPACK_BCM4712S)) {
+ b43_phy_set(dev, B43_LPPHY_CRSGAIN_CTL, 0x0006);
+ b43_phy_write(dev, B43_LPPHY_GPIO_SELECT, 0x0005);
+ b43_phy_write(dev, B43_LPPHY_GPIO_OUTEN, 0xFFFF);
+ b43_hf_write(dev, b43_hf_read(dev) | B43_HF_PR45960W);
+ }
+ if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
+ b43_phy_set(dev, B43_LPPHY_LP_PHY_CTL, 0x8000);
+ b43_phy_set(dev, B43_LPPHY_CRSGAIN_CTL, 0x0040);
+ b43_phy_maskset(dev, B43_LPPHY_MINPWR_LEVEL, 0x00FF, 0xA400);
+ b43_phy_maskset(dev, B43_LPPHY_CRSGAIN_CTL, 0xF0FF, 0x0B00);
+ b43_phy_maskset(dev, B43_LPPHY_SYNCPEAKCNT, 0xFFF8, 0x0007);
+ b43_phy_maskset(dev, B43_LPPHY_DSSS_CONFIRM_CNT, 0xFFF8, 0x0003);
+ b43_phy_maskset(dev, B43_LPPHY_DSSS_CONFIRM_CNT, 0xFFC7, 0x0020);
+ b43_phy_mask(dev, B43_LPPHY_IDLEAFTERPKTRXTO, 0x00FF);
+ } else { /* 5GHz */
+ b43_phy_mask(dev, B43_LPPHY_LP_PHY_CTL, 0x7FFF);
+ b43_phy_mask(dev, B43_LPPHY_CRSGAIN_CTL, 0xFFBF);
+ }
+ if (dev->phy.rev == 1) {
+ tmp = b43_phy_read(dev, B43_LPPHY_CLIPCTRTHRESH);
+ tmp2 = (tmp & 0x03E0) >> 5;
+ tmp2 |= tmp << 5;
+ b43_phy_write(dev, B43_LPPHY_4C3, tmp2);
+ tmp = b43_phy_read(dev, B43_LPPHY_OFDMSYNCTHRESH0);
+ tmp2 = (tmp & 0x1F00) >> 8;
+ tmp2 |= tmp << 5;
+ b43_phy_write(dev, B43_LPPHY_4C4, tmp2);
+ tmp = b43_phy_read(dev, B43_LPPHY_VERYLOWGAINDB);
+ tmp2 = tmp & 0x00FF;
+ tmp2 |= tmp << 8;
+ b43_phy_write(dev, B43_LPPHY_4C5, tmp2);
+ }
+}
+
+static void lpphy_save_dig_flt_state(struct b43_wldev *dev)
+{
+ static const u16 addr[] = {
+ B43_PHY_OFDM(0xC1),
+ B43_PHY_OFDM(0xC2),
+ B43_PHY_OFDM(0xC3),
+ B43_PHY_OFDM(0xC4),
+ B43_PHY_OFDM(0xC5),
+ B43_PHY_OFDM(0xC6),
+ B43_PHY_OFDM(0xC7),
+ B43_PHY_OFDM(0xC8),
+ B43_PHY_OFDM(0xCF),
+ };
+
+ static const u16 coefs[] = {
+ 0xDE5E, 0xE832, 0xE331, 0x4D26,
+ 0x0026, 0x1420, 0x0020, 0xFE08,
+ 0x0008,
+ };
+
+ struct b43_phy_lp *lpphy = dev->phy.lp;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(addr); i++) {
+ lpphy->dig_flt_state[i] = b43_phy_read(dev, addr[i]);
+ b43_phy_write(dev, addr[i], coefs[i]);
+ }
+}
+
+static void lpphy_restore_dig_flt_state(struct b43_wldev *dev)
+{
+ static const u16 addr[] = {
+ B43_PHY_OFDM(0xC1),
+ B43_PHY_OFDM(0xC2),
+ B43_PHY_OFDM(0xC3),
+ B43_PHY_OFDM(0xC4),
+ B43_PHY_OFDM(0xC5),
+ B43_PHY_OFDM(0xC6),
+ B43_PHY_OFDM(0xC7),
+ B43_PHY_OFDM(0xC8),
+ B43_PHY_OFDM(0xCF),
+ };
+
+ struct b43_phy_lp *lpphy = dev->phy.lp;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(addr); i++)
+ b43_phy_write(dev, addr[i], lpphy->dig_flt_state[i]);
}
static void lpphy_baseband_rev2plus_init(struct b43_wldev *dev)
@@ -83,7 +342,7 @@ static void lpphy_baseband_rev2plus_init(struct b43_wldev *dev)
b43_phy_write(dev, B43_PHY_OFDM(0xF9), 0);
b43_phy_write(dev, B43_LPPHY_TR_LOOKUP_1, 0);
b43_phy_set(dev, B43_LPPHY_ADC_COMPENSATION_CTL, 0x10);
- b43_phy_maskset(dev, B43_LPPHY_OFDMSYNCTHRESH0, 0xFF00, 0x78);
+ b43_phy_maskset(dev, B43_LPPHY_OFDMSYNCTHRESH0, 0xFF00, 0xB4);
b43_phy_maskset(dev, B43_LPPHY_DCOFFSETTRANSIENT, 0xF8FF, 0x200);
b43_phy_maskset(dev, B43_LPPHY_DCOFFSETTRANSIENT, 0xFF00, 0x7F);
b43_phy_maskset(dev, B43_LPPHY_GAINDIRECTMISMATCH, 0xFF0F, 0x40);
@@ -91,7 +350,12 @@ static void lpphy_baseband_rev2plus_init(struct b43_wldev *dev)
b43_phy_mask(dev, B43_LPPHY_CRSGAIN_CTL, ~0x4000);
b43_phy_mask(dev, B43_LPPHY_CRSGAIN_CTL, ~0x2000);
b43_phy_set(dev, B43_PHY_OFDM(0x10A), 0x1);
- b43_phy_maskset(dev, B43_PHY_OFDM(0x10A), 0xFF01, 0x10);
+ if (bus->boardinfo.rev >= 0x18) {
+ b43_lptab_write(dev, B43_LPTAB32(17, 65), 0xEC);
+ b43_phy_maskset(dev, B43_PHY_OFDM(0x10A), 0xFF01, 0x14);
+ } else {
+ b43_phy_maskset(dev, B43_PHY_OFDM(0x10A), 0xFF01, 0x10);
+ }
b43_phy_maskset(dev, B43_PHY_OFDM(0xDF), 0xFF00, 0xF4);
b43_phy_maskset(dev, B43_PHY_OFDM(0xDF), 0x00FF, 0xF100);
b43_phy_write(dev, B43_LPPHY_CLIPTHRESH, 0x48);
@@ -121,8 +385,10 @@ static void lpphy_baseband_rev2plus_init(struct b43_wldev *dev)
b43_phy_maskset(dev, B43_LPPHY_CLIPCTRTHRESH, 0xFFE0, 0x12);
b43_phy_maskset(dev, B43_LPPHY_GAINMISMATCH, 0x0FFF, 0x9000);
- b43_lptab_write(dev, B43_LPTAB16(0x08, 0x14), 0);
- b43_lptab_write(dev, B43_LPTAB16(0x08, 0x12), 0x40);
+ if ((bus->chip_id == 0x4325) && (bus->chip_rev == 1)) {
+ b43_lptab_write(dev, B43_LPTAB16(0x08, 0x14), 0);
+ b43_lptab_write(dev, B43_LPTAB16(0x08, 0x12), 0x40);
+ }
if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
b43_phy_set(dev, B43_LPPHY_CRSGAIN_CTL, 0x40);
@@ -142,6 +408,14 @@ static void lpphy_baseband_rev2plus_init(struct b43_wldev *dev)
b43_phy_write(dev, B43_LPPHY_AFE_RSSI_CTL_1,
0x2000 | ((u16)lpphy->rssi_gs << 10) |
((u16)lpphy->rssi_vc << 4) | lpphy->rssi_vf);
+
+ if ((bus->chip_id == 0x4325) && (bus->chip_rev == 0)) {
+ b43_phy_set(dev, B43_LPPHY_AFE_ADC_CTL_0, 0x1C);
+ b43_phy_maskset(dev, B43_LPPHY_AFE_CTL, 0x00FF, 0x8800);
+ b43_phy_maskset(dev, B43_LPPHY_AFE_ADC_CTL_1, 0xFC3C, 0x0400);
+ }
+
+ lpphy_save_dig_flt_state(dev);
}
static void lpphy_baseband_init(struct b43_wldev *dev)
@@ -241,12 +515,73 @@ static void lpphy_2062_init(struct b43_wldev *dev)
/* Initialize the 2063 radio. */
static void lpphy_2063_init(struct b43_wldev *dev)
{
- //TODO
+ b2063_upload_init_table(dev);
+ b43_radio_write(dev, B2063_LOGEN_SP5, 0);
+ b43_radio_set(dev, B2063_COMM8, 0x38);
+ b43_radio_write(dev, B2063_REG_SP1, 0x56);
+ b43_radio_mask(dev, B2063_RX_BB_CTL2, ~0x2);
+ b43_radio_write(dev, B2063_PA_SP7, 0);
+ b43_radio_write(dev, B2063_TX_RF_SP6, 0x20);
+ b43_radio_write(dev, B2063_TX_RF_SP9, 0x40);
+ b43_radio_write(dev, B2063_PA_SP3, 0xa0);
+ b43_radio_write(dev, B2063_PA_SP4, 0xa0);
+ b43_radio_write(dev, B2063_PA_SP2, 0x18);
}
+struct lpphy_stx_table_entry {
+ u16 phy_offset;
+ u16 phy_shift;
+ u16 rf_addr;
+ u16 rf_shift;
+ u16 mask;
+};
+
+static const struct lpphy_stx_table_entry lpphy_stx_table[] = {
+ { .phy_offset = 2, .phy_shift = 6, .rf_addr = 0x3d, .rf_shift = 3, .mask = 0x01, },
+ { .phy_offset = 1, .phy_shift = 12, .rf_addr = 0x4c, .rf_shift = 1, .mask = 0x01, },
+ { .phy_offset = 1, .phy_shift = 8, .rf_addr = 0x50, .rf_shift = 0, .mask = 0x7f, },
+ { .phy_offset = 0, .phy_shift = 8, .rf_addr = 0x44, .rf_shift = 0, .mask = 0xff, },
+ { .phy_offset = 1, .phy_shift = 0, .rf_addr = 0x4a, .rf_shift = 0, .mask = 0xff, },
+ { .phy_offset = 0, .phy_shift = 4, .rf_addr = 0x4d, .rf_shift = 0, .mask = 0xff, },
+ { .phy_offset = 1, .phy_shift = 4, .rf_addr = 0x4e, .rf_shift = 0, .mask = 0xff, },
+ { .phy_offset = 0, .phy_shift = 12, .rf_addr = 0x4f, .rf_shift = 0, .mask = 0x0f, },
+ { .phy_offset = 1, .phy_shift = 0, .rf_addr = 0x4f, .rf_shift = 4, .mask = 0x0f, },
+ { .phy_offset = 3, .phy_shift = 0, .rf_addr = 0x49, .rf_shift = 0, .mask = 0x0f, },
+ { .phy_offset = 4, .phy_shift = 3, .rf_addr = 0x46, .rf_shift = 4, .mask = 0x07, },
+ { .phy_offset = 3, .phy_shift = 15, .rf_addr = 0x46, .rf_shift = 0, .mask = 0x01, },
+ { .phy_offset = 4, .phy_shift = 0, .rf_addr = 0x46, .rf_shift = 1, .mask = 0x07, },
+ { .phy_offset = 3, .phy_shift = 8, .rf_addr = 0x48, .rf_shift = 4, .mask = 0x07, },
+ { .phy_offset = 3, .phy_shift = 11, .rf_addr = 0x48, .rf_shift = 0, .mask = 0x0f, },
+ { .phy_offset = 3, .phy_shift = 4, .rf_addr = 0x49, .rf_shift = 4, .mask = 0x0f, },
+ { .phy_offset = 2, .phy_shift = 15, .rf_addr = 0x45, .rf_shift = 0, .mask = 0x01, },
+ { .phy_offset = 5, .phy_shift = 13, .rf_addr = 0x52, .rf_shift = 4, .mask = 0x07, },
+ { .phy_offset = 6, .phy_shift = 0, .rf_addr = 0x52, .rf_shift = 7, .mask = 0x01, },
+ { .phy_offset = 5, .phy_shift = 3, .rf_addr = 0x41, .rf_shift = 5, .mask = 0x07, },
+ { .phy_offset = 5, .phy_shift = 6, .rf_addr = 0x41, .rf_shift = 0, .mask = 0x0f, },
+ { .phy_offset = 5, .phy_shift = 10, .rf_addr = 0x42, .rf_shift = 5, .mask = 0x07, },
+ { .phy_offset = 4, .phy_shift = 15, .rf_addr = 0x42, .rf_shift = 0, .mask = 0x01, },
+ { .phy_offset = 5, .phy_shift = 0, .rf_addr = 0x42, .rf_shift = 1, .mask = 0x07, },
+ { .phy_offset = 4, .phy_shift = 11, .rf_addr = 0x43, .rf_shift = 4, .mask = 0x0f, },
+ { .phy_offset = 4, .phy_shift = 7, .rf_addr = 0x43, .rf_shift = 0, .mask = 0x0f, },
+ { .phy_offset = 4, .phy_shift = 6, .rf_addr = 0x45, .rf_shift = 1, .mask = 0x01, },
+ { .phy_offset = 2, .phy_shift = 7, .rf_addr = 0x40, .rf_shift = 4, .mask = 0x0f, },
+ { .phy_offset = 2, .phy_shift = 11, .rf_addr = 0x40, .rf_shift = 0, .mask = 0x0f, },
+};
+
static void lpphy_sync_stx(struct b43_wldev *dev)
{
- //TODO
+ const struct lpphy_stx_table_entry *e;
+ unsigned int i;
+ u16 tmp;
+
+ for (i = 0; i < ARRAY_SIZE(lpphy_stx_table); i++) {
+ e = &lpphy_stx_table[i];
+ tmp = b43_radio_read(dev, e->rf_addr);
+ tmp >>= e->rf_shift;
+ tmp <<= e->phy_shift;
+ b43_phy_maskset(dev, B43_PHY_OFDM(0xF2 + e->phy_offset),
+ ~(e->mask << e->phy_shift), tmp);
+ }
}
static void lpphy_radio_init(struct b43_wldev *dev)
@@ -264,8 +599,343 @@ static void lpphy_radio_init(struct b43_wldev *dev)
lpphy_sync_stx(dev);
b43_phy_write(dev, B43_PHY_OFDM(0xF0), 0x5F80);
b43_phy_write(dev, B43_PHY_OFDM(0xF1), 0);
- //TODO Do something on the backplane
+ if (dev->dev->bus->chip_id == 0x4325) {
+ // TODO SSB PMU recalibration
+ }
+ }
+}
+
+struct lpphy_iq_est { u32 iq_prod, i_pwr, q_pwr; };
+
+static void lpphy_set_rc_cap(struct b43_wldev *dev)
+{
+ u8 rc_cap = dev->phy.lp->rc_cap;
+
+ b43_radio_write(dev, B2062_N_RXBB_CALIB2, max_t(u8, rc_cap-4, 0x80));
+ b43_radio_write(dev, B2062_N_TX_CTL_A, ((rc_cap & 0x1F) >> 1) | 0x80);
+ b43_radio_write(dev, B2062_S_RXG_CNT16, ((rc_cap & 0x1F) >> 2) | 0x80);
+}
+
+static u8 lpphy_get_bb_mult(struct b43_wldev *dev)
+{
+ return (b43_lptab_read(dev, B43_LPTAB16(0, 87)) & 0xFF00) >> 8;
+}
+
+static void lpphy_set_bb_mult(struct b43_wldev *dev, u8 bb_mult)
+{
+ b43_lptab_write(dev, B43_LPTAB16(0, 87), (u16)bb_mult << 8);
+}
+
+static void lpphy_disable_crs(struct b43_wldev *dev)
+{
+ b43_phy_maskset(dev, B43_LPPHY_CRSGAIN_CTL, 0xFF1F, 0x80);
+ b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFFC, 0x1);
+ b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x3);
+ b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFFB);
+ b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x4);
+ b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFFF7);
+ b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x8);
+ b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0x10);
+ b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x10);
+ b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFDF);
+ b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x20);
+ b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFBF);
+ b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x40);
+ b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0x7);
+ b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0x38);
+ b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0xFF3F);
+ b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0x100);
+ b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0xFDFF);
+ b43_phy_write(dev, B43_LPPHY_PS_CTL_OVERRIDE_VAL0, 0);
+ b43_phy_write(dev, B43_LPPHY_PS_CTL_OVERRIDE_VAL1, 1);
+ b43_phy_write(dev, B43_LPPHY_PS_CTL_OVERRIDE_VAL2, 0x20);
+ b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0xFBFF);
+ b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0xF7FF);
+ b43_phy_write(dev, B43_LPPHY_TX_GAIN_CTL_OVERRIDE_VAL, 0);
+ b43_phy_write(dev, B43_LPPHY_RX_GAIN_CTL_OVERRIDE_VAL, 0x45AF);
+ b43_phy_write(dev, B43_LPPHY_RF_OVERRIDE_2, 0x3FF);
+}
+
+static void lpphy_restore_crs(struct b43_wldev *dev)
+{
+ if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
+ b43_phy_maskset(dev, B43_LPPHY_CRSGAIN_CTL, 0xFF1F, 0x60);
+ else
+ b43_phy_maskset(dev, B43_LPPHY_CRSGAIN_CTL, 0xFF1F, 0x20);
+ b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFF80);
+ b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFC00);
+}
+
+struct lpphy_tx_gains { u16 gm, pga, pad, dac; };
+
+static struct lpphy_tx_gains lpphy_get_tx_gains(struct b43_wldev *dev)
+{
+ struct lpphy_tx_gains gains;
+ u16 tmp;
+
+ gains.dac = (b43_phy_read(dev, B43_LPPHY_AFE_DAC_CTL) & 0x380) >> 7;
+ if (dev->phy.rev < 2) {
+ tmp = b43_phy_read(dev,
+ B43_LPPHY_TX_GAIN_CTL_OVERRIDE_VAL) & 0x7FF;
+ gains.gm = tmp & 0x0007;
+ gains.pga = (tmp & 0x0078) >> 3;
+ gains.pad = (tmp & 0x780) >> 7;
+ } else {
+ tmp = b43_phy_read(dev, B43_LPPHY_TX_GAIN_CTL_OVERRIDE_VAL);
+ gains.pad = b43_phy_read(dev, B43_PHY_OFDM(0xFB)) & 0xFF;
+ gains.gm = tmp & 0xFF;
+ gains.pga = (tmp >> 8) & 0xFF;
}
+
+ return gains;
+}
+
+static void lpphy_set_dac_gain(struct b43_wldev *dev, u16 dac)
+{
+ u16 ctl = b43_phy_read(dev, B43_LPPHY_AFE_DAC_CTL) & 0xC7F;
+ ctl |= dac << 7;
+ b43_phy_maskset(dev, B43_LPPHY_AFE_DAC_CTL, 0xF000, ctl);
+}
+
+static void lpphy_set_tx_gains(struct b43_wldev *dev,
+ struct lpphy_tx_gains gains)
+{
+ u16 rf_gain, pa_gain;
+
+ if (dev->phy.rev < 2) {
+ rf_gain = (gains.pad << 7) | (gains.pga << 3) | gains.gm;
+ b43_phy_maskset(dev, B43_LPPHY_TX_GAIN_CTL_OVERRIDE_VAL,
+ 0xF800, rf_gain);
+ } else {
+ pa_gain = b43_phy_read(dev, B43_PHY_OFDM(0xFB)) & 0x7F00;
+ b43_phy_write(dev, B43_LPPHY_TX_GAIN_CTL_OVERRIDE_VAL,
+ (gains.pga << 8) | gains.gm);
+ b43_phy_maskset(dev, B43_LPPHY_TX_GAIN_CTL_OVERRIDE_VAL,
+ 0x8000, gains.pad | pa_gain);
+ b43_phy_write(dev, B43_PHY_OFDM(0xFC),
+ (gains.pga << 8) | gains.gm);
+ b43_phy_maskset(dev, B43_PHY_OFDM(0xFD),
+ 0x8000, gains.pad | pa_gain);
+ }
+ lpphy_set_dac_gain(dev, gains.dac);
+ if (dev->phy.rev < 2) {
+ b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFEFF, 1 << 8);
+ } else {
+ b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFF7F, 1 << 7);
+ b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2, 0xBFFF, 1 << 14);
+ }
+ b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFFBF, 1 << 4);
+}
+
+static void lpphy_rev0_1_set_rx_gain(struct b43_wldev *dev, u32 gain)
+{
+ u16 trsw = gain & 0x1;
+ u16 lna = (gain & 0xFFFC) | ((gain & 0xC) >> 2);
+ u16 ext_lna = (gain & 2) >> 1;
+
+ b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFFE, trsw);
+ b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2_VAL,
+ 0xFBFF, ext_lna << 10);
+ b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2_VAL,
+ 0xF7FF, ext_lna << 11);
+ b43_phy_write(dev, B43_LPPHY_RX_GAIN_CTL_OVERRIDE_VAL, lna);
+}
+
+static void lpphy_rev2plus_set_rx_gain(struct b43_wldev *dev, u32 gain)
+{
+ u16 low_gain = gain & 0xFFFF;
+ u16 high_gain = (gain >> 16) & 0xF;
+ u16 ext_lna = (gain >> 21) & 0x1;
+ u16 trsw = ~(gain >> 20) & 0x1;
+ u16 tmp;
+
+ b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFFE, trsw);
+ b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2_VAL,
+ 0xFDFF, ext_lna << 9);
+ b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2_VAL,
+ 0xFBFF, ext_lna << 10);
+ b43_phy_write(dev, B43_LPPHY_RX_GAIN_CTL_OVERRIDE_VAL, low_gain);
+ b43_phy_maskset(dev, B43_LPPHY_AFE_DDFS, 0xFFF0, high_gain);
+ if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
+ tmp = (gain >> 2) & 0x3;
+ b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2_VAL,
+ 0xE7FF, tmp<<11);
+ b43_phy_maskset(dev, B43_PHY_OFDM(0xE6), 0xFFE7, tmp << 3);
+ }
+}
+
+static void lpphy_enable_rx_gain_override(struct b43_wldev *dev)
+{
+ b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFFFE);
+ b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFFEF);
+ b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFFBF);
+ if (dev->phy.rev >= 2) {
+ b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFEFF);
+ if (b43_current_band(dev->wl) != IEEE80211_BAND_2GHZ)
+ return;
+ b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFBFF);
+ b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFFF7);
+ } else {
+ b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFDFF);
+ }
+}
+
+static void lpphy_disable_rx_gain_override(struct b43_wldev *dev)
+{
+ b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x1);
+ b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x10);
+ b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x40);
+ if (dev->phy.rev >= 2) {
+ b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2, 0x100);
+ if (b43_current_band(dev->wl) != IEEE80211_BAND_2GHZ)
+ return;
+ b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2, 0x400);
+ b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2, 0x8);
+ } else {
+ b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2, 0x200);
+ }
+}
+
+static void lpphy_set_rx_gain(struct b43_wldev *dev, u32 gain)
+{
+ if (dev->phy.rev < 2)
+ lpphy_rev0_1_set_rx_gain(dev, gain);
+ else
+ lpphy_rev2plus_set_rx_gain(dev, gain);
+ lpphy_enable_rx_gain_override(dev);
+}
+
+static void lpphy_set_rx_gain_by_index(struct b43_wldev *dev, u16 idx)
+{
+ u32 gain = b43_lptab_read(dev, B43_LPTAB16(12, idx));
+ lpphy_set_rx_gain(dev, gain);
+}
+
+static void lpphy_stop_ddfs(struct b43_wldev *dev)
+{
+ b43_phy_mask(dev, B43_LPPHY_AFE_DDFS, 0xFFFD);
+ b43_phy_mask(dev, B43_LPPHY_LP_PHY_CTL, 0xFFDF);
+}
+
+static void lpphy_run_ddfs(struct b43_wldev *dev, int i_on, int q_on,
+ int incr1, int incr2, int scale_idx)
+{
+ lpphy_stop_ddfs(dev);
+ b43_phy_mask(dev, B43_LPPHY_AFE_DDFS_POINTER_INIT, 0xFF80);
+ b43_phy_mask(dev, B43_LPPHY_AFE_DDFS_POINTER_INIT, 0x80FF);
+ b43_phy_maskset(dev, B43_LPPHY_AFE_DDFS_INCR_INIT, 0xFF80, incr1);
+ b43_phy_maskset(dev, B43_LPPHY_AFE_DDFS_INCR_INIT, 0x80FF, incr2 << 8);
+ b43_phy_maskset(dev, B43_LPPHY_AFE_DDFS, 0xFFF7, i_on << 3);
+ b43_phy_maskset(dev, B43_LPPHY_AFE_DDFS, 0xFFEF, q_on << 4);
+ b43_phy_maskset(dev, B43_LPPHY_AFE_DDFS, 0xFF9F, scale_idx << 5);
+ b43_phy_mask(dev, B43_LPPHY_AFE_DDFS, 0xFFFB);
+ b43_phy_set(dev, B43_LPPHY_AFE_DDFS, 0x2);
+ b43_phy_set(dev, B43_LPPHY_AFE_DDFS, 0x20);
+}
+
+static bool lpphy_rx_iq_est(struct b43_wldev *dev, u16 samples, u8 time,
+ struct lpphy_iq_est *iq_est)
+{
+ int i;
+
+ b43_phy_mask(dev, B43_LPPHY_CRSGAIN_CTL, 0xFFF7);
+ b43_phy_write(dev, B43_LPPHY_IQ_NUM_SMPLS_ADDR, samples);
+ b43_phy_maskset(dev, B43_LPPHY_IQ_ENABLE_WAIT_TIME_ADDR, 0xFF00, time);
+ b43_phy_mask(dev, B43_LPPHY_IQ_ENABLE_WAIT_TIME_ADDR, 0xFEFF);
+ b43_phy_set(dev, B43_LPPHY_IQ_ENABLE_WAIT_TIME_ADDR, 0xFDFF);
+
+ for (i = 0; i < 500; i++) {
+ if (!(b43_phy_read(dev,
+ B43_LPPHY_IQ_ENABLE_WAIT_TIME_ADDR) & 0x200))
+ break;
+ msleep(1);
+ }
+
+ if ((b43_phy_read(dev, B43_LPPHY_IQ_ENABLE_WAIT_TIME_ADDR) & 0x200)) {
+ b43_phy_set(dev, B43_LPPHY_CRSGAIN_CTL, 0x8);
+ return false;
+ }
+
+ iq_est->iq_prod = b43_phy_read(dev, B43_LPPHY_IQ_ACC_HI_ADDR);
+ iq_est->iq_prod <<= 16;
+ iq_est->iq_prod |= b43_phy_read(dev, B43_LPPHY_IQ_ACC_LO_ADDR);
+
+ iq_est->i_pwr = b43_phy_read(dev, B43_LPPHY_IQ_I_PWR_ACC_HI_ADDR);
+ iq_est->i_pwr <<= 16;
+ iq_est->i_pwr |= b43_phy_read(dev, B43_LPPHY_IQ_I_PWR_ACC_LO_ADDR);
+
+ iq_est->q_pwr = b43_phy_read(dev, B43_LPPHY_IQ_Q_PWR_ACC_HI_ADDR);
+ iq_est->q_pwr <<= 16;
+ iq_est->q_pwr |= b43_phy_read(dev, B43_LPPHY_IQ_Q_PWR_ACC_LO_ADDR);
+
+ b43_phy_set(dev, B43_LPPHY_CRSGAIN_CTL, 0x8);
+ return true;
+}
+
+static int lpphy_loopback(struct b43_wldev *dev)
+{
+ struct lpphy_iq_est iq_est;
+ int i, index = -1;
+ u32 tmp;
+
+ memset(&iq_est, 0, sizeof(iq_est));
+
+ b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFFC, 0x3);
+ b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x3);
+ b43_phy_mask(dev, B43_LPPHY_AFE_CTL_OVRVAL, 0xFFFE);
+ b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x800);
+ b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0x800);
+ b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x8);
+ b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0x8);
+ b43_radio_write(dev, B2062_N_TX_CTL_A, 0x80);
+ b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x80);
+ b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0x80);
+ for (i = 0; i < 32; i++) {
+ lpphy_set_rx_gain_by_index(dev, i);
+ lpphy_run_ddfs(dev, 1, 1, 5, 5, 0);
+ if (!(lpphy_rx_iq_est(dev, 1000, 32, &iq_est)))
+ continue;
+ tmp = (iq_est.i_pwr + iq_est.q_pwr) / 1000;
+ if ((tmp > 4000) && (tmp < 10000)) {
+ index = i;
+ break;
+ }
+ }
+ lpphy_stop_ddfs(dev);
+ return index;
+}
+
+static u32 lpphy_qdiv_roundup(u32 dividend, u32 divisor, u8 precision)
+{
+ u32 quotient, remainder, rbit, roundup, tmp;
+
+ if (divisor == 0) {
+ quotient = 0;
+ remainder = 0;
+ } else {
+ quotient = dividend / divisor;
+ remainder = dividend % divisor;
+ }
+
+ rbit = divisor & 0x1;
+ roundup = (divisor >> 1) + rbit;
+ precision--;
+
+ while (precision != 0xFF) {
+ tmp = remainder - roundup;
+ quotient <<= 1;
+ remainder <<= 1;
+ if (remainder >= roundup) {
+ remainder = (tmp << 1) + rbit;
+ quotient--;
+ }
+ precision--;
+ }
+
+ if (remainder >= roundup)
+ quotient++;
+
+ return quotient;
}
/* Read the TX power control mode from hardware. */
@@ -352,6 +1022,170 @@ static void lpphy_set_tx_power_control(struct b43_wldev *dev,
lpphy_write_tx_pctl_mode_to_hardware(dev);
}
+static void lpphy_rev0_1_rc_calib(struct b43_wldev *dev)
+{
+ struct b43_phy_lp *lpphy = dev->phy.lp;
+ struct lpphy_iq_est iq_est;
+ struct lpphy_tx_gains tx_gains;
+ static const u32 ideal_pwr_table[22] = {
+ 0x10000, 0x10557, 0x10e2d, 0x113e0, 0x10f22, 0x0ff64,
+ 0x0eda2, 0x0e5d4, 0x0efd1, 0x0fbe8, 0x0b7b8, 0x04b35,
+ 0x01a5e, 0x00a0b, 0x00444, 0x001fd, 0x000ff, 0x00088,
+ 0x0004c, 0x0002c, 0x0001a, 0xc0006,
+ };
+ bool old_txg_ovr;
+ u8 old_bbmult;
+ u16 old_rf_ovr, old_rf_ovrval, old_afe_ovr, old_afe_ovrval,
+ old_rf2_ovr, old_rf2_ovrval, old_phy_ctl, old_txpctl;
+ u32 normal_pwr, ideal_pwr, mean_sq_pwr, tmp = 0, mean_sq_pwr_min = 0;
+ int loopback, i, j, inner_sum;
+
+ memset(&iq_est, 0, sizeof(iq_est));
+
+ b43_switch_channel(dev, 7);
+ old_txg_ovr = (b43_phy_read(dev, B43_LPPHY_AFE_CTL_OVR) >> 6) & 1;
+ old_bbmult = lpphy_get_bb_mult(dev);
+ if (old_txg_ovr)
+ tx_gains = lpphy_get_tx_gains(dev);
+ old_rf_ovr = b43_phy_read(dev, B43_LPPHY_RF_OVERRIDE_0);
+ old_rf_ovrval = b43_phy_read(dev, B43_LPPHY_RF_OVERRIDE_VAL_0);
+ old_afe_ovr = b43_phy_read(dev, B43_LPPHY_AFE_CTL_OVR);
+ old_afe_ovrval = b43_phy_read(dev, B43_LPPHY_AFE_CTL_OVRVAL);
+ old_rf2_ovr = b43_phy_read(dev, B43_LPPHY_RF_OVERRIDE_2);
+ old_rf2_ovrval = b43_phy_read(dev, B43_LPPHY_RF_OVERRIDE_2_VAL);
+ old_phy_ctl = b43_phy_read(dev, B43_LPPHY_LP_PHY_CTL);
+ old_txpctl = b43_phy_read(dev, B43_LPPHY_TX_PWR_CTL_CMD) &
+ B43_LPPHY_TX_PWR_CTL_CMD_MODE;
+
+ lpphy_set_tx_power_control(dev, B43_LPPHY_TX_PWR_CTL_CMD_MODE_OFF);
+ lpphy_disable_crs(dev);
+ loopback = lpphy_loopback(dev);
+ if (loopback == -1)
+ goto finish;
+ lpphy_set_rx_gain_by_index(dev, loopback);
+ b43_phy_maskset(dev, B43_LPPHY_LP_PHY_CTL, 0xFFBF, 0x40);
+ b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0xFFF8, 0x1);
+ b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0xFFC7, 0x8);
+ b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0xFF3F, 0xC0);
+ for (i = 128; i <= 159; i++) {
+ b43_radio_write(dev, B2062_N_RXBB_CALIB2, i);
+ inner_sum = 0;
+ for (j = 5; j <= 25; j++) {
+ lpphy_run_ddfs(dev, 1, 1, j, j, 0);
+ if (!(lpphy_rx_iq_est(dev, 1000, 32, &iq_est)))
+ goto finish;
+ mean_sq_pwr = iq_est.i_pwr + iq_est.q_pwr;
+ if (j == 5)
+ tmp = mean_sq_pwr;
+ ideal_pwr = ((ideal_pwr_table[j-5] >> 3) + 1) >> 1;
+ normal_pwr = lpphy_qdiv_roundup(mean_sq_pwr, tmp, 12);
+ mean_sq_pwr = ideal_pwr - normal_pwr;
+ mean_sq_pwr *= mean_sq_pwr;
+ inner_sum += mean_sq_pwr;
+ if ((i = 128) || (inner_sum < mean_sq_pwr_min)) {
+ lpphy->rc_cap = i;
+ mean_sq_pwr_min = inner_sum;
+ }
+ }
+ }
+ lpphy_stop_ddfs(dev);
+
+finish:
+ lpphy_restore_crs(dev);
+ b43_phy_write(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, old_rf_ovrval);
+ b43_phy_write(dev, B43_LPPHY_RF_OVERRIDE_0, old_rf_ovr);
+ b43_phy_write(dev, B43_LPPHY_AFE_CTL_OVRVAL, old_afe_ovrval);
+ b43_phy_write(dev, B43_LPPHY_AFE_CTL_OVR, old_afe_ovr);
+ b43_phy_write(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, old_rf2_ovrval);
+ b43_phy_write(dev, B43_LPPHY_RF_OVERRIDE_2, old_rf2_ovr);
+ b43_phy_write(dev, B43_LPPHY_LP_PHY_CTL, old_phy_ctl);
+
+ lpphy_set_bb_mult(dev, old_bbmult);
+ if (old_txg_ovr) {
+ /*
+ * SPEC FIXME: The specs say "get_tx_gains" here, which is
+ * illogical. According to lwfinger, vendor driver v4.150.10.5
+ * has a Set here, while v4.174.64.19 has a Get - regression in
+ * the vendor driver? This should be tested this once the code
+ * is testable.
+ */
+ lpphy_set_tx_gains(dev, tx_gains);
+ }
+ lpphy_set_tx_power_control(dev, old_txpctl);
+ if (lpphy->rc_cap)
+ lpphy_set_rc_cap(dev);
+}
+
+static void lpphy_rev2plus_rc_calib(struct b43_wldev *dev)
+{
+ struct ssb_bus *bus = dev->dev->bus;
+ u32 crystal_freq = bus->chipco.pmu.crystalfreq * 1000;
+ u8 tmp = b43_radio_read(dev, B2063_RX_BB_SP8) & 0xFF;
+ int i;
+
+ b43_radio_write(dev, B2063_RX_BB_SP8, 0x0);
+ b43_radio_write(dev, B2063_RC_CALIB_CTL1, 0x7E);
+ b43_radio_mask(dev, B2063_PLL_SP1, 0xF7);
+ b43_radio_write(dev, B2063_RC_CALIB_CTL1, 0x7C);
+ b43_radio_write(dev, B2063_RC_CALIB_CTL2, 0x15);
+ b43_radio_write(dev, B2063_RC_CALIB_CTL3, 0x70);
+ b43_radio_write(dev, B2063_RC_CALIB_CTL4, 0x52);
+ b43_radio_write(dev, B2063_RC_CALIB_CTL5, 0x1);
+ b43_radio_write(dev, B2063_RC_CALIB_CTL1, 0x7D);
+
+ for (i = 0; i < 10000; i++) {
+ if (b43_radio_read(dev, B2063_RC_CALIB_CTL6) & 0x2)
+ break;
+ msleep(1);
+ }
+
+ if (!(b43_radio_read(dev, B2063_RC_CALIB_CTL6) & 0x2))
+ b43_radio_write(dev, B2063_RX_BB_SP8, tmp);
+
+ tmp = b43_radio_read(dev, B2063_TX_BB_SP3) & 0xFF;
+
+ b43_radio_write(dev, B2063_TX_BB_SP3, 0x0);
+ b43_radio_write(dev, B2063_RC_CALIB_CTL1, 0x7E);
+ b43_radio_write(dev, B2063_RC_CALIB_CTL1, 0x7C);
+ b43_radio_write(dev, B2063_RC_CALIB_CTL2, 0x55);
+ b43_radio_write(dev, B2063_RC_CALIB_CTL3, 0x76);
+
+ if (crystal_freq == 24000000) {
+ b43_radio_write(dev, B2063_RC_CALIB_CTL4, 0xFC);
+ b43_radio_write(dev, B2063_RC_CALIB_CTL5, 0x0);
+ } else {
+ b43_radio_write(dev, B2063_RC_CALIB_CTL4, 0x13);
+ b43_radio_write(dev, B2063_RC_CALIB_CTL5, 0x1);
+ }
+
+ b43_radio_write(dev, B2063_PA_SP7, 0x7D);
+
+ for (i = 0; i < 10000; i++) {
+ if (b43_radio_read(dev, B2063_RC_CALIB_CTL6) & 0x2)
+ break;
+ msleep(1);
+ }
+
+ if (!(b43_radio_read(dev, B2063_RC_CALIB_CTL6) & 0x2))
+ b43_radio_write(dev, B2063_TX_BB_SP3, tmp);
+
+ b43_radio_write(dev, B2063_RC_CALIB_CTL1, 0x7E);
+}
+
+static void lpphy_calibrate_rc(struct b43_wldev *dev)
+{
+ struct b43_phy_lp *lpphy = dev->phy.lp;
+
+ if (dev->phy.rev >= 2) {
+ lpphy_rev2plus_rc_calib(dev);
+ } else if (!lpphy->rc_cap) {
+ if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
+ lpphy_rev0_1_rc_calib(dev);
+ } else {
+ lpphy_set_rc_cap(dev);
+ }
+}
+
static void lpphy_set_tx_power_by_index(struct b43_wldev *dev, u8 index)
{
struct b43_phy_lp *lpphy = dev->phy.lp;
@@ -440,13 +1274,14 @@ static void lpphy_tx_pctl_init(struct b43_wldev *dev)
static int b43_lpphy_op_init(struct b43_wldev *dev)
{
- /* TODO: band SPROM */
+ lpphy_read_band_sprom(dev); //FIXME should this be in prepare_structs?
lpphy_baseband_init(dev);
lpphy_radio_init(dev);
- //TODO calibrate RC
+ lpphy_calibrate_rc(dev);
//TODO set channel
lpphy_tx_pctl_init(dev);
- //TODO full calib
+ lpphy_calibration(dev);
+ //TODO ACI init
return 0;
}
@@ -524,7 +1359,6 @@ static enum b43_txpwr_result b43_lpphy_op_recalc_txpower(struct b43_wldev *dev,
return B43_TXPWR_RES_DONE;
}
-
const struct b43_phy_operations b43_phyops_lp = {
.allocate = b43_lpphy_op_allocate,
.free = b43_lpphy_op_free,
diff --git a/drivers/net/wireless/b43/phy_lp.h b/drivers/net/wireless/b43/phy_lp.h
index 18370b4ac38..0461d5b3144 100644
--- a/drivers/net/wireless/b43/phy_lp.h
+++ b/drivers/net/wireless/b43/phy_lp.h
@@ -273,12 +273,19 @@
#define B43_LPPHY_AFE_DDFS_POINTER_INIT B43_PHY_OFDM(0xB8) /* AFE DDFS pointer init */
#define B43_LPPHY_AFE_DDFS_INCR_INIT B43_PHY_OFDM(0xB9) /* AFE DDFS incr init */
#define B43_LPPHY_MRCNOISEREDUCTION B43_PHY_OFDM(0xBA) /* mrcNoiseReduction */
-#define B43_LPPHY_TRLOOKUP3 B43_PHY_OFDM(0xBB) /* TRLookup3 */
-#define B43_LPPHY_TRLOOKUP4 B43_PHY_OFDM(0xBC) /* TRLookup4 */
+#define B43_LPPHY_TR_LOOKUP_3 B43_PHY_OFDM(0xBB) /* TR Lookup 3 */
+#define B43_LPPHY_TR_LOOKUP_4 B43_PHY_OFDM(0xBC) /* TR Lookup 4 */
#define B43_LPPHY_RADAR_FIFO_STAT B43_PHY_OFDM(0xBD) /* Radar FIFO Status */
#define B43_LPPHY_GPIO_OUTEN B43_PHY_OFDM(0xBE) /* GPIO Out enable */
#define B43_LPPHY_GPIO_SELECT B43_PHY_OFDM(0xBF) /* GPIO Select */
#define B43_LPPHY_GPIO_OUT B43_PHY_OFDM(0xC0) /* GPIO Out */
+#define B43_LPPHY_4C3 B43_PHY_OFDM(0xC3) /* unknown, used during BB init */
+#define B43_LPPHY_4C4 B43_PHY_OFDM(0xC4) /* unknown, used during BB init */
+#define B43_LPPHY_4C5 B43_PHY_OFDM(0xC5) /* unknown, used during BB init */
+#define B43_LPPHY_TR_LOOKUP_5 B43_PHY_OFDM(0xC7) /* TR Lookup 5 */
+#define B43_LPPHY_TR_LOOKUP_6 B43_PHY_OFDM(0xC8) /* TR Lookup 6 */
+#define B43_LPPHY_TR_LOOKUP_7 B43_PHY_OFDM(0xC9) /* TR Lookup 7 */
+#define B43_LPPHY_TR_LOOKUP_8 B43_PHY_OFDM(0xCA) /* TR Lookup 8 */
@@ -824,6 +831,22 @@ struct b43_phy_lp {
/* Transmit isolation high band */
u8 tx_isolation_hi_band; /* FIXME initial value? */
+ /* Max transmit power medium band */
+ u16 max_tx_pwr_med_band;
+ /* Max transmit power low band */
+ u16 max_tx_pwr_low_band;
+ /* Max transmit power high band */
+ u16 max_tx_pwr_hi_band;
+
+ /* FIXME What are these used for? */
+ /* FIXME Is 15 the correct array size? */
+ u16 tx_max_rate[15];
+ u16 tx_max_ratel[15];
+ u16 tx_max_rateh[15];
+
+ /* Transmit power arrays */
+ s16 txpa[3], txpal[3], txpah[3];
+
/* Receive power offset */
u8 rx_pwr_offset; /* FIXME initial value? */
@@ -858,6 +881,9 @@ struct b43_phy_lp {
/* Transmit iqlocal best coeffs */
bool tx_iqloc_best_coeffs_valid;
u8 tx_iqloc_best_coeffs[11];
+
+ /* Used for "Save/Restore Dig Filt State" */
+ u16 dig_flt_state[9];
};
diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c
index be7b5604947..992318a7807 100644
--- a/drivers/net/wireless/b43/phy_n.c
+++ b/drivers/net/wireless/b43/phy_n.c
@@ -137,7 +137,8 @@ static void b43_radio_init2055_post(struct b43_wldev *dev)
b43_radio_mask(dev, B2055_MASTER1, 0xFFF3);
msleep(1);
- if ((sprom->revision != 4) || !(sprom->boardflags_hi & 0x0002)) {
+ if ((sprom->revision != 4) ||
+ !(sprom->boardflags_hi & B43_BFH_RSSIINV)) {
if ((binfo->vendor != PCI_VENDOR_ID_BROADCOM) ||
(binfo->type != 0x46D) ||
(binfo->rev < 0x41)) {
diff --git a/drivers/net/wireless/b43/pio.c b/drivers/net/wireless/b43/pio.c
index 69138e8c1db..73c047d8de4 100644
--- a/drivers/net/wireless/b43/pio.c
+++ b/drivers/net/wireless/b43/pio.c
@@ -783,7 +783,7 @@ void b43_pio_rx(struct b43_pio_rxqueue *q)
{
/* Due to latency issues we must run the RX path in
* a workqueue to be able to schedule between packets. */
- queue_work(q->dev->wl->hw->workqueue, &q->rx_work);
+ ieee80211_queue_work(q->dev->wl->hw, &q->rx_work);
}
static void b43_pio_tx_suspend_queue(struct b43_pio_txqueue *q)
diff --git a/drivers/net/wireless/b43/tables_lpphy.c b/drivers/net/wireless/b43/tables_lpphy.c
index 4ea734dce21..2721310acb2 100644
--- a/drivers/net/wireless/b43/tables_lpphy.c
+++ b/drivers/net/wireless/b43/tables_lpphy.c
@@ -28,22 +28,22 @@
#include "phy_lp.h"
-/* Entry of the 2062 radio init table */
-struct b2062_init_tab_entry {
+/* Entry of the 2062/2063 radio init table */
+struct b206x_init_tab_entry {
u16 offset;
u16 value_a;
u16 value_g;
u8 flags;
};
-#define B2062_FLAG_A 0x01 /* Flag: Init in A mode */
-#define B2062_FLAG_G 0x02 /* Flag: Init in G mode */
+#define B206X_FLAG_A 0x01 /* Flag: Init in A mode */
+#define B206X_FLAG_G 0x02 /* Flag: Init in G mode */
-static const struct b2062_init_tab_entry b2062_init_tab[] = {
+static const struct b206x_init_tab_entry b2062_init_tab[] = {
/* { .offset = B2062_N_COMM1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
/* { .offset = 0x0001, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
/* { .offset = B2062_N_COMM2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
/* { .offset = B2062_N_COMM3, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
- { .offset = B2062_N_COMM4, .value_a = 0x0001, .value_g = 0x0000, .flags = B2062_FLAG_A | B2062_FLAG_G, },
+ { .offset = B2062_N_COMM4, .value_a = 0x0001, .value_g = 0x0000, .flags = B206X_FLAG_A | B206X_FLAG_G, },
/* { .offset = B2062_N_COMM5, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
/* { .offset = B2062_N_COMM6, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
/* { .offset = B2062_N_COMM7, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
@@ -56,42 +56,42 @@ static const struct b2062_init_tab_entry b2062_init_tab[] = {
/* { .offset = B2062_N_COMM14, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
/* { .offset = B2062_N_COMM15, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
/* { .offset = B2062_N_PDN_CTL0, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
- { .offset = B2062_N_PDN_CTL1, .value_a = 0x0000, .value_g = 0x00CA, .flags = B2062_FLAG_G, },
+ { .offset = B2062_N_PDN_CTL1, .value_a = 0x0000, .value_g = 0x00CA, .flags = B206X_FLAG_G, },
/* { .offset = B2062_N_PDN_CTL2, .value_a = 0x0018, .value_g = 0x0018, .flags = 0, }, */
- { .offset = B2062_N_PDN_CTL3, .value_a = 0x0000, .value_g = 0x0000, .flags = B2062_FLAG_A | B2062_FLAG_G, },
- { .offset = B2062_N_PDN_CTL4, .value_a = 0x0015, .value_g = 0x002A, .flags = B2062_FLAG_A | B2062_FLAG_G, },
+ { .offset = B2062_N_PDN_CTL3, .value_a = 0x0000, .value_g = 0x0000, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+ { .offset = B2062_N_PDN_CTL4, .value_a = 0x0015, .value_g = 0x002A, .flags = B206X_FLAG_A | B206X_FLAG_G, },
/* { .offset = B2062_N_GEN_CTL0, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
/* { .offset = B2062_N_IQ_CALIB, .value_a = 0x0001, .value_g = 0x0001, .flags = 0, }, */
- { .offset = B2062_N_LGENC, .value_a = 0x00DB, .value_g = 0x00FF, .flags = B2062_FLAG_A, },
+ { .offset = B2062_N_LGENC, .value_a = 0x00DB, .value_g = 0x00FF, .flags = B206X_FLAG_A, },
/* { .offset = B2062_N_LGENA_LPF, .value_a = 0x0001, .value_g = 0x0001, .flags = 0, }, */
/* { .offset = B2062_N_LGENA_BIAS0, .value_a = 0x0041, .value_g = 0x0041, .flags = 0, }, */
/* { .offset = B2062_N_LGNEA_BIAS1, .value_a = 0x0002, .value_g = 0x0002, .flags = 0, }, */
/* { .offset = B2062_N_LGENA_CTL0, .value_a = 0x0032, .value_g = 0x0032, .flags = 0, }, */
/* { .offset = B2062_N_LGENA_CTL1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
/* { .offset = B2062_N_LGENA_CTL2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
- { .offset = B2062_N_LGENA_TUNE0, .value_a = 0x00DD, .value_g = 0x0000, .flags = B2062_FLAG_A | B2062_FLAG_G, },
+ { .offset = B2062_N_LGENA_TUNE0, .value_a = 0x00DD, .value_g = 0x0000, .flags = B206X_FLAG_A | B206X_FLAG_G, },
/* { .offset = B2062_N_LGENA_TUNE1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
- { .offset = B2062_N_LGENA_TUNE2, .value_a = 0x00DD, .value_g = 0x0000, .flags = B2062_FLAG_A | B2062_FLAG_G, },
- { .offset = B2062_N_LGENA_TUNE3, .value_a = 0x0077, .value_g = 0x00B5, .flags = B2062_FLAG_A | B2062_FLAG_G, },
- { .offset = B2062_N_LGENA_CTL3, .value_a = 0x0000, .value_g = 0x00FF, .flags = B2062_FLAG_A | B2062_FLAG_G, },
+ { .offset = B2062_N_LGENA_TUNE2, .value_a = 0x00DD, .value_g = 0x0000, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+ { .offset = B2062_N_LGENA_TUNE3, .value_a = 0x0077, .value_g = 0x00B5, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+ { .offset = B2062_N_LGENA_CTL3, .value_a = 0x0000, .value_g = 0x00FF, .flags = B206X_FLAG_A | B206X_FLAG_G, },
/* { .offset = B2062_N_LGENA_CTL4, .value_a = 0x001F, .value_g = 0x001F, .flags = 0, }, */
/* { .offset = B2062_N_LGENA_CTL5, .value_a = 0x0032, .value_g = 0x0032, .flags = 0, }, */
/* { .offset = B2062_N_LGENA_CTL6, .value_a = 0x0032, .value_g = 0x0032, .flags = 0, }, */
- { .offset = B2062_N_LGENA_CTL7, .value_a = 0x0033, .value_g = 0x0033, .flags = B2062_FLAG_A | B2062_FLAG_G, },
+ { .offset = B2062_N_LGENA_CTL7, .value_a = 0x0033, .value_g = 0x0033, .flags = B206X_FLAG_A | B206X_FLAG_G, },
/* { .offset = B2062_N_RXA_CTL0, .value_a = 0x0009, .value_g = 0x0009, .flags = 0, }, */
- { .offset = B2062_N_RXA_CTL1, .value_a = 0x0000, .value_g = 0x0000, .flags = B2062_FLAG_G, },
+ { .offset = B2062_N_RXA_CTL1, .value_a = 0x0000, .value_g = 0x0000, .flags = B206X_FLAG_G, },
/* { .offset = B2062_N_RXA_CTL2, .value_a = 0x0018, .value_g = 0x0018, .flags = 0, }, */
/* { .offset = B2062_N_RXA_CTL3, .value_a = 0x0027, .value_g = 0x0027, .flags = 0, }, */
/* { .offset = B2062_N_RXA_CTL4, .value_a = 0x0028, .value_g = 0x0028, .flags = 0, }, */
/* { .offset = B2062_N_RXA_CTL5, .value_a = 0x0007, .value_g = 0x0007, .flags = 0, }, */
/* { .offset = B2062_N_RXA_CTL6, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
/* { .offset = B2062_N_RXA_CTL7, .value_a = 0x0008, .value_g = 0x0008, .flags = 0, }, */
- { .offset = B2062_N_RXBB_CTL0, .value_a = 0x0082, .value_g = 0x0080, .flags = B2062_FLAG_A | B2062_FLAG_G, },
+ { .offset = B2062_N_RXBB_CTL0, .value_a = 0x0082, .value_g = 0x0080, .flags = B206X_FLAG_A | B206X_FLAG_G, },
/* { .offset = B2062_N_RXBB_CTL1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
/* { .offset = B2062_N_RXBB_CTL2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
/* { .offset = B2062_N_RXBB_GAIN0, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
- { .offset = B2062_N_RXBB_GAIN1, .value_a = 0x0004, .value_g = 0x0004, .flags = B2062_FLAG_A | B2062_FLAG_G, },
- { .offset = B2062_N_RXBB_GAIN2, .value_a = 0x0000, .value_g = 0x0000, .flags = B2062_FLAG_A | B2062_FLAG_G, },
+ { .offset = B2062_N_RXBB_GAIN1, .value_a = 0x0004, .value_g = 0x0004, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+ { .offset = B2062_N_RXBB_GAIN2, .value_a = 0x0000, .value_g = 0x0000, .flags = B206X_FLAG_A | B206X_FLAG_G, },
/* { .offset = B2062_N_RXBB_GAIN3, .value_a = 0x0011, .value_g = 0x0011, .flags = 0, }, */
/* { .offset = B2062_N_RXBB_RSSI0, .value_a = 0x0043, .value_g = 0x0043, .flags = 0, }, */
/* { .offset = B2062_N_RXBB_RSSI1, .value_a = 0x0033, .value_g = 0x0033, .flags = 0, }, */
@@ -112,8 +112,8 @@ static const struct b2062_init_tab_entry b2062_init_tab[] = {
/* { .offset = B2062_N_TX_CTL1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
/* { .offset = B2062_N_TX_CTL2, .value_a = 0x0084, .value_g = 0x0084, .flags = 0, }, */
/* { .offset = B2062_N_TX_CTL3, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
- { .offset = B2062_N_TX_CTL4, .value_a = 0x0003, .value_g = 0x0003, .flags = B2062_FLAG_A | B2062_FLAG_G, },
- { .offset = B2062_N_TX_CTL5, .value_a = 0x0002, .value_g = 0x0002, .flags = B2062_FLAG_A | B2062_FLAG_G, },
+ { .offset = B2062_N_TX_CTL4, .value_a = 0x0003, .value_g = 0x0003, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+ { .offset = B2062_N_TX_CTL5, .value_a = 0x0002, .value_g = 0x0002, .flags = B206X_FLAG_A | B206X_FLAG_G, },
/* { .offset = B2062_N_TX_CTL6, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
/* { .offset = B2062_N_TX_CTL7, .value_a = 0x0058, .value_g = 0x0058, .flags = 0, }, */
/* { .offset = B2062_N_TX_CTL8, .value_a = 0x0082, .value_g = 0x0082, .flags = 0, }, */
@@ -121,7 +121,7 @@ static const struct b2062_init_tab_entry b2062_init_tab[] = {
/* { .offset = B2062_N_TX_CTL_A, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
/* { .offset = B2062_N_TX_GC2G, .value_a = 0x00FF, .value_g = 0x00FF, .flags = 0, }, */
/* { .offset = B2062_N_TX_GC5G, .value_a = 0x00FF, .value_g = 0x00FF, .flags = 0, }, */
- { .offset = B2062_N_TX_TUNE, .value_a = 0x0088, .value_g = 0x001B, .flags = B2062_FLAG_A | B2062_FLAG_G, },
+ { .offset = B2062_N_TX_TUNE, .value_a = 0x0088, .value_g = 0x001B, .flags = B206X_FLAG_A | B206X_FLAG_G, },
/* { .offset = B2062_N_TX_PAD, .value_a = 0x0088, .value_g = 0x0088, .flags = 0, }, */
/* { .offset = B2062_N_TX_PGA, .value_a = 0x0088, .value_g = 0x0088, .flags = 0, }, */
/* { .offset = B2062_N_TX_PADAUX, .value_a = 0x0033, .value_g = 0x0033, .flags = 0, }, */
@@ -150,7 +150,7 @@ static const struct b2062_init_tab_entry b2062_init_tab[] = {
/* { .offset = B2062_S_RADIO_ID_CODE, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
/* { .offset = B2062_S_COMM2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
/* { .offset = B2062_S_COMM3, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
- { .offset = B2062_S_COMM4, .value_a = 0x0001, .value_g = 0x0000, .flags = B2062_FLAG_A | B2062_FLAG_G, },
+ { .offset = B2062_S_COMM4, .value_a = 0x0001, .value_g = 0x0000, .flags = B206X_FLAG_A | B206X_FLAG_G, },
/* { .offset = B2062_S_COMM5, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
/* { .offset = B2062_S_COMM6, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
/* { .offset = B2062_S_COMM7, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
@@ -162,24 +162,24 @@ static const struct b2062_init_tab_entry b2062_init_tab[] = {
/* { .offset = B2062_S_COMM13, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
/* { .offset = B2062_S_COMM14, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
/* { .offset = B2062_S_COMM15, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
- { .offset = B2062_S_PDS_CTL0, .value_a = 0x00FF, .value_g = 0x00FF, .flags = B2062_FLAG_A | B2062_FLAG_G, },
+ { .offset = B2062_S_PDS_CTL0, .value_a = 0x00FF, .value_g = 0x00FF, .flags = B206X_FLAG_A | B206X_FLAG_G, },
/* { .offset = B2062_S_PDS_CTL1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
/* { .offset = B2062_S_PDS_CTL2, .value_a = 0x008E, .value_g = 0x008E, .flags = 0, }, */
/* { .offset = B2062_S_PDS_CTL3, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
/* { .offset = B2062_S_BG_CTL0, .value_a = 0x0006, .value_g = 0x0006, .flags = 0, }, */
/* { .offset = B2062_S_BG_CTL1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
/* { .offset = B2062_S_BG_CTL2, .value_a = 0x0011, .value_g = 0x0011, .flags = 0, }, */
- { .offset = B2062_S_LGENG_CTL0, .value_a = 0x00F8, .value_g = 0x00D8, .flags = B2062_FLAG_A | B2062_FLAG_G, },
- { .offset = B2062_S_LGENG_CTL1, .value_a = 0x003C, .value_g = 0x0024, .flags = B2062_FLAG_A | B2062_FLAG_G, },
+ { .offset = B2062_S_LGENG_CTL0, .value_a = 0x00F8, .value_g = 0x00D8, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+ { .offset = B2062_S_LGENG_CTL1, .value_a = 0x003C, .value_g = 0x0024, .flags = B206X_FLAG_A | B206X_FLAG_G, },
/* { .offset = B2062_S_LGENG_CTL2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
/* { .offset = B2062_S_LGENG_CTL3, .value_a = 0x0041, .value_g = 0x0041, .flags = 0, }, */
/* { .offset = B2062_S_LGENG_CTL4, .value_a = 0x0002, .value_g = 0x0002, .flags = 0, }, */
/* { .offset = B2062_S_LGENG_CTL5, .value_a = 0x0033, .value_g = 0x0033, .flags = 0, }, */
/* { .offset = B2062_S_LGENG_CTL6, .value_a = 0x0022, .value_g = 0x0022, .flags = 0, }, */
/* { .offset = B2062_S_LGENG_CTL7, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
- { .offset = B2062_S_LGENG_CTL8, .value_a = 0x0088, .value_g = 0x0080, .flags = B2062_FLAG_A | B2062_FLAG_G, },
+ { .offset = B2062_S_LGENG_CTL8, .value_a = 0x0088, .value_g = 0x0080, .flags = B206X_FLAG_A | B206X_FLAG_G, },
/* { .offset = B2062_S_LGENG_CTL9, .value_a = 0x0088, .value_g = 0x0088, .flags = 0, }, */
- { .offset = B2062_S_LGENG_CTL10, .value_a = 0x0088, .value_g = 0x0080, .flags = B2062_FLAG_A | B2062_FLAG_G, },
+ { .offset = B2062_S_LGENG_CTL10, .value_a = 0x0088, .value_g = 0x0080, .flags = B206X_FLAG_A | B206X_FLAG_G, },
/* { .offset = B2062_S_LGENG_CTL11, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
/* { .offset = B2062_S_REFPLL_CTL0, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
/* { .offset = B2062_S_REFPLL_CTL1, .value_a = 0x0007, .value_g = 0x0007, .flags = 0, }, */
@@ -198,41 +198,41 @@ static const struct b2062_init_tab_entry b2062_init_tab[] = {
/* { .offset = B2062_S_REFPLL_CTL14, .value_a = 0x0075, .value_g = 0x0075, .flags = 0, }, */
/* { .offset = B2062_S_REFPLL_CTL15, .value_a = 0x00B4, .value_g = 0x00B4, .flags = 0, }, */
/* { .offset = B2062_S_REFPLL_CTL16, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
- { .offset = B2062_S_RFPLL_CTL0, .value_a = 0x0098, .value_g = 0x0098, .flags = B2062_FLAG_A | B2062_FLAG_G, },
- { .offset = B2062_S_RFPLL_CTL1, .value_a = 0x0010, .value_g = 0x0010, .flags = B2062_FLAG_A | B2062_FLAG_G, },
+ { .offset = B2062_S_RFPLL_CTL0, .value_a = 0x0098, .value_g = 0x0098, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+ { .offset = B2062_S_RFPLL_CTL1, .value_a = 0x0010, .value_g = 0x0010, .flags = B206X_FLAG_A | B206X_FLAG_G, },
/* { .offset = B2062_S_RFPLL_CTL2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
/* { .offset = B2062_S_RFPLL_CTL3, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
/* { .offset = B2062_S_RFPLL_CTL4, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
- { .offset = B2062_S_RFPLL_CTL5, .value_a = 0x0043, .value_g = 0x0043, .flags = B2062_FLAG_A | B2062_FLAG_G, },
- { .offset = B2062_S_RFPLL_CTL6, .value_a = 0x0047, .value_g = 0x0047, .flags = B2062_FLAG_A | B2062_FLAG_G, },
- { .offset = B2062_S_RFPLL_CTL7, .value_a = 0x000C, .value_g = 0x000C, .flags = B2062_FLAG_A | B2062_FLAG_G, },
- { .offset = B2062_S_RFPLL_CTL8, .value_a = 0x0011, .value_g = 0x0011, .flags = B2062_FLAG_A | B2062_FLAG_G, },
- { .offset = B2062_S_RFPLL_CTL9, .value_a = 0x0011, .value_g = 0x0011, .flags = B2062_FLAG_A | B2062_FLAG_G, },
- { .offset = B2062_S_RFPLL_CTL10, .value_a = 0x000E, .value_g = 0x000E, .flags = B2062_FLAG_A | B2062_FLAG_G, },
- { .offset = B2062_S_RFPLL_CTL11, .value_a = 0x0008, .value_g = 0x0008, .flags = B2062_FLAG_A | B2062_FLAG_G, },
- { .offset = B2062_S_RFPLL_CTL12, .value_a = 0x0033, .value_g = 0x0033, .flags = B2062_FLAG_A | B2062_FLAG_G, },
- { .offset = B2062_S_RFPLL_CTL13, .value_a = 0x000A, .value_g = 0x000A, .flags = B2062_FLAG_A | B2062_FLAG_G, },
- { .offset = B2062_S_RFPLL_CTL14, .value_a = 0x0006, .value_g = 0x0006, .flags = B2062_FLAG_A | B2062_FLAG_G, },
+ { .offset = B2062_S_RFPLL_CTL5, .value_a = 0x0043, .value_g = 0x0043, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+ { .offset = B2062_S_RFPLL_CTL6, .value_a = 0x0047, .value_g = 0x0047, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+ { .offset = B2062_S_RFPLL_CTL7, .value_a = 0x000C, .value_g = 0x000C, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+ { .offset = B2062_S_RFPLL_CTL8, .value_a = 0x0011, .value_g = 0x0011, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+ { .offset = B2062_S_RFPLL_CTL9, .value_a = 0x0011, .value_g = 0x0011, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+ { .offset = B2062_S_RFPLL_CTL10, .value_a = 0x000E, .value_g = 0x000E, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+ { .offset = B2062_S_RFPLL_CTL11, .value_a = 0x0008, .value_g = 0x0008, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+ { .offset = B2062_S_RFPLL_CTL12, .value_a = 0x0033, .value_g = 0x0033, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+ { .offset = B2062_S_RFPLL_CTL13, .value_a = 0x000A, .value_g = 0x000A, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+ { .offset = B2062_S_RFPLL_CTL14, .value_a = 0x0006, .value_g = 0x0006, .flags = B206X_FLAG_A | B206X_FLAG_G, },
/* { .offset = B2062_S_RFPLL_CTL15, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
/* { .offset = B2062_S_RFPLL_CTL16, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
/* { .offset = B2062_S_RFPLL_CTL17, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
- { .offset = B2062_S_RFPLL_CTL18, .value_a = 0x003E, .value_g = 0x003E, .flags = B2062_FLAG_A | B2062_FLAG_G, },
- { .offset = B2062_S_RFPLL_CTL19, .value_a = 0x0013, .value_g = 0x0013, .flags = B2062_FLAG_A | B2062_FLAG_G, },
+ { .offset = B2062_S_RFPLL_CTL18, .value_a = 0x003E, .value_g = 0x003E, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+ { .offset = B2062_S_RFPLL_CTL19, .value_a = 0x0013, .value_g = 0x0013, .flags = B206X_FLAG_A | B206X_FLAG_G, },
/* { .offset = B2062_S_RFPLL_CTL20, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
- { .offset = B2062_S_RFPLL_CTL21, .value_a = 0x0062, .value_g = 0x0062, .flags = B2062_FLAG_A | B2062_FLAG_G, },
- { .offset = B2062_S_RFPLL_CTL22, .value_a = 0x0007, .value_g = 0x0007, .flags = B2062_FLAG_A | B2062_FLAG_G, },
- { .offset = B2062_S_RFPLL_CTL23, .value_a = 0x0016, .value_g = 0x0016, .flags = B2062_FLAG_A | B2062_FLAG_G, },
- { .offset = B2062_S_RFPLL_CTL24, .value_a = 0x005C, .value_g = 0x005C, .flags = B2062_FLAG_A | B2062_FLAG_G, },
- { .offset = B2062_S_RFPLL_CTL25, .value_a = 0x0095, .value_g = 0x0095, .flags = B2062_FLAG_A | B2062_FLAG_G, },
+ { .offset = B2062_S_RFPLL_CTL21, .value_a = 0x0062, .value_g = 0x0062, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+ { .offset = B2062_S_RFPLL_CTL22, .value_a = 0x0007, .value_g = 0x0007, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+ { .offset = B2062_S_RFPLL_CTL23, .value_a = 0x0016, .value_g = 0x0016, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+ { .offset = B2062_S_RFPLL_CTL24, .value_a = 0x005C, .value_g = 0x005C, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+ { .offset = B2062_S_RFPLL_CTL25, .value_a = 0x0095, .value_g = 0x0095, .flags = B206X_FLAG_A | B206X_FLAG_G, },
/* { .offset = B2062_S_RFPLL_CTL26, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
/* { .offset = B2062_S_RFPLL_CTL27, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
/* { .offset = B2062_S_RFPLL_CTL28, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
/* { .offset = B2062_S_RFPLL_CTL29, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
- { .offset = B2062_S_RFPLL_CTL30, .value_a = 0x00A0, .value_g = 0x00A0, .flags = B2062_FLAG_A | B2062_FLAG_G, },
- { .offset = B2062_S_RFPLL_CTL31, .value_a = 0x0004, .value_g = 0x0004, .flags = B2062_FLAG_A | B2062_FLAG_G, },
+ { .offset = B2062_S_RFPLL_CTL30, .value_a = 0x00A0, .value_g = 0x00A0, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+ { .offset = B2062_S_RFPLL_CTL31, .value_a = 0x0004, .value_g = 0x0004, .flags = B206X_FLAG_A | B206X_FLAG_G, },
/* { .offset = B2062_S_RFPLL_CTL32, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
- { .offset = B2062_S_RFPLL_CTL33, .value_a = 0x00CC, .value_g = 0x00CC, .flags = B2062_FLAG_A | B2062_FLAG_G, },
- { .offset = B2062_S_RFPLL_CTL34, .value_a = 0x0007, .value_g = 0x0007, .flags = B2062_FLAG_A | B2062_FLAG_G, },
+ { .offset = B2062_S_RFPLL_CTL33, .value_a = 0x00CC, .value_g = 0x00CC, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+ { .offset = B2062_S_RFPLL_CTL34, .value_a = 0x0007, .value_g = 0x0007, .flags = B206X_FLAG_A | B206X_FLAG_G, },
/* { .offset = B2062_S_RXG_CNT0, .value_a = 0x0010, .value_g = 0x0010, .flags = 0, }, */
/* { .offset = B2062_S_RXG_CNT1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
/* { .offset = B2062_S_RXG_CNT2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
@@ -241,7 +241,7 @@ static const struct b2062_init_tab_entry b2062_init_tab[] = {
/* { .offset = B2062_S_RXG_CNT5, .value_a = 0x0055, .value_g = 0x0055, .flags = 0, }, */
/* { .offset = B2062_S_RXG_CNT6, .value_a = 0x0055, .value_g = 0x0055, .flags = 0, }, */
/* { .offset = B2062_S_RXG_CNT7, .value_a = 0x0005, .value_g = 0x0005, .flags = 0, }, */
- { .offset = B2062_S_RXG_CNT8, .value_a = 0x000F, .value_g = 0x000F, .flags = B2062_FLAG_A, },
+ { .offset = B2062_S_RXG_CNT8, .value_a = 0x000F, .value_g = 0x000F, .flags = B206X_FLAG_A, },
/* { .offset = B2062_S_RXG_CNT9, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
/* { .offset = B2062_S_RXG_CNT10, .value_a = 0x0055, .value_g = 0x0055, .flags = 0, }, */
/* { .offset = B2062_S_RXG_CNT11, .value_a = 0x0066, .value_g = 0x0066, .flags = 0, }, */
@@ -253,19 +253,337 @@ static const struct b2062_init_tab_entry b2062_init_tab[] = {
/* { .offset = B2062_S_RXG_CNT17, .value_a = 0x0055, .value_g = 0x0055, .flags = 0, }, */
};
+static const struct b206x_init_tab_entry b2063_init_tab[] = {
+ { .offset = B2063_COMM1, .value_a = 0x0000, .value_g = 0x0000, .flags = B206X_FLAG_G, },
+ /* { .offset = B2063_COMM2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+ /* { .offset = B2063_COMM3, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+ /* { .offset = B2063_COMM4, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+ /* { .offset = B2063_COMM5, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+ /* { .offset = B2063_COMM6, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+ /* { .offset = B2063_COMM7, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+ /* { .offset = B2063_COMM8, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+ /* { .offset = B2063_COMM9, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+ { .offset = B2063_COMM10, .value_a = 0x0001, .value_g = 0x0000, .flags = B206X_FLAG_A, },
+ /* { .offset = B2063_COMM11, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+ /* { .offset = B2063_COMM12, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+ /* { .offset = B2063_COMM13, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+ /* { .offset = B2063_COMM14, .value_a = 0x0006, .value_g = 0x0006, .flags = 0, }, */
+ /* { .offset = B2063_COMM15, .value_a = 0x000f, .value_g = 0x000f, .flags = 0, }, */
+ { .offset = B2063_COMM16, .value_a = 0x0000, .value_g = 0x0000, .flags = B206X_FLAG_G, },
+ { .offset = B2063_COMM17, .value_a = 0x0000, .value_g = 0x0000, .flags = B206X_FLAG_G, },
+ { .offset = B2063_COMM18, .value_a = 0x0000, .value_g = 0x0000, .flags = B206X_FLAG_G, },
+ { .offset = B2063_COMM19, .value_a = 0x0000, .value_g = 0x0000, .flags = B206X_FLAG_G, },
+ { .offset = B2063_COMM20, .value_a = 0x0000, .value_g = 0x0000, .flags = B206X_FLAG_G, },
+ { .offset = B2063_COMM21, .value_a = 0x0000, .value_g = 0x0000, .flags = B206X_FLAG_G, },
+ { .offset = B2063_COMM22, .value_a = 0x0000, .value_g = 0x0000, .flags = B206X_FLAG_G, },
+ { .offset = B2063_COMM23, .value_a = 0x0000, .value_g = 0x0000, .flags = B206X_FLAG_G, },
+ { .offset = B2063_COMM24, .value_a = 0x0000, .value_g = 0x0000, .flags = B206X_FLAG_G, },
+ /* { .offset = B2063_PWR_SWITCH_CTL, .value_a = 0x007f, .value_g = 0x007f, .flags = 0, }, */
+ /* { .offset = B2063_PLL_SP1, .value_a = 0x003f, .value_g = 0x003f, .flags = 0, }, */
+ /* { .offset = B2063_PLL_SP2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+ { .offset = B2063_LOGEN_SP1, .value_a = 0x00e8, .value_g = 0x00d4, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+ { .offset = B2063_LOGEN_SP2, .value_a = 0x00a7, .value_g = 0x0053, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+ /* { .offset = B2063_LOGEN_SP3, .value_a = 0x00ff, .value_g = 0x00ff, .flags = 0, }, */
+ { .offset = B2063_LOGEN_SP4, .value_a = 0x00f0, .value_g = 0x000f, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+ /* { .offset = B2063_LOGEN_SP5, .value_a = 0x0001, .value_g = 0x0001, .flags = 0, }, */
+ { .offset = B2063_G_RX_SP1, .value_a = 0x001f, .value_g = 0x005e, .flags = B206X_FLAG_G, },
+ { .offset = B2063_G_RX_SP2, .value_a = 0x007f, .value_g = 0x007e, .flags = B206X_FLAG_G, },
+ { .offset = B2063_G_RX_SP3, .value_a = 0x0030, .value_g = 0x00f0, .flags = B206X_FLAG_G, },
+ /* { .offset = B2063_G_RX_SP4, .value_a = 0x0035, .value_g = 0x0035, .flags = 0, }, */
+ /* { .offset = B2063_G_RX_SP5, .value_a = 0x003f, .value_g = 0x003f, .flags = 0, }, */
+ /* { .offset = B2063_G_RX_SP6, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+ { .offset = B2063_G_RX_SP7, .value_a = 0x007f, .value_g = 0x007f, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+ /* { .offset = B2063_G_RX_SP8, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+ /* { .offset = B2063_G_RX_SP9, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+ { .offset = B2063_G_RX_SP10, .value_a = 0x000c, .value_g = 0x000c, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+ /* { .offset = B2063_G_RX_SP11, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+ { .offset = B2063_A_RX_SP1, .value_a = 0x003c, .value_g = 0x003f, .flags = B206X_FLAG_A, },
+ { .offset = B2063_A_RX_SP2, .value_a = 0x00fc, .value_g = 0x00fe, .flags = B206X_FLAG_A, },
+ /* { .offset = B2063_A_RX_SP3, .value_a = 0x00ff, .value_g = 0x00ff, .flags = 0, }, */
+ /* { .offset = B2063_A_RX_SP4, .value_a = 0x00ff, .value_g = 0x00ff, .flags = 0, }, */
+ /* { .offset = B2063_A_RX_SP5, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+ /* { .offset = B2063_A_RX_SP6, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+ { .offset = B2063_A_RX_SP7, .value_a = 0x0008, .value_g = 0x0008, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+ /* { .offset = B2063_RX_BB_SP1, .value_a = 0x000f, .value_g = 0x000f, .flags = 0, }, */
+ /* { .offset = B2063_RX_BB_SP2, .value_a = 0x0022, .value_g = 0x0022, .flags = 0, }, */
+ /* { .offset = B2063_RX_BB_SP3, .value_a = 0x00a8, .value_g = 0x00a8, .flags = 0, }, */
+ { .offset = B2063_RX_BB_SP4, .value_a = 0x0060, .value_g = 0x0060, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+ /* { .offset = B2063_RX_BB_SP5, .value_a = 0x0011, .value_g = 0x0011, .flags = 0, }, */
+ /* { .offset = B2063_RX_BB_SP6, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+ /* { .offset = B2063_RX_BB_SP7, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+ { .offset = B2063_RX_BB_SP8, .value_a = 0x0030, .value_g = 0x0030, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+ /* { .offset = B2063_TX_RF_SP1, .value_a = 0x0001, .value_g = 0x0001, .flags = 0, }, */
+ /* { .offset = B2063_TX_RF_SP2, .value_a = 0x0003, .value_g = 0x0003, .flags = 0, }, */
+ { .offset = B2063_TX_RF_SP3, .value_a = 0x000c, .value_g = 0x000b, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+ { .offset = B2063_TX_RF_SP4, .value_a = 0x0010, .value_g = 0x000f, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+ /* { .offset = B2063_TX_RF_SP5, .value_a = 0x000f, .value_g = 0x000f, .flags = 0, }, */
+ /* { .offset = B2063_TX_RF_SP6, .value_a = 0x0080, .value_g = 0x0080, .flags = 0, }, */
+ /* { .offset = B2063_TX_RF_SP7, .value_a = 0x0068, .value_g = 0x0068, .flags = 0, }, */
+ /* { .offset = B2063_TX_RF_SP8, .value_a = 0x0068, .value_g = 0x0068, .flags = 0, }, */
+ /* { .offset = B2063_TX_RF_SP9, .value_a = 0x0080, .value_g = 0x0080, .flags = 0, }, */
+ /* { .offset = B2063_TX_RF_SP10, .value_a = 0x00ff, .value_g = 0x00ff, .flags = 0, }, */
+ /* { .offset = B2063_TX_RF_SP11, .value_a = 0x0003, .value_g = 0x0003, .flags = 0, }, */
+ /* { .offset = B2063_TX_RF_SP12, .value_a = 0x0038, .value_g = 0x0038, .flags = 0, }, */
+ /* { .offset = B2063_TX_RF_SP13, .value_a = 0x00ff, .value_g = 0x00ff, .flags = 0, }, */
+ /* { .offset = B2063_TX_RF_SP14, .value_a = 0x0038, .value_g = 0x0038, .flags = 0, }, */
+ /* { .offset = B2063_TX_RF_SP15, .value_a = 0x00c0, .value_g = 0x00c0, .flags = 0, }, */
+ /* { .offset = B2063_TX_RF_SP16, .value_a = 0x00ff, .value_g = 0x00ff, .flags = 0, }, */
+ /* { .offset = B2063_TX_RF_SP17, .value_a = 0x00ff, .value_g = 0x00ff, .flags = 0, }, */
+ { .offset = B2063_PA_SP1, .value_a = 0x003d, .value_g = 0x00fd, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+ /* { .offset = B2063_PA_SP2, .value_a = 0x000c, .value_g = 0x000c, .flags = 0, }, */
+ /* { .offset = B2063_PA_SP3, .value_a = 0x0096, .value_g = 0x0096, .flags = 0, }, */
+ /* { .offset = B2063_PA_SP4, .value_a = 0x005a, .value_g = 0x005a, .flags = 0, }, */
+ /* { .offset = B2063_PA_SP5, .value_a = 0x007f, .value_g = 0x007f, .flags = 0, }, */
+ /* { .offset = B2063_PA_SP6, .value_a = 0x007f, .value_g = 0x007f, .flags = 0, }, */
+ /* { .offset = B2063_PA_SP7, .value_a = 0x0033, .value_g = 0x0033, .flags = 0, }, */
+ { .offset = B2063_TX_BB_SP1, .value_a = 0x0002, .value_g = 0x0002, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+ /* { .offset = B2063_TX_BB_SP2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+ /* { .offset = B2063_TX_BB_SP3, .value_a = 0x0030, .value_g = 0x0030, .flags = 0, }, */
+ /* { .offset = B2063_REG_SP1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+ { .offset = B2063_BANDGAP_CTL1, .value_a = 0x0056, .value_g = 0x0056, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+ /* { .offset = B2063_BANDGAP_CTL2, .value_a = 0x0006, .value_g = 0x0006, .flags = 0, }, */
+ /* { .offset = B2063_LPO_CTL1, .value_a = 0x000e, .value_g = 0x000e, .flags = 0, }, */
+ /* { .offset = B2063_RC_CALIB_CTL1, .value_a = 0x007e, .value_g = 0x007e, .flags = 0, }, */
+ /* { .offset = B2063_RC_CALIB_CTL2, .value_a = 0x0015, .value_g = 0x0015, .flags = 0, }, */
+ /* { .offset = B2063_RC_CALIB_CTL3, .value_a = 0x000f, .value_g = 0x000f, .flags = 0, }, */
+ /* { .offset = B2063_RC_CALIB_CTL4, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+ /* { .offset = B2063_RC_CALIB_CTL5, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+ /* { .offset = B2063_RC_CALIB_CTL6, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+ /* { .offset = B2063_RC_CALIB_CTL7, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+ /* { .offset = B2063_RC_CALIB_CTL8, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+ /* { .offset = B2063_RC_CALIB_CTL9, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+ /* { .offset = B2063_RC_CALIB_CTL10, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+ /* { .offset = B2063_PLL_JTAG_CALNRST, .value_a = 0x0004, .value_g = 0x0004, .flags = 0, }, */
+ /* { .offset = B2063_PLL_JTAG_IN_PLL1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+ /* { .offset = B2063_PLL_JTAG_IN_PLL2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+ /* { .offset = B2063_PLL_JTAG_PLL_CP1, .value_a = 0x00cf, .value_g = 0x00cf, .flags = 0, }, */
+ /* { .offset = B2063_PLL_JTAG_PLL_CP2, .value_a = 0x0059, .value_g = 0x0059, .flags = 0, }, */
+ /* { .offset = B2063_PLL_JTAG_PLL_CP3, .value_a = 0x0007, .value_g = 0x0007, .flags = 0, }, */
+ /* { .offset = B2063_PLL_JTAG_PLL_CP4, .value_a = 0x0042, .value_g = 0x0042, .flags = 0, }, */
+ /* { .offset = B2063_PLL_JTAG_PLL_CTL1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+ /* { .offset = B2063_PLL_JTAG_PLL_LF1, .value_a = 0x00db, .value_g = 0x00db, .flags = 0, }, */
+ /* { .offset = B2063_PLL_JTAG_PLL_LF2, .value_a = 0x0094, .value_g = 0x0094, .flags = 0, }, */
+ /* { .offset = B2063_PLL_JTAG_PLL_LF3, .value_a = 0x0028, .value_g = 0x0028, .flags = 0, }, */
+ /* { .offset = B2063_PLL_JTAG_PLL_LF4, .value_a = 0x0063, .value_g = 0x0063, .flags = 0, }, */
+ /* { .offset = B2063_PLL_JTAG_PLL_SG1, .value_a = 0x0007, .value_g = 0x0007, .flags = 0, }, */
+ /* { .offset = B2063_PLL_JTAG_PLL_SG2, .value_a = 0x00d3, .value_g = 0x00d3, .flags = 0, }, */
+ /* { .offset = B2063_PLL_JTAG_PLL_SG3, .value_a = 0x00b1, .value_g = 0x00b1, .flags = 0, }, */
+ /* { .offset = B2063_PLL_JTAG_PLL_SG4, .value_a = 0x003b, .value_g = 0x003b, .flags = 0, }, */
+ /* { .offset = B2063_PLL_JTAG_PLL_SG5, .value_a = 0x0006, .value_g = 0x0006, .flags = 0, }, */
+ /* { .offset = B2063_PLL_JTAG_PLL_VCO1, .value_a = 0x0058, .value_g = 0x0058, .flags = 0, }, */
+ { .offset = B2063_PLL_JTAG_PLL_VCO2, .value_a = 0x00f7, .value_g = 0x00f7, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+ /* { .offset = B2063_PLL_JTAG_PLL_VCO_CALIB1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+ /* { .offset = B2063_PLL_JTAG_PLL_VCO_CALIB2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+ /* { .offset = B2063_PLL_JTAG_PLL_VCO_CALIB3, .value_a = 0x0002, .value_g = 0x0002, .flags = 0, }, */
+ /* { .offset = B2063_PLL_JTAG_PLL_VCO_CALIB4, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+ /* { .offset = B2063_PLL_JTAG_PLL_VCO_CALIB5, .value_a = 0x0009, .value_g = 0x0009, .flags = 0, }, */
+ /* { .offset = B2063_PLL_JTAG_PLL_VCO_CALIB6, .value_a = 0x0005, .value_g = 0x0005, .flags = 0, }, */
+ /* { .offset = B2063_PLL_JTAG_PLL_VCO_CALIB7, .value_a = 0x0016, .value_g = 0x0016, .flags = 0, }, */
+ /* { .offset = B2063_PLL_JTAG_PLL_VCO_CALIB8, .value_a = 0x006b, .value_g = 0x006b, .flags = 0, }, */
+ /* { .offset = B2063_PLL_JTAG_PLL_VCO_CALIB9, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+ /* { .offset = B2063_PLL_JTAG_PLL_VCO_CALIB10, .value_a = 0x00b3, .value_g = 0x00b3, .flags = 0, }, */
+ /* { .offset = B2063_PLL_JTAG_PLL_XTAL_12, .value_a = 0x0004, .value_g = 0x0004, .flags = 0, }, */
+ /* { .offset = B2063_PLL_JTAG_PLL_XTAL3, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+ /* { .offset = B2063_LOGEN_ACL1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+ /* { .offset = B2063_LOGEN_ACL2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+ /* { .offset = B2063_LOGEN_ACL3, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+ /* { .offset = B2063_LOGEN_ACL4, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+ /* { .offset = B2063_LOGEN_ACL5, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+ /* { .offset = B2063_LO_CALIB_INPUTS, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+ /* { .offset = B2063_LO_CALIB_CTL1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+ /* { .offset = B2063_LO_CALIB_CTL2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+ /* { .offset = B2063_LO_CALIB_CTL3, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+ /* { .offset = B2063_LO_CALIB_WAITCNT, .value_a = 0x0002, .value_g = 0x0002, .flags = 0, }, */
+ /* { .offset = B2063_LO_CALIB_OVR1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+ /* { .offset = B2063_LO_CALIB_OVR2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+ /* { .offset = B2063_LO_CALIB_OVAL1, .value_a = 0x0066, .value_g = 0x0066, .flags = 0, }, */
+ /* { .offset = B2063_LO_CALIB_OVAL2, .value_a = 0x0066, .value_g = 0x0066, .flags = 0, }, */
+ /* { .offset = B2063_LO_CALIB_OVAL3, .value_a = 0x0066, .value_g = 0x0066, .flags = 0, }, */
+ /* { .offset = B2063_LO_CALIB_OVAL4, .value_a = 0x0066, .value_g = 0x0066, .flags = 0, }, */
+ /* { .offset = B2063_LO_CALIB_OVAL5, .value_a = 0x0066, .value_g = 0x0066, .flags = 0, }, */
+ /* { .offset = B2063_LO_CALIB_OVAL6, .value_a = 0x0066, .value_g = 0x0066, .flags = 0, }, */
+ /* { .offset = B2063_LO_CALIB_OVAL7, .value_a = 0x0066, .value_g = 0x0066, .flags = 0, }, */
+ /* { .offset = B2063_LO_CALIB_CALVLD1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+ /* { .offset = B2063_LO_CALIB_CALVLD2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+ /* { .offset = B2063_LO_CALIB_CVAL1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+ /* { .offset = B2063_LO_CALIB_CVAL2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+ /* { .offset = B2063_LO_CALIB_CVAL3, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+ /* { .offset = B2063_LO_CALIB_CVAL4, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+ /* { .offset = B2063_LO_CALIB_CVAL5, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+ /* { .offset = B2063_LO_CALIB_CVAL6, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+ /* { .offset = B2063_LO_CALIB_CVAL7, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+ /* { .offset = B2063_LOGEN_CALIB_EN, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+ /* { .offset = B2063_LOGEN_PEAKDET1, .value_a = 0x00ff, .value_g = 0x00ff, .flags = 0, }, */
+ /* { .offset = B2063_LOGEN_RCCR1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+ /* { .offset = B2063_LOGEN_VCOBUF1, .value_a = 0x0060, .value_g = 0x0060, .flags = 0, }, */
+ /* { .offset = B2063_LOGEN_MIXER1, .value_a = 0x0066, .value_g = 0x0066, .flags = 0, }, */
+ /* { .offset = B2063_LOGEN_MIXER2, .value_a = 0x000c, .value_g = 0x000c, .flags = 0, }, */
+ /* { .offset = B2063_LOGEN_BUF1, .value_a = 0x0066, .value_g = 0x0066, .flags = 0, }, */
+ /* { .offset = B2063_LOGEN_BUF2, .value_a = 0x000c, .value_g = 0x000c, .flags = 0, }, */
+ /* { .offset = B2063_LOGEN_DIV1, .value_a = 0x0001, .value_g = 0x0001, .flags = 0, }, */
+ /* { .offset = B2063_LOGEN_DIV2, .value_a = 0x0066, .value_g = 0x0066, .flags = 0, }, */
+ /* { .offset = B2063_LOGEN_DIV3, .value_a = 0x0066, .value_g = 0x0066, .flags = 0, }, */
+ /* { .offset = B2063_LOGEN_CBUFRX1, .value_a = 0x0066, .value_g = 0x0066, .flags = 0, }, */
+ /* { .offset = B2063_LOGEN_CBUFRX2, .value_a = 0x0066, .value_g = 0x0066, .flags = 0, }, */
+ /* { .offset = B2063_LOGEN_CBUFTX1, .value_a = 0x0066, .value_g = 0x0066, .flags = 0, }, */
+ /* { .offset = B2063_LOGEN_CBUFTX2, .value_a = 0x0066, .value_g = 0x0066, .flags = 0, }, */
+ /* { .offset = B2063_LOGEN_IDAC1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+ /* { .offset = B2063_LOGEN_SPARE1, .value_a = 0x0001, .value_g = 0x0001, .flags = 0, }, */
+ /* { .offset = B2063_LOGEN_SPARE2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+ /* { .offset = B2063_LOGEN_SPARE3, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+ /* { .offset = B2063_G_RX_1ST1, .value_a = 0x0033, .value_g = 0x0033, .flags = 0, }, */
+ /* { .offset = B2063_G_RX_1ST2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+ /* { .offset = B2063_G_RX_1ST3, .value_a = 0x0005, .value_g = 0x0005, .flags = 0, }, */
+ /* { .offset = B2063_G_RX_2ND1, .value_a = 0x0030, .value_g = 0x0030, .flags = 0, }, */
+ /* { .offset = B2063_G_RX_2ND2, .value_a = 0x0055, .value_g = 0x0055, .flags = 0, }, */
+ /* { .offset = B2063_G_RX_2ND3, .value_a = 0x0033, .value_g = 0x0033, .flags = 0, }, */
+ /* { .offset = B2063_G_RX_2ND4, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+ /* { .offset = B2063_G_RX_2ND5, .value_a = 0x0033, .value_g = 0x0033, .flags = 0, }, */
+ /* { .offset = B2063_G_RX_2ND6, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+ /* { .offset = B2063_G_RX_2ND7, .value_a = 0x0035, .value_g = 0x0035, .flags = 0, }, */
+ /* { .offset = B2063_G_RX_2ND8, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+ /* { .offset = B2063_G_RX_PS1, .value_a = 0x0033, .value_g = 0x0033, .flags = 0, }, */
+ /* { .offset = B2063_G_RX_PS2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+ /* { .offset = B2063_G_RX_PS3, .value_a = 0x0033, .value_g = 0x0033, .flags = 0, }, */
+ /* { .offset = B2063_G_RX_PS4, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+ /* { .offset = B2063_G_RX_PS5, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+ /* { .offset = B2063_G_RX_MIX1, .value_a = 0x0044, .value_g = 0x0044, .flags = 0, }, */
+ /* { .offset = B2063_G_RX_MIX2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+ { .offset = B2063_G_RX_MIX3, .value_a = 0x0071, .value_g = 0x0071, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+ { .offset = B2063_G_RX_MIX4, .value_a = 0x0071, .value_g = 0x0071, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+ /* { .offset = B2063_G_RX_MIX5, .value_a = 0x0003, .value_g = 0x0003, .flags = 0, }, */
+ /* { .offset = B2063_G_RX_MIX6, .value_a = 0x0088, .value_g = 0x0088, .flags = 0, }, */
+ /* { .offset = B2063_G_RX_MIX7, .value_a = 0x0044, .value_g = 0x0044, .flags = 0, }, */
+ /* { .offset = B2063_G_RX_MIX8, .value_a = 0x0001, .value_g = 0x0001, .flags = 0, }, */
+ /* { .offset = B2063_G_RX_PDET1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+ /* { .offset = B2063_G_RX_SPARES1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+ /* { .offset = B2063_G_RX_SPARES2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+ /* { .offset = B2063_G_RX_SPARES3, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+ /* { .offset = B2063_A_RX_1ST1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+ { .offset = B2063_A_RX_1ST2, .value_a = 0x00f0, .value_g = 0x0030, .flags = B206X_FLAG_A, },
+ /* { .offset = B2063_A_RX_1ST3, .value_a = 0x0005, .value_g = 0x0005, .flags = 0, }, */
+ /* { .offset = B2063_A_RX_1ST4, .value_a = 0x0033, .value_g = 0x0033, .flags = 0, }, */
+ /* { .offset = B2063_A_RX_1ST5, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+ /* { .offset = B2063_A_RX_2ND1, .value_a = 0x0005, .value_g = 0x0005, .flags = 0, }, */
+ /* { .offset = B2063_A_RX_2ND2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+ /* { .offset = B2063_A_RX_2ND3, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+ /* { .offset = B2063_A_RX_2ND4, .value_a = 0x0005, .value_g = 0x0005, .flags = 0, }, */
+ /* { .offset = B2063_A_RX_2ND5, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+ /* { .offset = B2063_A_RX_2ND6, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+ /* { .offset = B2063_A_RX_2ND7, .value_a = 0x0005, .value_g = 0x0005, .flags = 0, }, */
+ /* { .offset = B2063_A_RX_PS1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+ /* { .offset = B2063_A_RX_PS2, .value_a = 0x0033, .value_g = 0x0033, .flags = 0, }, */
+ /* { .offset = B2063_A_RX_PS3, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+ /* { .offset = B2063_A_RX_PS4, .value_a = 0x0033, .value_g = 0x0033, .flags = 0, }, */
+ /* { .offset = B2063_A_RX_PS5, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+ { .offset = B2063_A_RX_PS6, .value_a = 0x0077, .value_g = 0x0077, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+ /* { .offset = B2063_A_RX_MIX1, .value_a = 0x0088, .value_g = 0x0088, .flags = 0, }, */
+ /* { .offset = B2063_A_RX_MIX2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+ /* { .offset = B2063_A_RX_MIX3, .value_a = 0x0044, .value_g = 0x0044, .flags = 0, }, */
+ { .offset = B2063_A_RX_MIX4, .value_a = 0x0003, .value_g = 0x0003, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+ { .offset = B2063_A_RX_MIX5, .value_a = 0x000f, .value_g = 0x000f, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+ { .offset = B2063_A_RX_MIX6, .value_a = 0x000f, .value_g = 0x000f, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+ /* { .offset = B2063_A_RX_MIX7, .value_a = 0x0044, .value_g = 0x0044, .flags = 0, }, */
+ /* { .offset = B2063_A_RX_MIX8, .value_a = 0x0001, .value_g = 0x0001, .flags = 0, }, */
+ /* { .offset = B2063_A_RX_PWRDET1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+ /* { .offset = B2063_A_RX_SPARE1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+ /* { .offset = B2063_A_RX_SPARE2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+ /* { .offset = B2063_A_RX_SPARE3, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+ { .offset = B2063_RX_TIA_CTL1, .value_a = 0x0077, .value_g = 0x0077, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+ /* { .offset = B2063_RX_TIA_CTL2, .value_a = 0x0058, .value_g = 0x0058, .flags = 0, }, */
+ { .offset = B2063_RX_TIA_CTL3, .value_a = 0x0077, .value_g = 0x0077, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+ /* { .offset = B2063_RX_TIA_CTL4, .value_a = 0x0058, .value_g = 0x0058, .flags = 0, }, */
+ /* { .offset = B2063_RX_TIA_CTL5, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+ /* { .offset = B2063_RX_TIA_CTL6, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+ /* { .offset = B2063_RX_BB_CTL1, .value_a = 0x0074, .value_g = 0x0074, .flags = 0, }, */
+ { .offset = B2063_RX_BB_CTL2, .value_a = 0x0004, .value_g = 0x0004, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+ /* { .offset = B2063_RX_BB_CTL3, .value_a = 0x00a2, .value_g = 0x00a2, .flags = 0, }, */
+ /* { .offset = B2063_RX_BB_CTL4, .value_a = 0x00aa, .value_g = 0x00aa, .flags = 0, }, */
+ /* { .offset = B2063_RX_BB_CTL5, .value_a = 0x0024, .value_g = 0x0024, .flags = 0, }, */
+ /* { .offset = B2063_RX_BB_CTL6, .value_a = 0x00a9, .value_g = 0x00a9, .flags = 0, }, */
+ /* { .offset = B2063_RX_BB_CTL7, .value_a = 0x0028, .value_g = 0x0028, .flags = 0, }, */
+ /* { .offset = B2063_RX_BB_CTL8, .value_a = 0x0010, .value_g = 0x0010, .flags = 0, }, */
+ /* { .offset = B2063_RX_BB_CTL9, .value_a = 0x0055, .value_g = 0x0055, .flags = 0, }, */
+ /* { .offset = B2063_TX_RF_CTL1, .value_a = 0x0080, .value_g = 0x0080, .flags = 0, }, */
+ /* { .offset = B2063_TX_RF_IDAC_LO_RF_I, .value_a = 0x0088, .value_g = 0x0088, .flags = 0, }, */
+ /* { .offset = B2063_TX_RF_IDAC_LO_RF_Q, .value_a = 0x0088, .value_g = 0x0088, .flags = 0, }, */
+ /* { .offset = B2063_TX_RF_IDAC_LO_BB_I, .value_a = 0x0088, .value_g = 0x0088, .flags = 0, }, */
+ /* { .offset = B2063_TX_RF_IDAC_LO_BB_Q, .value_a = 0x0088, .value_g = 0x0088, .flags = 0, }, */
+ /* { .offset = B2063_TX_RF_CTL2, .value_a = 0x0080, .value_g = 0x0080, .flags = 0, }, */
+ /* { .offset = B2063_TX_RF_CTL3, .value_a = 0x0038, .value_g = 0x0038, .flags = 0, }, */
+ /* { .offset = B2063_TX_RF_CTL4, .value_a = 0x00b8, .value_g = 0x00b8, .flags = 0, }, */
+ /* { .offset = B2063_TX_RF_CTL5, .value_a = 0x0080, .value_g = 0x0080, .flags = 0, }, */
+ /* { .offset = B2063_TX_RF_CTL6, .value_a = 0x0038, .value_g = 0x0038, .flags = 0, }, */
+ /* { .offset = B2063_TX_RF_CTL7, .value_a = 0x0078, .value_g = 0x0078, .flags = 0, }, */
+ /* { .offset = B2063_TX_RF_CTL8, .value_a = 0x00c0, .value_g = 0x00c0, .flags = 0, }, */
+ /* { .offset = B2063_TX_RF_CTL9, .value_a = 0x0003, .value_g = 0x0003, .flags = 0, }, */
+ /* { .offset = B2063_TX_RF_CTL10, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+ /* { .offset = B2063_TX_RF_CTL14, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+ /* { .offset = B2063_TX_RF_CTL15, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+ { .offset = B2063_PA_CTL1, .value_a = 0x0000, .value_g = 0x0004, .flags = B206X_FLAG_A, },
+ /* { .offset = B2063_PA_CTL2, .value_a = 0x000c, .value_g = 0x000c, .flags = 0, }, */
+ /* { .offset = B2063_PA_CTL3, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+ /* { .offset = B2063_PA_CTL4, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+ /* { .offset = B2063_PA_CTL5, .value_a = 0x0096, .value_g = 0x0096, .flags = 0, }, */
+ /* { .offset = B2063_PA_CTL6, .value_a = 0x0077, .value_g = 0x0077, .flags = 0, }, */
+ /* { .offset = B2063_PA_CTL7, .value_a = 0x005a, .value_g = 0x005a, .flags = 0, }, */
+ /* { .offset = B2063_PA_CTL8, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+ /* { .offset = B2063_PA_CTL9, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+ /* { .offset = B2063_PA_CTL10, .value_a = 0x0021, .value_g = 0x0021, .flags = 0, }, */
+ /* { .offset = B2063_PA_CTL11, .value_a = 0x0070, .value_g = 0x0070, .flags = 0, }, */
+ /* { .offset = B2063_PA_CTL12, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+ /* { .offset = B2063_PA_CTL13, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+ /* { .offset = B2063_TX_BB_CTL1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+ /* { .offset = B2063_TX_BB_CTL2, .value_a = 0x00b3, .value_g = 0x00b3, .flags = 0, }, */
+ /* { .offset = B2063_TX_BB_CTL3, .value_a = 0x0055, .value_g = 0x0055, .flags = 0, }, */
+ /* { .offset = B2063_TX_BB_CTL4, .value_a = 0x000b, .value_g = 0x000b, .flags = 0, }, */
+ /* { .offset = B2063_GPIO_CTL1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+ { .offset = B2063_VREG_CTL1, .value_a = 0x0003, .value_g = 0x0003, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+ /* { .offset = B2063_AMUX_CTL1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+ /* { .offset = B2063_IQ_CALIB_GVAR, .value_a = 0x00b3, .value_g = 0x00b3, .flags = 0, }, */
+ /* { .offset = B2063_IQ_CALIB_CTL1, .value_a = 0x0055, .value_g = 0x0055, .flags = 0, }, */
+ /* { .offset = B2063_IQ_CALIB_CTL2, .value_a = 0x0030, .value_g = 0x0030, .flags = 0, }, */
+ /* { .offset = B2063_TEMPSENSE_CTL1, .value_a = 0x0046, .value_g = 0x0046, .flags = 0, }, */
+ /* { .offset = B2063_TEMPSENSE_CTL2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+ /* { .offset = B2063_TX_RX_LOOPBACK1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+ /* { .offset = B2063_TX_RX_LOOPBACK2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+ /* { .offset = B2063_EXT_TSSI_CTL1, .value_a = 0x0021, .value_g = 0x0021, .flags = 0, }, */
+ /* { .offset = B2063_EXT_TSSI_CTL2, .value_a = 0x0023, .value_g = 0x0023, .flags = 0, }, */
+ /* { .offset = B2063_AFE_CTL , .value_a = 0x0002, .value_g = 0x0002, .flags = 0, }, */
+};
+
void b2062_upload_init_table(struct b43_wldev *dev)
{
- const struct b2062_init_tab_entry *e;
+ const struct b206x_init_tab_entry *e;
unsigned int i;
for (i = 0; i < ARRAY_SIZE(b2062_init_tab); i++) {
e = &b2062_init_tab[i];
if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
- if (!(e->flags & B2062_FLAG_G))
+ if (!(e->flags & B206X_FLAG_G))
+ continue;
+ b43_radio_write(dev, e->offset, e->value_g);
+ } else {
+ if (!(e->flags & B206X_FLAG_A))
+ continue;
+ b43_radio_write(dev, e->offset, e->value_a);
+ }
+ }
+}
+
+void b2063_upload_init_table(struct b43_wldev *dev)
+{
+ const struct b206x_init_tab_entry *e;
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(b2063_init_tab); i++) {
+ e = &b2063_init_tab[i];
+ if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
+ if (!(e->flags & B206X_FLAG_G))
continue;
b43_radio_write(dev, e->offset, e->value_g);
} else {
- if (!(e->flags & B2062_FLAG_A))
+ if (!(e->flags & B206X_FLAG_A))
continue;
b43_radio_write(dev, e->offset, e->value_a);
}
@@ -392,3 +710,1726 @@ void b43_lptab_write_bulk(struct b43_wldev *dev, u32 offset,
offset++;
}
}
+
+static const u8 lpphy_min_sig_sq_table[] = {
+ 0xde, 0xdc, 0xda, 0xd8, 0xd6, 0xd4, 0xd2, 0xcf, 0xcd,
+ 0xca, 0xc7, 0xc4, 0xc1, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe,
+ 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0x00,
+ 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe,
+ 0xbe, 0xbe, 0xbe, 0xbe, 0xc1, 0xc4, 0xc7, 0xca, 0xcd,
+ 0xcf, 0xd2, 0xd4, 0xd6, 0xd8, 0xda, 0xdc, 0xde,
+};
+
+static const u16 lpphy_rev01_noise_scale_table[] = {
+ 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4,
+ 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa400, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4,
+ 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0x00a4,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4c00, 0x2d36,
+ 0x0000, 0x0000, 0x4c00, 0x2d36,
+};
+
+static const u16 lpphy_rev2plus_noise_scale_table[] = {
+ 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
+ 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
+ 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x0000,
+ 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
+ 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
+ 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
+ 0x00a4,
+};
+
+static const u16 lpphy_crs_gain_nft_table[] = {
+ 0x0366, 0x036a, 0x036f, 0x0364, 0x0367, 0x036d, 0x0374, 0x037f, 0x036f,
+ 0x037b, 0x038a, 0x0378, 0x0367, 0x036d, 0x0375, 0x0381, 0x0374, 0x0381,
+ 0x0392, 0x03a9, 0x03c4, 0x03e1, 0x0001, 0x001f, 0x0040, 0x005e, 0x007f,
+ 0x009e, 0x00bd, 0x00dd, 0x00fd, 0x011d, 0x013d,
+};
+
+static const u16 lpphy_rev01_filter_control_table[] = {
+ 0xa0fc, 0x10fc, 0x10db, 0x20b7, 0xff93, 0x10bf, 0x109b, 0x2077, 0xff53,
+ 0x0127,
+};
+
+static const u32 lpphy_rev2plus_filter_control_table[] = {
+ 0x000141fc, 0x000021fc, 0x000021b7, 0x0000416f, 0x0001ff27, 0x0000217f,
+ 0x00002137, 0x000040ef, 0x0001fea7, 0x0000024f,
+};
+
+static const u32 lpphy_rev01_ps_control_table[] = {
+ 0x00010000, 0x000000a0, 0x00040000, 0x00000048, 0x08080101, 0x00000080,
+ 0x08080101, 0x00000040, 0x08080101, 0x000000c0, 0x08a81501, 0x000000c0,
+ 0x0fe8fd01, 0x000000c0, 0x08300105, 0x000000c0, 0x08080201, 0x000000c0,
+ 0x08280205, 0x000000c0, 0xe80802fe, 0x000000c7, 0x28080206, 0x000000c0,
+ 0x08080202, 0x000000c0, 0x0ba87602, 0x000000c0, 0x1068013d, 0x000000c0,
+ 0x10280105, 0x000000c0, 0x08880102, 0x000000c0, 0x08280106, 0x000000c0,
+ 0xe80801fd, 0x000000c7, 0xa8080115, 0x000000c0,
+};
+
+static const u32 lpphy_rev2plus_ps_control_table[] = {
+ 0x00e38e08, 0x00e08e38, 0x00000000, 0x00000000, 0x00000000, 0x00002080,
+ 0x00006180, 0x00003002, 0x00000040, 0x00002042, 0x00180047, 0x00080043,
+ 0x00000041, 0x000020c1, 0x00046006, 0x00042002, 0x00040000, 0x00002003,
+ 0x00180006, 0x00080002,
+};
+
+static const u8 lpphy_pll_fraction_table[] = {
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+};
+
+static const u16 lpphy_iq_local_table[] = {
+ 0x0200, 0x0300, 0x0400, 0x0600, 0x0800, 0x0b00, 0x1000, 0x1001, 0x1002,
+ 0x1003, 0x1004, 0x1005, 0x1006, 0x1007, 0x1707, 0x2007, 0x2d07, 0x4007,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0200, 0x0300, 0x0400, 0x0600,
+ 0x0800, 0x0b00, 0x1000, 0x1001, 0x1002, 0x1003, 0x1004, 0x1005, 0x1006,
+ 0x1007, 0x1707, 0x2007, 0x2d07, 0x4007, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000,
+};
+
+static const u16 lpphy_ofdm_cck_gain_table[] = {
+ 0x5000, 0x6000, 0x7000, 0x0001, 0x1001, 0x2001, 0x3001, 0x4001, 0x5001,
+ 0x6001, 0x7001, 0x7011, 0x7021, 0x2035, 0x2045, 0x2055, 0x2065, 0x2075,
+ 0x006d, 0x007d, 0x014d, 0x015d, 0x115d, 0x035d, 0x135d, 0x055d, 0x155d,
+ 0x0d5d, 0x1d5d, 0x2d5d, 0x555d, 0x655d, 0x755d,
+};
+
+static const u16 lpphy_gain_delta_table[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+};
+
+static const u32 lpphy_tx_power_control_table[] = {
+ 0x00000050, 0x0000004f, 0x0000004e, 0x0000004d, 0x0000004c, 0x0000004b,
+ 0x0000004a, 0x00000049, 0x00000048, 0x00000047, 0x00000046, 0x00000045,
+ 0x00000044, 0x00000043, 0x00000042, 0x00000041, 0x00000040, 0x0000003f,
+ 0x0000003e, 0x0000003d, 0x0000003c, 0x0000003b, 0x0000003a, 0x00000039,
+ 0x00000038, 0x00000037, 0x00000036, 0x00000035, 0x00000034, 0x00000033,
+ 0x00000032, 0x00000031, 0x00000030, 0x0000002f, 0x0000002e, 0x0000002d,
+ 0x0000002c, 0x0000002b, 0x0000002a, 0x00000029, 0x00000028, 0x00000027,
+ 0x00000026, 0x00000025, 0x00000024, 0x00000023, 0x00000022, 0x00000021,
+ 0x00000020, 0x0000001f, 0x0000001e, 0x0000001d, 0x0000001c, 0x0000001b,
+ 0x0000001a, 0x00000019, 0x00000018, 0x00000017, 0x00000016, 0x00000015,
+ 0x00000014, 0x00000013, 0x00000012, 0x00000011, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x000075a0, 0x000075a0, 0x000075a1, 0x000075a1, 0x000075a2, 0x000075a2,
+ 0x000075a3, 0x000075a3, 0x000074b0, 0x000074b0, 0x000074b1, 0x000074b1,
+ 0x000074b2, 0x000074b2, 0x000074b3, 0x000074b3, 0x00006d20, 0x00006d20,
+ 0x00006d21, 0x00006d21, 0x00006d22, 0x00006d22, 0x00006d23, 0x00006d23,
+ 0x00004660, 0x00004660, 0x00004661, 0x00004661, 0x00004662, 0x00004662,
+ 0x00004663, 0x00004663, 0x00003e60, 0x00003e60, 0x00003e61, 0x00003e61,
+ 0x00003e62, 0x00003e62, 0x00003e63, 0x00003e63, 0x00003660, 0x00003660,
+ 0x00003661, 0x00003661, 0x00003662, 0x00003662, 0x00003663, 0x00003663,
+ 0x00002e60, 0x00002e60, 0x00002e61, 0x00002e61, 0x00002e62, 0x00002e62,
+ 0x00002e63, 0x00002e63, 0x00002660, 0x00002660, 0x00002661, 0x00002661,
+ 0x00002662, 0x00002662, 0x00002663, 0x00002663, 0x000025e0, 0x000025e0,
+ 0x000025e1, 0x000025e1, 0x000025e2, 0x000025e2, 0x000025e3, 0x000025e3,
+ 0x00001de0, 0x00001de0, 0x00001de1, 0x00001de1, 0x00001de2, 0x00001de2,
+ 0x00001de3, 0x00001de3, 0x00001d60, 0x00001d60, 0x00001d61, 0x00001d61,
+ 0x00001d62, 0x00001d62, 0x00001d63, 0x00001d63, 0x00001560, 0x00001560,
+ 0x00001561, 0x00001561, 0x00001562, 0x00001562, 0x00001563, 0x00001563,
+ 0x00000d60, 0x00000d60, 0x00000d61, 0x00000d61, 0x00000d62, 0x00000d62,
+ 0x00000d63, 0x00000d63, 0x00000ce0, 0x00000ce0, 0x00000ce1, 0x00000ce1,
+ 0x00000ce2, 0x00000ce2, 0x00000ce3, 0x00000ce3, 0x00000e10, 0x00000e10,
+ 0x00000e11, 0x00000e11, 0x00000e12, 0x00000e12, 0x00000e13, 0x00000e13,
+ 0x00000bf0, 0x00000bf0, 0x00000bf1, 0x00000bf1, 0x00000bf2, 0x00000bf2,
+ 0x00000bf3, 0x00000bf3, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
+ 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
+ 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
+ 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
+ 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
+ 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
+ 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
+ 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
+ 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
+ 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
+ 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
+ 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
+ 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
+ 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
+ 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
+ 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
+ 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
+ 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
+ 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
+ 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
+ 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
+ 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x000000ff, 0x000002fc,
+ 0x0000fa08, 0x00000305, 0x00000206, 0x00000304, 0x0000fb04, 0x0000fcff,
+ 0x000005fb, 0x0000fd01, 0x00000401, 0x00000006, 0x0000ff03, 0x000007fc,
+ 0x0000fc08, 0x00000203, 0x0000fffb, 0x00000600, 0x0000fa01, 0x0000fc03,
+ 0x0000fe06, 0x0000fe00, 0x00000102, 0x000007fd, 0x000004fb, 0x000006ff,
+ 0x000004fd, 0x0000fdfa, 0x000007fb, 0x0000fdfa, 0x0000fa06, 0x00000500,
+ 0x0000f902, 0x000007fa, 0x0000fafa, 0x00000500, 0x000007fa, 0x00000700,
+ 0x00000305, 0x000004ff, 0x00000801, 0x00000503, 0x000005f9, 0x00000404,
+ 0x0000fb08, 0x000005fd, 0x00000501, 0x00000405, 0x0000fb03, 0x000007fc,
+ 0x00000403, 0x00000303, 0x00000402, 0x0000faff, 0x0000fe05, 0x000005fd,
+ 0x0000fe01, 0x000007fa, 0x00000202, 0x00000504, 0x00000102, 0x000008fe,
+ 0x0000fa04, 0x0000fafc, 0x0000fe08, 0x000000f9, 0x000002fa, 0x000003fe,
+ 0x00000304, 0x000004f9, 0x00000100, 0x0000fd06, 0x000008fc, 0x00000701,
+ 0x00000504, 0x0000fdfe, 0x0000fdfc, 0x000003fe, 0x00000704, 0x000002fc,
+ 0x000004f9, 0x0000fdfd, 0x0000fa07, 0x00000205, 0x000003fd, 0x000005fb,
+ 0x000004f9, 0x00000804, 0x0000fc06, 0x0000fcf9, 0x00000100, 0x0000fe05,
+ 0x00000408, 0x0000fb02, 0x00000304, 0x000006fe, 0x000004fa, 0x00000305,
+ 0x000008fc, 0x00000102, 0x000001fd, 0x000004fc, 0x0000fe03, 0x00000701,
+ 0x000001fb, 0x000001f9, 0x00000206, 0x000006fd, 0x00000508, 0x00000700,
+ 0x00000304, 0x000005fe, 0x000005ff, 0x0000fa04, 0x00000303, 0x0000fefb,
+ 0x000007f9, 0x0000fefc, 0x000004fd, 0x000005fc, 0x0000fffd, 0x0000fc08,
+ 0x0000fbf9, 0x0000fd07, 0x000008fb, 0x0000fe02, 0x000006fb, 0x00000702,
+};
+
+static const u32 lpphy_gain_idx_table[] = {
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x10000001, 0x00000000, 0x20000082, 0x00000000, 0x40000104, 0x00000000,
+ 0x60004207, 0x00000001, 0x7000838a, 0x00000001, 0xd021050d, 0x00000001,
+ 0xe041c683, 0x00000001, 0x50828805, 0x00000000, 0x80e34288, 0x00000000,
+ 0xb144040b, 0x00000000, 0xe1a6058e, 0x00000000, 0x12064711, 0x00000001,
+ 0xb0a18612, 0x00000010, 0xe1024794, 0x00000010, 0x11630915, 0x00000011,
+ 0x31c3ca1b, 0x00000011, 0xc1848a9c, 0x00000018, 0xf1e50da0, 0x00000018,
+ 0x22468e21, 0x00000019, 0x4286d023, 0x00000019, 0xa347d0a4, 0x00000019,
+ 0xb36811a6, 0x00000019, 0xf3e89227, 0x00000019, 0x0408d329, 0x0000001a,
+ 0x244953aa, 0x0000001a, 0x346994ab, 0x0000001a, 0x54aa152c, 0x0000001a,
+ 0x64ca55ad, 0x0000001a, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x10000001, 0x00000000, 0x20000082, 0x00000000,
+ 0x40000104, 0x00000000, 0x60004207, 0x00000001, 0x7000838a, 0x00000001,
+ 0xd021050d, 0x00000001, 0xe041c683, 0x00000001, 0x50828805, 0x00000000,
+ 0x80e34288, 0x00000000, 0xb144040b, 0x00000000, 0xe1a6058e, 0x00000000,
+ 0x12064711, 0x00000001, 0xb0a18612, 0x00000010, 0xe1024794, 0x00000010,
+ 0x11630915, 0x00000011, 0x31c3ca1b, 0x00000011, 0xc1848a9c, 0x00000018,
+ 0xf1e50da0, 0x00000018, 0x22468e21, 0x00000019, 0x4286d023, 0x00000019,
+ 0xa347d0a4, 0x00000019, 0xb36811a6, 0x00000019, 0xf3e89227, 0x00000019,
+ 0x0408d329, 0x0000001a, 0x244953aa, 0x0000001a, 0x346994ab, 0x0000001a,
+ 0x54aa152c, 0x0000001a, 0x64ca55ad, 0x0000001a,
+};
+
+static const u16 lpphy_aux_gain_idx_table[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0001, 0x0002, 0x0004, 0x0016, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0002, 0x0004, 0x0016,
+};
+
+static const u32 lpphy_gain_value_table[] = {
+ 0x00000008, 0x0000000e, 0x00000014, 0x0000001a, 0x000000fb, 0x00000004,
+ 0x00000008, 0x0000000d, 0x00000001, 0x00000004, 0x00000007, 0x0000000a,
+ 0x0000000d, 0x00000010, 0x00000012, 0x00000015, 0x00000000, 0x00000006,
+ 0x0000000c, 0x00000000, 0x00000000, 0x00000000, 0x00000012, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000018, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x0000001e, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000003, 0x00000006, 0x00000009, 0x0000000c, 0x0000000f,
+ 0x00000012, 0x00000015, 0x00000018, 0x0000001b, 0x0000001e, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000009, 0x000000f1,
+ 0x00000000, 0x00000000,
+};
+
+static const u16 lpphy_gain_table[] = {
+ 0x0000, 0x0400, 0x0800, 0x0802, 0x0804, 0x0806, 0x0807, 0x0808, 0x080a,
+ 0x080b, 0x080c, 0x080e, 0x080f, 0x0810, 0x0812, 0x0813, 0x0814, 0x0816,
+ 0x0817, 0x081a, 0x081b, 0x081f, 0x0820, 0x0824, 0x0830, 0x0834, 0x0837,
+ 0x083b, 0x083f, 0x0840, 0x0844, 0x0857, 0x085b, 0x085f, 0x08d7, 0x08db,
+ 0x08df, 0x0957, 0x095b, 0x095f, 0x0b57, 0x0b5b, 0x0b5f, 0x0f5f, 0x135f,
+ 0x175f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+};
+
+static const u32 lpphy_a0_gain_idx_table[] = {
+ 0x001111e0, 0x00652051, 0x00606055, 0x005b005a, 0x00555060, 0x00511065,
+ 0x004c806b, 0x0047d072, 0x00444078, 0x00400080, 0x003ca087, 0x0039408f,
+ 0x0035e098, 0x0032e0a1, 0x003030aa, 0x002d80b4, 0x002ae0bf, 0x002880ca,
+ 0x002640d6, 0x002410e3, 0x002220f0, 0x002020ff, 0x001e510e, 0x001ca11e,
+ 0x001b012f, 0x00199140, 0x00182153, 0x0016c168, 0x0015817d, 0x00145193,
+ 0x001321ab, 0x001211c5, 0x001111e0, 0x001021fc, 0x000f321a, 0x000e523a,
+ 0x000d925c, 0x000cd27f, 0x000c12a5, 0x000b62cd, 0x000ac2f8, 0x000a2325,
+ 0x00099355, 0x00091387, 0x000883bd, 0x000813f5, 0x0007a432, 0x00073471,
+ 0x0006c4b5, 0x000664fc, 0x00061547, 0x0005b598, 0x000565ec, 0x00051646,
+ 0x0004d6a5, 0x0004870a, 0x00044775, 0x000407e6, 0x0003d85e, 0x000398dd,
+ 0x00036963, 0x000339f2, 0x00030a89, 0x0002db28,
+};
+
+static const u16 lpphy_a0_aux_gain_idx_table[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0002, 0x0014, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0002, 0x0014,
+};
+
+static const u32 lpphy_a0_gain_value_table[] = {
+ 0x00000008, 0x0000000e, 0x00000014, 0x0000001a, 0x000000fb, 0x00000004,
+ 0x00000008, 0x0000000d, 0x00000001, 0x00000004, 0x00000007, 0x0000000a,
+ 0x0000000d, 0x00000010, 0x00000012, 0x00000015, 0x00000000, 0x00000006,
+ 0x0000000c, 0x00000000, 0x00000000, 0x00000000, 0x00000012, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000018, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x0000001e, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000003, 0x00000006, 0x00000009, 0x0000000c, 0x0000000f,
+ 0x00000012, 0x00000015, 0x00000018, 0x0000001b, 0x0000001e, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0000000f, 0x000000f7,
+ 0x00000000, 0x00000000,
+};
+
+static const u16 lpphy_a0_gain_table[] = {
+ 0x0000, 0x0002, 0x0004, 0x0006, 0x0007, 0x0008, 0x000a, 0x000b, 0x000c,
+ 0x000e, 0x000f, 0x0010, 0x0012, 0x0013, 0x0014, 0x0016, 0x0017, 0x001a,
+ 0x001b, 0x001f, 0x0020, 0x0024, 0x0030, 0x0034, 0x0037, 0x003b, 0x003f,
+ 0x0040, 0x0044, 0x0057, 0x005b, 0x005f, 0x00d7, 0x00db, 0x00df, 0x0157,
+ 0x015b, 0x015f, 0x0357, 0x035b, 0x035f, 0x075f, 0x0b5f, 0x0f5f, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+};
+
+static const u16 lpphy_sw_control_table[] = {
+ 0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028, 0x0128,
+ 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028, 0x0009, 0x0009,
+ 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0018, 0x0018, 0x0018,
+ 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0128, 0x0128, 0x0009, 0x0009,
+ 0x0028, 0x0028, 0x0028, 0x0028, 0x0128, 0x0128, 0x0009, 0x0009, 0x0028,
+ 0x0028, 0x0028, 0x0028, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009,
+ 0x0009, 0x0009, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018,
+ 0x0018,
+};
+
+static const u8 lpphy_hf_table[] = {
+ 0x4b, 0x36, 0x24, 0x18, 0x49, 0x34, 0x23, 0x17, 0x48,
+ 0x33, 0x23, 0x17, 0x48, 0x33, 0x23, 0x17,
+};
+
+static const u32 lpphy_papd_eps_table[] = {
+ 0x00000000, 0x00013ffc, 0x0001dff3, 0x0001bff0, 0x00023fe9, 0x00021fdf,
+ 0x00028fdf, 0x00033fd2, 0x00039fcb, 0x00043fc7, 0x0004efc2, 0x00055fb5,
+ 0x0005cfb0, 0x00063fa8, 0x00068fa3, 0x00071f98, 0x0007ef92, 0x00084f8b,
+ 0x0008df82, 0x00097f77, 0x0009df69, 0x000a3f62, 0x000adf57, 0x000b6f4c,
+ 0x000bff41, 0x000c9f39, 0x000cff30, 0x000dbf27, 0x000e4f1e, 0x000edf16,
+ 0x000f7f13, 0x00102f11, 0x00110f10, 0x0011df11, 0x0012ef15, 0x00143f1c,
+ 0x00158f27, 0x00172f35, 0x00193f47, 0x001baf5f, 0x001e6f7e, 0x0021cfa4,
+ 0x0025bfd2, 0x002a2008, 0x002fb047, 0x00360090, 0x003d40e0, 0x0045c135,
+ 0x004fb189, 0x005ae1d7, 0x0067221d, 0x0075025a, 0x007ff291, 0x007ff2bf,
+ 0x007ff2e3, 0x007ff2ff, 0x007ff315, 0x007ff329, 0x007ff33f, 0x007ff356,
+ 0x007ff36e, 0x007ff39c, 0x007ff441, 0x007ff506,
+};
+
+static const u32 lpphy_papd_mult_table[] = {
+ 0x001111e0, 0x00652051, 0x00606055, 0x005b005a, 0x00555060, 0x00511065,
+ 0x004c806b, 0x0047d072, 0x00444078, 0x00400080, 0x003ca087, 0x0039408f,
+ 0x0035e098, 0x0032e0a1, 0x003030aa, 0x002d80b4, 0x002ae0bf, 0x002880ca,
+ 0x002640d6, 0x002410e3, 0x002220f0, 0x002020ff, 0x001e510e, 0x001ca11e,
+ 0x001b012f, 0x00199140, 0x00182153, 0x0016c168, 0x0015817d, 0x00145193,
+ 0x001321ab, 0x001211c5, 0x001111e0, 0x001021fc, 0x000f321a, 0x000e523a,
+ 0x000d925c, 0x000cd27f, 0x000c12a5, 0x000b62cd, 0x000ac2f8, 0x000a2325,
+ 0x00099355, 0x00091387, 0x000883bd, 0x000813f5, 0x0007a432, 0x00073471,
+ 0x0006c4b5, 0x000664fc, 0x00061547, 0x0005b598, 0x000565ec, 0x00051646,
+ 0x0004d6a5, 0x0004870a, 0x00044775, 0x000407e6, 0x0003d85e, 0x000398dd,
+ 0x00036963, 0x000339f2, 0x00030a89, 0x0002db28,
+};
+
+static struct lpphy_tx_gain_table_entry lpphy_rev0_nopa_tx_gain_table[] = {
+ { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 152, },
+ { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 147, },
+ { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 143, },
+ { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 139, },
+ { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 135, },
+ { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 131, },
+ { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 128, },
+ { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 124, },
+ { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 121, },
+ { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 117, },
+ { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 114, },
+ { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 111, },
+ { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 107, },
+ { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 104, },
+ { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 101, },
+ { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 99, },
+ { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 96, },
+ { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 93, },
+ { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 90, },
+ { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 88, },
+ { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 85, },
+ { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 83, },
+ { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 81, },
+ { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 78, },
+ { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 76, },
+ { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 74, },
+ { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 72, },
+ { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 70, },
+ { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 68, },
+ { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 66, },
+ { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 62, },
+ { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 60, },
+ { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 59, },
+ { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 57, },
+ { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 72, },
+ { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 70, },
+ { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 68, },
+ { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 66, },
+ { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 62, },
+ { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 60, },
+ { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 59, },
+ { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 57, },
+ { .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 71, },
+ { .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 69, },
+ { .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 67, },
+ { .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 65, },
+ { .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 63, },
+ { .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 62, },
+ { .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 60, },
+ { .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 58, },
+ { .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 57, },
+ { .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 70, },
+ { .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 68, },
+ { .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 66, },
+ { .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 65, },
+ { .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 63, },
+ { .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 61, },
+ { .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 59, },
+ { .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 58, },
+ { .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 71, },
+ { .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 69, },
+ { .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 67, },
+ { .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 65, },
+ { .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 63, },
+ { .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 61, },
+ { .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 60, },
+ { .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 58, },
+ { .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 56, },
+ { .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 70, },
+ { .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 68, },
+ { .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 66, },
+ { .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 62, },
+ { .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 60, },
+ { .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 59, },
+ { .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 72, },
+ { .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 70, },
+ { .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 68, },
+ { .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 66, },
+ { .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 62, },
+ { .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 60, },
+ { .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 59, },
+ { .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 72, },
+ { .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 70, },
+ { .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 68, },
+ { .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 66, },
+ { .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 63, },
+ { .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 61, },
+ { .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 59, },
+ { .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 57, },
+ { .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 72, },
+ { .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 70, },
+ { .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 68, },
+ { .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 66, },
+ { .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 62, },
+ { .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 60, },
+ { .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 59, },
+ { .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 72, },
+ { .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 70, },
+ { .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 68, },
+ { .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 66, },
+ { .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 62, },
+ { .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 61, },
+ { .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 59, },
+ { .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 73, },
+ { .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 71, },
+ { .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 69, },
+ { .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 67, },
+ { .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 65, },
+ { .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 63, },
+ { .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 61, },
+ { .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 59, },
+ { .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 72, },
+ { .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 70, },
+ { .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 68, },
+ { .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 66, },
+ { .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 65, },
+ { .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 63, },
+ { .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 61, },
+ { .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 59, },
+ { .gm = 7, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 73, },
+ { .gm = 7, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 71, },
+};
+
+static struct lpphy_tx_gain_table_entry lpphy_rev0_2ghz_tx_gain_table[] = {
+ { .gm = 4, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 64, },
+ { .gm = 4, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 62, },
+ { .gm = 4, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 60, },
+ { .gm = 4, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 59, },
+ { .gm = 4, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 72, },
+ { .gm = 4, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 70, },
+ { .gm = 4, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 68, },
+ { .gm = 4, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 66, },
+ { .gm = 4, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 64, },
+ { .gm = 4, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 62, },
+ { .gm = 4, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 60, },
+ { .gm = 4, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 59, },
+ { .gm = 4, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 72, },
+ { .gm = 4, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 70, },
+ { .gm = 4, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 68, },
+ { .gm = 4, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 66, },
+ { .gm = 4, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 64, },
+ { .gm = 4, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 63, },
+ { .gm = 4, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 61, },
+ { .gm = 4, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 59, },
+ { .gm = 4, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 57, },
+ { .gm = 4, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 72, },
+ { .gm = 4, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 70, },
+ { .gm = 4, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 68, },
+ { .gm = 4, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 66, },
+ { .gm = 4, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 64, },
+ { .gm = 4, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 62, },
+ { .gm = 4, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 60, },
+ { .gm = 4, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 59, },
+ { .gm = 4, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 72, },
+ { .gm = 4, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 70, },
+ { .gm = 4, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 68, },
+ { .gm = 4, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 66, },
+ { .gm = 4, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 64, },
+ { .gm = 4, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 62, },
+ { .gm = 4, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 61, },
+ { .gm = 4, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 59, },
+ { .gm = 4, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 73, },
+ { .gm = 4, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 71, },
+ { .gm = 4, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 69, },
+ { .gm = 4, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 67, },
+ { .gm = 4, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 65, },
+ { .gm = 4, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 63, },
+ { .gm = 4, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 61, },
+ { .gm = 4, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 59, },
+ { .gm = 4, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 72, },
+ { .gm = 4, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 70, },
+ { .gm = 4, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 68, },
+ { .gm = 4, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 66, },
+ { .gm = 4, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 65, },
+ { .gm = 4, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 63, },
+ { .gm = 4, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 61, },
+ { .gm = 4, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 59, },
+ { .gm = 4, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 73, },
+ { .gm = 4, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 71, },
+ { .gm = 4, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 69, },
+ { .gm = 4, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 67, },
+ { .gm = 4, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 65, },
+ { .gm = 4, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 63, },
+ { .gm = 4, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 61, },
+ { .gm = 4, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 60, },
+ { .gm = 4, .pga = 10, .pad = 6, .dac = 0, .bb_mult = 72, },
+ { .gm = 4, .pga = 10, .pad = 6, .dac = 0, .bb_mult = 70, },
+ { .gm = 4, .pga = 10, .pad = 6, .dac = 0, .bb_mult = 68, },
+ { .gm = 4, .pga = 10, .pad = 6, .dac = 0, .bb_mult = 66, },
+ { .gm = 4, .pga = 10, .pad = 6, .dac = 0, .bb_mult = 64, },
+ { .gm = 4, .pga = 10, .pad = 6, .dac = 0, .bb_mult = 62, },
+ { .gm = 4, .pga = 10, .pad = 6, .dac = 0, .bb_mult = 60, },
+ { .gm = 4, .pga = 10, .pad = 6, .dac = 0, .bb_mult = 59, },
+ { .gm = 4, .pga = 10, .pad = 5, .dac = 0, .bb_mult = 72, },
+ { .gm = 4, .pga = 10, .pad = 5, .dac = 0, .bb_mult = 70, },
+ { .gm = 4, .pga = 10, .pad = 5, .dac = 0, .bb_mult = 68, },
+ { .gm = 4, .pga = 10, .pad = 5, .dac = 0, .bb_mult = 66, },
+ { .gm = 4, .pga = 10, .pad = 5, .dac = 0, .bb_mult = 64, },
+ { .gm = 4, .pga = 10, .pad = 5, .dac = 0, .bb_mult = 62, },
+ { .gm = 4, .pga = 10, .pad = 5, .dac = 0, .bb_mult = 60, },
+ { .gm = 4, .pga = 10, .pad = 5, .dac = 0, .bb_mult = 59, },
+ { .gm = 4, .pga = 9, .pad = 5, .dac = 0, .bb_mult = 70, },
+ { .gm = 4, .pga = 9, .pad = 5, .dac = 0, .bb_mult = 68, },
+ { .gm = 4, .pga = 9, .pad = 5, .dac = 0, .bb_mult = 66, },
+ { .gm = 4, .pga = 9, .pad = 5, .dac = 0, .bb_mult = 64, },
+ { .gm = 4, .pga = 9, .pad = 5, .dac = 0, .bb_mult = 63, },
+ { .gm = 4, .pga = 9, .pad = 5, .dac = 0, .bb_mult = 61, },
+ { .gm = 4, .pga = 9, .pad = 5, .dac = 0, .bb_mult = 59, },
+ { .gm = 4, .pga = 9, .pad = 4, .dac = 0, .bb_mult = 71, },
+ { .gm = 4, .pga = 9, .pad = 4, .dac = 0, .bb_mult = 69, },
+ { .gm = 4, .pga = 9, .pad = 4, .dac = 0, .bb_mult = 67, },
+ { .gm = 4, .pga = 9, .pad = 4, .dac = 0, .bb_mult = 65, },
+ { .gm = 4, .pga = 9, .pad = 4, .dac = 0, .bb_mult = 63, },
+ { .gm = 4, .pga = 9, .pad = 4, .dac = 0, .bb_mult = 62, },
+ { .gm = 4, .pga = 9, .pad = 4, .dac = 0, .bb_mult = 60, },
+ { .gm = 4, .pga = 9, .pad = 4, .dac = 0, .bb_mult = 58, },
+ { .gm = 4, .pga = 8, .pad = 4, .dac = 0, .bb_mult = 70, },
+ { .gm = 4, .pga = 8, .pad = 4, .dac = 0, .bb_mult = 68, },
+ { .gm = 4, .pga = 8, .pad = 4, .dac = 0, .bb_mult = 66, },
+ { .gm = 4, .pga = 8, .pad = 4, .dac = 0, .bb_mult = 65, },
+ { .gm = 4, .pga = 8, .pad = 4, .dac = 0, .bb_mult = 63, },
+ { .gm = 4, .pga = 8, .pad = 4, .dac = 0, .bb_mult = 61, },
+ { .gm = 4, .pga = 8, .pad = 4, .dac = 0, .bb_mult = 59, },
+ { .gm = 4, .pga = 7, .pad = 4, .dac = 0, .bb_mult = 68, },
+ { .gm = 4, .pga = 7, .pad = 4, .dac = 0, .bb_mult = 66, },
+ { .gm = 4, .pga = 7, .pad = 4, .dac = 0, .bb_mult = 64, },
+ { .gm = 4, .pga = 7, .pad = 4, .dac = 0, .bb_mult = 62, },
+ { .gm = 4, .pga = 7, .pad = 4, .dac = 0, .bb_mult = 61, },
+ { .gm = 4, .pga = 7, .pad = 4, .dac = 0, .bb_mult = 59, },
+ { .gm = 4, .pga = 7, .pad = 3, .dac = 0, .bb_mult = 67, },
+ { .gm = 4, .pga = 7, .pad = 3, .dac = 0, .bb_mult = 65, },
+ { .gm = 4, .pga = 7, .pad = 3, .dac = 0, .bb_mult = 63, },
+ { .gm = 4, .pga = 7, .pad = 3, .dac = 0, .bb_mult = 62, },
+ { .gm = 4, .pga = 7, .pad = 3, .dac = 0, .bb_mult = 60, },
+ { .gm = 4, .pga = 6, .pad = 3, .dac = 0, .bb_mult = 65, },
+ { .gm = 4, .pga = 6, .pad = 3, .dac = 0, .bb_mult = 63, },
+ { .gm = 4, .pga = 6, .pad = 3, .dac = 0, .bb_mult = 61, },
+ { .gm = 4, .pga = 6, .pad = 3, .dac = 0, .bb_mult = 60, },
+ { .gm = 4, .pga = 6, .pad = 3, .dac = 0, .bb_mult = 58, },
+ { .gm = 4, .pga = 5, .pad = 3, .dac = 0, .bb_mult = 68, },
+ { .gm = 4, .pga = 5, .pad = 3, .dac = 0, .bb_mult = 66, },
+ { .gm = 4, .pga = 5, .pad = 3, .dac = 0, .bb_mult = 64, },
+ { .gm = 4, .pga = 5, .pad = 3, .dac = 0, .bb_mult = 62, },
+ { .gm = 4, .pga = 5, .pad = 3, .dac = 0, .bb_mult = 60, },
+ { .gm = 4, .pga = 5, .pad = 3, .dac = 0, .bb_mult = 59, },
+ { .gm = 4, .pga = 5, .pad = 3, .dac = 0, .bb_mult = 57, },
+ { .gm = 4, .pga = 4, .pad = 2, .dac = 0, .bb_mult = 83, },
+ { .gm = 4, .pga = 4, .pad = 2, .dac = 0, .bb_mult = 81, },
+ { .gm = 4, .pga = 4, .pad = 2, .dac = 0, .bb_mult = 78, },
+ { .gm = 4, .pga = 4, .pad = 2, .dac = 0, .bb_mult = 76, },
+ { .gm = 4, .pga = 4, .pad = 2, .dac = 0, .bb_mult = 74, },
+ { .gm = 4, .pga = 4, .pad = 2, .dac = 0, .bb_mult = 72, },
+};
+
+static struct lpphy_tx_gain_table_entry lpphy_rev0_5ghz_tx_gain_table[] = {
+ { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 99, },
+ { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 96, },
+ { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 93, },
+ { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 90, },
+ { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 88, },
+ { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 85, },
+ { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 83, },
+ { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 81, },
+ { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 78, },
+ { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 76, },
+ { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 74, },
+ { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 72, },
+ { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 70, },
+ { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 68, },
+ { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 66, },
+ { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 62, },
+ { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 60, },
+ { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 59, },
+ { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 57, },
+ { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 55, },
+ { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 72, },
+ { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 70, },
+ { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 68, },
+ { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 66, },
+ { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 62, },
+ { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 60, },
+ { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 58, },
+ { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 56, },
+ { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 55, },
+ { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 71, },
+ { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 69, },
+ { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 67, },
+ { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 65, },
+ { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 63, },
+ { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 62, },
+ { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 60, },
+ { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 58, },
+ { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 56, },
+ { .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 72, },
+ { .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 70, },
+ { .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 68, },
+ { .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 66, },
+ { .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 62, },
+ { .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 60, },
+ { .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 59, },
+ { .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 57, },
+ { .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 73, },
+ { .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 71, },
+ { .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 69, },
+ { .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 67, },
+ { .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 65, },
+ { .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 63, },
+ { .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 61, },
+ { .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 60, },
+ { .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 58, },
+ { .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 71, },
+ { .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 69, },
+ { .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 67, },
+ { .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 65, },
+ { .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 63, },
+ { .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 61, },
+ { .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 60, },
+ { .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 58, },
+ { .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 70, },
+ { .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 68, },
+ { .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 66, },
+ { .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 62, },
+ { .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 61, },
+ { .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 59, },
+ { .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 57, },
+ { .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 56, },
+ { .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 68, },
+ { .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 66, },
+ { .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 65, },
+ { .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 63, },
+ { .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 61, },
+ { .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 59, },
+ { .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 58, },
+ { .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 70, },
+ { .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 68, },
+ { .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 66, },
+ { .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 63, },
+ { .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 61, },
+ { .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 59, },
+ { .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 57, },
+ { .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 70, },
+ { .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 68, },
+ { .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 66, },
+ { .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 62, },
+ { .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 60, },
+ { .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 59, },
+ { .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 57, },
+ { .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 70, },
+ { .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 68, },
+ { .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 66, },
+ { .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 62, },
+ { .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 61, },
+ { .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 59, },
+ { .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 57, },
+ { .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 70, },
+ { .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 68, },
+ { .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 66, },
+ { .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 62, },
+ { .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 61, },
+ { .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 59, },
+ { .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 57, },
+ { .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 70, },
+ { .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 68, },
+ { .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 66, },
+ { .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 62, },
+ { .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 61, },
+ { .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 59, },
+ { .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 57, },
+ { .gm = 7, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 69, },
+ { .gm = 7, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 67, },
+ { .gm = 7, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 65, },
+ { .gm = 7, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 63, },
+ { .gm = 7, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 62, },
+ { .gm = 7, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 60, },
+};
+
+static struct lpphy_tx_gain_table_entry lpphy_rev1_nopa_tx_gain_table[] = {
+ { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 152, },
+ { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 147, },
+ { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 143, },
+ { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 139, },
+ { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 135, },
+ { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 131, },
+ { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 128, },
+ { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 124, },
+ { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 121, },
+ { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 117, },
+ { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 114, },
+ { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 111, },
+ { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 107, },
+ { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 104, },
+ { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 101, },
+ { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 99, },
+ { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 96, },
+ { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 93, },
+ { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 90, },
+ { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 88, },
+ { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 85, },
+ { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 83, },
+ { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 81, },
+ { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 78, },
+ { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 76, },
+ { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 74, },
+ { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 72, },
+ { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 70, },
+ { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 68, },
+ { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 66, },
+ { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 62, },
+ { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 60, },
+ { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 59, },
+ { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 57, },
+ { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 72, },
+ { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 70, },
+ { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 68, },
+ { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 66, },
+ { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 62, },
+ { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 60, },
+ { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 59, },
+ { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 57, },
+ { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 72, },
+ { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 70, },
+ { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 68, },
+ { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 66, },
+ { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 62, },
+ { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 60, },
+ { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 59, },
+ { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 57, },
+ { .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 71, },
+ { .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 69, },
+ { .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 67, },
+ { .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 65, },
+ { .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 63, },
+ { .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 62, },
+ { .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 60, },
+ { .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 58, },
+ { .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 57, },
+ { .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 70, },
+ { .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 68, },
+ { .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 66, },
+ { .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 65, },
+ { .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 63, },
+ { .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 61, },
+ { .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 59, },
+ { .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 58, },
+ { .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 71, },
+ { .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 69, },
+ { .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 67, },
+ { .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 65, },
+ { .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 63, },
+ { .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 61, },
+ { .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 60, },
+ { .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 58, },
+ { .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 56, },
+ { .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 70, },
+ { .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 68, },
+ { .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 66, },
+ { .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 62, },
+ { .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 60, },
+ { .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 59, },
+ { .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 72, },
+ { .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 70, },
+ { .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 68, },
+ { .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 66, },
+ { .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 62, },
+ { .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 60, },
+ { .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 59, },
+ { .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 72, },
+ { .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 70, },
+ { .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 68, },
+ { .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 66, },
+ { .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 63, },
+ { .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 61, },
+ { .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 59, },
+ { .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 57, },
+ { .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 72, },
+ { .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 70, },
+ { .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 68, },
+ { .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 66, },
+ { .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 62, },
+ { .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 60, },
+ { .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 59, },
+ { .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 72, },
+ { .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 70, },
+ { .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 68, },
+ { .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 66, },
+ { .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 62, },
+ { .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 61, },
+ { .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 59, },
+ { .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 73, },
+ { .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 71, },
+ { .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 69, },
+ { .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 67, },
+ { .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 65, },
+ { .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 63, },
+ { .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 61, },
+ { .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 59, },
+ { .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 72, },
+ { .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 70, },
+ { .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 68, },
+ { .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 66, },
+ { .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 65, },
+ { .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 63, },
+ { .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 61, },
+ { .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 59, },
+ { .gm = 7, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 73, },
+ { .gm = 7, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 71, },
+};
+
+static struct lpphy_tx_gain_table_entry lpphy_rev1_2ghz_tx_gain_table[] = {
+ { .gm = 4, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 85, },
+ { .gm = 4, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 81, },
+ { .gm = 4, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 78, },
+ { .gm = 4, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 76, },
+ { .gm = 4, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 74, },
+ { .gm = 4, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 72, },
+ { .gm = 4, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 70, },
+ { .gm = 4, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 68, },
+ { .gm = 4, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 66, },
+ { .gm = 4, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 64, },
+ { .gm = 4, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 62, },
+ { .gm = 4, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 60, },
+ { .gm = 4, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 59, },
+ { .gm = 4, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 72, },
+ { .gm = 4, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 70, },
+ { .gm = 4, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 68, },
+ { .gm = 4, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 66, },
+ { .gm = 4, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 64, },
+ { .gm = 4, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 62, },
+ { .gm = 4, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 60, },
+ { .gm = 4, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 59, },
+ { .gm = 4, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 72, },
+ { .gm = 4, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 70, },
+ { .gm = 4, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 68, },
+ { .gm = 4, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 66, },
+ { .gm = 4, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 64, },
+ { .gm = 4, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 63, },
+ { .gm = 4, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 61, },
+ { .gm = 4, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 59, },
+ { .gm = 4, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 57, },
+ { .gm = 4, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 72, },
+ { .gm = 4, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 70, },
+ { .gm = 4, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 68, },
+ { .gm = 4, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 66, },
+ { .gm = 4, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 64, },
+ { .gm = 4, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 62, },
+ { .gm = 4, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 60, },
+ { .gm = 4, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 59, },
+ { .gm = 4, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 72, },
+ { .gm = 4, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 70, },
+ { .gm = 4, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 68, },
+ { .gm = 4, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 66, },
+ { .gm = 4, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 64, },
+ { .gm = 4, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 62, },
+ { .gm = 4, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 61, },
+ { .gm = 4, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 59, },
+ { .gm = 4, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 73, },
+ { .gm = 4, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 71, },
+ { .gm = 4, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 69, },
+ { .gm = 4, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 67, },
+ { .gm = 4, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 65, },
+ { .gm = 4, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 63, },
+ { .gm = 4, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 61, },
+ { .gm = 4, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 59, },
+ { .gm = 4, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 72, },
+ { .gm = 4, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 70, },
+ { .gm = 4, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 68, },
+ { .gm = 4, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 66, },
+ { .gm = 4, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 65, },
+ { .gm = 4, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 63, },
+ { .gm = 4, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 61, },
+ { .gm = 4, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 59, },
+ { .gm = 4, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 73, },
+ { .gm = 4, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 71, },
+ { .gm = 4, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 69, },
+ { .gm = 4, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 67, },
+ { .gm = 4, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 65, },
+ { .gm = 4, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 63, },
+ { .gm = 4, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 61, },
+ { .gm = 4, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 60, },
+ { .gm = 4, .pga = 10, .pad = 6, .dac = 0, .bb_mult = 72, },
+ { .gm = 4, .pga = 10, .pad = 6, .dac = 0, .bb_mult = 70, },
+ { .gm = 4, .pga = 10, .pad = 6, .dac = 0, .bb_mult = 68, },
+ { .gm = 4, .pga = 10, .pad = 6, .dac = 0, .bb_mult = 66, },
+ { .gm = 4, .pga = 10, .pad = 6, .dac = 0, .bb_mult = 64, },
+ { .gm = 4, .pga = 10, .pad = 6, .dac = 0, .bb_mult = 62, },
+ { .gm = 4, .pga = 10, .pad = 6, .dac = 0, .bb_mult = 60, },
+ { .gm = 4, .pga = 10, .pad = 6, .dac = 0, .bb_mult = 59, },
+ { .gm = 4, .pga = 10, .pad = 5, .dac = 0, .bb_mult = 72, },
+ { .gm = 4, .pga = 10, .pad = 5, .dac = 0, .bb_mult = 70, },
+ { .gm = 4, .pga = 10, .pad = 5, .dac = 0, .bb_mult = 68, },
+ { .gm = 4, .pga = 10, .pad = 5, .dac = 0, .bb_mult = 66, },
+ { .gm = 4, .pga = 10, .pad = 5, .dac = 0, .bb_mult = 64, },
+ { .gm = 4, .pga = 10, .pad = 5, .dac = 0, .bb_mult = 62, },
+ { .gm = 4, .pga = 10, .pad = 5, .dac = 0, .bb_mult = 60, },
+ { .gm = 4, .pga = 10, .pad = 5, .dac = 0, .bb_mult = 59, },
+ { .gm = 4, .pga = 9, .pad = 5, .dac = 0, .bb_mult = 70, },
+ { .gm = 4, .pga = 9, .pad = 5, .dac = 0, .bb_mult = 68, },
+ { .gm = 4, .pga = 9, .pad = 5, .dac = 0, .bb_mult = 66, },
+ { .gm = 4, .pga = 9, .pad = 5, .dac = 0, .bb_mult = 64, },
+ { .gm = 4, .pga = 9, .pad = 5, .dac = 0, .bb_mult = 63, },
+ { .gm = 4, .pga = 9, .pad = 5, .dac = 0, .bb_mult = 61, },
+ { .gm = 4, .pga = 9, .pad = 5, .dac = 0, .bb_mult = 59, },
+ { .gm = 4, .pga = 9, .pad = 4, .dac = 0, .bb_mult = 71, },
+ { .gm = 4, .pga = 9, .pad = 4, .dac = 0, .bb_mult = 69, },
+ { .gm = 4, .pga = 9, .pad = 4, .dac = 0, .bb_mult = 67, },
+ { .gm = 4, .pga = 9, .pad = 4, .dac = 0, .bb_mult = 65, },
+ { .gm = 4, .pga = 9, .pad = 4, .dac = 0, .bb_mult = 63, },
+ { .gm = 4, .pga = 9, .pad = 4, .dac = 0, .bb_mult = 62, },
+ { .gm = 4, .pga = 9, .pad = 4, .dac = 0, .bb_mult = 60, },
+ { .gm = 4, .pga = 9, .pad = 4, .dac = 0, .bb_mult = 58, },
+ { .gm = 4, .pga = 8, .pad = 4, .dac = 0, .bb_mult = 70, },
+ { .gm = 4, .pga = 8, .pad = 4, .dac = 0, .bb_mult = 68, },
+ { .gm = 4, .pga = 8, .pad = 4, .dac = 0, .bb_mult = 66, },
+ { .gm = 4, .pga = 8, .pad = 4, .dac = 0, .bb_mult = 65, },
+ { .gm = 4, .pga = 8, .pad = 4, .dac = 0, .bb_mult = 63, },
+ { .gm = 4, .pga = 8, .pad = 4, .dac = 0, .bb_mult = 61, },
+ { .gm = 4, .pga = 8, .pad = 4, .dac = 0, .bb_mult = 59, },
+ { .gm = 4, .pga = 7, .pad = 4, .dac = 0, .bb_mult = 68, },
+ { .gm = 4, .pga = 7, .pad = 4, .dac = 0, .bb_mult = 66, },
+ { .gm = 4, .pga = 7, .pad = 4, .dac = 0, .bb_mult = 64, },
+ { .gm = 4, .pga = 7, .pad = 4, .dac = 0, .bb_mult = 62, },
+ { .gm = 4, .pga = 7, .pad = 4, .dac = 0, .bb_mult = 61, },
+ { .gm = 4, .pga = 7, .pad = 4, .dac = 0, .bb_mult = 59, },
+ { .gm = 4, .pga = 7, .pad = 3, .dac = 0, .bb_mult = 67, },
+ { .gm = 4, .pga = 7, .pad = 3, .dac = 0, .bb_mult = 65, },
+ { .gm = 4, .pga = 7, .pad = 3, .dac = 0, .bb_mult = 63, },
+ { .gm = 4, .pga = 7, .pad = 3, .dac = 0, .bb_mult = 62, },
+ { .gm = 4, .pga = 7, .pad = 3, .dac = 0, .bb_mult = 60, },
+ { .gm = 4, .pga = 6, .pad = 3, .dac = 0, .bb_mult = 65, },
+ { .gm = 4, .pga = 6, .pad = 3, .dac = 0, .bb_mult = 63, },
+ { .gm = 4, .pga = 6, .pad = 3, .dac = 0, .bb_mult = 61, },
+ { .gm = 4, .pga = 6, .pad = 3, .dac = 0, .bb_mult = 60, },
+ { .gm = 4, .pga = 6, .pad = 3, .dac = 0, .bb_mult = 58, },
+ { .gm = 4, .pga = 5, .pad = 3, .dac = 0, .bb_mult = 68, },
+ { .gm = 4, .pga = 5, .pad = 3, .dac = 0, .bb_mult = 66, },
+ { .gm = 4, .pga = 5, .pad = 3, .dac = 0, .bb_mult = 64, },
+ { .gm = 4, .pga = 5, .pad = 3, .dac = 0, .bb_mult = 62, },
+};
+
+static struct lpphy_tx_gain_table_entry lpphy_rev1_5ghz_tx_gain_table[] = {
+ { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 99, },
+ { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 96, },
+ { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 93, },
+ { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 90, },
+ { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 88, },
+ { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 85, },
+ { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 83, },
+ { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 81, },
+ { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 78, },
+ { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 76, },
+ { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 74, },
+ { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 72, },
+ { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 70, },
+ { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 68, },
+ { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 66, },
+ { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 62, },
+ { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 60, },
+ { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 59, },
+ { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 57, },
+ { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 55, },
+ { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 72, },
+ { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 70, },
+ { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 68, },
+ { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 66, },
+ { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 62, },
+ { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 60, },
+ { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 58, },
+ { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 56, },
+ { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 55, },
+ { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 71, },
+ { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 69, },
+ { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 67, },
+ { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 65, },
+ { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 63, },
+ { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 62, },
+ { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 60, },
+ { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 58, },
+ { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 56, },
+ { .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 72, },
+ { .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 70, },
+ { .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 68, },
+ { .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 66, },
+ { .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 62, },
+ { .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 60, },
+ { .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 59, },
+ { .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 57, },
+ { .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 73, },
+ { .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 71, },
+ { .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 69, },
+ { .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 67, },
+ { .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 65, },
+ { .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 63, },
+ { .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 61, },
+ { .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 60, },
+ { .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 58, },
+ { .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 71, },
+ { .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 69, },
+ { .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 67, },
+ { .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 65, },
+ { .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 63, },
+ { .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 61, },
+ { .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 60, },
+ { .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 58, },
+ { .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 70, },
+ { .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 68, },
+ { .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 66, },
+ { .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 62, },
+ { .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 61, },
+ { .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 59, },
+ { .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 57, },
+ { .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 56, },
+ { .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 68, },
+ { .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 66, },
+ { .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 65, },
+ { .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 63, },
+ { .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 61, },
+ { .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 59, },
+ { .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 58, },
+ { .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 70, },
+ { .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 68, },
+ { .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 66, },
+ { .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 63, },
+ { .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 61, },
+ { .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 59, },
+ { .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 57, },
+ { .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 70, },
+ { .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 68, },
+ { .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 66, },
+ { .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 62, },
+ { .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 60, },
+ { .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 59, },
+ { .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 57, },
+ { .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 70, },
+ { .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 68, },
+ { .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 66, },
+ { .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 62, },
+ { .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 61, },
+ { .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 59, },
+ { .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 57, },
+ { .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 70, },
+ { .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 68, },
+ { .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 66, },
+ { .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 62, },
+ { .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 61, },
+ { .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 59, },
+ { .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 57, },
+ { .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 70, },
+ { .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 68, },
+ { .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 66, },
+ { .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 62, },
+ { .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 61, },
+ { .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 59, },
+ { .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 57, },
+ { .gm = 7, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 69, },
+ { .gm = 7, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 67, },
+ { .gm = 7, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 65, },
+ { .gm = 7, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 63, },
+ { .gm = 7, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 62, },
+ { .gm = 7, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 60, },
+};
+
+static struct lpphy_tx_gain_table_entry lpphy_rev2_nopa_tx_gain_table[] = {
+ { .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 152, },
+ { .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 147, },
+ { .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 143, },
+ { .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 139, },
+ { .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 135, },
+ { .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 131, },
+ { .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 128, },
+ { .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 124, },
+ { .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 121, },
+ { .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 117, },
+ { .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 114, },
+ { .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 111, },
+ { .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 107, },
+ { .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 104, },
+ { .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 101, },
+ { .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 99, },
+ { .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 96, },
+ { .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 93, },
+ { .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 90, },
+ { .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 88, },
+ { .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 85, },
+ { .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 83, },
+ { .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 81, },
+ { .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 78, },
+ { .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 76, },
+ { .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 74, },
+ { .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 72, },
+ { .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 70, },
+ { .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 68, },
+ { .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 66, },
+ { .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 255, .pad = 197, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 255, .pad = 192, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 255, .pad = 186, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 255, .pad = 181, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 255, .pad = 176, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 255, .pad = 171, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 255, .pad = 166, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 255, .pad = 161, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 255, .pad = 157, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 255, .pad = 152, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 255, .pad = 148, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 255, .pad = 144, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 255, .pad = 140, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 255, .pad = 136, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 255, .pad = 132, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 255, .pad = 128, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 255, .pad = 124, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 255, .pad = 121, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 255, .pad = 117, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 255, .pad = 114, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 255, .pad = 111, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 255, .pad = 108, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 255, .pad = 105, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 255, .pad = 102, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 255, .pad = 99, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 255, .pad = 96, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 255, .pad = 93, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 255, .pad = 91, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 255, .pad = 88, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 255, .pad = 86, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 255, .pad = 83, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 255, .pad = 81, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 255, .pad = 79, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 255, .pad = 76, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 255, .pad = 74, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 255, .pad = 72, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 255, .pad = 70, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 255, .pad = 68, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 255, .pad = 66, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 255, .pad = 64, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 248, .pad = 64, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 248, .pad = 62, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 241, .pad = 62, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 241, .pad = 60, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 234, .pad = 60, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 234, .pad = 59, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 227, .pad = 59, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 227, .pad = 57, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 221, .pad = 57, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 221, .pad = 55, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 215, .pad = 55, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 215, .pad = 54, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 208, .pad = 54, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 208, .pad = 52, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 203, .pad = 52, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 203, .pad = 51, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 197, .pad = 51, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 197, .pad = 49, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 191, .pad = 49, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 191, .pad = 48, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 186, .pad = 48, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 186, .pad = 47, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 181, .pad = 47, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 181, .pad = 45, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 175, .pad = 45, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 175, .pad = 44, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 170, .pad = 44, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 170, .pad = 43, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 166, .pad = 43, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 166, .pad = 42, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 161, .pad = 42, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 161, .pad = 40, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 156, .pad = 40, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 156, .pad = 39, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 152, .pad = 39, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 152, .pad = 38, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 148, .pad = 38, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 148, .pad = 37, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 143, .pad = 37, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 143, .pad = 36, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 139, .pad = 36, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 139, .pad = 35, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 135, .pad = 35, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 135, .pad = 34, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 132, .pad = 34, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 132, .pad = 33, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 128, .pad = 33, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 128, .pad = 32, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 124, .pad = 32, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 124, .pad = 31, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 121, .pad = 31, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 121, .pad = 30, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 117, .pad = 30, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 117, .pad = 29, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 114, .pad = 29, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 114, .pad = 29, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 111, .pad = 29, .dac = 0, .bb_mult = 64, },
+};
+
+static struct lpphy_tx_gain_table_entry lpphy_rev2_2ghz_tx_gain_table[] = {
+ { .gm = 7, .pga = 99, .pad = 255, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 96, .pad = 255, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 93, .pad = 255, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 90, .pad = 255, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 88, .pad = 255, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 85, .pad = 255, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 83, .pad = 255, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 81, .pad = 255, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 78, .pad = 255, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 76, .pad = 255, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 74, .pad = 255, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 72, .pad = 255, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 70, .pad = 255, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 68, .pad = 255, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 66, .pad = 255, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 64, .pad = 255, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 64, .pad = 255, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 62, .pad = 255, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 62, .pad = 248, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 60, .pad = 248, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 60, .pad = 241, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 59, .pad = 241, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 59, .pad = 234, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 57, .pad = 234, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 57, .pad = 227, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 55, .pad = 227, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 55, .pad = 221, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 54, .pad = 221, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 54, .pad = 215, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 52, .pad = 215, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 52, .pad = 208, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 51, .pad = 208, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 51, .pad = 203, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 49, .pad = 203, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 49, .pad = 197, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 48, .pad = 197, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 48, .pad = 191, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 47, .pad = 191, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 47, .pad = 186, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 45, .pad = 186, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 45, .pad = 181, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 44, .pad = 181, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 44, .pad = 175, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 43, .pad = 175, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 43, .pad = 170, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 42, .pad = 170, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 42, .pad = 166, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 40, .pad = 166, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 40, .pad = 161, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 39, .pad = 161, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 39, .pad = 156, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 38, .pad = 156, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 38, .pad = 152, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 37, .pad = 152, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 37, .pad = 148, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 36, .pad = 148, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 36, .pad = 143, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 35, .pad = 143, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 35, .pad = 139, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 34, .pad = 139, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 34, .pad = 135, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 33, .pad = 135, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 33, .pad = 132, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 32, .pad = 132, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 32, .pad = 128, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 31, .pad = 128, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 31, .pad = 124, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 30, .pad = 124, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 30, .pad = 121, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 29, .pad = 121, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 29, .pad = 117, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 29, .pad = 117, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 29, .pad = 114, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 28, .pad = 114, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 28, .pad = 111, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 27, .pad = 111, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 27, .pad = 108, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 26, .pad = 108, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 26, .pad = 104, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 25, .pad = 104, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 25, .pad = 102, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 25, .pad = 102, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 25, .pad = 99, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 24, .pad = 99, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 24, .pad = 96, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 23, .pad = 96, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 23, .pad = 93, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 23, .pad = 93, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 23, .pad = 90, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 22, .pad = 90, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 22, .pad = 88, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 21, .pad = 88, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 21, .pad = 85, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 21, .pad = 85, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 21, .pad = 83, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 20, .pad = 83, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 20, .pad = 81, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 20, .pad = 81, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 20, .pad = 78, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 19, .pad = 78, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 19, .pad = 76, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 19, .pad = 76, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 19, .pad = 74, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 18, .pad = 74, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 18, .pad = 72, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 18, .pad = 72, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 18, .pad = 70, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 17, .pad = 70, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 17, .pad = 68, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 17, .pad = 68, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 17, .pad = 66, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 16, .pad = 66, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 16, .pad = 64, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 16, .pad = 64, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 16, .pad = 62, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 15, .pad = 62, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 15, .pad = 60, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 15, .pad = 60, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 15, .pad = 59, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 14, .pad = 59, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 14, .pad = 57, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 14, .pad = 57, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 14, .pad = 55, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 14, .pad = 55, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 14, .pad = 54, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 13, .pad = 54, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 13, .pad = 52, .dac = 0, .bb_mult = 64, },
+ { .gm = 7, .pga = 13, .pad = 52, .dac = 0, .bb_mult = 64, },
+};
+
+static struct lpphy_tx_gain_table_entry lpphy_rev2_5ghz_tx_gain_table[] = {
+ { .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 152, },
+ { .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 147, },
+ { .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 143, },
+ { .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 139, },
+ { .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 135, },
+ { .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 131, },
+ { .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 128, },
+ { .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 124, },
+ { .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 121, },
+ { .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 117, },
+ { .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 114, },
+ { .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 111, },
+ { .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 107, },
+ { .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 104, },
+ { .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 101, },
+ { .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 99, },
+ { .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 96, },
+ { .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 93, },
+ { .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 90, },
+ { .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 88, },
+ { .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 85, },
+ { .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 83, },
+ { .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 81, },
+ { .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 78, },
+ { .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 76, },
+ { .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 74, },
+ { .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 72, },
+ { .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 70, },
+ { .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 68, },
+ { .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 66, },
+ { .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 248, .pad = 255, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 241, .pad = 255, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 234, .pad = 255, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 227, .pad = 255, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 221, .pad = 255, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 215, .pad = 255, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 208, .pad = 255, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 203, .pad = 255, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 197, .pad = 255, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 191, .pad = 255, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 186, .pad = 255, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 181, .pad = 255, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 175, .pad = 255, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 170, .pad = 255, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 166, .pad = 255, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 161, .pad = 255, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 156, .pad = 255, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 152, .pad = 255, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 148, .pad = 255, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 143, .pad = 255, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 139, .pad = 255, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 135, .pad = 255, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 132, .pad = 255, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 128, .pad = 255, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 124, .pad = 255, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 121, .pad = 255, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 117, .pad = 255, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 114, .pad = 255, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 111, .pad = 255, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 108, .pad = 255, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 104, .pad = 255, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 102, .pad = 255, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 99, .pad = 255, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 96, .pad = 255, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 93, .pad = 255, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 90, .pad = 255, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 88, .pad = 255, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 85, .pad = 255, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 83, .pad = 255, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 81, .pad = 255, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 78, .pad = 255, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 76, .pad = 255, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 74, .pad = 255, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 72, .pad = 255, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 70, .pad = 255, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 68, .pad = 255, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 66, .pad = 255, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 64, .pad = 255, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 64, .pad = 255, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 62, .pad = 255, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 62, .pad = 248, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 60, .pad = 248, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 60, .pad = 241, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 59, .pad = 241, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 59, .pad = 234, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 57, .pad = 234, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 57, .pad = 227, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 55, .pad = 227, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 55, .pad = 221, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 54, .pad = 221, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 54, .pad = 215, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 52, .pad = 215, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 52, .pad = 208, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 51, .pad = 208, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 51, .pad = 203, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 49, .pad = 203, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 49, .pad = 197, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 48, .pad = 197, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 48, .pad = 191, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 47, .pad = 191, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 47, .pad = 186, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 45, .pad = 186, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 45, .pad = 181, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 44, .pad = 181, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 44, .pad = 175, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 43, .pad = 175, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 43, .pad = 170, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 42, .pad = 170, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 42, .pad = 166, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 40, .pad = 166, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 40, .pad = 161, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 39, .pad = 161, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 39, .pad = 156, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 38, .pad = 156, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 38, .pad = 152, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 37, .pad = 152, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 37, .pad = 148, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 36, .pad = 148, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 36, .pad = 143, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 35, .pad = 143, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 35, .pad = 139, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 34, .pad = 139, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 34, .pad = 135, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 33, .pad = 135, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 33, .pad = 132, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 32, .pad = 132, .dac = 0, .bb_mult = 64, },
+ { .gm = 255, .pga = 32, .pad = 128, .dac = 0, .bb_mult = 64, },
+};
+
+void lpphy_rev0_1_table_init(struct b43_wldev *dev)
+{
+ B43_WARN_ON(dev->phy.rev >= 2);
+
+ b43_lptab_write_bulk(dev, B43_LPTAB8(2, 0),
+ ARRAY_SIZE(lpphy_min_sig_sq_table), lpphy_min_sig_sq_table);
+ b43_lptab_write_bulk(dev, B43_LPTAB16(1, 0),
+ ARRAY_SIZE(lpphy_rev01_noise_scale_table), lpphy_rev01_noise_scale_table);
+ b43_lptab_write_bulk(dev, B43_LPTAB16(14, 0),
+ ARRAY_SIZE(lpphy_crs_gain_nft_table), lpphy_crs_gain_nft_table);
+ b43_lptab_write_bulk(dev, B43_LPTAB16(8, 0),
+ ARRAY_SIZE(lpphy_rev01_filter_control_table), lpphy_rev01_filter_control_table);
+ b43_lptab_write_bulk(dev, B43_LPTAB32(9, 0),
+ ARRAY_SIZE(lpphy_rev01_ps_control_table), lpphy_rev01_ps_control_table);
+ b43_lptab_write_bulk(dev, B43_LPTAB8(6, 0),
+ ARRAY_SIZE(lpphy_pll_fraction_table), lpphy_pll_fraction_table);
+ b43_lptab_write_bulk(dev, B43_LPTAB16(0, 0),
+ ARRAY_SIZE(lpphy_iq_local_table), lpphy_iq_local_table);
+ b43_lptab_write_bulk(dev, B43_LPTAB16(13, 0),
+ ARRAY_SIZE(lpphy_ofdm_cck_gain_table), lpphy_ofdm_cck_gain_table);
+ b43_lptab_write_bulk(dev, B43_LPTAB16(12, 0),
+ ARRAY_SIZE(lpphy_ofdm_cck_gain_table), lpphy_ofdm_cck_gain_table);
+ b43_lptab_write_bulk(dev, B43_LPTAB16(15, 0),
+ ARRAY_SIZE(lpphy_gain_delta_table), lpphy_gain_delta_table);
+ b43_lptab_write_bulk(dev, B43_LPTAB32(10, 0),
+ ARRAY_SIZE(lpphy_tx_power_control_table), lpphy_tx_power_control_table);
+}
+
+void lpphy_rev2plus_table_init(struct b43_wldev *dev)
+{
+ struct ssb_bus *bus = dev->dev->bus;
+ int i;
+
+ B43_WARN_ON(dev->phy.rev < 2);
+
+ /*
+ * FIXME This code follows the specs, but it looks wrong:
+ * In each pass, it writes 4 bytes to an offset in table ID 7,
+ * then increments the offset by 1 for the next pass. This results
+ * in the first 3 bytes of each pass except the first one getting
+ * written to a location that has already been zeroed in the previous
+ * pass.
+ * This is what the vendor driver does, but it still looks suspicious.
+ *
+ * This should probably suffice:
+ *
+ * for (i = 0; i < 704; i+=4)
+ * b43_lptab_write(dev, B43_LPTAB32(7, i), 0)
+ *
+ * This should be tested once the code is functional.
+ */
+ for (i = 0; i < 704; i++)
+ b43_lptab_write(dev, B43_LPTAB32(7, i), 0);
+
+ b43_lptab_write_bulk(dev, B43_LPTAB8(2, 0),
+ ARRAY_SIZE(lpphy_min_sig_sq_table), lpphy_min_sig_sq_table);
+ b43_lptab_write_bulk(dev, B43_LPTAB16(1, 0),
+ ARRAY_SIZE(lpphy_rev2plus_noise_scale_table), lpphy_rev2plus_noise_scale_table);
+ b43_lptab_write_bulk(dev, B43_LPTAB32(11, 0),
+ ARRAY_SIZE(lpphy_rev2plus_filter_control_table), lpphy_rev2plus_filter_control_table);
+ b43_lptab_write_bulk(dev, B43_LPTAB32(12, 0),
+ ARRAY_SIZE(lpphy_rev2plus_ps_control_table), lpphy_rev2plus_ps_control_table);
+ b43_lptab_write_bulk(dev, B43_LPTAB32(13, 0),
+ ARRAY_SIZE(lpphy_gain_idx_table), lpphy_gain_idx_table);
+ b43_lptab_write_bulk(dev, B43_LPTAB16(14, 0),
+ ARRAY_SIZE(lpphy_aux_gain_idx_table), lpphy_aux_gain_idx_table);
+ b43_lptab_write_bulk(dev, B43_LPTAB16(15, 0),
+ ARRAY_SIZE(lpphy_sw_control_table), lpphy_sw_control_table);
+ b43_lptab_write_bulk(dev, B43_LPTAB8(16, 0),
+ ARRAY_SIZE(lpphy_hf_table), lpphy_hf_table);
+ b43_lptab_write_bulk(dev, B43_LPTAB32(17, 0),
+ ARRAY_SIZE(lpphy_gain_value_table), lpphy_gain_value_table);
+ b43_lptab_write_bulk(dev, B43_LPTAB16(18, 0),
+ ARRAY_SIZE(lpphy_gain_table), lpphy_gain_table);
+ b43_lptab_write_bulk(dev, B43_LPTAB8(6, 0),
+ ARRAY_SIZE(lpphy_pll_fraction_table), lpphy_pll_fraction_table);
+ b43_lptab_write_bulk(dev, B43_LPTAB16(0, 0),
+ ARRAY_SIZE(lpphy_iq_local_table), lpphy_iq_local_table);
+ b43_lptab_write_bulk(dev, B43_LPTAB32(9, 0),
+ ARRAY_SIZE(lpphy_papd_eps_table), lpphy_papd_eps_table);
+ b43_lptab_write_bulk(dev, B43_LPTAB32(10, 0),
+ ARRAY_SIZE(lpphy_papd_mult_table), lpphy_papd_mult_table);
+
+ if ((bus->chip_id == 0x4325) && (bus->chip_rev == 0)) {
+ b43_lptab_write_bulk(dev, B43_LPTAB32(13, 0),
+ ARRAY_SIZE(lpphy_a0_gain_idx_table), lpphy_a0_gain_idx_table);
+ b43_lptab_write_bulk(dev, B43_LPTAB16(14, 0),
+ ARRAY_SIZE(lpphy_a0_aux_gain_idx_table), lpphy_a0_aux_gain_idx_table);
+ b43_lptab_write_bulk(dev, B43_LPTAB32(17, 0),
+ ARRAY_SIZE(lpphy_a0_gain_value_table), lpphy_a0_gain_value_table);
+ b43_lptab_write_bulk(dev, B43_LPTAB16(18, 0),
+ ARRAY_SIZE(lpphy_a0_gain_table), lpphy_a0_gain_table);
+ }
+}
+
+static void lpphy_rev0_1_write_gain_table(struct b43_wldev *dev, int offset,
+ struct lpphy_tx_gain_table_entry data)
+{
+ u32 tmp;
+
+ B43_WARN_ON(dev->phy.rev >= 2);
+
+ tmp = data.pad << 11;
+ tmp |= data.pga << 7;
+ tmp |= data.gm << 4;
+ tmp |= data.dac;
+ b43_lptab_write(dev, B43_LPTAB32(10, 0xC0 + offset), tmp);
+ tmp = data.bb_mult << 20;
+ b43_lptab_write(dev, B43_LPTAB32(10, 0x140 + offset), tmp);
+}
+
+static void lpphy_rev2plus_write_gain_table(struct b43_wldev *dev, int offset,
+ struct lpphy_tx_gain_table_entry data)
+{
+ u32 tmp;
+
+ B43_WARN_ON(dev->phy.rev < 2);
+
+ tmp = data.pad << 16;
+ tmp |= data.pga << 8;
+ tmp |= data.gm;
+ tmp |= 0x7f000000;
+ b43_lptab_write(dev, B43_LPTAB32(7, 0xC0 + offset), tmp);
+ tmp = data.bb_mult << 20;
+ tmp |= data.dac << 28;
+ b43_lptab_write(dev, B43_LPTAB32(7, 0x140 + offset), tmp);
+}
+
+void lpphy_write_gain_table(struct b43_wldev *dev, int offset,
+ struct lpphy_tx_gain_table_entry data)
+{
+ if (dev->phy.rev >= 2)
+ lpphy_rev2plus_write_gain_table(dev, offset, data);
+ else
+ lpphy_rev0_1_write_gain_table(dev, offset, data);
+}
+
+void lpphy_write_gain_table_bulk(struct b43_wldev *dev, int offset, int count,
+ struct lpphy_tx_gain_table_entry *table)
+{
+ int i;
+
+ for (i = offset; i < count; i++)
+ lpphy_write_gain_table(dev, i, table[i]);
+}
+
+void lpphy_init_tx_gain_table(struct b43_wldev *dev)
+{
+ struct ssb_bus *bus = dev->dev->bus;
+
+ switch (dev->phy.rev) {
+ case 0:
+ if ((bus->sprom.boardflags_hi & B43_BFH_NOPA) ||
+ (bus->sprom.boardflags_lo & B43_BFL_HGPA))
+ lpphy_write_gain_table_bulk(dev, 0, 128,
+ lpphy_rev0_nopa_tx_gain_table);
+ else if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
+ lpphy_write_gain_table_bulk(dev, 0, 128,
+ lpphy_rev0_2ghz_tx_gain_table);
+ else
+ lpphy_write_gain_table_bulk(dev, 0, 128,
+ lpphy_rev0_5ghz_tx_gain_table);
+ break;
+ case 1:
+ if ((bus->sprom.boardflags_hi & B43_BFH_NOPA) ||
+ (bus->sprom.boardflags_lo & B43_BFL_HGPA))
+ lpphy_write_gain_table_bulk(dev, 0, 128,
+ lpphy_rev1_nopa_tx_gain_table);
+ else if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
+ lpphy_write_gain_table_bulk(dev, 0, 128,
+ lpphy_rev1_2ghz_tx_gain_table);
+ else
+ lpphy_write_gain_table_bulk(dev, 0, 128,
+ lpphy_rev1_5ghz_tx_gain_table);
+ break;
+ default:
+ if (bus->sprom.boardflags_hi & B43_BFH_NOPA)
+ lpphy_write_gain_table_bulk(dev, 0, 128,
+ lpphy_rev2_nopa_tx_gain_table);
+ else if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
+ lpphy_write_gain_table_bulk(dev, 0, 128,
+ lpphy_rev2_2ghz_tx_gain_table);
+ else
+ lpphy_write_gain_table_bulk(dev, 0, 128,
+ lpphy_rev2_5ghz_tx_gain_table);
+ }
+}
diff --git a/drivers/net/wireless/b43/tables_lpphy.h b/drivers/net/wireless/b43/tables_lpphy.h
index 0b8d02895a5..84f1d265f65 100644
--- a/drivers/net/wireless/b43/tables_lpphy.h
+++ b/drivers/net/wireless/b43/tables_lpphy.h
@@ -26,6 +26,19 @@ void b43_lptab_write_bulk(struct b43_wldev *dev, u32 offset,
unsigned int nr_elements, const void *data);
void b2062_upload_init_table(struct b43_wldev *dev);
+void b2063_upload_init_table(struct b43_wldev *dev);
+struct lpphy_tx_gain_table_entry {
+ u8 gm, pga, pad, dac, bb_mult;
+};
+
+void lpphy_write_gain_table(struct b43_wldev *dev, int offset,
+ struct lpphy_tx_gain_table_entry data);
+void lpphy_write_gain_table_bulk(struct b43_wldev *dev, int offset, int count,
+ struct lpphy_tx_gain_table_entry *table);
+
+void lpphy_rev0_1_table_init(struct b43_wldev *dev);
+void lpphy_rev2plus_table_init(struct b43_wldev *dev);
+void lpphy_init_tx_gain_table(struct b43_wldev *dev);
#endif /* B43_TABLES_LPPHY_H_ */
diff --git a/drivers/net/wireless/b43/xmit.c b/drivers/net/wireless/b43/xmit.c
index 55f36a7254d..5280ebc8c6e 100644
--- a/drivers/net/wireless/b43/xmit.c
+++ b/drivers/net/wireless/b43/xmit.c
@@ -237,7 +237,7 @@ int b43_generate_txhdr(struct b43_wldev *dev,
int wlhdr_len;
size_t iv_len;
- B43_WARN_ON(key_idx >= dev->max_nr_keys);
+ B43_WARN_ON(key_idx >= ARRAY_SIZE(dev->key));
key = &(dev->key[key_idx]);
if (unlikely(!key->keyconf)) {
@@ -578,7 +578,7 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr)
* key index, but the ucode passed it slightly different.
*/
keyidx = b43_kidx_to_raw(dev, keyidx);
- B43_WARN_ON(keyidx >= dev->max_nr_keys);
+ B43_WARN_ON(keyidx >= ARRAY_SIZE(dev->key));
if (dev->key[keyidx].algorithm != B43_SEC_ALGO_NONE) {
wlhdr_len = ieee80211_hdrlen(fctl);
@@ -670,7 +670,8 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr)
goto drop;
}
- ieee80211_rx_irqsafe(dev->wl->hw, skb, &status);
+ memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status));
+ ieee80211_rx_irqsafe(dev->wl->hw, skb);
return;
drop:
diff --git a/drivers/net/wireless/b43legacy/dma.c b/drivers/net/wireless/b43legacy/dma.c
index 2f90fb9f536..86640341581 100644
--- a/drivers/net/wireless/b43legacy/dma.c
+++ b/drivers/net/wireless/b43legacy/dma.c
@@ -1366,15 +1366,25 @@ int b43legacy_dma_tx(struct b43legacy_wldev *dev,
ring = priority_to_txring(dev, skb_get_queue_mapping(skb));
spin_lock_irqsave(&ring->lock, flags);
B43legacy_WARN_ON(!ring->tx);
- if (unlikely(free_slots(ring) < SLOTS_PER_PACKET)) {
- b43legacywarn(dev->wl, "DMA queue overflow\n");
+
+ if (unlikely(ring->stopped)) {
+ /* We get here only because of a bug in mac80211.
+ * Because of a race, one packet may be queued after
+ * the queue is stopped, thus we got called when we shouldn't.
+ * For now, just refuse the transmit. */
+ if (b43legacy_debug(dev, B43legacy_DBG_DMAVERBOSE))
+ b43legacyerr(dev->wl, "Packet after queue stopped\n");
+ err = -ENOSPC;
+ goto out_unlock;
+ }
+
+ if (unlikely(WARN_ON(free_slots(ring) < SLOTS_PER_PACKET))) {
+ /* If we get here, we have a real error with the queue
+ * full, but queues not stopped. */
+ b43legacyerr(dev->wl, "DMA queue overflow\n");
err = -ENOSPC;
goto out_unlock;
}
- /* Check if the queue was stopped in mac80211,
- * but we got called nevertheless.
- * That would be a mac80211 bug. */
- B43legacy_BUG_ON(ring->stopped);
err = dma_tx_fragment(ring, skb);
if (unlikely(err == -ENOKEY)) {
diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c
index c4973c1942b..b1435594921 100644
--- a/drivers/net/wireless/b43legacy/main.c
+++ b/drivers/net/wireless/b43legacy/main.c
@@ -1252,7 +1252,7 @@ static void b43legacy_update_templates(struct b43legacy_wl *wl)
wl->current_beacon = beacon;
wl->beacon0_uploaded = 0;
wl->beacon1_uploaded = 0;
- queue_work(wl->hw->workqueue, &wl->beacon_update_trigger);
+ ieee80211_queue_work(wl->hw, &wl->beacon_update_trigger);
}
static void b43legacy_set_beacon_int(struct b43legacy_wldev *dev,
@@ -2300,7 +2300,7 @@ out_requeue:
delay = msecs_to_jiffies(50);
else
delay = round_jiffies_relative(HZ * 15);
- queue_delayed_work(wl->hw->workqueue, &dev->periodic_work, delay);
+ ieee80211_queue_delayed_work(wl->hw, &dev->periodic_work, delay);
out:
mutex_unlock(&wl->mutex);
}
@@ -2311,7 +2311,7 @@ static void b43legacy_periodic_tasks_setup(struct b43legacy_wldev *dev)
dev->periodic_state = 0;
INIT_DELAYED_WORK(work, b43legacy_periodic_work_handler);
- queue_delayed_work(dev->wl->hw->workqueue, work, 0);
+ ieee80211_queue_delayed_work(dev->wl->hw, work, 0);
}
/* Validate access to the chip (SHM) */
@@ -3885,7 +3885,7 @@ void b43legacy_controller_restart(struct b43legacy_wldev *dev,
if (b43legacy_status(dev) < B43legacy_STAT_INITIALIZED)
return;
b43legacyinfo(dev->wl, "Controller RESET (%s) ...\n", reason);
- queue_work(dev->wl->hw->workqueue, &dev->restart_work);
+ ieee80211_queue_work(dev->wl->hw, &dev->restart_work);
}
#ifdef CONFIG_PM
diff --git a/drivers/net/wireless/b43legacy/xmit.c b/drivers/net/wireless/b43legacy/xmit.c
index b8e39dd06e9..f79cee82601 100644
--- a/drivers/net/wireless/b43legacy/xmit.c
+++ b/drivers/net/wireless/b43legacy/xmit.c
@@ -591,7 +591,8 @@ void b43legacy_rx(struct b43legacy_wldev *dev,
}
dev->stats.last_rx = jiffies;
- ieee80211_rx_irqsafe(dev->wl->hw, skb, &status);
+ memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status));
+ ieee80211_rx_irqsafe(dev->wl->hw, skb);
return;
drop:
diff --git a/drivers/net/wireless/hostap/hostap_80211_tx.c b/drivers/net/wireless/hostap/hostap_80211_tx.c
index d313b005114..1fe1bbabb90 100644
--- a/drivers/net/wireless/hostap/hostap_80211_tx.c
+++ b/drivers/net/wireless/hostap/hostap_80211_tx.c
@@ -75,7 +75,7 @@ int hostap_data_start_xmit(struct sk_buff *skb, struct net_device *dev)
printk(KERN_DEBUG "%s: hostap_data_start_xmit: short skb "
"(len=%d)\n", dev->name, skb->len);
kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
}
if (local->ddev != dev) {
@@ -89,14 +89,14 @@ int hostap_data_start_xmit(struct sk_buff *skb, struct net_device *dev)
printk(KERN_DEBUG "%s: prism2_tx: trying to use "
"AP device with Ethernet net dev\n", dev->name);
kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
}
} else {
if (local->iw_mode == IW_MODE_REPEAT) {
printk(KERN_DEBUG "%s: prism2_tx: trying to use "
"non-WDS link in Repeater mode\n", dev->name);
kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
} else if (local->iw_mode == IW_MODE_INFRA &&
(local->wds_type & HOSTAP_WDS_AP_CLIENT) &&
memcmp(skb->data + ETH_ALEN, dev->dev_addr,
@@ -210,13 +210,13 @@ int hostap_data_start_xmit(struct sk_buff *skb, struct net_device *dev)
skb = skb_unshare(skb, GFP_ATOMIC);
if (skb == NULL) {
iface->stats.tx_dropped++;
- return 0;
+ return NETDEV_TX_OK;
}
if (pskb_expand_head(skb, need_headroom, need_tailroom,
GFP_ATOMIC)) {
kfree_skb(skb);
iface->stats.tx_dropped++;
- return 0;
+ return NETDEV_TX_OK;
}
} else if (skb_headroom(skb) < need_headroom) {
struct sk_buff *tmp = skb;
@@ -224,13 +224,13 @@ int hostap_data_start_xmit(struct sk_buff *skb, struct net_device *dev)
kfree_skb(tmp);
if (skb == NULL) {
iface->stats.tx_dropped++;
- return 0;
+ return NETDEV_TX_OK;
}
} else {
skb = skb_unshare(skb, GFP_ATOMIC);
if (skb == NULL) {
iface->stats.tx_dropped++;
- return 0;
+ return NETDEV_TX_OK;
}
}
@@ -256,7 +256,7 @@ int hostap_data_start_xmit(struct sk_buff *skb, struct net_device *dev)
/* Send IEEE 802.11 encapsulated frame using the master radio device */
skb->dev = local->dev;
dev_queue_xmit(skb);
- return 0;
+ return NETDEV_TX_OK;
}
@@ -276,7 +276,7 @@ int hostap_mgmt_start_xmit(struct sk_buff *skb, struct net_device *dev)
printk(KERN_DEBUG "%s: hostap_mgmt_start_xmit: short skb "
"(len=%d)\n", dev->name, skb->len);
kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
}
iface->stats.tx_packets++;
@@ -301,7 +301,7 @@ int hostap_mgmt_start_xmit(struct sk_buff *skb, struct net_device *dev)
/* Send IEEE 802.11 encapsulated frame using the master radio device */
skb->dev = local->dev;
dev_queue_xmit(skb);
- return 0;
+ return NETDEV_TX_OK;
}
@@ -396,7 +396,7 @@ int hostap_master_start_xmit(struct sk_buff *skb, struct net_device *dev)
printk(KERN_DEBUG "%s: invalid skb->cb magic (0x%08x, "
"expected 0x%08x)\n",
dev->name, meta->magic, HOSTAP_SKB_TX_DATA_MAGIC);
- ret = 0;
+ ret = NETDEV_TX_OK;
iface->stats.tx_dropped++;
goto fail;
}
@@ -414,7 +414,7 @@ int hostap_master_start_xmit(struct sk_buff *skb, struct net_device *dev)
if (skb->len < 24) {
printk(KERN_DEBUG "%s: hostap_master_start_xmit: short skb "
"(len=%d)\n", dev->name, skb->len);
- ret = 0;
+ ret = NETDEV_TX_OK;
iface->stats.tx_dropped++;
goto fail;
}
@@ -441,13 +441,13 @@ int hostap_master_start_xmit(struct sk_buff *skb, struct net_device *dev)
dev->name, meta->ethertype);
hostap_dump_tx_80211(dev->name, skb);
- ret = 0; /* drop packet */
+ ret = NETDEV_TX_OK; /* drop packet */
iface->stats.tx_dropped++;
goto fail;
}
break;
case AP_TX_DROP:
- ret = 0; /* drop packet */
+ ret = NETDEV_TX_OK; /* drop packet */
iface->stats.tx_dropped++;
goto fail;
case AP_TX_RETRY:
@@ -455,7 +455,7 @@ int hostap_master_start_xmit(struct sk_buff *skb, struct net_device *dev)
case AP_TX_BUFFERED:
/* do not free skb here, it will be freed when the
* buffered frame is sent/timed out */
- ret = 0;
+ ret = NETDEV_TX_OK;
goto tx_exit;
}
@@ -501,7 +501,7 @@ int hostap_master_start_xmit(struct sk_buff *skb, struct net_device *dev)
"frame (drop_unencrypted=1)\n", dev->name);
}
iface->stats.tx_dropped++;
- ret = 0;
+ ret = NETDEV_TX_OK;
goto fail;
}
@@ -510,7 +510,7 @@ int hostap_master_start_xmit(struct sk_buff *skb, struct net_device *dev)
if (skb == NULL) {
printk(KERN_DEBUG "%s: TX - encryption failed\n",
dev->name);
- ret = 0;
+ ret = NETDEV_TX_OK;
goto fail;
}
meta = (struct hostap_skb_tx_data *) skb->cb;
@@ -519,23 +519,23 @@ int hostap_master_start_xmit(struct sk_buff *skb, struct net_device *dev)
"expected 0x%08x) after hostap_tx_encrypt\n",
dev->name, meta->magic,
HOSTAP_SKB_TX_DATA_MAGIC);
- ret = 0;
+ ret = NETDEV_TX_OK;
iface->stats.tx_dropped++;
goto fail;
}
}
if (local->func->tx == NULL || local->func->tx(skb, dev)) {
- ret = 0;
+ ret = NETDEV_TX_OK;
iface->stats.tx_dropped++;
} else {
- ret = 0;
+ ret = NETDEV_TX_OK;
iface->stats.tx_packets++;
iface->stats.tx_bytes += skb->len;
}
fail:
- if (!ret && skb)
+ if (ret == NETDEV_TX_OK && skb)
dev_kfree_skb(skb);
tx_exit:
if (tx.sta_ptr)
diff --git a/drivers/net/wireless/hostap/hostap_cs.c b/drivers/net/wireless/hostap/hostap_cs.c
index 63374027735..ad8eab4a639 100644
--- a/drivers/net/wireless/hostap/hostap_cs.c
+++ b/drivers/net/wireless/hostap/hostap_cs.c
@@ -666,7 +666,8 @@ static int prism2_config(struct pcmcia_device *link)
* irq structure is initialized.
*/
if (link->conf.Attributes & CONF_ENABLE_IRQ) {
- link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
+ link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING |
+ IRQ_HANDLE_PRESENT;
link->irq.IRQInfo1 = IRQ_LEVEL_ID;
link->irq.Handler = prism2_interrupt;
link->irq.Instance = dev;
diff --git a/drivers/net/wireless/ipw2x00/ipw2200.c b/drivers/net/wireless/ipw2x00/ipw2200.c
index 6dcac73b4d2..07f171c4d30 100644
--- a/drivers/net/wireless/ipw2x00/ipw2200.c
+++ b/drivers/net/wireless/ipw2x00/ipw2200.c
@@ -7250,9 +7250,6 @@ static void ipw_bg_qos_activate(struct work_struct *work)
struct ipw_priv *priv =
container_of(work, struct ipw_priv, qos_activate);
- if (priv == NULL)
- return;
-
mutex_lock(&priv->mutex);
if (priv->status & STATUS_ASSOCIATED)
@@ -11436,11 +11433,11 @@ static struct pci_device_id card_ids[] = {
{PCI_VENDOR_ID_INTEL, 0x1043, 0x8086, 0x2754, 0, 0, 0},
{PCI_VENDOR_ID_INTEL, 0x1043, 0x8086, 0x2761, 0, 0, 0},
{PCI_VENDOR_ID_INTEL, 0x1043, 0x8086, 0x2762, 0, 0, 0},
- {PCI_VENDOR_ID_INTEL, 0x104f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
- {PCI_VENDOR_ID_INTEL, 0x4220, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, /* BG */
- {PCI_VENDOR_ID_INTEL, 0x4221, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, /* BG */
- {PCI_VENDOR_ID_INTEL, 0x4223, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, /* ABG */
- {PCI_VENDOR_ID_INTEL, 0x4224, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, /* ABG */
+ {PCI_VDEVICE(INTEL, 0x104f), 0},
+ {PCI_VDEVICE(INTEL, 0x4220), 0}, /* BG */
+ {PCI_VDEVICE(INTEL, 0x4221), 0}, /* BG */
+ {PCI_VDEVICE(INTEL, 0x4223), 0}, /* ABG */
+ {PCI_VDEVICE(INTEL, 0x4224), 0}, /* ABG */
/* required last entry */
{0,}
diff --git a/drivers/net/wireless/ipw2x00/libipw_tx.c b/drivers/net/wireless/ipw2x00/libipw_tx.c
index da2ad5437ce..2e8f84fb29f 100644
--- a/drivers/net/wireless/ipw2x00/libipw_tx.c
+++ b/drivers/net/wireless/ipw2x00/libipw_tx.c
@@ -527,13 +527,13 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
if (ret == 0) {
dev->stats.tx_packets++;
dev->stats.tx_bytes += txb->payload_size;
- return 0;
+ return NETDEV_TX_OK;
}
ieee80211_txb_free(txb);
}
- return 0;
+ return NETDEV_TX_OK;
failed:
spin_unlock_irqrestore(&ieee->lock, flags);
diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig
index e092af09d6b..99310c03325 100644
--- a/drivers/net/wireless/iwlwifi/Kconfig
+++ b/drivers/net/wireless/iwlwifi/Kconfig
@@ -9,6 +9,9 @@ config IWLWIFI
config IWLWIFI_LEDS
bool "Enable LED support in iwlagn and iwl3945 drivers"
depends on IWLWIFI
+ default y
+ ---help---
+ Select this if you want LED support.
config IWLWIFI_SPECTRUM_MEASUREMENT
bool "Enable Spectrum Measurement in iwlagn driver"
diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c
index 7da52f1cc1d..191718a0c54 100644
--- a/drivers/net/wireless/iwlwifi/iwl-1000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-1000.c
@@ -46,7 +46,7 @@
#include "iwl-5000-hw.h"
/* Highest firmware API version supported */
-#define IWL1000_UCODE_API_MAX 2
+#define IWL1000_UCODE_API_MAX 3
/* Lowest firmware API version supported */
#define IWL1000_UCODE_API_MIN 1
@@ -55,13 +55,100 @@
#define _IWL1000_MODULE_FIRMWARE(api) IWL1000_FW_PRE #api ".ucode"
#define IWL1000_MODULE_FIRMWARE(api) _IWL1000_MODULE_FIRMWARE(api)
+
+/*
+ * For 1000, use advance thermal throttling critical temperature threshold,
+ * but legacy thermal management implementation for now.
+ * This is for the reason of 1000 uCode using advance thermal throttling API
+ * but not implement ct_kill_exit based on ct_kill exit temperature
+ * so the thermal throttling will still based on legacy thermal throttling
+ * management.
+ * The code here need to be modified once 1000 uCode has the advanced thermal
+ * throttling algorithm in place
+ */
+static void iwl1000_set_ct_threshold(struct iwl_priv *priv)
+{
+ /* want Celsius */
+ priv->hw_params.ct_kill_threshold = CT_KILL_THRESHOLD_LEGACY;
+ priv->hw_params.ct_kill_exit_threshold = CT_KILL_EXIT_THRESHOLD;
+}
+
+/* NIC configuration for 1000 series */
+static void iwl1000_nic_config(struct iwl_priv *priv)
+{
+ iwl5000_nic_config(priv);
+
+ /* Setting digital SVR for 1000 card to 1.32V */
+ /* locking is acquired in iwl_set_bits_mask_prph() function */
+ iwl_set_bits_mask_prph(priv, APMG_DIGITAL_SVR_REG,
+ APMG_SVR_DIGITAL_VOLTAGE_1_32,
+ ~APMG_SVR_VOLTAGE_CONFIG_BIT_MSK);
+}
+
+static struct iwl_lib_ops iwl1000_lib = {
+ .set_hw_params = iwl5000_hw_set_hw_params,
+ .txq_update_byte_cnt_tbl = iwl5000_txq_update_byte_cnt_tbl,
+ .txq_inval_byte_cnt_tbl = iwl5000_txq_inval_byte_cnt_tbl,
+ .txq_set_sched = iwl5000_txq_set_sched,
+ .txq_agg_enable = iwl5000_txq_agg_enable,
+ .txq_agg_disable = iwl5000_txq_agg_disable,
+ .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd,
+ .txq_free_tfd = iwl_hw_txq_free_tfd,
+ .txq_init = iwl_hw_tx_queue_init,
+ .rx_handler_setup = iwl5000_rx_handler_setup,
+ .setup_deferred_work = iwl5000_setup_deferred_work,
+ .is_valid_rtc_data_addr = iwl5000_hw_valid_rtc_data_addr,
+ .load_ucode = iwl5000_load_ucode,
+ .init_alive_start = iwl5000_init_alive_start,
+ .alive_notify = iwl5000_alive_notify,
+ .send_tx_power = iwl5000_send_tx_power,
+ .update_chain_flags = iwl_update_chain_flags,
+ .apm_ops = {
+ .init = iwl5000_apm_init,
+ .reset = iwl5000_apm_reset,
+ .stop = iwl5000_apm_stop,
+ .config = iwl1000_nic_config,
+ .set_pwr_src = iwl_set_pwr_src,
+ },
+ .eeprom_ops = {
+ .regulatory_bands = {
+ EEPROM_5000_REG_BAND_1_CHANNELS,
+ EEPROM_5000_REG_BAND_2_CHANNELS,
+ EEPROM_5000_REG_BAND_3_CHANNELS,
+ EEPROM_5000_REG_BAND_4_CHANNELS,
+ EEPROM_5000_REG_BAND_5_CHANNELS,
+ EEPROM_5000_REG_BAND_24_HT40_CHANNELS,
+ EEPROM_5000_REG_BAND_52_HT40_CHANNELS
+ },
+ .verify_signature = iwlcore_eeprom_verify_signature,
+ .acquire_semaphore = iwlcore_eeprom_acquire_semaphore,
+ .release_semaphore = iwlcore_eeprom_release_semaphore,
+ .calib_version = iwl5000_eeprom_calib_version,
+ .query_addr = iwl5000_eeprom_query_addr,
+ },
+ .post_associate = iwl_post_associate,
+ .isr = iwl_isr_ict,
+ .config_ap = iwl_config_ap,
+ .temp_ops = {
+ .temperature = iwl5000_temperature,
+ .set_ct_kill = iwl1000_set_ct_threshold,
+ },
+};
+
+static struct iwl_ops iwl1000_ops = {
+ .ucode = &iwl5000_ucode,
+ .lib = &iwl1000_lib,
+ .hcmd = &iwl5000_hcmd,
+ .utils = &iwl5000_hcmd_utils,
+};
+
struct iwl_cfg iwl1000_bgn_cfg = {
.name = "1000 Series BGN",
.fw_name_pre = IWL1000_FW_PRE,
.ucode_api_max = IWL1000_UCODE_API_MAX,
.ucode_api_min = IWL1000_UCODE_API_MIN,
.sku = IWL_SKU_G|IWL_SKU_N,
- .ops = &iwl5000_ops,
+ .ops = &iwl1000_ops,
.eeprom_size = IWL_5000_EEPROM_IMG_SIZE,
.eeprom_ver = EEPROM_5000_EEPROM_VERSION,
.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h
index 73f93a0ff2d..16772780c5b 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h
+++ b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h
@@ -176,7 +176,7 @@ struct iwl3945_eeprom {
* in EEPROM containing EEPROM_CHANNEL_* usage flags (LSB) and max regulatory
* txpower (MSB).
*
- * Entries immediately below are for 20 MHz channel width. FAT (40 MHz)
+ * Entries immediately below are for 20 MHz channel width. HT40 (40 MHz)
* channels (only for 4965, not supported by 3945) appear later in the EEPROM.
*
* 2.4 GHz channels 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14
@@ -232,9 +232,8 @@ struct iwl3945_eeprom {
#define PCI_CFG_REV_ID_BIT_BASIC_SKU (0x40) /* bit 6 */
#define PCI_CFG_REV_ID_BIT_RTP (0x80) /* bit 7 */
-#define TFD_QUEUE_MIN 0
-#define TFD_QUEUE_MAX 5 /* 4 DATA + 1 CMD */
-
+/* 4 DATA + 1 CMD. There are 2 HCCA queues that are not used. */
+#define IWL39_NUM_QUEUES 5
#define IWL_NUM_SCAN_RATES (2)
#define IWL_DEFAULT_TX_RETRY 15
@@ -280,8 +279,6 @@ struct iwl3945_eeprom {
/* Size of uCode instruction memory in bootstrap state machine */
#define IWL39_MAX_BSM_SIZE IWL39_RTC_INST_SIZE
-#define IWL39_MAX_NUM_QUEUES 8
-
static inline int iwl3945_hw_valid_rtc_data_addr(u32 addr)
{
return (addr >= IWL39_RTC_DATA_LOWER_BOUND) &&
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-led.c b/drivers/net/wireless/iwlwifi/iwl-3945-led.c
index 225e5f88934..8c29ded7d02 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945-led.c
+++ b/drivers/net/wireless/iwlwifi/iwl-3945-led.c
@@ -79,11 +79,10 @@ static const struct {
#define IWL_MAX_BLINK_TBL (ARRAY_SIZE(blink_tbl) - 1) /*Exclude Solid on*/
#define IWL_SOLID_BLINK_IDX (ARRAY_SIZE(blink_tbl) - 1)
-static int iwl3945_led_cmd_callback(struct iwl_priv *priv,
- struct iwl_cmd *cmd,
- struct sk_buff *skb)
+static void iwl3945_led_cmd_callback(struct iwl_priv *priv,
+ struct iwl_device_cmd *cmd,
+ struct sk_buff *skb)
{
- return 1;
}
static inline int iwl3945_brightness_to_idx(enum led_brightness brightness)
@@ -99,8 +98,8 @@ static int iwl_send_led_cmd(struct iwl_priv *priv,
.id = REPLY_LEDS_CMD,
.len = sizeof(struct iwl_led_cmd),
.data = led_cmd,
- .meta.flags = CMD_ASYNC,
- .meta.u.callback = iwl3945_led_cmd_callback,
+ .flags = CMD_ASYNC,
+ .callback = iwl3945_led_cmd_callback,
};
return iwl_send_cmd(priv, &cmd);
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c
index 5eb538d18a8..a16bd4147ea 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c
@@ -673,33 +673,17 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta,
s8 scale_action = 0;
unsigned long flags;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
- u16 fc;
- u16 rate_mask = 0;
+ u16 rate_mask = sta ? sta->supp_rates[sband->band] : 0;
s8 max_rate_idx = -1;
struct iwl_priv *priv = (struct iwl_priv *)priv_r;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
IWL_DEBUG_RATE(priv, "enter\n");
- if (sta)
- rate_mask = sta->supp_rates[sband->band];
-
- /* Send management frames and NO_ACK data using lowest rate. */
- fc = le16_to_cpu(hdr->frame_control);
- if ((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA ||
- info->flags & IEEE80211_TX_CTL_NO_ACK ||
- !sta || !priv_sta) {
- IWL_DEBUG_RATE(priv, "leave: No STA priv data to update!\n");
- if (!rate_mask)
- info->control.rates[0].idx =
- rate_lowest_index(sband, NULL);
- else
- info->control.rates[0].idx =
- rate_lowest_index(sband, sta);
- if (info->flags & IEEE80211_TX_CTL_NO_ACK)
- info->control.rates[0].count = 1;
+ if (rate_control_send_low(sta, priv_sta, txrc))
return;
- }
+
+ rate_mask = sta->supp_rates[sband->band];
/* get user max rate if set */
max_rate_idx = txrc->max_rate_idx;
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c
index 46288e72488..ba5ef832d77 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945.c
+++ b/drivers/net/wireless/iwlwifi/iwl-3945.c
@@ -509,7 +509,7 @@ static void iwl3945_dbg_report_frame(struct iwl_priv *priv,
struct iwl_rx_packet *pkt,
struct ieee80211_hdr *header, int group100)
{
- if (priv->debug_level & IWL_DL_RX)
+ if (iwl_get_debug_level(priv) & IWL_DL_RX)
_iwl3945_dbg_report_frame(priv, pkt, header, group100);
}
@@ -544,9 +544,7 @@ static void iwl3945_pass_packet_to_mac80211(struct iwl_priv *priv,
struct ieee80211_rx_status *stats)
{
struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
-#ifdef CONFIG_IWLWIFI_LEDS
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)IWL_RX_DATA(pkt);
-#endif
struct iwl3945_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt);
struct iwl3945_rx_frame_end *rx_end = IWL_RX_END(pkt);
short len = le16_to_cpu(rx_hdr->len);
@@ -577,7 +575,10 @@ static void iwl3945_pass_packet_to_mac80211(struct iwl_priv *priv,
if (ieee80211_is_data(hdr->frame_control))
priv->rxtxpackets += len;
#endif
- ieee80211_rx_irqsafe(priv->hw, rxb->skb, stats);
+ iwl_update_stats(priv, false, hdr->frame_control, len);
+
+ memcpy(IEEE80211_SKB_RXCB(rxb->skb), stats, sizeof(*stats));
+ ieee80211_rx_irqsafe(priv->hw, rxb->skb);
rxb->skb = NULL;
}
@@ -678,6 +679,7 @@ static void iwl3945_rx_reply_rx(struct iwl_priv *priv,
/* Set "1" to report good data frames in groups of 100 */
iwl3945_dbg_report_frame(priv, pkt, header, 1);
+ iwl_dbg_log_rx_data_frame(priv, le16_to_cpu(rx_hdr->len), header);
if (network_packet) {
priv->last_beacon_time = le32_to_cpu(rx_end->beacon_timestamp);
@@ -748,8 +750,8 @@ void iwl3945_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq)
/* Unmap tx_cmd */
if (counter)
pci_unmap_single(dev,
- pci_unmap_addr(&txq->cmd[index]->meta, mapping),
- pci_unmap_len(&txq->cmd[index]->meta, len),
+ pci_unmap_addr(&txq->meta[index], mapping),
+ pci_unmap_len(&txq->meta[index], len),
PCI_DMA_TODEVICE);
/* unmap chunks if any */
@@ -773,9 +775,11 @@ void iwl3945_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq)
* iwl3945_hw_build_tx_cmd_rate - Add rate portion to TX_CMD:
*
*/
-void iwl3945_hw_build_tx_cmd_rate(struct iwl_priv *priv, struct iwl_cmd *cmd,
- struct ieee80211_tx_info *info,
- struct ieee80211_hdr *hdr, int sta_id, int tx_id)
+void iwl3945_hw_build_tx_cmd_rate(struct iwl_priv *priv,
+ struct iwl_device_cmd *cmd,
+ struct ieee80211_tx_info *info,
+ struct ieee80211_hdr *hdr,
+ int sta_id, int tx_id)
{
u16 hw_value = ieee80211_get_tx_rate(priv->hw, info)->hw_value;
u16 rate_index = min(hw_value & 0xffff, IWL_RATE_COUNT - 1);
@@ -962,7 +966,7 @@ static int iwl3945_txq_ctx_reset(struct iwl_priv *priv)
goto error;
/* Tx queue(s) */
- for (txq_id = 0; txq_id <= priv->hw_params.max_txq_num; txq_id++) {
+ for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) {
slots_num = (txq_id == IWL_CMD_QUEUE_NUM) ?
TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS;
rc = iwl_tx_queue_init(priv, &priv->txq[txq_id], slots_num,
@@ -1139,7 +1143,7 @@ void iwl3945_hw_txq_ctx_free(struct iwl_priv *priv)
int txq_id;
/* Tx queues */
- for (txq_id = 0; txq_id <= priv->hw_params.max_txq_num; txq_id++)
+ for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++)
if (txq_id == IWL_CMD_QUEUE_NUM)
iwl_cmd_queue_free(priv);
else
@@ -1155,7 +1159,7 @@ void iwl3945_hw_txq_ctx_stop(struct iwl_priv *priv)
iwl_write_prph(priv, ALM_SCD_MODE_REG, 0);
/* reset TFD queues */
- for (txq_id = 0; txq_id <= priv->hw_params.max_txq_num; txq_id++) {
+ for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) {
iwl_write_direct32(priv, FH39_TCSR_CONFIG(txq_id), 0x0);
iwl_poll_direct_bit(priv, FH39_TSSR_TX_STATUS,
FH39_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(txq_id),
@@ -1857,7 +1861,7 @@ static int iwl3945_send_rxon_assoc(struct iwl_priv *priv)
struct iwl_host_cmd cmd = {
.id = REPLY_RXON_ASSOC,
.len = sizeof(rxon_assoc),
- .meta.flags = CMD_WANT_SKB,
+ .flags = CMD_WANT_SKB,
.data = &rxon_assoc,
};
const struct iwl_rxon_cmd *rxon1 = &priv->staging_rxon;
@@ -1881,14 +1885,14 @@ static int iwl3945_send_rxon_assoc(struct iwl_priv *priv)
if (rc)
return rc;
- res = (struct iwl_rx_packet *)cmd.meta.u.skb->data;
+ res = (struct iwl_rx_packet *)cmd.reply_skb->data;
if (res->hdr.flags & IWL_CMD_FAILED_MSK) {
IWL_ERR(priv, "Bad return from REPLY_RXON_ASSOC command\n");
rc = -EIO;
}
priv->alloc_rxb_skb--;
- dev_kfree_skb_any(cmd.meta.u.skb);
+ dev_kfree_skb_any(cmd.reply_skb);
return rc;
}
@@ -1986,7 +1990,7 @@ static int iwl3945_commit_rxon(struct iwl_priv *priv)
staging_rxon->reserved4 = 0;
staging_rxon->reserved5 = 0;
- iwl_set_rxon_hwcrypto(priv, !priv->hw_params.sw_crypto);
+ iwl_set_rxon_hwcrypto(priv, !iwl3945_mod_params.sw_crypto);
/* Apply the new configuration */
rc = iwl_send_cmd_pdu(priv, REPLY_RXON,
@@ -2551,7 +2555,7 @@ int iwl3945_hw_set_hw_params(struct iwl_priv *priv)
}
/* Assign number of Usable TX queues */
- priv->hw_params.max_txq_num = TFD_QUEUE_MAX;
+ priv->hw_params.max_txq_num = IWL39_NUM_QUEUES;
priv->hw_params.tfd_size = sizeof(struct iwl3945_tfd);
priv->hw_params.rx_buf_size = IWL_RX_BUF_SIZE_3K;
@@ -2562,6 +2566,7 @@ int iwl3945_hw_set_hw_params(struct iwl_priv *priv)
priv->hw_params.bcast_sta_id = IWL3945_BROADCAST_ID;
priv->hw_params.rx_wrt_ptr_reg = FH39_RSCSR_CHNL0_WPTR;
+ priv->hw_params.max_beacon_itrvl = IWL39_MAX_UCODE_BEACON_INTERVAL;
return 0;
}
@@ -2784,11 +2789,50 @@ static int iwl3945_load_bsm(struct iwl_priv *priv)
return 0;
}
+#define IWL3945_UCODE_GET(item) \
+static u32 iwl3945_ucode_get_##item(const struct iwl_ucode_header *ucode,\
+ u32 api_ver) \
+{ \
+ return le32_to_cpu(ucode->u.v1.item); \
+}
+
+static u32 iwl3945_ucode_get_header_size(u32 api_ver)
+{
+ return UCODE_HEADER_SIZE(1);
+}
+static u32 iwl3945_ucode_get_build(const struct iwl_ucode_header *ucode,
+ u32 api_ver)
+{
+ return 0;
+}
+static u8 *iwl3945_ucode_get_data(const struct iwl_ucode_header *ucode,
+ u32 api_ver)
+{
+ return (u8 *) ucode->u.v1.data;
+}
+
+IWL3945_UCODE_GET(inst_size);
+IWL3945_UCODE_GET(data_size);
+IWL3945_UCODE_GET(init_size);
+IWL3945_UCODE_GET(init_data_size);
+IWL3945_UCODE_GET(boot_size);
+
static struct iwl_hcmd_ops iwl3945_hcmd = {
.rxon_assoc = iwl3945_send_rxon_assoc,
.commit_rxon = iwl3945_commit_rxon,
};
+static struct iwl_ucode_ops iwl3945_ucode = {
+ .get_header_size = iwl3945_ucode_get_header_size,
+ .get_build = iwl3945_ucode_get_build,
+ .get_inst_size = iwl3945_ucode_get_inst_size,
+ .get_data_size = iwl3945_ucode_get_data_size,
+ .get_init_size = iwl3945_ucode_get_init_size,
+ .get_init_data_size = iwl3945_ucode_get_init_data_size,
+ .get_boot_size = iwl3945_ucode_get_boot_size,
+ .get_data = iwl3945_ucode_get_data,
+};
+
static struct iwl_lib_ops iwl3945_lib = {
.txq_attach_buf_to_tfd = iwl3945_hw_txq_attach_buf_to_tfd,
.txq_free_tfd = iwl3945_hw_txq_free_tfd,
@@ -2808,8 +2852,8 @@ static struct iwl_lib_ops iwl3945_lib = {
EEPROM_REGULATORY_BAND_3_CHANNELS,
EEPROM_REGULATORY_BAND_4_CHANNELS,
EEPROM_REGULATORY_BAND_5_CHANNELS,
- EEPROM_REGULATORY_BAND_NO_FAT,
- EEPROM_REGULATORY_BAND_NO_FAT,
+ EEPROM_REGULATORY_BAND_NO_HT40,
+ EEPROM_REGULATORY_BAND_NO_HT40,
},
.verify_signature = iwlcore_eeprom_verify_signature,
.acquire_semaphore = iwl3945_eeprom_acquire_semaphore,
@@ -2829,6 +2873,7 @@ static struct iwl_hcmd_utils_ops iwl3945_hcmd_utils = {
};
static struct iwl_ops iwl3945_ops = {
+ .ucode = &iwl3945_ucode,
.lib = &iwl3945_lib,
.hcmd = &iwl3945_hcmd,
.utils = &iwl3945_hcmd_utils,
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h
index 2de6471d4be..f2403690991 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945.h
+++ b/drivers/net/wireless/iwlwifi/iwl-3945.h
@@ -111,9 +111,6 @@ enum iwl3945_antenna {
#define IWL_TX_FIFO_HCCA_2 6
#define IWL_TX_FIFO_NONE 7
-/* Minimum number of queues. MAX_NUM is defined in hw specific files */
-#define IWL39_MIN_NUM_QUEUES 4
-
#define IEEE80211_DATA_LEN 2304
#define IEEE80211_4ADDR_LEN 30
#define IEEE80211_HLEN (IEEE80211_4ADDR_LEN)
@@ -257,10 +254,11 @@ extern int iwl3945_hw_tx_queue_init(struct iwl_priv *priv,
struct iwl_tx_queue *txq);
extern unsigned int iwl3945_hw_get_beacon_cmd(struct iwl_priv *priv,
struct iwl3945_frame *frame, u8 rate);
-void iwl3945_hw_build_tx_cmd_rate(struct iwl_priv *priv, struct iwl_cmd *cmd,
- struct ieee80211_tx_info *info,
- struct ieee80211_hdr *hdr,
- int sta_id, int tx_id);
+void iwl3945_hw_build_tx_cmd_rate(struct iwl_priv *priv,
+ struct iwl_device_cmd *cmd,
+ struct ieee80211_tx_info *info,
+ struct ieee80211_hdr *hdr,
+ int sta_id, int tx_id);
extern int iwl3945_hw_reg_send_txpower(struct iwl_priv *priv);
extern int iwl3945_hw_reg_set_txpower(struct iwl_priv *priv, s8 power);
extern void iwl3945_hw_rx_statistics(struct iwl_priv *priv,
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h
index a71a489096f..b34322a3245 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h
+++ b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h
@@ -188,7 +188,7 @@ static inline int iwl4965_hw_valid_rtc_data_addr(u32 addr)
*
* 1) Regulatory information (max txpower and channel usage flags) is provided
* separately for each channel that can possibly supported by 4965.
- * 40 MHz wide (.11n fat) channels are listed separately from 20 MHz
+ * 40 MHz wide (.11n HT40) channels are listed separately from 20 MHz
* (legacy) channels.
*
* See struct iwl4965_eeprom_channel for format, and struct iwl4965_eeprom
@@ -251,8 +251,8 @@ static inline int iwl4965_hw_valid_rtc_data_addr(u32 addr)
* no reduction (such as with regulatory txpower limits) is required.
*
* Saturation and Backoff values apply equally to 20 Mhz (legacy) channel
- * widths and 40 Mhz (.11n fat) channel widths; there is no separate
- * factory measurement for fat channels.
+ * widths and 40 Mhz (.11n HT40) channel widths; there is no separate
+ * factory measurement for ht40 channels.
*
* The result of this step is the final target txpower. The rest of
* the steps figure out the proper settings for the device to achieve
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c
index 8f3d4bc6a03..e427a8937ed 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965.c
+++ b/drivers/net/wireless/iwlwifi/iwl-4965.c
@@ -46,7 +46,7 @@
#include "iwl-sta.h"
static int iwl4965_send_tx_power(struct iwl_priv *priv);
-static int iwl4965_hw_get_temperature(const struct iwl_priv *priv);
+static int iwl4965_hw_get_temperature(struct iwl_priv *priv);
/* Highest firmware API version supported */
#define IWL4965_UCODE_API_MAX 2
@@ -293,7 +293,7 @@ restart:
queue_work(priv->workqueue, &priv->restart);
}
-static bool is_fat_channel(__le32 rxon_flags)
+static bool is_ht40_channel(__le32 rxon_flags)
{
int chan_mod = le32_to_cpu(rxon_flags & RXON_FLG_CHANNEL_MODE_MSK)
>> RXON_FLG_CHANNEL_MODE_POS;
@@ -728,7 +728,7 @@ static int iwl4965_alive_notify(struct iwl_priv *priv)
static struct iwl_sensitivity_ranges iwl4965_sensitivity = {
.min_nrg_cck = 97,
- .max_nrg_cck = 0,
+ .max_nrg_cck = 0, /* not used, set to 0 */
.auto_corr_min_ofdm = 85,
.auto_corr_min_ofdm_mrc = 170,
@@ -752,7 +752,8 @@ static struct iwl_sensitivity_ranges iwl4965_sensitivity = {
static void iwl4965_set_ct_threshold(struct iwl_priv *priv)
{
/* want Kelvin */
- priv->hw_params.ct_kill_threshold = CELSIUS_TO_KELVIN(CT_KILL_THRESHOLD);
+ priv->hw_params.ct_kill_threshold =
+ CELSIUS_TO_KELVIN(CT_KILL_THRESHOLD_LEGACY);
}
/**
@@ -781,7 +782,7 @@ static int iwl4965_hw_set_hw_params(struct iwl_priv *priv)
priv->hw_params.max_data_size = IWL49_RTC_DATA_SIZE;
priv->hw_params.max_inst_size = IWL49_RTC_INST_SIZE;
priv->hw_params.max_bsm_size = BSM_SRAM_SIZE;
- priv->hw_params.fat_channel = BIT(IEEE80211_BAND_5GHZ);
+ priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_5GHZ);
priv->hw_params.rx_wrt_ptr_reg = FH_RSCSR_CHNL0_WPTR;
@@ -1241,7 +1242,7 @@ static const struct gain_entry gain_table[2][108] = {
};
static int iwl4965_fill_txpower_tbl(struct iwl_priv *priv, u8 band, u16 channel,
- u8 is_fat, u8 ctrl_chan_high,
+ u8 is_ht40, u8 ctrl_chan_high,
struct iwl4965_tx_power_db *tx_power_tbl)
{
u8 saturation_power;
@@ -1273,8 +1274,8 @@ static int iwl4965_fill_txpower_tbl(struct iwl_priv *priv, u8 band, u16 channel,
user_target_power = 2 * priv->tx_power_user_lmt;
/* Get current (RXON) channel, band, width */
- IWL_DEBUG_TXPOWER(priv, "chan %d band %d is_fat %d\n", channel, band,
- is_fat);
+ IWL_DEBUG_TXPOWER(priv, "chan %d band %d is_ht40 %d\n", channel, band,
+ is_ht40);
ch_info = iwl_get_channel_info(priv, priv->band, channel);
@@ -1293,7 +1294,7 @@ static int iwl4965_fill_txpower_tbl(struct iwl_priv *priv, u8 band, u16 channel,
IWL_DEBUG_TXPOWER(priv, "channel %d belongs to txatten group %d\n",
channel, txatten_grp);
- if (is_fat) {
+ if (is_ht40) {
if (ctrl_chan_high)
channel -= 2;
else
@@ -1317,8 +1318,8 @@ static int iwl4965_fill_txpower_tbl(struct iwl_priv *priv, u8 band, u16 channel,
/* regulatory txpower limits ... reg_limit values are in half-dBm,
* max_power_avg values are in dBm, convert * 2 */
- if (is_fat)
- reg_limit = ch_info->fat_max_power_avg * 2;
+ if (is_ht40)
+ reg_limit = ch_info->ht40_max_power_avg * 2;
else
reg_limit = ch_info->max_power_avg * 2;
@@ -1484,7 +1485,7 @@ static int iwl4965_fill_txpower_tbl(struct iwl_priv *priv, u8 band, u16 channel,
/**
* iwl4965_send_tx_power - Configure the TXPOWER level user limit
*
- * Uses the active RXON for channel, band, and characteristics (fat, high)
+ * Uses the active RXON for channel, band, and characteristics (ht40, high)
* The power limit is taken from priv->tx_power_user_lmt.
*/
static int iwl4965_send_tx_power(struct iwl_priv *priv)
@@ -1492,7 +1493,7 @@ static int iwl4965_send_tx_power(struct iwl_priv *priv)
struct iwl4965_txpowertable_cmd cmd = { 0 };
int ret;
u8 band = 0;
- bool is_fat = false;
+ bool is_ht40 = false;
u8 ctrl_chan_high = 0;
if (test_bit(STATUS_SCANNING, &priv->status)) {
@@ -1505,9 +1506,9 @@ static int iwl4965_send_tx_power(struct iwl_priv *priv)
band = priv->band == IEEE80211_BAND_2GHZ;
- is_fat = is_fat_channel(priv->active_rxon.flags);
+ is_ht40 = is_ht40_channel(priv->active_rxon.flags);
- if (is_fat &&
+ if (is_ht40 &&
(priv->active_rxon.flags & RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK))
ctrl_chan_high = 1;
@@ -1516,7 +1517,7 @@ static int iwl4965_send_tx_power(struct iwl_priv *priv)
ret = iwl4965_fill_txpower_tbl(priv, band,
le16_to_cpu(priv->active_rxon.channel),
- is_fat, ctrl_chan_high, &cmd.tx_power);
+ is_ht40, ctrl_chan_high, &cmd.tx_power);
if (ret)
goto out;
@@ -1570,7 +1571,7 @@ static int iwl4965_hw_channel_switch(struct iwl_priv *priv, u16 channel)
{
int rc;
u8 band = 0;
- bool is_fat = false;
+ bool is_ht40 = false;
u8 ctrl_chan_high = 0;
struct iwl4965_channel_switch_cmd cmd = { 0 };
const struct iwl_channel_info *ch_info;
@@ -1579,9 +1580,9 @@ static int iwl4965_hw_channel_switch(struct iwl_priv *priv, u16 channel)
ch_info = iwl_get_channel_info(priv, priv->band, channel);
- is_fat = is_fat_channel(priv->staging_rxon.flags);
+ is_ht40 = is_ht40_channel(priv->staging_rxon.flags);
- if (is_fat &&
+ if (is_ht40 &&
(priv->active_rxon.flags & RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK))
ctrl_chan_high = 1;
@@ -1596,7 +1597,7 @@ static int iwl4965_hw_channel_switch(struct iwl_priv *priv, u16 channel)
else
cmd.expect_beacon = 1;
- rc = iwl4965_fill_txpower_tbl(priv, band, channel, is_fat,
+ rc = iwl4965_fill_txpower_tbl(priv, band, channel, is_ht40,
ctrl_chan_high, &cmd.tx_power);
if (rc) {
IWL_DEBUG_11H(priv, "error:%d fill txpower_tbl\n", rc);
@@ -1655,7 +1656,7 @@ static s32 sign_extend(u32 oper, int index)
*
* A return of <0 indicates bogus data in the statistics
*/
-static int iwl4965_hw_get_temperature(const struct iwl_priv *priv)
+static int iwl4965_hw_get_temperature(struct iwl_priv *priv)
{
s32 temperature;
s32 vt;
@@ -1663,8 +1664,8 @@ static int iwl4965_hw_get_temperature(const struct iwl_priv *priv)
u32 R4;
if (test_bit(STATUS_TEMPERATURE, &priv->status) &&
- (priv->statistics.flag & STATISTICS_REPLY_FLG_FAT_MODE_MSK)) {
- IWL_DEBUG_TEMP(priv, "Running FAT temperature calibration\n");
+ (priv->statistics.flag & STATISTICS_REPLY_FLG_HT40_MODE_MSK)) {
+ IWL_DEBUG_TEMP(priv, "Running HT40 temperature calibration\n");
R1 = (s32)le32_to_cpu(priv->card_alive_init.therm_r1[1]);
R2 = (s32)le32_to_cpu(priv->card_alive_init.therm_r2[1]);
R3 = (s32)le32_to_cpu(priv->card_alive_init.therm_r3[1]);
@@ -1772,6 +1773,7 @@ static void iwl4965_temperature_calib(struct iwl_priv *priv)
}
priv->temperature = temp;
+ iwl_tt_handler(priv);
set_bit(STATUS_TEMPERATURE, &priv->status);
if (!priv->disable_tx_power_cal &&
@@ -2221,12 +2223,50 @@ static void iwl4965_cancel_deferred_work(struct iwl_priv *priv)
cancel_work_sync(&priv->txpower_work);
}
+#define IWL4965_UCODE_GET(item) \
+static u32 iwl4965_ucode_get_##item(const struct iwl_ucode_header *ucode,\
+ u32 api_ver) \
+{ \
+ return le32_to_cpu(ucode->u.v1.item); \
+}
+
+static u32 iwl4965_ucode_get_header_size(u32 api_ver)
+{
+ return UCODE_HEADER_SIZE(1);
+}
+static u32 iwl4965_ucode_get_build(const struct iwl_ucode_header *ucode,
+ u32 api_ver)
+{
+ return 0;
+}
+static u8 *iwl4965_ucode_get_data(const struct iwl_ucode_header *ucode,
+ u32 api_ver)
+{
+ return (u8 *) ucode->u.v1.data;
+}
+
+IWL4965_UCODE_GET(inst_size);
+IWL4965_UCODE_GET(data_size);
+IWL4965_UCODE_GET(init_size);
+IWL4965_UCODE_GET(init_data_size);
+IWL4965_UCODE_GET(boot_size);
+
static struct iwl_hcmd_ops iwl4965_hcmd = {
.rxon_assoc = iwl4965_send_rxon_assoc,
.commit_rxon = iwl_commit_rxon,
.set_rxon_chain = iwl_set_rxon_chain,
};
+static struct iwl_ucode_ops iwl4965_ucode = {
+ .get_header_size = iwl4965_ucode_get_header_size,
+ .get_build = iwl4965_ucode_get_build,
+ .get_inst_size = iwl4965_ucode_get_inst_size,
+ .get_data_size = iwl4965_ucode_get_data_size,
+ .get_init_size = iwl4965_ucode_get_init_size,
+ .get_init_data_size = iwl4965_ucode_get_init_data_size,
+ .get_boot_size = iwl4965_ucode_get_boot_size,
+ .get_data = iwl4965_ucode_get_data,
+};
static struct iwl_hcmd_utils_ops iwl4965_hcmd_utils = {
.get_hcmd_size = iwl4965_get_hcmd_size,
.build_addsta_hcmd = iwl4965_build_addsta_hcmd,
@@ -2266,8 +2306,8 @@ static struct iwl_lib_ops iwl4965_lib = {
EEPROM_REGULATORY_BAND_3_CHANNELS,
EEPROM_REGULATORY_BAND_4_CHANNELS,
EEPROM_REGULATORY_BAND_5_CHANNELS,
- EEPROM_4965_REGULATORY_BAND_24_FAT_CHANNELS,
- EEPROM_4965_REGULATORY_BAND_52_FAT_CHANNELS
+ EEPROM_4965_REGULATORY_BAND_24_HT40_CHANNELS,
+ EEPROM_4965_REGULATORY_BAND_52_HT40_CHANNELS
},
.verify_signature = iwlcore_eeprom_verify_signature,
.acquire_semaphore = iwlcore_eeprom_acquire_semaphore,
@@ -2287,6 +2327,7 @@ static struct iwl_lib_ops iwl4965_lib = {
};
static struct iwl_ops iwl4965_ops = {
+ .ucode = &iwl4965_ucode,
.lib = &iwl4965_lib,
.hcmd = &iwl4965_hcmd,
.utils = &iwl4965_hcmd_utils,
@@ -2313,8 +2354,6 @@ module_param_named(antenna, iwl4965_mod_params.antenna, int, 0444);
MODULE_PARM_DESC(antenna, "select antenna (1=Main, 2=Aux, default 0 [both])");
module_param_named(swcrypto, iwl4965_mod_params.sw_crypto, int, 0444);
MODULE_PARM_DESC(swcrypto, "using crypto in software (default 0 [hardware])");
-module_param_named(debug, iwl4965_mod_params.debug, uint, 0444);
-MODULE_PARM_DESC(debug, "debug output mask");
module_param_named(
disable_hw_scan, iwl4965_mod_params.disable_hw_scan, int, 0444);
MODULE_PARM_DESC(disable_hw_scan, "disable hardware scanning (default 0)");
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c
index b3c648ce8c7..755c184b3ec 100644
--- a/drivers/net/wireless/iwlwifi/iwl-5000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-5000.c
@@ -91,7 +91,7 @@ static int iwl5000_apm_stop_master(struct iwl_priv *priv)
}
-static int iwl5000_apm_init(struct iwl_priv *priv)
+int iwl5000_apm_init(struct iwl_priv *priv)
{
int ret = 0;
@@ -137,7 +137,7 @@ static int iwl5000_apm_init(struct iwl_priv *priv)
}
/* FIXME: this is identical to 4965 */
-static void iwl5000_apm_stop(struct iwl_priv *priv)
+void iwl5000_apm_stop(struct iwl_priv *priv)
{
unsigned long flags;
@@ -156,7 +156,7 @@ static void iwl5000_apm_stop(struct iwl_priv *priv)
}
-static int iwl5000_apm_reset(struct iwl_priv *priv)
+int iwl5000_apm_reset(struct iwl_priv *priv)
{
int ret = 0;
@@ -198,7 +198,8 @@ out:
}
-static void iwl5000_nic_config(struct iwl_priv *priv)
+/* NIC configuration for 5000 series and up */
+void iwl5000_nic_config(struct iwl_priv *priv)
{
unsigned long flags;
u16 radio_cfg;
@@ -239,11 +240,11 @@ static void iwl5000_nic_config(struct iwl_priv *priv)
APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS,
~APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS);
+
spin_unlock_irqrestore(&priv->lock, flags);
}
-
/*
* EEPROM
*/
@@ -283,7 +284,7 @@ static u32 eeprom_indirect_address(const struct iwl_priv *priv, u32 address)
return (address & ADDRESS_MSK) + (offset << 1);
}
-static u16 iwl5000_eeprom_calib_version(struct iwl_priv *priv)
+u16 iwl5000_eeprom_calib_version(struct iwl_priv *priv)
{
struct iwl_eeprom_calib_hdr {
u8 version;
@@ -388,7 +389,7 @@ void iwl5000_rts_tx_cmd_flag(struct ieee80211_tx_info *info,
static struct iwl_sensitivity_ranges iwl5000_sensitivity = {
.min_nrg_cck = 95,
- .max_nrg_cck = 0,
+ .max_nrg_cck = 0, /* not used, set to 0 */
.auto_corr_min_ofdm = 90,
.auto_corr_min_ofdm_mrc = 170,
.auto_corr_min_ofdm_x1 = 120,
@@ -407,7 +408,29 @@ static struct iwl_sensitivity_ranges iwl5000_sensitivity = {
.nrg_th_ofdm = 95,
};
-static const u8 *iwl5000_eeprom_query_addr(const struct iwl_priv *priv,
+static struct iwl_sensitivity_ranges iwl5150_sensitivity = {
+ .min_nrg_cck = 95,
+ .max_nrg_cck = 0, /* not used, set to 0 */
+ .auto_corr_min_ofdm = 90,
+ .auto_corr_min_ofdm_mrc = 170,
+ .auto_corr_min_ofdm_x1 = 105,
+ .auto_corr_min_ofdm_mrc_x1 = 220,
+
+ .auto_corr_max_ofdm = 120,
+ .auto_corr_max_ofdm_mrc = 210,
+ /* max = min for performance bug in 5150 DSP */
+ .auto_corr_max_ofdm_x1 = 105,
+ .auto_corr_max_ofdm_mrc_x1 = 220,
+
+ .auto_corr_min_cck = 125,
+ .auto_corr_max_cck = 200,
+ .auto_corr_min_cck_mrc = 170,
+ .auto_corr_max_cck_mrc = 400,
+ .nrg_th_cck = 95,
+ .nrg_th_ofdm = 95,
+};
+
+const u8 *iwl5000_eeprom_query_addr(const struct iwl_priv *priv,
size_t offset)
{
u32 address = eeprom_indirect_address(priv, offset);
@@ -418,7 +441,7 @@ static const u8 *iwl5000_eeprom_query_addr(const struct iwl_priv *priv,
static void iwl5150_set_ct_threshold(struct iwl_priv *priv)
{
const s32 volt2temp_coef = IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF;
- s32 threshold = (s32)CELSIUS_TO_KELVIN(CT_KILL_THRESHOLD) -
+ s32 threshold = (s32)CELSIUS_TO_KELVIN(CT_KILL_THRESHOLD_LEGACY) -
iwl_temp_calib_to_offset(priv);
priv->hw_params.ct_kill_threshold = threshold * volt2temp_coef;
@@ -427,7 +450,7 @@ static void iwl5150_set_ct_threshold(struct iwl_priv *priv)
static void iwl5000_set_ct_threshold(struct iwl_priv *priv)
{
/* want Celsius */
- priv->hw_params.ct_kill_threshold = CT_KILL_THRESHOLD;
+ priv->hw_params.ct_kill_threshold = CT_KILL_THRESHOLD_LEGACY;
}
/*
@@ -602,7 +625,7 @@ static int iwl5000_load_given_ucode(struct iwl_priv *priv,
return ret;
}
-static int iwl5000_load_ucode(struct iwl_priv *priv)
+int iwl5000_load_ucode(struct iwl_priv *priv)
{
int ret = 0;
@@ -629,7 +652,7 @@ static int iwl5000_load_ucode(struct iwl_priv *priv)
return ret;
}
-static void iwl5000_init_alive_start(struct iwl_priv *priv)
+void iwl5000_init_alive_start(struct iwl_priv *priv)
{
int ret = 0;
@@ -705,7 +728,7 @@ static int iwl5000_send_wimax_coex(struct iwl_priv *priv)
sizeof(coex_cmd), &coex_cmd);
}
-static int iwl5000_alive_notify(struct iwl_priv *priv)
+int iwl5000_alive_notify(struct iwl_priv *priv)
{
u32 a;
unsigned long flags;
@@ -792,7 +815,7 @@ static int iwl5000_alive_notify(struct iwl_priv *priv)
return 0;
}
-static int iwl5000_hw_set_hw_params(struct iwl_priv *priv)
+int iwl5000_hw_set_hw_params(struct iwl_priv *priv)
{
if ((priv->cfg->mod_params->num_of_queues > IWL50_NUM_QUEUES) ||
(priv->cfg->mod_params->num_of_queues < IWL_MIN_NUM_QUEUES)) {
@@ -822,12 +845,10 @@ static int iwl5000_hw_set_hw_params(struct iwl_priv *priv)
}
priv->hw_params.max_bsm_size = 0;
- priv->hw_params.fat_channel = BIT(IEEE80211_BAND_2GHZ) |
+ priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ) |
BIT(IEEE80211_BAND_5GHZ);
priv->hw_params.rx_wrt_ptr_reg = FH_RSCSR_CHNL0_WPTR;
- priv->hw_params.sens = &iwl5000_sensitivity;
-
priv->hw_params.tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant);
priv->hw_params.rx_chains_num = num_of_ant(priv->cfg->valid_rx_ant);
priv->hw_params.valid_tx_ant = priv->cfg->valid_tx_ant;
@@ -836,9 +857,11 @@ static int iwl5000_hw_set_hw_params(struct iwl_priv *priv)
if (priv->cfg->ops->lib->temp_ops.set_ct_kill)
priv->cfg->ops->lib->temp_ops.set_ct_kill(priv);
+ /* Set initial sensitivity parameters */
/* Set initial calibration set */
switch (priv->hw_rev & CSR_HW_REV_TYPE_MSK) {
case CSR_HW_REV_TYPE_5150:
+ priv->hw_params.sens = &iwl5150_sensitivity;
priv->hw_params.calib_init_cfg =
BIT(IWL_CALIB_DC) |
BIT(IWL_CALIB_LO) |
@@ -847,6 +870,7 @@ static int iwl5000_hw_set_hw_params(struct iwl_priv *priv)
break;
default:
+ priv->hw_params.sens = &iwl5000_sensitivity;
priv->hw_params.calib_init_cfg =
BIT(IWL_CALIB_XTAL) |
BIT(IWL_CALIB_LO) |
@@ -862,7 +886,7 @@ static int iwl5000_hw_set_hw_params(struct iwl_priv *priv)
/**
* iwl5000_txq_update_byte_cnt_tbl - Set up entry in Tx byte-count array
*/
-static void iwl5000_txq_update_byte_cnt_tbl(struct iwl_priv *priv,
+void iwl5000_txq_update_byte_cnt_tbl(struct iwl_priv *priv,
struct iwl_tx_queue *txq,
u16 byte_cnt)
{
@@ -902,7 +926,7 @@ static void iwl5000_txq_update_byte_cnt_tbl(struct iwl_priv *priv,
tfd_offset[TFD_QUEUE_SIZE_MAX + write_ptr] = bc_ent;
}
-static void iwl5000_txq_inval_byte_cnt_tbl(struct iwl_priv *priv,
+void iwl5000_txq_inval_byte_cnt_tbl(struct iwl_priv *priv,
struct iwl_tx_queue *txq)
{
struct iwl5000_scd_bc_tbl *scd_bc_tbl = priv->scd_bc_tbls.addr;
@@ -957,7 +981,7 @@ static void iwl5000_tx_queue_stop_scheduler(struct iwl_priv *priv, u16 txq_id)
(1 << IWL50_SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN));
}
-static int iwl5000_txq_agg_enable(struct iwl_priv *priv, int txq_id,
+int iwl5000_txq_agg_enable(struct iwl_priv *priv, int txq_id,
int tx_fifo, int sta_id, int tid, u16 ssn_idx)
{
unsigned long flags;
@@ -1018,7 +1042,7 @@ static int iwl5000_txq_agg_enable(struct iwl_priv *priv, int txq_id,
return 0;
}
-static int iwl5000_txq_agg_disable(struct iwl_priv *priv, u16 txq_id,
+int iwl5000_txq_agg_disable(struct iwl_priv *priv, u16 txq_id,
u16 ssn_idx, u8 tx_fifo)
{
if ((IWL50_FIRST_AMPDU_QUEUE > txq_id) ||
@@ -1061,7 +1085,7 @@ u16 iwl5000_build_addsta_hcmd(const struct iwl_addsta_cmd *cmd, u8 *data)
* Activate/Deactivate Tx DMA/FIFO channels according tx fifos mask
* must be called under priv->lock and mac access
*/
-static void iwl5000_txq_set_sched(struct iwl_priv *priv, u32 mask)
+void iwl5000_txq_set_sched(struct iwl_priv *priv, u32 mask)
{
iwl_write_prph(priv, IWL50_SCD_TXFACT, mask);
}
@@ -1282,13 +1306,13 @@ u16 iwl5000_get_hcmd_size(u8 cmd_id, u16 len)
return len;
}
-static void iwl5000_setup_deferred_work(struct iwl_priv *priv)
+void iwl5000_setup_deferred_work(struct iwl_priv *priv)
{
/* in 5000 the tx power calibration is done in uCode */
priv->disable_tx_power_cal = 1;
}
-static void iwl5000_rx_handler_setup(struct iwl_priv *priv)
+void iwl5000_rx_handler_setup(struct iwl_priv *priv)
{
/* init calibration handlers */
priv->rx_handlers[CALIBRATION_RES_NOTIFICATION] =
@@ -1299,7 +1323,7 @@ static void iwl5000_rx_handler_setup(struct iwl_priv *priv)
}
-static int iwl5000_hw_valid_rtc_data_addr(u32 addr)
+int iwl5000_hw_valid_rtc_data_addr(u32 addr)
{
return (addr >= IWL50_RTC_DATA_LOWER_BOUND) &&
(addr < IWL50_RTC_DATA_UPPER_BOUND);
@@ -1351,7 +1375,7 @@ static int iwl5000_send_rxon_assoc(struct iwl_priv *priv)
return ret;
}
-static int iwl5000_send_tx_power(struct iwl_priv *priv)
+int iwl5000_send_tx_power(struct iwl_priv *priv)
{
struct iwl5000_tx_power_dbm_cmd tx_power_cmd;
u8 tx_ant_cfg_cmd;
@@ -1371,10 +1395,11 @@ static int iwl5000_send_tx_power(struct iwl_priv *priv)
NULL);
}
-static void iwl5000_temperature(struct iwl_priv *priv)
+void iwl5000_temperature(struct iwl_priv *priv)
{
/* store temperature from statistics (in Celsius) */
priv->temperature = le32_to_cpu(priv->statistics.general.temperature);
+ iwl_tt_handler(priv);
}
static void iwl5150_temperature(struct iwl_priv *priv)
@@ -1426,6 +1451,44 @@ int iwl5000_calc_rssi(struct iwl_priv *priv,
return max_rssi - agc - IWL49_RSSI_OFFSET;
}
+#define IWL5000_UCODE_GET(item) \
+static u32 iwl5000_ucode_get_##item(const struct iwl_ucode_header *ucode,\
+ u32 api_ver) \
+{ \
+ if (api_ver <= 2) \
+ return le32_to_cpu(ucode->u.v1.item); \
+ return le32_to_cpu(ucode->u.v2.item); \
+}
+
+static u32 iwl5000_ucode_get_header_size(u32 api_ver)
+{
+ if (api_ver <= 2)
+ return UCODE_HEADER_SIZE(1);
+ return UCODE_HEADER_SIZE(2);
+}
+
+static u32 iwl5000_ucode_get_build(const struct iwl_ucode_header *ucode,
+ u32 api_ver)
+{
+ if (api_ver <= 2)
+ return 0;
+ return le32_to_cpu(ucode->u.v2.build);
+}
+
+static u8 *iwl5000_ucode_get_data(const struct iwl_ucode_header *ucode,
+ u32 api_ver)
+{
+ if (api_ver <= 2)
+ return (u8 *) ucode->u.v1.data;
+ return (u8 *) ucode->u.v2.data;
+}
+
+IWL5000_UCODE_GET(inst_size);
+IWL5000_UCODE_GET(data_size);
+IWL5000_UCODE_GET(init_size);
+IWL5000_UCODE_GET(init_data_size);
+IWL5000_UCODE_GET(boot_size);
+
struct iwl_hcmd_ops iwl5000_hcmd = {
.rxon_assoc = iwl5000_send_rxon_assoc,
.commit_rxon = iwl_commit_rxon,
@@ -1441,6 +1504,17 @@ struct iwl_hcmd_utils_ops iwl5000_hcmd_utils = {
.calc_rssi = iwl5000_calc_rssi,
};
+struct iwl_ucode_ops iwl5000_ucode = {
+ .get_header_size = iwl5000_ucode_get_header_size,
+ .get_build = iwl5000_ucode_get_build,
+ .get_inst_size = iwl5000_ucode_get_inst_size,
+ .get_data_size = iwl5000_ucode_get_data_size,
+ .get_init_size = iwl5000_ucode_get_init_size,
+ .get_init_data_size = iwl5000_ucode_get_init_data_size,
+ .get_boot_size = iwl5000_ucode_get_boot_size,
+ .get_data = iwl5000_ucode_get_data,
+};
+
struct iwl_lib_ops iwl5000_lib = {
.set_hw_params = iwl5000_hw_set_hw_params,
.txq_update_byte_cnt_tbl = iwl5000_txq_update_byte_cnt_tbl,
@@ -1473,8 +1547,8 @@ struct iwl_lib_ops iwl5000_lib = {
EEPROM_5000_REG_BAND_3_CHANNELS,
EEPROM_5000_REG_BAND_4_CHANNELS,
EEPROM_5000_REG_BAND_5_CHANNELS,
- EEPROM_5000_REG_BAND_24_FAT_CHANNELS,
- EEPROM_5000_REG_BAND_52_FAT_CHANNELS
+ EEPROM_5000_REG_BAND_24_HT40_CHANNELS,
+ EEPROM_5000_REG_BAND_52_HT40_CHANNELS
},
.verify_signature = iwlcore_eeprom_verify_signature,
.acquire_semaphore = iwlcore_eeprom_acquire_semaphore,
@@ -1523,8 +1597,8 @@ static struct iwl_lib_ops iwl5150_lib = {
EEPROM_5000_REG_BAND_3_CHANNELS,
EEPROM_5000_REG_BAND_4_CHANNELS,
EEPROM_5000_REG_BAND_5_CHANNELS,
- EEPROM_5000_REG_BAND_24_FAT_CHANNELS,
- EEPROM_5000_REG_BAND_52_FAT_CHANNELS
+ EEPROM_5000_REG_BAND_24_HT40_CHANNELS,
+ EEPROM_5000_REG_BAND_52_HT40_CHANNELS
},
.verify_signature = iwlcore_eeprom_verify_signature,
.acquire_semaphore = iwlcore_eeprom_acquire_semaphore,
@@ -1542,12 +1616,14 @@ static struct iwl_lib_ops iwl5150_lib = {
};
struct iwl_ops iwl5000_ops = {
+ .ucode = &iwl5000_ucode,
.lib = &iwl5000_lib,
.hcmd = &iwl5000_hcmd,
.utils = &iwl5000_hcmd_utils,
};
static struct iwl_ops iwl5150_ops = {
+ .ucode = &iwl5000_ucode,
.lib = &iwl5150_lib,
.hcmd = &iwl5000_hcmd,
.utils = &iwl5000_hcmd_utils,
@@ -1664,8 +1740,6 @@ MODULE_FIRMWARE(IWL5150_MODULE_FIRMWARE(IWL5150_UCODE_API_MAX));
module_param_named(swcrypto50, iwl50_mod_params.sw_crypto, bool, 0444);
MODULE_PARM_DESC(swcrypto50,
"using software crypto engine (default 0 [hardware])\n");
-module_param_named(debug50, iwl50_mod_params.debug, uint, 0444);
-MODULE_PARM_DESC(debug50, "50XX debug output mask");
module_param_named(queues_num50, iwl50_mod_params.num_of_queues, int, 0444);
MODULE_PARM_DESC(queues_num50, "number of hw queues in 50xx series");
module_param_named(11n_disable50, iwl50_mod_params.disable_11n, int, 0444);
diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c
index bd438d8acf5..c3ec6c20cc9 100644
--- a/drivers/net/wireless/iwlwifi/iwl-6000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-6000.c
@@ -46,8 +46,8 @@
#include "iwl-5000-hw.h"
/* Highest firmware API version supported */
-#define IWL6000_UCODE_API_MAX 2
-#define IWL6050_UCODE_API_MAX 2
+#define IWL6000_UCODE_API_MAX 3
+#define IWL6050_UCODE_API_MAX 3
/* Lowest firmware API version supported */
#define IWL6000_UCODE_API_MIN 1
@@ -61,6 +61,81 @@
#define _IWL6050_MODULE_FIRMWARE(api) IWL6050_FW_PRE #api ".ucode"
#define IWL6050_MODULE_FIRMWARE(api) _IWL6050_MODULE_FIRMWARE(api)
+static void iwl6000_set_ct_threshold(struct iwl_priv *priv)
+{
+ /* want Celsius */
+ priv->hw_params.ct_kill_threshold = CT_KILL_THRESHOLD;
+ priv->hw_params.ct_kill_exit_threshold = CT_KILL_EXIT_THRESHOLD;
+}
+
+/* NIC configuration for 6000 series */
+static void iwl6000_nic_config(struct iwl_priv *priv)
+{
+ iwl5000_nic_config(priv);
+
+ /* no locking required for register write */
+ if (priv->cfg->pa_type == IWL_PA_HYBRID) {
+ /* 2x2 hybrid phy type */
+ iwl_write32(priv, CSR_GP_DRIVER_REG,
+ CSR_GP_DRIVER_REG_BIT_RADIO_SKU_2x2_HYB);
+ } else if (priv->cfg->pa_type == IWL_PA_INTERNAL) {
+ /* 2x2 IPA phy type */
+ iwl_write32(priv, CSR_GP_DRIVER_REG,
+ CSR_GP_DRIVER_REG_BIT_RADIO_SKU_2x2_IPA);
+ }
+ /* else do nothing, uCode configured */
+}
+
+static struct iwl_lib_ops iwl6000_lib = {
+ .set_hw_params = iwl5000_hw_set_hw_params,
+ .txq_update_byte_cnt_tbl = iwl5000_txq_update_byte_cnt_tbl,
+ .txq_inval_byte_cnt_tbl = iwl5000_txq_inval_byte_cnt_tbl,
+ .txq_set_sched = iwl5000_txq_set_sched,
+ .txq_agg_enable = iwl5000_txq_agg_enable,
+ .txq_agg_disable = iwl5000_txq_agg_disable,
+ .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd,
+ .txq_free_tfd = iwl_hw_txq_free_tfd,
+ .txq_init = iwl_hw_tx_queue_init,
+ .rx_handler_setup = iwl5000_rx_handler_setup,
+ .setup_deferred_work = iwl5000_setup_deferred_work,
+ .is_valid_rtc_data_addr = iwl5000_hw_valid_rtc_data_addr,
+ .load_ucode = iwl5000_load_ucode,
+ .init_alive_start = iwl5000_init_alive_start,
+ .alive_notify = iwl5000_alive_notify,
+ .send_tx_power = iwl5000_send_tx_power,
+ .update_chain_flags = iwl_update_chain_flags,
+ .apm_ops = {
+ .init = iwl5000_apm_init,
+ .reset = iwl5000_apm_reset,
+ .stop = iwl5000_apm_stop,
+ .config = iwl6000_nic_config,
+ .set_pwr_src = iwl_set_pwr_src,
+ },
+ .eeprom_ops = {
+ .regulatory_bands = {
+ EEPROM_5000_REG_BAND_1_CHANNELS,
+ EEPROM_5000_REG_BAND_2_CHANNELS,
+ EEPROM_5000_REG_BAND_3_CHANNELS,
+ EEPROM_5000_REG_BAND_4_CHANNELS,
+ EEPROM_5000_REG_BAND_5_CHANNELS,
+ EEPROM_5000_REG_BAND_24_HT40_CHANNELS,
+ EEPROM_5000_REG_BAND_52_HT40_CHANNELS
+ },
+ .verify_signature = iwlcore_eeprom_verify_signature,
+ .acquire_semaphore = iwlcore_eeprom_acquire_semaphore,
+ .release_semaphore = iwlcore_eeprom_release_semaphore,
+ .calib_version = iwl5000_eeprom_calib_version,
+ .query_addr = iwl5000_eeprom_query_addr,
+ },
+ .post_associate = iwl_post_associate,
+ .isr = iwl_isr_ict,
+ .config_ap = iwl_config_ap,
+ .temp_ops = {
+ .temperature = iwl5000_temperature,
+ .set_ct_kill = iwl6000_set_ct_threshold,
+ },
+};
+
static struct iwl_hcmd_utils_ops iwl6000_hcmd_utils = {
.get_hcmd_size = iwl5000_get_hcmd_size,
.build_addsta_hcmd = iwl5000_build_addsta_hcmd,
@@ -69,28 +144,37 @@ static struct iwl_hcmd_utils_ops iwl6000_hcmd_utils = {
};
static struct iwl_ops iwl6000_ops = {
- .lib = &iwl5000_lib,
+ .ucode = &iwl5000_ucode,
+ .lib = &iwl6000_lib,
.hcmd = &iwl5000_hcmd,
.utils = &iwl6000_hcmd_utils,
};
-struct iwl_cfg iwl6000_2ag_cfg = {
- .name = "6000 Series 2x2 AG",
+
+/*
+ * "h": Hybrid configuration, use both internal and external Power Amplifier
+ */
+struct iwl_cfg iwl6000h_2agn_cfg = {
+ .name = "6000 Series 2x2 AGN",
.fw_name_pre = IWL6000_FW_PRE,
.ucode_api_max = IWL6000_UCODE_API_MAX,
.ucode_api_min = IWL6000_UCODE_API_MIN,
- .sku = IWL_SKU_A|IWL_SKU_G,
+ .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
.ops = &iwl6000_ops,
.eeprom_size = IWL_5000_EEPROM_IMG_SIZE,
.eeprom_ver = EEPROM_5000_EEPROM_VERSION,
.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
.mod_params = &iwl50_mod_params,
- .valid_tx_ant = ANT_BC,
- .valid_rx_ant = ANT_BC,
+ .valid_tx_ant = ANT_AB,
+ .valid_rx_ant = ANT_AB,
.need_pll_cfg = false,
+ .pa_type = IWL_PA_HYBRID,
};
-struct iwl_cfg iwl6000_2agn_cfg = {
+/*
+ * "i": Internal configuration, use internal Power Amplifier
+ */
+struct iwl_cfg iwl6000i_2agn_cfg = {
.name = "6000 Series 2x2 AGN",
.fw_name_pre = IWL6000_FW_PRE,
.ucode_api_max = IWL6000_UCODE_API_MAX,
@@ -101,9 +185,10 @@ struct iwl_cfg iwl6000_2agn_cfg = {
.eeprom_ver = EEPROM_5000_EEPROM_VERSION,
.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
.mod_params = &iwl50_mod_params,
- .valid_tx_ant = ANT_AB,
- .valid_rx_ant = ANT_AB,
+ .valid_tx_ant = ANT_BC,
+ .valid_rx_ant = ANT_BC,
.need_pll_cfg = false,
+ .pa_type = IWL_PA_INTERNAL,
};
struct iwl_cfg iwl6050_2agn_cfg = {
@@ -120,6 +205,7 @@ struct iwl_cfg iwl6050_2agn_cfg = {
.valid_tx_ant = ANT_AB,
.valid_rx_ant = ANT_AB,
.need_pll_cfg = false,
+ .pa_type = IWL_PA_SYSTEM,
};
struct iwl_cfg iwl6000_3agn_cfg = {
@@ -136,6 +222,7 @@ struct iwl_cfg iwl6000_3agn_cfg = {
.valid_tx_ant = ANT_ABC,
.valid_rx_ant = ANT_ABC,
.need_pll_cfg = false,
+ .pa_type = IWL_PA_SYSTEM,
};
struct iwl_cfg iwl6050_3agn_cfg = {
@@ -152,6 +239,7 @@ struct iwl_cfg iwl6050_3agn_cfg = {
.valid_tx_ant = ANT_ABC,
.valid_rx_ant = ANT_ABC,
.need_pll_cfg = false,
+ .pa_type = IWL_PA_SYSTEM,
};
MODULE_FIRMWARE(IWL6000_MODULE_FIRMWARE(IWL6000_UCODE_API_MAX));
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
index ff20e5048a5..21331552ff2 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
@@ -97,7 +97,7 @@ struct iwl_scale_tbl_info {
enum iwl_table_type lq_type;
u8 ant_type;
u8 is_SGI; /* 1 = short guard interval */
- u8 is_fat; /* 1 = 40 MHz channel width */
+ u8 is_ht40; /* 1 = 40 MHz channel width */
u8 is_dup; /* 1 = duplicated data streams */
u8 action; /* change modulation; IWL_[LEGACY/SISO/MIMO]_SWITCH_* */
u8 max_search; /* maximun number of tables we can search */
@@ -177,7 +177,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
struct sk_buff *skb,
struct ieee80211_sta *sta,
struct iwl_lq_sta *lq_sta);
-static void rs_fill_link_cmd(const struct iwl_priv *priv,
+static void rs_fill_link_cmd(struct iwl_priv *priv,
struct iwl_lq_sta *lq_sta, u32 rate_n_flags);
@@ -539,11 +539,11 @@ static u32 rate_n_flags_from_tbl(struct iwl_priv *priv,
RATE_MCS_ANT_ABC_MSK);
if (is_Ht(tbl->lq_type)) {
- if (tbl->is_fat) {
+ if (tbl->is_ht40) {
if (tbl->is_dup)
rate_n_flags |= RATE_MCS_DUP_MSK;
else
- rate_n_flags |= RATE_MCS_FAT_MSK;
+ rate_n_flags |= RATE_MCS_HT40_MSK;
}
if (tbl->is_SGI)
rate_n_flags |= RATE_MCS_SGI_MSK;
@@ -579,7 +579,7 @@ static int rs_get_tbl_info_from_mcs(const u32 rate_n_flags,
return -EINVAL;
}
tbl->is_SGI = 0; /* default legacy setup */
- tbl->is_fat = 0;
+ tbl->is_ht40 = 0;
tbl->is_dup = 0;
tbl->ant_type = (ant_msk >> RATE_MCS_ANT_POS);
tbl->lq_type = LQ_NONE;
@@ -598,9 +598,9 @@ static int rs_get_tbl_info_from_mcs(const u32 rate_n_flags,
if (rate_n_flags & RATE_MCS_SGI_MSK)
tbl->is_SGI = 1;
- if ((rate_n_flags & RATE_MCS_FAT_MSK) ||
+ if ((rate_n_flags & RATE_MCS_HT40_MSK) ||
(rate_n_flags & RATE_MCS_DUP_MSK))
- tbl->is_fat = 1;
+ tbl->is_ht40 = 1;
if (rate_n_flags & RATE_MCS_DUP_MSK)
tbl->is_dup = 1;
@@ -776,7 +776,7 @@ static u32 rs_get_lower_rate(struct iwl_lq_sta *lq_sta,
if (num_of_ant(tbl->ant_type) > 1)
tbl->ant_type = ANT_A;/*FIXME:RS*/
- tbl->is_fat = 0;
+ tbl->is_ht40 = 0;
tbl->is_SGI = 0;
tbl->max_search = IWL_MAX_SEARCH;
}
@@ -880,7 +880,7 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband,
if ((info->status.rates[0].idx < 0) ||
(tbl_type.is_SGI != !!(info->status.rates[0].flags & IEEE80211_TX_RC_SHORT_GI)) ||
- (tbl_type.is_fat != !!(info->status.rates[0].flags & IEEE80211_TX_RC_40_MHZ_WIDTH)) ||
+ (tbl_type.is_ht40 != !!(info->status.rates[0].flags & IEEE80211_TX_RC_40_MHZ_WIDTH)) ||
(tbl_type.is_dup != !!(info->status.rates[0].flags & IEEE80211_TX_RC_DUP_DATA)) ||
(tbl_type.ant_type != info->antenna_sel_tx) ||
(!!(tx_rate & RATE_MCS_HT_MSK) != !!(info->status.rates[0].flags & IEEE80211_TX_RC_MCS)) ||
@@ -1049,7 +1049,7 @@ static void rs_set_expected_tpt_table(struct iwl_lq_sta *lq_sta,
else
tbl->expected_tpt = expected_tpt_A;
} else if (is_siso(tbl->lq_type)) {
- if (tbl->is_fat && !lq_sta->is_dup)
+ if (tbl->is_ht40 && !lq_sta->is_dup)
if (tbl->is_SGI)
tbl->expected_tpt = expected_tpt_siso40MHzSGI;
else
@@ -1059,7 +1059,7 @@ static void rs_set_expected_tpt_table(struct iwl_lq_sta *lq_sta,
else
tbl->expected_tpt = expected_tpt_siso20MHz;
} else if (is_mimo2(tbl->lq_type)) {
- if (tbl->is_fat && !lq_sta->is_dup)
+ if (tbl->is_ht40 && !lq_sta->is_dup)
if (tbl->is_SGI)
tbl->expected_tpt = expected_tpt_mimo2_40MHzSGI;
else
@@ -1069,7 +1069,7 @@ static void rs_set_expected_tpt_table(struct iwl_lq_sta *lq_sta,
else
tbl->expected_tpt = expected_tpt_mimo2_20MHz;
} else if (is_mimo3(tbl->lq_type)) {
- if (tbl->is_fat && !lq_sta->is_dup)
+ if (tbl->is_ht40 && !lq_sta->is_dup)
if (tbl->is_SGI)
tbl->expected_tpt = expected_tpt_mimo3_40MHzSGI;
else
@@ -1217,13 +1217,13 @@ static int rs_switch_to_mimo2(struct iwl_priv *priv,
tbl->max_search = IWL_MAX_SEARCH;
rate_mask = lq_sta->active_mimo2_rate;
- if (iwl_is_fat_tx_allowed(priv, &sta->ht_cap))
- tbl->is_fat = 1;
+ if (iwl_is_ht40_tx_allowed(priv, &sta->ht_cap))
+ tbl->is_ht40 = 1;
else
- tbl->is_fat = 0;
+ tbl->is_ht40 = 0;
/* FIXME: - don't toggle SGI here
- if (tbl->is_fat) {
+ if (tbl->is_ht40) {
if (priv->current_ht_config.sgf & HT_SHORT_GI_40MHZ_ONLY)
tbl->is_SGI = 1;
else
@@ -1283,13 +1283,13 @@ static int rs_switch_to_mimo3(struct iwl_priv *priv,
tbl->max_search = IWL_MAX_11N_MIMO3_SEARCH;
rate_mask = lq_sta->active_mimo3_rate;
- if (iwl_is_fat_tx_allowed(priv, &sta->ht_cap))
- tbl->is_fat = 1;
+ if (iwl_is_ht40_tx_allowed(priv, &sta->ht_cap))
+ tbl->is_ht40 = 1;
else
- tbl->is_fat = 0;
+ tbl->is_ht40 = 0;
/* FIXME: - don't toggle SGI here
- if (tbl->is_fat) {
+ if (tbl->is_ht40) {
if (priv->current_ht_config.sgf & HT_SHORT_GI_40MHZ_ONLY)
tbl->is_SGI = 1;
else
@@ -1342,13 +1342,13 @@ static int rs_switch_to_siso(struct iwl_priv *priv,
tbl->max_search = IWL_MAX_SEARCH;
rate_mask = lq_sta->active_siso_rate;
- if (iwl_is_fat_tx_allowed(priv, &sta->ht_cap))
- tbl->is_fat = 1;
+ if (iwl_is_ht40_tx_allowed(priv, &sta->ht_cap))
+ tbl->is_ht40 = 1;
else
- tbl->is_fat = 0;
+ tbl->is_ht40 = 0;
/* FIXME: - don't toggle SGI here
- if (tbl->is_fat) {
+ if (tbl->is_ht40) {
if (priv->current_ht_config.sgf & HT_SHORT_GI_40MHZ_ONLY)
tbl->is_SGI = 1;
else
@@ -1398,6 +1398,12 @@ static int rs_move_legacy_other(struct iwl_priv *priv,
int ret = 0;
u8 update_search_tbl_counter = 0;
+ if (!iwl_ht_enabled(priv))
+ /* stay in Legacy */
+ tbl->action = IWL_LEGACY_SWITCH_ANTENNA1;
+ else if (iwl_tx_ant_restriction(priv) == IWL_ANT_OK_SINGLE &&
+ tbl->action > IWL_LEGACY_SWITCH_SISO)
+ tbl->action = IWL_LEGACY_SWITCH_SISO;
for (; ;) {
lq_sta->action_counter++;
switch (tbl->action) {
@@ -1529,6 +1535,11 @@ static int rs_move_siso_to_other(struct iwl_priv *priv,
u8 update_search_tbl_counter = 0;
int ret;
+ if (iwl_tx_ant_restriction(priv) == IWL_ANT_OK_SINGLE &&
+ tbl->action > IWL_SISO_SWITCH_ANTENNA2) {
+ /* stay in SISO */
+ tbl->action = IWL_SISO_SWITCH_ANTENNA1;
+ }
for (;;) {
lq_sta->action_counter++;
switch (tbl->action) {
@@ -1575,11 +1586,11 @@ static int rs_move_siso_to_other(struct iwl_priv *priv,
goto out;
break;
case IWL_SISO_SWITCH_GI:
- if (!tbl->is_fat &&
+ if (!tbl->is_ht40 &&
!(priv->current_ht_config.sgf &
HT_SHORT_GI_20MHZ))
break;
- if (tbl->is_fat &&
+ if (tbl->is_ht40 &&
!(priv->current_ht_config.sgf &
HT_SHORT_GI_40MHZ))
break;
@@ -1663,6 +1674,12 @@ static int rs_move_mimo2_to_other(struct iwl_priv *priv,
u8 update_search_tbl_counter = 0;
int ret;
+ if ((iwl_tx_ant_restriction(priv) == IWL_ANT_OK_SINGLE) &&
+ (tbl->action < IWL_MIMO2_SWITCH_SISO_A ||
+ tbl->action > IWL_MIMO2_SWITCH_SISO_C)) {
+ /* switch in SISO */
+ tbl->action = IWL_MIMO2_SWITCH_SISO_A;
+ }
for (;;) {
lq_sta->action_counter++;
switch (tbl->action) {
@@ -1709,11 +1726,11 @@ static int rs_move_mimo2_to_other(struct iwl_priv *priv,
break;
case IWL_MIMO2_SWITCH_GI:
- if (!tbl->is_fat &&
+ if (!tbl->is_ht40 &&
!(priv->current_ht_config.sgf &
HT_SHORT_GI_20MHZ))
break;
- if (tbl->is_fat &&
+ if (tbl->is_ht40 &&
!(priv->current_ht_config.sgf &
HT_SHORT_GI_40MHZ))
break;
@@ -1799,6 +1816,12 @@ static int rs_move_mimo3_to_other(struct iwl_priv *priv,
int ret;
u8 update_search_tbl_counter = 0;
+ if ((iwl_tx_ant_restriction(priv) == IWL_ANT_OK_SINGLE) &&
+ (tbl->action < IWL_MIMO3_SWITCH_SISO_A ||
+ tbl->action > IWL_MIMO3_SWITCH_SISO_C)) {
+ /* switch in SISO */
+ tbl->action = IWL_MIMO3_SWITCH_SISO_A;
+ }
for (;;) {
lq_sta->action_counter++;
switch (tbl->action) {
@@ -1867,11 +1890,11 @@ static int rs_move_mimo3_to_other(struct iwl_priv *priv,
break;
case IWL_MIMO3_SWITCH_GI:
- if (!tbl->is_fat &&
+ if (!tbl->is_ht40 &&
!(priv->current_ht_config.sgf &
HT_SHORT_GI_20MHZ))
break;
- if (tbl->is_fat &&
+ if (tbl->is_ht40 &&
!(priv->current_ht_config.sgf &
HT_SHORT_GI_40MHZ))
break;
@@ -2003,6 +2026,25 @@ static void rs_stay_in_table(struct iwl_lq_sta *lq_sta)
}
/*
+ * setup rate table in uCode
+ * return rate_n_flags as used in the table
+ */
+static u32 rs_update_rate_tbl(struct iwl_priv *priv,
+ struct iwl_lq_sta *lq_sta,
+ struct iwl_scale_tbl_info *tbl,
+ int index, u8 is_green)
+{
+ u32 rate;
+
+ /* Update uCode's rate table. */
+ rate = rate_n_flags_from_tbl(priv, tbl, index, is_green);
+ rs_fill_link_cmd(priv, lq_sta, rate);
+ iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC);
+
+ return rate;
+}
+
+/*
* Do rate scaling and search for new modulation mode.
*/
static void rs_rate_scale_perform(struct iwl_priv *priv,
@@ -2098,6 +2140,16 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
if (!((1 << index) & rate_scale_index_msk)) {
IWL_ERR(priv, "Current Rate is not valid\n");
+ if (lq_sta->search_better_tbl) {
+ /* revert to active table if search table is not valid*/
+ tbl->lq_type = LQ_NONE;
+ lq_sta->search_better_tbl = 0;
+ tbl = &(lq_sta->lq_info[lq_sta->active_tbl]);
+ /* get "active" rate info */
+ index = iwl_hwrate_to_plcp_idx(tbl->current_rate);
+ rate = rs_update_rate_tbl(priv, lq_sta,
+ tbl, index, is_green);
+ }
return;
}
@@ -2149,8 +2201,8 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
tbl->expected_tpt[index] + 64) / 128));
/* If we are searching for better modulation mode, check success. */
- if (lq_sta->search_better_tbl) {
-
+ if (lq_sta->search_better_tbl &&
+ (iwl_tx_ant_restriction(priv) == IWL_ANT_OK_MULTI)) {
/* If good success, continue using the "search" mode;
* no need to send new link quality command, since we're
* continuing to use the setup that we've been trying. */
@@ -2278,7 +2330,11 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
((sr > IWL_RATE_HIGH_TH) ||
(current_tpt > (100 * tbl->expected_tpt[low]))))
scale_action = 0;
-
+ if (!iwl_ht_enabled(priv) && !is_legacy(tbl->lq_type))
+ scale_action = -1;
+ if (iwl_tx_ant_restriction(priv) != IWL_ANT_OK_MULTI &&
+ (is_mimo2(tbl->lq_type) || is_mimo3(tbl->lq_type)))
+ scale_action = -1;
switch (scale_action) {
case -1:
/* Decrease starting rate, update uCode's rate table */
@@ -2308,15 +2364,15 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
lq_update:
/* Replace uCode's rate table for the destination station. */
- if (update_lq) {
- rate = rate_n_flags_from_tbl(priv, tbl, index, is_green);
- rs_fill_link_cmd(priv, lq_sta, rate);
- iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC);
- }
-
- /* Should we stay with this modulation mode, or search for a new one? */
- rs_stay_in_table(lq_sta);
+ if (update_lq)
+ rate = rs_update_rate_tbl(priv, lq_sta,
+ tbl, index, is_green);
+ if (iwl_tx_ant_restriction(priv) == IWL_ANT_OK_MULTI) {
+ /* Should we stay with this modulation mode,
+ * or search for a new one? */
+ rs_stay_in_table(lq_sta);
+ }
/*
* Search for new modulation mode if we're:
* 1) Not changing rates right now
@@ -2373,7 +2429,8 @@ lq_update:
* have been tried and compared, stay in this best modulation
* mode for a while before next round of mode comparisons. */
if (lq_sta->enable_counter &&
- (lq_sta->action_counter >= tbl1->max_search)) {
+ (lq_sta->action_counter >= tbl1->max_search) &&
+ iwl_ht_enabled(priv)) {
if ((lq_sta->last_tpt > IWL_AGG_TPT_THREHOLD) &&
(lq_sta->tx_agg_tid_en & (1 << tid)) &&
(tid != MAX_TID_COUNT)) {
@@ -2466,7 +2523,6 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, void *priv_sta,
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct iwl_lq_sta *lq_sta = priv_sta;
int rate_idx;
- u64 mask_bit = 0;
IWL_DEBUG_RATE_LIMIT(priv, "rate scale calculate new rate for skb\n");
@@ -2481,22 +2537,9 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, void *priv_sta,
lq_sta->max_rate_idx = -1;
}
- if (sta)
- mask_bit = sta->supp_rates[sband->band];
-
/* Send management frames and NO_ACK data using lowest rate. */
- if (!ieee80211_is_data(hdr->frame_control) ||
- info->flags & IEEE80211_TX_CTL_NO_ACK || !sta || !lq_sta) {
- if (!mask_bit)
- info->control.rates[0].idx =
- rate_lowest_index(sband, NULL);
- else
- info->control.rates[0].idx =
- rate_lowest_index(sband, sta);
- if (info->flags & IEEE80211_TX_CTL_NO_ACK)
- info->control.rates[0].count = 1;
+ if (rate_control_send_low(sta, priv_sta, txrc))
return;
- }
rate_idx = lq_sta->last_txrate_idx;
@@ -2533,7 +2576,7 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, void *priv_sta,
info->control.rates[0].flags |= IEEE80211_TX_RC_SHORT_GI;
if (lq_sta->last_rate_n_flags & RATE_MCS_DUP_MSK)
info->control.rates[0].flags |= IEEE80211_TX_RC_DUP_DATA;
- if (lq_sta->last_rate_n_flags & RATE_MCS_FAT_MSK)
+ if (lq_sta->last_rate_n_flags & RATE_MCS_HT40_MSK)
info->control.rates[0].flags |= IEEE80211_TX_RC_40_MHZ_WIDTH;
if (lq_sta->last_rate_n_flags & RATE_MCS_GF_MSK)
info->control.rates[0].flags |= IEEE80211_TX_RC_GREEN_FIELD;
@@ -2673,7 +2716,7 @@ static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband,
rs_initialize_lq(priv, conf, sta, lq_sta);
}
-static void rs_fill_link_cmd(const struct iwl_priv *priv,
+static void rs_fill_link_cmd(struct iwl_priv *priv,
struct iwl_lq_sta *lq_sta, u32 new_rate)
{
struct iwl_scale_tbl_info tbl_type;
@@ -2920,7 +2963,7 @@ static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file,
(is_siso(tbl->lq_type)) ? "SISO" :
((is_mimo2(tbl->lq_type)) ? "MIMO2" : "MIMO3"));
desc += sprintf(buff+desc, " %s",
- (tbl->is_fat) ? "40MHz" : "20MHz");
+ (tbl->is_ht40) ? "40MHz" : "20MHz");
desc += sprintf(buff+desc, " %s %s\n", (tbl->is_SGI) ? "SGI" : "",
(lq_sta->is_green) ? "GF enabled" : "");
}
@@ -2985,12 +3028,13 @@ static ssize_t rs_sta_dbgfs_stats_table_read(struct file *file,
return -ENOMEM;
for (i = 0; i < LQ_SIZE; i++) {
- desc += sprintf(buff+desc, "%s type=%d SGI=%d FAT=%d DUP=%d GF=%d\n"
+ desc += sprintf(buff+desc,
+ "%s type=%d SGI=%d HT40=%d DUP=%d GF=%d\n"
"rate=0x%X\n",
lq_sta->active_tbl == i ? "*" : "x",
lq_sta->lq_info[i].lq_type,
lq_sta->lq_info[i].is_SGI,
- lq_sta->lq_info[i].is_fat,
+ lq_sta->lq_info[i].is_ht40,
lq_sta->lq_info[i].is_dup,
lq_sta->is_green,
lq_sta->lq_info[i].current_rate);
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index 355f50ea7fe..2232b1794e7 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -171,7 +171,7 @@ int iwl_commit_rxon(struct iwl_priv *priv)
le16_to_cpu(priv->staging_rxon.channel),
priv->staging_rxon.bssid_addr);
- iwl_set_rxon_hwcrypto(priv, !priv->hw_params.sw_crypto);
+ iwl_set_rxon_hwcrypto(priv, !priv->cfg->mod_params->sw_crypto);
/* Apply the new configuration
* RXON unassoc clears the station table in uCode, send it before
@@ -442,8 +442,8 @@ void iwl_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq)
/* Unmap tx_cmd */
if (num_tbs)
pci_unmap_single(dev,
- pci_unmap_addr(&txq->cmd[index]->meta, mapping),
- pci_unmap_len(&txq->cmd[index]->meta, len),
+ pci_unmap_addr(&txq->meta[index], mapping),
+ pci_unmap_len(&txq->meta[index], len),
PCI_DMA_BIDIRECTIONAL);
/* Unmap chunks, if any. */
@@ -512,70 +512,6 @@ int iwl_hw_tx_queue_init(struct iwl_priv *priv,
return 0;
}
-
-/******************************************************************************
- *
- * Misc. internal state and helper functions
- *
- ******************************************************************************/
-
-#define MAX_UCODE_BEACON_INTERVAL 4096
-
-static u16 iwl_adjust_beacon_interval(u16 beacon_val)
-{
- u16 new_val = 0;
- u16 beacon_factor = 0;
-
- beacon_factor = (beacon_val + MAX_UCODE_BEACON_INTERVAL)
- / MAX_UCODE_BEACON_INTERVAL;
- new_val = beacon_val / beacon_factor;
-
- if (!new_val)
- new_val = MAX_UCODE_BEACON_INTERVAL;
-
- return new_val;
-}
-
-static void iwl_setup_rxon_timing(struct iwl_priv *priv)
-{
- u64 tsf;
- s32 interval_tm, rem;
- unsigned long flags;
- struct ieee80211_conf *conf = NULL;
- u16 beacon_int = 0;
-
- conf = ieee80211_get_hw_conf(priv->hw);
-
- spin_lock_irqsave(&priv->lock, flags);
- priv->rxon_timing.timestamp = cpu_to_le64(priv->timestamp);
- priv->rxon_timing.listen_interval = cpu_to_le16(conf->listen_interval);
-
- if (priv->iw_mode == NL80211_IFTYPE_STATION) {
- beacon_int = iwl_adjust_beacon_interval(priv->beacon_int);
- priv->rxon_timing.atim_window = 0;
- } else {
- beacon_int = iwl_adjust_beacon_interval(
- priv->vif->bss_conf.beacon_int);
-
- /* TODO: we need to get atim_window from upper stack
- * for now we set to 0 */
- priv->rxon_timing.atim_window = 0;
- }
-
- priv->rxon_timing.beacon_interval = cpu_to_le16(beacon_int);
-
- tsf = priv->timestamp; /* tsf is modifed by do_div: copy it */
- interval_tm = beacon_int * 1024;
- rem = do_div(tsf, interval_tm);
- priv->rxon_timing.beacon_init_val = cpu_to_le32(interval_tm - rem);
-
- spin_unlock_irqrestore(&priv->lock, flags);
- IWL_DEBUG_ASSOC(priv, "beacon interval %d beacon timer %d beacon tim %d\n",
- le16_to_cpu(priv->rxon_timing.beacon_interval),
- le32_to_cpu(priv->rxon_timing.beacon_init_val),
- le16_to_cpu(priv->rxon_timing.atim_window));
-}
-
/******************************************************************************
*
* Generic RX handler implementations
@@ -697,7 +633,6 @@ static void iwl_rx_card_state_notif(struct iwl_priv *priv,
struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
u32 flags = le32_to_cpu(pkt->u.card_state_notif.flags);
unsigned long status = priv->status;
- unsigned long reg_flags;
IWL_DEBUG_RF_KILL(priv, "Card state received: HW:%s SW:%s\n",
(flags & HW_CARD_DISABLED) ? "Kill" : "On",
@@ -717,19 +652,12 @@ static void iwl_rx_card_state_notif(struct iwl_priv *priv,
CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
iwl_write_direct32(priv, HBUS_TARG_MBX_C,
HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED);
-
- }
-
- if (flags & RF_CARD_DISABLED) {
- iwl_write32(priv, CSR_UCODE_DRV_GP1_SET,
- CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT);
- iwl_read32(priv, CSR_UCODE_DRV_GP1);
- spin_lock_irqsave(&priv->reg_lock, reg_flags);
- if (!iwl_grab_nic_access(priv))
- iwl_release_nic_access(priv);
- spin_unlock_irqrestore(&priv->reg_lock, reg_flags);
}
+ if (flags & RF_CARD_DISABLED)
+ iwl_tt_enter_ct_kill(priv);
}
+ if (!(flags & RF_CARD_DISABLED))
+ iwl_tt_exit_ct_kill(priv);
if (flags & HW_CARD_DISABLED)
set_bit(STATUS_RF_KILL_HW, &priv->status);
@@ -964,7 +892,7 @@ static void iwl_irq_tasklet_legacy(struct iwl_priv *priv)
iwl_write32(priv, CSR_FH_INT_STATUS, inta_fh);
#ifdef CONFIG_IWLWIFI_DEBUG
- if (priv->debug_level & IWL_DL_ISR) {
+ if (iwl_get_debug_level(priv) & IWL_DL_ISR) {
/* just for debug */
inta_mask = iwl_read32(priv, CSR_INT_MASK);
IWL_DEBUG_ISR(priv, "inta 0x%08x, enabled 0x%08x, fh 0x%08x\n",
@@ -983,7 +911,7 @@ static void iwl_irq_tasklet_legacy(struct iwl_priv *priv)
/* Now service all interrupt bits discovered above. */
if (inta & CSR_INT_BIT_HW_ERR) {
- IWL_ERR(priv, "Microcode HW error detected. Restarting.\n");
+ IWL_ERR(priv, "Hardware error detected. Restarting.\n");
/* Tell the device to stop sending interrupts */
iwl_disable_interrupts(priv);
@@ -999,7 +927,7 @@ static void iwl_irq_tasklet_legacy(struct iwl_priv *priv)
}
#ifdef CONFIG_IWLWIFI_DEBUG
- if (priv->debug_level & (IWL_DL_ISR)) {
+ if (iwl_get_debug_level(priv) & (IWL_DL_ISR)) {
/* NIC fires this, but we don't use it, redundant with WAKEUP */
if (inta & CSR_INT_BIT_SCD) {
IWL_DEBUG_ISR(priv, "Scheduler finished to transmit "
@@ -1024,7 +952,7 @@ static void iwl_irq_tasklet_legacy(struct iwl_priv *priv)
CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW))
hw_rf_kill = 1;
- IWL_DEBUG_RF_KILL(priv, "RF_KILL bit toggled to %s.\n",
+ IWL_WARN(priv, "RF_KILL bit toggled to %s.\n",
hw_rf_kill ? "disable radio" : "enable radio");
priv->isr_stats.rfkill++;
@@ -1113,7 +1041,7 @@ static void iwl_irq_tasklet_legacy(struct iwl_priv *priv)
iwl_enable_interrupts(priv);
#ifdef CONFIG_IWLWIFI_DEBUG
- if (priv->debug_level & (IWL_DL_ISR)) {
+ if (iwl_get_debug_level(priv) & (IWL_DL_ISR)) {
inta = iwl_read32(priv, CSR_INT);
inta_mask = iwl_read32(priv, CSR_INT_MASK);
inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS);
@@ -1144,7 +1072,7 @@ static void iwl_irq_tasklet(struct iwl_priv *priv)
inta = priv->inta;
#ifdef CONFIG_IWLWIFI_DEBUG
- if (priv->debug_level & IWL_DL_ISR) {
+ if (iwl_get_debug_level(priv) & IWL_DL_ISR) {
/* just for debug */
inta_mask = iwl_read32(priv, CSR_INT_MASK);
IWL_DEBUG_ISR(priv, "inta 0x%08x, enabled 0x%08x\n ",
@@ -1156,7 +1084,7 @@ static void iwl_irq_tasklet(struct iwl_priv *priv)
/* Now service all interrupt bits discovered above. */
if (inta & CSR_INT_BIT_HW_ERR) {
- IWL_ERR(priv, "Microcode HW error detected. Restarting.\n");
+ IWL_ERR(priv, "Hardware error detected. Restarting.\n");
/* Tell the device to stop sending interrupts */
iwl_disable_interrupts(priv);
@@ -1172,7 +1100,7 @@ static void iwl_irq_tasklet(struct iwl_priv *priv)
}
#ifdef CONFIG_IWLWIFI_DEBUG
- if (priv->debug_level & (IWL_DL_ISR)) {
+ if (iwl_get_debug_level(priv) & (IWL_DL_ISR)) {
/* NIC fires this, but we don't use it, redundant with WAKEUP */
if (inta & CSR_INT_BIT_SCD) {
IWL_DEBUG_ISR(priv, "Scheduler finished to transmit "
@@ -1197,7 +1125,7 @@ static void iwl_irq_tasklet(struct iwl_priv *priv)
CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW))
hw_rf_kill = 1;
- IWL_DEBUG_RF_KILL(priv, "RF_KILL bit toggled to %s.\n",
+ IWL_WARN(priv, "RF_KILL bit toggled to %s.\n",
hw_rf_kill ? "disable radio" : "enable radio");
priv->isr_stats.rfkill++;
@@ -1348,7 +1276,7 @@ static void iwl_nic_start(struct iwl_priv *priv)
*/
static int iwl_read_ucode(struct iwl_priv *priv)
{
- struct iwl_ucode *ucode;
+ struct iwl_ucode_header *ucode;
int ret = -EINVAL, index;
const struct firmware *ucode_raw;
const char *name_pre = priv->cfg->fw_name_pre;
@@ -1357,7 +1285,9 @@ static int iwl_read_ucode(struct iwl_priv *priv)
char buf[25];
u8 *src;
size_t len;
- u32 api_ver, inst_size, data_size, init_size, init_data_size, boot_size;
+ u32 api_ver, build;
+ u32 inst_size, data_size, init_size, init_data_size, boot_size;
+ u16 eeprom_ver;
/* Ask kernel firmware_class module to get the boot firmware off disk.
* request_firmware() is synchronous, file is in memory on return. */
@@ -1387,23 +1317,26 @@ static int iwl_read_ucode(struct iwl_priv *priv)
if (ret < 0)
goto error;
- /* Make sure that we got at least our header! */
- if (ucode_raw->size < sizeof(*ucode)) {
+ /* Make sure that we got at least the v1 header! */
+ if (ucode_raw->size < priv->cfg->ops->ucode->get_header_size(1)) {
IWL_ERR(priv, "File size way too small!\n");
ret = -EINVAL;
goto err_release;
}
/* Data from ucode file: header followed by uCode images */
- ucode = (void *)ucode_raw->data;
+ ucode = (struct iwl_ucode_header *)ucode_raw->data;
priv->ucode_ver = le32_to_cpu(ucode->ver);
api_ver = IWL_UCODE_API(priv->ucode_ver);
- inst_size = le32_to_cpu(ucode->inst_size);
- data_size = le32_to_cpu(ucode->data_size);
- init_size = le32_to_cpu(ucode->init_size);
- init_data_size = le32_to_cpu(ucode->init_data_size);
- boot_size = le32_to_cpu(ucode->boot_size);
+ build = priv->cfg->ops->ucode->get_build(ucode, api_ver);
+ inst_size = priv->cfg->ops->ucode->get_inst_size(ucode, api_ver);
+ data_size = priv->cfg->ops->ucode->get_data_size(ucode, api_ver);
+ init_size = priv->cfg->ops->ucode->get_init_size(ucode, api_ver);
+ init_data_size =
+ priv->cfg->ops->ucode->get_init_data_size(ucode, api_ver);
+ boot_size = priv->cfg->ops->ucode->get_boot_size(ucode, api_ver);
+ src = priv->cfg->ops->ucode->get_data(ucode, api_ver);
/* api_ver should match the api version forming part of the
* firmware filename ... but we don't check for that and only rely
@@ -1429,6 +1362,14 @@ static int iwl_read_ucode(struct iwl_priv *priv)
IWL_UCODE_API(priv->ucode_ver),
IWL_UCODE_SERIAL(priv->ucode_ver));
+ if (build)
+ IWL_DEBUG_INFO(priv, "Build %u\n", build);
+
+ eeprom_ver = iwl_eeprom_query16(priv, EEPROM_VERSION);
+ IWL_DEBUG_INFO(priv, "NVM Type: %s, version: 0x%x\n",
+ (priv->nvm_device_type == NVM_DEVICE_TYPE_OTP)
+ ? "OTP" : "EEPROM", eeprom_ver);
+
IWL_DEBUG_INFO(priv, "f/w package hdr ucode version raw = 0x%x\n",
priv->ucode_ver);
IWL_DEBUG_INFO(priv, "f/w package hdr runtime inst size = %u\n",
@@ -1443,12 +1384,14 @@ static int iwl_read_ucode(struct iwl_priv *priv)
boot_size);
/* Verify size of file vs. image size info in file's header */
- if (ucode_raw->size < sizeof(*ucode) +
+ if (ucode_raw->size !=
+ priv->cfg->ops->ucode->get_header_size(api_ver) +
inst_size + data_size + init_size +
init_data_size + boot_size) {
- IWL_DEBUG_INFO(priv, "uCode file size %d too small\n",
- (int)ucode_raw->size);
+ IWL_DEBUG_INFO(priv,
+ "uCode file size %d does not match expected size\n",
+ (int)ucode_raw->size);
ret = -EINVAL;
goto err_release;
}
@@ -1528,42 +1471,42 @@ static int iwl_read_ucode(struct iwl_priv *priv)
/* Copy images into buffers for card's bus-master reads ... */
/* Runtime instructions (first block of data in file) */
- src = &ucode->data[0];
- len = priv->ucode_code.len;
+ len = inst_size;
IWL_DEBUG_INFO(priv, "Copying (but not loading) uCode instr len %Zd\n", len);
memcpy(priv->ucode_code.v_addr, src, len);
+ src += len;
+
IWL_DEBUG_INFO(priv, "uCode instr buf vaddr = 0x%p, paddr = 0x%08x\n",
priv->ucode_code.v_addr, (u32)priv->ucode_code.p_addr);
/* Runtime data (2nd block)
* NOTE: Copy into backup buffer will be done in iwl_up() */
- src = &ucode->data[inst_size];
- len = priv->ucode_data.len;
+ len = data_size;
IWL_DEBUG_INFO(priv, "Copying (but not loading) uCode data len %Zd\n", len);
memcpy(priv->ucode_data.v_addr, src, len);
memcpy(priv->ucode_data_backup.v_addr, src, len);
+ src += len;
/* Initialization instructions (3rd block) */
if (init_size) {
- src = &ucode->data[inst_size + data_size];
- len = priv->ucode_init.len;
+ len = init_size;
IWL_DEBUG_INFO(priv, "Copying (but not loading) init instr len %Zd\n",
len);
memcpy(priv->ucode_init.v_addr, src, len);
+ src += len;
}
/* Initialization data (4th block) */
if (init_data_size) {
- src = &ucode->data[inst_size + data_size + init_size];
- len = priv->ucode_init_data.len;
+ len = init_data_size;
IWL_DEBUG_INFO(priv, "Copying (but not loading) init data len %Zd\n",
len);
memcpy(priv->ucode_init_data.v_addr, src, len);
+ src += len;
}
/* Bootstrap instructions (5th block) */
- src = &ucode->data[inst_size + data_size + init_size + init_data_size];
- len = priv->ucode_boot.len;
+ len = boot_size;
IWL_DEBUG_INFO(priv, "Copying (but not loading) boot instr len %Zd\n", len);
memcpy(priv->ucode_boot.v_addr, src, len);
@@ -1663,7 +1606,7 @@ static void iwl_alive_start(struct iwl_priv *priv)
set_bit(STATUS_READY, &priv->status);
wake_up_interruptible(&priv->wait_command_queue);
- iwl_power_update_mode(priv, 1);
+ iwl_power_update_mode(priv, true);
/* reassociate for ADHOC mode */
if (priv->vif && (priv->iw_mode == NL80211_IFTYPE_ADHOC)) {
@@ -1812,6 +1755,11 @@ static int iwl_prepare_card_hw(struct iwl_priv *priv)
IWL_DEBUG_INFO(priv, "iwl_prepare_card_hw enter \n");
+ ret = iwl_set_hw_ready(priv);
+ if (priv->hw_ready)
+ return ret;
+
+ /* If HW is not ready, prepare the conditions to check again */
iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
CSR_HW_IF_CONFIG_REG_PREPARE);
@@ -1819,6 +1767,7 @@ static int iwl_prepare_card_hw(struct iwl_priv *priv)
~CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE,
CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE, 150000);
+ /* HW should be ready by now, check again. */
if (ret != -ETIMEDOUT)
iwl_set_hw_ready(priv);
@@ -2126,7 +2075,7 @@ void iwl_post_associate(struct iwl_priv *priv)
* If chain noise has already been run, then we need to enable
* power management here */
if (priv->chain_noise_data.state == IWL_CHAIN_NOISE_DONE)
- iwl_power_update_mode(priv, 0);
+ iwl_power_update_mode(priv, false);
/* Enable Rx differential gain and sensitivity calibrations */
iwl_chain_noise_reset(priv);
@@ -2331,7 +2280,7 @@ static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
IWL_DEBUG_MAC80211(priv, "enter\n");
- if (priv->hw_params.sw_crypto) {
+ if (priv->cfg->mod_params->sw_crypto) {
IWL_DEBUG_MAC80211(priv, "leave - hwcrypto disabled\n");
return -EOPNOTSUPP;
}
@@ -2455,14 +2404,16 @@ static int iwl_mac_get_stats(struct ieee80211_hw *hw,
* used for controlling the debug level.
*
* See the level definitions in iwl for details.
+ *
+ * The debug_level being managed using sysfs below is a per device debug
+ * level that is used instead of the global debug level if it (the per
+ * device debug level) is set.
*/
-
static ssize_t show_debug_level(struct device *d,
struct device_attribute *attr, char *buf)
{
struct iwl_priv *priv = dev_get_drvdata(d);
-
- return sprintf(buf, "0x%08X\n", priv->debug_level);
+ return sprintf(buf, "0x%08X\n", iwl_get_debug_level(priv));
}
static ssize_t store_debug_level(struct device *d,
struct device_attribute *attr,
@@ -2475,9 +2426,12 @@ static ssize_t store_debug_level(struct device *d,
ret = strict_strtoul(buf, 0, &val);
if (ret)
IWL_ERR(priv, "%s is not in hex or decimal form.\n", buf);
- else
+ else {
priv->debug_level = val;
-
+ if (iwl_alloc_traffic_mem(priv))
+ IWL_ERR(priv,
+ "Not enough memory to generate traffic log\n");
+ }
return strnlen(buf, count);
}
@@ -2488,39 +2442,6 @@ static DEVICE_ATTR(debug_level, S_IWUSR | S_IRUGO,
#endif /* CONFIG_IWLWIFI_DEBUG */
-static ssize_t show_version(struct device *d,
- struct device_attribute *attr, char *buf)
-{
- struct iwl_priv *priv = dev_get_drvdata(d);
- struct iwl_alive_resp *palive = &priv->card_alive;
- ssize_t pos = 0;
- u16 eeprom_ver;
-
- if (palive->is_valid)
- pos += sprintf(buf + pos,
- "fw version: 0x%01X.0x%01X.0x%01X.0x%01X\n"
- "fw type: 0x%01X 0x%01X\n",
- palive->ucode_major, palive->ucode_minor,
- palive->sw_rev[0], palive->sw_rev[1],
- palive->ver_type, palive->ver_subtype);
- else
- pos += sprintf(buf + pos, "fw not loaded\n");
-
- if (priv->eeprom) {
- eeprom_ver = iwl_eeprom_query16(priv, EEPROM_VERSION);
- pos += sprintf(buf + pos, "NVM Type: %s, version: 0x%x\n",
- (priv->nvm_device_type == NVM_DEVICE_TYPE_OTP)
- ? "OTP" : "EEPROM", eeprom_ver);
-
- } else {
- pos += sprintf(buf + pos, "EEPROM not initialzed\n");
- }
-
- return pos;
-}
-
-static DEVICE_ATTR(version, S_IWUSR | S_IRUGO, show_version, NULL);
-
static ssize_t show_temperature(struct device *d,
struct device_attribute *attr, char *buf)
{
@@ -2644,67 +2565,6 @@ static ssize_t store_filter_flags(struct device *d,
static DEVICE_ATTR(filter_flags, S_IWUSR | S_IRUGO, show_filter_flags,
store_filter_flags);
-static ssize_t store_power_level(struct device *d,
- struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct iwl_priv *priv = dev_get_drvdata(d);
- int ret;
- unsigned long mode;
-
-
- mutex_lock(&priv->mutex);
-
- ret = strict_strtoul(buf, 10, &mode);
- if (ret)
- goto out;
-
- ret = iwl_power_set_user_mode(priv, mode);
- if (ret) {
- IWL_DEBUG_MAC80211(priv, "failed setting power mode.\n");
- goto out;
- }
- ret = count;
-
- out:
- mutex_unlock(&priv->mutex);
- return ret;
-}
-
-static ssize_t show_power_level(struct device *d,
- struct device_attribute *attr, char *buf)
-{
- struct iwl_priv *priv = dev_get_drvdata(d);
- int level = priv->power_data.power_mode;
- char *p = buf;
-
- p += sprintf(p, "%d\n", level);
- return p - buf + 1;
-}
-
-static DEVICE_ATTR(power_level, S_IWUSR | S_IRUSR, show_power_level,
- store_power_level);
-
-static ssize_t show_qos(struct device *d,
- struct device_attribute *attr, char *buf)
-{
- struct iwl_priv *priv = dev_get_drvdata(d);
- char *p = buf;
- int q;
-
- for (q = 0; q < AC_NUM; q++) {
- p += sprintf(p, "\tcw_min\tcw_max\taifsn\ttxop\n");
- p += sprintf(p, "AC[%d]\t%u\t%u\t%u\t%u\n", q,
- priv->qos_data.def_qos_parm.ac[q].cw_min,
- priv->qos_data.def_qos_parm.ac[q].cw_max,
- priv->qos_data.def_qos_parm.ac[q].aifsn,
- priv->qos_data.def_qos_parm.ac[q].edca_txop);
- }
-
- return p - buf + 1;
-}
-
-static DEVICE_ATTR(qos, S_IRUGO, show_qos, NULL);
static ssize_t show_statistics(struct device *d,
struct device_attribute *attr, char *buf)
@@ -2797,15 +2657,12 @@ static void iwl_cancel_deferred_work(struct iwl_priv *priv)
static struct attribute *iwl_sysfs_entries[] = {
&dev_attr_flags.attr,
&dev_attr_filter_flags.attr,
- &dev_attr_power_level.attr,
&dev_attr_statistics.attr,
&dev_attr_temperature.attr,
&dev_attr_tx_power.attr,
#ifdef CONFIG_IWLWIFI_DEBUG
&dev_attr_debug_level.attr,
#endif
- &dev_attr_version.attr,
- &dev_attr_qos.attr,
NULL
};
@@ -2849,7 +2706,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
/* Disabling hardware scan means that mac80211 will perform scans
* "the hard way", rather than using device's scan. */
if (cfg->mod_params->disable_hw_scan) {
- if (cfg->mod_params->debug & IWL_DL_INFO)
+ if (iwl_debug_level & IWL_DL_INFO)
dev_printk(KERN_DEBUG, &(pdev->dev),
"Disabling hw_scan\n");
iwl_hw_ops.hw_scan = NULL;
@@ -2871,9 +2728,10 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
priv->inta_mask = CSR_INI_SET_MASK;
#ifdef CONFIG_IWLWIFI_DEBUG
- priv->debug_level = priv->cfg->mod_params->debug;
atomic_set(&priv->restrict_refcnt, 0);
#endif
+ if (iwl_alloc_traffic_mem(priv))
+ IWL_ERR(priv, "Not enough memory to generate traffic log\n");
/**************************
* 2. Initializing PCI bus
@@ -3034,6 +2892,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
test_bit(STATUS_RF_KILL_HW, &priv->status));
iwl_power_initialize(priv);
+ iwl_tt_initialize(priv);
return 0;
out_remove_sysfs:
@@ -3057,6 +2916,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
pci_disable_device(pdev);
out_ieee80211_free_hw:
ieee80211_free_hw(priv->hw);
+ iwl_free_traffic_mem(priv);
out:
return err;
}
@@ -3086,6 +2946,8 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev)
iwl_down(priv);
}
+ iwl_tt_exit(priv);
+
/* make sure we flush any pending irq or
* tasklet for the driver
*/
@@ -3113,6 +2975,7 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev)
* until now... */
destroy_workqueue(priv->workqueue);
priv->workqueue = NULL;
+ iwl_free_traffic_mem(priv);
free_irq(priv->pci_dev->irq, priv);
pci_disable_msi(priv->pci_dev);
@@ -3163,15 +3026,12 @@ static struct pci_device_id iwl_hw_card_ids[] = {
{IWL_PCI_DEVICE(0x423C, PCI_ANY_ID, iwl5150_agn_cfg)},
{IWL_PCI_DEVICE(0x423D, PCI_ANY_ID, iwl5150_agn_cfg)},
/* 6000/6050 Series */
- {IWL_PCI_DEVICE(0x0082, 0x1102, iwl6000_2ag_cfg)},
- {IWL_PCI_DEVICE(0x0085, 0x1112, iwl6000_2ag_cfg)},
- {IWL_PCI_DEVICE(0x0082, 0x1122, iwl6000_2ag_cfg)},
+ {IWL_PCI_DEVICE(0x008D, PCI_ANY_ID, iwl6000h_2agn_cfg)},
+ {IWL_PCI_DEVICE(0x008E, PCI_ANY_ID, iwl6000h_2agn_cfg)},
{IWL_PCI_DEVICE(0x422B, PCI_ANY_ID, iwl6000_3agn_cfg)},
- {IWL_PCI_DEVICE(0x422C, PCI_ANY_ID, iwl6000_2agn_cfg)},
+ {IWL_PCI_DEVICE(0x422C, PCI_ANY_ID, iwl6000i_2agn_cfg)},
{IWL_PCI_DEVICE(0x4238, PCI_ANY_ID, iwl6000_3agn_cfg)},
- {IWL_PCI_DEVICE(0x4239, PCI_ANY_ID, iwl6000_2agn_cfg)},
- {IWL_PCI_DEVICE(0x0082, PCI_ANY_ID, iwl6000_2agn_cfg)},
- {IWL_PCI_DEVICE(0x0085, PCI_ANY_ID, iwl6000_3agn_cfg)},
+ {IWL_PCI_DEVICE(0x4239, PCI_ANY_ID, iwl6000i_2agn_cfg)},
{IWL_PCI_DEVICE(0x0086, PCI_ANY_ID, iwl6050_3agn_cfg)},
{IWL_PCI_DEVICE(0x0087, PCI_ANY_ID, iwl6050_2agn_cfg)},
{IWL_PCI_DEVICE(0x0088, PCI_ANY_ID, iwl6050_3agn_cfg)},
@@ -3231,3 +3091,11 @@ static void __exit iwl_exit(void)
module_exit(iwl_exit);
module_init(iwl_init);
+
+#ifdef CONFIG_IWLWIFI_DEBUG
+module_param_named(debug50, iwl_debug_level, uint, 0444);
+MODULE_PARM_DESC(debug50, "50XX debug output mask (deprecated)");
+module_param_named(debug, iwl_debug_level, uint, 0644);
+MODULE_PARM_DESC(debug, "debug output mask");
+#endif
+
diff --git a/drivers/net/wireless/iwlwifi/iwl-calib.c b/drivers/net/wireless/iwlwifi/iwl-calib.c
index a5d63672ad3..c4b565a2de9 100644
--- a/drivers/net/wireless/iwlwifi/iwl-calib.c
+++ b/drivers/net/wireless/iwlwifi/iwl-calib.c
@@ -86,7 +86,7 @@ int iwl_send_calib_results(struct iwl_priv *priv)
struct iwl_host_cmd hcmd = {
.id = REPLY_PHY_CALIBRATION_CMD,
- .meta.flags = CMD_SIZE_HUGE,
+ .flags = CMD_SIZE_HUGE,
};
for (i = 0; i < IWL_CALIB_MAX; i++) {
@@ -251,12 +251,7 @@ static int iwl_sens_energy_cck(struct iwl_priv *priv,
/* increase energy threshold (reduce nrg value)
* to decrease sensitivity */
- if (data->nrg_th_cck >
- (ranges->max_nrg_cck + NRG_STEP_CCK))
- data->nrg_th_cck = data->nrg_th_cck
- - NRG_STEP_CCK;
- else
- data->nrg_th_cck = ranges->max_nrg_cck;
+ data->nrg_th_cck = data->nrg_th_cck - NRG_STEP_CCK;
/* Else if we got fewer than desired, increase sensitivity */
} else if (false_alarms < min_false_alarms) {
data->nrg_curr_state = IWL_FA_TOO_FEW;
@@ -424,7 +419,7 @@ static int iwl_sensitivity_write(struct iwl_priv *priv)
struct iwl_host_cmd cmd_out = {
.id = SENSITIVITY_CMD,
.len = sizeof(struct iwl_sensitivity_cmd),
- .meta.flags = CMD_ASYNC,
+ .flags = CMD_ASYNC,
.data = &cmd,
};
@@ -857,7 +852,7 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv,
priv->cfg->ops->lib->update_chain_flags(priv);
data->state = IWL_CHAIN_NOISE_DONE;
- iwl_power_update_mode(priv, 0);
+ iwl_power_update_mode(priv, false);
}
EXPORT_SYMBOL(iwl_chain_noise_calibration);
diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h
index c87033bf3ad..68d7719071f 100644
--- a/drivers/net/wireless/iwlwifi/iwl-commands.h
+++ b/drivers/net/wireless/iwlwifi/iwl-commands.h
@@ -283,7 +283,7 @@ struct iwl3945_power_per_rate {
* 1) Dual stream (MIMO)
* 2) Triple stream (MIMO)
*
- * 5: Value of 0x20 in bits 7:0 indicates 6 Mbps FAT duplicate data
+ * 5: Value of 0x20 in bits 7:0 indicates 6 Mbps HT40 duplicate data
*
* Legacy OFDM rate format for bits 7:0 (bit 8 must be "0", bit 9 "0"):
* 3-0: 0xD) 6 Mbps
@@ -320,11 +320,11 @@ struct iwl3945_power_per_rate {
#define RATE_MCS_GF_POS 10
#define RATE_MCS_GF_MSK 0x400
-/* Bit 11: (1) Use 40Mhz FAT chnl width, (0) use 20 MHz legacy chnl width */
-#define RATE_MCS_FAT_POS 11
-#define RATE_MCS_FAT_MSK 0x800
+/* Bit 11: (1) Use 40Mhz HT40 chnl width, (0) use 20 MHz legacy chnl width */
+#define RATE_MCS_HT40_POS 11
+#define RATE_MCS_HT40_MSK 0x800
-/* Bit 12: (1) Duplicate data on both 20MHz chnls. FAT (bit 11) must be set. */
+/* Bit 12: (1) Duplicate data on both 20MHz chnls. HT40 (bit 11) must be set. */
#define RATE_MCS_DUP_POS 12
#define RATE_MCS_DUP_MSK 0x1000
@@ -459,7 +459,7 @@ struct iwl_init_alive_resp {
/* calibration values from "initialize" uCode */
__le32 voltage; /* signed, higher value is lower voltage */
- __le32 therm_r1[2]; /* signed, 1st for normal, 2nd for FAT channel*/
+ __le32 therm_r1[2]; /* signed, 1st for normal, 2nd for HT40 */
__le32 therm_r2[2]; /* signed */
__le32 therm_r3[2]; /* signed */
__le32 therm_r4[2]; /* signed */
@@ -610,7 +610,7 @@ enum {
#define RXON_FLG_HT_OPERATING_MODE_POS (23)
#define RXON_FLG_HT_PROT_MSK cpu_to_le32(0x1 << 23)
-#define RXON_FLG_FAT_PROT_MSK cpu_to_le32(0x2 << 23)
+#define RXON_FLG_HT40_PROT_MSK cpu_to_le32(0x2 << 23)
#define RXON_FLG_CHANNEL_MODE_POS (25)
#define RXON_FLG_CHANNEL_MODE_MSK cpu_to_le32(0x3 << 25)
@@ -765,6 +765,8 @@ struct iwl5000_rxon_assoc_cmd {
} __attribute__ ((packed));
#define IWL_CONN_MAX_LISTEN_INTERVAL 10
+#define IWL_MAX_UCODE_BEACON_INTERVAL 4 /* 4096 */
+#define IWL39_MAX_UCODE_BEACON_INTERVAL 1 /* 1024 */
/*
* REPLY_RXON_TIMING = 0x14 (command, has simple generic response)
@@ -889,7 +891,7 @@ struct iwl_qosparam_cmd {
#define STA_FLG_AGG_MPDU_8US_MSK cpu_to_le32(1 << 18)
#define STA_FLG_MAX_AGG_SIZE_POS (19)
#define STA_FLG_MAX_AGG_SIZE_MSK cpu_to_le32(3 << 19)
-#define STA_FLG_FAT_EN_MSK cpu_to_le32(1 << 21)
+#define STA_FLG_HT40_EN_MSK cpu_to_le32(1 << 21)
#define STA_FLG_MIMO_DIS_MSK cpu_to_le32(1 << 22)
#define STA_FLG_AGG_MPDU_DENSITY_POS (23)
#define STA_FLG_AGG_MPDU_DENSITY_MSK cpu_to_le32(7 << 23)
@@ -1922,7 +1924,7 @@ struct iwl_link_qual_general_params {
#define LINK_QUAL_AGG_DISABLE_START_MIN (0)
#define LINK_QUAL_AGG_FRAME_LIMIT_DEF (31)
-#define LINK_QUAL_AGG_FRAME_LIMIT_MAX (64)
+#define LINK_QUAL_AGG_FRAME_LIMIT_MAX (63)
#define LINK_QUAL_AGG_FRAME_LIMIT_MIN (0)
/**
@@ -1982,10 +1984,10 @@ struct iwl_link_qual_agg_params {
* a) Use this same initial rate for first 3 entries.
* b) Find next lower available rate using same mode (SISO or MIMO),
* use for next 3 entries. If no lower rate available, switch to
- * legacy mode (no FAT channel, no MIMO, no short guard interval).
+ * legacy mode (no HT40 channel, no MIMO, no short guard interval).
* c) If using MIMO, set command's mimo_delimiter to number of entries
* using MIMO (3 or 6).
- * d) After trying 2 HT rates, switch to legacy mode (no FAT channel,
+ * d) After trying 2 HT rates, switch to legacy mode (no HT40 channel,
* no MIMO, no short guard interval), at the next lower bit rate
* (e.g. if second HT bit rate was 54, try 48 legacy), and follow
* legacy procedure for remaining table entries.
@@ -2311,15 +2313,22 @@ struct iwl_spectrum_notification {
* PM allow:
* bit 0 - '0' Driver not allow power management
* '1' Driver allow PM (use rest of parameters)
+ *
* uCode send sleep notifications:
* bit 1 - '0' Don't send sleep notification
* '1' send sleep notification (SEND_PM_NOTIFICATION)
+ *
* Sleep over DTIM
* bit 2 - '0' PM have to walk up every DTIM
* '1' PM could sleep over DTIM till listen Interval.
+ *
* PCI power managed
* bit 3 - '0' (PCI_CFG_LINK_CTRL & 0x1)
* '1' !(PCI_CFG_LINK_CTRL & 0x1)
+ *
+ * Fast PD
+ * bit 4 - '1' Put radio to sleep when receiving frame for others
+ *
* Force sleep Modes
* bit 31/30- '00' use both mac/xtal sleeps
* '01' force Mac sleep
@@ -2411,6 +2420,13 @@ struct iwl_ct_kill_config {
__le32 critical_temperature_R;
} __attribute__ ((packed));
+/* 1000, and 6x00 */
+struct iwl_ct_kill_throttling_config {
+ __le32 critical_temperature_exit;
+ __le32 reserved;
+ __le32 critical_temperature_enter;
+} __attribute__ ((packed));
+
/******************************************************************************
* (8)
* Scan Commands, Responses, Notifications:
@@ -3008,7 +3024,7 @@ struct iwl_statistics_cmd {
* one channel that has just been scanned.
*/
#define STATISTICS_REPLY_FLG_BAND_24G_MSK cpu_to_le32(0x2)
-#define STATISTICS_REPLY_FLG_FAT_MODE_MSK cpu_to_le32(0x8)
+#define STATISTICS_REPLY_FLG_HT40_MODE_MSK cpu_to_le32(0x8)
struct iwl3945_notif_statistics {
__le32 flag;
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index 18b135f510e..af735128333 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -59,6 +59,9 @@ MODULE_LICENSE("GPL");
IWL_RATE_##pp##M_INDEX, \
IWL_RATE_##np##M_INDEX }
+u32 iwl_debug_level;
+EXPORT_SYMBOL(iwl_debug_level);
+
static irqreturn_t iwl_isr(int irq, void *data);
/*
@@ -102,7 +105,7 @@ void iwl_hwrate_to_tx_control(struct iwl_priv *priv, u32 rate_n_flags,
r->flags |= IEEE80211_TX_RC_MCS;
if (rate_n_flags & RATE_MCS_GF_MSK)
r->flags |= IEEE80211_TX_RC_GREEN_FIELD;
- if (rate_n_flags & RATE_MCS_FAT_MSK)
+ if (rate_n_flags & RATE_MCS_HT40_MSK)
r->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH;
if (rate_n_flags & RATE_MCS_DUP_MSK)
r->flags |= IEEE80211_TX_RC_DUP_DATA;
@@ -397,7 +400,7 @@ static void iwlcore_init_ht_hw_capab(const struct iwl_priv *priv,
(WLAN_HT_CAP_SM_PS_DISABLED << 2));
max_bit_rate = MAX_BIT_RATE_20_MHZ;
- if (priv->hw_params.fat_channel & BIT(band)) {
+ if (priv->hw_params.ht40_channel & BIT(band)) {
ht_info->cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40;
ht_info->cap |= IEEE80211_HT_CAP_SGI_40;
ht_info->mcs.rx_mask[4] = 0x01;
@@ -537,7 +540,7 @@ int iwlcore_init_geos(struct iwl_priv *priv)
if (ch->flags & EEPROM_CHANNEL_RADAR)
geo_ch->flags |= IEEE80211_CHAN_RADAR;
- geo_ch->flags |= ch->fat_extension_channel;
+ geo_ch->flags |= ch->ht40_extension_channel;
if (ch->max_power_avg > priv->tx_power_channel_lmt)
priv->tx_power_channel_lmt = ch->max_power_avg;
@@ -545,9 +548,6 @@ int iwlcore_init_geos(struct iwl_priv *priv)
geo_ch->flags |= IEEE80211_CHAN_DISABLED;
}
- /* Save flags for reg domain usage */
- geo_ch->orig_flags = geo_ch->flags;
-
IWL_DEBUG_INFO(priv, "Channel %d Freq=%d[%sGHz] %s flag=0x%X\n",
ch->channel, geo_ch->center_freq,
is_channel_a_band(ch) ? "5.2" : "2.4",
@@ -604,16 +604,16 @@ static u8 iwl_is_channel_extension(struct iwl_priv *priv,
return 0;
if (extension_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_ABOVE)
- return !(ch_info->fat_extension_channel &
+ return !(ch_info->ht40_extension_channel &
IEEE80211_CHAN_NO_HT40PLUS);
else if (extension_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_BELOW)
- return !(ch_info->fat_extension_channel &
+ return !(ch_info->ht40_extension_channel &
IEEE80211_CHAN_NO_HT40MINUS);
return 0;
}
-u8 iwl_is_fat_tx_allowed(struct iwl_priv *priv,
+u8 iwl_is_ht40_tx_allowed(struct iwl_priv *priv,
struct ieee80211_sta_ht_cap *sta_ht_inf)
{
struct iwl_ht_info *iwl_ht_conf = &priv->current_ht_config;
@@ -629,11 +629,72 @@ u8 iwl_is_fat_tx_allowed(struct iwl_priv *priv,
if (!sta_ht_inf->ht_supported)
return 0;
}
+#ifdef CONFIG_IWLWIFI_DEBUG
+ if (priv->disable_ht40)
+ return 0;
+#endif
return iwl_is_channel_extension(priv, priv->band,
le16_to_cpu(priv->staging_rxon.channel),
iwl_ht_conf->extension_chan_offset);
}
-EXPORT_SYMBOL(iwl_is_fat_tx_allowed);
+EXPORT_SYMBOL(iwl_is_ht40_tx_allowed);
+
+static u16 iwl_adjust_beacon_interval(u16 beacon_val, u16 max_beacon_val)
+{
+ u16 new_val = 0;
+ u16 beacon_factor = 0;
+
+ beacon_factor = (beacon_val + max_beacon_val) / max_beacon_val;
+ new_val = beacon_val / beacon_factor;
+
+ if (!new_val)
+ new_val = max_beacon_val;
+
+ return new_val;
+}
+
+void iwl_setup_rxon_timing(struct iwl_priv *priv)
+{
+ u64 tsf;
+ s32 interval_tm, rem;
+ unsigned long flags;
+ struct ieee80211_conf *conf = NULL;
+ u16 beacon_int;
+
+ conf = ieee80211_get_hw_conf(priv->hw);
+
+ spin_lock_irqsave(&priv->lock, flags);
+ priv->rxon_timing.timestamp = cpu_to_le64(priv->timestamp);
+ priv->rxon_timing.listen_interval = cpu_to_le16(conf->listen_interval);
+
+ if (priv->iw_mode == NL80211_IFTYPE_STATION) {
+ beacon_int = priv->beacon_int;
+ priv->rxon_timing.atim_window = 0;
+ } else {
+ beacon_int = priv->vif->bss_conf.beacon_int;
+
+ /* TODO: we need to get atim_window from upper stack
+ * for now we set to 0 */
+ priv->rxon_timing.atim_window = 0;
+ }
+
+ beacon_int = iwl_adjust_beacon_interval(beacon_int,
+ priv->hw_params.max_beacon_itrvl * 1024);
+ priv->rxon_timing.beacon_interval = cpu_to_le16(beacon_int);
+
+ tsf = priv->timestamp; /* tsf is modifed by do_div: copy it */
+ interval_tm = beacon_int * 1024;
+ rem = do_div(tsf, interval_tm);
+ priv->rxon_timing.beacon_init_val = cpu_to_le32(interval_tm - rem);
+
+ spin_unlock_irqrestore(&priv->lock, flags);
+ IWL_DEBUG_ASSOC(priv,
+ "beacon interval %d beacon timer %d beacon tim %d\n",
+ le16_to_cpu(priv->rxon_timing.beacon_interval),
+ le32_to_cpu(priv->rxon_timing.beacon_init_val),
+ le16_to_cpu(priv->rxon_timing.atim_window));
+}
+EXPORT_SYMBOL(iwl_setup_rxon_timing);
void iwl_set_rxon_hwcrypto(struct iwl_priv *priv, int hw_decrypt)
{
@@ -805,7 +866,7 @@ void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_info *ht_info)
if (!ht_info->is_ht) {
rxon->flags &= ~(RXON_FLG_CHANNEL_MODE_MSK |
RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK |
- RXON_FLG_FAT_PROT_MSK |
+ RXON_FLG_HT40_PROT_MSK |
RXON_FLG_HT_PROT_MSK);
return;
}
@@ -816,12 +877,12 @@ void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_info *ht_info)
rxon->flags |= cpu_to_le32(ht_info->ht_protection << RXON_FLG_HT_OPERATING_MODE_POS);
/* Set up channel bandwidth:
- * 20 MHz only, 20/40 mixed or pure 40 if fat ok */
+ * 20 MHz only, 20/40 mixed or pure 40 if ht40 ok */
/* clear the HT channel mode before set the mode */
rxon->flags &= ~(RXON_FLG_CHANNEL_MODE_MSK |
RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK);
- if (iwl_is_fat_tx_allowed(priv, NULL)) {
- /* pure 40 fat */
+ if (iwl_is_ht40_tx_allowed(priv, NULL)) {
+ /* pure ht40 */
if (ht_info->ht_protection == IEEE80211_HT_OP_MODE_PROTECTION_20MHZ) {
rxon->flags |= RXON_FLG_CHANNEL_MODE_PURE_40;
/* Note: control channel is opposite of extension channel */
@@ -1076,7 +1137,6 @@ void iwl_set_flags_for_band(struct iwl_priv *priv,
priv->staging_rxon.flags &= ~RXON_FLG_CCK_MSK;
}
}
-EXPORT_SYMBOL(iwl_set_flags_for_band);
/*
* initialize rxon structure with default values from eeprom
@@ -1231,9 +1291,191 @@ static void iwl_print_rx_config_cmd(struct iwl_priv *priv)
IWL_DEBUG_RADIO(priv, "u8[6] bssid_addr: %pM\n", rxon->bssid_addr);
IWL_DEBUG_RADIO(priv, "u16 assoc_id: 0x%x\n", le16_to_cpu(rxon->assoc_id));
}
-#endif
+
+static const char *desc_lookup_text[] = {
+ "OK",
+ "FAIL",
+ "BAD_PARAM",
+ "BAD_CHECKSUM",
+ "NMI_INTERRUPT_WDG",
+ "SYSASSERT",
+ "FATAL_ERROR",
+ "BAD_COMMAND",
+ "HW_ERROR_TUNE_LOCK",
+ "HW_ERROR_TEMPERATURE",
+ "ILLEGAL_CHAN_FREQ",
+ "VCC_NOT_STABLE",
+ "FH_ERROR",
+ "NMI_INTERRUPT_HOST",
+ "NMI_INTERRUPT_ACTION_PT",
+ "NMI_INTERRUPT_UNKNOWN",
+ "UCODE_VERSION_MISMATCH",
+ "HW_ERROR_ABS_LOCK",
+ "HW_ERROR_CAL_LOCK_FAIL",
+ "NMI_INTERRUPT_INST_ACTION_PT",
+ "NMI_INTERRUPT_DATA_ACTION_PT",
+ "NMI_TRM_HW_ER",
+ "NMI_INTERRUPT_TRM",
+ "NMI_INTERRUPT_BREAK_POINT"
+ "DEBUG_0",
+ "DEBUG_1",
+ "DEBUG_2",
+ "DEBUG_3",
+ "UNKNOWN"
+};
+
+static const char *desc_lookup(int i)
+{
+ int max = ARRAY_SIZE(desc_lookup_text) - 1;
+
+ if (i < 0 || i > max)
+ i = max;
+
+ return desc_lookup_text[i];
+}
+
+#define ERROR_START_OFFSET (1 * sizeof(u32))
+#define ERROR_ELEM_SIZE (7 * sizeof(u32))
+
+static void iwl_dump_nic_error_log(struct iwl_priv *priv)
+{
+ u32 data2, line;
+ u32 desc, time, count, base, data1;
+ u32 blink1, blink2, ilink1, ilink2;
+
+ if (priv->ucode_type == UCODE_INIT)
+ base = le32_to_cpu(priv->card_alive_init.error_event_table_ptr);
+ else
+ base = le32_to_cpu(priv->card_alive.error_event_table_ptr);
+
+ if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) {
+ IWL_ERR(priv, "Not valid error log pointer 0x%08X\n", base);
+ return;
+ }
+
+ count = iwl_read_targ_mem(priv, base);
+
+ if (ERROR_START_OFFSET <= count * ERROR_ELEM_SIZE) {
+ IWL_ERR(priv, "Start IWL Error Log Dump:\n");
+ IWL_ERR(priv, "Status: 0x%08lX, count: %d\n",
+ priv->status, count);
+ }
+
+ desc = iwl_read_targ_mem(priv, base + 1 * sizeof(u32));
+ blink1 = iwl_read_targ_mem(priv, base + 3 * sizeof(u32));
+ blink2 = iwl_read_targ_mem(priv, base + 4 * sizeof(u32));
+ ilink1 = iwl_read_targ_mem(priv, base + 5 * sizeof(u32));
+ ilink2 = iwl_read_targ_mem(priv, base + 6 * sizeof(u32));
+ data1 = iwl_read_targ_mem(priv, base + 7 * sizeof(u32));
+ data2 = iwl_read_targ_mem(priv, base + 8 * sizeof(u32));
+ line = iwl_read_targ_mem(priv, base + 9 * sizeof(u32));
+ time = iwl_read_targ_mem(priv, base + 11 * sizeof(u32));
+
+ IWL_ERR(priv, "Desc Time "
+ "data1 data2 line\n");
+ IWL_ERR(priv, "%-28s (#%02d) %010u 0x%08X 0x%08X %u\n",
+ desc_lookup(desc), desc, time, data1, data2, line);
+ IWL_ERR(priv, "blink1 blink2 ilink1 ilink2\n");
+ IWL_ERR(priv, "0x%05X 0x%05X 0x%05X 0x%05X\n", blink1, blink2,
+ ilink1, ilink2);
+
+}
+
+#define EVENT_START_OFFSET (4 * sizeof(u32))
/**
+ * iwl_print_event_log - Dump error event log to syslog
+ *
+ */
+static void iwl_print_event_log(struct iwl_priv *priv, u32 start_idx,
+ u32 num_events, u32 mode)
+{
+ u32 i;
+ u32 base; /* SRAM byte address of event log header */
+ u32 event_size; /* 2 u32s, or 3 u32s if timestamp recorded */
+ u32 ptr; /* SRAM byte address of log data */
+ u32 ev, time, data; /* event log data */
+
+ if (num_events == 0)
+ return;
+ if (priv->ucode_type == UCODE_INIT)
+ base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr);
+ else
+ base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
+
+ if (mode == 0)
+ event_size = 2 * sizeof(u32);
+ else
+ event_size = 3 * sizeof(u32);
+
+ ptr = base + EVENT_START_OFFSET + (start_idx * event_size);
+
+ /* "time" is actually "data" for mode 0 (no timestamp).
+ * place event id # at far right for easier visual parsing. */
+ for (i = 0; i < num_events; i++) {
+ ev = iwl_read_targ_mem(priv, ptr);
+ ptr += sizeof(u32);
+ time = iwl_read_targ_mem(priv, ptr);
+ ptr += sizeof(u32);
+ if (mode == 0) {
+ /* data, ev */
+ IWL_ERR(priv, "EVT_LOG:0x%08x:%04u\n", time, ev);
+ } else {
+ data = iwl_read_targ_mem(priv, ptr);
+ ptr += sizeof(u32);
+ IWL_ERR(priv, "EVT_LOGT:%010u:0x%08x:%04u\n",
+ time, data, ev);
+ }
+ }
+}
+
+void iwl_dump_nic_event_log(struct iwl_priv *priv)
+{
+ u32 base; /* SRAM byte address of event log header */
+ u32 capacity; /* event log capacity in # entries */
+ u32 mode; /* 0 - no timestamp, 1 - timestamp recorded */
+ u32 num_wraps; /* # times uCode wrapped to top of log */
+ u32 next_entry; /* index of next entry to be written by uCode */
+ u32 size; /* # entries that we'll print */
+
+ if (priv->ucode_type == UCODE_INIT)
+ base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr);
+ else
+ base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
+
+ if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) {
+ IWL_ERR(priv, "Invalid event log pointer 0x%08X\n", base);
+ return;
+ }
+
+ /* event log header */
+ capacity = iwl_read_targ_mem(priv, base);
+ mode = iwl_read_targ_mem(priv, base + (1 * sizeof(u32)));
+ num_wraps = iwl_read_targ_mem(priv, base + (2 * sizeof(u32)));
+ next_entry = iwl_read_targ_mem(priv, base + (3 * sizeof(u32)));
+
+ size = num_wraps ? capacity : next_entry;
+
+ /* bail out if nothing in log */
+ if (size == 0) {
+ IWL_ERR(priv, "Start IWL Event Log Dump: nothing in log\n");
+ return;
+ }
+
+ IWL_ERR(priv, "Start IWL Event Log Dump: display count %d, wraps %d\n",
+ size, num_wraps);
+
+ /* if uCode has wrapped back to top of log, start at the oldest entry,
+ * i.e the next one that uCode would fill. */
+ if (num_wraps)
+ iwl_print_event_log(priv, next_entry,
+ capacity - next_entry, mode);
+ /* (then/else) start at top of log */
+ iwl_print_event_log(priv, 0, next_entry, mode);
+
+}
+#endif
+/**
* iwl_irq_handle_error - called for HW or SW error interrupt from card
*/
void iwl_irq_handle_error(struct iwl_priv *priv)
@@ -1245,7 +1487,7 @@ void iwl_irq_handle_error(struct iwl_priv *priv)
clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
#ifdef CONFIG_IWLWIFI_DEBUG
- if (priv->debug_level & IWL_DL_FW_ERRORS) {
+ if (iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS) {
iwl_dump_nic_error_log(priv);
iwl_dump_nic_event_log(priv);
iwl_print_rx_config_cmd(priv);
@@ -1325,7 +1567,9 @@ int iwl_setup_mac(struct iwl_priv *priv)
hw->flags = IEEE80211_HW_SIGNAL_DBM |
IEEE80211_HW_NOISE_DBM |
IEEE80211_HW_AMPDU_AGGREGATION |
- IEEE80211_HW_SPECTRUM_MGMT;
+ IEEE80211_HW_SPECTRUM_MGMT |
+ IEEE80211_HW_SUPPORTS_PS |
+ IEEE80211_HW_SUPPORTS_DYNAMIC_PS;
hw->wiphy->interface_modes =
BIT(NL80211_IFTYPE_STATION) |
BIT(NL80211_IFTYPE_ADHOC);
@@ -1364,7 +1608,6 @@ EXPORT_SYMBOL(iwl_setup_mac);
int iwl_set_hw_params(struct iwl_priv *priv)
{
- priv->hw_params.sw_crypto = priv->cfg->mod_params->sw_crypto;
priv->hw_params.max_rxq_size = RX_QUEUE_SIZE;
priv->hw_params.max_rxq_log = RX_QUEUE_SIZE_LOG;
if (priv->cfg->mod_params->amsdu_size_8K)
@@ -1373,6 +1616,8 @@ int iwl_set_hw_params(struct iwl_priv *priv)
priv->hw_params.rx_buf_size = IWL_RX_BUF_SIZE_4K;
priv->hw_params.max_pkt_size = priv->hw_params.rx_buf_size - 256;
+ priv->hw_params.max_beacon_itrvl = IWL_MAX_UCODE_BEACON_INTERVAL;
+
if (priv->cfg->mod_params->disable_11n)
priv->cfg->sku &= ~IWL_SKU_N;
@@ -1419,8 +1664,6 @@ int iwl_init_drv(struct iwl_priv *priv)
priv->qos_data.qos_cap.val = 0;
priv->rates_mask = IWL_RATES_MASK;
- /* If power management is turned on, default to CAM mode */
- priv->power_mode = IWL_POWER_MODE_CAM;
priv->tx_power_user_lmt = IWL_TX_POWER_TARGET_POWER_MAX;
ret = iwl_init_channel_map(priv);
@@ -1487,31 +1730,6 @@ void iwl_uninit_drv(struct iwl_priv *priv)
}
EXPORT_SYMBOL(iwl_uninit_drv);
-
-void iwl_disable_interrupts(struct iwl_priv *priv)
-{
- clear_bit(STATUS_INT_ENABLED, &priv->status);
-
- /* disable interrupts from uCode/NIC to host */
- iwl_write32(priv, CSR_INT_MASK, 0x00000000);
-
- /* acknowledge/clear/reset any interrupts still pending
- * from uCode or flow handler (Rx/Tx DMA) */
- iwl_write32(priv, CSR_INT, 0xffffffff);
- iwl_write32(priv, CSR_FH_INT_STATUS, 0xffffffff);
- IWL_DEBUG_ISR(priv, "Disabled interrupts\n");
-}
-EXPORT_SYMBOL(iwl_disable_interrupts);
-
-void iwl_enable_interrupts(struct iwl_priv *priv)
-{
- IWL_DEBUG_ISR(priv, "Enabling interrupts\n");
- set_bit(STATUS_INT_ENABLED, &priv->status);
- iwl_write32(priv, CSR_INT_MASK, priv->inta_mask);
-}
-EXPORT_SYMBOL(iwl_enable_interrupts);
-
-
#define ICT_COUNT (PAGE_SIZE/sizeof(u32))
/* Free dram table */
@@ -1745,7 +1963,7 @@ static irqreturn_t iwl_isr(int irq, void *data)
}
#ifdef CONFIG_IWLWIFI_DEBUG
- if (priv->debug_level & (IWL_DL_ISR)) {
+ if (iwl_get_debug_level(priv) & (IWL_DL_ISR)) {
inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS);
IWL_DEBUG_ISR(priv, "ISR inta 0x%08x, enabled 0x%08x, "
"fh 0x%08x\n", inta, inta_mask, inta_fh);
@@ -1852,7 +2070,7 @@ int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags)
u32 stat_flags = 0;
struct iwl_host_cmd cmd = {
.id = REPLY_STATISTICS_CMD,
- .meta.flags = flags,
+ .flags = flags,
.len = sizeof(stat_flags),
.data = (u8 *) &stat_flags,
};
@@ -1984,194 +2202,10 @@ int iwl_verify_ucode(struct iwl_priv *priv)
EXPORT_SYMBOL(iwl_verify_ucode);
-static const char *desc_lookup_text[] = {
- "OK",
- "FAIL",
- "BAD_PARAM",
- "BAD_CHECKSUM",
- "NMI_INTERRUPT_WDG",
- "SYSASSERT",
- "FATAL_ERROR",
- "BAD_COMMAND",
- "HW_ERROR_TUNE_LOCK",
- "HW_ERROR_TEMPERATURE",
- "ILLEGAL_CHAN_FREQ",
- "VCC_NOT_STABLE",
- "FH_ERROR",
- "NMI_INTERRUPT_HOST",
- "NMI_INTERRUPT_ACTION_PT",
- "NMI_INTERRUPT_UNKNOWN",
- "UCODE_VERSION_MISMATCH",
- "HW_ERROR_ABS_LOCK",
- "HW_ERROR_CAL_LOCK_FAIL",
- "NMI_INTERRUPT_INST_ACTION_PT",
- "NMI_INTERRUPT_DATA_ACTION_PT",
- "NMI_TRM_HW_ER",
- "NMI_INTERRUPT_TRM",
- "NMI_INTERRUPT_BREAK_POINT"
- "DEBUG_0",
- "DEBUG_1",
- "DEBUG_2",
- "DEBUG_3",
- "UNKNOWN"
-};
-
-static const char *desc_lookup(int i)
-{
- int max = ARRAY_SIZE(desc_lookup_text) - 1;
-
- if (i < 0 || i > max)
- i = max;
-
- return desc_lookup_text[i];
-}
-
-#define ERROR_START_OFFSET (1 * sizeof(u32))
-#define ERROR_ELEM_SIZE (7 * sizeof(u32))
-
-void iwl_dump_nic_error_log(struct iwl_priv *priv)
-{
- u32 data2, line;
- u32 desc, time, count, base, data1;
- u32 blink1, blink2, ilink1, ilink2;
-
- if (priv->ucode_type == UCODE_INIT)
- base = le32_to_cpu(priv->card_alive_init.error_event_table_ptr);
- else
- base = le32_to_cpu(priv->card_alive.error_event_table_ptr);
-
- if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) {
- IWL_ERR(priv, "Not valid error log pointer 0x%08X\n", base);
- return;
- }
-
- count = iwl_read_targ_mem(priv, base);
-
- if (ERROR_START_OFFSET <= count * ERROR_ELEM_SIZE) {
- IWL_ERR(priv, "Start IWL Error Log Dump:\n");
- IWL_ERR(priv, "Status: 0x%08lX, count: %d\n",
- priv->status, count);
- }
-
- desc = iwl_read_targ_mem(priv, base + 1 * sizeof(u32));
- blink1 = iwl_read_targ_mem(priv, base + 3 * sizeof(u32));
- blink2 = iwl_read_targ_mem(priv, base + 4 * sizeof(u32));
- ilink1 = iwl_read_targ_mem(priv, base + 5 * sizeof(u32));
- ilink2 = iwl_read_targ_mem(priv, base + 6 * sizeof(u32));
- data1 = iwl_read_targ_mem(priv, base + 7 * sizeof(u32));
- data2 = iwl_read_targ_mem(priv, base + 8 * sizeof(u32));
- line = iwl_read_targ_mem(priv, base + 9 * sizeof(u32));
- time = iwl_read_targ_mem(priv, base + 11 * sizeof(u32));
-
- IWL_ERR(priv, "Desc Time "
- "data1 data2 line\n");
- IWL_ERR(priv, "%-28s (#%02d) %010u 0x%08X 0x%08X %u\n",
- desc_lookup(desc), desc, time, data1, data2, line);
- IWL_ERR(priv, "blink1 blink2 ilink1 ilink2\n");
- IWL_ERR(priv, "0x%05X 0x%05X 0x%05X 0x%05X\n", blink1, blink2,
- ilink1, ilink2);
-
-}
-EXPORT_SYMBOL(iwl_dump_nic_error_log);
-
-#define EVENT_START_OFFSET (4 * sizeof(u32))
-
-/**
- * iwl_print_event_log - Dump error event log to syslog
- *
- */
-static void iwl_print_event_log(struct iwl_priv *priv, u32 start_idx,
- u32 num_events, u32 mode)
-{
- u32 i;
- u32 base; /* SRAM byte address of event log header */
- u32 event_size; /* 2 u32s, or 3 u32s if timestamp recorded */
- u32 ptr; /* SRAM byte address of log data */
- u32 ev, time, data; /* event log data */
-
- if (num_events == 0)
- return;
- if (priv->ucode_type == UCODE_INIT)
- base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr);
- else
- base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
-
- if (mode == 0)
- event_size = 2 * sizeof(u32);
- else
- event_size = 3 * sizeof(u32);
-
- ptr = base + EVENT_START_OFFSET + (start_idx * event_size);
-
- /* "time" is actually "data" for mode 0 (no timestamp).
- * place event id # at far right for easier visual parsing. */
- for (i = 0; i < num_events; i++) {
- ev = iwl_read_targ_mem(priv, ptr);
- ptr += sizeof(u32);
- time = iwl_read_targ_mem(priv, ptr);
- ptr += sizeof(u32);
- if (mode == 0) {
- /* data, ev */
- IWL_ERR(priv, "EVT_LOG:0x%08x:%04u\n", time, ev);
- } else {
- data = iwl_read_targ_mem(priv, ptr);
- ptr += sizeof(u32);
- IWL_ERR(priv, "EVT_LOGT:%010u:0x%08x:%04u\n",
- time, data, ev);
- }
- }
-}
-
-void iwl_dump_nic_event_log(struct iwl_priv *priv)
-{
- u32 base; /* SRAM byte address of event log header */
- u32 capacity; /* event log capacity in # entries */
- u32 mode; /* 0 - no timestamp, 1 - timestamp recorded */
- u32 num_wraps; /* # times uCode wrapped to top of log */
- u32 next_entry; /* index of next entry to be written by uCode */
- u32 size; /* # entries that we'll print */
-
- if (priv->ucode_type == UCODE_INIT)
- base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr);
- else
- base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
-
- if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) {
- IWL_ERR(priv, "Invalid event log pointer 0x%08X\n", base);
- return;
- }
-
- /* event log header */
- capacity = iwl_read_targ_mem(priv, base);
- mode = iwl_read_targ_mem(priv, base + (1 * sizeof(u32)));
- num_wraps = iwl_read_targ_mem(priv, base + (2 * sizeof(u32)));
- next_entry = iwl_read_targ_mem(priv, base + (3 * sizeof(u32)));
-
- size = num_wraps ? capacity : next_entry;
-
- /* bail out if nothing in log */
- if (size == 0) {
- IWL_ERR(priv, "Start IWL Event Log Dump: nothing in log\n");
- return;
- }
-
- IWL_ERR(priv, "Start IWL Event Log Dump: display count %d, wraps %d\n",
- size, num_wraps);
-
- /* if uCode has wrapped back to top of log, start at the oldest entry,
- * i.e the next one that uCode would fill. */
- if (num_wraps)
- iwl_print_event_log(priv, next_entry,
- capacity - next_entry, mode);
- /* (then/else) start at top of log */
- iwl_print_event_log(priv, 0, next_entry, mode);
-
-}
-EXPORT_SYMBOL(iwl_dump_nic_event_log);
-
void iwl_rf_kill_ct_config(struct iwl_priv *priv)
{
struct iwl_ct_kill_config cmd;
+ struct iwl_ct_kill_throttling_config adv_cmd;
unsigned long flags;
int ret = 0;
@@ -2179,18 +2213,44 @@ void iwl_rf_kill_ct_config(struct iwl_priv *priv)
iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR,
CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT);
spin_unlock_irqrestore(&priv->lock, flags);
+ priv->thermal_throttle.ct_kill_toggle = false;
+
+ switch (priv->hw_rev & CSR_HW_REV_TYPE_MSK) {
+ case CSR_HW_REV_TYPE_1000:
+ case CSR_HW_REV_TYPE_6x00:
+ case CSR_HW_REV_TYPE_6x50:
+ adv_cmd.critical_temperature_enter =
+ cpu_to_le32(priv->hw_params.ct_kill_threshold);
+ adv_cmd.critical_temperature_exit =
+ cpu_to_le32(priv->hw_params.ct_kill_exit_threshold);
+
+ ret = iwl_send_cmd_pdu(priv, REPLY_CT_KILL_CONFIG_CMD,
+ sizeof(adv_cmd), &adv_cmd);
+ if (ret)
+ IWL_ERR(priv, "REPLY_CT_KILL_CONFIG_CMD failed\n");
+ else
+ IWL_DEBUG_INFO(priv, "REPLY_CT_KILL_CONFIG_CMD "
+ "succeeded, "
+ "critical temperature enter is %d,"
+ "exit is %d\n",
+ priv->hw_params.ct_kill_threshold,
+ priv->hw_params.ct_kill_exit_threshold);
+ break;
+ default:
+ cmd.critical_temperature_R =
+ cpu_to_le32(priv->hw_params.ct_kill_threshold);
- cmd.critical_temperature_R =
- cpu_to_le32(priv->hw_params.ct_kill_threshold);
-
- ret = iwl_send_cmd_pdu(priv, REPLY_CT_KILL_CONFIG_CMD,
- sizeof(cmd), &cmd);
- if (ret)
- IWL_ERR(priv, "REPLY_CT_KILL_CONFIG_CMD failed\n");
- else
- IWL_DEBUG_INFO(priv, "REPLY_CT_KILL_CONFIG_CMD succeeded, "
- "critical temperature is %d\n",
- cmd.critical_temperature_R);
+ ret = iwl_send_cmd_pdu(priv, REPLY_CT_KILL_CONFIG_CMD,
+ sizeof(cmd), &cmd);
+ if (ret)
+ IWL_ERR(priv, "REPLY_CT_KILL_CONFIG_CMD failed\n");
+ else
+ IWL_DEBUG_INFO(priv, "REPLY_CT_KILL_CONFIG_CMD "
+ "succeeded, "
+ "critical temperature is %d\n",
+ priv->hw_params.ct_kill_threshold);
+ break;
+ }
}
EXPORT_SYMBOL(iwl_rf_kill_ct_config);
@@ -2211,12 +2271,11 @@ int iwl_send_card_state(struct iwl_priv *priv, u32 flags, u8 meta_flag)
.id = REPLY_CARD_STATE_CMD,
.len = sizeof(u32),
.data = &flags,
- .meta.flags = meta_flag,
+ .flags = meta_flag,
};
return iwl_send_cmd(priv, &cmd);
}
-EXPORT_SYMBOL(iwl_send_card_state);
void iwl_rx_pm_sleep_notif(struct iwl_priv *priv,
struct iwl_rx_mem_buffer *rxb)
@@ -2260,7 +2319,6 @@ void iwl_clear_isr_stats(struct iwl_priv *priv)
{
memset(&priv->isr_stats, 0, sizeof(priv->isr_stats));
}
-EXPORT_SYMBOL(iwl_clear_isr_stats);
int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue,
const struct ieee80211_tx_queue_params *params)
@@ -2356,7 +2414,7 @@ static void iwl_ht_conf(struct iwl_priv *priv,
else if (conf_is_ht40_plus(&priv->hw->conf))
iwl_conf->extension_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
- /* If no above or below channel supplied disable FAT channel */
+ /* If no above or below channel supplied disable HT40 channel */
if (iwl_conf->extension_chan_offset != IEEE80211_HT_PARAM_CHA_SEC_ABOVE &&
iwl_conf->extension_chan_offset != IEEE80211_HT_PARAM_CHA_SEC_BELOW)
iwl_conf->supported_chan_width = 0;
@@ -2492,7 +2550,6 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw,
if (bss_conf->assoc) {
priv->assoc_id = bss_conf->aid;
priv->beacon_int = bss_conf->beacon_int;
- priv->power_data.dtim_period = bss_conf->dtim_period;
priv->timestamp = bss_conf->timestamp;
priv->assoc_capability = bss_conf->assoc_capability;
@@ -2742,13 +2799,10 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed)
iwl_set_rate(priv);
}
- if (changed & IEEE80211_CONF_CHANGE_PS &&
- priv->iw_mode == NL80211_IFTYPE_STATION) {
- priv->power_data.power_disabled =
- !(conf->flags & IEEE80211_CONF_PS);
- ret = iwl_power_update_mode(priv, 0);
+ if (changed & IEEE80211_CONF_CHANGE_PS) {
+ ret = iwl_power_update_mode(priv, false);
if (ret)
- IWL_DEBUG_MAC80211(priv, "Error setting power level\n");
+ IWL_DEBUG_MAC80211(priv, "Error setting sleep level\n");
}
if (changed & IEEE80211_CONF_CHANGE_POWER) {
@@ -2881,6 +2935,248 @@ void iwl_mac_reset_tsf(struct ieee80211_hw *hw)
}
EXPORT_SYMBOL(iwl_mac_reset_tsf);
+#ifdef CONFIG_IWLWIFI_DEBUGFS
+
+#define IWL_TRAFFIC_DUMP_SIZE (IWL_TRAFFIC_ENTRY_SIZE * IWL_TRAFFIC_ENTRIES)
+
+void iwl_reset_traffic_log(struct iwl_priv *priv)
+{
+ priv->tx_traffic_idx = 0;
+ priv->rx_traffic_idx = 0;
+ if (priv->tx_traffic)
+ memset(priv->tx_traffic, 0, IWL_TRAFFIC_DUMP_SIZE);
+ if (priv->rx_traffic)
+ memset(priv->rx_traffic, 0, IWL_TRAFFIC_DUMP_SIZE);
+}
+
+int iwl_alloc_traffic_mem(struct iwl_priv *priv)
+{
+ u32 traffic_size = IWL_TRAFFIC_DUMP_SIZE;
+
+ if (iwl_debug_level & IWL_DL_TX) {
+ if (!priv->tx_traffic) {
+ priv->tx_traffic =
+ kzalloc(traffic_size, GFP_KERNEL);
+ if (!priv->tx_traffic)
+ return -ENOMEM;
+ }
+ }
+ if (iwl_debug_level & IWL_DL_RX) {
+ if (!priv->rx_traffic) {
+ priv->rx_traffic =
+ kzalloc(traffic_size, GFP_KERNEL);
+ if (!priv->rx_traffic)
+ return -ENOMEM;
+ }
+ }
+ iwl_reset_traffic_log(priv);
+ return 0;
+}
+EXPORT_SYMBOL(iwl_alloc_traffic_mem);
+
+void iwl_free_traffic_mem(struct iwl_priv *priv)
+{
+ kfree(priv->tx_traffic);
+ priv->tx_traffic = NULL;
+
+ kfree(priv->rx_traffic);
+ priv->rx_traffic = NULL;
+}
+EXPORT_SYMBOL(iwl_free_traffic_mem);
+
+void iwl_dbg_log_tx_data_frame(struct iwl_priv *priv,
+ u16 length, struct ieee80211_hdr *header)
+{
+ __le16 fc;
+ u16 len;
+
+ if (likely(!(iwl_debug_level & IWL_DL_TX)))
+ return;
+
+ if (!priv->tx_traffic)
+ return;
+
+ fc = header->frame_control;
+ if (ieee80211_is_data(fc)) {
+ len = (length > IWL_TRAFFIC_ENTRY_SIZE)
+ ? IWL_TRAFFIC_ENTRY_SIZE : length;
+ memcpy((priv->tx_traffic +
+ (priv->tx_traffic_idx * IWL_TRAFFIC_ENTRY_SIZE)),
+ header, len);
+ priv->tx_traffic_idx =
+ (priv->tx_traffic_idx + 1) % IWL_TRAFFIC_ENTRIES;
+ }
+}
+EXPORT_SYMBOL(iwl_dbg_log_tx_data_frame);
+
+void iwl_dbg_log_rx_data_frame(struct iwl_priv *priv,
+ u16 length, struct ieee80211_hdr *header)
+{
+ __le16 fc;
+ u16 len;
+
+ if (likely(!(iwl_debug_level & IWL_DL_RX)))
+ return;
+
+ if (!priv->rx_traffic)
+ return;
+
+ fc = header->frame_control;
+ if (ieee80211_is_data(fc)) {
+ len = (length > IWL_TRAFFIC_ENTRY_SIZE)
+ ? IWL_TRAFFIC_ENTRY_SIZE : length;
+ memcpy((priv->rx_traffic +
+ (priv->rx_traffic_idx * IWL_TRAFFIC_ENTRY_SIZE)),
+ header, len);
+ priv->rx_traffic_idx =
+ (priv->rx_traffic_idx + 1) % IWL_TRAFFIC_ENTRIES;
+ }
+}
+EXPORT_SYMBOL(iwl_dbg_log_rx_data_frame);
+
+const char *get_mgmt_string(int cmd)
+{
+ switch (cmd) {
+ IWL_CMD(MANAGEMENT_ASSOC_REQ);
+ IWL_CMD(MANAGEMENT_ASSOC_RESP);
+ IWL_CMD(MANAGEMENT_REASSOC_REQ);
+ IWL_CMD(MANAGEMENT_REASSOC_RESP);
+ IWL_CMD(MANAGEMENT_PROBE_REQ);
+ IWL_CMD(MANAGEMENT_PROBE_RESP);
+ IWL_CMD(MANAGEMENT_BEACON);
+ IWL_CMD(MANAGEMENT_ATIM);
+ IWL_CMD(MANAGEMENT_DISASSOC);
+ IWL_CMD(MANAGEMENT_AUTH);
+ IWL_CMD(MANAGEMENT_DEAUTH);
+ IWL_CMD(MANAGEMENT_ACTION);
+ default:
+ return "UNKNOWN";
+
+ }
+}
+
+const char *get_ctrl_string(int cmd)
+{
+ switch (cmd) {
+ IWL_CMD(CONTROL_BACK_REQ);
+ IWL_CMD(CONTROL_BACK);
+ IWL_CMD(CONTROL_PSPOLL);
+ IWL_CMD(CONTROL_RTS);
+ IWL_CMD(CONTROL_CTS);
+ IWL_CMD(CONTROL_ACK);
+ IWL_CMD(CONTROL_CFEND);
+ IWL_CMD(CONTROL_CFENDACK);
+ default:
+ return "UNKNOWN";
+
+ }
+}
+
+void iwl_clear_tx_stats(struct iwl_priv *priv)
+{
+ memset(&priv->tx_stats, 0, sizeof(struct traffic_stats));
+
+}
+
+void iwl_clear_rx_stats(struct iwl_priv *priv)
+{
+ memset(&priv->rx_stats, 0, sizeof(struct traffic_stats));
+}
+
+/*
+ * if CONFIG_IWLWIFI_DEBUGFS defined, iwl_update_stats function will
+ * record all the MGMT, CTRL and DATA pkt for both TX and Rx pass.
+ * Use debugFs to display the rx/rx_statistics
+ * if CONFIG_IWLWIFI_DEBUGFS not being defined, then no MGMT and CTRL
+ * information will be recorded, but DATA pkt still will be recorded
+ * for the reason of iwl_led.c need to control the led blinking based on
+ * number of tx and rx data.
+ *
+ */
+void iwl_update_stats(struct iwl_priv *priv, bool is_tx, __le16 fc, u16 len)
+{
+ struct traffic_stats *stats;
+
+ if (is_tx)
+ stats = &priv->tx_stats;
+ else
+ stats = &priv->rx_stats;
+
+ if (ieee80211_is_mgmt(fc)) {
+ switch (fc & cpu_to_le16(IEEE80211_FCTL_STYPE)) {
+ case cpu_to_le16(IEEE80211_STYPE_ASSOC_REQ):
+ stats->mgmt[MANAGEMENT_ASSOC_REQ]++;
+ break;
+ case cpu_to_le16(IEEE80211_STYPE_ASSOC_RESP):
+ stats->mgmt[MANAGEMENT_ASSOC_RESP]++;
+ break;
+ case cpu_to_le16(IEEE80211_STYPE_REASSOC_REQ):
+ stats->mgmt[MANAGEMENT_REASSOC_REQ]++;
+ break;
+ case cpu_to_le16(IEEE80211_STYPE_REASSOC_RESP):
+ stats->mgmt[MANAGEMENT_REASSOC_RESP]++;
+ break;
+ case cpu_to_le16(IEEE80211_STYPE_PROBE_REQ):
+ stats->mgmt[MANAGEMENT_PROBE_REQ]++;
+ break;
+ case cpu_to_le16(IEEE80211_STYPE_PROBE_RESP):
+ stats->mgmt[MANAGEMENT_PROBE_RESP]++;
+ break;
+ case cpu_to_le16(IEEE80211_STYPE_BEACON):
+ stats->mgmt[MANAGEMENT_BEACON]++;
+ break;
+ case cpu_to_le16(IEEE80211_STYPE_ATIM):
+ stats->mgmt[MANAGEMENT_ATIM]++;
+ break;
+ case cpu_to_le16(IEEE80211_STYPE_DISASSOC):
+ stats->mgmt[MANAGEMENT_DISASSOC]++;
+ break;
+ case cpu_to_le16(IEEE80211_STYPE_AUTH):
+ stats->mgmt[MANAGEMENT_AUTH]++;
+ break;
+ case cpu_to_le16(IEEE80211_STYPE_DEAUTH):
+ stats->mgmt[MANAGEMENT_DEAUTH]++;
+ break;
+ case cpu_to_le16(IEEE80211_STYPE_ACTION):
+ stats->mgmt[MANAGEMENT_ACTION]++;
+ break;
+ }
+ } else if (ieee80211_is_ctl(fc)) {
+ switch (fc & cpu_to_le16(IEEE80211_FCTL_STYPE)) {
+ case cpu_to_le16(IEEE80211_STYPE_BACK_REQ):
+ stats->ctrl[CONTROL_BACK_REQ]++;
+ break;
+ case cpu_to_le16(IEEE80211_STYPE_BACK):
+ stats->ctrl[CONTROL_BACK]++;
+ break;
+ case cpu_to_le16(IEEE80211_STYPE_PSPOLL):
+ stats->ctrl[CONTROL_PSPOLL]++;
+ break;
+ case cpu_to_le16(IEEE80211_STYPE_RTS):
+ stats->ctrl[CONTROL_RTS]++;
+ break;
+ case cpu_to_le16(IEEE80211_STYPE_CTS):
+ stats->ctrl[CONTROL_CTS]++;
+ break;
+ case cpu_to_le16(IEEE80211_STYPE_ACK):
+ stats->ctrl[CONTROL_ACK]++;
+ break;
+ case cpu_to_le16(IEEE80211_STYPE_CFEND):
+ stats->ctrl[CONTROL_CFEND]++;
+ break;
+ case cpu_to_le16(IEEE80211_STYPE_CFENDACK):
+ stats->ctrl[CONTROL_CFENDACK]++;
+ break;
+ }
+ } else {
+ /* data */
+ stats->data_cnt++;
+ stats->data_bytes += len;
+ }
+}
+EXPORT_SYMBOL(iwl_update_stats);
+#endif
+
#ifdef CONFIG_PM
int iwl_pci_suspend(struct pci_dev *pdev, pm_message_t state)
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
index dabf663e36e..32750f4f1ce 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -83,6 +83,8 @@ struct iwl_cmd;
#define IWL_SKU_A 0x2
#define IWL_SKU_N 0x8
+#define IWL_CMD(x) case x: return #x
+
struct iwl_hcmd_ops {
int (*rxon_assoc)(struct iwl_priv *priv);
int (*commit_rxon)(struct iwl_priv *priv);
@@ -116,6 +118,17 @@ struct iwl_temp_ops {
void (*set_ct_kill)(struct iwl_priv *priv);
};
+struct iwl_ucode_ops {
+ u32 (*get_header_size)(u32);
+ u32 (*get_build)(const struct iwl_ucode_header *, u32);
+ u32 (*get_inst_size)(const struct iwl_ucode_header *, u32);
+ u32 (*get_data_size)(const struct iwl_ucode_header *, u32);
+ u32 (*get_init_size)(const struct iwl_ucode_header *, u32);
+ u32 (*get_init_data_size)(const struct iwl_ucode_header *, u32);
+ u32 (*get_boot_size)(const struct iwl_ucode_header *, u32);
+ u8 * (*get_data)(const struct iwl_ucode_header *, u32);
+};
+
struct iwl_lib_ops {
/* set hw dependent parameters */
int (*set_hw_params)(struct iwl_priv *priv);
@@ -171,6 +184,7 @@ struct iwl_lib_ops {
};
struct iwl_ops {
+ const struct iwl_ucode_ops *ucode;
const struct iwl_lib_ops *lib;
const struct iwl_hcmd_ops *hcmd;
const struct iwl_hcmd_utils_ops *utils;
@@ -178,7 +192,6 @@ struct iwl_ops {
struct iwl_mod_params {
int sw_crypto; /* def: 0 = using hardware encryption */
- u32 debug; /* def: 0 = minimal debug log messages */
int disable_hw_scan; /* def: 0 = use h/w scan */
int num_of_queues; /* def: HW dependent */
int num_of_ampdu_queues;/* def: HW dependent */
@@ -195,6 +208,7 @@ struct iwl_mod_params {
* filename is constructed as fw_name_pre<api>.ucode.
* @ucode_api_max: Highest version of uCode API supported by driver.
* @ucode_api_min: Lowest version of uCode API supported by driver.
+ * @pa_type: used by 6000 series only to identify the type of Power Amplifier
*
* We enable the driver to be backward compatible wrt API version. The
* driver specifies which APIs it supports (with @ucode_api_max being the
@@ -215,6 +229,7 @@ struct iwl_mod_params {
* iwl_hcmd_utils_ops etc. we accommodate different command structures
* and flows between hardware versions (4965/5000) as well as their API
* versions.
+ *
*/
struct iwl_cfg {
const char *name;
@@ -231,6 +246,7 @@ struct iwl_cfg {
u8 valid_rx_ant;
bool need_pll_cfg;
bool use_isr_legacy;
+ enum iwl_pa_type pa_type;
};
/***************************
@@ -250,7 +266,7 @@ int iwl_full_rxon_required(struct iwl_priv *priv);
void iwl_set_rxon_chain(struct iwl_priv *priv);
int iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch);
void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_info *ht_info);
-u8 iwl_is_fat_tx_allowed(struct iwl_priv *priv,
+u8 iwl_is_ht40_tx_allowed(struct iwl_priv *priv,
struct ieee80211_sta_ht_cap *sta_ht_inf);
void iwl_set_flags_for_band(struct iwl_priv *priv, enum ieee80211_band band);
void iwl_connection_init_rx_config(struct iwl_priv *priv, int mode);
@@ -286,7 +302,55 @@ void iwl_config_ap(struct iwl_priv *priv);
int iwl_mac_get_tx_stats(struct ieee80211_hw *hw,
struct ieee80211_tx_queue_stats *stats);
void iwl_mac_reset_tsf(struct ieee80211_hw *hw);
+#ifdef CONFIG_IWLWIFI_DEBUGFS
+int iwl_alloc_traffic_mem(struct iwl_priv *priv);
+void iwl_free_traffic_mem(struct iwl_priv *priv);
+void iwl_reset_traffic_log(struct iwl_priv *priv);
+void iwl_dbg_log_tx_data_frame(struct iwl_priv *priv,
+ u16 length, struct ieee80211_hdr *header);
+void iwl_dbg_log_rx_data_frame(struct iwl_priv *priv,
+ u16 length, struct ieee80211_hdr *header);
+const char *get_mgmt_string(int cmd);
+const char *get_ctrl_string(int cmd);
+void iwl_clear_tx_stats(struct iwl_priv *priv);
+void iwl_clear_rx_stats(struct iwl_priv *priv);
+void iwl_update_stats(struct iwl_priv *priv, bool is_tx, __le16 fc,
+ u16 len);
+#else
+static inline int iwl_alloc_traffic_mem(struct iwl_priv *priv)
+{
+ return 0;
+}
+static inline void iwl_free_traffic_mem(struct iwl_priv *priv)
+{
+}
+static inline void iwl_reset_traffic_log(struct iwl_priv *priv)
+{
+}
+static inline void iwl_dbg_log_tx_data_frame(struct iwl_priv *priv,
+ u16 length, struct ieee80211_hdr *header)
+{
+}
+static inline void iwl_dbg_log_rx_data_frame(struct iwl_priv *priv,
+ u16 length, struct ieee80211_hdr *header)
+{
+}
+static inline void iwl_update_stats(struct iwl_priv *priv, bool is_tx,
+ __le16 fc, u16 len)
+{
+ struct traffic_stats *stats;
+
+ if (is_tx)
+ stats = &priv->tx_stats;
+ else
+ stats = &priv->rx_stats;
+ if (ieee80211_is_data(fc)) {
+ /* data */
+ stats->data_bytes += len;
+ }
+}
+#endif
/*****************************************************
* RX handlers.
* **************************************************/
@@ -384,7 +448,6 @@ static inline __le32 iwl_hw_set_rate_n_flags(u8 rate, u32 flags)
void iwl_init_scan_params(struct iwl_priv *priv);
int iwl_scan_cancel(struct iwl_priv *priv);
int iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms);
-int iwl_scan_initiate(struct iwl_priv *priv);
int iwl_mac_hw_scan(struct ieee80211_hw *hw, struct cfg80211_scan_request *req);
u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame,
const u8 *ie, int ie_len, int left);
@@ -398,7 +461,6 @@ void iwl_bg_scan_check(struct work_struct *data);
void iwl_bg_abort_scan(struct work_struct *work);
void iwl_bg_scan_completed(struct work_struct *work);
void iwl_setup_scan_deferred_work(struct iwl_priv *priv);
-int iwl_send_scan_abort(struct iwl_priv *priv);
/* For faster active scanning, scan will move to the next channel if fewer than
* PLCP_QUIET_THRESH packets are heard on this channel within
@@ -437,9 +499,9 @@ int __must_check iwl_send_cmd_pdu(struct iwl_priv *priv, u8 id,
u16 len, const void *data);
int iwl_send_cmd_pdu_async(struct iwl_priv *priv, u8 id, u16 len,
const void *data,
- int (*callback)(struct iwl_priv *priv,
- struct iwl_cmd *cmd,
- struct sk_buff *skb));
+ void (*callback)(struct iwl_priv *priv,
+ struct iwl_device_cmd *cmd,
+ struct sk_buff *skb));
int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd);
@@ -449,8 +511,6 @@ int iwl_send_card_state(struct iwl_priv *priv, u32 flags,
/*****************************************************
* PCI *
*****************************************************/
-void iwl_disable_interrupts(struct iwl_priv *priv);
-void iwl_enable_interrupts(struct iwl_priv *priv);
irqreturn_t iwl_isr_legacy(int irq, void *data);
int iwl_reset_ict(struct iwl_priv *priv);
void iwl_disable_ict(struct iwl_priv *priv);
@@ -474,7 +534,6 @@ int iwl_pci_resume(struct pci_dev *pdev);
/*****************************************************
* Error Handling Debugging
******************************************************/
-void iwl_dump_nic_error_log(struct iwl_priv *priv);
void iwl_dump_nic_event_log(struct iwl_priv *priv);
void iwl_clear_isr_stats(struct iwl_priv *priv);
@@ -556,6 +615,7 @@ extern void iwl_rx_reply_rx_phy(struct iwl_priv *priv,
void iwl_rx_reply_compressed_ba(struct iwl_priv *priv,
struct iwl_rx_mem_buffer *rxb);
+void iwl_setup_rxon_timing(struct iwl_priv *priv);
static inline int iwl_send_rxon_assoc(struct iwl_priv *priv)
{
return priv->cfg->ops->hcmd->rxon_assoc(priv);
diff --git a/drivers/net/wireless/iwlwifi/iwl-csr.h b/drivers/net/wireless/iwlwifi/iwl-csr.h
index f03dae1b2f3..06437d13e73 100644
--- a/drivers/net/wireless/iwlwifi/iwl-csr.h
+++ b/drivers/net/wireless/iwlwifi/iwl-csr.h
@@ -91,7 +91,8 @@
#define CSR_EEPROM_GP (CSR_BASE+0x030)
#define CSR_OTP_GP_REG (CSR_BASE+0x034)
#define CSR_GIO_REG (CSR_BASE+0x03C)
-#define CSR_GP_UCODE (CSR_BASE+0x044)
+#define CSR_GP_UCODE_REG (CSR_BASE+0x048)
+#define CSR_GP_DRIVER_REG (CSR_BASE+0x050)
#define CSR_UCODE_DRV_GP1 (CSR_BASE+0x054)
#define CSR_UCODE_DRV_GP1_SET (CSR_BASE+0x058)
#define CSR_UCODE_DRV_GP1_CLR (CSR_BASE+0x05c)
@@ -245,6 +246,13 @@
#define CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED (0x00000004)
#define CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT (0x00000008)
+/* GP Driver */
+#define CSR_GP_DRIVER_REG_BIT_RADIO_SKU_MSK (0x00000003)
+#define CSR_GP_DRIVER_REG_BIT_RADIO_SKU_3x3_HYB (0x00000000)
+#define CSR_GP_DRIVER_REG_BIT_RADIO_SKU_2x2_HYB (0x00000001)
+#define CSR_GP_DRIVER_REG_BIT_RADIO_SKU_2x2_IPA (0x00000002)
+
+
/* GI Chicken Bits */
#define CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX (0x00800000)
#define CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER (0x20000000)
diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h
index 2cf014f523b..723f38a023c 100644
--- a/drivers/net/wireless/iwlwifi/iwl-debug.h
+++ b/drivers/net/wireless/iwlwifi/iwl-debug.h
@@ -30,16 +30,23 @@
#define __iwl_debug_h__
struct iwl_priv;
+extern u32 iwl_debug_level;
#define IWL_ERR(p, f, a...) dev_err(&((p)->pci_dev->dev), f, ## a)
#define IWL_WARN(p, f, a...) dev_warn(&((p)->pci_dev->dev), f, ## a)
#define IWL_INFO(p, f, a...) dev_info(&((p)->pci_dev->dev), f, ## a)
#define IWL_CRIT(p, f, a...) dev_crit(&((p)->pci_dev->dev), f, ## a)
+#define iwl_print_hex_error(priv, p, len) \
+do { \
+ print_hex_dump(KERN_ERR, "iwl data: ", \
+ DUMP_PREFIX_OFFSET, 16, 1, p, len, 1); \
+} while (0)
+
#ifdef CONFIG_IWLWIFI_DEBUG
#define IWL_DEBUG(__priv, level, fmt, args...) \
do { \
- if (__priv->debug_level & (level)) \
+ if (iwl_get_debug_level(__priv) & (level)) \
dev_printk(KERN_ERR, &(__priv->hw->wiphy->dev), \
"%c %s " fmt, in_interrupt() ? 'I' : 'U', \
__func__ , ## args); \
@@ -47,7 +54,7 @@ do { \
#define IWL_DEBUG_LIMIT(__priv, level, fmt, args...) \
do { \
- if ((__priv->debug_level & (level)) && net_ratelimit()) \
+ if ((iwl_get_debug_level(__priv) & (level)) && net_ratelimit()) \
dev_printk(KERN_ERR, &(__priv->hw->wiphy->dev), \
"%c %s " fmt, in_interrupt() ? 'I' : 'U', \
__func__ , ## args); \
@@ -55,7 +62,7 @@ do { \
#define iwl_print_hex_dump(priv, level, p, len) \
do { \
- if (priv->debug_level & level) \
+ if (iwl_get_debug_level(priv) & level) \
print_hex_dump(KERN_DEBUG, "iwl data: ", \
DUMP_PREFIX_OFFSET, 16, 1, p, len, 1); \
} while (0)
@@ -65,23 +72,42 @@ struct iwl_debugfs {
const char *name;
struct dentry *dir_drv;
struct dentry *dir_data;
+ struct dentry *dir_debug;
struct dentry *dir_rf;
struct dir_data_files {
struct dentry *file_sram;
struct dentry *file_nvm;
struct dentry *file_stations;
- struct dentry *file_rx_statistics;
- struct dentry *file_tx_statistics;
struct dentry *file_log_event;
struct dentry *file_channels;
struct dentry *file_status;
struct dentry *file_interrupt;
+ struct dentry *file_qos;
+ struct dentry *file_thermal_throttling;
+#ifdef CONFIG_IWLWIFI_LEDS
+ struct dentry *file_led;
+#endif
+ struct dentry *file_disable_ht40;
+ struct dentry *file_sleep_level_override;
+ struct dentry *file_current_sleep_command;
} dbgfs_data_files;
struct dir_rf_files {
struct dentry *file_disable_sensitivity;
struct dentry *file_disable_chain_noise;
struct dentry *file_disable_tx_power;
} dbgfs_rf_files;
+ struct dir_debug_files {
+ struct dentry *file_rx_statistics;
+ struct dentry *file_tx_statistics;
+ struct dentry *file_traffic_log;
+ struct dentry *file_rx_queue;
+ struct dentry *file_tx_queue;
+ struct dentry *file_ucode_rx_stats;
+ struct dentry *file_ucode_tx_stats;
+ struct dentry *file_ucode_general_stats;
+ struct dentry *file_sensitivity;
+ struct dentry *file_chain_noise;
+ } dbgfs_debug_files;
u32 sram_offset;
u32 sram_len;
};
diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c
index ca00cc8ad4c..f68fb4711da 100644
--- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c
@@ -38,7 +38,7 @@
#include "iwl-debug.h"
#include "iwl-core.h"
#include "iwl-io.h"
-
+#include "iwl-calib.h"
/* create and remove of files */
#define DEBUGFS_ADD_DIR(name, parent) do { \
@@ -49,7 +49,8 @@
#define DEBUGFS_ADD_FILE(name, parent) do { \
dbgfs->dbgfs_##parent##_files.file_##name = \
- debugfs_create_file(#name, 0644, dbgfs->dir_##parent, priv, \
+ debugfs_create_file(#name, S_IWUSR | S_IRUSR, \
+ dbgfs->dir_##parent, priv, \
&iwl_dbgfs_##name##_ops); \
if (!(dbgfs->dbgfs_##parent##_files.file_##name)) \
goto err; \
@@ -57,7 +58,8 @@
#define DEBUGFS_ADD_BOOL(name, parent, ptr) do { \
dbgfs->dbgfs_##parent##_files.file_##name = \
- debugfs_create_bool(#name, 0644, dbgfs->dir_##parent, ptr); \
+ debugfs_create_bool(#name, S_IWUSR | S_IRUSR, \
+ dbgfs->dir_##parent, ptr); \
if (IS_ERR(dbgfs->dbgfs_##parent##_files.file_##name) \
|| !dbgfs->dbgfs_##parent##_files.file_##name) \
goto err; \
@@ -65,7 +67,7 @@
#define DEBUGFS_ADD_X32(name, parent, ptr) do { \
dbgfs->dbgfs_##parent##_files.file_##name = \
- debugfs_create_x32(#name, 0444, dbgfs->dir_##parent, ptr); \
+ debugfs_create_x32(#name, S_IRUSR, dbgfs->dir_##parent, ptr); \
if (IS_ERR(dbgfs->dbgfs_##parent##_files.file_##name) \
|| !dbgfs->dbgfs_##parent##_files.file_##name) \
goto err; \
@@ -124,18 +126,58 @@ static ssize_t iwl_dbgfs_tx_statistics_read(struct file *file,
size_t count, loff_t *ppos) {
struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
- char buf[256];
+ char *buf;
int pos = 0;
- const size_t bufsz = sizeof(buf);
- pos += scnprintf(buf + pos, bufsz - pos, "mgmt: %u\n",
- priv->tx_stats[0].cnt);
- pos += scnprintf(buf + pos, bufsz - pos, "ctrl: %u\n",
- priv->tx_stats[1].cnt);
- pos += scnprintf(buf + pos, bufsz - pos, "data: %u\n",
- priv->tx_stats[2].cnt);
+ int cnt;
+ ssize_t ret;
+ const size_t bufsz = 100 + sizeof(char) * 24 * (MANAGEMENT_MAX + CONTROL_MAX);
+ buf = kzalloc(bufsz, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+ pos += scnprintf(buf + pos, bufsz - pos, "Management:\n");
+ for (cnt = 0; cnt < MANAGEMENT_MAX; cnt++) {
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "\t%s\t\t: %u\n",
+ get_mgmt_string(cnt),
+ priv->tx_stats.mgmt[cnt]);
+ }
+ pos += scnprintf(buf + pos, bufsz - pos, "Control\n");
+ for (cnt = 0; cnt < CONTROL_MAX; cnt++) {
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "\t%s\t\t: %u\n",
+ get_ctrl_string(cnt),
+ priv->tx_stats.ctrl[cnt]);
+ }
+ pos += scnprintf(buf + pos, bufsz - pos, "Data:\n");
+ pos += scnprintf(buf + pos, bufsz - pos, "\tcnt: %u\n",
+ priv->tx_stats.data_cnt);
+ pos += scnprintf(buf + pos, bufsz - pos, "\tbytes: %llu\n",
+ priv->tx_stats.data_bytes);
+ ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+ kfree(buf);
+ return ret;
+}
+
+static ssize_t iwl_dbgfs_tx_statistics_write(struct file *file,
+ const char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct iwl_priv *priv = file->private_data;
+ u32 clear_flag;
+ char buf[8];
+ int buf_size;
- return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+ memset(buf, 0, sizeof(buf));
+ buf_size = min(count, sizeof(buf) - 1);
+ if (copy_from_user(buf, user_buf, buf_size))
+ return -EFAULT;
+ if (sscanf(buf, "%x", &clear_flag) != 1)
+ return -EFAULT;
+ if (clear_flag == 1)
+ iwl_clear_tx_stats(priv);
+
+ return count;
}
static ssize_t iwl_dbgfs_rx_statistics_read(struct file *file,
@@ -143,18 +185,59 @@ static ssize_t iwl_dbgfs_rx_statistics_read(struct file *file,
size_t count, loff_t *ppos) {
struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
- char buf[256];
+ char *buf;
int pos = 0;
- const size_t bufsz = sizeof(buf);
+ int cnt;
+ ssize_t ret;
+ const size_t bufsz = 100 +
+ sizeof(char) * 24 * (MANAGEMENT_MAX + CONTROL_MAX);
+ buf = kzalloc(bufsz, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
- pos += scnprintf(buf + pos, bufsz - pos, "mgmt: %u\n",
- priv->rx_stats[0].cnt);
- pos += scnprintf(buf + pos, bufsz - pos, "ctrl: %u\n",
- priv->rx_stats[1].cnt);
- pos += scnprintf(buf + pos, bufsz - pos, "data: %u\n",
- priv->rx_stats[2].cnt);
+ pos += scnprintf(buf + pos, bufsz - pos, "Management:\n");
+ for (cnt = 0; cnt < MANAGEMENT_MAX; cnt++) {
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "\t%s\t\t: %u\n",
+ get_mgmt_string(cnt),
+ priv->rx_stats.mgmt[cnt]);
+ }
+ pos += scnprintf(buf + pos, bufsz - pos, "Control:\n");
+ for (cnt = 0; cnt < CONTROL_MAX; cnt++) {
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "\t%s\t\t: %u\n",
+ get_ctrl_string(cnt),
+ priv->rx_stats.ctrl[cnt]);
+ }
+ pos += scnprintf(buf + pos, bufsz - pos, "Data:\n");
+ pos += scnprintf(buf + pos, bufsz - pos, "\tcnt: %u\n",
+ priv->rx_stats.data_cnt);
+ pos += scnprintf(buf + pos, bufsz - pos, "\tbytes: %llu\n",
+ priv->rx_stats.data_bytes);
- return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+ ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+ kfree(buf);
+ return ret;
+}
+
+static ssize_t iwl_dbgfs_rx_statistics_write(struct file *file,
+ const char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct iwl_priv *priv = file->private_data;
+ u32 clear_flag;
+ char buf[8];
+ int buf_size;
+
+ memset(buf, 0, sizeof(buf));
+ buf_size = min(count, sizeof(buf) - 1);
+ if (copy_from_user(buf, user_buf, buf_size))
+ return -EFAULT;
+ if (sscanf(buf, "%x", &clear_flag) != 1)
+ return -EFAULT;
+ if (clear_flag == 1)
+ iwl_clear_rx_stats(priv);
+ return count;
}
#define BYTE1_MASK 0x000000ff;
@@ -566,16 +649,930 @@ static ssize_t iwl_dbgfs_interrupt_write(struct file *file,
return count;
}
+static ssize_t iwl_dbgfs_qos_read(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
+ int pos = 0, i;
+ char buf[256];
+ const size_t bufsz = sizeof(buf);
+ ssize_t ret;
+
+ for (i = 0; i < AC_NUM; i++) {
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "\tcw_min\tcw_max\taifsn\ttxop\n");
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "AC[%d]\t%u\t%u\t%u\t%u\n", i,
+ priv->qos_data.def_qos_parm.ac[i].cw_min,
+ priv->qos_data.def_qos_parm.ac[i].cw_max,
+ priv->qos_data.def_qos_parm.ac[i].aifsn,
+ priv->qos_data.def_qos_parm.ac[i].edca_txop);
+ }
+ ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+ return ret;
+}
+
+#ifdef CONFIG_IWLWIFI_LEDS
+static ssize_t iwl_dbgfs_led_read(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
+ int pos = 0;
+ char buf[256];
+ const size_t bufsz = sizeof(buf);
+ ssize_t ret;
+
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "allow blinking: %s\n",
+ (priv->allow_blinking) ? "True" : "False");
+ if (priv->allow_blinking) {
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "Led blinking rate: %u\n",
+ priv->last_blink_rate);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "Last blink time: %lu\n",
+ priv->last_blink_time);
+ }
+
+ ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+ return ret;
+}
+#endif
+
+static ssize_t iwl_dbgfs_thermal_throttling_read(struct file *file,
+ char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
+ struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
+ struct iwl_tt_restriction *restriction;
+ char buf[100];
+ int pos = 0;
+ const size_t bufsz = sizeof(buf);
+ ssize_t ret;
+
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "Thermal Throttling Mode: %s\n",
+ tt->advanced_tt ? "Advance" : "Legacy");
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "Thermal Throttling State: %d\n",
+ tt->state);
+ if (tt->advanced_tt) {
+ restriction = tt->restriction + tt->state;
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "Tx mode: %d\n",
+ restriction->tx_stream);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "Rx mode: %d\n",
+ restriction->rx_stream);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "HT mode: %d\n",
+ restriction->is_ht);
+ }
+ ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+ return ret;
+}
+
+static ssize_t iwl_dbgfs_disable_ht40_write(struct file *file,
+ const char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct iwl_priv *priv = file->private_data;
+ char buf[8];
+ int buf_size;
+ int ht40;
+
+ memset(buf, 0, sizeof(buf));
+ buf_size = min(count, sizeof(buf) - 1);
+ if (copy_from_user(buf, user_buf, buf_size))
+ return -EFAULT;
+ if (sscanf(buf, "%d", &ht40) != 1)
+ return -EFAULT;
+ if (!iwl_is_associated(priv))
+ priv->disable_ht40 = ht40 ? true : false;
+ else {
+ IWL_ERR(priv, "Sta associated with AP - "
+ "Change to 40MHz channel support is not allowed\n");
+ return -EINVAL;
+ }
+
+ return count;
+}
+
+static ssize_t iwl_dbgfs_disable_ht40_read(struct file *file,
+ char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
+ char buf[100];
+ int pos = 0;
+ const size_t bufsz = sizeof(buf);
+ ssize_t ret;
+
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "11n 40MHz Mode: %s\n",
+ priv->disable_ht40 ? "Disabled" : "Enabled");
+ ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+ return ret;
+}
+
+static ssize_t iwl_dbgfs_sleep_level_override_write(struct file *file,
+ const char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct iwl_priv *priv = file->private_data;
+ char buf[8];
+ int buf_size;
+ int value;
+
+ memset(buf, 0, sizeof(buf));
+ buf_size = min(count, sizeof(buf) - 1);
+ if (copy_from_user(buf, user_buf, buf_size))
+ return -EFAULT;
+
+ if (sscanf(buf, "%d", &value) != 1)
+ return -EINVAL;
+
+ /*
+ * Our users expect 0 to be "CAM", but 0 isn't actually
+ * valid here. However, let's not confuse them and present
+ * IWL_POWER_INDEX_1 as "1", not "0".
+ */
+ if (value > 0)
+ value -= 1;
+
+ if (value != -1 && (value < 0 || value >= IWL_POWER_NUM))
+ return -EINVAL;
+
+ priv->power_data.debug_sleep_level_override = value;
+
+ iwl_power_update_mode(priv, false);
+
+ return count;
+}
+
+static ssize_t iwl_dbgfs_sleep_level_override_read(struct file *file,
+ char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
+ char buf[10];
+ int pos, value;
+ const size_t bufsz = sizeof(buf);
+
+ /* see the write function */
+ value = priv->power_data.debug_sleep_level_override;
+ if (value >= 0)
+ value += 1;
+
+ pos = scnprintf(buf, bufsz, "%d\n", value);
+ return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+}
+
+static ssize_t iwl_dbgfs_current_sleep_command_read(struct file *file,
+ char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
+ char buf[200];
+ int pos = 0, i;
+ const size_t bufsz = sizeof(buf);
+ struct iwl_powertable_cmd *cmd = &priv->power_data.sleep_cmd;
+
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "flags: %#.2x\n", le16_to_cpu(cmd->flags));
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "RX/TX timeout: %d/%d usec\n",
+ le32_to_cpu(cmd->rx_data_timeout),
+ le32_to_cpu(cmd->tx_data_timeout));
+ for (i = 0; i < IWL_POWER_VEC_SIZE; i++)
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "sleep_interval[%d]: %d\n", i,
+ le32_to_cpu(cmd->sleep_interval[i]));
+
+ return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+}
DEBUGFS_READ_WRITE_FILE_OPS(sram);
DEBUGFS_WRITE_FILE_OPS(log_event);
DEBUGFS_READ_FILE_OPS(nvm);
DEBUGFS_READ_FILE_OPS(stations);
-DEBUGFS_READ_FILE_OPS(rx_statistics);
-DEBUGFS_READ_FILE_OPS(tx_statistics);
DEBUGFS_READ_FILE_OPS(channels);
DEBUGFS_READ_FILE_OPS(status);
DEBUGFS_READ_WRITE_FILE_OPS(interrupt);
+DEBUGFS_READ_FILE_OPS(qos);
+#ifdef CONFIG_IWLWIFI_LEDS
+DEBUGFS_READ_FILE_OPS(led);
+#endif
+DEBUGFS_READ_FILE_OPS(thermal_throttling);
+DEBUGFS_READ_WRITE_FILE_OPS(disable_ht40);
+DEBUGFS_READ_WRITE_FILE_OPS(sleep_level_override);
+DEBUGFS_READ_FILE_OPS(current_sleep_command);
+
+static ssize_t iwl_dbgfs_traffic_log_read(struct file *file,
+ char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct iwl_priv *priv = file->private_data;
+ int pos = 0, ofs = 0;
+ int cnt = 0, entry;
+ struct iwl_tx_queue *txq;
+ struct iwl_queue *q;
+ struct iwl_rx_queue *rxq = &priv->rxq;
+ char *buf;
+ int bufsz = ((IWL_TRAFFIC_ENTRIES * IWL_TRAFFIC_ENTRY_SIZE * 64) * 2) +
+ (IWL_MAX_NUM_QUEUES * 32 * 8) + 400;
+ const u8 *ptr;
+ ssize_t ret;
+
+ buf = kzalloc(bufsz, GFP_KERNEL);
+ if (!buf) {
+ IWL_ERR(priv, "Can not allocate buffer\n");
+ return -ENOMEM;
+ }
+ pos += scnprintf(buf + pos, bufsz - pos, "Tx Queue\n");
+ for (cnt = 0; cnt < priv->hw_params.max_txq_num; cnt++) {
+ txq = &priv->txq[cnt];
+ q = &txq->q;
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "q[%d]: read_ptr: %u, write_ptr: %u\n",
+ cnt, q->read_ptr, q->write_ptr);
+ }
+ if (priv->tx_traffic && (iwl_debug_level & IWL_DL_TX)) {
+ ptr = priv->tx_traffic;
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "Tx Traffic idx: %u\n", priv->tx_traffic_idx);
+ for (cnt = 0, ofs = 0; cnt < IWL_TRAFFIC_ENTRIES; cnt++) {
+ for (entry = 0; entry < IWL_TRAFFIC_ENTRY_SIZE / 16;
+ entry++, ofs += 16) {
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "0x%.4x ", ofs);
+ hex_dump_to_buffer(ptr + ofs, 16, 16, 2,
+ buf + pos, bufsz - pos, 0);
+ pos += strlen(buf);
+ if (bufsz - pos > 0)
+ buf[pos++] = '\n';
+ }
+ }
+ }
+
+ pos += scnprintf(buf + pos, bufsz - pos, "Rx Queue\n");
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "read: %u, write: %u\n",
+ rxq->read, rxq->write);
+
+ if (priv->rx_traffic && (iwl_debug_level & IWL_DL_RX)) {
+ ptr = priv->rx_traffic;
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "Rx Traffic idx: %u\n", priv->rx_traffic_idx);
+ for (cnt = 0, ofs = 0; cnt < IWL_TRAFFIC_ENTRIES; cnt++) {
+ for (entry = 0; entry < IWL_TRAFFIC_ENTRY_SIZE / 16;
+ entry++, ofs += 16) {
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "0x%.4x ", ofs);
+ hex_dump_to_buffer(ptr + ofs, 16, 16, 2,
+ buf + pos, bufsz - pos, 0);
+ pos += strlen(buf);
+ if (bufsz - pos > 0)
+ buf[pos++] = '\n';
+ }
+ }
+ }
+
+ ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+ kfree(buf);
+ return ret;
+}
+
+static ssize_t iwl_dbgfs_traffic_log_write(struct file *file,
+ const char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct iwl_priv *priv = file->private_data;
+ char buf[8];
+ int buf_size;
+ int traffic_log;
+
+ memset(buf, 0, sizeof(buf));
+ buf_size = min(count, sizeof(buf) - 1);
+ if (copy_from_user(buf, user_buf, buf_size))
+ return -EFAULT;
+ if (sscanf(buf, "%d", &traffic_log) != 1)
+ return -EFAULT;
+ if (traffic_log == 0)
+ iwl_reset_traffic_log(priv);
+
+ return count;
+}
+
+static ssize_t iwl_dbgfs_tx_queue_read(struct file *file,
+ char __user *user_buf,
+ size_t count, loff_t *ppos) {
+
+ struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
+ struct iwl_tx_queue *txq;
+ struct iwl_queue *q;
+ char *buf;
+ int pos = 0;
+ int cnt;
+ int ret;
+ const size_t bufsz = sizeof(char) * 60 * IWL_MAX_NUM_QUEUES;
+
+ buf = kzalloc(bufsz, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ for (cnt = 0; cnt < priv->hw_params.max_txq_num; cnt++) {
+ txq = &priv->txq[cnt];
+ q = &txq->q;
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "hwq %.2d: read=%u write=%u stop=%d"
+ " swq_id=%#.2x (ac %d/hwq %d)\n",
+ cnt, q->read_ptr, q->write_ptr,
+ !!test_bit(cnt, priv->queue_stopped),
+ txq->swq_id,
+ txq->swq_id & 0x80 ? txq->swq_id & 3 :
+ txq->swq_id,
+ txq->swq_id & 0x80 ? (txq->swq_id >> 2) &
+ 0x1f : txq->swq_id);
+ if (cnt >= 4)
+ continue;
+ /* for the ACs, display the stop count too */
+ pos += scnprintf(buf + pos, bufsz - pos,
+ " stop-count: %d\n",
+ atomic_read(&priv->queue_stop_count[cnt]));
+ }
+ ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+ kfree(buf);
+ return ret;
+}
+
+static ssize_t iwl_dbgfs_rx_queue_read(struct file *file,
+ char __user *user_buf,
+ size_t count, loff_t *ppos) {
+
+ struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
+ struct iwl_rx_queue *rxq = &priv->rxq;
+ char buf[256];
+ int pos = 0;
+ const size_t bufsz = sizeof(buf);
+
+ pos += scnprintf(buf + pos, bufsz - pos, "read: %u\n",
+ rxq->read);
+ pos += scnprintf(buf + pos, bufsz - pos, "write: %u\n",
+ rxq->write);
+ pos += scnprintf(buf + pos, bufsz - pos, "free_count: %u\n",
+ rxq->free_count);
+ pos += scnprintf(buf + pos, bufsz - pos, "closed_rb_num: %u\n",
+ le16_to_cpu(rxq->rb_stts->closed_rb_num) & 0x0FFF);
+ return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+}
+
+#define UCODE_STATISTICS_CLEAR_MSK (0x1 << 0)
+#define UCODE_STATISTICS_FREQUENCY_MSK (0x1 << 1)
+#define UCODE_STATISTICS_NARROW_BAND_MSK (0x1 << 2)
+
+static int iwl_dbgfs_statistics_flag(struct iwl_priv *priv, char *buf,
+ int bufsz)
+{
+ int p = 0;
+
+ p += scnprintf(buf + p, bufsz - p,
+ "Statistics Flag(0x%X):\n",
+ le32_to_cpu(priv->statistics.flag));
+ if (le32_to_cpu(priv->statistics.flag) & UCODE_STATISTICS_CLEAR_MSK)
+ p += scnprintf(buf + p, bufsz - p,
+ "\tStatistics have been cleared\n");
+ p += scnprintf(buf + p, bufsz - p,
+ "\tOperational Frequency: %s\n",
+ (le32_to_cpu(priv->statistics.flag) &
+ UCODE_STATISTICS_FREQUENCY_MSK)
+ ? "2.4 GHz" : "5.2 GHz");
+ p += scnprintf(buf + p, bufsz - p,
+ "\tTGj Narrow Band: %s\n",
+ (le32_to_cpu(priv->statistics.flag) &
+ UCODE_STATISTICS_NARROW_BAND_MSK)
+ ? "enabled" : "disabled");
+ return p;
+}
+
+
+static ssize_t iwl_dbgfs_ucode_rx_stats_read(struct file *file,
+ char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
+ int pos = 0;
+ char *buf;
+ int bufsz = sizeof(struct statistics_rx_phy) * 20 +
+ sizeof(struct statistics_rx_non_phy) * 20 +
+ sizeof(struct statistics_rx_ht_phy) * 20 + 400;
+ ssize_t ret;
+ struct statistics_rx_phy *ofdm;
+ struct statistics_rx_phy *cck;
+ struct statistics_rx_non_phy *general;
+ struct statistics_rx_ht_phy *ht;
+
+ if (!iwl_is_alive(priv))
+ return -EAGAIN;
+
+ /* make request to uCode to retrieve statistics information */
+ mutex_lock(&priv->mutex);
+ ret = iwl_send_statistics_request(priv, 0);
+ mutex_unlock(&priv->mutex);
+
+ if (ret) {
+ IWL_ERR(priv,
+ "Error sending statistics request: %zd\n", ret);
+ return -EAGAIN;
+ }
+ buf = kzalloc(bufsz, GFP_KERNEL);
+ if (!buf) {
+ IWL_ERR(priv, "Can not allocate Buffer\n");
+ return -ENOMEM;
+ }
+
+ /* the statistic information display here is based on
+ * the last statistics notification from uCode
+ * might not reflect the current uCode activity
+ */
+ ofdm = &priv->statistics.rx.ofdm;
+ cck = &priv->statistics.rx.cck;
+ general = &priv->statistics.rx.general;
+ ht = &priv->statistics.rx.ofdm_ht;
+ pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz);
+ pos += scnprintf(buf + pos, bufsz - pos, "Statistics_Rx - OFDM:\n");
+ pos += scnprintf(buf + pos, bufsz - pos, "ina_cnt: %u\n",
+ le32_to_cpu(ofdm->ina_cnt));
+ pos += scnprintf(buf + pos, bufsz - pos, "fina_cnt: %u\n",
+ le32_to_cpu(ofdm->fina_cnt));
+ pos += scnprintf(buf + pos, bufsz - pos, "plcp_err: %u\n",
+ le32_to_cpu(ofdm->plcp_err));
+ pos += scnprintf(buf + pos, bufsz - pos, "crc32_err: %u\n",
+ le32_to_cpu(ofdm->crc32_err));
+ pos += scnprintf(buf + pos, bufsz - pos, "overrun_err: %u\n",
+ le32_to_cpu(ofdm->overrun_err));
+ pos += scnprintf(buf + pos, bufsz - pos, "early_overrun_err: %u\n",
+ le32_to_cpu(ofdm->early_overrun_err));
+ pos += scnprintf(buf + pos, bufsz - pos, "crc32_good: %u\n",
+ le32_to_cpu(ofdm->crc32_good));
+ pos += scnprintf(buf + pos, bufsz - pos, "false_alarm_cnt: %u\n",
+ le32_to_cpu(ofdm->false_alarm_cnt));
+ pos += scnprintf(buf + pos, bufsz - pos, "fina_sync_err_cnt: %u\n",
+ le32_to_cpu(ofdm->fina_sync_err_cnt));
+ pos += scnprintf(buf + pos, bufsz - pos, "sfd_timeout: %u\n",
+ le32_to_cpu(ofdm->sfd_timeout));
+ pos += scnprintf(buf + pos, bufsz - pos, "fina_timeout: %u\n",
+ le32_to_cpu(ofdm->fina_timeout));
+ pos += scnprintf(buf + pos, bufsz - pos, "unresponded_rts: %u\n",
+ le32_to_cpu(ofdm->unresponded_rts));
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "rxe_frame_limit_overrun: %u\n",
+ le32_to_cpu(ofdm->rxe_frame_limit_overrun));
+ pos += scnprintf(buf + pos, bufsz - pos, "sent_ack_cnt: %u\n",
+ le32_to_cpu(ofdm->sent_ack_cnt));
+ pos += scnprintf(buf + pos, bufsz - pos, "sent_cts_cnt: %u\n",
+ le32_to_cpu(ofdm->sent_cts_cnt));
+ pos += scnprintf(buf + pos, bufsz - pos, "sent_ba_rsp_cnt: %u\n",
+ le32_to_cpu(ofdm->sent_ba_rsp_cnt));
+ pos += scnprintf(buf + pos, bufsz - pos, "dsp_self_kill: %u\n",
+ le32_to_cpu(ofdm->dsp_self_kill));
+ pos += scnprintf(buf + pos, bufsz - pos, "mh_format_err: %u\n",
+ le32_to_cpu(ofdm->mh_format_err));
+ pos += scnprintf(buf + pos, bufsz - pos, "re_acq_main_rssi_sum: %u\n",
+ le32_to_cpu(ofdm->re_acq_main_rssi_sum));
+
+ pos += scnprintf(buf + pos, bufsz - pos, "Statistics_Rx - CCK:\n");
+ pos += scnprintf(buf + pos, bufsz - pos, "ina_cnt: %u\n",
+ le32_to_cpu(cck->ina_cnt));
+ pos += scnprintf(buf + pos, bufsz - pos, "fina_cnt: %u\n",
+ le32_to_cpu(cck->fina_cnt));
+ pos += scnprintf(buf + pos, bufsz - pos, "plcp_err: %u\n",
+ le32_to_cpu(cck->plcp_err));
+ pos += scnprintf(buf + pos, bufsz - pos, "crc32_err: %u\n",
+ le32_to_cpu(cck->crc32_err));
+ pos += scnprintf(buf + pos, bufsz - pos, "overrun_err: %u\n",
+ le32_to_cpu(cck->overrun_err));
+ pos += scnprintf(buf + pos, bufsz - pos, "early_overrun_err: %u\n",
+ le32_to_cpu(cck->early_overrun_err));
+ pos += scnprintf(buf + pos, bufsz - pos, "crc32_good: %u\n",
+ le32_to_cpu(cck->crc32_good));
+ pos += scnprintf(buf + pos, bufsz - pos, "false_alarm_cnt: %u\n",
+ le32_to_cpu(cck->false_alarm_cnt));
+ pos += scnprintf(buf + pos, bufsz - pos, "fina_sync_err_cnt: %u\n",
+ le32_to_cpu(cck->fina_sync_err_cnt));
+ pos += scnprintf(buf + pos, bufsz - pos, "sfd_timeout: %u\n",
+ le32_to_cpu(cck->sfd_timeout));
+ pos += scnprintf(buf + pos, bufsz - pos, "fina_timeout: %u\n",
+ le32_to_cpu(cck->fina_timeout));
+ pos += scnprintf(buf + pos, bufsz - pos, "unresponded_rts: %u\n",
+ le32_to_cpu(cck->unresponded_rts));
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "rxe_frame_limit_overrun: %u\n",
+ le32_to_cpu(cck->rxe_frame_limit_overrun));
+ pos += scnprintf(buf + pos, bufsz - pos, "sent_ack_cnt: %u\n",
+ le32_to_cpu(cck->sent_ack_cnt));
+ pos += scnprintf(buf + pos, bufsz - pos, "sent_cts_cnt: %u\n",
+ le32_to_cpu(cck->sent_cts_cnt));
+ pos += scnprintf(buf + pos, bufsz - pos, "sent_ba_rsp_cnt: %u\n",
+ le32_to_cpu(cck->sent_ba_rsp_cnt));
+ pos += scnprintf(buf + pos, bufsz - pos, "dsp_self_kill: %u\n",
+ le32_to_cpu(cck->dsp_self_kill));
+ pos += scnprintf(buf + pos, bufsz - pos, "mh_format_err: %u\n",
+ le32_to_cpu(cck->mh_format_err));
+ pos += scnprintf(buf + pos, bufsz - pos, "re_acq_main_rssi_sum: %u\n",
+ le32_to_cpu(cck->re_acq_main_rssi_sum));
+
+ pos += scnprintf(buf + pos, bufsz - pos, "Statistics_Rx - GENERAL:\n");
+ pos += scnprintf(buf + pos, bufsz - pos, "bogus_cts: %u\n",
+ le32_to_cpu(general->bogus_cts));
+ pos += scnprintf(buf + pos, bufsz - pos, "bogus_ack: %u\n",
+ le32_to_cpu(general->bogus_ack));
+ pos += scnprintf(buf + pos, bufsz - pos, "non_bssid_frames: %u\n",
+ le32_to_cpu(general->non_bssid_frames));
+ pos += scnprintf(buf + pos, bufsz - pos, "filtered_frames: %u\n",
+ le32_to_cpu(general->filtered_frames));
+ pos += scnprintf(buf + pos, bufsz - pos, "non_channel_beacons: %u\n",
+ le32_to_cpu(general->non_channel_beacons));
+ pos += scnprintf(buf + pos, bufsz - pos, "channel_beacons: %u\n",
+ le32_to_cpu(general->channel_beacons));
+ pos += scnprintf(buf + pos, bufsz - pos, "num_missed_bcon: %u\n",
+ le32_to_cpu(general->num_missed_bcon));
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "adc_rx_saturation_time: %u\n",
+ le32_to_cpu(general->adc_rx_saturation_time));
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "ina_detection_search_time: %u\n",
+ le32_to_cpu(general->ina_detection_search_time));
+ pos += scnprintf(buf + pos, bufsz - pos, "beacon_silence_rssi_a: %u\n",
+ le32_to_cpu(general->beacon_silence_rssi_a));
+ pos += scnprintf(buf + pos, bufsz - pos, "beacon_silence_rssi_b: %u\n",
+ le32_to_cpu(general->beacon_silence_rssi_b));
+ pos += scnprintf(buf + pos, bufsz - pos, "beacon_silence_rssi_c: %u\n",
+ le32_to_cpu(general->beacon_silence_rssi_c));
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "interference_data_flag: %u\n",
+ le32_to_cpu(general->interference_data_flag));
+ pos += scnprintf(buf + pos, bufsz - pos, "channel_load: %u\n",
+ le32_to_cpu(general->channel_load));
+ pos += scnprintf(buf + pos, bufsz - pos, "dsp_false_alarms: %u\n",
+ le32_to_cpu(general->dsp_false_alarms));
+ pos += scnprintf(buf + pos, bufsz - pos, "beacon_rssi_a: %u\n",
+ le32_to_cpu(general->beacon_rssi_a));
+ pos += scnprintf(buf + pos, bufsz - pos, "beacon_rssi_b: %u\n",
+ le32_to_cpu(general->beacon_rssi_b));
+ pos += scnprintf(buf + pos, bufsz - pos, "beacon_rssi_c: %u\n",
+ le32_to_cpu(general->beacon_rssi_c));
+ pos += scnprintf(buf + pos, bufsz - pos, "beacon_energy_a: %u\n",
+ le32_to_cpu(general->beacon_energy_a));
+ pos += scnprintf(buf + pos, bufsz - pos, "beacon_energy_b: %u\n",
+ le32_to_cpu(general->beacon_energy_b));
+ pos += scnprintf(buf + pos, bufsz - pos, "beacon_energy_c: %u\n",
+ le32_to_cpu(general->beacon_energy_c));
+
+ pos += scnprintf(buf + pos, bufsz - pos, "Statistics_Rx - OFDM_HT:\n");
+ pos += scnprintf(buf + pos, bufsz - pos, "plcp_err: %u\n",
+ le32_to_cpu(ht->plcp_err));
+ pos += scnprintf(buf + pos, bufsz - pos, "overrun_err: %u\n",
+ le32_to_cpu(ht->overrun_err));
+ pos += scnprintf(buf + pos, bufsz - pos, "early_overrun_err: %u\n",
+ le32_to_cpu(ht->early_overrun_err));
+ pos += scnprintf(buf + pos, bufsz - pos, "crc32_good: %u\n",
+ le32_to_cpu(ht->crc32_good));
+ pos += scnprintf(buf + pos, bufsz - pos, "crc32_err: %u\n",
+ le32_to_cpu(ht->crc32_err));
+ pos += scnprintf(buf + pos, bufsz - pos, "mh_format_err: %u\n",
+ le32_to_cpu(ht->mh_format_err));
+ pos += scnprintf(buf + pos, bufsz - pos, "agg_crc32_good: %u\n",
+ le32_to_cpu(ht->agg_crc32_good));
+ pos += scnprintf(buf + pos, bufsz - pos, "agg_mpdu_cnt: %u\n",
+ le32_to_cpu(ht->agg_mpdu_cnt));
+ pos += scnprintf(buf + pos, bufsz - pos, "agg_cnt: %u\n",
+ le32_to_cpu(ht->agg_cnt));
+
+ ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+ kfree(buf);
+ return ret;
+}
+
+static ssize_t iwl_dbgfs_ucode_tx_stats_read(struct file *file,
+ char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
+ int pos = 0;
+ char *buf;
+ int bufsz = (sizeof(struct statistics_tx) * 24) + 250;
+ ssize_t ret;
+ struct statistics_tx *tx;
+
+ if (!iwl_is_alive(priv))
+ return -EAGAIN;
+
+ /* make request to uCode to retrieve statistics information */
+ mutex_lock(&priv->mutex);
+ ret = iwl_send_statistics_request(priv, 0);
+ mutex_unlock(&priv->mutex);
+
+ if (ret) {
+ IWL_ERR(priv,
+ "Error sending statistics request: %zd\n", ret);
+ return -EAGAIN;
+ }
+ buf = kzalloc(bufsz, GFP_KERNEL);
+ if (!buf) {
+ IWL_ERR(priv, "Can not allocate Buffer\n");
+ return -ENOMEM;
+ }
+
+ /* the statistic information display here is based on
+ * the last statistics notification from uCode
+ * might not reflect the current uCode activity
+ */
+ tx = &priv->statistics.tx;
+ pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz);
+ pos += scnprintf(buf + pos, bufsz - pos, "Statistics_Tx:\n");
+ pos += scnprintf(buf + pos, bufsz - pos, "preamble: %u\n",
+ le32_to_cpu(tx->preamble_cnt));
+ pos += scnprintf(buf + pos, bufsz - pos, "rx_detected_cnt: %u\n",
+ le32_to_cpu(tx->rx_detected_cnt));
+ pos += scnprintf(buf + pos, bufsz - pos, "bt_prio_defer_cnt: %u\n",
+ le32_to_cpu(tx->bt_prio_defer_cnt));
+ pos += scnprintf(buf + pos, bufsz - pos, "bt_prio_kill_cnt: %u\n",
+ le32_to_cpu(tx->bt_prio_kill_cnt));
+ pos += scnprintf(buf + pos, bufsz - pos, "few_bytes_cnt: %u\n",
+ le32_to_cpu(tx->few_bytes_cnt));
+ pos += scnprintf(buf + pos, bufsz - pos, "cts_timeout: %u\n",
+ le32_to_cpu(tx->cts_timeout));
+ pos += scnprintf(buf + pos, bufsz - pos, "ack_timeout: %u\n",
+ le32_to_cpu(tx->ack_timeout));
+ pos += scnprintf(buf + pos, bufsz - pos, "expected_ack_cnt: %u\n",
+ le32_to_cpu(tx->expected_ack_cnt));
+ pos += scnprintf(buf + pos, bufsz - pos, "actual_ack_cnt: %u\n",
+ le32_to_cpu(tx->actual_ack_cnt));
+ pos += scnprintf(buf + pos, bufsz - pos, "dump_msdu_cnt: %u\n",
+ le32_to_cpu(tx->dump_msdu_cnt));
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "burst_abort_next_frame_mismatch_cnt: %u\n",
+ le32_to_cpu(tx->burst_abort_next_frame_mismatch_cnt));
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "burst_abort_missing_next_frame_cnt: %u\n",
+ le32_to_cpu(tx->burst_abort_missing_next_frame_cnt));
+ pos += scnprintf(buf + pos, bufsz - pos, "cts_timeout_collision: %u\n",
+ le32_to_cpu(tx->cts_timeout_collision));
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "ack_or_ba_timeout_collision: %u\n",
+ le32_to_cpu(tx->ack_or_ba_timeout_collision));
+ pos += scnprintf(buf + pos, bufsz - pos, "agg ba_timeout: %u\n",
+ le32_to_cpu(tx->agg.ba_timeout));
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "agg ba_reschedule_frames: %u\n",
+ le32_to_cpu(tx->agg.ba_reschedule_frames));
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "agg scd_query_agg_frame_cnt: %u\n",
+ le32_to_cpu(tx->agg.scd_query_agg_frame_cnt));
+ pos += scnprintf(buf + pos, bufsz - pos, "agg scd_query_no_agg: %u\n",
+ le32_to_cpu(tx->agg.scd_query_no_agg));
+ pos += scnprintf(buf + pos, bufsz - pos, "agg scd_query_agg: %u\n",
+ le32_to_cpu(tx->agg.scd_query_agg));
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "agg scd_query_mismatch: %u\n",
+ le32_to_cpu(tx->agg.scd_query_mismatch));
+ pos += scnprintf(buf + pos, bufsz - pos, "agg frame_not_ready: %u\n",
+ le32_to_cpu(tx->agg.frame_not_ready));
+ pos += scnprintf(buf + pos, bufsz - pos, "agg underrun: %u\n",
+ le32_to_cpu(tx->agg.underrun));
+ pos += scnprintf(buf + pos, bufsz - pos, "agg bt_prio_kill: %u\n",
+ le32_to_cpu(tx->agg.bt_prio_kill));
+ pos += scnprintf(buf + pos, bufsz - pos, "agg rx_ba_rsp_cnt: %u\n",
+ le32_to_cpu(tx->agg.rx_ba_rsp_cnt));
+
+ ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+ kfree(buf);
+ return ret;
+}
+
+static ssize_t iwl_dbgfs_ucode_general_stats_read(struct file *file,
+ char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
+ int pos = 0;
+ char *buf;
+ int bufsz = sizeof(struct statistics_general) * 4 + 250;
+ ssize_t ret;
+ struct statistics_general *general;
+ struct statistics_dbg *dbg;
+ struct statistics_div *div;
+
+ if (!iwl_is_alive(priv))
+ return -EAGAIN;
+
+ /* make request to uCode to retrieve statistics information */
+ mutex_lock(&priv->mutex);
+ ret = iwl_send_statistics_request(priv, 0);
+ mutex_unlock(&priv->mutex);
+
+ if (ret) {
+ IWL_ERR(priv,
+ "Error sending statistics request: %zd\n", ret);
+ return -EAGAIN;
+ }
+ buf = kzalloc(bufsz, GFP_KERNEL);
+ if (!buf) {
+ IWL_ERR(priv, "Can not allocate Buffer\n");
+ return -ENOMEM;
+ }
+
+ /* the statistic information display here is based on
+ * the last statistics notification from uCode
+ * might not reflect the current uCode activity
+ */
+ general = &priv->statistics.general;
+ dbg = &priv->statistics.general.dbg;
+ div = &priv->statistics.general.div;
+ pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz);
+ pos += scnprintf(buf + pos, bufsz - pos, "Statistics_General:\n");
+ pos += scnprintf(buf + pos, bufsz - pos, "temperature: %u\n",
+ le32_to_cpu(general->temperature));
+ pos += scnprintf(buf + pos, bufsz - pos, "temperature_m: %u\n",
+ le32_to_cpu(general->temperature_m));
+ pos += scnprintf(buf + pos, bufsz - pos, "burst_check: %u\n",
+ le32_to_cpu(dbg->burst_check));
+ pos += scnprintf(buf + pos, bufsz - pos, "burst_count: %u\n",
+ le32_to_cpu(dbg->burst_count));
+ pos += scnprintf(buf + pos, bufsz - pos, "sleep_time: %u\n",
+ le32_to_cpu(general->sleep_time));
+ pos += scnprintf(buf + pos, bufsz - pos, "slots_out: %u\n",
+ le32_to_cpu(general->slots_out));
+ pos += scnprintf(buf + pos, bufsz - pos, "slots_idle: %u\n",
+ le32_to_cpu(general->slots_idle));
+ pos += scnprintf(buf + pos, bufsz - pos, "ttl_timestamp: %u\n",
+ le32_to_cpu(general->ttl_timestamp));
+ pos += scnprintf(buf + pos, bufsz - pos, "tx_on_a: %u\n",
+ le32_to_cpu(div->tx_on_a));
+ pos += scnprintf(buf + pos, bufsz - pos, "tx_on_b: %u\n",
+ le32_to_cpu(div->tx_on_b));
+ pos += scnprintf(buf + pos, bufsz - pos, "exec_time: %u\n",
+ le32_to_cpu(div->exec_time));
+ pos += scnprintf(buf + pos, bufsz - pos, "probe_time: %u\n",
+ le32_to_cpu(div->probe_time));
+ pos += scnprintf(buf + pos, bufsz - pos, "rx_enable_counter: %u\n",
+ le32_to_cpu(general->rx_enable_counter));
+ ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+ kfree(buf);
+ return ret;
+}
+
+static ssize_t iwl_dbgfs_sensitivity_read(struct file *file,
+ char __user *user_buf,
+ size_t count, loff_t *ppos) {
+
+ struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
+ int pos = 0;
+ int cnt = 0;
+ char *buf;
+ int bufsz = sizeof(struct iwl_sensitivity_data) * 4 + 100;
+ ssize_t ret;
+ struct iwl_sensitivity_data *data;
+
+ data = &priv->sensitivity_data;
+ buf = kzalloc(bufsz, GFP_KERNEL);
+ if (!buf) {
+ IWL_ERR(priv, "Can not allocate Buffer\n");
+ return -ENOMEM;
+ }
+
+ pos += scnprintf(buf + pos, bufsz - pos, "auto_corr_ofdm:\t\t\t %u\n",
+ data->auto_corr_ofdm);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "auto_corr_ofdm_mrc:\t\t %u\n",
+ data->auto_corr_ofdm_mrc);
+ pos += scnprintf(buf + pos, bufsz - pos, "auto_corr_ofdm_x1:\t\t %u\n",
+ data->auto_corr_ofdm_x1);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "auto_corr_ofdm_mrc_x1:\t\t %u\n",
+ data->auto_corr_ofdm_mrc_x1);
+ pos += scnprintf(buf + pos, bufsz - pos, "auto_corr_cck:\t\t\t %u\n",
+ data->auto_corr_cck);
+ pos += scnprintf(buf + pos, bufsz - pos, "auto_corr_cck_mrc:\t\t %u\n",
+ data->auto_corr_cck_mrc);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "last_bad_plcp_cnt_ofdm:\t\t %u\n",
+ data->last_bad_plcp_cnt_ofdm);
+ pos += scnprintf(buf + pos, bufsz - pos, "last_fa_cnt_ofdm:\t\t %u\n",
+ data->last_fa_cnt_ofdm);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "last_bad_plcp_cnt_cck:\t\t %u\n",
+ data->last_bad_plcp_cnt_cck);
+ pos += scnprintf(buf + pos, bufsz - pos, "last_fa_cnt_cck:\t\t %u\n",
+ data->last_fa_cnt_cck);
+ pos += scnprintf(buf + pos, bufsz - pos, "nrg_curr_state:\t\t\t %u\n",
+ data->nrg_curr_state);
+ pos += scnprintf(buf + pos, bufsz - pos, "nrg_prev_state:\t\t\t %u\n",
+ data->nrg_prev_state);
+ pos += scnprintf(buf + pos, bufsz - pos, "nrg_value:\t\t\t");
+ for (cnt = 0; cnt < 10; cnt++) {
+ pos += scnprintf(buf + pos, bufsz - pos, " %u",
+ data->nrg_value[cnt]);
+ }
+ pos += scnprintf(buf + pos, bufsz - pos, "\n");
+ pos += scnprintf(buf + pos, bufsz - pos, "nrg_silence_rssi:\t\t");
+ for (cnt = 0; cnt < NRG_NUM_PREV_STAT_L; cnt++) {
+ pos += scnprintf(buf + pos, bufsz - pos, " %u",
+ data->nrg_silence_rssi[cnt]);
+ }
+ pos += scnprintf(buf + pos, bufsz - pos, "\n");
+ pos += scnprintf(buf + pos, bufsz - pos, "nrg_silence_ref:\t\t %u\n",
+ data->nrg_silence_ref);
+ pos += scnprintf(buf + pos, bufsz - pos, "nrg_energy_idx:\t\t\t %u\n",
+ data->nrg_energy_idx);
+ pos += scnprintf(buf + pos, bufsz - pos, "nrg_silence_idx:\t\t %u\n",
+ data->nrg_silence_idx);
+ pos += scnprintf(buf + pos, bufsz - pos, "nrg_th_cck:\t\t\t %u\n",
+ data->nrg_th_cck);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "nrg_auto_corr_silence_diff:\t %u\n",
+ data->nrg_auto_corr_silence_diff);
+ pos += scnprintf(buf + pos, bufsz - pos, "num_in_cck_no_fa:\t\t %u\n",
+ data->num_in_cck_no_fa);
+ pos += scnprintf(buf + pos, bufsz - pos, "nrg_th_ofdm:\t\t\t %u\n",
+ data->nrg_th_ofdm);
+
+ ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+ kfree(buf);
+ return ret;
+}
+
+
+static ssize_t iwl_dbgfs_chain_noise_read(struct file *file,
+ char __user *user_buf,
+ size_t count, loff_t *ppos) {
+
+ struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
+ int pos = 0;
+ int cnt = 0;
+ char *buf;
+ int bufsz = sizeof(struct iwl_chain_noise_data) * 4 + 100;
+ ssize_t ret;
+ struct iwl_chain_noise_data *data;
+
+ data = &priv->chain_noise_data;
+ buf = kzalloc(bufsz, GFP_KERNEL);
+ if (!buf) {
+ IWL_ERR(priv, "Can not allocate Buffer\n");
+ return -ENOMEM;
+ }
+
+ pos += scnprintf(buf + pos, bufsz - pos, "active_chains:\t\t\t %u\n",
+ data->active_chains);
+ pos += scnprintf(buf + pos, bufsz - pos, "chain_noise_a:\t\t\t %u\n",
+ data->chain_noise_a);
+ pos += scnprintf(buf + pos, bufsz - pos, "chain_noise_b:\t\t\t %u\n",
+ data->chain_noise_b);
+ pos += scnprintf(buf + pos, bufsz - pos, "chain_noise_c:\t\t\t %u\n",
+ data->chain_noise_c);
+ pos += scnprintf(buf + pos, bufsz - pos, "chain_signal_a:\t\t\t %u\n",
+ data->chain_signal_a);
+ pos += scnprintf(buf + pos, bufsz - pos, "chain_signal_b:\t\t\t %u\n",
+ data->chain_signal_b);
+ pos += scnprintf(buf + pos, bufsz - pos, "chain_signal_c:\t\t\t %u\n",
+ data->chain_signal_c);
+ pos += scnprintf(buf + pos, bufsz - pos, "beacon_count:\t\t\t %u\n",
+ data->beacon_count);
+
+ pos += scnprintf(buf + pos, bufsz - pos, "disconn_array:\t\t\t");
+ for (cnt = 0; cnt < NUM_RX_CHAINS; cnt++) {
+ pos += scnprintf(buf + pos, bufsz - pos, " %u",
+ data->disconn_array[cnt]);
+ }
+ pos += scnprintf(buf + pos, bufsz - pos, "\n");
+ pos += scnprintf(buf + pos, bufsz - pos, "delta_gain_code:\t\t");
+ for (cnt = 0; cnt < NUM_RX_CHAINS; cnt++) {
+ pos += scnprintf(buf + pos, bufsz - pos, " %u",
+ data->delta_gain_code[cnt]);
+ }
+ pos += scnprintf(buf + pos, bufsz - pos, "\n");
+ pos += scnprintf(buf + pos, bufsz - pos, "radio_write:\t\t\t %u\n",
+ data->radio_write);
+ pos += scnprintf(buf + pos, bufsz - pos, "state:\t\t\t\t %u\n",
+ data->state);
+
+ ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+ kfree(buf);
+ return ret;
+}
+
+DEBUGFS_READ_WRITE_FILE_OPS(rx_statistics);
+DEBUGFS_READ_WRITE_FILE_OPS(tx_statistics);
+DEBUGFS_READ_WRITE_FILE_OPS(traffic_log);
+DEBUGFS_READ_FILE_OPS(rx_queue);
+DEBUGFS_READ_FILE_OPS(tx_queue);
+DEBUGFS_READ_FILE_OPS(ucode_rx_stats);
+DEBUGFS_READ_FILE_OPS(ucode_tx_stats);
+DEBUGFS_READ_FILE_OPS(ucode_general_stats);
+DEBUGFS_READ_FILE_OPS(sensitivity);
+DEBUGFS_READ_FILE_OPS(chain_noise);
/*
* Create the debugfs files and directories
@@ -603,19 +1600,41 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
DEBUGFS_ADD_DIR(data, dbgfs->dir_drv);
DEBUGFS_ADD_DIR(rf, dbgfs->dir_drv);
+ DEBUGFS_ADD_DIR(debug, dbgfs->dir_drv);
DEBUGFS_ADD_FILE(nvm, data);
DEBUGFS_ADD_FILE(sram, data);
DEBUGFS_ADD_FILE(log_event, data);
DEBUGFS_ADD_FILE(stations, data);
- DEBUGFS_ADD_FILE(rx_statistics, data);
- DEBUGFS_ADD_FILE(tx_statistics, data);
DEBUGFS_ADD_FILE(channels, data);
DEBUGFS_ADD_FILE(status, data);
DEBUGFS_ADD_FILE(interrupt, data);
+ DEBUGFS_ADD_FILE(qos, data);
+#ifdef CONFIG_IWLWIFI_LEDS
+ DEBUGFS_ADD_FILE(led, data);
+#endif
+ DEBUGFS_ADD_FILE(sleep_level_override, data);
+ DEBUGFS_ADD_FILE(current_sleep_command, data);
+ DEBUGFS_ADD_FILE(thermal_throttling, data);
+ DEBUGFS_ADD_FILE(disable_ht40, data);
+ DEBUGFS_ADD_FILE(rx_statistics, debug);
+ DEBUGFS_ADD_FILE(tx_statistics, debug);
+ DEBUGFS_ADD_FILE(traffic_log, debug);
+ DEBUGFS_ADD_FILE(rx_queue, debug);
+ DEBUGFS_ADD_FILE(tx_queue, debug);
+ if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) != CSR_HW_REV_TYPE_3945) {
+ DEBUGFS_ADD_FILE(ucode_rx_stats, debug);
+ DEBUGFS_ADD_FILE(ucode_tx_stats, debug);
+ DEBUGFS_ADD_FILE(ucode_general_stats, debug);
+ DEBUGFS_ADD_FILE(sensitivity, debug);
+ DEBUGFS_ADD_FILE(chain_noise, debug);
+ }
DEBUGFS_ADD_BOOL(disable_sensitivity, rf, &priv->disable_sens_cal);
DEBUGFS_ADD_BOOL(disable_chain_noise, rf,
&priv->disable_chain_noise_cal);
- DEBUGFS_ADD_BOOL(disable_tx_power, rf, &priv->disable_tx_power_cal);
+ if (((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_4965) ||
+ ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_3945))
+ DEBUGFS_ADD_BOOL(disable_tx_power, rf,
+ &priv->disable_tx_power_cal);
return 0;
err:
@@ -634,19 +1653,45 @@ void iwl_dbgfs_unregister(struct iwl_priv *priv)
if (!priv->dbgfs)
return;
+ DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_sleep_level_override);
+ DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_current_sleep_command);
DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_nvm);
- DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_rx_statistics);
- DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_tx_statistics);
DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_sram);
DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_log_event);
DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_stations);
DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_channels);
DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_status);
DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_interrupt);
+ DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_qos);
+#ifdef CONFIG_IWLWIFI_LEDS
+ DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_led);
+#endif
+ DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_thermal_throttling);
+ DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_disable_ht40);
DEBUGFS_REMOVE(priv->dbgfs->dir_data);
+ DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_rx_statistics);
+ DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_tx_statistics);
+ DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_traffic_log);
+ DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_rx_queue);
+ DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_tx_queue);
+ if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) != CSR_HW_REV_TYPE_3945) {
+ DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.
+ file_ucode_rx_stats);
+ DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.
+ file_ucode_tx_stats);
+ DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.
+ file_ucode_general_stats);
+ DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.
+ file_sensitivity);
+ DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.
+ file_chain_noise);
+ }
+ DEBUGFS_REMOVE(priv->dbgfs->dir_debug);
DEBUGFS_REMOVE(priv->dbgfs->dbgfs_rf_files.file_disable_sensitivity);
DEBUGFS_REMOVE(priv->dbgfs->dbgfs_rf_files.file_disable_chain_noise);
- DEBUGFS_REMOVE(priv->dbgfs->dbgfs_rf_files.file_disable_tx_power);
+ if (((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_4965) ||
+ ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_3945))
+ DEBUGFS_REMOVE(priv->dbgfs->dbgfs_rf_files.file_disable_tx_power);
DEBUGFS_REMOVE(priv->dbgfs->dir_rf);
DEBUGFS_REMOVE(priv->dbgfs->dir_drv);
kfree(priv->dbgfs);
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index 650e20af20f..b96c3c9e92a 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -56,16 +56,19 @@ extern struct iwl_cfg iwl5350_agn_cfg;
extern struct iwl_cfg iwl5100_bg_cfg;
extern struct iwl_cfg iwl5100_abg_cfg;
extern struct iwl_cfg iwl5150_agn_cfg;
-extern struct iwl_cfg iwl6000_2ag_cfg;
-extern struct iwl_cfg iwl6000_2agn_cfg;
+extern struct iwl_cfg iwl6000h_2agn_cfg;
+extern struct iwl_cfg iwl6000i_2agn_cfg;
extern struct iwl_cfg iwl6000_3agn_cfg;
extern struct iwl_cfg iwl6050_2agn_cfg;
extern struct iwl_cfg iwl6050_3agn_cfg;
extern struct iwl_cfg iwl1000_bgn_cfg;
+struct iwl_tx_queue;
+
/* shared structures from iwl-5000.c */
extern struct iwl_mod_params iwl50_mod_params;
extern struct iwl_ops iwl5000_ops;
+extern struct iwl_ucode_ops iwl5000_ucode;
extern struct iwl_lib_ops iwl5000_lib;
extern struct iwl_hcmd_ops iwl5000_hcmd;
extern struct iwl_hcmd_utils_ops iwl5000_hcmd_utils;
@@ -78,9 +81,37 @@ extern void iwl5000_rts_tx_cmd_flag(struct ieee80211_tx_info *info,
__le32 *tx_flags);
extern int iwl5000_calc_rssi(struct iwl_priv *priv,
struct iwl_rx_phy_res *rx_resp);
+extern int iwl5000_apm_init(struct iwl_priv *priv);
+extern void iwl5000_apm_stop(struct iwl_priv *priv);
+extern int iwl5000_apm_reset(struct iwl_priv *priv);
+extern void iwl5000_nic_config(struct iwl_priv *priv);
+extern u16 iwl5000_eeprom_calib_version(struct iwl_priv *priv);
+extern const u8 *iwl5000_eeprom_query_addr(const struct iwl_priv *priv,
+ size_t offset);
+extern void iwl5000_txq_update_byte_cnt_tbl(struct iwl_priv *priv,
+ struct iwl_tx_queue *txq,
+ u16 byte_cnt);
+extern void iwl5000_txq_inval_byte_cnt_tbl(struct iwl_priv *priv,
+ struct iwl_tx_queue *txq);
+extern int iwl5000_load_ucode(struct iwl_priv *priv);
+extern void iwl5000_init_alive_start(struct iwl_priv *priv);
+extern int iwl5000_alive_notify(struct iwl_priv *priv);
+extern int iwl5000_hw_set_hw_params(struct iwl_priv *priv);
+extern int iwl5000_txq_agg_enable(struct iwl_priv *priv, int txq_id,
+ int tx_fifo, int sta_id, int tid, u16 ssn_idx);
+extern int iwl5000_txq_agg_disable(struct iwl_priv *priv, u16 txq_id,
+ u16 ssn_idx, u8 tx_fifo);
+extern void iwl5000_txq_set_sched(struct iwl_priv *priv, u32 mask);
+extern void iwl5000_setup_deferred_work(struct iwl_priv *priv);
+extern void iwl5000_rx_handler_setup(struct iwl_priv *priv);
+extern int iwl5000_hw_valid_rtc_data_addr(u32 addr);
+extern int iwl5000_send_tx_power(struct iwl_priv *priv);
+extern void iwl5000_temperature(struct iwl_priv *priv);
/* CT-KILL constants */
-#define CT_KILL_THRESHOLD 110 /* in Celsius */
+#define CT_KILL_THRESHOLD_LEGACY 110 /* in Celsius */
+#define CT_KILL_THRESHOLD 114 /* in Celsius */
+#define CT_KILL_EXIT_THRESHOLD 95 /* in Celsius */
/* Default noise level to report when noise measurement is not available.
* This may be because we're:
@@ -119,6 +150,31 @@ struct iwl_rx_mem_buffer {
struct list_head list;
};
+/* defined below */
+struct iwl_device_cmd;
+
+struct iwl_cmd_meta {
+ /* only for SYNC commands, iff the reply skb is wanted */
+ struct iwl_host_cmd *source;
+ /*
+ * only for ASYNC commands
+ * (which is somewhat stupid -- look at iwl-sta.c for instance
+ * which duplicates a bunch of code because the callback isn't
+ * invoked for SYNC commands, if it were and its result passed
+ * through it would be simpler...)
+ */
+ void (*callback)(struct iwl_priv *priv,
+ struct iwl_device_cmd *cmd,
+ struct sk_buff *skb);
+
+ /* The CMD_SIZE_HUGE flag bit indicates that the command
+ * structure is stored at the end of the shared queue memory. */
+ u32 flags;
+
+ DECLARE_PCI_UNMAP_ADDR(mapping)
+ DECLARE_PCI_UNMAP_LEN(len)
+};
+
/*
* Generic queue structure
*
@@ -146,7 +202,8 @@ struct iwl_tx_info {
* struct iwl_tx_queue - Tx Queue for DMA
* @q: generic Rx/Tx queue descriptor
* @bd: base of circular buffer of TFDs
- * @cmd: array of command/Tx buffers
+ * @cmd: array of command/TX buffer pointers
+ * @meta: array of meta data for each command/tx buffer
* @dma_addr_cmd: physical address of cmd/tx buffer array
* @txb: array of per-TFD driver data
* @need_update: indicates need to update read/write index
@@ -161,7 +218,8 @@ struct iwl_tx_info {
struct iwl_tx_queue {
struct iwl_queue q;
void *tfds;
- struct iwl_cmd *cmd[TFD_TX_CMD_SLOTS];
+ struct iwl_device_cmd **cmd;
+ struct iwl_cmd_meta *meta;
struct iwl_tx_info *txb;
u8 need_update;
u8 sched_retry;
@@ -219,8 +277,8 @@ struct iwl_channel_info {
struct iwl4965_channel_tgd_info tgd;
struct iwl4965_channel_tgh_info tgh;
struct iwl_eeprom_channel eeprom; /* EEPROM regulatory limit */
- struct iwl_eeprom_channel fat_eeprom; /* EEPROM regulatory limit for
- * FAT channel */
+ struct iwl_eeprom_channel ht40_eeprom; /* EEPROM regulatory limit for
+ * HT40 channel */
u8 channel; /* channel number */
u8 flags; /* flags copied from EEPROM */
@@ -233,13 +291,13 @@ struct iwl_channel_info {
u8 band_index; /* 0-4, maps channel to band1/2/3/4/5 */
enum ieee80211_band band;
- /* FAT channel info */
- s8 fat_max_power_avg; /* (dBm) regul. eeprom, normal Tx, any rate */
- s8 fat_curr_txpow; /* (dBm) regulatory/spectrum/user (not h/w) */
- s8 fat_min_power; /* always 0 */
- s8 fat_scan_power; /* (dBm) eeprom, direct scans, any rate */
- u8 fat_flags; /* flags copied from EEPROM */
- u8 fat_extension_channel; /* HT_IE_EXT_CHANNEL_* */
+ /* HT40 channel info */
+ s8 ht40_max_power_avg; /* (dBm) regul. eeprom, normal Tx, any rate */
+ s8 ht40_curr_txpow; /* (dBm) regulatory/spectrum/user (not h/w) */
+ s8 ht40_min_power; /* always 0 */
+ s8 ht40_scan_power; /* (dBm) eeprom, direct scans, any rate */
+ u8 ht40_flags; /* flags copied from EEPROM */
+ u8 ht40_extension_channel; /* HT_IE_EXT_CHANNEL_* */
/* Radio/DSP gain settings for each "normal" data Tx rate.
* These include, in addition to RF and DSP gain, a few fields for
@@ -298,35 +356,16 @@ enum {
CMD_WANT_SKB = (1 << 2),
};
-struct iwl_cmd;
-struct iwl_priv;
-
-struct iwl_cmd_meta {
- struct iwl_cmd_meta *source;
- union {
- struct sk_buff *skb;
- int (*callback)(struct iwl_priv *priv,
- struct iwl_cmd *cmd, struct sk_buff *skb);
- } __attribute__ ((packed)) u;
-
- /* The CMD_SIZE_HUGE flag bit indicates that the command
- * structure is stored at the end of the shared queue memory. */
- u32 flags;
- DECLARE_PCI_UNMAP_ADDR(mapping)
- DECLARE_PCI_UNMAP_LEN(len)
-} __attribute__ ((packed));
-
#define IWL_CMD_MAX_PAYLOAD 320
/**
- * struct iwl_cmd
+ * struct iwl_device_cmd
*
* For allocation of the command and tx queues, this establishes the overall
* size of the largest command we send to uCode, except for a scan command
* (which is relatively huge; space is allocated separately).
*/
-struct iwl_cmd {
- struct iwl_cmd_meta meta; /* driver data */
+struct iwl_device_cmd {
struct iwl_cmd_header hdr; /* uCode API */
union {
u32 flags;
@@ -338,17 +377,20 @@ struct iwl_cmd {
} __attribute__ ((packed)) cmd;
} __attribute__ ((packed));
+#define TFD_MAX_PAYLOAD_SIZE (sizeof(struct iwl_device_cmd))
+
struct iwl_host_cmd {
- u8 id;
- u16 len;
- struct iwl_cmd_meta meta;
const void *data;
+ struct sk_buff *reply_skb;
+ void (*callback)(struct iwl_priv *priv,
+ struct iwl_device_cmd *cmd,
+ struct sk_buff *skb);
+ u32 flags;
+ u16 len;
+ u8 id;
};
-#define TFD_MAX_PAYLOAD_SIZE (sizeof(struct iwl_cmd) - \
- sizeof(struct iwl_cmd_meta))
-
/*
* RX related structures and functions
*/
@@ -449,8 +491,16 @@ union iwl_ht_rate_supp {
};
#define CFG_HT_RX_AMPDU_FACTOR_DEF (0x3)
-#define CFG_HT_MPDU_DENSITY_2USEC (0x5)
-#define CFG_HT_MPDU_DENSITY_DEF CFG_HT_MPDU_DENSITY_2USEC
+
+/*
+ * Maximal MPDU density for TX aggregation
+ * 4 - 2us density
+ * 5 - 4us density
+ * 6 - 8us density
+ * 7 - 16us density
+ */
+#define CFG_HT_MPDU_DENSITY_4USEC (0x5)
+#define CFG_HT_MPDU_DENSITY_DEF CFG_HT_MPDU_DENSITY_4USEC
struct iwl_ht_info {
/* self configuration data */
@@ -525,15 +575,29 @@ struct fw_desc {
};
/* uCode file layout */
-struct iwl_ucode {
- __le32 ver; /* major/minor/API/serial */
- __le32 inst_size; /* bytes of runtime instructions */
- __le32 data_size; /* bytes of runtime data */
- __le32 init_size; /* bytes of initialization instructions */
- __le32 init_data_size; /* bytes of initialization data */
- __le32 boot_size; /* bytes of bootstrap instructions */
- u8 data[0]; /* data in same order as "size" elements */
+struct iwl_ucode_header {
+ __le32 ver; /* major/minor/API/serial */
+ union {
+ struct {
+ __le32 inst_size; /* bytes of runtime code */
+ __le32 data_size; /* bytes of runtime data */
+ __le32 init_size; /* bytes of init code */
+ __le32 init_data_size; /* bytes of init data */
+ __le32 boot_size; /* bytes of bootstrap code */
+ u8 data[0]; /* in same order as sizes */
+ } v1;
+ struct {
+ __le32 build; /* build number */
+ __le32 inst_size; /* bytes of runtime code */
+ __le32 data_size; /* bytes of runtime data */
+ __le32 init_size; /* bytes of init code */
+ __le32 init_data_size; /* bytes of init data */
+ __le32 boot_size; /* bytes of bootstrap code */
+ u8 data[0]; /* in same order as sizes */
+ } v2;
+ } u;
};
+#define UCODE_HEADER_SIZE(ver) ((ver) == 1 ? 24 : 28)
struct iwl4965_ibss_seq {
u8 mac[ETH_ALEN];
@@ -585,7 +649,7 @@ struct iwl_sensitivity_ranges {
* @rx_wrt_ptr_reg: FH{39}_RSCSR_CHNL0_WPTR
* @max_stations:
* @bcast_sta_id:
- * @fat_channel: is 40MHz width possible in band 2.4
+ * @ht40_channel: is 40MHz width possible in band 2.4
* BIT(IEEE80211_BAND_5GHZ) BIT(IEEE80211_BAND_5GHZ)
* @sw_crypto: 0 for hw, 1 for sw
* @max_xxx_size: for ucode uses
@@ -609,12 +673,14 @@ struct iwl_hw_params {
u32 max_pkt_size;
u8 max_stations;
u8 bcast_sta_id;
- u8 fat_channel;
- u8 sw_crypto;
+ u8 ht40_channel;
+ u8 max_beacon_itrvl; /* in 1024 ms */
u32 max_inst_size;
u32 max_data_size;
u32 max_bsm_size;
u32 ct_kill_threshold; /* value in hw-dependent units */
+ u32 ct_kill_exit_threshold; /* value in hw-dependent units */
+ /* for 1000, 6000 series and up */
u32 calib_init_cfg;
const struct iwl_sensitivity_ranges *sens;
};
@@ -809,6 +875,8 @@ struct iwl_chain_noise_data {
#define EEPROM_SEM_TIMEOUT 10 /* milliseconds */
#define EEPROM_SEM_RETRY_LIMIT 1000 /* number of attempts (not time) */
+#define IWL_TRAFFIC_ENTRIES (256)
+#define IWL_TRAFFIC_ENTRY_SIZE (64)
enum {
MEASUREMENT_READY = (1 << 0),
@@ -820,6 +888,19 @@ enum iwl_nvm_type {
NVM_DEVICE_TYPE_OTP,
};
+
+/**
+ * enum iwl_pa_type - Power Amplifier type
+ * @IWL_PA_SYSTEM: based on uCode configuration
+ * @IWL_PA_HYBRID: use both Internal and external PA
+ * @IWL_PA_INTERNAL: use Internal only
+ */
+enum iwl_pa_type {
+ IWL_PA_SYSTEM = 0,
+ IWL_PA_HYBRID = 1,
+ IWL_PA_INTERNAL = 2,
+};
+
/* interrupt statistics */
struct isr_statistics {
u32 hw;
@@ -836,6 +917,48 @@ struct isr_statistics {
u32 unhandled;
};
+#ifdef CONFIG_IWLWIFI_DEBUGFS
+/* management statistics */
+enum iwl_mgmt_stats {
+ MANAGEMENT_ASSOC_REQ = 0,
+ MANAGEMENT_ASSOC_RESP,
+ MANAGEMENT_REASSOC_REQ,
+ MANAGEMENT_REASSOC_RESP,
+ MANAGEMENT_PROBE_REQ,
+ MANAGEMENT_PROBE_RESP,
+ MANAGEMENT_BEACON,
+ MANAGEMENT_ATIM,
+ MANAGEMENT_DISASSOC,
+ MANAGEMENT_AUTH,
+ MANAGEMENT_DEAUTH,
+ MANAGEMENT_ACTION,
+ MANAGEMENT_MAX,
+};
+/* control statistics */
+enum iwl_ctrl_stats {
+ CONTROL_BACK_REQ = 0,
+ CONTROL_BACK,
+ CONTROL_PSPOLL,
+ CONTROL_RTS,
+ CONTROL_CTS,
+ CONTROL_ACK,
+ CONTROL_CFEND,
+ CONTROL_CFENDACK,
+ CONTROL_MAX,
+};
+
+struct traffic_stats {
+ u32 mgmt[MANAGEMENT_MAX];
+ u32 ctrl[CONTROL_MAX];
+ u32 data_cnt;
+ u64 data_bytes;
+};
+#else
+struct traffic_stats {
+ u64 data_bytes;
+};
+#endif
+
#define IWL_MAX_NUM_QUEUES 20 /* FIXME: do dynamic allocation */
struct iwl_priv {
@@ -981,15 +1104,14 @@ struct iwl_priv {
int last_rx_noise; /* From beacon statistics */
/* counts mgmt, ctl, and data packets */
- struct traffic_stats {
- u32 cnt;
- u64 bytes;
- } tx_stats[3], rx_stats[3];
+ struct traffic_stats tx_stats;
+ struct traffic_stats rx_stats;
/* counts interrupts */
struct isr_statistics isr_stats;
struct iwl_power_mgr power_data;
+ struct iwl_tt_mgmt thermal_throttle;
struct iwl_notif_statistics statistics;
unsigned long last_statistics_time;
@@ -997,7 +1119,6 @@ struct iwl_priv {
/* context information */
u16 rates_mask;
- u32 power_mode;
u8 bssid[ETH_ALEN];
u16 rts_threshold;
u8 mac_addr[ETH_ALEN];
@@ -1076,6 +1197,9 @@ struct iwl_priv {
struct work_struct report_work;
struct work_struct request_scan;
struct work_struct beacon_update;
+ struct work_struct tt_work;
+ struct work_struct ct_enter;
+ struct work_struct ct_exit;
struct tasklet_struct irq_tasklet;
@@ -1094,11 +1218,17 @@ struct iwl_priv {
#ifdef CONFIG_IWLWIFI_DEBUG
/* debugging info */
- u32 debug_level;
+ u32 debug_level; /* per device debugging will override global
+ iwl_debug_level if set */
u32 framecnt_to_us;
atomic_t restrict_refcnt;
+ bool disable_ht40;
#ifdef CONFIG_IWLWIFI_DEBUGFS
/* debugfs */
+ u16 tx_traffic_idx;
+ u16 rx_traffic_idx;
+ u8 *tx_traffic;
+ u8 *rx_traffic;
struct iwl_debugfs *dbgfs;
#endif /* CONFIG_IWLWIFI_DEBUGFS */
#endif /* CONFIG_IWLWIFI_DEBUG */
@@ -1130,8 +1260,27 @@ static inline void iwl_txq_ctx_deactivate(struct iwl_priv *priv, int txq_id)
#ifdef CONFIG_IWLWIFI_DEBUG
const char *iwl_get_tx_fail_reason(u32 status);
+/*
+ * iwl_get_debug_level: Return active debug level for device
+ *
+ * Using sysfs it is possible to set per device debug level. This debug
+ * level will be used if set, otherwise the global debug level which can be
+ * set via module parameter is used.
+ */
+static inline u32 iwl_get_debug_level(struct iwl_priv *priv)
+{
+ if (priv->debug_level)
+ return priv->debug_level;
+ else
+ return iwl_debug_level;
+}
#else
static inline const char *iwl_get_tx_fail_reason(u32 status) { return ""; }
+
+static inline u32 iwl_get_debug_level(struct iwl_priv *priv)
+{
+ return iwl_debug_level;
+}
#endif
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c
index 7d7554a2f34..78c4a324a3b 100644
--- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c
+++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c
@@ -127,11 +127,11 @@ static const u8 iwl_eeprom_band_5[] = { /* 5725-5825MHz */
145, 149, 153, 157, 161, 165
};
-static const u8 iwl_eeprom_band_6[] = { /* 2.4 FAT channel */
+static const u8 iwl_eeprom_band_6[] = { /* 2.4 ht40 channel */
1, 2, 3, 4, 5, 6, 7
};
-static const u8 iwl_eeprom_band_7[] = { /* 5.2 FAT channel */
+static const u8 iwl_eeprom_band_7[] = { /* 5.2 ht40 channel */
36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157
};
@@ -159,6 +159,9 @@ static int iwlcore_get_nvm_type(struct iwl_priv *priv)
/* OTP only valid for CP/PP and after */
switch (priv->hw_rev & CSR_HW_REV_TYPE_MSK) {
+ case CSR_HW_REV_TYPE_NONE:
+ IWL_ERR(priv, "Unknown hardware type\n");
+ return -ENOENT;
case CSR_HW_REV_TYPE_3945:
case CSR_HW_REV_TYPE_4965:
case CSR_HW_REV_TYPE_5300:
@@ -266,7 +269,8 @@ int iwl_eeprom_init(struct iwl_priv *priv)
u32 otpgp;
priv->nvm_device_type = iwlcore_get_nvm_type(priv);
-
+ if (priv->nvm_device_type == -ENOENT)
+ return -ENOENT;
/* allocate eeprom */
if (priv->nvm_device_type == NVM_DEVICE_TYPE_OTP)
priv->cfg->eeprom_size =
@@ -458,13 +462,13 @@ static void iwl_init_band_reference(const struct iwl_priv *priv,
iwl_eeprom_query_addr(priv, offset);
*eeprom_ch_index = iwl_eeprom_band_5;
break;
- case 6: /* 2.4GHz FAT channels */
+ case 6: /* 2.4GHz ht40 channels */
*eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_6);
*eeprom_ch_info = (struct iwl_eeprom_channel *)
iwl_eeprom_query_addr(priv, offset);
*eeprom_ch_index = iwl_eeprom_band_6;
break;
- case 7: /* 5 GHz FAT channels */
+ case 7: /* 5 GHz ht40 channels */
*eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_7);
*eeprom_ch_info = (struct iwl_eeprom_channel *)
iwl_eeprom_query_addr(priv, offset);
@@ -480,14 +484,14 @@ static void iwl_init_band_reference(const struct iwl_priv *priv,
? # x " " : "")
/**
- * iwl_set_fat_chan_info - Copy fat channel info into driver's priv.
+ * iwl_set_ht40_chan_info - Copy ht40 channel info into driver's priv.
*
* Does not set up a command, or touch hardware.
*/
-static int iwl_set_fat_chan_info(struct iwl_priv *priv,
+static int iwl_set_ht40_chan_info(struct iwl_priv *priv,
enum ieee80211_band band, u16 channel,
const struct iwl_eeprom_channel *eeprom_ch,
- u8 fat_extension_channel)
+ u8 ht40_extension_channel)
{
struct iwl_channel_info *ch_info;
@@ -497,7 +501,7 @@ static int iwl_set_fat_chan_info(struct iwl_priv *priv,
if (!is_channel_valid(ch_info))
return -1;
- IWL_DEBUG_INFO(priv, "FAT Ch. %d [%sGHz] %s%s%s%s%s(0x%02x %ddBm):"
+ IWL_DEBUG_INFO(priv, "HT40 Ch. %d [%sGHz] %s%s%s%s%s(0x%02x %ddBm):"
" Ad-Hoc %ssupported\n",
ch_info->channel,
is_channel_a_band(ch_info) ?
@@ -513,13 +517,13 @@ static int iwl_set_fat_chan_info(struct iwl_priv *priv,
&& !(eeprom_ch->flags & EEPROM_CHANNEL_RADAR)) ?
"" : "not ");
- ch_info->fat_eeprom = *eeprom_ch;
- ch_info->fat_max_power_avg = eeprom_ch->max_power_avg;
- ch_info->fat_curr_txpow = eeprom_ch->max_power_avg;
- ch_info->fat_min_power = 0;
- ch_info->fat_scan_power = eeprom_ch->max_power_avg;
- ch_info->fat_flags = eeprom_ch->flags;
- ch_info->fat_extension_channel = fat_extension_channel;
+ ch_info->ht40_eeprom = *eeprom_ch;
+ ch_info->ht40_max_power_avg = eeprom_ch->max_power_avg;
+ ch_info->ht40_curr_txpow = eeprom_ch->max_power_avg;
+ ch_info->ht40_min_power = 0;
+ ch_info->ht40_scan_power = eeprom_ch->max_power_avg;
+ ch_info->ht40_flags = eeprom_ch->flags;
+ ch_info->ht40_extension_channel = ht40_extension_channel;
return 0;
}
@@ -585,9 +589,9 @@ int iwl_init_channel_map(struct iwl_priv *priv)
/* Copy the run-time flags so they are there even on
* invalid channels */
ch_info->flags = eeprom_ch_info[ch].flags;
- /* First write that fat is not enabled, and then enable
+ /* First write that ht40 is not enabled, and then enable
* one by one */
- ch_info->fat_extension_channel =
+ ch_info->ht40_extension_channel =
(IEEE80211_CHAN_NO_HT40PLUS |
IEEE80211_CHAN_NO_HT40MINUS);
@@ -638,17 +642,17 @@ int iwl_init_channel_map(struct iwl_priv *priv)
}
}
- /* Check if we do have FAT channels */
+ /* Check if we do have HT40 channels */
if (priv->cfg->ops->lib->eeprom_ops.regulatory_bands[5] ==
- EEPROM_REGULATORY_BAND_NO_FAT &&
+ EEPROM_REGULATORY_BAND_NO_HT40 &&
priv->cfg->ops->lib->eeprom_ops.regulatory_bands[6] ==
- EEPROM_REGULATORY_BAND_NO_FAT)
+ EEPROM_REGULATORY_BAND_NO_HT40)
return 0;
- /* Two additional EEPROM bands for 2.4 and 5 GHz FAT channels */
+ /* Two additional EEPROM bands for 2.4 and 5 GHz HT40 channels */
for (band = 6; band <= 7; band++) {
enum ieee80211_band ieeeband;
- u8 fat_extension_chan;
+ u8 ht40_extension_chan;
iwl_init_band_reference(priv, band, &eeprom_ch_count,
&eeprom_ch_info, &eeprom_ch_index);
@@ -665,19 +669,19 @@ int iwl_init_channel_map(struct iwl_priv *priv)
(eeprom_ch_index[ch] == 6) ||
(eeprom_ch_index[ch] == 7)))
/* both are allowed: above and below */
- fat_extension_chan = 0;
+ ht40_extension_chan = 0;
else
- fat_extension_chan =
+ ht40_extension_chan =
IEEE80211_CHAN_NO_HT40MINUS;
/* Set up driver's info for lower half */
- iwl_set_fat_chan_info(priv, ieeeband,
+ iwl_set_ht40_chan_info(priv, ieeeband,
eeprom_ch_index[ch],
&(eeprom_ch_info[ch]),
- fat_extension_chan);
+ ht40_extension_chan);
/* Set up driver's info for upper half */
- iwl_set_fat_chan_info(priv, ieeeband,
+ iwl_set_ht40_chan_info(priv, ieeeband,
(eeprom_ch_index[ch] + 4),
&(eeprom_ch_info[ch]),
IEEE80211_CHAN_NO_HT40PLUS);
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.h b/drivers/net/wireless/iwlwifi/iwl-eeprom.h
index 195b4ef12c2..05d4fc4451d 100644
--- a/drivers/net/wireless/iwlwifi/iwl-eeprom.h
+++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.h
@@ -88,10 +88,10 @@ struct iwl_priv;
* requirement for establishing a new network for legal operation on channels
* requiring RADAR detection or restricting ACTIVE scanning.
*
- * NOTE: "WIDE" flag does not indicate anything about "FAT" 40 MHz channels.
- * It only indicates that 20 MHz channel use is supported; FAT channel
+ * NOTE: "WIDE" flag does not indicate anything about "HT40" 40 MHz channels.
+ * It only indicates that 20 MHz channel use is supported; HT40 channel
* usage is indicated by a separate set of regulatory flags for each
- * FAT channel pair.
+ * HT40 channel pair.
*
* NOTE: Using a channel inappropriately will result in a uCode error!
*/
@@ -112,7 +112,7 @@ enum {
#define EEPROM_SKU_CAP_HW_RF_KILL_ENABLE (1 << 1)
/* *regulatory* channel data format in eeprom, one for each channel.
- * There are separate entries for FAT (40 MHz) vs. normal (20 MHz) channels. */
+ * There are separate entries for HT40 (40 MHz) vs. normal (20 MHz) channels. */
struct iwl_eeprom_channel {
u8 flags; /* EEPROM_CHANNEL_* flags copied from EEPROM */
s8 max_power_avg; /* max power (dBm) on this chnl, limit 31 */
@@ -170,9 +170,9 @@ struct iwl_eeprom_channel {
| INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 22 bytes */
#define EEPROM_5000_REG_BAND_5_CHANNELS ((0x74)\
| INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 12 bytes */
-#define EEPROM_5000_REG_BAND_24_FAT_CHANNELS ((0x82)\
+#define EEPROM_5000_REG_BAND_24_HT40_CHANNELS ((0x82)\
| INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 14 bytes */
-#define EEPROM_5000_REG_BAND_52_FAT_CHANNELS ((0x92)\
+#define EEPROM_5000_REG_BAND_52_HT40_CHANNELS ((0x92)\
| INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 22 bytes */
/* 5050 Specific */
@@ -313,7 +313,7 @@ struct iwl_eeprom_calib_info {
* in EEPROM containing EEPROM_CHANNEL_* usage flags (LSB) and max regulatory
* txpower (MSB).
*
- * Entries immediately below are for 20 MHz channel width. FAT (40 MHz)
+ * Entries immediately below are for 20 MHz channel width. HT40 (40 MHz)
* channels (only for 4965, not supported by 3945) appear later in the EEPROM.
*
* 2.4 GHz channels 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14
@@ -352,29 +352,29 @@ struct iwl_eeprom_calib_info {
#define EEPROM_REGULATORY_BAND_5_CHANNELS (2*0x99) /* 12 bytes */
/*
- * 2.4 GHz FAT channels 1 (5), 2 (6), 3 (7), 4 (8), 5 (9), 6 (10), 7 (11)
+ * 2.4 GHz HT40 channels 1 (5), 2 (6), 3 (7), 4 (8), 5 (9), 6 (10), 7 (11)
*
* The channel listed is the center of the lower 20 MHz half of the channel.
* The overall center frequency is actually 2 channels (10 MHz) above that,
- * and the upper half of each FAT channel is centered 4 channels (20 MHz) away
- * from the lower half; e.g. the upper half of FAT channel 1 is channel 5,
- * and the overall FAT channel width centers on channel 3.
+ * and the upper half of each HT40 channel is centered 4 channels (20 MHz) away
+ * from the lower half; e.g. the upper half of HT40 channel 1 is channel 5,
+ * and the overall HT40 channel width centers on channel 3.
*
* NOTE: The RXON command uses 20 MHz channel numbers to specify the
* control channel to which to tune. RXON also specifies whether the
- * control channel is the upper or lower half of a FAT channel.
+ * control channel is the upper or lower half of a HT40 channel.
*
- * NOTE: 4965 does not support FAT channels on 2.4 GHz.
+ * NOTE: 4965 does not support HT40 channels on 2.4 GHz.
*/
-#define EEPROM_4965_REGULATORY_BAND_24_FAT_CHANNELS (2*0xA0) /* 14 bytes */
+#define EEPROM_4965_REGULATORY_BAND_24_HT40_CHANNELS (2*0xA0) /* 14 bytes */
/*
- * 5.2 GHz FAT channels 36 (40), 44 (48), 52 (56), 60 (64),
+ * 5.2 GHz HT40 channels 36 (40), 44 (48), 52 (56), 60 (64),
* 100 (104), 108 (112), 116 (120), 124 (128), 132 (136), 149 (153), 157 (161)
*/
-#define EEPROM_4965_REGULATORY_BAND_52_FAT_CHANNELS (2*0xA8) /* 22 bytes */
+#define EEPROM_4965_REGULATORY_BAND_52_HT40_CHANNELS (2*0xA8) /* 22 bytes */
-#define EEPROM_REGULATORY_BAND_NO_FAT (0)
+#define EEPROM_REGULATORY_BAND_NO_HT40 (0)
struct iwl_eeprom_ops {
const u32 regulatory_bands[7];
diff --git a/drivers/net/wireless/iwlwifi/iwl-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-hcmd.c
index 17d61ac8ed6..532c8d6cd8d 100644
--- a/drivers/net/wireless/iwlwifi/iwl-hcmd.c
+++ b/drivers/net/wireless/iwlwifi/iwl-hcmd.c
@@ -36,8 +36,6 @@
#include "iwl-core.h"
-#define IWL_CMD(x) case x: return #x
-
const char *get_cmd_string(u8 cmd)
{
switch (cmd) {
@@ -103,22 +101,23 @@ EXPORT_SYMBOL(get_cmd_string);
#define HOST_COMPLETE_TIMEOUT (HZ / 2)
-static int iwl_generic_cmd_callback(struct iwl_priv *priv,
- struct iwl_cmd *cmd, struct sk_buff *skb)
+static void iwl_generic_cmd_callback(struct iwl_priv *priv,
+ struct iwl_device_cmd *cmd,
+ struct sk_buff *skb)
{
struct iwl_rx_packet *pkt = NULL;
if (!skb) {
IWL_ERR(priv, "Error: Response NULL in %s.\n",
get_cmd_string(cmd->hdr.cmd));
- return 1;
+ return;
}
pkt = (struct iwl_rx_packet *)skb->data;
if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) {
IWL_ERR(priv, "Bad return from %s (0x%08X)\n",
get_cmd_string(cmd->hdr.cmd), pkt->hdr.flags);
- return 1;
+ return;
}
#ifdef CONFIG_IWLWIFI_DEBUG
@@ -127,29 +126,26 @@ static int iwl_generic_cmd_callback(struct iwl_priv *priv,
case SENSITIVITY_CMD:
IWL_DEBUG_HC_DUMP(priv, "back from %s (0x%08X)\n",
get_cmd_string(cmd->hdr.cmd), pkt->hdr.flags);
- break;
+ break;
default:
IWL_DEBUG_HC(priv, "back from %s (0x%08X)\n",
get_cmd_string(cmd->hdr.cmd), pkt->hdr.flags);
}
#endif
-
- /* Let iwl_tx_complete free the response skb */
- return 1;
}
static int iwl_send_cmd_async(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
{
int ret;
- BUG_ON(!(cmd->meta.flags & CMD_ASYNC));
+ BUG_ON(!(cmd->flags & CMD_ASYNC));
/* An asynchronous command can not expect an SKB to be set. */
- BUG_ON(cmd->meta.flags & CMD_WANT_SKB);
+ BUG_ON(cmd->flags & CMD_WANT_SKB);
/* Assign a generic callback if one is not provided */
- if (!cmd->meta.u.callback)
- cmd->meta.u.callback = iwl_generic_cmd_callback;
+ if (!cmd->callback)
+ cmd->callback = iwl_generic_cmd_callback;
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
return -EBUSY;
@@ -168,10 +164,10 @@ int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
int cmd_idx;
int ret;
- BUG_ON(cmd->meta.flags & CMD_ASYNC);
+ BUG_ON(cmd->flags & CMD_ASYNC);
/* A synchronous command can not have a callback set. */
- BUG_ON(cmd->meta.u.callback != NULL);
+ BUG_ON(cmd->callback);
if (test_and_set_bit(STATUS_HCMD_SYNC_ACTIVE, &priv->status)) {
IWL_ERR(priv,
@@ -183,9 +179,6 @@ int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
set_bit(STATUS_HCMD_ACTIVE, &priv->status);
- if (cmd->meta.flags & CMD_WANT_SKB)
- cmd->meta.source = &cmd->meta;
-
cmd_idx = iwl_enqueue_hcmd(priv, cmd);
if (cmd_idx < 0) {
ret = cmd_idx;
@@ -222,7 +215,7 @@ int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
ret = -EIO;
goto fail;
}
- if ((cmd->meta.flags & CMD_WANT_SKB) && !cmd->meta.u.skb) {
+ if ((cmd->flags & CMD_WANT_SKB) && !cmd->reply_skb) {
IWL_ERR(priv, "Error: Response NULL in '%s'\n",
get_cmd_string(cmd->id));
ret = -EIO;
@@ -233,20 +226,20 @@ int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
goto out;
cancel:
- if (cmd->meta.flags & CMD_WANT_SKB) {
- struct iwl_cmd *qcmd;
-
- /* Cancel the CMD_WANT_SKB flag for the cmd in the
+ if (cmd->flags & CMD_WANT_SKB) {
+ /*
+ * Cancel the CMD_WANT_SKB flag for the cmd in the
* TX cmd queue. Otherwise in case the cmd comes
* in later, it will possibly set an invalid
- * address (cmd->meta.source). */
- qcmd = priv->txq[IWL_CMD_QUEUE_NUM].cmd[cmd_idx];
- qcmd->meta.flags &= ~CMD_WANT_SKB;
+ * address (cmd->meta.source).
+ */
+ priv->txq[IWL_CMD_QUEUE_NUM].meta[cmd_idx].flags &=
+ ~CMD_WANT_SKB;
}
fail:
- if (cmd->meta.u.skb) {
- dev_kfree_skb_any(cmd->meta.u.skb);
- cmd->meta.u.skb = NULL;
+ if (cmd->reply_skb) {
+ dev_kfree_skb_any(cmd->reply_skb);
+ cmd->reply_skb = NULL;
}
out:
clear_bit(STATUS_HCMD_SYNC_ACTIVE, &priv->status);
@@ -256,7 +249,7 @@ EXPORT_SYMBOL(iwl_send_cmd_sync);
int iwl_send_cmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
{
- if (cmd->meta.flags & CMD_ASYNC)
+ if (cmd->flags & CMD_ASYNC)
return iwl_send_cmd_async(priv, cmd);
return iwl_send_cmd_sync(priv, cmd);
@@ -277,9 +270,9 @@ EXPORT_SYMBOL(iwl_send_cmd_pdu);
int iwl_send_cmd_pdu_async(struct iwl_priv *priv,
u8 id, u16 len, const void *data,
- int (*callback)(struct iwl_priv *priv,
- struct iwl_cmd *cmd,
- struct sk_buff *skb))
+ void (*callback)(struct iwl_priv *priv,
+ struct iwl_device_cmd *cmd,
+ struct sk_buff *skb))
{
struct iwl_host_cmd cmd = {
.id = id,
@@ -287,8 +280,8 @@ int iwl_send_cmd_pdu_async(struct iwl_priv *priv,
.data = data,
};
- cmd.meta.flags |= CMD_ASYNC;
- cmd.meta.u.callback = callback;
+ cmd.flags |= CMD_ASYNC;
+ cmd.callback = callback;
return iwl_send_cmd_async(priv, &cmd);
}
diff --git a/drivers/net/wireless/iwlwifi/iwl-helpers.h b/drivers/net/wireless/iwlwifi/iwl-helpers.h
index a1328c3c81a..bd0b12efb5c 100644
--- a/drivers/net/wireless/iwlwifi/iwl-helpers.h
+++ b/drivers/net/wireless/iwlwifi/iwl-helpers.h
@@ -145,4 +145,25 @@ static inline void iwl_stop_queue(struct iwl_priv *priv, u8 queue)
#define ieee80211_stop_queue DO_NOT_USE_ieee80211_stop_queue
#define ieee80211_wake_queue DO_NOT_USE_ieee80211_wake_queue
+static inline void iwl_disable_interrupts(struct iwl_priv *priv)
+{
+ clear_bit(STATUS_INT_ENABLED, &priv->status);
+
+ /* disable interrupts from uCode/NIC to host */
+ iwl_write32(priv, CSR_INT_MASK, 0x00000000);
+
+ /* acknowledge/clear/reset any interrupts still pending
+ * from uCode or flow handler (Rx/Tx DMA) */
+ iwl_write32(priv, CSR_INT, 0xffffffff);
+ iwl_write32(priv, CSR_FH_INT_STATUS, 0xffffffff);
+ IWL_DEBUG_ISR(priv, "Disabled interrupts\n");
+}
+
+static inline void iwl_enable_interrupts(struct iwl_priv *priv)
+{
+ IWL_DEBUG_ISR(priv, "Enabling interrupts\n");
+ set_bit(STATUS_INT_ENABLED, &priv->status);
+ iwl_write32(priv, CSR_INT_MASK, priv->inta_mask);
+}
+
#endif /* __iwl_helpers_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-led.c b/drivers/net/wireless/iwlwifi/iwl-led.c
index 5e64252f80f..f420c99e724 100644
--- a/drivers/net/wireless/iwlwifi/iwl-led.c
+++ b/drivers/net/wireless/iwlwifi/iwl-led.c
@@ -54,7 +54,7 @@ static const char *led_type_str[] = {
static const struct {
- u16 tpt;
+ u16 tpt; /* Mb/s */
u8 on_time;
u8 off_time;
} blink_tbl[] =
@@ -91,8 +91,8 @@ static int iwl_send_led_cmd(struct iwl_priv *priv, struct iwl_led_cmd *led_cmd)
.id = REPLY_LEDS_CMD,
.len = sizeof(struct iwl_led_cmd),
.data = led_cmd,
- .meta.flags = CMD_ASYNC,
- .meta.u.callback = NULL,
+ .flags = CMD_ASYNC,
+ .callback = NULL,
};
u32 reg;
@@ -104,7 +104,7 @@ static int iwl_send_led_cmd(struct iwl_priv *priv, struct iwl_led_cmd *led_cmd)
}
/* Set led pattern command */
-static int iwl4965_led_pattern(struct iwl_priv *priv, int led_id,
+static int iwl_led_pattern(struct iwl_priv *priv, int led_id,
unsigned int idx)
{
struct iwl_led_cmd led_cmd = {
@@ -121,7 +121,7 @@ static int iwl4965_led_pattern(struct iwl_priv *priv, int led_id,
}
/* Set led register off */
-static int iwl4965_led_on_reg(struct iwl_priv *priv, int led_id)
+static int iwl_led_on_reg(struct iwl_priv *priv, int led_id)
{
IWL_DEBUG_LED(priv, "led on %d\n", led_id);
iwl_write32(priv, CSR_LED_REG, CSR_LED_REG_TRUN_ON);
@@ -130,7 +130,7 @@ static int iwl4965_led_on_reg(struct iwl_priv *priv, int led_id)
#if 0
/* Set led on command */
-static int iwl4965_led_on(struct iwl_priv *priv, int led_id)
+static int iwl_led_on(struct iwl_priv *priv, int led_id)
{
struct iwl_led_cmd led_cmd = {
.id = led_id,
@@ -142,7 +142,7 @@ static int iwl4965_led_on(struct iwl_priv *priv, int led_id)
}
/* Set led off command */
-int iwl4965_led_off(struct iwl_priv *priv, int led_id)
+int iwl_led_off(struct iwl_priv *priv, int led_id)
{
struct iwl_led_cmd led_cmd = {
.id = led_id,
@@ -157,7 +157,7 @@ int iwl4965_led_off(struct iwl_priv *priv, int led_id)
/* Set led register off */
-static int iwl4965_led_off_reg(struct iwl_priv *priv, int led_id)
+static int iwl_led_off_reg(struct iwl_priv *priv, int led_id)
{
IWL_DEBUG_LED(priv, "LED Reg off\n");
iwl_write32(priv, CSR_LED_REG, CSR_LED_REG_TRUN_OFF);
@@ -171,7 +171,7 @@ static int iwl_led_associate(struct iwl_priv *priv, int led_id)
{
IWL_DEBUG_LED(priv, "Associated\n");
priv->allow_blinking = 1;
- return iwl4965_led_on_reg(priv, led_id);
+ return iwl_led_on_reg(priv, led_id);
}
static int iwl_led_disassociate(struct iwl_priv *priv, int led_id)
{
@@ -264,13 +264,16 @@ static int iwl_leds_register_led(struct iwl_priv *priv, struct iwl_led *led,
/*
- * calculate blink rate according to last 2 sec Tx/Rx activities
+ * calculate blink rate according to last second Tx/Rx activities
*/
static int iwl_get_blink_rate(struct iwl_priv *priv)
{
int i;
- u64 current_tpt = priv->tx_stats[2].bytes;
- /* FIXME: + priv->rx_stats[2].bytes; */
+ /* count both tx and rx traffic to be able to
+ * handle traffic in either direction
+ */
+ u64 current_tpt = priv->tx_stats.data_bytes +
+ priv->rx_stats.data_bytes;
s64 tpt = current_tpt - priv->led_tpt;
if (tpt < 0) /* wraparound */
@@ -314,7 +317,7 @@ void iwl_leds_background(struct iwl_priv *priv)
priv->last_blink_time = 0;
if (priv->last_blink_rate != IWL_SOLID_BLINK_IDX) {
priv->last_blink_rate = IWL_SOLID_BLINK_IDX;
- iwl4965_led_pattern(priv, IWL_LED_LINK,
+ iwl_led_pattern(priv, IWL_LED_LINK,
IWL_SOLID_BLINK_IDX);
}
return;
@@ -328,12 +331,11 @@ void iwl_leds_background(struct iwl_priv *priv)
/* call only if blink rate change */
if (blink_idx != priv->last_blink_rate)
- iwl4965_led_pattern(priv, IWL_LED_LINK, blink_idx);
+ iwl_led_pattern(priv, IWL_LED_LINK, blink_idx);
priv->last_blink_time = jiffies;
priv->last_blink_rate = blink_idx;
}
-EXPORT_SYMBOL(iwl_leds_background);
/* Register all led handler */
int iwl_leds_register(struct iwl_priv *priv)
@@ -351,8 +353,8 @@ int iwl_leds_register(struct iwl_priv *priv)
sizeof(priv->led[IWL_LED_TRG_RADIO].name), "iwl-%s::radio",
wiphy_name(priv->hw->wiphy));
- priv->led[IWL_LED_TRG_RADIO].led_on = iwl4965_led_on_reg;
- priv->led[IWL_LED_TRG_RADIO].led_off = iwl4965_led_off_reg;
+ priv->led[IWL_LED_TRG_RADIO].led_on = iwl_led_on_reg;
+ priv->led[IWL_LED_TRG_RADIO].led_off = iwl_led_off_reg;
priv->led[IWL_LED_TRG_RADIO].led_pattern = NULL;
ret = iwl_leds_register_led(priv, &priv->led[IWL_LED_TRG_RADIO],
@@ -386,7 +388,7 @@ int iwl_leds_register(struct iwl_priv *priv)
priv->led[IWL_LED_TRG_RX].led_on = iwl_led_associated;
priv->led[IWL_LED_TRG_RX].led_off = iwl_led_associated;
- priv->led[IWL_LED_TRG_RX].led_pattern = iwl4965_led_pattern;
+ priv->led[IWL_LED_TRG_RX].led_pattern = iwl_led_pattern;
if (ret)
goto exit_fail;
@@ -401,7 +403,7 @@ int iwl_leds_register(struct iwl_priv *priv)
priv->led[IWL_LED_TRG_TX].led_on = iwl_led_associated;
priv->led[IWL_LED_TRG_TX].led_off = iwl_led_associated;
- priv->led[IWL_LED_TRG_TX].led_pattern = iwl4965_led_pattern;
+ priv->led[IWL_LED_TRG_TX].led_pattern = iwl_led_pattern;
if (ret)
goto exit_fail;
diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c
index f2ea3f05f6e..0b16841f45f 100644
--- a/drivers/net/wireless/iwlwifi/iwl-power.c
+++ b/drivers/net/wireless/iwlwifi/iwl-power.c
@@ -36,25 +36,41 @@
#include "iwl-eeprom.h"
#include "iwl-dev.h"
#include "iwl-core.h"
+#include "iwl-io.h"
#include "iwl-commands.h"
#include "iwl-debug.h"
#include "iwl-power.h"
/*
- * Setting power level allow the card to go to sleep when not busy.
+ * Setting power level allows the card to go to sleep when not busy.
*
- * The power level is set to INDEX_1 (the least deep state) by
- * default, and will, in the future, be the deepest state unless
- * otherwise required by pm_qos network latency requirements.
- *
- * Using INDEX_1 without pm_qos is ok because mac80211 will disable
- * PS when even checking every beacon for the TIM bit would exceed
- * the required latency.
+ * We calculate a sleep command based on the required latency, which
+ * we get from mac80211. In order to handle thermal throttling, we can
+ * also use pre-defined power levels.
*/
-#define IWL_POWER_RANGE_0_MAX (2)
-#define IWL_POWER_RANGE_1_MAX (10)
+/*
+ * For now, keep using power level 1 instead of automatically
+ * adjusting ...
+ */
+bool no_sleep_autoadjust = true;
+module_param(no_sleep_autoadjust, bool, S_IRUGO);
+MODULE_PARM_DESC(no_sleep_autoadjust,
+ "don't automatically adjust sleep level "
+ "according to maximum network latency");
+/*
+ * This defines the old power levels. They are still used by default
+ * (level 1) and for thermal throttle (levels 3 through 5)
+ */
+
+struct iwl_power_vec_entry {
+ struct iwl_powertable_cmd cmd;
+ u8 no_dtim;
+};
+
+#define IWL_DTIM_RANGE_0_MAX 2
+#define IWL_DTIM_RANGE_1_MAX 10
#define NOSLP cpu_to_le16(0), 0, 0
#define SLP IWL_POWER_DRIVER_ALLOW_SLEEP_MSK, 0, 0
@@ -66,9 +82,8 @@
cpu_to_le32(X3), \
cpu_to_le32(X4)}
/* default power management (not Tx power) table values */
-/* for DTIM period 0 through IWL_POWER_RANGE_0_MAX */
+/* for DTIM period 0 through IWL_DTIM_RANGE_0_MAX */
static const struct iwl_power_vec_entry range_0[IWL_POWER_NUM] = {
- {{NOSLP, SLP_TOUT(0), SLP_TOUT(0), SLP_VEC(0, 0, 0, 0, 0)}, 0},
{{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 2, 2, 2, 0xFF)}, 0},
{{SLP, SLP_TOUT(200), SLP_TOUT(300), SLP_VEC(1, 2, 2, 2, 0xFF)}, 0},
{{SLP, SLP_TOUT(50), SLP_TOUT(100), SLP_VEC(2, 2, 2, 2, 0xFF)}, 0},
@@ -77,9 +92,8 @@ static const struct iwl_power_vec_entry range_0[IWL_POWER_NUM] = {
};
-/* for DTIM period IWL_POWER_RANGE_0_MAX + 1 through IWL_POWER_RANGE_1_MAX */
+/* for DTIM period IWL_DTIM_RANGE_0_MAX + 1 through IWL_DTIM_RANGE_1_MAX */
static const struct iwl_power_vec_entry range_1[IWL_POWER_NUM] = {
- {{NOSLP, SLP_TOUT(0), SLP_TOUT(0), SLP_VEC(0, 0, 0, 0, 0)}, 0},
{{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 2, 3, 4, 4)}, 0},
{{SLP, SLP_TOUT(200), SLP_TOUT(300), SLP_VEC(1, 2, 3, 4, 7)}, 0},
{{SLP, SLP_TOUT(50), SLP_TOUT(100), SLP_VEC(2, 4, 6, 7, 9)}, 0},
@@ -87,9 +101,8 @@ static const struct iwl_power_vec_entry range_1[IWL_POWER_NUM] = {
{{SLP, SLP_TOUT(25), SLP_TOUT(25), SLP_VEC(2, 4, 7, 10, 10)}, 2}
};
-/* for DTIM period > IWL_POWER_RANGE_1_MAX */
+/* for DTIM period > IWL_DTIM_RANGE_1_MAX */
static const struct iwl_power_vec_entry range_2[IWL_POWER_NUM] = {
- {{NOSLP, SLP_TOUT(0), SLP_TOUT(0), SLP_VEC(0, 0, 0, 0, 0)}, 0},
{{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 2, 3, 4, 0xFF)}, 0},
{{SLP, SLP_TOUT(200), SLP_TOUT(300), SLP_VEC(2, 4, 6, 7, 0xFF)}, 0},
{{SLP, SLP_TOUT(50), SLP_TOUT(100), SLP_VEC(2, 7, 9, 9, 0xFF)}, 0},
@@ -97,80 +110,29 @@ static const struct iwl_power_vec_entry range_2[IWL_POWER_NUM] = {
{{SLP, SLP_TOUT(25), SLP_TOUT(25), SLP_VEC(4, 7, 10, 10, 0xFF)}, 0}
};
-
-/* set card power command */
-static int iwl_set_power(struct iwl_priv *priv, void *cmd)
-{
- return iwl_send_cmd_pdu(priv, POWER_TABLE_CMD,
- sizeof(struct iwl_powertable_cmd), cmd);
-}
-
-/* initialize to default */
-static void iwl_power_init_handle(struct iwl_priv *priv)
-{
- struct iwl_power_mgr *pow_data;
- int size = sizeof(struct iwl_power_vec_entry) * IWL_POWER_NUM;
- struct iwl_powertable_cmd *cmd;
- int i;
- u16 lctl;
-
- IWL_DEBUG_POWER(priv, "Initialize power \n");
-
- pow_data = &priv->power_data;
-
- memset(pow_data, 0, sizeof(*pow_data));
-
- memcpy(&pow_data->pwr_range_0[0], &range_0[0], size);
- memcpy(&pow_data->pwr_range_1[0], &range_1[0], size);
- memcpy(&pow_data->pwr_range_2[0], &range_2[0], size);
-
- lctl = iwl_pcie_link_ctl(priv);
-
- IWL_DEBUG_POWER(priv, "adjust power command flags\n");
-
- for (i = 0; i < IWL_POWER_NUM; i++) {
- cmd = &pow_data->pwr_range_0[i].cmd;
-
- if (lctl & PCI_CFG_LINK_CTRL_VAL_L0S_EN)
- cmd->flags &= ~IWL_POWER_PCI_PM_MSK;
- else
- cmd->flags |= IWL_POWER_PCI_PM_MSK;
- }
-}
-
-/* adjust power command according to DTIM period and power level*/
-static int iwl_update_power_cmd(struct iwl_priv *priv,
- struct iwl_powertable_cmd *cmd, u16 mode)
+static void iwl_static_sleep_cmd(struct iwl_priv *priv,
+ struct iwl_powertable_cmd *cmd,
+ enum iwl_power_level lvl, int period)
{
- struct iwl_power_vec_entry *range;
- struct iwl_power_mgr *pow_data;
- int i;
- u32 max_sleep = 0;
- u8 period;
+ const struct iwl_power_vec_entry *table;
+ int max_sleep, i;
bool skip;
- if (mode > IWL_POWER_INDEX_5) {
- IWL_DEBUG_POWER(priv, "Error invalid power mode \n");
- return -EINVAL;
- }
+ table = range_2;
+ if (period < IWL_DTIM_RANGE_1_MAX)
+ table = range_1;
+ if (period < IWL_DTIM_RANGE_0_MAX)
+ table = range_0;
- pow_data = &priv->power_data;
+ BUG_ON(lvl < 0 || lvl >= IWL_POWER_NUM);
- if (pow_data->dtim_period <= IWL_POWER_RANGE_0_MAX)
- range = &pow_data->pwr_range_0[0];
- else if (pow_data->dtim_period <= IWL_POWER_RANGE_1_MAX)
- range = &pow_data->pwr_range_1[0];
- else
- range = &pow_data->pwr_range_2[0];
-
- period = pow_data->dtim_period;
- memcpy(cmd, &range[mode].cmd, sizeof(struct iwl_powertable_cmd));
+ *cmd = table[lvl].cmd;
if (period == 0) {
- period = 1;
skip = false;
+ period = 1;
} else {
- skip = !!range[mode].no_dtim;
+ skip = !!table[lvl].no_dtim;
}
if (skip) {
@@ -178,7 +140,7 @@ static int iwl_update_power_cmd(struct iwl_priv *priv,
max_sleep = le32_to_cpu(slp_itrvl);
if (max_sleep == 0xFF)
max_sleep = period * (skip + 1);
- else if (max_sleep > period)
+ else if (max_sleep > period)
max_sleep = (le32_to_cpu(slp_itrvl) / period) * period;
cmd->flags |= IWL_POWER_SLEEP_OVER_DTIM_MSK;
} else {
@@ -190,6 +152,92 @@ static int iwl_update_power_cmd(struct iwl_priv *priv,
if (le32_to_cpu(cmd->sleep_interval[i]) > max_sleep)
cmd->sleep_interval[i] = cpu_to_le32(max_sleep);
+ if (priv->power_data.pci_pm)
+ cmd->flags |= IWL_POWER_PCI_PM_MSK;
+ else
+ cmd->flags &= ~IWL_POWER_PCI_PM_MSK;
+
+ IWL_DEBUG_POWER(priv, "Sleep command for index %d\n", lvl + 1);
+}
+
+/* default Thermal Throttling transaction table
+ * Current state | Throttling Down | Throttling Up
+ *=============================================================================
+ * Condition Nxt State Condition Nxt State Condition Nxt State
+ *-----------------------------------------------------------------------------
+ * IWL_TI_0 T >= 115 CT_KILL 115>T>=105 TI_1 N/A N/A
+ * IWL_TI_1 T >= 115 CT_KILL 115>T>=110 TI_2 T<=95 TI_0
+ * IWL_TI_2 T >= 115 CT_KILL T<=100 TI_1
+ * IWL_CT_KILL N/A N/A N/A N/A T<=95 TI_0
+ *=============================================================================
+ */
+static const struct iwl_tt_trans tt_range_0[IWL_TI_STATE_MAX - 1] = {
+ {IWL_TI_0, IWL_ABSOLUTE_ZERO, 104},
+ {IWL_TI_1, 105, CT_KILL_THRESHOLD},
+ {IWL_TI_CT_KILL, CT_KILL_THRESHOLD + 1, IWL_ABSOLUTE_MAX}
+};
+static const struct iwl_tt_trans tt_range_1[IWL_TI_STATE_MAX - 1] = {
+ {IWL_TI_0, IWL_ABSOLUTE_ZERO, 95},
+ {IWL_TI_2, 110, CT_KILL_THRESHOLD},
+ {IWL_TI_CT_KILL, CT_KILL_THRESHOLD + 1, IWL_ABSOLUTE_MAX}
+};
+static const struct iwl_tt_trans tt_range_2[IWL_TI_STATE_MAX - 1] = {
+ {IWL_TI_1, IWL_ABSOLUTE_ZERO, 100},
+ {IWL_TI_CT_KILL, CT_KILL_THRESHOLD + 1, IWL_ABSOLUTE_MAX},
+ {IWL_TI_CT_KILL, CT_KILL_THRESHOLD + 1, IWL_ABSOLUTE_MAX}
+};
+static const struct iwl_tt_trans tt_range_3[IWL_TI_STATE_MAX - 1] = {
+ {IWL_TI_0, IWL_ABSOLUTE_ZERO, CT_KILL_EXIT_THRESHOLD},
+ {IWL_TI_CT_KILL, CT_KILL_EXIT_THRESHOLD + 1, IWL_ABSOLUTE_MAX},
+ {IWL_TI_CT_KILL, CT_KILL_EXIT_THRESHOLD + 1, IWL_ABSOLUTE_MAX}
+};
+
+/* Advance Thermal Throttling default restriction table */
+static const struct iwl_tt_restriction restriction_range[IWL_TI_STATE_MAX] = {
+ {IWL_ANT_OK_MULTI, IWL_ANT_OK_MULTI, true },
+ {IWL_ANT_OK_SINGLE, IWL_ANT_OK_MULTI, true },
+ {IWL_ANT_OK_SINGLE, IWL_ANT_OK_SINGLE, false },
+ {IWL_ANT_OK_NONE, IWL_ANT_OK_NONE, false }
+};
+
+
+static void iwl_power_sleep_cam_cmd(struct iwl_priv *priv,
+ struct iwl_powertable_cmd *cmd)
+{
+ memset(cmd, 0, sizeof(*cmd));
+
+ if (priv->power_data.pci_pm)
+ cmd->flags |= IWL_POWER_PCI_PM_MSK;
+
+ IWL_DEBUG_POWER(priv, "Sleep command for CAM\n");
+}
+
+static void iwl_power_fill_sleep_cmd(struct iwl_priv *priv,
+ struct iwl_powertable_cmd *cmd,
+ int dynps_ms, int wakeup_period)
+{
+ int i;
+
+ memset(cmd, 0, sizeof(*cmd));
+
+ cmd->flags = IWL_POWER_DRIVER_ALLOW_SLEEP_MSK |
+ IWL_POWER_FAST_PD; /* no use seeing frames for others */
+
+ if (priv->power_data.pci_pm)
+ cmd->flags |= IWL_POWER_PCI_PM_MSK;
+
+ cmd->rx_data_timeout = cpu_to_le32(1000 * dynps_ms);
+ cmd->tx_data_timeout = cpu_to_le32(1000 * dynps_ms);
+
+ for (i = 0; i < IWL_POWER_VEC_SIZE; i++)
+ cmd->sleep_interval[i] = cpu_to_le32(wakeup_period);
+
+ IWL_DEBUG_POWER(priv, "Automatic sleep command\n");
+}
+
+static int iwl_set_power(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd)
+{
+ IWL_DEBUG_POWER(priv, "Sending power/sleep command\n");
IWL_DEBUG_POWER(priv, "Flags value = 0x%08X\n", cmd->flags);
IWL_DEBUG_POWER(priv, "Tx timeout = %u\n", le32_to_cpu(cmd->tx_data_timeout));
IWL_DEBUG_POWER(priv, "Rx timeout = %u\n", le32_to_cpu(cmd->rx_data_timeout));
@@ -200,79 +248,587 @@ static int iwl_update_power_cmd(struct iwl_priv *priv,
le32_to_cpu(cmd->sleep_interval[3]),
le32_to_cpu(cmd->sleep_interval[4]));
- return 0;
+ return iwl_send_cmd_pdu(priv, POWER_TABLE_CMD,
+ sizeof(struct iwl_powertable_cmd), cmd);
}
-/*
- * compute the final power mode index
- */
int iwl_power_update_mode(struct iwl_priv *priv, bool force)
{
- struct iwl_power_mgr *setting = &(priv->power_data);
int ret = 0;
- u16 uninitialized_var(final_mode);
+ struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
+ bool enabled = (priv->iw_mode == NL80211_IFTYPE_STATION) &&
+ (priv->hw->conf.flags & IEEE80211_CONF_PS);
bool update_chains;
+ struct iwl_powertable_cmd cmd;
+ int dtimper;
/* Don't update the RX chain when chain noise calibration is running */
update_chains = priv->chain_noise_data.state == IWL_CHAIN_NOISE_DONE ||
priv->chain_noise_data.state == IWL_CHAIN_NOISE_ALIVE;
- final_mode = priv->power_data.user_power_setting;
-
- if (setting->power_disabled)
- final_mode = IWL_POWER_MODE_CAM;
+ if (priv->vif)
+ dtimper = priv->vif->bss_conf.dtim_period;
+ else
+ dtimper = 1;
+
+ /* TT power setting overwrites everything */
+ if (tt->state >= IWL_TI_1)
+ iwl_static_sleep_cmd(priv, &cmd, tt->tt_power_mode, dtimper);
+ else if (!enabled)
+ iwl_power_sleep_cam_cmd(priv, &cmd);
+ else if (priv->power_data.debug_sleep_level_override >= 0)
+ iwl_static_sleep_cmd(priv, &cmd,
+ priv->power_data.debug_sleep_level_override,
+ dtimper);
+ else if (no_sleep_autoadjust)
+ iwl_static_sleep_cmd(priv, &cmd, IWL_POWER_INDEX_1, dtimper);
+ else
+ iwl_power_fill_sleep_cmd(priv, &cmd,
+ priv->hw->conf.dynamic_ps_timeout,
+ priv->hw->conf.max_sleep_period);
if (iwl_is_ready_rf(priv) &&
- ((setting->power_mode != final_mode) || force)) {
- struct iwl_powertable_cmd cmd;
-
- if (final_mode != IWL_POWER_MODE_CAM)
+ (memcmp(&priv->power_data.sleep_cmd, &cmd, sizeof(cmd)) || force)) {
+ if (cmd.flags & IWL_POWER_DRIVER_ALLOW_SLEEP_MSK)
set_bit(STATUS_POWER_PMI, &priv->status);
- iwl_update_power_cmd(priv, &cmd, final_mode);
- cmd.keep_alive_beacons = 0;
-
- if (final_mode == IWL_POWER_INDEX_5)
- cmd.flags |= IWL_POWER_FAST_PD;
-
ret = iwl_set_power(priv, &cmd);
-
- if (final_mode == IWL_POWER_MODE_CAM)
- clear_bit(STATUS_POWER_PMI, &priv->status);
-
- if (priv->cfg->ops->lib->update_chain_flags && update_chains)
- priv->cfg->ops->lib->update_chain_flags(priv);
- else
- IWL_DEBUG_POWER(priv, "Cannot update the power, chain noise "
+ if (!ret) {
+ if (!(cmd.flags & IWL_POWER_DRIVER_ALLOW_SLEEP_MSK))
+ clear_bit(STATUS_POWER_PMI, &priv->status);
+
+ if (priv->cfg->ops->lib->update_chain_flags &&
+ update_chains)
+ priv->cfg->ops->lib->update_chain_flags(priv);
+ else
+ IWL_DEBUG_POWER(priv,
+ "Cannot update the power, chain noise "
"calibration running: %d\n",
priv->chain_noise_data.state);
- if (!ret)
- setting->power_mode = final_mode;
+ memcpy(&priv->power_data.sleep_cmd, &cmd, sizeof(cmd));
+ } else
+ IWL_ERR(priv, "set power fail, ret = %d", ret);
}
return ret;
}
EXPORT_SYMBOL(iwl_power_update_mode);
-/* set user_power_setting */
-int iwl_power_set_user_mode(struct iwl_priv *priv, u16 mode)
+bool iwl_ht_enabled(struct iwl_priv *priv)
{
- if (mode >= IWL_POWER_NUM)
- return -EINVAL;
+ struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
+ struct iwl_tt_restriction *restriction;
- priv->power_data.user_power_setting = mode;
+ if (!priv->thermal_throttle.advanced_tt)
+ return true;
+ restriction = tt->restriction + tt->state;
+ return restriction->is_ht;
+}
+EXPORT_SYMBOL(iwl_ht_enabled);
+
+enum iwl_antenna_ok iwl_tx_ant_restriction(struct iwl_priv *priv)
+{
+ struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
+ struct iwl_tt_restriction *restriction;
- return iwl_power_update_mode(priv, 0);
+ if (!priv->thermal_throttle.advanced_tt)
+ return IWL_ANT_OK_MULTI;
+ restriction = tt->restriction + tt->state;
+ return restriction->tx_stream;
}
-EXPORT_SYMBOL(iwl_power_set_user_mode);
+EXPORT_SYMBOL(iwl_tx_ant_restriction);
+
+enum iwl_antenna_ok iwl_rx_ant_restriction(struct iwl_priv *priv)
+{
+ struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
+ struct iwl_tt_restriction *restriction;
+
+ if (!priv->thermal_throttle.advanced_tt)
+ return IWL_ANT_OK_MULTI;
+ restriction = tt->restriction + tt->state;
+ return restriction->rx_stream;
+}
+
+#define CT_KILL_EXIT_DURATION (5) /* 5 seconds duration */
+
+/*
+ * toggle the bit to wake up uCode and check the temperature
+ * if the temperature is below CT, uCode will stay awake and send card
+ * state notification with CT_KILL bit clear to inform Thermal Throttling
+ * Management to change state. Otherwise, uCode will go back to sleep
+ * without doing anything, driver should continue the 5 seconds timer
+ * to wake up uCode for temperature check until temperature drop below CT
+ */
+static void iwl_tt_check_exit_ct_kill(unsigned long data)
+{
+ struct iwl_priv *priv = (struct iwl_priv *)data;
+ struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
+ unsigned long flags;
+
+ if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+ return;
+
+ if (tt->state == IWL_TI_CT_KILL) {
+ if (priv->thermal_throttle.ct_kill_toggle) {
+ iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR,
+ CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT);
+ priv->thermal_throttle.ct_kill_toggle = false;
+ } else {
+ iwl_write32(priv, CSR_UCODE_DRV_GP1_SET,
+ CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT);
+ priv->thermal_throttle.ct_kill_toggle = true;
+ }
+ iwl_read32(priv, CSR_UCODE_DRV_GP1);
+ spin_lock_irqsave(&priv->reg_lock, flags);
+ if (!iwl_grab_nic_access(priv))
+ iwl_release_nic_access(priv);
+ spin_unlock_irqrestore(&priv->reg_lock, flags);
+
+ /* Reschedule the ct_kill timer to occur in
+ * CT_KILL_EXIT_DURATION seconds to ensure we get a
+ * thermal update */
+ mod_timer(&priv->thermal_throttle.ct_kill_exit_tm, jiffies +
+ CT_KILL_EXIT_DURATION * HZ);
+ }
+}
+
+static void iwl_perform_ct_kill_task(struct iwl_priv *priv,
+ bool stop)
+{
+ if (stop) {
+ IWL_DEBUG_POWER(priv, "Stop all queues\n");
+ if (priv->mac80211_registered)
+ ieee80211_stop_queues(priv->hw);
+ IWL_DEBUG_POWER(priv,
+ "Schedule 5 seconds CT_KILL Timer\n");
+ mod_timer(&priv->thermal_throttle.ct_kill_exit_tm, jiffies +
+ CT_KILL_EXIT_DURATION * HZ);
+ } else {
+ IWL_DEBUG_POWER(priv, "Wake all queues\n");
+ if (priv->mac80211_registered)
+ ieee80211_wake_queues(priv->hw);
+ }
+}
+
+#define IWL_MINIMAL_POWER_THRESHOLD (CT_KILL_THRESHOLD_LEGACY)
+#define IWL_REDUCED_PERFORMANCE_THRESHOLD_2 (100)
+#define IWL_REDUCED_PERFORMANCE_THRESHOLD_1 (90)
+
+/*
+ * Legacy thermal throttling
+ * 1) Avoid NIC destruction due to high temperatures
+ * Chip will identify dangerously high temperatures that can
+ * harm the device and will power down
+ * 2) Avoid the NIC power down due to high temperature
+ * Throttle early enough to lower the power consumption before
+ * drastic steps are needed
+ */
+static void iwl_legacy_tt_handler(struct iwl_priv *priv, s32 temp)
+{
+ struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
+ enum iwl_tt_state old_state;
+
+#ifdef CONFIG_IWLWIFI_DEBUG
+ if ((tt->tt_previous_temp) &&
+ (temp > tt->tt_previous_temp) &&
+ ((temp - tt->tt_previous_temp) >
+ IWL_TT_INCREASE_MARGIN)) {
+ IWL_DEBUG_POWER(priv,
+ "Temperature increase %d degree Celsius\n",
+ (temp - tt->tt_previous_temp));
+ }
+#endif
+ old_state = tt->state;
+ /* in Celsius */
+ if (temp >= IWL_MINIMAL_POWER_THRESHOLD)
+ tt->state = IWL_TI_CT_KILL;
+ else if (temp >= IWL_REDUCED_PERFORMANCE_THRESHOLD_2)
+ tt->state = IWL_TI_2;
+ else if (temp >= IWL_REDUCED_PERFORMANCE_THRESHOLD_1)
+ tt->state = IWL_TI_1;
+ else
+ tt->state = IWL_TI_0;
+
+#ifdef CONFIG_IWLWIFI_DEBUG
+ tt->tt_previous_temp = temp;
+#endif
+ if (tt->state != old_state) {
+ switch (tt->state) {
+ case IWL_TI_0:
+ /*
+ * When the system is ready to go back to IWL_TI_0
+ * we only have to call iwl_power_update_mode() to
+ * do so.
+ */
+ break;
+ case IWL_TI_1:
+ tt->tt_power_mode = IWL_POWER_INDEX_3;
+ break;
+ case IWL_TI_2:
+ tt->tt_power_mode = IWL_POWER_INDEX_4;
+ break;
+ default:
+ tt->tt_power_mode = IWL_POWER_INDEX_5;
+ break;
+ }
+ mutex_lock(&priv->mutex);
+ if (iwl_power_update_mode(priv, true)) {
+ /* TT state not updated
+ * try again during next temperature read
+ */
+ tt->state = old_state;
+ IWL_ERR(priv, "Cannot update power mode, "
+ "TT state not updated\n");
+ } else {
+ if (tt->state == IWL_TI_CT_KILL)
+ iwl_perform_ct_kill_task(priv, true);
+ else if (old_state == IWL_TI_CT_KILL &&
+ tt->state != IWL_TI_CT_KILL)
+ iwl_perform_ct_kill_task(priv, false);
+ IWL_DEBUG_POWER(priv, "Temperature state changed %u\n",
+ tt->state);
+ IWL_DEBUG_POWER(priv, "Power Index change to %u\n",
+ tt->tt_power_mode);
+ }
+ mutex_unlock(&priv->mutex);
+ }
+}
+
+/*
+ * Advance thermal throttling
+ * 1) Avoid NIC destruction due to high temperatures
+ * Chip will identify dangerously high temperatures that can
+ * harm the device and will power down
+ * 2) Avoid the NIC power down due to high temperature
+ * Throttle early enough to lower the power consumption before
+ * drastic steps are needed
+ * Actions include relaxing the power down sleep thresholds and
+ * decreasing the number of TX streams
+ * 3) Avoid throughput performance impact as much as possible
+ *
+ *=============================================================================
+ * Condition Nxt State Condition Nxt State Condition Nxt State
+ *-----------------------------------------------------------------------------
+ * IWL_TI_0 T >= 115 CT_KILL 115>T>=105 TI_1 N/A N/A
+ * IWL_TI_1 T >= 115 CT_KILL 115>T>=110 TI_2 T<=95 TI_0
+ * IWL_TI_2 T >= 115 CT_KILL T<=100 TI_1
+ * IWL_CT_KILL N/A N/A N/A N/A T<=95 TI_0
+ *=============================================================================
+ */
+static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp)
+{
+ struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
+ int i;
+ bool changed = false;
+ enum iwl_tt_state old_state;
+ struct iwl_tt_trans *transaction;
+
+ old_state = tt->state;
+ for (i = 0; i < IWL_TI_STATE_MAX - 1; i++) {
+ /* based on the current TT state,
+ * find the curresponding transaction table
+ * each table has (IWL_TI_STATE_MAX - 1) entries
+ * tt->transaction + ((old_state * (IWL_TI_STATE_MAX - 1))
+ * will advance to the correct table.
+ * then based on the current temperature
+ * find the next state need to transaction to
+ * go through all the possible (IWL_TI_STATE_MAX - 1) entries
+ * in the current table to see if transaction is needed
+ */
+ transaction = tt->transaction +
+ ((old_state * (IWL_TI_STATE_MAX - 1)) + i);
+ if (temp >= transaction->tt_low &&
+ temp <= transaction->tt_high) {
+#ifdef CONFIG_IWLWIFI_DEBUG
+ if ((tt->tt_previous_temp) &&
+ (temp > tt->tt_previous_temp) &&
+ ((temp - tt->tt_previous_temp) >
+ IWL_TT_INCREASE_MARGIN)) {
+ IWL_DEBUG_POWER(priv,
+ "Temperature increase %d "
+ "degree Celsius\n",
+ (temp - tt->tt_previous_temp));
+ }
+ tt->tt_previous_temp = temp;
+#endif
+ if (old_state !=
+ transaction->next_state) {
+ changed = true;
+ tt->state =
+ transaction->next_state;
+ }
+ break;
+ }
+ }
+ if (changed) {
+ struct iwl_rxon_cmd *rxon = &priv->staging_rxon;
+
+ if (tt->state >= IWL_TI_1) {
+ /* force PI = IWL_POWER_INDEX_5 in the case of TI > 0 */
+ tt->tt_power_mode = IWL_POWER_INDEX_5;
+ if (!iwl_ht_enabled(priv))
+ /* disable HT */
+ rxon->flags &= ~(RXON_FLG_CHANNEL_MODE_MSK |
+ RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK |
+ RXON_FLG_HT40_PROT_MSK |
+ RXON_FLG_HT_PROT_MSK);
+ else {
+ /* check HT capability and set
+ * according to the system HT capability
+ * in case get disabled before */
+ iwl_set_rxon_ht(priv, &priv->current_ht_config);
+ }
+
+ } else {
+ /*
+ * restore system power setting -- it will be
+ * recalculated automatically.
+ */
+
+ /* check HT capability and set
+ * according to the system HT capability
+ * in case get disabled before */
+ iwl_set_rxon_ht(priv, &priv->current_ht_config);
+ }
+ mutex_lock(&priv->mutex);
+ if (iwl_power_update_mode(priv, true)) {
+ /* TT state not updated
+ * try again during next temperature read
+ */
+ IWL_ERR(priv, "Cannot update power mode, "
+ "TT state not updated\n");
+ tt->state = old_state;
+ } else {
+ IWL_DEBUG_POWER(priv,
+ "Thermal Throttling to new state: %u\n",
+ tt->state);
+ if (old_state != IWL_TI_CT_KILL &&
+ tt->state == IWL_TI_CT_KILL) {
+ IWL_DEBUG_POWER(priv, "Enter IWL_TI_CT_KILL\n");
+ iwl_perform_ct_kill_task(priv, true);
+
+ } else if (old_state == IWL_TI_CT_KILL &&
+ tt->state != IWL_TI_CT_KILL) {
+ IWL_DEBUG_POWER(priv, "Exit IWL_TI_CT_KILL\n");
+ iwl_perform_ct_kill_task(priv, false);
+ }
+ }
+ mutex_unlock(&priv->mutex);
+ }
+}
+
+/* Card State Notification indicated reach critical temperature
+ * if PSP not enable, no Thermal Throttling function will be performed
+ * just set the GP1 bit to acknowledge the event
+ * otherwise, go into IWL_TI_CT_KILL state
+ * since Card State Notification will not provide any temperature reading
+ * for Legacy mode
+ * so just pass the CT_KILL temperature to iwl_legacy_tt_handler()
+ * for advance mode
+ * pass CT_KILL_THRESHOLD+1 to make sure move into IWL_TI_CT_KILL state
+ */
+static void iwl_bg_ct_enter(struct work_struct *work)
+{
+ struct iwl_priv *priv = container_of(work, struct iwl_priv, ct_enter);
+ struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
+
+ if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+ return;
+
+ if (!iwl_is_ready(priv))
+ return;
+
+ if (tt->state != IWL_TI_CT_KILL) {
+ IWL_ERR(priv, "Device reached critical temperature "
+ "- ucode going to sleep!\n");
+ if (!priv->thermal_throttle.advanced_tt)
+ iwl_legacy_tt_handler(priv,
+ IWL_MINIMAL_POWER_THRESHOLD);
+ else
+ iwl_advance_tt_handler(priv,
+ CT_KILL_THRESHOLD + 1);
+ }
+}
+
+/* Card State Notification indicated out of critical temperature
+ * since Card State Notification will not provide any temperature reading
+ * so pass the IWL_REDUCED_PERFORMANCE_THRESHOLD_2 temperature
+ * to iwl_legacy_tt_handler() to get out of IWL_CT_KILL state
+ */
+static void iwl_bg_ct_exit(struct work_struct *work)
+{
+ struct iwl_priv *priv = container_of(work, struct iwl_priv, ct_exit);
+ struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
+
+ if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+ return;
+
+ if (!iwl_is_ready(priv))
+ return;
+
+ /* stop ct_kill_exit_tm timer */
+ del_timer_sync(&priv->thermal_throttle.ct_kill_exit_tm);
+
+ if (tt->state == IWL_TI_CT_KILL) {
+ IWL_ERR(priv,
+ "Device temperature below critical"
+ "- ucode awake!\n");
+ if (!priv->thermal_throttle.advanced_tt)
+ iwl_legacy_tt_handler(priv,
+ IWL_REDUCED_PERFORMANCE_THRESHOLD_2);
+ else
+ iwl_advance_tt_handler(priv, CT_KILL_EXIT_THRESHOLD);
+ }
+}
+
+void iwl_tt_enter_ct_kill(struct iwl_priv *priv)
+{
+ if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+ return;
+
+ IWL_DEBUG_POWER(priv, "Queueing critical temperature enter.\n");
+ queue_work(priv->workqueue, &priv->ct_enter);
+}
+EXPORT_SYMBOL(iwl_tt_enter_ct_kill);
+
+void iwl_tt_exit_ct_kill(struct iwl_priv *priv)
+{
+ if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+ return;
+
+ IWL_DEBUG_POWER(priv, "Queueing critical temperature exit.\n");
+ queue_work(priv->workqueue, &priv->ct_exit);
+}
+EXPORT_SYMBOL(iwl_tt_exit_ct_kill);
+
+static void iwl_bg_tt_work(struct work_struct *work)
+{
+ struct iwl_priv *priv = container_of(work, struct iwl_priv, tt_work);
+ s32 temp = priv->temperature; /* degrees CELSIUS except 4965 */
+
+ if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+ return;
+
+ if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_4965)
+ temp = KELVIN_TO_CELSIUS(priv->temperature);
+
+ if (!priv->thermal_throttle.advanced_tt)
+ iwl_legacy_tt_handler(priv, temp);
+ else
+ iwl_advance_tt_handler(priv, temp);
+}
+
+void iwl_tt_handler(struct iwl_priv *priv)
+{
+ if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+ return;
+
+ IWL_DEBUG_POWER(priv, "Queueing thermal throttling work.\n");
+ queue_work(priv->workqueue, &priv->tt_work);
+}
+EXPORT_SYMBOL(iwl_tt_handler);
+
+/* Thermal throttling initialization
+ * For advance thermal throttling:
+ * Initialize Thermal Index and temperature threshold table
+ * Initialize thermal throttling restriction table
+ */
+void iwl_tt_initialize(struct iwl_priv *priv)
+{
+ struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
+ int size = sizeof(struct iwl_tt_trans) * (IWL_TI_STATE_MAX - 1);
+ struct iwl_tt_trans *transaction;
+
+ IWL_DEBUG_POWER(priv, "Initialize Thermal Throttling \n");
+
+ memset(tt, 0, sizeof(struct iwl_tt_mgmt));
+
+ tt->state = IWL_TI_0;
+ init_timer(&priv->thermal_throttle.ct_kill_exit_tm);
+ priv->thermal_throttle.ct_kill_exit_tm.data = (unsigned long)priv;
+ priv->thermal_throttle.ct_kill_exit_tm.function = iwl_tt_check_exit_ct_kill;
+
+ /* setup deferred ct kill work */
+ INIT_WORK(&priv->tt_work, iwl_bg_tt_work);
+ INIT_WORK(&priv->ct_enter, iwl_bg_ct_enter);
+ INIT_WORK(&priv->ct_exit, iwl_bg_ct_exit);
+
+ switch (priv->hw_rev & CSR_HW_REV_TYPE_MSK) {
+ case CSR_HW_REV_TYPE_6x00:
+ case CSR_HW_REV_TYPE_6x50:
+ IWL_DEBUG_POWER(priv, "Advanced Thermal Throttling\n");
+ tt->restriction = kzalloc(sizeof(struct iwl_tt_restriction) *
+ IWL_TI_STATE_MAX, GFP_KERNEL);
+ tt->transaction = kzalloc(sizeof(struct iwl_tt_trans) *
+ IWL_TI_STATE_MAX * (IWL_TI_STATE_MAX - 1),
+ GFP_KERNEL);
+ if (!tt->restriction || !tt->transaction) {
+ IWL_ERR(priv, "Fallback to Legacy Throttling\n");
+ priv->thermal_throttle.advanced_tt = false;
+ kfree(tt->restriction);
+ tt->restriction = NULL;
+ kfree(tt->transaction);
+ tt->transaction = NULL;
+ } else {
+ transaction = tt->transaction +
+ (IWL_TI_0 * (IWL_TI_STATE_MAX - 1));
+ memcpy(transaction, &tt_range_0[0], size);
+ transaction = tt->transaction +
+ (IWL_TI_1 * (IWL_TI_STATE_MAX - 1));
+ memcpy(transaction, &tt_range_1[0], size);
+ transaction = tt->transaction +
+ (IWL_TI_2 * (IWL_TI_STATE_MAX - 1));
+ memcpy(transaction, &tt_range_2[0], size);
+ transaction = tt->transaction +
+ (IWL_TI_CT_KILL * (IWL_TI_STATE_MAX - 1));
+ memcpy(transaction, &tt_range_3[0], size);
+ size = sizeof(struct iwl_tt_restriction) *
+ IWL_TI_STATE_MAX;
+ memcpy(tt->restriction,
+ &restriction_range[0], size);
+ priv->thermal_throttle.advanced_tt = true;
+ }
+ break;
+ default:
+ IWL_DEBUG_POWER(priv, "Legacy Thermal Throttling\n");
+ priv->thermal_throttle.advanced_tt = false;
+ break;
+ }
+}
+EXPORT_SYMBOL(iwl_tt_initialize);
+
+/* cleanup thermal throttling management related memory and timer */
+void iwl_tt_exit(struct iwl_priv *priv)
+{
+ struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
+
+ /* stop ct_kill_exit_tm timer if activated */
+ del_timer_sync(&priv->thermal_throttle.ct_kill_exit_tm);
+ cancel_work_sync(&priv->tt_work);
+ cancel_work_sync(&priv->ct_enter);
+ cancel_work_sync(&priv->ct_exit);
+
+ if (priv->thermal_throttle.advanced_tt) {
+ /* free advance thermal throttling memory */
+ kfree(tt->restriction);
+ tt->restriction = NULL;
+ kfree(tt->transaction);
+ tt->transaction = NULL;
+ }
+}
+EXPORT_SYMBOL(iwl_tt_exit);
/* initialize to default */
void iwl_power_initialize(struct iwl_priv *priv)
{
- iwl_power_init_handle(priv);
- priv->power_data.user_power_setting = IWL_POWER_INDEX_1;
- /* default to disabled until mac80211 says otherwise */
- priv->power_data.power_disabled = 1;
+ u16 lctl = iwl_pcie_link_ctl(priv);
+
+ priv->power_data.pci_pm = !(lctl & PCI_CFG_LINK_CTRL_VAL_L0S_EN);
+
+ priv->power_data.debug_sleep_level_override = -1;
+
+ memset(&priv->power_data.sleep_cmd, 0,
+ sizeof(priv->power_data.sleep_cmd));
}
EXPORT_SYMBOL(iwl_power_initialize);
diff --git a/drivers/net/wireless/iwlwifi/iwl-power.h b/drivers/net/wireless/iwlwifi/iwl-power.h
index 37ba3bb7a25..df6f6a49712 100644
--- a/drivers/net/wireless/iwlwifi/iwl-power.h
+++ b/drivers/net/wireless/iwlwifi/iwl-power.h
@@ -28,13 +28,91 @@
#ifndef __iwl_power_setting_h__
#define __iwl_power_setting_h__
-#include <net/mac80211.h>
#include "iwl-commands.h"
-struct iwl_priv;
+#define IWL_ABSOLUTE_ZERO 0
+#define IWL_ABSOLUTE_MAX 0xFFFFFFFF
+#define IWL_TT_INCREASE_MARGIN 5
-enum {
- IWL_POWER_MODE_CAM, /* Continuously Aware Mode, always on */
+enum iwl_antenna_ok {
+ IWL_ANT_OK_NONE,
+ IWL_ANT_OK_SINGLE,
+ IWL_ANT_OK_MULTI,
+};
+
+/* Thermal Throttling State Machine states */
+enum iwl_tt_state {
+ IWL_TI_0, /* normal temperature, system power state */
+ IWL_TI_1, /* high temperature detect, low power state */
+ IWL_TI_2, /* higher temperature detected, lower power state */
+ IWL_TI_CT_KILL, /* critical temperature detected, lowest power state */
+ IWL_TI_STATE_MAX
+};
+
+/**
+ * struct iwl_tt_restriction - Thermal Throttling restriction table
+ * @tx_stream: number of tx stream allowed
+ * @is_ht: ht enable/disable
+ * @rx_stream: number of rx stream allowed
+ *
+ * This table is used by advance thermal throttling management
+ * based on the current thermal throttling state, and determines
+ * the number of tx/rx streams and the status of HT operation.
+ */
+struct iwl_tt_restriction {
+ enum iwl_antenna_ok tx_stream;
+ enum iwl_antenna_ok rx_stream;
+ bool is_ht;
+};
+
+/**
+ * struct iwl_tt_trans - Thermal Throttling transaction table
+ * @next_state: next thermal throttling mode
+ * @tt_low: low temperature threshold to change state
+ * @tt_high: high temperature threshold to change state
+ *
+ * This is used by the advanced thermal throttling algorithm
+ * to determine the next thermal state to go based on the
+ * current temperature.
+ */
+struct iwl_tt_trans {
+ enum iwl_tt_state next_state;
+ u32 tt_low;
+ u32 tt_high;
+};
+
+/**
+ * struct iwl_tt_mgnt - Thermal Throttling Management structure
+ * @advanced_tt: advanced thermal throttle required
+ * @state: current Thermal Throttling state
+ * @tt_power_mode: Thermal Throttling power mode index
+ * being used to set power level when
+ * when thermal throttling state != IWL_TI_0
+ * the tt_power_mode should set to different
+ * power mode based on the current tt state
+ * @tt_previous_temperature: last measured temperature
+ * @iwl_tt_restriction: ptr to restriction tbl, used by advance
+ * thermal throttling to determine how many tx/rx streams
+ * should be used in tt state; and can HT be enabled or not
+ * @iwl_tt_trans: ptr to adv trans table, used by advance thermal throttling
+ * state transaction
+ * @ct_kill_toggle: used to toggle the CSR bit when checking uCode temperature
+ * @ct_kill_exit_tm: timer to exit thermal kill
+ */
+struct iwl_tt_mgmt {
+ enum iwl_tt_state state;
+ bool advanced_tt;
+ u8 tt_power_mode;
+ bool ct_kill_toggle;
+#ifdef CONFIG_IWLWIFI_DEBUG
+ s32 tt_previous_temp;
+#endif
+ struct iwl_tt_restriction *restriction;
+ struct iwl_tt_trans *transaction;
+ struct timer_list ct_kill_exit_tm;
+};
+
+enum iwl_power_level {
IWL_POWER_INDEX_1,
IWL_POWER_INDEX_2,
IWL_POWER_INDEX_3,
@@ -43,26 +121,23 @@ enum {
IWL_POWER_NUM
};
-/* Power management (not Tx power) structures */
-
-struct iwl_power_vec_entry {
- struct iwl_powertable_cmd cmd;
- u8 no_dtim;
-};
-
struct iwl_power_mgr {
- struct iwl_power_vec_entry pwr_range_0[IWL_POWER_NUM];
- struct iwl_power_vec_entry pwr_range_1[IWL_POWER_NUM];
- struct iwl_power_vec_entry pwr_range_2[IWL_POWER_NUM];
- u32 dtim_period;
- /* final power level that used to calculate final power command */
- u8 power_mode;
- u8 user_power_setting; /* set by user through sysfs */
- u8 power_disabled; /* set by mac80211's CONF_PS */
+ struct iwl_powertable_cmd sleep_cmd;
+ int debug_sleep_level_override;
+ bool pci_pm;
};
int iwl_power_update_mode(struct iwl_priv *priv, bool force);
-int iwl_power_set_user_mode(struct iwl_priv *priv, u16 mode);
+bool iwl_ht_enabled(struct iwl_priv *priv);
+enum iwl_antenna_ok iwl_tx_ant_restriction(struct iwl_priv *priv);
+enum iwl_antenna_ok iwl_rx_ant_restriction(struct iwl_priv *priv);
+void iwl_tt_enter_ct_kill(struct iwl_priv *priv);
+void iwl_tt_exit_ct_kill(struct iwl_priv *priv);
+void iwl_tt_handler(struct iwl_priv *priv);
+void iwl_tt_initialize(struct iwl_priv *priv);
+void iwl_tt_exit(struct iwl_priv *priv);
void iwl_power_initialize(struct iwl_priv *priv);
+extern bool no_sleep_autoadjust;
+
#endif /* __iwl_power_setting_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-prph.h b/drivers/net/wireless/iwlwifi/iwl-prph.h
index 3b9cac3fd21..d393e8f0210 100644
--- a/drivers/net/wireless/iwlwifi/iwl-prph.h
+++ b/drivers/net/wireless/iwlwifi/iwl-prph.h
@@ -80,6 +80,8 @@
#define APMG_RFKILL_REG (APMG_BASE + 0x0014)
#define APMG_RTC_INT_STT_REG (APMG_BASE + 0x001c)
#define APMG_RTC_INT_MSK_REG (APMG_BASE + 0x0020)
+#define APMG_DIGITAL_SVR_REG (APMG_BASE + 0x0058)
+#define APMG_ANALOG_SVR_REG (APMG_BASE + 0x006C)
#define APMG_CLK_VAL_DMA_CLK_RQT (0x00000200)
#define APMG_CLK_VAL_BSM_CLK_RQT (0x00000800)
@@ -91,7 +93,8 @@
#define APMG_PS_CTRL_VAL_PWR_SRC_VMAIN (0x00000000)
#define APMG_PS_CTRL_VAL_PWR_SRC_MAX (0x01000000) /* 3945 only */
#define APMG_PS_CTRL_VAL_PWR_SRC_VAUX (0x02000000)
-
+#define APMG_SVR_VOLTAGE_CONFIG_BIT_MSK (0x000001E0) /* bit 8:5 */
+#define APMG_SVR_DIGITAL_VOLTAGE_1_32 (0x00000060)
#define APMG_PCIDEV_STT_VAL_L1_ACT_DIS (0x00000800)
diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c
index 2b8d40b37a1..43b2fce4cbf 100644
--- a/drivers/net/wireless/iwlwifi/iwl-rx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-rx.c
@@ -406,7 +406,6 @@ void iwl_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
rxq->free_count = 0;
spin_unlock_irqrestore(&rxq->lock, flags);
}
-EXPORT_SYMBOL(iwl_rx_queue_reset);
int iwl_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
{
@@ -545,8 +544,8 @@ void iwl_rx_statistics(struct iwl_priv *priv,
change = ((priv->statistics.general.temperature !=
pkt->u.stats.general.temperature) ||
((priv->statistics.flag &
- STATISTICS_REPLY_FLG_FAT_MODE_MSK) !=
- (pkt->u.stats.flag & STATISTICS_REPLY_FLG_FAT_MODE_MSK)));
+ STATISTICS_REPLY_FLG_HT40_MODE_MSK) !=
+ (pkt->u.stats.flag & STATISTICS_REPLY_FLG_HT40_MODE_MSK)));
memcpy(&priv->statistics, &pkt->u.stats, sizeof(priv->statistics));
@@ -646,7 +645,7 @@ static void iwl_dbg_report_frame(struct iwl_priv *priv,
u32 tsf_low;
int rssi;
- if (likely(!(priv->debug_level & IWL_DL_RX)))
+ if (likely(!(iwl_get_debug_level(priv) & IWL_DL_RX)))
return;
/* MAC header */
@@ -746,14 +745,6 @@ static void iwl_dbg_report_frame(struct iwl_priv *priv,
}
#endif
-static void iwl_update_rx_stats(struct iwl_priv *priv, u16 fc, u16 len)
-{
- /* 0 - mgmt, 1 - cnt, 2 - data */
- int idx = (fc & IEEE80211_FCTL_FTYPE) >> 2;
- priv->rx_stats[idx].cnt++;
- priv->rx_stats[idx].bytes += len;
-}
-
/*
* returns non-zero if packet should be dropped
*/
@@ -927,12 +918,13 @@ static void iwl_pass_packet_to_mac80211(struct iwl_priv *priv,
hdr = (struct ieee80211_hdr *)rxb->skb->data;
/* in case of HW accelerated crypto and bad decryption, drop */
- if (!priv->hw_params.sw_crypto &&
+ if (!priv->cfg->mod_params->sw_crypto &&
iwl_set_decrypted_flag(priv, hdr, ampdu_status, stats))
return;
- iwl_update_rx_stats(priv, le16_to_cpu(hdr->frame_control), len);
- ieee80211_rx_irqsafe(priv->hw, rxb->skb, stats);
+ iwl_update_stats(priv, false, hdr->frame_control, len);
+ memcpy(IEEE80211_SKB_RXCB(rxb->skb), stats, sizeof(*stats));
+ ieee80211_rx_irqsafe(priv->hw, rxb->skb);
priv->alloc_rxb_skb--;
rxb->skb = NULL;
}
@@ -1060,11 +1052,12 @@ void iwl_rx_reply_rx(struct iwl_priv *priv,
/* Set "1" to report good data frames in groups of 100 */
#ifdef CONFIG_IWLWIFI_DEBUG
- if (unlikely(priv->debug_level & IWL_DL_RX))
+ if (unlikely(iwl_get_debug_level(priv) & IWL_DL_RX))
iwl_dbg_report_frame(priv, rx_start, len, header, 1);
#endif
+ iwl_dbg_log_rx_data_frame(priv, len, header);
IWL_DEBUG_STATS_LIMIT(priv, "Rssi %d, noise %d, qual %d, TSF %llu\n",
- rx_status.signal, rx_status.noise, rx_status.signal,
+ rx_status.signal, rx_status.noise, rx_status.qual,
(unsigned long long)rx_status.mactime);
/*
diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c
index e26875dbe85..c4c916df4a4 100644
--- a/drivers/net/wireless/iwlwifi/iwl-scan.c
+++ b/drivers/net/wireless/iwlwifi/iwl-scan.c
@@ -109,13 +109,13 @@ int iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms)
}
EXPORT_SYMBOL(iwl_scan_cancel_timeout);
-int iwl_send_scan_abort(struct iwl_priv *priv)
+static int iwl_send_scan_abort(struct iwl_priv *priv)
{
int ret = 0;
struct iwl_rx_packet *res;
struct iwl_host_cmd cmd = {
.id = REPLY_SCAN_ABORT_CMD,
- .meta.flags = CMD_WANT_SKB,
+ .flags = CMD_WANT_SKB,
};
/* If there isn't a scan actively going on in the hardware
@@ -132,7 +132,7 @@ int iwl_send_scan_abort(struct iwl_priv *priv)
return ret;
}
- res = (struct iwl_rx_packet *)cmd.meta.u.skb->data;
+ res = (struct iwl_rx_packet *)cmd.reply_skb->data;
if (res->u.status != CAN_ABORT_STATUS) {
/* The scan abort will return 1 for success or
* 2 for "failure". A failure condition can be
@@ -146,11 +146,10 @@ int iwl_send_scan_abort(struct iwl_priv *priv)
}
priv->alloc_rxb_skb--;
- dev_kfree_skb_any(cmd.meta.u.skb);
+ dev_kfree_skb_any(cmd.reply_skb);
return ret;
}
-EXPORT_SYMBOL(iwl_send_scan_abort);
/* Service response to REPLY_SCAN_CMD (0x80) */
static void iwl_rx_reply_scan(struct iwl_priv *priv,
@@ -322,7 +321,7 @@ static int iwl_get_channels_for_scan(struct iwl_priv *priv,
u8 is_active, u8 n_probes,
struct iwl_scan_channel *scan_ch)
{
- const struct ieee80211_channel *channels = NULL;
+ struct ieee80211_channel *chan;
const struct ieee80211_supported_band *sband;
const struct iwl_channel_info *ch_info;
u16 passive_dwell = 0;
@@ -334,20 +333,19 @@ static int iwl_get_channels_for_scan(struct iwl_priv *priv,
if (!sband)
return 0;
- channels = sband->channels;
-
active_dwell = iwl_get_active_dwell_time(priv, band, n_probes);
passive_dwell = iwl_get_passive_dwell_time(priv, band);
if (passive_dwell <= active_dwell)
passive_dwell = active_dwell + 1;
- for (i = 0, added = 0; i < sband->n_channels; i++) {
- if (channels[i].flags & IEEE80211_CHAN_DISABLED)
+ for (i = 0, added = 0; i < priv->scan_request->n_channels; i++) {
+ chan = priv->scan_request->channels[i];
+
+ if (chan->band != band)
continue;
- channel =
- ieee80211_frequency_to_channel(channels[i].center_freq);
+ channel = ieee80211_frequency_to_channel(chan->center_freq);
scan_ch->channel = cpu_to_le16(channel);
ch_info = iwl_get_channel_info(priv, band, channel);
@@ -358,7 +356,7 @@ static int iwl_get_channels_for_scan(struct iwl_priv *priv,
}
if (!is_active || is_channel_passive(ch_info) ||
- (channels[i].flags & IEEE80211_CHAN_PASSIVE_SCAN))
+ (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN))
scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE;
else
scan_ch->type = SCAN_CHANNEL_TYPE_ACTIVE;
@@ -405,7 +403,7 @@ void iwl_init_scan_params(struct iwl_priv *priv)
priv->scan_tx_ant[IEEE80211_BAND_2GHZ] = ant_idx;
}
-int iwl_scan_initiate(struct iwl_priv *priv)
+static int iwl_scan_initiate(struct iwl_priv *priv)
{
if (!iwl_is_ready_rf(priv)) {
IWL_DEBUG_SCAN(priv, "Aborting scan due to not ready.\n");
@@ -423,10 +421,6 @@ int iwl_scan_initiate(struct iwl_priv *priv)
}
IWL_DEBUG_INFO(priv, "Starting scan...\n");
- if (priv->cfg->sku & IWL_SKU_G)
- priv->scan_bands |= BIT(IEEE80211_BAND_2GHZ);
- if (priv->cfg->sku & IWL_SKU_A)
- priv->scan_bands |= BIT(IEEE80211_BAND_5GHZ);
set_bit(STATUS_SCANNING, &priv->status);
priv->scan_start = jiffies;
priv->scan_pass_start = priv->scan_start;
@@ -435,7 +429,6 @@ int iwl_scan_initiate(struct iwl_priv *priv)
return 0;
}
-EXPORT_SYMBOL(iwl_scan_initiate);
#define IWL_DELAY_NEXT_SCAN (HZ*2)
@@ -444,7 +437,7 @@ int iwl_mac_hw_scan(struct ieee80211_hw *hw,
{
unsigned long flags;
struct iwl_priv *priv = hw->priv;
- int ret;
+ int ret, i;
IWL_DEBUG_MAC80211(priv, "enter\n");
@@ -478,6 +471,10 @@ int iwl_mac_hw_scan(struct ieee80211_hw *hw,
goto out_unlock;
}
+ priv->scan_bands = 0;
+ for (i = 0; i < req->n_channels; i++)
+ priv->scan_bands |= BIT(req->channels[i]->band);
+
priv->scan_request = req;
ret = iwl_scan_initiate(priv);
@@ -570,7 +567,7 @@ static void iwl_bg_request_scan(struct work_struct *data)
struct iwl_host_cmd cmd = {
.id = REPLY_SCAN_CMD,
.len = sizeof(struct iwl_scan_cmd),
- .meta.flags = CMD_SIZE_HUGE,
+ .flags = CMD_SIZE_HUGE,
};
struct iwl_scan_cmd *scan;
struct ieee80211_conf *conf = NULL;
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c
index ffd5c61a755..c6633fec821 100644
--- a/drivers/net/wireless/iwlwifi/iwl-sta.c
+++ b/drivers/net/wireless/iwlwifi/iwl-sta.c
@@ -97,8 +97,9 @@ static void iwl_sta_ucode_activate(struct iwl_priv *priv, u8 sta_id)
spin_unlock_irqrestore(&priv->sta_lock, flags);
}
-static int iwl_add_sta_callback(struct iwl_priv *priv,
- struct iwl_cmd *cmd, struct sk_buff *skb)
+static void iwl_add_sta_callback(struct iwl_priv *priv,
+ struct iwl_device_cmd *cmd,
+ struct sk_buff *skb)
{
struct iwl_rx_packet *res = NULL;
struct iwl_addsta_cmd *addsta =
@@ -107,14 +108,14 @@ static int iwl_add_sta_callback(struct iwl_priv *priv,
if (!skb) {
IWL_ERR(priv, "Error: Response NULL in REPLY_ADD_STA.\n");
- return 1;
+ return;
}
res = (struct iwl_rx_packet *)skb->data;
if (res->hdr.flags & IWL_CMD_FAILED_MSK) {
IWL_ERR(priv, "Bad return from REPLY_ADD_STA (0x%08X)\n",
res->hdr.flags);
- return 1;
+ return;
}
switch (res->u.add_sta.status) {
@@ -126,9 +127,6 @@ static int iwl_add_sta_callback(struct iwl_priv *priv,
res->u.add_sta.status);
break;
}
-
- /* We didn't cache the SKB; let the caller free it */
- return 1;
}
int iwl_send_add_sta(struct iwl_priv *priv,
@@ -139,14 +137,14 @@ int iwl_send_add_sta(struct iwl_priv *priv,
u8 data[sizeof(*sta)];
struct iwl_host_cmd cmd = {
.id = REPLY_ADD_STA,
- .meta.flags = flags,
+ .flags = flags,
.data = data,
};
if (flags & CMD_ASYNC)
- cmd.meta.u.callback = iwl_add_sta_callback;
+ cmd.callback = iwl_add_sta_callback;
else
- cmd.meta.flags |= CMD_WANT_SKB;
+ cmd.flags |= CMD_WANT_SKB;
cmd.len = priv->cfg->ops->utils->build_addsta_hcmd(sta, data);
ret = iwl_send_cmd(priv, &cmd);
@@ -154,7 +152,7 @@ int iwl_send_add_sta(struct iwl_priv *priv,
if (ret || (flags & CMD_ASYNC))
return ret;
- res = (struct iwl_rx_packet *)cmd.meta.u.skb->data;
+ res = (struct iwl_rx_packet *)cmd.reply_skb->data;
if (res->hdr.flags & IWL_CMD_FAILED_MSK) {
IWL_ERR(priv, "Bad return from REPLY_ADD_STA (0x%08X)\n",
res->hdr.flags);
@@ -175,7 +173,7 @@ int iwl_send_add_sta(struct iwl_priv *priv,
}
priv->alloc_rxb_skb--;
- dev_kfree_skb_any(cmd.meta.u.skb);
+ dev_kfree_skb_any(cmd.reply_skb);
return ret;
}
@@ -216,10 +214,10 @@ static void iwl_set_ht_add_station(struct iwl_priv *priv, u8 index,
sta_flags |= cpu_to_le32(
(u32)sta_ht_inf->ampdu_density << STA_FLG_AGG_MPDU_DENSITY_POS);
- if (iwl_is_fat_tx_allowed(priv, sta_ht_inf))
- sta_flags |= STA_FLG_FAT_EN_MSK;
+ if (iwl_is_ht40_tx_allowed(priv, sta_ht_inf))
+ sta_flags |= STA_FLG_HT40_EN_MSK;
else
- sta_flags &= ~STA_FLG_FAT_EN_MSK;
+ sta_flags &= ~STA_FLG_HT40_EN_MSK;
priv->stations[index].sta.station_flags = sta_flags;
done:
@@ -324,8 +322,9 @@ static void iwl_sta_ucode_deactivate(struct iwl_priv *priv, const char *addr)
spin_unlock_irqrestore(&priv->sta_lock, flags);
}
-static int iwl_remove_sta_callback(struct iwl_priv *priv,
- struct iwl_cmd *cmd, struct sk_buff *skb)
+static void iwl_remove_sta_callback(struct iwl_priv *priv,
+ struct iwl_device_cmd *cmd,
+ struct sk_buff *skb)
{
struct iwl_rx_packet *res = NULL;
struct iwl_rem_sta_cmd *rm_sta =
@@ -334,14 +333,14 @@ static int iwl_remove_sta_callback(struct iwl_priv *priv,
if (!skb) {
IWL_ERR(priv, "Error: Response NULL in REPLY_REMOVE_STA.\n");
- return 1;
+ return;
}
res = (struct iwl_rx_packet *)skb->data;
if (res->hdr.flags & IWL_CMD_FAILED_MSK) {
IWL_ERR(priv, "Bad return from REPLY_REMOVE_STA (0x%08X)\n",
res->hdr.flags);
- return 1;
+ return;
}
switch (res->u.rem_sta.status) {
@@ -352,9 +351,6 @@ static int iwl_remove_sta_callback(struct iwl_priv *priv,
IWL_ERR(priv, "REPLY_REMOVE_STA failed\n");
break;
}
-
- /* We didn't cache the SKB; let the caller free it */
- return 1;
}
static int iwl_send_remove_station(struct iwl_priv *priv, const u8 *addr,
@@ -368,7 +364,7 @@ static int iwl_send_remove_station(struct iwl_priv *priv, const u8 *addr,
struct iwl_host_cmd cmd = {
.id = REPLY_REMOVE_STA,
.len = sizeof(struct iwl_rem_sta_cmd),
- .meta.flags = flags,
+ .flags = flags,
.data = &rm_sta_cmd,
};
@@ -377,15 +373,15 @@ static int iwl_send_remove_station(struct iwl_priv *priv, const u8 *addr,
memcpy(&rm_sta_cmd.addr, addr , ETH_ALEN);
if (flags & CMD_ASYNC)
- cmd.meta.u.callback = iwl_remove_sta_callback;
+ cmd.callback = iwl_remove_sta_callback;
else
- cmd.meta.flags |= CMD_WANT_SKB;
+ cmd.flags |= CMD_WANT_SKB;
ret = iwl_send_cmd(priv, &cmd);
if (ret || (flags & CMD_ASYNC))
return ret;
- res = (struct iwl_rx_packet *)cmd.meta.u.skb->data;
+ res = (struct iwl_rx_packet *)cmd.reply_skb->data;
if (res->hdr.flags & IWL_CMD_FAILED_MSK) {
IWL_ERR(priv, "Bad return from REPLY_REMOVE_STA (0x%08X)\n",
res->hdr.flags);
@@ -406,7 +402,7 @@ static int iwl_send_remove_station(struct iwl_priv *priv, const u8 *addr,
}
priv->alloc_rxb_skb--;
- dev_kfree_skb_any(cmd.meta.u.skb);
+ dev_kfree_skb_any(cmd.reply_skb);
return ret;
}
@@ -468,7 +464,6 @@ out:
spin_unlock_irqrestore(&priv->sta_lock, flags);
return ret;
}
-EXPORT_SYMBOL(iwl_remove_station);
/**
* iwl_clear_stations_table - Clear the driver's station table
@@ -525,7 +520,7 @@ int iwl_send_static_wepkey_cmd(struct iwl_priv *priv, u8 send_if_empty)
struct iwl_host_cmd cmd = {
.id = REPLY_WEPKEY,
.data = wep_cmd,
- .meta.flags = CMD_ASYNC,
+ .flags = CMD_ASYNC,
};
memset(wep_cmd, 0, cmd_size +
@@ -930,7 +925,7 @@ int iwl_send_lq_cmd(struct iwl_priv *priv,
struct iwl_host_cmd cmd = {
.id = REPLY_TX_LINK_QUALITY_CMD,
.len = sizeof(struct iwl_link_quality_cmd),
- .meta.flags = flags,
+ .flags = flags,
.data = lq,
};
@@ -1056,11 +1051,10 @@ EXPORT_SYMBOL(iwl_rxon_add_station);
int iwl_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr)
{
int sta_id;
- u16 fc = le16_to_cpu(hdr->frame_control);
+ __le16 fc = hdr->frame_control;
/* If this frame is broadcast or management, use broadcast station id */
- if (((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA) ||
- is_multicast_ether_addr(hdr->addr1))
+ if (!ieee80211_is_data(fc) || is_multicast_ether_addr(hdr->addr1))
return priv->hw_params.bcast_sta_id;
switch (priv->iw_mode) {
diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c
index 2e89040e63b..9b76bd41f21 100644
--- a/drivers/net/wireless/iwlwifi/iwl-tx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-tx.c
@@ -141,7 +141,7 @@ void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id)
q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd))
priv->cfg->ops->lib->txq_free_tfd(priv, txq);
- len = sizeof(struct iwl_cmd) * q->n_window;
+ len = sizeof(struct iwl_device_cmd) * q->n_window;
/* De-alloc array of command/tx buffers */
for (i = 0; i < TFD_TX_CMD_SLOTS; i++)
@@ -156,6 +156,12 @@ void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id)
kfree(txq->txb);
txq->txb = NULL;
+ /* deallocate arrays */
+ kfree(txq->cmd);
+ kfree(txq->meta);
+ txq->cmd = NULL;
+ txq->meta = NULL;
+
/* 0-fill queue descriptor structure */
memset(txq, 0, sizeof(*txq));
}
@@ -179,7 +185,7 @@ void iwl_cmd_queue_free(struct iwl_priv *priv)
if (q->n_bd == 0)
return;
- len = sizeof(struct iwl_cmd) * q->n_window;
+ len = sizeof(struct iwl_device_cmd) * q->n_window;
len += IWL_MAX_SCAN_SIZE;
/* De-alloc array of command/tx buffers */
@@ -318,6 +324,7 @@ int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq,
{
int i, len;
int ret;
+ int actual_slots = slots_num;
/*
* Alloc buffer array for commands (Tx or other types of commands).
@@ -327,14 +334,22 @@ int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq,
* For normal Tx queues (all other queues), no super-size command
* space is needed.
*/
- len = sizeof(struct iwl_cmd);
- for (i = 0; i <= slots_num; i++) {
- if (i == slots_num) {
- if (txq_id == IWL_CMD_QUEUE_NUM)
- len += IWL_MAX_SCAN_SIZE;
- else
- continue;
- }
+ if (txq_id == IWL_CMD_QUEUE_NUM)
+ actual_slots++;
+
+ txq->meta = kzalloc(sizeof(struct iwl_cmd_meta) * actual_slots,
+ GFP_KERNEL);
+ txq->cmd = kzalloc(sizeof(struct iwl_device_cmd *) * actual_slots,
+ GFP_KERNEL);
+
+ if (!txq->meta || !txq->cmd)
+ goto out_free_arrays;
+
+ len = sizeof(struct iwl_device_cmd);
+ for (i = 0; i < actual_slots; i++) {
+ /* only happens for cmd queue */
+ if (i == slots_num)
+ len += IWL_MAX_SCAN_SIZE;
txq->cmd[i] = kmalloc(len, GFP_KERNEL);
if (!txq->cmd[i])
@@ -348,6 +363,10 @@ int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq,
txq->need_update = 0;
+ /* aggregation TX queues will get their ID when aggregation begins */
+ if (txq_id <= IWL_TX_FIFO_AC3)
+ txq->swq_id = txq_id;
+
/* TFD_QUEUE_SIZE_MAX must be power-of-two size, otherwise
* iwl_queue_inc_wrap and iwl_queue_dec_wrap are broken. */
BUILD_BUG_ON(TFD_QUEUE_SIZE_MAX & (TFD_QUEUE_SIZE_MAX - 1));
@@ -360,15 +379,12 @@ int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq,
return 0;
err:
- for (i = 0; i < slots_num; i++) {
+ for (i = 0; i < actual_slots; i++)
kfree(txq->cmd[i]);
- txq->cmd[i] = NULL;
- }
+out_free_arrays:
+ kfree(txq->meta);
+ kfree(txq->cmd);
- if (txq_id == IWL_CMD_QUEUE_NUM) {
- kfree(txq->cmd[slots_num]);
- txq->cmd[slots_num] = NULL;
- }
return -ENOMEM;
}
EXPORT_SYMBOL(iwl_tx_queue_init);
@@ -652,14 +668,6 @@ static void iwl_tx_cmd_build_hwcrypto(struct iwl_priv *priv,
}
}
-static void iwl_update_tx_stats(struct iwl_priv *priv, u16 fc, u16 len)
-{
- /* 0 - mgmt, 1 - cnt, 2 - data */
- int idx = (fc & IEEE80211_FCTL_FTYPE) >> 2;
- priv->tx_stats[idx].cnt++;
- priv->tx_stats[idx].bytes += len;
-}
-
/*
* start REPLY_TX command process
*/
@@ -669,7 +677,8 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct iwl_tx_queue *txq;
struct iwl_queue *q;
- struct iwl_cmd *out_cmd;
+ struct iwl_device_cmd *out_cmd;
+ struct iwl_cmd_meta *out_meta;
struct iwl_tx_cmd *tx_cmd;
int swq_id, txq_id;
dma_addr_t phys_addr;
@@ -732,8 +741,7 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
IWL_DEBUG_TX(priv, "station Id %d\n", sta_id);
- swq_id = skb_get_queue_mapping(skb);
- txq_id = swq_id;
+ txq_id = skb_get_queue_mapping(skb);
if (ieee80211_is_data_qos(fc)) {
qc = ieee80211_get_qos_ctl(hdr);
tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK;
@@ -744,15 +752,13 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
hdr->seq_ctrl |= cpu_to_le16(seq_number);
seq_number += 0x10;
/* aggregation is on for this <sta,tid> */
- if (info->flags & IEEE80211_TX_CTL_AMPDU) {
+ if (info->flags & IEEE80211_TX_CTL_AMPDU)
txq_id = priv->stations[sta_id].tid[tid].agg.txq_id;
- swq_id = iwl_virtual_agg_queue_num(swq_id, txq_id);
- }
}
txq = &priv->txq[txq_id];
+ swq_id = txq->swq_id;
q = &txq->q;
- txq->swq_id = swq_id;
if (unlikely(iwl_queue_space(q) < q->high_mark))
goto drop_unlock;
@@ -766,6 +772,7 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
/* Set up first empty entry in queue's array of Tx/cmd buffers */
out_cmd = txq->cmd[q->write_ptr];
+ out_meta = &txq->meta[q->write_ptr];
tx_cmd = &out_cmd->cmd.tx;
memset(&out_cmd->hdr, 0, sizeof(out_cmd->hdr));
memset(tx_cmd, 0, sizeof(struct iwl_tx_cmd));
@@ -793,12 +800,12 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
/* TODO need this for burst mode later on */
iwl_tx_cmd_build_basic(priv, tx_cmd, info, hdr, sta_id);
+ iwl_dbg_log_tx_data_frame(priv, len, hdr);
/* set is_hcca to 0; it probably will never be implemented */
iwl_tx_cmd_build_rate(priv, tx_cmd, info, fc, sta_id, 0);
- iwl_update_tx_stats(priv, le16_to_cpu(fc), len);
-
+ iwl_update_stats(priv, true, fc, len);
/*
* Use the first empty entry in this queue's command buffer array
* to contain the Tx command and MAC header concatenated together
@@ -828,8 +835,8 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
txcmd_phys = pci_map_single(priv->pci_dev,
&out_cmd->hdr, len,
PCI_DMA_BIDIRECTIONAL);
- pci_unmap_addr_set(&out_cmd->meta, mapping, txcmd_phys);
- pci_unmap_len_set(&out_cmd->meta, len, len);
+ pci_unmap_addr_set(out_meta, mapping, txcmd_phys);
+ pci_unmap_len_set(out_meta, len, len);
/* Add buffer containing Tx command and MAC(!) header to TFD's
* first entry */
priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq,
@@ -922,7 +929,8 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
{
struct iwl_tx_queue *txq = &priv->txq[IWL_CMD_QUEUE_NUM];
struct iwl_queue *q = &txq->q;
- struct iwl_cmd *out_cmd;
+ struct iwl_device_cmd *out_cmd;
+ struct iwl_cmd_meta *out_meta;
dma_addr_t phys_addr;
unsigned long flags;
int len, ret;
@@ -936,25 +944,32 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
* the TFD_MAX_PAYLOAD_SIZE, and it sent as a 'small' command then
* we will need to increase the size of the TFD entries */
BUG_ON((fix_size > TFD_MAX_PAYLOAD_SIZE) &&
- !(cmd->meta.flags & CMD_SIZE_HUGE));
+ !(cmd->flags & CMD_SIZE_HUGE));
if (iwl_is_rfkill(priv)) {
- IWL_DEBUG_INFO(priv, "Not sending command - RF KILL");
+ IWL_DEBUG_INFO(priv, "Not sending command - RF KILL\n");
return -EIO;
}
- if (iwl_queue_space(q) < ((cmd->meta.flags & CMD_ASYNC) ? 2 : 1)) {
+ if (iwl_queue_space(q) < ((cmd->flags & CMD_ASYNC) ? 2 : 1)) {
IWL_ERR(priv, "No space for Tx\n");
return -ENOSPC;
}
spin_lock_irqsave(&priv->hcmd_lock, flags);
- idx = get_cmd_index(q, q->write_ptr, cmd->meta.flags & CMD_SIZE_HUGE);
+ idx = get_cmd_index(q, q->write_ptr, cmd->flags & CMD_SIZE_HUGE);
out_cmd = txq->cmd[idx];
+ out_meta = &txq->meta[idx];
+
+ memset(out_meta, 0, sizeof(*out_meta)); /* re-initialize to NULL */
+ out_meta->flags = cmd->flags;
+ if (cmd->flags & CMD_WANT_SKB)
+ out_meta->source = cmd;
+ if (cmd->flags & CMD_ASYNC)
+ out_meta->callback = cmd->callback;
out_cmd->hdr.cmd = cmd->id;
- memcpy(&out_cmd->meta, &cmd->meta, sizeof(cmd->meta));
memcpy(&out_cmd->cmd.payload, cmd->data, cmd->len);
/* At this point, the out_cmd now has all of the incoming cmd
@@ -963,9 +978,9 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
out_cmd->hdr.flags = 0;
out_cmd->hdr.sequence = cpu_to_le16(QUEUE_TO_SEQ(IWL_CMD_QUEUE_NUM) |
INDEX_TO_SEQ(q->write_ptr));
- if (out_cmd->meta.flags & CMD_SIZE_HUGE)
+ if (cmd->flags & CMD_SIZE_HUGE)
out_cmd->hdr.sequence |= SEQ_HUGE_FRAME;
- len = sizeof(struct iwl_cmd) - sizeof(struct iwl_cmd_meta);
+ len = sizeof(struct iwl_device_cmd);
len += (idx == TFD_CMD_SLOTS) ? IWL_MAX_SCAN_SIZE : 0;
@@ -997,8 +1012,8 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
phys_addr = pci_map_single(priv->pci_dev, &out_cmd->hdr,
fix_size, PCI_DMA_BIDIRECTIONAL);
- pci_unmap_addr_set(&out_cmd->meta, mapping, phys_addr);
- pci_unmap_len_set(&out_cmd->meta, len, fix_size);
+ pci_unmap_addr_set(out_meta, mapping, phys_addr);
+ pci_unmap_len_set(out_meta, len, fix_size);
priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq,
phys_addr, fix_size, 1,
@@ -1067,8 +1082,8 @@ static void iwl_hcmd_queue_reclaim(struct iwl_priv *priv, int txq_id,
}
pci_unmap_single(priv->pci_dev,
- pci_unmap_addr(&txq->cmd[cmd_idx]->meta, mapping),
- pci_unmap_len(&txq->cmd[cmd_idx]->meta, len),
+ pci_unmap_addr(&txq->meta[cmd_idx], mapping),
+ pci_unmap_len(&txq->meta[cmd_idx], len),
PCI_DMA_BIDIRECTIONAL);
for (idx = iwl_queue_inc_wrap(idx, q->n_bd); q->read_ptr != idx;
@@ -1099,7 +1114,8 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
int index = SEQ_TO_INDEX(sequence);
int cmd_index;
bool huge = !!(pkt->hdr.sequence & SEQ_HUGE_FRAME);
- struct iwl_cmd *cmd;
+ struct iwl_device_cmd *cmd;
+ struct iwl_cmd_meta *meta;
/* If a Tx command is being handled and it isn't in the actual
* command queue then there a command routing bug has been introduced
@@ -1109,24 +1125,24 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
txq_id, sequence,
priv->txq[IWL_CMD_QUEUE_NUM].q.read_ptr,
priv->txq[IWL_CMD_QUEUE_NUM].q.write_ptr)) {
- iwl_print_hex_dump(priv, IWL_DL_INFO , rxb, 32);
+ iwl_print_hex_error(priv, pkt, 32);
return;
}
cmd_index = get_cmd_index(&priv->txq[IWL_CMD_QUEUE_NUM].q, index, huge);
cmd = priv->txq[IWL_CMD_QUEUE_NUM].cmd[cmd_index];
+ meta = &priv->txq[IWL_CMD_QUEUE_NUM].meta[cmd_index];
/* Input error checking is done when commands are added to queue. */
- if (cmd->meta.flags & CMD_WANT_SKB) {
- cmd->meta.source->u.skb = rxb->skb;
- rxb->skb = NULL;
- } else if (cmd->meta.u.callback &&
- !cmd->meta.u.callback(priv, cmd, rxb->skb))
+ if (meta->flags & CMD_WANT_SKB) {
+ meta->source->reply_skb = rxb->skb;
rxb->skb = NULL;
+ } else if (meta->callback)
+ meta->callback(priv, cmd, rxb->skb);
iwl_hcmd_queue_reclaim(priv, txq_id, index, cmd_index);
- if (!(cmd->meta.flags & CMD_ASYNC)) {
+ if (!(meta->flags & CMD_ASYNC)) {
clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
wake_up_interruptible(&priv->wait_command_queue);
}
@@ -1189,6 +1205,7 @@ int iwl_tx_agg_start(struct iwl_priv *priv, const u8 *ra, u16 tid, u16 *ssn)
tid_data = &priv->stations[sta_id].tid[tid];
*ssn = SEQ_TO_SN(tid_data->seq_number);
tid_data->agg.txq_id = txq_id;
+ priv->txq[txq_id].swq_id = iwl_virtual_agg_queue_num(tx_fifo, txq_id);
spin_unlock_irqrestore(&priv->sta_lock, flags);
ret = priv->cfg->ops->lib->txq_agg_enable(priv, txq_id, tx_fifo,
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index 523843369ca..e617411d0c5 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -89,7 +89,7 @@ MODULE_LICENSE("GPL");
/* module parameters */
struct iwl_mod_params iwl3945_mod_params = {
- .num_of_queues = IWL39_MAX_NUM_QUEUES,
+ .num_of_queues = IWL39_NUM_QUEUES, /* Not used */
.sw_crypto = 1,
.restart_fw = 1,
/* the rest are 0 by default */
@@ -361,79 +361,9 @@ static void iwl3945_unset_hw_params(struct iwl_priv *priv)
priv->shared_phys);
}
-#define MAX_UCODE_BEACON_INTERVAL 1024
-#define INTEL_CONN_LISTEN_INTERVAL cpu_to_le16(0xA)
-
-static __le16 iwl3945_adjust_beacon_interval(u16 beacon_val)
-{
- u16 new_val = 0;
- u16 beacon_factor = 0;
-
- beacon_factor =
- (beacon_val + MAX_UCODE_BEACON_INTERVAL)
- / MAX_UCODE_BEACON_INTERVAL;
- new_val = beacon_val / beacon_factor;
-
- return cpu_to_le16(new_val);
-}
-
-static void iwl3945_setup_rxon_timing(struct iwl_priv *priv)
-{
- u64 interval_tm_unit;
- u64 tsf, result;
- unsigned long flags;
- struct ieee80211_conf *conf = NULL;
- u16 beacon_int = 0;
-
- conf = ieee80211_get_hw_conf(priv->hw);
-
- spin_lock_irqsave(&priv->lock, flags);
- priv->rxon_timing.timestamp = cpu_to_le64(priv->timestamp);
- priv->rxon_timing.listen_interval = INTEL_CONN_LISTEN_INTERVAL;
-
- tsf = priv->timestamp;
-
- beacon_int = priv->beacon_int;
- spin_unlock_irqrestore(&priv->lock, flags);
-
- if (priv->iw_mode == NL80211_IFTYPE_STATION) {
- if (beacon_int == 0) {
- priv->rxon_timing.beacon_interval = cpu_to_le16(100);
- priv->rxon_timing.beacon_init_val = cpu_to_le32(102400);
- } else {
- priv->rxon_timing.beacon_interval =
- cpu_to_le16(beacon_int);
- priv->rxon_timing.beacon_interval =
- iwl3945_adjust_beacon_interval(
- le16_to_cpu(priv->rxon_timing.beacon_interval));
- }
-
- priv->rxon_timing.atim_window = 0;
- } else {
- priv->rxon_timing.beacon_interval =
- iwl3945_adjust_beacon_interval(
- priv->vif->bss_conf.beacon_int);
- /* TODO: we need to get atim_window from upper stack
- * for now we set to 0 */
- priv->rxon_timing.atim_window = 0;
- }
-
- interval_tm_unit =
- (le16_to_cpu(priv->rxon_timing.beacon_interval) * 1024);
- result = do_div(tsf, interval_tm_unit);
- priv->rxon_timing.beacon_init_val =
- cpu_to_le32((u32) ((u64) interval_tm_unit - result));
-
- IWL_DEBUG_ASSOC(priv,
- "beacon interval %d beacon timer %d beacon tim %d\n",
- le16_to_cpu(priv->rxon_timing.beacon_interval),
- le32_to_cpu(priv->rxon_timing.beacon_init_val),
- le16_to_cpu(priv->rxon_timing.atim_window));
-}
-
static void iwl3945_build_tx_cmd_hwcrypto(struct iwl_priv *priv,
struct ieee80211_tx_info *info,
- struct iwl_cmd *cmd,
+ struct iwl_device_cmd *cmd,
struct sk_buff *skb_frag,
int sta_id)
{
@@ -473,7 +403,7 @@ static void iwl3945_build_tx_cmd_hwcrypto(struct iwl_priv *priv,
* handle build REPLY_TX command notification.
*/
static void iwl3945_build_tx_cmd_basic(struct iwl_priv *priv,
- struct iwl_cmd *cmd,
+ struct iwl_device_cmd *cmd,
struct ieee80211_tx_info *info,
struct ieee80211_hdr *hdr, u8 std_id)
{
@@ -546,7 +476,8 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
struct iwl3945_tx_cmd *tx;
struct iwl_tx_queue *txq = NULL;
struct iwl_queue *q = NULL;
- struct iwl_cmd *out_cmd = NULL;
+ struct iwl_device_cmd *out_cmd;
+ struct iwl_cmd_meta *out_meta;
dma_addr_t phys_addr;
dma_addr_t txcmd_phys;
int txq_id = skb_get_queue_mapping(skb);
@@ -635,6 +566,7 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
/* Init first empty entry in queue's array of Tx/cmd buffers */
out_cmd = txq->cmd[idx];
+ out_meta = &txq->meta[idx];
tx = (struct iwl3945_tx_cmd *)out_cmd->cmd.payload;
memset(&out_cmd->hdr, 0, sizeof(out_cmd->hdr));
memset(tx, 0, sizeof(*tx));
@@ -666,7 +598,8 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
len = (u16)skb->len;
tx->len = cpu_to_le16(len);
-
+ iwl_dbg_log_tx_data_frame(priv, len, hdr);
+ iwl_update_stats(priv, true, fc, len);
tx->tx_flags &= ~TX_CMD_FLG_ANT_A_MSK;
tx->tx_flags &= ~TX_CMD_FLG_ANT_B_MSK;
@@ -712,8 +645,8 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
len, PCI_DMA_TODEVICE);
/* we do not map meta data ... so we can safely access address to
* provide to unmap command*/
- pci_unmap_addr_set(&out_cmd->meta, mapping, txcmd_phys);
- pci_unmap_len_set(&out_cmd->meta, len, len);
+ pci_unmap_addr_set(out_meta, mapping, txcmd_phys);
+ pci_unmap_len_set(out_meta, len, len);
/* Add buffer containing Tx command and MAC(!) header to TFD's
* first entry */
@@ -823,7 +756,7 @@ static int iwl3945_get_measurement(struct iwl_priv *priv,
struct iwl_host_cmd cmd = {
.id = REPLY_SPECTRUM_MEASUREMENT_CMD,
.data = (void *)&spectrum,
- .meta.flags = CMD_WANT_SKB,
+ .flags = CMD_WANT_SKB,
};
u32 add_time = le64_to_cpu(params->start_time);
int rc;
@@ -864,7 +797,7 @@ static int iwl3945_get_measurement(struct iwl_priv *priv,
if (rc)
return rc;
- res = (struct iwl_rx_packet *)cmd.meta.u.skb->data;
+ res = (struct iwl_rx_packet *)cmd.reply_skb->data;
if (res->hdr.flags & IWL_CMD_FAILED_MSK) {
IWL_ERR(priv, "Bad return from REPLY_RX_ON_ASSOC command\n");
rc = -EIO;
@@ -887,7 +820,7 @@ static int iwl3945_get_measurement(struct iwl_priv *priv,
break;
}
- dev_kfree_skb_any(cmd.meta.u.skb);
+ dev_kfree_skb_any(cmd.reply_skb);
return rc;
}
@@ -996,7 +929,7 @@ static void iwl3945_rx_card_state_notif(struct iwl_priv *priv,
u32 flags = le32_to_cpu(pkt->u.card_state_notif.flags);
unsigned long status = priv->status;
- IWL_DEBUG_RF_KILL(priv, "Card state received: HW:%s SW:%s\n",
+ IWL_WARN(priv, "Card state received: HW:%s SW:%s\n",
(flags & HW_CARD_DISABLED) ? "Kill" : "On",
(flags & SW_CARD_DISABLED) ? "Kill" : "On");
@@ -1714,7 +1647,7 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv)
iwl_write32(priv, CSR_FH_INT_STATUS, inta_fh);
#ifdef CONFIG_IWLWIFI_DEBUG
- if (priv->debug_level & IWL_DL_ISR) {
+ if (iwl_get_debug_level(priv) & IWL_DL_ISR) {
/* just for debug */
inta_mask = iwl_read32(priv, CSR_INT_MASK);
IWL_DEBUG_ISR(priv, "inta 0x%08x, enabled 0x%08x, fh 0x%08x\n",
@@ -1733,7 +1666,7 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv)
/* Now service all interrupt bits discovered above. */
if (inta & CSR_INT_BIT_HW_ERR) {
- IWL_ERR(priv, "Microcode HW error detected. Restarting.\n");
+ IWL_ERR(priv, "Hardware error detected. Restarting.\n");
/* Tell the device to stop sending interrupts */
iwl_disable_interrupts(priv);
@@ -1749,7 +1682,7 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv)
}
#ifdef CONFIG_IWLWIFI_DEBUG
- if (priv->debug_level & (IWL_DL_ISR)) {
+ if (iwl_get_debug_level(priv) & (IWL_DL_ISR)) {
/* NIC fires this, but we don't use it, redundant with WAKEUP */
if (inta & CSR_INT_BIT_SCD) {
IWL_DEBUG_ISR(priv, "Scheduler finished to transmit "
@@ -1828,7 +1761,7 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv)
iwl_enable_interrupts(priv);
#ifdef CONFIG_IWLWIFI_DEBUG
- if (priv->debug_level & (IWL_DL_ISR)) {
+ if (iwl_get_debug_level(priv) & (IWL_DL_ISR)) {
inta = iwl_read32(priv, CSR_INT);
inta_mask = iwl_read32(priv, CSR_INT_MASK);
inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS);
@@ -1844,7 +1777,7 @@ static int iwl3945_get_channels_for_scan(struct iwl_priv *priv,
u8 is_active, u8 n_probes,
struct iwl3945_scan_channel *scan_ch)
{
- const struct ieee80211_channel *channels = NULL;
+ struct ieee80211_channel *chan;
const struct ieee80211_supported_band *sband;
const struct iwl_channel_info *ch_info;
u16 passive_dwell = 0;
@@ -1855,19 +1788,19 @@ static int iwl3945_get_channels_for_scan(struct iwl_priv *priv,
if (!sband)
return 0;
- channels = sband->channels;
-
active_dwell = iwl_get_active_dwell_time(priv, band, n_probes);
passive_dwell = iwl_get_passive_dwell_time(priv, band);
if (passive_dwell <= active_dwell)
passive_dwell = active_dwell + 1;
- for (i = 0, added = 0; i < sband->n_channels; i++) {
- if (channels[i].flags & IEEE80211_CHAN_DISABLED)
+ for (i = 0, added = 0; i < priv->scan_request->n_channels; i++) {
+ chan = priv->scan_request->channels[i];
+
+ if (chan->band != band)
continue;
- scan_ch->channel = channels[i].hw_value;
+ scan_ch->channel = chan->hw_value;
ch_info = iwl_get_channel_info(priv, band, scan_ch->channel);
if (!is_channel_valid(ch_info)) {
@@ -1882,7 +1815,7 @@ static int iwl3945_get_channels_for_scan(struct iwl_priv *priv,
* and use long active_dwell time.
*/
if (!is_active || is_channel_passive(ch_info) ||
- (channels[i].flags & IEEE80211_CHAN_PASSIVE_SCAN)) {
+ (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN)) {
scan_ch->type = 0; /* passive */
if (IWL_UCODE_API(priv->ucode_ver) == 1)
scan_ch->active_dwell = cpu_to_le16(passive_dwell - 1);
@@ -2111,7 +2044,7 @@ static void iwl3945_nic_start(struct iwl_priv *priv)
*/
static int iwl3945_read_ucode(struct iwl_priv *priv)
{
- struct iwl_ucode *ucode;
+ const struct iwl_ucode_header *ucode;
int ret = -EINVAL, index;
const struct firmware *ucode_raw;
/* firmware file name contains uCode/driver compatibility version */
@@ -2152,22 +2085,24 @@ static int iwl3945_read_ucode(struct iwl_priv *priv)
goto error;
/* Make sure that we got at least our header! */
- if (ucode_raw->size < sizeof(*ucode)) {
+ if (ucode_raw->size < priv->cfg->ops->ucode->get_header_size(1)) {
IWL_ERR(priv, "File size way too small!\n");
ret = -EINVAL;
goto err_release;
}
/* Data from ucode file: header followed by uCode images */
- ucode = (void *)ucode_raw->data;
+ ucode = (struct iwl_ucode_header *)ucode_raw->data;
priv->ucode_ver = le32_to_cpu(ucode->ver);
api_ver = IWL_UCODE_API(priv->ucode_ver);
- inst_size = le32_to_cpu(ucode->inst_size);
- data_size = le32_to_cpu(ucode->data_size);
- init_size = le32_to_cpu(ucode->init_size);
- init_data_size = le32_to_cpu(ucode->init_data_size);
- boot_size = le32_to_cpu(ucode->boot_size);
+ inst_size = priv->cfg->ops->ucode->get_inst_size(ucode, api_ver);
+ data_size = priv->cfg->ops->ucode->get_data_size(ucode, api_ver);
+ init_size = priv->cfg->ops->ucode->get_init_size(ucode, api_ver);
+ init_data_size =
+ priv->cfg->ops->ucode->get_init_data_size(ucode, api_ver);
+ boot_size = priv->cfg->ops->ucode->get_boot_size(ucode, api_ver);
+ src = priv->cfg->ops->ucode->get_data(ucode, api_ver);
/* api_ver should match the api version forming part of the
* firmware filename ... but we don't check for that and only rely
@@ -2208,12 +2143,13 @@ static int iwl3945_read_ucode(struct iwl_priv *priv)
/* Verify size of file vs. image size info in file's header */
- if (ucode_raw->size < sizeof(*ucode) +
+ if (ucode_raw->size != priv->cfg->ops->ucode->get_header_size(api_ver) +
inst_size + data_size + init_size +
init_data_size + boot_size) {
- IWL_DEBUG_INFO(priv, "uCode file size %zd too small\n",
- ucode_raw->size);
+ IWL_DEBUG_INFO(priv,
+ "uCode file size %zd does not match expected size\n",
+ ucode_raw->size);
ret = -EINVAL;
goto err_release;
}
@@ -2296,44 +2232,44 @@ static int iwl3945_read_ucode(struct iwl_priv *priv)
/* Copy images into buffers for card's bus-master reads ... */
/* Runtime instructions (first block of data in file) */
- src = &ucode->data[0];
- len = priv->ucode_code.len;
+ len = inst_size;
IWL_DEBUG_INFO(priv,
"Copying (but not loading) uCode instr len %zd\n", len);
memcpy(priv->ucode_code.v_addr, src, len);
+ src += len;
+
IWL_DEBUG_INFO(priv, "uCode instr buf vaddr = 0x%p, paddr = 0x%08x\n",
priv->ucode_code.v_addr, (u32)priv->ucode_code.p_addr);
/* Runtime data (2nd block)
* NOTE: Copy into backup buffer will be done in iwl3945_up() */
- src = &ucode->data[inst_size];
- len = priv->ucode_data.len;
+ len = data_size;
IWL_DEBUG_INFO(priv,
"Copying (but not loading) uCode data len %zd\n", len);
memcpy(priv->ucode_data.v_addr, src, len);
memcpy(priv->ucode_data_backup.v_addr, src, len);
+ src += len;
/* Initialization instructions (3rd block) */
if (init_size) {
- src = &ucode->data[inst_size + data_size];
- len = priv->ucode_init.len;
+ len = init_size;
IWL_DEBUG_INFO(priv,
"Copying (but not loading) init instr len %zd\n", len);
memcpy(priv->ucode_init.v_addr, src, len);
+ src += len;
}
/* Initialization data (4th block) */
if (init_data_size) {
- src = &ucode->data[inst_size + data_size + init_size];
- len = priv->ucode_init_data.len;
+ len = init_data_size;
IWL_DEBUG_INFO(priv,
"Copying (but not loading) init data len %zd\n", len);
memcpy(priv->ucode_init_data.v_addr, src, len);
+ src += len;
}
/* Bootstrap instructions (5th block) */
- src = &ucode->data[inst_size + data_size + init_size + init_data_size];
- len = priv->ucode_boot.len;
+ len = boot_size;
IWL_DEBUG_INFO(priv,
"Copying (but not loading) boot instr len %zd\n", len);
memcpy(priv->ucode_boot.v_addr, src, len);
@@ -2784,7 +2720,7 @@ static void iwl3945_bg_request_scan(struct work_struct *data)
struct iwl_host_cmd cmd = {
.id = REPLY_SCAN_CMD,
.len = sizeof(struct iwl3945_scan_cmd),
- .meta.flags = CMD_SIZE_HUGE,
+ .flags = CMD_SIZE_HUGE,
};
int rc = 0;
struct iwl3945_scan_cmd *scan;
@@ -3066,7 +3002,7 @@ void iwl3945_post_associate(struct iwl_priv *priv)
iwlcore_commit_rxon(priv);
memset(&priv->rxon_timing, 0, sizeof(struct iwl_rxon_time_cmd));
- iwl3945_setup_rxon_timing(priv);
+ iwl_setup_rxon_timing(priv);
rc = iwl_send_cmd_pdu(priv, REPLY_RXON_TIMING,
sizeof(priv->rxon_timing), &priv->rxon_timing);
if (rc)
@@ -3261,7 +3197,7 @@ void iwl3945_config_ap(struct iwl_priv *priv)
/* RXON Timing */
memset(&priv->rxon_timing, 0, sizeof(struct iwl_rxon_time_cmd));
- iwl3945_setup_rxon_timing(priv);
+ iwl_setup_rxon_timing(priv);
rc = iwl_send_cmd_pdu(priv, REPLY_RXON_TIMING,
sizeof(priv->rxon_timing),
&priv->rxon_timing);
@@ -3375,13 +3311,16 @@ static int iwl3945_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
* used for controlling the debug level.
*
* See the level definitions in iwl for details.
+ *
+ * The debug_level being managed using sysfs below is a per device debug
+ * level that is used instead of the global debug level if it (the per
+ * device debug level) is set.
*/
static ssize_t show_debug_level(struct device *d,
struct device_attribute *attr, char *buf)
{
struct iwl_priv *priv = dev_get_drvdata(d);
-
- return sprintf(buf, "0x%08X\n", priv->debug_level);
+ return sprintf(buf, "0x%08X\n", iwl_get_debug_level(priv));
}
static ssize_t store_debug_level(struct device *d,
struct device_attribute *attr,
@@ -3394,9 +3333,12 @@ static ssize_t store_debug_level(struct device *d,
ret = strict_strtoul(buf, 0, &val);
if (ret)
IWL_INFO(priv, "%s is not in hex or decimal form.\n", buf);
- else
+ else {
priv->debug_level = val;
-
+ if (iwl_alloc_traffic_mem(priv))
+ IWL_ERR(priv,
+ "Not enough memory to generate traffic log\n");
+ }
return strnlen(buf, count);
}
@@ -3612,65 +3554,6 @@ static DEVICE_ATTR(retry_rate, S_IWUSR | S_IRUSR, show_retry_rate,
store_retry_rate);
-static ssize_t store_power_level(struct device *d,
- struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct iwl_priv *priv = dev_get_drvdata(d);
- int ret;
- unsigned long mode;
-
-
- mutex_lock(&priv->mutex);
-
- ret = strict_strtoul(buf, 10, &mode);
- if (ret)
- goto out;
-
- ret = iwl_power_set_user_mode(priv, mode);
- if (ret) {
- IWL_DEBUG_MAC80211(priv, "failed setting power mode.\n");
- goto out;
- }
- ret = count;
-
- out:
- mutex_unlock(&priv->mutex);
- return ret;
-}
-
-static ssize_t show_power_level(struct device *d,
- struct device_attribute *attr, char *buf)
-{
- struct iwl_priv *priv = dev_get_drvdata(d);
- int level = priv->power_data.power_mode;
- char *p = buf;
-
- p += sprintf(p, "%d\n", level);
- return p - buf + 1;
-}
-
-static DEVICE_ATTR(power_level, S_IWUSR | S_IRUSR,
- show_power_level, store_power_level);
-
-#define MAX_WX_STRING 80
-
-/* Values are in microsecond */
-static const s32 timeout_duration[] = {
- 350000,
- 250000,
- 75000,
- 37000,
- 25000,
-};
-static const s32 period_duration[] = {
- 400000,
- 700000,
- 1000000,
- 1000000,
- 1000000
-};
-
static ssize_t show_channels(struct device *d,
struct device_attribute *attr, char *buf)
{
@@ -3847,7 +3730,6 @@ static struct attribute *iwl3945_sysfs_entries[] = {
#ifdef CONFIG_IWL3945_SPECTRUM_MEASUREMENT
&dev_attr_measurement.attr,
#endif
- &dev_attr_power_level.attr,
&dev_attr_retry_rate.attr,
&dev_attr_statistics.attr,
&dev_attr_status.attr,
@@ -3912,8 +3794,6 @@ static int iwl3945_init_drv(struct iwl_priv *priv)
priv->qos_data.qos_cap.val = 0;
priv->rates_mask = IWL_RATES_MASK;
- /* If power management is turned on, default to CAM mode */
- priv->power_mode = IWL_POWER_MODE_CAM;
priv->tx_power_user_lmt = IWL_DEFAULT_TX_POWER;
if (eeprom->version < EEPROM_3945_EEPROM_VERSION) {
@@ -3960,7 +3840,9 @@ static int iwl3945_setup_mac(struct iwl_priv *priv)
/* Tell mac80211 our characteristics */
hw->flags = IEEE80211_HW_SIGNAL_DBM |
IEEE80211_HW_NOISE_DBM |
- IEEE80211_HW_SPECTRUM_MGMT;
+ IEEE80211_HW_SPECTRUM_MGMT |
+ IEEE80211_HW_SUPPORTS_PS |
+ IEEE80211_HW_SUPPORTS_DYNAMIC_PS;
hw->wiphy->interface_modes =
BIT(NL80211_IFTYPE_STATION) |
@@ -4020,15 +3902,6 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
priv = hw->priv;
SET_IEEE80211_DEV(hw, &pdev->dev);
- if ((iwl3945_mod_params.num_of_queues > IWL39_MAX_NUM_QUEUES) ||
- (iwl3945_mod_params.num_of_queues < IWL39_MIN_NUM_QUEUES)) {
- IWL_ERR(priv,
- "invalid queues_num, should be between %d and %d\n",
- IWL39_MIN_NUM_QUEUES, IWL39_MAX_NUM_QUEUES);
- err = -EINVAL;
- goto out_ieee80211_free_hw;
- }
-
/*
* Disabling hardware scan means that mac80211 will perform scans
* "the hard way", rather than using device's scan.
@@ -4045,9 +3918,10 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
priv->inta_mask = CSR_INI_SET_MASK;
#ifdef CONFIG_IWLWIFI_DEBUG
- priv->debug_level = iwl3945_mod_params.debug;
atomic_set(&priv->restrict_refcnt, 0);
#endif
+ if (iwl_alloc_traffic_mem(priv))
+ IWL_ERR(priv, "Not enough memory to generate traffic log\n");
/***************************
* 2. Initializing PCI bus
@@ -4210,6 +4084,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
pci_disable_device(pdev);
out_ieee80211_free_hw:
ieee80211_free_hw(priv->hw);
+ iwl_free_traffic_mem(priv);
out:
return err;
}
@@ -4265,6 +4140,7 @@ static void __devexit iwl3945_pci_remove(struct pci_dev *pdev)
* until now... */
destroy_workqueue(priv->workqueue);
priv->workqueue = NULL;
+ iwl_free_traffic_mem(priv);
free_irq(pdev->irq, priv);
pci_disable_msi(pdev);
@@ -4341,14 +4217,12 @@ MODULE_PARM_DESC(antenna, "select antenna (1=Main, 2=Aux, default 0 [both])");
module_param_named(swcrypto, iwl3945_mod_params.sw_crypto, int, 0444);
MODULE_PARM_DESC(swcrypto,
"using software crypto (default 1 [software])\n");
-module_param_named(debug, iwl3945_mod_params.debug, uint, 0444);
+#ifdef CONFIG_IWLWIFI_DEBUG
+module_param_named(debug, iwl_debug_level, uint, 0644);
MODULE_PARM_DESC(debug, "debug output mask");
+#endif
module_param_named(disable_hw_scan, iwl3945_mod_params.disable_hw_scan, int, 0444);
MODULE_PARM_DESC(disable_hw_scan, "disable hardware scanning (default 0)");
-
-module_param_named(queues_num, iwl3945_mod_params.num_of_queues, int, 0444);
-MODULE_PARM_DESC(queues_num, "number of hw queues.");
-
module_param_named(fw_restart3945, iwl3945_mod_params.restart_fw, int, 0444);
MODULE_PARM_DESC(fw_restart3945, "restart firmware in case of error");
diff --git a/drivers/net/wireless/iwmc3200wifi/Kconfig b/drivers/net/wireless/iwmc3200wifi/Kconfig
index 030401d367d..c62da435285 100644
--- a/drivers/net/wireless/iwmc3200wifi/Kconfig
+++ b/drivers/net/wireless/iwmc3200wifi/Kconfig
@@ -2,7 +2,6 @@ config IWM
tristate "Intel Wireless Multicomm 3200 WiFi driver"
depends on MMC && WLAN_80211 && EXPERIMENTAL
depends on CFG80211
- select WIRELESS_EXT
select FW_LOADER
help
The Intel Wireless Multicomm 3200 hardware is a combo
diff --git a/drivers/net/wireless/iwmc3200wifi/Makefile b/drivers/net/wireless/iwmc3200wifi/Makefile
index 927f022545c..d34291b652d 100644
--- a/drivers/net/wireless/iwmc3200wifi/Makefile
+++ b/drivers/net/wireless/iwmc3200wifi/Makefile
@@ -1,5 +1,5 @@
obj-$(CONFIG_IWM) := iwmc3200wifi.o
iwmc3200wifi-objs += main.o netdev.o rx.o tx.o sdio.o hal.o fw.o
-iwmc3200wifi-objs += commands.o wext.o cfg80211.o eeprom.o
+iwmc3200wifi-objs += commands.o cfg80211.o eeprom.o
iwmc3200wifi-$(CONFIG_IWM_DEBUG) += debugfs.o
diff --git a/drivers/net/wireless/iwmc3200wifi/cfg80211.c b/drivers/net/wireless/iwmc3200wifi/cfg80211.c
index 96f714e6e12..a6e852f4f92 100644
--- a/drivers/net/wireless/iwmc3200wifi/cfg80211.c
+++ b/drivers/net/wireless/iwmc3200wifi/cfg80211.c
@@ -23,6 +23,7 @@
#include <linux/kernel.h>
#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
#include <linux/wireless.h>
#include <linux/ieee80211.h>
#include <net/cfg80211.h>
@@ -130,6 +131,133 @@ static struct ieee80211_supported_band iwm_band_5ghz = {
.n_bitrates = iwm_a_rates_size,
};
+static int iwm_key_init(struct iwm_key *key, u8 key_index,
+ const u8 *mac_addr, struct key_params *params)
+{
+ key->hdr.key_idx = key_index;
+ if (!mac_addr || is_broadcast_ether_addr(mac_addr)) {
+ key->hdr.multicast = 1;
+ memset(key->hdr.mac, 0xff, ETH_ALEN);
+ } else {
+ key->hdr.multicast = 0;
+ memcpy(key->hdr.mac, mac_addr, ETH_ALEN);
+ }
+
+ if (params) {
+ if (params->key_len > WLAN_MAX_KEY_LEN ||
+ params->seq_len > IW_ENCODE_SEQ_MAX_SIZE)
+ return -EINVAL;
+
+ key->cipher = params->cipher;
+ key->key_len = params->key_len;
+ key->seq_len = params->seq_len;
+ memcpy(key->key, params->key, key->key_len);
+ memcpy(key->seq, params->seq, key->seq_len);
+ }
+
+ return 0;
+}
+
+static int iwm_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
+ u8 key_index, const u8 *mac_addr,
+ struct key_params *params)
+{
+ struct iwm_priv *iwm = ndev_to_iwm(ndev);
+ struct iwm_key *key = &iwm->keys[key_index];
+ int ret;
+
+ IWM_DBG_WEXT(iwm, DBG, "Adding key for %pM\n", mac_addr);
+
+ memset(key, 0, sizeof(struct iwm_key));
+ ret = iwm_key_init(key, key_index, mac_addr, params);
+ if (ret < 0) {
+ IWM_ERR(iwm, "Invalid key_params\n");
+ return ret;
+ }
+
+ return iwm_set_key(iwm, 0, key);
+}
+
+static int iwm_cfg80211_get_key(struct wiphy *wiphy, struct net_device *ndev,
+ u8 key_index, const u8 *mac_addr, void *cookie,
+ void (*callback)(void *cookie,
+ struct key_params*))
+{
+ struct iwm_priv *iwm = ndev_to_iwm(ndev);
+ struct iwm_key *key = &iwm->keys[key_index];
+ struct key_params params;
+
+ IWM_DBG_WEXT(iwm, DBG, "Getting key %d\n", key_index);
+
+ memset(&params, 0, sizeof(params));
+
+ params.cipher = key->cipher;
+ params.key_len = key->key_len;
+ params.seq_len = key->seq_len;
+ params.seq = key->seq;
+ params.key = key->key;
+
+ callback(cookie, &params);
+
+ return key->key_len ? 0 : -ENOENT;
+}
+
+
+static int iwm_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev,
+ u8 key_index, const u8 *mac_addr)
+{
+ struct iwm_priv *iwm = ndev_to_iwm(ndev);
+ struct iwm_key *key = &iwm->keys[key_index];
+
+ if (!iwm->keys[key_index].key_len) {
+ IWM_DBG_WEXT(iwm, DBG, "Key %d not used\n", key_index);
+ return 0;
+ }
+
+ if (key_index == iwm->default_key)
+ iwm->default_key = -1;
+
+ return iwm_set_key(iwm, 1, key);
+}
+
+static int iwm_cfg80211_set_default_key(struct wiphy *wiphy,
+ struct net_device *ndev,
+ u8 key_index)
+{
+ struct iwm_priv *iwm = ndev_to_iwm(ndev);
+
+ IWM_DBG_WEXT(iwm, DBG, "Default key index is: %d\n", key_index);
+
+ if (!iwm->keys[key_index].key_len) {
+ IWM_ERR(iwm, "Key %d not used\n", key_index);
+ return -EINVAL;
+ }
+
+ iwm->default_key = key_index;
+
+ return iwm_set_tx_key(iwm, key_index);
+}
+
+int iwm_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev,
+ u8 *mac, struct station_info *sinfo)
+{
+ struct iwm_priv *iwm = ndev_to_iwm(ndev);
+
+ if (memcmp(mac, iwm->bssid, ETH_ALEN))
+ return -ENOENT;
+
+ sinfo->filled |= STATION_INFO_TX_BITRATE;
+ sinfo->txrate.legacy = iwm->rate * 10;
+
+ if (test_bit(IWM_STATUS_ASSOCIATED, &iwm->status)) {
+ sinfo->filled |= STATION_INFO_SIGNAL;
+ sinfo->signal = iwm->wstats.qual.level;
+ }
+
+ return 0;
+}
+
+
int iwm_cfg80211_inform_bss(struct iwm_priv *iwm)
{
struct wiphy *wiphy = iwm_to_wiphy(iwm);
@@ -167,20 +295,15 @@ int iwm_cfg80211_inform_bss(struct iwm_priv *iwm)
return 0;
}
-static int iwm_cfg80211_change_iface(struct wiphy *wiphy, int ifindex,
+static int iwm_cfg80211_change_iface(struct wiphy *wiphy,
+ struct net_device *ndev,
enum nl80211_iftype type, u32 *flags,
struct vif_params *params)
{
- struct net_device *ndev;
struct wireless_dev *wdev;
struct iwm_priv *iwm;
u32 old_mode;
- /* we're under RTNL */
- ndev = __dev_get_by_index(&init_net, ifindex);
- if (!ndev)
- return -ENODEV;
-
wdev = ndev->ieee80211_ptr;
iwm = ndev_to_iwm(ndev);
old_mode = iwm->conf.mode;
@@ -329,12 +452,250 @@ static int iwm_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
return 0;
}
+static int iwm_set_auth_type(struct iwm_priv *iwm,
+ enum nl80211_auth_type sme_auth_type)
+{
+ u8 *auth_type = &iwm->umac_profile->sec.auth_type;
+
+ switch (sme_auth_type) {
+ case NL80211_AUTHTYPE_AUTOMATIC:
+ case NL80211_AUTHTYPE_OPEN_SYSTEM:
+ IWM_DBG_WEXT(iwm, DBG, "OPEN auth\n");
+ *auth_type = UMAC_AUTH_TYPE_OPEN;
+ break;
+ case NL80211_AUTHTYPE_SHARED_KEY:
+ if (iwm->umac_profile->sec.flags &
+ (UMAC_SEC_FLG_WPA_ON_MSK | UMAC_SEC_FLG_RSNA_ON_MSK)) {
+ IWM_DBG_WEXT(iwm, DBG, "WPA auth alg\n");
+ *auth_type = UMAC_AUTH_TYPE_RSNA_PSK;
+ } else {
+ IWM_DBG_WEXT(iwm, DBG, "WEP shared key auth alg\n");
+ *auth_type = UMAC_AUTH_TYPE_LEGACY_PSK;
+ }
+
+ break;
+ default:
+ IWM_ERR(iwm, "Unsupported auth alg: 0x%x\n", sme_auth_type);
+ return -ENOTSUPP;
+ }
+
+ return 0;
+}
+
+static int iwm_set_wpa_version(struct iwm_priv *iwm, u32 wpa_version)
+{
+ IWM_DBG_WEXT(iwm, DBG, "wpa_version: %d\n", wpa_version);
+
+ if (!wpa_version) {
+ iwm->umac_profile->sec.flags = UMAC_SEC_FLG_LEGACY_PROFILE;
+ return 0;
+ }
+
+ if (wpa_version & NL80211_WPA_VERSION_2)
+ iwm->umac_profile->sec.flags = UMAC_SEC_FLG_RSNA_ON_MSK;
+
+ if (wpa_version & NL80211_WPA_VERSION_1)
+ iwm->umac_profile->sec.flags |= UMAC_SEC_FLG_WPA_ON_MSK;
+
+ return 0;
+}
+
+static int iwm_set_cipher(struct iwm_priv *iwm, u32 cipher, bool ucast)
+{
+ u8 *profile_cipher = ucast ? &iwm->umac_profile->sec.ucast_cipher :
+ &iwm->umac_profile->sec.mcast_cipher;
+
+ if (!cipher) {
+ *profile_cipher = UMAC_CIPHER_TYPE_NONE;
+ return 0;
+ }
+
+ IWM_DBG_WEXT(iwm, DBG, "%ccast cipher is 0x%x\n", ucast ? 'u' : 'm',
+ cipher);
+
+ switch (cipher) {
+ case IW_AUTH_CIPHER_NONE:
+ *profile_cipher = UMAC_CIPHER_TYPE_NONE;
+ break;
+ case WLAN_CIPHER_SUITE_WEP40:
+ *profile_cipher = UMAC_CIPHER_TYPE_WEP_40;
+ break;
+ case WLAN_CIPHER_SUITE_WEP104:
+ *profile_cipher = UMAC_CIPHER_TYPE_WEP_104;
+ break;
+ case WLAN_CIPHER_SUITE_TKIP:
+ *profile_cipher = UMAC_CIPHER_TYPE_TKIP;
+ break;
+ case WLAN_CIPHER_SUITE_CCMP:
+ *profile_cipher = UMAC_CIPHER_TYPE_CCMP;
+ break;
+ default:
+ IWM_ERR(iwm, "Unsupported cipher: 0x%x\n", cipher);
+ return -ENOTSUPP;
+ }
+
+ return 0;
+}
+
+static int iwm_set_key_mgt(struct iwm_priv *iwm, u32 key_mgt)
+{
+ u8 *auth_type = &iwm->umac_profile->sec.auth_type;
+
+ IWM_DBG_WEXT(iwm, DBG, "key_mgt: 0x%x\n", key_mgt);
+
+ if (key_mgt == WLAN_AKM_SUITE_8021X)
+ *auth_type = UMAC_AUTH_TYPE_8021X;
+ else if (key_mgt == WLAN_AKM_SUITE_PSK) {
+ if (iwm->umac_profile->sec.flags &
+ (UMAC_SEC_FLG_WPA_ON_MSK | UMAC_SEC_FLG_RSNA_ON_MSK))
+ *auth_type = UMAC_AUTH_TYPE_RSNA_PSK;
+ else
+ *auth_type = UMAC_AUTH_TYPE_LEGACY_PSK;
+ } else {
+ IWM_ERR(iwm, "Invalid key mgt: 0x%x\n", key_mgt);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+
+static int iwm_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
+ struct cfg80211_connect_params *sme)
+{
+ struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
+ struct ieee80211_channel *chan = sme->channel;
+ int ret;
+
+ if (!test_bit(IWM_STATUS_READY, &iwm->status))
+ return -EIO;
+
+ if (!sme->ssid)
+ return -EINVAL;
+
+ if (chan)
+ iwm->channel =
+ ieee80211_frequency_to_channel(chan->center_freq);
+
+ iwm->umac_profile->ssid.ssid_len = sme->ssid_len;
+ memcpy(iwm->umac_profile->ssid.ssid, sme->ssid, sme->ssid_len);
+
+ if (sme->bssid) {
+ IWM_DBG_WEXT(iwm, DBG, "BSSID: %pM\n", sme->bssid);
+ memcpy(&iwm->umac_profile->bssid[0], sme->bssid, ETH_ALEN);
+ iwm->umac_profile->bss_num = 1;
+ } else {
+ memset(&iwm->umac_profile->bssid[0], 0, ETH_ALEN);
+ iwm->umac_profile->bss_num = 0;
+ }
+
+ ret = iwm_set_wpa_version(iwm, sme->crypto.wpa_versions);
+ if (ret < 0)
+ return ret;
+
+ ret = iwm_set_auth_type(iwm, sme->auth_type);
+ if (ret < 0)
+ return ret;
+
+ if (sme->crypto.n_ciphers_pairwise) {
+ ret = iwm_set_cipher(iwm, sme->crypto.ciphers_pairwise[0],
+ true);
+ if (ret < 0)
+ return ret;
+ }
+
+ ret = iwm_set_cipher(iwm, sme->crypto.cipher_group, false);
+ if (ret < 0)
+ return ret;
+
+ if (sme->crypto.n_akm_suites) {
+ ret = iwm_set_key_mgt(iwm, sme->crypto.akm_suites[0]);
+ if (ret < 0)
+ return ret;
+ }
+
+ return iwm_send_mlme_profile(iwm);
+}
+
+static int iwm_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev,
+ u16 reason_code)
+{
+ struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
+
+ IWM_DBG_WEXT(iwm, DBG, "Active: %d\n", iwm->umac_profile_active);
+
+ if (iwm->umac_profile_active)
+ return iwm_invalidate_mlme_profile(iwm);
+
+ return 0;
+}
+
+static int iwm_cfg80211_set_txpower(struct wiphy *wiphy,
+ enum tx_power_setting type, int dbm)
+{
+ switch (type) {
+ case TX_POWER_AUTOMATIC:
+ return 0;
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ return 0;
+}
+
+static int iwm_cfg80211_get_txpower(struct wiphy *wiphy, int *dbm)
+{
+ struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
+
+ *dbm = iwm->txpower;
+
+ return 0;
+}
+
+static int iwm_cfg80211_set_power_mgmt(struct wiphy *wiphy,
+ struct net_device *dev,
+ bool enabled, int timeout)
+{
+ struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
+ u32 power_index;
+
+ if (enabled)
+ power_index = IWM_POWER_INDEX_DEFAULT;
+ else
+ power_index = IWM_POWER_INDEX_MIN;
+
+ if (power_index == iwm->conf.power_index)
+ return 0;
+
+ iwm->conf.power_index = power_index;
+
+ return iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX,
+ CFG_POWER_INDEX, iwm->conf.power_index);
+}
+
static struct cfg80211_ops iwm_cfg80211_ops = {
.change_virtual_intf = iwm_cfg80211_change_iface,
+ .add_key = iwm_cfg80211_add_key,
+ .get_key = iwm_cfg80211_get_key,
+ .del_key = iwm_cfg80211_del_key,
+ .set_default_key = iwm_cfg80211_set_default_key,
+ .get_station = iwm_cfg80211_get_station,
.scan = iwm_cfg80211_scan,
.set_wiphy_params = iwm_cfg80211_set_wiphy_params,
+ .connect = iwm_cfg80211_connect,
+ .disconnect = iwm_cfg80211_disconnect,
.join_ibss = iwm_cfg80211_join_ibss,
.leave_ibss = iwm_cfg80211_leave_ibss,
+ .set_tx_power = iwm_cfg80211_set_txpower,
+ .get_tx_power = iwm_cfg80211_get_txpower,
+ .set_power_mgmt = iwm_cfg80211_set_power_mgmt,
+};
+
+static const u32 cipher_suites[] = {
+ WLAN_CIPHER_SUITE_WEP40,
+ WLAN_CIPHER_SUITE_WEP104,
+ WLAN_CIPHER_SUITE_TKIP,
+ WLAN_CIPHER_SUITE_CCMP,
};
struct wireless_dev *iwm_wdev_alloc(int sizeof_bus, struct device *dev)
@@ -379,6 +740,9 @@ struct wireless_dev *iwm_wdev_alloc(int sizeof_bus, struct device *dev)
wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = &iwm_band_5ghz;
wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
+ wdev->wiphy->cipher_suites = cipher_suites;
+ wdev->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);
+
ret = wiphy_register(wdev->wiphy);
if (ret < 0) {
dev_err(dev, "Couldn't register wiphy device\n");
diff --git a/drivers/net/wireless/iwmc3200wifi/commands.c b/drivers/net/wireless/iwmc3200wifi/commands.c
index e2334d12359..a68a2aff3c1 100644
--- a/drivers/net/wireless/iwmc3200wifi/commands.c
+++ b/drivers/net/wireless/iwmc3200wifi/commands.c
@@ -70,14 +70,27 @@ static int iwm_send_lmac_ptrough_cmd(struct iwm_priv *iwm,
int iwm_send_wifi_if_cmd(struct iwm_priv *iwm, void *payload, u16 payload_size,
bool resp)
{
+ struct iwm_umac_wifi_if *hdr = (struct iwm_umac_wifi_if *)payload;
struct iwm_udma_wifi_cmd udma_cmd = UDMA_UMAC_INIT;
struct iwm_umac_cmd umac_cmd;
+ int ret;
+ u8 oid = hdr->oid;
umac_cmd.id = UMAC_CMD_OPCODE_WIFI_IF_WRAPPER;
umac_cmd.resp = resp;
- return iwm_hal_send_umac_cmd(iwm, &udma_cmd, &umac_cmd,
- payload, payload_size);
+ ret = iwm_hal_send_umac_cmd(iwm, &udma_cmd, &umac_cmd,
+ payload, payload_size);
+
+ if (resp) {
+ ret = wait_event_interruptible_timeout(iwm->wifi_ntfy_queue,
+ test_and_clear_bit(oid, &iwm->wifi_ntfy[0]),
+ 3 * HZ);
+
+ return ret ? 0 : -EBUSY;
+ }
+
+ return ret;
}
static struct coex_event iwm_sta_xor_prio_tbl[COEX_EVENTS_NUM] =
@@ -106,7 +119,7 @@ static struct coex_event iwm_sta_cm_prio_tbl[COEX_EVENTS_NUM] =
{4, 3, 0, COEX_UNASSOC_MANUAL_SCAN_FLAGS},
{3, 3, 0, COEX_UNASSOC_AUTO_SCAN_FLAGS},
{5, 5, 0, COEX_CALIBRATION_FLAGS},
- {4, 4, 0, COEX_PERIODIC_CALIBRATION_FLAGS},
+ {3, 3, 0, COEX_PERIODIC_CALIBRATION_FLAGS},
{5, 4, 0, COEX_CONNECTION_ESTAB_FLAGS},
{4, 4, 0, COEX_ASSOCIATED_IDLE_FLAGS},
{4, 4, 0, COEX_ASSOC_MANUAL_SCAN_FLAGS},
@@ -332,8 +345,7 @@ int iwm_umac_set_config_var(struct iwm_priv *iwm, u16 key,
return ret;
}
-int iwm_send_umac_config(struct iwm_priv *iwm,
- __le32 reset_flags)
+int iwm_send_umac_config(struct iwm_priv *iwm, __le32 reset_flags)
{
int ret;
@@ -361,6 +373,12 @@ int iwm_send_umac_config(struct iwm_priv *iwm,
return ret;
ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX,
+ CFG_WIRELESS_MODE,
+ iwm->conf.wireless_mode);
+ if (ret < 0)
+ return ret;
+
+ ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX,
CFG_COEX_MODE, iwm->conf.coexist_mode);
if (ret < 0)
return ret;
@@ -402,7 +420,7 @@ int iwm_send_umac_config(struct iwm_priv *iwm,
return ret;
ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX,
- CFG_PM_CTRL_FLAGS, 0x30001);
+ CFG_PM_CTRL_FLAGS, 0x1);
if (ret < 0)
return ret;
@@ -462,8 +480,10 @@ static int iwm_target_read(struct iwm_priv *iwm, __le32 address,
target_cmd.eop = 1;
ret = iwm_hal_send_target_cmd(iwm, &target_cmd, NULL);
- if (ret < 0)
+ if (ret < 0) {
IWM_ERR(iwm, "Couldn't send READ command\n");
+ return ret;
+ }
/* When succeding, the send_target routine returns the seq number */
seq_num = ret;
@@ -483,7 +503,7 @@ static int iwm_target_read(struct iwm_priv *iwm, __le32 address,
kfree(cmd);
- return ret;
+ return 0;
}
int iwm_read_mac(struct iwm_priv *iwm, u8 *mac)
@@ -493,7 +513,7 @@ int iwm_read_mac(struct iwm_priv *iwm, u8 *mac)
ret = iwm_target_read(iwm, cpu_to_le32(WICO_MAC_ADDRESS_ADDR),
mac_align, sizeof(mac_align));
- if (ret < 0)
+ if (ret)
return ret;
if (is_valid_ether_addr(mac_align))
@@ -507,22 +527,6 @@ int iwm_read_mac(struct iwm_priv *iwm, u8 *mac)
return 0;
}
-int iwm_set_tx_key(struct iwm_priv *iwm, u8 key_idx)
-{
- struct iwm_umac_tx_key_id tx_key_id;
-
- if (!iwm->default_key || !iwm->default_key->in_use)
- return -EINVAL;
-
- tx_key_id.hdr.oid = UMAC_WIFI_IF_CMD_GLOBAL_TX_KEY_ID;
- tx_key_id.hdr.buf_size = cpu_to_le16(sizeof(struct iwm_umac_tx_key_id) -
- sizeof(struct iwm_umac_wifi_if));
-
- tx_key_id.key_idx = key_idx;
-
- return iwm_send_wifi_if_cmd(iwm, &tx_key_id, sizeof(tx_key_id), 1);
-}
-
static int iwm_check_profile(struct iwm_priv *iwm)
{
if (!iwm->umac_profile_active)
@@ -556,10 +560,35 @@ static int iwm_check_profile(struct iwm_priv *iwm)
return 0;
}
-int iwm_set_key(struct iwm_priv *iwm, bool remove, bool set_tx_key,
- struct iwm_key *key)
+int iwm_set_tx_key(struct iwm_priv *iwm, u8 key_idx)
{
+ struct iwm_umac_tx_key_id tx_key_id;
int ret;
+
+ ret = iwm_check_profile(iwm);
+ if (ret < 0)
+ return ret;
+
+ /* UMAC only allows to set default key for WEP and auth type is
+ * NOT 802.1X or RSNA. */
+ if ((iwm->umac_profile->sec.ucast_cipher != UMAC_CIPHER_TYPE_WEP_40 &&
+ iwm->umac_profile->sec.ucast_cipher != UMAC_CIPHER_TYPE_WEP_104) ||
+ iwm->umac_profile->sec.auth_type == UMAC_AUTH_TYPE_8021X ||
+ iwm->umac_profile->sec.auth_type == UMAC_AUTH_TYPE_RSNA_PSK)
+ return 0;
+
+ tx_key_id.hdr.oid = UMAC_WIFI_IF_CMD_GLOBAL_TX_KEY_ID;
+ tx_key_id.hdr.buf_size = cpu_to_le16(sizeof(struct iwm_umac_tx_key_id) -
+ sizeof(struct iwm_umac_wifi_if));
+
+ tx_key_id.key_idx = key_idx;
+
+ return iwm_send_wifi_if_cmd(iwm, &tx_key_id, sizeof(tx_key_id), 1);
+}
+
+int iwm_set_key(struct iwm_priv *iwm, bool remove, struct iwm_key *key)
+{
+ int ret = 0;
u8 cmd[64], *sta_addr, *key_data, key_len;
s8 key_idx;
u16 cmd_size = 0;
@@ -569,15 +598,6 @@ int iwm_set_key(struct iwm_priv *iwm, bool remove, bool set_tx_key,
struct iwm_umac_key_tkip *tkip = (struct iwm_umac_key_tkip *)cmd;
struct iwm_umac_key_ccmp *ccmp = (struct iwm_umac_key_ccmp *)cmd;
- if (set_tx_key)
- iwm->default_key = key;
-
- /*
- * We check if our current profile is valid.
- * If not, we dont push the key, we just cache them,
- * so that with the next siwsessid call, the keys
- * will be actually pushed.
- */
if (!remove) {
ret = iwm_check_profile(iwm);
if (ret < 0)
@@ -590,8 +610,9 @@ int iwm_set_key(struct iwm_priv *iwm, bool remove, bool set_tx_key,
key_idx = key->hdr.key_idx;
if (!remove) {
- IWM_DBG_WEXT(iwm, DBG, "key_idx:%d set tx key:%d\n",
- key_idx, set_tx_key);
+ u8 auth_type = iwm->umac_profile->sec.auth_type;
+
+ IWM_DBG_WEXT(iwm, DBG, "key_idx:%d\n", key_idx);
IWM_DBG_WEXT(iwm, DBG, "key_len:%d\n", key_len);
IWM_DBG_WEXT(iwm, DBG, "MAC:%pM, idx:%d, multicast:%d\n",
key_hdr->mac, key_hdr->key_idx, key_hdr->multicast);
@@ -603,8 +624,8 @@ int iwm_set_key(struct iwm_priv *iwm, bool remove, bool set_tx_key,
iwm->umac_profile->sec.auth_type,
iwm->umac_profile->sec.flags);
- switch (key->alg) {
- case UMAC_CIPHER_TYPE_WEP_40:
+ switch (key->cipher) {
+ case WLAN_CIPHER_SUITE_WEP40:
wep40->hdr.oid = UMAC_WIFI_IF_CMD_ADD_WEP40_KEY;
wep40->hdr.buf_size =
cpu_to_le16(sizeof(struct iwm_umac_key_wep40) -
@@ -613,12 +634,14 @@ int iwm_set_key(struct iwm_priv *iwm, bool remove, bool set_tx_key,
memcpy(&wep40->key_hdr, key_hdr,
sizeof(struct iwm_umac_key_hdr));
memcpy(wep40->key, key_data, key_len);
- wep40->static_key = 1;
+ wep40->static_key =
+ !!((auth_type != UMAC_AUTH_TYPE_8021X) &&
+ (auth_type != UMAC_AUTH_TYPE_RSNA_PSK));
cmd_size = sizeof(struct iwm_umac_key_wep40);
break;
- case UMAC_CIPHER_TYPE_WEP_104:
+ case WLAN_CIPHER_SUITE_WEP104:
wep104->hdr.oid = UMAC_WIFI_IF_CMD_ADD_WEP104_KEY;
wep104->hdr.buf_size =
cpu_to_le16(sizeof(struct iwm_umac_key_wep104) -
@@ -627,12 +650,14 @@ int iwm_set_key(struct iwm_priv *iwm, bool remove, bool set_tx_key,
memcpy(&wep104->key_hdr, key_hdr,
sizeof(struct iwm_umac_key_hdr));
memcpy(wep104->key, key_data, key_len);
- wep104->static_key = 1;
+ wep104->static_key =
+ !!((auth_type != UMAC_AUTH_TYPE_8021X) &&
+ (auth_type != UMAC_AUTH_TYPE_RSNA_PSK));
cmd_size = sizeof(struct iwm_umac_key_wep104);
break;
- case UMAC_CIPHER_TYPE_CCMP:
+ case WLAN_CIPHER_SUITE_CCMP:
key_hdr->key_idx++;
ccmp->hdr.oid = UMAC_WIFI_IF_CMD_ADD_CCMP_KEY;
ccmp->hdr.buf_size =
@@ -644,13 +669,13 @@ int iwm_set_key(struct iwm_priv *iwm, bool remove, bool set_tx_key,
memcpy(ccmp->key, key_data, key_len);
- if (key->flags & IW_ENCODE_EXT_RX_SEQ_VALID)
- memcpy(ccmp->iv_count, key->rx_seq, 6);
+ if (key->seq_len)
+ memcpy(ccmp->iv_count, key->seq, key->seq_len);
cmd_size = sizeof(struct iwm_umac_key_ccmp);
break;
- case UMAC_CIPHER_TYPE_TKIP:
+ case WLAN_CIPHER_SUITE_TKIP:
key_hdr->key_idx++;
tkip->hdr.oid = UMAC_WIFI_IF_CMD_ADD_TKIP_KEY;
tkip->hdr.buf_size =
@@ -667,8 +692,8 @@ int iwm_set_key(struct iwm_priv *iwm, bool remove, bool set_tx_key,
key_data + IWM_TKIP_KEY_SIZE + IWM_TKIP_MIC_SIZE,
IWM_TKIP_MIC_SIZE);
- if (key->flags & IW_ENCODE_EXT_RX_SEQ_VALID)
- memcpy(ccmp->iv_count, key->rx_seq, 6);
+ if (key->seq_len)
+ memcpy(ccmp->iv_count, key->seq, key->seq_len);
cmd_size = sizeof(struct iwm_umac_key_tkip);
break;
@@ -677,8 +702,8 @@ int iwm_set_key(struct iwm_priv *iwm, bool remove, bool set_tx_key,
return -ENOTSUPP;
}
- if ((key->alg == UMAC_CIPHER_TYPE_CCMP) ||
- (key->alg == UMAC_CIPHER_TYPE_TKIP))
+ if ((key->cipher == WLAN_CIPHER_SUITE_TKIP) ||
+ (key->cipher == WLAN_CIPHER_SUITE_CCMP))
/*
* UGLY_UGLY_UGLY
* Copied HACK from the MWG driver.
@@ -689,23 +714,11 @@ int iwm_set_key(struct iwm_priv *iwm, bool remove, bool set_tx_key,
schedule_timeout_interruptible(usecs_to_jiffies(300));
ret = iwm_send_wifi_if_cmd(iwm, cmd, cmd_size, 1);
- if (ret < 0)
- goto err;
-
- /*
- * We need a default key only if it is set and
- * if we're doing WEP.
- */
- if (iwm->default_key == key &&
- ((key->alg == UMAC_CIPHER_TYPE_WEP_40) ||
- (key->alg == UMAC_CIPHER_TYPE_WEP_104))) {
- ret = iwm_set_tx_key(iwm, key_idx);
- if (ret < 0)
- goto err;
- }
} else {
struct iwm_umac_key_remove key_remove;
+ IWM_DBG_WEXT(iwm, ERR, "Removing key_idx:%d\n", key_idx);
+
key_remove.hdr.oid = UMAC_WIFI_IF_CMD_REMOVE_KEY;
key_remove.hdr.buf_size =
cpu_to_le16(sizeof(struct iwm_umac_key_remove) -
@@ -716,23 +729,19 @@ int iwm_set_key(struct iwm_priv *iwm, bool remove, bool set_tx_key,
ret = iwm_send_wifi_if_cmd(iwm, &key_remove,
sizeof(struct iwm_umac_key_remove),
1);
- if (ret < 0)
+ if (ret)
return ret;
- iwm->keys[key_idx].in_use = 0;
+ iwm->keys[key_idx].key_len = 0;
}
- return 0;
-
- err:
- kfree(key);
return ret;
}
int iwm_send_mlme_profile(struct iwm_priv *iwm)
{
- int ret, i;
+ int ret;
struct iwm_umac_profile profile;
memcpy(&profile, iwm->umac_profile, sizeof(profile));
@@ -742,45 +751,18 @@ int iwm_send_mlme_profile(struct iwm_priv *iwm)
sizeof(struct iwm_umac_wifi_if));
ret = iwm_send_wifi_if_cmd(iwm, &profile, sizeof(profile), 1);
- if (ret < 0) {
+ if (ret) {
IWM_ERR(iwm, "Send profile command failed\n");
return ret;
}
- /* Wait for the profile to be active */
- ret = wait_event_interruptible_timeout(iwm->mlme_queue,
- iwm->umac_profile_active == 1,
- 3 * HZ);
- if (!ret)
- return -EBUSY;
-
-
- for (i = 0; i < IWM_NUM_KEYS; i++)
- if (iwm->keys[i].in_use) {
- int default_key = 0;
- struct iwm_key *key = &iwm->keys[i];
-
- if (key == iwm->default_key)
- default_key = 1;
-
- /* Wait for the profile before sending the keys */
- wait_event_interruptible_timeout(iwm->mlme_queue,
- (test_bit(IWM_STATUS_ASSOCIATING, &iwm->status) ||
- test_bit(IWM_STATUS_ASSOCIATED, &iwm->status)),
- 3 * HZ);
-
- ret = iwm_set_key(iwm, 0, default_key, key);
- if (ret < 0)
- return ret;
- }
-
return 0;
}
int iwm_invalidate_mlme_profile(struct iwm_priv *iwm)
{
- int ret;
struct iwm_umac_invalidate_profile invalid;
+ int ret;
invalid.hdr.oid = UMAC_WIFI_IF_CMD_INVALIDATE_PROFILE;
invalid.hdr.buf_size =
@@ -790,16 +772,13 @@ int iwm_invalidate_mlme_profile(struct iwm_priv *iwm)
invalid.reason = WLAN_REASON_UNSPECIFIED;
ret = iwm_send_wifi_if_cmd(iwm, &invalid, sizeof(invalid), 1);
- if (ret < 0)
+ if (ret)
return ret;
ret = wait_event_interruptible_timeout(iwm->mlme_queue,
- (iwm->umac_profile_active == 0),
- 2 * HZ);
- if (!ret)
- return -EBUSY;
+ (iwm->umac_profile_active == 0), 2 * HZ);
- return 0;
+ return ret ? 0 : -EBUSY;
}
int iwm_send_umac_stats_req(struct iwm_priv *iwm, u32 flags)
@@ -882,7 +861,7 @@ int iwm_scan_ssids(struct iwm_priv *iwm, struct cfg80211_ssid *ssids,
}
ret = iwm_send_wifi_if_cmd(iwm, &req, sizeof(req), 0);
- if (ret < 0) {
+ if (ret) {
IWM_ERR(iwm, "Couldn't send scan request\n");
return ret;
}
diff --git a/drivers/net/wireless/iwmc3200wifi/commands.h b/drivers/net/wireless/iwmc3200wifi/commands.h
index 36b13a13059..e24d5b63399 100644
--- a/drivers/net/wireless/iwmc3200wifi/commands.h
+++ b/drivers/net/wireless/iwmc3200wifi/commands.h
@@ -106,8 +106,7 @@ enum {
CFG_TLC_SPATIAL_STREAM_SUPPORTED,
CFG_TLC_RETRY_PER_RATE,
CFG_TLC_RETRY_PER_HT_RATE,
- CFG_TLC_FIXED_RATE,
- CFG_TLC_FIXED_RATE_FLAGS,
+ CFG_TLC_FIXED_MCS,
CFG_TLC_CONTROL_FLAGS,
CFG_TLC_SR_MIN_FAIL,
CFG_TLC_SR_MIN_PASS,
@@ -232,6 +231,7 @@ struct iwm_umac_cmd_get_channel_list {
/* Wireless mode */
#define WIRELESS_MODE_11A 0x1
#define WIRELESS_MODE_11G 0x2
+#define WIRELESS_MODE_11N 0x4
#define UMAC_PROFILE_EX_IE_REQUIRED 0x1
#define UMAC_PROFILE_QOS_ALLOWED 0x2
@@ -406,8 +406,7 @@ int iwm_send_mlme_profile(struct iwm_priv *iwm);
int iwm_invalidate_mlme_profile(struct iwm_priv *iwm);
int iwm_send_packet(struct iwm_priv *iwm, struct sk_buff *skb, int pool_id);
int iwm_set_tx_key(struct iwm_priv *iwm, u8 key_idx);
-int iwm_set_key(struct iwm_priv *iwm, bool remove, bool set_tx_key,
- struct iwm_key *key);
+int iwm_set_key(struct iwm_priv *iwm, bool remove, struct iwm_key *key);
int iwm_send_umac_stats_req(struct iwm_priv *iwm, u32 flags);
int iwm_send_umac_channel_list(struct iwm_priv *iwm);
int iwm_scan_ssids(struct iwm_priv *iwm, struct cfg80211_ssid *ssids,
diff --git a/drivers/net/wireless/iwmc3200wifi/eeprom.c b/drivers/net/wireless/iwmc3200wifi/eeprom.c
index 0f34b84fd2e..365910fbe01 100644
--- a/drivers/net/wireless/iwmc3200wifi/eeprom.c
+++ b/drivers/net/wireless/iwmc3200wifi/eeprom.c
@@ -156,10 +156,6 @@ int iwm_eeprom_init(struct iwm_priv *iwm)
return -ENOMEM;
for (i = IWM_EEPROM_FIRST; i < IWM_EEPROM_LAST; i++) {
-#ifdef CONFIG_IWM_B0_HW_SUPPORT
- if (iwm->conf.hw_b0 && (i >= IWM_EEPROM_INDIRECT_OFFSET))
- break;
-#endif
ret = iwm_eeprom_read(iwm, i);
if (ret < 0) {
IWM_ERR(iwm, "Couldn't read eeprom entry #%d: %s\n",
diff --git a/drivers/net/wireless/iwmc3200wifi/fw.c b/drivers/net/wireless/iwmc3200wifi/fw.c
index ec1a15a5a0e..0f32cab9ced 100644
--- a/drivers/net/wireless/iwmc3200wifi/fw.c
+++ b/drivers/net/wireless/iwmc3200wifi/fw.c
@@ -275,6 +275,7 @@ static int iwm_load_lmac(struct iwm_priv *iwm, const char *img_name)
*/
int iwm_load_fw(struct iwm_priv *iwm)
{
+ unsigned long init_calib_map, periodic_calib_map;
int ret;
/* We first start downloading the UMAC */
@@ -315,23 +316,19 @@ int iwm_load_fw(struct iwm_priv *iwm)
return ret;
}
-#ifdef CONFIG_IWM_B0_HW_SUPPORT
- if (iwm->conf.hw_b0) {
- clear_bit(PHY_CALIBRATE_RX_IQ_CMD, &iwm->conf.init_calib_map);
- clear_bit(PHY_CALIBRATE_RX_IQ_CMD,
- &iwm->conf.periodic_calib_map);
- }
-#endif
+ init_calib_map = iwm->conf.calib_map & IWM_CALIB_MAP_INIT_MSK;
+ periodic_calib_map = IWM_CALIB_MAP_PER_LMAC(iwm->conf.calib_map);
+
/* Read RX IQ calibration result from EEPROM */
- if (test_bit(PHY_CALIBRATE_RX_IQ_CMD, &iwm->conf.init_calib_map)) {
+ if (test_bit(PHY_CALIBRATE_RX_IQ_CMD, &init_calib_map)) {
iwm_store_rxiq_calib_result(iwm);
set_bit(PHY_CALIBRATE_RX_IQ_CMD, &iwm->calib_done_map);
}
iwm_send_prio_table(iwm);
- iwm_send_init_calib_cfg(iwm, iwm->conf.init_calib_map);
+ iwm_send_init_calib_cfg(iwm, init_calib_map);
- while (iwm->calib_done_map != iwm->conf.init_calib_map) {
+ while (iwm->calib_done_map != init_calib_map) {
ret = iwm_notif_handle(iwm, CALIBRATION_RES_NOTIFICATION,
IWM_SRC_LMAC, WAIT_NOTIF_TIMEOUT);
if (ret) {
@@ -340,7 +337,7 @@ int iwm_load_fw(struct iwm_priv *iwm)
}
IWM_DBG_FW(iwm, DBG, "Got calibration result. calib_done_map: "
"0x%lx, requested calibrations: 0x%lx\n",
- iwm->calib_done_map, iwm->conf.init_calib_map);
+ iwm->calib_done_map, init_calib_map);
}
/* Handle LMAC CALIBRATION_COMPLETE notification */
@@ -378,7 +375,7 @@ int iwm_load_fw(struct iwm_priv *iwm)
iwm_send_prio_table(iwm);
iwm_send_calib_results(iwm);
- iwm_send_periodic_calib_cfg(iwm, iwm->conf.periodic_calib_map);
+ iwm_send_periodic_calib_cfg(iwm, periodic_calib_map);
return 0;
diff --git a/drivers/net/wireless/iwmc3200wifi/hal.c b/drivers/net/wireless/iwmc3200wifi/hal.c
index ee127fe4f43..c430418248b 100644
--- a/drivers/net/wireless/iwmc3200wifi/hal.c
+++ b/drivers/net/wireless/iwmc3200wifi/hal.c
@@ -105,9 +105,9 @@
#include "umac.h"
#include "debug.h"
-static void iwm_nonwifi_cmd_init(struct iwm_priv *iwm,
- struct iwm_nonwifi_cmd *cmd,
- struct iwm_udma_nonwifi_cmd *udma_cmd)
+static int iwm_nonwifi_cmd_init(struct iwm_priv *iwm,
+ struct iwm_nonwifi_cmd *cmd,
+ struct iwm_udma_nonwifi_cmd *udma_cmd)
{
INIT_LIST_HEAD(&cmd->pending);
@@ -118,7 +118,7 @@ static void iwm_nonwifi_cmd_init(struct iwm_priv *iwm,
cmd->seq_num = iwm->nonwifi_seq_num;
udma_cmd->seq_num = cpu_to_le16(cmd->seq_num);
- cmd->seq_num = iwm->nonwifi_seq_num++;
+ iwm->nonwifi_seq_num++;
iwm->nonwifi_seq_num %= UMAC_NONWIFI_SEQ_NUM_MAX;
if (udma_cmd->resp)
@@ -130,6 +130,8 @@ static void iwm_nonwifi_cmd_init(struct iwm_priv *iwm,
cmd->buf.len = 0;
memcpy(&cmd->udma_cmd, udma_cmd, sizeof(*udma_cmd));
+
+ return cmd->seq_num;
}
u16 iwm_alloc_wifi_cmd_seq(struct iwm_priv *iwm)
@@ -369,7 +371,7 @@ int iwm_hal_send_target_cmd(struct iwm_priv *iwm,
const void *payload)
{
struct iwm_nonwifi_cmd *cmd;
- int ret;
+ int ret, seq_num;
cmd = kzalloc(sizeof(struct iwm_nonwifi_cmd), GFP_KERNEL);
if (!cmd) {
@@ -377,7 +379,7 @@ int iwm_hal_send_target_cmd(struct iwm_priv *iwm,
return -ENOMEM;
}
- iwm_nonwifi_cmd_init(iwm, cmd, udma_cmd);
+ seq_num = iwm_nonwifi_cmd_init(iwm, cmd, udma_cmd);
if (cmd->udma_cmd.opcode == UMAC_HDI_OUT_OPCODE_WRITE ||
cmd->udma_cmd.opcode == UMAC_HDI_OUT_OPCODE_WRITE_PERSISTENT) {
@@ -393,7 +395,7 @@ int iwm_hal_send_target_cmd(struct iwm_priv *iwm,
if (ret < 0)
return ret;
- return cmd->seq_num;
+ return seq_num;
}
static void iwm_build_lmac_hdr(struct iwm_priv *iwm, struct iwm_lmac_hdr *hdr,
diff --git a/drivers/net/wireless/iwmc3200wifi/iwm.h b/drivers/net/wireless/iwmc3200wifi/iwm.h
index 77c339f8516..7a51bc340fd 100644
--- a/drivers/net/wireless/iwmc3200wifi/iwm.h
+++ b/drivers/net/wireless/iwmc3200wifi/iwm.h
@@ -52,8 +52,6 @@
#define IWM_COPYRIGHT "Copyright(c) 2009 Intel Corporation"
#define IWM_AUTHOR "<ilw@linux.intel.com>"
-#define CONFIG_IWM_B0_HW_SUPPORT 1
-
#define IWM_SRC_LMAC UMAC_HDI_IN_SOURCE_FHRX
#define IWM_SRC_UDMA UMAC_HDI_IN_SOURCE_UDMA
#define IWM_SRC_UMAC UMAC_HDI_IN_SOURCE_FW
@@ -65,8 +63,7 @@
struct iwm_conf {
u32 sdio_ior_timeout;
- unsigned long init_calib_map;
- unsigned long periodic_calib_map;
+ unsigned long calib_map;
bool reset_on_fatal_err;
bool auto_connect;
bool wimax_not_present;
@@ -87,9 +84,6 @@ struct iwm_conf {
u8 ibss_channel;
u8 mac_addr[ETH_ALEN];
-#ifdef CONFIG_IWM_B0_HW_SUPPORT
- bool hw_b0;
-#endif
};
enum {
@@ -162,13 +156,11 @@ struct iwm_umac_key_hdr {
struct iwm_key {
struct iwm_umac_key_hdr hdr;
- u8 in_use;
- u8 alg;
- u32 flags;
- u8 tx_seq[IW_ENCODE_SEQ_MAX_SIZE];
- u8 rx_seq[IW_ENCODE_SEQ_MAX_SIZE];
- u8 key_len;
- u8 key[32];
+ u32 cipher;
+ u8 key[WLAN_MAX_KEY_LEN];
+ u8 seq[IW_ENCODE_SEQ_MAX_SIZE];
+ int key_len;
+ int seq_len;
};
#define IWM_RX_ID_HASH 0xff
@@ -186,10 +178,6 @@ struct iwm_key {
#define IWM_STATUS_ASSOCIATING 3
#define IWM_STATUS_ASSOCIATED 4
-#define IWM_RADIO_RFKILL_OFF 0
-#define IWM_RADIO_RFKILL_HW 1
-#define IWM_RADIO_RFKILL_SW 2
-
struct iwm_tx_queue {
int id;
struct sk_buff_head queue;
@@ -223,7 +211,6 @@ struct iwm_priv {
struct iwm_conf conf;
unsigned long status;
- unsigned long radio;
struct list_head pending_notif;
wait_queue_head_t notif_queue;
@@ -242,6 +229,7 @@ struct iwm_priv {
u8 bssid[ETH_ALEN];
u8 channel;
u16 rate;
+ u32 txpower;
struct iwm_sta_info sta_table[IWM_STA_TABLE_NUM];
struct list_head bss_list;
@@ -276,7 +264,10 @@ struct iwm_priv {
struct iwm_tx_queue txq[IWM_TX_QUEUES];
struct iwm_key keys[IWM_NUM_KEYS];
- struct iwm_key *default_key;
+ s8 default_key;
+
+ DECLARE_BITMAP(wifi_ntfy, WIFI_IF_NTFY_MAX);
+ wait_queue_head_t wifi_ntfy_queue;
wait_queue_head_t mlme_queue;
@@ -289,7 +280,11 @@ struct iwm_priv {
struct timer_list watchdog;
struct work_struct reset_worker;
struct mutex mutex;
- struct rfkill *rfkill;
+
+ u8 *req_ie;
+ int req_ie_len;
+ u8 *resp_ie;
+ int resp_ie_len;
char private[0] __attribute__((__aligned__(NETDEV_ALIGN)));
};
@@ -311,8 +306,6 @@ static inline void *iwm_private(struct iwm_priv *iwm)
#define skb_to_rx_info(s) ((struct iwm_rx_info *)(s->cb))
#define skb_to_tx_info(s) ((struct iwm_tx_info *)s->cb)
-extern const struct iw_handler_def iwm_iw_handler_def;
-
void *iwm_if_alloc(int sizeof_bus, struct device *dev,
struct iwm_if_ops *if_ops);
void iwm_if_free(struct iwm_priv *iwm);
diff --git a/drivers/net/wireless/iwmc3200wifi/lmac.h b/drivers/net/wireless/iwmc3200wifi/lmac.h
index db2e5eea189..19213e165f5 100644
--- a/drivers/net/wireless/iwmc3200wifi/lmac.h
+++ b/drivers/net/wireless/iwmc3200wifi/lmac.h
@@ -396,6 +396,10 @@ enum {
CALIBRATION_CMD_NUM,
};
+#define IWM_CALIB_MAP_INIT_MSK 0xFFFF
+#define IWM_CALIB_MAP_PER_LMAC(m) ((m & 0xFF0000) >> 16)
+#define IWM_CALIB_MAP_PER_UMAC(m) ((m & 0xFF000000) >> 24)
+
struct iwm_lmac_calib_hdr {
u8 opcode;
u8 first_grp;
diff --git a/drivers/net/wireless/iwmc3200wifi/main.c b/drivers/net/wireless/iwmc3200wifi/main.c
index 8be206d5822..cf2574442b5 100644
--- a/drivers/net/wireless/iwmc3200wifi/main.c
+++ b/drivers/net/wireless/iwmc3200wifi/main.c
@@ -53,11 +53,7 @@
static struct iwm_conf def_iwm_conf = {
.sdio_ior_timeout = 5000,
- .init_calib_map = BIT(PHY_CALIBRATE_DC_CMD) |
- BIT(PHY_CALIBRATE_LO_CMD) |
- BIT(PHY_CALIBRATE_TX_IQ_CMD) |
- BIT(PHY_CALIBRATE_RX_IQ_CMD),
- .periodic_calib_map = BIT(PHY_CALIBRATE_DC_CMD) |
+ .calib_map = BIT(PHY_CALIBRATE_DC_CMD) |
BIT(PHY_CALIBRATE_LO_CMD) |
BIT(PHY_CALIBRATE_TX_IQ_CMD) |
BIT(PHY_CALIBRATE_RX_IQ_CMD) |
@@ -191,6 +187,7 @@ int iwm_priv_init(struct iwm_priv *iwm)
INIT_LIST_HEAD(&iwm->pending_notif);
init_waitqueue_head(&iwm->notif_queue);
init_waitqueue_head(&iwm->nonwifi_queue);
+ init_waitqueue_head(&iwm->wifi_ntfy_queue);
init_waitqueue_head(&iwm->mlme_queue);
memcpy(&iwm->conf, &def_iwm_conf, sizeof(struct iwm_conf));
spin_lock_init(&iwm->tx_credit.lock);
@@ -229,7 +226,7 @@ int iwm_priv_init(struct iwm_priv *iwm)
for (i = 0; i < IWM_NUM_KEYS; i++)
memset(&iwm->keys[i], 0, sizeof(struct iwm_key));
- iwm->default_key = NULL;
+ iwm->default_key = -1;
init_timer(&iwm->watchdog);
iwm->watchdog.function = iwm_watchdog;
@@ -500,6 +497,13 @@ void iwm_link_off(struct iwm_priv *iwm)
memset(wstats, 0, sizeof(struct iw_statistics));
wstats->qual.updated = IW_QUAL_ALL_INVALID;
+ kfree(iwm->req_ie);
+ iwm->req_ie = NULL;
+ iwm->req_ie_len = 0;
+ kfree(iwm->resp_ie);
+ iwm->resp_ie = NULL;
+ iwm->resp_ie_len = 0;
+
del_timer_sync(&iwm->watchdog);
}
@@ -518,13 +522,6 @@ static int iwm_channels_init(struct iwm_priv *iwm)
{
int ret;
-#ifdef CONFIG_IWM_B0_HW_SUPPORT
- if (iwm->conf.hw_b0) {
- IWM_INFO(iwm, "Workaround EEPROM channels for B0 hardware\n");
- return 0;
- }
-#endif
-
ret = iwm_send_umac_channel_list(iwm);
if (ret) {
IWM_ERR(iwm, "Send channel list failed\n");
@@ -642,19 +639,10 @@ int __iwm_up(struct iwm_priv *iwm)
}
}
- iwm->umac_profile = kmalloc(sizeof(struct iwm_umac_profile),
- GFP_KERNEL);
- if (!iwm->umac_profile) {
- IWM_ERR(iwm, "Couldn't alloc memory for profile\n");
- goto err_fw;
- }
-
- iwm_init_default_profile(iwm, iwm->umac_profile);
-
ret = iwm_channels_init(iwm);
if (ret < 0) {
IWM_ERR(iwm, "Couldn't init channels\n");
- goto err_profile;
+ goto err_fw;
}
/* Set the READY bit to indicate interface is brought up successfully */
@@ -662,10 +650,6 @@ int __iwm_up(struct iwm_priv *iwm)
return 0;
- err_profile:
- kfree(iwm->umac_profile);
- iwm->umac_profile = NULL;
-
err_fw:
iwm_eeprom_exit(iwm);
@@ -704,11 +688,10 @@ int __iwm_down(struct iwm_priv *iwm)
clear_bit(IWM_STATUS_READY, &iwm->status);
iwm_eeprom_exit(iwm);
- kfree(iwm->umac_profile);
- iwm->umac_profile = NULL;
iwm_bss_list_clean(iwm);
-
- iwm->default_key = NULL;
+ iwm_init_default_profile(iwm, iwm->umac_profile);
+ iwm->umac_profile_active = false;
+ iwm->default_key = -1;
iwm->core_enabled = 0;
ret = iwm_bus_disable(iwm);
diff --git a/drivers/net/wireless/iwmc3200wifi/netdev.c b/drivers/net/wireless/iwmc3200wifi/netdev.c
index bf294e41753..35ec006c2d2 100644
--- a/drivers/net/wireless/iwmc3200wifi/netdev.c
+++ b/drivers/net/wireless/iwmc3200wifi/netdev.c
@@ -48,29 +48,22 @@
#include <linux/netdevice.h>
#include "iwm.h"
+#include "commands.h"
#include "cfg80211.h"
#include "debug.h"
static int iwm_open(struct net_device *ndev)
{
struct iwm_priv *iwm = ndev_to_iwm(ndev);
- int ret = 0;
-
- if (!test_bit(IWM_RADIO_RFKILL_SW, &iwm->radio))
- ret = iwm_up(iwm);
- return ret;
+ return iwm_up(iwm);
}
static int iwm_stop(struct net_device *ndev)
{
struct iwm_priv *iwm = ndev_to_iwm(ndev);
- int ret = 0;
-
- if (!test_bit(IWM_RADIO_RFKILL_SW, &iwm->radio))
- ret = iwm_down(iwm);
- return ret;
+ return iwm_down(iwm);
}
/*
@@ -128,13 +121,24 @@ void *iwm_if_alloc(int sizeof_bus, struct device *dev,
}
ndev->netdev_ops = &iwm_netdev_ops;
- ndev->wireless_handlers = &iwm_iw_handler_def;
ndev->ieee80211_ptr = wdev;
SET_NETDEV_DEV(ndev, wiphy_dev(wdev->wiphy));
wdev->netdev = ndev;
+ iwm->umac_profile = kmalloc(sizeof(struct iwm_umac_profile),
+ GFP_KERNEL);
+ if (!iwm->umac_profile) {
+ dev_err(dev, "Couldn't alloc memory for profile\n");
+ goto out_profile;
+ }
+
+ iwm_init_default_profile(iwm, iwm->umac_profile);
+
return iwm;
+ out_profile:
+ free_netdev(ndev);
+
out_priv:
iwm_priv_deinit(iwm);
@@ -150,6 +154,8 @@ void iwm_if_free(struct iwm_priv *iwm)
free_netdev(iwm_to_ndev(iwm));
iwm_priv_deinit(iwm);
+ kfree(iwm->umac_profile);
+ iwm->umac_profile = NULL;
iwm_wdev_free(iwm);
}
diff --git a/drivers/net/wireless/iwmc3200wifi/rx.c b/drivers/net/wireless/iwmc3200wifi/rx.c
index d73cf96c6dc..86079a187ee 100644
--- a/drivers/net/wireless/iwmc3200wifi/rx.c
+++ b/drivers/net/wireless/iwmc3200wifi/rx.c
@@ -102,7 +102,6 @@ static int iwm_ntf_error(struct iwm_priv *iwm, u8 *buf,
error = (struct iwm_umac_notif_error *)buf;
fw_err = &error->err;
-
IWM_ERR(iwm, "%cMAC FW ERROR:\n",
(le32_to_cpu(fw_err->category) == UMAC_SYS_ERR_CAT_LMAC) ? 'L' : 'U');
IWM_ERR(iwm, "\tCategory: %d\n", le32_to_cpu(fw_err->category));
@@ -143,17 +142,18 @@ static int iwm_ntf_init_complete(struct iwm_priv *iwm, u8 *buf,
unsigned long buf_size,
struct iwm_wifi_cmd *cmd)
{
+ struct wiphy *wiphy = iwm_to_wiphy(iwm);
struct iwm_umac_notif_init_complete *init_complete =
(struct iwm_umac_notif_init_complete *)(buf);
u16 status = le16_to_cpu(init_complete->status);
+ bool blocked = (status == UMAC_NTFY_INIT_COMPLETE_STATUS_ERR);
- if (status == UMAC_NTFY_INIT_COMPLETE_STATUS_ERR) {
+ if (blocked)
IWM_DBG_NTF(iwm, DBG, "Hardware rf kill is on (radio off)\n");
- set_bit(IWM_RADIO_RFKILL_HW, &iwm->radio);
- } else {
+ else
IWM_DBG_NTF(iwm, DBG, "Hardware rf kill is off (radio on)\n");
- clear_bit(IWM_RADIO_RFKILL_HW, &iwm->radio);
- }
+
+ wiphy_rfkill_set_hw_state(wiphy, blocked);
return 0;
}
@@ -218,17 +218,17 @@ static int iwm_ntf_tx(struct iwm_priv *iwm, u8 *buf,
(buf + sizeof(struct iwm_umac_wifi_in_hdr));
hdr = (struct iwm_umac_wifi_in_hdr *)buf;
- IWM_DBG_NTF(iwm, DBG, "REPLY_TX, buf size: %lu\n", buf_size);
+ IWM_DBG_TX(iwm, DBG, "REPLY_TX, buf size: %lu\n", buf_size);
- IWM_DBG_NTF(iwm, DBG, "Seqnum: %d\n",
- le16_to_cpu(hdr->sw_hdr.cmd.seq_num));
- IWM_DBG_NTF(iwm, DBG, "\tFrame cnt: %d\n", tx_resp->frame_cnt);
- IWM_DBG_NTF(iwm, DBG, "\tRetry cnt: %d\n",
- le16_to_cpu(tx_resp->retry_cnt));
- IWM_DBG_NTF(iwm, DBG, "\tSeq ctl: %d\n", le16_to_cpu(tx_resp->seq_ctl));
- IWM_DBG_NTF(iwm, DBG, "\tByte cnt: %d\n",
- le16_to_cpu(tx_resp->byte_cnt));
- IWM_DBG_NTF(iwm, DBG, "\tStatus: 0x%x\n", le32_to_cpu(tx_resp->status));
+ IWM_DBG_TX(iwm, DBG, "Seqnum: %d\n",
+ le16_to_cpu(hdr->sw_hdr.cmd.seq_num));
+ IWM_DBG_TX(iwm, DBG, "\tFrame cnt: %d\n", tx_resp->frame_cnt);
+ IWM_DBG_TX(iwm, DBG, "\tRetry cnt: %d\n",
+ le16_to_cpu(tx_resp->retry_cnt));
+ IWM_DBG_TX(iwm, DBG, "\tSeq ctl: %d\n", le16_to_cpu(tx_resp->seq_ctl));
+ IWM_DBG_TX(iwm, DBG, "\tByte cnt: %d\n",
+ le16_to_cpu(tx_resp->byte_cnt));
+ IWM_DBG_TX(iwm, DBG, "\tStatus: 0x%x\n", le32_to_cpu(tx_resp->status));
return 0;
}
@@ -418,8 +418,8 @@ static int iwm_ntf_rx_ticket(struct iwm_priv *iwm, u8 *buf,
if (IS_ERR(ticket_node))
return PTR_ERR(ticket_node);
- IWM_DBG_NTF(iwm, DBG, "TICKET RELEASE(%d)\n",
- ticket->id);
+ IWM_DBG_RX(iwm, DBG, "TICKET RELEASE(%d)\n",
+ ticket->id);
list_add_tail(&ticket_node->node, &iwm->rx_tickets);
/*
@@ -454,15 +454,15 @@ static int iwm_ntf_rx_packet(struct iwm_priv *iwm, u8 *buf,
u16 id, buf_offset;
u32 packet_size;
- IWM_DBG_NTF(iwm, DBG, "\n");
+ IWM_DBG_RX(iwm, DBG, "\n");
wifi_hdr = (struct iwm_umac_wifi_in_hdr *)buf;
id = le16_to_cpu(wifi_hdr->sw_hdr.cmd.seq_num);
buf_offset = sizeof(struct iwm_umac_wifi_in_hdr);
packet_size = buf_size - sizeof(struct iwm_umac_wifi_in_hdr);
- IWM_DBG_NTF(iwm, DBG, "CMD:0x%x, seqnum: %d, packet size: %d\n",
- wifi_hdr->sw_hdr.cmd.cmd, id, packet_size);
+ IWM_DBG_RX(iwm, DBG, "CMD:0x%x, seqnum: %d, packet size: %d\n",
+ wifi_hdr->sw_hdr.cmd.cmd, id, packet_size);
IWM_DBG_RX(iwm, DBG, "Packet id: %d\n", id);
IWM_HEXDUMP(iwm, DBG, RX, "PACKET: ", buf + buf_offset, packet_size);
@@ -503,13 +503,10 @@ static int iwm_mlme_assoc_complete(struct iwm_priv *iwm, u8 *buf,
{
struct iwm_umac_notif_assoc_complete *complete =
(struct iwm_umac_notif_assoc_complete *)buf;
- union iwreq_data wrqu;
IWM_DBG_MLME(iwm, INFO, "Association with %pM completed, status: %d\n",
complete->bssid, complete->status);
- memset(&wrqu, 0, sizeof(wrqu));
-
clear_bit(IWM_STATUS_ASSOCIATING, &iwm->status);
switch (le32_to_cpu(complete->status)) {
@@ -520,7 +517,14 @@ static int iwm_mlme_assoc_complete(struct iwm_priv *iwm, u8 *buf,
iwm_link_on(iwm);
- memcpy(wrqu.ap_addr.sa_data, complete->bssid, ETH_ALEN);
+ if (iwm->conf.mode == UMAC_MODE_IBSS)
+ goto ibss;
+
+ cfg80211_connect_result(iwm_to_ndev(iwm),
+ complete->bssid,
+ iwm->req_ie, iwm->req_ie_len,
+ iwm->resp_ie, iwm->resp_ie_len,
+ WLAN_STATUS_SUCCESS, GFP_KERNEL);
break;
case UMAC_ASSOC_COMPLETE_FAILURE:
clear_bit(IWM_STATUS_ASSOCIATED, &iwm->status);
@@ -528,18 +532,22 @@ static int iwm_mlme_assoc_complete(struct iwm_priv *iwm, u8 *buf,
iwm->channel = 0;
iwm_link_off(iwm);
+
+ if (iwm->conf.mode == UMAC_MODE_IBSS)
+ goto ibss;
+
+ cfg80211_connect_result(iwm_to_ndev(iwm), complete->bssid,
+ NULL, 0, NULL, 0,
+ WLAN_STATUS_UNSPECIFIED_FAILURE,
+ GFP_KERNEL);
default:
break;
}
- if (iwm->conf.mode == UMAC_MODE_IBSS) {
- cfg80211_ibss_joined(iwm_to_ndev(iwm), iwm->bssid, GFP_KERNEL);
- return 0;
- }
-
- wrqu.ap_addr.sa_family = ARPHRD_ETHER;
- wireless_send_event(iwm_to_ndev(iwm), SIOCGIWAP, &wrqu, NULL);
+ return 0;
+ ibss:
+ cfg80211_ibss_joined(iwm_to_ndev(iwm), iwm->bssid, GFP_KERNEL);
return 0;
}
@@ -769,37 +777,46 @@ static int iwm_mlme_mgt_frame(struct iwm_priv *iwm, u8 *buf,
unsigned long buf_size, struct iwm_wifi_cmd *cmd)
{
struct iwm_umac_notif_mgt_frame *mgt_frame =
- (struct iwm_umac_notif_mgt_frame *)buf;
+ (struct iwm_umac_notif_mgt_frame *)buf;
struct ieee80211_mgmt *mgt = (struct ieee80211_mgmt *)mgt_frame->frame;
u8 *ie;
- unsigned int event;
- union iwreq_data wrqu;
IWM_HEXDUMP(iwm, DBG, MLME, "MGT: ", mgt_frame->frame,
le16_to_cpu(mgt_frame->len));
if (ieee80211_is_assoc_req(mgt->frame_control)) {
ie = mgt->u.assoc_req.variable;;
- event = IWEVASSOCREQIE;
+ iwm->req_ie_len =
+ le16_to_cpu(mgt_frame->len) - (ie - (u8 *)mgt);
+ kfree(iwm->req_ie);
+ iwm->req_ie = kmemdup(mgt->u.assoc_req.variable,
+ iwm->req_ie_len, GFP_KERNEL);
} else if (ieee80211_is_reassoc_req(mgt->frame_control)) {
ie = mgt->u.reassoc_req.variable;;
- event = IWEVASSOCREQIE;
+ iwm->req_ie_len =
+ le16_to_cpu(mgt_frame->len) - (ie - (u8 *)mgt);
+ kfree(iwm->req_ie);
+ iwm->req_ie = kmemdup(mgt->u.reassoc_req.variable,
+ iwm->req_ie_len, GFP_KERNEL);
} else if (ieee80211_is_assoc_resp(mgt->frame_control)) {
ie = mgt->u.assoc_resp.variable;;
- event = IWEVASSOCRESPIE;
+ iwm->resp_ie_len =
+ le16_to_cpu(mgt_frame->len) - (ie - (u8 *)mgt);
+ kfree(iwm->resp_ie);
+ iwm->resp_ie = kmemdup(mgt->u.assoc_resp.variable,
+ iwm->resp_ie_len, GFP_KERNEL);
} else if (ieee80211_is_reassoc_resp(mgt->frame_control)) {
ie = mgt->u.reassoc_resp.variable;;
- event = IWEVASSOCRESPIE;
+ iwm->resp_ie_len =
+ le16_to_cpu(mgt_frame->len) - (ie - (u8 *)mgt);
+ kfree(iwm->resp_ie);
+ iwm->resp_ie = kmemdup(mgt->u.reassoc_resp.variable,
+ iwm->resp_ie_len, GFP_KERNEL);
} else {
IWM_ERR(iwm, "Unsupported management frame");
return 0;
}
- wrqu.data.length = le16_to_cpu(mgt_frame->len) - (ie - (u8 *)mgt);
-
- IWM_HEXDUMP(iwm, DBG, MLME, "EVT: ", ie, wrqu.data.length);
- wireless_send_event(iwm_to_ndev(iwm), event, &wrqu, ie);
-
return 0;
}
@@ -875,6 +892,7 @@ static int iwm_ntf_statistics(struct iwm_priv *iwm, u8 *buf,
/* UMAC passes rate info multiplies by 2 */
iwm->rate = max_rate >> 1;
}
+ iwm->txpower = le32_to_cpu(stats->tx_power);
wstats->status = 0;
@@ -922,13 +940,6 @@ static int iwm_ntf_eeprom_proxy(struct iwm_priv *iwm, u8 *buf,
if ((hdr_offset + hdr_len) > IWM_EEPROM_LEN)
return -EINVAL;
-#ifdef CONFIG_IWM_B0_HW_SUPPORT
- if (hdr_offset == IWM_EEPROM_SKU_CAP_OFF) {
- if (eeprom_proxy->buf[0] == 0xff)
- iwm->conf.hw_b0 = 1;
- }
-#endif
-
switch (hdr_type) {
case IWM_UMAC_CMD_EEPROM_TYPE_READ:
memcpy(iwm->eeprom + hdr_offset, eeprom_proxy->buf, hdr_len);
@@ -993,12 +1004,17 @@ static int iwm_ntf_wifi_if_wrapper(struct iwm_priv *iwm, u8 *buf,
(struct iwm_umac_wifi_if *)cmd->buf.payload;
IWM_DBG_NTF(iwm, DBG, "WIFI_IF_WRAPPER cmd is delivered to UMAC: "
- "oid is %d\n", hdr->oid);
+ "oid is 0x%x\n", hdr->oid);
+
+ if (hdr->oid <= WIFI_IF_NTFY_MAX) {
+ set_bit(hdr->oid, &iwm->wifi_ntfy[0]);
+ wake_up_interruptible(&iwm->wifi_ntfy_queue);
+ } else
+ return -EINVAL;
switch (hdr->oid) {
case UMAC_WIFI_IF_CMD_SET_PROFILE:
iwm->umac_profile_active = 1;
- wake_up_interruptible(&iwm->mlme_queue);
break;
default:
break;
@@ -1010,6 +1026,7 @@ static int iwm_ntf_wifi_if_wrapper(struct iwm_priv *iwm, u8 *buf,
static int iwm_ntf_card_state(struct iwm_priv *iwm, u8 *buf,
unsigned long buf_size, struct iwm_wifi_cmd *cmd)
{
+ struct wiphy *wiphy = iwm_to_wiphy(iwm);
struct iwm_lmac_card_state *state = (struct iwm_lmac_card_state *)
(buf + sizeof(struct iwm_umac_wifi_in_hdr));
u32 flags = le32_to_cpu(state->flags);
@@ -1018,10 +1035,7 @@ static int iwm_ntf_card_state(struct iwm_priv *iwm, u8 *buf,
flags & IWM_CARD_STATE_HW_DISABLED ? "ON" : "OFF",
flags & IWM_CARD_STATE_CTKILL_DISABLED ? "ON" : "OFF");
- if (flags & IWM_CARD_STATE_HW_DISABLED)
- set_bit(IWM_RADIO_RFKILL_HW, &iwm->radio);
- else
- clear_bit(IWM_RADIO_RFKILL_HW, &iwm->radio);
+ wiphy_rfkill_set_hw_state(wiphy, flags & IWM_CARD_STATE_HW_DISABLED);
return 0;
}
@@ -1362,13 +1376,13 @@ static void iwm_rx_process_packet(struct iwm_priv *iwm,
skb->dev = iwm_to_ndev(iwm);
skb->protocol = eth_type_trans(skb, ndev);
- skb->ip_summed = CHECKSUM_UNNECESSARY;
+ skb->ip_summed = CHECKSUM_NONE;
memset(skb->cb, 0, sizeof(skb->cb));
ndev->stats.rx_packets++;
ndev->stats.rx_bytes += skb->len;
- if (netif_rx(skb) == NET_RX_DROP) {
+ if (netif_rx_ni(skb) == NET_RX_DROP) {
IWM_ERR(iwm, "Packet dropped\n");
ndev->stats.rx_dropped++;
}
diff --git a/drivers/net/wireless/iwmc3200wifi/sdio.c b/drivers/net/wireless/iwmc3200wifi/sdio.c
index 916681837fd..8b1de84003c 100644
--- a/drivers/net/wireless/iwmc3200wifi/sdio.c
+++ b/drivers/net/wireless/iwmc3200wifi/sdio.c
@@ -65,6 +65,7 @@
#include <linux/kernel.h>
#include <linux/netdevice.h>
#include <linux/debugfs.h>
+#include <linux/mmc/sdio_ids.h>
#include <linux/mmc/sdio.h>
#include <linux/mmc/sdio_func.h>
@@ -492,7 +493,8 @@ static void iwm_sdio_remove(struct sdio_func *func)
}
static const struct sdio_device_id iwm_sdio_ids[] = {
- { SDIO_DEVICE(SDIO_VENDOR_ID_INTEL, SDIO_DEVICE_ID_IWM) },
+ { SDIO_DEVICE(SDIO_VENDOR_ID_INTEL,
+ SDIO_DEVICE_ID_INTEL_IWMC3200WIFI) },
{ /* end: all zeroes */ },
};
MODULE_DEVICE_TABLE(sdio, iwm_sdio_ids);
@@ -506,11 +508,7 @@ static struct sdio_driver iwm_sdio_driver = {
static int __init iwm_sdio_init_module(void)
{
- int ret;
-
- ret = sdio_register_driver(&iwm_sdio_driver);
-
- return ret;
+ return sdio_register_driver(&iwm_sdio_driver);
}
static void __exit iwm_sdio_exit_module(void)
diff --git a/drivers/net/wireless/iwmc3200wifi/sdio.h b/drivers/net/wireless/iwmc3200wifi/sdio.h
index b3c156b08dd..aab6b6892e4 100644
--- a/drivers/net/wireless/iwmc3200wifi/sdio.h
+++ b/drivers/net/wireless/iwmc3200wifi/sdio.h
@@ -39,9 +39,6 @@
#ifndef __IWM_SDIO_H__
#define __IWM_SDIO_H__
-#define SDIO_VENDOR_ID_INTEL 0x89
-#define SDIO_DEVICE_ID_IWM 0x1403
-
#define IWM_SDIO_DATA_ADDR 0x0
#define IWM_SDIO_INTR_ENABLE_ADDR 0x14
#define IWM_SDIO_INTR_STATUS_ADDR 0x13
diff --git a/drivers/net/wireless/iwmc3200wifi/umac.h b/drivers/net/wireless/iwmc3200wifi/umac.h
index 4a95cce1f0a..c5a14ae3160 100644
--- a/drivers/net/wireless/iwmc3200wifi/umac.h
+++ b/drivers/net/wireless/iwmc3200wifi/umac.h
@@ -495,6 +495,8 @@ struct iwm_fw_alive_hdr {
#define WIFI_DBG_IF_NTFY_COEX_HANDLE_ENVELOP 0xE8
#define WIFI_DBG_IF_NTFY_COEX_HANDLE_RELEASE_ENVELOP 0xE9
+#define WIFI_IF_NTFY_MAX 0xff
+
/* Notification structures */
struct iwm_umac_notif_wifi_if {
struct iwm_umac_wifi_in_hdr hdr;
@@ -613,6 +615,7 @@ struct iwm_umac_notif_alive {
} __attribute__ ((packed));
struct iwm_umac_notif_init_complete {
+ struct iwm_umac_wifi_in_hdr hdr;
__le16 status;
__le16 reserved;
} __attribute__ ((packed));
@@ -641,6 +644,11 @@ struct iwm_fw_error_hdr {
__le32 umac_status;
__le32 lmac_status;
__le32 sdio_status;
+ __le32 dbm_sample_ctrl;
+ __le32 dbm_buf_base;
+ __le32 dbm_buf_end;
+ __le32 dbm_buf_write_ptr;
+ __le32 dbm_buf_cycle_cnt;
} __attribute__ ((packed));
struct iwm_umac_notif_error {
diff --git a/drivers/net/wireless/iwmc3200wifi/wext.c b/drivers/net/wireless/iwmc3200wifi/wext.c
deleted file mode 100644
index 584c94d0f39..00000000000
--- a/drivers/net/wireless/iwmc3200wifi/wext.c
+++ /dev/null
@@ -1,723 +0,0 @@
-/*
- * Intel Wireless Multicomm 3200 WiFi driver
- *
- * Copyright (C) 2009 Intel Corporation <ilw@linux.intel.com>
- * Samuel Ortiz <samuel.ortiz@intel.com>
- * Zhu Yi <yi.zhu@intel.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License version
- * 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/netdevice.h>
-#include <linux/wireless.h>
-#include <linux/if_arp.h>
-#include <linux/etherdevice.h>
-#include <net/cfg80211.h>
-#include <net/iw_handler.h>
-
-#include "iwm.h"
-#include "umac.h"
-#include "commands.h"
-#include "debug.h"
-
-static struct iw_statistics *iwm_get_wireless_stats(struct net_device *dev)
-{
- struct iwm_priv *iwm = ndev_to_iwm(dev);
- struct iw_statistics *wstats = &iwm->wstats;
-
- if (!test_bit(IWM_STATUS_ASSOCIATED, &iwm->status)) {
- memset(wstats, 0, sizeof(struct iw_statistics));
- wstats->qual.updated = IW_QUAL_ALL_INVALID;
- }
-
- return wstats;
-}
-
-static int iwm_wext_siwfreq(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_freq *freq, char *extra)
-{
- struct iwm_priv *iwm = ndev_to_iwm(dev);
-
- if (freq->flags == IW_FREQ_AUTO)
- return 0;
-
- /* frequency/channel can only be set in IBSS mode */
- if (iwm->conf.mode != UMAC_MODE_IBSS)
- return -EOPNOTSUPP;
-
- return cfg80211_ibss_wext_siwfreq(dev, info, freq, extra);
-}
-
-static int iwm_wext_giwfreq(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_freq *freq, char *extra)
-{
- struct iwm_priv *iwm = ndev_to_iwm(dev);
-
- if (iwm->conf.mode == UMAC_MODE_IBSS)
- return cfg80211_ibss_wext_giwfreq(dev, info, freq, extra);
-
- freq->e = 0;
- freq->m = iwm->channel;
-
- return 0;
-}
-
-static int iwm_wext_siwap(struct net_device *dev, struct iw_request_info *info,
- struct sockaddr *ap_addr, char *extra)
-{
- struct iwm_priv *iwm = ndev_to_iwm(dev);
-
- if (iwm->conf.mode == UMAC_MODE_IBSS)
- return cfg80211_ibss_wext_siwap(dev, info, ap_addr, extra);
-
- if (!test_bit(IWM_STATUS_READY, &iwm->status))
- return -EIO;
-
- if (is_zero_ether_addr(ap_addr->sa_data) ||
- is_broadcast_ether_addr(ap_addr->sa_data)) {
- IWM_DBG_WEXT(iwm, DBG, "clear mandatory bssid %pM\n",
- iwm->umac_profile->bssid[0]);
- memset(&iwm->umac_profile->bssid[0], 0, ETH_ALEN);
- iwm->umac_profile->bss_num = 0;
- } else {
- IWM_DBG_WEXT(iwm, DBG, "add mandatory bssid %pM\n",
- ap_addr->sa_data);
- memcpy(&iwm->umac_profile->bssid[0], ap_addr->sa_data,
- ETH_ALEN);
- iwm->umac_profile->bss_num = 1;
- }
-
- if (iwm->umac_profile_active) {
- if (!memcmp(&iwm->umac_profile->bssid[0], iwm->bssid, ETH_ALEN))
- return 0;
-
- iwm_invalidate_mlme_profile(iwm);
- }
-
- if (iwm->umac_profile->ssid.ssid_len)
- return iwm_send_mlme_profile(iwm);
-
- return 0;
-}
-
-static int iwm_wext_giwap(struct net_device *dev, struct iw_request_info *info,
- struct sockaddr *ap_addr, char *extra)
-{
- struct iwm_priv *iwm = ndev_to_iwm(dev);
-
- switch (iwm->conf.mode) {
- case UMAC_MODE_IBSS:
- return cfg80211_ibss_wext_giwap(dev, info, ap_addr, extra);
- case UMAC_MODE_BSS:
- if (test_bit(IWM_STATUS_ASSOCIATED, &iwm->status)) {
- ap_addr->sa_family = ARPHRD_ETHER;
- memcpy(&ap_addr->sa_data, iwm->bssid, ETH_ALEN);
- } else
- memset(&ap_addr->sa_data, 0, ETH_ALEN);
- break;
- default:
- return -EOPNOTSUPP;
- }
-
- return 0;
-}
-
-static int iwm_wext_siwessid(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_point *data, char *ssid)
-{
- struct iwm_priv *iwm = ndev_to_iwm(dev);
- size_t len = data->length;
- int ret;
-
- if (iwm->conf.mode == UMAC_MODE_IBSS)
- return cfg80211_ibss_wext_siwessid(dev, info, data, ssid);
-
- if (!test_bit(IWM_STATUS_READY, &iwm->status))
- return -EIO;
-
- if (len > 0 && ssid[len - 1] == '\0')
- len--;
-
- if (iwm->umac_profile_active) {
- if (iwm->umac_profile->ssid.ssid_len == len &&
- !memcmp(iwm->umac_profile->ssid.ssid, ssid, len))
- return 0;
-
- ret = iwm_invalidate_mlme_profile(iwm);
- if (ret < 0) {
- IWM_ERR(iwm, "Couldn't invalidate profile\n");
- return ret;
- }
- }
-
- iwm->umac_profile->ssid.ssid_len = len;
- memcpy(iwm->umac_profile->ssid.ssid, ssid, len);
-
- return iwm_send_mlme_profile(iwm);
-}
-
-static int iwm_wext_giwessid(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_point *data, char *ssid)
-{
- struct iwm_priv *iwm = ndev_to_iwm(dev);
-
- if (iwm->conf.mode == UMAC_MODE_IBSS)
- return cfg80211_ibss_wext_giwessid(dev, info, data, ssid);
-
- if (!test_bit(IWM_STATUS_READY, &iwm->status))
- return -EIO;
-
- data->length = iwm->umac_profile->ssid.ssid_len;
- if (data->length) {
- memcpy(ssid, iwm->umac_profile->ssid.ssid, data->length);
- data->flags = 1;
- } else
- data->flags = 0;
-
- return 0;
-}
-
-static struct iwm_key *
-iwm_key_init(struct iwm_priv *iwm, u8 key_idx, bool in_use,
- struct iw_encode_ext *ext, u8 alg)
-{
- struct iwm_key *key = &iwm->keys[key_idx];
-
- memset(key, 0, sizeof(struct iwm_key));
- memcpy(key->hdr.mac, ext->addr.sa_data, ETH_ALEN);
- key->hdr.key_idx = key_idx;
- if (is_broadcast_ether_addr(ext->addr.sa_data))
- key->hdr.multicast = 1;
-
- key->in_use = in_use;
- key->flags = ext->ext_flags;
- key->alg = alg;
- key->key_len = ext->key_len;
- memcpy(key->key, ext->key, ext->key_len);
-
- return key;
-}
-
-static int iwm_wext_giwrate(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_param *rate, char *extra)
-{
- struct iwm_priv *iwm = ndev_to_iwm(dev);
-
- rate->value = iwm->rate * 1000000;
-
- return 0;
-}
-
-static int iwm_wext_siwencode(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_point *erq, char *key_buf)
-{
- struct iwm_priv *iwm = ndev_to_iwm(dev);
- struct iwm_key *uninitialized_var(key);
- int idx, i, uninitialized_var(alg), remove = 0, ret;
-
- IWM_DBG_WEXT(iwm, DBG, "key len: %d\n", erq->length);
- IWM_DBG_WEXT(iwm, DBG, "flags: 0x%x\n", erq->flags);
-
- if (!iwm->umac_profile) {
- IWM_ERR(iwm, "UMAC profile not allocated yet\n");
- return -ENODEV;
- }
-
- if (erq->length == WLAN_KEY_LEN_WEP40) {
- alg = UMAC_CIPHER_TYPE_WEP_40;
- iwm->umac_profile->sec.ucast_cipher = UMAC_CIPHER_TYPE_WEP_40;
- iwm->umac_profile->sec.mcast_cipher = UMAC_CIPHER_TYPE_WEP_40;
- } else if (erq->length == WLAN_KEY_LEN_WEP104) {
- alg = UMAC_CIPHER_TYPE_WEP_104;
- iwm->umac_profile->sec.ucast_cipher = UMAC_CIPHER_TYPE_WEP_104;
- iwm->umac_profile->sec.mcast_cipher = UMAC_CIPHER_TYPE_WEP_104;
- }
-
- if (erq->flags & IW_ENCODE_RESTRICTED)
- iwm->umac_profile->sec.auth_type = UMAC_AUTH_TYPE_LEGACY_PSK;
- else
- iwm->umac_profile->sec.auth_type = UMAC_AUTH_TYPE_OPEN;
-
- idx = erq->flags & IW_ENCODE_INDEX;
- if (idx == 0) {
- if (iwm->default_key)
- for (i = 0; i < IWM_NUM_KEYS; i++) {
- if (iwm->default_key == &iwm->keys[i]) {
- idx = i;
- break;
- }
- }
- else
- iwm->default_key = &iwm->keys[idx];
- } else if (idx < 1 || idx > 4) {
- return -EINVAL;
- } else
- idx--;
-
- if (erq->flags & IW_ENCODE_DISABLED)
- remove = 1;
- else if (erq->length == 0) {
- if (!iwm->keys[idx].in_use)
- return -EINVAL;
- iwm->default_key = &iwm->keys[idx];
- }
-
- if (erq->length) {
- key = &iwm->keys[idx];
- memset(key, 0, sizeof(struct iwm_key));
- memset(key->hdr.mac, 0xff, ETH_ALEN);
- key->hdr.key_idx = idx;
- key->hdr.multicast = 1;
- key->in_use = !remove;
- key->alg = alg;
- key->key_len = erq->length;
- memcpy(key->key, key_buf, erq->length);
-
- IWM_DBG_WEXT(iwm, DBG, "Setting key %d, default: %d\n",
- idx, !!iwm->default_key);
- }
-
- if (remove) {
- if ((erq->flags & IW_ENCODE_NOKEY) || (erq->length == 0)) {
- int j;
- for (j = 0; j < IWM_NUM_KEYS; j++)
- if (iwm->keys[j].in_use) {
- struct iwm_key *k = &iwm->keys[j];
-
- k->in_use = 0;
- ret = iwm_set_key(iwm, remove, 0, k);
- if (ret < 0)
- return ret;
- }
-
- iwm->umac_profile->sec.ucast_cipher =
- UMAC_CIPHER_TYPE_NONE;
- iwm->umac_profile->sec.mcast_cipher =
- UMAC_CIPHER_TYPE_NONE;
- iwm->umac_profile->sec.auth_type =
- UMAC_AUTH_TYPE_OPEN;
-
- return 0;
- } else {
- key->in_use = 0;
- return iwm_set_key(iwm, remove, 0, key);
- }
- }
-
- /*
- * If we havent set a profile yet, we cant set keys.
- * Keys will be pushed after we're associated.
- */
- if (!iwm->umac_profile_active)
- return 0;
-
- /*
- * If there is a current active profile, but no
- * default key, it's not worth trying to associate again.
- */
- if (!iwm->default_key)
- return 0;
-
- /*
- * Here we have an active profile, but a key setting changed.
- * We thus have to invalidate the current profile, and push the
- * new one. Keys will be pushed when association takes place.
- */
- ret = iwm_invalidate_mlme_profile(iwm);
- if (ret < 0) {
- IWM_ERR(iwm, "Couldn't invalidate profile\n");
- return ret;
- }
-
- return iwm_send_mlme_profile(iwm);
-}
-
-static int iwm_wext_giwencode(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_point *erq, char *key)
-{
- struct iwm_priv *iwm = ndev_to_iwm(dev);
- int idx, i;
-
- idx = erq->flags & IW_ENCODE_INDEX;
- if (idx < 1 || idx > 4) {
- idx = -1;
- if (!iwm->default_key) {
- erq->length = 0;
- erq->flags |= IW_ENCODE_NOKEY;
- return 0;
- } else
- for (i = 0; i < IWM_NUM_KEYS; i++) {
- if (iwm->default_key == &iwm->keys[i]) {
- idx = i;
- break;
- }
- }
- if (idx < 0)
- return -EINVAL;
- } else
- idx--;
-
- erq->flags = idx + 1;
-
- if (!iwm->keys[idx].in_use) {
- erq->length = 0;
- erq->flags |= IW_ENCODE_DISABLED;
- return 0;
- }
-
- memcpy(key, iwm->keys[idx].key,
- min_t(int, erq->length, iwm->keys[idx].key_len));
- erq->length = iwm->keys[idx].key_len;
- erq->flags |= IW_ENCODE_ENABLED;
-
- if (iwm->umac_profile->mode == UMAC_MODE_BSS) {
- switch (iwm->umac_profile->sec.auth_type) {
- case UMAC_AUTH_TYPE_OPEN:
- erq->flags |= IW_ENCODE_OPEN;
- break;
- default:
- erq->flags |= IW_ENCODE_RESTRICTED;
- break;
- }
- }
-
- return 0;
-}
-
-static int iwm_set_wpa_version(struct iwm_priv *iwm, u8 wpa_version)
-{
- if (wpa_version & IW_AUTH_WPA_VERSION_WPA2)
- iwm->umac_profile->sec.flags = UMAC_SEC_FLG_RSNA_ON_MSK;
- else if (wpa_version & IW_AUTH_WPA_VERSION_WPA)
- iwm->umac_profile->sec.flags = UMAC_SEC_FLG_WPA_ON_MSK;
- else
- iwm->umac_profile->sec.flags = UMAC_SEC_FLG_LEGACY_PROFILE;
-
- return 0;
-}
-
-static int iwm_wext_siwpower(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_param *wrq, char *extra)
-{
- struct iwm_priv *iwm = ndev_to_iwm(dev);
- u32 power_index;
-
- if (wrq->disabled) {
- power_index = IWM_POWER_INDEX_MIN;
- goto set;
- } else
- power_index = IWM_POWER_INDEX_DEFAULT;
-
- switch (wrq->flags & IW_POWER_MODE) {
- case IW_POWER_ON:
- case IW_POWER_MODE:
- case IW_POWER_ALL_R:
- break;
- default:
- return -EINVAL;
- }
-
- set:
- if (power_index == iwm->conf.power_index)
- return 0;
-
- iwm->conf.power_index = power_index;
-
- return iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX,
- CFG_POWER_INDEX, iwm->conf.power_index);
-}
-
-static int iwm_wext_giwpower(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- struct iwm_priv *iwm = ndev_to_iwm(dev);
-
- wrqu->power.disabled = (iwm->conf.power_index == IWM_POWER_INDEX_MIN);
-
- return 0;
-}
-
-static int iwm_set_key_mgt(struct iwm_priv *iwm, u8 key_mgt)
-{
- u8 *auth_type = &iwm->umac_profile->sec.auth_type;
-
- if (key_mgt == IW_AUTH_KEY_MGMT_802_1X)
- *auth_type = UMAC_AUTH_TYPE_8021X;
- else if (key_mgt == IW_AUTH_KEY_MGMT_PSK) {
- if (iwm->umac_profile->sec.flags &
- (UMAC_SEC_FLG_WPA_ON_MSK | UMAC_SEC_FLG_RSNA_ON_MSK))
- *auth_type = UMAC_AUTH_TYPE_RSNA_PSK;
- else
- *auth_type = UMAC_AUTH_TYPE_LEGACY_PSK;
- } else {
- IWM_ERR(iwm, "Invalid key mgt: 0x%x\n", key_mgt);
- return -EINVAL;
- }
-
- return 0;
-}
-
-static int iwm_set_cipher(struct iwm_priv *iwm, u8 cipher, u8 ucast)
-{
- u8 *profile_cipher = ucast ? &iwm->umac_profile->sec.ucast_cipher :
- &iwm->umac_profile->sec.mcast_cipher;
-
- switch (cipher) {
- case IW_AUTH_CIPHER_NONE:
- *profile_cipher = UMAC_CIPHER_TYPE_NONE;
- break;
- case IW_AUTH_CIPHER_WEP40:
- *profile_cipher = UMAC_CIPHER_TYPE_WEP_40;
- break;
- case IW_AUTH_CIPHER_TKIP:
- *profile_cipher = UMAC_CIPHER_TYPE_TKIP;
- break;
- case IW_AUTH_CIPHER_CCMP:
- *profile_cipher = UMAC_CIPHER_TYPE_CCMP;
- break;
- case IW_AUTH_CIPHER_WEP104:
- *profile_cipher = UMAC_CIPHER_TYPE_WEP_104;
- break;
- default:
- IWM_ERR(iwm, "Unsupported cipher: 0x%x\n", cipher);
- return -ENOTSUPP;
- }
-
- return 0;
-}
-
-static int iwm_set_auth_alg(struct iwm_priv *iwm, u8 auth_alg)
-{
- u8 *auth_type = &iwm->umac_profile->sec.auth_type;
-
- switch (auth_alg) {
- case IW_AUTH_ALG_OPEN_SYSTEM:
- *auth_type = UMAC_AUTH_TYPE_OPEN;
- break;
- case IW_AUTH_ALG_SHARED_KEY:
- if (iwm->umac_profile->sec.flags &
- (UMAC_SEC_FLG_WPA_ON_MSK | UMAC_SEC_FLG_RSNA_ON_MSK)) {
- if (*auth_type == UMAC_AUTH_TYPE_8021X)
- return -EINVAL;
- *auth_type = UMAC_AUTH_TYPE_RSNA_PSK;
- } else {
- *auth_type = UMAC_AUTH_TYPE_LEGACY_PSK;
- }
- break;
- case IW_AUTH_ALG_LEAP:
- default:
- IWM_ERR(iwm, "Unsupported auth alg: 0x%x\n", auth_alg);
- return -ENOTSUPP;
- }
-
- return 0;
-}
-
-static int iwm_wext_siwauth(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_param *data, char *extra)
-{
- struct iwm_priv *iwm = ndev_to_iwm(dev);
- int ret;
-
- if ((data->flags) &
- (IW_AUTH_WPA_VERSION | IW_AUTH_KEY_MGMT |
- IW_AUTH_WPA_ENABLED | IW_AUTH_80211_AUTH_ALG)) {
- /* We need to invalidate the current profile */
- if (iwm->umac_profile_active) {
- ret = iwm_invalidate_mlme_profile(iwm);
- if (ret < 0) {
- IWM_ERR(iwm, "Couldn't invalidate profile\n");
- return ret;
- }
- }
- }
-
- switch (data->flags & IW_AUTH_INDEX) {
- case IW_AUTH_WPA_VERSION:
- return iwm_set_wpa_version(iwm, data->value);
- break;
- case IW_AUTH_CIPHER_PAIRWISE:
- return iwm_set_cipher(iwm, data->value, 1);
- break;
- case IW_AUTH_CIPHER_GROUP:
- return iwm_set_cipher(iwm, data->value, 0);
- break;
- case IW_AUTH_KEY_MGMT:
- return iwm_set_key_mgt(iwm, data->value);
- break;
- case IW_AUTH_80211_AUTH_ALG:
- return iwm_set_auth_alg(iwm, data->value);
- break;
- default:
- return -ENOTSUPP;
- }
-
- return 0;
-}
-
-static int iwm_wext_giwauth(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_param *data, char *extra)
-{
- return 0;
-}
-
-static int iwm_wext_siwencodeext(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_point *erq, char *extra)
-{
- struct iwm_priv *iwm = ndev_to_iwm(dev);
- struct iwm_key *key;
- struct iw_encode_ext *ext = (struct iw_encode_ext *) extra;
- int uninitialized_var(alg), idx, i, remove = 0;
-
- IWM_DBG_WEXT(iwm, DBG, "alg: 0x%x\n", ext->alg);
- IWM_DBG_WEXT(iwm, DBG, "key len: %d\n", ext->key_len);
- IWM_DBG_WEXT(iwm, DBG, "ext_flags: 0x%x\n", ext->ext_flags);
- IWM_DBG_WEXT(iwm, DBG, "flags: 0x%x\n", erq->flags);
- IWM_DBG_WEXT(iwm, DBG, "length: 0x%x\n", erq->length);
-
- switch (ext->alg) {
- case IW_ENCODE_ALG_NONE:
- remove = 1;
- break;
- case IW_ENCODE_ALG_WEP:
- if (ext->key_len == WLAN_KEY_LEN_WEP40)
- alg = UMAC_CIPHER_TYPE_WEP_40;
- else if (ext->key_len == WLAN_KEY_LEN_WEP104)
- alg = UMAC_CIPHER_TYPE_WEP_104;
- else {
- IWM_ERR(iwm, "Invalid key length: %d\n", ext->key_len);
- return -EINVAL;
- }
-
- break;
- case IW_ENCODE_ALG_TKIP:
- alg = UMAC_CIPHER_TYPE_TKIP;
- break;
- case IW_ENCODE_ALG_CCMP:
- alg = UMAC_CIPHER_TYPE_CCMP;
- break;
- default:
- return -EOPNOTSUPP;
- }
-
- idx = erq->flags & IW_ENCODE_INDEX;
-
- if (idx == 0) {
- if (iwm->default_key)
- for (i = 0; i < IWM_NUM_KEYS; i++) {
- if (iwm->default_key == &iwm->keys[i]) {
- idx = i;
- break;
- }
- }
- } else if (idx < 1 || idx > 4) {
- return -EINVAL;
- } else
- idx--;
-
- if (erq->flags & IW_ENCODE_DISABLED)
- remove = 1;
- else if ((erq->length == 0) ||
- (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)) {
- iwm->default_key = &iwm->keys[idx];
- if (iwm->umac_profile_active && ext->alg == IW_ENCODE_ALG_WEP)
- return iwm_set_tx_key(iwm, idx);
- }
-
- key = iwm_key_init(iwm, idx, !remove, ext, alg);
-
- return iwm_set_key(iwm, remove, !iwm->default_key, key);
-}
-
-static const iw_handler iwm_handlers[] =
-{
- (iw_handler) NULL, /* SIOCSIWCOMMIT */
- (iw_handler) cfg80211_wext_giwname, /* SIOCGIWNAME */
- (iw_handler) NULL, /* SIOCSIWNWID */
- (iw_handler) NULL, /* SIOCGIWNWID */
- (iw_handler) iwm_wext_siwfreq, /* SIOCSIWFREQ */
- (iw_handler) iwm_wext_giwfreq, /* SIOCGIWFREQ */
- (iw_handler) cfg80211_wext_siwmode, /* SIOCSIWMODE */
- (iw_handler) cfg80211_wext_giwmode, /* SIOCGIWMODE */
- (iw_handler) NULL, /* SIOCSIWSENS */
- (iw_handler) NULL, /* SIOCGIWSENS */
- (iw_handler) NULL /* not used */, /* SIOCSIWRANGE */
- (iw_handler) cfg80211_wext_giwrange, /* SIOCGIWRANGE */
- (iw_handler) NULL /* not used */, /* SIOCSIWPRIV */
- (iw_handler) NULL /* kernel code */, /* SIOCGIWPRIV */
- (iw_handler) NULL /* not used */, /* SIOCSIWSTATS */
- (iw_handler) NULL /* kernel code */, /* SIOCGIWSTATS */
- (iw_handler) NULL, /* SIOCSIWSPY */
- (iw_handler) NULL, /* SIOCGIWSPY */
- (iw_handler) NULL, /* SIOCSIWTHRSPY */
- (iw_handler) NULL, /* SIOCGIWTHRSPY */
- (iw_handler) iwm_wext_siwap, /* SIOCSIWAP */
- (iw_handler) iwm_wext_giwap, /* SIOCGIWAP */
- (iw_handler) NULL, /* SIOCSIWMLME */
- (iw_handler) NULL, /* SIOCGIWAPLIST */
- (iw_handler) cfg80211_wext_siwscan, /* SIOCSIWSCAN */
- (iw_handler) cfg80211_wext_giwscan, /* SIOCGIWSCAN */
- (iw_handler) iwm_wext_siwessid, /* SIOCSIWESSID */
- (iw_handler) iwm_wext_giwessid, /* SIOCGIWESSID */
- (iw_handler) NULL, /* SIOCSIWNICKN */
- (iw_handler) NULL, /* SIOCGIWNICKN */
- (iw_handler) NULL, /* -- hole -- */
- (iw_handler) NULL, /* -- hole -- */
- (iw_handler) NULL, /* SIOCSIWRATE */
- (iw_handler) iwm_wext_giwrate, /* SIOCGIWRATE */
- (iw_handler) cfg80211_wext_siwrts, /* SIOCSIWRTS */
- (iw_handler) cfg80211_wext_giwrts, /* SIOCGIWRTS */
- (iw_handler) cfg80211_wext_siwfrag, /* SIOCSIWFRAG */
- (iw_handler) cfg80211_wext_giwfrag, /* SIOCGIWFRAG */
- (iw_handler) NULL, /* SIOCSIWTXPOW */
- (iw_handler) NULL, /* SIOCGIWTXPOW */
- (iw_handler) NULL, /* SIOCSIWRETRY */
- (iw_handler) NULL, /* SIOCGIWRETRY */
- (iw_handler) iwm_wext_siwencode, /* SIOCSIWENCODE */
- (iw_handler) iwm_wext_giwencode, /* SIOCGIWENCODE */
- (iw_handler) iwm_wext_siwpower, /* SIOCSIWPOWER */
- (iw_handler) iwm_wext_giwpower, /* SIOCGIWPOWER */
- (iw_handler) NULL, /* -- hole -- */
- (iw_handler) NULL, /* -- hole -- */
- (iw_handler) NULL, /* SIOCSIWGENIE */
- (iw_handler) NULL, /* SIOCGIWGENIE */
- (iw_handler) iwm_wext_siwauth, /* SIOCSIWAUTH */
- (iw_handler) iwm_wext_giwauth, /* SIOCGIWAUTH */
- (iw_handler) iwm_wext_siwencodeext, /* SIOCSIWENCODEEXT */
- (iw_handler) NULL, /* SIOCGIWENCODEEXT */
- (iw_handler) NULL, /* SIOCSIWPMKSA */
- (iw_handler) NULL, /* -- hole -- */
-};
-
-const struct iw_handler_def iwm_iw_handler_def = {
- .num_standard = ARRAY_SIZE(iwm_handlers),
- .standard = (iw_handler *) iwm_handlers,
- .get_wireless_stats = iwm_get_wireless_stats,
-};
-
diff --git a/drivers/net/wireless/libertas/assoc.c b/drivers/net/wireless/libertas/assoc.c
index b9b37411903..385b50f4b10 100644
--- a/drivers/net/wireless/libertas/assoc.c
+++ b/drivers/net/wireless/libertas/assoc.c
@@ -129,7 +129,6 @@ static int lbs_set_authentication(struct lbs_private *priv, u8 bssid[6], u8 auth
{
struct cmd_ds_802_11_authenticate cmd;
int ret = -1;
- DECLARE_MAC_BUF(mac);
lbs_deb_enter(LBS_DEB_JOIN);
@@ -138,8 +137,7 @@ static int lbs_set_authentication(struct lbs_private *priv, u8 bssid[6], u8 auth
cmd.authtype = iw_auth_to_ieee_auth(auth);
- lbs_deb_join("AUTH_CMD: BSSID %s, auth 0x%x\n",
- print_mac(mac, bssid), cmd.authtype);
+ lbs_deb_join("AUTH_CMD: BSSID %pM, auth 0x%x\n", bssid, cmd.authtype);
ret = lbs_cmd_with_response(priv, CMD_802_11_AUTHENTICATE, &cmd);
@@ -342,8 +340,6 @@ static int lbs_associate(struct lbs_private *priv,
/* Firmware v9+ indicate authentication suites as a TLV */
if (priv->fwrelease >= 0x09000000) {
- DECLARE_MAC_BUF(mac);
-
auth = (struct mrvl_ie_auth_type *) pos;
auth->header.type = cpu_to_le16(TLV_TYPE_AUTH_TYPE);
auth->header.len = cpu_to_le16(2);
@@ -351,8 +347,8 @@ static int lbs_associate(struct lbs_private *priv,
auth->auth = cpu_to_le16(tmpauth);
pos += sizeof(auth->header) + 2;
- lbs_deb_join("AUTH_CMD: BSSID %s, auth 0x%x\n",
- print_mac(mac, bss->bssid), priv->secinfo.auth_mode);
+ lbs_deb_join("AUTH_CMD: BSSID %pM, auth 0x%x\n",
+ bss->bssid, priv->secinfo.auth_mode);
}
/* WPA/WPA2 IEs */
@@ -1368,11 +1364,17 @@ static int assoc_helper_wpa_keys(struct lbs_private *priv,
if (ret)
goto out;
+ memcpy(&priv->wpa_unicast_key, &assoc_req->wpa_unicast_key,
+ sizeof(struct enc_key));
+
if (test_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags)) {
clear_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags);
ret = lbs_cmd_802_11_key_material(priv, CMD_ACT_SET, assoc_req);
assoc_req->flags = flags;
+
+ memcpy(&priv->wpa_mcast_key, &assoc_req->wpa_mcast_key,
+ sizeof(struct enc_key));
}
out:
diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h
index f9ec69e0473..578c6978358 100644
--- a/drivers/net/wireless/libertas/dev.h
+++ b/drivers/net/wireless/libertas/dev.h
@@ -260,7 +260,6 @@ struct lbs_private {
u16 psmode; /* Wlan802_11PowermodeCAM=disable
Wlan802_11PowermodeMAX_PSP=enable */
u32 psstate;
- char ps_supported;
u8 needtowakeup;
struct assoc_request * pending_assoc_req;
diff --git a/drivers/net/wireless/libertas/if_cs.c b/drivers/net/wireless/libertas/if_cs.c
index 2a5b083bf9b..f658fd6a2c0 100644
--- a/drivers/net/wireless/libertas/if_cs.c
+++ b/drivers/net/wireless/libertas/if_cs.c
@@ -933,9 +933,6 @@ static int if_cs_probe(struct pcmcia_device *p_dev)
goto out3;
}
- /* The firmware for the CF card supports powersave */
- priv->ps_supported = 1;
-
ret = 0;
goto out;
diff --git a/drivers/net/wireless/libertas/if_sdio.c b/drivers/net/wireless/libertas/if_sdio.c
index 8cdb88c6ca2..485a8d40652 100644
--- a/drivers/net/wireless/libertas/if_sdio.c
+++ b/drivers/net/wireless/libertas/if_sdio.c
@@ -1039,9 +1039,6 @@ static int if_sdio_probe(struct sdio_func *func,
if (ret)
goto err_activate_card;
- if (priv->fwcapinfo & FW_CAPINFO_PS)
- priv->ps_supported = 1;
-
out:
lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret);
@@ -1096,11 +1093,11 @@ static void if_sdio_remove(struct sdio_func *func)
lbs_pr_alert("CMD_FUNC_SHUTDOWN cmd failed\n");
}
- card->priv->surpriseremoved = 1;
lbs_deb_sdio("call remove card\n");
lbs_stop_card(card->priv);
lbs_remove_card(card->priv);
+ card->priv->surpriseremoved = 1;
flush_workqueue(card->workqueue);
destroy_workqueue(card->workqueue);
diff --git a/drivers/net/wireless/libertas/if_spi.c b/drivers/net/wireless/libertas/if_spi.c
index 6564282ce47..446e327180f 100644
--- a/drivers/net/wireless/libertas/if_spi.c
+++ b/drivers/net/wireless/libertas/if_spi.c
@@ -376,7 +376,7 @@ static int spu_set_bus_mode(struct if_spi_card *card, u16 mode)
err = spu_read_u16(card, IF_SPI_SPU_BUS_MODE_REG, &rval);
if (err)
return err;
- if (rval != mode) {
+ if ((rval & 0xF) != mode) {
lbs_pr_err("Can't read bus mode register.\n");
return -EIO;
}
@@ -737,7 +737,7 @@ static int if_spi_c2h_data(struct if_spi_card *card)
goto out;
} else if (len > MRVDRV_ETH_RX_PACKET_BUFFER_SIZE) {
lbs_pr_err("%s: error: card has %d bytes of data, but "
- "our maximum skb size is %lu\n",
+ "our maximum skb size is %zu\n",
__func__, len, MRVDRV_ETH_RX_PACKET_BUFFER_SIZE);
err = -EINVAL;
goto out;
@@ -1118,7 +1118,6 @@ static int __devinit if_spi_probe(struct spi_device *spi)
priv->card = card;
priv->hw_host_to_card = if_spi_host_to_card;
priv->fw_ready = 1;
- priv->ps_supported = 1;
/* Initialize interrupt handling stuff. */
card->run_thread = 1;
@@ -1171,12 +1170,13 @@ static int __devexit libertas_spi_remove(struct spi_device *spi)
lbs_deb_spi("libertas_spi_remove\n");
lbs_deb_enter(LBS_DEB_SPI);
- priv->surpriseremoved = 1;
lbs_stop_card(priv);
+ lbs_remove_card(priv); /* will call free_netdev */
+
+ priv->surpriseremoved = 1;
free_irq(spi->irq, card);
if_spi_terminate_spi_thread(card);
- lbs_remove_card(priv); /* will call free_netdev */
if (card->pdata->teardown)
card->pdata->teardown(spi);
free_if_spi_card(card);
diff --git a/drivers/net/wireless/libertas/if_usb.c b/drivers/net/wireless/libertas/if_usb.c
index 1844c5adf6e..92bc8c5f1ca 100644
--- a/drivers/net/wireless/libertas/if_usb.c
+++ b/drivers/net/wireless/libertas/if_usb.c
@@ -181,13 +181,14 @@ static void if_usb_setup_firmware(struct lbs_private *priv)
wake_method.action = cpu_to_le16(CMD_ACT_GET);
if (lbs_cmd_with_response(priv, CMD_802_11_FW_WAKE_METHOD, &wake_method)) {
lbs_pr_info("Firmware does not seem to support PS mode\n");
+ priv->fwcapinfo &= ~FW_CAPINFO_PS;
} else {
if (le16_to_cpu(wake_method.method) == CMD_WAKE_METHOD_COMMAND_INT) {
lbs_deb_usb("Firmware seems to support PS with wake-via-command\n");
- priv->ps_supported = 1;
} else {
/* The versions which boot up this way don't seem to
work even if we set it to the command interrupt */
+ priv->fwcapinfo &= ~FW_CAPINFO_PS;
lbs_pr_info("Firmware doesn't wake via command interrupt; disabling PS mode\n");
}
}
diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c
index 89575e44801..8df1cfd5f93 100644
--- a/drivers/net/wireless/libertas/main.c
+++ b/drivers/net/wireless/libertas/main.c
@@ -1176,7 +1176,7 @@ struct lbs_private *lbs_add_card(void *card, struct device *dmdev)
/* Allocate an Ethernet device and register it */
dev = alloc_etherdev(sizeof(struct lbs_private));
if (!dev) {
- lbs_pr_err("init ethX device failed\n");
+ lbs_pr_err("init wlanX device failed\n");
goto done;
}
priv = netdev_priv(dev);
@@ -1204,6 +1204,7 @@ struct lbs_private *lbs_add_card(void *card, struct device *dmdev)
SET_NETDEV_DEV(dev, dmdev);
priv->rtap_net_dev = NULL;
+ strcpy(dev->name, "wlan%d");
lbs_deb_thread("Starting main thread...\n");
init_waitqueue_head(&priv->waitq);
diff --git a/drivers/net/wireless/libertas/wext.c b/drivers/net/wireless/libertas/wext.c
index 8bc1907458b..be837a0d251 100644
--- a/drivers/net/wireless/libertas/wext.c
+++ b/drivers/net/wireless/libertas/wext.c
@@ -712,7 +712,7 @@ static int lbs_set_power(struct net_device *dev, struct iw_request_info *info,
lbs_deb_enter(LBS_DEB_WEXT);
- if (!priv->ps_supported) {
+ if (!(priv->fwcapinfo & FW_CAPINFO_PS)) {
if (vwrq->disabled)
return 0;
else
@@ -1728,6 +1728,8 @@ static int lbs_set_auth(struct net_device *dev,
}
switch (dwrq->flags & IW_AUTH_INDEX) {
+ case IW_AUTH_PRIVACY_INVOKED:
+ case IW_AUTH_RX_UNENCRYPTED_EAPOL:
case IW_AUTH_TKIP_COUNTERMEASURES:
case IW_AUTH_CIPHER_PAIRWISE:
case IW_AUTH_CIPHER_GROUP:
diff --git a/drivers/net/wireless/libertas_tf/main.c b/drivers/net/wireless/libertas_tf/main.c
index 10a99e26d39..4872345a2f6 100644
--- a/drivers/net/wireless/libertas_tf/main.c
+++ b/drivers/net/wireless/libertas_tf/main.c
@@ -503,7 +503,8 @@ int lbtf_rx(struct lbtf_private *priv, struct sk_buff *skb)
skb_reserve(skb, 2);
}
- ieee80211_rx_irqsafe(priv->hw, skb, &stats);
+ memcpy(IEEE80211_SKB_RXCB(skb), &stats, sizeof(stats));
+ ieee80211_rx_irqsafe(priv->hw, skb);
return 0;
}
EXPORT_SYMBOL_GPL(lbtf_rx);
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
index 7916ca3f84c..930f5c7da4a 100644
--- a/drivers/net/wireless/mac80211_hwsim.c
+++ b/drivers/net/wireless/mac80211_hwsim.c
@@ -15,6 +15,8 @@
#include <linux/list.h>
#include <linux/spinlock.h>
+#include <net/dst.h>
+#include <net/xfrm.h>
#include <net/mac80211.h>
#include <net/ieee80211_radiotap.h>
#include <linux/if_arp.h>
@@ -314,7 +316,7 @@ static int hwsim_mon_xmit(struct sk_buff *skb, struct net_device *dev)
{
/* TODO: allow packet injection */
dev_kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
}
@@ -404,11 +406,19 @@ static bool mac80211_hwsim_tx_frame(struct ieee80211_hw *hw,
rx_status.freq = data->channel->center_freq;
rx_status.band = data->channel->band;
rx_status.rate_idx = info->control.rates[0].idx;
- /* TODO: simulate signal strength (and optional packet drop) */
+ /* TODO: simulate real signal strength (and optional packet loss) */
+ rx_status.signal = -50;
if (data->ps != PS_DISABLED)
hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM);
+ /* release the skb's source info */
+ skb_orphan(skb);
+ skb_dst_drop(skb);
+ skb->mark = 0;
+ secpath_reset(skb);
+ nf_reset(skb);
+
/* Copy skb to all enabled radios that are on the current frequency */
spin_lock(&hwsim_radio_lock);
list_for_each_entry(data2, &hwsim_radios, list) {
@@ -430,7 +440,8 @@ static bool mac80211_hwsim_tx_frame(struct ieee80211_hw *hw,
if (memcmp(hdr->addr1, data2->hw->wiphy->perm_addr,
ETH_ALEN) == 0)
ack = true;
- ieee80211_rx_irqsafe(data2->hw, nskb, &rx_status);
+ memcpy(IEEE80211_SKB_RXCB(nskb), &rx_status, sizeof(rx_status));
+ ieee80211_rx_irqsafe(data2->hw, nskb);
}
spin_unlock(&hwsim_radio_lock);
@@ -690,6 +701,74 @@ static int mac80211_hwsim_conf_tx(
return 0;
}
+#ifdef CONFIG_NL80211_TESTMODE
+/*
+ * This section contains example code for using netlink
+ * attributes with the testmode command in nl80211.
+ */
+
+/* These enums need to be kept in sync with userspace */
+enum hwsim_testmode_attr {
+ __HWSIM_TM_ATTR_INVALID = 0,
+ HWSIM_TM_ATTR_CMD = 1,
+ HWSIM_TM_ATTR_PS = 2,
+
+ /* keep last */
+ __HWSIM_TM_ATTR_AFTER_LAST,
+ HWSIM_TM_ATTR_MAX = __HWSIM_TM_ATTR_AFTER_LAST - 1
+};
+
+enum hwsim_testmode_cmd {
+ HWSIM_TM_CMD_SET_PS = 0,
+ HWSIM_TM_CMD_GET_PS = 1,
+};
+
+static const struct nla_policy hwsim_testmode_policy[HWSIM_TM_ATTR_MAX + 1] = {
+ [HWSIM_TM_ATTR_CMD] = { .type = NLA_U32 },
+ [HWSIM_TM_ATTR_PS] = { .type = NLA_U32 },
+};
+
+static int hwsim_fops_ps_write(void *dat, u64 val);
+
+static int mac80211_hwsim_testmode_cmd(struct ieee80211_hw *hw,
+ void *data, int len)
+{
+ struct mac80211_hwsim_data *hwsim = hw->priv;
+ struct nlattr *tb[HWSIM_TM_ATTR_MAX + 1];
+ struct sk_buff *skb;
+ int err, ps;
+
+ err = nla_parse(tb, HWSIM_TM_ATTR_MAX, data, len,
+ hwsim_testmode_policy);
+ if (err)
+ return err;
+
+ if (!tb[HWSIM_TM_ATTR_CMD])
+ return -EINVAL;
+
+ switch (nla_get_u32(tb[HWSIM_TM_ATTR_CMD])) {
+ case HWSIM_TM_CMD_SET_PS:
+ if (!tb[HWSIM_TM_ATTR_PS])
+ return -EINVAL;
+ ps = nla_get_u32(tb[HWSIM_TM_ATTR_PS]);
+ return hwsim_fops_ps_write(hwsim, ps);
+ case HWSIM_TM_CMD_GET_PS:
+ skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy,
+ nla_total_size(sizeof(u32)));
+ if (!skb)
+ return -ENOMEM;
+ NLA_PUT_U32(skb, HWSIM_TM_ATTR_PS, hwsim->ps);
+ return cfg80211_testmode_reply(skb);
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ nla_put_failure:
+ kfree_skb(skb);
+ return -ENOBUFS;
+}
+#endif
+
static const struct ieee80211_ops mac80211_hwsim_ops =
{
.tx = mac80211_hwsim_tx,
@@ -703,6 +782,7 @@ static const struct ieee80211_ops mac80211_hwsim_ops =
.sta_notify = mac80211_hwsim_sta_notify,
.set_tim = mac80211_hwsim_set_tim,
.conf_tx = mac80211_hwsim_conf_tx,
+ CFG80211_TESTMODE_CMD(mac80211_hwsim_testmode_cmd)
};
@@ -757,7 +837,6 @@ static void hwsim_send_ps_poll(void *dat, u8 *mac, struct ieee80211_vif *vif)
{
struct mac80211_hwsim_data *data = dat;
struct hwsim_vif_priv *vp = (void *)vif->drv_priv;
- DECLARE_MAC_BUF(buf);
struct sk_buff *skb;
struct ieee80211_pspoll *pspoll;
@@ -787,7 +866,6 @@ static void hwsim_send_nullfunc(struct mac80211_hwsim_data *data, u8 *mac,
struct ieee80211_vif *vif, int ps)
{
struct hwsim_vif_priv *vp = (void *)vif->drv_priv;
- DECLARE_MAC_BUF(buf);
struct sk_buff *skb;
struct ieee80211_hdr *hdr;
@@ -945,7 +1023,8 @@ static int __init init_mac80211_hwsim(void)
BIT(NL80211_IFTYPE_AP) |
BIT(NL80211_IFTYPE_MESH_POINT);
- hw->flags = IEEE80211_HW_MFP_CAPABLE;
+ hw->flags = IEEE80211_HW_MFP_CAPABLE |
+ IEEE80211_HW_SIGNAL_DBM;
/* ask mac80211 to reserve space for magic */
hw->vif_data_size = sizeof(struct hwsim_vif_priv);
diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c
index 83967afe082..8a6d3afe412 100644
--- a/drivers/net/wireless/mwl8k.c
+++ b/drivers/net/wireless/mwl8k.c
@@ -1049,7 +1049,8 @@ static int rxq_process(struct ieee80211_hw *hw, int index, int limit)
status.flag = 0;
status.band = IEEE80211_BAND_2GHZ;
status.freq = ieee80211_channel_to_frequency(rx_desc->channel);
- ieee80211_rx_irqsafe(hw, skb, &status);
+ memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status));
+ ieee80211_rx_irqsafe(hw, skb);
processed++;
}
@@ -2273,7 +2274,6 @@ static int mwl8k_cmd_update_sta_db(struct ieee80211_hw *hw,
struct mwl8k_cmd_update_sta_db *cmd;
struct peer_capability_info *peer_info;
struct ieee80211_rate *bitrates = mv_vif->legacy_rates;
- DECLARE_MAC_BUF(mac);
int rc;
__u8 count, *rates;
@@ -3486,7 +3486,6 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev,
{
struct ieee80211_hw *hw;
struct mwl8k_priv *priv;
- DECLARE_MAC_BUF(mac);
int rc;
int i;
u8 *fw;
@@ -3675,8 +3674,8 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev,
MWL8K_DESC);
printk(KERN_INFO "%s: Driver Ver:%s Firmware Ver:%u.%u.%u.%u\n",
priv->name, MWL8K_VERSION, fw[3], fw[2], fw[1], fw[0]);
- printk(KERN_INFO "%s: MAC Address: %s\n", priv->name,
- print_mac(mac, hw->wiphy->perm_addr));
+ printk(KERN_INFO "%s: MAC Address: %pM\n", priv->name,
+ hw->wiphy->perm_addr);
return 0;
diff --git a/drivers/net/wireless/netwave_cs.c b/drivers/net/wireless/netwave_cs.c
index d63c8992f22..712f26eef35 100644
--- a/drivers/net/wireless/netwave_cs.c
+++ b/drivers/net/wireless/netwave_cs.c
@@ -1047,7 +1047,7 @@ static int netwave_start_xmit(struct sk_buff *skb, struct net_device *dev) {
}
dev_kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
} /* netwave_start_xmit */
/*
diff --git a/drivers/net/wireless/orinoco/Kconfig b/drivers/net/wireless/orinoco/Kconfig
index 44411eb4e91..83b635fd778 100644
--- a/drivers/net/wireless/orinoco/Kconfig
+++ b/drivers/net/wireless/orinoco/Kconfig
@@ -1,6 +1,7 @@
config HERMES
tristate "Hermes chipset 802.11b support (Orinoco/Prism2/Symbol)"
depends on (PPC_PMAC || PCI || PCMCIA) && WLAN_80211
+ depends on CFG80211
select WIRELESS_EXT
select FW_LOADER
select CRYPTO
diff --git a/drivers/net/wireless/orinoco/Makefile b/drivers/net/wireless/orinoco/Makefile
index 1fc7409d669..9abd6329bcb 100644
--- a/drivers/net/wireless/orinoco/Makefile
+++ b/drivers/net/wireless/orinoco/Makefile
@@ -1,7 +1,7 @@
#
# Makefile for the orinoco wireless device drivers.
#
-orinoco-objs := main.o fw.o hw.o mic.o scan.o wext.o hermes_dld.o hermes.o
+orinoco-objs := main.o fw.o hw.o mic.o scan.o wext.o hermes_dld.o hermes.o cfg.o
obj-$(CONFIG_HERMES) += orinoco.o
obj-$(CONFIG_PCMCIA_HERMES) += orinoco_cs.o
diff --git a/drivers/net/wireless/orinoco/airport.c b/drivers/net/wireless/orinoco/airport.c
index 8c4065f1b0d..c60df2c1aca 100644
--- a/drivers/net/wireless/orinoco/airport.c
+++ b/drivers/net/wireless/orinoco/airport.c
@@ -27,6 +27,7 @@
struct airport {
struct macio_dev *mdev;
void __iomem *vaddr;
+ unsigned int irq;
int irq_requested;
int ndev_registered;
};
@@ -34,8 +35,9 @@ struct airport {
static int
airport_suspend(struct macio_dev *mdev, pm_message_t state)
{
- struct net_device *dev = dev_get_drvdata(&mdev->ofdev.dev);
- struct orinoco_private *priv = netdev_priv(dev);
+ struct orinoco_private *priv = dev_get_drvdata(&mdev->ofdev.dev);
+ struct net_device *dev = priv->ndev;
+ struct airport *card = priv->card;
unsigned long flags;
int err;
@@ -48,18 +50,10 @@ airport_suspend(struct macio_dev *mdev, pm_message_t state)
return 0;
}
- err = __orinoco_down(dev);
- if (err)
- printk(KERN_WARNING "%s: PBOOK_SLEEP_NOW: Error %d downing interface\n",
- dev->name, err);
-
- netif_device_detach(dev);
-
- priv->hw_unavailable++;
-
+ orinoco_down(priv);
orinoco_unlock(priv, &flags);
- disable_irq(dev->irq);
+ disable_irq(card->irq);
pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE,
macio_get_of_node(mdev), 0, 0);
@@ -69,8 +63,9 @@ airport_suspend(struct macio_dev *mdev, pm_message_t state)
static int
airport_resume(struct macio_dev *mdev)
{
- struct net_device *dev = dev_get_drvdata(&mdev->ofdev.dev);
- struct orinoco_private *priv = netdev_priv(dev);
+ struct orinoco_private *priv = dev_get_drvdata(&mdev->ofdev.dev);
+ struct net_device *dev = priv->ndev;
+ struct airport *card = priv->card;
unsigned long flags;
int err;
@@ -80,47 +75,27 @@ airport_resume(struct macio_dev *mdev)
macio_get_of_node(mdev), 0, 1);
msleep(200);
- enable_irq(dev->irq);
-
- err = orinoco_reinit_firmware(dev);
- if (err) {
- printk(KERN_ERR "%s: Error %d re-initializing firmware on PBOOK_WAKE\n",
- dev->name, err);
- return 0;
- }
+ enable_irq(card->irq);
spin_lock_irqsave(&priv->lock, flags);
-
- netif_device_attach(dev);
-
- priv->hw_unavailable--;
-
- if (priv->open && (!priv->hw_unavailable)) {
- err = __orinoco_up(dev);
- if (err)
- printk(KERN_ERR "%s: Error %d restarting card on PBOOK_WAKE\n",
- dev->name, err);
- }
-
-
+ err = orinoco_up(priv);
spin_unlock_irqrestore(&priv->lock, flags);
- return 0;
+ return err;
}
static int
airport_detach(struct macio_dev *mdev)
{
- struct net_device *dev = dev_get_drvdata(&mdev->ofdev.dev);
- struct orinoco_private *priv = netdev_priv(dev);
+ struct orinoco_private *priv = dev_get_drvdata(&mdev->ofdev.dev);
struct airport *card = priv->card;
if (card->ndev_registered)
- unregister_netdev(dev);
+ orinoco_if_del(priv);
card->ndev_registered = 0;
if (card->irq_requested)
- free_irq(dev->irq, dev);
+ free_irq(card->irq, priv);
card->irq_requested = 0;
if (card->vaddr)
@@ -134,7 +109,7 @@ airport_detach(struct macio_dev *mdev)
ssleep(1);
macio_set_drvdata(mdev, NULL);
- free_orinocodev(dev);
+ free_orinocodev(priv);
return 0;
}
@@ -146,7 +121,6 @@ static int airport_hard_reset(struct orinoco_private *priv)
* re-initialize properly, it falls in a screaming heap
* shortly afterwards. */
#if 0
- struct net_device *dev = priv->ndev;
struct airport *card = priv->card;
/* Vitally important. If we don't do this it seems we get an
@@ -154,7 +128,7 @@ static int airport_hard_reset(struct orinoco_private *priv)
* hw_unavailable is already set it doesn't get ACKed, we get
* into an interrupt loop and the PMU decides to turn us
* off. */
- disable_irq(dev->irq);
+ disable_irq(card->irq);
pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE,
macio_get_of_node(card->mdev), 0, 0);
@@ -163,7 +137,7 @@ static int airport_hard_reset(struct orinoco_private *priv)
macio_get_of_node(card->mdev), 0, 1);
ssleep(1);
- enable_irq(dev->irq);
+ enable_irq(card->irq);
ssleep(1);
#endif
@@ -174,7 +148,6 @@ static int
airport_attach(struct macio_dev *mdev, const struct of_device_id *match)
{
struct orinoco_private *priv;
- struct net_device *dev;
struct airport *card;
unsigned long phys_addr;
hermes_t *hw;
@@ -185,33 +158,29 @@ airport_attach(struct macio_dev *mdev, const struct of_device_id *match)
}
/* Allocate space for private device-specific data */
- dev = alloc_orinocodev(sizeof(*card), &mdev->ofdev.dev,
- airport_hard_reset, NULL);
- if (!dev) {
+ priv = alloc_orinocodev(sizeof(*card), &mdev->ofdev.dev,
+ airport_hard_reset, NULL);
+ if (!priv) {
printk(KERN_ERR PFX "Cannot allocate network device\n");
return -ENODEV;
}
- priv = netdev_priv(dev);
card = priv->card;
hw = &priv->hw;
card->mdev = mdev;
- if (macio_request_resource(mdev, 0, "airport")) {
+ if (macio_request_resource(mdev, 0, DRIVER_NAME)) {
printk(KERN_ERR PFX "can't request IO resource !\n");
- free_orinocodev(dev);
+ free_orinocodev(priv);
return -EBUSY;
}
- SET_NETDEV_DEV(dev, &mdev->ofdev.dev);
-
- macio_set_drvdata(mdev, dev);
+ macio_set_drvdata(mdev, priv);
/* Setup interrupts & base address */
- dev->irq = macio_irq(mdev, 0);
+ card->irq = macio_irq(mdev, 0);
phys_addr = macio_resource_start(mdev, 0); /* Physical address */
printk(KERN_DEBUG PFX "Physical address %lx\n", phys_addr);
- dev->base_addr = phys_addr;
card->vaddr = ioremap(phys_addr, AIRPORT_IO_LEN);
if (!card->vaddr) {
printk(KERN_ERR PFX "ioremap() failed\n");
@@ -228,18 +197,23 @@ airport_attach(struct macio_dev *mdev, const struct of_device_id *match)
/* Reset it before we get the interrupt */
hermes_init(hw);
- if (request_irq(dev->irq, orinoco_interrupt, 0, dev->name, dev)) {
- printk(KERN_ERR PFX "Couldn't get IRQ %d\n", dev->irq);
+ if (request_irq(card->irq, orinoco_interrupt, 0, DRIVER_NAME, priv)) {
+ printk(KERN_ERR PFX "Couldn't get IRQ %d\n", card->irq);
goto failed;
}
card->irq_requested = 1;
- /* Tell the stack we exist */
- if (register_netdev(dev) != 0) {
- printk(KERN_ERR PFX "register_netdev() failed\n");
+ /* Initialise the main driver */
+ if (orinoco_init(priv) != 0) {
+ printk(KERN_ERR PFX "orinoco_init() failed\n");
+ goto failed;
+ }
+
+ /* Register an interface with the stack */
+ if (orinoco_if_add(priv, phys_addr, card->irq) != 0) {
+ printk(KERN_ERR PFX "orinoco_if_add() failed\n");
goto failed;
}
- printk(KERN_DEBUG PFX "Card registered for interface %s\n", dev->name);
card->ndev_registered = 1;
return 0;
failed:
diff --git a/drivers/net/wireless/orinoco/cfg.c b/drivers/net/wireless/orinoco/cfg.c
new file mode 100644
index 00000000000..27f2d334264
--- /dev/null
+++ b/drivers/net/wireless/orinoco/cfg.c
@@ -0,0 +1,203 @@
+/* cfg80211 support
+ *
+ * See copyright notice in main.c
+ */
+#include <linux/ieee80211.h>
+#include <net/cfg80211.h>
+#include "hw.h"
+#include "main.h"
+#include "orinoco.h"
+
+#include "cfg.h"
+
+/* Supported bitrates. Must agree with hw.c */
+static struct ieee80211_rate orinoco_rates[] = {
+ { .bitrate = 10 },
+ { .bitrate = 20 },
+ { .bitrate = 55 },
+ { .bitrate = 110 },
+};
+
+static const void * const orinoco_wiphy_privid = &orinoco_wiphy_privid;
+
+/* Called after orinoco_private is allocated. */
+void orinoco_wiphy_init(struct wiphy *wiphy)
+{
+ struct orinoco_private *priv = wiphy_priv(wiphy);
+
+ wiphy->privid = orinoco_wiphy_privid;
+
+ set_wiphy_dev(wiphy, priv->dev);
+}
+
+/* Called after firmware is initialised */
+int orinoco_wiphy_register(struct wiphy *wiphy)
+{
+ struct orinoco_private *priv = wiphy_priv(wiphy);
+ int i, channels = 0;
+
+ if (priv->firmware_type == FIRMWARE_TYPE_AGERE)
+ wiphy->max_scan_ssids = 1;
+ else
+ wiphy->max_scan_ssids = 0;
+
+ wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
+
+ /* TODO: should we set if we only have demo ad-hoc?
+ * (priv->has_port3)
+ */
+ if (priv->has_ibss)
+ wiphy->interface_modes |= BIT(NL80211_IFTYPE_ADHOC);
+
+ if (!priv->broken_monitor || force_monitor)
+ wiphy->interface_modes |= BIT(NL80211_IFTYPE_MONITOR);
+
+ priv->band.bitrates = orinoco_rates;
+ priv->band.n_bitrates = ARRAY_SIZE(orinoco_rates);
+
+ /* Only support channels allowed by the card EEPROM */
+ for (i = 0; i < NUM_CHANNELS; i++) {
+ if (priv->channel_mask & (1 << i)) {
+ priv->channels[i].center_freq =
+ ieee80211_dsss_chan_to_freq(i+1);
+ channels++;
+ }
+ }
+ priv->band.channels = priv->channels;
+ priv->band.n_channels = channels;
+
+ wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band;
+ wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
+
+ i = 0;
+ if (priv->has_wep) {
+ priv->cipher_suites[i] = WLAN_CIPHER_SUITE_WEP40;
+ i++;
+
+ if (priv->has_big_wep) {
+ priv->cipher_suites[i] = WLAN_CIPHER_SUITE_WEP104;
+ i++;
+ }
+ }
+ if (priv->has_wpa) {
+ priv->cipher_suites[i] = WLAN_CIPHER_SUITE_TKIP;
+ i++;
+ }
+ wiphy->cipher_suites = priv->cipher_suites;
+ wiphy->n_cipher_suites = i;
+
+ wiphy->rts_threshold = priv->rts_thresh;
+ if (!priv->has_mwo)
+ wiphy->frag_threshold = priv->frag_thresh;
+
+ return wiphy_register(wiphy);
+}
+
+static int orinoco_change_vif(struct wiphy *wiphy, struct net_device *dev,
+ enum nl80211_iftype type, u32 *flags,
+ struct vif_params *params)
+{
+ struct orinoco_private *priv = wiphy_priv(wiphy);
+ int err = 0;
+ unsigned long lock;
+
+ if (orinoco_lock(priv, &lock) != 0)
+ return -EBUSY;
+
+ switch (type) {
+ case NL80211_IFTYPE_ADHOC:
+ if (!priv->has_ibss && !priv->has_port3)
+ err = -EINVAL;
+ break;
+
+ case NL80211_IFTYPE_STATION:
+ break;
+
+ case NL80211_IFTYPE_MONITOR:
+ if (priv->broken_monitor && !force_monitor) {
+ printk(KERN_WARNING "%s: Monitor mode support is "
+ "buggy in this firmware, not enabling\n",
+ wiphy_name(wiphy));
+ err = -EINVAL;
+ }
+ break;
+
+ default:
+ err = -EINVAL;
+ }
+
+ if (!err) {
+ priv->iw_mode = type;
+ set_port_type(priv);
+ err = orinoco_commit(priv);
+ }
+
+ orinoco_unlock(priv, &lock);
+
+ return err;
+}
+
+static int orinoco_scan(struct wiphy *wiphy, struct net_device *dev,
+ struct cfg80211_scan_request *request)
+{
+ struct orinoco_private *priv = wiphy_priv(wiphy);
+ int err;
+
+ if (!request)
+ return -EINVAL;
+
+ if (priv->scan_request && priv->scan_request != request)
+ return -EBUSY;
+
+ priv->scan_request = request;
+
+ err = orinoco_hw_trigger_scan(priv, request->ssids);
+
+ return err;
+}
+
+static int orinoco_set_channel(struct wiphy *wiphy,
+ struct ieee80211_channel *chan,
+ enum nl80211_channel_type channel_type)
+{
+ struct orinoco_private *priv = wiphy_priv(wiphy);
+ int err = 0;
+ unsigned long flags;
+ int channel;
+
+ if (!chan)
+ return -EINVAL;
+
+ if (channel_type != NL80211_CHAN_NO_HT)
+ return -EINVAL;
+
+ if (chan->band != IEEE80211_BAND_2GHZ)
+ return -EINVAL;
+
+ channel = ieee80211_freq_to_dsss_chan(chan->center_freq);
+
+ if ((channel < 1) || (channel > NUM_CHANNELS) ||
+ !(priv->channel_mask & (1 << (channel-1))))
+ return -EINVAL;
+
+ if (orinoco_lock(priv, &flags) != 0)
+ return -EBUSY;
+
+ priv->channel = channel;
+ if (priv->iw_mode == NL80211_IFTYPE_MONITOR) {
+ /* Fast channel change - no commit if successful */
+ hermes_t *hw = &priv->hw;
+ err = hermes_docmd_wait(hw, HERMES_CMD_TEST |
+ HERMES_TEST_SET_CHANNEL,
+ channel, NULL);
+ }
+ orinoco_unlock(priv, &flags);
+
+ return err;
+}
+
+const struct cfg80211_ops orinoco_cfg_ops = {
+ .change_virtual_intf = orinoco_change_vif,
+ .set_channel = orinoco_set_channel,
+ .scan = orinoco_scan,
+};
diff --git a/drivers/net/wireless/orinoco/cfg.h b/drivers/net/wireless/orinoco/cfg.h
new file mode 100644
index 00000000000..3ddc96a06cd
--- /dev/null
+++ b/drivers/net/wireless/orinoco/cfg.h
@@ -0,0 +1,15 @@
+/* cfg80211 support.
+ *
+ * See copyright notice in main.c
+ */
+#ifndef ORINOCO_CFG_H
+#define ORINOCO_CFG_H
+
+#include <net/cfg80211.h>
+
+extern const struct cfg80211_ops orinoco_cfg_ops;
+
+void orinoco_wiphy_init(struct wiphy *wiphy);
+int orinoco_wiphy_register(struct wiphy *wiphy);
+
+#endif /* ORINOCO_CFG_H */
diff --git a/drivers/net/wireless/orinoco/fw.c b/drivers/net/wireless/orinoco/fw.c
index 1084b43e04b..1257250a1e2 100644
--- a/drivers/net/wireless/orinoco/fw.c
+++ b/drivers/net/wireless/orinoco/fw.c
@@ -4,6 +4,7 @@
*/
#include <linux/kernel.h>
#include <linux/firmware.h>
+#include <linux/device.h>
#include "hermes.h"
#include "hermes_dld.h"
@@ -99,7 +100,7 @@ orinoco_dl_firmware(struct orinoco_private *priv,
const void *end;
const char *firmware;
const char *fw_err;
- struct net_device *dev = priv->ndev;
+ struct device *dev = priv->dev;
int err = 0;
pda = kzalloc(fw->pda_size, GFP_KERNEL);
@@ -111,12 +112,11 @@ orinoco_dl_firmware(struct orinoco_private *priv,
else
firmware = fw->sta_fw;
- printk(KERN_DEBUG "%s: Attempting to download firmware %s\n",
- dev->name, firmware);
+ dev_dbg(dev, "Attempting to download firmware %s\n", firmware);
/* Read current plug data */
err = hermes_read_pda(hw, pda, fw->pda_addr, fw->pda_size, 0);
- printk(KERN_DEBUG "%s: Read PDA returned %d\n", dev->name, err);
+ dev_dbg(dev, "Read PDA returned %d\n", err);
if (err)
goto free;
@@ -124,8 +124,7 @@ orinoco_dl_firmware(struct orinoco_private *priv,
err = request_firmware(&fw_entry, firmware, priv->dev);
if (err) {
- printk(KERN_ERR "%s: Cannot find firmware %s\n",
- dev->name, firmware);
+ dev_err(dev, "Cannot find firmware %s\n", firmware);
err = -ENOENT;
goto free;
}
@@ -136,16 +135,15 @@ orinoco_dl_firmware(struct orinoco_private *priv,
fw_err = validate_fw(hdr, fw_entry->size);
if (fw_err) {
- printk(KERN_WARNING "%s: Invalid firmware image detected (%s). "
- "Aborting download\n",
- dev->name, fw_err);
+ dev_warn(dev, "Invalid firmware image detected (%s). "
+ "Aborting download\n", fw_err);
err = -EINVAL;
goto abort;
}
/* Enable aux port to allow programming */
err = hermesi_program_init(hw, le32_to_cpu(hdr->entry_point));
- printk(KERN_DEBUG "%s: Program init returned %d\n", dev->name, err);
+ dev_dbg(dev, "Program init returned %d\n", err);
if (err != 0)
goto abort;
@@ -156,7 +154,7 @@ orinoco_dl_firmware(struct orinoco_private *priv,
end = fw_entry->data + fw_entry->size;
err = hermes_program(hw, first_block, end);
- printk(KERN_DEBUG "%s: Program returned %d\n", dev->name, err);
+ dev_dbg(dev, "Program returned %d\n", err);
if (err != 0)
goto abort;
@@ -167,19 +165,18 @@ orinoco_dl_firmware(struct orinoco_private *priv,
err = hermes_apply_pda_with_defaults(hw, first_block, end, pda,
&pda[fw->pda_size / sizeof(*pda)]);
- printk(KERN_DEBUG "%s: Apply PDA returned %d\n", dev->name, err);
+ dev_dbg(dev, "Apply PDA returned %d\n", err);
if (err)
goto abort;
/* Tell card we've finished */
err = hermesi_program_end(hw);
- printk(KERN_DEBUG "%s: Program end returned %d\n", dev->name, err);
+ dev_dbg(dev, "Program end returned %d\n", err);
if (err != 0)
goto abort;
/* Check if we're running */
- printk(KERN_DEBUG "%s: hermes_present returned %d\n",
- dev->name, hermes_present(hw));
+ dev_dbg(dev, "hermes_present returned %d\n", hermes_present(hw));
abort:
/* If we requested the firmware, release it. */
@@ -282,14 +279,13 @@ static int
symbol_dl_firmware(struct orinoco_private *priv,
const struct fw_info *fw)
{
- struct net_device *dev = priv->ndev;
+ struct device *dev = priv->dev;
int ret;
const struct firmware *fw_entry;
if (!orinoco_cached_fw_get(priv, true)) {
if (request_firmware(&fw_entry, fw->pri_fw, priv->dev) != 0) {
- printk(KERN_ERR "%s: Cannot find firmware: %s\n",
- dev->name, fw->pri_fw);
+ dev_err(dev, "Cannot find firmware: %s\n", fw->pri_fw);
return -ENOENT;
}
} else
@@ -302,15 +298,13 @@ symbol_dl_firmware(struct orinoco_private *priv,
if (!orinoco_cached_fw_get(priv, true))
release_firmware(fw_entry);
if (ret) {
- printk(KERN_ERR "%s: Primary firmware download failed\n",
- dev->name);
+ dev_err(dev, "Primary firmware download failed\n");
return ret;
}
if (!orinoco_cached_fw_get(priv, false)) {
if (request_firmware(&fw_entry, fw->sta_fw, priv->dev) != 0) {
- printk(KERN_ERR "%s: Cannot find firmware: %s\n",
- dev->name, fw->sta_fw);
+ dev_err(dev, "Cannot find firmware: %s\n", fw->sta_fw);
return -ENOENT;
}
} else
@@ -322,8 +316,7 @@ symbol_dl_firmware(struct orinoco_private *priv,
if (!orinoco_cached_fw_get(priv, false))
release_firmware(fw_entry);
if (ret) {
- printk(KERN_ERR "%s: Secondary firmware download failed\n",
- dev->name);
+ dev_err(dev, "Secondary firmware download failed\n");
}
return ret;
diff --git a/drivers/net/wireless/orinoco/hermes.c b/drivers/net/wireless/orinoco/hermes.c
index f2c918c2572..1a2fca76fd3 100644
--- a/drivers/net/wireless/orinoco/hermes.c
+++ b/drivers/net/wireless/orinoco/hermes.c
@@ -469,7 +469,7 @@ int hermes_read_ltv(hermes_t *hw, int bap, u16 rid, unsigned bufsize,
u16 rlength, rtype;
unsigned nwords;
- if ((bufsize < 0) || (bufsize % 2))
+ if (bufsize % 2)
return -EINVAL;
err = hermes_docmd_wait(hw, HERMES_CMD_ACCESS, rid, NULL);
diff --git a/drivers/net/wireless/orinoco/hermes.h b/drivers/net/wireless/orinoco/hermes.h
index c78c442a02c..2dddbb597c4 100644
--- a/drivers/net/wireless/orinoco/hermes.h
+++ b/drivers/net/wireless/orinoco/hermes.h
@@ -342,7 +342,7 @@ struct agere_ext_scan_info {
__le64 timestamp;
__le16 beacon_interval;
__le16 capabilities;
- u8 data[316];
+ u8 data[0];
} __attribute__ ((packed));
#define HERMES_LINKSTATUS_NOT_CONNECTED (0x0000)
diff --git a/drivers/net/wireless/orinoco/hermes_dld.c b/drivers/net/wireless/orinoco/hermes_dld.c
index a9ba195cdad..a3eefe109df 100644
--- a/drivers/net/wireless/orinoco/hermes_dld.c
+++ b/drivers/net/wireless/orinoco/hermes_dld.c
@@ -309,7 +309,7 @@ int hermes_read_pda(hermes_t *hw,
/* Open auxiliary port */
ret = hermes_aux_control(hw, 1);
- printk(KERN_DEBUG PFX "AUX enable returned %d\n", ret);
+ pr_debug(PFX "AUX enable returned %d\n", ret);
if (ret)
return ret;
@@ -319,12 +319,12 @@ int hermes_read_pda(hermes_t *hw,
/* Close aux port */
ret = hermes_aux_control(hw, 0);
- printk(KERN_DEBUG PFX "AUX disable returned %d\n", ret);
+ pr_debug(PFX "AUX disable returned %d\n", ret);
/* Check PDA length */
pda_size = le16_to_cpu(pda[0]);
- printk(KERN_DEBUG PFX "Actual PDA length %d, Max allowed %d\n",
- pda_size, pda_len);
+ pr_debug(PFX "Actual PDA length %d, Max allowed %d\n",
+ pda_size, pda_len);
if (pda_size > pda_len)
return -EINVAL;
@@ -422,20 +422,19 @@ int hermesi_program_init(hermes_t *hw, u32 offset)
return err;
err = hermes_aux_control(hw, 1);
- printk(KERN_DEBUG PFX "AUX enable returned %d\n", err);
+ pr_debug(PFX "AUX enable returned %d\n", err);
if (err)
return err;
- printk(KERN_DEBUG PFX "Enabling volatile, EP 0x%08x\n", offset);
+ pr_debug(KERN_DEBUG PFX "Enabling volatile, EP 0x%08x\n", offset);
err = hermes_doicmd_wait(hw,
HERMES_PROGRAM_ENABLE_VOLATILE,
offset & 0xFFFFu,
offset >> 16,
0,
NULL);
- printk(KERN_DEBUG PFX "PROGRAM_ENABLE returned %d\n",
- err);
+ pr_debug(PFX "PROGRAM_ENABLE returned %d\n", err);
return err;
}
@@ -454,16 +453,16 @@ int hermesi_program_end(hermes_t *hw)
rc = hermes_docmd_wait(hw, HERMES_PROGRAM_DISABLE, 0, &resp);
- printk(KERN_DEBUG PFX "PROGRAM_DISABLE returned %d, "
- "r0 0x%04x, r1 0x%04x, r2 0x%04x\n",
- rc, resp.resp0, resp.resp1, resp.resp2);
+ pr_debug(PFX "PROGRAM_DISABLE returned %d, "
+ "r0 0x%04x, r1 0x%04x, r2 0x%04x\n",
+ rc, resp.resp0, resp.resp1, resp.resp2);
if ((rc == 0) &&
((resp.status & HERMES_STATUS_CMDCODE) != HERMES_CMD_DOWNLD))
rc = -EIO;
err = hermes_aux_control(hw, 0);
- printk(KERN_DEBUG PFX "AUX disable returned %d\n", err);
+ pr_debug(PFX "AUX disable returned %d\n", err);
/* Acknowledge any outstanding command */
hermes_write_regn(hw, EVACK, 0xFFFF);
@@ -496,9 +495,8 @@ int hermes_program(hermes_t *hw, const char *first_block, const void *end)
while ((blkaddr != BLOCK_END) &&
(((void *) blk + blklen) <= end)) {
- printk(KERN_DEBUG PFX
- "Programming block of length %d to address 0x%08x\n",
- blklen, blkaddr);
+ pr_debug(PFX "Programming block of length %d "
+ "to address 0x%08x\n", blklen, blkaddr);
#if !LIMIT_PROGRAM_SIZE
/* wl_lkm driver splits this into writes of 2000 bytes */
@@ -510,10 +508,9 @@ int hermes_program(hermes_t *hw, const char *first_block, const void *end)
addr = blkaddr;
while (addr < (blkaddr + blklen)) {
- printk(KERN_DEBUG PFX
- "Programming subblock of length %d "
- "to address 0x%08x. Data @ %p\n",
- len, addr, &blk->data[addr - blkaddr]);
+ pr_debug(PFX "Programming subblock of length %d "
+ "to address 0x%08x. Data @ %p\n",
+ len, addr, &blk->data[addr - blkaddr]);
hermes_aux_setaddr(hw, addr);
hermes_write_bytes(hw, HERMES_AUXDATA,
@@ -643,8 +640,8 @@ int hermes_apply_pda_with_defaults(hermes_t *hw,
pdi = hermes_find_pdi(first_pdi, record_id, pda_end);
if (pdi)
- printk(KERN_DEBUG PFX "Found record 0x%04x at %p\n",
- record_id, pdi);
+ pr_debug(PFX "Found record 0x%04x at %p\n",
+ record_id, pdi);
switch (record_id) {
case 0x110: /* Modem REFDAC values */
@@ -654,9 +651,9 @@ int hermes_apply_pda_with_defaults(hermes_t *hw,
default_pdi = NULL;
if (outdoor_pdi) {
pdi = outdoor_pdi;
- printk(KERN_DEBUG PFX
- "Using outdoor record 0x%04x at %p\n",
- record_id + 1, pdi);
+ pr_debug(PFX
+ "Using outdoor record 0x%04x at %p\n",
+ record_id + 1, pdi);
}
break;
case 0x5: /* HWIF Compatiblity */
@@ -684,9 +681,8 @@ int hermes_apply_pda_with_defaults(hermes_t *hw,
if (!pdi && default_pdi) {
/* Use default */
pdi = default_pdi;
- printk(KERN_DEBUG PFX
- "Using default record 0x%04x at %p\n",
- record_id, pdi);
+ pr_debug(PFX "Using default record 0x%04x at %p\n",
+ record_id, pdi);
}
if (pdi) {
diff --git a/drivers/net/wireless/orinoco/hw.c b/drivers/net/wireless/orinoco/hw.c
index 632fac86a30..40d8dfa7eac 100644
--- a/drivers/net/wireless/orinoco/hw.c
+++ b/drivers/net/wireless/orinoco/hw.c
@@ -3,16 +3,22 @@
* See copyright notice in main.c
*/
#include <linux/kernel.h>
+#include <linux/device.h>
#include <linux/if_arp.h>
#include <linux/ieee80211.h>
#include <linux/wireless.h>
-
+#include <net/cfg80211.h>
#include "hermes.h"
#include "hermes_rid.h"
#include "orinoco.h"
#include "hw.h"
+#define SYMBOL_MAX_VER_LEN (14)
+
+/* Symbol firmware has a bug allocating buffers larger than this */
+#define TX_NICBUF_SIZE_BUG 1585
+
/********************************************************************/
/* Data tables */
/********************************************************************/
@@ -36,6 +42,343 @@ static const struct {
};
#define BITRATE_TABLE_SIZE ARRAY_SIZE(bitrate_table)
+/* Firmware version encoding */
+struct comp_id {
+ u16 id, variant, major, minor;
+} __attribute__ ((packed));
+
+static inline fwtype_t determine_firmware_type(struct comp_id *nic_id)
+{
+ if (nic_id->id < 0x8000)
+ return FIRMWARE_TYPE_AGERE;
+ else if (nic_id->id == 0x8000 && nic_id->major == 0)
+ return FIRMWARE_TYPE_SYMBOL;
+ else
+ return FIRMWARE_TYPE_INTERSIL;
+}
+
+/* Set priv->firmware type, determine firmware properties
+ * This function can be called before we have registerred with netdev,
+ * so all errors go out with dev_* rather than printk
+ */
+int determine_fw_capabilities(struct orinoco_private *priv)
+{
+ struct device *dev = priv->dev;
+ hermes_t *hw = &priv->hw;
+ int err;
+ struct comp_id nic_id, sta_id;
+ unsigned int firmver;
+ char tmp[SYMBOL_MAX_VER_LEN+1] __attribute__((aligned(2)));
+
+ /* Get the hardware version */
+ err = HERMES_READ_RECORD(hw, USER_BAP, HERMES_RID_NICID, &nic_id);
+ if (err) {
+ dev_err(dev, "Cannot read hardware identity: error %d\n",
+ err);
+ return err;
+ }
+
+ le16_to_cpus(&nic_id.id);
+ le16_to_cpus(&nic_id.variant);
+ le16_to_cpus(&nic_id.major);
+ le16_to_cpus(&nic_id.minor);
+ dev_info(dev, "Hardware identity %04x:%04x:%04x:%04x\n",
+ nic_id.id, nic_id.variant, nic_id.major, nic_id.minor);
+
+ priv->firmware_type = determine_firmware_type(&nic_id);
+
+ /* Get the firmware version */
+ err = HERMES_READ_RECORD(hw, USER_BAP, HERMES_RID_STAID, &sta_id);
+ if (err) {
+ dev_err(dev, "Cannot read station identity: error %d\n",
+ err);
+ return err;
+ }
+
+ le16_to_cpus(&sta_id.id);
+ le16_to_cpus(&sta_id.variant);
+ le16_to_cpus(&sta_id.major);
+ le16_to_cpus(&sta_id.minor);
+ dev_info(dev, "Station identity %04x:%04x:%04x:%04x\n",
+ sta_id.id, sta_id.variant, sta_id.major, sta_id.minor);
+
+ switch (sta_id.id) {
+ case 0x15:
+ dev_err(dev, "Primary firmware is active\n");
+ return -ENODEV;
+ case 0x14b:
+ dev_err(dev, "Tertiary firmware is active\n");
+ return -ENODEV;
+ case 0x1f: /* Intersil, Agere, Symbol Spectrum24 */
+ case 0x21: /* Symbol Spectrum24 Trilogy */
+ break;
+ default:
+ dev_notice(dev, "Unknown station ID, please report\n");
+ break;
+ }
+
+ /* Default capabilities */
+ priv->has_sensitivity = 1;
+ priv->has_mwo = 0;
+ priv->has_preamble = 0;
+ priv->has_port3 = 1;
+ priv->has_ibss = 1;
+ priv->has_wep = 0;
+ priv->has_big_wep = 0;
+ priv->has_alt_txcntl = 0;
+ priv->has_ext_scan = 0;
+ priv->has_wpa = 0;
+ priv->do_fw_download = 0;
+
+ /* Determine capabilities from the firmware version */
+ switch (priv->firmware_type) {
+ case FIRMWARE_TYPE_AGERE:
+ /* Lucent Wavelan IEEE, Lucent Orinoco, Cabletron RoamAbout,
+ ELSA, Melco, HP, IBM, Dell 1150, Compaq 110/210 */
+ snprintf(priv->fw_name, sizeof(priv->fw_name) - 1,
+ "Lucent/Agere %d.%02d", sta_id.major, sta_id.minor);
+
+ firmver = ((unsigned long)sta_id.major << 16) | sta_id.minor;
+
+ priv->has_ibss = (firmver >= 0x60006);
+ priv->has_wep = (firmver >= 0x40020);
+ priv->has_big_wep = 1; /* FIXME: this is wrong - how do we tell
+ Gold cards from the others? */
+ priv->has_mwo = (firmver >= 0x60000);
+ priv->has_pm = (firmver >= 0x40020); /* Don't work in 7.52 ? */
+ priv->ibss_port = 1;
+ priv->has_hostscan = (firmver >= 0x8000a);
+ priv->do_fw_download = 1;
+ priv->broken_monitor = (firmver >= 0x80000);
+ priv->has_alt_txcntl = (firmver >= 0x90000); /* All 9.x ? */
+ priv->has_ext_scan = (firmver >= 0x90000); /* All 9.x ? */
+ priv->has_wpa = (firmver >= 0x9002a);
+ /* Tested with Agere firmware :
+ * 1.16 ; 4.08 ; 4.52 ; 6.04 ; 6.16 ; 7.28 => Jean II
+ * Tested CableTron firmware : 4.32 => Anton */
+ break;
+ case FIRMWARE_TYPE_SYMBOL:
+ /* Symbol , 3Com AirConnect, Intel, Ericsson WLAN */
+ /* Intel MAC : 00:02:B3:* */
+ /* 3Com MAC : 00:50:DA:* */
+ memset(tmp, 0, sizeof(tmp));
+ /* Get the Symbol firmware version */
+ err = hermes_read_ltv(hw, USER_BAP,
+ HERMES_RID_SECONDARYVERSION_SYMBOL,
+ SYMBOL_MAX_VER_LEN, NULL, &tmp);
+ if (err) {
+ dev_warn(dev, "Error %d reading Symbol firmware info. "
+ "Wildly guessing capabilities...\n", err);
+ firmver = 0;
+ tmp[0] = '\0';
+ } else {
+ /* The firmware revision is a string, the format is
+ * something like : "V2.20-01".
+ * Quick and dirty parsing... - Jean II
+ */
+ firmver = ((tmp[1] - '0') << 16)
+ | ((tmp[3] - '0') << 12)
+ | ((tmp[4] - '0') << 8)
+ | ((tmp[6] - '0') << 4)
+ | (tmp[7] - '0');
+
+ tmp[SYMBOL_MAX_VER_LEN] = '\0';
+ }
+
+ snprintf(priv->fw_name, sizeof(priv->fw_name) - 1,
+ "Symbol %s", tmp);
+
+ priv->has_ibss = (firmver >= 0x20000);
+ priv->has_wep = (firmver >= 0x15012);
+ priv->has_big_wep = (firmver >= 0x20000);
+ priv->has_pm = (firmver >= 0x20000 && firmver < 0x22000) ||
+ (firmver >= 0x29000 && firmver < 0x30000) ||
+ firmver >= 0x31000;
+ priv->has_preamble = (firmver >= 0x20000);
+ priv->ibss_port = 4;
+
+ /* Symbol firmware is found on various cards, but
+ * there has been no attempt to check firmware
+ * download on non-spectrum_cs based cards.
+ *
+ * Given that the Agere firmware download works
+ * differently, we should avoid doing a firmware
+ * download with the Symbol algorithm on non-spectrum
+ * cards.
+ *
+ * For now we can identify a spectrum_cs based card
+ * because it has a firmware reset function.
+ */
+ priv->do_fw_download = (priv->stop_fw != NULL);
+
+ priv->broken_disableport = (firmver == 0x25013) ||
+ (firmver >= 0x30000 && firmver <= 0x31000);
+ priv->has_hostscan = (firmver >= 0x31001) ||
+ (firmver >= 0x29057 && firmver < 0x30000);
+ /* Tested with Intel firmware : 0x20015 => Jean II */
+ /* Tested with 3Com firmware : 0x15012 & 0x22001 => Jean II */
+ break;
+ case FIRMWARE_TYPE_INTERSIL:
+ /* D-Link, Linksys, Adtron, ZoomAir, and many others...
+ * Samsung, Compaq 100/200 and Proxim are slightly
+ * different and less well tested */
+ /* D-Link MAC : 00:40:05:* */
+ /* Addtron MAC : 00:90:D1:* */
+ snprintf(priv->fw_name, sizeof(priv->fw_name) - 1,
+ "Intersil %d.%d.%d", sta_id.major, sta_id.minor,
+ sta_id.variant);
+
+ firmver = ((unsigned long)sta_id.major << 16) |
+ ((unsigned long)sta_id.minor << 8) | sta_id.variant;
+
+ priv->has_ibss = (firmver >= 0x000700); /* FIXME */
+ priv->has_big_wep = priv->has_wep = (firmver >= 0x000800);
+ priv->has_pm = (firmver >= 0x000700);
+ priv->has_hostscan = (firmver >= 0x010301);
+
+ if (firmver >= 0x000800)
+ priv->ibss_port = 0;
+ else {
+ dev_notice(dev, "Intersil firmware earlier than v0.8.x"
+ " - several features not supported\n");
+ priv->ibss_port = 1;
+ }
+ break;
+ }
+ dev_info(dev, "Firmware determined as %s\n", priv->fw_name);
+
+ return 0;
+}
+
+/* Read settings from EEPROM into our private structure.
+ * MAC address gets dropped into callers buffer
+ * Can be called before netdev registration.
+ */
+int orinoco_hw_read_card_settings(struct orinoco_private *priv, u8 *dev_addr)
+{
+ struct device *dev = priv->dev;
+ struct hermes_idstring nickbuf;
+ hermes_t *hw = &priv->hw;
+ int len;
+ int err;
+ u16 reclen;
+
+ /* Get the MAC address */
+ err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CNFOWNMACADDR,
+ ETH_ALEN, NULL, dev_addr);
+ if (err) {
+ dev_warn(dev, "Failed to read MAC address!\n");
+ goto out;
+ }
+
+ dev_dbg(dev, "MAC address %pM\n", dev_addr);
+
+ /* Get the station name */
+ err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CNFOWNNAME,
+ sizeof(nickbuf), &reclen, &nickbuf);
+ if (err) {
+ dev_err(dev, "failed to read station name\n");
+ goto out;
+ }
+ if (nickbuf.len)
+ len = min(IW_ESSID_MAX_SIZE, (int)le16_to_cpu(nickbuf.len));
+ else
+ len = min(IW_ESSID_MAX_SIZE, 2 * reclen);
+ memcpy(priv->nick, &nickbuf.val, len);
+ priv->nick[len] = '\0';
+
+ dev_dbg(dev, "Station name \"%s\"\n", priv->nick);
+
+ /* Get allowed channels */
+ err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CHANNELLIST,
+ &priv->channel_mask);
+ if (err) {
+ dev_err(dev, "Failed to read channel list!\n");
+ goto out;
+ }
+
+ /* Get initial AP density */
+ err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CNFSYSTEMSCALE,
+ &priv->ap_density);
+ if (err || priv->ap_density < 1 || priv->ap_density > 3)
+ priv->has_sensitivity = 0;
+
+ /* Get initial RTS threshold */
+ err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CNFRTSTHRESHOLD,
+ &priv->rts_thresh);
+ if (err) {
+ dev_err(dev, "Failed to read RTS threshold!\n");
+ goto out;
+ }
+
+ /* Get initial fragmentation settings */
+ if (priv->has_mwo)
+ err = hermes_read_wordrec(hw, USER_BAP,
+ HERMES_RID_CNFMWOROBUST_AGERE,
+ &priv->mwo_robust);
+ else
+ err = hermes_read_wordrec(hw, USER_BAP,
+ HERMES_RID_CNFFRAGMENTATIONTHRESHOLD,
+ &priv->frag_thresh);
+ if (err) {
+ dev_err(dev, "Failed to read fragmentation settings!\n");
+ goto out;
+ }
+
+ /* Power management setup */
+ if (priv->has_pm) {
+ priv->pm_on = 0;
+ priv->pm_mcast = 1;
+ err = hermes_read_wordrec(hw, USER_BAP,
+ HERMES_RID_CNFMAXSLEEPDURATION,
+ &priv->pm_period);
+ if (err) {
+ dev_err(dev, "Failed to read power management "
+ "period!\n");
+ goto out;
+ }
+ err = hermes_read_wordrec(hw, USER_BAP,
+ HERMES_RID_CNFPMHOLDOVERDURATION,
+ &priv->pm_timeout);
+ if (err) {
+ dev_err(dev, "Failed to read power management "
+ "timeout!\n");
+ goto out;
+ }
+ }
+
+ /* Preamble setup */
+ if (priv->has_preamble) {
+ err = hermes_read_wordrec(hw, USER_BAP,
+ HERMES_RID_CNFPREAMBLE_SYMBOL,
+ &priv->preamble);
+ }
+
+out:
+ return err;
+}
+
+/* Can be called before netdev registration */
+int orinoco_hw_allocate_fid(struct orinoco_private *priv)
+{
+ struct device *dev = priv->dev;
+ struct hermes *hw = &priv->hw;
+ int err;
+
+ err = hermes_allocate(hw, priv->nicbuf_size, &priv->txfid);
+ if (err == -EIO && priv->nicbuf_size > TX_NICBUF_SIZE_BUG) {
+ /* Try workaround for old Symbol firmware bug */
+ priv->nicbuf_size = TX_NICBUF_SIZE_BUG;
+ err = hermes_allocate(hw, priv->nicbuf_size, &priv->txfid);
+
+ dev_warn(dev, "Firmware ALLOC bug detected "
+ "(old Symbol firmware?). Work around %s\n",
+ err ? "failed!" : "ok.");
+ }
+
+ return err;
+}
+
int orinoco_get_bitratemode(int bitrate, int automatic)
{
int ratemode = -1;
@@ -63,12 +406,243 @@ void orinoco_get_ratemode_cfg(int ratemode, int *bitrate, int *automatic)
*automatic = bitrate_table[ratemode].automatic;
}
+int orinoco_hw_program_rids(struct orinoco_private *priv)
+{
+ struct net_device *dev = priv->ndev;
+ struct wireless_dev *wdev = netdev_priv(dev);
+ hermes_t *hw = &priv->hw;
+ int err;
+ struct hermes_idstring idbuf;
+
+ /* Set the MAC address */
+ err = hermes_write_ltv(hw, USER_BAP, HERMES_RID_CNFOWNMACADDR,
+ HERMES_BYTES_TO_RECLEN(ETH_ALEN), dev->dev_addr);
+ if (err) {
+ printk(KERN_ERR "%s: Error %d setting MAC address\n",
+ dev->name, err);
+ return err;
+ }
+
+ /* Set up the link mode */
+ err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNFPORTTYPE,
+ priv->port_type);
+ if (err) {
+ printk(KERN_ERR "%s: Error %d setting port type\n",
+ dev->name, err);
+ return err;
+ }
+ /* Set the channel/frequency */
+ if (priv->channel != 0 && priv->iw_mode != NL80211_IFTYPE_STATION) {
+ err = hermes_write_wordrec(hw, USER_BAP,
+ HERMES_RID_CNFOWNCHANNEL,
+ priv->channel);
+ if (err) {
+ printk(KERN_ERR "%s: Error %d setting channel %d\n",
+ dev->name, err, priv->channel);
+ return err;
+ }
+ }
+
+ if (priv->has_ibss) {
+ u16 createibss;
+
+ if ((strlen(priv->desired_essid) == 0) && (priv->createibss)) {
+ printk(KERN_WARNING "%s: This firmware requires an "
+ "ESSID in IBSS-Ad-Hoc mode.\n", dev->name);
+ /* With wvlan_cs, in this case, we would crash.
+ * hopefully, this driver will behave better...
+ * Jean II */
+ createibss = 0;
+ } else {
+ createibss = priv->createibss;
+ }
+
+ err = hermes_write_wordrec(hw, USER_BAP,
+ HERMES_RID_CNFCREATEIBSS,
+ createibss);
+ if (err) {
+ printk(KERN_ERR "%s: Error %d setting CREATEIBSS\n",
+ dev->name, err);
+ return err;
+ }
+ }
+
+ /* Set the desired BSSID */
+ err = __orinoco_hw_set_wap(priv);
+ if (err) {
+ printk(KERN_ERR "%s: Error %d setting AP address\n",
+ dev->name, err);
+ return err;
+ }
+
+ /* Set the desired ESSID */
+ idbuf.len = cpu_to_le16(strlen(priv->desired_essid));
+ memcpy(&idbuf.val, priv->desired_essid, sizeof(idbuf.val));
+ /* WinXP wants partner to configure OWNSSID even in IBSS mode. (jimc) */
+ err = hermes_write_ltv(hw, USER_BAP, HERMES_RID_CNFOWNSSID,
+ HERMES_BYTES_TO_RECLEN(strlen(priv->desired_essid)+2),
+ &idbuf);
+ if (err) {
+ printk(KERN_ERR "%s: Error %d setting OWNSSID\n",
+ dev->name, err);
+ return err;
+ }
+ err = hermes_write_ltv(hw, USER_BAP, HERMES_RID_CNFDESIREDSSID,
+ HERMES_BYTES_TO_RECLEN(strlen(priv->desired_essid)+2),
+ &idbuf);
+ if (err) {
+ printk(KERN_ERR "%s: Error %d setting DESIREDSSID\n",
+ dev->name, err);
+ return err;
+ }
+
+ /* Set the station name */
+ idbuf.len = cpu_to_le16(strlen(priv->nick));
+ memcpy(&idbuf.val, priv->nick, sizeof(idbuf.val));
+ err = hermes_write_ltv(hw, USER_BAP, HERMES_RID_CNFOWNNAME,
+ HERMES_BYTES_TO_RECLEN(strlen(priv->nick)+2),
+ &idbuf);
+ if (err) {
+ printk(KERN_ERR "%s: Error %d setting nickname\n",
+ dev->name, err);
+ return err;
+ }
+
+ /* Set AP density */
+ if (priv->has_sensitivity) {
+ err = hermes_write_wordrec(hw, USER_BAP,
+ HERMES_RID_CNFSYSTEMSCALE,
+ priv->ap_density);
+ if (err) {
+ printk(KERN_WARNING "%s: Error %d setting SYSTEMSCALE. "
+ "Disabling sensitivity control\n",
+ dev->name, err);
+
+ priv->has_sensitivity = 0;
+ }
+ }
+
+ /* Set RTS threshold */
+ err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNFRTSTHRESHOLD,
+ priv->rts_thresh);
+ if (err) {
+ printk(KERN_ERR "%s: Error %d setting RTS threshold\n",
+ dev->name, err);
+ return err;
+ }
+
+ /* Set fragmentation threshold or MWO robustness */
+ if (priv->has_mwo)
+ err = hermes_write_wordrec(hw, USER_BAP,
+ HERMES_RID_CNFMWOROBUST_AGERE,
+ priv->mwo_robust);
+ else
+ err = hermes_write_wordrec(hw, USER_BAP,
+ HERMES_RID_CNFFRAGMENTATIONTHRESHOLD,
+ priv->frag_thresh);
+ if (err) {
+ printk(KERN_ERR "%s: Error %d setting fragmentation\n",
+ dev->name, err);
+ return err;
+ }
+
+ /* Set bitrate */
+ err = __orinoco_hw_set_bitrate(priv);
+ if (err) {
+ printk(KERN_ERR "%s: Error %d setting bitrate\n",
+ dev->name, err);
+ return err;
+ }
+
+ /* Set power management */
+ if (priv->has_pm) {
+ err = hermes_write_wordrec(hw, USER_BAP,
+ HERMES_RID_CNFPMENABLED,
+ priv->pm_on);
+ if (err) {
+ printk(KERN_ERR "%s: Error %d setting up PM\n",
+ dev->name, err);
+ return err;
+ }
+
+ err = hermes_write_wordrec(hw, USER_BAP,
+ HERMES_RID_CNFMULTICASTRECEIVE,
+ priv->pm_mcast);
+ if (err) {
+ printk(KERN_ERR "%s: Error %d setting up PM\n",
+ dev->name, err);
+ return err;
+ }
+ err = hermes_write_wordrec(hw, USER_BAP,
+ HERMES_RID_CNFMAXSLEEPDURATION,
+ priv->pm_period);
+ if (err) {
+ printk(KERN_ERR "%s: Error %d setting up PM\n",
+ dev->name, err);
+ return err;
+ }
+ err = hermes_write_wordrec(hw, USER_BAP,
+ HERMES_RID_CNFPMHOLDOVERDURATION,
+ priv->pm_timeout);
+ if (err) {
+ printk(KERN_ERR "%s: Error %d setting up PM\n",
+ dev->name, err);
+ return err;
+ }
+ }
+
+ /* Set preamble - only for Symbol so far... */
+ if (priv->has_preamble) {
+ err = hermes_write_wordrec(hw, USER_BAP,
+ HERMES_RID_CNFPREAMBLE_SYMBOL,
+ priv->preamble);
+ if (err) {
+ printk(KERN_ERR "%s: Error %d setting preamble\n",
+ dev->name, err);
+ return err;
+ }
+ }
+
+ /* Set up encryption */
+ if (priv->has_wep || priv->has_wpa) {
+ err = __orinoco_hw_setup_enc(priv);
+ if (err) {
+ printk(KERN_ERR "%s: Error %d activating encryption\n",
+ dev->name, err);
+ return err;
+ }
+ }
+
+ if (priv->iw_mode == NL80211_IFTYPE_MONITOR) {
+ /* Enable monitor mode */
+ dev->type = ARPHRD_IEEE80211;
+ err = hermes_docmd_wait(hw, HERMES_CMD_TEST |
+ HERMES_TEST_MONITOR, 0, NULL);
+ } else {
+ /* Disable monitor mode */
+ dev->type = ARPHRD_ETHER;
+ err = hermes_docmd_wait(hw, HERMES_CMD_TEST |
+ HERMES_TEST_STOP, 0, NULL);
+ }
+ if (err)
+ return err;
+
+ /* Reset promiscuity / multicast*/
+ priv->promiscuous = 0;
+ priv->mc_count = 0;
+
+ /* Record mode change */
+ wdev->iftype = priv->iw_mode;
+
+ return 0;
+}
+
/* Get tsc from the firmware */
int orinoco_hw_get_tkip_iv(struct orinoco_private *priv, int key, u8 *tsc)
{
hermes_t *hw = &priv->hw;
int err = 0;
- u8 tsc_arr[4][IW_ENCODE_SEQ_MAX_SIZE];
+ u8 tsc_arr[4][ORINOCO_SEQ_LEN];
if ((key < 0) || (key > 4))
return -EINVAL;
@@ -194,12 +768,29 @@ int __orinoco_hw_setup_wepkeys(struct orinoco_private *priv)
{
hermes_t *hw = &priv->hw;
int err = 0;
+ int i;
switch (priv->firmware_type) {
case FIRMWARE_TYPE_AGERE:
+ {
+ struct orinoco_key keys[ORINOCO_MAX_KEYS];
+
+ memset(&keys, 0, sizeof(keys));
+ for (i = 0; i < ORINOCO_MAX_KEYS; i++) {
+ int len = min(priv->keys[i].key_len,
+ ORINOCO_MAX_KEY_SIZE);
+ memcpy(&keys[i].data, priv->keys[i].key, len);
+ if (len > SMALL_KEY_SIZE)
+ keys[i].len = cpu_to_le16(LARGE_KEY_SIZE);
+ else if (len > 0)
+ keys[i].len = cpu_to_le16(SMALL_KEY_SIZE);
+ else
+ keys[i].len = cpu_to_le16(0);
+ }
+
err = HERMES_WRITE_RECORD(hw, USER_BAP,
HERMES_RID_CNFWEPKEYS_AGERE,
- &priv->keys);
+ &keys);
if (err)
return err;
err = hermes_write_wordrec(hw, USER_BAP,
@@ -208,28 +799,38 @@ int __orinoco_hw_setup_wepkeys(struct orinoco_private *priv)
if (err)
return err;
break;
+ }
case FIRMWARE_TYPE_INTERSIL:
case FIRMWARE_TYPE_SYMBOL:
{
int keylen;
- int i;
/* Force uniform key length to work around
* firmware bugs */
- keylen = le16_to_cpu(priv->keys[priv->tx_key].len);
+ keylen = priv->keys[priv->tx_key].key_len;
if (keylen > LARGE_KEY_SIZE) {
printk(KERN_ERR "%s: BUG: Key %d has oversize length %d.\n",
priv->ndev->name, priv->tx_key, keylen);
return -E2BIG;
- }
+ } else if (keylen > SMALL_KEY_SIZE)
+ keylen = LARGE_KEY_SIZE;
+ else if (keylen > 0)
+ keylen = SMALL_KEY_SIZE;
+ else
+ keylen = 0;
/* Write all 4 keys */
for (i = 0; i < ORINOCO_MAX_KEYS; i++) {
+ u8 key[LARGE_KEY_SIZE] = { 0 };
+
+ memcpy(key, priv->keys[i].key,
+ priv->keys[i].key_len);
+
err = hermes_write_ltv(hw, USER_BAP,
HERMES_RID_CNFDEFAULTKEY0 + i,
HERMES_BYTES_TO_RECLEN(keylen),
- priv->keys[i].data);
+ key);
if (err)
return err;
}
@@ -255,8 +856,8 @@ int __orinoco_hw_setup_enc(struct orinoco_private *priv)
int auth_flag;
int enc_flag;
- /* Setup WEP keys for WEP and WPA */
- if (priv->encode_alg)
+ /* Setup WEP keys */
+ if (priv->encode_alg == ORINOCO_ALG_WEP)
__orinoco_hw_setup_wepkeys(priv);
if (priv->wep_restrict)
@@ -266,14 +867,14 @@ int __orinoco_hw_setup_enc(struct orinoco_private *priv)
if (priv->wpa_enabled)
enc_flag = 2;
- else if (priv->encode_alg == IW_ENCODE_ALG_WEP)
+ else if (priv->encode_alg == ORINOCO_ALG_WEP)
enc_flag = 1;
else
enc_flag = 0;
switch (priv->firmware_type) {
case FIRMWARE_TYPE_AGERE: /* Agere style WEP */
- if (priv->encode_alg == IW_ENCODE_ALG_WEP) {
+ if (priv->encode_alg == ORINOCO_ALG_WEP) {
/* Enable the shared-key authentication. */
err = hermes_write_wordrec(hw, USER_BAP,
HERMES_RID_CNFAUTHENTICATION_AGERE,
@@ -298,7 +899,7 @@ int __orinoco_hw_setup_enc(struct orinoco_private *priv)
case FIRMWARE_TYPE_INTERSIL: /* Intersil style WEP */
case FIRMWARE_TYPE_SYMBOL: /* Symbol style WEP */
- if (priv->encode_alg == IW_ENCODE_ALG_WEP) {
+ if (priv->encode_alg == ORINOCO_ALG_WEP) {
if (priv->wep_restrict ||
(priv->firmware_type == FIRMWARE_TYPE_SYMBOL))
master_wep_flag = HERMES_WEP_PRIVACY_INVOKED |
@@ -314,7 +915,7 @@ int __orinoco_hw_setup_enc(struct orinoco_private *priv)
} else
master_wep_flag = 0;
- if (priv->iw_mode == IW_MODE_MONITOR)
+ if (priv->iw_mode == NL80211_IFTYPE_MONITOR)
master_wep_flag |= HERMES_WEP_HOST_DECRYPT;
/* Master WEP setting : on/off */
@@ -331,20 +932,22 @@ int __orinoco_hw_setup_enc(struct orinoco_private *priv)
}
/* key must be 32 bytes, including the tx and rx MIC keys.
- * rsc must be 8 bytes
- * tsc must be 8 bytes or NULL
+ * rsc must be NULL or up to 8 bytes
+ * tsc must be NULL or up to 8 bytes
*/
-int __orinoco_hw_set_tkip_key(hermes_t *hw, int key_idx, int set_tx,
- u8 *key, u8 *rsc, u8 *tsc)
+int __orinoco_hw_set_tkip_key(struct orinoco_private *priv, int key_idx,
+ int set_tx, u8 *key, u8 *rsc, size_t rsc_len,
+ u8 *tsc, size_t tsc_len)
{
struct {
__le16 idx;
- u8 rsc[IW_ENCODE_SEQ_MAX_SIZE];
+ u8 rsc[ORINOCO_SEQ_LEN];
u8 key[TKIP_KEYLEN];
u8 tx_mic[MIC_KEYLEN];
u8 rx_mic[MIC_KEYLEN];
- u8 tsc[IW_ENCODE_SEQ_MAX_SIZE];
+ u8 tsc[ORINOCO_SEQ_LEN];
} __attribute__ ((packed)) buf;
+ hermes_t *hw = &priv->hw;
int ret;
int err;
int k;
@@ -359,17 +962,22 @@ int __orinoco_hw_set_tkip_key(hermes_t *hw, int key_idx, int set_tx,
memcpy(buf.key, key,
sizeof(buf.key) + sizeof(buf.tx_mic) + sizeof(buf.rx_mic));
- if (rsc == NULL)
- memset(buf.rsc, 0, sizeof(buf.rsc));
- else
- memcpy(buf.rsc, rsc, sizeof(buf.rsc));
+ if (rsc_len > sizeof(buf.rsc))
+ rsc_len = sizeof(buf.rsc);
+
+ if (tsc_len > sizeof(buf.tsc))
+ tsc_len = sizeof(buf.tsc);
- if (tsc == NULL) {
- memset(buf.tsc, 0, sizeof(buf.tsc));
+ memset(buf.rsc, 0, sizeof(buf.rsc));
+ memset(buf.tsc, 0, sizeof(buf.tsc));
+
+ if (rsc != NULL)
+ memcpy(buf.rsc, rsc, rsc_len);
+
+ if (tsc != NULL)
+ memcpy(buf.tsc, tsc, tsc_len);
+ else
buf.tsc[4] = 0x10;
- } else {
- memcpy(buf.tsc, tsc, sizeof(buf.tsc));
- }
/* Wait upto 100ms for tx queue to empty */
for (k = 100; k > 0; k--) {
@@ -395,7 +1003,6 @@ int orinoco_clear_tkip_key(struct orinoco_private *priv, int key_idx)
hermes_t *hw = &priv->hw;
int err;
- memset(&priv->tkip_key[key_idx], 0, sizeof(priv->tkip_key[key_idx]));
err = hermes_write_wordrec(hw, USER_BAP,
HERMES_RID_CNFREMDEFAULTTKIPKEY_AGERE,
key_idx);
@@ -582,3 +1189,124 @@ int orinoco_hw_get_bitratelist(struct orinoco_private *priv,
return 0;
}
+
+int orinoco_hw_trigger_scan(struct orinoco_private *priv,
+ const struct cfg80211_ssid *ssid)
+{
+ struct net_device *dev = priv->ndev;
+ hermes_t *hw = &priv->hw;
+ unsigned long flags;
+ int err = 0;
+
+ if (orinoco_lock(priv, &flags) != 0)
+ return -EBUSY;
+
+ /* Scanning with port 0 disabled would fail */
+ if (!netif_running(dev)) {
+ err = -ENETDOWN;
+ goto out;
+ }
+
+ /* In monitor mode, the scan results are always empty.
+ * Probe responses are passed to the driver as received
+ * frames and could be processed in software. */
+ if (priv->iw_mode == NL80211_IFTYPE_MONITOR) {
+ err = -EOPNOTSUPP;
+ goto out;
+ }
+
+ if (priv->has_hostscan) {
+ switch (priv->firmware_type) {
+ case FIRMWARE_TYPE_SYMBOL:
+ err = hermes_write_wordrec(hw, USER_BAP,
+ HERMES_RID_CNFHOSTSCAN_SYMBOL,
+ HERMES_HOSTSCAN_SYMBOL_ONCE |
+ HERMES_HOSTSCAN_SYMBOL_BCAST);
+ break;
+ case FIRMWARE_TYPE_INTERSIL: {
+ __le16 req[3];
+
+ req[0] = cpu_to_le16(0x3fff); /* All channels */
+ req[1] = cpu_to_le16(0x0001); /* rate 1 Mbps */
+ req[2] = 0; /* Any ESSID */
+ err = HERMES_WRITE_RECORD(hw, USER_BAP,
+ HERMES_RID_CNFHOSTSCAN, &req);
+ break;
+ }
+ case FIRMWARE_TYPE_AGERE:
+ if (ssid->ssid_len > 0) {
+ struct hermes_idstring idbuf;
+ size_t len = ssid->ssid_len;
+
+ idbuf.len = cpu_to_le16(len);
+ memcpy(idbuf.val, ssid->ssid, len);
+
+ err = hermes_write_ltv(hw, USER_BAP,
+ HERMES_RID_CNFSCANSSID_AGERE,
+ HERMES_BYTES_TO_RECLEN(len + 2),
+ &idbuf);
+ } else
+ err = hermes_write_wordrec(hw, USER_BAP,
+ HERMES_RID_CNFSCANSSID_AGERE,
+ 0); /* Any ESSID */
+ if (err)
+ break;
+
+ if (priv->has_ext_scan) {
+ err = hermes_write_wordrec(hw, USER_BAP,
+ HERMES_RID_CNFSCANCHANNELS2GHZ,
+ 0x7FFF);
+ if (err)
+ goto out;
+
+ err = hermes_inquire(hw,
+ HERMES_INQ_CHANNELINFO);
+ } else
+ err = hermes_inquire(hw, HERMES_INQ_SCAN);
+
+ break;
+ }
+ } else
+ err = hermes_inquire(hw, HERMES_INQ_SCAN);
+
+ out:
+ orinoco_unlock(priv, &flags);
+
+ return err;
+}
+
+/* Disassociate from node with BSSID addr */
+int orinoco_hw_disassociate(struct orinoco_private *priv,
+ u8 *addr, u16 reason_code)
+{
+ hermes_t *hw = &priv->hw;
+ int err;
+
+ struct {
+ u8 addr[ETH_ALEN];
+ __le16 reason_code;
+ } __attribute__ ((packed)) buf;
+
+ /* Currently only supported by WPA enabled Agere fw */
+ if (!priv->has_wpa)
+ return -EOPNOTSUPP;
+
+ memcpy(buf.addr, addr, ETH_ALEN);
+ buf.reason_code = cpu_to_le16(reason_code);
+ err = HERMES_WRITE_RECORD(hw, USER_BAP,
+ HERMES_RID_CNFDISASSOCIATE,
+ &buf);
+ return err;
+}
+
+int orinoco_hw_get_current_bssid(struct orinoco_private *priv,
+ u8 *addr)
+{
+ hermes_t *hw = &priv->hw;
+ int err;
+
+ err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENTBSSID,
+ ETH_ALEN, NULL, addr);
+
+ return err;
+}
diff --git a/drivers/net/wireless/orinoco/hw.h b/drivers/net/wireless/orinoco/hw.h
index dc3f23a9c1c..8df6e8752be 100644
--- a/drivers/net/wireless/orinoco/hw.h
+++ b/drivers/net/wireless/orinoco/hw.h
@@ -7,6 +7,7 @@
#include <linux/types.h>
#include <linux/wireless.h>
+#include <net/cfg80211.h>
/* Hardware BAPs */
#define USER_BAP 0
@@ -23,17 +24,22 @@
struct orinoco_private;
struct dev_addr_list;
+int determine_fw_capabilities(struct orinoco_private *priv);
+int orinoco_hw_read_card_settings(struct orinoco_private *priv, u8 *dev_addr);
+int orinoco_hw_allocate_fid(struct orinoco_private *priv);
int orinoco_get_bitratemode(int bitrate, int automatic);
void orinoco_get_ratemode_cfg(int ratemode, int *bitrate, int *automatic);
+int orinoco_hw_program_rids(struct orinoco_private *priv);
int orinoco_hw_get_tkip_iv(struct orinoco_private *priv, int key, u8 *tsc);
int __orinoco_hw_set_bitrate(struct orinoco_private *priv);
int orinoco_hw_get_act_bitrate(struct orinoco_private *priv, int *bitrate);
int __orinoco_hw_set_wap(struct orinoco_private *priv);
int __orinoco_hw_setup_wepkeys(struct orinoco_private *priv);
int __orinoco_hw_setup_enc(struct orinoco_private *priv);
-int __orinoco_hw_set_tkip_key(hermes_t *hw, int key_idx, int set_tx,
- u8 *key, u8 *rsc, u8 *tsc);
+int __orinoco_hw_set_tkip_key(struct orinoco_private *priv, int key_idx,
+ int set_tx, u8 *key, u8 *rsc, size_t rsc_len,
+ u8 *tsc, size_t tsc_len);
int orinoco_clear_tkip_key(struct orinoco_private *priv, int key_idx);
int __orinoco_hw_set_multicast_list(struct orinoco_private *priv,
struct dev_addr_list *mc_list,
@@ -43,5 +49,11 @@ int orinoco_hw_get_essid(struct orinoco_private *priv, int *active,
int orinoco_hw_get_freq(struct orinoco_private *priv);
int orinoco_hw_get_bitratelist(struct orinoco_private *priv,
int *numrates, s32 *rates, int max);
+int orinoco_hw_trigger_scan(struct orinoco_private *priv,
+ const struct cfg80211_ssid *ssid);
+int orinoco_hw_disassociate(struct orinoco_private *priv,
+ u8 *addr, u16 reason_code);
+int orinoco_hw_get_current_bssid(struct orinoco_private *priv,
+ u8 *addr);
#endif /* _ORINOCO_HW_H_ */
diff --git a/drivers/net/wireless/orinoco/main.c b/drivers/net/wireless/orinoco/main.c
index a370e510f19..2c7dc65cd2b 100644
--- a/drivers/net/wireless/orinoco/main.c
+++ b/drivers/net/wireless/orinoco/main.c
@@ -80,6 +80,7 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/delay.h>
+#include <linux/device.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/ethtool.h>
@@ -88,6 +89,7 @@
#include <linux/wireless.h>
#include <linux/ieee80211.h>
#include <net/iw_handler.h>
+#include <net/cfg80211.h>
#include "hermes_rid.h"
#include "hermes_dld.h"
@@ -96,6 +98,7 @@
#include "mic.h"
#include "fw.h"
#include "wext.h"
+#include "cfg.h"
#include "main.h"
#include "orinoco.h"
@@ -142,13 +145,11 @@ static const u8 encaps_hdr[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00};
#define ORINOCO_MIN_MTU 256
#define ORINOCO_MAX_MTU (IEEE80211_MAX_DATA_LEN - ENCAPS_OVERHEAD)
-#define SYMBOL_MAX_VER_LEN (14)
#define MAX_IRQLOOPS_PER_IRQ 10
#define MAX_IRQLOOPS_PER_JIFFY (20000/HZ) /* Based on a guestimate of
* how many events the
* device could
* legitimately generate */
-#define TX_NICBUF_SIZE_BUG 1585 /* Bug in Symbol firmware */
#define DUMMY_FID 0xFFFF
@@ -205,11 +206,21 @@ struct orinoco_rx_data {
struct list_head list;
};
+struct orinoco_scan_data {
+ void *buf;
+ size_t len;
+ int type;
+ struct list_head list;
+};
+
/********************************************************************/
/* Function prototypes */
/********************************************************************/
-static void __orinoco_set_multicast_list(struct net_device *dev);
+static int __orinoco_set_multicast_list(struct net_device *dev);
+static int __orinoco_up(struct orinoco_private *priv);
+static int __orinoco_down(struct orinoco_private *priv);
+static int __orinoco_commit(struct orinoco_private *priv);
/********************************************************************/
/* Internal helper functions */
@@ -218,11 +229,11 @@ static void __orinoco_set_multicast_list(struct net_device *dev);
void set_port_type(struct orinoco_private *priv)
{
switch (priv->iw_mode) {
- case IW_MODE_INFRA:
+ case NL80211_IFTYPE_STATION:
priv->port_type = 1;
priv->createibss = 0;
break;
- case IW_MODE_ADHOC:
+ case NL80211_IFTYPE_ADHOC:
if (priv->prefer_port3) {
priv->port_type = 3;
priv->createibss = 0;
@@ -231,7 +242,7 @@ void set_port_type(struct orinoco_private *priv)
priv->createibss = 1;
}
break;
- case IW_MODE_MONITOR:
+ case NL80211_IFTYPE_MONITOR:
priv->port_type = 3;
priv->createibss = 0;
break;
@@ -247,14 +258,14 @@ void set_port_type(struct orinoco_private *priv)
static int orinoco_open(struct net_device *dev)
{
- struct orinoco_private *priv = netdev_priv(dev);
+ struct orinoco_private *priv = ndev_priv(dev);
unsigned long flags;
int err;
if (orinoco_lock(priv, &flags) != 0)
return -EBUSY;
- err = __orinoco_up(dev);
+ err = __orinoco_up(priv);
if (!err)
priv->open = 1;
@@ -266,7 +277,7 @@ static int orinoco_open(struct net_device *dev)
static int orinoco_stop(struct net_device *dev)
{
- struct orinoco_private *priv = netdev_priv(dev);
+ struct orinoco_private *priv = ndev_priv(dev);
int err = 0;
/* We mustn't use orinoco_lock() here, because we need to be
@@ -276,7 +287,7 @@ static int orinoco_stop(struct net_device *dev)
priv->open = 0;
- err = __orinoco_down(dev);
+ err = __orinoco_down(priv);
spin_unlock_irq(&priv->lock);
@@ -285,14 +296,14 @@ static int orinoco_stop(struct net_device *dev)
static struct net_device_stats *orinoco_get_stats(struct net_device *dev)
{
- struct orinoco_private *priv = netdev_priv(dev);
+ struct orinoco_private *priv = ndev_priv(dev);
return &priv->stats;
}
static void orinoco_set_multicast_list(struct net_device *dev)
{
- struct orinoco_private *priv = netdev_priv(dev);
+ struct orinoco_private *priv = ndev_priv(dev);
unsigned long flags;
if (orinoco_lock(priv, &flags) != 0) {
@@ -307,7 +318,7 @@ static void orinoco_set_multicast_list(struct net_device *dev)
static int orinoco_change_mtu(struct net_device *dev, int new_mtu)
{
- struct orinoco_private *priv = netdev_priv(dev);
+ struct orinoco_private *priv = ndev_priv(dev);
if ((new_mtu < ORINOCO_MIN_MTU) || (new_mtu > ORINOCO_MAX_MTU))
return -EINVAL;
@@ -328,14 +339,16 @@ static int orinoco_change_mtu(struct net_device *dev, int new_mtu)
static int orinoco_xmit(struct sk_buff *skb, struct net_device *dev)
{
- struct orinoco_private *priv = netdev_priv(dev);
+ struct orinoco_private *priv = ndev_priv(dev);
struct net_device_stats *stats = &priv->stats;
+ struct orinoco_tkip_key *key;
hermes_t *hw = &priv->hw;
int err = 0;
u16 txfid = priv->txfid;
struct ethhdr *eh;
int tx_control;
unsigned long flags;
+ int do_mic;
if (!netif_running(dev)) {
printk(KERN_ERR "%s: Tx on stopped device!\n",
@@ -355,7 +368,8 @@ static int orinoco_xmit(struct sk_buff *skb, struct net_device *dev)
return NETDEV_TX_BUSY;
}
- if (!netif_carrier_ok(dev) || (priv->iw_mode == IW_MODE_MONITOR)) {
+ if (!netif_carrier_ok(dev) ||
+ (priv->iw_mode == NL80211_IFTYPE_MONITOR)) {
/* Oops, the firmware hasn't established a connection,
silently drop the packet (this seems to be the
safest approach). */
@@ -366,9 +380,14 @@ static int orinoco_xmit(struct sk_buff *skb, struct net_device *dev)
if (skb->len < ETH_HLEN)
goto drop;
+ key = (struct orinoco_tkip_key *) priv->keys[priv->tx_key].key;
+
+ do_mic = ((priv->encode_alg == ORINOCO_ALG_TKIP) &&
+ (key != NULL));
+
tx_control = HERMES_TXCTRL_TX_OK | HERMES_TXCTRL_TX_EX;
- if (priv->encode_alg == IW_ENCODE_ALG_TKIP)
+ if (do_mic)
tx_control |= (priv->tx_key << HERMES_MIC_KEY_ID_SHIFT) |
HERMES_TXCTRL_MIC;
@@ -450,7 +469,7 @@ static int orinoco_xmit(struct sk_buff *skb, struct net_device *dev)
}
/* Calculate Michael MIC */
- if (priv->encode_alg == IW_ENCODE_ALG_TKIP) {
+ if (do_mic) {
u8 mic_buf[MICHAEL_MIC_LEN + 1];
u8 *mic;
size_t offset;
@@ -468,8 +487,7 @@ static int orinoco_xmit(struct sk_buff *skb, struct net_device *dev)
len = MICHAEL_MIC_LEN;
}
- orinoco_mic(priv->tx_tfm_mic,
- priv->tkip_key[priv->tx_key].tx_mic,
+ orinoco_mic(priv->tx_tfm_mic, key->tx_mic,
eh->h_dest, eh->h_source, 0 /* priority */,
skb->data + ETH_HLEN, skb->len - ETH_HLEN, mic);
@@ -518,7 +536,7 @@ static int orinoco_xmit(struct sk_buff *skb, struct net_device *dev)
static void __orinoco_ev_alloc(struct net_device *dev, hermes_t *hw)
{
- struct orinoco_private *priv = netdev_priv(dev);
+ struct orinoco_private *priv = ndev_priv(dev);
u16 fid = hermes_read_regn(hw, ALLOCFID);
if (fid != priv->txfid) {
@@ -533,7 +551,7 @@ static void __orinoco_ev_alloc(struct net_device *dev, hermes_t *hw)
static void __orinoco_ev_tx(struct net_device *dev, hermes_t *hw)
{
- struct orinoco_private *priv = netdev_priv(dev);
+ struct orinoco_private *priv = ndev_priv(dev);
struct net_device_stats *stats = &priv->stats;
stats->tx_packets++;
@@ -545,7 +563,7 @@ static void __orinoco_ev_tx(struct net_device *dev, hermes_t *hw)
static void __orinoco_ev_txexc(struct net_device *dev, hermes_t *hw)
{
- struct orinoco_private *priv = netdev_priv(dev);
+ struct orinoco_private *priv = ndev_priv(dev);
struct net_device_stats *stats = &priv->stats;
u16 fid = hermes_read_regn(hw, TXCOMPLFID);
u16 status;
@@ -601,7 +619,7 @@ static void __orinoco_ev_txexc(struct net_device *dev, hermes_t *hw)
static void orinoco_tx_timeout(struct net_device *dev)
{
- struct orinoco_private *priv = netdev_priv(dev);
+ struct orinoco_private *priv = ndev_priv(dev);
struct net_device_stats *stats = &priv->stats;
struct hermes *hw = &priv->hw;
@@ -650,7 +668,7 @@ static void orinoco_stat_gather(struct net_device *dev,
struct sk_buff *skb,
struct hermes_rx_descriptor *desc)
{
- struct orinoco_private *priv = netdev_priv(dev);
+ struct orinoco_private *priv = ndev_priv(dev);
/* Using spy support with lots of Rx packets, like in an
* infrastructure (AP), will really slow down everything, because
@@ -687,7 +705,7 @@ static void orinoco_rx_monitor(struct net_device *dev, u16 rxfid,
int err;
int len;
struct sk_buff *skb;
- struct orinoco_private *priv = netdev_priv(dev);
+ struct orinoco_private *priv = ndev_priv(dev);
struct net_device_stats *stats = &priv->stats;
hermes_t *hw = &priv->hw;
@@ -778,7 +796,7 @@ static void orinoco_rx_monitor(struct net_device *dev, u16 rxfid,
static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw)
{
- struct orinoco_private *priv = netdev_priv(dev);
+ struct orinoco_private *priv = ndev_priv(dev);
struct net_device_stats *stats = &priv->stats;
struct iw_statistics *wstats = &priv->wstats;
struct sk_buff *skb = NULL;
@@ -816,7 +834,7 @@ static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw)
}
/* Handle frames in monitor mode */
- if (priv->iw_mode == IW_MODE_MONITOR) {
+ if (priv->iw_mode == NL80211_IFTYPE_MONITOR) {
orinoco_rx_monitor(dev, rxfid, desc);
goto out;
}
@@ -902,7 +920,7 @@ static void orinoco_rx(struct net_device *dev,
struct hermes_rx_descriptor *desc,
struct sk_buff *skb)
{
- struct orinoco_private *priv = netdev_priv(dev);
+ struct orinoco_private *priv = ndev_priv(dev);
struct net_device_stats *stats = &priv->stats;
u16 status, fc;
int length;
@@ -914,6 +932,7 @@ static void orinoco_rx(struct net_device *dev,
/* Calculate and check MIC */
if (status & HERMES_RXSTAT_MIC) {
+ struct orinoco_tkip_key *key;
int key_id = ((status & HERMES_RXSTAT_MIC_KEY_ID) >>
HERMES_MIC_KEY_ID_SHIFT);
u8 mic[MICHAEL_MIC_LEN];
@@ -927,14 +946,18 @@ static void orinoco_rx(struct net_device *dev,
skb_trim(skb, skb->len - MICHAEL_MIC_LEN);
length -= MICHAEL_MIC_LEN;
- orinoco_mic(priv->rx_tfm_mic,
- priv->tkip_key[key_id].rx_mic,
- desc->addr1,
- src,
+ key = (struct orinoco_tkip_key *) priv->keys[key_id].key;
+
+ if (!key) {
+ printk(KERN_WARNING "%s: Received encrypted frame from "
+ "%pM using key %i, but key is not installed\n",
+ dev->name, src, key_id);
+ goto drop;
+ }
+
+ orinoco_mic(priv->rx_tfm_mic, key->rx_mic, desc->addr1, src,
0, /* priority or QoS? */
- skb->data,
- skb->len,
- &mic[0]);
+ skb->data, skb->len, &mic[0]);
if (memcmp(mic, rxmic,
MICHAEL_MIC_LEN)) {
@@ -1016,8 +1039,8 @@ static void orinoco_rx(struct net_device *dev,
static void orinoco_rx_isr_tasklet(unsigned long data)
{
- struct net_device *dev = (struct net_device *) data;
- struct orinoco_private *priv = netdev_priv(dev);
+ struct orinoco_private *priv = (struct orinoco_private *) data;
+ struct net_device *dev = priv->ndev;
struct orinoco_rx_data *rx_data, *temp;
struct hermes_rx_descriptor *desc;
struct sk_buff *skb;
@@ -1260,9 +1283,81 @@ static void orinoco_send_wevents(struct work_struct *work)
orinoco_unlock(priv, &flags);
}
+static void qbuf_scan(struct orinoco_private *priv, void *buf,
+ int len, int type)
+{
+ struct orinoco_scan_data *sd;
+ unsigned long flags;
+
+ sd = kmalloc(sizeof(*sd), GFP_ATOMIC);
+ sd->buf = buf;
+ sd->len = len;
+ sd->type = type;
+
+ spin_lock_irqsave(&priv->scan_lock, flags);
+ list_add_tail(&sd->list, &priv->scan_list);
+ spin_unlock_irqrestore(&priv->scan_lock, flags);
+
+ schedule_work(&priv->process_scan);
+}
+
+static void qabort_scan(struct orinoco_private *priv)
+{
+ struct orinoco_scan_data *sd;
+ unsigned long flags;
+
+ sd = kmalloc(sizeof(*sd), GFP_ATOMIC);
+ sd->len = -1; /* Abort */
+
+ spin_lock_irqsave(&priv->scan_lock, flags);
+ list_add_tail(&sd->list, &priv->scan_list);
+ spin_unlock_irqrestore(&priv->scan_lock, flags);
+
+ schedule_work(&priv->process_scan);
+}
+
+static void orinoco_process_scan_results(struct work_struct *work)
+{
+ struct orinoco_private *priv =
+ container_of(work, struct orinoco_private, process_scan);
+ struct orinoco_scan_data *sd, *temp;
+ unsigned long flags;
+ void *buf;
+ int len;
+ int type;
+
+ spin_lock_irqsave(&priv->scan_lock, flags);
+ list_for_each_entry_safe(sd, temp, &priv->scan_list, list) {
+ spin_unlock_irqrestore(&priv->scan_lock, flags);
+
+ buf = sd->buf;
+ len = sd->len;
+ type = sd->type;
+
+ list_del(&sd->list);
+ kfree(sd);
+
+ if (len > 0) {
+ if (type == HERMES_INQ_CHANNELINFO)
+ orinoco_add_extscan_result(priv, buf, len);
+ else
+ orinoco_add_hostscan_results(priv, buf, len);
+
+ kfree(buf);
+ } else if (priv->scan_request) {
+ /* Either abort or complete the scan */
+ cfg80211_scan_done(priv->scan_request, (len < 0));
+ priv->scan_request = NULL;
+ }
+
+ spin_lock_irqsave(&priv->scan_lock, flags);
+ }
+ spin_unlock_irqrestore(&priv->scan_lock, flags);
+}
+
static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw)
{
- struct orinoco_private *priv = netdev_priv(dev);
+ struct orinoco_private *priv = ndev_priv(dev);
u16 infofid;
struct {
__le16 len;
@@ -1327,7 +1422,7 @@ static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw)
u16 newstatus;
int connected;
- if (priv->iw_mode == IW_MODE_MONITOR)
+ if (priv->iw_mode == NL80211_IFTYPE_MONITOR)
break;
if (len != sizeof(linkstatus)) {
@@ -1346,7 +1441,7 @@ static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw)
* the hostscan frame can be requested. */
if (newstatus == HERMES_LINKSTATUS_AP_OUT_OF_RANGE &&
priv->firmware_type == FIRMWARE_TYPE_SYMBOL &&
- priv->has_hostscan && priv->scan_inprogress) {
+ priv->has_hostscan && priv->scan_request) {
hermes_inquire(hw, HERMES_INQ_HOSTSCAN_SYMBOL);
break;
}
@@ -1372,7 +1467,7 @@ static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw)
}
break;
case HERMES_INQ_SCAN:
- if (!priv->scan_inprogress && priv->bssid_fixed &&
+ if (!priv->scan_request && priv->bssid_fixed &&
priv->firmware_type == FIRMWARE_TYPE_INTERSIL) {
schedule_work(&priv->join_work);
break;
@@ -1382,30 +1477,30 @@ static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw)
case HERMES_INQ_HOSTSCAN_SYMBOL: {
/* Result of a scanning. Contains information about
* cells in the vicinity - Jean II */
- union iwreq_data wrqu;
unsigned char *buf;
- /* Scan is no longer in progress */
- priv->scan_inprogress = 0;
-
/* Sanity check */
if (len > 4096) {
printk(KERN_WARNING "%s: Scan results too large (%d bytes)\n",
dev->name, len);
+ qabort_scan(priv);
break;
}
/* Allocate buffer for results */
buf = kmalloc(len, GFP_ATOMIC);
- if (buf == NULL)
+ if (buf == NULL) {
/* No memory, so can't printk()... */
+ qabort_scan(priv);
break;
+ }
/* Read scan data */
err = hermes_bap_pread(hw, IRQ_BAP, (void *) buf, len,
infofid, sizeof(info));
if (err) {
kfree(buf);
+ qabort_scan(priv);
break;
}
@@ -1419,24 +1514,14 @@ static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw)
}
#endif /* ORINOCO_DEBUG */
- if (orinoco_process_scan_results(priv, buf, len) == 0) {
- /* Send an empty event to user space.
- * We don't send the received data on the event because
- * it would require us to do complex transcoding, and
- * we want to minimise the work done in the irq handler
- * Use a request to extract the data - Jean II */
- wrqu.data.length = 0;
- wrqu.data.flags = 0;
- wireless_send_event(dev, SIOCGIWSCAN, &wrqu, NULL);
- }
- kfree(buf);
+ qbuf_scan(priv, buf, len, type);
}
break;
case HERMES_INQ_CHANNELINFO:
{
struct agere_ext_scan_info *bss;
- if (!priv->scan_inprogress) {
+ if (!priv->scan_request) {
printk(KERN_DEBUG "%s: Got chaninfo without scan, "
"len=%d\n", dev->name, len);
break;
@@ -1444,25 +1529,12 @@ static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw)
/* An empty result indicates that the scan is complete */
if (len == 0) {
- union iwreq_data wrqu;
-
- /* Scan is no longer in progress */
- priv->scan_inprogress = 0;
-
- wrqu.data.length = 0;
- wrqu.data.flags = 0;
- wireless_send_event(dev, SIOCGIWSCAN, &wrqu, NULL);
+ qbuf_scan(priv, NULL, len, type);
break;
}
/* Sanity check */
- else if (len > sizeof(*bss)) {
- printk(KERN_WARNING
- "%s: Ext scan results too large (%d bytes). "
- "Truncating results to %zd bytes.\n",
- dev->name, len, sizeof(*bss));
- len = sizeof(*bss);
- } else if (len < (offsetof(struct agere_ext_scan_info,
+ else if (len < (offsetof(struct agere_ext_scan_info,
data) + 2)) {
/* Drop this result now so we don't have to
* keep checking later */
@@ -1472,21 +1544,18 @@ static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw)
break;
}
- bss = kmalloc(sizeof(*bss), GFP_ATOMIC);
+ bss = kmalloc(len, GFP_ATOMIC);
if (bss == NULL)
break;
/* Read scan data */
err = hermes_bap_pread(hw, IRQ_BAP, (void *) bss, len,
infofid, sizeof(info));
- if (err) {
+ if (err)
kfree(bss);
- break;
- }
-
- orinoco_add_ext_scan_result(priv, bss);
+ else
+ qbuf_scan(priv, bss, len, type);
- kfree(bss);
break;
}
case HERMES_INQ_SEC_STAT_AGERE:
@@ -1501,6 +1570,8 @@ static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw)
/* We don't actually do anything about it */
break;
}
+
+ return;
}
static void __orinoco_ev_infdrop(struct net_device *dev, hermes_t *hw)
@@ -1513,15 +1584,15 @@ static void __orinoco_ev_infdrop(struct net_device *dev, hermes_t *hw)
/* Internal hardware control routines */
/********************************************************************/
-int __orinoco_up(struct net_device *dev)
+static int __orinoco_up(struct orinoco_private *priv)
{
- struct orinoco_private *priv = netdev_priv(dev);
+ struct net_device *dev = priv->ndev;
struct hermes *hw = &priv->hw;
int err;
netif_carrier_off(dev); /* just to make sure */
- err = __orinoco_program_rids(dev);
+ err = __orinoco_commit(priv);
if (err) {
printk(KERN_ERR "%s: Error %d configuring card\n",
dev->name, err);
@@ -1541,11 +1612,10 @@ int __orinoco_up(struct net_device *dev)
return 0;
}
-EXPORT_SYMBOL(__orinoco_up);
-int __orinoco_down(struct net_device *dev)
+static int __orinoco_down(struct orinoco_private *priv)
{
- struct orinoco_private *priv = netdev_priv(dev);
+ struct net_device *dev = priv->ndev;
struct hermes *hw = &priv->hw;
int err;
@@ -1573,31 +1643,9 @@ int __orinoco_down(struct net_device *dev)
return 0;
}
-EXPORT_SYMBOL(__orinoco_down);
-
-static int orinoco_allocate_fid(struct net_device *dev)
-{
- struct orinoco_private *priv = netdev_priv(dev);
- struct hermes *hw = &priv->hw;
- int err;
-
- err = hermes_allocate(hw, priv->nicbuf_size, &priv->txfid);
- if (err == -EIO && priv->nicbuf_size > TX_NICBUF_SIZE_BUG) {
- /* Try workaround for old Symbol firmware bug */
- priv->nicbuf_size = TX_NICBUF_SIZE_BUG;
- err = hermes_allocate(hw, priv->nicbuf_size, &priv->txfid);
-
- printk(KERN_WARNING "%s: firmware ALLOC bug detected "
- "(old Symbol firmware?). Work around %s\n",
- dev->name, err ? "failed!" : "ok.");
- }
-
- return err;
-}
-int orinoco_reinit_firmware(struct net_device *dev)
+static int orinoco_reinit_firmware(struct orinoco_private *priv)
{
- struct orinoco_private *priv = netdev_priv(dev);
struct hermes *hw = &priv->hw;
int err;
@@ -1608,246 +1656,15 @@ int orinoco_reinit_firmware(struct net_device *dev)
priv->do_fw_download = 0;
}
if (!err)
- err = orinoco_allocate_fid(dev);
+ err = orinoco_hw_allocate_fid(priv);
return err;
}
-EXPORT_SYMBOL(orinoco_reinit_firmware);
-
-int __orinoco_program_rids(struct net_device *dev)
-{
- struct orinoco_private *priv = netdev_priv(dev);
- hermes_t *hw = &priv->hw;
- int err;
- struct hermes_idstring idbuf;
-
- /* Set the MAC address */
- err = hermes_write_ltv(hw, USER_BAP, HERMES_RID_CNFOWNMACADDR,
- HERMES_BYTES_TO_RECLEN(ETH_ALEN), dev->dev_addr);
- if (err) {
- printk(KERN_ERR "%s: Error %d setting MAC address\n",
- dev->name, err);
- return err;
- }
-
- /* Set up the link mode */
- err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNFPORTTYPE,
- priv->port_type);
- if (err) {
- printk(KERN_ERR "%s: Error %d setting port type\n",
- dev->name, err);
- return err;
- }
- /* Set the channel/frequency */
- if (priv->channel != 0 && priv->iw_mode != IW_MODE_INFRA) {
- err = hermes_write_wordrec(hw, USER_BAP,
- HERMES_RID_CNFOWNCHANNEL,
- priv->channel);
- if (err) {
- printk(KERN_ERR "%s: Error %d setting channel %d\n",
- dev->name, err, priv->channel);
- return err;
- }
- }
-
- if (priv->has_ibss) {
- u16 createibss;
-
- if ((strlen(priv->desired_essid) == 0) && (priv->createibss)) {
- printk(KERN_WARNING "%s: This firmware requires an "
- "ESSID in IBSS-Ad-Hoc mode.\n", dev->name);
- /* With wvlan_cs, in this case, we would crash.
- * hopefully, this driver will behave better...
- * Jean II */
- createibss = 0;
- } else {
- createibss = priv->createibss;
- }
-
- err = hermes_write_wordrec(hw, USER_BAP,
- HERMES_RID_CNFCREATEIBSS,
- createibss);
- if (err) {
- printk(KERN_ERR "%s: Error %d setting CREATEIBSS\n",
- dev->name, err);
- return err;
- }
- }
- /* Set the desired BSSID */
- err = __orinoco_hw_set_wap(priv);
- if (err) {
- printk(KERN_ERR "%s: Error %d setting AP address\n",
- dev->name, err);
- return err;
- }
- /* Set the desired ESSID */
- idbuf.len = cpu_to_le16(strlen(priv->desired_essid));
- memcpy(&idbuf.val, priv->desired_essid, sizeof(idbuf.val));
- /* WinXP wants partner to configure OWNSSID even in IBSS mode. (jimc) */
- err = hermes_write_ltv(hw, USER_BAP, HERMES_RID_CNFOWNSSID,
- HERMES_BYTES_TO_RECLEN(strlen(priv->desired_essid)+2),
- &idbuf);
- if (err) {
- printk(KERN_ERR "%s: Error %d setting OWNSSID\n",
- dev->name, err);
- return err;
- }
- err = hermes_write_ltv(hw, USER_BAP, HERMES_RID_CNFDESIREDSSID,
- HERMES_BYTES_TO_RECLEN(strlen(priv->desired_essid)+2),
- &idbuf);
- if (err) {
- printk(KERN_ERR "%s: Error %d setting DESIREDSSID\n",
- dev->name, err);
- return err;
- }
-
- /* Set the station name */
- idbuf.len = cpu_to_le16(strlen(priv->nick));
- memcpy(&idbuf.val, priv->nick, sizeof(idbuf.val));
- err = hermes_write_ltv(hw, USER_BAP, HERMES_RID_CNFOWNNAME,
- HERMES_BYTES_TO_RECLEN(strlen(priv->nick)+2),
- &idbuf);
- if (err) {
- printk(KERN_ERR "%s: Error %d setting nickname\n",
- dev->name, err);
- return err;
- }
-
- /* Set AP density */
- if (priv->has_sensitivity) {
- err = hermes_write_wordrec(hw, USER_BAP,
- HERMES_RID_CNFSYSTEMSCALE,
- priv->ap_density);
- if (err) {
- printk(KERN_WARNING "%s: Error %d setting SYSTEMSCALE. "
- "Disabling sensitivity control\n",
- dev->name, err);
-
- priv->has_sensitivity = 0;
- }
- }
-
- /* Set RTS threshold */
- err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNFRTSTHRESHOLD,
- priv->rts_thresh);
- if (err) {
- printk(KERN_ERR "%s: Error %d setting RTS threshold\n",
- dev->name, err);
- return err;
- }
-
- /* Set fragmentation threshold or MWO robustness */
- if (priv->has_mwo)
- err = hermes_write_wordrec(hw, USER_BAP,
- HERMES_RID_CNFMWOROBUST_AGERE,
- priv->mwo_robust);
- else
- err = hermes_write_wordrec(hw, USER_BAP,
- HERMES_RID_CNFFRAGMENTATIONTHRESHOLD,
- priv->frag_thresh);
- if (err) {
- printk(KERN_ERR "%s: Error %d setting fragmentation\n",
- dev->name, err);
- return err;
- }
-
- /* Set bitrate */
- err = __orinoco_hw_set_bitrate(priv);
- if (err) {
- printk(KERN_ERR "%s: Error %d setting bitrate\n",
- dev->name, err);
- return err;
- }
-
- /* Set power management */
- if (priv->has_pm) {
- err = hermes_write_wordrec(hw, USER_BAP,
- HERMES_RID_CNFPMENABLED,
- priv->pm_on);
- if (err) {
- printk(KERN_ERR "%s: Error %d setting up PM\n",
- dev->name, err);
- return err;
- }
-
- err = hermes_write_wordrec(hw, USER_BAP,
- HERMES_RID_CNFMULTICASTRECEIVE,
- priv->pm_mcast);
- if (err) {
- printk(KERN_ERR "%s: Error %d setting up PM\n",
- dev->name, err);
- return err;
- }
- err = hermes_write_wordrec(hw, USER_BAP,
- HERMES_RID_CNFMAXSLEEPDURATION,
- priv->pm_period);
- if (err) {
- printk(KERN_ERR "%s: Error %d setting up PM\n",
- dev->name, err);
- return err;
- }
- err = hermes_write_wordrec(hw, USER_BAP,
- HERMES_RID_CNFPMHOLDOVERDURATION,
- priv->pm_timeout);
- if (err) {
- printk(KERN_ERR "%s: Error %d setting up PM\n",
- dev->name, err);
- return err;
- }
- }
-
- /* Set preamble - only for Symbol so far... */
- if (priv->has_preamble) {
- err = hermes_write_wordrec(hw, USER_BAP,
- HERMES_RID_CNFPREAMBLE_SYMBOL,
- priv->preamble);
- if (err) {
- printk(KERN_ERR "%s: Error %d setting preamble\n",
- dev->name, err);
- return err;
- }
- }
-
- /* Set up encryption */
- if (priv->has_wep || priv->has_wpa) {
- err = __orinoco_hw_setup_enc(priv);
- if (err) {
- printk(KERN_ERR "%s: Error %d activating encryption\n",
- dev->name, err);
- return err;
- }
- }
-
- if (priv->iw_mode == IW_MODE_MONITOR) {
- /* Enable monitor mode */
- dev->type = ARPHRD_IEEE80211;
- err = hermes_docmd_wait(hw, HERMES_CMD_TEST |
- HERMES_TEST_MONITOR, 0, NULL);
- } else {
- /* Disable monitor mode */
- dev->type = ARPHRD_ETHER;
- err = hermes_docmd_wait(hw, HERMES_CMD_TEST |
- HERMES_TEST_STOP, 0, NULL);
- }
- if (err)
- return err;
-
- /* Set promiscuity / multicast*/
- priv->promiscuous = 0;
- priv->mc_count = 0;
-
- /* FIXME: what about netif_tx_lock */
- __orinoco_set_multicast_list(dev);
-
- return 0;
-}
-
-/* FIXME: return int? */
-static void
+static int
__orinoco_set_multicast_list(struct net_device *dev)
{
- struct orinoco_private *priv = netdev_priv(dev);
+ struct orinoco_private *priv = ndev_priv(dev);
int err = 0;
int promisc, mc_count;
@@ -1864,6 +1681,8 @@ __orinoco_set_multicast_list(struct net_device *dev)
err = __orinoco_hw_set_multicast_list(priv, dev->mc_list, mc_count,
promisc);
+
+ return err;
}
/* This must be called from user context, without locks held - use
@@ -1896,9 +1715,11 @@ void orinoco_reset(struct work_struct *work)
orinoco_unlock(priv, &flags);
- /* Scanning support: Cleanup of driver struct */
- orinoco_clear_scan_results(priv, 0);
- priv->scan_inprogress = 0;
+ /* Scanning support: Notify scan cancellation */
+ if (priv->scan_request) {
+ cfg80211_scan_done(priv->scan_request, 1);
+ priv->scan_request = NULL;
+ }
if (priv->hard_reset) {
err = (*priv->hard_reset)(priv);
@@ -1909,7 +1730,7 @@ void orinoco_reset(struct work_struct *work)
}
}
- err = orinoco_reinit_firmware(dev);
+ err = orinoco_reinit_firmware(priv);
if (err) {
printk(KERN_ERR "%s: orinoco_reset: Error %d re-initializing firmware\n",
dev->name, err);
@@ -1924,7 +1745,7 @@ void orinoco_reset(struct work_struct *work)
/* priv->open or priv->hw_unavailable might have changed while
* we dropped the lock */
if (priv->open && (!priv->hw_unavailable)) {
- err = __orinoco_up(dev);
+ err = __orinoco_up(priv);
if (err) {
printk(KERN_ERR "%s: orinoco_reset: Error %d reenabling card\n",
dev->name, err);
@@ -1941,6 +1762,64 @@ void orinoco_reset(struct work_struct *work)
printk(KERN_ERR "%s: Device has been disabled!\n", dev->name);
}
+static int __orinoco_commit(struct orinoco_private *priv)
+{
+ struct net_device *dev = priv->ndev;
+ int err = 0;
+
+ err = orinoco_hw_program_rids(priv);
+
+ /* FIXME: what about netif_tx_lock */
+ (void) __orinoco_set_multicast_list(dev);
+
+ return err;
+}
+
+/* Ensures configuration changes are applied. May result in a reset.
+ * The caller should hold priv->lock
+ */
+int orinoco_commit(struct orinoco_private *priv)
+{
+ struct net_device *dev = priv->ndev;
+ hermes_t *hw = &priv->hw;
+ int err;
+
+ if (priv->broken_disableport) {
+ schedule_work(&priv->reset_work);
+ return 0;
+ }
+
+ err = hermes_disable_port(hw, 0);
+ if (err) {
+ printk(KERN_WARNING "%s: Unable to disable port "
+ "while reconfiguring card\n", dev->name);
+ priv->broken_disableport = 1;
+ goto out;
+ }
+
+ err = __orinoco_commit(priv);
+ if (err) {
+ printk(KERN_WARNING "%s: Unable to reconfigure card\n",
+ dev->name);
+ goto out;
+ }
+
+ err = hermes_enable_port(hw, 0);
+ if (err) {
+ printk(KERN_WARNING "%s: Unable to enable port while reconfiguring card\n",
+ dev->name);
+ goto out;
+ }
+
+ out:
+ if (err) {
+ printk(KERN_WARNING "%s: Resetting instead...\n", dev->name);
+ schedule_work(&priv->reset_work);
+ err = 0;
+ }
+ return err;
+}
+
/********************************************************************/
/* Interrupt handler */
/********************************************************************/
@@ -1960,8 +1839,8 @@ static void __orinoco_ev_wterr(struct net_device *dev, hermes_t *hw)
irqreturn_t orinoco_interrupt(int irq, void *dev_id)
{
- struct net_device *dev = dev_id;
- struct orinoco_private *priv = netdev_priv(dev);
+ struct orinoco_private *priv = dev_id;
+ struct net_device *dev = priv->ndev;
hermes_t *hw = &priv->hw;
int count = MAX_IRQLOOPS_PER_IRQ;
u16 evstat, events;
@@ -2096,227 +1975,12 @@ static void orinoco_unregister_pm_notifier(struct orinoco_private *priv)
/* Initialization */
/********************************************************************/
-struct comp_id {
- u16 id, variant, major, minor;
-} __attribute__ ((packed));
-
-static inline fwtype_t determine_firmware_type(struct comp_id *nic_id)
-{
- if (nic_id->id < 0x8000)
- return FIRMWARE_TYPE_AGERE;
- else if (nic_id->id == 0x8000 && nic_id->major == 0)
- return FIRMWARE_TYPE_SYMBOL;
- else
- return FIRMWARE_TYPE_INTERSIL;
-}
-
-/* Set priv->firmware type, determine firmware properties */
-static int determine_firmware(struct net_device *dev)
+int orinoco_init(struct orinoco_private *priv)
{
- struct orinoco_private *priv = netdev_priv(dev);
- hermes_t *hw = &priv->hw;
- int err;
- struct comp_id nic_id, sta_id;
- unsigned int firmver;
- char tmp[SYMBOL_MAX_VER_LEN+1] __attribute__((aligned(2)));
-
- /* Get the hardware version */
- err = HERMES_READ_RECORD(hw, USER_BAP, HERMES_RID_NICID, &nic_id);
- if (err) {
- printk(KERN_ERR "%s: Cannot read hardware identity: error %d\n",
- dev->name, err);
- return err;
- }
-
- le16_to_cpus(&nic_id.id);
- le16_to_cpus(&nic_id.variant);
- le16_to_cpus(&nic_id.major);
- le16_to_cpus(&nic_id.minor);
- printk(KERN_DEBUG "%s: Hardware identity %04x:%04x:%04x:%04x\n",
- dev->name, nic_id.id, nic_id.variant,
- nic_id.major, nic_id.minor);
-
- priv->firmware_type = determine_firmware_type(&nic_id);
-
- /* Get the firmware version */
- err = HERMES_READ_RECORD(hw, USER_BAP, HERMES_RID_STAID, &sta_id);
- if (err) {
- printk(KERN_ERR "%s: Cannot read station identity: error %d\n",
- dev->name, err);
- return err;
- }
-
- le16_to_cpus(&sta_id.id);
- le16_to_cpus(&sta_id.variant);
- le16_to_cpus(&sta_id.major);
- le16_to_cpus(&sta_id.minor);
- printk(KERN_DEBUG "%s: Station identity %04x:%04x:%04x:%04x\n",
- dev->name, sta_id.id, sta_id.variant,
- sta_id.major, sta_id.minor);
-
- switch (sta_id.id) {
- case 0x15:
- printk(KERN_ERR "%s: Primary firmware is active\n",
- dev->name);
- return -ENODEV;
- case 0x14b:
- printk(KERN_ERR "%s: Tertiary firmware is active\n",
- dev->name);
- return -ENODEV;
- case 0x1f: /* Intersil, Agere, Symbol Spectrum24 */
- case 0x21: /* Symbol Spectrum24 Trilogy */
- break;
- default:
- printk(KERN_NOTICE "%s: Unknown station ID, please report\n",
- dev->name);
- break;
- }
-
- /* Default capabilities */
- priv->has_sensitivity = 1;
- priv->has_mwo = 0;
- priv->has_preamble = 0;
- priv->has_port3 = 1;
- priv->has_ibss = 1;
- priv->has_wep = 0;
- priv->has_big_wep = 0;
- priv->has_alt_txcntl = 0;
- priv->has_ext_scan = 0;
- priv->has_wpa = 0;
- priv->do_fw_download = 0;
-
- /* Determine capabilities from the firmware version */
- switch (priv->firmware_type) {
- case FIRMWARE_TYPE_AGERE:
- /* Lucent Wavelan IEEE, Lucent Orinoco, Cabletron RoamAbout,
- ELSA, Melco, HP, IBM, Dell 1150, Compaq 110/210 */
- snprintf(priv->fw_name, sizeof(priv->fw_name) - 1,
- "Lucent/Agere %d.%02d", sta_id.major, sta_id.minor);
-
- firmver = ((unsigned long)sta_id.major << 16) | sta_id.minor;
-
- priv->has_ibss = (firmver >= 0x60006);
- priv->has_wep = (firmver >= 0x40020);
- priv->has_big_wep = 1; /* FIXME: this is wrong - how do we tell
- Gold cards from the others? */
- priv->has_mwo = (firmver >= 0x60000);
- priv->has_pm = (firmver >= 0x40020); /* Don't work in 7.52 ? */
- priv->ibss_port = 1;
- priv->has_hostscan = (firmver >= 0x8000a);
- priv->do_fw_download = 1;
- priv->broken_monitor = (firmver >= 0x80000);
- priv->has_alt_txcntl = (firmver >= 0x90000); /* All 9.x ? */
- priv->has_ext_scan = (firmver >= 0x90000); /* All 9.x ? */
- priv->has_wpa = (firmver >= 0x9002a);
- /* Tested with Agere firmware :
- * 1.16 ; 4.08 ; 4.52 ; 6.04 ; 6.16 ; 7.28 => Jean II
- * Tested CableTron firmware : 4.32 => Anton */
- break;
- case FIRMWARE_TYPE_SYMBOL:
- /* Symbol , 3Com AirConnect, Intel, Ericsson WLAN */
- /* Intel MAC : 00:02:B3:* */
- /* 3Com MAC : 00:50:DA:* */
- memset(tmp, 0, sizeof(tmp));
- /* Get the Symbol firmware version */
- err = hermes_read_ltv(hw, USER_BAP,
- HERMES_RID_SECONDARYVERSION_SYMBOL,
- SYMBOL_MAX_VER_LEN, NULL, &tmp);
- if (err) {
- printk(KERN_WARNING
- "%s: Error %d reading Symbol firmware info. "
- "Wildly guessing capabilities...\n",
- dev->name, err);
- firmver = 0;
- tmp[0] = '\0';
- } else {
- /* The firmware revision is a string, the format is
- * something like : "V2.20-01".
- * Quick and dirty parsing... - Jean II
- */
- firmver = ((tmp[1] - '0') << 16)
- | ((tmp[3] - '0') << 12)
- | ((tmp[4] - '0') << 8)
- | ((tmp[6] - '0') << 4)
- | (tmp[7] - '0');
-
- tmp[SYMBOL_MAX_VER_LEN] = '\0';
- }
-
- snprintf(priv->fw_name, sizeof(priv->fw_name) - 1,
- "Symbol %s", tmp);
-
- priv->has_ibss = (firmver >= 0x20000);
- priv->has_wep = (firmver >= 0x15012);
- priv->has_big_wep = (firmver >= 0x20000);
- priv->has_pm = (firmver >= 0x20000 && firmver < 0x22000) ||
- (firmver >= 0x29000 && firmver < 0x30000) ||
- firmver >= 0x31000;
- priv->has_preamble = (firmver >= 0x20000);
- priv->ibss_port = 4;
-
- /* Symbol firmware is found on various cards, but
- * there has been no attempt to check firmware
- * download on non-spectrum_cs based cards.
- *
- * Given that the Agere firmware download works
- * differently, we should avoid doing a firmware
- * download with the Symbol algorithm on non-spectrum
- * cards.
- *
- * For now we can identify a spectrum_cs based card
- * because it has a firmware reset function.
- */
- priv->do_fw_download = (priv->stop_fw != NULL);
-
- priv->broken_disableport = (firmver == 0x25013) ||
- (firmver >= 0x30000 && firmver <= 0x31000);
- priv->has_hostscan = (firmver >= 0x31001) ||
- (firmver >= 0x29057 && firmver < 0x30000);
- /* Tested with Intel firmware : 0x20015 => Jean II */
- /* Tested with 3Com firmware : 0x15012 & 0x22001 => Jean II */
- break;
- case FIRMWARE_TYPE_INTERSIL:
- /* D-Link, Linksys, Adtron, ZoomAir, and many others...
- * Samsung, Compaq 100/200 and Proxim are slightly
- * different and less well tested */
- /* D-Link MAC : 00:40:05:* */
- /* Addtron MAC : 00:90:D1:* */
- snprintf(priv->fw_name, sizeof(priv->fw_name) - 1,
- "Intersil %d.%d.%d", sta_id.major, sta_id.minor,
- sta_id.variant);
-
- firmver = ((unsigned long)sta_id.major << 16) |
- ((unsigned long)sta_id.minor << 8) | sta_id.variant;
-
- priv->has_ibss = (firmver >= 0x000700); /* FIXME */
- priv->has_big_wep = priv->has_wep = (firmver >= 0x000800);
- priv->has_pm = (firmver >= 0x000700);
- priv->has_hostscan = (firmver >= 0x010301);
-
- if (firmver >= 0x000800)
- priv->ibss_port = 0;
- else {
- printk(KERN_NOTICE "%s: Intersil firmware earlier "
- "than v0.8.x - several features not supported\n",
- dev->name);
- priv->ibss_port = 1;
- }
- break;
- }
- printk(KERN_DEBUG "%s: Firmware determined as %s\n", dev->name,
- priv->fw_name);
-
- return 0;
-}
-
-static int orinoco_init(struct net_device *dev)
-{
- struct orinoco_private *priv = netdev_priv(dev);
+ struct device *dev = priv->dev;
+ struct wiphy *wiphy = priv_to_wiphy(priv);
hermes_t *hw = &priv->hw;
int err = 0;
- struct hermes_idstring nickbuf;
- u16 reclen;
- int len;
/* No need to lock, the hw_unavailable flag is already set in
* alloc_orinocodev() */
@@ -2325,15 +1989,14 @@ static int orinoco_init(struct net_device *dev)
/* Initialize the firmware */
err = hermes_init(hw);
if (err != 0) {
- printk(KERN_ERR "%s: failed to initialize firmware (err = %d)\n",
- dev->name, err);
+ dev_err(dev, "Failed to initialize firmware (err = %d)\n",
+ err);
goto out;
}
- err = determine_firmware(dev);
+ err = determine_fw_capabilities(priv);
if (err != 0) {
- printk(KERN_ERR "%s: Incompatible firmware, aborting\n",
- dev->name);
+ dev_err(dev, "Incompatible firmware, aborting\n");
goto out;
}
@@ -2347,154 +2010,48 @@ static int orinoco_init(struct net_device *dev)
priv->do_fw_download = 0;
/* Check firmware version again */
- err = determine_firmware(dev);
+ err = determine_fw_capabilities(priv);
if (err != 0) {
- printk(KERN_ERR "%s: Incompatible firmware, aborting\n",
- dev->name);
+ dev_err(dev, "Incompatible firmware, aborting\n");
goto out;
}
}
if (priv->has_port3)
- printk(KERN_DEBUG "%s: Ad-hoc demo mode supported\n",
- dev->name);
+ dev_info(dev, "Ad-hoc demo mode supported\n");
if (priv->has_ibss)
- printk(KERN_DEBUG "%s: IEEE standard IBSS ad-hoc mode supported\n",
- dev->name);
- if (priv->has_wep) {
- printk(KERN_DEBUG "%s: WEP supported, %s-bit key\n", dev->name,
- priv->has_big_wep ? "104" : "40");
- }
+ dev_info(dev, "IEEE standard IBSS ad-hoc mode supported\n");
+ if (priv->has_wep)
+ dev_info(dev, "WEP supported, %s-bit key\n",
+ priv->has_big_wep ? "104" : "40");
if (priv->has_wpa) {
- printk(KERN_DEBUG "%s: WPA-PSK supported\n", dev->name);
+ dev_info(dev, "WPA-PSK supported\n");
if (orinoco_mic_init(priv)) {
- printk(KERN_ERR "%s: Failed to setup MIC crypto "
- "algorithm. Disabling WPA support\n", dev->name);
+ dev_err(dev, "Failed to setup MIC crypto algorithm. "
+ "Disabling WPA support\n");
priv->has_wpa = 0;
}
}
- /* Now we have the firmware capabilities, allocate appropiate
- * sized scan buffers */
- if (orinoco_bss_data_allocate(priv))
- goto out;
- orinoco_bss_data_init(priv);
-
- /* Get the MAC address */
- err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CNFOWNMACADDR,
- ETH_ALEN, NULL, dev->dev_addr);
- if (err) {
- printk(KERN_WARNING "%s: failed to read MAC address!\n",
- dev->name);
- goto out;
- }
-
- printk(KERN_DEBUG "%s: MAC address %pM\n",
- dev->name, dev->dev_addr);
-
- /* Get the station name */
- err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CNFOWNNAME,
- sizeof(nickbuf), &reclen, &nickbuf);
- if (err) {
- printk(KERN_ERR "%s: failed to read station name\n",
- dev->name);
- goto out;
- }
- if (nickbuf.len)
- len = min(IW_ESSID_MAX_SIZE, (int)le16_to_cpu(nickbuf.len));
- else
- len = min(IW_ESSID_MAX_SIZE, 2 * reclen);
- memcpy(priv->nick, &nickbuf.val, len);
- priv->nick[len] = '\0';
-
- printk(KERN_DEBUG "%s: Station name \"%s\"\n", dev->name, priv->nick);
-
- err = orinoco_allocate_fid(dev);
- if (err) {
- printk(KERN_ERR "%s: failed to allocate NIC buffer!\n",
- dev->name);
- goto out;
- }
-
- /* Get allowed channels */
- err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CHANNELLIST,
- &priv->channel_mask);
- if (err) {
- printk(KERN_ERR "%s: failed to read channel list!\n",
- dev->name);
- goto out;
- }
-
- /* Get initial AP density */
- err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CNFSYSTEMSCALE,
- &priv->ap_density);
- if (err || priv->ap_density < 1 || priv->ap_density > 3)
- priv->has_sensitivity = 0;
-
- /* Get initial RTS threshold */
- err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CNFRTSTHRESHOLD,
- &priv->rts_thresh);
- if (err) {
- printk(KERN_ERR "%s: failed to read RTS threshold!\n",
- dev->name);
+ err = orinoco_hw_read_card_settings(priv, wiphy->perm_addr);
+ if (err)
goto out;
- }
- /* Get initial fragmentation settings */
- if (priv->has_mwo)
- err = hermes_read_wordrec(hw, USER_BAP,
- HERMES_RID_CNFMWOROBUST_AGERE,
- &priv->mwo_robust);
- else
- err = hermes_read_wordrec(hw, USER_BAP,
- HERMES_RID_CNFFRAGMENTATIONTHRESHOLD,
- &priv->frag_thresh);
+ err = orinoco_hw_allocate_fid(priv);
if (err) {
- printk(KERN_ERR "%s: failed to read fragmentation settings!\n",
- dev->name);
+ dev_err(dev, "Failed to allocate NIC buffer!\n");
goto out;
}
- /* Power management setup */
- if (priv->has_pm) {
- priv->pm_on = 0;
- priv->pm_mcast = 1;
- err = hermes_read_wordrec(hw, USER_BAP,
- HERMES_RID_CNFMAXSLEEPDURATION,
- &priv->pm_period);
- if (err) {
- printk(KERN_ERR "%s: failed to read power management period!\n",
- dev->name);
- goto out;
- }
- err = hermes_read_wordrec(hw, USER_BAP,
- HERMES_RID_CNFPMHOLDOVERDURATION,
- &priv->pm_timeout);
- if (err) {
- printk(KERN_ERR "%s: failed to read power management timeout!\n",
- dev->name);
- goto out;
- }
- }
-
- /* Preamble setup */
- if (priv->has_preamble) {
- err = hermes_read_wordrec(hw, USER_BAP,
- HERMES_RID_CNFPREAMBLE_SYMBOL,
- &priv->preamble);
- if (err)
- goto out;
- }
-
/* Set up the default configuration */
- priv->iw_mode = IW_MODE_INFRA;
+ priv->iw_mode = NL80211_IFTYPE_STATION;
/* By default use IEEE/IBSS ad-hoc mode if we have it */
priv->prefer_port3 = priv->has_port3 && (!priv->has_ibss);
set_port_type(priv);
priv->channel = 0; /* use firmware default */
priv->promiscuous = 0;
- priv->encode_alg = IW_ENCODE_ALG_NONE;
+ priv->encode_alg = ORINOCO_ALG_NONE;
priv->tx_key = 0;
priv->wpa_enabled = 0;
priv->tkip_cm_active = 0;
@@ -2502,20 +2059,25 @@ static int orinoco_init(struct net_device *dev)
priv->wpa_ie_len = 0;
priv->wpa_ie = NULL;
+ if (orinoco_wiphy_register(wiphy)) {
+ err = -ENODEV;
+ goto out;
+ }
+
/* Make the hardware available, as long as it hasn't been
* removed elsewhere (e.g. by PCMCIA hot unplug) */
spin_lock_irq(&priv->lock);
priv->hw_unavailable--;
spin_unlock_irq(&priv->lock);
- printk(KERN_DEBUG "%s: ready\n", dev->name);
+ dev_dbg(dev, "Ready\n");
out:
return err;
}
+EXPORT_SYMBOL(orinoco_init);
static const struct net_device_ops orinoco_netdev_ops = {
- .ndo_init = orinoco_init,
.ndo_open = orinoco_open,
.ndo_stop = orinoco_stop,
.ndo_start_xmit = orinoco_xmit,
@@ -2527,40 +2089,64 @@ static const struct net_device_ops orinoco_netdev_ops = {
.ndo_get_stats = orinoco_get_stats,
};
-struct net_device
+/* Allocate private data.
+ *
+ * This driver has a number of structures associated with it
+ * netdev - Net device structure for each network interface
+ * wiphy - structure associated with wireless phy
+ * wireless_dev (wdev) - structure for each wireless interface
+ * hw - structure for hermes chip info
+ * card - card specific structure for use by the card driver
+ * (airport, orinoco_cs)
+ * priv - orinoco private data
+ * device - generic linux device structure
+ *
+ * +---------+ +---------+
+ * | wiphy | | netdev |
+ * | +-------+ | +-------+
+ * | | priv | | | wdev |
+ * | | +-----+ +-+-------+
+ * | | | hw |
+ * | +-+-----+
+ * | | card |
+ * +-+-------+
+ *
+ * priv has a link to netdev and device
+ * wdev has a link to wiphy
+ */
+struct orinoco_private
*alloc_orinocodev(int sizeof_card,
struct device *device,
int (*hard_reset)(struct orinoco_private *),
int (*stop_fw)(struct orinoco_private *, int))
{
- struct net_device *dev;
struct orinoco_private *priv;
+ struct wiphy *wiphy;
- dev = alloc_etherdev(sizeof(struct orinoco_private) + sizeof_card);
- if (!dev)
+ /* allocate wiphy
+ * NOTE: We only support a single virtual interface
+ * but this may change when monitor mode is added
+ */
+ wiphy = wiphy_new(&orinoco_cfg_ops,
+ sizeof(struct orinoco_private) + sizeof_card);
+ if (!wiphy)
return NULL;
- priv = netdev_priv(dev);
- priv->ndev = dev;
+
+ priv = wiphy_priv(wiphy);
+ priv->dev = device;
+
if (sizeof_card)
priv->card = (void *)((unsigned long)priv
+ sizeof(struct orinoco_private));
else
priv->card = NULL;
- priv->dev = device;
- /* Setup / override net_device fields */
- dev->netdev_ops = &orinoco_netdev_ops;
- dev->watchdog_timeo = HZ; /* 1 second timeout */
- dev->ethtool_ops = &orinoco_ethtool_ops;
- dev->wireless_handlers = &orinoco_handler_def;
+ orinoco_wiphy_init(wiphy);
+
#ifdef WIRELESS_SPY
priv->wireless_data.spy_data = &priv->spy_data;
- dev->wireless_data = &priv->wireless_data;
#endif
- /* Reserve space in skb for the SNAP header */
- dev->hard_header_len += ENCAPS_OVERHEAD;
-
/* Set up default callbacks */
priv->hard_reset = hard_reset;
priv->stop_fw = stop_fw;
@@ -2576,9 +2162,12 @@ struct net_device
INIT_LIST_HEAD(&priv->rx_list);
tasklet_init(&priv->rx_tasklet, orinoco_rx_isr_tasklet,
- (unsigned long) dev);
+ (unsigned long) priv);
+
+ spin_lock_init(&priv->scan_lock);
+ INIT_LIST_HEAD(&priv->scan_list);
+ INIT_WORK(&priv->process_scan, orinoco_process_scan_results);
- netif_carrier_off(dev);
priv->last_linkstatus = 0xffff;
#if defined(CONFIG_HERMES_CACHE_FW_ON_INIT) || defined(CONFIG_PM_SLEEP)
@@ -2589,14 +2178,91 @@ struct net_device
/* Register PM notifiers */
orinoco_register_pm_notifier(priv);
- return dev;
+ return priv;
}
EXPORT_SYMBOL(alloc_orinocodev);
-void free_orinocodev(struct net_device *dev)
+/* We can only support a single interface. We provide a separate
+ * function to set it up to distinguish between hardware
+ * initialisation and interface setup.
+ *
+ * The base_addr and irq parameters are passed on to netdev for use
+ * with SIOCGIFMAP.
+ */
+int orinoco_if_add(struct orinoco_private *priv,
+ unsigned long base_addr,
+ unsigned int irq)
+{
+ struct wiphy *wiphy = priv_to_wiphy(priv);
+ struct wireless_dev *wdev;
+ struct net_device *dev;
+ int ret;
+
+ dev = alloc_etherdev(sizeof(struct wireless_dev));
+
+ if (!dev)
+ return -ENOMEM;
+
+ /* Initialise wireless_dev */
+ wdev = netdev_priv(dev);
+ wdev->wiphy = wiphy;
+ wdev->iftype = NL80211_IFTYPE_STATION;
+
+ /* Setup / override net_device fields */
+ dev->ieee80211_ptr = wdev;
+ dev->netdev_ops = &orinoco_netdev_ops;
+ dev->watchdog_timeo = HZ; /* 1 second timeout */
+ dev->ethtool_ops = &orinoco_ethtool_ops;
+ dev->wireless_handlers = &orinoco_handler_def;
+#ifdef WIRELESS_SPY
+ dev->wireless_data = &priv->wireless_data;
+#endif
+ /* we use the default eth_mac_addr for setting the MAC addr */
+
+ /* Reserve space in skb for the SNAP header */
+ dev->hard_header_len += ENCAPS_OVERHEAD;
+
+ netif_carrier_off(dev);
+
+ memcpy(dev->dev_addr, wiphy->perm_addr, ETH_ALEN);
+
+ dev->base_addr = base_addr;
+ dev->irq = irq;
+
+ SET_NETDEV_DEV(dev, priv->dev);
+ ret = register_netdev(dev);
+ if (ret)
+ goto fail;
+
+ priv->ndev = dev;
+
+ /* Report what we've done */
+ dev_dbg(priv->dev, "Registerred interface %s.\n", dev->name);
+
+ return 0;
+
+ fail:
+ free_netdev(dev);
+ return ret;
+}
+EXPORT_SYMBOL(orinoco_if_add);
+
+void orinoco_if_del(struct orinoco_private *priv)
+{
+ struct net_device *dev = priv->ndev;
+
+ unregister_netdev(dev);
+ free_netdev(dev);
+}
+EXPORT_SYMBOL(orinoco_if_del);
+
+void free_orinocodev(struct orinoco_private *priv)
{
- struct orinoco_private *priv = netdev_priv(dev);
+ struct wiphy *wiphy = priv_to_wiphy(priv);
struct orinoco_rx_data *rx_data, *temp;
+ struct orinoco_scan_data *sd, *sdtemp;
+
+ wiphy_unregister(wiphy);
/* If the tasklet is scheduled when we call tasklet_kill it
* will run one final time. However the tasklet will only
@@ -2612,21 +2278,80 @@ void free_orinocodev(struct net_device *dev)
kfree(rx_data);
}
+ cancel_work_sync(&priv->process_scan);
+ /* Explicitly drain priv->scan_list */
+ list_for_each_entry_safe(sd, sdtemp, &priv->scan_list, list) {
+ list_del(&sd->list);
+
+ if ((sd->len > 0) && sd->buf)
+ kfree(sd->buf);
+ kfree(sd);
+ }
+
orinoco_unregister_pm_notifier(priv);
orinoco_uncache_fw(priv);
priv->wpa_ie_len = 0;
kfree(priv->wpa_ie);
orinoco_mic_free(priv);
- orinoco_bss_data_free(priv);
- free_netdev(dev);
+ wiphy_free(wiphy);
}
EXPORT_SYMBOL(free_orinocodev);
+int orinoco_up(struct orinoco_private *priv)
+{
+ struct net_device *dev = priv->ndev;
+ unsigned long flags;
+ int err;
+
+ spin_lock_irqsave(&priv->lock, flags);
+
+ err = orinoco_reinit_firmware(priv);
+ if (err) {
+ printk(KERN_ERR "%s: Error %d re-initializing firmware\n",
+ dev->name, err);
+ goto exit;
+ }
+
+ netif_device_attach(dev);
+ priv->hw_unavailable--;
+
+ if (priv->open && !priv->hw_unavailable) {
+ err = __orinoco_up(priv);
+ if (err)
+ printk(KERN_ERR "%s: Error %d restarting card\n",
+ dev->name, err);
+ }
+
+exit:
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ return 0;
+}
+EXPORT_SYMBOL(orinoco_up);
+
+void orinoco_down(struct orinoco_private *priv)
+{
+ struct net_device *dev = priv->ndev;
+ unsigned long flags;
+ int err;
+
+ spin_lock_irqsave(&priv->lock, flags);
+ err = __orinoco_down(priv);
+ if (err)
+ printk(KERN_WARNING "%s: Error %d downing interface\n",
+ dev->name, err);
+
+ netif_device_detach(dev);
+ priv->hw_unavailable++;
+ spin_unlock_irqrestore(&priv->lock, flags);
+}
+EXPORT_SYMBOL(orinoco_down);
+
static void orinoco_get_drvinfo(struct net_device *dev,
struct ethtool_drvinfo *info)
{
- struct orinoco_private *priv = netdev_priv(dev);
+ struct orinoco_private *priv = ndev_priv(dev);
strncpy(info->driver, DRIVER_NAME, sizeof(info->driver) - 1);
strncpy(info->version, DRIVER_VERSION, sizeof(info->version) - 1);
diff --git a/drivers/net/wireless/orinoco/main.h b/drivers/net/wireless/orinoco/main.h
index af2bae4fe39..21ab36cd76c 100644
--- a/drivers/net/wireless/orinoco/main.h
+++ b/drivers/net/wireless/orinoco/main.h
@@ -29,10 +29,9 @@ struct net_device;
struct work_struct;
void set_port_type(struct orinoco_private *priv);
-int __orinoco_program_rids(struct net_device *dev);
+int orinoco_commit(struct orinoco_private *priv);
void orinoco_reset(struct work_struct *work);
-
/* Information element helpers - find a home for these... */
static inline u8 *orinoco_get_ie(u8 *data, size_t len,
enum ieee80211_eid eid)
diff --git a/drivers/net/wireless/orinoco/orinoco.h b/drivers/net/wireless/orinoco/orinoco.h
index 8e5a72cc297..9ac6f1dda4b 100644
--- a/drivers/net/wireless/orinoco/orinoco.h
+++ b/drivers/net/wireless/orinoco/orinoco.h
@@ -14,6 +14,7 @@
#include <linux/netdevice.h>
#include <linux/wireless.h>
#include <net/iw_handler.h>
+#include <net/cfg80211.h>
#include "hermes.h"
@@ -24,6 +25,7 @@
#define MAX_SCAN_LEN 4096
+#define ORINOCO_SEQ_LEN 8
#define ORINOCO_MAX_KEY_SIZE 14
#define ORINOCO_MAX_KEYS 4
@@ -41,24 +43,18 @@ struct orinoco_tkip_key {
u8 rx_mic[MIC_KEYLEN];
};
+enum orinoco_alg {
+ ORINOCO_ALG_NONE,
+ ORINOCO_ALG_WEP,
+ ORINOCO_ALG_TKIP
+};
+
typedef enum {
FIRMWARE_TYPE_AGERE,
FIRMWARE_TYPE_INTERSIL,
FIRMWARE_TYPE_SYMBOL
} fwtype_t;
-struct bss_element {
- union hermes_scan_info bss;
- unsigned long last_scanned;
- struct list_head list;
-};
-
-struct xbss_element {
- struct agere_ext_scan_info bss;
- unsigned long last_scanned;
- struct list_head list;
-};
-
struct firmware;
struct orinoco_private {
@@ -67,6 +63,10 @@ struct orinoco_private {
int (*hard_reset)(struct orinoco_private *);
int (*stop_fw)(struct orinoco_private *, int);
+ struct ieee80211_supported_band band;
+ struct ieee80211_channel channels[14];
+ u32 cipher_suites[3];
+
/* Synchronisation stuff */
spinlock_t lock;
int hw_unavailable;
@@ -114,12 +114,14 @@ struct orinoco_private {
unsigned int do_fw_download:1;
unsigned int broken_disableport:1;
unsigned int broken_monitor:1;
+ unsigned int prefer_port3:1;
/* Configuration paramaters */
- u32 iw_mode;
- int prefer_port3;
- u16 encode_alg, wep_restrict, tx_key;
- struct orinoco_key keys[ORINOCO_MAX_KEYS];
+ enum nl80211_iftype iw_mode;
+ enum orinoco_alg encode_alg;
+ u16 wep_restrict, tx_key;
+ struct key_params keys[ORINOCO_MAX_KEYS];
+
int bitratemode;
char nick[IW_ESSID_MAX_SIZE+1];
char desired_essid[IW_ESSID_MAX_SIZE+1];
@@ -140,18 +142,15 @@ struct orinoco_private {
int promiscuous, mc_count;
/* Scanning support */
- struct list_head bss_list;
- struct list_head bss_free_list;
- void *bss_xbss_data;
-
- int scan_inprogress; /* Scan pending... */
- u32 scan_mode; /* Type of scan done */
+ struct cfg80211_scan_request *scan_request;
+ struct work_struct process_scan;
+ struct list_head scan_list;
+ spinlock_t scan_lock; /* protects the scan list */
/* WPA support */
u8 *wpa_ie;
int wpa_ie_len;
- struct orinoco_tkip_key tkip_key[ORINOCO_MAX_KEYS];
struct crypto_hash *rx_tfm_mic;
struct crypto_hash *tx_tfm_mic;
@@ -182,14 +181,18 @@ extern int orinoco_debug;
/* Exported prototypes */
/********************************************************************/
-extern struct net_device *alloc_orinocodev(
+extern struct orinoco_private *alloc_orinocodev(
int sizeof_card, struct device *device,
int (*hard_reset)(struct orinoco_private *),
int (*stop_fw)(struct orinoco_private *, int));
-extern void free_orinocodev(struct net_device *dev);
-extern int __orinoco_up(struct net_device *dev);
-extern int __orinoco_down(struct net_device *dev);
-extern int orinoco_reinit_firmware(struct net_device *dev);
+extern void free_orinocodev(struct orinoco_private *priv);
+extern int orinoco_init(struct orinoco_private *priv);
+extern int orinoco_if_add(struct orinoco_private *priv,
+ unsigned long base_addr,
+ unsigned int irq);
+extern void orinoco_if_del(struct orinoco_private *priv);
+extern int orinoco_up(struct orinoco_private *priv);
+extern void orinoco_down(struct orinoco_private *priv);
extern irqreturn_t orinoco_interrupt(int irq, void *dev_id);
/********************************************************************/
@@ -215,4 +218,10 @@ static inline void orinoco_unlock(struct orinoco_private *priv,
spin_unlock_irqrestore(&priv->lock, *flags);
}
+/*** Navigate from net_device to orinoco_private ***/
+static inline struct orinoco_private *ndev_priv(struct net_device *dev)
+{
+ struct wireless_dev *wdev = netdev_priv(dev);
+ return wdev_priv(wdev);
+}
#endif /* _ORINOCO_H */
diff --git a/drivers/net/wireless/orinoco/orinoco_cs.c b/drivers/net/wireless/orinoco/orinoco_cs.c
index b381aed24d7..38c1c9d2abb 100644
--- a/drivers/net/wireless/orinoco/orinoco_cs.c
+++ b/drivers/net/wireless/orinoco/orinoco_cs.c
@@ -106,26 +106,24 @@ orinoco_cs_hard_reset(struct orinoco_private *priv)
static int
orinoco_cs_probe(struct pcmcia_device *link)
{
- struct net_device *dev;
struct orinoco_private *priv;
struct orinoco_pccard *card;
- dev = alloc_orinocodev(sizeof(*card), &handle_to_dev(link),
- orinoco_cs_hard_reset, NULL);
- if (!dev)
+ priv = alloc_orinocodev(sizeof(*card), &handle_to_dev(link),
+ orinoco_cs_hard_reset, NULL);
+ if (!priv)
return -ENOMEM;
- priv = netdev_priv(dev);
card = priv->card;
/* Link both structures together */
card->p_dev = link;
- link->priv = dev;
+ link->priv = priv;
/* Interrupt setup */
link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING | IRQ_HANDLE_PRESENT;
link->irq.IRQInfo1 = IRQ_LEVEL_ID;
link->irq.Handler = orinoco_interrupt;
- link->irq.Instance = dev;
+ link->irq.Instance = priv;
/* General socket configuration defaults can go here. In this
* client, we assume very little, and rely on the CIS for
@@ -146,14 +144,14 @@ orinoco_cs_probe(struct pcmcia_device *link)
*/
static void orinoco_cs_detach(struct pcmcia_device *link)
{
- struct net_device *dev = link->priv;
+ struct orinoco_private *priv = link->priv;
if (link->dev_node)
- unregister_netdev(dev);
+ orinoco_if_del(priv);
orinoco_cs_release(link);
- free_orinocodev(dev);
+ free_orinocodev(priv);
} /* orinoco_cs_detach */
/*
@@ -239,8 +237,7 @@ next_entry:
static int
orinoco_cs_config(struct pcmcia_device *link)
{
- struct net_device *dev = link->priv;
- struct orinoco_private *priv = netdev_priv(dev);
+ struct orinoco_private *priv = link->priv;
struct orinoco_pccard *card = priv->card;
hermes_t *hw = &priv->hw;
int last_fn, last_ret;
@@ -295,29 +292,27 @@ orinoco_cs_config(struct pcmcia_device *link)
pcmcia_request_configuration(link, &link->conf));
/* Ok, we have the configuration, prepare to register the netdev */
- dev->base_addr = link->io.BasePort1;
- dev->irq = link->irq.AssignedIRQ;
card->node.major = card->node.minor = 0;
- SET_NETDEV_DEV(dev, &handle_to_dev(link));
- /* Tell the stack we exist */
- if (register_netdev(dev) != 0) {
- printk(KERN_ERR PFX "register_netdev() failed\n");
+ /* Initialise the main driver */
+ if (orinoco_init(priv) != 0) {
+ printk(KERN_ERR PFX "orinoco_init() failed\n");
+ goto failed;
+ }
+
+ /* Register an interface with the stack */
+ if (orinoco_if_add(priv, link->io.BasePort1,
+ link->irq.AssignedIRQ) != 0) {
+ printk(KERN_ERR PFX "orinoco_if_add() failed\n");
goto failed;
}
/* At this point, the dev_node_t structure(s) needs to be
* initialized and arranged in a linked list at link->dev_node. */
- strcpy(card->node.dev_name, dev->name);
+ strcpy(card->node.dev_name, priv->ndev->name);
link->dev_node = &card->node; /* link->dev_node being non-NULL is also
* used to indicate that the
* net_device has been registered */
-
- /* Finally, report what we've done */
- printk(KERN_DEBUG "%s: " DRIVER_NAME " at %s, irq %d, io "
- "0x%04x-0x%04x\n", dev->name, dev_name(dev->dev.parent),
- link->irq.AssignedIRQ, link->io.BasePort1,
- link->io.BasePort1 + link->io.NumPorts1 - 1);
return 0;
cs_failed:
@@ -336,8 +331,7 @@ orinoco_cs_config(struct pcmcia_device *link)
static void
orinoco_cs_release(struct pcmcia_device *link)
{
- struct net_device *dev = link->priv;
- struct orinoco_private *priv = netdev_priv(dev);
+ struct orinoco_private *priv = link->priv;
unsigned long flags;
/* We're committed to taking the device away now, so mark the
@@ -353,62 +347,26 @@ orinoco_cs_release(struct pcmcia_device *link)
static int orinoco_cs_suspend(struct pcmcia_device *link)
{
- struct net_device *dev = link->priv;
- struct orinoco_private *priv = netdev_priv(dev);
+ struct orinoco_private *priv = link->priv;
struct orinoco_pccard *card = priv->card;
- int err = 0;
- unsigned long flags;
/* This is probably racy, but I can't think of
a better way, short of rewriting the PCMCIA
layer to not suck :-( */
- if (!test_bit(0, &card->hard_reset_in_progress)) {
- spin_lock_irqsave(&priv->lock, flags);
-
- err = __orinoco_down(dev);
- if (err)
- printk(KERN_WARNING "%s: Error %d downing interface\n",
- dev->name, err);
-
- netif_device_detach(dev);
- priv->hw_unavailable++;
-
- spin_unlock_irqrestore(&priv->lock, flags);
- }
+ if (!test_bit(0, &card->hard_reset_in_progress))
+ orinoco_down(priv);
return 0;
}
static int orinoco_cs_resume(struct pcmcia_device *link)
{
- struct net_device *dev = link->priv;
- struct orinoco_private *priv = netdev_priv(dev);
+ struct orinoco_private *priv = link->priv;
struct orinoco_pccard *card = priv->card;
int err = 0;
- unsigned long flags;
-
- if (!test_bit(0, &card->hard_reset_in_progress)) {
- err = orinoco_reinit_firmware(dev);
- if (err) {
- printk(KERN_ERR "%s: Error %d re-initializing firmware\n",
- dev->name, err);
- return -EIO;
- }
-
- spin_lock_irqsave(&priv->lock, flags);
- netif_device_attach(dev);
- priv->hw_unavailable--;
-
- if (priv->open && !priv->hw_unavailable) {
- err = __orinoco_up(dev);
- if (err)
- printk(KERN_ERR "%s: Error %d restarting card\n",
- dev->name, err);
- }
-
- spin_unlock_irqrestore(&priv->lock, flags);
- }
+ if (!test_bit(0, &card->hard_reset_in_progress))
+ err = orinoco_up(priv);
return err;
}
diff --git a/drivers/net/wireless/orinoco/orinoco_nortel.c b/drivers/net/wireless/orinoco/orinoco_nortel.c
index b01726255c6..c13a4c38341 100644
--- a/drivers/net/wireless/orinoco/orinoco_nortel.c
+++ b/drivers/net/wireless/orinoco/orinoco_nortel.c
@@ -144,7 +144,6 @@ static int orinoco_nortel_init_one(struct pci_dev *pdev,
int err;
struct orinoco_private *priv;
struct orinoco_pci_card *card;
- struct net_device *dev;
void __iomem *hermes_io, *bridge_io, *attr_io;
err = pci_enable_device(pdev);
@@ -181,24 +180,22 @@ static int orinoco_nortel_init_one(struct pci_dev *pdev,
}
/* Allocate network device */
- dev = alloc_orinocodev(sizeof(*card), &pdev->dev,
- orinoco_nortel_cor_reset, NULL);
- if (!dev) {
+ priv = alloc_orinocodev(sizeof(*card), &pdev->dev,
+ orinoco_nortel_cor_reset, NULL);
+ if (!priv) {
printk(KERN_ERR PFX "Cannot allocate network device\n");
err = -ENOMEM;
goto fail_alloc;
}
- priv = netdev_priv(dev);
card = priv->card;
card->bridge_io = bridge_io;
card->attr_io = attr_io;
- SET_NETDEV_DEV(dev, &pdev->dev);
hermes_struct_init(&priv->hw, hermes_io, HERMES_16BIT_REGSPACING);
err = request_irq(pdev->irq, orinoco_interrupt, IRQF_SHARED,
- dev->name, dev);
+ DRIVER_NAME, priv);
if (err) {
printk(KERN_ERR PFX "Cannot allocate IRQ %d\n", pdev->irq);
err = -EBUSY;
@@ -217,24 +214,28 @@ static int orinoco_nortel_init_one(struct pci_dev *pdev,
goto fail;
}
- err = register_netdev(dev);
+ err = orinoco_init(priv);
if (err) {
- printk(KERN_ERR PFX "Cannot register network device\n");
+ printk(KERN_ERR PFX "orinoco_init() failed\n");
goto fail;
}
- pci_set_drvdata(pdev, dev);
- printk(KERN_DEBUG "%s: " DRIVER_NAME " at %s\n", dev->name,
- pci_name(pdev));
+ err = orinoco_if_add(priv, 0, 0);
+ if (err) {
+ printk(KERN_ERR PFX "orinoco_if_add() failed\n");
+ goto fail;
+ }
+
+ pci_set_drvdata(pdev, priv);
return 0;
fail:
- free_irq(pdev->irq, dev);
+ free_irq(pdev->irq, priv);
fail_irq:
pci_set_drvdata(pdev, NULL);
- free_orinocodev(dev);
+ free_orinocodev(priv);
fail_alloc:
pci_iounmap(pdev, hermes_io);
@@ -256,17 +257,16 @@ static int orinoco_nortel_init_one(struct pci_dev *pdev,
static void __devexit orinoco_nortel_remove_one(struct pci_dev *pdev)
{
- struct net_device *dev = pci_get_drvdata(pdev);
- struct orinoco_private *priv = netdev_priv(dev);
+ struct orinoco_private *priv = pci_get_drvdata(pdev);
struct orinoco_pci_card *card = priv->card;
/* Clear LEDs */
iowrite16(0, card->bridge_io + 10);
- unregister_netdev(dev);
- free_irq(pdev->irq, dev);
+ orinoco_if_del(priv);
+ free_irq(pdev->irq, priv);
pci_set_drvdata(pdev, NULL);
- free_orinocodev(dev);
+ free_orinocodev(priv);
pci_iounmap(pdev, priv->hw.iobase);
pci_iounmap(pdev, card->attr_io);
pci_iounmap(pdev, card->bridge_io);
diff --git a/drivers/net/wireless/orinoco/orinoco_pci.c b/drivers/net/wireless/orinoco/orinoco_pci.c
index 78cafff1fb2..fea7781948e 100644
--- a/drivers/net/wireless/orinoco/orinoco_pci.c
+++ b/drivers/net/wireless/orinoco/orinoco_pci.c
@@ -116,7 +116,6 @@ static int orinoco_pci_init_one(struct pci_dev *pdev,
int err;
struct orinoco_private *priv;
struct orinoco_pci_card *card;
- struct net_device *dev;
void __iomem *hermes_io;
err = pci_enable_device(pdev);
@@ -139,22 +138,20 @@ static int orinoco_pci_init_one(struct pci_dev *pdev,
}
/* Allocate network device */
- dev = alloc_orinocodev(sizeof(*card), &pdev->dev,
- orinoco_pci_cor_reset, NULL);
- if (!dev) {
+ priv = alloc_orinocodev(sizeof(*card), &pdev->dev,
+ orinoco_pci_cor_reset, NULL);
+ if (!priv) {
printk(KERN_ERR PFX "Cannot allocate network device\n");
err = -ENOMEM;
goto fail_alloc;
}
- priv = netdev_priv(dev);
card = priv->card;
- SET_NETDEV_DEV(dev, &pdev->dev);
hermes_struct_init(&priv->hw, hermes_io, HERMES_32BIT_REGSPACING);
err = request_irq(pdev->irq, orinoco_interrupt, IRQF_SHARED,
- dev->name, dev);
+ DRIVER_NAME, priv);
if (err) {
printk(KERN_ERR PFX "Cannot allocate IRQ %d\n", pdev->irq);
err = -EBUSY;
@@ -167,24 +164,28 @@ static int orinoco_pci_init_one(struct pci_dev *pdev,
goto fail;
}
- err = register_netdev(dev);
+ err = orinoco_init(priv);
if (err) {
- printk(KERN_ERR PFX "Cannot register network device\n");
+ printk(KERN_ERR PFX "orinoco_init() failed\n");
goto fail;
}
- pci_set_drvdata(pdev, dev);
- printk(KERN_DEBUG "%s: " DRIVER_NAME " at %s\n", dev->name,
- pci_name(pdev));
+ err = orinoco_if_add(priv, 0, 0);
+ if (err) {
+ printk(KERN_ERR PFX "orinoco_if_add() failed\n");
+ goto fail;
+ }
+
+ pci_set_drvdata(pdev, priv);
return 0;
fail:
- free_irq(pdev->irq, dev);
+ free_irq(pdev->irq, priv);
fail_irq:
pci_set_drvdata(pdev, NULL);
- free_orinocodev(dev);
+ free_orinocodev(priv);
fail_alloc:
pci_iounmap(pdev, hermes_io);
@@ -200,13 +201,12 @@ static int orinoco_pci_init_one(struct pci_dev *pdev,
static void __devexit orinoco_pci_remove_one(struct pci_dev *pdev)
{
- struct net_device *dev = pci_get_drvdata(pdev);
- struct orinoco_private *priv = netdev_priv(dev);
+ struct orinoco_private *priv = pci_get_drvdata(pdev);
- unregister_netdev(dev);
- free_irq(pdev->irq, dev);
+ orinoco_if_del(priv);
+ free_irq(pdev->irq, priv);
pci_set_drvdata(pdev, NULL);
- free_orinocodev(dev);
+ free_orinocodev(priv);
pci_iounmap(pdev, priv->hw.iobase);
pci_release_regions(pdev);
pci_disable_device(pdev);
diff --git a/drivers/net/wireless/orinoco/orinoco_pci.h b/drivers/net/wireless/orinoco/orinoco_pci.h
index c655b4a3de1..ea7231af40a 100644
--- a/drivers/net/wireless/orinoco/orinoco_pci.h
+++ b/drivers/net/wireless/orinoco/orinoco_pci.h
@@ -21,30 +21,10 @@ struct orinoco_pci_card {
#ifdef CONFIG_PM
static int orinoco_pci_suspend(struct pci_dev *pdev, pm_message_t state)
{
- struct net_device *dev = pci_get_drvdata(pdev);
- struct orinoco_private *priv = netdev_priv(dev);
- unsigned long flags;
- int err;
-
- err = orinoco_lock(priv, &flags);
- if (err) {
- printk(KERN_ERR "%s: cannot lock hardware for suspend\n",
- dev->name);
- return err;
- }
-
- err = __orinoco_down(dev);
- if (err)
- printk(KERN_WARNING "%s: error %d bringing interface down "
- "for suspend\n", dev->name, err);
-
- netif_device_detach(dev);
-
- priv->hw_unavailable++;
-
- orinoco_unlock(priv, &flags);
+ struct orinoco_private *priv = pci_get_drvdata(pdev);
- free_irq(pdev->irq, dev);
+ orinoco_down(priv);
+ free_irq(pdev->irq, priv);
pci_save_state(pdev);
pci_disable_device(pdev);
pci_set_power_state(pdev, PCI_D3hot);
@@ -54,9 +34,8 @@ static int orinoco_pci_suspend(struct pci_dev *pdev, pm_message_t state)
static int orinoco_pci_resume(struct pci_dev *pdev)
{
- struct net_device *dev = pci_get_drvdata(pdev);
- struct orinoco_private *priv = netdev_priv(dev);
- unsigned long flags;
+ struct orinoco_private *priv = pci_get_drvdata(pdev);
+ struct net_device *dev = priv->ndev;
int err;
pci_set_power_state(pdev, 0);
@@ -69,7 +48,7 @@ static int orinoco_pci_resume(struct pci_dev *pdev)
pci_restore_state(pdev);
err = request_irq(pdev->irq, orinoco_interrupt, IRQF_SHARED,
- dev->name, dev);
+ dev->name, priv);
if (err) {
printk(KERN_ERR "%s: cannot re-allocate IRQ on resume\n",
dev->name);
@@ -77,29 +56,9 @@ static int orinoco_pci_resume(struct pci_dev *pdev)
return -EBUSY;
}
- err = orinoco_reinit_firmware(dev);
- if (err) {
- printk(KERN_ERR "%s: error %d re-initializing firmware "
- "on resume\n", dev->name, err);
- return err;
- }
-
- spin_lock_irqsave(&priv->lock, flags);
-
- netif_device_attach(dev);
+ err = orinoco_up(priv);
- priv->hw_unavailable--;
-
- if (priv->open && (!priv->hw_unavailable)) {
- err = __orinoco_up(dev);
- if (err)
- printk(KERN_ERR "%s: Error %d restarting card on resume\n",
- dev->name, err);
- }
-
- spin_unlock_irqrestore(&priv->lock, flags);
-
- return 0;
+ return err;
}
#else
#define orinoco_pci_suspend NULL
diff --git a/drivers/net/wireless/orinoco/orinoco_plx.c b/drivers/net/wireless/orinoco/orinoco_plx.c
index a2a4471c033..3f2942a1e4f 100644
--- a/drivers/net/wireless/orinoco/orinoco_plx.c
+++ b/drivers/net/wireless/orinoco/orinoco_plx.c
@@ -183,7 +183,6 @@ static int orinoco_plx_init_one(struct pci_dev *pdev,
int err;
struct orinoco_private *priv;
struct orinoco_pci_card *card;
- struct net_device *dev;
void __iomem *hermes_io, *attr_io, *bridge_io;
err = pci_enable_device(pdev);
@@ -220,24 +219,22 @@ static int orinoco_plx_init_one(struct pci_dev *pdev,
}
/* Allocate network device */
- dev = alloc_orinocodev(sizeof(*card), &pdev->dev,
- orinoco_plx_cor_reset, NULL);
- if (!dev) {
+ priv = alloc_orinocodev(sizeof(*card), &pdev->dev,
+ orinoco_plx_cor_reset, NULL);
+ if (!priv) {
printk(KERN_ERR PFX "Cannot allocate network device\n");
err = -ENOMEM;
goto fail_alloc;
}
- priv = netdev_priv(dev);
card = priv->card;
card->bridge_io = bridge_io;
card->attr_io = attr_io;
- SET_NETDEV_DEV(dev, &pdev->dev);
hermes_struct_init(&priv->hw, hermes_io, HERMES_16BIT_REGSPACING);
err = request_irq(pdev->irq, orinoco_interrupt, IRQF_SHARED,
- dev->name, dev);
+ DRIVER_NAME, priv);
if (err) {
printk(KERN_ERR PFX "Cannot allocate IRQ %d\n", pdev->irq);
err = -EBUSY;
@@ -256,24 +253,28 @@ static int orinoco_plx_init_one(struct pci_dev *pdev,
goto fail;
}
- err = register_netdev(dev);
+ err = orinoco_init(priv);
if (err) {
- printk(KERN_ERR PFX "Cannot register network device\n");
+ printk(KERN_ERR PFX "orinoco_init() failed\n");
goto fail;
}
- pci_set_drvdata(pdev, dev);
- printk(KERN_DEBUG "%s: " DRIVER_NAME " at %s\n", dev->name,
- pci_name(pdev));
+ err = orinoco_if_add(priv, 0, 0);
+ if (err) {
+ printk(KERN_ERR PFX "orinoco_if_add() failed\n");
+ goto fail;
+ }
+
+ pci_set_drvdata(pdev, priv);
return 0;
fail:
- free_irq(pdev->irq, dev);
+ free_irq(pdev->irq, priv);
fail_irq:
pci_set_drvdata(pdev, NULL);
- free_orinocodev(dev);
+ free_orinocodev(priv);
fail_alloc:
pci_iounmap(pdev, hermes_io);
@@ -295,14 +296,13 @@ static int orinoco_plx_init_one(struct pci_dev *pdev,
static void __devexit orinoco_plx_remove_one(struct pci_dev *pdev)
{
- struct net_device *dev = pci_get_drvdata(pdev);
- struct orinoco_private *priv = netdev_priv(dev);
+ struct orinoco_private *priv = pci_get_drvdata(pdev);
struct orinoco_pci_card *card = priv->card;
- unregister_netdev(dev);
- free_irq(pdev->irq, dev);
+ orinoco_if_del(priv);
+ free_irq(pdev->irq, priv);
pci_set_drvdata(pdev, NULL);
- free_orinocodev(dev);
+ free_orinocodev(priv);
pci_iounmap(pdev, priv->hw.iobase);
pci_iounmap(pdev, card->attr_io);
pci_iounmap(pdev, card->bridge_io);
diff --git a/drivers/net/wireless/orinoco/orinoco_tmd.c b/drivers/net/wireless/orinoco/orinoco_tmd.c
index cda0e6e4d7a..d3452548cc7 100644
--- a/drivers/net/wireless/orinoco/orinoco_tmd.c
+++ b/drivers/net/wireless/orinoco/orinoco_tmd.c
@@ -94,7 +94,6 @@ static int orinoco_tmd_init_one(struct pci_dev *pdev,
int err;
struct orinoco_private *priv;
struct orinoco_pci_card *card;
- struct net_device *dev;
void __iomem *hermes_io, *bridge_io;
err = pci_enable_device(pdev);
@@ -124,23 +123,21 @@ static int orinoco_tmd_init_one(struct pci_dev *pdev,
}
/* Allocate network device */
- dev = alloc_orinocodev(sizeof(*card), &pdev->dev,
- orinoco_tmd_cor_reset, NULL);
- if (!dev) {
+ priv = alloc_orinocodev(sizeof(*card), &pdev->dev,
+ orinoco_tmd_cor_reset, NULL);
+ if (!priv) {
printk(KERN_ERR PFX "Cannot allocate network device\n");
err = -ENOMEM;
goto fail_alloc;
}
- priv = netdev_priv(dev);
card = priv->card;
card->bridge_io = bridge_io;
- SET_NETDEV_DEV(dev, &pdev->dev);
hermes_struct_init(&priv->hw, hermes_io, HERMES_16BIT_REGSPACING);
err = request_irq(pdev->irq, orinoco_interrupt, IRQF_SHARED,
- dev->name, dev);
+ DRIVER_NAME, priv);
if (err) {
printk(KERN_ERR PFX "Cannot allocate IRQ %d\n", pdev->irq);
err = -EBUSY;
@@ -153,24 +150,28 @@ static int orinoco_tmd_init_one(struct pci_dev *pdev,
goto fail;
}
- err = register_netdev(dev);
+ err = orinoco_init(priv);
if (err) {
- printk(KERN_ERR PFX "Cannot register network device\n");
+ printk(KERN_ERR PFX "orinoco_init() failed\n");
goto fail;
}
- pci_set_drvdata(pdev, dev);
- printk(KERN_DEBUG "%s: " DRIVER_NAME " at %s\n", dev->name,
- pci_name(pdev));
+ err = orinoco_if_add(priv, 0, 0);
+ if (err) {
+ printk(KERN_ERR PFX "orinoco_if_add() failed\n");
+ goto fail;
+ }
+
+ pci_set_drvdata(pdev, priv);
return 0;
fail:
- free_irq(pdev->irq, dev);
+ free_irq(pdev->irq, priv);
fail_irq:
pci_set_drvdata(pdev, NULL);
- free_orinocodev(dev);
+ free_orinocodev(priv);
fail_alloc:
pci_iounmap(pdev, hermes_io);
@@ -189,14 +190,13 @@ static int orinoco_tmd_init_one(struct pci_dev *pdev,
static void __devexit orinoco_tmd_remove_one(struct pci_dev *pdev)
{
- struct net_device *dev = pci_get_drvdata(pdev);
- struct orinoco_private *priv = netdev_priv(dev);
+ struct orinoco_private *priv = pci_get_drvdata(pdev);
struct orinoco_pci_card *card = priv->card;
- unregister_netdev(dev);
- free_irq(pdev->irq, dev);
+ orinoco_if_del(priv);
+ free_irq(pdev->irq, priv);
pci_set_drvdata(pdev, NULL);
- free_orinocodev(dev);
+ free_orinocodev(priv);
pci_iounmap(pdev, priv->hw.iobase);
pci_iounmap(pdev, card->bridge_io);
pci_release_regions(pdev);
diff --git a/drivers/net/wireless/orinoco/scan.c b/drivers/net/wireless/orinoco/scan.c
index 89d699d4dfe..d2f10e9c216 100644
--- a/drivers/net/wireless/orinoco/scan.c
+++ b/drivers/net/wireless/orinoco/scan.c
@@ -5,147 +5,166 @@
#include <linux/kernel.h>
#include <linux/string.h>
-#include <linux/etherdevice.h>
+#include <linux/ieee80211.h>
+#include <net/cfg80211.h>
#include "hermes.h"
#include "orinoco.h"
+#include "main.h"
#include "scan.h"
-#define ORINOCO_MAX_BSS_COUNT 64
+#define ZERO_DBM_OFFSET 0x95
+#define MAX_SIGNAL_LEVEL 0x8A
+#define MIN_SIGNAL_LEVEL 0x2F
-#define PRIV_BSS ((struct bss_element *)priv->bss_xbss_data)
-#define PRIV_XBSS ((struct xbss_element *)priv->bss_xbss_data)
+#define SIGNAL_TO_DBM(x) \
+ (clamp_t(s32, (x), MIN_SIGNAL_LEVEL, MAX_SIGNAL_LEVEL) \
+ - ZERO_DBM_OFFSET)
+#define SIGNAL_TO_MBM(x) (SIGNAL_TO_DBM(x) * 100)
-int orinoco_bss_data_allocate(struct orinoco_private *priv)
+static int symbol_build_supp_rates(u8 *buf, const __le16 *rates)
{
- if (priv->bss_xbss_data)
- return 0;
-
- if (priv->has_ext_scan)
- priv->bss_xbss_data = kzalloc(ORINOCO_MAX_BSS_COUNT *
- sizeof(struct xbss_element),
- GFP_KERNEL);
- else
- priv->bss_xbss_data = kzalloc(ORINOCO_MAX_BSS_COUNT *
- sizeof(struct bss_element),
- GFP_KERNEL);
-
- if (!priv->bss_xbss_data) {
- printk(KERN_WARNING "Out of memory allocating beacons");
- return -ENOMEM;
+ int i;
+ u8 rate;
+
+ buf[0] = WLAN_EID_SUPP_RATES;
+ for (i = 0; i < 5; i++) {
+ rate = le16_to_cpu(rates[i]);
+ /* NULL terminated */
+ if (rate == 0x0)
+ break;
+ buf[i + 2] = rate;
}
- return 0;
-}
+ buf[1] = i;
-void orinoco_bss_data_free(struct orinoco_private *priv)
-{
- kfree(priv->bss_xbss_data);
- priv->bss_xbss_data = NULL;
+ return i + 2;
}
-void orinoco_bss_data_init(struct orinoco_private *priv)
+static int prism_build_supp_rates(u8 *buf, const u8 *rates)
{
int i;
- INIT_LIST_HEAD(&priv->bss_free_list);
- INIT_LIST_HEAD(&priv->bss_list);
- if (priv->has_ext_scan)
- for (i = 0; i < ORINOCO_MAX_BSS_COUNT; i++)
- list_add_tail(&(PRIV_XBSS[i].list),
- &priv->bss_free_list);
- else
- for (i = 0; i < ORINOCO_MAX_BSS_COUNT; i++)
- list_add_tail(&(PRIV_BSS[i].list),
- &priv->bss_free_list);
-
-}
-
-void orinoco_clear_scan_results(struct orinoco_private *priv,
- unsigned long scan_age)
-{
- if (priv->has_ext_scan) {
- struct xbss_element *bss;
- struct xbss_element *tmp_bss;
-
- /* Blow away current list of scan results */
- list_for_each_entry_safe(bss, tmp_bss, &priv->bss_list, list) {
- if (!scan_age ||
- time_after(jiffies, bss->last_scanned + scan_age)) {
- list_move_tail(&bss->list,
- &priv->bss_free_list);
- /* Don't blow away ->list, just BSS data */
- memset(&bss->bss, 0, sizeof(bss->bss));
- bss->last_scanned = 0;
- }
- }
- } else {
- struct bss_element *bss;
- struct bss_element *tmp_bss;
-
- /* Blow away current list of scan results */
- list_for_each_entry_safe(bss, tmp_bss, &priv->bss_list, list) {
- if (!scan_age ||
- time_after(jiffies, bss->last_scanned + scan_age)) {
- list_move_tail(&bss->list,
- &priv->bss_free_list);
- /* Don't blow away ->list, just BSS data */
- memset(&bss->bss, 0, sizeof(bss->bss));
- bss->last_scanned = 0;
- }
+ buf[0] = WLAN_EID_SUPP_RATES;
+ for (i = 0; i < 8; i++) {
+ /* NULL terminated */
+ if (rates[i] == 0x0)
+ break;
+ buf[i + 2] = rates[i];
+ }
+ buf[1] = i;
+
+ /* We might still have another 2 rates, which need to go in
+ * extended supported rates */
+ if (i == 8 && rates[i] > 0) {
+ buf[10] = WLAN_EID_EXT_SUPP_RATES;
+ for (; i < 10; i++) {
+ /* NULL terminated */
+ if (rates[i] == 0x0)
+ break;
+ buf[i + 2] = rates[i];
}
+ buf[11] = i - 8;
}
+
+ return (i < 8) ? i + 2 : i + 4;
}
-void orinoco_add_ext_scan_result(struct orinoco_private *priv,
- struct agere_ext_scan_info *atom)
+static void orinoco_add_hostscan_result(struct orinoco_private *priv,
+ const union hermes_scan_info *bss)
{
- struct xbss_element *bss = NULL;
- int found = 0;
-
- /* Try to update an existing bss first */
- list_for_each_entry(bss, &priv->bss_list, list) {
- if (compare_ether_addr(bss->bss.bssid, atom->bssid))
- continue;
- /* ESSID lengths */
- if (bss->bss.data[1] != atom->data[1])
- continue;
- if (memcmp(&bss->bss.data[2], &atom->data[2],
- atom->data[1]))
- continue;
- found = 1;
+ struct wiphy *wiphy = priv_to_wiphy(priv);
+ struct ieee80211_channel *channel;
+ u8 *ie;
+ u8 ie_buf[46];
+ u64 timestamp;
+ s32 signal;
+ u16 capability;
+ u16 beacon_interval;
+ int ie_len;
+ int freq;
+ int len;
+
+ len = le16_to_cpu(bss->a.essid_len);
+
+ /* Reconstruct SSID and bitrate IEs to pass up */
+ ie_buf[0] = WLAN_EID_SSID;
+ ie_buf[1] = len;
+ memcpy(&ie_buf[2], bss->a.essid, len);
+
+ ie = ie_buf + len + 2;
+ ie_len = ie_buf[1] + 2;
+ switch (priv->firmware_type) {
+ case FIRMWARE_TYPE_SYMBOL:
+ ie_len += symbol_build_supp_rates(ie, bss->s.rates);
break;
- }
- /* Grab a bss off the free list */
- if (!found && !list_empty(&priv->bss_free_list)) {
- bss = list_entry(priv->bss_free_list.next,
- struct xbss_element, list);
- list_del(priv->bss_free_list.next);
+ case FIRMWARE_TYPE_INTERSIL:
+ ie_len += prism_build_supp_rates(ie, bss->p.rates);
+ break;
- list_add_tail(&bss->list, &priv->bss_list);
+ case FIRMWARE_TYPE_AGERE:
+ default:
+ break;
}
- if (bss) {
- /* Always update the BSS to get latest beacon info */
- memcpy(&bss->bss, atom, sizeof(bss->bss));
- bss->last_scanned = jiffies;
- }
+ freq = ieee80211_dsss_chan_to_freq(le16_to_cpu(bss->a.channel));
+ channel = ieee80211_get_channel(wiphy, freq);
+ timestamp = 0;
+ capability = le16_to_cpu(bss->a.capabilities);
+ beacon_interval = le16_to_cpu(bss->a.beacon_interv);
+ signal = SIGNAL_TO_MBM(le16_to_cpu(bss->a.level));
+
+ cfg80211_inform_bss(wiphy, channel, bss->a.bssid, timestamp,
+ capability, beacon_interval, ie_buf, ie_len,
+ signal, GFP_KERNEL);
}
-int orinoco_process_scan_results(struct orinoco_private *priv,
- unsigned char *buf,
- int len)
+void orinoco_add_extscan_result(struct orinoco_private *priv,
+ struct agere_ext_scan_info *bss,
+ size_t len)
{
- int offset; /* In the scan data */
- union hermes_scan_info *atom;
- int atom_len;
+ struct wiphy *wiphy = priv_to_wiphy(priv);
+ struct ieee80211_channel *channel;
+ u8 *ie;
+ u64 timestamp;
+ s32 signal;
+ u16 capability;
+ u16 beacon_interval;
+ size_t ie_len;
+ int chan, freq;
+
+ ie_len = len - sizeof(*bss);
+ ie = orinoco_get_ie(bss->data, ie_len, WLAN_EID_DS_PARAMS);
+ chan = ie ? ie[2] : 0;
+ freq = ieee80211_dsss_chan_to_freq(chan);
+ channel = ieee80211_get_channel(wiphy, freq);
+
+ timestamp = le64_to_cpu(bss->timestamp);
+ capability = le16_to_cpu(bss->capabilities);
+ beacon_interval = le16_to_cpu(bss->beacon_interval);
+ ie = bss->data;
+ signal = SIGNAL_TO_MBM(bss->level);
+
+ cfg80211_inform_bss(wiphy, channel, bss->bssid, timestamp,
+ capability, beacon_interval, ie, ie_len,
+ signal, GFP_KERNEL);
+}
+
+void orinoco_add_hostscan_results(struct orinoco_private *priv,
+ unsigned char *buf,
+ size_t len)
+{
+ int offset; /* In the scan data */
+ size_t atom_len;
+ bool abort = false;
switch (priv->firmware_type) {
case FIRMWARE_TYPE_AGERE:
atom_len = sizeof(struct agere_scan_apinfo);
offset = 0;
break;
+
case FIRMWARE_TYPE_SYMBOL:
/* Lack of documentation necessitates this hack.
* Different firmwares have 68 or 76 byte long atoms.
@@ -163,6 +182,7 @@ int orinoco_process_scan_results(struct orinoco_private *priv,
atom_len = 68;
offset = 0;
break;
+
case FIRMWARE_TYPE_INTERSIL:
offset = 4;
if (priv->has_hostscan) {
@@ -170,64 +190,41 @@ int orinoco_process_scan_results(struct orinoco_private *priv,
/* Sanity check for atom_len */
if (atom_len < sizeof(struct prism2_scan_apinfo)) {
printk(KERN_ERR "%s: Invalid atom_len in scan "
- "data: %d\n", priv->ndev->name,
+ "data: %zu\n", priv->ndev->name,
atom_len);
- return -EIO;
+ abort = true;
+ goto scan_abort;
}
} else
atom_len = offsetof(struct prism2_scan_apinfo, atim);
break;
+
default:
- return -EOPNOTSUPP;
+ abort = true;
+ goto scan_abort;
}
/* Check that we got an whole number of atoms */
if ((len - offset) % atom_len) {
- printk(KERN_ERR "%s: Unexpected scan data length %d, "
- "atom_len %d, offset %d\n", priv->ndev->name, len,
+ printk(KERN_ERR "%s: Unexpected scan data length %zu, "
+ "atom_len %zu, offset %d\n", priv->ndev->name, len,
atom_len, offset);
- return -EIO;
+ abort = true;
+ goto scan_abort;
}
- orinoco_clear_scan_results(priv, msecs_to_jiffies(15000));
-
- /* Read the entries one by one */
+ /* Process the entries one by one */
for (; offset + atom_len <= len; offset += atom_len) {
- int found = 0;
- struct bss_element *bss = NULL;
+ union hermes_scan_info *atom;
- /* Get next atom */
atom = (union hermes_scan_info *) (buf + offset);
- /* Try to update an existing bss first */
- list_for_each_entry(bss, &priv->bss_list, list) {
- if (compare_ether_addr(bss->bss.a.bssid, atom->a.bssid))
- continue;
- if (le16_to_cpu(bss->bss.a.essid_len) !=
- le16_to_cpu(atom->a.essid_len))
- continue;
- if (memcmp(bss->bss.a.essid, atom->a.essid,
- le16_to_cpu(atom->a.essid_len)))
- continue;
- found = 1;
- break;
- }
-
- /* Grab a bss off the free list */
- if (!found && !list_empty(&priv->bss_free_list)) {
- bss = list_entry(priv->bss_free_list.next,
- struct bss_element, list);
- list_del(priv->bss_free_list.next);
-
- list_add_tail(&bss->list, &priv->bss_list);
- }
-
- if (bss) {
- /* Always update the BSS to get latest beacon info */
- memcpy(&bss->bss, atom, sizeof(bss->bss));
- bss->last_scanned = jiffies;
- }
+ orinoco_add_hostscan_result(priv, atom);
}
- return 0;
+ scan_abort:
+ if (priv->scan_request) {
+ cfg80211_scan_done(priv->scan_request, abort);
+ priv->scan_request = NULL;
+ }
}
diff --git a/drivers/net/wireless/orinoco/scan.h b/drivers/net/wireless/orinoco/scan.h
index f319f7466af..2dc4e046dbd 100644
--- a/drivers/net/wireless/orinoco/scan.h
+++ b/drivers/net/wireless/orinoco/scan.h
@@ -9,21 +9,12 @@
struct orinoco_private;
struct agere_ext_scan_info;
-/* Setup and free memory for scan results */
-int orinoco_bss_data_allocate(struct orinoco_private *priv);
-void orinoco_bss_data_free(struct orinoco_private *priv);
-void orinoco_bss_data_init(struct orinoco_private *priv);
-
/* Add scan results */
-void orinoco_add_ext_scan_result(struct orinoco_private *priv,
- struct agere_ext_scan_info *atom);
-int orinoco_process_scan_results(struct orinoco_private *dev,
- unsigned char *buf,
- int len);
-
-/* Clear scan results */
-void orinoco_clear_scan_results(struct orinoco_private *priv,
- unsigned long scan_age);
-
+void orinoco_add_extscan_result(struct orinoco_private *priv,
+ struct agere_ext_scan_info *atom,
+ size_t len);
+void orinoco_add_hostscan_results(struct orinoco_private *dev,
+ unsigned char *buf,
+ size_t len);
#endif /* _ORINOCO_SCAN_H_ */
diff --git a/drivers/net/wireless/orinoco/spectrum_cs.c b/drivers/net/wireless/orinoco/spectrum_cs.c
index 38e5198e44c..c361310b885 100644
--- a/drivers/net/wireless/orinoco/spectrum_cs.c
+++ b/drivers/net/wireless/orinoco/spectrum_cs.c
@@ -178,27 +178,25 @@ spectrum_cs_stop_firmware(struct orinoco_private *priv, int idle)
static int
spectrum_cs_probe(struct pcmcia_device *link)
{
- struct net_device *dev;
struct orinoco_private *priv;
struct orinoco_pccard *card;
- dev = alloc_orinocodev(sizeof(*card), &handle_to_dev(link),
- spectrum_cs_hard_reset,
- spectrum_cs_stop_firmware);
- if (!dev)
+ priv = alloc_orinocodev(sizeof(*card), &handle_to_dev(link),
+ spectrum_cs_hard_reset,
+ spectrum_cs_stop_firmware);
+ if (!priv)
return -ENOMEM;
- priv = netdev_priv(dev);
card = priv->card;
/* Link both structures together */
card->p_dev = link;
- link->priv = dev;
+ link->priv = priv;
/* Interrupt setup */
link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING | IRQ_HANDLE_PRESENT;
link->irq.IRQInfo1 = IRQ_LEVEL_ID;
link->irq.Handler = orinoco_interrupt;
- link->irq.Instance = dev;
+ link->irq.Instance = priv;
/* General socket configuration defaults can go here. In this
* client, we assume very little, and rely on the CIS for
@@ -219,14 +217,14 @@ spectrum_cs_probe(struct pcmcia_device *link)
*/
static void spectrum_cs_detach(struct pcmcia_device *link)
{
- struct net_device *dev = link->priv;
+ struct orinoco_private *priv = link->priv;
if (link->dev_node)
- unregister_netdev(dev);
+ orinoco_if_del(priv);
spectrum_cs_release(link);
- free_orinocodev(dev);
+ free_orinocodev(priv);
} /* spectrum_cs_detach */
/*
@@ -306,8 +304,7 @@ next_entry:
static int
spectrum_cs_config(struct pcmcia_device *link)
{
- struct net_device *dev = link->priv;
- struct orinoco_private *priv = netdev_priv(dev);
+ struct orinoco_private *priv = link->priv;
struct orinoco_pccard *card = priv->card;
hermes_t *hw = &priv->hw;
int last_fn, last_ret;
@@ -362,34 +359,31 @@ spectrum_cs_config(struct pcmcia_device *link)
pcmcia_request_configuration(link, &link->conf));
/* Ok, we have the configuration, prepare to register the netdev */
- dev->base_addr = link->io.BasePort1;
- dev->irq = link->irq.AssignedIRQ;
card->node.major = card->node.minor = 0;
/* Reset card */
if (spectrum_cs_hard_reset(priv) != 0)
goto failed;
- SET_NETDEV_DEV(dev, &handle_to_dev(link));
- /* Tell the stack we exist */
- if (register_netdev(dev) != 0) {
- printk(KERN_ERR PFX "register_netdev() failed\n");
+ /* Initialise the main driver */
+ if (orinoco_init(priv) != 0) {
+ printk(KERN_ERR PFX "orinoco_init() failed\n");
+ goto failed;
+ }
+
+ /* Register an interface with the stack */
+ if (orinoco_if_add(priv, link->io.BasePort1,
+ link->irq.AssignedIRQ) != 0) {
+ printk(KERN_ERR PFX "orinoco_if_add() failed\n");
goto failed;
}
/* At this point, the dev_node_t structure(s) needs to be
* initialized and arranged in a linked list at link->dev_node. */
- strcpy(card->node.dev_name, dev->name);
+ strcpy(card->node.dev_name, priv->ndev->name);
link->dev_node = &card->node; /* link->dev_node being non-NULL is also
* used to indicate that the
* net_device has been registered */
-
- /* Finally, report what we've done */
- printk(KERN_DEBUG "%s: " DRIVER_NAME " at %s, irq %d, io "
- "0x%04x-0x%04x\n", dev->name, dev_name(dev->dev.parent),
- link->irq.AssignedIRQ, link->io.BasePort1,
- link->io.BasePort1 + link->io.NumPorts1 - 1);
-
return 0;
cs_failed:
@@ -408,8 +402,7 @@ spectrum_cs_config(struct pcmcia_device *link)
static void
spectrum_cs_release(struct pcmcia_device *link)
{
- struct net_device *dev = link->priv;
- struct orinoco_private *priv = netdev_priv(dev);
+ struct orinoco_private *priv = link->priv;
unsigned long flags;
/* We're committed to taking the device away now, so mark the
@@ -427,23 +420,11 @@ spectrum_cs_release(struct pcmcia_device *link)
static int
spectrum_cs_suspend(struct pcmcia_device *link)
{
- struct net_device *dev = link->priv;
- struct orinoco_private *priv = netdev_priv(dev);
- unsigned long flags;
+ struct orinoco_private *priv = link->priv;
int err = 0;
/* Mark the device as stopped, to block IO until later */
- spin_lock_irqsave(&priv->lock, flags);
-
- err = __orinoco_down(dev);
- if (err)
- printk(KERN_WARNING "%s: Error %d downing interface\n",
- dev->name, err);
-
- netif_device_detach(dev);
- priv->hw_unavailable++;
-
- spin_unlock_irqrestore(&priv->lock, flags);
+ orinoco_down(priv);
return err;
}
@@ -451,33 +432,10 @@ spectrum_cs_suspend(struct pcmcia_device *link)
static int
spectrum_cs_resume(struct pcmcia_device *link)
{
- struct net_device *dev = link->priv;
- struct orinoco_private *priv = netdev_priv(dev);
- unsigned long flags;
- int err;
-
- err = orinoco_reinit_firmware(dev);
- if (err) {
- printk(KERN_ERR "%s: Error %d re-initializing firmware\n",
- dev->name, err);
- return -EIO;
- }
-
- spin_lock_irqsave(&priv->lock, flags);
-
- netif_device_attach(dev);
- priv->hw_unavailable--;
+ struct orinoco_private *priv = link->priv;
+ int err = orinoco_up(priv);
- if (priv->open && !priv->hw_unavailable) {
- err = __orinoco_up(dev);
- if (err)
- printk(KERN_ERR "%s: Error %d restarting card\n",
- dev->name, err);
- }
-
- spin_unlock_irqrestore(&priv->lock, flags);
-
- return 0;
+ return err;
}
diff --git a/drivers/net/wireless/orinoco/wext.c b/drivers/net/wireless/orinoco/wext.c
index 3f081423439..3e56f7643df 100644
--- a/drivers/net/wireless/orinoco/wext.c
+++ b/drivers/net/wireless/orinoco/wext.c
@@ -7,6 +7,7 @@
#include <linux/wireless.h>
#include <linux/ieee80211.h>
#include <net/iw_handler.h>
+#include <net/cfg80211.h>
#include "hermes.h"
#include "hermes_rid.h"
@@ -21,9 +22,70 @@
#define MAX_RID_LEN 1024
+/* Helper routine to record keys
+ * Do not call from interrupt context */
+static int orinoco_set_key(struct orinoco_private *priv, int index,
+ enum orinoco_alg alg, const u8 *key, int key_len,
+ const u8 *seq, int seq_len)
+{
+ kzfree(priv->keys[index].key);
+ kzfree(priv->keys[index].seq);
+
+ if (key_len) {
+ priv->keys[index].key = kzalloc(key_len, GFP_KERNEL);
+ if (!priv->keys[index].key)
+ goto nomem;
+ } else
+ priv->keys[index].key = NULL;
+
+ if (seq_len) {
+ priv->keys[index].seq = kzalloc(seq_len, GFP_KERNEL);
+ if (!priv->keys[index].seq)
+ goto free_key;
+ } else
+ priv->keys[index].seq = NULL;
+
+ priv->keys[index].key_len = key_len;
+ priv->keys[index].seq_len = seq_len;
+
+ if (key_len)
+ memcpy(priv->keys[index].key, key, key_len);
+ if (seq_len)
+ memcpy(priv->keys[index].seq, seq, seq_len);
+
+ switch (alg) {
+ case ORINOCO_ALG_TKIP:
+ priv->keys[index].cipher = WLAN_CIPHER_SUITE_TKIP;
+ break;
+
+ case ORINOCO_ALG_WEP:
+ priv->keys[index].cipher = (key_len > SMALL_KEY_SIZE) ?
+ WLAN_CIPHER_SUITE_WEP104 : WLAN_CIPHER_SUITE_WEP40;
+ break;
+
+ case ORINOCO_ALG_NONE:
+ default:
+ priv->keys[index].cipher = 0;
+ break;
+ }
+
+ return 0;
+
+free_key:
+ kfree(priv->keys[index].key);
+ priv->keys[index].key = NULL;
+
+nomem:
+ priv->keys[index].key_len = 0;
+ priv->keys[index].seq_len = 0;
+ priv->keys[index].cipher = 0;
+
+ return -ENOMEM;
+}
+
static struct iw_statistics *orinoco_get_wireless_stats(struct net_device *dev)
{
- struct orinoco_private *priv = netdev_priv(dev);
+ struct orinoco_private *priv = ndev_priv(dev);
hermes_t *hw = &priv->hw;
struct iw_statistics *wstats = &priv->wstats;
int err;
@@ -51,7 +113,7 @@ static struct iw_statistics *orinoco_get_wireless_stats(struct net_device *dev)
* here so we're not safe to sleep here. */
hermes_inquire(hw, HERMES_INQ_TALLIES);
- if (priv->iw_mode == IW_MODE_ADHOC) {
+ if (priv->iw_mode == NL80211_IFTYPE_ADHOC) {
memset(&wstats->qual, 0, sizeof(wstats->qual));
/* If a spy address is defined, we report stats of the
* first spy address - Jean II */
@@ -87,31 +149,12 @@ static struct iw_statistics *orinoco_get_wireless_stats(struct net_device *dev)
/* Wireless extensions */
/********************************************************************/
-static int orinoco_ioctl_getname(struct net_device *dev,
- struct iw_request_info *info,
- char *name,
- char *extra)
-{
- struct orinoco_private *priv = netdev_priv(dev);
- int numrates;
- int err;
-
- err = orinoco_hw_get_bitratelist(priv, &numrates, NULL, 0);
-
- if (!err && (numrates > 2))
- strcpy(name, "IEEE 802.11b");
- else
- strcpy(name, "IEEE 802.11-DS");
-
- return 0;
-}
-
static int orinoco_ioctl_setwap(struct net_device *dev,
struct iw_request_info *info,
struct sockaddr *ap_addr,
char *extra)
{
- struct orinoco_private *priv = netdev_priv(dev);
+ struct orinoco_private *priv = ndev_priv(dev);
int err = -EINPROGRESS; /* Call commit handler */
unsigned long flags;
static const u8 off_addr[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
@@ -142,7 +185,7 @@ static int orinoco_ioctl_setwap(struct net_device *dev,
goto out;
}
- if (priv->iw_mode != IW_MODE_INFRA) {
+ if (priv->iw_mode != NL80211_IFTYPE_STATION) {
printk(KERN_WARNING "%s: Manual roaming supported only in "
"managed mode\n", dev->name);
err = -EOPNOTSUPP;
@@ -172,9 +215,8 @@ static int orinoco_ioctl_getwap(struct net_device *dev,
struct sockaddr *ap_addr,
char *extra)
{
- struct orinoco_private *priv = netdev_priv(dev);
+ struct orinoco_private *priv = ndev_priv(dev);
- hermes_t *hw = &priv->hw;
int err = 0;
unsigned long flags;
@@ -182,197 +224,23 @@ static int orinoco_ioctl_getwap(struct net_device *dev,
return -EBUSY;
ap_addr->sa_family = ARPHRD_ETHER;
- err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENTBSSID,
- ETH_ALEN, NULL, ap_addr->sa_data);
+ err = orinoco_hw_get_current_bssid(priv, ap_addr->sa_data);
orinoco_unlock(priv, &flags);
return err;
}
-static int orinoco_ioctl_setmode(struct net_device *dev,
- struct iw_request_info *info,
- u32 *mode,
- char *extra)
-{
- struct orinoco_private *priv = netdev_priv(dev);
- int err = -EINPROGRESS; /* Call commit handler */
- unsigned long flags;
-
- if (priv->iw_mode == *mode)
- return 0;
-
- if (orinoco_lock(priv, &flags) != 0)
- return -EBUSY;
-
- switch (*mode) {
- case IW_MODE_ADHOC:
- if (!priv->has_ibss && !priv->has_port3)
- err = -EOPNOTSUPP;
- break;
-
- case IW_MODE_INFRA:
- break;
-
- case IW_MODE_MONITOR:
- if (priv->broken_monitor && !force_monitor) {
- printk(KERN_WARNING "%s: Monitor mode support is "
- "buggy in this firmware, not enabling\n",
- dev->name);
- err = -EOPNOTSUPP;
- }
- break;
-
- default:
- err = -EOPNOTSUPP;
- break;
- }
-
- if (err == -EINPROGRESS) {
- priv->iw_mode = *mode;
- set_port_type(priv);
- }
-
- orinoco_unlock(priv, &flags);
-
- return err;
-}
-
-static int orinoco_ioctl_getmode(struct net_device *dev,
- struct iw_request_info *info,
- u32 *mode,
- char *extra)
-{
- struct orinoco_private *priv = netdev_priv(dev);
-
- *mode = priv->iw_mode;
- return 0;
-}
-
-static int orinoco_ioctl_getiwrange(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_point *rrq,
- char *extra)
-{
- struct orinoco_private *priv = netdev_priv(dev);
- int err = 0;
- struct iw_range *range = (struct iw_range *) extra;
- int numrates;
- int i, k;
-
- rrq->length = sizeof(struct iw_range);
- memset(range, 0, sizeof(struct iw_range));
-
- range->we_version_compiled = WIRELESS_EXT;
- range->we_version_source = 22;
-
- /* Set available channels/frequencies */
- range->num_channels = NUM_CHANNELS;
- k = 0;
- for (i = 0; i < NUM_CHANNELS; i++) {
- if (priv->channel_mask & (1 << i)) {
- range->freq[k].i = i + 1;
- range->freq[k].m = (ieee80211_dsss_chan_to_freq(i + 1) *
- 100000);
- range->freq[k].e = 1;
- k++;
- }
-
- if (k >= IW_MAX_FREQUENCIES)
- break;
- }
- range->num_frequency = k;
- range->sensitivity = 3;
-
- if (priv->has_wep) {
- range->max_encoding_tokens = ORINOCO_MAX_KEYS;
- range->encoding_size[0] = SMALL_KEY_SIZE;
- range->num_encoding_sizes = 1;
-
- if (priv->has_big_wep) {
- range->encoding_size[1] = LARGE_KEY_SIZE;
- range->num_encoding_sizes = 2;
- }
- }
-
- if (priv->has_wpa)
- range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_CIPHER_TKIP;
-
- if ((priv->iw_mode == IW_MODE_ADHOC) && (!SPY_NUMBER(priv))) {
- /* Quality stats meaningless in ad-hoc mode */
- } else {
- range->max_qual.qual = 0x8b - 0x2f;
- range->max_qual.level = 0x2f - 0x95 - 1;
- range->max_qual.noise = 0x2f - 0x95 - 1;
- /* Need to get better values */
- range->avg_qual.qual = 0x24;
- range->avg_qual.level = 0xC2;
- range->avg_qual.noise = 0x9E;
- }
-
- err = orinoco_hw_get_bitratelist(priv, &numrates,
- range->bitrate, IW_MAX_BITRATES);
- if (err)
- return err;
- range->num_bitrates = numrates;
-
- /* Set an indication of the max TCP throughput in bit/s that we can
- * expect using this interface. May be use for QoS stuff...
- * Jean II */
- if (numrates > 2)
- range->throughput = 5 * 1000 * 1000; /* ~5 Mb/s */
- else
- range->throughput = 1.5 * 1000 * 1000; /* ~1.5 Mb/s */
-
- range->min_rts = 0;
- range->max_rts = 2347;
- range->min_frag = 256;
- range->max_frag = 2346;
-
- range->min_pmp = 0;
- range->max_pmp = 65535000;
- range->min_pmt = 0;
- range->max_pmt = 65535 * 1000; /* ??? */
- range->pmp_flags = IW_POWER_PERIOD;
- range->pmt_flags = IW_POWER_TIMEOUT;
- range->pm_capa = (IW_POWER_PERIOD | IW_POWER_TIMEOUT |
- IW_POWER_UNICAST_R);
-
- range->retry_capa = IW_RETRY_LIMIT | IW_RETRY_LIFETIME;
- range->retry_flags = IW_RETRY_LIMIT;
- range->r_time_flags = IW_RETRY_LIFETIME;
- range->min_retry = 0;
- range->max_retry = 65535; /* ??? */
- range->min_r_time = 0;
- range->max_r_time = 65535 * 1000; /* ??? */
-
- if (priv->firmware_type == FIRMWARE_TYPE_AGERE)
- range->scan_capa = IW_SCAN_CAPA_ESSID;
- else
- range->scan_capa = IW_SCAN_CAPA_NONE;
-
- /* Event capability (kernel) */
- IW_EVENT_CAPA_SET_KERNEL(range->event_capa);
- /* Event capability (driver) */
- IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWTHRSPY);
- IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWAP);
- IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWSCAN);
- IW_EVENT_CAPA_SET(range->event_capa, IWEVTXDROP);
-
- return 0;
-}
-
static int orinoco_ioctl_setiwencode(struct net_device *dev,
struct iw_request_info *info,
struct iw_point *erq,
char *keybuf)
{
- struct orinoco_private *priv = netdev_priv(dev);
+ struct orinoco_private *priv = ndev_priv(dev);
int index = (erq->flags & IW_ENCODE_INDEX) - 1;
int setindex = priv->tx_key;
- int encode_alg = priv->encode_alg;
+ enum orinoco_alg encode_alg = priv->encode_alg;
int restricted = priv->wep_restrict;
- u16 xlen = 0;
int err = -EINPROGRESS; /* Call commit handler */
unsigned long flags;
@@ -392,25 +260,17 @@ static int orinoco_ioctl_setiwencode(struct net_device *dev,
return -EBUSY;
/* Clear any TKIP key we have */
- if ((priv->has_wpa) && (priv->encode_alg == IW_ENCODE_ALG_TKIP))
+ if ((priv->has_wpa) && (priv->encode_alg == ORINOCO_ALG_TKIP))
(void) orinoco_clear_tkip_key(priv, setindex);
if (erq->length > 0) {
if ((index < 0) || (index >= ORINOCO_MAX_KEYS))
index = priv->tx_key;
- /* Adjust key length to a supported value */
- if (erq->length > SMALL_KEY_SIZE)
- xlen = LARGE_KEY_SIZE;
- else if (erq->length > 0)
- xlen = SMALL_KEY_SIZE;
- else
- xlen = 0;
-
/* Switch on WEP if off */
- if ((encode_alg != IW_ENCODE_ALG_WEP) && (xlen > 0)) {
+ if (encode_alg != ORINOCO_ALG_WEP) {
setindex = index;
- encode_alg = IW_ENCODE_ALG_WEP;
+ encode_alg = ORINOCO_ALG_WEP;
}
} else {
/* Important note : if the user do "iwconfig eth0 enc off",
@@ -423,7 +283,7 @@ static int orinoco_ioctl_setiwencode(struct net_device *dev,
}
} else {
/* Set the index : Check that the key is valid */
- if (priv->keys[index].len == 0) {
+ if (priv->keys[index].key_len == 0) {
err = -EINVAL;
goto out;
}
@@ -432,17 +292,15 @@ static int orinoco_ioctl_setiwencode(struct net_device *dev,
}
if (erq->flags & IW_ENCODE_DISABLED)
- encode_alg = IW_ENCODE_ALG_NONE;
+ encode_alg = ORINOCO_ALG_NONE;
if (erq->flags & IW_ENCODE_OPEN)
restricted = 0;
if (erq->flags & IW_ENCODE_RESTRICTED)
restricted = 1;
if (erq->pointer && erq->length > 0) {
- priv->keys[index].len = cpu_to_le16(xlen);
- memset(priv->keys[index].data, 0,
- sizeof(priv->keys[index].data));
- memcpy(priv->keys[index].data, keybuf, erq->length);
+ err = orinoco_set_key(priv, index, ORINOCO_ALG_WEP, keybuf,
+ erq->length, NULL, 0);
}
priv->tx_key = setindex;
@@ -469,9 +327,8 @@ static int orinoco_ioctl_getiwencode(struct net_device *dev,
struct iw_point *erq,
char *keybuf)
{
- struct orinoco_private *priv = netdev_priv(dev);
+ struct orinoco_private *priv = ndev_priv(dev);
int index = (erq->flags & IW_ENCODE_INDEX) - 1;
- u16 xlen = 0;
unsigned long flags;
if (!priv->has_wep)
@@ -493,11 +350,9 @@ static int orinoco_ioctl_getiwencode(struct net_device *dev,
else
erq->flags |= IW_ENCODE_OPEN;
- xlen = le16_to_cpu(priv->keys[index].len);
-
- erq->length = xlen;
+ erq->length = priv->keys[index].key_len;
- memcpy(keybuf, priv->keys[index].data, ORINOCO_MAX_KEY_SIZE);
+ memcpy(keybuf, priv->keys[index].key, erq->length);
orinoco_unlock(priv, &flags);
return 0;
@@ -508,7 +363,7 @@ static int orinoco_ioctl_setessid(struct net_device *dev,
struct iw_point *erq,
char *essidbuf)
{
- struct orinoco_private *priv = netdev_priv(dev);
+ struct orinoco_private *priv = ndev_priv(dev);
unsigned long flags;
/* Note : ESSID is ignored in Ad-Hoc demo mode, but we can set it
@@ -539,7 +394,7 @@ static int orinoco_ioctl_getessid(struct net_device *dev,
struct iw_point *erq,
char *essidbuf)
{
- struct orinoco_private *priv = netdev_priv(dev);
+ struct orinoco_private *priv = ndev_priv(dev);
int active;
int err = 0;
unsigned long flags;
@@ -562,59 +417,18 @@ static int orinoco_ioctl_getessid(struct net_device *dev,
return 0;
}
-static int orinoco_ioctl_setnick(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_point *nrq,
- char *nickbuf)
-{
- struct orinoco_private *priv = netdev_priv(dev);
- unsigned long flags;
-
- if (nrq->length > IW_ESSID_MAX_SIZE)
- return -E2BIG;
-
- if (orinoco_lock(priv, &flags) != 0)
- return -EBUSY;
-
- memset(priv->nick, 0, sizeof(priv->nick));
- memcpy(priv->nick, nickbuf, nrq->length);
-
- orinoco_unlock(priv, &flags);
-
- return -EINPROGRESS; /* Call commit handler */
-}
-
-static int orinoco_ioctl_getnick(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_point *nrq,
- char *nickbuf)
-{
- struct orinoco_private *priv = netdev_priv(dev);
- unsigned long flags;
-
- if (orinoco_lock(priv, &flags) != 0)
- return -EBUSY;
-
- memcpy(nickbuf, priv->nick, IW_ESSID_MAX_SIZE);
- orinoco_unlock(priv, &flags);
-
- nrq->length = strlen(priv->nick);
-
- return 0;
-}
-
static int orinoco_ioctl_setfreq(struct net_device *dev,
struct iw_request_info *info,
struct iw_freq *frq,
char *extra)
{
- struct orinoco_private *priv = netdev_priv(dev);
+ struct orinoco_private *priv = ndev_priv(dev);
int chan = -1;
unsigned long flags;
int err = -EINPROGRESS; /* Call commit handler */
/* In infrastructure mode the AP sets the channel */
- if (priv->iw_mode == IW_MODE_INFRA)
+ if (priv->iw_mode == NL80211_IFTYPE_STATION)
return -EBUSY;
if ((frq->e == 0) && (frq->m <= 1000)) {
@@ -640,7 +454,7 @@ static int orinoco_ioctl_setfreq(struct net_device *dev,
return -EBUSY;
priv->channel = chan;
- if (priv->iw_mode == IW_MODE_MONITOR) {
+ if (priv->iw_mode == NL80211_IFTYPE_MONITOR) {
/* Fast channel change - no commit if successful */
hermes_t *hw = &priv->hw;
err = hermes_docmd_wait(hw, HERMES_CMD_TEST |
@@ -657,7 +471,7 @@ static int orinoco_ioctl_getfreq(struct net_device *dev,
struct iw_freq *frq,
char *extra)
{
- struct orinoco_private *priv = netdev_priv(dev);
+ struct orinoco_private *priv = ndev_priv(dev);
int tmp;
/* Locking done in there */
@@ -676,7 +490,7 @@ static int orinoco_ioctl_getsens(struct net_device *dev,
struct iw_param *srq,
char *extra)
{
- struct orinoco_private *priv = netdev_priv(dev);
+ struct orinoco_private *priv = ndev_priv(dev);
hermes_t *hw = &priv->hw;
u16 val;
int err;
@@ -705,7 +519,7 @@ static int orinoco_ioctl_setsens(struct net_device *dev,
struct iw_param *srq,
char *extra)
{
- struct orinoco_private *priv = netdev_priv(dev);
+ struct orinoco_private *priv = ndev_priv(dev);
int val = srq->value;
unsigned long flags;
@@ -728,7 +542,7 @@ static int orinoco_ioctl_setrts(struct net_device *dev,
struct iw_param *rrq,
char *extra)
{
- struct orinoco_private *priv = netdev_priv(dev);
+ struct orinoco_private *priv = ndev_priv(dev);
int val = rrq->value;
unsigned long flags;
@@ -752,7 +566,7 @@ static int orinoco_ioctl_getrts(struct net_device *dev,
struct iw_param *rrq,
char *extra)
{
- struct orinoco_private *priv = netdev_priv(dev);
+ struct orinoco_private *priv = ndev_priv(dev);
rrq->value = priv->rts_thresh;
rrq->disabled = (rrq->value == 2347);
@@ -766,7 +580,7 @@ static int orinoco_ioctl_setfrag(struct net_device *dev,
struct iw_param *frq,
char *extra)
{
- struct orinoco_private *priv = netdev_priv(dev);
+ struct orinoco_private *priv = ndev_priv(dev);
int err = -EINPROGRESS; /* Call commit handler */
unsigned long flags;
@@ -806,7 +620,7 @@ static int orinoco_ioctl_getfrag(struct net_device *dev,
struct iw_param *frq,
char *extra)
{
- struct orinoco_private *priv = netdev_priv(dev);
+ struct orinoco_private *priv = ndev_priv(dev);
hermes_t *hw = &priv->hw;
int err;
u16 val;
@@ -847,7 +661,7 @@ static int orinoco_ioctl_setrate(struct net_device *dev,
struct iw_param *rrq,
char *extra)
{
- struct orinoco_private *priv = netdev_priv(dev);
+ struct orinoco_private *priv = ndev_priv(dev);
int ratemode;
int bitrate; /* 100s of kilobits */
unsigned long flags;
@@ -881,7 +695,7 @@ static int orinoco_ioctl_getrate(struct net_device *dev,
struct iw_param *rrq,
char *extra)
{
- struct orinoco_private *priv = netdev_priv(dev);
+ struct orinoco_private *priv = ndev_priv(dev);
int err = 0;
int bitrate, automatic;
unsigned long flags;
@@ -910,7 +724,7 @@ static int orinoco_ioctl_setpower(struct net_device *dev,
struct iw_param *prq,
char *extra)
{
- struct orinoco_private *priv = netdev_priv(dev);
+ struct orinoco_private *priv = ndev_priv(dev);
int err = -EINPROGRESS; /* Call commit handler */
unsigned long flags;
@@ -964,7 +778,7 @@ static int orinoco_ioctl_getpower(struct net_device *dev,
struct iw_param *prq,
char *extra)
{
- struct orinoco_private *priv = netdev_priv(dev);
+ struct orinoco_private *priv = ndev_priv(dev);
hermes_t *hw = &priv->hw;
int err = 0;
u16 enable, period, timeout, mcast;
@@ -1018,13 +832,12 @@ static int orinoco_ioctl_set_encodeext(struct net_device *dev,
union iwreq_data *wrqu,
char *extra)
{
- struct orinoco_private *priv = netdev_priv(dev);
+ struct orinoco_private *priv = ndev_priv(dev);
struct iw_point *encoding = &wrqu->encoding;
struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
int idx, alg = ext->alg, set_key = 1;
unsigned long flags;
int err = -EINVAL;
- u16 key_len;
if (orinoco_lock(priv, &flags) != 0)
return -EBUSY;
@@ -1056,48 +869,41 @@ static int orinoco_ioctl_set_encodeext(struct net_device *dev,
/* Set the requested key first */
switch (alg) {
case IW_ENCODE_ALG_NONE:
- priv->encode_alg = alg;
- priv->keys[idx].len = 0;
+ priv->encode_alg = ORINOCO_ALG_NONE;
+ err = orinoco_set_key(priv, idx, ORINOCO_ALG_NONE,
+ NULL, 0, NULL, 0);
break;
case IW_ENCODE_ALG_WEP:
- if (ext->key_len > SMALL_KEY_SIZE)
- key_len = LARGE_KEY_SIZE;
- else if (ext->key_len > 0)
- key_len = SMALL_KEY_SIZE;
- else
+ if (ext->key_len <= 0)
goto out;
- priv->encode_alg = alg;
- priv->keys[idx].len = cpu_to_le16(key_len);
-
- key_len = min(ext->key_len, key_len);
-
- memset(priv->keys[idx].data, 0, ORINOCO_MAX_KEY_SIZE);
- memcpy(priv->keys[idx].data, ext->key, key_len);
+ priv->encode_alg = ORINOCO_ALG_WEP;
+ err = orinoco_set_key(priv, idx, ORINOCO_ALG_WEP,
+ ext->key, ext->key_len, NULL, 0);
break;
case IW_ENCODE_ALG_TKIP:
{
- hermes_t *hw = &priv->hw;
u8 *tkip_iv = NULL;
if (!priv->has_wpa ||
- (ext->key_len > sizeof(priv->tkip_key[0])))
+ (ext->key_len > sizeof(struct orinoco_tkip_key)))
goto out;
- priv->encode_alg = alg;
- memset(&priv->tkip_key[idx], 0,
- sizeof(priv->tkip_key[idx]));
- memcpy(&priv->tkip_key[idx], ext->key, ext->key_len);
+ priv->encode_alg = ORINOCO_ALG_TKIP;
if (ext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID)
tkip_iv = &ext->rx_seq[0];
- err = __orinoco_hw_set_tkip_key(hw, idx,
+ err = orinoco_set_key(priv, idx, ORINOCO_ALG_TKIP,
+ ext->key, ext->key_len, tkip_iv,
+ ORINOCO_SEQ_LEN);
+
+ err = __orinoco_hw_set_tkip_key(priv, idx,
ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY,
- (u8 *) &priv->tkip_key[idx],
- tkip_iv, NULL);
+ priv->keys[idx].key,
+ tkip_iv, ORINOCO_SEQ_LEN, NULL, 0);
if (err)
printk(KERN_ERR "%s: Error %d setting TKIP key"
"\n", dev->name, err);
@@ -1120,7 +926,7 @@ static int orinoco_ioctl_get_encodeext(struct net_device *dev,
union iwreq_data *wrqu,
char *extra)
{
- struct orinoco_private *priv = netdev_priv(dev);
+ struct orinoco_private *priv = ndev_priv(dev);
struct iw_point *encoding = &wrqu->encoding;
struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
int idx, max_key_len;
@@ -1146,22 +952,22 @@ static int orinoco_ioctl_get_encodeext(struct net_device *dev,
encoding->flags = idx + 1;
memset(ext, 0, sizeof(*ext));
- ext->alg = priv->encode_alg;
switch (priv->encode_alg) {
- case IW_ENCODE_ALG_NONE:
+ case ORINOCO_ALG_NONE:
+ ext->alg = IW_ENCODE_ALG_NONE;
ext->key_len = 0;
encoding->flags |= IW_ENCODE_DISABLED;
break;
- case IW_ENCODE_ALG_WEP:
- ext->key_len = min_t(u16, le16_to_cpu(priv->keys[idx].len),
- max_key_len);
- memcpy(ext->key, priv->keys[idx].data, ext->key_len);
+ case ORINOCO_ALG_WEP:
+ ext->alg = IW_ENCODE_ALG_WEP;
+ ext->key_len = min(priv->keys[idx].key_len, max_key_len);
+ memcpy(ext->key, priv->keys[idx].key, ext->key_len);
encoding->flags |= IW_ENCODE_ENABLED;
break;
- case IW_ENCODE_ALG_TKIP:
- ext->key_len = min_t(u16, sizeof(struct orinoco_tkip_key),
- max_key_len);
- memcpy(ext->key, &priv->tkip_key[idx], ext->key_len);
+ case ORINOCO_ALG_TKIP:
+ ext->alg = IW_ENCODE_ALG_TKIP;
+ ext->key_len = min(priv->keys[idx].key_len, max_key_len);
+ memcpy(ext->key, priv->keys[idx].key, ext->key_len);
encoding->flags |= IW_ENCODE_ENABLED;
break;
}
@@ -1177,7 +983,7 @@ static int orinoco_ioctl_set_auth(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
- struct orinoco_private *priv = netdev_priv(dev);
+ struct orinoco_private *priv = ndev_priv(dev);
hermes_t *hw = &priv->hw;
struct iw_param *param = &wrqu->param;
unsigned long flags;
@@ -1255,7 +1061,7 @@ static int orinoco_ioctl_get_auth(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
- struct orinoco_private *priv = netdev_priv(dev);
+ struct orinoco_private *priv = ndev_priv(dev);
struct iw_param *param = &wrqu->param;
unsigned long flags;
int ret = 0;
@@ -1295,7 +1101,7 @@ static int orinoco_ioctl_set_genie(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
- struct orinoco_private *priv = netdev_priv(dev);
+ struct orinoco_private *priv = ndev_priv(dev);
u8 *buf;
unsigned long flags;
@@ -1338,7 +1144,7 @@ static int orinoco_ioctl_get_genie(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
- struct orinoco_private *priv = netdev_priv(dev);
+ struct orinoco_private *priv = ndev_priv(dev);
unsigned long flags;
int err = 0;
@@ -1367,8 +1173,7 @@ static int orinoco_ioctl_set_mlme(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
- struct orinoco_private *priv = netdev_priv(dev);
- hermes_t *hw = &priv->hw;
+ struct orinoco_private *priv = ndev_priv(dev);
struct iw_mlme *mlme = (struct iw_mlme *)extra;
unsigned long flags;
int ret = 0;
@@ -1382,19 +1187,11 @@ static int orinoco_ioctl_set_mlme(struct net_device *dev,
break;
case IW_MLME_DISASSOC:
- {
- struct {
- u8 addr[ETH_ALEN];
- __le16 reason_code;
- } __attribute__ ((packed)) buf;
-
- memcpy(buf.addr, mlme->addr.sa_data, ETH_ALEN);
- buf.reason_code = cpu_to_le16(mlme->reason_code);
- ret = HERMES_WRITE_RECORD(hw, USER_BAP,
- HERMES_RID_CNFDISASSOCIATE,
- &buf);
+
+ ret = orinoco_hw_disassociate(priv, mlme->addr.sa_data,
+ mlme->reason_code);
break;
- }
+
default:
ret = -EOPNOTSUPP;
}
@@ -1408,7 +1205,7 @@ static int orinoco_ioctl_getretry(struct net_device *dev,
struct iw_param *rrq,
char *extra)
{
- struct orinoco_private *priv = netdev_priv(dev);
+ struct orinoco_private *priv = ndev_priv(dev);
hermes_t *hw = &priv->hw;
int err = 0;
u16 short_limit, long_limit, lifetime;
@@ -1462,7 +1259,7 @@ static int orinoco_ioctl_reset(struct net_device *dev,
void *wrqu,
char *extra)
{
- struct orinoco_private *priv = netdev_priv(dev);
+ struct orinoco_private *priv = ndev_priv(dev);
if (!capable(CAP_NET_ADMIN))
return -EPERM;
@@ -1487,7 +1284,7 @@ static int orinoco_ioctl_setibssport(struct net_device *dev,
char *extra)
{
- struct orinoco_private *priv = netdev_priv(dev);
+ struct orinoco_private *priv = ndev_priv(dev);
int val = *((int *) extra);
unsigned long flags;
@@ -1508,7 +1305,7 @@ static int orinoco_ioctl_getibssport(struct net_device *dev,
void *wrqu,
char *extra)
{
- struct orinoco_private *priv = netdev_priv(dev);
+ struct orinoco_private *priv = ndev_priv(dev);
int *val = (int *) extra;
*val = priv->ibss_port;
@@ -1520,7 +1317,7 @@ static int orinoco_ioctl_setport3(struct net_device *dev,
void *wrqu,
char *extra)
{
- struct orinoco_private *priv = netdev_priv(dev);
+ struct orinoco_private *priv = ndev_priv(dev);
int val = *((int *) extra);
int err = 0;
unsigned long flags;
@@ -1566,7 +1363,7 @@ static int orinoco_ioctl_getport3(struct net_device *dev,
void *wrqu,
char *extra)
{
- struct orinoco_private *priv = netdev_priv(dev);
+ struct orinoco_private *priv = ndev_priv(dev);
int *val = (int *) extra;
*val = priv->prefer_port3;
@@ -1578,7 +1375,7 @@ static int orinoco_ioctl_setpreamble(struct net_device *dev,
void *wrqu,
char *extra)
{
- struct orinoco_private *priv = netdev_priv(dev);
+ struct orinoco_private *priv = ndev_priv(dev);
unsigned long flags;
int val;
@@ -1610,7 +1407,7 @@ static int orinoco_ioctl_getpreamble(struct net_device *dev,
void *wrqu,
char *extra)
{
- struct orinoco_private *priv = netdev_priv(dev);
+ struct orinoco_private *priv = ndev_priv(dev);
int *val = (int *) extra;
if (!priv->has_preamble)
@@ -1630,7 +1427,7 @@ static int orinoco_ioctl_getrid(struct net_device *dev,
struct iw_point *data,
char *extra)
{
- struct orinoco_private *priv = netdev_priv(dev);
+ struct orinoco_private *priv = ndev_priv(dev);
hermes_t *hw = &priv->hw;
int rid = data->flags;
u16 length;
@@ -1661,519 +1458,6 @@ static int orinoco_ioctl_getrid(struct net_device *dev,
return err;
}
-/* Trigger a scan (look for other cells in the vicinity) */
-static int orinoco_ioctl_setscan(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_point *srq,
- char *extra)
-{
- struct orinoco_private *priv = netdev_priv(dev);
- hermes_t *hw = &priv->hw;
- struct iw_scan_req *si = (struct iw_scan_req *) extra;
- int err = 0;
- unsigned long flags;
-
- /* Note : you may have realised that, as this is a SET operation,
- * this is privileged and therefore a normal user can't
- * perform scanning.
- * This is not an error, while the device perform scanning,
- * traffic doesn't flow, so it's a perfect DoS...
- * Jean II */
-
- if (orinoco_lock(priv, &flags) != 0)
- return -EBUSY;
-
- /* Scanning with port 0 disabled would fail */
- if (!netif_running(dev)) {
- err = -ENETDOWN;
- goto out;
- }
-
- /* In monitor mode, the scan results are always empty.
- * Probe responses are passed to the driver as received
- * frames and could be processed in software. */
- if (priv->iw_mode == IW_MODE_MONITOR) {
- err = -EOPNOTSUPP;
- goto out;
- }
-
- /* Note : because we don't lock out the irq handler, the way
- * we access scan variables in priv is critical.
- * o scan_inprogress : not touched by irq handler
- * o scan_mode : not touched by irq handler
- * Before modifying anything on those variables, please think hard !
- * Jean II */
-
- /* Save flags */
- priv->scan_mode = srq->flags;
-
- /* Always trigger scanning, even if it's in progress.
- * This way, if the info frame get lost, we will recover somewhat
- * gracefully - Jean II */
-
- if (priv->has_hostscan) {
- switch (priv->firmware_type) {
- case FIRMWARE_TYPE_SYMBOL:
- err = hermes_write_wordrec(hw, USER_BAP,
- HERMES_RID_CNFHOSTSCAN_SYMBOL,
- HERMES_HOSTSCAN_SYMBOL_ONCE |
- HERMES_HOSTSCAN_SYMBOL_BCAST);
- break;
- case FIRMWARE_TYPE_INTERSIL: {
- __le16 req[3];
-
- req[0] = cpu_to_le16(0x3fff); /* All channels */
- req[1] = cpu_to_le16(0x0001); /* rate 1 Mbps */
- req[2] = 0; /* Any ESSID */
- err = HERMES_WRITE_RECORD(hw, USER_BAP,
- HERMES_RID_CNFHOSTSCAN, &req);
- }
- break;
- case FIRMWARE_TYPE_AGERE:
- if (priv->scan_mode & IW_SCAN_THIS_ESSID) {
- struct hermes_idstring idbuf;
- size_t len = min(sizeof(idbuf.val),
- (size_t) si->essid_len);
- idbuf.len = cpu_to_le16(len);
- memcpy(idbuf.val, si->essid, len);
-
- err = hermes_write_ltv(hw, USER_BAP,
- HERMES_RID_CNFSCANSSID_AGERE,
- HERMES_BYTES_TO_RECLEN(len + 2),
- &idbuf);
- } else
- err = hermes_write_wordrec(hw, USER_BAP,
- HERMES_RID_CNFSCANSSID_AGERE,
- 0); /* Any ESSID */
- if (err)
- break;
-
- if (priv->has_ext_scan) {
- /* Clear scan results at the start of
- * an extended scan */
- orinoco_clear_scan_results(priv,
- msecs_to_jiffies(15000));
-
- /* TODO: Is this available on older firmware?
- * Can we use it to scan specific channels
- * for IW_SCAN_THIS_FREQ? */
- err = hermes_write_wordrec(hw, USER_BAP,
- HERMES_RID_CNFSCANCHANNELS2GHZ,
- 0x7FFF);
- if (err)
- goto out;
-
- err = hermes_inquire(hw,
- HERMES_INQ_CHANNELINFO);
- } else
- err = hermes_inquire(hw, HERMES_INQ_SCAN);
- break;
- }
- } else
- err = hermes_inquire(hw, HERMES_INQ_SCAN);
-
- /* One more client */
- if (!err)
- priv->scan_inprogress = 1;
-
- out:
- orinoco_unlock(priv, &flags);
- return err;
-}
-
-#define MAX_CUSTOM_LEN 64
-
-/* Translate scan data returned from the card to a card independant
- * format that the Wireless Tools will understand - Jean II */
-static inline char *orinoco_translate_scan(struct net_device *dev,
- struct iw_request_info *info,
- char *current_ev,
- char *end_buf,
- union hermes_scan_info *bss,
- unsigned long last_scanned)
-{
- struct orinoco_private *priv = netdev_priv(dev);
- u16 capabilities;
- u16 channel;
- struct iw_event iwe; /* Temporary buffer */
- char custom[MAX_CUSTOM_LEN];
-
- memset(&iwe, 0, sizeof(iwe));
-
- /* First entry *MUST* be the AP MAC address */
- iwe.cmd = SIOCGIWAP;
- iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
- memcpy(iwe.u.ap_addr.sa_data, bss->a.bssid, ETH_ALEN);
- current_ev = iwe_stream_add_event(info, current_ev, end_buf,
- &iwe, IW_EV_ADDR_LEN);
-
- /* Other entries will be displayed in the order we give them */
-
- /* Add the ESSID */
- iwe.u.data.length = le16_to_cpu(bss->a.essid_len);
- if (iwe.u.data.length > 32)
- iwe.u.data.length = 32;
- iwe.cmd = SIOCGIWESSID;
- iwe.u.data.flags = 1;
- current_ev = iwe_stream_add_point(info, current_ev, end_buf,
- &iwe, bss->a.essid);
-
- /* Add mode */
- iwe.cmd = SIOCGIWMODE;
- capabilities = le16_to_cpu(bss->a.capabilities);
- if (capabilities & (WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_IBSS)) {
- if (capabilities & WLAN_CAPABILITY_ESS)
- iwe.u.mode = IW_MODE_MASTER;
- else
- iwe.u.mode = IW_MODE_ADHOC;
- current_ev = iwe_stream_add_event(info, current_ev, end_buf,
- &iwe, IW_EV_UINT_LEN);
- }
-
- channel = bss->s.channel;
- if ((channel >= 1) && (channel <= NUM_CHANNELS)) {
- /* Add channel and frequency */
- iwe.cmd = SIOCGIWFREQ;
- iwe.u.freq.m = channel;
- iwe.u.freq.e = 0;
- current_ev = iwe_stream_add_event(info, current_ev, end_buf,
- &iwe, IW_EV_FREQ_LEN);
-
- iwe.u.freq.m = ieee80211_dsss_chan_to_freq(channel) * 100000;
- iwe.u.freq.e = 1;
- current_ev = iwe_stream_add_event(info, current_ev, end_buf,
- &iwe, IW_EV_FREQ_LEN);
- }
-
- /* Add quality statistics. level and noise in dB. No link quality */
- iwe.cmd = IWEVQUAL;
- iwe.u.qual.updated = IW_QUAL_DBM | IW_QUAL_QUAL_INVALID;
- iwe.u.qual.level = (__u8) le16_to_cpu(bss->a.level) - 0x95;
- iwe.u.qual.noise = (__u8) le16_to_cpu(bss->a.noise) - 0x95;
- /* Wireless tools prior to 27.pre22 will show link quality
- * anyway, so we provide a reasonable value. */
- if (iwe.u.qual.level > iwe.u.qual.noise)
- iwe.u.qual.qual = iwe.u.qual.level - iwe.u.qual.noise;
- else
- iwe.u.qual.qual = 0;
- current_ev = iwe_stream_add_event(info, current_ev, end_buf,
- &iwe, IW_EV_QUAL_LEN);
-
- /* Add encryption capability */
- iwe.cmd = SIOCGIWENCODE;
- if (capabilities & WLAN_CAPABILITY_PRIVACY)
- iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
- else
- iwe.u.data.flags = IW_ENCODE_DISABLED;
- iwe.u.data.length = 0;
- current_ev = iwe_stream_add_point(info, current_ev, end_buf,
- &iwe, NULL);
-
- /* Bit rate is not available in Lucent/Agere firmwares */
- if (priv->firmware_type != FIRMWARE_TYPE_AGERE) {
- char *current_val = current_ev + iwe_stream_lcp_len(info);
- int i;
- int step;
-
- if (priv->firmware_type == FIRMWARE_TYPE_SYMBOL)
- step = 2;
- else
- step = 1;
-
- iwe.cmd = SIOCGIWRATE;
- /* Those two flags are ignored... */
- iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
- /* Max 10 values */
- for (i = 0; i < 10; i += step) {
- /* NULL terminated */
- if (bss->p.rates[i] == 0x0)
- break;
- /* Bit rate given in 500 kb/s units (+ 0x80) */
- iwe.u.bitrate.value =
- ((bss->p.rates[i] & 0x7f) * 500000);
- current_val = iwe_stream_add_value(info, current_ev,
- current_val,
- end_buf, &iwe,
- IW_EV_PARAM_LEN);
- }
- /* Check if we added any event */
- if ((current_val - current_ev) > iwe_stream_lcp_len(info))
- current_ev = current_val;
- }
-
- /* Beacon interval */
- iwe.cmd = IWEVCUSTOM;
- iwe.u.data.length = snprintf(custom, MAX_CUSTOM_LEN,
- "bcn_int=%d",
- le16_to_cpu(bss->a.beacon_interv));
- if (iwe.u.data.length)
- current_ev = iwe_stream_add_point(info, current_ev, end_buf,
- &iwe, custom);
-
- /* Capabilites */
- iwe.cmd = IWEVCUSTOM;
- iwe.u.data.length = snprintf(custom, MAX_CUSTOM_LEN,
- "capab=0x%04x",
- capabilities);
- if (iwe.u.data.length)
- current_ev = iwe_stream_add_point(info, current_ev, end_buf,
- &iwe, custom);
-
- /* Add EXTRA: Age to display seconds since last beacon/probe response
- * for given network. */
- iwe.cmd = IWEVCUSTOM;
- iwe.u.data.length = snprintf(custom, MAX_CUSTOM_LEN,
- " Last beacon: %dms ago",
- jiffies_to_msecs(jiffies - last_scanned));
- if (iwe.u.data.length)
- current_ev = iwe_stream_add_point(info, current_ev, end_buf,
- &iwe, custom);
-
- return current_ev;
-}
-
-static inline char *orinoco_translate_ext_scan(struct net_device *dev,
- struct iw_request_info *info,
- char *current_ev,
- char *end_buf,
- struct agere_ext_scan_info *bss,
- unsigned long last_scanned)
-{
- u16 capabilities;
- u16 channel;
- struct iw_event iwe; /* Temporary buffer */
- char custom[MAX_CUSTOM_LEN];
- u8 *ie;
-
- memset(&iwe, 0, sizeof(iwe));
-
- /* First entry *MUST* be the AP MAC address */
- iwe.cmd = SIOCGIWAP;
- iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
- memcpy(iwe.u.ap_addr.sa_data, bss->bssid, ETH_ALEN);
- current_ev = iwe_stream_add_event(info, current_ev, end_buf,
- &iwe, IW_EV_ADDR_LEN);
-
- /* Other entries will be displayed in the order we give them */
-
- /* Add the ESSID */
- ie = bss->data;
- iwe.u.data.length = ie[1];
- if (iwe.u.data.length) {
- if (iwe.u.data.length > 32)
- iwe.u.data.length = 32;
- iwe.cmd = SIOCGIWESSID;
- iwe.u.data.flags = 1;
- current_ev = iwe_stream_add_point(info, current_ev, end_buf,
- &iwe, &ie[2]);
- }
-
- /* Add mode */
- capabilities = le16_to_cpu(bss->capabilities);
- if (capabilities & (WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_IBSS)) {
- iwe.cmd = SIOCGIWMODE;
- if (capabilities & WLAN_CAPABILITY_ESS)
- iwe.u.mode = IW_MODE_MASTER;
- else
- iwe.u.mode = IW_MODE_ADHOC;
- current_ev = iwe_stream_add_event(info, current_ev, end_buf,
- &iwe, IW_EV_UINT_LEN);
- }
-
- ie = orinoco_get_ie(bss->data, sizeof(bss->data), WLAN_EID_DS_PARAMS);
- channel = ie ? ie[2] : 0;
- if ((channel >= 1) && (channel <= NUM_CHANNELS)) {
- /* Add channel and frequency */
- iwe.cmd = SIOCGIWFREQ;
- iwe.u.freq.m = channel;
- iwe.u.freq.e = 0;
- current_ev = iwe_stream_add_event(info, current_ev, end_buf,
- &iwe, IW_EV_FREQ_LEN);
-
- iwe.u.freq.m = ieee80211_dsss_chan_to_freq(channel) * 100000;
- iwe.u.freq.e = 1;
- current_ev = iwe_stream_add_event(info, current_ev, end_buf,
- &iwe, IW_EV_FREQ_LEN);
- }
-
- /* Add quality statistics. level and noise in dB. No link quality */
- iwe.cmd = IWEVQUAL;
- iwe.u.qual.updated = IW_QUAL_DBM | IW_QUAL_QUAL_INVALID;
- iwe.u.qual.level = bss->level - 0x95;
- iwe.u.qual.noise = bss->noise - 0x95;
- /* Wireless tools prior to 27.pre22 will show link quality
- * anyway, so we provide a reasonable value. */
- if (iwe.u.qual.level > iwe.u.qual.noise)
- iwe.u.qual.qual = iwe.u.qual.level - iwe.u.qual.noise;
- else
- iwe.u.qual.qual = 0;
- current_ev = iwe_stream_add_event(info, current_ev, end_buf,
- &iwe, IW_EV_QUAL_LEN);
-
- /* Add encryption capability */
- iwe.cmd = SIOCGIWENCODE;
- if (capabilities & WLAN_CAPABILITY_PRIVACY)
- iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
- else
- iwe.u.data.flags = IW_ENCODE_DISABLED;
- iwe.u.data.length = 0;
- current_ev = iwe_stream_add_point(info, current_ev, end_buf,
- &iwe, NULL);
-
- /* WPA IE */
- ie = orinoco_get_wpa_ie(bss->data, sizeof(bss->data));
- if (ie) {
- iwe.cmd = IWEVGENIE;
- iwe.u.data.length = ie[1] + 2;
- current_ev = iwe_stream_add_point(info, current_ev, end_buf,
- &iwe, ie);
- }
-
- /* RSN IE */
- ie = orinoco_get_ie(bss->data, sizeof(bss->data), WLAN_EID_RSN);
- if (ie) {
- iwe.cmd = IWEVGENIE;
- iwe.u.data.length = ie[1] + 2;
- current_ev = iwe_stream_add_point(info, current_ev, end_buf,
- &iwe, ie);
- }
-
- ie = orinoco_get_ie(bss->data, sizeof(bss->data), WLAN_EID_SUPP_RATES);
- if (ie) {
- char *p = current_ev + iwe_stream_lcp_len(info);
- int i;
-
- iwe.cmd = SIOCGIWRATE;
- /* Those two flags are ignored... */
- iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
-
- for (i = 2; i < (ie[1] + 2); i++) {
- iwe.u.bitrate.value = ((ie[i] & 0x7F) * 500000);
- p = iwe_stream_add_value(info, current_ev, p, end_buf,
- &iwe, IW_EV_PARAM_LEN);
- }
- /* Check if we added any event */
- if (p > (current_ev + iwe_stream_lcp_len(info)))
- current_ev = p;
- }
-
- /* Timestamp */
- iwe.cmd = IWEVCUSTOM;
- iwe.u.data.length =
- snprintf(custom, MAX_CUSTOM_LEN, "tsf=%016llx",
- (unsigned long long) le64_to_cpu(bss->timestamp));
- if (iwe.u.data.length)
- current_ev = iwe_stream_add_point(info, current_ev, end_buf,
- &iwe, custom);
-
- /* Beacon interval */
- iwe.cmd = IWEVCUSTOM;
- iwe.u.data.length = snprintf(custom, MAX_CUSTOM_LEN,
- "bcn_int=%d",
- le16_to_cpu(bss->beacon_interval));
- if (iwe.u.data.length)
- current_ev = iwe_stream_add_point(info, current_ev, end_buf,
- &iwe, custom);
-
- /* Capabilites */
- iwe.cmd = IWEVCUSTOM;
- iwe.u.data.length = snprintf(custom, MAX_CUSTOM_LEN,
- "capab=0x%04x",
- capabilities);
- if (iwe.u.data.length)
- current_ev = iwe_stream_add_point(info, current_ev, end_buf,
- &iwe, custom);
-
- /* Add EXTRA: Age to display seconds since last beacon/probe response
- * for given network. */
- iwe.cmd = IWEVCUSTOM;
- iwe.u.data.length = snprintf(custom, MAX_CUSTOM_LEN,
- " Last beacon: %dms ago",
- jiffies_to_msecs(jiffies - last_scanned));
- if (iwe.u.data.length)
- current_ev = iwe_stream_add_point(info, current_ev, end_buf,
- &iwe, custom);
-
- return current_ev;
-}
-
-/* Return results of a scan */
-static int orinoco_ioctl_getscan(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_point *srq,
- char *extra)
-{
- struct orinoco_private *priv = netdev_priv(dev);
- int err = 0;
- unsigned long flags;
- char *current_ev = extra;
-
- if (orinoco_lock(priv, &flags) != 0)
- return -EBUSY;
-
- if (priv->scan_inprogress) {
- /* Important note : we don't want to block the caller
- * until results are ready for various reasons.
- * First, managing wait queues is complex and racy.
- * Second, we grab some rtnetlink lock before comming
- * here (in dev_ioctl()).
- * Third, we generate an Wireless Event, so the
- * caller can wait itself on that - Jean II */
- err = -EAGAIN;
- goto out;
- }
-
- if (priv->has_ext_scan) {
- struct xbss_element *bss;
-
- list_for_each_entry(bss, &priv->bss_list, list) {
- /* Translate this entry to WE format */
- current_ev =
- orinoco_translate_ext_scan(dev, info,
- current_ev,
- extra + srq->length,
- &bss->bss,
- bss->last_scanned);
-
- /* Check if there is space for one more entry */
- if ((extra + srq->length - current_ev)
- <= IW_EV_ADDR_LEN) {
- /* Ask user space to try again with a
- * bigger buffer */
- err = -E2BIG;
- goto out;
- }
- }
-
- } else {
- struct bss_element *bss;
-
- list_for_each_entry(bss, &priv->bss_list, list) {
- /* Translate this entry to WE format */
- current_ev = orinoco_translate_scan(dev, info,
- current_ev,
- extra + srq->length,
- &bss->bss,
- bss->last_scanned);
-
- /* Check if there is space for one more entry */
- if ((extra + srq->length - current_ev)
- <= IW_EV_ADDR_LEN) {
- /* Ask user space to try again with a
- * bigger buffer */
- err = -E2BIG;
- goto out;
- }
- }
- }
-
- srq->length = (current_ev - extra);
- srq->flags = (__u16) priv->scan_mode;
-
-out:
- orinoco_unlock(priv, &flags);
- return err;
-}
/* Commit handler, called after set operations */
static int orinoco_ioctl_commit(struct net_device *dev,
@@ -2181,50 +1465,17 @@ static int orinoco_ioctl_commit(struct net_device *dev,
void *wrqu,
char *extra)
{
- struct orinoco_private *priv = netdev_priv(dev);
- struct hermes *hw = &priv->hw;
+ struct orinoco_private *priv = ndev_priv(dev);
unsigned long flags;
int err = 0;
if (!priv->open)
return 0;
- if (priv->broken_disableport) {
- orinoco_reset(&priv->reset_work);
- return 0;
- }
-
if (orinoco_lock(priv, &flags) != 0)
return err;
- err = hermes_disable_port(hw, 0);
- if (err) {
- printk(KERN_WARNING "%s: Unable to disable port "
- "while reconfiguring card\n", dev->name);
- priv->broken_disableport = 1;
- goto out;
- }
-
- err = __orinoco_program_rids(dev);
- if (err) {
- printk(KERN_WARNING "%s: Unable to reconfigure card\n",
- dev->name);
- goto out;
- }
-
- err = hermes_enable_port(hw, 0);
- if (err) {
- printk(KERN_WARNING "%s: Unable to enable port while reconfiguring card\n",
- dev->name);
- goto out;
- }
-
- out:
- if (err) {
- printk(KERN_WARNING "%s: Resetting instead...\n", dev->name);
- schedule_work(&priv->reset_work);
- err = 0;
- }
+ err = orinoco_commit(priv);
orinoco_unlock(priv, &flags);
return err;
@@ -2258,26 +1509,24 @@ static const struct iw_priv_args orinoco_privtab[] = {
[IW_IOCTL_IDX(id)] = (iw_handler) func
static const iw_handler orinoco_handler[] = {
STD_IW_HANDLER(SIOCSIWCOMMIT, orinoco_ioctl_commit),
- STD_IW_HANDLER(SIOCGIWNAME, orinoco_ioctl_getname),
+ STD_IW_HANDLER(SIOCGIWNAME, cfg80211_wext_giwname),
STD_IW_HANDLER(SIOCSIWFREQ, orinoco_ioctl_setfreq),
STD_IW_HANDLER(SIOCGIWFREQ, orinoco_ioctl_getfreq),
- STD_IW_HANDLER(SIOCSIWMODE, orinoco_ioctl_setmode),
- STD_IW_HANDLER(SIOCGIWMODE, orinoco_ioctl_getmode),
+ STD_IW_HANDLER(SIOCSIWMODE, cfg80211_wext_siwmode),
+ STD_IW_HANDLER(SIOCGIWMODE, cfg80211_wext_giwmode),
STD_IW_HANDLER(SIOCSIWSENS, orinoco_ioctl_setsens),
STD_IW_HANDLER(SIOCGIWSENS, orinoco_ioctl_getsens),
- STD_IW_HANDLER(SIOCGIWRANGE, orinoco_ioctl_getiwrange),
+ STD_IW_HANDLER(SIOCGIWRANGE, cfg80211_wext_giwrange),
STD_IW_HANDLER(SIOCSIWSPY, iw_handler_set_spy),
STD_IW_HANDLER(SIOCGIWSPY, iw_handler_get_spy),
STD_IW_HANDLER(SIOCSIWTHRSPY, iw_handler_set_thrspy),
STD_IW_HANDLER(SIOCGIWTHRSPY, iw_handler_get_thrspy),
STD_IW_HANDLER(SIOCSIWAP, orinoco_ioctl_setwap),
STD_IW_HANDLER(SIOCGIWAP, orinoco_ioctl_getwap),
- STD_IW_HANDLER(SIOCSIWSCAN, orinoco_ioctl_setscan),
- STD_IW_HANDLER(SIOCGIWSCAN, orinoco_ioctl_getscan),
+ STD_IW_HANDLER(SIOCSIWSCAN, cfg80211_wext_siwscan),
+ STD_IW_HANDLER(SIOCGIWSCAN, cfg80211_wext_giwscan),
STD_IW_HANDLER(SIOCSIWESSID, orinoco_ioctl_setessid),
STD_IW_HANDLER(SIOCGIWESSID, orinoco_ioctl_getessid),
- STD_IW_HANDLER(SIOCSIWNICKN, orinoco_ioctl_setnick),
- STD_IW_HANDLER(SIOCGIWNICKN, orinoco_ioctl_getnick),
STD_IW_HANDLER(SIOCSIWRATE, orinoco_ioctl_setrate),
STD_IW_HANDLER(SIOCGIWRATE, orinoco_ioctl_getrate),
STD_IW_HANDLER(SIOCSIWRTS, orinoco_ioctl_setrts),
diff --git a/drivers/net/wireless/p54/Makefile b/drivers/net/wireless/p54/Makefile
index c2050dee629..b542e68f178 100644
--- a/drivers/net/wireless/p54/Makefile
+++ b/drivers/net/wireless/p54/Makefile
@@ -1,3 +1,6 @@
+p54common-objs := eeprom.o fwio.o txrx.o main.o
+p54common-$(CONFIG_P54_LEDS) += led.o
+
obj-$(CONFIG_P54_COMMON) += p54common.o
obj-$(CONFIG_P54_USB) += p54usb.o
obj-$(CONFIG_P54_PCI) += p54pci.o
diff --git a/drivers/net/wireless/p54/eeprom.c b/drivers/net/wireless/p54/eeprom.c
new file mode 100644
index 00000000000..0efe67deede
--- /dev/null
+++ b/drivers/net/wireless/p54/eeprom.c
@@ -0,0 +1,753 @@
+/*
+ * EEPROM parser code for mac80211 Prism54 drivers
+ *
+ * Copyright (c) 2006, Michael Wu <flamingice@sourmilk.net>
+ * Copyright (c) 2007-2009, Christian Lamparter <chunkeey@web.de>
+ * Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
+ *
+ * Based on:
+ * - the islsm (softmac prism54) driver, which is:
+ * Copyright 2004-2006 Jean-Baptiste Note <jbnote@gmail.com>, et al.
+ * - stlc45xx driver
+ * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/firmware.h>
+#include <linux/etherdevice.h>
+#include <linux/sort.h>
+
+#include <net/mac80211.h>
+
+#include "p54.h"
+#include "eeprom.h"
+#include "lmac.h"
+
+static struct ieee80211_rate p54_bgrates[] = {
+ { .bitrate = 10, .hw_value = 0, },
+ { .bitrate = 20, .hw_value = 1, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
+ { .bitrate = 55, .hw_value = 2, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
+ { .bitrate = 110, .hw_value = 3, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
+ { .bitrate = 60, .hw_value = 4, },
+ { .bitrate = 90, .hw_value = 5, },
+ { .bitrate = 120, .hw_value = 6, },
+ { .bitrate = 180, .hw_value = 7, },
+ { .bitrate = 240, .hw_value = 8, },
+ { .bitrate = 360, .hw_value = 9, },
+ { .bitrate = 480, .hw_value = 10, },
+ { .bitrate = 540, .hw_value = 11, },
+};
+
+static struct ieee80211_rate p54_arates[] = {
+ { .bitrate = 60, .hw_value = 4, },
+ { .bitrate = 90, .hw_value = 5, },
+ { .bitrate = 120, .hw_value = 6, },
+ { .bitrate = 180, .hw_value = 7, },
+ { .bitrate = 240, .hw_value = 8, },
+ { .bitrate = 360, .hw_value = 9, },
+ { .bitrate = 480, .hw_value = 10, },
+ { .bitrate = 540, .hw_value = 11, },
+};
+
+#define CHAN_HAS_CAL BIT(0)
+#define CHAN_HAS_LIMIT BIT(1)
+#define CHAN_HAS_CURVE BIT(2)
+#define CHAN_HAS_ALL (CHAN_HAS_CAL | CHAN_HAS_LIMIT | CHAN_HAS_CURVE)
+
+struct p54_channel_entry {
+ u16 freq;
+ u16 data;
+ int index;
+ enum ieee80211_band band;
+};
+
+struct p54_channel_list {
+ struct p54_channel_entry *channels;
+ size_t entries;
+ size_t max_entries;
+ size_t band_channel_num[IEEE80211_NUM_BANDS];
+};
+
+static int p54_get_band_from_freq(u16 freq)
+{
+ /* FIXME: sync these values with the 802.11 spec */
+
+ if ((freq >= 2412) && (freq <= 2484))
+ return IEEE80211_BAND_2GHZ;
+
+ if ((freq >= 4920) && (freq <= 5825))
+ return IEEE80211_BAND_5GHZ;
+
+ return -1;
+}
+
+static int p54_compare_channels(const void *_a,
+ const void *_b)
+{
+ const struct p54_channel_entry *a = _a;
+ const struct p54_channel_entry *b = _b;
+
+ return a->index - b->index;
+}
+
+static int p54_fill_band_bitrates(struct ieee80211_hw *dev,
+ struct ieee80211_supported_band *band_entry,
+ enum ieee80211_band band)
+{
+ /* TODO: generate rate array dynamically */
+
+ switch (band) {
+ case IEEE80211_BAND_2GHZ:
+ band_entry->bitrates = p54_bgrates;
+ band_entry->n_bitrates = ARRAY_SIZE(p54_bgrates);
+ break;
+ case IEEE80211_BAND_5GHZ:
+ band_entry->bitrates = p54_arates;
+ band_entry->n_bitrates = ARRAY_SIZE(p54_arates);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int p54_generate_band(struct ieee80211_hw *dev,
+ struct p54_channel_list *list,
+ enum ieee80211_band band)
+{
+ struct p54_common *priv = dev->priv;
+ struct ieee80211_supported_band *tmp, *old;
+ unsigned int i, j;
+ int ret = -ENOMEM;
+
+ if ((!list->entries) || (!list->band_channel_num[band]))
+ return 0;
+
+ tmp = kzalloc(sizeof(*tmp), GFP_KERNEL);
+ if (!tmp)
+ goto err_out;
+
+ tmp->channels = kzalloc(sizeof(struct ieee80211_channel) *
+ list->band_channel_num[band], GFP_KERNEL);
+ if (!tmp->channels)
+ goto err_out;
+
+ ret = p54_fill_band_bitrates(dev, tmp, band);
+ if (ret)
+ goto err_out;
+
+ for (i = 0, j = 0; (j < list->band_channel_num[band]) &&
+ (i < list->entries); i++) {
+
+ if (list->channels[i].band != band)
+ continue;
+
+ if (list->channels[i].data != CHAN_HAS_ALL) {
+ printk(KERN_ERR "%s:%s%s%s is/are missing for "
+ "channel:%d [%d MHz].\n",
+ wiphy_name(dev->wiphy),
+ (list->channels[i].data & CHAN_HAS_CAL ? "" :
+ " [iqauto calibration data]"),
+ (list->channels[i].data & CHAN_HAS_LIMIT ? "" :
+ " [output power limits]"),
+ (list->channels[i].data & CHAN_HAS_CURVE ? "" :
+ " [curve data]"),
+ list->channels[i].index, list->channels[i].freq);
+ }
+
+ tmp->channels[j].band = list->channels[i].band;
+ tmp->channels[j].center_freq = list->channels[i].freq;
+ j++;
+ }
+
+ tmp->n_channels = list->band_channel_num[band];
+ old = priv->band_table[band];
+ priv->band_table[band] = tmp;
+ if (old) {
+ kfree(old->channels);
+ kfree(old);
+ }
+
+ return 0;
+
+err_out:
+ if (tmp) {
+ kfree(tmp->channels);
+ kfree(tmp);
+ }
+
+ return ret;
+}
+
+static void p54_update_channel_param(struct p54_channel_list *list,
+ u16 freq, u16 data)
+{
+ int band, i;
+
+ /*
+ * usually all lists in the eeprom are mostly sorted.
+ * so it's very likely that the entry we are looking for
+ * is right at the end of the list
+ */
+ for (i = list->entries; i >= 0; i--) {
+ if (freq == list->channels[i].freq) {
+ list->channels[i].data |= data;
+ break;
+ }
+ }
+
+ if ((i < 0) && (list->entries < list->max_entries)) {
+ /* entry does not exist yet. Initialize a new one. */
+ band = p54_get_band_from_freq(freq);
+
+ /*
+ * filter out frequencies which don't belong into
+ * any supported band.
+ */
+ if (band < 0)
+ return ;
+
+ i = list->entries++;
+ list->band_channel_num[band]++;
+
+ list->channels[i].freq = freq;
+ list->channels[i].data = data;
+ list->channels[i].band = band;
+ list->channels[i].index = ieee80211_frequency_to_channel(freq);
+ /* TODO: parse output_limit and fill max_power */
+ }
+}
+
+static int p54_generate_channel_lists(struct ieee80211_hw *dev)
+{
+ struct p54_common *priv = dev->priv;
+ struct p54_channel_list *list;
+ unsigned int i, j, max_channel_num;
+ int ret = -ENOMEM;
+ u16 freq;
+
+ if ((priv->iq_autocal_len != priv->curve_data->entries) ||
+ (priv->iq_autocal_len != priv->output_limit->entries))
+ printk(KERN_ERR "%s: EEPROM is damaged... you may not be able"
+ "to use all channels with this device.\n",
+ wiphy_name(dev->wiphy));
+
+ max_channel_num = max_t(unsigned int, priv->output_limit->entries,
+ priv->iq_autocal_len);
+ max_channel_num = max_t(unsigned int, max_channel_num,
+ priv->curve_data->entries);
+
+ list = kzalloc(sizeof(*list), GFP_KERNEL);
+ if (!list)
+ goto free;
+
+ list->max_entries = max_channel_num;
+ list->channels = kzalloc(sizeof(struct p54_channel_entry) *
+ max_channel_num, GFP_KERNEL);
+ if (!list->channels)
+ goto free;
+
+ for (i = 0; i < max_channel_num; i++) {
+ if (i < priv->iq_autocal_len) {
+ freq = le16_to_cpu(priv->iq_autocal[i].freq);
+ p54_update_channel_param(list, freq, CHAN_HAS_CAL);
+ }
+
+ if (i < priv->output_limit->entries) {
+ freq = le16_to_cpup((__le16 *) (i *
+ priv->output_limit->entry_size +
+ priv->output_limit->offset +
+ priv->output_limit->data));
+
+ p54_update_channel_param(list, freq, CHAN_HAS_LIMIT);
+ }
+
+ if (i < priv->curve_data->entries) {
+ freq = le16_to_cpup((__le16 *) (i *
+ priv->curve_data->entry_size +
+ priv->curve_data->offset +
+ priv->curve_data->data));
+
+ p54_update_channel_param(list, freq, CHAN_HAS_CURVE);
+ }
+ }
+
+ /* sort the list by the channel index */
+ sort(list->channels, list->entries, sizeof(struct p54_channel_entry),
+ p54_compare_channels, NULL);
+
+ for (i = 0, j = 0; i < IEEE80211_NUM_BANDS; i++) {
+ if (list->band_channel_num[i]) {
+ ret = p54_generate_band(dev, list, i);
+ if (ret)
+ goto free;
+
+ j++;
+ }
+ }
+ if (j == 0) {
+ /* no useable band available. */
+ ret = -EINVAL;
+ }
+
+free:
+ if (list) {
+ kfree(list->channels);
+ kfree(list);
+ }
+
+ return ret;
+}
+
+static int p54_convert_rev0(struct ieee80211_hw *dev,
+ struct pda_pa_curve_data *curve_data)
+{
+ struct p54_common *priv = dev->priv;
+ struct p54_pa_curve_data_sample *dst;
+ struct pda_pa_curve_data_sample_rev0 *src;
+ size_t cd_len = sizeof(*curve_data) +
+ (curve_data->points_per_channel*sizeof(*dst) + 2) *
+ curve_data->channels;
+ unsigned int i, j;
+ void *source, *target;
+
+ priv->curve_data = kmalloc(sizeof(*priv->curve_data) + cd_len,
+ GFP_KERNEL);
+ if (!priv->curve_data)
+ return -ENOMEM;
+
+ priv->curve_data->entries = curve_data->channels;
+ priv->curve_data->entry_size = sizeof(__le16) +
+ sizeof(*dst) * curve_data->points_per_channel;
+ priv->curve_data->offset = offsetof(struct pda_pa_curve_data, data);
+ priv->curve_data->len = cd_len;
+ memcpy(priv->curve_data->data, curve_data, sizeof(*curve_data));
+ source = curve_data->data;
+ target = ((struct pda_pa_curve_data *) priv->curve_data->data)->data;
+ for (i = 0; i < curve_data->channels; i++) {
+ __le16 *freq = source;
+ source += sizeof(__le16);
+ *((__le16 *)target) = *freq;
+ target += sizeof(__le16);
+ for (j = 0; j < curve_data->points_per_channel; j++) {
+ dst = target;
+ src = source;
+
+ dst->rf_power = src->rf_power;
+ dst->pa_detector = src->pa_detector;
+ dst->data_64qam = src->pcv;
+ /* "invent" the points for the other modulations */
+#define SUB(x, y) (u8)(((x) - (y)) > (x) ? 0 : (x) - (y))
+ dst->data_16qam = SUB(src->pcv, 12);
+ dst->data_qpsk = SUB(dst->data_16qam, 12);
+ dst->data_bpsk = SUB(dst->data_qpsk, 12);
+ dst->data_barker = SUB(dst->data_bpsk, 14);
+#undef SUB
+ target += sizeof(*dst);
+ source += sizeof(*src);
+ }
+ }
+
+ return 0;
+}
+
+static int p54_convert_rev1(struct ieee80211_hw *dev,
+ struct pda_pa_curve_data *curve_data)
+{
+ struct p54_common *priv = dev->priv;
+ struct p54_pa_curve_data_sample *dst;
+ struct pda_pa_curve_data_sample_rev1 *src;
+ size_t cd_len = sizeof(*curve_data) +
+ (curve_data->points_per_channel*sizeof(*dst) + 2) *
+ curve_data->channels;
+ unsigned int i, j;
+ void *source, *target;
+
+ priv->curve_data = kzalloc(cd_len + sizeof(*priv->curve_data),
+ GFP_KERNEL);
+ if (!priv->curve_data)
+ return -ENOMEM;
+
+ priv->curve_data->entries = curve_data->channels;
+ priv->curve_data->entry_size = sizeof(__le16) +
+ sizeof(*dst) * curve_data->points_per_channel;
+ priv->curve_data->offset = offsetof(struct pda_pa_curve_data, data);
+ priv->curve_data->len = cd_len;
+ memcpy(priv->curve_data->data, curve_data, sizeof(*curve_data));
+ source = curve_data->data;
+ target = ((struct pda_pa_curve_data *) priv->curve_data->data)->data;
+ for (i = 0; i < curve_data->channels; i++) {
+ __le16 *freq = source;
+ source += sizeof(__le16);
+ *((__le16 *)target) = *freq;
+ target += sizeof(__le16);
+ for (j = 0; j < curve_data->points_per_channel; j++) {
+ memcpy(target, source, sizeof(*src));
+
+ target += sizeof(*dst);
+ source += sizeof(*src);
+ }
+ source++;
+ }
+
+ return 0;
+}
+
+static const char *p54_rf_chips[] = { "INVALID-0", "Duette3", "Duette2",
+ "Frisbee", "Xbow", "Longbow", "INVALID-6", "INVALID-7" };
+
+static void p54_parse_rssical(struct ieee80211_hw *dev, void *data, int len,
+ u16 type)
+{
+ struct p54_common *priv = dev->priv;
+ int offset = (type == PDR_RSSI_LINEAR_APPROXIMATION_EXTENDED) ? 2 : 0;
+ int entry_size = sizeof(struct pda_rssi_cal_entry) + offset;
+ int num_entries = (type == PDR_RSSI_LINEAR_APPROXIMATION) ? 1 : 2;
+ int i;
+
+ if (len != (entry_size * num_entries)) {
+ printk(KERN_ERR "%s: unknown rssi calibration data packing "
+ " type:(%x) len:%d.\n",
+ wiphy_name(dev->wiphy), type, len);
+
+ print_hex_dump_bytes("rssical:", DUMP_PREFIX_NONE,
+ data, len);
+
+ printk(KERN_ERR "%s: please report this issue.\n",
+ wiphy_name(dev->wiphy));
+ return;
+ }
+
+ for (i = 0; i < num_entries; i++) {
+ struct pda_rssi_cal_entry *cal = data +
+ (offset + i * entry_size);
+ priv->rssical_db[i].mul = (s16) le16_to_cpu(cal->mul);
+ priv->rssical_db[i].add = (s16) le16_to_cpu(cal->add);
+ }
+}
+
+static void p54_parse_default_country(struct ieee80211_hw *dev,
+ void *data, int len)
+{
+ struct pda_country *country;
+
+ if (len != sizeof(*country)) {
+ printk(KERN_ERR "%s: found possible invalid default country "
+ "eeprom entry. (entry size: %d)\n",
+ wiphy_name(dev->wiphy), len);
+
+ print_hex_dump_bytes("country:", DUMP_PREFIX_NONE,
+ data, len);
+
+ printk(KERN_ERR "%s: please report this issue.\n",
+ wiphy_name(dev->wiphy));
+ return;
+ }
+
+ country = (struct pda_country *) data;
+ if (country->flags == PDR_COUNTRY_CERT_CODE_PSEUDO)
+ regulatory_hint(dev->wiphy, country->alpha2);
+ else {
+ /* TODO:
+ * write a shared/common function that converts
+ * "Regulatory domain codes" (802.11-2007 14.8.2.2)
+ * into ISO/IEC 3166-1 alpha2 for regulatory_hint.
+ */
+ }
+}
+
+static int p54_convert_output_limits(struct ieee80211_hw *dev,
+ u8 *data, size_t len)
+{
+ struct p54_common *priv = dev->priv;
+
+ if (len < 2)
+ return -EINVAL;
+
+ if (data[0] != 0) {
+ printk(KERN_ERR "%s: unknown output power db revision:%x\n",
+ wiphy_name(dev->wiphy), data[0]);
+ return -EINVAL;
+ }
+
+ if (2 + data[1] * sizeof(struct pda_channel_output_limit) > len)
+ return -EINVAL;
+
+ priv->output_limit = kmalloc(data[1] *
+ sizeof(struct pda_channel_output_limit) +
+ sizeof(*priv->output_limit), GFP_KERNEL);
+
+ if (!priv->output_limit)
+ return -ENOMEM;
+
+ priv->output_limit->offset = 0;
+ priv->output_limit->entries = data[1];
+ priv->output_limit->entry_size =
+ sizeof(struct pda_channel_output_limit);
+ priv->output_limit->len = priv->output_limit->entry_size *
+ priv->output_limit->entries +
+ priv->output_limit->offset;
+
+ memcpy(priv->output_limit->data, &data[2],
+ data[1] * sizeof(struct pda_channel_output_limit));
+
+ return 0;
+}
+
+static struct p54_cal_database *p54_convert_db(struct pda_custom_wrapper *src,
+ size_t total_len)
+{
+ struct p54_cal_database *dst;
+ size_t payload_len, entries, entry_size, offset;
+
+ payload_len = le16_to_cpu(src->len);
+ entries = le16_to_cpu(src->entries);
+ entry_size = le16_to_cpu(src->entry_size);
+ offset = le16_to_cpu(src->offset);
+ if (((entries * entry_size + offset) != payload_len) ||
+ (payload_len + sizeof(*src) != total_len))
+ return NULL;
+
+ dst = kmalloc(sizeof(*dst) + payload_len, GFP_KERNEL);
+ if (!dst)
+ return NULL;
+
+ dst->entries = entries;
+ dst->entry_size = entry_size;
+ dst->offset = offset;
+ dst->len = payload_len;
+
+ memcpy(dst->data, src->data, payload_len);
+ return dst;
+}
+
+int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len)
+{
+ struct p54_common *priv = dev->priv;
+ struct eeprom_pda_wrap *wrap;
+ struct pda_entry *entry;
+ unsigned int data_len, entry_len;
+ void *tmp;
+ int err;
+ u8 *end = (u8 *)eeprom + len;
+ u16 synth = 0;
+
+ wrap = (struct eeprom_pda_wrap *) eeprom;
+ entry = (void *)wrap->data + le16_to_cpu(wrap->len);
+
+ /* verify that at least the entry length/code fits */
+ while ((u8 *)entry <= end - sizeof(*entry)) {
+ entry_len = le16_to_cpu(entry->len);
+ data_len = ((entry_len - 1) << 1);
+
+ /* abort if entry exceeds whole structure */
+ if ((u8 *)entry + sizeof(*entry) + data_len > end)
+ break;
+
+ switch (le16_to_cpu(entry->code)) {
+ case PDR_MAC_ADDRESS:
+ if (data_len != ETH_ALEN)
+ break;
+ SET_IEEE80211_PERM_ADDR(dev, entry->data);
+ break;
+ case PDR_PRISM_PA_CAL_OUTPUT_POWER_LIMITS:
+ if (priv->output_limit)
+ break;
+ err = p54_convert_output_limits(dev, entry->data,
+ data_len);
+ if (err)
+ goto err;
+ break;
+ case PDR_PRISM_PA_CAL_CURVE_DATA: {
+ struct pda_pa_curve_data *curve_data =
+ (struct pda_pa_curve_data *)entry->data;
+ if (data_len < sizeof(*curve_data)) {
+ err = -EINVAL;
+ goto err;
+ }
+
+ switch (curve_data->cal_method_rev) {
+ case 0:
+ err = p54_convert_rev0(dev, curve_data);
+ break;
+ case 1:
+ err = p54_convert_rev1(dev, curve_data);
+ break;
+ default:
+ printk(KERN_ERR "%s: unknown curve data "
+ "revision %d\n",
+ wiphy_name(dev->wiphy),
+ curve_data->cal_method_rev);
+ err = -ENODEV;
+ break;
+ }
+ if (err)
+ goto err;
+ }
+ break;
+ case PDR_PRISM_ZIF_TX_IQ_CALIBRATION:
+ priv->iq_autocal = kmalloc(data_len, GFP_KERNEL);
+ if (!priv->iq_autocal) {
+ err = -ENOMEM;
+ goto err;
+ }
+
+ memcpy(priv->iq_autocal, entry->data, data_len);
+ priv->iq_autocal_len = data_len / sizeof(struct pda_iq_autocal_entry);
+ break;
+ case PDR_DEFAULT_COUNTRY:
+ p54_parse_default_country(dev, entry->data, data_len);
+ break;
+ case PDR_INTERFACE_LIST:
+ tmp = entry->data;
+ while ((u8 *)tmp < entry->data + data_len) {
+ struct exp_if *exp_if = tmp;
+ if (exp_if->if_id == cpu_to_le16(IF_ID_ISL39000))
+ synth = le16_to_cpu(exp_if->variant);
+ tmp += sizeof(*exp_if);
+ }
+ break;
+ case PDR_HARDWARE_PLATFORM_COMPONENT_ID:
+ if (data_len < 2)
+ break;
+ priv->version = *(u8 *)(entry->data + 1);
+ break;
+ case PDR_RSSI_LINEAR_APPROXIMATION:
+ case PDR_RSSI_LINEAR_APPROXIMATION_DUAL_BAND:
+ case PDR_RSSI_LINEAR_APPROXIMATION_EXTENDED:
+ p54_parse_rssical(dev, entry->data, data_len,
+ le16_to_cpu(entry->code));
+ break;
+ case PDR_RSSI_LINEAR_APPROXIMATION_CUSTOM: {
+ __le16 *src = (void *) entry->data;
+ s16 *dst = (void *) &priv->rssical_db;
+ int i;
+
+ if (data_len != sizeof(priv->rssical_db)) {
+ err = -EINVAL;
+ goto err;
+ }
+ for (i = 0; i < sizeof(priv->rssical_db) /
+ sizeof(*src); i++)
+ *(dst++) = (s16) le16_to_cpu(*(src++));
+ }
+ break;
+ case PDR_PRISM_PA_CAL_OUTPUT_POWER_LIMITS_CUSTOM: {
+ struct pda_custom_wrapper *pda = (void *) entry->data;
+ if (priv->output_limit || data_len < sizeof(*pda))
+ break;
+ priv->output_limit = p54_convert_db(pda, data_len);
+ }
+ break;
+ case PDR_PRISM_PA_CAL_CURVE_DATA_CUSTOM: {
+ struct pda_custom_wrapper *pda = (void *) entry->data;
+ if (priv->curve_data || data_len < sizeof(*pda))
+ break;
+ priv->curve_data = p54_convert_db(pda, data_len);
+ }
+ break;
+ case PDR_END:
+ /* make it overrun */
+ entry_len = len;
+ break;
+ default:
+ break;
+ }
+
+ entry = (void *)entry + (entry_len + 1)*2;
+ }
+
+ if (!synth || !priv->iq_autocal || !priv->output_limit ||
+ !priv->curve_data) {
+ printk(KERN_ERR "%s: not all required entries found in eeprom!\n",
+ wiphy_name(dev->wiphy));
+ err = -EINVAL;
+ goto err;
+ }
+
+ err = p54_generate_channel_lists(dev);
+ if (err)
+ goto err;
+
+ priv->rxhw = synth & PDR_SYNTH_FRONTEND_MASK;
+ if (priv->rxhw == PDR_SYNTH_FRONTEND_XBOW)
+ p54_init_xbow_synth(priv);
+ if (!(synth & PDR_SYNTH_24_GHZ_DISABLED))
+ dev->wiphy->bands[IEEE80211_BAND_2GHZ] =
+ priv->band_table[IEEE80211_BAND_2GHZ];
+ if (!(synth & PDR_SYNTH_5_GHZ_DISABLED))
+ dev->wiphy->bands[IEEE80211_BAND_5GHZ] =
+ priv->band_table[IEEE80211_BAND_5GHZ];
+ if ((synth & PDR_SYNTH_RX_DIV_MASK) == PDR_SYNTH_RX_DIV_SUPPORTED)
+ priv->rx_diversity_mask = 3;
+ if ((synth & PDR_SYNTH_TX_DIV_MASK) == PDR_SYNTH_TX_DIV_SUPPORTED)
+ priv->tx_diversity_mask = 3;
+
+ if (!is_valid_ether_addr(dev->wiphy->perm_addr)) {
+ u8 perm_addr[ETH_ALEN];
+
+ printk(KERN_WARNING "%s: Invalid hwaddr! Using randomly generated MAC addr\n",
+ wiphy_name(dev->wiphy));
+ random_ether_addr(perm_addr);
+ SET_IEEE80211_PERM_ADDR(dev, perm_addr);
+ }
+
+ printk(KERN_INFO "%s: hwaddr %pM, MAC:isl38%02x RF:%s\n",
+ wiphy_name(dev->wiphy), dev->wiphy->perm_addr, priv->version,
+ p54_rf_chips[priv->rxhw]);
+
+ return 0;
+
+err:
+ kfree(priv->iq_autocal);
+ kfree(priv->output_limit);
+ kfree(priv->curve_data);
+ priv->iq_autocal = NULL;
+ priv->output_limit = NULL;
+ priv->curve_data = NULL;
+
+ printk(KERN_ERR "%s: eeprom parse failed!\n",
+ wiphy_name(dev->wiphy));
+ return err;
+}
+EXPORT_SYMBOL_GPL(p54_parse_eeprom);
+
+int p54_read_eeprom(struct ieee80211_hw *dev)
+{
+ struct p54_common *priv = dev->priv;
+ size_t eeprom_size = 0x2020, offset = 0, blocksize, maxblocksize;
+ int ret = -ENOMEM;
+ void *eeprom;
+
+ maxblocksize = EEPROM_READBACK_LEN;
+ if (priv->fw_var >= 0x509)
+ maxblocksize -= 0xc;
+ else
+ maxblocksize -= 0x4;
+
+ eeprom = kzalloc(eeprom_size, GFP_KERNEL);
+ if (unlikely(!eeprom))
+ goto free;
+
+ while (eeprom_size) {
+ blocksize = min(eeprom_size, maxblocksize);
+ ret = p54_download_eeprom(priv, (void *) (eeprom + offset),
+ offset, blocksize);
+ if (unlikely(ret))
+ goto free;
+
+ offset += blocksize;
+ eeprom_size -= blocksize;
+ }
+
+ ret = p54_parse_eeprom(dev, eeprom, offset);
+free:
+ kfree(eeprom);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(p54_read_eeprom);
diff --git a/drivers/net/wireless/p54/eeprom.h b/drivers/net/wireless/p54/eeprom.h
new file mode 100644
index 00000000000..9051aef1124
--- /dev/null
+++ b/drivers/net/wireless/p54/eeprom.h
@@ -0,0 +1,226 @@
+/*
+ * eeprom specific definitions for mac80211 Prism54 drivers
+ *
+ * Copyright (c) 2006, Michael Wu <flamingice@sourmilk.net>
+ * Copyright (c) 2007-2009, Christian Lamparter <chunkeey@web.de>
+ *
+ * Based on:
+ * - the islsm (softmac prism54) driver, which is:
+ * Copyright 2004-2006 Jean-Baptiste Note <jbnote@gmail.com>, et al.
+ *
+ * - LMAC API interface header file for STLC4560 (lmac_longbow.h)
+ * Copyright (C) 2007 Conexant Systems, Inc.
+ *
+ * - islmvc driver
+ * Copyright (C) 2001 Intersil Americas Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef EEPROM_H
+#define EEPROM_H
+
+/* PDA defines are Copyright (C) 2005 Nokia Corporation (taken from islsm_pda.h) */
+
+struct pda_entry {
+ __le16 len; /* includes both code and data */
+ __le16 code;
+ u8 data[0];
+} __packed;
+
+struct eeprom_pda_wrap {
+ __le32 magic;
+ __le16 pad;
+ __le16 len;
+ __le32 arm_opcode;
+ u8 data[0];
+} __packed;
+
+struct p54_iq_autocal_entry {
+ __le16 iq_param[4];
+} __packed;
+
+struct pda_iq_autocal_entry {
+ __le16 freq;
+ struct p54_iq_autocal_entry params;
+} __packed;
+
+struct pda_channel_output_limit {
+ __le16 freq;
+ u8 val_bpsk;
+ u8 val_qpsk;
+ u8 val_16qam;
+ u8 val_64qam;
+ u8 rate_set_mask;
+ u8 rate_set_size;
+} __packed;
+
+struct pda_pa_curve_data_sample_rev0 {
+ u8 rf_power;
+ u8 pa_detector;
+ u8 pcv;
+} __packed;
+
+struct pda_pa_curve_data_sample_rev1 {
+ u8 rf_power;
+ u8 pa_detector;
+ u8 data_barker;
+ u8 data_bpsk;
+ u8 data_qpsk;
+ u8 data_16qam;
+ u8 data_64qam;
+} __packed;
+
+struct pda_pa_curve_data {
+ u8 cal_method_rev;
+ u8 channels;
+ u8 points_per_channel;
+ u8 padding;
+ u8 data[0];
+} __packed;
+
+struct pda_rssi_cal_entry {
+ __le16 mul;
+ __le16 add;
+} __packed;
+
+struct pda_country {
+ u8 regdomain;
+ u8 alpha2[2];
+ u8 flags;
+} __packed;
+
+struct pda_antenna_gain {
+ struct {
+ u8 gain_5GHz; /* 0.25 dBi units */
+ u8 gain_2GHz; /* 0.25 dBi units */
+ } __packed antenna[0];
+} __packed;
+
+struct pda_custom_wrapper {
+ __le16 entries;
+ __le16 entry_size;
+ __le16 offset;
+ __le16 len;
+ u8 data[0];
+} __packed;
+
+/*
+ * this defines the PDR codes used to build PDAs as defined in document
+ * number 553155. The current implementation mirrors version 1.1 of the
+ * document and lists only PDRs supported by the ARM platform.
+ */
+
+/* common and choice range (0x0000 - 0x0fff) */
+#define PDR_END 0x0000
+#define PDR_MANUFACTURING_PART_NUMBER 0x0001
+#define PDR_PDA_VERSION 0x0002
+#define PDR_NIC_SERIAL_NUMBER 0x0003
+#define PDR_NIC_RAM_SIZE 0x0005
+#define PDR_RFMODEM_SUP_RANGE 0x0006
+#define PDR_PRISM_MAC_SUP_RANGE 0x0007
+#define PDR_NIC_ID 0x0008
+
+#define PDR_MAC_ADDRESS 0x0101
+#define PDR_REGULATORY_DOMAIN_LIST 0x0103 /* obsolete */
+#define PDR_ALLOWED_CHAN_SET 0x0104
+#define PDR_DEFAULT_CHAN 0x0105
+#define PDR_TEMPERATURE_TYPE 0x0107
+
+#define PDR_IFR_SETTING 0x0200
+#define PDR_RFR_SETTING 0x0201
+#define PDR_3861_BASELINE_REG_SETTINGS 0x0202
+#define PDR_3861_SHADOW_REG_SETTINGS 0x0203
+#define PDR_3861_IFRF_REG_SETTINGS 0x0204
+
+#define PDR_3861_CHAN_CALIB_SET_POINTS 0x0300
+#define PDR_3861_CHAN_CALIB_INTEGRATOR 0x0301
+
+#define PDR_3842_PRISM_II_NIC_CONFIG 0x0400
+#define PDR_PRISM_USB_ID 0x0401
+#define PDR_PRISM_PCI_ID 0x0402
+#define PDR_PRISM_PCI_IF_CONFIG 0x0403
+#define PDR_PRISM_PCI_PM_CONFIG 0x0404
+
+#define PDR_3861_MF_TEST_CHAN_SET_POINTS 0x0900
+#define PDR_3861_MF_TEST_CHAN_INTEGRATORS 0x0901
+
+/* ARM range (0x1000 - 0x1fff) */
+#define PDR_COUNTRY_INFORMATION 0x1000 /* obsolete */
+#define PDR_INTERFACE_LIST 0x1001
+#define PDR_HARDWARE_PLATFORM_COMPONENT_ID 0x1002
+#define PDR_OEM_NAME 0x1003
+#define PDR_PRODUCT_NAME 0x1004
+#define PDR_UTF8_OEM_NAME 0x1005
+#define PDR_UTF8_PRODUCT_NAME 0x1006
+#define PDR_COUNTRY_LIST 0x1007
+#define PDR_DEFAULT_COUNTRY 0x1008
+
+#define PDR_ANTENNA_GAIN 0x1100
+
+#define PDR_PRISM_INDIGO_PA_CALIBRATION_DATA 0x1901
+#define PDR_RSSI_LINEAR_APPROXIMATION 0x1902
+#define PDR_PRISM_PA_CAL_OUTPUT_POWER_LIMITS 0x1903
+#define PDR_PRISM_PA_CAL_CURVE_DATA 0x1904
+#define PDR_RSSI_LINEAR_APPROXIMATION_DUAL_BAND 0x1905
+#define PDR_PRISM_ZIF_TX_IQ_CALIBRATION 0x1906
+#define PDR_REGULATORY_POWER_LIMITS 0x1907
+#define PDR_RSSI_LINEAR_APPROXIMATION_EXTENDED 0x1908
+#define PDR_RADIATED_TRANSMISSION_CORRECTION 0x1909
+#define PDR_PRISM_TX_IQ_CALIBRATION 0x190a
+
+/* reserved range (0x2000 - 0x7fff) */
+
+/* customer range (0x8000 - 0xffff) */
+#define PDR_BASEBAND_REGISTERS 0x8000
+#define PDR_PER_CHANNEL_BASEBAND_REGISTERS 0x8001
+
+/* used by our modificated eeprom image */
+#define PDR_RSSI_LINEAR_APPROXIMATION_CUSTOM 0xDEAD
+#define PDR_PRISM_PA_CAL_OUTPUT_POWER_LIMITS_CUSTOM 0xBEEF
+#define PDR_PRISM_PA_CAL_CURVE_DATA_CUSTOM 0xB05D
+
+/* Interface Definitions */
+#define PDR_INTERFACE_ROLE_SERVER 0x0000
+#define PDR_INTERFACE_ROLE_CLIENT 0x0001
+
+/* PDR definitions for default country & country list */
+#define PDR_COUNTRY_CERT_CODE 0x80
+#define PDR_COUNTRY_CERT_CODE_REAL 0x00
+#define PDR_COUNTRY_CERT_CODE_PSEUDO 0x80
+#define PDR_COUNTRY_CERT_BAND 0x40
+#define PDR_COUNTRY_CERT_BAND_2GHZ 0x00
+#define PDR_COUNTRY_CERT_BAND_5GHZ 0x40
+#define PDR_COUNTRY_CERT_IODOOR 0x30
+#define PDR_COUNTRY_CERT_IODOOR_BOTH 0x00
+#define PDR_COUNTRY_CERT_IODOOR_INDOOR 0x20
+#define PDR_COUNTRY_CERT_IODOOR_OUTDOOR 0x30
+#define PDR_COUNTRY_CERT_INDEX 0x0f
+
+/* Specific LMAC FW/HW variant definitions */
+#define PDR_SYNTH_FRONTEND_MASK 0x0007
+#define PDR_SYNTH_FRONTEND_DUETTE3 0x0001
+#define PDR_SYNTH_FRONTEND_DUETTE2 0x0002
+#define PDR_SYNTH_FRONTEND_FRISBEE 0x0003
+#define PDR_SYNTH_FRONTEND_XBOW 0x0004
+#define PDR_SYNTH_FRONTEND_LONGBOW 0x0005
+#define PDR_SYNTH_IQ_CAL_MASK 0x0018
+#define PDR_SYNTH_IQ_CAL_PA_DETECTOR 0x0000
+#define PDR_SYNTH_IQ_CAL_DISABLED 0x0008
+#define PDR_SYNTH_IQ_CAL_ZIF 0x0010
+#define PDR_SYNTH_FAA_SWITCH_MASK 0x0020
+#define PDR_SYNTH_FAA_SWITCH_ENABLED 0x0020
+#define PDR_SYNTH_24_GHZ_MASK 0x0040
+#define PDR_SYNTH_24_GHZ_DISABLED 0x0040
+#define PDR_SYNTH_5_GHZ_MASK 0x0080
+#define PDR_SYNTH_5_GHZ_DISABLED 0x0080
+#define PDR_SYNTH_RX_DIV_MASK 0x0100
+#define PDR_SYNTH_RX_DIV_SUPPORTED 0x0100
+#define PDR_SYNTH_TX_DIV_MASK 0x0200
+#define PDR_SYNTH_TX_DIV_SUPPORTED 0x0200
+#define PDR_SYNTH_ASM_MASK 0x0400
+#define PDR_SYNTH_ASM_XSWON 0x0400
+
+#endif /* EEPROM_H */
diff --git a/drivers/net/wireless/p54/fwio.c b/drivers/net/wireless/p54/fwio.c
new file mode 100644
index 00000000000..e7b9e9cb39f
--- /dev/null
+++ b/drivers/net/wireless/p54/fwio.c
@@ -0,0 +1,716 @@
+/*
+ * Firmware I/O code for mac80211 Prism54 drivers
+ *
+ * Copyright (c) 2006, Michael Wu <flamingice@sourmilk.net>
+ * Copyright (c) 2007-2009, Christian Lamparter <chunkeey@web.de>
+ * Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
+ *
+ * Based on:
+ * - the islsm (softmac prism54) driver, which is:
+ * Copyright 2004-2006 Jean-Baptiste Note <jbnote@gmail.com>, et al.
+ * - stlc45xx driver
+ * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/firmware.h>
+#include <linux/etherdevice.h>
+
+#include <net/mac80211.h>
+
+#include "p54.h"
+#include "eeprom.h"
+#include "lmac.h"
+
+int p54_parse_firmware(struct ieee80211_hw *dev, const struct firmware *fw)
+{
+ struct p54_common *priv = dev->priv;
+ struct exp_if *exp_if;
+ struct bootrec *bootrec;
+ u32 *data = (u32 *)fw->data;
+ u32 *end_data = (u32 *)fw->data + (fw->size >> 2);
+ u8 *fw_version = NULL;
+ size_t len;
+ int i;
+ int maxlen;
+
+ if (priv->rx_start)
+ return 0;
+
+ while (data < end_data && *data)
+ data++;
+
+ while (data < end_data && !*data)
+ data++;
+
+ bootrec = (struct bootrec *) data;
+
+ while (bootrec->data <= end_data && (bootrec->data +
+ (len = le32_to_cpu(bootrec->len))) <= end_data) {
+ u32 code = le32_to_cpu(bootrec->code);
+ switch (code) {
+ case BR_CODE_COMPONENT_ID:
+ priv->fw_interface = be32_to_cpup((__be32 *)
+ bootrec->data);
+ switch (priv->fw_interface) {
+ case FW_LM86:
+ case FW_LM20:
+ case FW_LM87: {
+ char *iftype = (char *)bootrec->data;
+ printk(KERN_INFO "%s: p54 detected a LM%c%c "
+ "firmware\n",
+ wiphy_name(priv->hw->wiphy),
+ iftype[2], iftype[3]);
+ break;
+ }
+ case FW_FMAC:
+ default:
+ printk(KERN_ERR "%s: unsupported firmware\n",
+ wiphy_name(priv->hw->wiphy));
+ return -ENODEV;
+ }
+ break;
+ case BR_CODE_COMPONENT_VERSION:
+ /* 24 bytes should be enough for all firmwares */
+ if (strnlen((unsigned char *) bootrec->data, 24) < 24)
+ fw_version = (unsigned char *) bootrec->data;
+ break;
+ case BR_CODE_DESCR: {
+ struct bootrec_desc *desc =
+ (struct bootrec_desc *)bootrec->data;
+ priv->rx_start = le32_to_cpu(desc->rx_start);
+ /* FIXME add sanity checking */
+ priv->rx_end = le32_to_cpu(desc->rx_end) - 0x3500;
+ priv->headroom = desc->headroom;
+ priv->tailroom = desc->tailroom;
+ priv->privacy_caps = desc->privacy_caps;
+ priv->rx_keycache_size = desc->rx_keycache_size;
+ if (le32_to_cpu(bootrec->len) == 11)
+ priv->rx_mtu = le16_to_cpu(desc->rx_mtu);
+ else
+ priv->rx_mtu = (size_t)
+ 0x620 - priv->tx_hdr_len;
+ maxlen = priv->tx_hdr_len + /* USB devices */
+ sizeof(struct p54_rx_data) +
+ 4 + /* rx alignment */
+ IEEE80211_MAX_FRAG_THRESHOLD;
+ if (priv->rx_mtu > maxlen && PAGE_SIZE == 4096) {
+ printk(KERN_INFO "p54: rx_mtu reduced from %d "
+ "to %d\n", priv->rx_mtu, maxlen);
+ priv->rx_mtu = maxlen;
+ }
+ break;
+ }
+ case BR_CODE_EXPOSED_IF:
+ exp_if = (struct exp_if *) bootrec->data;
+ for (i = 0; i < (len * sizeof(*exp_if) / 4); i++)
+ if (exp_if[i].if_id == cpu_to_le16(IF_ID_LMAC))
+ priv->fw_var = le16_to_cpu(exp_if[i].variant);
+ break;
+ case BR_CODE_DEPENDENT_IF:
+ break;
+ case BR_CODE_END_OF_BRA:
+ case LEGACY_BR_CODE_END_OF_BRA:
+ end_data = NULL;
+ break;
+ default:
+ break;
+ }
+ bootrec = (struct bootrec *)&bootrec->data[len];
+ }
+
+ if (fw_version)
+ printk(KERN_INFO "%s: FW rev %s - Softmac protocol %x.%x\n",
+ wiphy_name(priv->hw->wiphy), fw_version,
+ priv->fw_var >> 8, priv->fw_var & 0xff);
+
+ if (priv->fw_var < 0x500)
+ printk(KERN_INFO "%s: you are using an obsolete firmware. "
+ "visit http://wireless.kernel.org/en/users/Drivers/p54 "
+ "and grab one for \"kernel >= 2.6.28\"!\n",
+ wiphy_name(priv->hw->wiphy));
+
+ if (priv->fw_var >= 0x300) {
+ /* Firmware supports QoS, use it! */
+
+ if (priv->fw_var >= 0x500) {
+ priv->tx_stats[P54_QUEUE_AC_VO].limit = 16;
+ priv->tx_stats[P54_QUEUE_AC_VI].limit = 16;
+ priv->tx_stats[P54_QUEUE_AC_BE].limit = 16;
+ priv->tx_stats[P54_QUEUE_AC_BK].limit = 16;
+ } else {
+ priv->tx_stats[P54_QUEUE_AC_VO].limit = 3;
+ priv->tx_stats[P54_QUEUE_AC_VI].limit = 4;
+ priv->tx_stats[P54_QUEUE_AC_BE].limit = 3;
+ priv->tx_stats[P54_QUEUE_AC_BK].limit = 2;
+ }
+ priv->hw->queues = P54_QUEUE_AC_NUM;
+ }
+
+ printk(KERN_INFO "%s: cryptographic accelerator "
+ "WEP:%s, TKIP:%s, CCMP:%s\n", wiphy_name(priv->hw->wiphy),
+ (priv->privacy_caps & BR_DESC_PRIV_CAP_WEP) ? "YES" :
+ "no", (priv->privacy_caps & (BR_DESC_PRIV_CAP_TKIP |
+ BR_DESC_PRIV_CAP_MICHAEL)) ? "YES" : "no",
+ (priv->privacy_caps & BR_DESC_PRIV_CAP_AESCCMP) ?
+ "YES" : "no");
+
+ if (priv->rx_keycache_size) {
+ /*
+ * NOTE:
+ *
+ * The firmware provides at most 255 (0 - 254) slots
+ * for keys which are then used to offload decryption.
+ * As a result the 255 entry (aka 0xff) can be used
+ * safely by the driver to mark keys that didn't fit
+ * into the full cache. This trick saves us from
+ * keeping a extra list for uploaded keys.
+ */
+
+ priv->used_rxkeys = kzalloc(BITS_TO_LONGS(
+ priv->rx_keycache_size), GFP_KERNEL);
+
+ if (!priv->used_rxkeys)
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(p54_parse_firmware);
+
+static struct sk_buff *p54_alloc_skb(struct p54_common *priv, u16 hdr_flags,
+ u16 payload_len, u16 type, gfp_t memflags)
+{
+ struct p54_hdr *hdr;
+ struct sk_buff *skb;
+ size_t frame_len = sizeof(*hdr) + payload_len;
+
+ if (frame_len > P54_MAX_CTRL_FRAME_LEN)
+ return NULL;
+
+ if (unlikely(skb_queue_len(&priv->tx_pending) > 64))
+ return NULL;
+
+ skb = __dev_alloc_skb(priv->tx_hdr_len + frame_len, memflags);
+ if (!skb)
+ return NULL;
+ skb_reserve(skb, priv->tx_hdr_len);
+
+ hdr = (struct p54_hdr *) skb_put(skb, sizeof(*hdr));
+ hdr->flags = cpu_to_le16(hdr_flags);
+ hdr->len = cpu_to_le16(payload_len);
+ hdr->type = cpu_to_le16(type);
+ hdr->tries = hdr->rts_tries = 0;
+ return skb;
+}
+
+int p54_download_eeprom(struct p54_common *priv, void *buf,
+ u16 offset, u16 len)
+{
+ struct p54_eeprom_lm86 *eeprom_hdr;
+ struct sk_buff *skb;
+ size_t eeprom_hdr_size;
+ int ret = 0;
+
+ if (priv->fw_var >= 0x509)
+ eeprom_hdr_size = sizeof(*eeprom_hdr);
+ else
+ eeprom_hdr_size = 0x4;
+
+ skb = p54_alloc_skb(priv, P54_HDR_FLAG_CONTROL, eeprom_hdr_size +
+ len, P54_CONTROL_TYPE_EEPROM_READBACK,
+ GFP_KERNEL);
+ if (unlikely(!skb))
+ return -ENOMEM;
+
+ mutex_lock(&priv->eeprom_mutex);
+ priv->eeprom = buf;
+ eeprom_hdr = (struct p54_eeprom_lm86 *) skb_put(skb,
+ eeprom_hdr_size + len);
+
+ if (priv->fw_var < 0x509) {
+ eeprom_hdr->v1.offset = cpu_to_le16(offset);
+ eeprom_hdr->v1.len = cpu_to_le16(len);
+ } else {
+ eeprom_hdr->v2.offset = cpu_to_le32(offset);
+ eeprom_hdr->v2.len = cpu_to_le16(len);
+ eeprom_hdr->v2.magic2 = 0xf;
+ memcpy(eeprom_hdr->v2.magic, (const char *)"LOCK", 4);
+ }
+
+ p54_tx(priv, skb);
+
+ if (!wait_for_completion_interruptible_timeout(
+ &priv->eeprom_comp, HZ)) {
+ printk(KERN_ERR "%s: device does not respond!\n",
+ wiphy_name(priv->hw->wiphy));
+ ret = -EBUSY;
+ }
+ priv->eeprom = NULL;
+ mutex_unlock(&priv->eeprom_mutex);
+ return ret;
+}
+
+int p54_update_beacon_tim(struct p54_common *priv, u16 aid, bool set)
+{
+ struct sk_buff *skb;
+ struct p54_tim *tim;
+
+ skb = p54_alloc_skb(priv, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*tim),
+ P54_CONTROL_TYPE_TIM, GFP_ATOMIC);
+ if (unlikely(!skb))
+ return -ENOMEM;
+
+ tim = (struct p54_tim *) skb_put(skb, sizeof(*tim));
+ tim->count = 1;
+ tim->entry[0] = cpu_to_le16(set ? (aid | 0x8000) : aid);
+ p54_tx(priv, skb);
+ return 0;
+}
+
+int p54_sta_unlock(struct p54_common *priv, u8 *addr)
+{
+ struct sk_buff *skb;
+ struct p54_sta_unlock *sta;
+
+ skb = p54_alloc_skb(priv, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*sta),
+ P54_CONTROL_TYPE_PSM_STA_UNLOCK, GFP_ATOMIC);
+ if (unlikely(!skb))
+ return -ENOMEM;
+
+ sta = (struct p54_sta_unlock *)skb_put(skb, sizeof(*sta));
+ memcpy(sta->addr, addr, ETH_ALEN);
+ p54_tx(priv, skb);
+ return 0;
+}
+
+int p54_tx_cancel(struct p54_common *priv, __le32 req_id)
+{
+ struct sk_buff *skb;
+ struct p54_txcancel *cancel;
+ u32 _req_id = le32_to_cpu(req_id);
+
+ if (unlikely(_req_id < priv->rx_start || _req_id > priv->rx_end))
+ return -EINVAL;
+
+ skb = p54_alloc_skb(priv, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*cancel),
+ P54_CONTROL_TYPE_TXCANCEL, GFP_ATOMIC);
+ if (unlikely(!skb))
+ return -ENOMEM;
+
+ cancel = (struct p54_txcancel *)skb_put(skb, sizeof(*cancel));
+ cancel->req_id = req_id;
+ p54_tx(priv, skb);
+ return 0;
+}
+
+int p54_setup_mac(struct p54_common *priv)
+{
+ struct sk_buff *skb;
+ struct p54_setup_mac *setup;
+ u16 mode;
+
+ skb = p54_alloc_skb(priv, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*setup),
+ P54_CONTROL_TYPE_SETUP, GFP_ATOMIC);
+ if (!skb)
+ return -ENOMEM;
+
+ setup = (struct p54_setup_mac *) skb_put(skb, sizeof(*setup));
+ if (!(priv->hw->conf.flags & IEEE80211_CONF_IDLE)) {
+ switch (priv->mode) {
+ case NL80211_IFTYPE_STATION:
+ mode = P54_FILTER_TYPE_STATION;
+ break;
+ case NL80211_IFTYPE_AP:
+ mode = P54_FILTER_TYPE_AP;
+ break;
+ case NL80211_IFTYPE_ADHOC:
+ case NL80211_IFTYPE_MESH_POINT:
+ mode = P54_FILTER_TYPE_IBSS;
+ break;
+ case NL80211_IFTYPE_MONITOR:
+ mode = P54_FILTER_TYPE_PROMISCUOUS;
+ break;
+ default:
+ mode = P54_FILTER_TYPE_HIBERNATE;
+ break;
+ }
+
+ /*
+ * "TRANSPARENT and PROMISCUOUS are mutually exclusive"
+ * STSW45X0C LMAC API - page 12
+ */
+ if (((priv->filter_flags & FIF_PROMISC_IN_BSS) ||
+ (priv->filter_flags & FIF_OTHER_BSS)) &&
+ (mode != P54_FILTER_TYPE_PROMISCUOUS))
+ mode |= P54_FILTER_TYPE_TRANSPARENT;
+ } else {
+ mode = P54_FILTER_TYPE_HIBERNATE;
+ }
+
+ setup->mac_mode = cpu_to_le16(mode);
+ memcpy(setup->mac_addr, priv->mac_addr, ETH_ALEN);
+ memcpy(setup->bssid, priv->bssid, ETH_ALEN);
+ setup->rx_antenna = 2 & priv->rx_diversity_mask; /* automatic */
+ setup->rx_align = 0;
+ if (priv->fw_var < 0x500) {
+ setup->v1.basic_rate_mask = cpu_to_le32(priv->basic_rate_mask);
+ memset(setup->v1.rts_rates, 0, 8);
+ setup->v1.rx_addr = cpu_to_le32(priv->rx_end);
+ setup->v1.max_rx = cpu_to_le16(priv->rx_mtu);
+ setup->v1.rxhw = cpu_to_le16(priv->rxhw);
+ setup->v1.wakeup_timer = cpu_to_le16(priv->wakeup_timer);
+ setup->v1.unalloc0 = cpu_to_le16(0);
+ } else {
+ setup->v2.rx_addr = cpu_to_le32(priv->rx_end);
+ setup->v2.max_rx = cpu_to_le16(priv->rx_mtu);
+ setup->v2.rxhw = cpu_to_le16(priv->rxhw);
+ setup->v2.timer = cpu_to_le16(priv->wakeup_timer);
+ setup->v2.truncate = cpu_to_le16(48896);
+ setup->v2.basic_rate_mask = cpu_to_le32(priv->basic_rate_mask);
+ setup->v2.sbss_offset = 0;
+ setup->v2.mcast_window = 0;
+ setup->v2.rx_rssi_threshold = 0;
+ setup->v2.rx_ed_threshold = 0;
+ setup->v2.ref_clock = cpu_to_le32(644245094);
+ setup->v2.lpf_bandwidth = cpu_to_le16(65535);
+ setup->v2.osc_start_delay = cpu_to_le16(65535);
+ }
+ p54_tx(priv, skb);
+ return 0;
+}
+
+int p54_scan(struct p54_common *priv, u16 mode, u16 dwell)
+{
+ struct sk_buff *skb;
+ struct p54_hdr *hdr;
+ struct p54_scan_head *head;
+ struct p54_iq_autocal_entry *iq_autocal;
+ union p54_scan_body_union *body;
+ struct p54_scan_tail_rate *rate;
+ struct pda_rssi_cal_entry *rssi;
+ unsigned int i;
+ void *entry;
+ int band = priv->hw->conf.channel->band;
+ __le16 freq = cpu_to_le16(priv->hw->conf.channel->center_freq);
+
+ skb = p54_alloc_skb(priv, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*head) +
+ 2 + sizeof(*iq_autocal) + sizeof(*body) +
+ sizeof(*rate) + 2 * sizeof(*rssi),
+ P54_CONTROL_TYPE_SCAN, GFP_ATOMIC);
+ if (!skb)
+ return -ENOMEM;
+
+ head = (struct p54_scan_head *) skb_put(skb, sizeof(*head));
+ memset(head->scan_params, 0, sizeof(head->scan_params));
+ head->mode = cpu_to_le16(mode);
+ head->dwell = cpu_to_le16(dwell);
+ head->freq = freq;
+
+ if (priv->rxhw == PDR_SYNTH_FRONTEND_LONGBOW) {
+ __le16 *pa_power_points = (__le16 *) skb_put(skb, 2);
+ *pa_power_points = cpu_to_le16(0x0c);
+ }
+
+ iq_autocal = (void *) skb_put(skb, sizeof(*iq_autocal));
+ for (i = 0; i < priv->iq_autocal_len; i++) {
+ if (priv->iq_autocal[i].freq != freq)
+ continue;
+
+ memcpy(iq_autocal, &priv->iq_autocal[i].params,
+ sizeof(struct p54_iq_autocal_entry));
+ break;
+ }
+ if (i == priv->iq_autocal_len)
+ goto err;
+
+ if (priv->rxhw == PDR_SYNTH_FRONTEND_LONGBOW)
+ body = (void *) skb_put(skb, sizeof(body->longbow));
+ else
+ body = (void *) skb_put(skb, sizeof(body->normal));
+
+ for (i = 0; i < priv->output_limit->entries; i++) {
+ __le16 *entry_freq = (void *) (priv->output_limit->data +
+ priv->output_limit->entry_size * i);
+
+ if (*entry_freq != freq)
+ continue;
+
+ if (priv->rxhw == PDR_SYNTH_FRONTEND_LONGBOW) {
+ memcpy(&body->longbow.power_limits,
+ (void *) entry_freq + sizeof(__le16),
+ priv->output_limit->entry_size);
+ } else {
+ struct pda_channel_output_limit *limits =
+ (void *) entry_freq;
+
+ body->normal.val_barker = 0x38;
+ body->normal.val_bpsk = body->normal.dup_bpsk =
+ limits->val_bpsk;
+ body->normal.val_qpsk = body->normal.dup_qpsk =
+ limits->val_qpsk;
+ body->normal.val_16qam = body->normal.dup_16qam =
+ limits->val_16qam;
+ body->normal.val_64qam = body->normal.dup_64qam =
+ limits->val_64qam;
+ }
+ break;
+ }
+ if (i == priv->output_limit->entries)
+ goto err;
+
+ entry = (void *)(priv->curve_data->data + priv->curve_data->offset);
+ for (i = 0; i < priv->curve_data->entries; i++) {
+ if (*((__le16 *)entry) != freq) {
+ entry += priv->curve_data->entry_size;
+ continue;
+ }
+
+ if (priv->rxhw == PDR_SYNTH_FRONTEND_LONGBOW) {
+ memcpy(&body->longbow.curve_data,
+ (void *) entry + sizeof(__le16),
+ priv->curve_data->entry_size);
+ } else {
+ struct p54_scan_body *chan = &body->normal;
+ struct pda_pa_curve_data *curve_data =
+ (void *) priv->curve_data->data;
+
+ entry += sizeof(__le16);
+ chan->pa_points_per_curve = 8;
+ memset(chan->curve_data, 0, sizeof(*chan->curve_data));
+ memcpy(chan->curve_data, entry,
+ sizeof(struct p54_pa_curve_data_sample) *
+ min((u8)8, curve_data->points_per_channel));
+ }
+ break;
+ }
+ if (i == priv->curve_data->entries)
+ goto err;
+
+ if ((priv->fw_var >= 0x500) && (priv->fw_var < 0x509)) {
+ rate = (void *) skb_put(skb, sizeof(*rate));
+ rate->basic_rate_mask = cpu_to_le32(priv->basic_rate_mask);
+ for (i = 0; i < sizeof(rate->rts_rates); i++)
+ rate->rts_rates[i] = i;
+ }
+
+ rssi = (struct pda_rssi_cal_entry *) skb_put(skb, sizeof(*rssi));
+ rssi->mul = cpu_to_le16(priv->rssical_db[band].mul);
+ rssi->add = cpu_to_le16(priv->rssical_db[band].add);
+ if (priv->rxhw == PDR_SYNTH_FRONTEND_LONGBOW) {
+ /* Longbow frontend needs ever more */
+ rssi = (void *) skb_put(skb, sizeof(*rssi));
+ rssi->mul = cpu_to_le16(priv->rssical_db[band].longbow_unkn);
+ rssi->add = cpu_to_le16(priv->rssical_db[band].longbow_unk2);
+ }
+
+ if (priv->fw_var >= 0x509) {
+ rate = (void *) skb_put(skb, sizeof(*rate));
+ rate->basic_rate_mask = cpu_to_le32(priv->basic_rate_mask);
+ for (i = 0; i < sizeof(rate->rts_rates); i++)
+ rate->rts_rates[i] = i;
+ }
+
+ hdr = (struct p54_hdr *) skb->data;
+ hdr->len = cpu_to_le16(skb->len - sizeof(*hdr));
+
+ p54_tx(priv, skb);
+ return 0;
+
+err:
+ printk(KERN_ERR "%s: frequency change to channel %d failed.\n",
+ wiphy_name(priv->hw->wiphy), ieee80211_frequency_to_channel(
+ priv->hw->conf.channel->center_freq));
+
+ dev_kfree_skb_any(skb);
+ return -EINVAL;
+}
+
+int p54_set_leds(struct p54_common *priv)
+{
+ struct sk_buff *skb;
+ struct p54_led *led;
+
+ skb = p54_alloc_skb(priv, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*led),
+ P54_CONTROL_TYPE_LED, GFP_ATOMIC);
+ if (unlikely(!skb))
+ return -ENOMEM;
+
+ led = (struct p54_led *) skb_put(skb, sizeof(*led));
+ led->flags = cpu_to_le16(0x0003);
+ led->mask[0] = led->mask[1] = cpu_to_le16(priv->softled_state);
+ led->delay[0] = cpu_to_le16(1);
+ led->delay[1] = cpu_to_le16(0);
+ p54_tx(priv, skb);
+ return 0;
+}
+
+int p54_set_edcf(struct p54_common *priv)
+{
+ struct sk_buff *skb;
+ struct p54_edcf *edcf;
+
+ skb = p54_alloc_skb(priv, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*edcf),
+ P54_CONTROL_TYPE_DCFINIT, GFP_ATOMIC);
+ if (unlikely(!skb))
+ return -ENOMEM;
+
+ edcf = (struct p54_edcf *)skb_put(skb, sizeof(*edcf));
+ if (priv->use_short_slot) {
+ edcf->slottime = 9;
+ edcf->sifs = 0x10;
+ edcf->eofpad = 0x00;
+ } else {
+ edcf->slottime = 20;
+ edcf->sifs = 0x0a;
+ edcf->eofpad = 0x06;
+ }
+ /* (see prism54/isl_oid.h for further details) */
+ edcf->frameburst = cpu_to_le16(0);
+ edcf->round_trip_delay = cpu_to_le16(0);
+ edcf->flags = 0;
+ memset(edcf->mapping, 0, sizeof(edcf->mapping));
+ memcpy(edcf->queue, priv->qos_params, sizeof(edcf->queue));
+ p54_tx(priv, skb);
+ return 0;
+}
+
+int p54_set_ps(struct p54_common *priv)
+{
+ struct sk_buff *skb;
+ struct p54_psm *psm;
+ unsigned int i;
+ u16 mode;
+
+ if (priv->hw->conf.flags & IEEE80211_CONF_PS &&
+ !priv->powersave_override)
+ mode = P54_PSM | P54_PSM_BEACON_TIMEOUT | P54_PSM_DTIM |
+ P54_PSM_CHECKSUM | P54_PSM_MCBC;
+ else
+ mode = P54_PSM_CAM;
+
+ skb = p54_alloc_skb(priv, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*psm),
+ P54_CONTROL_TYPE_PSM, GFP_ATOMIC);
+ if (!skb)
+ return -ENOMEM;
+
+ psm = (struct p54_psm *)skb_put(skb, sizeof(*psm));
+ psm->mode = cpu_to_le16(mode);
+ psm->aid = cpu_to_le16(priv->aid);
+ for (i = 0; i < ARRAY_SIZE(psm->intervals); i++) {
+ psm->intervals[i].interval =
+ cpu_to_le16(priv->hw->conf.listen_interval);
+ psm->intervals[i].periods = cpu_to_le16(1);
+ }
+
+ psm->beacon_rssi_skip_max = 200;
+ psm->rssi_delta_threshold = 0;
+ psm->nr = 1;
+ psm->exclude[0] = WLAN_EID_TIM;
+
+ p54_tx(priv, skb);
+ return 0;
+}
+
+int p54_init_xbow_synth(struct p54_common *priv)
+{
+ struct sk_buff *skb;
+ struct p54_xbow_synth *xbow;
+
+ skb = p54_alloc_skb(priv, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*xbow),
+ P54_CONTROL_TYPE_XBOW_SYNTH_CFG, GFP_KERNEL);
+ if (unlikely(!skb))
+ return -ENOMEM;
+
+ xbow = (struct p54_xbow_synth *)skb_put(skb, sizeof(*xbow));
+ xbow->magic1 = cpu_to_le16(0x1);
+ xbow->magic2 = cpu_to_le16(0x2);
+ xbow->freq = cpu_to_le16(5390);
+ memset(xbow->padding, 0, sizeof(xbow->padding));
+ p54_tx(priv, skb);
+ return 0;
+}
+
+int p54_upload_key(struct p54_common *priv, u8 algo, int slot, u8 idx, u8 len,
+ u8 *addr, u8* key)
+{
+ struct sk_buff *skb;
+ struct p54_keycache *rxkey;
+
+ skb = p54_alloc_skb(priv, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*rxkey),
+ P54_CONTROL_TYPE_RX_KEYCACHE, GFP_KERNEL);
+ if (unlikely(!skb))
+ return -ENOMEM;
+
+ rxkey = (struct p54_keycache *)skb_put(skb, sizeof(*rxkey));
+ rxkey->entry = slot;
+ rxkey->key_id = idx;
+ rxkey->key_type = algo;
+ if (addr)
+ memcpy(rxkey->mac, addr, ETH_ALEN);
+ else
+ memset(rxkey->mac, ~0, ETH_ALEN);
+
+ switch (algo) {
+ case P54_CRYPTO_WEP:
+ case P54_CRYPTO_AESCCMP:
+ rxkey->key_len = min_t(u8, 16, len);
+ memcpy(rxkey->key, key, rxkey->key_len);
+ break;
+
+ case P54_CRYPTO_TKIPMICHAEL:
+ rxkey->key_len = 24;
+ memcpy(rxkey->key, key, 16);
+ memcpy(&(rxkey->key[16]), &(key
+ [NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY]), 8);
+ break;
+
+ case P54_CRYPTO_NONE:
+ rxkey->key_len = 0;
+ memset(rxkey->key, 0, sizeof(rxkey->key));
+ break;
+
+ default:
+ printk(KERN_ERR "%s: invalid cryptographic algorithm: %d\n",
+ wiphy_name(priv->hw->wiphy), algo);
+ dev_kfree_skb(skb);
+ return -EINVAL;
+ }
+
+ p54_tx(priv, skb);
+ return 0;
+}
+
+int p54_fetch_statistics(struct p54_common *priv)
+{
+ struct ieee80211_tx_info *txinfo;
+ struct p54_tx_info *p54info;
+ struct sk_buff *skb;
+
+ skb = p54_alloc_skb(priv, P54_HDR_FLAG_CONTROL,
+ sizeof(struct p54_statistics),
+ P54_CONTROL_TYPE_STAT_READBACK, GFP_KERNEL);
+ if (!skb)
+ return -ENOMEM;
+
+ /*
+ * The statistic feedback causes some extra headaches here, if it
+ * is not to crash/corrupt the firmware data structures.
+ *
+ * Unlike all other Control Get OIDs we can not use helpers like
+ * skb_put to reserve the space for the data we're requesting.
+ * Instead the extra frame length -which will hold the results later-
+ * will only be told to the p54_assign_address, so that following
+ * frames won't be placed into the allegedly empty area.
+ */
+ txinfo = IEEE80211_SKB_CB(skb);
+ p54info = (void *) txinfo->rate_driver_data;
+ p54info->extra_len = sizeof(struct p54_statistics);
+
+ p54_tx(priv, skb);
+ return 0;
+}
diff --git a/drivers/net/wireless/p54/led.c b/drivers/net/wireless/p54/led.c
new file mode 100644
index 00000000000..9575ac03363
--- /dev/null
+++ b/drivers/net/wireless/p54/led.c
@@ -0,0 +1,162 @@
+/*
+ * Common code for mac80211 Prism54 drivers
+ *
+ * Copyright (c) 2006, Michael Wu <flamingice@sourmilk.net>
+ * Copyright (c) 2007-2009, Christian Lamparter <chunkeey@web.de>
+ * Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
+ *
+ * Based on:
+ * - the islsm (softmac prism54) driver, which is:
+ * Copyright 2004-2006 Jean-Baptiste Note <jbnote@gmail.com>, et al.
+ * - stlc45xx driver
+ * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/firmware.h>
+#include <linux/etherdevice.h>
+
+#include <net/mac80211.h>
+#ifdef CONFIG_P54_LEDS
+#include <linux/leds.h>
+#endif /* CONFIG_P54_LEDS */
+
+#include "p54.h"
+#include "lmac.h"
+
+static void p54_update_leds(struct work_struct *work)
+{
+ struct p54_common *priv = container_of(work, struct p54_common,
+ led_work.work);
+ int err, i, tmp, blink_delay = 400;
+ bool rerun = false;
+
+ /* Don't toggle the LED, when the device is down. */
+ if (priv->mode == NL80211_IFTYPE_UNSPECIFIED)
+ return ;
+
+ for (i = 0; i < ARRAY_SIZE(priv->leds); i++)
+ if (priv->leds[i].toggled) {
+ priv->softled_state |= BIT(i);
+
+ tmp = 70 + 200 / (priv->leds[i].toggled);
+ if (tmp < blink_delay)
+ blink_delay = tmp;
+
+ if (priv->leds[i].led_dev.brightness == LED_OFF)
+ rerun = true;
+
+ priv->leds[i].toggled =
+ !!priv->leds[i].led_dev.brightness;
+ } else
+ priv->softled_state &= ~BIT(i);
+
+ err = p54_set_leds(priv);
+ if (err && net_ratelimit())
+ printk(KERN_ERR "%s: failed to update LEDs (%d).\n",
+ wiphy_name(priv->hw->wiphy), err);
+
+ if (rerun)
+ ieee80211_queue_delayed_work(priv->hw, &priv->led_work,
+ msecs_to_jiffies(blink_delay));
+}
+
+static void p54_led_brightness_set(struct led_classdev *led_dev,
+ enum led_brightness brightness)
+{
+ struct p54_led_dev *led = container_of(led_dev, struct p54_led_dev,
+ led_dev);
+ struct ieee80211_hw *dev = led->hw_dev;
+ struct p54_common *priv = dev->priv;
+
+ if (priv->mode == NL80211_IFTYPE_UNSPECIFIED)
+ return ;
+
+ if ((brightness) && (led->registered)) {
+ led->toggled++;
+ ieee80211_queue_delayed_work(priv->hw, &priv->led_work, HZ/10);
+ }
+}
+
+static int p54_register_led(struct p54_common *priv,
+ unsigned int led_index,
+ char *name, char *trigger)
+{
+ struct p54_led_dev *led = &priv->leds[led_index];
+ int err;
+
+ if (led->registered)
+ return -EEXIST;
+
+ snprintf(led->name, sizeof(led->name), "p54-%s::%s",
+ wiphy_name(priv->hw->wiphy), name);
+ led->hw_dev = priv->hw;
+ led->index = led_index;
+ led->led_dev.name = led->name;
+ led->led_dev.default_trigger = trigger;
+ led->led_dev.brightness_set = p54_led_brightness_set;
+
+ err = led_classdev_register(wiphy_dev(priv->hw->wiphy), &led->led_dev);
+ if (err)
+ printk(KERN_ERR "%s: Failed to register %s LED.\n",
+ wiphy_name(priv->hw->wiphy), name);
+ else
+ led->registered = 1;
+
+ return err;
+}
+
+int p54_init_leds(struct p54_common *priv)
+{
+ int err;
+
+ /*
+ * TODO:
+ * Figure out if the EEPROM contains some hints about the number
+ * of available/programmable LEDs of the device.
+ */
+
+ INIT_DELAYED_WORK(&priv->led_work, p54_update_leds);
+
+ err = p54_register_led(priv, 0, "assoc",
+ ieee80211_get_assoc_led_name(priv->hw));
+ if (err)
+ return err;
+
+ err = p54_register_led(priv, 1, "tx",
+ ieee80211_get_tx_led_name(priv->hw));
+ if (err)
+ return err;
+
+ err = p54_register_led(priv, 2, "rx",
+ ieee80211_get_rx_led_name(priv->hw));
+ if (err)
+ return err;
+
+ err = p54_register_led(priv, 3, "radio",
+ ieee80211_get_radio_led_name(priv->hw));
+ if (err)
+ return err;
+
+ err = p54_set_leds(priv);
+ return err;
+}
+
+void p54_unregister_leds(struct p54_common *priv)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(priv->leds); i++) {
+ if (priv->leds[i].registered) {
+ priv->leds[i].registered = false;
+ priv->leds[i].toggled = 0;
+ led_classdev_unregister(&priv->leds[i].led_dev);
+ }
+ }
+
+ cancel_delayed_work_sync(&priv->led_work);
+}
diff --git a/drivers/net/wireless/p54/lmac.h b/drivers/net/wireless/p54/lmac.h
new file mode 100644
index 00000000000..04b63ec80fa
--- /dev/null
+++ b/drivers/net/wireless/p54/lmac.h
@@ -0,0 +1,558 @@
+/*
+ * LMAC Interface specific definitions for mac80211 Prism54 drivers
+ *
+ * Copyright (c) 2006, Michael Wu <flamingice@sourmilk.net>
+ * Copyright (c) 2007 - 2009, Christian Lamparter <chunkeey@web.de>
+ *
+ * Based on:
+ * - the islsm (softmac prism54) driver, which is:
+ * Copyright 2004-2006 Jean-Baptiste Note <jbnote@gmail.com>, et al.
+ *
+ * - LMAC API interface header file for STLC4560 (lmac_longbow.h)
+ * Copyright (C) 2007 Conexant Systems, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef LMAC_H
+#define LMAC_H
+
+enum p54_control_frame_types {
+ P54_CONTROL_TYPE_SETUP = 0,
+ P54_CONTROL_TYPE_SCAN,
+ P54_CONTROL_TYPE_TRAP,
+ P54_CONTROL_TYPE_DCFINIT,
+ P54_CONTROL_TYPE_RX_KEYCACHE,
+ P54_CONTROL_TYPE_TIM,
+ P54_CONTROL_TYPE_PSM,
+ P54_CONTROL_TYPE_TXCANCEL,
+ P54_CONTROL_TYPE_TXDONE,
+ P54_CONTROL_TYPE_BURST,
+ P54_CONTROL_TYPE_STAT_READBACK,
+ P54_CONTROL_TYPE_BBP,
+ P54_CONTROL_TYPE_EEPROM_READBACK,
+ P54_CONTROL_TYPE_LED,
+ P54_CONTROL_TYPE_GPIO,
+ P54_CONTROL_TYPE_TIMER,
+ P54_CONTROL_TYPE_MODULATION,
+ P54_CONTROL_TYPE_SYNTH_CONFIG,
+ P54_CONTROL_TYPE_DETECTOR_VALUE,
+ P54_CONTROL_TYPE_XBOW_SYNTH_CFG,
+ P54_CONTROL_TYPE_CCE_QUIET,
+ P54_CONTROL_TYPE_PSM_STA_UNLOCK,
+ P54_CONTROL_TYPE_PCS,
+ P54_CONTROL_TYPE_BT_BALANCER = 28,
+ P54_CONTROL_TYPE_GROUP_ADDRESS_TABLE = 30,
+ P54_CONTROL_TYPE_ARPTABLE = 31,
+ P54_CONTROL_TYPE_BT_OPTIONS = 35,
+};
+
+#define P54_HDR_FLAG_CONTROL BIT(15)
+#define P54_HDR_FLAG_CONTROL_OPSET (BIT(15) + BIT(0))
+#define P54_HDR_FLAG_DATA_ALIGN BIT(14)
+
+#define P54_HDR_FLAG_DATA_OUT_PROMISC BIT(0)
+#define P54_HDR_FLAG_DATA_OUT_TIMESTAMP BIT(1)
+#define P54_HDR_FLAG_DATA_OUT_SEQNR BIT(2)
+#define P54_HDR_FLAG_DATA_OUT_BIT3 BIT(3)
+#define P54_HDR_FLAG_DATA_OUT_BURST BIT(4)
+#define P54_HDR_FLAG_DATA_OUT_NOCANCEL BIT(5)
+#define P54_HDR_FLAG_DATA_OUT_CLEARTIM BIT(6)
+#define P54_HDR_FLAG_DATA_OUT_HITCHHIKE BIT(7)
+#define P54_HDR_FLAG_DATA_OUT_COMPRESS BIT(8)
+#define P54_HDR_FLAG_DATA_OUT_CONCAT BIT(9)
+#define P54_HDR_FLAG_DATA_OUT_PCS_ACCEPT BIT(10)
+#define P54_HDR_FLAG_DATA_OUT_WAITEOSP BIT(11)
+
+#define P54_HDR_FLAG_DATA_IN_FCS_GOOD BIT(0)
+#define P54_HDR_FLAG_DATA_IN_MATCH_MAC BIT(1)
+#define P54_HDR_FLAG_DATA_IN_MCBC BIT(2)
+#define P54_HDR_FLAG_DATA_IN_BEACON BIT(3)
+#define P54_HDR_FLAG_DATA_IN_MATCH_BSS BIT(4)
+#define P54_HDR_FLAG_DATA_IN_BCAST_BSS BIT(5)
+#define P54_HDR_FLAG_DATA_IN_DATA BIT(6)
+#define P54_HDR_FLAG_DATA_IN_TRUNCATED BIT(7)
+#define P54_HDR_FLAG_DATA_IN_BIT8 BIT(8)
+#define P54_HDR_FLAG_DATA_IN_TRANSPARENT BIT(9)
+
+struct p54_hdr {
+ __le16 flags;
+ __le16 len;
+ __le32 req_id;
+ __le16 type; /* enum p54_control_frame_types */
+ u8 rts_tries;
+ u8 tries;
+ u8 data[0];
+} __packed;
+
+#define GET_REQ_ID(skb) \
+ (((struct p54_hdr *) ((struct sk_buff *) skb)->data)->req_id) \
+
+#define FREE_AFTER_TX(skb) \
+ ((((struct p54_hdr *) ((struct sk_buff *) skb)->data)-> \
+ flags) == cpu_to_le16(P54_HDR_FLAG_CONTROL_OPSET))
+
+#define IS_DATA_FRAME(skb) \
+ (!((((struct p54_hdr *) ((struct sk_buff *) skb)->data)-> \
+ flags) & cpu_to_le16(P54_HDR_FLAG_CONTROL)))
+
+#define GET_HW_QUEUE(skb) \
+ (((struct p54_tx_data *)((struct p54_hdr *) \
+ skb->data)->data)->hw_queue)
+
+/*
+ * shared interface ID definitions
+ * The interface ID is a unique identification of a specific interface.
+ * The following values are reserved: 0x0000, 0x0002, 0x0012, 0x0014, 0x0015
+ */
+#define IF_ID_ISL36356A 0x0001 /* ISL36356A <-> Firmware */
+#define IF_ID_MVC 0x0003 /* MAC Virtual Coprocessor */
+#define IF_ID_DEBUG 0x0008 /* PolDebug Interface */
+#define IF_ID_PRODUCT 0x0009
+#define IF_ID_OEM 0x000a
+#define IF_ID_PCI3877 0x000b /* 3877 <-> Host PCI */
+#define IF_ID_ISL37704C 0x000c /* ISL37704C <-> Fw */
+#define IF_ID_ISL39000 0x000f /* ISL39000 <-> Fw */
+#define IF_ID_ISL39300A 0x0010 /* ISL39300A <-> Fw */
+#define IF_ID_ISL37700_UAP 0x0016 /* ISL37700 uAP Fw <-> Fw */
+#define IF_ID_ISL39000_UAP 0x0017 /* ISL39000 uAP Fw <-> Fw */
+#define IF_ID_LMAC 0x001a /* Interface exposed by LMAC */
+
+struct exp_if {
+ __le16 role;
+ __le16 if_id;
+ __le16 variant;
+ __le16 btm_compat;
+ __le16 top_compat;
+} __packed;
+
+struct dep_if {
+ __le16 role;
+ __le16 if_id;
+ __le16 variant;
+} __packed;
+
+/* driver <-> lmac definitions */
+struct p54_eeprom_lm86 {
+ union {
+ struct {
+ __le16 offset;
+ __le16 len;
+ u8 data[0];
+ } __packed v1;
+ struct {
+ __le32 offset;
+ __le16 len;
+ u8 magic2;
+ u8 pad;
+ u8 magic[4];
+ u8 data[0];
+ } __packed v2;
+ } __packed;
+} __packed;
+
+enum p54_rx_decrypt_status {
+ P54_DECRYPT_NONE = 0,
+ P54_DECRYPT_OK,
+ P54_DECRYPT_NOKEY,
+ P54_DECRYPT_NOMICHAEL,
+ P54_DECRYPT_NOCKIPMIC,
+ P54_DECRYPT_FAIL_WEP,
+ P54_DECRYPT_FAIL_TKIP,
+ P54_DECRYPT_FAIL_MICHAEL,
+ P54_DECRYPT_FAIL_CKIPKP,
+ P54_DECRYPT_FAIL_CKIPMIC,
+ P54_DECRYPT_FAIL_AESCCMP
+};
+
+struct p54_rx_data {
+ __le16 flags;
+ __le16 len;
+ __le16 freq;
+ u8 antenna;
+ u8 rate;
+ u8 rssi;
+ u8 quality;
+ u8 decrypt_status;
+ u8 rssi_raw;
+ __le32 tsf32;
+ __le32 unalloc0;
+ u8 align[0];
+} __packed;
+
+enum p54_trap_type {
+ P54_TRAP_SCAN = 0,
+ P54_TRAP_TIMER,
+ P54_TRAP_BEACON_TX,
+ P54_TRAP_FAA_RADIO_ON,
+ P54_TRAP_FAA_RADIO_OFF,
+ P54_TRAP_RADAR,
+ P54_TRAP_NO_BEACON,
+ P54_TRAP_TBTT,
+ P54_TRAP_SCO_ENTER,
+ P54_TRAP_SCO_EXIT
+};
+
+struct p54_trap {
+ __le16 event;
+ __le16 frequency;
+} __packed;
+
+enum p54_frame_sent_status {
+ P54_TX_OK = 0,
+ P54_TX_FAILED,
+ P54_TX_PSM,
+ P54_TX_PSM_CANCELLED = 4
+};
+
+struct p54_frame_sent {
+ u8 status;
+ u8 tries;
+ u8 ack_rssi;
+ u8 quality;
+ __le16 seq;
+ u8 antenna;
+ u8 padding;
+} __packed;
+
+enum p54_tx_data_crypt {
+ P54_CRYPTO_NONE = 0,
+ P54_CRYPTO_WEP,
+ P54_CRYPTO_TKIP,
+ P54_CRYPTO_TKIPMICHAEL,
+ P54_CRYPTO_CCX_WEPMIC,
+ P54_CRYPTO_CCX_KPMIC,
+ P54_CRYPTO_CCX_KP,
+ P54_CRYPTO_AESCCMP
+};
+
+enum p54_tx_data_queue {
+ P54_QUEUE_BEACON = 0,
+ P54_QUEUE_FWSCAN = 1,
+ P54_QUEUE_MGMT = 2,
+ P54_QUEUE_CAB = 3,
+ P54_QUEUE_DATA = 4,
+
+ P54_QUEUE_AC_NUM = 4,
+ P54_QUEUE_AC_VO = 4,
+ P54_QUEUE_AC_VI = 5,
+ P54_QUEUE_AC_BE = 6,
+ P54_QUEUE_AC_BK = 7,
+
+ /* keep last */
+ P54_QUEUE_NUM = 8,
+};
+
+#define IS_QOS_QUEUE(n) (n >= P54_QUEUE_DATA)
+
+struct p54_tx_data {
+ u8 rateset[8];
+ u8 rts_rate_idx;
+ u8 crypt_offset;
+ u8 key_type;
+ u8 key_len;
+ u8 key[16];
+ u8 hw_queue;
+ u8 backlog;
+ __le16 durations[4];
+ u8 tx_antenna;
+ union {
+ struct {
+ u8 cts_rate;
+ __le16 output_power;
+ } __packed longbow;
+ struct {
+ u8 output_power;
+ u8 cts_rate;
+ u8 unalloc;
+ } __packed normal;
+ } __packed;
+ u8 unalloc2[2];
+ u8 align[0];
+} __packed;
+
+/* unit is ms */
+#define P54_TX_FRAME_LIFETIME 2000
+#define P54_TX_TIMEOUT 4000
+#define P54_STATISTICS_UPDATE 5000
+
+#define P54_FILTER_TYPE_NONE 0
+#define P54_FILTER_TYPE_STATION BIT(0)
+#define P54_FILTER_TYPE_IBSS BIT(1)
+#define P54_FILTER_TYPE_AP BIT(2)
+#define P54_FILTER_TYPE_TRANSPARENT BIT(3)
+#define P54_FILTER_TYPE_PROMISCUOUS BIT(4)
+#define P54_FILTER_TYPE_HIBERNATE BIT(5)
+#define P54_FILTER_TYPE_NOACK BIT(6)
+#define P54_FILTER_TYPE_RX_DISABLED BIT(7)
+
+struct p54_setup_mac {
+ __le16 mac_mode;
+ u8 mac_addr[ETH_ALEN];
+ u8 bssid[ETH_ALEN];
+ u8 rx_antenna;
+ u8 rx_align;
+ union {
+ struct {
+ __le32 basic_rate_mask;
+ u8 rts_rates[8];
+ __le32 rx_addr;
+ __le16 max_rx;
+ __le16 rxhw;
+ __le16 wakeup_timer;
+ __le16 unalloc0;
+ } __packed v1;
+ struct {
+ __le32 rx_addr;
+ __le16 max_rx;
+ __le16 rxhw;
+ __le16 timer;
+ __le16 truncate;
+ __le32 basic_rate_mask;
+ u8 sbss_offset;
+ u8 mcast_window;
+ u8 rx_rssi_threshold;
+ u8 rx_ed_threshold;
+ __le32 ref_clock;
+ __le16 lpf_bandwidth;
+ __le16 osc_start_delay;
+ } __packed v2;
+ } __packed;
+} __packed;
+
+#define P54_SETUP_V1_LEN 40
+#define P54_SETUP_V2_LEN (sizeof(struct p54_setup_mac))
+
+#define P54_SCAN_EXIT BIT(0)
+#define P54_SCAN_TRAP BIT(1)
+#define P54_SCAN_ACTIVE BIT(2)
+#define P54_SCAN_FILTER BIT(3)
+
+struct p54_scan_head {
+ __le16 mode;
+ __le16 dwell;
+ u8 scan_params[20];
+ __le16 freq;
+} __packed;
+
+struct p54_pa_curve_data_sample {
+ u8 rf_power;
+ u8 pa_detector;
+ u8 data_barker;
+ u8 data_bpsk;
+ u8 data_qpsk;
+ u8 data_16qam;
+ u8 data_64qam;
+ u8 padding;
+} __packed;
+
+struct p54_scan_body {
+ u8 pa_points_per_curve;
+ u8 val_barker;
+ u8 val_bpsk;
+ u8 val_qpsk;
+ u8 val_16qam;
+ u8 val_64qam;
+ struct p54_pa_curve_data_sample curve_data[8];
+ u8 dup_bpsk;
+ u8 dup_qpsk;
+ u8 dup_16qam;
+ u8 dup_64qam;
+} __packed;
+
+/*
+ * Warning: Longbow's structures are bogus.
+ */
+struct p54_channel_output_limit_longbow {
+ __le16 rf_power_points[12];
+} __packed;
+
+struct p54_pa_curve_data_sample_longbow {
+ __le16 rf_power;
+ __le16 pa_detector;
+ struct {
+ __le16 data[4];
+ } points[3] __packed;
+} __packed;
+
+struct p54_scan_body_longbow {
+ struct p54_channel_output_limit_longbow power_limits;
+ struct p54_pa_curve_data_sample_longbow curve_data[8];
+ __le16 unkn[6]; /* maybe more power_limits or rate_mask */
+} __packed;
+
+union p54_scan_body_union {
+ struct p54_scan_body normal;
+ struct p54_scan_body_longbow longbow;
+} __packed;
+
+struct p54_scan_tail_rate {
+ __le32 basic_rate_mask;
+ u8 rts_rates[8];
+} __packed;
+
+struct p54_led {
+ __le16 flags;
+ __le16 mask[2];
+ __le16 delay[2];
+} __packed;
+
+struct p54_edcf {
+ u8 flags;
+ u8 slottime;
+ u8 sifs;
+ u8 eofpad;
+ struct p54_edcf_queue_param queue[8];
+ u8 mapping[4];
+ __le16 frameburst;
+ __le16 round_trip_delay;
+} __packed;
+
+struct p54_statistics {
+ __le32 rx_success;
+ __le32 rx_bad_fcs;
+ __le32 rx_abort;
+ __le32 rx_abort_phy;
+ __le32 rts_success;
+ __le32 rts_fail;
+ __le32 tsf32;
+ __le32 airtime;
+ __le32 noise;
+ __le32 sample_noise[8];
+ __le32 sample_cca;
+ __le32 sample_tx;
+} __packed;
+
+struct p54_xbow_synth {
+ __le16 magic1;
+ __le16 magic2;
+ __le16 freq;
+ u32 padding[5];
+} __packed;
+
+struct p54_timer {
+ __le32 interval;
+} __packed;
+
+struct p54_keycache {
+ u8 entry;
+ u8 key_id;
+ u8 mac[ETH_ALEN];
+ u8 padding[2];
+ u8 key_type;
+ u8 key_len;
+ u8 key[24];
+} __packed;
+
+struct p54_burst {
+ u8 flags;
+ u8 queue;
+ u8 backlog;
+ u8 pad;
+ __le16 durations[32];
+} __packed;
+
+struct p54_psm_interval {
+ __le16 interval;
+ __le16 periods;
+} __packed;
+
+#define P54_PSM_CAM 0
+#define P54_PSM BIT(0)
+#define P54_PSM_DTIM BIT(1)
+#define P54_PSM_MCBC BIT(2)
+#define P54_PSM_CHECKSUM BIT(3)
+#define P54_PSM_SKIP_MORE_DATA BIT(4)
+#define P54_PSM_BEACON_TIMEOUT BIT(5)
+#define P54_PSM_HFOSLEEP BIT(6)
+#define P54_PSM_AUTOSWITCH_SLEEP BIT(7)
+#define P54_PSM_LPIT BIT(8)
+#define P54_PSM_BF_UCAST_SKIP BIT(9)
+#define P54_PSM_BF_MCAST_SKIP BIT(10)
+
+struct p54_psm {
+ __le16 mode;
+ __le16 aid;
+ struct p54_psm_interval intervals[4];
+ u8 beacon_rssi_skip_max;
+ u8 rssi_delta_threshold;
+ u8 nr;
+ u8 exclude[1];
+} __packed;
+
+#define MC_FILTER_ADDRESS_NUM 4
+
+struct p54_group_address_table {
+ __le16 filter_enable;
+ __le16 num_address;
+ u8 mac_list[MC_FILTER_ADDRESS_NUM][ETH_ALEN];
+} __packed;
+
+struct p54_txcancel {
+ __le32 req_id;
+} __packed;
+
+struct p54_sta_unlock {
+ u8 addr[ETH_ALEN];
+ u16 padding;
+} __packed;
+
+#define P54_TIM_CLEAR BIT(15)
+struct p54_tim {
+ u8 count;
+ u8 padding[3];
+ __le16 entry[8];
+} __packed;
+
+struct p54_cce_quiet {
+ __le32 period;
+} __packed;
+
+struct p54_bt_balancer {
+ __le16 prio_thresh;
+ __le16 acl_thresh;
+} __packed;
+
+struct p54_arp_table {
+ __le16 filter_enable;
+ u8 ipv4_addr[4];
+} __packed;
+
+/* LED control */
+int p54_set_leds(struct p54_common *priv);
+int p54_init_leds(struct p54_common *priv);
+void p54_unregister_leds(struct p54_common *priv);
+
+/* xmit functions */
+int p54_tx_80211(struct ieee80211_hw *dev, struct sk_buff *skb);
+int p54_tx_cancel(struct p54_common *priv, __le32 req_id);
+void p54_tx(struct p54_common *priv, struct sk_buff *skb);
+
+/* synth/phy configuration */
+int p54_init_xbow_synth(struct p54_common *priv);
+int p54_scan(struct p54_common *priv, u16 mode, u16 dwell);
+
+/* MAC */
+int p54_sta_unlock(struct p54_common *priv, u8 *addr);
+int p54_update_beacon_tim(struct p54_common *priv, u16 aid, bool set);
+int p54_setup_mac(struct p54_common *priv);
+int p54_set_ps(struct p54_common *priv);
+int p54_fetch_statistics(struct p54_common *priv);
+
+/* e/v DCF setup */
+int p54_set_edcf(struct p54_common *priv);
+
+/* cryptographic engine */
+int p54_upload_key(struct p54_common *priv, u8 algo, int slot,
+ u8 idx, u8 len, u8 *addr, u8* key);
+
+/* eeprom */
+int p54_download_eeprom(struct p54_common *priv, void *buf,
+ u16 offset, u16 len);
+
+/* utility */
+u8 *p54_find_ie(struct sk_buff *skb, u8 ie);
+
+#endif /* LMAC_H */
diff --git a/drivers/net/wireless/p54/main.c b/drivers/net/wireless/p54/main.c
new file mode 100644
index 00000000000..4a741df9c08
--- /dev/null
+++ b/drivers/net/wireless/p54/main.c
@@ -0,0 +1,642 @@
+/*
+ * mac80211 glue code for mac80211 Prism54 drivers
+ *
+ * Copyright (c) 2006, Michael Wu <flamingice@sourmilk.net>
+ * Copyright (c) 2007-2009, Christian Lamparter <chunkeey@web.de>
+ * Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
+ *
+ * Based on:
+ * - the islsm (softmac prism54) driver, which is:
+ * Copyright 2004-2006 Jean-Baptiste Note <jbnote@gmail.com>, et al.
+ * - stlc45xx driver
+ * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/firmware.h>
+#include <linux/etherdevice.h>
+
+#include <net/mac80211.h>
+
+#include "p54.h"
+#include "lmac.h"
+
+static int modparam_nohwcrypt;
+module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO);
+MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption.");
+MODULE_AUTHOR("Michael Wu <flamingice@sourmilk.net>");
+MODULE_DESCRIPTION("Softmac Prism54 common code");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("prism54common");
+
+static void p54_sta_notify(struct ieee80211_hw *dev, struct ieee80211_vif *vif,
+ enum sta_notify_cmd notify_cmd,
+ struct ieee80211_sta *sta)
+{
+ struct p54_common *priv = dev->priv;
+ switch (notify_cmd) {
+ case STA_NOTIFY_ADD:
+ case STA_NOTIFY_REMOVE:
+ /*
+ * Notify the firmware that we don't want or we don't
+ * need to buffer frames for this station anymore.
+ */
+
+ p54_sta_unlock(priv, sta->addr);
+ break;
+ case STA_NOTIFY_AWAKE:
+ /* update the firmware's filter table */
+ p54_sta_unlock(priv, sta->addr);
+ break;
+ default:
+ break;
+ }
+}
+
+static int p54_set_tim(struct ieee80211_hw *dev, struct ieee80211_sta *sta,
+ bool set)
+{
+ struct p54_common *priv = dev->priv;
+
+ return p54_update_beacon_tim(priv, sta->aid, set);
+}
+
+u8 *p54_find_ie(struct sk_buff *skb, u8 ie)
+{
+ struct ieee80211_mgmt *mgmt = (void *)skb->data;
+ u8 *pos, *end;
+
+ if (skb->len <= sizeof(mgmt))
+ return NULL;
+
+ pos = (u8 *)mgmt->u.beacon.variable;
+ end = skb->data + skb->len;
+ while (pos < end) {
+ if (pos + 2 + pos[1] > end)
+ return NULL;
+
+ if (pos[0] == ie)
+ return pos;
+
+ pos += 2 + pos[1];
+ }
+ return NULL;
+}
+
+static int p54_beacon_format_ie_tim(struct sk_buff *skb)
+{
+ /*
+ * the good excuse for this mess is ... the firmware.
+ * The dummy TIM MUST be at the end of the beacon frame,
+ * because it'll be overwritten!
+ */
+ u8 *tim;
+ u8 dtim_len;
+ u8 dtim_period;
+ u8 *next;
+
+ tim = p54_find_ie(skb, WLAN_EID_TIM);
+ if (!tim)
+ return 0;
+
+ dtim_len = tim[1];
+ dtim_period = tim[3];
+ next = tim + 2 + dtim_len;
+
+ if (dtim_len < 3)
+ return -EINVAL;
+
+ memmove(tim, next, skb_tail_pointer(skb) - next);
+ tim = skb_tail_pointer(skb) - (dtim_len + 2);
+
+ /* add the dummy at the end */
+ tim[0] = WLAN_EID_TIM;
+ tim[1] = 3;
+ tim[2] = 0;
+ tim[3] = dtim_period;
+ tim[4] = 0;
+
+ if (dtim_len > 3)
+ skb_trim(skb, skb->len - (dtim_len - 3));
+
+ return 0;
+}
+
+static int p54_beacon_update(struct p54_common *priv,
+ struct ieee80211_vif *vif)
+{
+ struct sk_buff *beacon;
+ int ret;
+
+ beacon = ieee80211_beacon_get(priv->hw, vif);
+ if (!beacon)
+ return -ENOMEM;
+ ret = p54_beacon_format_ie_tim(beacon);
+ if (ret)
+ return ret;
+
+ /*
+ * During operation, the firmware takes care of beaconing.
+ * The driver only needs to upload a new beacon template, once
+ * the template was changed by the stack or userspace.
+ *
+ * LMAC API 3.2.2 also specifies that the driver does not need
+ * to cancel the old beacon template by hand, instead the firmware
+ * will release the previous one through the feedback mechanism.
+ */
+ WARN_ON(p54_tx_80211(priv->hw, beacon));
+ priv->tsf_high32 = 0;
+ priv->tsf_low32 = 0;
+
+ return 0;
+}
+
+static int p54_start(struct ieee80211_hw *dev)
+{
+ struct p54_common *priv = dev->priv;
+ int err;
+
+ mutex_lock(&priv->conf_mutex);
+ err = priv->open(dev);
+ if (err)
+ goto out;
+ P54_SET_QUEUE(priv->qos_params[0], 0x0002, 0x0003, 0x0007, 47);
+ P54_SET_QUEUE(priv->qos_params[1], 0x0002, 0x0007, 0x000f, 94);
+ P54_SET_QUEUE(priv->qos_params[2], 0x0003, 0x000f, 0x03ff, 0);
+ P54_SET_QUEUE(priv->qos_params[3], 0x0007, 0x000f, 0x03ff, 0);
+ err = p54_set_edcf(priv);
+ if (err)
+ goto out;
+
+ memset(priv->bssid, ~0, ETH_ALEN);
+ priv->mode = NL80211_IFTYPE_MONITOR;
+ err = p54_setup_mac(priv);
+ if (err) {
+ priv->mode = NL80211_IFTYPE_UNSPECIFIED;
+ goto out;
+ }
+
+ ieee80211_queue_delayed_work(dev, &priv->work, 0);
+
+ priv->softled_state = 0;
+ err = p54_set_leds(priv);
+
+out:
+ mutex_unlock(&priv->conf_mutex);
+ return err;
+}
+
+static void p54_stop(struct ieee80211_hw *dev)
+{
+ struct p54_common *priv = dev->priv;
+ int i;
+
+ mutex_lock(&priv->conf_mutex);
+ priv->mode = NL80211_IFTYPE_UNSPECIFIED;
+ priv->softled_state = 0;
+ p54_set_leds(priv);
+
+ cancel_delayed_work_sync(&priv->work);
+
+ priv->stop(dev);
+ skb_queue_purge(&priv->tx_pending);
+ skb_queue_purge(&priv->tx_queue);
+ for (i = 0; i < P54_QUEUE_NUM; i++) {
+ priv->tx_stats[i].count = 0;
+ priv->tx_stats[i].len = 0;
+ }
+
+ priv->beacon_req_id = cpu_to_le32(0);
+ priv->tsf_high32 = priv->tsf_low32 = 0;
+ mutex_unlock(&priv->conf_mutex);
+}
+
+static int p54_add_interface(struct ieee80211_hw *dev,
+ struct ieee80211_if_init_conf *conf)
+{
+ struct p54_common *priv = dev->priv;
+
+ mutex_lock(&priv->conf_mutex);
+ if (priv->mode != NL80211_IFTYPE_MONITOR) {
+ mutex_unlock(&priv->conf_mutex);
+ return -EOPNOTSUPP;
+ }
+
+ priv->vif = conf->vif;
+
+ switch (conf->type) {
+ case NL80211_IFTYPE_STATION:
+ case NL80211_IFTYPE_ADHOC:
+ case NL80211_IFTYPE_AP:
+ case NL80211_IFTYPE_MESH_POINT:
+ priv->mode = conf->type;
+ break;
+ default:
+ mutex_unlock(&priv->conf_mutex);
+ return -EOPNOTSUPP;
+ }
+
+ memcpy(priv->mac_addr, conf->mac_addr, ETH_ALEN);
+ p54_setup_mac(priv);
+ mutex_unlock(&priv->conf_mutex);
+ return 0;
+}
+
+static void p54_remove_interface(struct ieee80211_hw *dev,
+ struct ieee80211_if_init_conf *conf)
+{
+ struct p54_common *priv = dev->priv;
+
+ mutex_lock(&priv->conf_mutex);
+ priv->vif = NULL;
+
+ /*
+ * LMAC API 3.2.2 states that any active beacon template must be
+ * canceled by the driver before attempting a mode transition.
+ */
+ if (le32_to_cpu(priv->beacon_req_id) != 0) {
+ p54_tx_cancel(priv, priv->beacon_req_id);
+ wait_for_completion_interruptible_timeout(&priv->beacon_comp, HZ);
+ }
+ priv->mode = NL80211_IFTYPE_MONITOR;
+ memset(priv->mac_addr, 0, ETH_ALEN);
+ memset(priv->bssid, 0, ETH_ALEN);
+ p54_setup_mac(priv);
+ mutex_unlock(&priv->conf_mutex);
+}
+
+static int p54_config(struct ieee80211_hw *dev, u32 changed)
+{
+ int ret = 0;
+ struct p54_common *priv = dev->priv;
+ struct ieee80211_conf *conf = &dev->conf;
+
+ mutex_lock(&priv->conf_mutex);
+ if (changed & IEEE80211_CONF_CHANGE_POWER)
+ priv->output_power = conf->power_level << 2;
+ if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
+ ret = p54_scan(priv, P54_SCAN_EXIT, 0);
+ if (ret)
+ goto out;
+ }
+ if (changed & IEEE80211_CONF_CHANGE_PS) {
+ ret = p54_set_ps(priv);
+ if (ret)
+ goto out;
+ }
+ if (changed & IEEE80211_CONF_CHANGE_IDLE) {
+ ret = p54_setup_mac(priv);
+ if (ret)
+ goto out;
+ }
+
+out:
+ mutex_unlock(&priv->conf_mutex);
+ return ret;
+}
+
+static void p54_configure_filter(struct ieee80211_hw *dev,
+ unsigned int changed_flags,
+ unsigned int *total_flags,
+ int mc_count, struct dev_mc_list *mclist)
+{
+ struct p54_common *priv = dev->priv;
+
+ *total_flags &= FIF_PROMISC_IN_BSS |
+ FIF_OTHER_BSS;
+
+ priv->filter_flags = *total_flags;
+
+ if (changed_flags & (FIF_PROMISC_IN_BSS | FIF_OTHER_BSS))
+ p54_setup_mac(priv);
+}
+
+static int p54_conf_tx(struct ieee80211_hw *dev, u16 queue,
+ const struct ieee80211_tx_queue_params *params)
+{
+ struct p54_common *priv = dev->priv;
+ int ret;
+
+ mutex_lock(&priv->conf_mutex);
+ if (queue < dev->queues) {
+ P54_SET_QUEUE(priv->qos_params[queue], params->aifs,
+ params->cw_min, params->cw_max, params->txop);
+ ret = p54_set_edcf(priv);
+ } else
+ ret = -EINVAL;
+ mutex_unlock(&priv->conf_mutex);
+ return ret;
+}
+
+static void p54_work(struct work_struct *work)
+{
+ struct p54_common *priv = container_of(work, struct p54_common,
+ work.work);
+
+ if (unlikely(priv->mode == NL80211_IFTYPE_UNSPECIFIED))
+ return ;
+
+ /*
+ * TODO: walk through tx_queue and do the following tasks
+ * 1. initiate bursts.
+ * 2. cancel stuck frames / reset the device if necessary.
+ */
+
+ p54_fetch_statistics(priv);
+}
+
+static int p54_get_stats(struct ieee80211_hw *dev,
+ struct ieee80211_low_level_stats *stats)
+{
+ struct p54_common *priv = dev->priv;
+
+ memcpy(stats, &priv->stats, sizeof(*stats));
+ return 0;
+}
+
+static int p54_get_tx_stats(struct ieee80211_hw *dev,
+ struct ieee80211_tx_queue_stats *stats)
+{
+ struct p54_common *priv = dev->priv;
+
+ memcpy(stats, &priv->tx_stats[P54_QUEUE_DATA],
+ sizeof(stats[0]) * dev->queues);
+ return 0;
+}
+
+static void p54_bss_info_changed(struct ieee80211_hw *dev,
+ struct ieee80211_vif *vif,
+ struct ieee80211_bss_conf *info,
+ u32 changed)
+{
+ struct p54_common *priv = dev->priv;
+
+ mutex_lock(&priv->conf_mutex);
+ if (changed & BSS_CHANGED_BSSID) {
+ memcpy(priv->bssid, info->bssid, ETH_ALEN);
+ p54_setup_mac(priv);
+ }
+
+ if (changed & BSS_CHANGED_BEACON) {
+ p54_scan(priv, P54_SCAN_EXIT, 0);
+ p54_setup_mac(priv);
+ p54_beacon_update(priv, vif);
+ p54_set_edcf(priv);
+ }
+
+ if (changed & (BSS_CHANGED_ERP_SLOT | BSS_CHANGED_BEACON)) {
+ priv->use_short_slot = info->use_short_slot;
+ p54_set_edcf(priv);
+ }
+ if (changed & BSS_CHANGED_BASIC_RATES) {
+ if (dev->conf.channel->band == IEEE80211_BAND_5GHZ)
+ priv->basic_rate_mask = (info->basic_rates << 4);
+ else
+ priv->basic_rate_mask = info->basic_rates;
+ p54_setup_mac(priv);
+ if (priv->fw_var >= 0x500)
+ p54_scan(priv, P54_SCAN_EXIT, 0);
+ }
+ if (changed & BSS_CHANGED_ASSOC) {
+ if (info->assoc) {
+ priv->aid = info->aid;
+ priv->wakeup_timer = info->beacon_int *
+ info->dtim_period * 5;
+ p54_setup_mac(priv);
+ } else {
+ priv->wakeup_timer = 500;
+ priv->aid = 0;
+ }
+ }
+
+ mutex_unlock(&priv->conf_mutex);
+}
+
+static int p54_set_key(struct ieee80211_hw *dev, enum set_key_cmd cmd,
+ struct ieee80211_vif *vif, struct ieee80211_sta *sta,
+ struct ieee80211_key_conf *key)
+{
+ struct p54_common *priv = dev->priv;
+ int slot, ret = 0;
+ u8 algo = 0;
+ u8 *addr = NULL;
+
+ if (modparam_nohwcrypt)
+ return -EOPNOTSUPP;
+
+ mutex_lock(&priv->conf_mutex);
+ if (cmd == SET_KEY) {
+ switch (key->alg) {
+ case ALG_TKIP:
+ if (!(priv->privacy_caps & (BR_DESC_PRIV_CAP_MICHAEL |
+ BR_DESC_PRIV_CAP_TKIP))) {
+ ret = -EOPNOTSUPP;
+ goto out_unlock;
+ }
+ key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
+ algo = P54_CRYPTO_TKIPMICHAEL;
+ break;
+ case ALG_WEP:
+ if (!(priv->privacy_caps & BR_DESC_PRIV_CAP_WEP)) {
+ ret = -EOPNOTSUPP;
+ goto out_unlock;
+ }
+ key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
+ algo = P54_CRYPTO_WEP;
+ break;
+ case ALG_CCMP:
+ if (!(priv->privacy_caps & BR_DESC_PRIV_CAP_AESCCMP)) {
+ ret = -EOPNOTSUPP;
+ goto out_unlock;
+ }
+ key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
+ algo = P54_CRYPTO_AESCCMP;
+ break;
+ default:
+ ret = -EOPNOTSUPP;
+ goto out_unlock;
+ }
+ slot = bitmap_find_free_region(priv->used_rxkeys,
+ priv->rx_keycache_size, 0);
+
+ if (slot < 0) {
+ /*
+ * The device supports the choosen algorithm, but the
+ * firmware does not provide enough key slots to store
+ * all of them.
+ * But encryption offload for outgoing frames is always
+ * possible, so we just pretend that the upload was
+ * successful and do the decryption in software.
+ */
+
+ /* mark the key as invalid. */
+ key->hw_key_idx = 0xff;
+ goto out_unlock;
+ }
+ } else {
+ slot = key->hw_key_idx;
+
+ if (slot == 0xff) {
+ /* This key was not uploaded into the rx key cache. */
+
+ goto out_unlock;
+ }
+
+ bitmap_release_region(priv->used_rxkeys, slot, 0);
+ algo = 0;
+ }
+
+ if (sta)
+ addr = sta->addr;
+
+ ret = p54_upload_key(priv, algo, slot, key->keyidx,
+ key->keylen, addr, key->key);
+ if (ret) {
+ bitmap_release_region(priv->used_rxkeys, slot, 0);
+ ret = -EOPNOTSUPP;
+ goto out_unlock;
+ }
+
+ key->hw_key_idx = slot;
+
+out_unlock:
+ mutex_unlock(&priv->conf_mutex);
+ return ret;
+}
+
+static const struct ieee80211_ops p54_ops = {
+ .tx = p54_tx_80211,
+ .start = p54_start,
+ .stop = p54_stop,
+ .add_interface = p54_add_interface,
+ .remove_interface = p54_remove_interface,
+ .set_tim = p54_set_tim,
+ .sta_notify = p54_sta_notify,
+ .set_key = p54_set_key,
+ .config = p54_config,
+ .bss_info_changed = p54_bss_info_changed,
+ .configure_filter = p54_configure_filter,
+ .conf_tx = p54_conf_tx,
+ .get_stats = p54_get_stats,
+ .get_tx_stats = p54_get_tx_stats
+};
+
+struct ieee80211_hw *p54_init_common(size_t priv_data_len)
+{
+ struct ieee80211_hw *dev;
+ struct p54_common *priv;
+
+ dev = ieee80211_alloc_hw(priv_data_len, &p54_ops);
+ if (!dev)
+ return NULL;
+
+ priv = dev->priv;
+ priv->hw = dev;
+ priv->mode = NL80211_IFTYPE_UNSPECIFIED;
+ priv->basic_rate_mask = 0x15f;
+ spin_lock_init(&priv->tx_stats_lock);
+ skb_queue_head_init(&priv->tx_queue);
+ skb_queue_head_init(&priv->tx_pending);
+ dev->flags = IEEE80211_HW_RX_INCLUDES_FCS |
+ IEEE80211_HW_SIGNAL_DBM |
+ IEEE80211_HW_SUPPORTS_PS |
+ IEEE80211_HW_PS_NULLFUNC_STACK |
+ IEEE80211_HW_BEACON_FILTER |
+ IEEE80211_HW_NOISE_DBM;
+
+ dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
+ BIT(NL80211_IFTYPE_ADHOC) |
+ BIT(NL80211_IFTYPE_AP) |
+ BIT(NL80211_IFTYPE_MESH_POINT);
+
+ dev->channel_change_time = 1000; /* TODO: find actual value */
+ priv->beacon_req_id = cpu_to_le32(0);
+ priv->tx_stats[P54_QUEUE_BEACON].limit = 1;
+ priv->tx_stats[P54_QUEUE_FWSCAN].limit = 1;
+ priv->tx_stats[P54_QUEUE_MGMT].limit = 3;
+ priv->tx_stats[P54_QUEUE_CAB].limit = 3;
+ priv->tx_stats[P54_QUEUE_DATA].limit = 5;
+ dev->queues = 1;
+ priv->noise = -94;
+ /*
+ * We support at most 8 tries no matter which rate they're at,
+ * we cannot support max_rates * max_rate_tries as we set it
+ * here, but setting it correctly to 4/2 or so would limit us
+ * artificially if the RC algorithm wants just two rates, so
+ * let's say 4/7, we'll redistribute it at TX time, see the
+ * comments there.
+ */
+ dev->max_rates = 4;
+ dev->max_rate_tries = 7;
+ dev->extra_tx_headroom = sizeof(struct p54_hdr) + 4 +
+ sizeof(struct p54_tx_data);
+
+ mutex_init(&priv->conf_mutex);
+ mutex_init(&priv->eeprom_mutex);
+ init_completion(&priv->eeprom_comp);
+ init_completion(&priv->beacon_comp);
+ INIT_DELAYED_WORK(&priv->work, p54_work);
+
+ return dev;
+}
+EXPORT_SYMBOL_GPL(p54_init_common);
+
+int p54_register_common(struct ieee80211_hw *dev, struct device *pdev)
+{
+ struct p54_common *priv = dev->priv;
+ int err;
+
+ err = ieee80211_register_hw(dev);
+ if (err) {
+ dev_err(pdev, "Cannot register device (%d).\n", err);
+ return err;
+ }
+
+#ifdef CONFIG_P54_LEDS
+ err = p54_init_leds(priv);
+ if (err)
+ return err;
+#endif /* CONFIG_P54_LEDS */
+
+ dev_info(pdev, "is registered as '%s'\n", wiphy_name(dev->wiphy));
+ return 0;
+}
+EXPORT_SYMBOL_GPL(p54_register_common);
+
+void p54_free_common(struct ieee80211_hw *dev)
+{
+ struct p54_common *priv = dev->priv;
+ unsigned int i;
+
+ for (i = 0; i < IEEE80211_NUM_BANDS; i++)
+ kfree(priv->band_table[i]);
+
+ kfree(priv->iq_autocal);
+ kfree(priv->output_limit);
+ kfree(priv->curve_data);
+ kfree(priv->used_rxkeys);
+ priv->iq_autocal = NULL;
+ priv->output_limit = NULL;
+ priv->curve_data = NULL;
+ priv->used_rxkeys = NULL;
+ ieee80211_free_hw(dev);
+}
+EXPORT_SYMBOL_GPL(p54_free_common);
+
+void p54_unregister_common(struct ieee80211_hw *dev)
+{
+ struct p54_common *priv = dev->priv;
+
+#ifdef CONFIG_P54_LEDS
+ p54_unregister_leds(priv);
+#endif /* CONFIG_P54_LEDS */
+
+ ieee80211_unregister_hw(dev);
+ mutex_destroy(&priv->conf_mutex);
+ mutex_destroy(&priv->eeprom_mutex);
+}
+EXPORT_SYMBOL_GPL(p54_unregister_common);
diff --git a/drivers/net/wireless/p54/p54.h b/drivers/net/wireless/p54/p54.h
index db3df947d8e..1afc39410e8 100644
--- a/drivers/net/wireless/p54/p54.h
+++ b/drivers/net/wireless/p54/p54.h
@@ -1,6 +1,3 @@
-#ifndef P54_H
-#define P54_H
-
/*
* Shared defines for all mac80211 Prism54 code
*
@@ -14,39 +11,78 @@
* published by the Free Software Foundation.
*/
+#ifndef P54_H
+#define P54_H
+
#ifdef CONFIG_P54_LEDS
#include <linux/leds.h>
#endif /* CONFIG_P54_LEDS */
-enum p54_control_frame_types {
- P54_CONTROL_TYPE_SETUP = 0,
- P54_CONTROL_TYPE_SCAN,
- P54_CONTROL_TYPE_TRAP,
- P54_CONTROL_TYPE_DCFINIT,
- P54_CONTROL_TYPE_RX_KEYCACHE,
- P54_CONTROL_TYPE_TIM,
- P54_CONTROL_TYPE_PSM,
- P54_CONTROL_TYPE_TXCANCEL,
- P54_CONTROL_TYPE_TXDONE,
- P54_CONTROL_TYPE_BURST,
- P54_CONTROL_TYPE_STAT_READBACK,
- P54_CONTROL_TYPE_BBP,
- P54_CONTROL_TYPE_EEPROM_READBACK,
- P54_CONTROL_TYPE_LED,
- P54_CONTROL_TYPE_GPIO,
- P54_CONTROL_TYPE_TIMER,
- P54_CONTROL_TYPE_MODULATION,
- P54_CONTROL_TYPE_SYNTH_CONFIG,
- P54_CONTROL_TYPE_DETECTOR_VALUE,
- P54_CONTROL_TYPE_XBOW_SYNTH_CFG,
- P54_CONTROL_TYPE_CCE_QUIET,
- P54_CONTROL_TYPE_PSM_STA_UNLOCK,
- P54_CONTROL_TYPE_PCS,
- P54_CONTROL_TYPE_BT_BALANCER = 28,
- P54_CONTROL_TYPE_GROUP_ADDRESS_TABLE = 30,
- P54_CONTROL_TYPE_ARPTABLE = 31,
- P54_CONTROL_TYPE_BT_OPTIONS = 35
-};
+#define ISL38XX_DEV_FIRMWARE_ADDR 0x20000
+
+#define BR_CODE_MIN 0x80000000
+#define BR_CODE_COMPONENT_ID 0x80000001
+#define BR_CODE_COMPONENT_VERSION 0x80000002
+#define BR_CODE_DEPENDENT_IF 0x80000003
+#define BR_CODE_EXPOSED_IF 0x80000004
+#define BR_CODE_DESCR 0x80000101
+#define BR_CODE_MAX 0x8FFFFFFF
+#define BR_CODE_END_OF_BRA 0xFF0000FF
+#define LEGACY_BR_CODE_END_OF_BRA 0xFFFFFFFF
+
+struct bootrec {
+ __le32 code;
+ __le32 len;
+ u32 data[10];
+} __packed;
+
+/* Interface role definitions */
+#define BR_INTERFACE_ROLE_SERVER 0x0000
+#define BR_INTERFACE_ROLE_CLIENT 0x8000
+
+#define BR_DESC_PRIV_CAP_WEP BIT(0)
+#define BR_DESC_PRIV_CAP_TKIP BIT(1)
+#define BR_DESC_PRIV_CAP_MICHAEL BIT(2)
+#define BR_DESC_PRIV_CAP_CCX_CP BIT(3)
+#define BR_DESC_PRIV_CAP_CCX_MIC BIT(4)
+#define BR_DESC_PRIV_CAP_AESCCMP BIT(5)
+
+struct bootrec_desc {
+ __le16 modes;
+ __le16 flags;
+ __le32 rx_start;
+ __le32 rx_end;
+ u8 headroom;
+ u8 tailroom;
+ u8 tx_queues;
+ u8 tx_depth;
+ u8 privacy_caps;
+ u8 rx_keycache_size;
+ u8 time_size;
+ u8 padding;
+ u8 rates[16];
+ u8 padding2[4];
+ __le16 rx_mtu;
+} __packed;
+
+#define FW_FMAC 0x464d4143
+#define FW_LM86 0x4c4d3836
+#define FW_LM87 0x4c4d3837
+#define FW_LM20 0x4c4d3230
+
+struct bootrec_comp_id {
+ __le32 fw_variant;
+} __packed;
+
+struct bootrec_comp_ver {
+ char fw_version[24];
+} __packed;
+
+struct bootrec_end {
+ __le16 crc;
+ u8 padding[2];
+ u8 md5[16];
+} __packed;
/* provide 16 bytes for the transport back-end */
#define P54_TX_INFO_DATA_SIZE 16
@@ -55,34 +91,30 @@ enum p54_control_frame_types {
struct p54_tx_info {
u32 start_addr;
u32 end_addr;
- void *data[P54_TX_INFO_DATA_SIZE / sizeof(void *)];
+ union {
+ void *data[P54_TX_INFO_DATA_SIZE / sizeof(void *)];
+ struct {
+ u32 extra_len;
+ };
+ };
};
#define P54_MAX_CTRL_FRAME_LEN 0x1000
-#define P54_HDR_FLAG_CONTROL BIT(15)
-#define P54_HDR_FLAG_CONTROL_OPSET (BIT(15) + BIT(0))
-
-struct p54_hdr {
- __le16 flags;
- __le16 len;
- __le32 req_id;
- __le16 type; /* enum p54_control_frame_types */
- u8 rts_tries;
- u8 tries;
- u8 data[0];
-} __attribute__ ((packed));
-
-#define FREE_AFTER_TX(skb) \
- ((((struct p54_hdr *) ((struct sk_buff *) skb)->data)-> \
- flags) == cpu_to_le16(P54_HDR_FLAG_CONTROL_OPSET))
+#define P54_SET_QUEUE(queue, ai_fs, cw_min, cw_max, _txop) \
+do { \
+ queue.aifs = cpu_to_le16(ai_fs); \
+ queue.cwmin = cpu_to_le16(cw_min); \
+ queue.cwmax = cpu_to_le16(cw_max); \
+ queue.txop = cpu_to_le16(_txop); \
+} while (0)
struct p54_edcf_queue_param {
__le16 aifs;
__le16 cwmin;
__le16 cwmax;
__le16 txop;
-} __attribute__ ((packed));
+} __packed;
struct p54_rssi_linear_approximation {
s16 mul;
@@ -101,13 +133,6 @@ struct p54_cal_database {
#define EEPROM_READBACK_LEN 0x3fc
-#define ISL38XX_DEV_FIRMWARE_ADDR 0x20000
-
-#define FW_FMAC 0x464d4143
-#define FW_LM86 0x4c4d3836
-#define FW_LM87 0x4c4d3837
-#define FW_LM20 0x4c4d3230
-
enum fw_state {
FW_STATE_OFF,
FW_STATE_BOOTING,
@@ -138,6 +163,7 @@ struct p54_common {
void (*tx)(struct ieee80211_hw *dev, struct sk_buff *skb);
int (*open)(struct ieee80211_hw *dev);
void (*stop)(struct ieee80211_hw *dev);
+ struct sk_buff_head tx_pending;
struct sk_buff_head tx_queue;
struct mutex conf_mutex;
@@ -156,6 +182,7 @@ struct p54_common {
/* (e)DCF / QOS state */
bool use_short_slot;
+ spinlock_t tx_stats_lock;
struct ieee80211_tx_queue_stats tx_stats[8];
struct p54_edcf_queue_param qos_params[8];
@@ -171,6 +198,7 @@ struct p54_common {
struct p54_cal_database *curve_data;
struct p54_cal_database *output_limit;
struct p54_rssi_linear_approximation rssical_db[IEEE80211_NUM_BANDS];
+ struct ieee80211_supported_band *band_table[IEEE80211_NUM_BANDS];
/* BBP/MAC state */
u8 mac_addr[ETH_ALEN];
@@ -181,7 +209,9 @@ struct p54_common {
u32 tsf_low32, tsf_high32;
u32 basic_rate_mask;
u16 aid;
- struct sk_buff *cached_beacon;
+ bool powersave_override;
+ __le32 beacon_req_id;
+ struct completion beacon_comp;
/* cryptographic engine information */
u8 privacy_caps;
@@ -202,15 +232,20 @@ struct p54_common {
/* eeprom handling */
void *eeprom;
struct completion eeprom_comp;
+ struct mutex eeprom_mutex;
};
+/* interfaces for the drivers */
int p54_rx(struct ieee80211_hw *dev, struct sk_buff *skb);
void p54_free_skb(struct ieee80211_hw *dev, struct sk_buff *skb);
int p54_parse_firmware(struct ieee80211_hw *dev, const struct firmware *fw);
int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len);
int p54_read_eeprom(struct ieee80211_hw *dev);
+
struct ieee80211_hw *p54_init_common(size_t priv_data_len);
int p54_register_common(struct ieee80211_hw *dev, struct device *pdev);
void p54_free_common(struct ieee80211_hw *dev);
+void p54_unregister_common(struct ieee80211_hw *dev);
+
#endif /* P54_H */
diff --git a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c
deleted file mode 100644
index 22ca122bd79..00000000000
--- a/drivers/net/wireless/p54/p54common.c
+++ /dev/null
@@ -1,2688 +0,0 @@
-/*
- * Common code for mac80211 Prism54 drivers
- *
- * Copyright (c) 2006, Michael Wu <flamingice@sourmilk.net>
- * Copyright (c) 2007, Christian Lamparter <chunkeey@web.de>
- * Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
- *
- * Based on:
- * - the islsm (softmac prism54) driver, which is:
- * Copyright 2004-2006 Jean-Baptiste Note <jbnote@gmail.com>, et al.
- * - stlc45xx driver
- * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/init.h>
-#include <linux/firmware.h>
-#include <linux/etherdevice.h>
-
-#include <net/mac80211.h>
-#ifdef CONFIG_P54_LEDS
-#include <linux/leds.h>
-#endif /* CONFIG_P54_LEDS */
-
-#include "p54.h"
-#include "p54common.h"
-
-static int modparam_nohwcrypt;
-module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO);
-MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption.");
-MODULE_AUTHOR("Michael Wu <flamingice@sourmilk.net>");
-MODULE_DESCRIPTION("Softmac Prism54 common code");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("prism54common");
-
-static struct ieee80211_rate p54_bgrates[] = {
- { .bitrate = 10, .hw_value = 0, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
- { .bitrate = 20, .hw_value = 1, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
- { .bitrate = 55, .hw_value = 2, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
- { .bitrate = 110, .hw_value = 3, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
- { .bitrate = 60, .hw_value = 4, },
- { .bitrate = 90, .hw_value = 5, },
- { .bitrate = 120, .hw_value = 6, },
- { .bitrate = 180, .hw_value = 7, },
- { .bitrate = 240, .hw_value = 8, },
- { .bitrate = 360, .hw_value = 9, },
- { .bitrate = 480, .hw_value = 10, },
- { .bitrate = 540, .hw_value = 11, },
-};
-
-static struct ieee80211_channel p54_bgchannels[] = {
- { .center_freq = 2412, .hw_value = 1, },
- { .center_freq = 2417, .hw_value = 2, },
- { .center_freq = 2422, .hw_value = 3, },
- { .center_freq = 2427, .hw_value = 4, },
- { .center_freq = 2432, .hw_value = 5, },
- { .center_freq = 2437, .hw_value = 6, },
- { .center_freq = 2442, .hw_value = 7, },
- { .center_freq = 2447, .hw_value = 8, },
- { .center_freq = 2452, .hw_value = 9, },
- { .center_freq = 2457, .hw_value = 10, },
- { .center_freq = 2462, .hw_value = 11, },
- { .center_freq = 2467, .hw_value = 12, },
- { .center_freq = 2472, .hw_value = 13, },
- { .center_freq = 2484, .hw_value = 14, },
-};
-
-static struct ieee80211_supported_band band_2GHz = {
- .channels = p54_bgchannels,
- .n_channels = ARRAY_SIZE(p54_bgchannels),
- .bitrates = p54_bgrates,
- .n_bitrates = ARRAY_SIZE(p54_bgrates),
-};
-
-static struct ieee80211_rate p54_arates[] = {
- { .bitrate = 60, .hw_value = 4, },
- { .bitrate = 90, .hw_value = 5, },
- { .bitrate = 120, .hw_value = 6, },
- { .bitrate = 180, .hw_value = 7, },
- { .bitrate = 240, .hw_value = 8, },
- { .bitrate = 360, .hw_value = 9, },
- { .bitrate = 480, .hw_value = 10, },
- { .bitrate = 540, .hw_value = 11, },
-};
-
-static struct ieee80211_channel p54_achannels[] = {
- { .center_freq = 4920 },
- { .center_freq = 4940 },
- { .center_freq = 4960 },
- { .center_freq = 4980 },
- { .center_freq = 5040 },
- { .center_freq = 5060 },
- { .center_freq = 5080 },
- { .center_freq = 5170 },
- { .center_freq = 5180 },
- { .center_freq = 5190 },
- { .center_freq = 5200 },
- { .center_freq = 5210 },
- { .center_freq = 5220 },
- { .center_freq = 5230 },
- { .center_freq = 5240 },
- { .center_freq = 5260 },
- { .center_freq = 5280 },
- { .center_freq = 5300 },
- { .center_freq = 5320 },
- { .center_freq = 5500 },
- { .center_freq = 5520 },
- { .center_freq = 5540 },
- { .center_freq = 5560 },
- { .center_freq = 5580 },
- { .center_freq = 5600 },
- { .center_freq = 5620 },
- { .center_freq = 5640 },
- { .center_freq = 5660 },
- { .center_freq = 5680 },
- { .center_freq = 5700 },
- { .center_freq = 5745 },
- { .center_freq = 5765 },
- { .center_freq = 5785 },
- { .center_freq = 5805 },
- { .center_freq = 5825 },
-};
-
-static struct ieee80211_supported_band band_5GHz = {
- .channels = p54_achannels,
- .n_channels = ARRAY_SIZE(p54_achannels),
- .bitrates = p54_arates,
- .n_bitrates = ARRAY_SIZE(p54_arates),
-};
-
-int p54_parse_firmware(struct ieee80211_hw *dev, const struct firmware *fw)
-{
- struct p54_common *priv = dev->priv;
- struct bootrec_exp_if *exp_if;
- struct bootrec *bootrec;
- u32 *data = (u32 *)fw->data;
- u32 *end_data = (u32 *)fw->data + (fw->size >> 2);
- u8 *fw_version = NULL;
- size_t len;
- int i;
- int maxlen;
-
- if (priv->rx_start)
- return 0;
-
- while (data < end_data && *data)
- data++;
-
- while (data < end_data && !*data)
- data++;
-
- bootrec = (struct bootrec *) data;
-
- while (bootrec->data <= end_data &&
- (bootrec->data + (len = le32_to_cpu(bootrec->len))) <= end_data) {
- u32 code = le32_to_cpu(bootrec->code);
- switch (code) {
- case BR_CODE_COMPONENT_ID:
- priv->fw_interface = be32_to_cpup((__be32 *)
- bootrec->data);
- switch (priv->fw_interface) {
- case FW_LM86:
- case FW_LM20:
- case FW_LM87: {
- char *iftype = (char *)bootrec->data;
- printk(KERN_INFO "%s: p54 detected a LM%c%c "
- "firmware\n",
- wiphy_name(dev->wiphy),
- iftype[2], iftype[3]);
- break;
- }
- case FW_FMAC:
- default:
- printk(KERN_ERR "%s: unsupported firmware\n",
- wiphy_name(dev->wiphy));
- return -ENODEV;
- }
- break;
- case BR_CODE_COMPONENT_VERSION:
- /* 24 bytes should be enough for all firmwares */
- if (strnlen((unsigned char*)bootrec->data, 24) < 24)
- fw_version = (unsigned char*)bootrec->data;
- break;
- case BR_CODE_DESCR: {
- struct bootrec_desc *desc =
- (struct bootrec_desc *)bootrec->data;
- priv->rx_start = le32_to_cpu(desc->rx_start);
- /* FIXME add sanity checking */
- priv->rx_end = le32_to_cpu(desc->rx_end) - 0x3500;
- priv->headroom = desc->headroom;
- priv->tailroom = desc->tailroom;
- priv->privacy_caps = desc->privacy_caps;
- priv->rx_keycache_size = desc->rx_keycache_size;
- if (le32_to_cpu(bootrec->len) == 11)
- priv->rx_mtu = le16_to_cpu(desc->rx_mtu);
- else
- priv->rx_mtu = (size_t)
- 0x620 - priv->tx_hdr_len;
- maxlen = priv->tx_hdr_len + /* USB devices */
- sizeof(struct p54_rx_data) +
- 4 + /* rx alignment */
- IEEE80211_MAX_FRAG_THRESHOLD;
- if (priv->rx_mtu > maxlen && PAGE_SIZE == 4096) {
- printk(KERN_INFO "p54: rx_mtu reduced from %d "
- "to %d\n", priv->rx_mtu,
- maxlen);
- priv->rx_mtu = maxlen;
- }
- break;
- }
- case BR_CODE_EXPOSED_IF:
- exp_if = (struct bootrec_exp_if *) bootrec->data;
- for (i = 0; i < (len * sizeof(*exp_if) / 4); i++)
- if (exp_if[i].if_id == cpu_to_le16(0x1a))
- priv->fw_var = le16_to_cpu(exp_if[i].variant);
- break;
- case BR_CODE_DEPENDENT_IF:
- break;
- case BR_CODE_END_OF_BRA:
- case LEGACY_BR_CODE_END_OF_BRA:
- end_data = NULL;
- break;
- default:
- break;
- }
- bootrec = (struct bootrec *)&bootrec->data[len];
- }
-
- if (fw_version)
- printk(KERN_INFO "%s: FW rev %s - Softmac protocol %x.%x\n",
- wiphy_name(dev->wiphy), fw_version,
- priv->fw_var >> 8, priv->fw_var & 0xff);
-
- if (priv->fw_var < 0x500)
- printk(KERN_INFO "%s: you are using an obsolete firmware. "
- "visit http://wireless.kernel.org/en/users/Drivers/p54 "
- "and grab one for \"kernel >= 2.6.28\"!\n",
- wiphy_name(dev->wiphy));
-
- if (priv->fw_var >= 0x300) {
- /* Firmware supports QoS, use it! */
- priv->tx_stats[P54_QUEUE_AC_VO].limit = 3;
- priv->tx_stats[P54_QUEUE_AC_VI].limit = 4;
- priv->tx_stats[P54_QUEUE_AC_BE].limit = 3;
- priv->tx_stats[P54_QUEUE_AC_BK].limit = 2;
- dev->queues = P54_QUEUE_AC_NUM;
- }
-
- if (!modparam_nohwcrypt) {
- printk(KERN_INFO "%s: cryptographic accelerator "
- "WEP:%s, TKIP:%s, CCMP:%s\n",
- wiphy_name(dev->wiphy),
- (priv->privacy_caps & BR_DESC_PRIV_CAP_WEP) ? "YES" :
- "no", (priv->privacy_caps & (BR_DESC_PRIV_CAP_TKIP |
- BR_DESC_PRIV_CAP_MICHAEL)) ? "YES" : "no",
- (priv->privacy_caps & BR_DESC_PRIV_CAP_AESCCMP) ?
- "YES" : "no");
-
- if (priv->rx_keycache_size) {
- /*
- * NOTE:
- *
- * The firmware provides at most 255 (0 - 254) slots
- * for keys which are then used to offload decryption.
- * As a result the 255 entry (aka 0xff) can be used
- * safely by the driver to mark keys that didn't fit
- * into the full cache. This trick saves us from
- * keeping a extra list for uploaded keys.
- */
-
- priv->used_rxkeys = kzalloc(BITS_TO_LONGS(
- priv->rx_keycache_size), GFP_KERNEL);
-
- if (!priv->used_rxkeys)
- return -ENOMEM;
- }
- }
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(p54_parse_firmware);
-
-static int p54_convert_rev0(struct ieee80211_hw *dev,
- struct pda_pa_curve_data *curve_data)
-{
- struct p54_common *priv = dev->priv;
- struct p54_pa_curve_data_sample *dst;
- struct pda_pa_curve_data_sample_rev0 *src;
- size_t cd_len = sizeof(*curve_data) +
- (curve_data->points_per_channel*sizeof(*dst) + 2) *
- curve_data->channels;
- unsigned int i, j;
- void *source, *target;
-
- priv->curve_data = kmalloc(sizeof(*priv->curve_data) + cd_len,
- GFP_KERNEL);
- if (!priv->curve_data)
- return -ENOMEM;
-
- priv->curve_data->entries = curve_data->channels;
- priv->curve_data->entry_size = sizeof(__le16) +
- sizeof(*dst) * curve_data->points_per_channel;
- priv->curve_data->offset = offsetof(struct pda_pa_curve_data, data);
- priv->curve_data->len = cd_len;
- memcpy(priv->curve_data->data, curve_data, sizeof(*curve_data));
- source = curve_data->data;
- target = ((struct pda_pa_curve_data *) priv->curve_data->data)->data;
- for (i = 0; i < curve_data->channels; i++) {
- __le16 *freq = source;
- source += sizeof(__le16);
- *((__le16 *)target) = *freq;
- target += sizeof(__le16);
- for (j = 0; j < curve_data->points_per_channel; j++) {
- dst = target;
- src = source;
-
- dst->rf_power = src->rf_power;
- dst->pa_detector = src->pa_detector;
- dst->data_64qam = src->pcv;
- /* "invent" the points for the other modulations */
-#define SUB(x,y) (u8)((x) - (y)) > (x) ? 0 : (x) - (y)
- dst->data_16qam = SUB(src->pcv, 12);
- dst->data_qpsk = SUB(dst->data_16qam, 12);
- dst->data_bpsk = SUB(dst->data_qpsk, 12);
- dst->data_barker = SUB(dst->data_bpsk, 14);
-#undef SUB
- target += sizeof(*dst);
- source += sizeof(*src);
- }
- }
-
- return 0;
-}
-
-static int p54_convert_rev1(struct ieee80211_hw *dev,
- struct pda_pa_curve_data *curve_data)
-{
- struct p54_common *priv = dev->priv;
- struct p54_pa_curve_data_sample *dst;
- struct pda_pa_curve_data_sample_rev1 *src;
- size_t cd_len = sizeof(*curve_data) +
- (curve_data->points_per_channel*sizeof(*dst) + 2) *
- curve_data->channels;
- unsigned int i, j;
- void *source, *target;
-
- priv->curve_data = kzalloc(cd_len + sizeof(*priv->curve_data),
- GFP_KERNEL);
- if (!priv->curve_data)
- return -ENOMEM;
-
- priv->curve_data->entries = curve_data->channels;
- priv->curve_data->entry_size = sizeof(__le16) +
- sizeof(*dst) * curve_data->points_per_channel;
- priv->curve_data->offset = offsetof(struct pda_pa_curve_data, data);
- priv->curve_data->len = cd_len;
- memcpy(priv->curve_data->data, curve_data, sizeof(*curve_data));
- source = curve_data->data;
- target = ((struct pda_pa_curve_data *) priv->curve_data->data)->data;
- for (i = 0; i < curve_data->channels; i++) {
- __le16 *freq = source;
- source += sizeof(__le16);
- *((__le16 *)target) = *freq;
- target += sizeof(__le16);
- for (j = 0; j < curve_data->points_per_channel; j++) {
- memcpy(target, source, sizeof(*src));
-
- target += sizeof(*dst);
- source += sizeof(*src);
- }
- source++;
- }
-
- return 0;
-}
-
-static const char *p54_rf_chips[] = { "NULL", "Duette3", "Duette2",
- "Frisbee", "Xbow", "Longbow", "NULL", "NULL" };
-static int p54_init_xbow_synth(struct ieee80211_hw *dev);
-
-static void p54_parse_rssical(struct ieee80211_hw *dev, void *data, int len,
- u16 type)
-{
- struct p54_common *priv = dev->priv;
- int offset = (type == PDR_RSSI_LINEAR_APPROXIMATION_EXTENDED) ? 2 : 0;
- int entry_size = sizeof(struct pda_rssi_cal_entry) + offset;
- int num_entries = (type == PDR_RSSI_LINEAR_APPROXIMATION) ? 1 : 2;
- int i;
-
- if (len != (entry_size * num_entries)) {
- printk(KERN_ERR "%s: unknown rssi calibration data packing "
- " type:(%x) len:%d.\n",
- wiphy_name(dev->wiphy), type, len);
-
- print_hex_dump_bytes("rssical:", DUMP_PREFIX_NONE,
- data, len);
-
- printk(KERN_ERR "%s: please report this issue.\n",
- wiphy_name(dev->wiphy));
- return;
- }
-
- for (i = 0; i < num_entries; i++) {
- struct pda_rssi_cal_entry *cal = data +
- (offset + i * entry_size);
- priv->rssical_db[i].mul = (s16) le16_to_cpu(cal->mul);
- priv->rssical_db[i].add = (s16) le16_to_cpu(cal->add);
- }
-}
-
-static void p54_parse_default_country(struct ieee80211_hw *dev,
- void *data, int len)
-{
- struct pda_country *country;
-
- if (len != sizeof(*country)) {
- printk(KERN_ERR "%s: found possible invalid default country "
- "eeprom entry. (entry size: %d)\n",
- wiphy_name(dev->wiphy), len);
-
- print_hex_dump_bytes("country:", DUMP_PREFIX_NONE,
- data, len);
-
- printk(KERN_ERR "%s: please report this issue.\n",
- wiphy_name(dev->wiphy));
- return;
- }
-
- country = (struct pda_country *) data;
- if (country->flags == PDR_COUNTRY_CERT_CODE_PSEUDO)
- regulatory_hint(dev->wiphy, country->alpha2);
- else {
- /* TODO:
- * write a shared/common function that converts
- * "Regulatory domain codes" (802.11-2007 14.8.2.2)
- * into ISO/IEC 3166-1 alpha2 for regulatory_hint.
- */
- }
-}
-
-static int p54_convert_output_limits(struct ieee80211_hw *dev,
- u8 *data, size_t len)
-{
- struct p54_common *priv = dev->priv;
-
- if (len < 2)
- return -EINVAL;
-
- if (data[0] != 0) {
- printk(KERN_ERR "%s: unknown output power db revision:%x\n",
- wiphy_name(dev->wiphy), data[0]);
- return -EINVAL;
- }
-
- if (2 + data[1] * sizeof(struct pda_channel_output_limit) > len)
- return -EINVAL;
-
- priv->output_limit = kmalloc(data[1] *
- sizeof(struct pda_channel_output_limit) +
- sizeof(*priv->output_limit), GFP_KERNEL);
-
- if (!priv->output_limit)
- return -ENOMEM;
-
- priv->output_limit->offset = 0;
- priv->output_limit->entries = data[1];
- priv->output_limit->entry_size =
- sizeof(struct pda_channel_output_limit);
- priv->output_limit->len = priv->output_limit->entry_size *
- priv->output_limit->entries +
- priv->output_limit->offset;
-
- memcpy(priv->output_limit->data, &data[2],
- data[1] * sizeof(struct pda_channel_output_limit));
-
- return 0;
-}
-
-static struct p54_cal_database *p54_convert_db(struct pda_custom_wrapper *src,
- size_t total_len)
-{
- struct p54_cal_database *dst;
- size_t payload_len, entries, entry_size, offset;
-
- payload_len = le16_to_cpu(src->len);
- entries = le16_to_cpu(src->entries);
- entry_size = le16_to_cpu(src->entry_size);
- offset = le16_to_cpu(src->offset);
- if (((entries * entry_size + offset) != payload_len) ||
- (payload_len + sizeof(*src) != total_len))
- return NULL;
-
- dst = kmalloc(sizeof(*dst) + payload_len, GFP_KERNEL);
- if (!dst)
- return NULL;
-
- dst->entries = entries;
- dst->entry_size = entry_size;
- dst->offset = offset;
- dst->len = payload_len;
-
- memcpy(dst->data, src->data, payload_len);
- return dst;
-}
-
-int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len)
-{
- struct p54_common *priv = dev->priv;
- struct eeprom_pda_wrap *wrap = NULL;
- struct pda_entry *entry;
- unsigned int data_len, entry_len;
- void *tmp;
- int err;
- u8 *end = (u8 *)eeprom + len;
- u16 synth = 0;
-
- wrap = (struct eeprom_pda_wrap *) eeprom;
- entry = (void *)wrap->data + le16_to_cpu(wrap->len);
-
- /* verify that at least the entry length/code fits */
- while ((u8 *)entry <= end - sizeof(*entry)) {
- entry_len = le16_to_cpu(entry->len);
- data_len = ((entry_len - 1) << 1);
-
- /* abort if entry exceeds whole structure */
- if ((u8 *)entry + sizeof(*entry) + data_len > end)
- break;
-
- switch (le16_to_cpu(entry->code)) {
- case PDR_MAC_ADDRESS:
- if (data_len != ETH_ALEN)
- break;
- SET_IEEE80211_PERM_ADDR(dev, entry->data);
- break;
- case PDR_PRISM_PA_CAL_OUTPUT_POWER_LIMITS:
- if (priv->output_limit)
- break;
- err = p54_convert_output_limits(dev, entry->data,
- data_len);
- if (err)
- goto err;
- break;
- case PDR_PRISM_PA_CAL_CURVE_DATA: {
- struct pda_pa_curve_data *curve_data =
- (struct pda_pa_curve_data *)entry->data;
- if (data_len < sizeof(*curve_data)) {
- err = -EINVAL;
- goto err;
- }
-
- switch (curve_data->cal_method_rev) {
- case 0:
- err = p54_convert_rev0(dev, curve_data);
- break;
- case 1:
- err = p54_convert_rev1(dev, curve_data);
- break;
- default:
- printk(KERN_ERR "%s: unknown curve data "
- "revision %d\n",
- wiphy_name(dev->wiphy),
- curve_data->cal_method_rev);
- err = -ENODEV;
- break;
- }
- if (err)
- goto err;
- }
- break;
- case PDR_PRISM_ZIF_TX_IQ_CALIBRATION:
- priv->iq_autocal = kmalloc(data_len, GFP_KERNEL);
- if (!priv->iq_autocal) {
- err = -ENOMEM;
- goto err;
- }
-
- memcpy(priv->iq_autocal, entry->data, data_len);
- priv->iq_autocal_len = data_len / sizeof(struct pda_iq_autocal_entry);
- break;
- case PDR_DEFAULT_COUNTRY:
- p54_parse_default_country(dev, entry->data, data_len);
- break;
- case PDR_INTERFACE_LIST:
- tmp = entry->data;
- while ((u8 *)tmp < entry->data + data_len) {
- struct bootrec_exp_if *exp_if = tmp;
- if (le16_to_cpu(exp_if->if_id) == 0xf)
- synth = le16_to_cpu(exp_if->variant);
- tmp += sizeof(struct bootrec_exp_if);
- }
- break;
- case PDR_HARDWARE_PLATFORM_COMPONENT_ID:
- if (data_len < 2)
- break;
- priv->version = *(u8 *)(entry->data + 1);
- break;
- case PDR_RSSI_LINEAR_APPROXIMATION:
- case PDR_RSSI_LINEAR_APPROXIMATION_DUAL_BAND:
- case PDR_RSSI_LINEAR_APPROXIMATION_EXTENDED:
- p54_parse_rssical(dev, entry->data, data_len,
- le16_to_cpu(entry->code));
- break;
- case PDR_RSSI_LINEAR_APPROXIMATION_CUSTOM: {
- __le16 *src = (void *) entry->data;
- s16 *dst = (void *) &priv->rssical_db;
- int i;
-
- if (data_len != sizeof(priv->rssical_db)) {
- err = -EINVAL;
- goto err;
- }
- for (i = 0; i < sizeof(priv->rssical_db) /
- sizeof(*src); i++)
- *(dst++) = (s16) le16_to_cpu(*(src++));
- }
- break;
- case PDR_PRISM_PA_CAL_OUTPUT_POWER_LIMITS_CUSTOM: {
- struct pda_custom_wrapper *pda = (void *) entry->data;
- if (priv->output_limit || data_len < sizeof(*pda))
- break;
- priv->output_limit = p54_convert_db(pda, data_len);
- }
- break;
- case PDR_PRISM_PA_CAL_CURVE_DATA_CUSTOM: {
- struct pda_custom_wrapper *pda = (void *) entry->data;
- if (priv->curve_data || data_len < sizeof(*pda))
- break;
- priv->curve_data = p54_convert_db(pda, data_len);
- }
- break;
- case PDR_END:
- /* make it overrun */
- entry_len = len;
- break;
- case PDR_MANUFACTURING_PART_NUMBER:
- case PDR_PDA_VERSION:
- case PDR_NIC_SERIAL_NUMBER:
- case PDR_REGULATORY_DOMAIN_LIST:
- case PDR_TEMPERATURE_TYPE:
- case PDR_PRISM_PCI_IDENTIFIER:
- case PDR_COUNTRY_INFORMATION:
- case PDR_OEM_NAME:
- case PDR_PRODUCT_NAME:
- case PDR_UTF8_OEM_NAME:
- case PDR_UTF8_PRODUCT_NAME:
- case PDR_COUNTRY_LIST:
- case PDR_ANTENNA_GAIN:
- case PDR_PRISM_INDIGO_PA_CALIBRATION_DATA:
- case PDR_REGULATORY_POWER_LIMITS:
- case PDR_RADIATED_TRANSMISSION_CORRECTION:
- case PDR_PRISM_TX_IQ_CALIBRATION:
- case PDR_BASEBAND_REGISTERS:
- case PDR_PER_CHANNEL_BASEBAND_REGISTERS:
- break;
- default:
- printk(KERN_INFO "%s: unknown eeprom code : 0x%x\n",
- wiphy_name(dev->wiphy),
- le16_to_cpu(entry->code));
- break;
- }
-
- entry = (void *)entry + (entry_len + 1)*2;
- }
-
- if (!synth || !priv->iq_autocal || !priv->output_limit ||
- !priv->curve_data) {
- printk(KERN_ERR "%s: not all required entries found in eeprom!\n",
- wiphy_name(dev->wiphy));
- err = -EINVAL;
- goto err;
- }
-
- priv->rxhw = synth & PDR_SYNTH_FRONTEND_MASK;
- if (priv->rxhw == PDR_SYNTH_FRONTEND_XBOW)
- p54_init_xbow_synth(dev);
- if (!(synth & PDR_SYNTH_24_GHZ_DISABLED))
- dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &band_2GHz;
- if (!(synth & PDR_SYNTH_5_GHZ_DISABLED))
- dev->wiphy->bands[IEEE80211_BAND_5GHZ] = &band_5GHz;
- if ((synth & PDR_SYNTH_RX_DIV_MASK) == PDR_SYNTH_RX_DIV_SUPPORTED)
- priv->rx_diversity_mask = 3;
- if ((synth & PDR_SYNTH_TX_DIV_MASK) == PDR_SYNTH_TX_DIV_SUPPORTED)
- priv->tx_diversity_mask = 3;
-
- if (!is_valid_ether_addr(dev->wiphy->perm_addr)) {
- u8 perm_addr[ETH_ALEN];
-
- printk(KERN_WARNING "%s: Invalid hwaddr! Using randomly generated MAC addr\n",
- wiphy_name(dev->wiphy));
- random_ether_addr(perm_addr);
- SET_IEEE80211_PERM_ADDR(dev, perm_addr);
- }
-
- printk(KERN_INFO "%s: hwaddr %pM, MAC:isl38%02x RF:%s\n",
- wiphy_name(dev->wiphy),
- dev->wiphy->perm_addr,
- priv->version, p54_rf_chips[priv->rxhw]);
-
- return 0;
-
- err:
- if (priv->iq_autocal) {
- kfree(priv->iq_autocal);
- priv->iq_autocal = NULL;
- }
-
- if (priv->output_limit) {
- kfree(priv->output_limit);
- priv->output_limit = NULL;
- }
-
- if (priv->curve_data) {
- kfree(priv->curve_data);
- priv->curve_data = NULL;
- }
-
- printk(KERN_ERR "%s: eeprom parse failed!\n",
- wiphy_name(dev->wiphy));
- return err;
-}
-EXPORT_SYMBOL_GPL(p54_parse_eeprom);
-
-static int p54_rssi_to_dbm(struct ieee80211_hw *dev, int rssi)
-{
- struct p54_common *priv = dev->priv;
- int band = dev->conf.channel->band;
-
- if (priv->rxhw != PDR_SYNTH_FRONTEND_LONGBOW)
- return ((rssi * priv->rssical_db[band].mul) / 64 +
- priv->rssical_db[band].add) / 4;
- else
- /*
- * TODO: find the correct formula
- */
- return ((rssi * priv->rssical_db[band].mul) / 64 +
- priv->rssical_db[band].add) / 4;
-}
-
-static int p54_rx_data(struct ieee80211_hw *dev, struct sk_buff *skb)
-{
- struct p54_common *priv = dev->priv;
- struct p54_rx_data *hdr = (struct p54_rx_data *) skb->data;
- struct ieee80211_rx_status rx_status = {0};
- u16 freq = le16_to_cpu(hdr->freq);
- size_t header_len = sizeof(*hdr);
- u32 tsf32;
- u8 rate = hdr->rate & 0xf;
-
- /*
- * If the device is in a unspecified state we have to
- * ignore all data frames. Else we could end up with a
- * nasty crash.
- */
- if (unlikely(priv->mode == NL80211_IFTYPE_UNSPECIFIED))
- return 0;
-
- if (!(hdr->flags & cpu_to_le16(P54_HDR_FLAG_DATA_IN_FCS_GOOD))) {
- return 0;
- }
-
- if (hdr->decrypt_status == P54_DECRYPT_OK)
- rx_status.flag |= RX_FLAG_DECRYPTED;
- if ((hdr->decrypt_status == P54_DECRYPT_FAIL_MICHAEL) ||
- (hdr->decrypt_status == P54_DECRYPT_FAIL_TKIP))
- rx_status.flag |= RX_FLAG_MMIC_ERROR;
-
- rx_status.signal = p54_rssi_to_dbm(dev, hdr->rssi);
- rx_status.noise = priv->noise;
- if (hdr->rate & 0x10)
- rx_status.flag |= RX_FLAG_SHORTPRE;
- if (dev->conf.channel->band == IEEE80211_BAND_5GHZ)
- rx_status.rate_idx = (rate < 4) ? 0 : rate - 4;
- else
- rx_status.rate_idx = rate;
-
- rx_status.freq = freq;
- rx_status.band = dev->conf.channel->band;
- rx_status.antenna = hdr->antenna;
-
- tsf32 = le32_to_cpu(hdr->tsf32);
- if (tsf32 < priv->tsf_low32)
- priv->tsf_high32++;
- rx_status.mactime = ((u64)priv->tsf_high32) << 32 | tsf32;
- priv->tsf_low32 = tsf32;
-
- rx_status.flag |= RX_FLAG_TSFT;
-
- if (hdr->flags & cpu_to_le16(P54_HDR_FLAG_DATA_ALIGN))
- header_len += hdr->align[0];
-
- skb_pull(skb, header_len);
- skb_trim(skb, le16_to_cpu(hdr->len));
-
- ieee80211_rx_irqsafe(dev, skb, &rx_status);
-
- queue_delayed_work(dev->workqueue, &priv->work,
- msecs_to_jiffies(P54_STATISTICS_UPDATE));
-
- return -1;
-}
-
-static void inline p54_wake_free_queues(struct ieee80211_hw *dev)
-{
- struct p54_common *priv = dev->priv;
- int i;
-
- if (priv->mode == NL80211_IFTYPE_UNSPECIFIED)
- return ;
-
- for (i = 0; i < dev->queues; i++)
- if (priv->tx_stats[i + P54_QUEUE_DATA].len <
- priv->tx_stats[i + P54_QUEUE_DATA].limit)
- ieee80211_wake_queue(dev, i);
-}
-
-void p54_free_skb(struct ieee80211_hw *dev, struct sk_buff *skb)
-{
- struct p54_common *priv = dev->priv;
- struct ieee80211_tx_info *info;
- struct p54_tx_info *range;
- unsigned long flags;
-
- if (unlikely(!skb || !dev || !skb_queue_len(&priv->tx_queue)))
- return;
-
- /*
- * don't try to free an already unlinked skb
- */
- if (unlikely((!skb->next) || (!skb->prev)))
- return;
-
- spin_lock_irqsave(&priv->tx_queue.lock, flags);
- info = IEEE80211_SKB_CB(skb);
- range = (void *)info->rate_driver_data;
- if (skb->prev != (struct sk_buff *)&priv->tx_queue) {
- struct ieee80211_tx_info *ni;
- struct p54_tx_info *mr;
-
- ni = IEEE80211_SKB_CB(skb->prev);
- mr = (struct p54_tx_info *)ni->rate_driver_data;
- }
- if (skb->next != (struct sk_buff *)&priv->tx_queue) {
- struct ieee80211_tx_info *ni;
- struct p54_tx_info *mr;
-
- ni = IEEE80211_SKB_CB(skb->next);
- mr = (struct p54_tx_info *)ni->rate_driver_data;
- }
- __skb_unlink(skb, &priv->tx_queue);
- spin_unlock_irqrestore(&priv->tx_queue.lock, flags);
- dev_kfree_skb_any(skb);
- p54_wake_free_queues(dev);
-}
-EXPORT_SYMBOL_GPL(p54_free_skb);
-
-static struct sk_buff *p54_find_tx_entry(struct ieee80211_hw *dev,
- __le32 req_id)
-{
- struct p54_common *priv = dev->priv;
- struct sk_buff *entry;
- unsigned long flags;
-
- spin_lock_irqsave(&priv->tx_queue.lock, flags);
- entry = priv->tx_queue.next;
- while (entry != (struct sk_buff *)&priv->tx_queue) {
- struct p54_hdr *hdr = (struct p54_hdr *) entry->data;
-
- if (hdr->req_id == req_id) {
- spin_unlock_irqrestore(&priv->tx_queue.lock, flags);
- return entry;
- }
- entry = entry->next;
- }
- spin_unlock_irqrestore(&priv->tx_queue.lock, flags);
- return NULL;
-}
-
-static void p54_rx_frame_sent(struct ieee80211_hw *dev, struct sk_buff *skb)
-{
- struct p54_common *priv = dev->priv;
- struct p54_hdr *hdr = (struct p54_hdr *) skb->data;
- struct p54_frame_sent *payload = (struct p54_frame_sent *) hdr->data;
- struct sk_buff *entry;
- u32 addr = le32_to_cpu(hdr->req_id) - priv->headroom;
- struct p54_tx_info *range = NULL;
- unsigned long flags;
- int count, idx;
-
- spin_lock_irqsave(&priv->tx_queue.lock, flags);
- entry = (struct sk_buff *) priv->tx_queue.next;
- while (entry != (struct sk_buff *)&priv->tx_queue) {
- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(entry);
- struct p54_hdr *entry_hdr;
- struct p54_tx_data *entry_data;
- unsigned int pad = 0, frame_len;
-
- range = (void *)info->rate_driver_data;
- if (range->start_addr != addr) {
- entry = entry->next;
- continue;
- }
-
- if (entry->next != (struct sk_buff *)&priv->tx_queue) {
- struct ieee80211_tx_info *ni;
- struct p54_tx_info *mr;
-
- ni = IEEE80211_SKB_CB(entry->next);
- mr = (struct p54_tx_info *)ni->rate_driver_data;
- }
-
- __skb_unlink(entry, &priv->tx_queue);
-
- frame_len = entry->len;
- entry_hdr = (struct p54_hdr *) entry->data;
- entry_data = (struct p54_tx_data *) entry_hdr->data;
- if (priv->tx_stats[entry_data->hw_queue].len)
- priv->tx_stats[entry_data->hw_queue].len--;
- priv->stats.dot11ACKFailureCount += payload->tries - 1;
- spin_unlock_irqrestore(&priv->tx_queue.lock, flags);
-
- /*
- * Frames in P54_QUEUE_FWSCAN and P54_QUEUE_BEACON are
- * generated by the driver. Therefore tx_status is bogus
- * and we don't want to confuse the mac80211 stack.
- */
- if (unlikely(entry_data->hw_queue < P54_QUEUE_FWSCAN)) {
- if (entry_data->hw_queue == P54_QUEUE_BEACON)
- priv->cached_beacon = NULL;
-
- kfree_skb(entry);
- goto out;
- }
-
- /*
- * Clear manually, ieee80211_tx_info_clear_status would
- * clear the counts too and we need them.
- */
- memset(&info->status.ampdu_ack_len, 0,
- sizeof(struct ieee80211_tx_info) -
- offsetof(struct ieee80211_tx_info, status.ampdu_ack_len));
- BUILD_BUG_ON(offsetof(struct ieee80211_tx_info,
- status.ampdu_ack_len) != 23);
-
- if (entry_hdr->flags & cpu_to_le16(P54_HDR_FLAG_DATA_ALIGN))
- pad = entry_data->align[0];
-
- /* walk through the rates array and adjust the counts */
- count = payload->tries;
- for (idx = 0; idx < 4; idx++) {
- if (count >= info->status.rates[idx].count) {
- count -= info->status.rates[idx].count;
- } else if (count > 0) {
- info->status.rates[idx].count = count;
- count = 0;
- } else {
- info->status.rates[idx].idx = -1;
- info->status.rates[idx].count = 0;
- }
- }
-
- if (!(info->flags & IEEE80211_TX_CTL_NO_ACK) &&
- (!payload->status))
- info->flags |= IEEE80211_TX_STAT_ACK;
- if (payload->status & P54_TX_PSM_CANCELLED)
- info->flags |= IEEE80211_TX_STAT_TX_FILTERED;
- info->status.ack_signal = p54_rssi_to_dbm(dev,
- (int)payload->ack_rssi);
-
- /* Undo all changes to the frame. */
- switch (entry_data->key_type) {
- case P54_CRYPTO_TKIPMICHAEL: {
- u8 *iv = (u8 *)(entry_data->align + pad +
- entry_data->crypt_offset);
-
- /* Restore the original TKIP IV. */
- iv[2] = iv[0];
- iv[0] = iv[1];
- iv[1] = (iv[0] | 0x20) & 0x7f; /* WEPSeed - 8.3.2.2 */
-
- frame_len -= 12; /* remove TKIP_MMIC + TKIP_ICV */
- break;
- }
- case P54_CRYPTO_AESCCMP:
- frame_len -= 8; /* remove CCMP_MIC */
- break;
- case P54_CRYPTO_WEP:
- frame_len -= 4; /* remove WEP_ICV */
- break;
- }
- skb_trim(entry, frame_len);
- skb_pull(entry, sizeof(*hdr) + pad + sizeof(*entry_data));
- ieee80211_tx_status_irqsafe(dev, entry);
- goto out;
- }
- spin_unlock_irqrestore(&priv->tx_queue.lock, flags);
-
-out:
- p54_wake_free_queues(dev);
-}
-
-static void p54_rx_eeprom_readback(struct ieee80211_hw *dev,
- struct sk_buff *skb)
-{
- struct p54_hdr *hdr = (struct p54_hdr *) skb->data;
- struct p54_eeprom_lm86 *eeprom = (struct p54_eeprom_lm86 *) hdr->data;
- struct p54_common *priv = dev->priv;
-
- if (!priv->eeprom)
- return ;
-
- if (priv->fw_var >= 0x509) {
- memcpy(priv->eeprom, eeprom->v2.data,
- le16_to_cpu(eeprom->v2.len));
- } else {
- memcpy(priv->eeprom, eeprom->v1.data,
- le16_to_cpu(eeprom->v1.len));
- }
-
- complete(&priv->eeprom_comp);
-}
-
-static void p54_rx_stats(struct ieee80211_hw *dev, struct sk_buff *skb)
-{
- struct p54_common *priv = dev->priv;
- struct p54_hdr *hdr = (struct p54_hdr *) skb->data;
- struct p54_statistics *stats = (struct p54_statistics *) hdr->data;
- u32 tsf32;
-
- if (unlikely(priv->mode == NL80211_IFTYPE_UNSPECIFIED))
- return ;
-
- tsf32 = le32_to_cpu(stats->tsf32);
- if (tsf32 < priv->tsf_low32)
- priv->tsf_high32++;
- priv->tsf_low32 = tsf32;
-
- priv->stats.dot11RTSFailureCount = le32_to_cpu(stats->rts_fail);
- priv->stats.dot11RTSSuccessCount = le32_to_cpu(stats->rts_success);
- priv->stats.dot11FCSErrorCount = le32_to_cpu(stats->rx_bad_fcs);
-
- priv->noise = p54_rssi_to_dbm(dev, le32_to_cpu(stats->noise));
-
- p54_free_skb(dev, p54_find_tx_entry(dev, hdr->req_id));
-}
-
-static void p54_rx_trap(struct ieee80211_hw *dev, struct sk_buff *skb)
-{
- struct p54_common *priv = dev->priv;
- struct p54_hdr *hdr = (struct p54_hdr *) skb->data;
- struct p54_trap *trap = (struct p54_trap *) hdr->data;
- u16 event = le16_to_cpu(trap->event);
- u16 freq = le16_to_cpu(trap->frequency);
-
- switch (event) {
- case P54_TRAP_BEACON_TX:
- break;
- case P54_TRAP_RADAR:
- printk(KERN_INFO "%s: radar (freq:%d MHz)\n",
- wiphy_name(dev->wiphy), freq);
- break;
- case P54_TRAP_NO_BEACON:
- if (priv->vif)
- ieee80211_beacon_loss(priv->vif);
- break;
- case P54_TRAP_SCAN:
- break;
- case P54_TRAP_TBTT:
- break;
- case P54_TRAP_TIMER:
- break;
- default:
- printk(KERN_INFO "%s: received event:%x freq:%d\n",
- wiphy_name(dev->wiphy), event, freq);
- break;
- }
-}
-
-static int p54_rx_control(struct ieee80211_hw *dev, struct sk_buff *skb)
-{
- struct p54_hdr *hdr = (struct p54_hdr *) skb->data;
-
- switch (le16_to_cpu(hdr->type)) {
- case P54_CONTROL_TYPE_TXDONE:
- p54_rx_frame_sent(dev, skb);
- break;
- case P54_CONTROL_TYPE_TRAP:
- p54_rx_trap(dev, skb);
- break;
- case P54_CONTROL_TYPE_BBP:
- break;
- case P54_CONTROL_TYPE_STAT_READBACK:
- p54_rx_stats(dev, skb);
- break;
- case P54_CONTROL_TYPE_EEPROM_READBACK:
- p54_rx_eeprom_readback(dev, skb);
- break;
- default:
- printk(KERN_DEBUG "%s: not handling 0x%02x type control frame\n",
- wiphy_name(dev->wiphy), le16_to_cpu(hdr->type));
- break;
- }
-
- return 0;
-}
-
-/* returns zero if skb can be reused */
-int p54_rx(struct ieee80211_hw *dev, struct sk_buff *skb)
-{
- u16 type = le16_to_cpu(*((__le16 *)skb->data));
-
- if (type & P54_HDR_FLAG_CONTROL)
- return p54_rx_control(dev, skb);
- else
- return p54_rx_data(dev, skb);
-}
-EXPORT_SYMBOL_GPL(p54_rx);
-
-/*
- * So, the firmware is somewhat stupid and doesn't know what places in its
- * memory incoming data should go to. By poking around in the firmware, we
- * can find some unused memory to upload our packets to. However, data that we
- * want the card to TX needs to stay intact until the card has told us that
- * it is done with it. This function finds empty places we can upload to and
- * marks allocated areas as reserved if necessary. p54_rx_frame_sent or
- * p54_free_skb frees allocated areas.
- */
-static int p54_assign_address(struct ieee80211_hw *dev, struct sk_buff *skb,
- struct p54_hdr *data, u32 len)
-{
- struct p54_common *priv = dev->priv;
- struct sk_buff *entry;
- struct sk_buff *target_skb = NULL;
- struct ieee80211_tx_info *info;
- struct p54_tx_info *range;
- u32 last_addr = priv->rx_start;
- u32 largest_hole = 0;
- u32 target_addr = priv->rx_start;
- unsigned long flags;
- unsigned int left;
- len = (len + priv->headroom + priv->tailroom + 3) & ~0x3;
-
- if (!skb)
- return -EINVAL;
-
- spin_lock_irqsave(&priv->tx_queue.lock, flags);
-
- left = skb_queue_len(&priv->tx_queue);
- if (unlikely(left >= 28)) {
- /*
- * The tx_queue is nearly full!
- * We have throttle normal data traffic, because we must
- * have a few spare slots for control frames left.
- */
- ieee80211_stop_queues(dev);
- queue_delayed_work(dev->workqueue, &priv->work,
- msecs_to_jiffies(P54_TX_TIMEOUT));
-
- if (unlikely(left == 32)) {
- /*
- * The tx_queue is now really full.
- *
- * TODO: check if the device has crashed and reset it.
- */
- spin_unlock_irqrestore(&priv->tx_queue.lock, flags);
- return -ENOSPC;
- }
- }
-
- entry = priv->tx_queue.next;
- while (left--) {
- u32 hole_size;
- info = IEEE80211_SKB_CB(entry);
- range = (void *)info->rate_driver_data;
- hole_size = range->start_addr - last_addr;
- if (!target_skb && hole_size >= len) {
- target_skb = entry->prev;
- hole_size -= len;
- target_addr = last_addr;
- }
- largest_hole = max(largest_hole, hole_size);
- last_addr = range->end_addr;
- entry = entry->next;
- }
- if (!target_skb && priv->rx_end - last_addr >= len) {
- target_skb = priv->tx_queue.prev;
- largest_hole = max(largest_hole, priv->rx_end - last_addr - len);
- if (!skb_queue_empty(&priv->tx_queue)) {
- info = IEEE80211_SKB_CB(target_skb);
- range = (void *)info->rate_driver_data;
- target_addr = range->end_addr;
- }
- } else
- largest_hole = max(largest_hole, priv->rx_end - last_addr);
-
- if (!target_skb) {
- spin_unlock_irqrestore(&priv->tx_queue.lock, flags);
- ieee80211_stop_queues(dev);
- return -ENOSPC;
- }
-
- info = IEEE80211_SKB_CB(skb);
- range = (void *)info->rate_driver_data;
- range->start_addr = target_addr;
- range->end_addr = target_addr + len;
- __skb_queue_after(&priv->tx_queue, target_skb, skb);
- spin_unlock_irqrestore(&priv->tx_queue.lock, flags);
-
- if (largest_hole < priv->headroom + sizeof(struct p54_hdr) +
- 48 + IEEE80211_MAX_RTS_THRESHOLD + priv->tailroom)
- ieee80211_stop_queues(dev);
-
- data->req_id = cpu_to_le32(target_addr + priv->headroom);
- return 0;
-}
-
-static struct sk_buff *p54_alloc_skb(struct ieee80211_hw *dev, u16 hdr_flags,
- u16 payload_len, u16 type, gfp_t memflags)
-{
- struct p54_common *priv = dev->priv;
- struct p54_hdr *hdr;
- struct sk_buff *skb;
- size_t frame_len = sizeof(*hdr) + payload_len;
-
- if (frame_len > P54_MAX_CTRL_FRAME_LEN)
- return NULL;
-
- skb = __dev_alloc_skb(priv->tx_hdr_len + frame_len, memflags);
- if (!skb)
- return NULL;
- skb_reserve(skb, priv->tx_hdr_len);
-
- hdr = (struct p54_hdr *) skb_put(skb, sizeof(*hdr));
- hdr->flags = cpu_to_le16(hdr_flags);
- hdr->len = cpu_to_le16(payload_len);
- hdr->type = cpu_to_le16(type);
- hdr->tries = hdr->rts_tries = 0;
-
- if (p54_assign_address(dev, skb, hdr, frame_len)) {
- kfree_skb(skb);
- return NULL;
- }
- return skb;
-}
-
-int p54_read_eeprom(struct ieee80211_hw *dev)
-{
- struct p54_common *priv = dev->priv;
- struct p54_eeprom_lm86 *eeprom_hdr;
- struct sk_buff *skb;
- size_t eeprom_size = 0x2020, offset = 0, blocksize, maxblocksize;
- int ret = -ENOMEM;
- void *eeprom = NULL;
-
- maxblocksize = EEPROM_READBACK_LEN;
- if (priv->fw_var >= 0x509)
- maxblocksize -= 0xc;
- else
- maxblocksize -= 0x4;
-
- skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL, sizeof(*eeprom_hdr) +
- maxblocksize, P54_CONTROL_TYPE_EEPROM_READBACK,
- GFP_KERNEL);
- if (!skb)
- goto free;
- priv->eeprom = kzalloc(EEPROM_READBACK_LEN, GFP_KERNEL);
- if (!priv->eeprom)
- goto free;
- eeprom = kzalloc(eeprom_size, GFP_KERNEL);
- if (!eeprom)
- goto free;
-
- eeprom_hdr = (struct p54_eeprom_lm86 *) skb_put(skb,
- sizeof(*eeprom_hdr) + maxblocksize);
-
- while (eeprom_size) {
- blocksize = min(eeprom_size, maxblocksize);
- if (priv->fw_var < 0x509) {
- eeprom_hdr->v1.offset = cpu_to_le16(offset);
- eeprom_hdr->v1.len = cpu_to_le16(blocksize);
- } else {
- eeprom_hdr->v2.offset = cpu_to_le32(offset);
- eeprom_hdr->v2.len = cpu_to_le16(blocksize);
- eeprom_hdr->v2.magic2 = 0xf;
- memcpy(eeprom_hdr->v2.magic, (const char *)"LOCK", 4);
- }
- priv->tx(dev, skb);
-
- if (!wait_for_completion_interruptible_timeout(&priv->eeprom_comp, HZ)) {
- printk(KERN_ERR "%s: device does not respond!\n",
- wiphy_name(dev->wiphy));
- ret = -EBUSY;
- goto free;
- }
-
- memcpy(eeprom + offset, priv->eeprom, blocksize);
- offset += blocksize;
- eeprom_size -= blocksize;
- }
-
- ret = p54_parse_eeprom(dev, eeprom, offset);
-free:
- kfree(priv->eeprom);
- priv->eeprom = NULL;
- p54_free_skb(dev, skb);
- kfree(eeprom);
-
- return ret;
-}
-EXPORT_SYMBOL_GPL(p54_read_eeprom);
-
-static int p54_set_tim(struct ieee80211_hw *dev, struct ieee80211_sta *sta,
- bool set)
-{
- struct p54_common *priv = dev->priv;
- struct sk_buff *skb;
- struct p54_tim *tim;
-
- skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*tim),
- P54_CONTROL_TYPE_TIM, GFP_ATOMIC);
- if (!skb)
- return -ENOMEM;
-
- tim = (struct p54_tim *) skb_put(skb, sizeof(*tim));
- tim->count = 1;
- tim->entry[0] = cpu_to_le16(set ? (sta->aid | 0x8000) : sta->aid);
- priv->tx(dev, skb);
- return 0;
-}
-
-static int p54_sta_unlock(struct ieee80211_hw *dev, u8 *addr)
-{
- struct p54_common *priv = dev->priv;
- struct sk_buff *skb;
- struct p54_sta_unlock *sta;
-
- skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*sta),
- P54_CONTROL_TYPE_PSM_STA_UNLOCK, GFP_ATOMIC);
- if (!skb)
- return -ENOMEM;
-
- sta = (struct p54_sta_unlock *)skb_put(skb, sizeof(*sta));
- memcpy(sta->addr, addr, ETH_ALEN);
- priv->tx(dev, skb);
- return 0;
-}
-
-static void p54_sta_notify(struct ieee80211_hw *dev, struct ieee80211_vif *vif,
- enum sta_notify_cmd notify_cmd,
- struct ieee80211_sta *sta)
-{
- switch (notify_cmd) {
- case STA_NOTIFY_ADD:
- case STA_NOTIFY_REMOVE:
- /*
- * Notify the firmware that we don't want or we don't
- * need to buffer frames for this station anymore.
- */
-
- p54_sta_unlock(dev, sta->addr);
- break;
- case STA_NOTIFY_AWAKE:
- /* update the firmware's filter table */
- p54_sta_unlock(dev, sta->addr);
- break;
- default:
- break;
- }
-}
-
-static int p54_tx_cancel(struct ieee80211_hw *dev, struct sk_buff *entry)
-{
- struct p54_common *priv = dev->priv;
- struct sk_buff *skb;
- struct p54_hdr *hdr;
- struct p54_txcancel *cancel;
-
- skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*cancel),
- P54_CONTROL_TYPE_TXCANCEL, GFP_ATOMIC);
- if (!skb)
- return -ENOMEM;
-
- hdr = (void *)entry->data;
- cancel = (struct p54_txcancel *)skb_put(skb, sizeof(*cancel));
- cancel->req_id = hdr->req_id;
- priv->tx(dev, skb);
- return 0;
-}
-
-static int p54_tx_fill(struct ieee80211_hw *dev, struct sk_buff *skb,
- struct ieee80211_tx_info *info, u8 *queue, size_t *extra_len,
- u16 *flags, u16 *aid)
-{
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
- struct p54_common *priv = dev->priv;
- int ret = 1;
-
- switch (priv->mode) {
- case NL80211_IFTYPE_MONITOR:
- /*
- * We have to set P54_HDR_FLAG_DATA_OUT_PROMISC for
- * every frame in promiscuous/monitor mode.
- * see STSW45x0C LMAC API - page 12.
- */
- *aid = 0;
- *flags = P54_HDR_FLAG_DATA_OUT_PROMISC;
- *queue += P54_QUEUE_DATA;
- break;
- case NL80211_IFTYPE_STATION:
- *aid = 1;
- if (unlikely(ieee80211_is_mgmt(hdr->frame_control))) {
- *queue = P54_QUEUE_MGMT;
- ret = 0;
- } else
- *queue += P54_QUEUE_DATA;
- break;
- case NL80211_IFTYPE_AP:
- case NL80211_IFTYPE_ADHOC:
- case NL80211_IFTYPE_MESH_POINT:
- if (info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) {
- *aid = 0;
- *queue = P54_QUEUE_CAB;
- return 0;
- }
-
- if (unlikely(ieee80211_is_mgmt(hdr->frame_control))) {
- if (ieee80211_is_probe_resp(hdr->frame_control)) {
- *aid = 0;
- *queue = P54_QUEUE_MGMT;
- *flags = P54_HDR_FLAG_DATA_OUT_TIMESTAMP |
- P54_HDR_FLAG_DATA_OUT_NOCANCEL;
- return 0;
- } else if (ieee80211_is_beacon(hdr->frame_control)) {
- *aid = 0;
-
- if (info->flags & IEEE80211_TX_CTL_INJECTED) {
- /*
- * Injecting beacons on top of a AP is
- * not a good idea... nevertheless,
- * it should be doable.
- */
-
- *queue += P54_QUEUE_DATA;
- return 1;
- }
-
- *flags = P54_HDR_FLAG_DATA_OUT_TIMESTAMP;
- *queue = P54_QUEUE_BEACON;
- *extra_len = IEEE80211_MAX_TIM_LEN;
- return 0;
- } else {
- *queue = P54_QUEUE_MGMT;
- ret = 0;
- }
- } else
- *queue += P54_QUEUE_DATA;
-
- if (info->control.sta)
- *aid = info->control.sta->aid;
-
- if (info->flags & IEEE80211_TX_CTL_CLEAR_PS_FILT)
- *flags |= P54_HDR_FLAG_DATA_OUT_NOCANCEL;
- break;
- }
- return ret;
-}
-
-static u8 p54_convert_algo(enum ieee80211_key_alg alg)
-{
- switch (alg) {
- case ALG_WEP:
- return P54_CRYPTO_WEP;
- case ALG_TKIP:
- return P54_CRYPTO_TKIPMICHAEL;
- case ALG_CCMP:
- return P54_CRYPTO_AESCCMP;
- default:
- return 0;
- }
-}
-
-static int p54_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
-{
- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
- struct ieee80211_tx_queue_stats *current_queue;
- struct p54_common *priv = dev->priv;
- struct p54_hdr *hdr;
- struct p54_tx_data *txhdr;
- size_t padding, len, tim_len = 0;
- int i, j, ridx, ret;
- u16 hdr_flags = 0, aid = 0;
- u8 rate, queue, crypt_offset = 0;
- u8 cts_rate = 0x20;
- u8 rc_flags;
- u8 calculated_tries[4];
- u8 nrates = 0, nremaining = 8;
-
- queue = skb_get_queue_mapping(skb);
-
- ret = p54_tx_fill(dev, skb, info, &queue, &tim_len, &hdr_flags, &aid);
- current_queue = &priv->tx_stats[queue];
- if (unlikely((current_queue->len > current_queue->limit) && ret))
- return NETDEV_TX_BUSY;
- current_queue->len++;
- current_queue->count++;
- if ((current_queue->len == current_queue->limit) && ret)
- ieee80211_stop_queue(dev, skb_get_queue_mapping(skb));
-
- padding = (unsigned long)(skb->data - (sizeof(*hdr) + sizeof(*txhdr))) & 3;
- len = skb->len;
-
- if (info->control.hw_key) {
- crypt_offset = ieee80211_get_hdrlen_from_skb(skb);
- if (info->control.hw_key->alg == ALG_TKIP) {
- u8 *iv = (u8 *)(skb->data + crypt_offset);
- /*
- * The firmware excepts that the IV has to have
- * this special format
- */
- iv[1] = iv[0];
- iv[0] = iv[2];
- iv[2] = 0;
- }
- }
-
- txhdr = (struct p54_tx_data *) skb_push(skb, sizeof(*txhdr) + padding);
- hdr = (struct p54_hdr *) skb_push(skb, sizeof(*hdr));
-
- if (padding)
- hdr_flags |= P54_HDR_FLAG_DATA_ALIGN;
- hdr->type = cpu_to_le16(aid);
- hdr->rts_tries = info->control.rates[0].count;
-
- /*
- * we register the rates in perfect order, and
- * RTS/CTS won't happen on 5 GHz
- */
- cts_rate = info->control.rts_cts_rate_idx;
-
- memset(&txhdr->rateset, 0, sizeof(txhdr->rateset));
-
- /* see how many rates got used */
- for (i = 0; i < 4; i++) {
- if (info->control.rates[i].idx < 0)
- break;
- nrates++;
- }
-
- /* limit tries to 8/nrates per rate */
- for (i = 0; i < nrates; i++) {
- /*
- * The magic expression here is equivalent to 8/nrates for
- * all values that matter, but avoids division and jumps.
- * Note that nrates can only take the values 1 through 4.
- */
- calculated_tries[i] = min_t(int, ((15 >> nrates) | 1) + 1,
- info->control.rates[i].count);
- nremaining -= calculated_tries[i];
- }
-
- /* if there are tries left, distribute from back to front */
- for (i = nrates - 1; nremaining > 0 && i >= 0; i--) {
- int tmp = info->control.rates[i].count - calculated_tries[i];
-
- if (tmp <= 0)
- continue;
- /* RC requested more tries at this rate */
-
- tmp = min_t(int, tmp, nremaining);
- calculated_tries[i] += tmp;
- nremaining -= tmp;
- }
-
- ridx = 0;
- for (i = 0; i < nrates && ridx < 8; i++) {
- /* we register the rates in perfect order */
- rate = info->control.rates[i].idx;
- if (info->band == IEEE80211_BAND_5GHZ)
- rate += 4;
-
- /* store the count we actually calculated for TX status */
- info->control.rates[i].count = calculated_tries[i];
-
- rc_flags = info->control.rates[i].flags;
- if (rc_flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) {
- rate |= 0x10;
- cts_rate |= 0x10;
- }
- if (rc_flags & IEEE80211_TX_RC_USE_RTS_CTS)
- rate |= 0x40;
- else if (rc_flags & IEEE80211_TX_RC_USE_CTS_PROTECT)
- rate |= 0x20;
- for (j = 0; j < calculated_tries[i] && ridx < 8; j++) {
- txhdr->rateset[ridx] = rate;
- ridx++;
- }
- }
-
- if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ)
- hdr_flags |= P54_HDR_FLAG_DATA_OUT_SEQNR;
-
- /* TODO: enable bursting */
- hdr->flags = cpu_to_le16(hdr_flags);
- hdr->tries = ridx;
- txhdr->rts_rate_idx = 0;
- if (info->control.hw_key) {
- txhdr->key_type = p54_convert_algo(info->control.hw_key->alg);
- txhdr->key_len = min((u8)16, info->control.hw_key->keylen);
- memcpy(txhdr->key, info->control.hw_key->key, txhdr->key_len);
- if (info->control.hw_key->alg == ALG_TKIP) {
- if (unlikely(skb_tailroom(skb) < 12))
- goto err;
- /* reserve space for the MIC key */
- len += 8;
- memcpy(skb_put(skb, 8), &(info->control.hw_key->key
- [NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY]), 8);
- }
- /* reserve some space for ICV */
- len += info->control.hw_key->icv_len;
- memset(skb_put(skb, info->control.hw_key->icv_len), 0,
- info->control.hw_key->icv_len);
- } else {
- txhdr->key_type = 0;
- txhdr->key_len = 0;
- }
- txhdr->crypt_offset = crypt_offset;
- txhdr->hw_queue = queue;
- txhdr->backlog = current_queue->len;
- memset(txhdr->durations, 0, sizeof(txhdr->durations));
- txhdr->tx_antenna = ((info->antenna_sel_tx == 0) ?
- 2 : info->antenna_sel_tx - 1) & priv->tx_diversity_mask;
- if (priv->rxhw == PDR_SYNTH_FRONTEND_LONGBOW) {
- txhdr->longbow.cts_rate = cts_rate;
- txhdr->longbow.output_power = cpu_to_le16(priv->output_power);
- } else {
- txhdr->normal.output_power = priv->output_power;
- txhdr->normal.cts_rate = cts_rate;
- }
- if (padding)
- txhdr->align[0] = padding;
-
- hdr->len = cpu_to_le16(len);
- /* modifies skb->cb and with it info, so must be last! */
- if (unlikely(p54_assign_address(dev, skb, hdr, skb->len + tim_len)))
- goto err;
- priv->tx(dev, skb);
-
- queue_delayed_work(dev->workqueue, &priv->work,
- msecs_to_jiffies(P54_TX_FRAME_LIFETIME));
-
- return NETDEV_TX_OK;
-
- err:
- skb_pull(skb, sizeof(*hdr) + sizeof(*txhdr) + padding);
- current_queue->len--;
- current_queue->count--;
- return NETDEV_TX_BUSY;
-}
-
-static int p54_setup_mac(struct ieee80211_hw *dev)
-{
- struct p54_common *priv = dev->priv;
- struct sk_buff *skb;
- struct p54_setup_mac *setup;
- u16 mode;
-
- skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*setup),
- P54_CONTROL_TYPE_SETUP, GFP_ATOMIC);
- if (!skb)
- return -ENOMEM;
-
- setup = (struct p54_setup_mac *) skb_put(skb, sizeof(*setup));
- if (dev->conf.radio_enabled) {
- switch (priv->mode) {
- case NL80211_IFTYPE_STATION:
- mode = P54_FILTER_TYPE_STATION;
- break;
- case NL80211_IFTYPE_AP:
- mode = P54_FILTER_TYPE_AP;
- break;
- case NL80211_IFTYPE_ADHOC:
- case NL80211_IFTYPE_MESH_POINT:
- mode = P54_FILTER_TYPE_IBSS;
- break;
- case NL80211_IFTYPE_MONITOR:
- mode = P54_FILTER_TYPE_PROMISCUOUS;
- break;
- default:
- mode = P54_FILTER_TYPE_HIBERNATE;
- break;
- }
-
- /*
- * "TRANSPARENT and PROMISCUOUS are mutually exclusive"
- * STSW45X0C LMAC API - page 12
- */
- if (((priv->filter_flags & FIF_PROMISC_IN_BSS) ||
- (priv->filter_flags & FIF_OTHER_BSS)) &&
- (mode != P54_FILTER_TYPE_PROMISCUOUS))
- mode |= P54_FILTER_TYPE_TRANSPARENT;
- } else
- mode = P54_FILTER_TYPE_HIBERNATE;
-
- setup->mac_mode = cpu_to_le16(mode);
- memcpy(setup->mac_addr, priv->mac_addr, ETH_ALEN);
- memcpy(setup->bssid, priv->bssid, ETH_ALEN);
- setup->rx_antenna = 2 & priv->rx_diversity_mask; /* automatic */
- setup->rx_align = 0;
- if (priv->fw_var < 0x500) {
- setup->v1.basic_rate_mask = cpu_to_le32(priv->basic_rate_mask);
- memset(setup->v1.rts_rates, 0, 8);
- setup->v1.rx_addr = cpu_to_le32(priv->rx_end);
- setup->v1.max_rx = cpu_to_le16(priv->rx_mtu);
- setup->v1.rxhw = cpu_to_le16(priv->rxhw);
- setup->v1.wakeup_timer = cpu_to_le16(priv->wakeup_timer);
- setup->v1.unalloc0 = cpu_to_le16(0);
- } else {
- setup->v2.rx_addr = cpu_to_le32(priv->rx_end);
- setup->v2.max_rx = cpu_to_le16(priv->rx_mtu);
- setup->v2.rxhw = cpu_to_le16(priv->rxhw);
- setup->v2.timer = cpu_to_le16(priv->wakeup_timer);
- setup->v2.truncate = cpu_to_le16(48896);
- setup->v2.basic_rate_mask = cpu_to_le32(priv->basic_rate_mask);
- setup->v2.sbss_offset = 0;
- setup->v2.mcast_window = 0;
- setup->v2.rx_rssi_threshold = 0;
- setup->v2.rx_ed_threshold = 0;
- setup->v2.ref_clock = cpu_to_le32(644245094);
- setup->v2.lpf_bandwidth = cpu_to_le16(65535);
- setup->v2.osc_start_delay = cpu_to_le16(65535);
- }
- priv->tx(dev, skb);
- return 0;
-}
-
-static int p54_scan(struct ieee80211_hw *dev, u16 mode, u16 dwell)
-{
- struct p54_common *priv = dev->priv;
- struct sk_buff *skb;
- struct p54_hdr *hdr;
- struct p54_scan_head *head;
- struct p54_iq_autocal_entry *iq_autocal;
- union p54_scan_body_union *body;
- struct p54_scan_tail_rate *rate;
- struct pda_rssi_cal_entry *rssi;
- unsigned int i;
- void *entry;
- int band = dev->conf.channel->band;
- __le16 freq = cpu_to_le16(dev->conf.channel->center_freq);
-
- skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*head) +
- 2 + sizeof(*iq_autocal) + sizeof(*body) +
- sizeof(*rate) + 2 * sizeof(*rssi),
- P54_CONTROL_TYPE_SCAN, GFP_ATOMIC);
- if (!skb)
- return -ENOMEM;
-
- head = (struct p54_scan_head *) skb_put(skb, sizeof(*head));
- memset(head->scan_params, 0, sizeof(head->scan_params));
- head->mode = cpu_to_le16(mode);
- head->dwell = cpu_to_le16(dwell);
- head->freq = freq;
-
- if (priv->rxhw == PDR_SYNTH_FRONTEND_LONGBOW) {
- __le16 *pa_power_points = (__le16 *) skb_put(skb, 2);
- *pa_power_points = cpu_to_le16(0x0c);
- }
-
- iq_autocal = (void *) skb_put(skb, sizeof(*iq_autocal));
- for (i = 0; i < priv->iq_autocal_len; i++) {
- if (priv->iq_autocal[i].freq != freq)
- continue;
-
- memcpy(iq_autocal, &priv->iq_autocal[i].params,
- sizeof(struct p54_iq_autocal_entry));
- break;
- }
- if (i == priv->iq_autocal_len)
- goto err;
-
- if (priv->rxhw == PDR_SYNTH_FRONTEND_LONGBOW)
- body = (void *) skb_put(skb, sizeof(body->longbow));
- else
- body = (void *) skb_put(skb, sizeof(body->normal));
-
- for (i = 0; i < priv->output_limit->entries; i++) {
- __le16 *entry_freq = (void *) (priv->output_limit->data +
- priv->output_limit->entry_size * i);
-
- if (*entry_freq != freq)
- continue;
-
- if (priv->rxhw == PDR_SYNTH_FRONTEND_LONGBOW) {
- memcpy(&body->longbow.power_limits,
- (void *) entry_freq + sizeof(__le16),
- priv->output_limit->entry_size);
- } else {
- struct pda_channel_output_limit *limits =
- (void *) entry_freq;
-
- body->normal.val_barker = 0x38;
- body->normal.val_bpsk = body->normal.dup_bpsk =
- limits->val_bpsk;
- body->normal.val_qpsk = body->normal.dup_qpsk =
- limits->val_qpsk;
- body->normal.val_16qam = body->normal.dup_16qam =
- limits->val_16qam;
- body->normal.val_64qam = body->normal.dup_64qam =
- limits->val_64qam;
- }
- break;
- }
- if (i == priv->output_limit->entries)
- goto err;
-
- entry = (void *)(priv->curve_data->data + priv->curve_data->offset);
- for (i = 0; i < priv->curve_data->entries; i++) {
- if (*((__le16 *)entry) != freq) {
- entry += priv->curve_data->entry_size;
- continue;
- }
-
- if (priv->rxhw == PDR_SYNTH_FRONTEND_LONGBOW) {
- memcpy(&body->longbow.curve_data,
- (void *) entry + sizeof(__le16),
- priv->curve_data->entry_size);
- } else {
- struct p54_scan_body *chan = &body->normal;
- struct pda_pa_curve_data *curve_data =
- (void *) priv->curve_data->data;
-
- entry += sizeof(__le16);
- chan->pa_points_per_curve = 8;
- memset(chan->curve_data, 0, sizeof(*chan->curve_data));
- memcpy(chan->curve_data, entry,
- sizeof(struct p54_pa_curve_data_sample) *
- min((u8)8, curve_data->points_per_channel));
- }
- break;
- }
- if (i == priv->curve_data->entries)
- goto err;
-
- if ((priv->fw_var >= 0x500) && (priv->fw_var < 0x509)) {
- rate = (void *) skb_put(skb, sizeof(*rate));
- rate->basic_rate_mask = cpu_to_le32(priv->basic_rate_mask);
- for (i = 0; i < sizeof(rate->rts_rates); i++)
- rate->rts_rates[i] = i;
- }
-
- rssi = (struct pda_rssi_cal_entry *) skb_put(skb, sizeof(*rssi));
- rssi->mul = cpu_to_le16(priv->rssical_db[band].mul);
- rssi->add = cpu_to_le16(priv->rssical_db[band].add);
- if (priv->rxhw == PDR_SYNTH_FRONTEND_LONGBOW) {
- /* Longbow frontend needs ever more */
- rssi = (void *) skb_put(skb, sizeof(*rssi));
- rssi->mul = cpu_to_le16(priv->rssical_db[band].longbow_unkn);
- rssi->add = cpu_to_le16(priv->rssical_db[band].longbow_unk2);
- }
-
- if (priv->fw_var >= 0x509) {
- rate = (void *) skb_put(skb, sizeof(*rate));
- rate->basic_rate_mask = cpu_to_le32(priv->basic_rate_mask);
- for (i = 0; i < sizeof(rate->rts_rates); i++)
- rate->rts_rates[i] = i;
- }
-
- hdr = (struct p54_hdr *) skb->data;
- hdr->len = cpu_to_le16(skb->len - sizeof(*hdr));
-
- priv->tx(dev, skb);
- return 0;
-
- err:
- printk(KERN_ERR "%s: frequency change failed\n", wiphy_name(dev->wiphy));
- p54_free_skb(dev, skb);
- return -EINVAL;
-}
-
-static int p54_set_leds(struct ieee80211_hw *dev)
-{
- struct p54_common *priv = dev->priv;
- struct sk_buff *skb;
- struct p54_led *led;
-
- skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*led),
- P54_CONTROL_TYPE_LED, GFP_ATOMIC);
- if (!skb)
- return -ENOMEM;
-
- led = (struct p54_led *) skb_put(skb, sizeof(*led));
- led->flags = cpu_to_le16(0x0003);
- led->mask[0] = led->mask[1] = cpu_to_le16(priv->softled_state);
- led->delay[0] = cpu_to_le16(1);
- led->delay[1] = cpu_to_le16(0);
- priv->tx(dev, skb);
- return 0;
-}
-
-#define P54_SET_QUEUE(queue, ai_fs, cw_min, cw_max, _txop) \
-do { \
- queue.aifs = cpu_to_le16(ai_fs); \
- queue.cwmin = cpu_to_le16(cw_min); \
- queue.cwmax = cpu_to_le16(cw_max); \
- queue.txop = cpu_to_le16(_txop); \
-} while(0)
-
-static int p54_set_edcf(struct ieee80211_hw *dev)
-{
- struct p54_common *priv = dev->priv;
- struct sk_buff *skb;
- struct p54_edcf *edcf;
-
- skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*edcf),
- P54_CONTROL_TYPE_DCFINIT, GFP_ATOMIC);
- if (!skb)
- return -ENOMEM;
-
- edcf = (struct p54_edcf *)skb_put(skb, sizeof(*edcf));
- if (priv->use_short_slot) {
- edcf->slottime = 9;
- edcf->sifs = 0x10;
- edcf->eofpad = 0x00;
- } else {
- edcf->slottime = 20;
- edcf->sifs = 0x0a;
- edcf->eofpad = 0x06;
- }
- /* (see prism54/isl_oid.h for further details) */
- edcf->frameburst = cpu_to_le16(0);
- edcf->round_trip_delay = cpu_to_le16(0);
- edcf->flags = 0;
- memset(edcf->mapping, 0, sizeof(edcf->mapping));
- memcpy(edcf->queue, priv->qos_params, sizeof(edcf->queue));
- priv->tx(dev, skb);
- return 0;
-}
-
-static int p54_set_ps(struct ieee80211_hw *dev)
-{
- struct p54_common *priv = dev->priv;
- struct sk_buff *skb;
- struct p54_psm *psm;
- u16 mode;
- int i;
-
- if (dev->conf.flags & IEEE80211_CONF_PS)
- mode = P54_PSM | P54_PSM_BEACON_TIMEOUT | P54_PSM_DTIM |
- P54_PSM_CHECKSUM | P54_PSM_MCBC;
- else
- mode = P54_PSM_CAM;
-
- skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*psm),
- P54_CONTROL_TYPE_PSM, GFP_ATOMIC);
- if (!skb)
- return -ENOMEM;
-
- psm = (struct p54_psm *)skb_put(skb, sizeof(*psm));
- psm->mode = cpu_to_le16(mode);
- psm->aid = cpu_to_le16(priv->aid);
- for (i = 0; i < ARRAY_SIZE(psm->intervals); i++) {
- psm->intervals[i].interval =
- cpu_to_le16(dev->conf.listen_interval);
- psm->intervals[i].periods = cpu_to_le16(1);
- }
-
- psm->beacon_rssi_skip_max = 200;
- psm->rssi_delta_threshold = 0;
- psm->nr = 10;
- psm->exclude[0] = 0;
-
- priv->tx(dev, skb);
-
- return 0;
-}
-
-static int p54_beacon_tim(struct sk_buff *skb)
-{
- /*
- * the good excuse for this mess is ... the firmware.
- * The dummy TIM MUST be at the end of the beacon frame,
- * because it'll be overwritten!
- */
-
- struct ieee80211_mgmt *mgmt = (void *)skb->data;
- u8 *pos, *end;
-
- if (skb->len <= sizeof(mgmt))
- return -EINVAL;
-
- pos = (u8 *)mgmt->u.beacon.variable;
- end = skb->data + skb->len;
- while (pos < end) {
- if (pos + 2 + pos[1] > end)
- return -EINVAL;
-
- if (pos[0] == WLAN_EID_TIM) {
- u8 dtim_len = pos[1];
- u8 dtim_period = pos[3];
- u8 *next = pos + 2 + dtim_len;
-
- if (dtim_len < 3)
- return -EINVAL;
-
- memmove(pos, next, end - next);
-
- if (dtim_len > 3)
- skb_trim(skb, skb->len - (dtim_len - 3));
-
- pos = end - (dtim_len + 2);
-
- /* add the dummy at the end */
- pos[0] = WLAN_EID_TIM;
- pos[1] = 3;
- pos[2] = 0;
- pos[3] = dtim_period;
- pos[4] = 0;
- return 0;
- }
- pos += 2 + pos[1];
- }
- return 0;
-}
-
-static int p54_beacon_update(struct ieee80211_hw *dev,
- struct ieee80211_vif *vif)
-{
- struct p54_common *priv = dev->priv;
- struct sk_buff *beacon;
- int ret;
-
- if (priv->cached_beacon) {
- p54_tx_cancel(dev, priv->cached_beacon);
- /* wait for the last beacon the be freed */
- msleep(10);
- }
-
- beacon = ieee80211_beacon_get(dev, vif);
- if (!beacon)
- return -ENOMEM;
- ret = p54_beacon_tim(beacon);
- if (ret)
- return ret;
- ret = p54_tx(dev, beacon);
- if (ret)
- return ret;
- priv->cached_beacon = beacon;
- priv->tsf_high32 = 0;
- priv->tsf_low32 = 0;
-
- return 0;
-}
-
-static int p54_start(struct ieee80211_hw *dev)
-{
- struct p54_common *priv = dev->priv;
- int err;
-
- mutex_lock(&priv->conf_mutex);
- err = priv->open(dev);
- if (err)
- goto out;
- P54_SET_QUEUE(priv->qos_params[0], 0x0002, 0x0003, 0x0007, 47);
- P54_SET_QUEUE(priv->qos_params[1], 0x0002, 0x0007, 0x000f, 94);
- P54_SET_QUEUE(priv->qos_params[2], 0x0003, 0x000f, 0x03ff, 0);
- P54_SET_QUEUE(priv->qos_params[3], 0x0007, 0x000f, 0x03ff, 0);
- err = p54_set_edcf(dev);
- if (err)
- goto out;
-
- memset(priv->bssid, ~0, ETH_ALEN);
- priv->mode = NL80211_IFTYPE_MONITOR;
- err = p54_setup_mac(dev);
- if (err) {
- priv->mode = NL80211_IFTYPE_UNSPECIFIED;
- goto out;
- }
-
- queue_delayed_work(dev->workqueue, &priv->work, 0);
-
- priv->softled_state = 0;
- err = p54_set_leds(dev);
-
-out:
- mutex_unlock(&priv->conf_mutex);
- return err;
-}
-
-static void p54_stop(struct ieee80211_hw *dev)
-{
- struct p54_common *priv = dev->priv;
- struct sk_buff *skb;
-
- mutex_lock(&priv->conf_mutex);
- priv->mode = NL80211_IFTYPE_UNSPECIFIED;
- priv->softled_state = 0;
- p54_set_leds(dev);
-
-#ifdef CONFIG_P54_LEDS
- cancel_delayed_work_sync(&priv->led_work);
-#endif /* CONFIG_P54_LEDS */
- cancel_delayed_work_sync(&priv->work);
- if (priv->cached_beacon)
- p54_tx_cancel(dev, priv->cached_beacon);
-
- priv->stop(dev);
- while ((skb = skb_dequeue(&priv->tx_queue)))
- kfree_skb(skb);
- priv->cached_beacon = NULL;
- priv->tsf_high32 = priv->tsf_low32 = 0;
- mutex_unlock(&priv->conf_mutex);
-}
-
-static int p54_add_interface(struct ieee80211_hw *dev,
- struct ieee80211_if_init_conf *conf)
-{
- struct p54_common *priv = dev->priv;
-
- mutex_lock(&priv->conf_mutex);
- if (priv->mode != NL80211_IFTYPE_MONITOR) {
- mutex_unlock(&priv->conf_mutex);
- return -EOPNOTSUPP;
- }
-
- priv->vif = conf->vif;
-
- switch (conf->type) {
- case NL80211_IFTYPE_STATION:
- case NL80211_IFTYPE_ADHOC:
- case NL80211_IFTYPE_AP:
- case NL80211_IFTYPE_MESH_POINT:
- priv->mode = conf->type;
- break;
- default:
- mutex_unlock(&priv->conf_mutex);
- return -EOPNOTSUPP;
- }
-
- memcpy(priv->mac_addr, conf->mac_addr, ETH_ALEN);
- p54_setup_mac(dev);
- mutex_unlock(&priv->conf_mutex);
- return 0;
-}
-
-static void p54_remove_interface(struct ieee80211_hw *dev,
- struct ieee80211_if_init_conf *conf)
-{
- struct p54_common *priv = dev->priv;
-
- mutex_lock(&priv->conf_mutex);
- priv->vif = NULL;
- if (priv->cached_beacon)
- p54_tx_cancel(dev, priv->cached_beacon);
- priv->mode = NL80211_IFTYPE_MONITOR;
- memset(priv->mac_addr, 0, ETH_ALEN);
- memset(priv->bssid, 0, ETH_ALEN);
- p54_setup_mac(dev);
- mutex_unlock(&priv->conf_mutex);
-}
-
-static int p54_config(struct ieee80211_hw *dev, u32 changed)
-{
- int ret = 0;
- struct p54_common *priv = dev->priv;
- struct ieee80211_conf *conf = &dev->conf;
-
- mutex_lock(&priv->conf_mutex);
- if (changed & IEEE80211_CONF_CHANGE_POWER)
- priv->output_power = conf->power_level << 2;
- if (changed & IEEE80211_CONF_CHANGE_RADIO_ENABLED) {
- ret = p54_setup_mac(dev);
- if (ret)
- goto out;
- }
- if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
- ret = p54_scan(dev, P54_SCAN_EXIT, 0);
- if (ret)
- goto out;
- }
- if (changed & IEEE80211_CONF_CHANGE_PS) {
- ret = p54_set_ps(dev);
- if (ret)
- goto out;
- }
-
-out:
- mutex_unlock(&priv->conf_mutex);
- return ret;
-}
-
-static void p54_configure_filter(struct ieee80211_hw *dev,
- unsigned int changed_flags,
- unsigned int *total_flags,
- int mc_count, struct dev_mc_list *mclist)
-{
- struct p54_common *priv = dev->priv;
-
- *total_flags &= FIF_PROMISC_IN_BSS |
- FIF_OTHER_BSS;
-
- priv->filter_flags = *total_flags;
-
- if (changed_flags & (FIF_PROMISC_IN_BSS | FIF_OTHER_BSS))
- p54_setup_mac(dev);
-}
-
-static int p54_conf_tx(struct ieee80211_hw *dev, u16 queue,
- const struct ieee80211_tx_queue_params *params)
-{
- struct p54_common *priv = dev->priv;
- int ret;
-
- mutex_lock(&priv->conf_mutex);
- if ((params) && !(queue > 4)) {
- P54_SET_QUEUE(priv->qos_params[queue], params->aifs,
- params->cw_min, params->cw_max, params->txop);
- ret = p54_set_edcf(dev);
- } else
- ret = -EINVAL;
- mutex_unlock(&priv->conf_mutex);
- return ret;
-}
-
-static int p54_init_xbow_synth(struct ieee80211_hw *dev)
-{
- struct p54_common *priv = dev->priv;
- struct sk_buff *skb;
- struct p54_xbow_synth *xbow;
-
- skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*xbow),
- P54_CONTROL_TYPE_XBOW_SYNTH_CFG, GFP_KERNEL);
- if (!skb)
- return -ENOMEM;
-
- xbow = (struct p54_xbow_synth *)skb_put(skb, sizeof(*xbow));
- xbow->magic1 = cpu_to_le16(0x1);
- xbow->magic2 = cpu_to_le16(0x2);
- xbow->freq = cpu_to_le16(5390);
- memset(xbow->padding, 0, sizeof(xbow->padding));
- priv->tx(dev, skb);
- return 0;
-}
-
-static void p54_work(struct work_struct *work)
-{
- struct p54_common *priv = container_of(work, struct p54_common,
- work.work);
- struct ieee80211_hw *dev = priv->hw;
- struct sk_buff *skb;
-
- if (unlikely(priv->mode == NL80211_IFTYPE_UNSPECIFIED))
- return ;
-
- /*
- * TODO: walk through tx_queue and do the following tasks
- * 1. initiate bursts.
- * 2. cancel stuck frames / reset the device if necessary.
- */
-
- skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL,
- sizeof(struct p54_statistics),
- P54_CONTROL_TYPE_STAT_READBACK, GFP_KERNEL);
- if (!skb)
- return ;
-
- priv->tx(dev, skb);
-}
-
-static int p54_get_stats(struct ieee80211_hw *dev,
- struct ieee80211_low_level_stats *stats)
-{
- struct p54_common *priv = dev->priv;
-
- memcpy(stats, &priv->stats, sizeof(*stats));
- return 0;
-}
-
-static int p54_get_tx_stats(struct ieee80211_hw *dev,
- struct ieee80211_tx_queue_stats *stats)
-{
- struct p54_common *priv = dev->priv;
-
- memcpy(stats, &priv->tx_stats[P54_QUEUE_DATA],
- sizeof(stats[0]) * dev->queues);
- return 0;
-}
-
-static void p54_bss_info_changed(struct ieee80211_hw *dev,
- struct ieee80211_vif *vif,
- struct ieee80211_bss_conf *info,
- u32 changed)
-{
- struct p54_common *priv = dev->priv;
- int ret;
-
- mutex_lock(&priv->conf_mutex);
- if (changed & BSS_CHANGED_BSSID) {
- memcpy(priv->bssid, info->bssid, ETH_ALEN);
- ret = p54_setup_mac(dev);
- if (ret)
- goto out;
- }
-
- if (changed & BSS_CHANGED_BEACON) {
- ret = p54_scan(dev, P54_SCAN_EXIT, 0);
- if (ret)
- goto out;
- ret = p54_setup_mac(dev);
- if (ret)
- goto out;
- ret = p54_beacon_update(dev, vif);
- if (ret)
- goto out;
- }
- /* XXX: this mimics having two callbacks... clean up */
- out:
- mutex_unlock(&priv->conf_mutex);
-
- if (changed & (BSS_CHANGED_ERP_SLOT | BSS_CHANGED_BEACON)) {
- priv->use_short_slot = info->use_short_slot;
- p54_set_edcf(dev);
- }
- if (changed & BSS_CHANGED_BASIC_RATES) {
- if (dev->conf.channel->band == IEEE80211_BAND_5GHZ)
- priv->basic_rate_mask = (info->basic_rates << 4);
- else
- priv->basic_rate_mask = info->basic_rates;
- p54_setup_mac(dev);
- if (priv->fw_var >= 0x500)
- p54_scan(dev, P54_SCAN_EXIT, 0);
- }
- if (changed & BSS_CHANGED_ASSOC) {
- if (info->assoc) {
- priv->aid = info->aid;
- priv->wakeup_timer = info->beacon_int *
- info->dtim_period * 5;
- p54_setup_mac(dev);
- }
- }
-}
-
-static int p54_set_key(struct ieee80211_hw *dev, enum set_key_cmd cmd,
- struct ieee80211_vif *vif, struct ieee80211_sta *sta,
- struct ieee80211_key_conf *key)
-{
- struct p54_common *priv = dev->priv;
- struct sk_buff *skb;
- struct p54_keycache *rxkey;
- int slot, ret = 0;
- u8 algo = 0;
-
- if (modparam_nohwcrypt)
- return -EOPNOTSUPP;
-
- mutex_lock(&priv->conf_mutex);
- if (cmd == SET_KEY) {
- switch (key->alg) {
- case ALG_TKIP:
- if (!(priv->privacy_caps & (BR_DESC_PRIV_CAP_MICHAEL |
- BR_DESC_PRIV_CAP_TKIP))) {
- ret = -EOPNOTSUPP;
- goto out_unlock;
- }
- key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
- algo = P54_CRYPTO_TKIPMICHAEL;
- break;
- case ALG_WEP:
- if (!(priv->privacy_caps & BR_DESC_PRIV_CAP_WEP)) {
- ret = -EOPNOTSUPP;
- goto out_unlock;
- }
- key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
- algo = P54_CRYPTO_WEP;
- break;
- case ALG_CCMP:
- if (!(priv->privacy_caps & BR_DESC_PRIV_CAP_AESCCMP)) {
- ret = -EOPNOTSUPP;
- goto out_unlock;
- }
- key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
- algo = P54_CRYPTO_AESCCMP;
- break;
- default:
- ret = -EOPNOTSUPP;
- goto out_unlock;
- }
- slot = bitmap_find_free_region(priv->used_rxkeys,
- priv->rx_keycache_size, 0);
-
- if (slot < 0) {
- /*
- * The device supports the choosen algorithm, but the
- * firmware does not provide enough key slots to store
- * all of them.
- * But encryption offload for outgoing frames is always
- * possible, so we just pretend that the upload was
- * successful and do the decryption in software.
- */
-
- /* mark the key as invalid. */
- key->hw_key_idx = 0xff;
- goto out_unlock;
- }
- } else {
- slot = key->hw_key_idx;
-
- if (slot == 0xff) {
- /* This key was not uploaded into the rx key cache. */
-
- goto out_unlock;
- }
-
- bitmap_release_region(priv->used_rxkeys, slot, 0);
- algo = 0;
- }
-
- skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*rxkey),
- P54_CONTROL_TYPE_RX_KEYCACHE, GFP_KERNEL);
- if (!skb) {
- bitmap_release_region(priv->used_rxkeys, slot, 0);
- ret = -ENOSPC;
- goto out_unlock;
- }
-
- rxkey = (struct p54_keycache *)skb_put(skb, sizeof(*rxkey));
- rxkey->entry = slot;
- rxkey->key_id = key->keyidx;
- rxkey->key_type = algo;
- if (sta)
- memcpy(rxkey->mac, sta->addr, ETH_ALEN);
- else
- memset(rxkey->mac, ~0, ETH_ALEN);
- if (key->alg != ALG_TKIP) {
- rxkey->key_len = min((u8)16, key->keylen);
- memcpy(rxkey->key, key->key, rxkey->key_len);
- } else {
- rxkey->key_len = 24;
- memcpy(rxkey->key, key->key, 16);
- memcpy(&(rxkey->key[16]), &(key->key
- [NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY]), 8);
- }
-
- priv->tx(dev, skb);
- key->hw_key_idx = slot;
-
-out_unlock:
- mutex_unlock(&priv->conf_mutex);
- return ret;
-}
-
-#ifdef CONFIG_P54_LEDS
-static void p54_update_leds(struct work_struct *work)
-{
- struct p54_common *priv = container_of(work, struct p54_common,
- led_work.work);
- int err, i, tmp, blink_delay = 400;
- bool rerun = false;
-
- /* Don't toggle the LED, when the device is down. */
- if (priv->mode == NL80211_IFTYPE_UNSPECIFIED)
- return ;
-
- for (i = 0; i < ARRAY_SIZE(priv->leds); i++)
- if (priv->leds[i].toggled) {
- priv->softled_state |= BIT(i);
-
- tmp = 70 + 200 / (priv->leds[i].toggled);
- if (tmp < blink_delay)
- blink_delay = tmp;
-
- if (priv->leds[i].led_dev.brightness == LED_OFF)
- rerun = true;
-
- priv->leds[i].toggled =
- !!priv->leds[i].led_dev.brightness;
- } else
- priv->softled_state &= ~BIT(i);
-
- err = p54_set_leds(priv->hw);
- if (err && net_ratelimit())
- printk(KERN_ERR "%s: failed to update LEDs.\n",
- wiphy_name(priv->hw->wiphy));
-
- if (rerun)
- queue_delayed_work(priv->hw->workqueue, &priv->led_work,
- msecs_to_jiffies(blink_delay));
-}
-
-static void p54_led_brightness_set(struct led_classdev *led_dev,
- enum led_brightness brightness)
-{
- struct p54_led_dev *led = container_of(led_dev, struct p54_led_dev,
- led_dev);
- struct ieee80211_hw *dev = led->hw_dev;
- struct p54_common *priv = dev->priv;
-
- if (priv->mode == NL80211_IFTYPE_UNSPECIFIED)
- return ;
-
- if (brightness) {
- led->toggled++;
- queue_delayed_work(priv->hw->workqueue, &priv->led_work,
- HZ/10);
- }
-}
-
-static int p54_register_led(struct ieee80211_hw *dev,
- unsigned int led_index,
- char *name, char *trigger)
-{
- struct p54_common *priv = dev->priv;
- struct p54_led_dev *led = &priv->leds[led_index];
- int err;
-
- if (led->registered)
- return -EEXIST;
-
- snprintf(led->name, sizeof(led->name), "p54-%s::%s",
- wiphy_name(dev->wiphy), name);
- led->hw_dev = dev;
- led->index = led_index;
- led->led_dev.name = led->name;
- led->led_dev.default_trigger = trigger;
- led->led_dev.brightness_set = p54_led_brightness_set;
-
- err = led_classdev_register(wiphy_dev(dev->wiphy), &led->led_dev);
- if (err)
- printk(KERN_ERR "%s: Failed to register %s LED.\n",
- wiphy_name(dev->wiphy), name);
- else
- led->registered = 1;
-
- return err;
-}
-
-static int p54_init_leds(struct ieee80211_hw *dev)
-{
- struct p54_common *priv = dev->priv;
- int err;
-
- /*
- * TODO:
- * Figure out if the EEPROM contains some hints about the number
- * of available/programmable LEDs of the device.
- */
-
- INIT_DELAYED_WORK(&priv->led_work, p54_update_leds);
-
- err = p54_register_led(dev, 0, "assoc",
- ieee80211_get_assoc_led_name(dev));
- if (err)
- return err;
-
- err = p54_register_led(dev, 1, "tx",
- ieee80211_get_tx_led_name(dev));
- if (err)
- return err;
-
- err = p54_register_led(dev, 2, "rx",
- ieee80211_get_rx_led_name(dev));
- if (err)
- return err;
-
- err = p54_register_led(dev, 3, "radio",
- ieee80211_get_radio_led_name(dev));
- if (err)
- return err;
-
- err = p54_set_leds(dev);
- return err;
-}
-
-static void p54_unregister_leds(struct ieee80211_hw *dev)
-{
- struct p54_common *priv = dev->priv;
- int i;
-
- for (i = 0; i < ARRAY_SIZE(priv->leds); i++)
- if (priv->leds[i].registered)
- led_classdev_unregister(&priv->leds[i].led_dev);
-}
-#endif /* CONFIG_P54_LEDS */
-
-static const struct ieee80211_ops p54_ops = {
- .tx = p54_tx,
- .start = p54_start,
- .stop = p54_stop,
- .add_interface = p54_add_interface,
- .remove_interface = p54_remove_interface,
- .set_tim = p54_set_tim,
- .sta_notify = p54_sta_notify,
- .set_key = p54_set_key,
- .config = p54_config,
- .bss_info_changed = p54_bss_info_changed,
- .configure_filter = p54_configure_filter,
- .conf_tx = p54_conf_tx,
- .get_stats = p54_get_stats,
- .get_tx_stats = p54_get_tx_stats
-};
-
-struct ieee80211_hw *p54_init_common(size_t priv_data_len)
-{
- struct ieee80211_hw *dev;
- struct p54_common *priv;
-
- dev = ieee80211_alloc_hw(priv_data_len, &p54_ops);
- if (!dev)
- return NULL;
-
- priv = dev->priv;
- priv->hw = dev;
- priv->mode = NL80211_IFTYPE_UNSPECIFIED;
- priv->basic_rate_mask = 0x15f;
- skb_queue_head_init(&priv->tx_queue);
- dev->flags = IEEE80211_HW_RX_INCLUDES_FCS |
- IEEE80211_HW_SIGNAL_DBM |
- IEEE80211_HW_NOISE_DBM;
-
- dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
- BIT(NL80211_IFTYPE_ADHOC) |
- BIT(NL80211_IFTYPE_AP) |
- BIT(NL80211_IFTYPE_MESH_POINT);
-
- dev->channel_change_time = 1000; /* TODO: find actual value */
- priv->tx_stats[P54_QUEUE_BEACON].limit = 1;
- priv->tx_stats[P54_QUEUE_FWSCAN].limit = 1;
- priv->tx_stats[P54_QUEUE_MGMT].limit = 3;
- priv->tx_stats[P54_QUEUE_CAB].limit = 3;
- priv->tx_stats[P54_QUEUE_DATA].limit = 5;
- dev->queues = 1;
- priv->noise = -94;
- /*
- * We support at most 8 tries no matter which rate they're at,
- * we cannot support max_rates * max_rate_tries as we set it
- * here, but setting it correctly to 4/2 or so would limit us
- * artificially if the RC algorithm wants just two rates, so
- * let's say 4/7, we'll redistribute it at TX time, see the
- * comments there.
- */
- dev->max_rates = 4;
- dev->max_rate_tries = 7;
- dev->extra_tx_headroom = sizeof(struct p54_hdr) + 4 +
- sizeof(struct p54_tx_data);
-
- mutex_init(&priv->conf_mutex);
- init_completion(&priv->eeprom_comp);
- INIT_DELAYED_WORK(&priv->work, p54_work);
-
- return dev;
-}
-EXPORT_SYMBOL_GPL(p54_init_common);
-
-int p54_register_common(struct ieee80211_hw *dev, struct device *pdev)
-{
- int err;
-
- err = ieee80211_register_hw(dev);
- if (err) {
- dev_err(pdev, "Cannot register device (%d).\n", err);
- return err;
- }
-
-#ifdef CONFIG_P54_LEDS
- err = p54_init_leds(dev);
- if (err)
- return err;
-#endif /* CONFIG_P54_LEDS */
-
- dev_info(pdev, "is registered as '%s'\n", wiphy_name(dev->wiphy));
- return 0;
-}
-EXPORT_SYMBOL_GPL(p54_register_common);
-
-void p54_free_common(struct ieee80211_hw *dev)
-{
- struct p54_common *priv = dev->priv;
- kfree(priv->iq_autocal);
- kfree(priv->output_limit);
- kfree(priv->curve_data);
- kfree(priv->used_rxkeys);
-
-#ifdef CONFIG_P54_LEDS
- p54_unregister_leds(dev);
-#endif /* CONFIG_P54_LEDS */
-}
-EXPORT_SYMBOL_GPL(p54_free_common);
diff --git a/drivers/net/wireless/p54/p54common.h b/drivers/net/wireless/p54/p54common.h
deleted file mode 100644
index 75ead7a150f..00000000000
--- a/drivers/net/wireless/p54/p54common.h
+++ /dev/null
@@ -1,644 +0,0 @@
-#ifndef P54COMMON_H
-#define P54COMMON_H
-
-/*
- * Common code specific definitions for mac80211 Prism54 drivers
- *
- * Copyright (c) 2006, Michael Wu <flamingice@sourmilk.net>
- * Copyright (c) 2007, Christian Lamparter <chunkeey@web.de>
- *
- * Based on:
- * - the islsm (softmac prism54) driver, which is:
- * Copyright 2004-2006 Jean-Baptiste Note <jbnote@gmail.com>, et al.
- *
- * - LMAC API interface header file for STLC4560 (lmac_longbow.h)
- * Copyright (C) 2007 Conexant Systems, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-struct bootrec {
- __le32 code;
- __le32 len;
- u32 data[10];
-} __attribute__((packed));
-
-#define PDR_SYNTH_FRONTEND_MASK 0x0007
-#define PDR_SYNTH_FRONTEND_DUETTE3 0x0001
-#define PDR_SYNTH_FRONTEND_DUETTE2 0x0002
-#define PDR_SYNTH_FRONTEND_FRISBEE 0x0003
-#define PDR_SYNTH_FRONTEND_XBOW 0x0004
-#define PDR_SYNTH_FRONTEND_LONGBOW 0x0005
-#define PDR_SYNTH_IQ_CAL_MASK 0x0018
-#define PDR_SYNTH_IQ_CAL_PA_DETECTOR 0x0000
-#define PDR_SYNTH_IQ_CAL_DISABLED 0x0008
-#define PDR_SYNTH_IQ_CAL_ZIF 0x0010
-#define PDR_SYNTH_FAA_SWITCH_MASK 0x0020
-#define PDR_SYNTH_FAA_SWITCH_ENABLED 0x0020
-#define PDR_SYNTH_24_GHZ_MASK 0x0040
-#define PDR_SYNTH_24_GHZ_DISABLED 0x0040
-#define PDR_SYNTH_5_GHZ_MASK 0x0080
-#define PDR_SYNTH_5_GHZ_DISABLED 0x0080
-#define PDR_SYNTH_RX_DIV_MASK 0x0100
-#define PDR_SYNTH_RX_DIV_SUPPORTED 0x0100
-#define PDR_SYNTH_TX_DIV_MASK 0x0200
-#define PDR_SYNTH_TX_DIV_SUPPORTED 0x0200
-
-struct bootrec_exp_if {
- __le16 role;
- __le16 if_id;
- __le16 variant;
- __le16 btm_compat;
- __le16 top_compat;
-} __attribute__((packed));
-
-#define BR_DESC_PRIV_CAP_WEP BIT(0)
-#define BR_DESC_PRIV_CAP_TKIP BIT(1)
-#define BR_DESC_PRIV_CAP_MICHAEL BIT(2)
-#define BR_DESC_PRIV_CAP_CCX_CP BIT(3)
-#define BR_DESC_PRIV_CAP_CCX_MIC BIT(4)
-#define BR_DESC_PRIV_CAP_AESCCMP BIT(5)
-
-struct bootrec_desc {
- __le16 modes;
- __le16 flags;
- __le32 rx_start;
- __le32 rx_end;
- u8 headroom;
- u8 tailroom;
- u8 tx_queues;
- u8 tx_depth;
- u8 privacy_caps;
- u8 rx_keycache_size;
- u8 time_size;
- u8 padding;
- u8 rates[16];
- u8 padding2[4];
- __le16 rx_mtu;
-} __attribute__((packed));
-
-#define BR_CODE_MIN 0x80000000
-#define BR_CODE_COMPONENT_ID 0x80000001
-#define BR_CODE_COMPONENT_VERSION 0x80000002
-#define BR_CODE_DEPENDENT_IF 0x80000003
-#define BR_CODE_EXPOSED_IF 0x80000004
-#define BR_CODE_DESCR 0x80000101
-#define BR_CODE_MAX 0x8FFFFFFF
-#define BR_CODE_END_OF_BRA 0xFF0000FF
-#define LEGACY_BR_CODE_END_OF_BRA 0xFFFFFFFF
-
-#define P54_HDR_FLAG_DATA_ALIGN BIT(14)
-#define P54_HDR_FLAG_DATA_OUT_PROMISC BIT(0)
-#define P54_HDR_FLAG_DATA_OUT_TIMESTAMP BIT(1)
-#define P54_HDR_FLAG_DATA_OUT_SEQNR BIT(2)
-#define P54_HDR_FLAG_DATA_OUT_BIT3 BIT(3)
-#define P54_HDR_FLAG_DATA_OUT_BURST BIT(4)
-#define P54_HDR_FLAG_DATA_OUT_NOCANCEL BIT(5)
-#define P54_HDR_FLAG_DATA_OUT_CLEARTIM BIT(6)
-#define P54_HDR_FLAG_DATA_OUT_HITCHHIKE BIT(7)
-#define P54_HDR_FLAG_DATA_OUT_COMPRESS BIT(8)
-#define P54_HDR_FLAG_DATA_OUT_CONCAT BIT(9)
-#define P54_HDR_FLAG_DATA_OUT_PCS_ACCEPT BIT(10)
-#define P54_HDR_FLAG_DATA_OUT_WAITEOSP BIT(11)
-
-#define P54_HDR_FLAG_DATA_IN_FCS_GOOD BIT(0)
-#define P54_HDR_FLAG_DATA_IN_MATCH_MAC BIT(1)
-#define P54_HDR_FLAG_DATA_IN_MCBC BIT(2)
-#define P54_HDR_FLAG_DATA_IN_BEACON BIT(3)
-#define P54_HDR_FLAG_DATA_IN_MATCH_BSS BIT(4)
-#define P54_HDR_FLAG_DATA_IN_BCAST_BSS BIT(5)
-#define P54_HDR_FLAG_DATA_IN_DATA BIT(6)
-#define P54_HDR_FLAG_DATA_IN_TRUNCATED BIT(7)
-#define P54_HDR_FLAG_DATA_IN_BIT8 BIT(8)
-#define P54_HDR_FLAG_DATA_IN_TRANSPARENT BIT(9)
-
-/* PDA defines are Copyright (C) 2005 Nokia Corporation (taken from islsm_pda.h) */
-
-struct pda_entry {
- __le16 len; /* includes both code and data */
- __le16 code;
- u8 data[0];
-} __attribute__ ((packed));
-
-struct eeprom_pda_wrap {
- __le32 magic;
- __le16 pad;
- __le16 len;
- __le32 arm_opcode;
- u8 data[0];
-} __attribute__ ((packed));
-
-struct p54_iq_autocal_entry {
- __le16 iq_param[4];
-} __attribute__ ((packed));
-
-struct pda_iq_autocal_entry {
- __le16 freq;
- struct p54_iq_autocal_entry params;
-} __attribute__ ((packed));
-
-struct pda_channel_output_limit {
- __le16 freq;
- u8 val_bpsk;
- u8 val_qpsk;
- u8 val_16qam;
- u8 val_64qam;
- u8 rate_set_mask;
- u8 rate_set_size;
-} __attribute__ ((packed));
-
-struct pda_pa_curve_data_sample_rev0 {
- u8 rf_power;
- u8 pa_detector;
- u8 pcv;
-} __attribute__ ((packed));
-
-struct pda_pa_curve_data_sample_rev1 {
- u8 rf_power;
- u8 pa_detector;
- u8 data_barker;
- u8 data_bpsk;
- u8 data_qpsk;
- u8 data_16qam;
- u8 data_64qam;
-} __attribute__ ((packed));
-
-struct p54_pa_curve_data_sample {
- u8 rf_power;
- u8 pa_detector;
- u8 data_barker;
- u8 data_bpsk;
- u8 data_qpsk;
- u8 data_16qam;
- u8 data_64qam;
- u8 padding;
-} __attribute__ ((packed));
-
-struct pda_pa_curve_data {
- u8 cal_method_rev;
- u8 channels;
- u8 points_per_channel;
- u8 padding;
- u8 data[0];
-} __attribute__ ((packed));
-
-struct pda_rssi_cal_entry {
- __le16 mul;
- __le16 add;
-} __attribute__ ((packed));
-
-struct pda_country {
- u8 regdomain;
- u8 alpha2[2];
- u8 flags;
-} __attribute__ ((packed));
-
-/*
- * Warning: Longbow's structures are bogus.
- */
-struct p54_channel_output_limit_longbow {
- __le16 rf_power_points[12];
-} __attribute__ ((packed));
-
-struct p54_pa_curve_data_sample_longbow {
- __le16 rf_power;
- __le16 pa_detector;
- struct {
- __le16 data[4];
- } points[3] __attribute__ ((packed));
-} __attribute__ ((packed));
-
-struct pda_custom_wrapper {
- __le16 entries;
- __le16 entry_size;
- __le16 offset;
- __le16 len;
- u8 data[0];
-} __attribute__ ((packed));
-
-/*
- * this defines the PDR codes used to build PDAs as defined in document
- * number 553155. The current implementation mirrors version 1.1 of the
- * document and lists only PDRs supported by the ARM platform.
- */
-
-/* common and choice range (0x0000 - 0x0fff) */
-#define PDR_END 0x0000
-#define PDR_MANUFACTURING_PART_NUMBER 0x0001
-#define PDR_PDA_VERSION 0x0002
-#define PDR_NIC_SERIAL_NUMBER 0x0003
-
-#define PDR_MAC_ADDRESS 0x0101
-#define PDR_REGULATORY_DOMAIN_LIST 0x0103
-#define PDR_TEMPERATURE_TYPE 0x0107
-
-#define PDR_PRISM_PCI_IDENTIFIER 0x0402
-
-/* ARM range (0x1000 - 0x1fff) */
-#define PDR_COUNTRY_INFORMATION 0x1000
-#define PDR_INTERFACE_LIST 0x1001
-#define PDR_HARDWARE_PLATFORM_COMPONENT_ID 0x1002
-#define PDR_OEM_NAME 0x1003
-#define PDR_PRODUCT_NAME 0x1004
-#define PDR_UTF8_OEM_NAME 0x1005
-#define PDR_UTF8_PRODUCT_NAME 0x1006
-#define PDR_COUNTRY_LIST 0x1007
-#define PDR_DEFAULT_COUNTRY 0x1008
-
-#define PDR_ANTENNA_GAIN 0x1100
-
-#define PDR_PRISM_INDIGO_PA_CALIBRATION_DATA 0x1901
-#define PDR_RSSI_LINEAR_APPROXIMATION 0x1902
-#define PDR_PRISM_PA_CAL_OUTPUT_POWER_LIMITS 0x1903
-#define PDR_PRISM_PA_CAL_CURVE_DATA 0x1904
-#define PDR_RSSI_LINEAR_APPROXIMATION_DUAL_BAND 0x1905
-#define PDR_PRISM_ZIF_TX_IQ_CALIBRATION 0x1906
-#define PDR_REGULATORY_POWER_LIMITS 0x1907
-#define PDR_RSSI_LINEAR_APPROXIMATION_EXTENDED 0x1908
-#define PDR_RADIATED_TRANSMISSION_CORRECTION 0x1909
-#define PDR_PRISM_TX_IQ_CALIBRATION 0x190a
-
-/* reserved range (0x2000 - 0x7fff) */
-
-/* customer range (0x8000 - 0xffff) */
-#define PDR_BASEBAND_REGISTERS 0x8000
-#define PDR_PER_CHANNEL_BASEBAND_REGISTERS 0x8001
-
-/* used by our modificated eeprom image */
-#define PDR_RSSI_LINEAR_APPROXIMATION_CUSTOM 0xDEAD
-#define PDR_PRISM_PA_CAL_OUTPUT_POWER_LIMITS_CUSTOM 0xBEEF
-#define PDR_PRISM_PA_CAL_CURVE_DATA_CUSTOM 0xB05D
-
-/* PDR definitions for default country & country list */
-#define PDR_COUNTRY_CERT_CODE 0x80
-#define PDR_COUNTRY_CERT_CODE_REAL 0x00
-#define PDR_COUNTRY_CERT_CODE_PSEUDO 0x80
-#define PDR_COUNTRY_CERT_BAND 0x40
-#define PDR_COUNTRY_CERT_BAND_2GHZ 0x00
-#define PDR_COUNTRY_CERT_BAND_5GHZ 0x40
-#define PDR_COUNTRY_CERT_IODOOR 0x30
-#define PDR_COUNTRY_CERT_IODOOR_BOTH 0x00
-#define PDR_COUNTRY_CERT_IODOOR_INDOOR 0x20
-#define PDR_COUNTRY_CERT_IODOOR_OUTDOOR 0x30
-#define PDR_COUNTRY_CERT_INDEX 0x0F
-
-struct p54_eeprom_lm86 {
- union {
- struct {
- __le16 offset;
- __le16 len;
- u8 data[0];
- } v1;
- struct {
- __le32 offset;
- __le16 len;
- u8 magic2;
- u8 pad;
- u8 magic[4];
- u8 data[0];
- } v2;
- } __attribute__ ((packed));
-} __attribute__ ((packed));
-
-enum p54_rx_decrypt_status {
- P54_DECRYPT_NONE = 0,
- P54_DECRYPT_OK,
- P54_DECRYPT_NOKEY,
- P54_DECRYPT_NOMICHAEL,
- P54_DECRYPT_NOCKIPMIC,
- P54_DECRYPT_FAIL_WEP,
- P54_DECRYPT_FAIL_TKIP,
- P54_DECRYPT_FAIL_MICHAEL,
- P54_DECRYPT_FAIL_CKIPKP,
- P54_DECRYPT_FAIL_CKIPMIC,
- P54_DECRYPT_FAIL_AESCCMP
-};
-
-struct p54_rx_data {
- __le16 flags;
- __le16 len;
- __le16 freq;
- u8 antenna;
- u8 rate;
- u8 rssi;
- u8 quality;
- u8 decrypt_status;
- u8 rssi_raw;
- __le32 tsf32;
- __le32 unalloc0;
- u8 align[0];
-} __attribute__ ((packed));
-
-enum p54_trap_type {
- P54_TRAP_SCAN = 0,
- P54_TRAP_TIMER,
- P54_TRAP_BEACON_TX,
- P54_TRAP_FAA_RADIO_ON,
- P54_TRAP_FAA_RADIO_OFF,
- P54_TRAP_RADAR,
- P54_TRAP_NO_BEACON,
- P54_TRAP_TBTT,
- P54_TRAP_SCO_ENTER,
- P54_TRAP_SCO_EXIT
-};
-
-struct p54_trap {
- __le16 event;
- __le16 frequency;
-} __attribute__ ((packed));
-
-enum p54_frame_sent_status {
- P54_TX_OK = 0,
- P54_TX_FAILED,
- P54_TX_PSM,
- P54_TX_PSM_CANCELLED = 4
-};
-
-struct p54_frame_sent {
- u8 status;
- u8 tries;
- u8 ack_rssi;
- u8 quality;
- __le16 seq;
- u8 antenna;
- u8 padding;
-} __attribute__ ((packed));
-
-enum p54_tx_data_crypt {
- P54_CRYPTO_NONE = 0,
- P54_CRYPTO_WEP,
- P54_CRYPTO_TKIP,
- P54_CRYPTO_TKIPMICHAEL,
- P54_CRYPTO_CCX_WEPMIC,
- P54_CRYPTO_CCX_KPMIC,
- P54_CRYPTO_CCX_KP,
- P54_CRYPTO_AESCCMP
-};
-
-enum p54_tx_data_queue {
- P54_QUEUE_BEACON = 0,
- P54_QUEUE_FWSCAN = 1,
- P54_QUEUE_MGMT = 2,
- P54_QUEUE_CAB = 3,
- P54_QUEUE_DATA = 4,
-
- P54_QUEUE_AC_NUM = 4,
- P54_QUEUE_AC_VO = 4,
- P54_QUEUE_AC_VI = 5,
- P54_QUEUE_AC_BE = 6,
- P54_QUEUE_AC_BK = 7,
-
- /* keep last */
- P54_QUEUE_NUM = 8,
-};
-
-struct p54_tx_data {
- u8 rateset[8];
- u8 rts_rate_idx;
- u8 crypt_offset;
- u8 key_type;
- u8 key_len;
- u8 key[16];
- u8 hw_queue;
- u8 backlog;
- __le16 durations[4];
- u8 tx_antenna;
- union {
- struct {
- u8 cts_rate;
- __le16 output_power;
- } __attribute__((packed)) longbow;
- struct {
- u8 output_power;
- u8 cts_rate;
- u8 unalloc;
- } __attribute__ ((packed)) normal;
- } __attribute__ ((packed));
- u8 unalloc2[2];
- u8 align[0];
-} __attribute__ ((packed));
-
-/* unit is ms */
-#define P54_TX_FRAME_LIFETIME 2000
-#define P54_TX_TIMEOUT 4000
-#define P54_STATISTICS_UPDATE 5000
-
-#define P54_FILTER_TYPE_NONE 0
-#define P54_FILTER_TYPE_STATION BIT(0)
-#define P54_FILTER_TYPE_IBSS BIT(1)
-#define P54_FILTER_TYPE_AP BIT(2)
-#define P54_FILTER_TYPE_TRANSPARENT BIT(3)
-#define P54_FILTER_TYPE_PROMISCUOUS BIT(4)
-#define P54_FILTER_TYPE_HIBERNATE BIT(5)
-#define P54_FILTER_TYPE_NOACK BIT(6)
-#define P54_FILTER_TYPE_RX_DISABLED BIT(7)
-
-struct p54_setup_mac {
- __le16 mac_mode;
- u8 mac_addr[ETH_ALEN];
- u8 bssid[ETH_ALEN];
- u8 rx_antenna;
- u8 rx_align;
- union {
- struct {
- __le32 basic_rate_mask;
- u8 rts_rates[8];
- __le32 rx_addr;
- __le16 max_rx;
- __le16 rxhw;
- __le16 wakeup_timer;
- __le16 unalloc0;
- } v1 __attribute__ ((packed));
- struct {
- __le32 rx_addr;
- __le16 max_rx;
- __le16 rxhw;
- __le16 timer;
- __le16 truncate;
- __le32 basic_rate_mask;
- u8 sbss_offset;
- u8 mcast_window;
- u8 rx_rssi_threshold;
- u8 rx_ed_threshold;
- __le32 ref_clock;
- __le16 lpf_bandwidth;
- __le16 osc_start_delay;
- } v2 __attribute__ ((packed));
- } __attribute__ ((packed));
-} __attribute__ ((packed));
-
-#define P54_SETUP_V1_LEN 40
-#define P54_SETUP_V2_LEN (sizeof(struct p54_setup_mac))
-
-#define P54_SCAN_EXIT BIT(0)
-#define P54_SCAN_TRAP BIT(1)
-#define P54_SCAN_ACTIVE BIT(2)
-#define P54_SCAN_FILTER BIT(3)
-
-struct p54_scan_head {
- __le16 mode;
- __le16 dwell;
- u8 scan_params[20];
- __le16 freq;
-} __attribute__ ((packed));
-
-struct p54_scan_body {
- u8 pa_points_per_curve;
- u8 val_barker;
- u8 val_bpsk;
- u8 val_qpsk;
- u8 val_16qam;
- u8 val_64qam;
- struct p54_pa_curve_data_sample curve_data[8];
- u8 dup_bpsk;
- u8 dup_qpsk;
- u8 dup_16qam;
- u8 dup_64qam;
-} __attribute__ ((packed));
-
-struct p54_scan_body_longbow {
- struct p54_channel_output_limit_longbow power_limits;
- struct p54_pa_curve_data_sample_longbow curve_data[8];
- __le16 unkn[6]; /* maybe more power_limits or rate_mask */
-} __attribute__ ((packed));
-
-union p54_scan_body_union {
- struct p54_scan_body normal;
- struct p54_scan_body_longbow longbow;
-} __attribute__ ((packed));
-
-struct p54_scan_tail_rate {
- __le32 basic_rate_mask;
- u8 rts_rates[8];
-} __attribute__ ((packed));
-
-struct p54_led {
- __le16 flags;
- __le16 mask[2];
- __le16 delay[2];
-} __attribute__ ((packed));
-
-struct p54_edcf {
- u8 flags;
- u8 slottime;
- u8 sifs;
- u8 eofpad;
- struct p54_edcf_queue_param queue[8];
- u8 mapping[4];
- __le16 frameburst;
- __le16 round_trip_delay;
-} __attribute__ ((packed));
-
-struct p54_statistics {
- __le32 rx_success;
- __le32 rx_bad_fcs;
- __le32 rx_abort;
- __le32 rx_abort_phy;
- __le32 rts_success;
- __le32 rts_fail;
- __le32 tsf32;
- __le32 airtime;
- __le32 noise;
- __le32 sample_noise[8];
- __le32 sample_cca;
- __le32 sample_tx;
-} __attribute__ ((packed));
-
-struct p54_xbow_synth {
- __le16 magic1;
- __le16 magic2;
- __le16 freq;
- u32 padding[5];
-} __attribute__ ((packed));
-
-struct p54_timer {
- __le32 interval;
-} __attribute__ ((packed));
-
-struct p54_keycache {
- u8 entry;
- u8 key_id;
- u8 mac[ETH_ALEN];
- u8 padding[2];
- u8 key_type;
- u8 key_len;
- u8 key[24];
-} __attribute__ ((packed));
-
-struct p54_burst {
- u8 flags;
- u8 queue;
- u8 backlog;
- u8 pad;
- __le16 durations[32];
-} __attribute__ ((packed));
-
-struct p54_psm_interval {
- __le16 interval;
- __le16 periods;
-} __attribute__ ((packed));
-
-#define P54_PSM_CAM 0
-#define P54_PSM BIT(0)
-#define P54_PSM_DTIM BIT(1)
-#define P54_PSM_MCBC BIT(2)
-#define P54_PSM_CHECKSUM BIT(3)
-#define P54_PSM_SKIP_MORE_DATA BIT(4)
-#define P54_PSM_BEACON_TIMEOUT BIT(5)
-#define P54_PSM_HFOSLEEP BIT(6)
-#define P54_PSM_AUTOSWITCH_SLEEP BIT(7)
-#define P54_PSM_LPIT BIT(8)
-#define P54_PSM_BF_UCAST_SKIP BIT(9)
-#define P54_PSM_BF_MCAST_SKIP BIT(10)
-
-struct p54_psm {
- __le16 mode;
- __le16 aid;
- struct p54_psm_interval intervals[4];
- u8 beacon_rssi_skip_max;
- u8 rssi_delta_threshold;
- u8 nr;
- u8 exclude[1];
-} __attribute__ ((packed));
-
-#define MC_FILTER_ADDRESS_NUM 4
-
-struct p54_group_address_table {
- __le16 filter_enable;
- __le16 num_address;
- u8 mac_list[MC_FILTER_ADDRESS_NUM][ETH_ALEN];
-} __attribute__ ((packed));
-
-struct p54_txcancel {
- __le32 req_id;
-} __attribute__ ((packed));
-
-struct p54_sta_unlock {
- u8 addr[ETH_ALEN];
- u16 padding;
-} __attribute__ ((packed));
-
-#define P54_TIM_CLEAR BIT(15)
-struct p54_tim {
- u8 count;
- u8 padding[3];
- __le16 entry[8];
-} __attribute__ ((packed));
-
-struct p54_cce_quiet {
- __le32 period;
-} __attribute__ ((packed));
-
-struct p54_bt_balancer {
- __le16 prio_thresh;
- __le16 acl_thresh;
-} __attribute__ ((packed));
-
-struct p54_arp_table {
- __le16 filter_enable;
- u8 ipv4_addr[4];
-} __attribute__ ((packed));
-
-#endif /* P54COMMON_H */
diff --git a/drivers/net/wireless/p54/p54pci.c b/drivers/net/wireless/p54/p54pci.c
index b1610ea4bb3..d348c265e86 100644
--- a/drivers/net/wireless/p54/p54pci.c
+++ b/drivers/net/wireless/p54/p54pci.c
@@ -22,6 +22,7 @@
#include <net/mac80211.h>
#include "p54.h"
+#include "lmac.h"
#include "p54pci.h"
MODULE_AUTHOR("Michael Wu <flamingice@sourmilk.net>");
@@ -564,7 +565,6 @@ static int __devinit p54p_probe(struct pci_dev *pdev,
err_free_common:
release_firmware(priv->firmware);
- p54_free_common(dev);
pci_free_consistent(pdev, sizeof(*priv->ring_control),
priv->ring_control, priv->ring_control_dma);
@@ -573,7 +573,7 @@ static int __devinit p54p_probe(struct pci_dev *pdev,
err_free_dev:
pci_set_drvdata(pdev, NULL);
- ieee80211_free_hw(dev);
+ p54_free_common(dev);
err_free_reg:
pci_release_regions(pdev);
@@ -590,16 +590,15 @@ static void __devexit p54p_remove(struct pci_dev *pdev)
if (!dev)
return;
- ieee80211_unregister_hw(dev);
+ p54_unregister_common(dev);
priv = dev->priv;
release_firmware(priv->firmware);
pci_free_consistent(pdev, sizeof(*priv->ring_control),
priv->ring_control, priv->ring_control_dma);
- p54_free_common(dev);
iounmap(priv->map);
pci_release_regions(pdev);
pci_disable_device(pdev);
- ieee80211_free_hw(dev);
+ p54_free_common(dev);
}
#ifdef CONFIG_PM
diff --git a/drivers/net/wireless/p54/p54spi.c b/drivers/net/wireless/p54/p54spi.c
index 72c7dbd39d0..05458d9249c 100644
--- a/drivers/net/wireless/p54/p54spi.c
+++ b/drivers/net/wireless/p54/p54spi.c
@@ -34,7 +34,7 @@
#include "p54spi_eeprom.h"
#include "p54.h"
-#include "p54common.h"
+#include "lmac.h"
MODULE_FIRMWARE("3826.arm");
MODULE_ALIAS("stlc45xx");
@@ -111,15 +111,6 @@ static void p54spi_spi_write(struct p54s_priv *priv, u8 address,
spi_sync(priv->spi, &m);
}
-static u16 p54spi_read16(struct p54s_priv *priv, u8 addr)
-{
- __le16 val;
-
- p54spi_spi_read(priv, addr, &val, sizeof(val));
-
- return le16_to_cpu(val);
-}
-
static u32 p54spi_read32(struct p54s_priv *priv, u8 addr)
{
__le32 val;
@@ -139,37 +130,12 @@ static inline void p54spi_write32(struct p54s_priv *priv, u8 addr, __le32 val)
p54spi_spi_write(priv, addr, &val, sizeof(val));
}
-struct p54spi_spi_reg {
- u16 address; /* __le16 ? */
- u16 length;
- char *name;
-};
-
-static const struct p54spi_spi_reg p54spi_registers_array[] =
-{
- { SPI_ADRS_ARM_INTERRUPTS, 32, "ARM_INT " },
- { SPI_ADRS_ARM_INT_EN, 32, "ARM_INT_ENA " },
- { SPI_ADRS_HOST_INTERRUPTS, 32, "HOST_INT " },
- { SPI_ADRS_HOST_INT_EN, 32, "HOST_INT_ENA" },
- { SPI_ADRS_HOST_INT_ACK, 32, "HOST_INT_ACK" },
- { SPI_ADRS_GEN_PURP_1, 32, "GP1_COMM " },
- { SPI_ADRS_GEN_PURP_2, 32, "GP2_COMM " },
- { SPI_ADRS_DEV_CTRL_STAT, 32, "DEV_CTRL_STA" },
- { SPI_ADRS_DMA_DATA, 16, "DMA_DATA " },
- { SPI_ADRS_DMA_WRITE_CTRL, 16, "DMA_WR_CTRL " },
- { SPI_ADRS_DMA_WRITE_LEN, 16, "DMA_WR_LEN " },
- { SPI_ADRS_DMA_WRITE_BASE, 32, "DMA_WR_BASE " },
- { SPI_ADRS_DMA_READ_CTRL, 16, "DMA_RD_CTRL " },
- { SPI_ADRS_DMA_READ_LEN, 16, "DMA_RD_LEN " },
- { SPI_ADRS_DMA_WRITE_BASE, 32, "DMA_RD_BASE " }
-};
-
-static int p54spi_wait_bit(struct p54s_priv *priv, u16 reg, __le32 bits)
+static int p54spi_wait_bit(struct p54s_priv *priv, u16 reg, u32 bits)
{
int i;
for (i = 0; i < 2000; i++) {
- __le32 buffer = p54spi_read32(priv, reg);
+ u32 buffer = p54spi_read32(priv, reg);
if ((buffer & bits) == bits)
return 1;
}
@@ -179,8 +145,7 @@ static int p54spi_wait_bit(struct p54s_priv *priv, u16 reg, __le32 bits)
static int p54spi_spi_write_dma(struct p54s_priv *priv, __le32 base,
const void *buf, size_t len)
{
- if (!p54spi_wait_bit(priv, SPI_ADRS_DMA_WRITE_CTRL,
- cpu_to_le32(HOST_ALLOWED))) {
+ if (!p54spi_wait_bit(priv, SPI_ADRS_DMA_WRITE_CTRL, HOST_ALLOWED)) {
dev_err(&priv->spi->dev, "spi_write_dma not allowed "
"to DMA write.\n");
return -EAGAIN;
@@ -333,7 +298,7 @@ static int p54spi_wakeup(struct p54s_priv *priv)
/* And wait for the READY interrupt */
if (!p54spi_wait_bit(priv, SPI_ADRS_HOST_INTERRUPTS,
- cpu_to_le32(SPI_HOST_INT_READY))) {
+ SPI_HOST_INT_READY)) {
dev_err(&priv->spi->dev, "INT_READY timeout\n");
return -EBUSY;
}
@@ -426,7 +391,7 @@ static irqreturn_t p54spi_interrupt(int irq, void *config)
struct spi_device *spi = config;
struct p54s_priv *priv = dev_get_drvdata(&spi->dev);
- queue_work(priv->hw->workqueue, &priv->work);
+ ieee80211_queue_work(priv->hw, &priv->work);
return IRQ_HANDLED;
}
@@ -444,7 +409,7 @@ static int p54spi_tx_frame(struct p54s_priv *priv, struct sk_buff *skb)
goto out;
if (!p54spi_wait_bit(priv, SPI_ADRS_HOST_INTERRUPTS,
- cpu_to_le32(SPI_HOST_INT_WR_READY))) {
+ SPI_HOST_INT_WR_READY)) {
dev_err(&priv->spi->dev, "WR_READY timeout\n");
ret = -EAGAIN;
goto out;
@@ -514,7 +479,7 @@ static void p54spi_op_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
list_add_tail(&di->tx_list, &priv->tx_pending);
spin_unlock_irqrestore(&priv->tx_lock, flags);
- queue_work(priv->hw->workqueue, &priv->work);
+ ieee80211_queue_work(priv->hw, &priv->work);
}
static void p54spi_work(struct work_struct *work)
@@ -713,7 +678,7 @@ static int __devexit p54spi_remove(struct spi_device *spi)
{
struct p54s_priv *priv = dev_get_drvdata(&spi->dev);
- ieee80211_unregister_hw(priv->hw);
+ p54_unregister_common(priv->hw);
free_irq(gpio_to_irq(p54spi_gpio_irq), spi);
@@ -724,7 +689,6 @@ static int __devexit p54spi_remove(struct spi_device *spi)
mutex_destroy(&priv->mutex);
p54_free_common(priv->hw);
- ieee80211_free_hw(priv->hw);
return 0;
}
diff --git a/drivers/net/wireless/p54/p54usb.c b/drivers/net/wireless/p54/p54usb.c
index 0e877a104a8..e44460ff149 100644
--- a/drivers/net/wireless/p54/p54usb.c
+++ b/drivers/net/wireless/p54/p54usb.c
@@ -22,6 +22,7 @@
#include <net/mac80211.h>
#include "p54.h"
+#include "lmac.h"
#include "p54usb.h"
MODULE_AUTHOR("Michael Wu <flamingice@sourmilk.net>");
@@ -245,8 +246,10 @@ static void p54u_tx_lm87(struct ieee80211_hw *dev, struct sk_buff *skb)
struct lm87_tx_hdr *hdr = (void *)skb->data - sizeof(*hdr);
data_urb = usb_alloc_urb(0, GFP_ATOMIC);
- if (!data_urb)
+ if (!data_urb) {
+ p54_free_skb(dev, skb);
return;
+ }
hdr->chksum = p54u_lm87_chksum((__le32 *)skb->data, skb->len);
hdr->device_addr = ((struct p54_hdr *)skb->data)->req_id;
@@ -268,27 +271,22 @@ static void p54u_tx_lm87(struct ieee80211_hw *dev, struct sk_buff *skb)
static void p54u_tx_net2280(struct ieee80211_hw *dev, struct sk_buff *skb)
{
struct p54u_priv *priv = dev->priv;
- struct urb *int_urb, *data_urb;
+ struct urb *int_urb = NULL, *data_urb = NULL;
struct net2280_tx_hdr *hdr = (void *)skb->data - sizeof(*hdr);
- struct net2280_reg_write *reg;
- int err = 0;
+ struct net2280_reg_write *reg = NULL;
+ int err = -ENOMEM;
reg = kmalloc(sizeof(*reg), GFP_ATOMIC);
if (!reg)
- return;
+ goto out;
int_urb = usb_alloc_urb(0, GFP_ATOMIC);
- if (!int_urb) {
- kfree(reg);
- return;
- }
+ if (!int_urb)
+ goto out;
data_urb = usb_alloc_urb(0, GFP_ATOMIC);
- if (!data_urb) {
- kfree(reg);
- usb_free_urb(int_urb);
- return;
- }
+ if (!data_urb)
+ goto out;
reg->port = cpu_to_le16(NET2280_DEV_U32);
reg->addr = cpu_to_le32(P54U_DEV_BASE);
@@ -303,11 +301,12 @@ static void p54u_tx_net2280(struct ieee80211_hw *dev, struct sk_buff *skb)
p54u_tx_dummy_cb, dev);
/*
- * This flag triggers a code path in the USB subsystem that will
- * free what's inside the transfer_buffer after the callback routine
- * has completed.
+ * URB_FREE_BUFFER triggers a code path in the USB subsystem that will
+ * free what is inside the transfer_buffer after the last reference to
+ * the int_urb is dropped.
*/
int_urb->transfer_flags |= URB_FREE_BUFFER | URB_ZERO_PACKET;
+ reg = NULL;
usb_fill_bulk_urb(data_urb, priv->udev,
usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA),
@@ -328,12 +327,12 @@ static void p54u_tx_net2280(struct ieee80211_hw *dev, struct sk_buff *skb)
usb_unanchor_urb(data_urb);
goto out;
}
- out:
+out:
usb_free_urb(int_urb);
usb_free_urb(data_urb);
if (err) {
- skb_pull(skb, sizeof(*hdr));
+ kfree(reg);
p54_free_skb(dev, skb);
}
}
@@ -961,7 +960,7 @@ err_free_fw:
release_firmware(priv->fw);
err_free_dev:
- ieee80211_free_hw(dev);
+ p54_free_common(dev);
usb_set_intfdata(intf, NULL);
usb_put_dev(udev);
return err;
@@ -975,13 +974,12 @@ static void __devexit p54u_disconnect(struct usb_interface *intf)
if (!dev)
return;
- ieee80211_unregister_hw(dev);
+ p54_unregister_common(dev);
priv = dev->priv;
usb_put_dev(interface_to_usbdev(intf));
release_firmware(priv->fw);
p54_free_common(dev);
- ieee80211_free_hw(dev);
}
static int p54u_pre_reset(struct usb_interface *intf)
diff --git a/drivers/net/wireless/p54/txrx.c b/drivers/net/wireless/p54/txrx.c
new file mode 100644
index 00000000000..6fc0b6148c8
--- /dev/null
+++ b/drivers/net/wireless/p54/txrx.c
@@ -0,0 +1,866 @@
+/*
+ * Common code for mac80211 Prism54 drivers
+ *
+ * Copyright (c) 2006, Michael Wu <flamingice@sourmilk.net>
+ * Copyright (c) 2007-2009, Christian Lamparter <chunkeey@web.de>
+ * Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
+ *
+ * Based on:
+ * - the islsm (softmac prism54) driver, which is:
+ * Copyright 2004-2006 Jean-Baptiste Note <jbnote@gmail.com>, et al.
+ * - stlc45xx driver
+ * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/firmware.h>
+#include <linux/etherdevice.h>
+
+#include <net/mac80211.h>
+
+#include "p54.h"
+#include "lmac.h"
+
+#ifdef P54_MM_DEBUG
+static void p54_dump_tx_queue(struct p54_common *priv)
+{
+ unsigned long flags;
+ struct ieee80211_tx_info *info;
+ struct p54_tx_info *range;
+ struct sk_buff *skb;
+ struct p54_hdr *hdr;
+ unsigned int i = 0;
+ u32 prev_addr;
+ u32 largest_hole = 0, free;
+
+ spin_lock_irqsave(&priv->tx_queue.lock, flags);
+ printk(KERN_DEBUG "%s: / --- tx queue dump (%d entries) --- \n",
+ wiphy_name(priv->hw->wiphy), skb_queue_len(&priv->tx_queue));
+
+ prev_addr = priv->rx_start;
+ skb_queue_walk(&priv->tx_queue, skb) {
+ info = IEEE80211_SKB_CB(skb);
+ range = (void *) info->rate_driver_data;
+ hdr = (void *) skb->data;
+
+ free = range->start_addr - prev_addr;
+ printk(KERN_DEBUG "%s: | [%02d] => [skb:%p skb_len:0x%04x "
+ "hdr:{flags:%02x len:%04x req_id:%04x type:%02x} "
+ "mem:{start:%04x end:%04x, free:%d}]\n",
+ wiphy_name(priv->hw->wiphy), i++, skb, skb->len,
+ le16_to_cpu(hdr->flags), le16_to_cpu(hdr->len),
+ le32_to_cpu(hdr->req_id), le16_to_cpu(hdr->type),
+ range->start_addr, range->end_addr, free);
+
+ prev_addr = range->end_addr;
+ largest_hole = max(largest_hole, free);
+ }
+ free = priv->rx_end - prev_addr;
+ largest_hole = max(largest_hole, free);
+ printk(KERN_DEBUG "%s: \\ --- [free: %d], largest free block: %d ---\n",
+ wiphy_name(priv->hw->wiphy), free, largest_hole);
+ spin_unlock_irqrestore(&priv->tx_queue.lock, flags);
+}
+#endif /* P54_MM_DEBUG */
+
+/*
+ * So, the firmware is somewhat stupid and doesn't know what places in its
+ * memory incoming data should go to. By poking around in the firmware, we
+ * can find some unused memory to upload our packets to. However, data that we
+ * want the card to TX needs to stay intact until the card has told us that
+ * it is done with it. This function finds empty places we can upload to and
+ * marks allocated areas as reserved if necessary. p54_find_and_unlink_skb or
+ * p54_free_skb frees allocated areas.
+ */
+static int p54_assign_address(struct p54_common *priv, struct sk_buff *skb)
+{
+ struct sk_buff *entry, *target_skb = NULL;
+ struct ieee80211_tx_info *info;
+ struct p54_tx_info *range;
+ struct p54_hdr *data = (void *) skb->data;
+ unsigned long flags;
+ u32 last_addr = priv->rx_start;
+ u32 target_addr = priv->rx_start;
+ u16 len = priv->headroom + skb->len + priv->tailroom + 3;
+
+ info = IEEE80211_SKB_CB(skb);
+ range = (void *) info->rate_driver_data;
+ len = (range->extra_len + len) & ~0x3;
+
+ spin_lock_irqsave(&priv->tx_queue.lock, flags);
+ if (unlikely(skb_queue_len(&priv->tx_queue) == 32)) {
+ /*
+ * The tx_queue is now really full.
+ *
+ * TODO: check if the device has crashed and reset it.
+ */
+ spin_unlock_irqrestore(&priv->tx_queue.lock, flags);
+ return -EBUSY;
+ }
+
+ skb_queue_walk(&priv->tx_queue, entry) {
+ u32 hole_size;
+ info = IEEE80211_SKB_CB(entry);
+ range = (void *) info->rate_driver_data;
+ hole_size = range->start_addr - last_addr;
+
+ if (!target_skb && hole_size >= len) {
+ target_skb = entry->prev;
+ hole_size -= len;
+ target_addr = last_addr;
+ break;
+ }
+ last_addr = range->end_addr;
+ }
+ if (unlikely(!target_skb)) {
+ if (priv->rx_end - last_addr >= len) {
+ target_skb = priv->tx_queue.prev;
+ if (!skb_queue_empty(&priv->tx_queue)) {
+ info = IEEE80211_SKB_CB(target_skb);
+ range = (void *)info->rate_driver_data;
+ target_addr = range->end_addr;
+ }
+ } else {
+ spin_unlock_irqrestore(&priv->tx_queue.lock, flags);
+ return -ENOSPC;
+ }
+ }
+
+ info = IEEE80211_SKB_CB(skb);
+ range = (void *) info->rate_driver_data;
+ range->start_addr = target_addr;
+ range->end_addr = target_addr + len;
+ data->req_id = cpu_to_le32(target_addr + priv->headroom);
+ if (IS_DATA_FRAME(skb) &&
+ unlikely(GET_HW_QUEUE(skb) == P54_QUEUE_BEACON))
+ priv->beacon_req_id = data->req_id;
+
+ __skb_queue_after(&priv->tx_queue, target_skb, skb);
+ spin_unlock_irqrestore(&priv->tx_queue.lock, flags);
+ return 0;
+}
+
+static void p54_tx_pending(struct p54_common *priv)
+{
+ struct sk_buff *skb;
+ int ret;
+
+ skb = skb_dequeue(&priv->tx_pending);
+ if (unlikely(!skb))
+ return ;
+
+ ret = p54_assign_address(priv, skb);
+ if (unlikely(ret))
+ skb_queue_head(&priv->tx_pending, skb);
+ else
+ priv->tx(priv->hw, skb);
+}
+
+static void p54_wake_queues(struct p54_common *priv)
+{
+ unsigned long flags;
+ unsigned int i;
+
+ if (unlikely(priv->mode == NL80211_IFTYPE_UNSPECIFIED))
+ return ;
+
+ p54_tx_pending(priv);
+
+ spin_lock_irqsave(&priv->tx_stats_lock, flags);
+ for (i = 0; i < priv->hw->queues; i++) {
+ if (priv->tx_stats[i + P54_QUEUE_DATA].len <
+ priv->tx_stats[i + P54_QUEUE_DATA].limit)
+ ieee80211_wake_queue(priv->hw, i);
+ }
+ spin_unlock_irqrestore(&priv->tx_stats_lock, flags);
+}
+
+static int p54_tx_qos_accounting_alloc(struct p54_common *priv,
+ struct sk_buff *skb,
+ const u16 p54_queue)
+{
+ struct ieee80211_tx_queue_stats *queue;
+ unsigned long flags;
+
+ if (WARN_ON(p54_queue > P54_QUEUE_NUM))
+ return -EINVAL;
+
+ queue = &priv->tx_stats[p54_queue];
+
+ spin_lock_irqsave(&priv->tx_stats_lock, flags);
+ if (unlikely(queue->len >= queue->limit && IS_QOS_QUEUE(p54_queue))) {
+ spin_unlock_irqrestore(&priv->tx_stats_lock, flags);
+ return -ENOSPC;
+ }
+
+ queue->len++;
+ queue->count++;
+
+ if (unlikely(queue->len == queue->limit && IS_QOS_QUEUE(p54_queue))) {
+ u16 ac_queue = p54_queue - P54_QUEUE_DATA;
+ ieee80211_stop_queue(priv->hw, ac_queue);
+ }
+
+ spin_unlock_irqrestore(&priv->tx_stats_lock, flags);
+ return 0;
+}
+
+static void p54_tx_qos_accounting_free(struct p54_common *priv,
+ struct sk_buff *skb)
+{
+ if (IS_DATA_FRAME(skb)) {
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->tx_stats_lock, flags);
+ priv->tx_stats[GET_HW_QUEUE(skb)].len--;
+ spin_unlock_irqrestore(&priv->tx_stats_lock, flags);
+
+ if (unlikely(GET_HW_QUEUE(skb) == P54_QUEUE_BEACON)) {
+ if (priv->beacon_req_id == GET_REQ_ID(skb)) {
+ /* this is the active beacon set anymore */
+ priv->beacon_req_id = 0;
+ }
+ complete(&priv->beacon_comp);
+ }
+ }
+ p54_wake_queues(priv);
+}
+
+void p54_free_skb(struct ieee80211_hw *dev, struct sk_buff *skb)
+{
+ struct p54_common *priv = dev->priv;
+ if (unlikely(!skb))
+ return ;
+
+ skb_unlink(skb, &priv->tx_queue);
+ p54_tx_qos_accounting_free(priv, skb);
+ dev_kfree_skb_any(skb);
+}
+EXPORT_SYMBOL_GPL(p54_free_skb);
+
+static struct sk_buff *p54_find_and_unlink_skb(struct p54_common *priv,
+ const __le32 req_id)
+{
+ struct sk_buff *entry;
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->tx_queue.lock, flags);
+ skb_queue_walk(&priv->tx_queue, entry) {
+ struct p54_hdr *hdr = (struct p54_hdr *) entry->data;
+
+ if (hdr->req_id == req_id) {
+ __skb_unlink(entry, &priv->tx_queue);
+ spin_unlock_irqrestore(&priv->tx_queue.lock, flags);
+ p54_tx_qos_accounting_free(priv, entry);
+ return entry;
+ }
+ }
+ spin_unlock_irqrestore(&priv->tx_queue.lock, flags);
+ return NULL;
+}
+
+void p54_tx(struct p54_common *priv, struct sk_buff *skb)
+{
+ skb_queue_tail(&priv->tx_pending, skb);
+ p54_tx_pending(priv);
+}
+
+static int p54_rssi_to_dbm(struct p54_common *priv, int rssi)
+{
+ int band = priv->hw->conf.channel->band;
+
+ if (priv->rxhw != 5)
+ return ((rssi * priv->rssical_db[band].mul) / 64 +
+ priv->rssical_db[band].add) / 4;
+ else
+ /*
+ * TODO: find the correct formula
+ */
+ return ((rssi * priv->rssical_db[band].mul) / 64 +
+ priv->rssical_db[band].add) / 4;
+}
+
+/*
+ * Even if the firmware is capable of dealing with incoming traffic,
+ * while dozing, we have to prepared in case mac80211 uses PS-POLL
+ * to retrieve outstanding frames from our AP.
+ * (see comment in net/mac80211/mlme.c @ line 1993)
+ */
+static void p54_pspoll_workaround(struct p54_common *priv, struct sk_buff *skb)
+{
+ struct ieee80211_hdr *hdr = (void *) skb->data;
+ struct ieee80211_tim_ie *tim_ie;
+ u8 *tim;
+ u8 tim_len;
+ bool new_psm;
+
+ /* only beacons have a TIM IE */
+ if (!ieee80211_is_beacon(hdr->frame_control))
+ return;
+
+ if (!priv->aid)
+ return;
+
+ /* only consider beacons from the associated BSSID */
+ if (compare_ether_addr(hdr->addr3, priv->bssid))
+ return;
+
+ tim = p54_find_ie(skb, WLAN_EID_TIM);
+ if (!tim)
+ return;
+
+ tim_len = tim[1];
+ tim_ie = (struct ieee80211_tim_ie *) &tim[2];
+
+ new_psm = ieee80211_check_tim(tim_ie, tim_len, priv->aid);
+ if (new_psm != priv->powersave_override) {
+ priv->powersave_override = new_psm;
+ p54_set_ps(priv);
+ }
+}
+
+static int p54_rx_data(struct p54_common *priv, struct sk_buff *skb)
+{
+ struct p54_rx_data *hdr = (struct p54_rx_data *) skb->data;
+ struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb);
+ u16 freq = le16_to_cpu(hdr->freq);
+ size_t header_len = sizeof(*hdr);
+ u32 tsf32;
+ u8 rate = hdr->rate & 0xf;
+
+ /*
+ * If the device is in a unspecified state we have to
+ * ignore all data frames. Else we could end up with a
+ * nasty crash.
+ */
+ if (unlikely(priv->mode == NL80211_IFTYPE_UNSPECIFIED))
+ return 0;
+
+ if (!(hdr->flags & cpu_to_le16(P54_HDR_FLAG_DATA_IN_FCS_GOOD)))
+ return 0;
+
+ if (hdr->decrypt_status == P54_DECRYPT_OK)
+ rx_status->flag |= RX_FLAG_DECRYPTED;
+ if ((hdr->decrypt_status == P54_DECRYPT_FAIL_MICHAEL) ||
+ (hdr->decrypt_status == P54_DECRYPT_FAIL_TKIP))
+ rx_status->flag |= RX_FLAG_MMIC_ERROR;
+
+ rx_status->signal = p54_rssi_to_dbm(priv, hdr->rssi);
+ rx_status->noise = priv->noise;
+ if (hdr->rate & 0x10)
+ rx_status->flag |= RX_FLAG_SHORTPRE;
+ if (priv->hw->conf.channel->band == IEEE80211_BAND_5GHZ)
+ rx_status->rate_idx = (rate < 4) ? 0 : rate - 4;
+ else
+ rx_status->rate_idx = rate;
+
+ rx_status->freq = freq;
+ rx_status->band = priv->hw->conf.channel->band;
+ rx_status->antenna = hdr->antenna;
+
+ tsf32 = le32_to_cpu(hdr->tsf32);
+ if (tsf32 < priv->tsf_low32)
+ priv->tsf_high32++;
+ rx_status->mactime = ((u64)priv->tsf_high32) << 32 | tsf32;
+ priv->tsf_low32 = tsf32;
+
+ rx_status->flag |= RX_FLAG_TSFT;
+
+ if (hdr->flags & cpu_to_le16(P54_HDR_FLAG_DATA_ALIGN))
+ header_len += hdr->align[0];
+
+ skb_pull(skb, header_len);
+ skb_trim(skb, le16_to_cpu(hdr->len));
+ if (unlikely(priv->hw->conf.flags & IEEE80211_CONF_PS))
+ p54_pspoll_workaround(priv, skb);
+
+ ieee80211_rx_irqsafe(priv->hw, skb);
+
+ ieee80211_queue_delayed_work(priv->hw, &priv->work,
+ msecs_to_jiffies(P54_STATISTICS_UPDATE));
+
+ return -1;
+}
+
+static void p54_rx_frame_sent(struct p54_common *priv, struct sk_buff *skb)
+{
+ struct p54_hdr *hdr = (struct p54_hdr *) skb->data;
+ struct p54_frame_sent *payload = (struct p54_frame_sent *) hdr->data;
+ struct ieee80211_tx_info *info;
+ struct p54_hdr *entry_hdr;
+ struct p54_tx_data *entry_data;
+ struct sk_buff *entry;
+ unsigned int pad = 0, frame_len;
+ int count, idx;
+
+ entry = p54_find_and_unlink_skb(priv, hdr->req_id);
+ if (unlikely(!entry))
+ return ;
+
+ frame_len = entry->len;
+ info = IEEE80211_SKB_CB(entry);
+ entry_hdr = (struct p54_hdr *) entry->data;
+ entry_data = (struct p54_tx_data *) entry_hdr->data;
+ priv->stats.dot11ACKFailureCount += payload->tries - 1;
+
+ /*
+ * Frames in P54_QUEUE_FWSCAN and P54_QUEUE_BEACON are
+ * generated by the driver. Therefore tx_status is bogus
+ * and we don't want to confuse the mac80211 stack.
+ */
+ if (unlikely(entry_data->hw_queue < P54_QUEUE_FWSCAN)) {
+ dev_kfree_skb_any(entry);
+ return ;
+ }
+
+ /*
+ * Clear manually, ieee80211_tx_info_clear_status would
+ * clear the counts too and we need them.
+ */
+ memset(&info->status.ampdu_ack_len, 0,
+ sizeof(struct ieee80211_tx_info) -
+ offsetof(struct ieee80211_tx_info, status.ampdu_ack_len));
+ BUILD_BUG_ON(offsetof(struct ieee80211_tx_info,
+ status.ampdu_ack_len) != 23);
+
+ if (entry_hdr->flags & cpu_to_le16(P54_HDR_FLAG_DATA_ALIGN))
+ pad = entry_data->align[0];
+
+ /* walk through the rates array and adjust the counts */
+ count = payload->tries;
+ for (idx = 0; idx < 4; idx++) {
+ if (count >= info->status.rates[idx].count) {
+ count -= info->status.rates[idx].count;
+ } else if (count > 0) {
+ info->status.rates[idx].count = count;
+ count = 0;
+ } else {
+ info->status.rates[idx].idx = -1;
+ info->status.rates[idx].count = 0;
+ }
+ }
+
+ if (!(info->flags & IEEE80211_TX_CTL_NO_ACK) &&
+ (!payload->status))
+ info->flags |= IEEE80211_TX_STAT_ACK;
+ if (payload->status & P54_TX_PSM_CANCELLED)
+ info->flags |= IEEE80211_TX_STAT_TX_FILTERED;
+ info->status.ack_signal = p54_rssi_to_dbm(priv,
+ (int)payload->ack_rssi);
+
+ /* Undo all changes to the frame. */
+ switch (entry_data->key_type) {
+ case P54_CRYPTO_TKIPMICHAEL: {
+ u8 *iv = (u8 *)(entry_data->align + pad +
+ entry_data->crypt_offset);
+
+ /* Restore the original TKIP IV. */
+ iv[2] = iv[0];
+ iv[0] = iv[1];
+ iv[1] = (iv[0] | 0x20) & 0x7f; /* WEPSeed - 8.3.2.2 */
+
+ frame_len -= 12; /* remove TKIP_MMIC + TKIP_ICV */
+ break;
+ }
+ case P54_CRYPTO_AESCCMP:
+ frame_len -= 8; /* remove CCMP_MIC */
+ break;
+ case P54_CRYPTO_WEP:
+ frame_len -= 4; /* remove WEP_ICV */
+ break;
+ }
+
+ skb_trim(entry, frame_len);
+ skb_pull(entry, sizeof(*hdr) + pad + sizeof(*entry_data));
+ ieee80211_tx_status_irqsafe(priv->hw, entry);
+}
+
+static void p54_rx_eeprom_readback(struct p54_common *priv,
+ struct sk_buff *skb)
+{
+ struct p54_hdr *hdr = (struct p54_hdr *) skb->data;
+ struct p54_eeprom_lm86 *eeprom = (struct p54_eeprom_lm86 *) hdr->data;
+ struct sk_buff *tmp;
+
+ if (!priv->eeprom)
+ return ;
+
+ if (priv->fw_var >= 0x509) {
+ memcpy(priv->eeprom, eeprom->v2.data,
+ le16_to_cpu(eeprom->v2.len));
+ } else {
+ memcpy(priv->eeprom, eeprom->v1.data,
+ le16_to_cpu(eeprom->v1.len));
+ }
+
+ priv->eeprom = NULL;
+ tmp = p54_find_and_unlink_skb(priv, hdr->req_id);
+ dev_kfree_skb_any(tmp);
+ complete(&priv->eeprom_comp);
+}
+
+static void p54_rx_stats(struct p54_common *priv, struct sk_buff *skb)
+{
+ struct p54_hdr *hdr = (struct p54_hdr *) skb->data;
+ struct p54_statistics *stats = (struct p54_statistics *) hdr->data;
+ struct sk_buff *tmp;
+ u32 tsf32;
+
+ if (unlikely(priv->mode == NL80211_IFTYPE_UNSPECIFIED))
+ return ;
+
+ tsf32 = le32_to_cpu(stats->tsf32);
+ if (tsf32 < priv->tsf_low32)
+ priv->tsf_high32++;
+ priv->tsf_low32 = tsf32;
+
+ priv->stats.dot11RTSFailureCount = le32_to_cpu(stats->rts_fail);
+ priv->stats.dot11RTSSuccessCount = le32_to_cpu(stats->rts_success);
+ priv->stats.dot11FCSErrorCount = le32_to_cpu(stats->rx_bad_fcs);
+
+ priv->noise = p54_rssi_to_dbm(priv, le32_to_cpu(stats->noise));
+
+ tmp = p54_find_and_unlink_skb(priv, hdr->req_id);
+ dev_kfree_skb_any(tmp);
+}
+
+static void p54_rx_trap(struct p54_common *priv, struct sk_buff *skb)
+{
+ struct p54_hdr *hdr = (struct p54_hdr *) skb->data;
+ struct p54_trap *trap = (struct p54_trap *) hdr->data;
+ u16 event = le16_to_cpu(trap->event);
+ u16 freq = le16_to_cpu(trap->frequency);
+
+ switch (event) {
+ case P54_TRAP_BEACON_TX:
+ break;
+ case P54_TRAP_RADAR:
+ printk(KERN_INFO "%s: radar (freq:%d MHz)\n",
+ wiphy_name(priv->hw->wiphy), freq);
+ break;
+ case P54_TRAP_NO_BEACON:
+ if (priv->vif)
+ ieee80211_beacon_loss(priv->vif);
+ break;
+ case P54_TRAP_SCAN:
+ break;
+ case P54_TRAP_TBTT:
+ break;
+ case P54_TRAP_TIMER:
+ break;
+ case P54_TRAP_FAA_RADIO_OFF:
+ wiphy_rfkill_set_hw_state(priv->hw->wiphy, true);
+ break;
+ case P54_TRAP_FAA_RADIO_ON:
+ wiphy_rfkill_set_hw_state(priv->hw->wiphy, false);
+ break;
+ default:
+ printk(KERN_INFO "%s: received event:%x freq:%d\n",
+ wiphy_name(priv->hw->wiphy), event, freq);
+ break;
+ }
+}
+
+static int p54_rx_control(struct p54_common *priv, struct sk_buff *skb)
+{
+ struct p54_hdr *hdr = (struct p54_hdr *) skb->data;
+
+ switch (le16_to_cpu(hdr->type)) {
+ case P54_CONTROL_TYPE_TXDONE:
+ p54_rx_frame_sent(priv, skb);
+ break;
+ case P54_CONTROL_TYPE_TRAP:
+ p54_rx_trap(priv, skb);
+ break;
+ case P54_CONTROL_TYPE_BBP:
+ break;
+ case P54_CONTROL_TYPE_STAT_READBACK:
+ p54_rx_stats(priv, skb);
+ break;
+ case P54_CONTROL_TYPE_EEPROM_READBACK:
+ p54_rx_eeprom_readback(priv, skb);
+ break;
+ default:
+ printk(KERN_DEBUG "%s: not handling 0x%02x type control frame\n",
+ wiphy_name(priv->hw->wiphy), le16_to_cpu(hdr->type));
+ break;
+ }
+ return 0;
+}
+
+/* returns zero if skb can be reused */
+int p54_rx(struct ieee80211_hw *dev, struct sk_buff *skb)
+{
+ struct p54_common *priv = dev->priv;
+ u16 type = le16_to_cpu(*((__le16 *)skb->data));
+
+ if (type & P54_HDR_FLAG_CONTROL)
+ return p54_rx_control(priv, skb);
+ else
+ return p54_rx_data(priv, skb);
+}
+EXPORT_SYMBOL_GPL(p54_rx);
+
+static void p54_tx_80211_header(struct p54_common *priv, struct sk_buff *skb,
+ struct ieee80211_tx_info *info, u8 *queue,
+ u32 *extra_len, u16 *flags, u16 *aid,
+ bool *burst_possible)
+{
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+
+ if (ieee80211_is_data_qos(hdr->frame_control))
+ *burst_possible = true;
+ else
+ *burst_possible = false;
+
+ if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ)
+ *flags |= P54_HDR_FLAG_DATA_OUT_SEQNR;
+
+ if (info->flags & IEEE80211_TX_CTL_PSPOLL_RESPONSE)
+ *flags |= P54_HDR_FLAG_DATA_OUT_NOCANCEL;
+
+ *queue = skb_get_queue_mapping(skb) + P54_QUEUE_DATA;
+
+ switch (priv->mode) {
+ case NL80211_IFTYPE_MONITOR:
+ /*
+ * We have to set P54_HDR_FLAG_DATA_OUT_PROMISC for
+ * every frame in promiscuous/monitor mode.
+ * see STSW45x0C LMAC API - page 12.
+ */
+ *aid = 0;
+ *flags |= P54_HDR_FLAG_DATA_OUT_PROMISC;
+ break;
+ case NL80211_IFTYPE_STATION:
+ *aid = 1;
+ break;
+ case NL80211_IFTYPE_AP:
+ case NL80211_IFTYPE_ADHOC:
+ case NL80211_IFTYPE_MESH_POINT:
+ if (info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) {
+ *aid = 0;
+ *queue = P54_QUEUE_CAB;
+ return;
+ }
+
+ if (unlikely(ieee80211_is_mgmt(hdr->frame_control))) {
+ if (ieee80211_is_probe_resp(hdr->frame_control)) {
+ *aid = 0;
+ *flags |= P54_HDR_FLAG_DATA_OUT_TIMESTAMP |
+ P54_HDR_FLAG_DATA_OUT_NOCANCEL;
+ return;
+ } else if (ieee80211_is_beacon(hdr->frame_control)) {
+ *aid = 0;
+
+ if (info->flags & IEEE80211_TX_CTL_INJECTED) {
+ /*
+ * Injecting beacons on top of a AP is
+ * not a good idea... nevertheless,
+ * it should be doable.
+ */
+
+ return;
+ }
+
+ *flags |= P54_HDR_FLAG_DATA_OUT_TIMESTAMP;
+ *queue = P54_QUEUE_BEACON;
+ *extra_len = IEEE80211_MAX_TIM_LEN;
+ return;
+ }
+ }
+
+ if (info->control.sta)
+ *aid = info->control.sta->aid;
+ break;
+ }
+}
+
+static u8 p54_convert_algo(enum ieee80211_key_alg alg)
+{
+ switch (alg) {
+ case ALG_WEP:
+ return P54_CRYPTO_WEP;
+ case ALG_TKIP:
+ return P54_CRYPTO_TKIPMICHAEL;
+ case ALG_CCMP:
+ return P54_CRYPTO_AESCCMP;
+ default:
+ return 0;
+ }
+}
+
+int p54_tx_80211(struct ieee80211_hw *dev, struct sk_buff *skb)
+{
+ struct p54_common *priv = dev->priv;
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+ struct p54_tx_info *p54info;
+ struct p54_hdr *hdr;
+ struct p54_tx_data *txhdr;
+ unsigned int padding, len, extra_len;
+ int i, j, ridx;
+ u16 hdr_flags = 0, aid = 0;
+ u8 rate, queue = 0, crypt_offset = 0;
+ u8 cts_rate = 0x20;
+ u8 rc_flags;
+ u8 calculated_tries[4];
+ u8 nrates = 0, nremaining = 8;
+ bool burst_allowed = false;
+
+ p54_tx_80211_header(priv, skb, info, &queue, &extra_len,
+ &hdr_flags, &aid, &burst_allowed);
+
+ if (p54_tx_qos_accounting_alloc(priv, skb, queue)) {
+ if (!IS_QOS_QUEUE(queue)) {
+ dev_kfree_skb_any(skb);
+ return NETDEV_TX_OK;
+ } else {
+ return NETDEV_TX_BUSY;
+ }
+ }
+
+ padding = (unsigned long)(skb->data - (sizeof(*hdr) + sizeof(*txhdr))) & 3;
+ len = skb->len;
+
+ if (info->control.hw_key) {
+ crypt_offset = ieee80211_get_hdrlen_from_skb(skb);
+ if (info->control.hw_key->alg == ALG_TKIP) {
+ u8 *iv = (u8 *)(skb->data + crypt_offset);
+ /*
+ * The firmware excepts that the IV has to have
+ * this special format
+ */
+ iv[1] = iv[0];
+ iv[0] = iv[2];
+ iv[2] = 0;
+ }
+ }
+
+ txhdr = (struct p54_tx_data *) skb_push(skb, sizeof(*txhdr) + padding);
+ hdr = (struct p54_hdr *) skb_push(skb, sizeof(*hdr));
+
+ if (padding)
+ hdr_flags |= P54_HDR_FLAG_DATA_ALIGN;
+ hdr->type = cpu_to_le16(aid);
+ hdr->rts_tries = info->control.rates[0].count;
+
+ /*
+ * we register the rates in perfect order, and
+ * RTS/CTS won't happen on 5 GHz
+ */
+ cts_rate = info->control.rts_cts_rate_idx;
+
+ memset(&txhdr->rateset, 0, sizeof(txhdr->rateset));
+
+ /* see how many rates got used */
+ for (i = 0; i < dev->max_rates; i++) {
+ if (info->control.rates[i].idx < 0)
+ break;
+ nrates++;
+ }
+
+ /* limit tries to 8/nrates per rate */
+ for (i = 0; i < nrates; i++) {
+ /*
+ * The magic expression here is equivalent to 8/nrates for
+ * all values that matter, but avoids division and jumps.
+ * Note that nrates can only take the values 1 through 4.
+ */
+ calculated_tries[i] = min_t(int, ((15 >> nrates) | 1) + 1,
+ info->control.rates[i].count);
+ nremaining -= calculated_tries[i];
+ }
+
+ /* if there are tries left, distribute from back to front */
+ for (i = nrates - 1; nremaining > 0 && i >= 0; i--) {
+ int tmp = info->control.rates[i].count - calculated_tries[i];
+
+ if (tmp <= 0)
+ continue;
+ /* RC requested more tries at this rate */
+
+ tmp = min_t(int, tmp, nremaining);
+ calculated_tries[i] += tmp;
+ nremaining -= tmp;
+ }
+
+ ridx = 0;
+ for (i = 0; i < nrates && ridx < 8; i++) {
+ /* we register the rates in perfect order */
+ rate = info->control.rates[i].idx;
+ if (info->band == IEEE80211_BAND_5GHZ)
+ rate += 4;
+
+ /* store the count we actually calculated for TX status */
+ info->control.rates[i].count = calculated_tries[i];
+
+ rc_flags = info->control.rates[i].flags;
+ if (rc_flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) {
+ rate |= 0x10;
+ cts_rate |= 0x10;
+ }
+ if (rc_flags & IEEE80211_TX_RC_USE_RTS_CTS) {
+ burst_allowed = false;
+ rate |= 0x40;
+ } else if (rc_flags & IEEE80211_TX_RC_USE_CTS_PROTECT) {
+ rate |= 0x20;
+ burst_allowed = false;
+ }
+ for (j = 0; j < calculated_tries[i] && ridx < 8; j++) {
+ txhdr->rateset[ridx] = rate;
+ ridx++;
+ }
+ }
+
+ if (burst_allowed)
+ hdr_flags |= P54_HDR_FLAG_DATA_OUT_BURST;
+
+ /* TODO: enable bursting */
+ hdr->flags = cpu_to_le16(hdr_flags);
+ hdr->tries = ridx;
+ txhdr->rts_rate_idx = 0;
+ if (info->control.hw_key) {
+ txhdr->key_type = p54_convert_algo(info->control.hw_key->alg);
+ txhdr->key_len = min((u8)16, info->control.hw_key->keylen);
+ memcpy(txhdr->key, info->control.hw_key->key, txhdr->key_len);
+ if (info->control.hw_key->alg == ALG_TKIP) {
+ /* reserve space for the MIC key */
+ len += 8;
+ memcpy(skb_put(skb, 8), &(info->control.hw_key->key
+ [NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY]), 8);
+ }
+ /* reserve some space for ICV */
+ len += info->control.hw_key->icv_len;
+ memset(skb_put(skb, info->control.hw_key->icv_len), 0,
+ info->control.hw_key->icv_len);
+ } else {
+ txhdr->key_type = 0;
+ txhdr->key_len = 0;
+ }
+ txhdr->crypt_offset = crypt_offset;
+ txhdr->hw_queue = queue;
+ txhdr->backlog = priv->tx_stats[queue].len - 1;
+ memset(txhdr->durations, 0, sizeof(txhdr->durations));
+ txhdr->tx_antenna = ((info->antenna_sel_tx == 0) ?
+ 2 : info->antenna_sel_tx - 1) & priv->tx_diversity_mask;
+ if (priv->rxhw == 5) {
+ txhdr->longbow.cts_rate = cts_rate;
+ txhdr->longbow.output_power = cpu_to_le16(priv->output_power);
+ } else {
+ txhdr->normal.output_power = priv->output_power;
+ txhdr->normal.cts_rate = cts_rate;
+ }
+ if (padding)
+ txhdr->align[0] = padding;
+
+ hdr->len = cpu_to_le16(len);
+ /* modifies skb->cb and with it info, so must be last! */
+ p54info = (void *) info->rate_driver_data;
+ p54info->extra_len = extra_len;
+
+ p54_tx(priv, skb);
+ return NETDEV_TX_OK;
+}
diff --git a/drivers/net/wireless/prism54/islpci_eth.c b/drivers/net/wireless/prism54/islpci_eth.c
index 8f621099344..c255d9c6a5f 100644
--- a/drivers/net/wireless/prism54/islpci_eth.c
+++ b/drivers/net/wireless/prism54/islpci_eth.c
@@ -234,7 +234,7 @@ islpci_eth_transmit(struct sk_buff *skb, struct net_device *ndev)
/* unlock the driver code */
spin_unlock_irqrestore(&priv->slock, flags);
- return 0;
+ return NETDEV_TX_OK;
drop_free:
ndev->stats.tx_dropped++;
diff --git a/drivers/net/wireless/prism54/islpci_hotplug.c b/drivers/net/wireless/prism54/islpci_hotplug.c
index 30876728d7e..83d366258c8 100644
--- a/drivers/net/wireless/prism54/islpci_hotplug.c
+++ b/drivers/net/wireless/prism54/islpci_hotplug.c
@@ -49,9 +49,7 @@ static const struct pci_device_id prism54_id_tbl[] = {
/* 3COM 3CRWE154G72 Wireless LAN adapter */
{
- 0x10b7, 0x6001,
- PCI_ANY_ID, PCI_ANY_ID,
- 0, 0, 0
+ PCI_VDEVICE(3COM, 0x6001), 0
},
/* Intersil PRISM Indigo Wireless LAN adapter */
diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c
index 698b11b1cad..325206969c9 100644
--- a/drivers/net/wireless/ray_cs.c
+++ b/drivers/net/wireless/ray_cs.c
@@ -937,7 +937,7 @@ static int ray_dev_start_xmit(struct sk_buff *skb, struct net_device *dev)
if (length < ETH_ZLEN) {
if (skb_padto(skb, ETH_ZLEN))
- return 0;
+ return NETDEV_TX_OK;
length = ETH_ZLEN;
}
switch (ray_hw_xmit(skb->data, length, dev, DATA_TYPE)) {
@@ -951,9 +951,9 @@ static int ray_dev_start_xmit(struct sk_buff *skb, struct net_device *dev)
default:
dev->trans_start = jiffies;
dev_kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
}
- return 0;
+ return NETDEV_TX_OK;
} /* ray_dev_start_xmit */
/*===========================================================================*/
@@ -1511,9 +1511,6 @@ static iw_stats *ray_get_wireless_stats(struct net_device *dev)
struct pcmcia_device *link = local->finder;
struct status __iomem *p = local->sram + STATUS_BASE;
- if (local == (ray_dev_t *) NULL)
- return (iw_stats *) NULL;
-
local->wstats.status = local->card_status;
#ifdef WIRELESS_SPY
if ((local->spy_data.spy_number > 0)
diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c
index 3bec3dbd345..d42692dfbc6 100644
--- a/drivers/net/wireless/rndis_wlan.c
+++ b/drivers/net/wireless/rndis_wlan.c
@@ -100,7 +100,6 @@ MODULE_PARM_DESC(workaround_interval,
#define OID_GEN_RCV_ERROR cpu_to_le32(0x00020104)
#define OID_GEN_RCV_NO_BUFFER cpu_to_le32(0x00020105)
-#define OID_802_3_PERMANENT_ADDRESS cpu_to_le32(0x01010101)
#define OID_802_3_CURRENT_ADDRESS cpu_to_le32(0x01010102)
#define OID_802_3_MULTICAST_LIST cpu_to_le32(0x01010103)
#define OID_802_3_MAXIMUM_LIST_SIZE cpu_to_le32(0x01010104)
@@ -139,9 +138,15 @@ MODULE_PARM_DESC(workaround_interval,
/* Assume that Broadcom 4320 (only chipset at time of writing known to be
* based on wireless rndis) has default txpower of 13dBm.
* This value is from Linksys WUSB54GSC User Guide, Appendix F: Specifications.
- * 13dBm == 19.9mW
+ * 100% : 20 mW ~ 13dBm
+ * 75% : 15 mW ~ 12dBm
+ * 50% : 10 mW ~ 10dBm
+ * 25% : 5 mW ~ 7dBm
*/
-#define BCM4320_DEFAULT_TXPOWER 20
+#define BCM4320_DEFAULT_TXPOWER_DBM_100 13
+#define BCM4320_DEFAULT_TXPOWER_DBM_75 12
+#define BCM4320_DEFAULT_TXPOWER_DBM_50 10
+#define BCM4320_DEFAULT_TXPOWER_DBM_25 7
/* codes for "status" field of completion messages */
@@ -196,6 +201,24 @@ enum ndis_80211_priv_filter {
NDIS_80211_PRIV_8021X_WEP
};
+enum ndis_80211_status_type {
+ NDIS_80211_STATUSTYPE_AUTHENTICATION,
+ NDIS_80211_STATUSTYPE_MEDIASTREAMMODE,
+ NDIS_80211_STATUSTYPE_PMKID_CANDIDATELIST,
+ NDIS_80211_STATUSTYPE_RADIOSTATE,
+};
+
+enum ndis_80211_media_stream_mode {
+ NDIS_80211_MEDIA_STREAM_OFF,
+ NDIS_80211_MEDIA_STREAM_ON
+};
+
+enum ndis_80211_radio_status {
+ NDIS_80211_RADIO_STATUS_ON,
+ NDIS_80211_RADIO_STATUS_HARDWARE_OFF,
+ NDIS_80211_RADIO_STATUS_SOFTWARE_OFF,
+};
+
enum ndis_80211_addkey_bits {
NDIS_80211_ADDKEY_8021X_AUTH = cpu_to_le32(1 << 28),
NDIS_80211_ADDKEY_SET_INIT_RECV_SEQ = cpu_to_le32(1 << 29),
@@ -208,6 +231,35 @@ enum ndis_80211_addwep_bits {
NDIS_80211_ADDWEP_TRANSMIT_KEY = cpu_to_le32(1 << 31)
};
+struct ndis_80211_auth_request {
+ __le32 length;
+ u8 bssid[6];
+ u8 padding[2];
+ __le32 flags;
+} __attribute__((packed));
+
+struct ndis_80211_pmkid_candidate {
+ u8 bssid[6];
+ u8 padding[2];
+ __le32 flags;
+} __attribute__((packed));
+
+struct ndis_80211_pmkid_cand_list {
+ __le32 version;
+ __le32 num_candidates;
+ struct ndis_80211_pmkid_candidate candidate_list[0];
+} __attribute__((packed));
+
+struct ndis_80211_status_indication {
+ __le32 status_type;
+ union {
+ enum ndis_80211_media_stream_mode media_stream_mode;
+ enum ndis_80211_radio_status radio_status;
+ struct ndis_80211_auth_request auth_request[0];
+ struct ndis_80211_pmkid_cand_list cand_list;
+ } u;
+} __attribute__((packed));
+
struct ndis_80211_ssid {
__le32 length;
u8 essid[NDIS_802_11_LENGTH_SSID];
@@ -275,6 +327,7 @@ struct ndis_80211_remove_key {
__le32 size;
__le32 index;
u8 bssid[6];
+ u8 padding[2];
} __attribute__((packed));
struct ndis_config_param {
@@ -360,6 +413,15 @@ static const struct ieee80211_rate rndis_rates[] = {
{ .bitrate = 540 }
};
+struct rndis_wlan_encr_key {
+ int len;
+ int cipher;
+ u8 material[32];
+ u8 bssid[ETH_ALEN];
+ bool pairwise;
+ bool tx_key;
+};
+
/* RNDIS device private data */
struct rndis_wlan_private {
struct usbnet *usbdev;
@@ -403,9 +465,7 @@ struct rndis_wlan_private {
/* encryption stuff */
int encr_tx_key_index;
- char encr_keys[4][32];
- int encr_key_len[4];
- char encr_key_wpa[4];
+ struct rndis_wlan_encr_key encr_keys[4];
int wpa_version;
int wpa_keymgmt;
int wpa_authalg;
@@ -420,21 +480,30 @@ struct rndis_wlan_private {
/*
* cfg80211 ops
*/
-static int rndis_change_virtual_intf(struct wiphy *wiphy, int ifindex,
+static int rndis_change_virtual_intf(struct wiphy *wiphy,
+ struct net_device *dev,
enum nl80211_iftype type, u32 *flags,
struct vif_params *params);
static int rndis_scan(struct wiphy *wiphy, struct net_device *dev,
struct cfg80211_scan_request *request);
+static int rndis_set_wiphy_params(struct wiphy *wiphy, u32 changed);
+
+static int rndis_set_tx_power(struct wiphy *wiphy, enum tx_power_setting type,
+ int dbm);
+static int rndis_get_tx_power(struct wiphy *wiphy, int *dbm);
+
static struct cfg80211_ops rndis_config_ops = {
.change_virtual_intf = rndis_change_virtual_intf,
.scan = rndis_scan,
+ .set_wiphy_params = rndis_set_wiphy_params,
+ .set_tx_power = rndis_set_tx_power,
+ .get_tx_power = rndis_get_tx_power,
};
static void *rndis_wiphy_privid = &rndis_wiphy_privid;
-static const int bcm4320_power_output[4] = { 25, 50, 75, 100 };
static const unsigned char zero_bssid[ETH_ALEN] = {0,};
static const unsigned char ffff_bssid[ETH_ALEN] = { 0xff, 0xff, 0xff,
@@ -447,13 +516,93 @@ static struct rndis_wlan_private *get_rndis_wlan_priv(struct usbnet *dev)
}
-static u32 get_bcm4320_power(struct rndis_wlan_private *priv)
+static u32 get_bcm4320_power_dbm(struct rndis_wlan_private *priv)
+{
+ switch (priv->param_power_output) {
+ default:
+ case 3:
+ return BCM4320_DEFAULT_TXPOWER_DBM_100;
+ case 2:
+ return BCM4320_DEFAULT_TXPOWER_DBM_75;
+ case 1:
+ return BCM4320_DEFAULT_TXPOWER_DBM_50;
+ case 0:
+ return BCM4320_DEFAULT_TXPOWER_DBM_25;
+ }
+}
+
+
+static bool is_wpa_key(struct rndis_wlan_private *priv, int idx)
{
- return BCM4320_DEFAULT_TXPOWER *
- bcm4320_power_output[priv->param_power_output] / 100;
+ int cipher = priv->encr_keys[idx].cipher;
+
+ return (cipher == WLAN_CIPHER_SUITE_CCMP ||
+ cipher == WLAN_CIPHER_SUITE_TKIP);
}
+#ifdef DEBUG
+static const char *oid_to_string(__le32 oid)
+{
+ switch (oid) {
+#define OID_STR(oid) case oid: return(#oid)
+ /* from rndis_host.h */
+ OID_STR(OID_802_3_PERMANENT_ADDRESS);
+ OID_STR(OID_GEN_MAXIMUM_FRAME_SIZE);
+ OID_STR(OID_GEN_CURRENT_PACKET_FILTER);
+ OID_STR(OID_GEN_PHYSICAL_MEDIUM);
+
+ /* from rndis_wlan.c */
+ OID_STR(OID_GEN_LINK_SPEED);
+ OID_STR(OID_GEN_RNDIS_CONFIG_PARAMETER);
+
+ OID_STR(OID_GEN_XMIT_OK);
+ OID_STR(OID_GEN_RCV_OK);
+ OID_STR(OID_GEN_XMIT_ERROR);
+ OID_STR(OID_GEN_RCV_ERROR);
+ OID_STR(OID_GEN_RCV_NO_BUFFER);
+
+ OID_STR(OID_802_3_CURRENT_ADDRESS);
+ OID_STR(OID_802_3_MULTICAST_LIST);
+ OID_STR(OID_802_3_MAXIMUM_LIST_SIZE);
+
+ OID_STR(OID_802_11_BSSID);
+ OID_STR(OID_802_11_SSID);
+ OID_STR(OID_802_11_INFRASTRUCTURE_MODE);
+ OID_STR(OID_802_11_ADD_WEP);
+ OID_STR(OID_802_11_REMOVE_WEP);
+ OID_STR(OID_802_11_DISASSOCIATE);
+ OID_STR(OID_802_11_AUTHENTICATION_MODE);
+ OID_STR(OID_802_11_PRIVACY_FILTER);
+ OID_STR(OID_802_11_BSSID_LIST_SCAN);
+ OID_STR(OID_802_11_ENCRYPTION_STATUS);
+ OID_STR(OID_802_11_ADD_KEY);
+ OID_STR(OID_802_11_REMOVE_KEY);
+ OID_STR(OID_802_11_ASSOCIATION_INFORMATION);
+ OID_STR(OID_802_11_PMKID);
+ OID_STR(OID_802_11_NETWORK_TYPES_SUPPORTED);
+ OID_STR(OID_802_11_NETWORK_TYPE_IN_USE);
+ OID_STR(OID_802_11_TX_POWER_LEVEL);
+ OID_STR(OID_802_11_RSSI);
+ OID_STR(OID_802_11_RSSI_TRIGGER);
+ OID_STR(OID_802_11_FRAGMENTATION_THRESHOLD);
+ OID_STR(OID_802_11_RTS_THRESHOLD);
+ OID_STR(OID_802_11_SUPPORTED_RATES);
+ OID_STR(OID_802_11_CONFIGURATION);
+ OID_STR(OID_802_11_BSSID_LIST);
+#undef OID_STR
+ }
+
+ return "?";
+}
+#else
+static const char *oid_to_string(__le32 oid)
+{
+ return "?";
+}
+#endif
+
+
/* translate error code */
static int rndis_error_status(__le32 rndis_status)
{
@@ -509,11 +658,21 @@ static int rndis_query_oid(struct usbnet *dev, __le32 oid, void *data, int *len)
u.get->oid = oid;
ret = rndis_command(dev, u.header, buflen);
+ if (ret < 0)
+ devdbg(dev, "rndis_query_oid(%s): rndis_command() failed, %d "
+ "(%08x)", oid_to_string(oid), ret,
+ le32_to_cpu(u.get_c->status));
+
if (ret == 0) {
ret = le32_to_cpu(u.get_c->len);
*len = (*len > ret) ? ret : *len;
memcpy(data, u.buf + le32_to_cpu(u.get_c->offset) + 8, *len);
ret = rndis_error_status(u.get_c->status);
+
+ if (ret < 0)
+ devdbg(dev, "rndis_query_oid(%s): device returned "
+ "error, 0x%08x (%d)", oid_to_string(oid),
+ le32_to_cpu(u.get_c->status), ret);
}
mutex_unlock(&priv->command_lock);
@@ -559,9 +718,20 @@ static int rndis_set_oid(struct usbnet *dev, __le32 oid, void *data, int len)
memcpy(u.buf + sizeof(*u.set), data, len);
ret = rndis_command(dev, u.header, buflen);
- if (ret == 0)
+ if (ret < 0)
+ devdbg(dev, "rndis_set_oid(%s): rndis_command() failed, %d "
+ "(%08x)", oid_to_string(oid), ret,
+ le32_to_cpu(u.set_c->status));
+
+ if (ret == 0) {
ret = rndis_error_status(u.set_c->status);
+ if (ret < 0)
+ devdbg(dev, "rndis_set_oid(%s): device returned error, "
+ "0x%08x (%d)", oid_to_string(oid),
+ le32_to_cpu(u.set_c->status), ret);
+ }
+
mutex_unlock(&priv->command_lock);
if (u.buf != priv->command_buffer)
@@ -570,6 +740,28 @@ static int rndis_set_oid(struct usbnet *dev, __le32 oid, void *data, int len)
}
+static int rndis_reset(struct usbnet *usbdev)
+{
+ struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
+ struct rndis_reset *reset;
+ int ret;
+
+ mutex_lock(&priv->command_lock);
+
+ reset = (void *)priv->command_buffer;
+ memset(reset, 0, sizeof(*reset));
+ reset->msg_type = RNDIS_MSG_RESET;
+ reset->msg_len = cpu_to_le32(sizeof(*reset));
+ ret = rndis_command(usbdev, (void *)reset, CONTROL_BUFFER_SIZE);
+
+ mutex_unlock(&priv->command_lock);
+
+ if (ret < 0)
+ return ret;
+ return 0;
+}
+
+
/*
* Specs say that we can only set config parameters only soon after device
* initialization.
@@ -719,8 +911,7 @@ static int freq_to_dsconfig(struct iw_freq *freq, unsigned int *dsconfig)
/*
* common functions
*/
-static int
-add_wep_key(struct usbnet *usbdev, char *key, int key_len, int index);
+static void restore_keys(struct usbnet *usbdev);
static int get_essid(struct usbnet *usbdev, struct ndis_80211_ssid *ssid)
{
@@ -939,7 +1130,7 @@ static int set_infra_mode(struct usbnet *usbdev, int mode)
{
struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
__le32 tmp;
- int ret, i;
+ int ret;
devdbg(usbdev, "set_infra_mode: infra_mode=0x%x", priv->infra_mode);
@@ -954,20 +1145,43 @@ static int set_infra_mode(struct usbnet *usbdev, int mode)
/* NDIS drivers clear keys when infrastructure mode is
* changed. But Linux tools assume otherwise. So set the
* keys */
- if (priv->wpa_keymgmt == 0 ||
- priv->wpa_keymgmt == IW_AUTH_KEY_MGMT_802_1X) {
- for (i = 0; i < 4; i++) {
- if (priv->encr_key_len[i] > 0 && !priv->encr_key_wpa[i])
- add_wep_key(usbdev, priv->encr_keys[i],
- priv->encr_key_len[i], i);
- }
- }
+ restore_keys(usbdev);
priv->infra_mode = mode;
return 0;
}
+static int set_rts_threshold(struct usbnet *usbdev, u32 rts_threshold)
+{
+ __le32 tmp;
+
+ devdbg(usbdev, "set_rts_threshold %i", rts_threshold);
+
+ if (rts_threshold < 0 || rts_threshold > 2347)
+ rts_threshold = 2347;
+
+ tmp = cpu_to_le32(rts_threshold);
+ return rndis_set_oid(usbdev, OID_802_11_RTS_THRESHOLD, &tmp,
+ sizeof(tmp));
+}
+
+
+static int set_frag_threshold(struct usbnet *usbdev, u32 frag_threshold)
+{
+ __le32 tmp;
+
+ devdbg(usbdev, "set_frag_threshold %i", frag_threshold);
+
+ if (frag_threshold < 256 || frag_threshold > 2346)
+ frag_threshold = 2346;
+
+ tmp = cpu_to_le32(frag_threshold);
+ return rndis_set_oid(usbdev, OID_802_11_FRAGMENTATION_THRESHOLD, &tmp,
+ sizeof(tmp));
+}
+
+
static void set_default_iw_params(struct usbnet *usbdev)
{
struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
@@ -998,11 +1212,16 @@ static int add_wep_key(struct usbnet *usbdev, char *key, int key_len, int index)
{
struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
struct ndis_80211_wep_key ndis_key;
- int ret;
+ int cipher, ret;
- if (key_len <= 0 || key_len > 32 || index < 0 || index >= 4)
+ if ((key_len != 5 || key_len != 13) || index < 0 || index > 3)
return -EINVAL;
+ if (key_len == 5)
+ cipher = WLAN_CIPHER_SUITE_WEP40;
+ else
+ cipher = WLAN_CIPHER_SUITE_WEP104;
+
memset(&ndis_key, 0, sizeof(ndis_key));
ndis_key.size = cpu_to_le32(sizeof(ndis_key));
@@ -1027,30 +1246,44 @@ static int add_wep_key(struct usbnet *usbdev, char *key, int key_len, int index)
return ret;
}
- priv->encr_key_len[index] = key_len;
- priv->encr_key_wpa[index] = 0;
- memcpy(&priv->encr_keys[index], key, key_len);
+ priv->encr_keys[index].len = key_len;
+ priv->encr_keys[index].cipher = cipher;
+ memcpy(&priv->encr_keys[index].material, key, key_len);
+ memset(&priv->encr_keys[index].bssid, 0xff, ETH_ALEN);
return 0;
}
static int add_wpa_key(struct usbnet *usbdev, const u8 *key, int key_len,
- int index, const struct sockaddr *addr,
- const u8 *rx_seq, int alg, int flags)
+ int index, const u8 *addr, const u8 *rx_seq, int cipher,
+ int flags)
{
struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
struct ndis_80211_key ndis_key;
+ bool is_addr_ok;
int ret;
- if (index < 0 || index >= 4)
+ if (index < 0 || index >= 4) {
+ devdbg(usbdev, "add_wpa_key: index out of range (%i)", index);
return -EINVAL;
- if (key_len > sizeof(ndis_key.material) || key_len < 0)
+ }
+ if (key_len > sizeof(ndis_key.material) || key_len < 0) {
+ devdbg(usbdev, "add_wpa_key: key length out of range (%i)",
+ key_len);
return -EINVAL;
- if ((flags & NDIS_80211_ADDKEY_SET_INIT_RECV_SEQ) && !rx_seq)
+ }
+ if ((flags & NDIS_80211_ADDKEY_SET_INIT_RECV_SEQ) && !rx_seq) {
+ devdbg(usbdev, "add_wpa_key: recv seq flag without buffer");
return -EINVAL;
- if ((flags & NDIS_80211_ADDKEY_PAIRWISE_KEY) && !addr)
+ }
+ is_addr_ok = addr && memcmp(addr, zero_bssid, ETH_ALEN) != 0 &&
+ memcmp(addr, ffff_bssid, ETH_ALEN) != 0;
+ if ((flags & NDIS_80211_ADDKEY_PAIRWISE_KEY) && !is_addr_ok) {
+ devdbg(usbdev, "add_wpa_key: pairwise but bssid invalid (%pM)",
+ addr);
return -EINVAL;
+ }
devdbg(usbdev, "add_wpa_key(%i): flags:%i%i%i", index,
!!(flags & NDIS_80211_ADDKEY_TRANSMIT_KEY),
@@ -1064,7 +1297,7 @@ static int add_wpa_key(struct usbnet *usbdev, const u8 *key, int key_len,
ndis_key.length = cpu_to_le32(key_len);
ndis_key.index = cpu_to_le32(index) | flags;
- if (alg == IW_ENCODE_ALG_TKIP && key_len == 32) {
+ if (cipher == WLAN_CIPHER_SUITE_TKIP && key_len == 32) {
/* wpa_supplicant gives us the Michael MIC RX/TX keys in
* different order than NDIS spec, so swap the order here. */
memcpy(ndis_key.material, key, 16);
@@ -1078,7 +1311,7 @@ static int add_wpa_key(struct usbnet *usbdev, const u8 *key, int key_len,
if (flags & NDIS_80211_ADDKEY_PAIRWISE_KEY) {
/* pairwise key */
- memcpy(ndis_key.bssid, addr->sa_data, ETH_ALEN);
+ memcpy(ndis_key.bssid, addr, ETH_ALEN);
} else {
/* group key */
if (priv->infra_mode == NDIS_80211_INFRA_ADHOC)
@@ -1093,8 +1326,14 @@ static int add_wpa_key(struct usbnet *usbdev, const u8 *key, int key_len,
if (ret != 0)
return ret;
- priv->encr_key_len[index] = key_len;
- priv->encr_key_wpa[index] = 1;
+ memset(&priv->encr_keys[index], 0, sizeof(priv->encr_keys[index]));
+ priv->encr_keys[index].len = key_len;
+ priv->encr_keys[index].cipher = cipher;
+ memcpy(&priv->encr_keys[index].material, key, key_len);
+ if (flags & NDIS_80211_ADDKEY_PAIRWISE_KEY)
+ memcpy(&priv->encr_keys[index].bssid, ndis_key.bssid, ETH_ALEN);
+ else
+ memset(&priv->encr_keys[index].bssid, 0xff, ETH_ALEN);
if (flags & NDIS_80211_ADDKEY_TRANSMIT_KEY)
priv->encr_tx_key_index = index;
@@ -1103,25 +1342,74 @@ static int add_wpa_key(struct usbnet *usbdev, const u8 *key, int key_len,
}
+static int restore_key(struct usbnet *usbdev, int key_idx)
+{
+ struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
+ struct rndis_wlan_encr_key key;
+ int flags;
+
+ key = priv->encr_keys[key_idx];
+
+ devdbg(usbdev, "restore_key: %i:%s:%i", key_idx,
+ is_wpa_key(priv, key_idx) ? "wpa" : "wep",
+ key.len);
+
+ if (key.len == 0)
+ return 0;
+
+ if (is_wpa_key(priv, key_idx)) {
+ flags = 0;
+
+ /*if (priv->encr_tx_key_index == key_idx)
+ flags |= NDIS_80211_ADDKEY_TRANSMIT_KEY;*/
+
+ if (memcmp(key.bssid, zero_bssid, ETH_ALEN) != 0 &&
+ memcmp(key.bssid, ffff_bssid, ETH_ALEN) != 0)
+ flags |= NDIS_80211_ADDKEY_PAIRWISE_KEY;
+
+ return add_wpa_key(usbdev, key.material, key.len, key_idx,
+ key.bssid, NULL, key.cipher, flags);
+ }
+
+ return add_wep_key(usbdev, key.material, key.len, key_idx);
+}
+
+
+static void restore_keys(struct usbnet *usbdev)
+{
+ int i;
+
+ for (i = 0; i < 4; i++)
+ restore_key(usbdev, i);
+}
+
+
+static void clear_key(struct rndis_wlan_private *priv, int idx)
+{
+ memset(&priv->encr_keys[idx], 0, sizeof(priv->encr_keys[idx]));
+}
+
+
/* remove_key is for both wep and wpa */
static int remove_key(struct usbnet *usbdev, int index, u8 bssid[ETH_ALEN])
{
struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
struct ndis_80211_remove_key remove_key;
__le32 keyindex;
+ bool is_wpa;
int ret;
- if (priv->encr_key_len[index] == 0)
+ if (priv->encr_keys[index].len == 0)
return 0;
- priv->encr_key_len[index] = 0;
- priv->encr_key_wpa[index] = 0;
- memset(&priv->encr_keys[index], 0, sizeof(priv->encr_keys[index]));
+ is_wpa = is_wpa_key(priv, index);
+
+ devdbg(usbdev, "remove_key: %i:%s:%i", index, is_wpa ? "wpa" : "wep",
+ priv->encr_keys[index].len);
- if (priv->wpa_cipher_pair == IW_AUTH_CIPHER_TKIP ||
- priv->wpa_cipher_pair == IW_AUTH_CIPHER_CCMP ||
- priv->wpa_cipher_group == IW_AUTH_CIPHER_TKIP ||
- priv->wpa_cipher_group == IW_AUTH_CIPHER_CCMP) {
+ clear_key(priv, index);
+
+ if (is_wpa) {
remove_key.size = cpu_to_le32(sizeof(remove_key));
remove_key.index = cpu_to_le32(index);
if (bssid) {
@@ -1222,20 +1510,14 @@ static void set_multicast_list(struct usbnet *usbdev)
/*
* cfg80211 ops
*/
-static int rndis_change_virtual_intf(struct wiphy *wiphy, int ifindex,
+static int rndis_change_virtual_intf(struct wiphy *wiphy,
+ struct net_device *dev,
enum nl80211_iftype type, u32 *flags,
struct vif_params *params)
{
- struct net_device *dev;
- struct usbnet *usbdev;
+ struct usbnet *usbdev = netdev_priv(dev);
int mode;
- /* we're under RTNL */
- dev = __dev_get_by_index(&init_net, ifindex);
- if (!dev)
- return -ENODEV;
- usbdev = netdev_priv(dev);
-
switch (type) {
case NL80211_IFTYPE_ADHOC:
mode = NDIS_80211_INFRA_ADHOC;
@@ -1251,6 +1533,64 @@ static int rndis_change_virtual_intf(struct wiphy *wiphy, int ifindex,
}
+static int rndis_set_wiphy_params(struct wiphy *wiphy, u32 changed)
+{
+ struct rndis_wlan_private *priv = wiphy_priv(wiphy);
+ struct usbnet *usbdev = priv->usbdev;
+ int err;
+
+ if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
+ err = set_frag_threshold(usbdev, wiphy->frag_threshold);
+ if (err < 0)
+ return err;
+ }
+
+ if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
+ err = set_rts_threshold(usbdev, wiphy->rts_threshold);
+ if (err < 0)
+ return err;
+ }
+
+ return 0;
+}
+
+
+static int rndis_set_tx_power(struct wiphy *wiphy, enum tx_power_setting type,
+ int dbm)
+{
+ struct rndis_wlan_private *priv = wiphy_priv(wiphy);
+ struct usbnet *usbdev = priv->usbdev;
+
+ devdbg(usbdev, "rndis_set_tx_power type:0x%x dbm:%i", type, dbm);
+
+ /* Device doesn't support changing txpower after initialization, only
+ * turn off/on radio. Support 'auto' mode and setting same dBm that is
+ * currently used.
+ */
+ if (type == TX_POWER_AUTOMATIC || dbm == get_bcm4320_power_dbm(priv)) {
+ if (!priv->radio_on)
+ disassociate(usbdev, 1); /* turn on radio */
+
+ return 0;
+ }
+
+ return -ENOTSUPP;
+}
+
+
+static int rndis_get_tx_power(struct wiphy *wiphy, int *dbm)
+{
+ struct rndis_wlan_private *priv = wiphy_priv(wiphy);
+ struct usbnet *usbdev = priv->usbdev;
+
+ *dbm = get_bcm4320_power_dbm(priv);
+
+ devdbg(usbdev, "rndis_get_tx_power dbm:%i", *dbm);
+
+ return 0;
+}
+
+
#define SCAN_DELAY_JIFFIES (HZ)
static int rndis_scan(struct wiphy *wiphy, struct net_device *dev,
struct cfg80211_scan_request *request)
@@ -1378,6 +1718,9 @@ static void rndis_get_scan_results(struct work_struct *work)
devdbg(usbdev, "get_scan_results");
+ if (!priv->scan_request)
+ return;
+
ret = rndis_check_bssid_list(usbdev);
cfg80211_scan_done(priv->scan_request, ret < 0);
@@ -1421,8 +1764,15 @@ static int rndis_iw_set_essid(struct net_device *dev,
if (!wrqu->essid.flags || length == 0)
return disassociate(usbdev, 1);
- else
+ else {
+ /* Pause and purge rx queue, so we don't pass packets before
+ * 'media connect'-indication.
+ */
+ usbnet_pause_rx(usbdev);
+ usbnet_purge_paused_rxq(usbdev);
+
return set_essid(usbdev, &ssid);
+ }
}
@@ -1610,8 +1960,9 @@ static int rndis_iw_set_encode(struct net_device *dev,
{
struct usbnet *usbdev = netdev_priv(dev);
struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
+ struct rndis_wlan_encr_key key;
int ret, index, key_len;
- u8 *key;
+ u8 *keybuf;
index = (wrqu->encoding.flags & IW_ENCODE_INDEX);
@@ -1646,17 +1997,18 @@ static int rndis_iw_set_encode(struct net_device *dev,
if (wrqu->data.length > 0) {
key_len = wrqu->data.length;
- key = extra;
+ keybuf = extra;
} else {
/* must be set as tx key */
- if (priv->encr_key_len[index] == 0)
+ if (priv->encr_keys[index].len == 0)
return -EINVAL;
- key_len = priv->encr_key_len[index];
key = priv->encr_keys[index];
+ key_len = key.len;
+ keybuf = key.material;
priv->encr_tx_key_index = index;
}
- if (add_wep_key(usbdev, key, key_len, index) != 0)
+ if (add_wep_key(usbdev, keybuf, key_len, index) != 0)
return -EINVAL;
if (index == priv->encr_tx_key_index)
@@ -1673,7 +2025,7 @@ static int rndis_iw_set_encode_ext(struct net_device *dev,
struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
struct usbnet *usbdev = netdev_priv(dev);
struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
- int keyidx, flags;
+ int keyidx, flags, cipher;
keyidx = wrqu->encoding.flags & IW_ENCODE_INDEX;
@@ -1683,8 +2035,10 @@ static int rndis_iw_set_encode_ext(struct net_device *dev,
else
keyidx = priv->encr_tx_key_index;
- if (keyidx < 0 || keyidx >= 4)
+ if (keyidx < 0 || keyidx >= 4) {
+ devwarn(usbdev, "encryption index out of range (%u)", keyidx);
return -EINVAL;
+ }
if (ext->alg == WPA_ALG_WEP) {
if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)
@@ -1692,10 +2046,19 @@ static int rndis_iw_set_encode_ext(struct net_device *dev,
return add_wep_key(usbdev, ext->key, ext->key_len, keyidx);
}
+ cipher = -1;
+ if (ext->alg == IW_ENCODE_ALG_TKIP)
+ cipher = WLAN_CIPHER_SUITE_TKIP;
+ else if (ext->alg == IW_ENCODE_ALG_CCMP)
+ cipher = WLAN_CIPHER_SUITE_CCMP;
+
if ((wrqu->encoding.flags & IW_ENCODE_DISABLED) ||
ext->alg == IW_ENCODE_ALG_NONE || ext->key_len == 0)
return remove_key(usbdev, keyidx, NULL);
+ if (cipher == -1)
+ return -EOPNOTSUPP;
+
flags = 0;
if (ext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID)
flags |= NDIS_80211_ADDKEY_SET_INIT_RECV_SEQ;
@@ -1704,8 +2067,9 @@ static int rndis_iw_set_encode_ext(struct net_device *dev,
if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)
flags |= NDIS_80211_ADDKEY_TRANSMIT_KEY;
- return add_wpa_key(usbdev, ext->key, ext->key_len, keyidx, &ext->addr,
- ext->rx_seq, ext->alg, flags);
+ return add_wpa_key(usbdev, ext->key, ext->key_len, keyidx,
+ (u8 *)&ext->addr.sa_data, ext->rx_seq, cipher,
+ flags);
}
@@ -1766,74 +2130,6 @@ static int rndis_iw_get_genie(struct net_device *dev,
}
-static int rndis_iw_set_rts(struct net_device *dev,
- struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
-{
- struct usbnet *usbdev = netdev_priv(dev);
- __le32 tmp;
- devdbg(usbdev, "SIOCSIWRTS");
-
- tmp = cpu_to_le32(wrqu->rts.value);
- return rndis_set_oid(usbdev, OID_802_11_RTS_THRESHOLD, &tmp,
- sizeof(tmp));
-}
-
-
-static int rndis_iw_get_rts(struct net_device *dev,
- struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
-{
- struct usbnet *usbdev = netdev_priv(dev);
- __le32 tmp;
- int len, ret;
-
- len = sizeof(tmp);
- ret = rndis_query_oid(usbdev, OID_802_11_RTS_THRESHOLD, &tmp, &len);
- if (ret == 0) {
- wrqu->rts.value = le32_to_cpu(tmp);
- wrqu->rts.flags = 1;
- wrqu->rts.disabled = 0;
- }
-
- devdbg(usbdev, "SIOCGIWRTS: %d", wrqu->rts.value);
-
- return ret;
-}
-
-
-static int rndis_iw_set_frag(struct net_device *dev,
- struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
-{
- struct usbnet *usbdev = netdev_priv(dev);
- __le32 tmp;
-
- devdbg(usbdev, "SIOCSIWFRAG");
-
- tmp = cpu_to_le32(wrqu->frag.value);
- return rndis_set_oid(usbdev, OID_802_11_FRAGMENTATION_THRESHOLD, &tmp,
- sizeof(tmp));
-}
-
-
-static int rndis_iw_get_frag(struct net_device *dev,
- struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
-{
- struct usbnet *usbdev = netdev_priv(dev);
- __le32 tmp;
- int len, ret;
-
- len = sizeof(tmp);
- ret = rndis_query_oid(usbdev, OID_802_11_FRAGMENTATION_THRESHOLD, &tmp,
- &len);
- if (ret == 0) {
- wrqu->frag.value = le32_to_cpu(tmp);
- wrqu->frag.flags = 1;
- wrqu->frag.disabled = 0;
- }
- devdbg(usbdev, "SIOCGIWFRAG: %d", wrqu->frag.value);
- return ret;
-}
-
-
static int rndis_iw_set_freq(struct net_device *dev,
struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
{
@@ -1882,71 +2178,6 @@ static int rndis_iw_get_freq(struct net_device *dev,
}
-static int rndis_iw_get_txpower(struct net_device *dev,
- struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
-{
- struct usbnet *usbdev = netdev_priv(dev);
- struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
- __le32 tx_power;
-
- if (priv->radio_on) {
- /* fake since changing tx_power (by userlevel) not supported */
- tx_power = cpu_to_le32(get_bcm4320_power(priv));
-
- wrqu->txpower.flags = IW_TXPOW_MWATT;
- wrqu->txpower.value = le32_to_cpu(tx_power);
- wrqu->txpower.disabled = 0;
- } else {
- wrqu->txpower.flags = IW_TXPOW_MWATT;
- wrqu->txpower.value = 0;
- wrqu->txpower.disabled = 1;
- }
-
- devdbg(usbdev, "SIOCGIWTXPOW: %d", wrqu->txpower.value);
-
- return 0;
-}
-
-
-static int rndis_iw_set_txpower(struct net_device *dev,
- struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
-{
- struct usbnet *usbdev = netdev_priv(dev);
- struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
- __le32 tx_power = 0;
-
- if (!wrqu->txpower.disabled) {
- if (wrqu->txpower.flags == IW_TXPOW_MWATT)
- tx_power = cpu_to_le32(wrqu->txpower.value);
- else { /* wrqu->txpower.flags == IW_TXPOW_DBM */
- if (wrqu->txpower.value > 20)
- tx_power = cpu_to_le32(128);
- else if (wrqu->txpower.value < -43)
- tx_power = cpu_to_le32(127);
- else {
- signed char tmp;
- tmp = wrqu->txpower.value;
- tmp = -12 - tmp;
- tmp <<= 2;
- tx_power = cpu_to_le32((unsigned char)tmp);
- }
- }
- }
-
- devdbg(usbdev, "SIOCSIWTXPOW: %d", le32_to_cpu(tx_power));
-
- if (le32_to_cpu(tx_power) != 0) {
- /* txpower unsupported, just turn radio on */
- if (!priv->radio_on)
- return disassociate(usbdev, 1);
- return 0; /* all ready on */
- }
-
- /* tx_power == 0, turn off radio */
- return disassociate(usbdev, 0);
-}
-
-
static int rndis_iw_get_rate(struct net_device *dev,
struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
{
@@ -2022,12 +2253,12 @@ static const iw_handler rndis_iw_handler[] =
IW_IOCTL(SIOCSIWESSID) = rndis_iw_set_essid,
IW_IOCTL(SIOCGIWESSID) = rndis_iw_get_essid,
IW_IOCTL(SIOCGIWRATE) = rndis_iw_get_rate,
- IW_IOCTL(SIOCSIWRTS) = rndis_iw_set_rts,
- IW_IOCTL(SIOCGIWRTS) = rndis_iw_get_rts,
- IW_IOCTL(SIOCSIWFRAG) = rndis_iw_set_frag,
- IW_IOCTL(SIOCGIWFRAG) = rndis_iw_get_frag,
- IW_IOCTL(SIOCSIWTXPOW) = rndis_iw_set_txpower,
- IW_IOCTL(SIOCGIWTXPOW) = rndis_iw_get_txpower,
+ IW_IOCTL(SIOCSIWRTS) = (iw_handler) cfg80211_wext_siwrts,
+ IW_IOCTL(SIOCGIWRTS) = (iw_handler) cfg80211_wext_giwrts,
+ IW_IOCTL(SIOCSIWFRAG) = (iw_handler) cfg80211_wext_siwfrag,
+ IW_IOCTL(SIOCGIWFRAG) = (iw_handler) cfg80211_wext_giwfrag,
+ IW_IOCTL(SIOCSIWTXPOW) = (iw_handler) cfg80211_wext_siwtxpower,
+ IW_IOCTL(SIOCGIWTXPOW) = (iw_handler) cfg80211_wext_giwtxpower,
IW_IOCTL(SIOCSIWENCODE) = rndis_iw_set_encode,
IW_IOCTL(SIOCSIWENCODEEXT) = rndis_iw_set_encode_ext,
IW_IOCTL(SIOCSIWAUTH) = rndis_iw_set_auth,
@@ -2104,6 +2335,8 @@ get_bssid:
memcpy(evt.ap_addr.sa_data, bssid, ETH_ALEN);
wireless_send_event(usbdev->net, SIOCGIWAP, &evt, NULL);
}
+
+ usbnet_resume_rx(usbdev);
}
if (test_and_clear_bit(WORK_LINK_DOWN, &priv->work_pending)) {
@@ -2131,13 +2364,218 @@ static void rndis_wlan_set_multicast_list(struct net_device *dev)
queue_work(priv->workqueue, &priv->work);
}
-static void rndis_wlan_link_change(struct usbnet *usbdev, int state)
+
+static void rndis_wlan_auth_indication(struct usbnet *usbdev,
+ struct ndis_80211_status_indication *indication,
+ int len)
+{
+ u8 *buf;
+ const char *type;
+ int flags, buflen;
+ bool pairwise_error, group_error;
+ struct ndis_80211_auth_request *auth_req;
+
+ /* must have at least one array entry */
+ if (len < offsetof(struct ndis_80211_status_indication, u) +
+ sizeof(struct ndis_80211_auth_request)) {
+ devinfo(usbdev, "authentication indication: "
+ "too short message (%i)", len);
+ return;
+ }
+
+ buf = (void *)&indication->u.auth_request[0];
+ buflen = len - offsetof(struct ndis_80211_status_indication, u);
+
+ while (buflen >= sizeof(*auth_req)) {
+ auth_req = (void *)buf;
+ type = "unknown";
+ flags = le32_to_cpu(auth_req->flags);
+ pairwise_error = false;
+ group_error = false;
+
+ if (flags & 0x1)
+ type = "reauth request";
+ if (flags & 0x2)
+ type = "key update request";
+ if (flags & 0x6) {
+ pairwise_error = true;
+ type = "pairwise_error";
+ }
+ if (flags & 0xe) {
+ group_error = true;
+ type = "group_error";
+ }
+
+ devinfo(usbdev, "authentication indication: %s (0x%08x)", type,
+ le32_to_cpu(auth_req->flags));
+
+ if (pairwise_error || group_error) {
+ union iwreq_data wrqu;
+ struct iw_michaelmicfailure micfailure;
+
+ memset(&micfailure, 0, sizeof(micfailure));
+ if (pairwise_error)
+ micfailure.flags |= IW_MICFAILURE_PAIRWISE;
+ if (group_error)
+ micfailure.flags |= IW_MICFAILURE_GROUP;
+
+ memcpy(micfailure.src_addr.sa_data, auth_req->bssid,
+ ETH_ALEN);
+
+ memset(&wrqu, 0, sizeof(wrqu));
+ wrqu.data.length = sizeof(micfailure);
+ wireless_send_event(usbdev->net, IWEVMICHAELMICFAILURE,
+ &wrqu, (u8 *)&micfailure);
+ }
+
+ buflen -= le32_to_cpu(auth_req->length);
+ buf += le32_to_cpu(auth_req->length);
+ }
+}
+
+static void rndis_wlan_pmkid_cand_list_indication(struct usbnet *usbdev,
+ struct ndis_80211_status_indication *indication,
+ int len)
+{
+ struct ndis_80211_pmkid_cand_list *cand_list;
+ int list_len, expected_len, i;
+
+ if (len < offsetof(struct ndis_80211_status_indication, u) +
+ sizeof(struct ndis_80211_pmkid_cand_list)) {
+ devinfo(usbdev, "pmkid candidate list indication: "
+ "too short message (%i)", len);
+ return;
+ }
+
+ list_len = le32_to_cpu(indication->u.cand_list.num_candidates) *
+ sizeof(struct ndis_80211_pmkid_candidate);
+ expected_len = sizeof(struct ndis_80211_pmkid_cand_list) + list_len +
+ offsetof(struct ndis_80211_status_indication, u);
+
+ if (len < expected_len) {
+ devinfo(usbdev, "pmkid candidate list indication: "
+ "list larger than buffer (%i < %i)",
+ len, expected_len);
+ return;
+ }
+
+ cand_list = &indication->u.cand_list;
+
+ devinfo(usbdev, "pmkid candidate list indication: "
+ "version %i, candidates %i",
+ le32_to_cpu(cand_list->version),
+ le32_to_cpu(cand_list->num_candidates));
+
+ if (le32_to_cpu(cand_list->version) != 1)
+ return;
+
+ for (i = 0; i < le32_to_cpu(cand_list->num_candidates); i++) {
+ struct iw_pmkid_cand pcand;
+ union iwreq_data wrqu;
+ struct ndis_80211_pmkid_candidate *cand =
+ &cand_list->candidate_list[i];
+
+ devdbg(usbdev, "cand[%i]: flags: 0x%08x, bssid: %pM",
+ i, le32_to_cpu(cand->flags), cand->bssid);
+
+ memset(&pcand, 0, sizeof(pcand));
+ if (le32_to_cpu(cand->flags) & 0x01)
+ pcand.flags |= IW_PMKID_CAND_PREAUTH;
+ pcand.index = i;
+ memcpy(pcand.bssid.sa_data, cand->bssid, ETH_ALEN);
+
+ memset(&wrqu, 0, sizeof(wrqu));
+ wrqu.data.length = sizeof(pcand);
+ wireless_send_event(usbdev->net, IWEVPMKIDCAND, &wrqu,
+ (u8 *)&pcand);
+ }
+}
+
+static void rndis_wlan_media_specific_indication(struct usbnet *usbdev,
+ struct rndis_indicate *msg, int buflen)
+{
+ struct ndis_80211_status_indication *indication;
+ int len, offset;
+
+ offset = offsetof(struct rndis_indicate, status) +
+ le32_to_cpu(msg->offset);
+ len = le32_to_cpu(msg->length);
+
+ if (len < 8) {
+ devinfo(usbdev, "media specific indication, "
+ "ignore too short message (%i < 8)", len);
+ return;
+ }
+
+ if (offset + len > buflen) {
+ devinfo(usbdev, "media specific indication, "
+ "too large to fit to buffer (%i > %i)",
+ offset + len, buflen);
+ return;
+ }
+
+ indication = (void *)((u8 *)msg + offset);
+
+ switch (le32_to_cpu(indication->status_type)) {
+ case NDIS_80211_STATUSTYPE_RADIOSTATE:
+ devinfo(usbdev, "radio state indication: %i",
+ le32_to_cpu(indication->u.radio_status));
+ return;
+
+ case NDIS_80211_STATUSTYPE_MEDIASTREAMMODE:
+ devinfo(usbdev, "media stream mode indication: %i",
+ le32_to_cpu(indication->u.media_stream_mode));
+ return;
+
+ case NDIS_80211_STATUSTYPE_AUTHENTICATION:
+ rndis_wlan_auth_indication(usbdev, indication, len);
+ return;
+
+ case NDIS_80211_STATUSTYPE_PMKID_CANDIDATELIST:
+ rndis_wlan_pmkid_cand_list_indication(usbdev, indication, len);
+ return;
+
+ default:
+ devinfo(usbdev, "media specific indication: "
+ "unknown status type 0x%08x",
+ le32_to_cpu(indication->status_type));
+ }
+}
+
+
+static void rndis_wlan_indication(struct usbnet *usbdev, void *ind, int buflen)
{
struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
+ struct rndis_indicate *msg = ind;
- /* queue work to avoid recursive calls into rndis_command */
- set_bit(state ? WORK_LINK_UP : WORK_LINK_DOWN, &priv->work_pending);
- queue_work(priv->workqueue, &priv->work);
+ switch (msg->status) {
+ case RNDIS_STATUS_MEDIA_CONNECT:
+ usbnet_pause_rx(usbdev);
+
+ devinfo(usbdev, "media connect");
+
+ /* queue work to avoid recursive calls into rndis_command */
+ set_bit(WORK_LINK_UP, &priv->work_pending);
+ queue_work(priv->workqueue, &priv->work);
+ break;
+
+ case RNDIS_STATUS_MEDIA_DISCONNECT:
+ devinfo(usbdev, "media disconnect");
+
+ /* queue work to avoid recursive calls into rndis_command */
+ set_bit(WORK_LINK_DOWN, &priv->work_pending);
+ queue_work(priv->workqueue, &priv->work);
+ break;
+
+ case RNDIS_STATUS_MEDIA_SPECIFIC_INDICATION:
+ rndis_wlan_media_specific_indication(usbdev, msg, buflen);
+ break;
+
+ default:
+ devinfo(usbdev, "indication: 0x%08x",
+ le32_to_cpu(msg->status));
+ break;
+ }
}
@@ -2475,14 +2913,15 @@ static int rndis_wlan_bind(struct usbnet *usbdev, struct usb_interface *intf)
set_default_iw_params(usbdev);
+ /* set default rts/frag */
+ rndis_set_wiphy_params(wiphy,
+ WIPHY_PARAM_FRAG_THRESHOLD | WIPHY_PARAM_RTS_THRESHOLD);
+
/* turn radio on */
priv->radio_on = 1;
disassociate(usbdev, 1);
netif_carrier_off(usbdev->net);
- queue_delayed_work(priv->workqueue, &priv->stats_work,
- round_jiffies_relative(STATS_UPDATE_JIFFIES));
-
return 0;
fail:
@@ -2522,47 +2961,100 @@ static void rndis_wlan_unbind(struct usbnet *usbdev, struct usb_interface *intf)
static int rndis_wlan_reset(struct usbnet *usbdev)
{
+ struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
+ int retval;
+
+ devdbg(usbdev, "rndis_wlan_reset");
+
+ retval = rndis_reset(usbdev);
+ if (retval)
+ devwarn(usbdev, "rndis_reset() failed: %d", retval);
+
+ /* rndis_reset cleared multicast list, so restore here.
+ (set_multicast_list() also turns on current packet filter) */
+ set_multicast_list(usbdev);
+
+ queue_delayed_work(priv->workqueue, &priv->stats_work,
+ round_jiffies_relative(STATS_UPDATE_JIFFIES));
+
return deauthenticate(usbdev);
}
+static int rndis_wlan_stop(struct usbnet *usbdev)
+{
+ struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
+ int retval;
+ __le32 filter;
+
+ devdbg(usbdev, "rndis_wlan_stop");
+
+ retval = disassociate(usbdev, 0);
+
+ priv->work_pending = 0;
+ cancel_delayed_work_sync(&priv->stats_work);
+ cancel_delayed_work_sync(&priv->scan_work);
+ cancel_work_sync(&priv->work);
+ flush_workqueue(priv->workqueue);
+
+ if (priv->scan_request) {
+ cfg80211_scan_done(priv->scan_request, true);
+ priv->scan_request = NULL;
+ }
+
+ /* Set current packet filter zero to block receiving data packets from
+ device. */
+ filter = 0;
+ rndis_set_oid(usbdev, OID_GEN_CURRENT_PACKET_FILTER, &filter,
+ sizeof(filter));
+
+ return retval;
+}
+
+
static const struct driver_info bcm4320b_info = {
.description = "Wireless RNDIS device, BCM4320b based",
- .flags = FLAG_WLAN | FLAG_FRAMING_RN | FLAG_NO_SETINT,
+ .flags = FLAG_WLAN | FLAG_FRAMING_RN | FLAG_NO_SETINT |
+ FLAG_AVOID_UNLINK_URBS,
.bind = rndis_wlan_bind,
.unbind = rndis_wlan_unbind,
.status = rndis_status,
.rx_fixup = rndis_rx_fixup,
.tx_fixup = rndis_tx_fixup,
.reset = rndis_wlan_reset,
+ .stop = rndis_wlan_stop,
.early_init = bcm4320b_early_init,
- .link_change = rndis_wlan_link_change,
+ .indication = rndis_wlan_indication,
};
static const struct driver_info bcm4320a_info = {
.description = "Wireless RNDIS device, BCM4320a based",
- .flags = FLAG_WLAN | FLAG_FRAMING_RN | FLAG_NO_SETINT,
+ .flags = FLAG_WLAN | FLAG_FRAMING_RN | FLAG_NO_SETINT |
+ FLAG_AVOID_UNLINK_URBS,
.bind = rndis_wlan_bind,
.unbind = rndis_wlan_unbind,
.status = rndis_status,
.rx_fixup = rndis_rx_fixup,
.tx_fixup = rndis_tx_fixup,
.reset = rndis_wlan_reset,
+ .stop = rndis_wlan_stop,
.early_init = bcm4320a_early_init,
- .link_change = rndis_wlan_link_change,
+ .indication = rndis_wlan_indication,
};
static const struct driver_info rndis_wlan_info = {
.description = "Wireless RNDIS device",
- .flags = FLAG_WLAN | FLAG_FRAMING_RN | FLAG_NO_SETINT,
+ .flags = FLAG_WLAN | FLAG_FRAMING_RN | FLAG_NO_SETINT |
+ FLAG_AVOID_UNLINK_URBS,
.bind = rndis_wlan_bind,
.unbind = rndis_wlan_unbind,
.status = rndis_status,
.rx_fixup = rndis_rx_fixup,
.tx_fixup = rndis_tx_fixup,
.reset = rndis_wlan_reset,
+ .stop = rndis_wlan_stop,
.early_init = bcm4320a_early_init,
- .link_change = rndis_wlan_link_change,
+ .indication = rndis_wlan_indication,
};
/*-------------------------------------------------------------------------*/
diff --git a/drivers/net/wireless/rt2x00/Kconfig b/drivers/net/wireless/rt2x00/Kconfig
index 8aab3e6754b..ed1f997e352 100644
--- a/drivers/net/wireless/rt2x00/Kconfig
+++ b/drivers/net/wireless/rt2x00/Kconfig
@@ -1,8 +1,8 @@
menuconfig RT2X00
tristate "Ralink driver support"
- depends on MAC80211 && WLAN_80211 && EXPERIMENTAL
+ depends on MAC80211 && WLAN_80211
---help---
- This will enable the experimental support for the Ralink drivers,
+ This will enable the support for the Ralink drivers,
developed in the rt2x00 project <http://rt2x00.serialmonkey.com>.
These drivers make use of the mac80211 stack.
@@ -79,14 +79,14 @@ config RT73USB
config RT2800USB
tristate "Ralink rt2800 (USB) support"
- depends on USB
+ depends on USB && EXPERIMENTAL
select RT2X00_LIB_USB
select RT2X00_LIB_HT
select RT2X00_LIB_FIRMWARE
select RT2X00_LIB_CRYPTO
select CRC_CCITT
---help---
- This adds support for rt2800 wireless chipset family.
+ This adds experimental support for rt2800 wireless chipset family.
Supported chips: RT2770, RT2870 & RT3070.
When compiled as a module, this driver will be called "rt2800usb.ko".
@@ -112,14 +112,6 @@ config RT2X00_LIB_FIRMWARE
config RT2X00_LIB_CRYPTO
boolean
-config RT2X00_LIB_RFKILL
- boolean
- default y if (RT2X00_LIB=y && INPUT=y) || (RT2X00_LIB=m && INPUT!=n)
- select INPUT_POLLDEV
-
-comment "rt2x00 rfkill support disabled due to modularized INPUT and built-in rt2x00"
- depends on RT2X00_LIB=y && INPUT=m
-
config RT2X00_LIB_LEDS
boolean
default y if (RT2X00_LIB=y && LEDS_CLASS=y) || (RT2X00_LIB=m && LEDS_CLASS!=n)
diff --git a/drivers/net/wireless/rt2x00/Makefile b/drivers/net/wireless/rt2x00/Makefile
index bfc7226f0af..13043ea9766 100644
--- a/drivers/net/wireless/rt2x00/Makefile
+++ b/drivers/net/wireless/rt2x00/Makefile
@@ -5,7 +5,6 @@ rt2x00lib-y += rt2x00queue.o
rt2x00lib-y += rt2x00link.o
rt2x00lib-$(CONFIG_RT2X00_LIB_DEBUGFS) += rt2x00debug.o
rt2x00lib-$(CONFIG_RT2X00_LIB_CRYPTO) += rt2x00crypto.o
-rt2x00lib-$(CONFIG_RT2X00_LIB_RFKILL) += rt2x00rfkill.o
rt2x00lib-$(CONFIG_RT2X00_LIB_FIRMWARE) += rt2x00firmware.o
rt2x00lib-$(CONFIG_RT2X00_LIB_LEDS) += rt2x00leds.o
rt2x00lib-$(CONFIG_RT2X00_LIB_HT) += rt2x00ht.o
diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c
index 435f945fe64..164df9347a2 100644
--- a/drivers/net/wireless/rt2x00/rt2400pci.c
+++ b/drivers/net/wireless/rt2x00/rt2400pci.c
@@ -199,7 +199,6 @@ static const struct rt2x00debug rt2400pci_rt2x00debug = {
};
#endif /* CONFIG_RT2X00_LIB_DEBUGFS */
-#ifdef CONFIG_RT2X00_LIB_RFKILL
static int rt2400pci_rfkill_poll(struct rt2x00_dev *rt2x00dev)
{
u32 reg;
@@ -207,9 +206,6 @@ static int rt2400pci_rfkill_poll(struct rt2x00_dev *rt2x00dev)
rt2x00pci_register_read(rt2x00dev, GPIOCSR, &reg);
return rt2x00_get_field32(reg, GPIOCSR_BIT0);
}
-#else
-#define rt2400pci_rfkill_poll NULL
-#endif /* CONFIG_RT2X00_LIB_RFKILL */
#ifdef CONFIG_RT2X00_LIB_LEDS
static void rt2400pci_brightness_set(struct led_classdev *led_cdev,
@@ -1073,8 +1069,6 @@ static void rt2400pci_write_beacon(struct queue_entry *entry)
* otherwise we might be sending out invalid data.
*/
rt2x00pci_register_read(rt2x00dev, CSR14, &reg);
- rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 0);
- rt2x00_set_field32(&reg, CSR14_TBCN, 0);
rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 0);
rt2x00pci_register_write(rt2x00dev, CSR14, reg);
@@ -1391,10 +1385,8 @@ static int rt2400pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
/*
* Detect if this device has an hardware controlled radio.
*/
-#ifdef CONFIG_RT2X00_LIB_RFKILL
if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_HARDWARE_RADIO))
__set_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags);
-#endif /* CONFIG_RT2X00_LIB_RFKILL */
/*
* Check if the BBP tuning should be enabled.
@@ -1567,12 +1559,14 @@ static const struct ieee80211_ops rt2400pci_mac80211_ops = {
.remove_interface = rt2x00mac_remove_interface,
.config = rt2x00mac_config,
.configure_filter = rt2x00mac_configure_filter,
+ .set_tim = rt2x00mac_set_tim,
.get_stats = rt2x00mac_get_stats,
.bss_info_changed = rt2x00mac_bss_info_changed,
.conf_tx = rt2400pci_conf_tx,
.get_tx_stats = rt2x00mac_get_tx_stats,
.get_tsf = rt2400pci_get_tsf,
.tx_last_beacon = rt2400pci_tx_last_beacon,
+ .rfkill_poll = rt2x00mac_rfkill_poll,
};
static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = {
diff --git a/drivers/net/wireless/rt2x00/rt2400pci.h b/drivers/net/wireless/rt2x00/rt2400pci.h
index ec3b004ddc3..ccd644104ad 100644
--- a/drivers/net/wireless/rt2x00/rt2400pci.h
+++ b/drivers/net/wireless/rt2x00/rt2400pci.h
@@ -928,7 +928,7 @@
#define RXD_W7_RESERVED FIELD32(0xffffffff)
/*
- * Macro's for converting txpower from EEPROM to mac80211 value
+ * Macros for converting txpower from EEPROM to mac80211 value
* and from mac80211 value to register value.
* NOTE: Logics in rt2400pci for txpower are reversed
* compared to the other rt2x00 drivers. A higher txpower
diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c
index 08b30d01e67..4186582f277 100644
--- a/drivers/net/wireless/rt2x00/rt2500pci.c
+++ b/drivers/net/wireless/rt2x00/rt2500pci.c
@@ -199,7 +199,6 @@ static const struct rt2x00debug rt2500pci_rt2x00debug = {
};
#endif /* CONFIG_RT2X00_LIB_DEBUGFS */
-#ifdef CONFIG_RT2X00_LIB_RFKILL
static int rt2500pci_rfkill_poll(struct rt2x00_dev *rt2x00dev)
{
u32 reg;
@@ -207,9 +206,6 @@ static int rt2500pci_rfkill_poll(struct rt2x00_dev *rt2x00dev)
rt2x00pci_register_read(rt2x00dev, GPIOCSR, &reg);
return rt2x00_get_field32(reg, GPIOCSR_BIT0);
}
-#else
-#define rt2500pci_rfkill_poll NULL
-#endif /* CONFIG_RT2X00_LIB_RFKILL */
#ifdef CONFIG_RT2X00_LIB_LEDS
static void rt2500pci_brightness_set(struct led_classdev *led_cdev,
@@ -1231,8 +1227,6 @@ static void rt2500pci_write_beacon(struct queue_entry *entry)
* otherwise we might be sending out invalid data.
*/
rt2x00pci_register_read(rt2x00dev, CSR14, &reg);
- rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 0);
- rt2x00_set_field32(&reg, CSR14_TBCN, 0);
rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 0);
rt2x00pci_register_write(rt2x00dev, CSR14, reg);
@@ -1548,10 +1542,8 @@ static int rt2500pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
/*
* Detect if this device has an hardware controlled radio.
*/
-#ifdef CONFIG_RT2X00_LIB_RFKILL
if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_HARDWARE_RADIO))
__set_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags);
-#endif /* CONFIG_RT2X00_LIB_RFKILL */
/*
* Check if the BBP tuning should be enabled.
@@ -1866,12 +1858,14 @@ static const struct ieee80211_ops rt2500pci_mac80211_ops = {
.remove_interface = rt2x00mac_remove_interface,
.config = rt2x00mac_config,
.configure_filter = rt2x00mac_configure_filter,
+ .set_tim = rt2x00mac_set_tim,
.get_stats = rt2x00mac_get_stats,
.bss_info_changed = rt2x00mac_bss_info_changed,
.conf_tx = rt2x00mac_conf_tx,
.get_tx_stats = rt2x00mac_get_tx_stats,
.get_tsf = rt2500pci_get_tsf,
.tx_last_beacon = rt2500pci_tx_last_beacon,
+ .rfkill_poll = rt2x00mac_rfkill_poll,
};
static const struct rt2x00lib_ops rt2500pci_rt2x00_ops = {
diff --git a/drivers/net/wireless/rt2x00/rt2500pci.h b/drivers/net/wireless/rt2x00/rt2500pci.h
index ce2f065c748..54d37957883 100644
--- a/drivers/net/wireless/rt2x00/rt2500pci.h
+++ b/drivers/net/wireless/rt2x00/rt2500pci.h
@@ -1218,7 +1218,7 @@
#define RXD_W10_DROP FIELD32(0x00000001)
/*
- * Macro's for converting txpower from EEPROM to mac80211 value
+ * Macros for converting txpower from EEPROM to mac80211 value
* and from mac80211 value to register value.
*/
#define MIN_TXPOWER 0
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c
index ce75426764a..09a589432da 100644
--- a/drivers/net/wireless/rt2x00/rt2500usb.c
+++ b/drivers/net/wireless/rt2x00/rt2500usb.c
@@ -277,7 +277,6 @@ static const struct rt2x00debug rt2500usb_rt2x00debug = {
};
#endif /* CONFIG_RT2X00_LIB_DEBUGFS */
-#ifdef CONFIG_RT2X00_LIB_RFKILL
static int rt2500usb_rfkill_poll(struct rt2x00_dev *rt2x00dev)
{
u16 reg;
@@ -285,9 +284,6 @@ static int rt2500usb_rfkill_poll(struct rt2x00_dev *rt2x00dev)
rt2500usb_register_read(rt2x00dev, MAC_CSR19, &reg);
return rt2x00_get_field32(reg, MAC_CSR19_BIT7);
}
-#else
-#define rt2500usb_rfkill_poll NULL
-#endif /* CONFIG_RT2X00_LIB_RFKILL */
#ifdef CONFIG_RT2X00_LIB_LEDS
static void rt2500usb_brightness_set(struct led_classdev *led_cdev,
@@ -1242,8 +1238,6 @@ static void rt2500usb_write_beacon(struct queue_entry *entry)
* otherwise we might be sending out invalid data.
*/
rt2500usb_register_read(rt2x00dev, TXRX_CSR19, &reg);
- rt2x00_set_field16(&reg, TXRX_CSR19_TSF_COUNT, 0);
- rt2x00_set_field16(&reg, TXRX_CSR19_TBCN, 0);
rt2x00_set_field16(&reg, TXRX_CSR19_BEACON_GEN, 0);
rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg);
@@ -1291,7 +1285,7 @@ static int rt2500usb_get_tx_data_len(struct queue_entry *entry)
static void rt2500usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
const enum data_queue_qid queue)
{
- u16 reg;
+ u16 reg, reg0;
if (queue != QID_BEACON) {
rt2x00usb_kick_tx_queue(rt2x00dev, queue);
@@ -1302,16 +1296,19 @@ static void rt2500usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
if (!rt2x00_get_field16(reg, TXRX_CSR19_BEACON_GEN)) {
rt2x00_set_field16(&reg, TXRX_CSR19_TSF_COUNT, 1);
rt2x00_set_field16(&reg, TXRX_CSR19_TBCN, 1);
+ reg0 = reg;
rt2x00_set_field16(&reg, TXRX_CSR19_BEACON_GEN, 1);
/*
* Beacon generation will fail initially.
- * To prevent this we need to register the TXRX_CSR19
- * register several times.
+ * To prevent this we need to change the TXRX_CSR19
+ * register several times (reg0 is the same as reg
+ * except for TXRX_CSR19_BEACON_GEN, which is 0 in reg0
+ * and 1 in reg).
*/
rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg);
- rt2500usb_register_write(rt2x00dev, TXRX_CSR19, 0);
+ rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg0);
rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg);
- rt2500usb_register_write(rt2x00dev, TXRX_CSR19, 0);
+ rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg0);
rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg);
}
}
@@ -1603,10 +1600,8 @@ static int rt2500usb_init_eeprom(struct rt2x00_dev *rt2x00dev)
/*
* Detect if this device has an hardware controlled radio.
*/
-#ifdef CONFIG_RT2X00_LIB_RFKILL
if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_HARDWARE_RADIO))
__set_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags);
-#endif /* CONFIG_RT2X00_LIB_RFKILL */
/*
* Check if the BBP tuning should be disabled.
@@ -1902,11 +1897,13 @@ static const struct ieee80211_ops rt2500usb_mac80211_ops = {
.remove_interface = rt2x00mac_remove_interface,
.config = rt2x00mac_config,
.configure_filter = rt2x00mac_configure_filter,
+ .set_tim = rt2x00mac_set_tim,
.set_key = rt2x00mac_set_key,
.get_stats = rt2x00mac_get_stats,
.bss_info_changed = rt2x00mac_bss_info_changed,
.conf_tx = rt2x00mac_conf_tx,
.get_tx_stats = rt2x00mac_get_tx_stats,
+ .rfkill_poll = rt2x00mac_rfkill_poll,
};
static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = {
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.h b/drivers/net/wireless/rt2x00/rt2500usb.h
index 5bc46fe7217..b01edca4258 100644
--- a/drivers/net/wireless/rt2x00/rt2500usb.h
+++ b/drivers/net/wireless/rt2x00/rt2500usb.h
@@ -831,7 +831,7 @@
#define RXD_W3_EIV FIELD32(0xffffffff)
/*
- * Macro's for converting txpower from EEPROM to mac80211 value
+ * Macros for converting txpower from EEPROM to mac80211 value
* and from mac80211 value to register value.
*/
#define MIN_TXPOWER 0
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c
index 37561667925..3856f06fdca 100644
--- a/drivers/net/wireless/rt2x00/rt2800usb.c
+++ b/drivers/net/wireless/rt2x00/rt2800usb.c
@@ -264,7 +264,6 @@ static const struct rt2x00debug rt2800usb_rt2x00debug = {
};
#endif /* CONFIG_RT2X00_LIB_DEBUGFS */
-#ifdef CONFIG_RT2X00_LIB_RFKILL
static int rt2800usb_rfkill_poll(struct rt2x00_dev *rt2x00dev)
{
u32 reg;
@@ -272,9 +271,6 @@ static int rt2800usb_rfkill_poll(struct rt2x00_dev *rt2x00dev)
rt2x00usb_register_read(rt2x00dev, GPIO_CTRL_CFG, &reg);
return rt2x00_get_field32(reg, GPIO_CTRL_CFG_BIT2);
}
-#else
-#define rt2800usb_rfkill_poll NULL
-#endif /* CONFIG_RT2X00_LIB_RFKILL */
#ifdef CONFIG_RT2X00_LIB_LEDS
static void rt2800usb_brightness_set(struct led_classdev *led_cdev,
@@ -522,7 +518,7 @@ static void rt2800usb_config_filter(struct rt2x00_dev *rt2x00dev,
rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_RTS,
!(filter_flags & FIF_CONTROL));
rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_PSPOLL,
- !(filter_flags & FIF_CONTROL));
+ !(filter_flags & FIF_PSPOLL));
rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_BA, 1);
rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_BAR, 0);
rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_CNTL,
@@ -1914,7 +1910,7 @@ static int rt2800usb_set_device_state(struct rt2x00_dev *rt2x00dev,
/*
* Before the radio can be enabled, the device first has
* to be woken up. After that it needs a bit of time
- * to be fully awake and the radio can be enabled.
+ * to be fully awake and then the radio can be enabled.
*/
rt2800usb_set_state(rt2x00dev, STATE_AWAKE);
msleep(1);
@@ -1922,7 +1918,7 @@ static int rt2800usb_set_device_state(struct rt2x00_dev *rt2x00dev,
break;
case STATE_RADIO_OFF:
/*
- * After the radio has been disablee, the device should
+ * After the radio has been disabled, the device should
* be put to sleep for powersaving.
*/
rt2800usb_disable_radio(rt2x00dev);
@@ -2054,8 +2050,6 @@ static void rt2800usb_write_beacon(struct queue_entry *entry)
* otherwise we might be sending out invalid data.
*/
rt2x00usb_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
- rt2x00_set_field32(&reg, BCN_TIME_CFG_TSF_TICKING, 0);
- rt2x00_set_field32(&reg, BCN_TIME_CFG_TBTT_ENABLE, 0);
rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_GEN, 0);
rt2x00usb_register_write(rt2x00dev, BCN_TIME_CFG, reg);
@@ -2224,10 +2218,8 @@ static int rt2800usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)
*/
mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0);
if (!is_valid_ether_addr(mac)) {
- DECLARE_MAC_BUF(macbuf);
-
random_ether_addr(mac);
- EEPROM(rt2x00dev, "MAC: %s\n", print_mac(macbuf, mac));
+ EEPROM(rt2x00dev, "MAC: %pM\n", mac);
}
rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &word);
@@ -2385,10 +2377,8 @@ static int rt2800usb_init_eeprom(struct rt2x00_dev *rt2x00dev)
/*
* Detect if this device has an hardware controlled radio.
*/
-#ifdef CONFIG_RT2X00_LIB_RFKILL
if (rt2x00_get_field16(eeprom, EEPROM_NIC_HW_RADIO))
__set_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags);
-#endif /* CONFIG_RT2X00_LIB_RFKILL */
/*
* Store led settings, for correct led behaviour.
@@ -2632,6 +2622,13 @@ static int rt2800usb_probe_hw(struct rt2x00_dev *rt2x00dev)
return retval;
/*
+ * This device has multiple filters for control frames
+ * and has a separate filter for PS Poll frames.
+ */
+ __set_bit(DRIVER_SUPPORT_CONTROL_FILTERS, &rt2x00dev->flags);
+ __set_bit(DRIVER_SUPPORT_CONTROL_FILTER_PSPOLL, &rt2x00dev->flags);
+
+ /*
* This device requires firmware.
*/
__set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags);
@@ -2792,6 +2789,7 @@ static const struct ieee80211_ops rt2800usb_mac80211_ops = {
.remove_interface = rt2x00mac_remove_interface,
.config = rt2x00mac_config,
.configure_filter = rt2x00mac_configure_filter,
+ .set_tim = rt2x00mac_set_tim,
.set_key = rt2x00mac_set_key,
.get_stats = rt2x00mac_get_stats,
.get_tkip_seq = rt2800usb_get_tkip_seq,
@@ -2800,6 +2798,7 @@ static const struct ieee80211_ops rt2800usb_mac80211_ops = {
.conf_tx = rt2800usb_conf_tx,
.get_tx_stats = rt2x00mac_get_tx_stats,
.get_tsf = rt2800usb_get_tsf,
+ .rfkill_poll = rt2x00mac_rfkill_poll,
};
static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = {
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.h b/drivers/net/wireless/rt2x00/rt2800usb.h
index 61a8be61d3f..2d9dc378336 100644
--- a/drivers/net/wireless/rt2x00/rt2800usb.h
+++ b/drivers/net/wireless/rt2x00/rt2800usb.h
@@ -1921,7 +1921,7 @@ struct mac_iveiv_entry {
#define RXWI_W3_SNR1 FIELD32(0x0000ff00)
/*
- * Macro's for converting txpower from EEPROM to mac80211 value
+ * Macros for converting txpower from EEPROM to mac80211 value
* and from mac80211 value to register value.
*/
#define MIN_G_TXPOWER 0
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
index 49c9e2c1433..99e89596cef 100644
--- a/drivers/net/wireless/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/rt2x00/rt2x00.h
@@ -134,6 +134,17 @@
GET_DURATION(IEEE80211_HEADER + ACK_SIZE, 10) )
/*
+ * Structure for average calculation
+ * The avg field contains the actual average value,
+ * but avg_weight is internally used during calculations
+ * to prevent rounding errors.
+ */
+struct avg_val {
+ int avg;
+ int avg_weight;
+};
+
+/*
* Chipset identification
* The chipset on the device is composed of a RT and RF chip.
* The chipset combination is important for determining device capabilities.
@@ -245,21 +256,18 @@ struct link_ant {
struct antenna_setup active;
/*
- * RSSI information for the different antenna's.
- * These statistics are used to determine when
- * to switch antenna when using software diversity.
- *
- * rssi[0] -> Antenna A RSSI
- * rssi[1] -> Antenna B RSSI
+ * RSSI history information for the antenna.
+ * Used to determine when to switch antenna
+ * when using software diversity.
*/
- int rssi_history[2];
+ int rssi_history;
/*
* Current RSSI average of the currently active antenna.
* Similar to the avg_rssi in the link_qual structure
* this value is updated by using the walking average.
*/
- int rssi_ant;
+ struct avg_val rssi_ant;
};
/*
@@ -288,7 +296,7 @@ struct link {
/*
* Currently active average RSSI value
*/
- int avg_rssi;
+ struct avg_val avg_rssi;
/*
* Currently precalculated percentages of successful
@@ -326,6 +334,11 @@ struct rt2x00_intf {
u8 bssid[ETH_ALEN];
/*
+ * beacon->skb must be protected with the mutex.
+ */
+ struct mutex beacon_skb_mutex;
+
+ /*
* Entry in the beacon queue which belongs to
* this interface. Each interface has its own
* dedicated beacon entry.
@@ -594,7 +607,6 @@ enum rt2x00_flags {
DEVICE_STATE_INITIALIZED,
DEVICE_STATE_STARTED,
DEVICE_STATE_ENABLED_RADIO,
- DEVICE_STATE_DISABLED_RADIO_HW,
/*
* Driver requirements
@@ -612,6 +624,8 @@ enum rt2x00_flags {
*/
CONFIG_SUPPORT_HW_BUTTON,
CONFIG_SUPPORT_HW_CRYPTO,
+ DRIVER_SUPPORT_CONTROL_FILTERS,
+ DRIVER_SUPPORT_CONTROL_FILTER_PSPOLL,
/*
* Driver configuration
@@ -634,7 +648,7 @@ struct rt2x00_dev {
* The structure stored in here depends on the
* system bus (PCI or USB).
* When accessing this variable, the rt2x00dev_{pci,usb}
- * macro's should be used for correct typecasting.
+ * macros should be used for correct typecasting.
*/
struct device *dev;
@@ -651,18 +665,6 @@ struct rt2x00_dev {
enum ieee80211_band curr_band;
/*
- * rfkill structure for RF state switching support.
- * This will only be compiled in when required.
- */
-#ifdef CONFIG_RT2X00_LIB_RFKILL
- unsigned long rfkill_state;
-#define RFKILL_STATE_ALLOCATED 1
-#define RFKILL_STATE_REGISTERED 2
-#define RFKILL_STATE_BLOCKED 3
- struct input_polled_dev *rfkill_poll_dev;
-#endif /* CONFIG_RT2X00_LIB_RFKILL */
-
- /*
* If enabled, the debugfs interface structures
* required for deregistration of debugfs.
*/
@@ -977,6 +979,8 @@ void rt2x00mac_configure_filter(struct ieee80211_hw *hw,
unsigned int changed_flags,
unsigned int *total_flags,
int mc_count, struct dev_addr_list *mc_list);
+int rt2x00mac_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta,
+ bool set);
#ifdef CONFIG_RT2X00_LIB_CRYPTO
int rt2x00mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
struct ieee80211_vif *vif, struct ieee80211_sta *sta,
@@ -994,6 +998,7 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw,
u32 changes);
int rt2x00mac_conf_tx(struct ieee80211_hw *hw, u16 queue,
const struct ieee80211_tx_queue_params *params);
+void rt2x00mac_rfkill_poll(struct ieee80211_hw *hw);
/*
* Driver allocation handlers.
diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c
index 3e019a12df2..3501788ab49 100644
--- a/drivers/net/wireless/rt2x00/rt2x00config.c
+++ b/drivers/net/wireless/rt2x00/rt2x00config.c
@@ -124,24 +124,34 @@ enum antenna rt2x00lib_config_antenna_check(enum antenna current_ant,
}
void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev,
- struct antenna_setup *ant)
+ struct antenna_setup config)
{
+ struct link_ant *ant = &rt2x00dev->link.ant;
struct antenna_setup *def = &rt2x00dev->default_ant;
struct antenna_setup *active = &rt2x00dev->link.ant.active;
/*
* Failsafe: Make sure we are not sending the
* ANTENNA_SW_DIVERSITY state to the driver.
- * If that happes fallback to hardware default,
+ * If that happens, fallback to hardware defaults,
* or our own default.
+ * If diversity handling is active for a particular antenna,
+ * we shouldn't overwrite that antenna.
* The calls to rt2x00lib_config_antenna_check()
* might have caused that we restore back to the already
* active setting. If that has happened we can quit.
*/
- ant->rx = rt2x00lib_config_antenna_check(ant->rx, def->rx);
- ant->tx = rt2x00lib_config_antenna_check(ant->tx, def->tx);
+ if (!(ant->flags & ANTENNA_RX_DIVERSITY))
+ config.rx = rt2x00lib_config_antenna_check(config.rx, def->rx);
+ else
+ config.rx = active->rx;
- if (ant->rx == active->rx && ant->tx == active->tx)
+ if (!(ant->flags & ANTENNA_TX_DIVERSITY))
+ config.tx = rt2x00lib_config_antenna_check(config.tx, def->tx);
+ else
+ config.tx = active->tx;
+
+ if (config.rx == active->rx && config.tx == active->tx)
return;
/*
@@ -156,11 +166,11 @@ void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev,
* The latter is required since we need to recalibrate the
* noise-sensitivity ratio for the new setup.
*/
- rt2x00dev->ops->lib->config_ant(rt2x00dev, ant);
+ rt2x00dev->ops->lib->config_ant(rt2x00dev, &config);
rt2x00link_reset_tuner(rt2x00dev, true);
- memcpy(active, ant, sizeof(*ant));
+ memcpy(active, &config, sizeof(config));
if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_ON_LINK);
diff --git a/drivers/net/wireless/rt2x00/rt2x00crypto.c b/drivers/net/wireless/rt2x00/rt2x00crypto.c
index bc4e81e2184..30fbd3bbe08 100644
--- a/drivers/net/wireless/rt2x00/rt2x00crypto.c
+++ b/drivers/net/wireless/rt2x00/rt2x00crypto.c
@@ -53,8 +53,7 @@ void rt2x00crypto_create_tx_descriptor(struct queue_entry *entry,
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb);
struct ieee80211_key_conf *hw_key = tx_info->control.hw_key;
- if (!test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags) ||
- !hw_key || entry->skb->do_not_encrypt)
+ if (!test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags) || !hw_key)
return;
__set_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags);
@@ -82,8 +81,7 @@ unsigned int rt2x00crypto_tx_overhead(struct rt2x00_dev *rt2x00dev,
struct ieee80211_key_conf *key = tx_info->control.hw_key;
unsigned int overhead = 0;
- if (!test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags) ||
- !key || skb->do_not_encrypt)
+ if (!test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags) || !key)
return overhead;
/*
@@ -131,7 +129,7 @@ void rt2x00crypto_tx_remove_iv(struct sk_buff *skb, struct txentry_desc *txdesc)
/* Pull buffer to correct size */
skb_pull(skb, txdesc->iv_len);
- /* IV/EIV data has officially be stripped */
+ /* IV/EIV data has officially been stripped */
skbdesc->flags |= SKBDESC_IV_STRIPPED;
}
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
index 57813e72c80..b6676c6722f 100644
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
@@ -40,8 +40,7 @@ int rt2x00lib_enable_radio(struct rt2x00_dev *rt2x00dev)
* Don't enable the radio twice.
* And check if the hardware button has been disabled.
*/
- if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags) ||
- test_bit(DEVICE_STATE_DISABLED_RADIO_HW, &rt2x00dev->flags))
+ if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
return 0;
/*
@@ -187,7 +186,6 @@ static void rt2x00lib_intf_scheduled(struct work_struct *work)
static void rt2x00lib_beacondone_iter(void *data, u8 *mac,
struct ieee80211_vif *vif)
{
- struct rt2x00_dev *rt2x00dev = data;
struct rt2x00_intf *intf = vif_to_intf(vif);
if (vif->type != NL80211_IFTYPE_AP &&
@@ -196,12 +194,6 @@ static void rt2x00lib_beacondone_iter(void *data, u8 *mac,
vif->type != NL80211_IFTYPE_WDS)
return;
- /*
- * Clean up the beacon skb.
- */
- rt2x00queue_free_skb(rt2x00dev, intf->beacon->skb);
- intf->beacon->skb = NULL;
-
spin_lock(&intf->lock);
intf->delayed_flags |= DELAYED_UPDATE_BEACON;
spin_unlock(&intf->lock);
@@ -216,7 +208,7 @@ void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev)
rt2x00lib_beacondone_iter,
rt2x00dev);
- queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->intf_work);
+ ieee80211_queue_work(rt2x00dev->hw, &rt2x00dev->intf_work);
}
EXPORT_SYMBOL_GPL(rt2x00lib_beacondone);
@@ -449,7 +441,8 @@ void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev,
* mac80211 will clean up the skb structure.
*/
rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_RXDONE, entry->skb);
- ieee80211_rx_irqsafe(rt2x00dev->hw, entry->skb, rx_status);
+ memcpy(IEEE80211_SKB_RXCB(entry->skb), rx_status, sizeof(*rx_status));
+ ieee80211_rx_irqsafe(rt2x00dev->hw, entry->skb);
/*
* Replace the skb with the freshly allocated one.
@@ -785,6 +778,13 @@ int rt2x00lib_start(struct rt2x00_dev *rt2x00dev)
rt2x00dev->intf_sta_count = 0;
rt2x00dev->intf_associated = 0;
+ /* Enable the radio */
+ retval = rt2x00lib_enable_radio(rt2x00dev);
+ if (retval) {
+ rt2x00queue_uninitialize(rt2x00dev);
+ return retval;
+ }
+
set_bit(DEVICE_STATE_STARTED, &rt2x00dev->flags);
return 0;
@@ -870,7 +870,6 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev)
*/
rt2x00link_register(rt2x00dev);
rt2x00leds_register(rt2x00dev);
- rt2x00rfkill_allocate(rt2x00dev);
rt2x00debug_register(rt2x00dev);
set_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags);
@@ -894,6 +893,12 @@ void rt2x00lib_remove_dev(struct rt2x00_dev *rt2x00dev)
rt2x00lib_disable_radio(rt2x00dev);
/*
+ * Stop all work.
+ */
+ cancel_work_sync(&rt2x00dev->filter_work);
+ cancel_work_sync(&rt2x00dev->intf_work);
+
+ /*
* Uninitialize device.
*/
rt2x00lib_uninitialize(rt2x00dev);
@@ -902,7 +907,6 @@ void rt2x00lib_remove_dev(struct rt2x00_dev *rt2x00dev)
* Free extra components
*/
rt2x00debug_deregister(rt2x00dev);
- rt2x00rfkill_free(rt2x00dev);
rt2x00leds_unregister(rt2x00dev);
/*
diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h
index 0bf2715fa93..eeb2881e818 100644
--- a/drivers/net/wireless/rt2x00/rt2x00lib.h
+++ b/drivers/net/wireless/rt2x00/rt2x00lib.h
@@ -30,10 +30,8 @@
/*
* Interval defines
- * Both the link tuner as the rfkill will be called once per second.
*/
#define LINK_TUNE_INTERVAL round_jiffies_relative(HZ)
-#define RFKILL_POLL_INTERVAL 1000
/*
* rt2x00_rate: Per rate device information
@@ -90,7 +88,7 @@ void rt2x00lib_config_erp(struct rt2x00_dev *rt2x00dev,
struct rt2x00_intf *intf,
struct ieee80211_bss_conf *conf);
void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev,
- struct antenna_setup *ant);
+ struct antenna_setup ant);
void rt2x00lib_config(struct rt2x00_dev *rt2x00dev,
struct ieee80211_conf *conf,
const unsigned int changed_flags);
@@ -386,29 +384,18 @@ static inline void rt2x00ht_create_tx_descriptor(struct queue_entry *entry,
/*
* RFkill handlers.
*/
-#ifdef CONFIG_RT2X00_LIB_RFKILL
-void rt2x00rfkill_register(struct rt2x00_dev *rt2x00dev);
-void rt2x00rfkill_unregister(struct rt2x00_dev *rt2x00dev);
-void rt2x00rfkill_allocate(struct rt2x00_dev *rt2x00dev);
-void rt2x00rfkill_free(struct rt2x00_dev *rt2x00dev);
-#else
static inline void rt2x00rfkill_register(struct rt2x00_dev *rt2x00dev)
{
+ if (test_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags))
+ wiphy_rfkill_start_polling(rt2x00dev->hw->wiphy);
}
static inline void rt2x00rfkill_unregister(struct rt2x00_dev *rt2x00dev)
{
+ if (test_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags))
+ wiphy_rfkill_stop_polling(rt2x00dev->hw->wiphy);
}
-static inline void rt2x00rfkill_allocate(struct rt2x00_dev *rt2x00dev)
-{
-}
-
-static inline void rt2x00rfkill_free(struct rt2x00_dev *rt2x00dev)
-{
-}
-#endif /* CONFIG_RT2X00_LIB_RFKILL */
-
/*
* LED handlers
*/
diff --git a/drivers/net/wireless/rt2x00/rt2x00link.c b/drivers/net/wireless/rt2x00/rt2x00link.c
index eb9b981b913..c64db0ba7f4 100644
--- a/drivers/net/wireless/rt2x00/rt2x00link.c
+++ b/drivers/net/wireless/rt2x00/rt2x00link.c
@@ -46,7 +46,15 @@
#define DEFAULT_PERCENTAGE 50
/*
- * Small helper macro to work with moving/walking averages.
+ * Small helper macro for percentage calculation
+ * This is a very simple macro with the only catch that it will
+ * produce a default value in case no total value was provided.
+ */
+#define PERCENTAGE(__value, __total) \
+ ( (__total) ? (((__value) * 100) / (__total)) : (DEFAULT_PERCENTAGE) )
+
+/*
+ * Helper struct and macro to work with moving/walking averages.
* When adding a value to the average value the following calculation
* is needed:
*
@@ -60,18 +68,28 @@
* for a few minutes but when the device is moved away from the AP
* the average will not decrease fast enough to compensate.
* The walking average compensates this and will move towards
- * the new values correctly allowing a effective link tuning.
- */
-#define MOVING_AVERAGE(__avg, __val, __samples) \
- ( (((__avg) * ((__samples) - 1)) + (__val)) / (__samples) )
-
-/*
- * Small helper macro for percentage calculation
- * This is a very simple macro with the only catch that it will
- * produce a default value in case no total value was provided.
+ * the new values correctly allowing a effective link tuning,
+ * the speed of the average moving towards other values depends
+ * on the value for the number of samples. The higher the number
+ * of samples, the slower the average will move.
+ * We use two variables to keep track of the average value to
+ * compensate for the rounding errors. This can be a significant
+ * error (>5dBm) if the factor is too low.
*/
-#define PERCENTAGE(__value, __total) \
- ( (__total) ? (((__value) * 100) / (__total)) : (DEFAULT_PERCENTAGE) )
+#define AVG_SAMPLES 8
+#define AVG_FACTOR 1000
+#define MOVING_AVERAGE(__avg, __val) \
+({ \
+ struct avg_val __new; \
+ __new.avg_weight = \
+ (__avg).avg_weight ? \
+ ((((__avg).avg_weight * ((AVG_SAMPLES) - 1)) + \
+ ((__val) * (AVG_FACTOR))) / \
+ (AVG_SAMPLES) ) : \
+ ((__val) * (AVG_FACTOR)); \
+ __new.avg = __new.avg_weight / (AVG_FACTOR); \
+ __new; \
+})
/*
* For calculating the Signal quality we have determined
@@ -98,56 +116,41 @@ static int rt2x00link_antenna_get_link_rssi(struct rt2x00_dev *rt2x00dev)
{
struct link_ant *ant = &rt2x00dev->link.ant;
- if (ant->rssi_ant && rt2x00dev->link.qual.rx_success)
- return ant->rssi_ant;
+ if (ant->rssi_ant.avg && rt2x00dev->link.qual.rx_success)
+ return ant->rssi_ant.avg;
return DEFAULT_RSSI;
}
-static int rt2x00link_antenna_get_rssi_history(struct rt2x00_dev *rt2x00dev,
- enum antenna antenna)
+static int rt2x00link_antenna_get_rssi_history(struct rt2x00_dev *rt2x00dev)
{
struct link_ant *ant = &rt2x00dev->link.ant;
- if (ant->rssi_history[antenna - ANTENNA_A])
- return ant->rssi_history[antenna - ANTENNA_A];
+ if (ant->rssi_history)
+ return ant->rssi_history;
return DEFAULT_RSSI;
}
-/* Small wrapper for rt2x00link_antenna_get_rssi_history() */
-#define rt2x00link_antenna_get_rssi_rx_history(__dev) \
- rt2x00link_antenna_get_rssi_history((__dev), \
- (__dev)->link.ant.active.rx)
-#define rt2x00link_antenna_get_rssi_tx_history(__dev) \
- rt2x00link_antenna_get_rssi_history((__dev), \
- (__dev)->link.ant.active.tx)
static void rt2x00link_antenna_update_rssi_history(struct rt2x00_dev *rt2x00dev,
- enum antenna antenna,
int rssi)
{
struct link_ant *ant = &rt2x00dev->link.ant;
- ant->rssi_history[ant->active.rx - ANTENNA_A] = rssi;
+ ant->rssi_history = rssi;
}
-/* Small wrapper for rt2x00link_antenna_get_rssi_history() */
-#define rt2x00link_antenna_update_rssi_rx_history(__dev, __rssi) \
- rt2x00link_antenna_update_rssi_history((__dev), \
- (__dev)->link.ant.active.rx, \
- (__rssi))
-#define rt2x00link_antenna_update_rssi_tx_history(__dev, __rssi) \
- rt2x00link_antenna_update_rssi_history((__dev), \
- (__dev)->link.ant.active.tx, \
- (__rssi))
static void rt2x00link_antenna_reset(struct rt2x00_dev *rt2x00dev)
{
- rt2x00dev->link.ant.rssi_ant = 0;
+ rt2x00dev->link.ant.rssi_ant.avg = 0;
+ rt2x00dev->link.ant.rssi_ant.avg_weight = 0;
}
static void rt2x00lib_antenna_diversity_sample(struct rt2x00_dev *rt2x00dev)
{
struct link_ant *ant = &rt2x00dev->link.ant;
struct antenna_setup new_ant;
- int sample_a = rt2x00link_antenna_get_rssi_history(rt2x00dev, ANTENNA_A);
- int sample_b = rt2x00link_antenna_get_rssi_history(rt2x00dev, ANTENNA_B);
+ int other_antenna;
+
+ int sample_current = rt2x00link_antenna_get_link_rssi(rt2x00dev);
+ int sample_other = rt2x00link_antenna_get_rssi_history(rt2x00dev);
memcpy(&new_ant, &ant->active, sizeof(new_ant));
@@ -158,22 +161,27 @@ static void rt2x00lib_antenna_diversity_sample(struct rt2x00_dev *rt2x00dev)
/*
* During the last period we have sampled the RSSI
- * from both antenna's. It now is time to determine
+ * from both antennas. It now is time to determine
* which antenna demonstrated the best performance.
* When we are already on the antenna with the best
- * performance, then there really is nothing for us
- * left to do.
+ * performance, just create a good starting point
+ * for the history and we are done.
*/
- if (sample_a == sample_b)
+ if (sample_current >= sample_other) {
+ rt2x00link_antenna_update_rssi_history(rt2x00dev,
+ sample_current);
return;
+ }
+
+ other_antenna = (ant->active.rx == ANTENNA_A) ? ANTENNA_B : ANTENNA_A;
if (ant->flags & ANTENNA_RX_DIVERSITY)
- new_ant.rx = (sample_a > sample_b) ? ANTENNA_A : ANTENNA_B;
+ new_ant.rx = other_antenna;
if (ant->flags & ANTENNA_TX_DIVERSITY)
- new_ant.tx = (sample_a > sample_b) ? ANTENNA_A : ANTENNA_B;
+ new_ant.tx = other_antenna;
- rt2x00lib_config_antenna(rt2x00dev, &new_ant);
+ rt2x00lib_config_antenna(rt2x00dev, new_ant);
}
static void rt2x00lib_antenna_diversity_eval(struct rt2x00_dev *rt2x00dev)
@@ -190,8 +198,8 @@ static void rt2x00lib_antenna_diversity_eval(struct rt2x00_dev *rt2x00dev)
* after that update the history with the current value.
*/
rssi_curr = rt2x00link_antenna_get_link_rssi(rt2x00dev);
- rssi_old = rt2x00link_antenna_get_rssi_rx_history(rt2x00dev);
- rt2x00link_antenna_update_rssi_rx_history(rt2x00dev, rssi_curr);
+ rssi_old = rt2x00link_antenna_get_rssi_history(rt2x00dev);
+ rt2x00link_antenna_update_rssi_history(rt2x00dev, rssi_curr);
/*
* Legacy driver indicates that we should swap antenna's
@@ -213,12 +221,13 @@ static void rt2x00lib_antenna_diversity_eval(struct rt2x00_dev *rt2x00dev)
if (ant->flags & ANTENNA_TX_DIVERSITY)
new_ant.tx = (new_ant.tx == ANTENNA_A) ? ANTENNA_B : ANTENNA_A;
- rt2x00lib_config_antenna(rt2x00dev, &new_ant);
+ rt2x00lib_config_antenna(rt2x00dev, new_ant);
}
-static void rt2x00lib_antenna_diversity(struct rt2x00_dev *rt2x00dev)
+static bool rt2x00lib_antenna_diversity(struct rt2x00_dev *rt2x00dev)
{
struct link_ant *ant = &rt2x00dev->link.ant;
+ unsigned int flags = ant->flags;
/*
* Determine if software diversity is enabled for
@@ -226,30 +235,38 @@ static void rt2x00lib_antenna_diversity(struct rt2x00_dev *rt2x00dev)
* Always perform this check since within the link
* tuner interval the configuration might have changed.
*/
- ant->flags &= ~ANTENNA_RX_DIVERSITY;
- ant->flags &= ~ANTENNA_TX_DIVERSITY;
+ flags &= ~ANTENNA_RX_DIVERSITY;
+ flags &= ~ANTENNA_TX_DIVERSITY;
if (rt2x00dev->default_ant.rx == ANTENNA_SW_DIVERSITY)
- ant->flags |= ANTENNA_RX_DIVERSITY;
+ flags |= ANTENNA_RX_DIVERSITY;
if (rt2x00dev->default_ant.tx == ANTENNA_SW_DIVERSITY)
- ant->flags |= ANTENNA_TX_DIVERSITY;
+ flags |= ANTENNA_TX_DIVERSITY;
if (!(ant->flags & ANTENNA_RX_DIVERSITY) &&
!(ant->flags & ANTENNA_TX_DIVERSITY)) {
ant->flags = 0;
- return;
+ return true;
}
+ /* Update flags */
+ ant->flags = flags;
+
/*
* If we have only sampled the data over the last period
* we should now harvest the data. Otherwise just evaluate
* the data. The latter should only be performed once
* every 2 seconds.
*/
- if (ant->flags & ANTENNA_MODE_SAMPLE)
+ if (ant->flags & ANTENNA_MODE_SAMPLE) {
rt2x00lib_antenna_diversity_sample(rt2x00dev);
- else if (rt2x00dev->link.count & 1)
+ return true;
+ } else if (rt2x00dev->link.count & 1) {
rt2x00lib_antenna_diversity_eval(rt2x00dev);
+ return true;
+ }
+
+ return false;
}
void rt2x00link_update_stats(struct rt2x00_dev *rt2x00dev,
@@ -260,8 +277,6 @@ void rt2x00link_update_stats(struct rt2x00_dev *rt2x00dev,
struct link_qual *qual = &rt2x00dev->link.qual;
struct link_ant *ant = &rt2x00dev->link.ant;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
- int avg_rssi = rxdesc->rssi;
- int ant_rssi = rxdesc->rssi;
/*
* Frame was received successfully since non-succesfull
@@ -281,16 +296,12 @@ void rt2x00link_update_stats(struct rt2x00_dev *rt2x00dev,
/*
* Update global RSSI
*/
- if (link->avg_rssi)
- avg_rssi = MOVING_AVERAGE(link->avg_rssi, rxdesc->rssi, 8);
- link->avg_rssi = avg_rssi;
+ link->avg_rssi = MOVING_AVERAGE(link->avg_rssi, rxdesc->rssi);
/*
* Update antenna RSSI
*/
- if (ant->rssi_ant)
- ant_rssi = MOVING_AVERAGE(ant->rssi_ant, rxdesc->rssi, 8);
- ant->rssi_ant = ant_rssi;
+ ant->rssi_ant = MOVING_AVERAGE(ant->rssi_ant, rxdesc->rssi);
}
static void rt2x00link_precalculate_signal(struct rt2x00_dev *rt2x00dev)
@@ -351,8 +362,8 @@ void rt2x00link_start_tuner(struct rt2x00_dev *rt2x00dev)
rt2x00link_reset_tuner(rt2x00dev, false);
- queue_delayed_work(rt2x00dev->hw->workqueue,
- &link->work, LINK_TUNE_INTERVAL);
+ ieee80211_queue_delayed_work(rt2x00dev->hw,
+ &link->work, LINK_TUNE_INTERVAL);
}
void rt2x00link_stop_tuner(struct rt2x00_dev *rt2x00dev)
@@ -423,10 +434,10 @@ static void rt2x00link_tuner(struct work_struct *work)
* collect the RSSI data we could use this. Otherwise we
* must fallback to the default RSSI value.
*/
- if (!link->avg_rssi || !qual->rx_success)
+ if (!link->avg_rssi.avg || !qual->rx_success)
qual->rssi = DEFAULT_RSSI;
else
- qual->rssi = link->avg_rssi;
+ qual->rssi = link->avg_rssi.avg;
/*
* Only perform the link tuning when Link tuning
@@ -444,25 +455,22 @@ static void rt2x00link_tuner(struct work_struct *work)
/*
* Send a signal to the led to update the led signal strength.
*/
- rt2x00leds_led_quality(rt2x00dev, link->avg_rssi);
-
- /*
- * Evaluate antenna setup, make this the last step since this could
- * possibly reset some statistics.
- */
- rt2x00lib_antenna_diversity(rt2x00dev);
+ rt2x00leds_led_quality(rt2x00dev, qual->rssi);
/*
- * Reset the quality counters which recounted during each period.
+ * Evaluate antenna setup, make this the last step when
+ * rt2x00lib_antenna_diversity made changes the quality
+ * statistics will be reset.
*/
- rt2x00link_reset_qual(rt2x00dev);
+ if (rt2x00lib_antenna_diversity(rt2x00dev))
+ rt2x00link_reset_qual(rt2x00dev);
/*
* Increase tuner counter, and reschedule the next link tuner run.
*/
link->count++;
- queue_delayed_work(rt2x00dev->hw->workqueue,
- &link->work, LINK_TUNE_INTERVAL);
+ ieee80211_queue_delayed_work(rt2x00dev->hw,
+ &link->work, LINK_TUNE_INTERVAL);
}
void rt2x00link_register(struct rt2x00_dev *rt2x00dev)
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c
index c4c06b4e1f0..cb7b6d45933 100644
--- a/drivers/net/wireless/rt2x00/rt2x00mac.c
+++ b/drivers/net/wireless/rt2x00/rt2x00mac.c
@@ -73,7 +73,8 @@ static int rt2x00mac_tx_rts_cts(struct rt2x00_dev *rt2x00dev,
else
rts_info->flags &= ~IEEE80211_TX_CTL_NO_ACK;
- skb->do_not_encrypt = 1;
+ /* Disable hardware encryption */
+ rts_info->control.hw_key = NULL;
/*
* RTS/CTS frame should use the length of the frame plus any
@@ -273,6 +274,7 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw,
spin_lock_init(&intf->lock);
spin_lock_init(&intf->seqlock);
+ mutex_init(&intf->beacon_skb_mutex);
intf->beacon = entry;
if (conf->type == NL80211_IFTYPE_AP)
@@ -337,54 +339,38 @@ int rt2x00mac_config(struct ieee80211_hw *hw, u32 changed)
{
struct rt2x00_dev *rt2x00dev = hw->priv;
struct ieee80211_conf *conf = &hw->conf;
- int status;
/*
- * Mac80211 might be calling this function while we are trying
+ * mac80211 might be calling this function while we are trying
* to remove the device or perhaps suspending it.
*/
if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
return 0;
/*
- * Only change device state when the radio is enabled. It does not
- * matter what parameters we have configured when the radio is disabled
- * because we won't be able to send or receive anyway. Also note that
- * some configuration parameters (e.g. channel and antenna values) can
- * only be set when the radio is enabled.
+ * Some configuration parameters (e.g. channel and antenna values) can
+ * only be set when the radio is enabled, but do require the RX to
+ * be off.
*/
- if (conf->radio_enabled) {
- /* For programming the values, we have to turn RX off */
- rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_OFF);
+ rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_OFF);
- /* Enable the radio */
- status = rt2x00lib_enable_radio(rt2x00dev);
- if (unlikely(status))
- return status;
+ /*
+ * When we've just turned on the radio, we want to reprogram
+ * everything to ensure a consistent state
+ */
+ rt2x00lib_config(rt2x00dev, conf, changed);
- /*
- * When we've just turned on the radio, we want to reprogram
- * everything to ensure a consistent state
- */
- rt2x00lib_config(rt2x00dev, conf, changed);
+ /*
+ * After the radio has been enabled we need to configure
+ * the antenna to the default settings. rt2x00lib_config_antenna()
+ * should determine if any action should be taken based on
+ * checking if diversity has been enabled or no antenna changes
+ * have been made since the last configuration change.
+ */
+ rt2x00lib_config_antenna(rt2x00dev, rt2x00dev->default_ant);
- /*
- * The radio was enabled, configure the antenna to the
- * default settings, the link tuner will later start
- * continue configuring the antenna based on the software
- * diversity. But for non-diversity configurations, we need
- * to have configured the correct state now.
- */
- if (changed & IEEE80211_CONF_CHANGE_RADIO_ENABLED)
- rt2x00lib_config_antenna(rt2x00dev,
- &rt2x00dev->default_ant);
-
- /* Turn RX back on */
- rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_ON);
- } else {
- /* Disable the radio */
- rt2x00lib_disable_radio(rt2x00dev);
- }
+ /* Turn RX back on */
+ rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_ON);
return 0;
}
@@ -406,6 +392,7 @@ void rt2x00mac_configure_filter(struct ieee80211_hw *hw,
FIF_FCSFAIL |
FIF_PLCPFAIL |
FIF_CONTROL |
+ FIF_PSPOLL |
FIF_OTHER_BSS |
FIF_PROMISC_IN_BSS;
@@ -421,6 +408,22 @@ void rt2x00mac_configure_filter(struct ieee80211_hw *hw,
*total_flags |= FIF_PROMISC_IN_BSS | FIF_OTHER_BSS;
/*
+ * If the device has a single filter for all control frames,
+ * FIF_CONTROL and FIF_PSPOLL flags imply each other.
+ * And if the device has more than one filter for control frames
+ * of different types, but has no a separate filter for PS Poll frames,
+ * FIF_CONTROL flag implies FIF_PSPOLL.
+ */
+ if (!test_bit(DRIVER_SUPPORT_CONTROL_FILTERS, &rt2x00dev->flags)) {
+ if (*total_flags & FIF_CONTROL || *total_flags & FIF_PSPOLL)
+ *total_flags |= FIF_CONTROL | FIF_PSPOLL;
+ }
+ if (!test_bit(DRIVER_SUPPORT_CONTROL_FILTER_PSPOLL, &rt2x00dev->flags)) {
+ if (*total_flags & FIF_CONTROL)
+ *total_flags |= FIF_PSPOLL;
+ }
+
+ /*
* Check if there is any work left for us.
*/
if (rt2x00dev->packet_filter == *total_flags)
@@ -430,10 +433,20 @@ void rt2x00mac_configure_filter(struct ieee80211_hw *hw,
if (!test_bit(DRIVER_REQUIRE_SCHEDULED, &rt2x00dev->flags))
rt2x00dev->ops->lib->config_filter(rt2x00dev, *total_flags);
else
- queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->filter_work);
+ ieee80211_queue_work(rt2x00dev->hw, &rt2x00dev->filter_work);
}
EXPORT_SYMBOL_GPL(rt2x00mac_configure_filter);
+int rt2x00mac_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta,
+ bool set)
+{
+ struct rt2x00_dev *rt2x00dev = hw->priv;
+
+ rt2x00lib_beacondone(rt2x00dev);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(rt2x00mac_set_tim);
+
#ifdef CONFIG_RT2X00_LIB_CRYPTO
static void memcpy_tkip(struct rt2x00lib_crypto *crypto, u8 *key, u8 key_len)
{
@@ -576,7 +589,7 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw,
int update_bssid = 0;
/*
- * Mac80211 might be calling this function while we are trying
+ * mac80211 might be calling this function while we are trying
* to remove the device or perhaps suspending it.
*/
if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
@@ -687,3 +700,12 @@ int rt2x00mac_conf_tx(struct ieee80211_hw *hw, u16 queue_idx,
return 0;
}
EXPORT_SYMBOL_GPL(rt2x00mac_conf_tx);
+
+void rt2x00mac_rfkill_poll(struct ieee80211_hw *hw)
+{
+ struct rt2x00_dev *rt2x00dev = hw->priv;
+ bool blocked = !!rt2x00dev->ops->lib->rfkill_poll(rt2x00dev);
+
+ wiphy_rfkill_set_hw_state(hw->wiphy, blocked);
+}
+EXPORT_SYMBOL_GPL(rt2x00mac_rfkill_poll);
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c
index 44e5b3279ca..06af823efd8 100644
--- a/drivers/net/wireless/rt2x00/rt2x00queue.c
+++ b/drivers/net/wireless/rt2x00/rt2x00queue.c
@@ -324,7 +324,8 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry,
/*
* Check if more fragments are pending
*/
- if (ieee80211_has_morefrags(hdr->frame_control)) {
+ if (ieee80211_has_morefrags(hdr->frame_control) ||
+ (tx_info->flags & IEEE80211_TX_CTL_MORE_FRAMES)) {
__set_bit(ENTRY_TXD_BURST, &txdesc->flags);
__set_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags);
}
@@ -452,9 +453,21 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb)
rt2x00crypto_tx_remove_iv(skb, &txdesc);
}
+ /*
+ * When DMA allocation is required we should guarentee to the
+ * driver that the DMA is aligned to a 4-byte boundary.
+ * Aligning the header to this boundary can be done by calling
+ * rt2x00queue_payload_align with the header length of 0.
+ * However some drivers require L2 padding to pad the payload
+ * rather then the header. This could be a requirement for
+ * PCI and USB devices, while header alignment only is valid
+ * for PCI devices.
+ */
if (test_bit(DRIVER_REQUIRE_L2PAD, &queue->rt2x00dev->flags))
rt2x00queue_payload_align(entry->skb, true,
txdesc.header_length);
+ else if (test_bit(DRIVER_REQUIRE_DMA, &queue->rt2x00dev->flags))
+ rt2x00queue_payload_align(entry->skb, false, 0);
/*
* It could be possible that the queue was corrupted and this
@@ -490,14 +503,25 @@ int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev,
if (unlikely(!intf->beacon))
return -ENOBUFS;
+ mutex_lock(&intf->beacon_skb_mutex);
+
+ /*
+ * Clean up the beacon skb.
+ */
+ rt2x00queue_free_skb(rt2x00dev, intf->beacon->skb);
+ intf->beacon->skb = NULL;
+
if (!enable_beacon) {
rt2x00dev->ops->lib->kill_tx_queue(rt2x00dev, QID_BEACON);
+ mutex_unlock(&intf->beacon_skb_mutex);
return 0;
}
intf->beacon->skb = ieee80211_beacon_get(rt2x00dev->hw, vif);
- if (!intf->beacon->skb)
+ if (!intf->beacon->skb) {
+ mutex_unlock(&intf->beacon_skb_mutex);
return -ENOMEM;
+ }
/*
* Copy all TX descriptor information into txdesc,
@@ -535,6 +559,8 @@ int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev,
rt2x00dev->ops->lib->write_beacon(intf->beacon);
rt2x00dev->ops->lib->kick_tx_queue(rt2x00dev, QID_BEACON);
+ mutex_unlock(&intf->beacon_skb_mutex);
+
return 0;
}
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h
index b5e06347c8a..47d175a1379 100644
--- a/drivers/net/wireless/rt2x00/rt2x00queue.h
+++ b/drivers/net/wireless/rt2x00/rt2x00queue.h
@@ -29,7 +29,7 @@
#include <linux/prefetch.h>
/**
- * DOC: Entrie frame size
+ * DOC: Entry frame size
*
* Ralink PCI devices demand the Frame size to be a multiple of 128 bytes,
* for USB devices this restriction does not apply, but the value of
@@ -45,13 +45,13 @@
/**
* DOC: Number of entries per queue
*
- * Under normal load without fragmentation 12 entries are sufficient
+ * Under normal load without fragmentation, 12 entries are sufficient
* without the queue being filled up to the maximum. When using fragmentation
- * and the queue threshold code we need to add some additional margins to
+ * and the queue threshold code, we need to add some additional margins to
* make sure the queue will never (or only under extreme load) fill up
* completely.
- * Since we don't use preallocated DMA having a large number of queue entries
- * will have only minimal impact on the memory requirements for the queue.
+ * Since we don't use preallocated DMA, having a large number of queue entries
+ * will have minimal impact on the memory requirements for the queue.
*/
#define RX_ENTRIES 24
#define TX_ENTRIES 24
diff --git a/drivers/net/wireless/rt2x00/rt2x00reg.h b/drivers/net/wireless/rt2x00/rt2x00reg.h
index 861322d97fc..983e52e127a 100644
--- a/drivers/net/wireless/rt2x00/rt2x00reg.h
+++ b/drivers/net/wireless/rt2x00/rt2x00reg.h
@@ -176,8 +176,8 @@ struct rt2x00_field32 {
#define is_valid_mask(x) is_power_of_two(1LU + (x) + low_bit_mask(x))
/*
- * Macro's to find first set bit in a variable.
- * These macro's behaves the same as the __ffs() function with
+ * Macros to find first set bit in a variable.
+ * These macros behave the same as the __ffs() functions but
* the most important difference that this is done during
* compile-time rather then run-time.
*/
diff --git a/drivers/net/wireless/rt2x00/rt2x00rfkill.c b/drivers/net/wireless/rt2x00/rt2x00rfkill.c
deleted file mode 100644
index b6d4c6700bf..00000000000
--- a/drivers/net/wireless/rt2x00/rt2x00rfkill.c
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
- <http://rt2x00.serialmonkey.com>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the
- Free Software Foundation, Inc.,
- 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-/*
- Module: rt2x00rfkill
- Abstract: rt2x00 rfkill routines.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-
-#include "rt2x00.h"
-#include "rt2x00lib.h"
-
-static void rt2x00rfkill_poll(struct input_polled_dev *poll_dev)
-{
- struct rt2x00_dev *rt2x00dev = poll_dev->private;
- int state, old_state;
-
- if (!test_bit(RFKILL_STATE_REGISTERED, &rt2x00dev->rfkill_state) ||
- !test_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags))
- return;
-
- /*
- * Poll latest state, if the state is different then the previous state,
- * we should generate an input event.
- */
- state = !!rt2x00dev->ops->lib->rfkill_poll(rt2x00dev);
- old_state = !!test_bit(RFKILL_STATE_BLOCKED, &rt2x00dev->rfkill_state);
-
- if (old_state != state) {
- input_report_switch(poll_dev->input, SW_RFKILL_ALL, state);
- change_bit(RFKILL_STATE_BLOCKED, &rt2x00dev->rfkill_state);
- }
-}
-
-void rt2x00rfkill_register(struct rt2x00_dev *rt2x00dev)
-{
- if (!test_bit(RFKILL_STATE_ALLOCATED, &rt2x00dev->rfkill_state) ||
- test_bit(RFKILL_STATE_REGISTERED, &rt2x00dev->rfkill_state))
- return;
-
- if (input_register_polled_device(rt2x00dev->rfkill_poll_dev)) {
- ERROR(rt2x00dev, "Failed to register polled device.\n");
- return;
- }
-
- __set_bit(RFKILL_STATE_REGISTERED, &rt2x00dev->rfkill_state);
-
- /*
- * Force initial poll which will detect the initial device state,
- * and correctly sends the signal to the input layer about this
- * state.
- */
- rt2x00rfkill_poll(rt2x00dev->rfkill_poll_dev);
-}
-
-void rt2x00rfkill_unregister(struct rt2x00_dev *rt2x00dev)
-{
- if (!test_bit(RFKILL_STATE_ALLOCATED, &rt2x00dev->rfkill_state) ||
- !test_bit(RFKILL_STATE_REGISTERED, &rt2x00dev->rfkill_state))
- return;
-
- input_unregister_polled_device(rt2x00dev->rfkill_poll_dev);
-
- __clear_bit(RFKILL_STATE_REGISTERED, &rt2x00dev->rfkill_state);
-}
-
-void rt2x00rfkill_allocate(struct rt2x00_dev *rt2x00dev)
-{
- struct input_polled_dev *poll_dev;
-
- if (test_bit(RFKILL_STATE_ALLOCATED, &rt2x00dev->rfkill_state) ||
- !test_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags))
- return;
-
- poll_dev = input_allocate_polled_device();
- if (!poll_dev) {
- ERROR(rt2x00dev, "Failed to allocate polled device.\n");
- return;
- }
-
- poll_dev->private = rt2x00dev;
- poll_dev->poll = rt2x00rfkill_poll;
- poll_dev->poll_interval = RFKILL_POLL_INTERVAL;
-
- poll_dev->input->name = rt2x00dev->ops->name;
- poll_dev->input->phys = wiphy_name(rt2x00dev->hw->wiphy);
- poll_dev->input->id.bustype = BUS_HOST;
- poll_dev->input->id.vendor = 0x1814;
- poll_dev->input->id.product = rt2x00dev->chip.rt;
- poll_dev->input->id.version = rt2x00dev->chip.rev;
- poll_dev->input->dev.parent = wiphy_dev(rt2x00dev->hw->wiphy);
- poll_dev->input->evbit[0] = BIT(EV_SW);
- poll_dev->input->swbit[0] = BIT(SW_RFKILL_ALL);
-
- rt2x00dev->rfkill_poll_dev = poll_dev;
-
- __set_bit(RFKILL_STATE_ALLOCATED, &rt2x00dev->rfkill_state);
-}
-
-void rt2x00rfkill_free(struct rt2x00_dev *rt2x00dev)
-{
- if (!__test_and_clear_bit(RFKILL_STATE_ALLOCATED,
- &rt2x00dev->rfkill_state))
- return;
-
- input_free_polled_device(rt2x00dev->rfkill_poll_dev);
- rt2x00dev->rfkill_poll_dev = NULL;
-}
diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c
index 49b29ff90c4..f4b4b86da4d 100644
--- a/drivers/net/wireless/rt2x00/rt61pci.c
+++ b/drivers/net/wireless/rt2x00/rt61pci.c
@@ -237,7 +237,6 @@ static const struct rt2x00debug rt61pci_rt2x00debug = {
};
#endif /* CONFIG_RT2X00_LIB_DEBUGFS */
-#ifdef CONFIG_RT2X00_LIB_RFKILL
static int rt61pci_rfkill_poll(struct rt2x00_dev *rt2x00dev)
{
u32 reg;
@@ -245,9 +244,6 @@ static int rt61pci_rfkill_poll(struct rt2x00_dev *rt2x00dev)
rt2x00pci_register_read(rt2x00dev, MAC_CSR13, &reg);
return rt2x00_get_field32(reg, MAC_CSR13_BIT5);
}
-#else
-#define rt61pci_rfkill_poll NULL
-#endif /* CONFIG_RT2X00_LIB_RFKILL */
#ifdef CONFIG_RT2X00_LIB_LEDS
static void rt61pci_brightness_set(struct led_classdev *led_cdev,
@@ -534,7 +530,7 @@ static void rt61pci_config_filter(struct rt2x00_dev *rt2x00dev,
rt2x00_set_field32(&reg, TXRX_CSR0_DROP_PHYSICAL,
!(filter_flags & FIF_PLCPFAIL));
rt2x00_set_field32(&reg, TXRX_CSR0_DROP_CONTROL,
- !(filter_flags & FIF_CONTROL));
+ !(filter_flags & (FIF_CONTROL | FIF_PSPOLL)));
rt2x00_set_field32(&reg, TXRX_CSR0_DROP_NOT_TO_ME,
!(filter_flags & FIF_PROMISC_IN_BSS));
rt2x00_set_field32(&reg, TXRX_CSR0_DROP_TO_DS,
@@ -1859,8 +1855,6 @@ static void rt61pci_write_beacon(struct queue_entry *entry)
* otherwise we might be sending out invalid data.
*/
rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, &reg);
- rt2x00_set_field32(&reg, TXRX_CSR9_TSF_TICKING, 0);
- rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE, 0);
rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 0);
rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg);
@@ -2316,7 +2310,7 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
}
/*
- * Determine number of antenna's.
+ * Determine number of antennas.
*/
if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_NUM) == 2)
__set_bit(CONFIG_DOUBLE_ANTENNA, &rt2x00dev->flags);
@@ -2338,10 +2332,8 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
/*
* Detect if this device has an hardware controlled radio.
*/
-#ifdef CONFIG_RT2X00_LIB_RFKILL
if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_HARDWARE_RADIO))
__set_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags);
-#endif /* CONFIG_RT2X00_LIB_RFKILL */
/*
* Read frequency offset and RF programming sequence.
@@ -2607,6 +2599,11 @@ static int rt61pci_probe_hw(struct rt2x00_dev *rt2x00dev)
int retval;
/*
+ * Disable power saving.
+ */
+ rt2x00pci_register_write(rt2x00dev, SOFT_RESET_CSR, 0x00000007);
+
+ /*
* Allocate eeprom data.
*/
retval = rt61pci_validate_eeprom(rt2x00dev);
@@ -2625,6 +2622,12 @@ static int rt61pci_probe_hw(struct rt2x00_dev *rt2x00dev)
return retval;
/*
+ * This device has multiple filters for control frames,
+ * but has no a separate filter for PS Poll frames.
+ */
+ __set_bit(DRIVER_SUPPORT_CONTROL_FILTERS, &rt2x00dev->flags);
+
+ /*
* This device requires firmware and DMA mapped skbs.
*/
__set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags);
@@ -2722,12 +2725,14 @@ static const struct ieee80211_ops rt61pci_mac80211_ops = {
.remove_interface = rt2x00mac_remove_interface,
.config = rt2x00mac_config,
.configure_filter = rt2x00mac_configure_filter,
+ .set_tim = rt2x00mac_set_tim,
.set_key = rt2x00mac_set_key,
.get_stats = rt2x00mac_get_stats,
.bss_info_changed = rt2x00mac_bss_info_changed,
.conf_tx = rt61pci_conf_tx,
.get_tx_stats = rt2x00mac_get_tx_stats,
.get_tsf = rt61pci_get_tsf,
+ .rfkill_poll = rt2x00mac_rfkill_poll,
};
static const struct rt2x00lib_ops rt61pci_rt2x00_ops = {
diff --git a/drivers/net/wireless/rt2x00/rt61pci.h b/drivers/net/wireless/rt2x00/rt61pci.h
index 6c71f77c816..93eb699165c 100644
--- a/drivers/net/wireless/rt2x00/rt61pci.h
+++ b/drivers/net/wireless/rt2x00/rt61pci.h
@@ -1476,7 +1476,7 @@ struct hw_pairwise_ta_entry {
#define RXD_W15_RESERVED FIELD32(0xffffffff)
/*
- * Macro's for converting txpower from EEPROM to mac80211 value
+ * Macros for converting txpower from EEPROM to mac80211 value
* and from mac80211 value to register value.
*/
#define MIN_TXPOWER 0
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c
index c18848836f2..4d94b65943f 100644
--- a/drivers/net/wireless/rt2x00/rt73usb.c
+++ b/drivers/net/wireless/rt2x00/rt73usb.c
@@ -183,7 +183,6 @@ static const struct rt2x00debug rt73usb_rt2x00debug = {
};
#endif /* CONFIG_RT2X00_LIB_DEBUGFS */
-#ifdef CONFIG_RT2X00_LIB_RFKILL
static int rt73usb_rfkill_poll(struct rt2x00_dev *rt2x00dev)
{
u32 reg;
@@ -191,9 +190,6 @@ static int rt73usb_rfkill_poll(struct rt2x00_dev *rt2x00dev)
rt2x00usb_register_read(rt2x00dev, MAC_CSR13, &reg);
return rt2x00_get_field32(reg, MAC_CSR13_BIT7);
}
-#else
-#define rt73usb_rfkill_poll NULL
-#endif /* CONFIG_RT2X00_LIB_RFKILL */
#ifdef CONFIG_RT2X00_LIB_LEDS
static void rt73usb_brightness_set(struct led_classdev *led_cdev,
@@ -497,7 +493,7 @@ static void rt73usb_config_filter(struct rt2x00_dev *rt2x00dev,
rt2x00_set_field32(&reg, TXRX_CSR0_DROP_PHYSICAL,
!(filter_flags & FIF_PLCPFAIL));
rt2x00_set_field32(&reg, TXRX_CSR0_DROP_CONTROL,
- !(filter_flags & FIF_CONTROL));
+ !(filter_flags & (FIF_CONTROL | FIF_PSPOLL)));
rt2x00_set_field32(&reg, TXRX_CSR0_DROP_NOT_TO_ME,
!(filter_flags & FIF_PROMISC_IN_BSS));
rt2x00_set_field32(&reg, TXRX_CSR0_DROP_TO_DS,
@@ -1531,8 +1527,6 @@ static void rt73usb_write_beacon(struct queue_entry *entry)
* otherwise we might be sending out invalid data.
*/
rt2x00usb_register_read(rt2x00dev, TXRX_CSR9, &reg);
- rt2x00_set_field32(&reg, TXRX_CSR9_TSF_TICKING, 0);
- rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE, 0);
rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 0);
rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg);
@@ -1863,10 +1857,8 @@ static int rt73usb_init_eeprom(struct rt2x00_dev *rt2x00dev)
/*
* Detect if this device has an hardware controlled radio.
*/
-#ifdef CONFIG_RT2X00_LIB_RFKILL
if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_HARDWARE_RADIO))
__set_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags);
-#endif /* CONFIG_RT2X00_LIB_RFKILL */
/*
* Read frequency offset.
@@ -2150,6 +2142,12 @@ static int rt73usb_probe_hw(struct rt2x00_dev *rt2x00dev)
return retval;
/*
+ * This device has multiple filters for control frames,
+ * but has no a separate filter for PS Poll frames.
+ */
+ __set_bit(DRIVER_SUPPORT_CONTROL_FILTERS, &rt2x00dev->flags);
+
+ /*
* This device requires firmware.
*/
__set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags);
@@ -2247,12 +2245,14 @@ static const struct ieee80211_ops rt73usb_mac80211_ops = {
.remove_interface = rt2x00mac_remove_interface,
.config = rt2x00mac_config,
.configure_filter = rt2x00mac_configure_filter,
+ .set_tim = rt2x00mac_set_tim,
.set_key = rt2x00mac_set_key,
.get_stats = rt2x00mac_get_stats,
.bss_info_changed = rt2x00mac_bss_info_changed,
.conf_tx = rt73usb_conf_tx,
.get_tx_stats = rt2x00mac_get_tx_stats,
.get_tsf = rt73usb_get_tsf,
+ .rfkill_poll = rt2x00mac_rfkill_poll,
};
static const struct rt2x00lib_ops rt73usb_rt2x00_ops = {
diff --git a/drivers/net/wireless/rt2x00/rt73usb.h b/drivers/net/wireless/rt2x00/rt73usb.h
index c8016f65b4b..81fe0be51c4 100644
--- a/drivers/net/wireless/rt2x00/rt73usb.h
+++ b/drivers/net/wireless/rt2x00/rt73usb.h
@@ -809,7 +809,7 @@ struct hw_pairwise_ta_entry {
/*
* EEPROM antenna.
- * ANTENNA_NUM: Number of antenna's.
+ * ANTENNA_NUM: Number of antennas.
* TX_DEFAULT: Default antenna 0: diversity, 1: A, 2: B.
* RX_DEFAULT: Default antenna 0: diversity, 1: A, 2: B.
* FRAME_TYPE: 0: DPDT , 1: SPDT , noted this bit is valid for g only.
@@ -1058,7 +1058,7 @@ struct hw_pairwise_ta_entry {
#define RXD_W5_RESERVED FIELD32(0xffffffff)
/*
- * Macro's for converting txpower from EEPROM to mac80211 value
+ * Macros for converting txpower from EEPROM to mac80211 value
* and from mac80211 value to register value.
*/
#define MIN_TXPOWER 0
diff --git a/drivers/net/wireless/rtl818x/rtl8180_dev.c b/drivers/net/wireless/rtl818x/rtl8180_dev.c
index 7e65d7c3180..09f46abc730 100644
--- a/drivers/net/wireless/rtl818x/rtl8180_dev.c
+++ b/drivers/net/wireless/rtl818x/rtl8180_dev.c
@@ -143,7 +143,8 @@ static void rtl8180_handle_rx(struct ieee80211_hw *dev)
if (flags & RTL818X_RX_DESC_FLAG_CRC32_ERR)
rx_status.flag |= RX_FLAG_FAILED_FCS_CRC;
- ieee80211_rx_irqsafe(dev, skb, &rx_status);
+ memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status));
+ ieee80211_rx_irqsafe(dev, skb);
skb = new_skb;
priv->rx_buf[priv->rx_idx] = skb;
@@ -280,7 +281,7 @@ static int rtl8180_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
(ieee80211_get_tx_rate(dev, info)->bitrate * 2) / 10);
remainder = (16 * (skb->len + 4)) %
((ieee80211_get_tx_rate(dev, info)->bitrate * 2) / 10);
- if (remainder > 0 && remainder <= 6)
+ if (remainder <= 6)
plcp_len |= 1 << 15;
}
diff --git a/drivers/net/wireless/rtl818x/rtl8187_dev.c b/drivers/net/wireless/rtl818x/rtl8187_dev.c
index 294250e294d..53f57dc5222 100644
--- a/drivers/net/wireless/rtl818x/rtl8187_dev.c
+++ b/drivers/net/wireless/rtl818x/rtl8187_dev.c
@@ -220,7 +220,7 @@ static void rtl8187_tx_cb(struct urb *urb)
* reading a register in the device. We are in interrupt mode
* here, thus queue the skb and finish on a work queue. */
skb_queue_tail(&priv->b_tx_status.queue, skb);
- queue_delayed_work(hw->workqueue, &priv->work, 0);
+ ieee80211_queue_delayed_work(hw, &priv->work, 0);
}
}
@@ -380,7 +380,8 @@ static void rtl8187_rx_cb(struct urb *urb)
rx_status.flag |= RX_FLAG_TSFT;
if (flags & RTL818X_RX_DESC_FLAG_CRC32_ERR)
rx_status.flag |= RX_FLAG_FAILED_FCS_CRC;
- ieee80211_rx_irqsafe(dev, skb, &rx_status);
+ memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status));
+ ieee80211_rx_irqsafe(dev, skb);
skb = dev_alloc_skb(RTL8187_MAX_RX);
if (unlikely(!skb)) {
diff --git a/drivers/net/wireless/rtl818x/rtl8187_leds.c b/drivers/net/wireless/rtl818x/rtl8187_leds.c
index cf9f899fe0e..a6cfb7e7799 100644
--- a/drivers/net/wireless/rtl818x/rtl8187_leds.c
+++ b/drivers/net/wireless/rtl818x/rtl8187_leds.c
@@ -108,11 +108,11 @@ static void rtl8187_led_brightness_set(struct led_classdev *led_dev,
struct rtl8187_priv *priv = hw->priv;
if (brightness == LED_OFF) {
- queue_delayed_work(hw->workqueue, &priv->led_off, 0);
+ ieee80211_queue_delayed_work(hw, &priv->led_off, 0);
/* The LED is off for 1/20 sec so that it just blinks. */
- queue_delayed_work(hw->workqueue, &priv->led_on, HZ / 20);
+ ieee80211_queue_delayed_work(hw, &priv->led_on, HZ / 20);
} else
- queue_delayed_work(hw->workqueue, &priv->led_on, 0);
+ ieee80211_queue_delayed_work(hw, &priv->led_on, 0);
}
static int rtl8187_register_led(struct ieee80211_hw *dev,
@@ -193,7 +193,7 @@ void rtl8187_leds_init(struct ieee80211_hw *dev, u16 custid)
err = rtl8187_register_led(dev, &priv->led_rx, name,
ieee80211_get_rx_led_name(dev), ledpin);
if (!err) {
- queue_delayed_work(dev->workqueue, &priv->led_on, 0);
+ ieee80211_queue_delayed_work(dev, &priv->led_on, 0);
return;
}
/* registration of RX LED failed - unregister TX */
@@ -209,7 +209,7 @@ void rtl8187_leds_exit(struct ieee80211_hw *dev)
struct rtl8187_priv *priv = dev->priv;
/* turn the LED off before exiting */
- queue_delayed_work(dev->workqueue, &priv->led_off, 0);
+ ieee80211_queue_delayed_work(dev, &priv->led_off, 0);
cancel_delayed_work_sync(&priv->led_off);
cancel_delayed_work_sync(&priv->led_on);
rtl8187_unregister_led(&priv->led_rx);
diff --git a/drivers/net/wireless/rtl818x/rtl818x.h b/drivers/net/wireless/rtl818x/rtl818x.h
index 34a5555cc19..562222e6cf1 100644
--- a/drivers/net/wireless/rtl818x/rtl818x.h
+++ b/drivers/net/wireless/rtl818x/rtl818x.h
@@ -194,8 +194,18 @@ struct rtl818x_rf_ops {
void (*conf_erp)(struct ieee80211_hw *, struct ieee80211_bss_conf *);
};
-/* Tx/Rx flags are common between RTL818X chips */
-
+/**
+ * enum rtl818x_tx_desc_flags - Tx/Rx flags are common between RTL818X chips
+ *
+ * @RTL818X_TX_DESC_FLAG_NO_ENC: Disable hardware based encryption.
+ * @RTL818X_TX_DESC_FLAG_TX_OK: TX frame was ACKed.
+ * @RTL818X_TX_DESC_FLAG_SPLCP: Use short preamble.
+ * @RTL818X_TX_DESC_FLAG_MOREFRAG: More fragments follow.
+ * @RTL818X_TX_DESC_FLAG_CTS: Use CTS-to-self protection.
+ * @RTL818X_TX_DESC_FLAG_RTS: Use RTS/CTS protection.
+ * @RTL818X_TX_DESC_FLAG_LS: Last segment of the frame.
+ * @RTL818X_TX_DESC_FLAG_FS: First segment of the frame.
+ */
enum rtl818x_tx_desc_flags {
RTL818X_TX_DESC_FLAG_NO_ENC = (1 << 15),
RTL818X_TX_DESC_FLAG_TX_OK = (1 << 15),
diff --git a/drivers/net/wireless/strip.c b/drivers/net/wireless/strip.c
index 38366a56b71..ef2cb20e96a 100644
--- a/drivers/net/wireless/strip.c
+++ b/drivers/net/wireless/strip.c
@@ -1550,9 +1550,12 @@ static int strip_xmit(struct sk_buff *skb, struct net_device *dev)
if (time_after(jiffies, strip_info->pps_timer + HZ)) {
unsigned long t = jiffies - strip_info->pps_timer;
- unsigned long rx_pps_count = (strip_info->rx_pps_count * HZ * 8 + t / 2) / t;
- unsigned long tx_pps_count = (strip_info->tx_pps_count * HZ * 8 + t / 2) / t;
- unsigned long sx_pps_count = (strip_info->sx_pps_count * HZ * 8 + t / 2) / t;
+ unsigned long rx_pps_count =
+ DIV_ROUND_CLOSEST(strip_info->rx_pps_count*HZ*8, t);
+ unsigned long tx_pps_count =
+ DIV_ROUND_CLOSEST(strip_info->tx_pps_count*HZ*8, t);
+ unsigned long sx_pps_count =
+ DIV_ROUND_CLOSEST(strip_info->sx_pps_count*HZ*8, t);
strip_info->pps_timer = jiffies;
strip_info->rx_pps_count = 0;
@@ -1582,7 +1585,7 @@ static int strip_xmit(struct sk_buff *skb, struct net_device *dev)
if (skb)
dev_kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
}
/*
diff --git a/drivers/net/wireless/wavelan.c b/drivers/net/wireless/wavelan.c
index ab7fc5c0c8b..5cb5329a20d 100644
--- a/drivers/net/wireless/wavelan.c
+++ b/drivers/net/wireless/wavelan.c
@@ -2891,7 +2891,7 @@ static int wavelan_packet_xmit(struct sk_buff *skb, struct net_device * dev)
#ifdef DEBUG_TX_TRACE
printk(KERN_DEBUG "%s: <-wavelan_packet_xmit()\n", dev->name);
#endif
- return 0;
+ return NETDEV_TX_OK;
}
/*********************** HARDWARE CONFIGURATION ***********************/
diff --git a/drivers/net/wireless/wavelan_cs.c b/drivers/net/wireless/wavelan_cs.c
index c6d300666ad..b9748d43201 100644
--- a/drivers/net/wireless/wavelan_cs.c
+++ b/drivers/net/wireless/wavelan_cs.c
@@ -3113,7 +3113,7 @@ wavelan_packet_xmit(struct sk_buff * skb,
* able to detect collisions, therefore in theory we don't really
* need to pad. Jean II */
if (skb_padto(skb, ETH_ZLEN))
- return 0;
+ return NETDEV_TX_OK;
wv_packet_write(dev, skb->data, skb->len);
@@ -3122,7 +3122,7 @@ wavelan_packet_xmit(struct sk_buff * skb,
#ifdef DEBUG_TX_TRACE
printk(KERN_DEBUG "%s: <-wavelan_packet_xmit()\n", dev->name);
#endif
- return(0);
+ return NETDEV_TX_OK;
}
/********************** HARDWARE CONFIGURATION **********************/
diff --git a/drivers/net/wireless/wl12xx/Kconfig b/drivers/net/wireless/wl12xx/Kconfig
index a82c4cd436d..7b14d5bc63d 100644
--- a/drivers/net/wireless/wl12xx/Kconfig
+++ b/drivers/net/wireless/wl12xx/Kconfig
@@ -1,11 +1,52 @@
-config WL12XX
- tristate "TI wl1251/wl1271 support"
- depends on MAC80211 && WLAN_80211 && SPI_MASTER && GENERIC_HARDIRQS && EXPERIMENTAL
+menuconfig WL12XX
+ boolean "TI wl12xx driver support"
+ depends on MAC80211 && WLAN_80211 && EXPERIMENTAL
+ ---help---
+ This will enable TI wl12xx driver support. The drivers make
+ use of the mac80211 stack.
+
+config WL1251
+ tristate "TI wl1251 support"
+ depends on WL12XX && GENERIC_HARDIRQS
select FW_LOADER
select CRC7
---help---
This module adds support for wireless adapters based on
- TI wl1251/wl1271 chipsets.
+ TI wl1251 chipset.
+
+ If you choose to build a module, it'll be called wl1251. Say
+ N if unsure.
+
+config WL1251_SPI
+ tristate "TI wl1251 SPI support"
+ depends on WL1251 && SPI_MASTER
+ ---help---
+ This module adds support for the SPI interface of adapters using
+ TI wl1251 chipset. Select this if your platform is using
+ the SPI bus.
+
+ If you choose to build a module, it'll be called wl1251_spi.
+ Say N if unsure.
+
+config WL1251_SDIO
+ tristate "TI wl1251 SDIO support"
+ depends on WL1251 && MMC
+ ---help---
+ This module adds support for the SDIO interface of adapters using
+ TI wl1251 chipset. Select this if your platform is using
+ the SDIO bus.
+
+ If you choose to build a module, it'll be called
+ wl1251_sdio. Say N if unsure.
+
+config WL1271
+ tristate "TI wl1271 support"
+ depends on WL12XX && SPI_MASTER && GENERIC_HARDIRQS
+ select FW_LOADER
+ select CRC7
+ ---help---
+ This module adds support for wireless adapters based on the
+ TI wl1271 chipset.
- If you choose to build a module, it'll be called wl12xx. Say N if
+ If you choose to build a module, it'll be called wl1271. Say N if
unsure.
diff --git a/drivers/net/wireless/wl12xx/Makefile b/drivers/net/wireless/wl12xx/Makefile
index d43de27dc54..62e37ad01cc 100644
--- a/drivers/net/wireless/wl12xx/Makefile
+++ b/drivers/net/wireless/wl12xx/Makefile
@@ -1,4 +1,14 @@
-wl12xx-objs = main.o spi.o event.o tx.o rx.o \
- ps.o cmd.o acx.o boot.o init.o wl1251.o \
- debugfs.o
-obj-$(CONFIG_WL12XX) += wl12xx.o
+wl1251-objs = wl1251_main.o wl1251_event.o \
+ wl1251_tx.o wl1251_rx.o wl1251_ps.o wl1251_cmd.o \
+ wl1251_acx.o wl1251_boot.o wl1251_init.o \
+ wl1251_debugfs.o wl1251_io.o
+
+obj-$(CONFIG_WL1251) += wl1251.o
+obj-$(CONFIG_WL1251_SPI) += wl1251_spi.o
+obj-$(CONFIG_WL1251_SDIO) += wl1251_sdio.o
+
+wl1271-objs = wl1271_main.o wl1271_spi.o wl1271_cmd.o \
+ wl1271_event.o wl1271_tx.o wl1271_rx.o \
+ wl1271_ps.o wl1271_acx.o wl1271_boot.o \
+ wl1271_init.o wl1271_debugfs.o
+obj-$(CONFIG_WL1271) += wl1271.o
diff --git a/drivers/net/wireless/wl12xx/acx.c b/drivers/net/wireless/wl12xx/acx.c
deleted file mode 100644
index 1cfd458ad5a..00000000000
--- a/drivers/net/wireless/wl12xx/acx.c
+++ /dev/null
@@ -1,689 +0,0 @@
-#include "acx.h"
-
-#include <linux/module.h>
-#include <linux/crc7.h>
-#include <linux/spi/spi.h>
-
-#include "wl12xx.h"
-#include "wl12xx_80211.h"
-#include "reg.h"
-#include "spi.h"
-#include "ps.h"
-
-int wl12xx_acx_frame_rates(struct wl12xx *wl, u8 ctrl_rate, u8 ctrl_mod,
- u8 mgt_rate, u8 mgt_mod)
-{
- int ret;
- struct acx_fw_gen_frame_rates rates;
-
- wl12xx_debug(DEBUG_ACX, "acx frame rates");
-
- rates.header.id = ACX_FW_GEN_FRAME_RATES;
- rates.header.len = sizeof(struct acx_fw_gen_frame_rates) -
- sizeof(struct acx_header);
-
- rates.tx_ctrl_frame_rate = ctrl_rate;
- rates.tx_ctrl_frame_mod = ctrl_mod;
- rates.tx_mgt_frame_rate = mgt_rate;
- rates.tx_mgt_frame_mod = mgt_mod;
-
- ret = wl12xx_cmd_configure(wl, &rates, sizeof(rates));
- if (ret < 0) {
- wl12xx_error("Failed to set FW rates and modulation");
- return ret;
- }
-
- return 0;
-}
-
-
-int wl12xx_acx_station_id(struct wl12xx *wl)
-{
- int ret, i;
- struct dot11_station_id mac;
-
- wl12xx_debug(DEBUG_ACX, "acx dot11_station_id");
-
- mac.header.id = DOT11_STATION_ID;
- mac.header.len = sizeof(mac) - sizeof(struct acx_header);
-
- for (i = 0; i < ETH_ALEN; i++)
- mac.mac[i] = wl->mac_addr[ETH_ALEN - 1 - i];
-
- ret = wl12xx_cmd_configure(wl, &mac, sizeof(mac));
- if (ret < 0)
- return ret;
-
- return 0;
-}
-
-int wl12xx_acx_default_key(struct wl12xx *wl, u8 key_id)
-{
- struct acx_dot11_default_key default_key;
- int ret;
-
- wl12xx_debug(DEBUG_ACX, "acx dot11_default_key (%d)", key_id);
-
- default_key.header.id = DOT11_DEFAULT_KEY;
- default_key.header.len = sizeof(default_key) -
- sizeof(struct acx_header);
-
- default_key.id = key_id;
-
- ret = wl12xx_cmd_configure(wl, &default_key, sizeof(default_key));
- if (ret < 0) {
- wl12xx_error("Couldnt set default key");
- return ret;
- }
-
- wl->default_key = key_id;
-
- return 0;
-}
-
-int wl12xx_acx_wake_up_conditions(struct wl12xx *wl, u8 listen_interval)
-{
- struct acx_wake_up_condition wake_up;
-
- wl12xx_debug(DEBUG_ACX, "acx wake up conditions");
-
- wake_up.header.id = ACX_WAKE_UP_CONDITIONS;
- wake_up.header.len = sizeof(wake_up) - sizeof(struct acx_header);
-
- wake_up.wake_up_event = WAKE_UP_EVENT_DTIM_BITMAP;
- wake_up.listen_interval = listen_interval;
-
- return wl12xx_cmd_configure(wl, &wake_up, sizeof(wake_up));
-}
-
-int wl12xx_acx_sleep_auth(struct wl12xx *wl, u8 sleep_auth)
-{
- int ret;
- struct acx_sleep_auth auth;
-
- wl12xx_debug(DEBUG_ACX, "acx sleep auth");
-
- auth.header.id = ACX_SLEEP_AUTH;
- auth.header.len = sizeof(auth) - sizeof(struct acx_header);
-
- auth.sleep_auth = sleep_auth;
-
- ret = wl12xx_cmd_configure(wl, &auth, sizeof(auth));
- if (ret < 0)
- return ret;
-
- return 0;
-}
-
-int wl12xx_acx_fw_version(struct wl12xx *wl, char *buf, size_t len)
-{
- struct wl12xx_command cmd;
- struct acx_revision *rev;
- int ret;
-
- wl12xx_debug(DEBUG_ACX, "acx fw rev");
-
- memset(&cmd, 0, sizeof(cmd));
-
- ret = wl12xx_cmd_interrogate(wl, ACX_FW_REV, sizeof(*rev), &cmd);
- if (ret < 0) {
- wl12xx_warning("ACX_FW_REV interrogate failed");
- return ret;
- }
-
- rev = (struct acx_revision *) &cmd.parameters;
-
- /* be careful with the buffer sizes */
- strncpy(buf, rev->fw_version, min(len, sizeof(rev->fw_version)));
-
- /*
- * if the firmware version string is exactly
- * sizeof(rev->fw_version) long or fw_len is less than
- * sizeof(rev->fw_version) it won't be null terminated
- */
- buf[min(len, sizeof(rev->fw_version)) - 1] = '\0';
-
- return 0;
-}
-
-int wl12xx_acx_tx_power(struct wl12xx *wl, int power)
-{
- struct acx_current_tx_power ie;
- int ret;
-
- wl12xx_debug(DEBUG_ACX, "acx dot11_cur_tx_pwr");
-
- if (power < 0 || power > 25)
- return -EINVAL;
-
- memset(&ie, 0, sizeof(ie));
-
- ie.header.id = DOT11_CUR_TX_PWR;
- ie.header.len = sizeof(ie) - sizeof(struct acx_header);
- ie.current_tx_power = power * 10;
-
- ret = wl12xx_cmd_configure(wl, &ie, sizeof(ie));
- if (ret < 0) {
- wl12xx_warning("configure of tx power failed: %d", ret);
- return ret;
- }
-
- return 0;
-}
-
-int wl12xx_acx_feature_cfg(struct wl12xx *wl)
-{
- struct acx_feature_config feature;
- int ret;
-
- wl12xx_debug(DEBUG_ACX, "acx feature cfg");
-
- memset(&feature, 0, sizeof(feature));
-
- feature.header.id = ACX_FEATURE_CFG;
- feature.header.len = sizeof(feature) - sizeof(struct acx_header);
-
- /* DF_ENCRYPTION_DISABLE and DF_SNIFF_MODE_ENABLE are disabled */
- feature.data_flow_options = 0;
- feature.options = 0;
-
- ret = wl12xx_cmd_configure(wl, &feature, sizeof(feature));
- if (ret < 0)
- wl12xx_error("Couldnt set HW encryption");
-
- return ret;
-}
-
-int wl12xx_acx_mem_map(struct wl12xx *wl, void *mem_map, size_t len)
-{
- struct wl12xx_command cmd;
- int ret;
-
- wl12xx_debug(DEBUG_ACX, "acx mem map");
-
- ret = wl12xx_cmd_interrogate(wl, ACX_MEM_MAP, len, &cmd);
- if (ret < 0)
- return ret;
- else if (cmd.status != CMD_STATUS_SUCCESS)
- return -EIO;
-
- memcpy(mem_map, &cmd.parameters, len);
-
- return 0;
-}
-
-int wl12xx_acx_data_path_params(struct wl12xx *wl,
- struct acx_data_path_params_resp *data_path)
-{
- struct acx_data_path_params params;
- struct wl12xx_command cmd;
- int ret;
-
- wl12xx_debug(DEBUG_ACX, "acx data path params");
-
- params.rx_packet_ring_chunk_size = DP_RX_PACKET_RING_CHUNK_SIZE;
- params.tx_packet_ring_chunk_size = DP_TX_PACKET_RING_CHUNK_SIZE;
-
- params.rx_packet_ring_chunk_num = DP_RX_PACKET_RING_CHUNK_NUM;
- params.tx_packet_ring_chunk_num = DP_TX_PACKET_RING_CHUNK_NUM;
-
- params.tx_complete_threshold = 1;
-
- params.tx_complete_ring_depth = FW_TX_CMPLT_BLOCK_SIZE;
-
- params.tx_complete_timeout = DP_TX_COMPLETE_TIME_OUT;
-
- params.header.id = ACX_DATA_PATH_PARAMS;
- params.header.len = sizeof(params) - sizeof(struct acx_header);
-
- ret = wl12xx_cmd_configure(wl, &params, sizeof(params));
- if (ret < 0)
- return ret;
-
-
- ret = wl12xx_cmd_interrogate(wl, ACX_DATA_PATH_PARAMS,
- sizeof(struct acx_data_path_params_resp),
- &cmd);
-
- if (ret < 0) {
- wl12xx_warning("failed to read data path parameters: %d", ret);
- return ret;
- } else if (cmd.status != CMD_STATUS_SUCCESS) {
- wl12xx_warning("data path parameter acx status failed");
- return -EIO;
- }
-
- memcpy(data_path, &cmd.parameters, sizeof(*data_path));
-
- return 0;
-}
-
-int wl12xx_acx_rx_msdu_life_time(struct wl12xx *wl, u32 life_time)
-{
- struct rx_msdu_lifetime msdu_lifetime;
- int ret;
-
- wl12xx_debug(DEBUG_ACX, "acx rx msdu life time");
-
- msdu_lifetime.header.id = DOT11_RX_MSDU_LIFE_TIME;
- msdu_lifetime.header.len = sizeof(msdu_lifetime) -
- sizeof(struct acx_header);
- msdu_lifetime.lifetime = life_time;
-
- ret = wl12xx_cmd_configure(wl, &msdu_lifetime, sizeof(msdu_lifetime));
- if (ret < 0) {
- wl12xx_warning("failed to set rx msdu life time: %d", ret);
- return ret;
- }
-
- return 0;
-}
-
-int wl12xx_acx_rx_config(struct wl12xx *wl, u32 config, u32 filter)
-{
- struct acx_rx_config rx_config;
- int ret;
-
- wl12xx_debug(DEBUG_ACX, "acx rx config");
-
- rx_config.header.id = ACX_RX_CFG;
- rx_config.header.len = sizeof(rx_config) - sizeof(struct acx_header);
- rx_config.config_options = config;
- rx_config.filter_options = filter;
-
- ret = wl12xx_cmd_configure(wl, &rx_config, sizeof(rx_config));
- if (ret < 0) {
- wl12xx_warning("failed to set rx config: %d", ret);
- return ret;
- }
-
- return 0;
-}
-
-int wl12xx_acx_pd_threshold(struct wl12xx *wl)
-{
- struct acx_packet_detection packet_detection;
- int ret;
-
- wl12xx_debug(DEBUG_ACX, "acx data pd threshold");
-
- /* FIXME: threshold value not set */
- packet_detection.header.id = ACX_PD_THRESHOLD;
- packet_detection.header.len = sizeof(packet_detection) -
- sizeof(struct acx_header);
-
- ret = wl12xx_cmd_configure(wl, &packet_detection,
- sizeof(packet_detection));
- if (ret < 0) {
- wl12xx_warning("failed to set pd threshold: %d", ret);
- return ret;
- }
-
- return 0;
-}
-
-int wl12xx_acx_slot(struct wl12xx *wl, enum acx_slot_type slot_time)
-{
- struct acx_slot slot;
- int ret;
-
- wl12xx_debug(DEBUG_ACX, "acx slot");
-
- slot.header.id = ACX_SLOT;
- slot.header.len = sizeof(slot) - sizeof(struct acx_header);
-
- slot.wone_index = STATION_WONE_INDEX;
- slot.slot_time = slot_time;
-
- ret = wl12xx_cmd_configure(wl, &slot, sizeof(slot));
- if (ret < 0) {
- wl12xx_warning("failed to set slot time: %d", ret);
- return ret;
- }
-
- return 0;
-}
-
-int wl12xx_acx_group_address_tbl(struct wl12xx *wl)
-{
- struct multicast_grp_addr_start multicast;
- int ret;
-
- wl12xx_debug(DEBUG_ACX, "acx group address tbl");
-
- /* MAC filtering */
- multicast.header.id = DOT11_GROUP_ADDRESS_TBL;
- multicast.header.len = sizeof(multicast) - sizeof(struct acx_header);
-
- multicast.enabled = 0;
- multicast.num_groups = 0;
- memset(multicast.mac_table, 0, ADDRESS_GROUP_MAX_LEN);
-
- ret = wl12xx_cmd_configure(wl, &multicast, sizeof(multicast));
- if (ret < 0) {
- wl12xx_warning("failed to set group addr table: %d", ret);
- return ret;
- }
-
- return 0;
-}
-
-int wl12xx_acx_service_period_timeout(struct wl12xx *wl)
-{
- struct acx_rx_timeout rx_timeout;
- int ret;
-
- wl12xx_debug(DEBUG_ACX, "acx service period timeout");
-
- /* RX timeout */
- rx_timeout.header.id = ACX_SERVICE_PERIOD_TIMEOUT;
- rx_timeout.header.len = sizeof(rx_timeout) - sizeof(struct acx_header);
-
- rx_timeout.ps_poll_timeout = RX_TIMEOUT_PS_POLL_DEF;
- rx_timeout.upsd_timeout = RX_TIMEOUT_UPSD_DEF;
-
- ret = wl12xx_cmd_configure(wl, &rx_timeout, sizeof(rx_timeout));
- if (ret < 0) {
- wl12xx_warning("failed to set service period timeout: %d",
- ret);
- return ret;
- }
-
- return 0;
-}
-
-int wl12xx_acx_rts_threshold(struct wl12xx *wl, u16 rts_threshold)
-{
- struct acx_rts_threshold rts;
- int ret;
-
- wl12xx_debug(DEBUG_ACX, "acx rts threshold");
-
- rts.header.id = DOT11_RTS_THRESHOLD;
- rts.header.len = sizeof(rts) - sizeof(struct acx_header);
-
- rts.threshold = rts_threshold;
-
- ret = wl12xx_cmd_configure(wl, &rts, sizeof(rts));
- if (ret < 0) {
- wl12xx_warning("failed to set rts threshold: %d", ret);
- return ret;
- }
-
- return 0;
-}
-
-int wl12xx_acx_beacon_filter_opt(struct wl12xx *wl)
-{
- struct acx_beacon_filter_option beacon_filter;
- int ret;
-
- wl12xx_debug(DEBUG_ACX, "acx beacon filter opt");
-
- beacon_filter.header.id = ACX_BEACON_FILTER_OPT;
- beacon_filter.header.len = sizeof(beacon_filter) -
- sizeof(struct acx_header);
-
- beacon_filter.enable = 0;
- beacon_filter.max_num_beacons = 0;
-
- ret = wl12xx_cmd_configure(wl, &beacon_filter, sizeof(beacon_filter));
- if (ret < 0) {
- wl12xx_warning("failed to set beacon filter opt: %d", ret);
- return ret;
- }
-
- return 0;
-}
-
-int wl12xx_acx_beacon_filter_table(struct wl12xx *wl)
-{
- struct acx_beacon_filter_ie_table ie_table;
- int ret;
-
- wl12xx_debug(DEBUG_ACX, "acx beacon filter table");
-
- ie_table.header.id = ACX_BEACON_FILTER_TABLE;
- ie_table.header.len = sizeof(ie_table) - sizeof(struct acx_header);
-
- ie_table.num_ie = 0;
- memset(ie_table.table, 0, BEACON_FILTER_TABLE_MAX_SIZE);
-
- ret = wl12xx_cmd_configure(wl, &ie_table, sizeof(ie_table));
- if (ret < 0) {
- wl12xx_warning("failed to set beacon filter table: %d", ret);
- return ret;
- }
-
- return 0;
-}
-
-int wl12xx_acx_sg_enable(struct wl12xx *wl)
-{
- struct acx_bt_wlan_coex pta;
- int ret;
-
- wl12xx_debug(DEBUG_ACX, "acx sg enable");
-
- pta.header.id = ACX_SG_ENABLE;
- pta.header.len = sizeof(pta) - sizeof(struct acx_header);
-
- pta.enable = SG_ENABLE;
-
- ret = wl12xx_cmd_configure(wl, &pta, sizeof(pta));
- if (ret < 0) {
- wl12xx_warning("failed to set softgemini enable: %d", ret);
- return ret;
- }
-
- return 0;
-}
-
-int wl12xx_acx_sg_cfg(struct wl12xx *wl)
-{
- struct acx_bt_wlan_coex_param param;
- int ret;
-
- wl12xx_debug(DEBUG_ACX, "acx sg cfg");
-
- /* BT-WLAN coext parameters */
- param.header.id = ACX_SG_CFG;
- param.header.len = sizeof(param) - sizeof(struct acx_header);
-
- param.min_rate = RATE_INDEX_24MBPS;
- param.bt_hp_max_time = PTA_BT_HP_MAXTIME_DEF;
- param.wlan_hp_max_time = PTA_WLAN_HP_MAX_TIME_DEF;
- param.sense_disable_timer = PTA_SENSE_DISABLE_TIMER_DEF;
- param.rx_time_bt_hp = PTA_PROTECTIVE_RX_TIME_DEF;
- param.tx_time_bt_hp = PTA_PROTECTIVE_TX_TIME_DEF;
- param.rx_time_bt_hp_fast = PTA_PROTECTIVE_RX_TIME_FAST_DEF;
- param.tx_time_bt_hp_fast = PTA_PROTECTIVE_TX_TIME_FAST_DEF;
- param.wlan_cycle_fast = PTA_CYCLE_TIME_FAST_DEF;
- param.bt_anti_starvation_period = PTA_ANTI_STARVE_PERIOD_DEF;
- param.next_bt_lp_packet = PTA_TIMEOUT_NEXT_BT_LP_PACKET_DEF;
- param.wake_up_beacon = PTA_TIME_BEFORE_BEACON_DEF;
- param.hp_dm_max_guard_time = PTA_HPDM_MAX_TIME_DEF;
- param.next_wlan_packet = PTA_TIME_OUT_NEXT_WLAN_DEF;
- param.antenna_type = PTA_ANTENNA_TYPE_DEF;
- param.signal_type = PTA_SIGNALING_TYPE_DEF;
- param.afh_leverage_on = PTA_AFH_LEVERAGE_ON_DEF;
- param.quiet_cycle_num = PTA_NUMBER_QUIET_CYCLE_DEF;
- param.max_cts = PTA_MAX_NUM_CTS_DEF;
- param.wlan_packets_num = PTA_NUMBER_OF_WLAN_PACKETS_DEF;
- param.bt_packets_num = PTA_NUMBER_OF_BT_PACKETS_DEF;
- param.missed_rx_avalanche = PTA_RX_FOR_AVALANCHE_DEF;
- param.wlan_elp_hp = PTA_ELP_HP_DEF;
- param.bt_anti_starvation_cycles = PTA_ANTI_STARVE_NUM_CYCLE_DEF;
- param.ack_mode_dual_ant = PTA_ACK_MODE_DEF;
- param.pa_sd_enable = PTA_ALLOW_PA_SD_DEF;
- param.pta_auto_mode_enable = PTA_AUTO_MODE_NO_CTS_DEF;
- param.bt_hp_respected_num = PTA_BT_HP_RESPECTED_DEF;
-
- ret = wl12xx_cmd_configure(wl, &param, sizeof(param));
- if (ret < 0) {
- wl12xx_warning("failed to set sg config: %d", ret);
- return ret;
- }
-
- return 0;
-}
-
-int wl12xx_acx_cca_threshold(struct wl12xx *wl)
-{
- struct acx_energy_detection detection;
- int ret;
-
- wl12xx_debug(DEBUG_ACX, "acx cca threshold");
-
- detection.header.id = ACX_CCA_THRESHOLD;
- detection.header.len = sizeof(detection) - sizeof(struct acx_header);
-
- detection.rx_cca_threshold = CCA_THRSH_DISABLE_ENERGY_D;
- detection.tx_energy_detection = 0;
-
- ret = wl12xx_cmd_configure(wl, &detection, sizeof(detection));
- if (ret < 0) {
- wl12xx_warning("failed to set cca threshold: %d", ret);
- return ret;
- }
-
- return 0;
-}
-
-int wl12xx_acx_bcn_dtim_options(struct wl12xx *wl)
-{
- struct acx_beacon_broadcast bb;
- int ret;
-
- wl12xx_debug(DEBUG_ACX, "acx bcn dtim options");
-
- bb.header.id = ACX_BCN_DTIM_OPTIONS;
- bb.header.len = sizeof(bb) - sizeof(struct acx_header);
-
- bb.beacon_rx_timeout = BCN_RX_TIMEOUT_DEF_VALUE;
- bb.broadcast_timeout = BROADCAST_RX_TIMEOUT_DEF_VALUE;
- bb.rx_broadcast_in_ps = RX_BROADCAST_IN_PS_DEF_VALUE;
- bb.ps_poll_threshold = CONSECUTIVE_PS_POLL_FAILURE_DEF;
-
- ret = wl12xx_cmd_configure(wl, &bb, sizeof(bb));
- if (ret < 0) {
- wl12xx_warning("failed to set rx config: %d", ret);
- return ret;
- }
-
- return 0;
-}
-
-int wl12xx_acx_aid(struct wl12xx *wl, u16 aid)
-{
- struct acx_aid acx_aid;
- int ret;
-
- wl12xx_debug(DEBUG_ACX, "acx aid");
-
- acx_aid.header.id = ACX_AID;
- acx_aid.header.len = sizeof(acx_aid) - sizeof(struct acx_header);
-
- acx_aid.aid = aid;
-
- ret = wl12xx_cmd_configure(wl, &acx_aid, sizeof(acx_aid));
- if (ret < 0) {
- wl12xx_warning("failed to set aid: %d", ret);
- return ret;
- }
-
- return 0;
-}
-
-int wl12xx_acx_event_mbox_mask(struct wl12xx *wl, u32 event_mask)
-{
- struct acx_event_mask mask;
- int ret;
-
- wl12xx_debug(DEBUG_ACX, "acx event mbox mask");
-
- mask.header.id = ACX_EVENT_MBOX_MASK;
- mask.header.len = sizeof(mask) - sizeof(struct acx_header);
-
- /* high event mask is unused */
- mask.high_event_mask = 0xffffffff;
-
- mask.event_mask = event_mask;
-
- ret = wl12xx_cmd_configure(wl, &mask, sizeof(mask));
- if (ret < 0) {
- wl12xx_warning("failed to set aid: %d", ret);
- return ret;
- }
-
- return 0;
-}
-
-int wl12xx_acx_set_preamble(struct wl12xx *wl, enum acx_preamble_type preamble)
-{
- struct acx_preamble ie;
- int ret;
-
- wl12xx_debug(DEBUG_ACX, "acx_set_preamble");
-
- memset(&ie, 0, sizeof(ie));
-
- ie.header.id = ACX_PREAMBLE_TYPE;
- ie.header.len = sizeof(ie) - sizeof(struct acx_header);
- ie.preamble = preamble;
- ret = wl12xx_cmd_configure(wl, &ie, sizeof(ie));
- if (ret < 0) {
- wl12xx_warning("Setting of preamble failed: %d", ret);
- return ret;
- }
- return 0;
-}
-
-int wl12xx_acx_cts_protect(struct wl12xx *wl,
- enum acx_ctsprotect_type ctsprotect)
-{
- struct acx_ctsprotect ie;
- int ret;
-
- wl12xx_debug(DEBUG_ACX, "acx_set_ctsprotect");
-
- memset(&ie, 0, sizeof(ie));
-
- ie.header.id = ACX_CTS_PROTECTION;
- ie.header.len = sizeof(ie) - sizeof(struct acx_header);
- ie.ctsprotect = ctsprotect;
- ret = wl12xx_cmd_configure(wl, &ie, sizeof(ie));
- if (ret < 0) {
- wl12xx_warning("Setting of ctsprotect failed: %d", ret);
- return ret;
- }
- return 0;
-}
-
-int wl12xx_acx_statistics(struct wl12xx *wl, struct acx_statistics *stats)
-{
- struct wl12xx_command *answer;
- int ret;
-
- wl12xx_debug(DEBUG_ACX, "acx statistics");
-
- answer = kmalloc(sizeof(*answer), GFP_KERNEL);
- if (!answer) {
- wl12xx_warning("could not allocate memory for acx statistics");
- ret = -ENOMEM;
- goto out;
- }
-
- ret = wl12xx_cmd_interrogate(wl, ACX_STATISTICS, sizeof(*answer),
- answer);
- if (ret < 0) {
- wl12xx_warning("acx statistics failed: %d", ret);
- goto out;
- }
-
- memcpy(stats, answer->parameters, sizeof(*stats));
-
-out:
- kfree(answer);
- return ret;
-}
diff --git a/drivers/net/wireless/wl12xx/boot.c b/drivers/net/wireless/wl12xx/boot.c
deleted file mode 100644
index 48ac08c429b..00000000000
--- a/drivers/net/wireless/wl12xx/boot.c
+++ /dev/null
@@ -1,295 +0,0 @@
-/*
- * This file is part of wl12xx
- *
- * Copyright (C) 2008 Nokia Corporation
- *
- * Contact: Kalle Valo <kalle.valo@nokia.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- *
- */
-
-#include <linux/gpio.h>
-
-#include "reg.h"
-#include "boot.h"
-#include "spi.h"
-#include "event.h"
-
-static void wl12xx_boot_enable_interrupts(struct wl12xx *wl)
-{
- enable_irq(wl->irq);
-}
-
-void wl12xx_boot_target_enable_interrupts(struct wl12xx *wl)
-{
- wl12xx_reg_write32(wl, ACX_REG_INTERRUPT_MASK, ~(wl->intr_mask));
- wl12xx_reg_write32(wl, HI_CFG, HI_CFG_DEF_VAL);
-}
-
-int wl12xx_boot_soft_reset(struct wl12xx *wl)
-{
- unsigned long timeout;
- u32 boot_data;
-
- /* perform soft reset */
- wl12xx_reg_write32(wl, ACX_REG_SLV_SOFT_RESET, ACX_SLV_SOFT_RESET_BIT);
-
- /* SOFT_RESET is self clearing */
- timeout = jiffies + usecs_to_jiffies(SOFT_RESET_MAX_TIME);
- while (1) {
- boot_data = wl12xx_reg_read32(wl, ACX_REG_SLV_SOFT_RESET);
- wl12xx_debug(DEBUG_BOOT, "soft reset bootdata 0x%x", boot_data);
- if ((boot_data & ACX_SLV_SOFT_RESET_BIT) == 0)
- break;
-
- if (time_after(jiffies, timeout)) {
- /* 1.2 check pWhalBus->uSelfClearTime if the
- * timeout was reached */
- wl12xx_error("soft reset timeout");
- return -1;
- }
-
- udelay(SOFT_RESET_STALL_TIME);
- }
-
- /* disable Rx/Tx */
- wl12xx_reg_write32(wl, ENABLE, 0x0);
-
- /* disable auto calibration on start*/
- wl12xx_reg_write32(wl, SPARE_A2, 0xffff);
-
- return 0;
-}
-
-int wl12xx_boot_init_seq(struct wl12xx *wl)
-{
- u32 scr_pad6, init_data, tmp, elp_cmd, ref_freq;
-
- /*
- * col #1: INTEGER_DIVIDER
- * col #2: FRACTIONAL_DIVIDER
- * col #3: ATTN_BB
- * col #4: ALPHA_BB
- * col #5: STOP_TIME_BB
- * col #6: BB_PLL_LOOP_FILTER
- */
- static const u32 LUT[REF_FREQ_NUM][LUT_PARAM_NUM] = {
-
- { 83, 87381, 0xB, 5, 0xF00, 3}, /* REF_FREQ_19_2*/
- { 61, 141154, 0xB, 5, 0x1450, 2}, /* REF_FREQ_26_0*/
- { 41, 174763, 0xC, 6, 0x2D00, 1}, /* REF_FREQ_38_4*/
- { 40, 0, 0xC, 6, 0x2EE0, 1}, /* REF_FREQ_40_0*/
- { 47, 162280, 0xC, 6, 0x2760, 1} /* REF_FREQ_33_6 */
- };
-
- /* read NVS params */
- scr_pad6 = wl12xx_reg_read32(wl, SCR_PAD6);
- wl12xx_debug(DEBUG_BOOT, "scr_pad6 0x%x", scr_pad6);
-
- /* read ELP_CMD */
- elp_cmd = wl12xx_reg_read32(wl, ELP_CMD);
- wl12xx_debug(DEBUG_BOOT, "elp_cmd 0x%x", elp_cmd);
-
- /* set the BB calibration time to be 300 usec (PLL_CAL_TIME) */
- ref_freq = scr_pad6 & 0x000000FF;
- wl12xx_debug(DEBUG_BOOT, "ref_freq 0x%x", ref_freq);
-
- wl12xx_reg_write32(wl, PLL_CAL_TIME, 0x9);
-
- /*
- * PG 1.2: set the clock buffer time to be 210 usec (CLK_BUF_TIME)
- */
- wl12xx_reg_write32(wl, CLK_BUF_TIME, 0x6);
-
- /*
- * set the clock detect feature to work in the restart wu procedure
- * (ELP_CFG_MODE[14]) and Select the clock source type
- * (ELP_CFG_MODE[13:12])
- */
- tmp = ((scr_pad6 & 0x0000FF00) << 4) | 0x00004000;
- wl12xx_reg_write32(wl, ELP_CFG_MODE, tmp);
-
- /* PG 1.2: enable the BB PLL fix. Enable the PLL_LIMP_CLK_EN_CMD */
- elp_cmd |= 0x00000040;
- wl12xx_reg_write32(wl, ELP_CMD, elp_cmd);
-
- /* PG 1.2: Set the BB PLL stable time to be 1000usec
- * (PLL_STABLE_TIME) */
- wl12xx_reg_write32(wl, CFG_PLL_SYNC_CNT, 0x20);
-
- /* PG 1.2: read clock request time */
- init_data = wl12xx_reg_read32(wl, CLK_REQ_TIME);
-
- /*
- * PG 1.2: set the clock request time to be ref_clk_settling_time -
- * 1ms = 4ms
- */
- if (init_data > 0x21)
- tmp = init_data - 0x21;
- else
- tmp = 0;
- wl12xx_reg_write32(wl, CLK_REQ_TIME, tmp);
-
- /* set BB PLL configurations in RF AFE */
- wl12xx_reg_write32(wl, 0x003058cc, 0x4B5);
-
- /* set RF_AFE_REG_5 */
- wl12xx_reg_write32(wl, 0x003058d4, 0x50);
-
- /* set RF_AFE_CTRL_REG_2 */
- wl12xx_reg_write32(wl, 0x00305948, 0x11c001);
-
- /*
- * change RF PLL and BB PLL divider for VCO clock and adjust VCO
- * bais current(RF_AFE_REG_13)
- */
- wl12xx_reg_write32(wl, 0x003058f4, 0x1e);
-
- /* set BB PLL configurations */
- tmp = LUT[ref_freq][LUT_PARAM_INTEGER_DIVIDER] | 0x00017000;
- wl12xx_reg_write32(wl, 0x00305840, tmp);
-
- /* set fractional divider according to Appendix C-BB PLL
- * Calculations
- */
- tmp = LUT[ref_freq][LUT_PARAM_FRACTIONAL_DIVIDER];
- wl12xx_reg_write32(wl, 0x00305844, tmp);
-
- /* set the initial data for the sigma delta */
- wl12xx_reg_write32(wl, 0x00305848, 0x3039);
-
- /*
- * set the accumulator attenuation value, calibration loop1
- * (alpha), calibration loop2 (beta), calibration loop3 (gamma) and
- * the VCO gain
- */
- tmp = (LUT[ref_freq][LUT_PARAM_ATTN_BB] << 16) |
- (LUT[ref_freq][LUT_PARAM_ALPHA_BB] << 12) | 0x1;
- wl12xx_reg_write32(wl, 0x00305854, tmp);
-
- /*
- * set the calibration stop time after holdoff time expires and set
- * settling time HOLD_OFF_TIME_BB
- */
- tmp = LUT[ref_freq][LUT_PARAM_STOP_TIME_BB] | 0x000A0000;
- wl12xx_reg_write32(wl, 0x00305858, tmp);
-
- /*
- * set BB PLL Loop filter capacitor3- BB_C3[2:0] and set BB PLL
- * constant leakage current to linearize PFD to 0uA -
- * BB_ILOOPF[7:3]
- */
- tmp = LUT[ref_freq][LUT_PARAM_BB_PLL_LOOP_FILTER] | 0x00000030;
- wl12xx_reg_write32(wl, 0x003058f8, tmp);
-
- /*
- * set regulator output voltage for n divider to
- * 1.35-BB_REFDIV[1:0], set charge pump current- BB_CPGAIN[4:2],
- * set BB PLL Loop filter capacitor2- BB_C2[7:5], set gain of BB
- * PLL auto-call to normal mode- BB_CALGAIN_3DB[8]
- */
- wl12xx_reg_write32(wl, 0x003058f0, 0x29);
-
- /* enable restart wakeup sequence (ELP_CMD[0]) */
- wl12xx_reg_write32(wl, ELP_CMD, elp_cmd | 0x1);
-
- /* restart sequence completed */
- udelay(2000);
-
- return 0;
-}
-
-int wl12xx_boot_run_firmware(struct wl12xx *wl)
-{
- int loop, ret;
- u32 chip_id, interrupt;
-
- wl->chip.op_set_ecpu_ctrl(wl, ECPU_CONTROL_HALT);
-
- chip_id = wl12xx_reg_read32(wl, CHIP_ID_B);
-
- wl12xx_debug(DEBUG_BOOT, "chip id after firmware boot: 0x%x", chip_id);
-
- if (chip_id != wl->chip.id) {
- wl12xx_error("chip id doesn't match after firmware boot");
- return -EIO;
- }
-
- /* wait for init to complete */
- loop = 0;
- while (loop++ < INIT_LOOP) {
- udelay(INIT_LOOP_DELAY);
- interrupt = wl12xx_reg_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR);
-
- if (interrupt == 0xffffffff) {
- wl12xx_error("error reading hardware complete "
- "init indication");
- return -EIO;
- }
- /* check that ACX_INTR_INIT_COMPLETE is enabled */
- else if (interrupt & wl->chip.intr_init_complete) {
- wl12xx_reg_write32(wl, ACX_REG_INTERRUPT_ACK,
- wl->chip.intr_init_complete);
- break;
- }
- }
-
- if (loop >= INIT_LOOP) {
- wl12xx_error("timeout waiting for the hardware to "
- "complete initialization");
- return -EIO;
- }
-
- /* get hardware config command mail box */
- wl->cmd_box_addr = wl12xx_reg_read32(wl, REG_COMMAND_MAILBOX_PTR);
-
- /* get hardware config event mail box */
- wl->event_box_addr = wl12xx_reg_read32(wl, REG_EVENT_MAILBOX_PTR);
-
- /* set the working partition to its "running" mode offset */
- wl12xx_set_partition(wl,
- wl->chip.p_table[PART_WORK].mem.start,
- wl->chip.p_table[PART_WORK].mem.size,
- wl->chip.p_table[PART_WORK].reg.start,
- wl->chip.p_table[PART_WORK].reg.size);
-
- wl12xx_debug(DEBUG_MAILBOX, "cmd_box_addr 0x%x event_box_addr 0x%x",
- wl->cmd_box_addr, wl->event_box_addr);
-
- /*
- * in case of full asynchronous mode the firmware event must be
- * ready to receive event from the command mailbox
- */
-
- /* enable gpio interrupts */
- wl12xx_boot_enable_interrupts(wl);
-
- wl->chip.op_target_enable_interrupts(wl);
-
- /* unmask all mbox events */
- wl->event_mask = 0xffffffff;
-
- ret = wl12xx_event_unmask(wl);
- if (ret < 0) {
- wl12xx_error("EVENT mask setting failed");
- return ret;
- }
-
- wl12xx_event_mbox_config(wl);
-
- /* firmware startup completed */
- return 0;
-}
diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c
deleted file mode 100644
index f73ab602b7a..00000000000
--- a/drivers/net/wireless/wl12xx/cmd.c
+++ /dev/null
@@ -1,353 +0,0 @@
-#include "cmd.h"
-
-#include <linux/module.h>
-#include <linux/crc7.h>
-#include <linux/spi/spi.h>
-
-#include "wl12xx.h"
-#include "wl12xx_80211.h"
-#include "reg.h"
-#include "spi.h"
-#include "ps.h"
-
-int wl12xx_cmd_send(struct wl12xx *wl, u16 type, void *buf, size_t buf_len)
-{
- struct wl12xx_command cmd;
- unsigned long timeout;
- size_t cmd_len;
- u32 intr;
- int ret = 0;
-
- memset(&cmd, 0, sizeof(cmd));
- cmd.id = type;
- cmd.status = 0;
- memcpy(cmd.parameters, buf, buf_len);
- cmd_len = ALIGN(buf_len, 4) + CMDMBOX_HEADER_LEN;
-
- wl12xx_ps_elp_wakeup(wl);
-
- wl12xx_spi_mem_write(wl, wl->cmd_box_addr, &cmd, cmd_len);
-
- wl12xx_reg_write32(wl, ACX_REG_INTERRUPT_TRIG, INTR_TRIG_CMD);
-
- timeout = jiffies + msecs_to_jiffies(WL12XX_COMMAND_TIMEOUT);
-
- intr = wl12xx_reg_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR);
- while (!(intr & wl->chip.intr_cmd_complete)) {
- if (time_after(jiffies, timeout)) {
- wl12xx_error("command complete timeout");
- ret = -ETIMEDOUT;
- goto out;
- }
-
- msleep(1);
-
- intr = wl12xx_reg_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR);
- }
-
- wl12xx_reg_write32(wl, ACX_REG_INTERRUPT_ACK,
- wl->chip.intr_cmd_complete);
-
-out:
- wl12xx_ps_elp_sleep(wl);
-
- return ret;
-}
-
-int wl12xx_cmd_test(struct wl12xx *wl, void *buf, size_t buf_len, u8 answer)
-{
- int ret;
-
- wl12xx_debug(DEBUG_CMD, "cmd test");
-
- ret = wl12xx_cmd_send(wl, CMD_TEST, buf, buf_len);
- if (ret < 0) {
- wl12xx_warning("TEST command failed");
- return ret;
- }
-
- if (answer) {
- struct wl12xx_command *cmd_answer;
-
- /*
- * The test command got in, we can read the answer.
- * The answer would be a wl12xx_command, where the
- * parameter array contains the actual answer.
- */
-
- wl12xx_ps_elp_wakeup(wl);
-
- wl12xx_spi_mem_read(wl, wl->cmd_box_addr, buf, buf_len);
-
- wl12xx_ps_elp_sleep(wl);
-
- cmd_answer = buf;
- if (cmd_answer->status != CMD_STATUS_SUCCESS)
- wl12xx_error("TEST command answer error: %d",
- cmd_answer->status);
- }
-
- return 0;
-}
-
-
-int wl12xx_cmd_interrogate(struct wl12xx *wl, u16 ie_id, u16 ie_len,
- void *answer)
-{
- struct wl12xx_command *cmd;
- struct acx_header header;
- int ret;
-
- wl12xx_debug(DEBUG_CMD, "cmd interrogate");
-
- header.id = ie_id;
- header.len = ie_len - sizeof(header);
-
- ret = wl12xx_cmd_send(wl, CMD_INTERROGATE, &header, sizeof(header));
- if (ret < 0) {
- wl12xx_error("INTERROGATE command failed");
- return ret;
- }
-
- wl12xx_ps_elp_wakeup(wl);
-
- /* the interrogate command got in, we can read the answer */
- wl12xx_spi_mem_read(wl, wl->cmd_box_addr, answer,
- CMDMBOX_HEADER_LEN + ie_len);
-
- wl12xx_ps_elp_sleep(wl);
-
- cmd = answer;
- if (cmd->status != CMD_STATUS_SUCCESS)
- wl12xx_error("INTERROGATE command error: %d",
- cmd->status);
-
- return 0;
-
-}
-
-int wl12xx_cmd_configure(struct wl12xx *wl, void *ie, int ie_len)
-{
- int ret;
-
- wl12xx_debug(DEBUG_CMD, "cmd configure");
-
- ret = wl12xx_cmd_send(wl, CMD_CONFIGURE, ie,
- ie_len);
- if (ret < 0) {
- wl12xx_warning("CONFIGURE command NOK");
- return ret;
- }
-
- return 0;
-
-}
-
-int wl12xx_cmd_vbm(struct wl12xx *wl, u8 identity,
- void *bitmap, u16 bitmap_len, u8 bitmap_control)
-{
- struct vbm_update_request vbm;
- int ret;
-
- wl12xx_debug(DEBUG_CMD, "cmd vbm");
-
- /* Count and period will be filled by the target */
- vbm.tim.bitmap_ctrl = bitmap_control;
- if (bitmap_len > PARTIAL_VBM_MAX) {
- wl12xx_warning("cmd vbm len is %d B, truncating to %d",
- bitmap_len, PARTIAL_VBM_MAX);
- bitmap_len = PARTIAL_VBM_MAX;
- }
- memcpy(vbm.tim.pvb_field, bitmap, bitmap_len);
- vbm.tim.identity = identity;
- vbm.tim.length = bitmap_len + 3;
-
- vbm.len = cpu_to_le16(bitmap_len + 5);
-
- ret = wl12xx_cmd_send(wl, CMD_VBM, &vbm, sizeof(vbm));
- if (ret < 0) {
- wl12xx_error("VBM command failed");
- return ret;
- }
-
- return 0;
-}
-
-int wl12xx_cmd_data_path(struct wl12xx *wl, u8 channel, u8 enable)
-{
- int ret;
- u16 cmd_rx, cmd_tx;
-
- wl12xx_debug(DEBUG_CMD, "cmd data path");
-
- if (enable) {
- cmd_rx = CMD_ENABLE_RX;
- cmd_tx = CMD_ENABLE_TX;
- } else {
- cmd_rx = CMD_DISABLE_RX;
- cmd_tx = CMD_DISABLE_TX;
- }
-
- ret = wl12xx_cmd_send(wl, cmd_rx, &channel, sizeof(channel));
- if (ret < 0) {
- wl12xx_error("rx %s cmd for channel %d failed",
- enable ? "start" : "stop", channel);
- return ret;
- }
-
- wl12xx_debug(DEBUG_BOOT, "rx %s cmd channel %d",
- enable ? "start" : "stop", channel);
-
- ret = wl12xx_cmd_send(wl, cmd_tx, &channel, sizeof(channel));
- if (ret < 0) {
- wl12xx_error("tx %s cmd for channel %d failed",
- enable ? "start" : "stop", channel);
- return ret;
- }
-
- wl12xx_debug(DEBUG_BOOT, "tx %s cmd channel %d",
- enable ? "start" : "stop", channel);
-
- return 0;
-}
-
-int wl12xx_cmd_join(struct wl12xx *wl, u8 bss_type, u8 dtim_interval,
- u16 beacon_interval, u8 wait)
-{
- unsigned long timeout;
- struct cmd_join join = {};
- int ret, i;
- u8 *bssid;
-
- /* FIXME: this should be in main.c */
- ret = wl12xx_acx_frame_rates(wl, DEFAULT_HW_GEN_TX_RATE,
- DEFAULT_HW_GEN_MODULATION_TYPE,
- wl->tx_mgmt_frm_rate,
- wl->tx_mgmt_frm_mod);
- if (ret < 0)
- return ret;
-
- wl12xx_debug(DEBUG_CMD, "cmd join");
-
- /* Reverse order BSSID */
- bssid = (u8 *)&join.bssid_lsb;
- for (i = 0; i < ETH_ALEN; i++)
- bssid[i] = wl->bssid[ETH_ALEN - i - 1];
-
- join.rx_config_options = wl->rx_config;
- join.rx_filter_options = wl->rx_filter;
-
- join.basic_rate_set = RATE_MASK_1MBPS | RATE_MASK_2MBPS |
- RATE_MASK_5_5MBPS | RATE_MASK_11MBPS;
-
- join.beacon_interval = beacon_interval;
- join.dtim_interval = dtim_interval;
- join.bss_type = bss_type;
- join.channel = wl->channel;
- join.ctrl = JOIN_CMD_CTRL_TX_FLUSH;
-
- ret = wl12xx_cmd_send(wl, CMD_START_JOIN, &join, sizeof(join));
- if (ret < 0) {
- wl12xx_error("failed to initiate cmd join");
- return ret;
- }
-
- timeout = msecs_to_jiffies(JOIN_TIMEOUT);
-
- /*
- * ugly hack: we should wait for JOIN_EVENT_COMPLETE_ID but to
- * simplify locking we just sleep instead, for now
- */
- if (wait)
- msleep(10);
-
- return 0;
-}
-
-int wl12xx_cmd_ps_mode(struct wl12xx *wl, u8 ps_mode)
-{
- int ret;
- struct acx_ps_params ps_params;
-
- /* FIXME: this should be in ps.c */
- ret = wl12xx_acx_wake_up_conditions(wl, wl->listen_int);
- if (ret < 0) {
- wl12xx_error("Couldnt set wake up conditions");
- return ret;
- }
-
- wl12xx_debug(DEBUG_CMD, "cmd set ps mode");
-
- ps_params.ps_mode = ps_mode;
- ps_params.send_null_data = 1;
- ps_params.retries = 5;
- ps_params.hang_over_period = 128;
- ps_params.null_data_rate = 1; /* 1 Mbps */
-
- ret = wl12xx_cmd_send(wl, CMD_SET_PS_MODE, &ps_params,
- sizeof(ps_params));
- if (ret < 0) {
- wl12xx_error("cmd set_ps_mode failed");
- return ret;
- }
-
- return 0;
-}
-
-int wl12xx_cmd_read_memory(struct wl12xx *wl, u32 addr, u32 len, void *answer)
-{
- struct cmd_read_write_memory mem_cmd, *mem_answer;
- struct wl12xx_command cmd;
- int ret;
-
- wl12xx_debug(DEBUG_CMD, "cmd read memory");
-
- memset(&mem_cmd, 0, sizeof(mem_cmd));
- mem_cmd.addr = addr;
- mem_cmd.size = len;
-
- ret = wl12xx_cmd_send(wl, CMD_READ_MEMORY, &mem_cmd, sizeof(mem_cmd));
- if (ret < 0) {
- wl12xx_error("read memory command failed: %d", ret);
- return ret;
- }
-
- /* the read command got in, we can now read the answer */
- wl12xx_spi_mem_read(wl, wl->cmd_box_addr, &cmd,
- CMDMBOX_HEADER_LEN + sizeof(mem_cmd));
-
- if (cmd.status != CMD_STATUS_SUCCESS)
- wl12xx_error("error in read command result: %d", cmd.status);
-
- mem_answer = (struct cmd_read_write_memory *) cmd.parameters;
- memcpy(answer, mem_answer->value, len);
-
- return 0;
-}
-
-int wl12xx_cmd_template_set(struct wl12xx *wl, u16 cmd_id,
- void *buf, size_t buf_len)
-{
- struct wl12xx_cmd_packet_template template;
- int ret;
-
- wl12xx_debug(DEBUG_CMD, "cmd template %d", cmd_id);
-
- memset(&template, 0, sizeof(template));
-
- WARN_ON(buf_len > WL12XX_MAX_TEMPLATE_SIZE);
- buf_len = min_t(size_t, buf_len, WL12XX_MAX_TEMPLATE_SIZE);
- template.size = cpu_to_le16(buf_len);
-
- if (buf)
- memcpy(template.template, buf, buf_len);
-
- ret = wl12xx_cmd_send(wl, cmd_id, &template,
- sizeof(template.size) + buf_len);
- if (ret < 0) {
- wl12xx_warning("cmd set_template failed: %d", ret);
- return ret;
- }
-
- return 0;
-}
diff --git a/drivers/net/wireless/wl12xx/init.c b/drivers/net/wireless/wl12xx/init.c
deleted file mode 100644
index 2a573a6010b..00000000000
--- a/drivers/net/wireless/wl12xx/init.c
+++ /dev/null
@@ -1,200 +0,0 @@
-/*
- * This file is part of wl12xx
- *
- * Copyright (C) 2009 Nokia Corporation
- *
- * Contact: Kalle Valo <kalle.valo@nokia.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-
-#include "init.h"
-#include "wl12xx_80211.h"
-#include "acx.h"
-#include "cmd.h"
-
-int wl12xx_hw_init_hwenc_config(struct wl12xx *wl)
-{
- int ret;
-
- ret = wl12xx_acx_feature_cfg(wl);
- if (ret < 0) {
- wl12xx_warning("couldn't set feature config");
- return ret;
- }
-
- ret = wl12xx_acx_default_key(wl, wl->default_key);
- if (ret < 0) {
- wl12xx_warning("couldn't set default key");
- return ret;
- }
-
- return 0;
-}
-
-int wl12xx_hw_init_templates_config(struct wl12xx *wl)
-{
- int ret;
- u8 partial_vbm[PARTIAL_VBM_MAX];
-
- /* send empty templates for fw memory reservation */
- ret = wl12xx_cmd_template_set(wl, CMD_PROBE_REQ, NULL,
- sizeof(struct wl12xx_probe_req_template));
- if (ret < 0)
- return ret;
-
- ret = wl12xx_cmd_template_set(wl, CMD_NULL_DATA, NULL,
- sizeof(struct wl12xx_null_data_template));
- if (ret < 0)
- return ret;
-
- ret = wl12xx_cmd_template_set(wl, CMD_PS_POLL, NULL,
- sizeof(struct wl12xx_ps_poll_template));
- if (ret < 0)
- return ret;
-
- ret = wl12xx_cmd_template_set(wl, CMD_QOS_NULL_DATA, NULL,
- sizeof
- (struct wl12xx_qos_null_data_template));
- if (ret < 0)
- return ret;
-
- ret = wl12xx_cmd_template_set(wl, CMD_PROBE_RESP, NULL,
- sizeof
- (struct wl12xx_probe_resp_template));
- if (ret < 0)
- return ret;
-
- ret = wl12xx_cmd_template_set(wl, CMD_BEACON, NULL,
- sizeof
- (struct wl12xx_beacon_template));
- if (ret < 0)
- return ret;
-
- /* tim templates, first reserve space then allocate an empty one */
- memset(partial_vbm, 0, PARTIAL_VBM_MAX);
- ret = wl12xx_cmd_vbm(wl, TIM_ELE_ID, partial_vbm, PARTIAL_VBM_MAX, 0);
- if (ret < 0)
- return ret;
-
- ret = wl12xx_cmd_vbm(wl, TIM_ELE_ID, partial_vbm, 1, 0);
- if (ret < 0)
- return ret;
-
- return 0;
-}
-
-int wl12xx_hw_init_rx_config(struct wl12xx *wl, u32 config, u32 filter)
-{
- int ret;
-
- ret = wl12xx_acx_rx_msdu_life_time(wl, RX_MSDU_LIFETIME_DEF);
- if (ret < 0)
- return ret;
-
- ret = wl12xx_acx_rx_config(wl, config, filter);
- if (ret < 0)
- return ret;
-
- return 0;
-}
-
-int wl12xx_hw_init_phy_config(struct wl12xx *wl)
-{
- int ret;
-
- ret = wl12xx_acx_pd_threshold(wl);
- if (ret < 0)
- return ret;
-
- ret = wl12xx_acx_slot(wl, DEFAULT_SLOT_TIME);
- if (ret < 0)
- return ret;
-
- ret = wl12xx_acx_group_address_tbl(wl);
- if (ret < 0)
- return ret;
-
- ret = wl12xx_acx_service_period_timeout(wl);
- if (ret < 0)
- return ret;
-
- ret = wl12xx_acx_rts_threshold(wl, RTS_THRESHOLD_DEF);
- if (ret < 0)
- return ret;
-
- return 0;
-}
-
-int wl12xx_hw_init_beacon_filter(struct wl12xx *wl)
-{
- int ret;
-
- ret = wl12xx_acx_beacon_filter_opt(wl);
- if (ret < 0)
- return ret;
-
- ret = wl12xx_acx_beacon_filter_table(wl);
- if (ret < 0)
- return ret;
-
- return 0;
-}
-
-int wl12xx_hw_init_pta(struct wl12xx *wl)
-{
- int ret;
-
- ret = wl12xx_acx_sg_enable(wl);
- if (ret < 0)
- return ret;
-
- ret = wl12xx_acx_sg_cfg(wl);
- if (ret < 0)
- return ret;
-
- return 0;
-}
-
-int wl12xx_hw_init_energy_detection(struct wl12xx *wl)
-{
- int ret;
-
- ret = wl12xx_acx_cca_threshold(wl);
- if (ret < 0)
- return ret;
-
- return 0;
-}
-
-int wl12xx_hw_init_beacon_broadcast(struct wl12xx *wl)
-{
- int ret;
-
- ret = wl12xx_acx_bcn_dtim_options(wl);
- if (ret < 0)
- return ret;
-
- return 0;
-}
-
-int wl12xx_hw_init_power_auth(struct wl12xx *wl)
-{
- return wl12xx_acx_sleep_auth(wl, WL12XX_PSM_CAM);
-}
diff --git a/drivers/net/wireless/wl12xx/wl1251.c b/drivers/net/wireless/wl12xx/wl1251.c
deleted file mode 100644
index ce1561a41fa..00000000000
--- a/drivers/net/wireless/wl12xx/wl1251.c
+++ /dev/null
@@ -1,709 +0,0 @@
-/*
- * This file is part of wl12xx
- *
- * Copyright (C) 2008-2009 Nokia Corporation
- *
- * Contact: Kalle Valo <kalle.valo@nokia.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-
-#include "wl1251.h"
-#include "reg.h"
-#include "spi.h"
-#include "boot.h"
-#include "event.h"
-#include "acx.h"
-#include "tx.h"
-#include "rx.h"
-#include "ps.h"
-#include "init.h"
-
-static struct wl12xx_partition_set wl1251_part_table[PART_TABLE_LEN] = {
- [PART_DOWN] = {
- .mem = {
- .start = 0x00000000,
- .size = 0x00016800
- },
- .reg = {
- .start = REGISTERS_BASE,
- .size = REGISTERS_DOWN_SIZE
- },
- },
-
- [PART_WORK] = {
- .mem = {
- .start = 0x00028000,
- .size = 0x00014000
- },
- .reg = {
- .start = REGISTERS_BASE,
- .size = REGISTERS_WORK_SIZE
- },
- },
-
- /* WL1251 doesn't use the DRPW partition, so we don't set it here */
-};
-
-static enum wl12xx_acx_int_reg wl1251_acx_reg_table[ACX_REG_TABLE_LEN] = {
- [ACX_REG_INTERRUPT_TRIG] = (REGISTERS_BASE + 0x0474),
- [ACX_REG_INTERRUPT_TRIG_H] = (REGISTERS_BASE + 0x0478),
- [ACX_REG_INTERRUPT_MASK] = (REGISTERS_BASE + 0x0494),
- [ACX_REG_HINT_MASK_SET] = (REGISTERS_BASE + 0x0498),
- [ACX_REG_HINT_MASK_CLR] = (REGISTERS_BASE + 0x049C),
- [ACX_REG_INTERRUPT_NO_CLEAR] = (REGISTERS_BASE + 0x04B0),
- [ACX_REG_INTERRUPT_CLEAR] = (REGISTERS_BASE + 0x04A4),
- [ACX_REG_INTERRUPT_ACK] = (REGISTERS_BASE + 0x04A8),
- [ACX_REG_SLV_SOFT_RESET] = (REGISTERS_BASE + 0x0000),
- [ACX_REG_EE_START] = (REGISTERS_BASE + 0x080C),
- [ACX_REG_ECPU_CONTROL] = (REGISTERS_BASE + 0x0804)
-};
-
-static int wl1251_upload_firmware(struct wl12xx *wl)
-{
- struct wl12xx_partition_set *p_table = wl->chip.p_table;
- int addr, chunk_num, partition_limit;
- size_t fw_data_len;
- u8 *p;
-
- /* whal_FwCtrl_LoadFwImageSm() */
-
- wl12xx_debug(DEBUG_BOOT, "chip id before fw upload: 0x%x",
- wl12xx_reg_read32(wl, CHIP_ID_B));
-
- /* 10.0 check firmware length and set partition */
- fw_data_len = (wl->fw[4] << 24) | (wl->fw[5] << 16) |
- (wl->fw[6] << 8) | (wl->fw[7]);
-
- wl12xx_debug(DEBUG_BOOT, "fw_data_len %zu chunk_size %d", fw_data_len,
- CHUNK_SIZE);
-
- if ((fw_data_len % 4) != 0) {
- wl12xx_error("firmware length not multiple of four");
- return -EIO;
- }
-
- wl12xx_set_partition(wl,
- p_table[PART_DOWN].mem.start,
- p_table[PART_DOWN].mem.size,
- p_table[PART_DOWN].reg.start,
- p_table[PART_DOWN].reg.size);
-
- /* 10.1 set partition limit and chunk num */
- chunk_num = 0;
- partition_limit = p_table[PART_DOWN].mem.size;
-
- while (chunk_num < fw_data_len / CHUNK_SIZE) {
- /* 10.2 update partition, if needed */
- addr = p_table[PART_DOWN].mem.start +
- (chunk_num + 2) * CHUNK_SIZE;
- if (addr > partition_limit) {
- addr = p_table[PART_DOWN].mem.start +
- chunk_num * CHUNK_SIZE;
- partition_limit = chunk_num * CHUNK_SIZE +
- p_table[PART_DOWN].mem.size;
- wl12xx_set_partition(wl,
- addr,
- p_table[PART_DOWN].mem.size,
- p_table[PART_DOWN].reg.start,
- p_table[PART_DOWN].reg.size);
- }
-
- /* 10.3 upload the chunk */
- addr = p_table[PART_DOWN].mem.start + chunk_num * CHUNK_SIZE;
- p = wl->fw + FW_HDR_SIZE + chunk_num * CHUNK_SIZE;
- wl12xx_debug(DEBUG_BOOT, "uploading fw chunk 0x%p to 0x%x",
- p, addr);
- wl12xx_spi_mem_write(wl, addr, p, CHUNK_SIZE);
-
- chunk_num++;
- }
-
- /* 10.4 upload the last chunk */
- addr = p_table[PART_DOWN].mem.start + chunk_num * CHUNK_SIZE;
- p = wl->fw + FW_HDR_SIZE + chunk_num * CHUNK_SIZE;
- wl12xx_debug(DEBUG_BOOT, "uploading fw last chunk (%zu B) 0x%p to 0x%x",
- fw_data_len % CHUNK_SIZE, p, addr);
- wl12xx_spi_mem_write(wl, addr, p, fw_data_len % CHUNK_SIZE);
-
- return 0;
-}
-
-static int wl1251_upload_nvs(struct wl12xx *wl)
-{
- size_t nvs_len, nvs_bytes_written, burst_len;
- int nvs_start, i;
- u32 dest_addr, val;
- u8 *nvs_ptr, *nvs;
-
- nvs = wl->nvs;
- if (nvs == NULL)
- return -ENODEV;
-
- nvs_ptr = nvs;
-
- nvs_len = wl->nvs_len;
- nvs_start = wl->fw_len;
-
- /*
- * Layout before the actual NVS tables:
- * 1 byte : burst length.
- * 2 bytes: destination address.
- * n bytes: data to burst copy.
- *
- * This is ended by a 0 length, then the NVS tables.
- */
-
- while (nvs_ptr[0]) {
- burst_len = nvs_ptr[0];
- dest_addr = (nvs_ptr[1] & 0xfe) | ((u32)(nvs_ptr[2] << 8));
-
- /* We move our pointer to the data */
- nvs_ptr += 3;
-
- for (i = 0; i < burst_len; i++) {
- val = (nvs_ptr[0] | (nvs_ptr[1] << 8)
- | (nvs_ptr[2] << 16) | (nvs_ptr[3] << 24));
-
- wl12xx_debug(DEBUG_BOOT,
- "nvs burst write 0x%x: 0x%x",
- dest_addr, val);
- wl12xx_mem_write32(wl, dest_addr, val);
-
- nvs_ptr += 4;
- dest_addr += 4;
- }
- }
-
- /*
- * We've reached the first zero length, the first NVS table
- * is 7 bytes further.
- */
- nvs_ptr += 7;
- nvs_len -= nvs_ptr - nvs;
- nvs_len = ALIGN(nvs_len, 4);
-
- /* Now we must set the partition correctly */
- wl12xx_set_partition(wl, nvs_start,
- wl->chip.p_table[PART_DOWN].mem.size,
- wl->chip.p_table[PART_DOWN].reg.start,
- wl->chip.p_table[PART_DOWN].reg.size);
-
- /* And finally we upload the NVS tables */
- nvs_bytes_written = 0;
- while (nvs_bytes_written < nvs_len) {
- val = (nvs_ptr[0] | (nvs_ptr[1] << 8)
- | (nvs_ptr[2] << 16) | (nvs_ptr[3] << 24));
-
- val = cpu_to_le32(val);
-
- wl12xx_debug(DEBUG_BOOT,
- "nvs write table 0x%x: 0x%x",
- nvs_start, val);
- wl12xx_mem_write32(wl, nvs_start, val);
-
- nvs_ptr += 4;
- nvs_bytes_written += 4;
- nvs_start += 4;
- }
-
- return 0;
-}
-
-static int wl1251_boot(struct wl12xx *wl)
-{
- int ret = 0, minor_minor_e2_ver;
- u32 tmp, boot_data;
-
- ret = wl12xx_boot_soft_reset(wl);
- if (ret < 0)
- goto out;
-
- /* 2. start processing NVS file */
- ret = wl->chip.op_upload_nvs(wl);
- if (ret < 0)
- goto out;
-
- /* write firmware's last address (ie. it's length) to
- * ACX_EEPROMLESS_IND_REG */
- wl12xx_reg_write32(wl, ACX_EEPROMLESS_IND_REG, wl->fw_len);
-
- /* 6. read the EEPROM parameters */
- tmp = wl12xx_reg_read32(wl, SCR_PAD2);
-
- /* 7. read bootdata */
- wl->boot_attr.radio_type = (tmp & 0x0000FF00) >> 8;
- wl->boot_attr.major = (tmp & 0x00FF0000) >> 16;
- tmp = wl12xx_reg_read32(wl, SCR_PAD3);
-
- /* 8. check bootdata and call restart sequence */
- wl->boot_attr.minor = (tmp & 0x00FF0000) >> 16;
- minor_minor_e2_ver = (tmp & 0xFF000000) >> 24;
-
- wl12xx_debug(DEBUG_BOOT, "radioType 0x%x majorE2Ver 0x%x "
- "minorE2Ver 0x%x minor_minor_e2_ver 0x%x",
- wl->boot_attr.radio_type, wl->boot_attr.major,
- wl->boot_attr.minor, minor_minor_e2_ver);
-
- ret = wl12xx_boot_init_seq(wl);
- if (ret < 0)
- goto out;
-
- /* 9. NVS processing done */
- boot_data = wl12xx_reg_read32(wl, ACX_REG_ECPU_CONTROL);
-
- wl12xx_debug(DEBUG_BOOT, "halt boot_data 0x%x", boot_data);
-
- /* 10. check that ECPU_CONTROL_HALT bits are set in
- * pWhalBus->uBootData and start uploading firmware
- */
- if ((boot_data & ECPU_CONTROL_HALT) == 0) {
- wl12xx_error("boot failed, ECPU_CONTROL_HALT not set");
- ret = -EIO;
- goto out;
- }
-
- ret = wl->chip.op_upload_fw(wl);
- if (ret < 0)
- goto out;
-
- /* 10.5 start firmware */
- ret = wl12xx_boot_run_firmware(wl);
- if (ret < 0)
- goto out;
-
- /* Get and save the firmware version */
- wl12xx_acx_fw_version(wl, wl->chip.fw_ver, sizeof(wl->chip.fw_ver));
-
-out:
- return ret;
-}
-
-static int wl1251_mem_cfg(struct wl12xx *wl)
-{
- struct wl1251_acx_config_memory mem_conf;
- int ret, i;
-
- wl12xx_debug(DEBUG_ACX, "wl1251 mem cfg");
-
- /* memory config */
- mem_conf.mem_config.num_stations = cpu_to_le16(DEFAULT_NUM_STATIONS);
- mem_conf.mem_config.rx_mem_block_num = 35;
- mem_conf.mem_config.tx_min_mem_block_num = 64;
- mem_conf.mem_config.num_tx_queues = MAX_TX_QUEUES;
- mem_conf.mem_config.host_if_options = HOSTIF_PKT_RING;
- mem_conf.mem_config.num_ssid_profiles = 1;
- mem_conf.mem_config.debug_buffer_size =
- cpu_to_le16(TRACE_BUFFER_MAX_SIZE);
-
- /* RX queue config */
- mem_conf.rx_queue_config.dma_address = 0;
- mem_conf.rx_queue_config.num_descs = ACX_RX_DESC_DEF;
- mem_conf.rx_queue_config.priority = DEFAULT_RXQ_PRIORITY;
- mem_conf.rx_queue_config.type = DEFAULT_RXQ_TYPE;
-
- /* TX queue config */
- for (i = 0; i < MAX_TX_QUEUES; i++) {
- mem_conf.tx_queue_config[i].num_descs = ACX_TX_DESC_DEF;
- mem_conf.tx_queue_config[i].attributes = i;
- }
-
- mem_conf.header.id = ACX_MEM_CFG;
- mem_conf.header.len = sizeof(struct wl1251_acx_config_memory) -
- sizeof(struct acx_header);
- mem_conf.header.len -=
- (MAX_TX_QUEUE_CONFIGS - mem_conf.mem_config.num_tx_queues) *
- sizeof(struct wl1251_acx_tx_queue_config);
-
- ret = wl12xx_cmd_configure(wl, &mem_conf,
- sizeof(struct wl1251_acx_config_memory));
- if (ret < 0)
- wl12xx_warning("wl1251 mem config failed: %d", ret);
-
- return ret;
-}
-
-static int wl1251_hw_init_mem_config(struct wl12xx *wl)
-{
- int ret;
-
- ret = wl1251_mem_cfg(wl);
- if (ret < 0)
- return ret;
-
- wl->target_mem_map = kzalloc(sizeof(struct wl1251_acx_mem_map),
- GFP_KERNEL);
- if (!wl->target_mem_map) {
- wl12xx_error("couldn't allocate target memory map");
- return -ENOMEM;
- }
-
- /* we now ask for the firmware built memory map */
- ret = wl12xx_acx_mem_map(wl, wl->target_mem_map,
- sizeof(struct wl1251_acx_mem_map));
- if (ret < 0) {
- wl12xx_error("couldn't retrieve firmware memory map");
- kfree(wl->target_mem_map);
- wl->target_mem_map = NULL;
- return ret;
- }
-
- return 0;
-}
-
-static void wl1251_set_ecpu_ctrl(struct wl12xx *wl, u32 flag)
-{
- u32 cpu_ctrl;
-
- /* 10.5.0 run the firmware (I) */
- cpu_ctrl = wl12xx_reg_read32(wl, ACX_REG_ECPU_CONTROL);
-
- /* 10.5.1 run the firmware (II) */
- cpu_ctrl &= ~flag;
- wl12xx_reg_write32(wl, ACX_REG_ECPU_CONTROL, cpu_ctrl);
-}
-
-static void wl1251_target_enable_interrupts(struct wl12xx *wl)
-{
- /* Enable target's interrupts */
- wl->intr_mask = WL1251_ACX_INTR_RX0_DATA |
- WL1251_ACX_INTR_RX1_DATA |
- WL1251_ACX_INTR_TX_RESULT |
- WL1251_ACX_INTR_EVENT_A |
- WL1251_ACX_INTR_EVENT_B |
- WL1251_ACX_INTR_INIT_COMPLETE;
- wl12xx_boot_target_enable_interrupts(wl);
-}
-
-static void wl1251_irq_work(struct work_struct *work)
-{
- u32 intr;
- struct wl12xx *wl =
- container_of(work, struct wl12xx, irq_work);
-
- mutex_lock(&wl->mutex);
-
- wl12xx_debug(DEBUG_IRQ, "IRQ work");
-
- if (wl->state == WL12XX_STATE_OFF)
- goto out;
-
- wl12xx_ps_elp_wakeup(wl);
-
- wl12xx_reg_write32(wl, ACX_REG_INTERRUPT_MASK, WL1251_ACX_INTR_ALL);
-
- intr = wl12xx_reg_read32(wl, ACX_REG_INTERRUPT_CLEAR);
- wl12xx_debug(DEBUG_IRQ, "intr: 0x%x", intr);
-
- if (wl->data_path) {
- wl12xx_spi_mem_read(wl, wl->data_path->rx_control_addr,
- &wl->rx_counter, sizeof(u32));
-
- /* We handle a frmware bug here */
- switch ((wl->rx_counter - wl->rx_handled) & 0xf) {
- case 0:
- wl12xx_debug(DEBUG_IRQ, "RX: FW and host in sync");
- intr &= ~WL1251_ACX_INTR_RX0_DATA;
- intr &= ~WL1251_ACX_INTR_RX1_DATA;
- break;
- case 1:
- wl12xx_debug(DEBUG_IRQ, "RX: FW +1");
- intr |= WL1251_ACX_INTR_RX0_DATA;
- intr &= ~WL1251_ACX_INTR_RX1_DATA;
- break;
- case 2:
- wl12xx_debug(DEBUG_IRQ, "RX: FW +2");
- intr |= WL1251_ACX_INTR_RX0_DATA;
- intr |= WL1251_ACX_INTR_RX1_DATA;
- break;
- default:
- wl12xx_warning("RX: FW and host out of sync: %d",
- wl->rx_counter - wl->rx_handled);
- break;
- }
-
- wl->rx_handled = wl->rx_counter;
-
-
- wl12xx_debug(DEBUG_IRQ, "RX counter: %d", wl->rx_counter);
- }
-
- intr &= wl->intr_mask;
-
- if (intr == 0) {
- wl12xx_debug(DEBUG_IRQ, "INTR is 0");
- wl12xx_reg_write32(wl, ACX_REG_INTERRUPT_MASK,
- ~(wl->intr_mask));
-
- goto out_sleep;
- }
-
- if (intr & WL1251_ACX_INTR_RX0_DATA) {
- wl12xx_debug(DEBUG_IRQ, "WL1251_ACX_INTR_RX0_DATA");
- wl12xx_rx(wl);
- }
-
- if (intr & WL1251_ACX_INTR_RX1_DATA) {
- wl12xx_debug(DEBUG_IRQ, "WL1251_ACX_INTR_RX1_DATA");
- wl12xx_rx(wl);
- }
-
- if (intr & WL1251_ACX_INTR_TX_RESULT) {
- wl12xx_debug(DEBUG_IRQ, "WL1251_ACX_INTR_TX_RESULT");
- wl12xx_tx_complete(wl);
- }
-
- if (intr & (WL1251_ACX_INTR_EVENT_A | WL1251_ACX_INTR_EVENT_B)) {
- wl12xx_debug(DEBUG_IRQ, "WL1251_ACX_INTR_EVENT (0x%x)", intr);
- if (intr & WL1251_ACX_INTR_EVENT_A)
- wl12xx_event_handle(wl, 0);
- else
- wl12xx_event_handle(wl, 1);
- }
-
- if (intr & WL1251_ACX_INTR_INIT_COMPLETE)
- wl12xx_debug(DEBUG_IRQ, "WL1251_ACX_INTR_INIT_COMPLETE");
-
- wl12xx_reg_write32(wl, ACX_REG_INTERRUPT_MASK, ~(wl->intr_mask));
-
-out_sleep:
- wl12xx_ps_elp_sleep(wl);
-out:
- mutex_unlock(&wl->mutex);
-}
-
-static int wl1251_hw_init_txq_fill(u8 qid,
- struct acx_tx_queue_qos_config *config,
- u32 num_blocks)
-{
- config->qid = qid;
-
- switch (qid) {
- case QOS_AC_BE:
- config->high_threshold =
- (QOS_TX_HIGH_BE_DEF * num_blocks) / 100;
- config->low_threshold =
- (QOS_TX_LOW_BE_DEF * num_blocks) / 100;
- break;
- case QOS_AC_BK:
- config->high_threshold =
- (QOS_TX_HIGH_BK_DEF * num_blocks) / 100;
- config->low_threshold =
- (QOS_TX_LOW_BK_DEF * num_blocks) / 100;
- break;
- case QOS_AC_VI:
- config->high_threshold =
- (QOS_TX_HIGH_VI_DEF * num_blocks) / 100;
- config->low_threshold =
- (QOS_TX_LOW_VI_DEF * num_blocks) / 100;
- break;
- case QOS_AC_VO:
- config->high_threshold =
- (QOS_TX_HIGH_VO_DEF * num_blocks) / 100;
- config->low_threshold =
- (QOS_TX_LOW_VO_DEF * num_blocks) / 100;
- break;
- default:
- wl12xx_error("Invalid TX queue id: %d", qid);
- return -EINVAL;
- }
-
- return 0;
-}
-
-static int wl1251_hw_init_tx_queue_config(struct wl12xx *wl)
-{
- struct acx_tx_queue_qos_config config;
- struct wl1251_acx_mem_map *wl_mem_map = wl->target_mem_map;
- int ret, i;
-
- wl12xx_debug(DEBUG_ACX, "acx tx queue config");
-
- config.header.id = ACX_TX_QUEUE_CFG;
- config.header.len = sizeof(struct acx_tx_queue_qos_config) -
- sizeof(struct acx_header);
-
- for (i = 0; i < MAX_NUM_OF_AC; i++) {
- ret = wl1251_hw_init_txq_fill(i, &config,
- wl_mem_map->num_tx_mem_blocks);
- if (ret < 0)
- return ret;
-
- ret = wl12xx_cmd_configure(wl, &config, sizeof(config));
- if (ret < 0)
- return ret;
- }
-
- return 0;
-}
-
-static int wl1251_hw_init_data_path_config(struct wl12xx *wl)
-{
- int ret;
-
- /* asking for the data path parameters */
- wl->data_path = kzalloc(sizeof(struct acx_data_path_params_resp),
- GFP_KERNEL);
- if (!wl->data_path) {
- wl12xx_error("Couldnt allocate data path parameters");
- return -ENOMEM;
- }
-
- ret = wl12xx_acx_data_path_params(wl, wl->data_path);
- if (ret < 0) {
- kfree(wl->data_path);
- wl->data_path = NULL;
- return ret;
- }
-
- return 0;
-}
-
-static int wl1251_hw_init(struct wl12xx *wl)
-{
- struct wl1251_acx_mem_map *wl_mem_map;
- int ret;
-
- ret = wl12xx_hw_init_hwenc_config(wl);
- if (ret < 0)
- return ret;
-
- /* Template settings */
- ret = wl12xx_hw_init_templates_config(wl);
- if (ret < 0)
- return ret;
-
- /* Default memory configuration */
- ret = wl1251_hw_init_mem_config(wl);
- if (ret < 0)
- return ret;
-
- /* Default data path configuration */
- ret = wl1251_hw_init_data_path_config(wl);
- if (ret < 0)
- goto out_free_memmap;
-
- /* RX config */
- ret = wl12xx_hw_init_rx_config(wl,
- RX_CFG_PROMISCUOUS | RX_CFG_TSF,
- RX_FILTER_OPTION_DEF);
- /* RX_CONFIG_OPTION_ANY_DST_ANY_BSS,
- RX_FILTER_OPTION_FILTER_ALL); */
- if (ret < 0)
- goto out_free_data_path;
-
- /* TX queues config */
- ret = wl1251_hw_init_tx_queue_config(wl);
- if (ret < 0)
- goto out_free_data_path;
-
- /* PHY layer config */
- ret = wl12xx_hw_init_phy_config(wl);
- if (ret < 0)
- goto out_free_data_path;
-
- /* Beacon filtering */
- ret = wl12xx_hw_init_beacon_filter(wl);
- if (ret < 0)
- goto out_free_data_path;
-
- /* Bluetooth WLAN coexistence */
- ret = wl12xx_hw_init_pta(wl);
- if (ret < 0)
- goto out_free_data_path;
-
- /* Energy detection */
- ret = wl12xx_hw_init_energy_detection(wl);
- if (ret < 0)
- goto out_free_data_path;
-
- /* Beacons and boradcast settings */
- ret = wl12xx_hw_init_beacon_broadcast(wl);
- if (ret < 0)
- goto out_free_data_path;
-
- /* Enable data path */
- ret = wl12xx_cmd_data_path(wl, wl->channel, 1);
- if (ret < 0)
- goto out_free_data_path;
-
- /* Default power state */
- ret = wl12xx_hw_init_power_auth(wl);
- if (ret < 0)
- goto out_free_data_path;
-
- wl_mem_map = wl->target_mem_map;
- wl12xx_info("%d tx blocks at 0x%x, %d rx blocks at 0x%x",
- wl_mem_map->num_tx_mem_blocks,
- wl->data_path->tx_control_addr,
- wl_mem_map->num_rx_mem_blocks,
- wl->data_path->rx_control_addr);
-
- return 0;
-
- out_free_data_path:
- kfree(wl->data_path);
-
- out_free_memmap:
- kfree(wl->target_mem_map);
-
- return ret;
-}
-
-static int wl1251_plt_init(struct wl12xx *wl)
-{
- int ret;
-
- ret = wl1251_hw_init_mem_config(wl);
- if (ret < 0)
- return ret;
-
- ret = wl12xx_cmd_data_path(wl, wl->channel, 1);
- if (ret < 0)
- return ret;
-
- return 0;
-}
-
-void wl1251_setup(struct wl12xx *wl)
-{
- /* FIXME: Is it better to use strncpy here or is this ok? */
- wl->chip.fw_filename = WL1251_FW_NAME;
- wl->chip.nvs_filename = WL1251_NVS_NAME;
-
- /* Now we know what chip we're using, so adjust the power on sleep
- * time accordingly */
- wl->chip.power_on_sleep = WL1251_POWER_ON_SLEEP;
-
- wl->chip.intr_cmd_complete = WL1251_ACX_INTR_CMD_COMPLETE;
- wl->chip.intr_init_complete = WL1251_ACX_INTR_INIT_COMPLETE;
-
- wl->chip.op_upload_nvs = wl1251_upload_nvs;
- wl->chip.op_upload_fw = wl1251_upload_firmware;
- wl->chip.op_boot = wl1251_boot;
- wl->chip.op_set_ecpu_ctrl = wl1251_set_ecpu_ctrl;
- wl->chip.op_target_enable_interrupts = wl1251_target_enable_interrupts;
- wl->chip.op_hw_init = wl1251_hw_init;
- wl->chip.op_plt_init = wl1251_plt_init;
-
- wl->chip.p_table = wl1251_part_table;
- wl->chip.acx_reg_table = wl1251_acx_reg_table;
-
- INIT_WORK(&wl->irq_work, wl1251_irq_work);
-}
diff --git a/drivers/net/wireless/wl12xx/wl1251.h b/drivers/net/wireless/wl12xx/wl1251.h
index 1f4a4433039..998e4b6252b 100644
--- a/drivers/net/wireless/wl12xx/wl1251.h
+++ b/drivers/net/wireless/wl12xx/wl1251.h
@@ -1,7 +1,8 @@
/*
- * This file is part of wl12xx
+ * This file is part of wl1251
*
- * Copyright (C) 2008 Nokia Corporation
+ * Copyright (c) 1998-2007 Texas Instruments Incorporated
+ * Copyright (C) 2008-2009 Nokia Corporation
*
* Contact: Kalle Valo <kalle.valo@nokia.com>
*
@@ -24,142 +25,400 @@
#ifndef __WL1251_H__
#define __WL1251_H__
+#include <linux/mutex.h>
+#include <linux/list.h>
#include <linux/bitops.h>
-
-#include "wl12xx.h"
-#include "acx.h"
-
-#define WL1251_FW_NAME "wl1251-fw.bin"
-#define WL1251_NVS_NAME "wl1251-nvs.bin"
-
-#define WL1251_POWER_ON_SLEEP 10 /* in miliseconds */
-
-void wl1251_setup(struct wl12xx *wl);
-
-
-struct wl1251_acx_memory {
- __le16 num_stations; /* number of STAs to be supported. */
- u16 reserved_1;
+#include <net/mac80211.h>
+
+#define DRIVER_NAME "wl1251"
+#define DRIVER_PREFIX DRIVER_NAME ": "
+
+enum {
+ DEBUG_NONE = 0,
+ DEBUG_IRQ = BIT(0),
+ DEBUG_SPI = BIT(1),
+ DEBUG_BOOT = BIT(2),
+ DEBUG_MAILBOX = BIT(3),
+ DEBUG_NETLINK = BIT(4),
+ DEBUG_EVENT = BIT(5),
+ DEBUG_TX = BIT(6),
+ DEBUG_RX = BIT(7),
+ DEBUG_SCAN = BIT(8),
+ DEBUG_CRYPT = BIT(9),
+ DEBUG_PSM = BIT(10),
+ DEBUG_MAC80211 = BIT(11),
+ DEBUG_CMD = BIT(12),
+ DEBUG_ACX = BIT(13),
+ DEBUG_ALL = ~0,
+};
+
+#define DEBUG_LEVEL (DEBUG_NONE)
+
+#define DEBUG_DUMP_LIMIT 1024
+
+#define wl1251_error(fmt, arg...) \
+ printk(KERN_ERR DRIVER_PREFIX "ERROR " fmt "\n", ##arg)
+
+#define wl1251_warning(fmt, arg...) \
+ printk(KERN_WARNING DRIVER_PREFIX "WARNING " fmt "\n", ##arg)
+
+#define wl1251_notice(fmt, arg...) \
+ printk(KERN_INFO DRIVER_PREFIX fmt "\n", ##arg)
+
+#define wl1251_info(fmt, arg...) \
+ printk(KERN_DEBUG DRIVER_PREFIX fmt "\n", ##arg)
+
+#define wl1251_debug(level, fmt, arg...) \
+ do { \
+ if (level & DEBUG_LEVEL) \
+ printk(KERN_DEBUG DRIVER_PREFIX fmt "\n", ##arg); \
+ } while (0)
+
+#define wl1251_dump(level, prefix, buf, len) \
+ do { \
+ if (level & DEBUG_LEVEL) \
+ print_hex_dump(KERN_DEBUG, DRIVER_PREFIX prefix, \
+ DUMP_PREFIX_OFFSET, 16, 1, \
+ buf, \
+ min_t(size_t, len, DEBUG_DUMP_LIMIT), \
+ 0); \
+ } while (0)
+
+#define wl1251_dump_ascii(level, prefix, buf, len) \
+ do { \
+ if (level & DEBUG_LEVEL) \
+ print_hex_dump(KERN_DEBUG, DRIVER_PREFIX prefix, \
+ DUMP_PREFIX_OFFSET, 16, 1, \
+ buf, \
+ min_t(size_t, len, DEBUG_DUMP_LIMIT), \
+ true); \
+ } while (0)
+
+#define WL1251_DEFAULT_RX_CONFIG (CFG_UNI_FILTER_EN | \
+ CFG_BSSID_FILTER_EN)
+
+#define WL1251_DEFAULT_RX_FILTER (CFG_RX_PRSP_EN | \
+ CFG_RX_MGMT_EN | \
+ CFG_RX_DATA_EN | \
+ CFG_RX_CTL_EN | \
+ CFG_RX_BCN_EN | \
+ CFG_RX_AUTH_EN | \
+ CFG_RX_ASSOC_EN)
+
+#define WL1251_BUSY_WORD_LEN 8
+
+struct boot_attr {
+ u32 radio_type;
+ u8 mac_clock;
+ u8 arm_clock;
+ int firmware_debug;
+ u32 minor;
+ u32 major;
+ u32 bugfix;
+};
+
+enum wl1251_state {
+ WL1251_STATE_OFF,
+ WL1251_STATE_ON,
+ WL1251_STATE_PLT,
+};
+
+enum wl1251_partition_type {
+ PART_DOWN,
+ PART_WORK,
+ PART_DRPW,
+
+ PART_TABLE_LEN
+};
+
+struct wl1251_partition {
+ u32 size;
+ u32 start;
+};
+
+struct wl1251_partition_set {
+ struct wl1251_partition mem;
+ struct wl1251_partition reg;
+};
+
+struct wl1251;
+
+struct wl1251_stats {
+ struct acx_statistics *fw_stats;
+ unsigned long fw_stats_update;
+
+ unsigned int retry_count;
+ unsigned int excessive_retries;
+};
+
+struct wl1251_debugfs {
+ struct dentry *rootdir;
+ struct dentry *fw_statistics;
+
+ struct dentry *tx_internal_desc_overflow;
+
+ struct dentry *rx_out_of_mem;
+ struct dentry *rx_hdr_overflow;
+ struct dentry *rx_hw_stuck;
+ struct dentry *rx_dropped;
+ struct dentry *rx_fcs_err;
+ struct dentry *rx_xfr_hint_trig;
+ struct dentry *rx_path_reset;
+ struct dentry *rx_reset_counter;
+
+ struct dentry *dma_rx_requested;
+ struct dentry *dma_rx_errors;
+ struct dentry *dma_tx_requested;
+ struct dentry *dma_tx_errors;
+
+ struct dentry *isr_cmd_cmplt;
+ struct dentry *isr_fiqs;
+ struct dentry *isr_rx_headers;
+ struct dentry *isr_rx_mem_overflow;
+ struct dentry *isr_rx_rdys;
+ struct dentry *isr_irqs;
+ struct dentry *isr_tx_procs;
+ struct dentry *isr_decrypt_done;
+ struct dentry *isr_dma0_done;
+ struct dentry *isr_dma1_done;
+ struct dentry *isr_tx_exch_complete;
+ struct dentry *isr_commands;
+ struct dentry *isr_rx_procs;
+ struct dentry *isr_hw_pm_mode_changes;
+ struct dentry *isr_host_acknowledges;
+ struct dentry *isr_pci_pm;
+ struct dentry *isr_wakeups;
+ struct dentry *isr_low_rssi;
+
+ struct dentry *wep_addr_key_count;
+ struct dentry *wep_default_key_count;
+ /* skipping wep.reserved */
+ struct dentry *wep_key_not_found;
+ struct dentry *wep_decrypt_fail;
+ struct dentry *wep_packets;
+ struct dentry *wep_interrupt;
+
+ struct dentry *pwr_ps_enter;
+ struct dentry *pwr_elp_enter;
+ struct dentry *pwr_missing_bcns;
+ struct dentry *pwr_wake_on_host;
+ struct dentry *pwr_wake_on_timer_exp;
+ struct dentry *pwr_tx_with_ps;
+ struct dentry *pwr_tx_without_ps;
+ struct dentry *pwr_rcvd_beacons;
+ struct dentry *pwr_power_save_off;
+ struct dentry *pwr_enable_ps;
+ struct dentry *pwr_disable_ps;
+ struct dentry *pwr_fix_tsf_ps;
+ /* skipping cont_miss_bcns_spread for now */
+ struct dentry *pwr_rcvd_awake_beacons;
+
+ struct dentry *mic_rx_pkts;
+ struct dentry *mic_calc_failure;
+
+ struct dentry *aes_encrypt_fail;
+ struct dentry *aes_decrypt_fail;
+ struct dentry *aes_encrypt_packets;
+ struct dentry *aes_decrypt_packets;
+ struct dentry *aes_encrypt_interrupt;
+ struct dentry *aes_decrypt_interrupt;
+
+ struct dentry *event_heart_beat;
+ struct dentry *event_calibration;
+ struct dentry *event_rx_mismatch;
+ struct dentry *event_rx_mem_empty;
+ struct dentry *event_rx_pool;
+ struct dentry *event_oom_late;
+ struct dentry *event_phy_transmit_error;
+ struct dentry *event_tx_stuck;
+
+ struct dentry *ps_pspoll_timeouts;
+ struct dentry *ps_upsd_timeouts;
+ struct dentry *ps_upsd_max_sptime;
+ struct dentry *ps_upsd_max_apturn;
+ struct dentry *ps_pspoll_max_apturn;
+ struct dentry *ps_pspoll_utilization;
+ struct dentry *ps_upsd_utilization;
+
+ struct dentry *rxpipe_rx_prep_beacon_drop;
+ struct dentry *rxpipe_descr_host_int_trig_rx_data;
+ struct dentry *rxpipe_beacon_buffer_thres_host_int_trig_rx_data;
+ struct dentry *rxpipe_missed_beacon_host_int_trig_rx_data;
+ struct dentry *rxpipe_tx_xfr_host_int_trig_rx_data;
+
+ struct dentry *tx_queue_len;
+
+ struct dentry *retry_count;
+ struct dentry *excessive_retries;
+};
+
+struct wl1251_if_operations {
+ void (*read)(struct wl1251 *wl, int addr, void *buf, size_t len);
+ void (*write)(struct wl1251 *wl, int addr, void *buf, size_t len);
+ void (*reset)(struct wl1251 *wl);
+ void (*enable_irq)(struct wl1251 *wl);
+ void (*disable_irq)(struct wl1251 *wl);
+};
+
+struct wl1251 {
+ struct ieee80211_hw *hw;
+ bool mac80211_registered;
+
+ void *if_priv;
+ const struct wl1251_if_operations *if_ops;
+
+ void (*set_power)(bool enable);
+ int irq;
+
+ enum wl1251_state state;
+ struct mutex mutex;
+
+ int physical_mem_addr;
+ int physical_reg_addr;
+ int virtual_mem_addr;
+ int virtual_reg_addr;
+
+ int cmd_box_addr;
+ int event_box_addr;
+ struct boot_attr boot_attr;
+
+ u8 *fw;
+ size_t fw_len;
+ u8 *nvs;
+ size_t nvs_len;
+
+ u8 bssid[ETH_ALEN];
+ u8 mac_addr[ETH_ALEN];
+ u8 bss_type;
+ u8 listen_int;
+ int channel;
+
+ void *target_mem_map;
+ struct acx_data_path_params_resp *data_path;
+
+ /* Number of TX packets transferred to the FW, modulo 16 */
+ u32 data_in_count;
+
+ /* Frames scheduled for transmission, not handled yet */
+ struct sk_buff_head tx_queue;
+ bool tx_queue_stopped;
+
+ struct work_struct tx_work;
+ struct work_struct filter_work;
+
+ /* Pending TX frames */
+ struct sk_buff *tx_frames[16];
/*
- * Nmber of memory buffers for the RX mem pool.
- * The actual number may be less if there are
- * not enough blocks left for the minimum num
- * of TX ones.
+ * Index pointing to the next TX complete entry
+ * in the cyclic XT complete array we get from
+ * the FW.
*/
- u8 rx_mem_block_num;
- u8 reserved_2;
- u8 num_tx_queues; /* From 1 to 16 */
- u8 host_if_options; /* HOST_IF* */
- u8 tx_min_mem_block_num;
- u8 num_ssid_profiles;
- __le16 debug_buffer_size;
-} __attribute__ ((packed));
+ u32 next_tx_complete;
+ /* FW Rx counter */
+ u32 rx_counter;
-#define ACX_RX_DESC_MIN 1
-#define ACX_RX_DESC_MAX 127
-#define ACX_RX_DESC_DEF 32
-struct wl1251_acx_rx_queue_config {
- u8 num_descs;
- u8 pad;
- u8 type;
- u8 priority;
- __le32 dma_address;
-} __attribute__ ((packed));
+ /* Rx frames handled */
+ u32 rx_handled;
-#define ACX_TX_DESC_MIN 1
-#define ACX_TX_DESC_MAX 127
-#define ACX_TX_DESC_DEF 16
-struct wl1251_acx_tx_queue_config {
- u8 num_descs;
- u8 pad[2];
- u8 attributes;
-} __attribute__ ((packed));
+ /* Current double buffer */
+ u32 rx_current_buffer;
+ u32 rx_last_id;
-#define MAX_TX_QUEUE_CONFIGS 5
-#define MAX_TX_QUEUES 4
-struct wl1251_acx_config_memory {
- struct acx_header header;
+ /* The target interrupt mask */
+ u32 intr_mask;
+ struct work_struct irq_work;
- struct wl1251_acx_memory mem_config;
- struct wl1251_acx_rx_queue_config rx_queue_config;
- struct wl1251_acx_tx_queue_config tx_queue_config[MAX_TX_QUEUE_CONFIGS];
-} __attribute__ ((packed));
+ /* The mbox event mask */
+ u32 event_mask;
-struct wl1251_acx_mem_map {
- struct acx_header header;
+ /* Mailbox pointers */
+ u32 mbox_ptr[2];
- void *code_start;
- void *code_end;
+ /* Are we currently scanning */
+ bool scanning;
- void *wep_defkey_start;
- void *wep_defkey_end;
+ /* Our association ID */
+ u16 aid;
- void *sta_table_start;
- void *sta_table_end;
+ /* Default key (for WEP) */
+ u32 default_key;
- void *packet_template_start;
- void *packet_template_end;
+ unsigned int tx_mgmt_frm_rate;
+ unsigned int tx_mgmt_frm_mod;
- void *queue_memory_start;
- void *queue_memory_end;
+ unsigned int rx_config;
+ unsigned int rx_filter;
- void *packet_memory_pool_start;
- void *packet_memory_pool_end;
+ /* is firmware in elp mode */
+ bool elp;
- void *debug_buffer1_start;
- void *debug_buffer1_end;
+ /* we can be in psm, but not in elp, we have to differentiate */
+ bool psm;
- void *debug_buffer2_start;
- void *debug_buffer2_end;
+ /* PSM mode requested */
+ bool psm_requested;
- /* Number of blocks FW allocated for TX packets */
- u32 num_tx_mem_blocks;
+ u16 beacon_int;
+ u8 dtim_period;
- /* Number of blocks FW allocated for RX packets */
- u32 num_rx_mem_blocks;
-} __attribute__ ((packed));
+ /* in dBm */
+ int power_level;
-/*************************************************************************
+ struct wl1251_stats stats;
+ struct wl1251_debugfs debugfs;
- Host Interrupt Register (WiLink -> Host)
+ u32 buffer_32;
+ u32 buffer_cmd;
+ u8 buffer_busyword[WL1251_BUSY_WORD_LEN];
+ struct wl1251_rx_descriptor *rx_descriptor;
-**************************************************************************/
+ u32 chip_id;
+ char fw_ver[21];
+};
-/* RX packet is ready in Xfer buffer #0 */
-#define WL1251_ACX_INTR_RX0_DATA BIT(0)
+int wl1251_plt_start(struct wl1251 *wl);
+int wl1251_plt_stop(struct wl1251 *wl);
-/* TX result(s) are in the TX complete buffer */
-#define WL1251_ACX_INTR_TX_RESULT BIT(1)
+struct ieee80211_hw *wl1251_alloc_hw(void);
+int wl1251_free_hw(struct wl1251 *wl);
+int wl1251_init_ieee80211(struct wl1251 *wl);
+void wl1251_enable_interrupts(struct wl1251 *wl);
+void wl1251_disable_interrupts(struct wl1251 *wl);
-/* OBSOLETE */
-#define WL1251_ACX_INTR_TX_XFR BIT(2)
+#define DEFAULT_HW_GEN_MODULATION_TYPE CCK_LONG /* Long Preamble */
+#define DEFAULT_HW_GEN_TX_RATE RATE_2MBPS
+#define JOIN_TIMEOUT 5000 /* 5000 milliseconds to join */
-/* RX packet is ready in Xfer buffer #1 */
-#define WL1251_ACX_INTR_RX1_DATA BIT(3)
+#define WL1251_DEFAULT_POWER_LEVEL 20
-/* Event was entered to Event MBOX #A */
-#define WL1251_ACX_INTR_EVENT_A BIT(4)
+#define WL1251_TX_QUEUE_MAX_LENGTH 20
-/* Event was entered to Event MBOX #B */
-#define WL1251_ACX_INTR_EVENT_B BIT(5)
+#define WL1251_DEFAULT_BEACON_INT 100
+#define WL1251_DEFAULT_DTIM_PERIOD 1
-/* OBSOLETE */
-#define WL1251_ACX_INTR_WAKE_ON_HOST BIT(6)
+#define WL1251_DEFAULT_CHANNEL 0
-/* Trace meassge on MBOX #A */
-#define WL1251_ACX_INTR_TRACE_A BIT(7)
+#define CHIP_ID_1251_PG10 (0x7010101)
+#define CHIP_ID_1251_PG11 (0x7020101)
+#define CHIP_ID_1251_PG12 (0x7030101)
+#define CHIP_ID_1271_PG10 (0x4030101)
+#define CHIP_ID_1271_PG20 (0x4030111)
-/* Trace meassge on MBOX #B */
-#define WL1251_ACX_INTR_TRACE_B BIT(8)
+#define WL1251_FW_NAME "wl1251-fw.bin"
+#define WL1251_NVS_NAME "wl1251-nvs.bin"
-/* Command processing completion */
-#define WL1251_ACX_INTR_CMD_COMPLETE BIT(9)
+#define WL1251_POWER_ON_SLEEP 10 /* in miliseconds */
-/* Init sequence is done */
-#define WL1251_ACX_INTR_INIT_COMPLETE BIT(14)
+#define WL1251_PART_DOWN_MEM_START 0x0
+#define WL1251_PART_DOWN_MEM_SIZE 0x16800
+#define WL1251_PART_DOWN_REG_START REGISTERS_BASE
+#define WL1251_PART_DOWN_REG_SIZE REGISTERS_DOWN_SIZE
-#define WL1251_ACX_INTR_ALL 0xFFFFFFFF
+#define WL1251_PART_WORK_MEM_START 0x28000
+#define WL1251_PART_WORK_MEM_SIZE 0x14000
+#define WL1251_PART_WORK_REG_START REGISTERS_BASE
+#define WL1251_PART_WORK_REG_SIZE REGISTERS_WORK_SIZE
#endif
diff --git a/drivers/net/wireless/wl12xx/wl1251_acx.c b/drivers/net/wireless/wl12xx/wl1251_acx.c
new file mode 100644
index 00000000000..10b26c4532c
--- /dev/null
+++ b/drivers/net/wireless/wl12xx/wl1251_acx.c
@@ -0,0 +1,918 @@
+#include "wl1251_acx.h"
+
+#include <linux/module.h>
+#include <linux/crc7.h>
+
+#include "wl1251.h"
+#include "wl1251_reg.h"
+#include "wl1251_cmd.h"
+#include "wl1251_ps.h"
+
+int wl1251_acx_frame_rates(struct wl1251 *wl, u8 ctrl_rate, u8 ctrl_mod,
+ u8 mgt_rate, u8 mgt_mod)
+{
+ struct acx_fw_gen_frame_rates *rates;
+ int ret;
+
+ wl1251_debug(DEBUG_ACX, "acx frame rates");
+
+ rates = kzalloc(sizeof(*rates), GFP_KERNEL);
+ if (!rates) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ rates->tx_ctrl_frame_rate = ctrl_rate;
+ rates->tx_ctrl_frame_mod = ctrl_mod;
+ rates->tx_mgt_frame_rate = mgt_rate;
+ rates->tx_mgt_frame_mod = mgt_mod;
+
+ ret = wl1251_cmd_configure(wl, ACX_FW_GEN_FRAME_RATES,
+ rates, sizeof(*rates));
+ if (ret < 0) {
+ wl1251_error("Failed to set FW rates and modulation");
+ goto out;
+ }
+
+out:
+ kfree(rates);
+ return ret;
+}
+
+
+int wl1251_acx_station_id(struct wl1251 *wl)
+{
+ struct acx_dot11_station_id *mac;
+ int ret, i;
+
+ wl1251_debug(DEBUG_ACX, "acx dot11_station_id");
+
+ mac = kzalloc(sizeof(*mac), GFP_KERNEL);
+ if (!mac) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ for (i = 0; i < ETH_ALEN; i++)
+ mac->mac[i] = wl->mac_addr[ETH_ALEN - 1 - i];
+
+ ret = wl1251_cmd_configure(wl, DOT11_STATION_ID, mac, sizeof(*mac));
+ if (ret < 0)
+ goto out;
+
+out:
+ kfree(mac);
+ return ret;
+}
+
+int wl1251_acx_default_key(struct wl1251 *wl, u8 key_id)
+{
+ struct acx_dot11_default_key *default_key;
+ int ret;
+
+ wl1251_debug(DEBUG_ACX, "acx dot11_default_key (%d)", key_id);
+
+ default_key = kzalloc(sizeof(*default_key), GFP_KERNEL);
+ if (!default_key) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ default_key->id = key_id;
+
+ ret = wl1251_cmd_configure(wl, DOT11_DEFAULT_KEY,
+ default_key, sizeof(*default_key));
+ if (ret < 0) {
+ wl1251_error("Couldn't set default key");
+ goto out;
+ }
+
+ wl->default_key = key_id;
+
+out:
+ kfree(default_key);
+ return ret;
+}
+
+int wl1251_acx_wake_up_conditions(struct wl1251 *wl, u8 wake_up_event,
+ u8 listen_interval)
+{
+ struct acx_wake_up_condition *wake_up;
+ int ret;
+
+ wl1251_debug(DEBUG_ACX, "acx wake up conditions");
+
+ wake_up = kzalloc(sizeof(*wake_up), GFP_KERNEL);
+ if (!wake_up) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ wake_up->wake_up_event = wake_up_event;
+ wake_up->listen_interval = listen_interval;
+
+ ret = wl1251_cmd_configure(wl, ACX_WAKE_UP_CONDITIONS,
+ wake_up, sizeof(*wake_up));
+ if (ret < 0) {
+ wl1251_warning("could not set wake up conditions: %d", ret);
+ goto out;
+ }
+
+out:
+ kfree(wake_up);
+ return ret;
+}
+
+int wl1251_acx_sleep_auth(struct wl1251 *wl, u8 sleep_auth)
+{
+ struct acx_sleep_auth *auth;
+ int ret;
+
+ wl1251_debug(DEBUG_ACX, "acx sleep auth");
+
+ auth = kzalloc(sizeof(*auth), GFP_KERNEL);
+ if (!auth) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ auth->sleep_auth = sleep_auth;
+
+ ret = wl1251_cmd_configure(wl, ACX_SLEEP_AUTH, auth, sizeof(*auth));
+ if (ret < 0)
+ return ret;
+
+out:
+ kfree(auth);
+ return ret;
+}
+
+int wl1251_acx_fw_version(struct wl1251 *wl, char *buf, size_t len)
+{
+ struct acx_revision *rev;
+ int ret;
+
+ wl1251_debug(DEBUG_ACX, "acx fw rev");
+
+ rev = kzalloc(sizeof(*rev), GFP_KERNEL);
+ if (!rev) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ ret = wl1251_cmd_interrogate(wl, ACX_FW_REV, rev, sizeof(*rev));
+ if (ret < 0) {
+ wl1251_warning("ACX_FW_REV interrogate failed");
+ goto out;
+ }
+
+ /* be careful with the buffer sizes */
+ strncpy(buf, rev->fw_version, min(len, sizeof(rev->fw_version)));
+
+ /*
+ * if the firmware version string is exactly
+ * sizeof(rev->fw_version) long or fw_len is less than
+ * sizeof(rev->fw_version) it won't be null terminated
+ */
+ buf[min(len, sizeof(rev->fw_version)) - 1] = '\0';
+
+out:
+ kfree(rev);
+ return ret;
+}
+
+int wl1251_acx_tx_power(struct wl1251 *wl, int power)
+{
+ struct acx_current_tx_power *acx;
+ int ret;
+
+ wl1251_debug(DEBUG_ACX, "acx dot11_cur_tx_pwr");
+
+ if (power < 0 || power > 25)
+ return -EINVAL;
+
+ acx = kzalloc(sizeof(*acx), GFP_KERNEL);
+ if (!acx) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ acx->current_tx_power = power * 10;
+
+ ret = wl1251_cmd_configure(wl, DOT11_CUR_TX_PWR, acx, sizeof(*acx));
+ if (ret < 0) {
+ wl1251_warning("configure of tx power failed: %d", ret);
+ goto out;
+ }
+
+out:
+ kfree(acx);
+ return ret;
+}
+
+int wl1251_acx_feature_cfg(struct wl1251 *wl)
+{
+ struct acx_feature_config *feature;
+ int ret;
+
+ wl1251_debug(DEBUG_ACX, "acx feature cfg");
+
+ feature = kzalloc(sizeof(*feature), GFP_KERNEL);
+ if (!feature) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ /* DF_ENCRYPTION_DISABLE and DF_SNIFF_MODE_ENABLE are disabled */
+ feature->data_flow_options = 0;
+ feature->options = 0;
+
+ ret = wl1251_cmd_configure(wl, ACX_FEATURE_CFG,
+ feature, sizeof(*feature));
+ if (ret < 0) {
+ wl1251_error("Couldn't set HW encryption");
+ goto out;
+ }
+
+out:
+ kfree(feature);
+ return ret;
+}
+
+int wl1251_acx_mem_map(struct wl1251 *wl, struct acx_header *mem_map,
+ size_t len)
+{
+ int ret;
+
+ wl1251_debug(DEBUG_ACX, "acx mem map");
+
+ ret = wl1251_cmd_interrogate(wl, ACX_MEM_MAP, mem_map, len);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+int wl1251_acx_data_path_params(struct wl1251 *wl,
+ struct acx_data_path_params_resp *resp)
+{
+ struct acx_data_path_params *params;
+ int ret;
+
+ wl1251_debug(DEBUG_ACX, "acx data path params");
+
+ params = kzalloc(sizeof(*params), GFP_KERNEL);
+ if (!params) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ params->rx_packet_ring_chunk_size = DP_RX_PACKET_RING_CHUNK_SIZE;
+ params->tx_packet_ring_chunk_size = DP_TX_PACKET_RING_CHUNK_SIZE;
+
+ params->rx_packet_ring_chunk_num = DP_RX_PACKET_RING_CHUNK_NUM;
+ params->tx_packet_ring_chunk_num = DP_TX_PACKET_RING_CHUNK_NUM;
+
+ params->tx_complete_threshold = 1;
+
+ params->tx_complete_ring_depth = FW_TX_CMPLT_BLOCK_SIZE;
+
+ params->tx_complete_timeout = DP_TX_COMPLETE_TIME_OUT;
+
+ ret = wl1251_cmd_configure(wl, ACX_DATA_PATH_PARAMS,
+ params, sizeof(*params));
+ if (ret < 0)
+ goto out;
+
+ /* FIXME: shouldn't this be ACX_DATA_PATH_RESP_PARAMS? */
+ ret = wl1251_cmd_interrogate(wl, ACX_DATA_PATH_PARAMS,
+ resp, sizeof(*resp));
+
+ if (ret < 0) {
+ wl1251_warning("failed to read data path parameters: %d", ret);
+ goto out;
+ } else if (resp->header.cmd.status != CMD_STATUS_SUCCESS) {
+ wl1251_warning("data path parameter acx status failed");
+ ret = -EIO;
+ goto out;
+ }
+
+out:
+ kfree(params);
+ return ret;
+}
+
+int wl1251_acx_rx_msdu_life_time(struct wl1251 *wl, u32 life_time)
+{
+ struct acx_rx_msdu_lifetime *acx;
+ int ret;
+
+ wl1251_debug(DEBUG_ACX, "acx rx msdu life time");
+
+ acx = kzalloc(sizeof(*acx), GFP_KERNEL);
+ if (!acx) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ acx->lifetime = life_time;
+ ret = wl1251_cmd_configure(wl, DOT11_RX_MSDU_LIFE_TIME,
+ acx, sizeof(*acx));
+ if (ret < 0) {
+ wl1251_warning("failed to set rx msdu life time: %d", ret);
+ goto out;
+ }
+
+out:
+ kfree(acx);
+ return ret;
+}
+
+int wl1251_acx_rx_config(struct wl1251 *wl, u32 config, u32 filter)
+{
+ struct acx_rx_config *rx_config;
+ int ret;
+
+ wl1251_debug(DEBUG_ACX, "acx rx config");
+
+ rx_config = kzalloc(sizeof(*rx_config), GFP_KERNEL);
+ if (!rx_config) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ rx_config->config_options = config;
+ rx_config->filter_options = filter;
+
+ ret = wl1251_cmd_configure(wl, ACX_RX_CFG,
+ rx_config, sizeof(*rx_config));
+ if (ret < 0) {
+ wl1251_warning("failed to set rx config: %d", ret);
+ goto out;
+ }
+
+out:
+ kfree(rx_config);
+ return ret;
+}
+
+int wl1251_acx_pd_threshold(struct wl1251 *wl)
+{
+ struct acx_packet_detection *pd;
+ int ret;
+
+ wl1251_debug(DEBUG_ACX, "acx data pd threshold");
+
+ pd = kzalloc(sizeof(*pd), GFP_KERNEL);
+ if (!pd) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ /* FIXME: threshold value not set */
+
+ ret = wl1251_cmd_configure(wl, ACX_PD_THRESHOLD, pd, sizeof(*pd));
+ if (ret < 0) {
+ wl1251_warning("failed to set pd threshold: %d", ret);
+ goto out;
+ }
+
+out:
+ kfree(pd);
+ return 0;
+}
+
+int wl1251_acx_slot(struct wl1251 *wl, enum acx_slot_type slot_time)
+{
+ struct acx_slot *slot;
+ int ret;
+
+ wl1251_debug(DEBUG_ACX, "acx slot");
+
+ slot = kzalloc(sizeof(*slot), GFP_KERNEL);
+ if (!slot) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ slot->wone_index = STATION_WONE_INDEX;
+ slot->slot_time = slot_time;
+
+ ret = wl1251_cmd_configure(wl, ACX_SLOT, slot, sizeof(*slot));
+ if (ret < 0) {
+ wl1251_warning("failed to set slot time: %d", ret);
+ goto out;
+ }
+
+out:
+ kfree(slot);
+ return ret;
+}
+
+int wl1251_acx_group_address_tbl(struct wl1251 *wl)
+{
+ struct acx_dot11_grp_addr_tbl *acx;
+ int ret;
+
+ wl1251_debug(DEBUG_ACX, "acx group address tbl");
+
+ acx = kzalloc(sizeof(*acx), GFP_KERNEL);
+ if (!acx) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ /* MAC filtering */
+ acx->enabled = 0;
+ acx->num_groups = 0;
+ memset(acx->mac_table, 0, ADDRESS_GROUP_MAX_LEN);
+
+ ret = wl1251_cmd_configure(wl, DOT11_GROUP_ADDRESS_TBL,
+ acx, sizeof(*acx));
+ if (ret < 0) {
+ wl1251_warning("failed to set group addr table: %d", ret);
+ goto out;
+ }
+
+out:
+ kfree(acx);
+ return ret;
+}
+
+int wl1251_acx_service_period_timeout(struct wl1251 *wl)
+{
+ struct acx_rx_timeout *rx_timeout;
+ int ret;
+
+ rx_timeout = kzalloc(sizeof(*rx_timeout), GFP_KERNEL);
+ if (!rx_timeout) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ wl1251_debug(DEBUG_ACX, "acx service period timeout");
+
+ rx_timeout->ps_poll_timeout = RX_TIMEOUT_PS_POLL_DEF;
+ rx_timeout->upsd_timeout = RX_TIMEOUT_UPSD_DEF;
+
+ ret = wl1251_cmd_configure(wl, ACX_SERVICE_PERIOD_TIMEOUT,
+ rx_timeout, sizeof(*rx_timeout));
+ if (ret < 0) {
+ wl1251_warning("failed to set service period timeout: %d",
+ ret);
+ goto out;
+ }
+
+out:
+ kfree(rx_timeout);
+ return ret;
+}
+
+int wl1251_acx_rts_threshold(struct wl1251 *wl, u16 rts_threshold)
+{
+ struct acx_rts_threshold *rts;
+ int ret;
+
+ wl1251_debug(DEBUG_ACX, "acx rts threshold");
+
+ rts = kzalloc(sizeof(*rts), GFP_KERNEL);
+ if (!rts) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ rts->threshold = rts_threshold;
+
+ ret = wl1251_cmd_configure(wl, DOT11_RTS_THRESHOLD, rts, sizeof(*rts));
+ if (ret < 0) {
+ wl1251_warning("failed to set rts threshold: %d", ret);
+ goto out;
+ }
+
+out:
+ kfree(rts);
+ return ret;
+}
+
+int wl1251_acx_beacon_filter_opt(struct wl1251 *wl)
+{
+ struct acx_beacon_filter_option *beacon_filter;
+ int ret;
+
+ wl1251_debug(DEBUG_ACX, "acx beacon filter opt");
+
+ beacon_filter = kzalloc(sizeof(*beacon_filter), GFP_KERNEL);
+ if (!beacon_filter) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ beacon_filter->enable = 0;
+ beacon_filter->max_num_beacons = 0;
+
+ ret = wl1251_cmd_configure(wl, ACX_BEACON_FILTER_OPT,
+ beacon_filter, sizeof(*beacon_filter));
+ if (ret < 0) {
+ wl1251_warning("failed to set beacon filter opt: %d", ret);
+ goto out;
+ }
+
+out:
+ kfree(beacon_filter);
+ return ret;
+}
+
+int wl1251_acx_beacon_filter_table(struct wl1251 *wl)
+{
+ struct acx_beacon_filter_ie_table *ie_table;
+ int ret;
+
+ wl1251_debug(DEBUG_ACX, "acx beacon filter table");
+
+ ie_table = kzalloc(sizeof(*ie_table), GFP_KERNEL);
+ if (!ie_table) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ ie_table->num_ie = 0;
+ memset(ie_table->table, 0, BEACON_FILTER_TABLE_MAX_SIZE);
+
+ ret = wl1251_cmd_configure(wl, ACX_BEACON_FILTER_TABLE,
+ ie_table, sizeof(*ie_table));
+ if (ret < 0) {
+ wl1251_warning("failed to set beacon filter table: %d", ret);
+ goto out;
+ }
+
+out:
+ kfree(ie_table);
+ return ret;
+}
+
+int wl1251_acx_sg_enable(struct wl1251 *wl)
+{
+ struct acx_bt_wlan_coex *pta;
+ int ret;
+
+ wl1251_debug(DEBUG_ACX, "acx sg enable");
+
+ pta = kzalloc(sizeof(*pta), GFP_KERNEL);
+ if (!pta) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ pta->enable = SG_ENABLE;
+
+ ret = wl1251_cmd_configure(wl, ACX_SG_ENABLE, pta, sizeof(*pta));
+ if (ret < 0) {
+ wl1251_warning("failed to set softgemini enable: %d", ret);
+ goto out;
+ }
+
+out:
+ kfree(pta);
+ return ret;
+}
+
+int wl1251_acx_sg_cfg(struct wl1251 *wl)
+{
+ struct acx_bt_wlan_coex_param *param;
+ int ret;
+
+ wl1251_debug(DEBUG_ACX, "acx sg cfg");
+
+ param = kzalloc(sizeof(*param), GFP_KERNEL);
+ if (!param) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ /* BT-WLAN coext parameters */
+ param->min_rate = RATE_INDEX_24MBPS;
+ param->bt_hp_max_time = PTA_BT_HP_MAXTIME_DEF;
+ param->wlan_hp_max_time = PTA_WLAN_HP_MAX_TIME_DEF;
+ param->sense_disable_timer = PTA_SENSE_DISABLE_TIMER_DEF;
+ param->rx_time_bt_hp = PTA_PROTECTIVE_RX_TIME_DEF;
+ param->tx_time_bt_hp = PTA_PROTECTIVE_TX_TIME_DEF;
+ param->rx_time_bt_hp_fast = PTA_PROTECTIVE_RX_TIME_FAST_DEF;
+ param->tx_time_bt_hp_fast = PTA_PROTECTIVE_TX_TIME_FAST_DEF;
+ param->wlan_cycle_fast = PTA_CYCLE_TIME_FAST_DEF;
+ param->bt_anti_starvation_period = PTA_ANTI_STARVE_PERIOD_DEF;
+ param->next_bt_lp_packet = PTA_TIMEOUT_NEXT_BT_LP_PACKET_DEF;
+ param->wake_up_beacon = PTA_TIME_BEFORE_BEACON_DEF;
+ param->hp_dm_max_guard_time = PTA_HPDM_MAX_TIME_DEF;
+ param->next_wlan_packet = PTA_TIME_OUT_NEXT_WLAN_DEF;
+ param->antenna_type = PTA_ANTENNA_TYPE_DEF;
+ param->signal_type = PTA_SIGNALING_TYPE_DEF;
+ param->afh_leverage_on = PTA_AFH_LEVERAGE_ON_DEF;
+ param->quiet_cycle_num = PTA_NUMBER_QUIET_CYCLE_DEF;
+ param->max_cts = PTA_MAX_NUM_CTS_DEF;
+ param->wlan_packets_num = PTA_NUMBER_OF_WLAN_PACKETS_DEF;
+ param->bt_packets_num = PTA_NUMBER_OF_BT_PACKETS_DEF;
+ param->missed_rx_avalanche = PTA_RX_FOR_AVALANCHE_DEF;
+ param->wlan_elp_hp = PTA_ELP_HP_DEF;
+ param->bt_anti_starvation_cycles = PTA_ANTI_STARVE_NUM_CYCLE_DEF;
+ param->ack_mode_dual_ant = PTA_ACK_MODE_DEF;
+ param->pa_sd_enable = PTA_ALLOW_PA_SD_DEF;
+ param->pta_auto_mode_enable = PTA_AUTO_MODE_NO_CTS_DEF;
+ param->bt_hp_respected_num = PTA_BT_HP_RESPECTED_DEF;
+
+ ret = wl1251_cmd_configure(wl, ACX_SG_CFG, param, sizeof(*param));
+ if (ret < 0) {
+ wl1251_warning("failed to set sg config: %d", ret);
+ goto out;
+ }
+
+out:
+ kfree(param);
+ return ret;
+}
+
+int wl1251_acx_cca_threshold(struct wl1251 *wl)
+{
+ struct acx_energy_detection *detection;
+ int ret;
+
+ wl1251_debug(DEBUG_ACX, "acx cca threshold");
+
+ detection = kzalloc(sizeof(*detection), GFP_KERNEL);
+ if (!detection) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ detection->rx_cca_threshold = CCA_THRSH_DISABLE_ENERGY_D;
+ detection->tx_energy_detection = 0;
+
+ ret = wl1251_cmd_configure(wl, ACX_CCA_THRESHOLD,
+ detection, sizeof(*detection));
+ if (ret < 0) {
+ wl1251_warning("failed to set cca threshold: %d", ret);
+ return ret;
+ }
+
+out:
+ kfree(detection);
+ return ret;
+}
+
+int wl1251_acx_bcn_dtim_options(struct wl1251 *wl)
+{
+ struct acx_beacon_broadcast *bb;
+ int ret;
+
+ wl1251_debug(DEBUG_ACX, "acx bcn dtim options");
+
+ bb = kzalloc(sizeof(*bb), GFP_KERNEL);
+ if (!bb) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ bb->beacon_rx_timeout = BCN_RX_TIMEOUT_DEF_VALUE;
+ bb->broadcast_timeout = BROADCAST_RX_TIMEOUT_DEF_VALUE;
+ bb->rx_broadcast_in_ps = RX_BROADCAST_IN_PS_DEF_VALUE;
+ bb->ps_poll_threshold = CONSECUTIVE_PS_POLL_FAILURE_DEF;
+
+ ret = wl1251_cmd_configure(wl, ACX_BCN_DTIM_OPTIONS, bb, sizeof(*bb));
+ if (ret < 0) {
+ wl1251_warning("failed to set rx config: %d", ret);
+ goto out;
+ }
+
+out:
+ kfree(bb);
+ return ret;
+}
+
+int wl1251_acx_aid(struct wl1251 *wl, u16 aid)
+{
+ struct acx_aid *acx_aid;
+ int ret;
+
+ wl1251_debug(DEBUG_ACX, "acx aid");
+
+ acx_aid = kzalloc(sizeof(*acx_aid), GFP_KERNEL);
+ if (!acx_aid) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ acx_aid->aid = aid;
+
+ ret = wl1251_cmd_configure(wl, ACX_AID, acx_aid, sizeof(*acx_aid));
+ if (ret < 0) {
+ wl1251_warning("failed to set aid: %d", ret);
+ goto out;
+ }
+
+out:
+ kfree(acx_aid);
+ return ret;
+}
+
+int wl1251_acx_event_mbox_mask(struct wl1251 *wl, u32 event_mask)
+{
+ struct acx_event_mask *mask;
+ int ret;
+
+ wl1251_debug(DEBUG_ACX, "acx event mbox mask");
+
+ mask = kzalloc(sizeof(*mask), GFP_KERNEL);
+ if (!mask) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ /* high event mask is unused */
+ mask->high_event_mask = 0xffffffff;
+
+ mask->event_mask = event_mask;
+
+ ret = wl1251_cmd_configure(wl, ACX_EVENT_MBOX_MASK,
+ mask, sizeof(*mask));
+ if (ret < 0) {
+ wl1251_warning("failed to set acx_event_mbox_mask: %d", ret);
+ goto out;
+ }
+
+out:
+ kfree(mask);
+ return ret;
+}
+
+int wl1251_acx_set_preamble(struct wl1251 *wl, enum acx_preamble_type preamble)
+{
+ struct acx_preamble *acx;
+ int ret;
+
+ wl1251_debug(DEBUG_ACX, "acx_set_preamble");
+
+ acx = kzalloc(sizeof(*acx), GFP_KERNEL);
+ if (!acx) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ acx->preamble = preamble;
+
+ ret = wl1251_cmd_configure(wl, ACX_PREAMBLE_TYPE, acx, sizeof(*acx));
+ if (ret < 0) {
+ wl1251_warning("Setting of preamble failed: %d", ret);
+ goto out;
+ }
+
+out:
+ kfree(acx);
+ return ret;
+}
+
+int wl1251_acx_cts_protect(struct wl1251 *wl,
+ enum acx_ctsprotect_type ctsprotect)
+{
+ struct acx_ctsprotect *acx;
+ int ret;
+
+ wl1251_debug(DEBUG_ACX, "acx_set_ctsprotect");
+
+ acx = kzalloc(sizeof(*acx), GFP_KERNEL);
+ if (!acx) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ acx->ctsprotect = ctsprotect;
+
+ ret = wl1251_cmd_configure(wl, ACX_CTS_PROTECTION, acx, sizeof(*acx));
+ if (ret < 0) {
+ wl1251_warning("Setting of ctsprotect failed: %d", ret);
+ goto out;
+ }
+
+out:
+ kfree(acx);
+ return ret;
+}
+
+int wl1251_acx_tsf_info(struct wl1251 *wl, u64 *mactime)
+{
+ struct acx_tsf_info *tsf_info;
+ int ret;
+
+ tsf_info = kzalloc(sizeof(*tsf_info), GFP_KERNEL);
+ if (!tsf_info) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ ret = wl1251_cmd_interrogate(wl, ACX_TSF_INFO,
+ tsf_info, sizeof(*tsf_info));
+ if (ret < 0) {
+ wl1251_warning("ACX_FW_REV interrogate failed");
+ goto out;
+ }
+
+ *mactime = tsf_info->current_tsf_lsb |
+ (tsf_info->current_tsf_msb << 31);
+
+out:
+ kfree(tsf_info);
+ return ret;
+}
+
+int wl1251_acx_statistics(struct wl1251 *wl, struct acx_statistics *stats)
+{
+ int ret;
+
+ wl1251_debug(DEBUG_ACX, "acx statistics");
+
+ ret = wl1251_cmd_interrogate(wl, ACX_STATISTICS, stats,
+ sizeof(*stats));
+ if (ret < 0) {
+ wl1251_warning("acx statistics failed: %d", ret);
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+int wl1251_acx_rate_policies(struct wl1251 *wl)
+{
+ struct acx_rate_policy *acx;
+ int ret = 0;
+
+ wl1251_debug(DEBUG_ACX, "acx rate policies");
+
+ acx = kzalloc(sizeof(*acx), GFP_KERNEL);
+
+ if (!acx) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ /* configure one default (one-size-fits-all) rate class */
+ acx->rate_class_cnt = 1;
+ acx->rate_class[0].enabled_rates = ACX_RATE_MASK_UNSPECIFIED;
+ acx->rate_class[0].short_retry_limit = ACX_RATE_RETRY_LIMIT;
+ acx->rate_class[0].long_retry_limit = ACX_RATE_RETRY_LIMIT;
+ acx->rate_class[0].aflags = 0;
+
+ ret = wl1251_cmd_configure(wl, ACX_RATE_POLICY, acx, sizeof(*acx));
+ if (ret < 0) {
+ wl1251_warning("Setting of rate policies failed: %d", ret);
+ goto out;
+ }
+
+out:
+ kfree(acx);
+ return ret;
+}
+
+int wl1251_acx_mem_cfg(struct wl1251 *wl)
+{
+ struct wl1251_acx_config_memory *mem_conf;
+ int ret, i;
+
+ wl1251_debug(DEBUG_ACX, "acx mem cfg");
+
+ mem_conf = kzalloc(sizeof(*mem_conf), GFP_KERNEL);
+ if (!mem_conf) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ /* memory config */
+ mem_conf->mem_config.num_stations = cpu_to_le16(DEFAULT_NUM_STATIONS);
+ mem_conf->mem_config.rx_mem_block_num = 35;
+ mem_conf->mem_config.tx_min_mem_block_num = 64;
+ mem_conf->mem_config.num_tx_queues = MAX_TX_QUEUES;
+ mem_conf->mem_config.host_if_options = HOSTIF_PKT_RING;
+ mem_conf->mem_config.num_ssid_profiles = 1;
+ mem_conf->mem_config.debug_buffer_size =
+ cpu_to_le16(TRACE_BUFFER_MAX_SIZE);
+
+ /* RX queue config */
+ mem_conf->rx_queue_config.dma_address = 0;
+ mem_conf->rx_queue_config.num_descs = ACX_RX_DESC_DEF;
+ mem_conf->rx_queue_config.priority = DEFAULT_RXQ_PRIORITY;
+ mem_conf->rx_queue_config.type = DEFAULT_RXQ_TYPE;
+
+ /* TX queue config */
+ for (i = 0; i < MAX_TX_QUEUES; i++) {
+ mem_conf->tx_queue_config[i].num_descs = ACX_TX_DESC_DEF;
+ mem_conf->tx_queue_config[i].attributes = i;
+ }
+
+ ret = wl1251_cmd_configure(wl, ACX_MEM_CFG, mem_conf,
+ sizeof(*mem_conf));
+ if (ret < 0) {
+ wl1251_warning("wl1251 mem config failed: %d", ret);
+ goto out;
+ }
+
+out:
+ kfree(mem_conf);
+ return ret;
+}
diff --git a/drivers/net/wireless/wl12xx/acx.h b/drivers/net/wireless/wl12xx/wl1251_acx.h
index fb2d2340993..cafb9145950 100644
--- a/drivers/net/wireless/wl12xx/acx.h
+++ b/drivers/net/wireless/wl12xx/wl1251_acx.h
@@ -1,5 +1,5 @@
/*
- * This file is part of wl12xx
+ * This file is part of wl1251
*
* Copyright (c) 1998-2007 Texas Instruments Incorporated
* Copyright (C) 2008 Nokia Corporation
@@ -22,14 +22,20 @@
*
*/
-#ifndef __WL12XX_ACX_H__
-#define __WL12XX_ACX_H__
+#ifndef __WL1251_ACX_H__
+#define __WL1251_ACX_H__
-#include "wl12xx.h"
+#include "wl1251.h"
+#include "wl1251_cmd.h"
/* Target's information element */
struct acx_header {
+ struct wl1251_cmd_header cmd;
+
+ /* acx (or information element) header */
u16 id;
+
+ /* payload length (not including headers */
u16 len;
};
@@ -85,15 +91,15 @@ struct acx_revision {
u32 hw_version;
} __attribute__ ((packed));
-enum wl12xx_psm_mode {
+enum wl1251_psm_mode {
/* Active mode */
- WL12XX_PSM_CAM = 0,
+ WL1251_PSM_CAM = 0,
/* Power save mode */
- WL12XX_PSM_PS = 1,
+ WL1251_PSM_PS = 1,
/* Extreme low power */
- WL12XX_PSM_ELP = 2,
+ WL1251_PSM_ELP = 2,
};
struct acx_sleep_auth {
@@ -107,25 +113,6 @@ struct acx_sleep_auth {
u8 padding[3];
} __attribute__ ((packed));
-#define TIM_ELE_ID 5
-#define PARTIAL_VBM_MAX 251
-
-struct tim {
- u8 identity;
- u8 length;
- u8 dtim_count;
- u8 dtim_period;
- u8 bitmap_ctrl;
- u8 pvb_field[PARTIAL_VBM_MAX]; /* Partial Virtual Bitmap */
-} __attribute__ ((packed));
-
-/* Virtual Bit Map update */
-struct vbm_update_request {
- __le16 len;
- u8 padding[2];
- struct tim tim;
-} __attribute__ ((packed));
-
enum {
HOSTIF_PCI_MASTER_HOST_INDIRECT,
HOSTIF_PCI_MASTER_HOST_DIRECT,
@@ -202,7 +189,7 @@ struct acx_data_path_params_resp {
#define RX_MSDU_LIFETIME_MAX 0xFFFFFFFF
#define RX_MSDU_LIFETIME_DEF 512000
-struct rx_msdu_lifetime {
+struct acx_rx_msdu_lifetime {
struct acx_header header;
/*
@@ -368,7 +355,7 @@ struct acx_slot {
#define ADDRESS_GROUP_MAX (8)
#define ADDRESS_GROUP_MAX_LEN (ETH_ALEN * ADDRESS_GROUP_MAX)
-struct multicast_grp_addr_start {
+struct acx_dot11_grp_addr_tbl {
struct acx_header header;
u8 enabled;
@@ -730,22 +717,13 @@ struct acx_fw_gen_frame_rates {
} __attribute__ ((packed));
/* STA MAC */
-struct dot11_station_id {
+struct acx_dot11_station_id {
struct acx_header header;
u8 mac[ETH_ALEN];
u8 pad[2];
} __attribute__ ((packed));
-/* HW encryption keys */
-#define NUM_ACCESS_CATEGORIES_COPY 4
-#define MAX_KEY_SIZE 32
-
-/* When set, disable HW encryption */
-#define DF_ENCRYPTION_DISABLE 0x01
-/* When set, disable HW decryption */
-#define DF_SNIFF_MODE_ENABLE 0x80
-
struct acx_feature_config {
struct acx_header header;
@@ -753,67 +731,6 @@ struct acx_feature_config {
u32 data_flow_options;
} __attribute__ ((packed));
-enum acx_key_action {
- KEY_ADD_OR_REPLACE = 1,
- KEY_REMOVE = 2,
- KEY_SET_ID = 3,
- MAX_KEY_ACTION = 0xffff,
-};
-
-enum acx_key_type {
- KEY_WEP_DEFAULT = 0,
- KEY_WEP_ADDR = 1,
- KEY_AES_GROUP = 4,
- KEY_AES_PAIRWISE = 5,
- KEY_WEP_GROUP = 6,
- KEY_TKIP_MIC_GROUP = 10,
- KEY_TKIP_MIC_PAIRWISE = 11,
-};
-
-/*
- *
- * key_type_e key size key format
- * ---------- --------- ----------
- * 0x00 5, 13, 29 Key data
- * 0x01 5, 13, 29 Key data
- * 0x04 16 16 bytes of key data
- * 0x05 16 16 bytes of key data
- * 0x0a 32 16 bytes of TKIP key data
- * 8 bytes of RX MIC key data
- * 8 bytes of TX MIC key data
- * 0x0b 32 16 bytes of TKIP key data
- * 8 bytes of RX MIC key data
- * 8 bytes of TX MIC key data
- *
- */
-
-struct acx_set_key {
- /* Ignored for default WEP key */
- u8 addr[ETH_ALEN];
-
- /* key_action_e */
- u16 key_action;
-
- u16 reserved_1;
-
- /* key size in bytes */
- u8 key_size;
-
- /* key_type_e */
- u8 key_type;
- u8 ssid_profile;
-
- /*
- * TKIP, AES: frame's key id field.
- * For WEP default key: key id;
- */
- u8 id;
- u8 reserved_2[6];
- u8 key[MAX_KEY_SIZE];
- u16 ac_seq_num16[NUM_ACCESS_CATEGORIES_COPY];
- u32 ac_seq_num32[NUM_ACCESS_CATEGORIES_COPY];
-} __attribute__ ((packed));
-
struct acx_current_tx_power {
struct acx_header header;
@@ -839,26 +756,6 @@ struct acx_tsf_info {
u8 pad[3];
} __attribute__ ((packed));
-/* 802.11 PS */
-enum acx_ps_mode {
- STATION_ACTIVE_MODE,
- STATION_POWER_SAVE_MODE
-};
-
-struct acx_ps_params {
- u8 ps_mode; /* STATION_* */
- u8 send_null_data; /* Do we have to send NULL data packet ? */
- u8 retries; /* Number of retires for the initial NULL data packet */
-
- /*
- * TUs during which the target stays awake after switching
- * to power save mode.
- */
- u8 hang_over_period;
- u16 null_data_rate;
- u8 pad[2];
-} __attribute__ ((packed));
-
enum acx_wake_up_event {
WAKE_UP_EVENT_BEACON_BITMAP = 0x01, /* Wake on every Beacon*/
WAKE_UP_EVENT_DTIM_BITMAP = 0x02, /* Wake on every DTIM*/
@@ -892,6 +789,7 @@ enum acx_preamble_type {
struct acx_preamble {
struct acx_header header;
+
/*
* When set, the WiLink transmits the frames with a short preamble and
* when cleared, the WiLink transmits the frames with a long preamble.
@@ -1133,6 +1031,150 @@ struct acx_statistics {
struct acx_rxpipe_statistics rxpipe;
} __attribute__ ((packed));
+#define ACX_MAX_RATE_CLASSES 8
+#define ACX_RATE_MASK_UNSPECIFIED 0
+#define ACX_RATE_RETRY_LIMIT 10
+
+struct acx_rate_class {
+ u32 enabled_rates;
+ u8 short_retry_limit;
+ u8 long_retry_limit;
+ u8 aflags;
+ u8 reserved;
+};
+
+struct acx_rate_policy {
+ struct acx_header header;
+
+ u32 rate_class_cnt;
+ struct acx_rate_class rate_class[ACX_MAX_RATE_CLASSES];
+} __attribute__ ((packed));
+
+struct wl1251_acx_memory {
+ __le16 num_stations; /* number of STAs to be supported. */
+ u16 reserved_1;
+
+ /*
+ * Nmber of memory buffers for the RX mem pool.
+ * The actual number may be less if there are
+ * not enough blocks left for the minimum num
+ * of TX ones.
+ */
+ u8 rx_mem_block_num;
+ u8 reserved_2;
+ u8 num_tx_queues; /* From 1 to 16 */
+ u8 host_if_options; /* HOST_IF* */
+ u8 tx_min_mem_block_num;
+ u8 num_ssid_profiles;
+ __le16 debug_buffer_size;
+} __attribute__ ((packed));
+
+
+#define ACX_RX_DESC_MIN 1
+#define ACX_RX_DESC_MAX 127
+#define ACX_RX_DESC_DEF 32
+struct wl1251_acx_rx_queue_config {
+ u8 num_descs;
+ u8 pad;
+ u8 type;
+ u8 priority;
+ __le32 dma_address;
+} __attribute__ ((packed));
+
+#define ACX_TX_DESC_MIN 1
+#define ACX_TX_DESC_MAX 127
+#define ACX_TX_DESC_DEF 16
+struct wl1251_acx_tx_queue_config {
+ u8 num_descs;
+ u8 pad[2];
+ u8 attributes;
+} __attribute__ ((packed));
+
+#define MAX_TX_QUEUE_CONFIGS 5
+#define MAX_TX_QUEUES 4
+struct wl1251_acx_config_memory {
+ struct acx_header header;
+
+ struct wl1251_acx_memory mem_config;
+ struct wl1251_acx_rx_queue_config rx_queue_config;
+ struct wl1251_acx_tx_queue_config tx_queue_config[MAX_TX_QUEUE_CONFIGS];
+} __attribute__ ((packed));
+
+struct wl1251_acx_mem_map {
+ struct acx_header header;
+
+ void *code_start;
+ void *code_end;
+
+ void *wep_defkey_start;
+ void *wep_defkey_end;
+
+ void *sta_table_start;
+ void *sta_table_end;
+
+ void *packet_template_start;
+ void *packet_template_end;
+
+ void *queue_memory_start;
+ void *queue_memory_end;
+
+ void *packet_memory_pool_start;
+ void *packet_memory_pool_end;
+
+ void *debug_buffer1_start;
+ void *debug_buffer1_end;
+
+ void *debug_buffer2_start;
+ void *debug_buffer2_end;
+
+ /* Number of blocks FW allocated for TX packets */
+ u32 num_tx_mem_blocks;
+
+ /* Number of blocks FW allocated for RX packets */
+ u32 num_rx_mem_blocks;
+} __attribute__ ((packed));
+
+/*************************************************************************
+
+ Host Interrupt Register (WiLink -> Host)
+
+**************************************************************************/
+
+/* RX packet is ready in Xfer buffer #0 */
+#define WL1251_ACX_INTR_RX0_DATA BIT(0)
+
+/* TX result(s) are in the TX complete buffer */
+#define WL1251_ACX_INTR_TX_RESULT BIT(1)
+
+/* OBSOLETE */
+#define WL1251_ACX_INTR_TX_XFR BIT(2)
+
+/* RX packet is ready in Xfer buffer #1 */
+#define WL1251_ACX_INTR_RX1_DATA BIT(3)
+
+/* Event was entered to Event MBOX #A */
+#define WL1251_ACX_INTR_EVENT_A BIT(4)
+
+/* Event was entered to Event MBOX #B */
+#define WL1251_ACX_INTR_EVENT_B BIT(5)
+
+/* OBSOLETE */
+#define WL1251_ACX_INTR_WAKE_ON_HOST BIT(6)
+
+/* Trace meassge on MBOX #A */
+#define WL1251_ACX_INTR_TRACE_A BIT(7)
+
+/* Trace meassge on MBOX #B */
+#define WL1251_ACX_INTR_TRACE_B BIT(8)
+
+/* Command processing completion */
+#define WL1251_ACX_INTR_CMD_COMPLETE BIT(9)
+
+/* Init sequence is done */
+#define WL1251_ACX_INTR_INIT_COMPLETE BIT(14)
+
+#define WL1251_ACX_INTR_ALL 0xFFFFFFFF
+
enum {
ACX_WAKE_UP_CONDITIONS = 0x0002,
ACX_MEM_CFG = 0x0003,
@@ -1210,36 +1252,41 @@ enum {
};
-int wl12xx_acx_frame_rates(struct wl12xx *wl, u8 ctrl_rate, u8 ctrl_mod,
+int wl1251_acx_frame_rates(struct wl1251 *wl, u8 ctrl_rate, u8 ctrl_mod,
u8 mgt_rate, u8 mgt_mod);
-int wl12xx_acx_station_id(struct wl12xx *wl);
-int wl12xx_acx_default_key(struct wl12xx *wl, u8 key_id);
-int wl12xx_acx_wake_up_conditions(struct wl12xx *wl, u8 listen_interval);
-int wl12xx_acx_sleep_auth(struct wl12xx *wl, u8 sleep_auth);
-int wl12xx_acx_fw_version(struct wl12xx *wl, char *buf, size_t len);
-int wl12xx_acx_tx_power(struct wl12xx *wl, int power);
-int wl12xx_acx_feature_cfg(struct wl12xx *wl);
-int wl12xx_acx_mem_map(struct wl12xx *wl, void *mem_map, size_t len);
-int wl12xx_acx_data_path_params(struct wl12xx *wl,
+int wl1251_acx_station_id(struct wl1251 *wl);
+int wl1251_acx_default_key(struct wl1251 *wl, u8 key_id);
+int wl1251_acx_wake_up_conditions(struct wl1251 *wl, u8 wake_up_event,
+ u8 listen_interval);
+int wl1251_acx_sleep_auth(struct wl1251 *wl, u8 sleep_auth);
+int wl1251_acx_fw_version(struct wl1251 *wl, char *buf, size_t len);
+int wl1251_acx_tx_power(struct wl1251 *wl, int power);
+int wl1251_acx_feature_cfg(struct wl1251 *wl);
+int wl1251_acx_mem_map(struct wl1251 *wl,
+ struct acx_header *mem_map, size_t len);
+int wl1251_acx_data_path_params(struct wl1251 *wl,
struct acx_data_path_params_resp *data_path);
-int wl12xx_acx_rx_msdu_life_time(struct wl12xx *wl, u32 life_time);
-int wl12xx_acx_rx_config(struct wl12xx *wl, u32 config, u32 filter);
-int wl12xx_acx_pd_threshold(struct wl12xx *wl);
-int wl12xx_acx_slot(struct wl12xx *wl, enum acx_slot_type slot_time);
-int wl12xx_acx_group_address_tbl(struct wl12xx *wl);
-int wl12xx_acx_service_period_timeout(struct wl12xx *wl);
-int wl12xx_acx_rts_threshold(struct wl12xx *wl, u16 rts_threshold);
-int wl12xx_acx_beacon_filter_opt(struct wl12xx *wl);
-int wl12xx_acx_beacon_filter_table(struct wl12xx *wl);
-int wl12xx_acx_sg_enable(struct wl12xx *wl);
-int wl12xx_acx_sg_cfg(struct wl12xx *wl);
-int wl12xx_acx_cca_threshold(struct wl12xx *wl);
-int wl12xx_acx_bcn_dtim_options(struct wl12xx *wl);
-int wl12xx_acx_aid(struct wl12xx *wl, u16 aid);
-int wl12xx_acx_event_mbox_mask(struct wl12xx *wl, u32 event_mask);
-int wl12xx_acx_set_preamble(struct wl12xx *wl, enum acx_preamble_type preamble);
-int wl12xx_acx_cts_protect(struct wl12xx *wl,
+int wl1251_acx_rx_msdu_life_time(struct wl1251 *wl, u32 life_time);
+int wl1251_acx_rx_config(struct wl1251 *wl, u32 config, u32 filter);
+int wl1251_acx_pd_threshold(struct wl1251 *wl);
+int wl1251_acx_slot(struct wl1251 *wl, enum acx_slot_type slot_time);
+int wl1251_acx_group_address_tbl(struct wl1251 *wl);
+int wl1251_acx_service_period_timeout(struct wl1251 *wl);
+int wl1251_acx_rts_threshold(struct wl1251 *wl, u16 rts_threshold);
+int wl1251_acx_beacon_filter_opt(struct wl1251 *wl);
+int wl1251_acx_beacon_filter_table(struct wl1251 *wl);
+int wl1251_acx_sg_enable(struct wl1251 *wl);
+int wl1251_acx_sg_cfg(struct wl1251 *wl);
+int wl1251_acx_cca_threshold(struct wl1251 *wl);
+int wl1251_acx_bcn_dtim_options(struct wl1251 *wl);
+int wl1251_acx_aid(struct wl1251 *wl, u16 aid);
+int wl1251_acx_event_mbox_mask(struct wl1251 *wl, u32 event_mask);
+int wl1251_acx_set_preamble(struct wl1251 *wl, enum acx_preamble_type preamble);
+int wl1251_acx_cts_protect(struct wl1251 *wl,
enum acx_ctsprotect_type ctsprotect);
-int wl12xx_acx_statistics(struct wl12xx *wl, struct acx_statistics *stats);
+int wl1251_acx_statistics(struct wl1251 *wl, struct acx_statistics *stats);
+int wl1251_acx_tsf_info(struct wl1251 *wl, u64 *mactime);
+int wl1251_acx_rate_policies(struct wl1251 *wl);
+int wl1251_acx_mem_cfg(struct wl1251 *wl);
-#endif /* __WL12XX_ACX_H__ */
+#endif /* __WL1251_ACX_H__ */
diff --git a/drivers/net/wireless/wl12xx/wl1251_boot.c b/drivers/net/wireless/wl12xx/wl1251_boot.c
new file mode 100644
index 00000000000..592c3b5cc8f
--- /dev/null
+++ b/drivers/net/wireless/wl12xx/wl1251_boot.c
@@ -0,0 +1,527 @@
+/*
+ * This file is part of wl1251
+ *
+ * Copyright (C) 2008 Nokia Corporation
+ *
+ * Contact: Kalle Valo <kalle.valo@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/gpio.h>
+
+#include "wl1251_reg.h"
+#include "wl1251_boot.h"
+#include "wl1251_io.h"
+#include "wl1251_spi.h"
+#include "wl1251_event.h"
+#include "wl1251_acx.h"
+
+void wl1251_boot_target_enable_interrupts(struct wl1251 *wl)
+{
+ wl1251_reg_write32(wl, ACX_REG_INTERRUPT_MASK, ~(wl->intr_mask));
+ wl1251_reg_write32(wl, HI_CFG, HI_CFG_DEF_VAL);
+}
+
+int wl1251_boot_soft_reset(struct wl1251 *wl)
+{
+ unsigned long timeout;
+ u32 boot_data;
+
+ /* perform soft reset */
+ wl1251_reg_write32(wl, ACX_REG_SLV_SOFT_RESET, ACX_SLV_SOFT_RESET_BIT);
+
+ /* SOFT_RESET is self clearing */
+ timeout = jiffies + usecs_to_jiffies(SOFT_RESET_MAX_TIME);
+ while (1) {
+ boot_data = wl1251_reg_read32(wl, ACX_REG_SLV_SOFT_RESET);
+ wl1251_debug(DEBUG_BOOT, "soft reset bootdata 0x%x", boot_data);
+ if ((boot_data & ACX_SLV_SOFT_RESET_BIT) == 0)
+ break;
+
+ if (time_after(jiffies, timeout)) {
+ /* 1.2 check pWhalBus->uSelfClearTime if the
+ * timeout was reached */
+ wl1251_error("soft reset timeout");
+ return -1;
+ }
+
+ udelay(SOFT_RESET_STALL_TIME);
+ }
+
+ /* disable Rx/Tx */
+ wl1251_reg_write32(wl, ENABLE, 0x0);
+
+ /* disable auto calibration on start*/
+ wl1251_reg_write32(wl, SPARE_A2, 0xffff);
+
+ return 0;
+}
+
+int wl1251_boot_init_seq(struct wl1251 *wl)
+{
+ u32 scr_pad6, init_data, tmp, elp_cmd, ref_freq;
+
+ /*
+ * col #1: INTEGER_DIVIDER
+ * col #2: FRACTIONAL_DIVIDER
+ * col #3: ATTN_BB
+ * col #4: ALPHA_BB
+ * col #5: STOP_TIME_BB
+ * col #6: BB_PLL_LOOP_FILTER
+ */
+ static const u32 LUT[REF_FREQ_NUM][LUT_PARAM_NUM] = {
+
+ { 83, 87381, 0xB, 5, 0xF00, 3}, /* REF_FREQ_19_2*/
+ { 61, 141154, 0xB, 5, 0x1450, 2}, /* REF_FREQ_26_0*/
+ { 41, 174763, 0xC, 6, 0x2D00, 1}, /* REF_FREQ_38_4*/
+ { 40, 0, 0xC, 6, 0x2EE0, 1}, /* REF_FREQ_40_0*/
+ { 47, 162280, 0xC, 6, 0x2760, 1} /* REF_FREQ_33_6 */
+ };
+
+ /* read NVS params */
+ scr_pad6 = wl1251_reg_read32(wl, SCR_PAD6);
+ wl1251_debug(DEBUG_BOOT, "scr_pad6 0x%x", scr_pad6);
+
+ /* read ELP_CMD */
+ elp_cmd = wl1251_reg_read32(wl, ELP_CMD);
+ wl1251_debug(DEBUG_BOOT, "elp_cmd 0x%x", elp_cmd);
+
+ /* set the BB calibration time to be 300 usec (PLL_CAL_TIME) */
+ ref_freq = scr_pad6 & 0x000000FF;
+ wl1251_debug(DEBUG_BOOT, "ref_freq 0x%x", ref_freq);
+
+ wl1251_reg_write32(wl, PLL_CAL_TIME, 0x9);
+
+ /*
+ * PG 1.2: set the clock buffer time to be 210 usec (CLK_BUF_TIME)
+ */
+ wl1251_reg_write32(wl, CLK_BUF_TIME, 0x6);
+
+ /*
+ * set the clock detect feature to work in the restart wu procedure
+ * (ELP_CFG_MODE[14]) and Select the clock source type
+ * (ELP_CFG_MODE[13:12])
+ */
+ tmp = ((scr_pad6 & 0x0000FF00) << 4) | 0x00004000;
+ wl1251_reg_write32(wl, ELP_CFG_MODE, tmp);
+
+ /* PG 1.2: enable the BB PLL fix. Enable the PLL_LIMP_CLK_EN_CMD */
+ elp_cmd |= 0x00000040;
+ wl1251_reg_write32(wl, ELP_CMD, elp_cmd);
+
+ /* PG 1.2: Set the BB PLL stable time to be 1000usec
+ * (PLL_STABLE_TIME) */
+ wl1251_reg_write32(wl, CFG_PLL_SYNC_CNT, 0x20);
+
+ /* PG 1.2: read clock request time */
+ init_data = wl1251_reg_read32(wl, CLK_REQ_TIME);
+
+ /*
+ * PG 1.2: set the clock request time to be ref_clk_settling_time -
+ * 1ms = 4ms
+ */
+ if (init_data > 0x21)
+ tmp = init_data - 0x21;
+ else
+ tmp = 0;
+ wl1251_reg_write32(wl, CLK_REQ_TIME, tmp);
+
+ /* set BB PLL configurations in RF AFE */
+ wl1251_reg_write32(wl, 0x003058cc, 0x4B5);
+
+ /* set RF_AFE_REG_5 */
+ wl1251_reg_write32(wl, 0x003058d4, 0x50);
+
+ /* set RF_AFE_CTRL_REG_2 */
+ wl1251_reg_write32(wl, 0x00305948, 0x11c001);
+
+ /*
+ * change RF PLL and BB PLL divider for VCO clock and adjust VCO
+ * bais current(RF_AFE_REG_13)
+ */
+ wl1251_reg_write32(wl, 0x003058f4, 0x1e);
+
+ /* set BB PLL configurations */
+ tmp = LUT[ref_freq][LUT_PARAM_INTEGER_DIVIDER] | 0x00017000;
+ wl1251_reg_write32(wl, 0x00305840, tmp);
+
+ /* set fractional divider according to Appendix C-BB PLL
+ * Calculations
+ */
+ tmp = LUT[ref_freq][LUT_PARAM_FRACTIONAL_DIVIDER];
+ wl1251_reg_write32(wl, 0x00305844, tmp);
+
+ /* set the initial data for the sigma delta */
+ wl1251_reg_write32(wl, 0x00305848, 0x3039);
+
+ /*
+ * set the accumulator attenuation value, calibration loop1
+ * (alpha), calibration loop2 (beta), calibration loop3 (gamma) and
+ * the VCO gain
+ */
+ tmp = (LUT[ref_freq][LUT_PARAM_ATTN_BB] << 16) |
+ (LUT[ref_freq][LUT_PARAM_ALPHA_BB] << 12) | 0x1;
+ wl1251_reg_write32(wl, 0x00305854, tmp);
+
+ /*
+ * set the calibration stop time after holdoff time expires and set
+ * settling time HOLD_OFF_TIME_BB
+ */
+ tmp = LUT[ref_freq][LUT_PARAM_STOP_TIME_BB] | 0x000A0000;
+ wl1251_reg_write32(wl, 0x00305858, tmp);
+
+ /*
+ * set BB PLL Loop filter capacitor3- BB_C3[2:0] and set BB PLL
+ * constant leakage current to linearize PFD to 0uA -
+ * BB_ILOOPF[7:3]
+ */
+ tmp = LUT[ref_freq][LUT_PARAM_BB_PLL_LOOP_FILTER] | 0x00000030;
+ wl1251_reg_write32(wl, 0x003058f8, tmp);
+
+ /*
+ * set regulator output voltage for n divider to
+ * 1.35-BB_REFDIV[1:0], set charge pump current- BB_CPGAIN[4:2],
+ * set BB PLL Loop filter capacitor2- BB_C2[7:5], set gain of BB
+ * PLL auto-call to normal mode- BB_CALGAIN_3DB[8]
+ */
+ wl1251_reg_write32(wl, 0x003058f0, 0x29);
+
+ /* enable restart wakeup sequence (ELP_CMD[0]) */
+ wl1251_reg_write32(wl, ELP_CMD, elp_cmd | 0x1);
+
+ /* restart sequence completed */
+ udelay(2000);
+
+ return 0;
+}
+
+static void wl1251_boot_set_ecpu_ctrl(struct wl1251 *wl, u32 flag)
+{
+ u32 cpu_ctrl;
+
+ /* 10.5.0 run the firmware (I) */
+ cpu_ctrl = wl1251_reg_read32(wl, ACX_REG_ECPU_CONTROL);
+
+ /* 10.5.1 run the firmware (II) */
+ cpu_ctrl &= ~flag;
+ wl1251_reg_write32(wl, ACX_REG_ECPU_CONTROL, cpu_ctrl);
+}
+
+int wl1251_boot_run_firmware(struct wl1251 *wl)
+{
+ int loop, ret;
+ u32 chip_id, interrupt;
+
+ wl1251_boot_set_ecpu_ctrl(wl, ECPU_CONTROL_HALT);
+
+ chip_id = wl1251_reg_read32(wl, CHIP_ID_B);
+
+ wl1251_debug(DEBUG_BOOT, "chip id after firmware boot: 0x%x", chip_id);
+
+ if (chip_id != wl->chip_id) {
+ wl1251_error("chip id doesn't match after firmware boot");
+ return -EIO;
+ }
+
+ /* wait for init to complete */
+ loop = 0;
+ while (loop++ < INIT_LOOP) {
+ udelay(INIT_LOOP_DELAY);
+ interrupt = wl1251_reg_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR);
+
+ if (interrupt == 0xffffffff) {
+ wl1251_error("error reading hardware complete "
+ "init indication");
+ return -EIO;
+ }
+ /* check that ACX_INTR_INIT_COMPLETE is enabled */
+ else if (interrupt & WL1251_ACX_INTR_INIT_COMPLETE) {
+ wl1251_reg_write32(wl, ACX_REG_INTERRUPT_ACK,
+ WL1251_ACX_INTR_INIT_COMPLETE);
+ break;
+ }
+ }
+
+ if (loop >= INIT_LOOP) {
+ wl1251_error("timeout waiting for the hardware to "
+ "complete initialization");
+ return -EIO;
+ }
+
+ /* get hardware config command mail box */
+ wl->cmd_box_addr = wl1251_reg_read32(wl, REG_COMMAND_MAILBOX_PTR);
+
+ /* get hardware config event mail box */
+ wl->event_box_addr = wl1251_reg_read32(wl, REG_EVENT_MAILBOX_PTR);
+
+ /* set the working partition to its "running" mode offset */
+ wl1251_set_partition(wl, WL1251_PART_WORK_MEM_START,
+ WL1251_PART_WORK_MEM_SIZE,
+ WL1251_PART_WORK_REG_START,
+ WL1251_PART_WORK_REG_SIZE);
+
+ wl1251_debug(DEBUG_MAILBOX, "cmd_box_addr 0x%x event_box_addr 0x%x",
+ wl->cmd_box_addr, wl->event_box_addr);
+
+ wl1251_acx_fw_version(wl, wl->fw_ver, sizeof(wl->fw_ver));
+
+ /*
+ * in case of full asynchronous mode the firmware event must be
+ * ready to receive event from the command mailbox
+ */
+
+ /* enable gpio interrupts */
+ wl1251_enable_interrupts(wl);
+
+ /* Enable target's interrupts */
+ wl->intr_mask = WL1251_ACX_INTR_RX0_DATA |
+ WL1251_ACX_INTR_RX1_DATA |
+ WL1251_ACX_INTR_TX_RESULT |
+ WL1251_ACX_INTR_EVENT_A |
+ WL1251_ACX_INTR_EVENT_B |
+ WL1251_ACX_INTR_INIT_COMPLETE;
+ wl1251_boot_target_enable_interrupts(wl);
+
+ /* unmask all mbox events */
+ wl->event_mask = 0xffffffff;
+
+ ret = wl1251_event_unmask(wl);
+ if (ret < 0) {
+ wl1251_error("EVENT mask setting failed");
+ return ret;
+ }
+
+ wl1251_event_mbox_config(wl);
+
+ /* firmware startup completed */
+ return 0;
+}
+
+static int wl1251_boot_upload_firmware(struct wl1251 *wl)
+{
+ int addr, chunk_num, partition_limit;
+ size_t fw_data_len;
+ u8 *p;
+
+ /* whal_FwCtrl_LoadFwImageSm() */
+
+ wl1251_debug(DEBUG_BOOT, "chip id before fw upload: 0x%x",
+ wl1251_reg_read32(wl, CHIP_ID_B));
+
+ /* 10.0 check firmware length and set partition */
+ fw_data_len = (wl->fw[4] << 24) | (wl->fw[5] << 16) |
+ (wl->fw[6] << 8) | (wl->fw[7]);
+
+ wl1251_debug(DEBUG_BOOT, "fw_data_len %zu chunk_size %d", fw_data_len,
+ CHUNK_SIZE);
+
+ if ((fw_data_len % 4) != 0) {
+ wl1251_error("firmware length not multiple of four");
+ return -EIO;
+ }
+
+ wl1251_set_partition(wl, WL1251_PART_DOWN_MEM_START,
+ WL1251_PART_DOWN_MEM_SIZE,
+ WL1251_PART_DOWN_REG_START,
+ WL1251_PART_DOWN_REG_SIZE);
+
+ /* 10.1 set partition limit and chunk num */
+ chunk_num = 0;
+ partition_limit = WL1251_PART_DOWN_MEM_SIZE;
+
+ while (chunk_num < fw_data_len / CHUNK_SIZE) {
+ /* 10.2 update partition, if needed */
+ addr = WL1251_PART_DOWN_MEM_START +
+ (chunk_num + 2) * CHUNK_SIZE;
+ if (addr > partition_limit) {
+ addr = WL1251_PART_DOWN_MEM_START +
+ chunk_num * CHUNK_SIZE;
+ partition_limit = chunk_num * CHUNK_SIZE +
+ WL1251_PART_DOWN_MEM_SIZE;
+ wl1251_set_partition(wl,
+ addr,
+ WL1251_PART_DOWN_MEM_SIZE,
+ WL1251_PART_DOWN_REG_START,
+ WL1251_PART_DOWN_REG_SIZE);
+ }
+
+ /* 10.3 upload the chunk */
+ addr = WL1251_PART_DOWN_MEM_START + chunk_num * CHUNK_SIZE;
+ p = wl->fw + FW_HDR_SIZE + chunk_num * CHUNK_SIZE;
+ wl1251_debug(DEBUG_BOOT, "uploading fw chunk 0x%p to 0x%x",
+ p, addr);
+ wl1251_mem_write(wl, addr, p, CHUNK_SIZE);
+
+ chunk_num++;
+ }
+
+ /* 10.4 upload the last chunk */
+ addr = WL1251_PART_DOWN_MEM_START + chunk_num * CHUNK_SIZE;
+ p = wl->fw + FW_HDR_SIZE + chunk_num * CHUNK_SIZE;
+ wl1251_debug(DEBUG_BOOT, "uploading fw last chunk (%zu B) 0x%p to 0x%x",
+ fw_data_len % CHUNK_SIZE, p, addr);
+ wl1251_mem_write(wl, addr, p, fw_data_len % CHUNK_SIZE);
+
+ return 0;
+}
+
+static int wl1251_boot_upload_nvs(struct wl1251 *wl)
+{
+ size_t nvs_len, nvs_bytes_written, burst_len;
+ int nvs_start, i;
+ u32 dest_addr, val;
+ u8 *nvs_ptr, *nvs;
+
+ nvs = wl->nvs;
+ if (nvs == NULL)
+ return -ENODEV;
+
+ nvs_ptr = nvs;
+
+ nvs_len = wl->nvs_len;
+ nvs_start = wl->fw_len;
+
+ /*
+ * Layout before the actual NVS tables:
+ * 1 byte : burst length.
+ * 2 bytes: destination address.
+ * n bytes: data to burst copy.
+ *
+ * This is ended by a 0 length, then the NVS tables.
+ */
+
+ while (nvs_ptr[0]) {
+ burst_len = nvs_ptr[0];
+ dest_addr = (nvs_ptr[1] & 0xfe) | ((u32)(nvs_ptr[2] << 8));
+
+ /* We move our pointer to the data */
+ nvs_ptr += 3;
+
+ for (i = 0; i < burst_len; i++) {
+ val = (nvs_ptr[0] | (nvs_ptr[1] << 8)
+ | (nvs_ptr[2] << 16) | (nvs_ptr[3] << 24));
+
+ wl1251_debug(DEBUG_BOOT,
+ "nvs burst write 0x%x: 0x%x",
+ dest_addr, val);
+ wl1251_mem_write32(wl, dest_addr, val);
+
+ nvs_ptr += 4;
+ dest_addr += 4;
+ }
+ }
+
+ /*
+ * We've reached the first zero length, the first NVS table
+ * is 7 bytes further.
+ */
+ nvs_ptr += 7;
+ nvs_len -= nvs_ptr - nvs;
+ nvs_len = ALIGN(nvs_len, 4);
+
+ /* Now we must set the partition correctly */
+ wl1251_set_partition(wl, nvs_start,
+ WL1251_PART_DOWN_MEM_SIZE,
+ WL1251_PART_DOWN_REG_START,
+ WL1251_PART_DOWN_REG_SIZE);
+
+ /* And finally we upload the NVS tables */
+ nvs_bytes_written = 0;
+ while (nvs_bytes_written < nvs_len) {
+ val = (nvs_ptr[0] | (nvs_ptr[1] << 8)
+ | (nvs_ptr[2] << 16) | (nvs_ptr[3] << 24));
+
+ val = cpu_to_le32(val);
+
+ wl1251_debug(DEBUG_BOOT,
+ "nvs write table 0x%x: 0x%x",
+ nvs_start, val);
+ wl1251_mem_write32(wl, nvs_start, val);
+
+ nvs_ptr += 4;
+ nvs_bytes_written += 4;
+ nvs_start += 4;
+ }
+
+ return 0;
+}
+
+int wl1251_boot(struct wl1251 *wl)
+{
+ int ret = 0, minor_minor_e2_ver;
+ u32 tmp, boot_data;
+
+ ret = wl1251_boot_soft_reset(wl);
+ if (ret < 0)
+ goto out;
+
+ /* 2. start processing NVS file */
+ ret = wl1251_boot_upload_nvs(wl);
+ if (ret < 0)
+ goto out;
+
+ /* write firmware's last address (ie. it's length) to
+ * ACX_EEPROMLESS_IND_REG */
+ wl1251_reg_write32(wl, ACX_EEPROMLESS_IND_REG, wl->fw_len);
+
+ /* 6. read the EEPROM parameters */
+ tmp = wl1251_reg_read32(wl, SCR_PAD2);
+
+ /* 7. read bootdata */
+ wl->boot_attr.radio_type = (tmp & 0x0000FF00) >> 8;
+ wl->boot_attr.major = (tmp & 0x00FF0000) >> 16;
+ tmp = wl1251_reg_read32(wl, SCR_PAD3);
+
+ /* 8. check bootdata and call restart sequence */
+ wl->boot_attr.minor = (tmp & 0x00FF0000) >> 16;
+ minor_minor_e2_ver = (tmp & 0xFF000000) >> 24;
+
+ wl1251_debug(DEBUG_BOOT, "radioType 0x%x majorE2Ver 0x%x "
+ "minorE2Ver 0x%x minor_minor_e2_ver 0x%x",
+ wl->boot_attr.radio_type, wl->boot_attr.major,
+ wl->boot_attr.minor, minor_minor_e2_ver);
+
+ ret = wl1251_boot_init_seq(wl);
+ if (ret < 0)
+ goto out;
+
+ /* 9. NVS processing done */
+ boot_data = wl1251_reg_read32(wl, ACX_REG_ECPU_CONTROL);
+
+ wl1251_debug(DEBUG_BOOT, "halt boot_data 0x%x", boot_data);
+
+ /* 10. check that ECPU_CONTROL_HALT bits are set in
+ * pWhalBus->uBootData and start uploading firmware
+ */
+ if ((boot_data & ECPU_CONTROL_HALT) == 0) {
+ wl1251_error("boot failed, ECPU_CONTROL_HALT not set");
+ ret = -EIO;
+ goto out;
+ }
+
+ ret = wl1251_boot_upload_firmware(wl);
+ if (ret < 0)
+ goto out;
+
+ /* 10.5 start firmware */
+ ret = wl1251_boot_run_firmware(wl);
+ if (ret < 0)
+ goto out;
+
+out:
+ return ret;
+}
diff --git a/drivers/net/wireless/wl12xx/boot.h b/drivers/net/wireless/wl12xx/wl1251_boot.h
index 4fa73132baa..90063697e8f 100644
--- a/drivers/net/wireless/wl12xx/boot.h
+++ b/drivers/net/wireless/wl12xx/wl1251_boot.h
@@ -1,5 +1,5 @@
/*
- * This file is part of wl12xx
+ * This file is part of wl1251
*
* Copyright (C) 2008 Nokia Corporation
*
@@ -24,12 +24,13 @@
#ifndef __BOOT_H__
#define __BOOT_H__
-#include "wl12xx.h"
+#include "wl1251.h"
-int wl12xx_boot_soft_reset(struct wl12xx *wl);
-int wl12xx_boot_init_seq(struct wl12xx *wl);
-int wl12xx_boot_run_firmware(struct wl12xx *wl);
-void wl12xx_boot_target_enable_interrupts(struct wl12xx *wl);
+int wl1251_boot_soft_reset(struct wl1251 *wl);
+int wl1251_boot_init_seq(struct wl1251 *wl);
+int wl1251_boot_run_firmware(struct wl1251 *wl);
+void wl1251_boot_target_enable_interrupts(struct wl1251 *wl);
+int wl1251_boot(struct wl1251 *wl);
/* number of times we try to read the INIT interrupt */
#define INIT_LOOP 20000
diff --git a/drivers/net/wireless/wl12xx/wl1251_cmd.c b/drivers/net/wireless/wl12xx/wl1251_cmd.c
new file mode 100644
index 00000000000..770f260726b
--- /dev/null
+++ b/drivers/net/wireless/wl12xx/wl1251_cmd.c
@@ -0,0 +1,412 @@
+#include "wl1251_cmd.h"
+
+#include <linux/module.h>
+#include <linux/crc7.h>
+
+#include "wl1251.h"
+#include "wl1251_reg.h"
+#include "wl1251_io.h"
+#include "wl1251_ps.h"
+#include "wl1251_acx.h"
+
+/**
+ * send command to firmware
+ *
+ * @wl: wl struct
+ * @id: command id
+ * @buf: buffer containing the command, must work with dma
+ * @len: length of the buffer
+ */
+int wl1251_cmd_send(struct wl1251 *wl, u16 id, void *buf, size_t len)
+{
+ struct wl1251_cmd_header *cmd;
+ unsigned long timeout;
+ u32 intr;
+ int ret = 0;
+
+ cmd = buf;
+ cmd->id = id;
+ cmd->status = 0;
+
+ WARN_ON(len % 4 != 0);
+
+ wl1251_mem_write(wl, wl->cmd_box_addr, buf, len);
+
+ wl1251_reg_write32(wl, ACX_REG_INTERRUPT_TRIG, INTR_TRIG_CMD);
+
+ timeout = jiffies + msecs_to_jiffies(WL1251_COMMAND_TIMEOUT);
+
+ intr = wl1251_reg_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR);
+ while (!(intr & WL1251_ACX_INTR_CMD_COMPLETE)) {
+ if (time_after(jiffies, timeout)) {
+ wl1251_error("command complete timeout");
+ ret = -ETIMEDOUT;
+ goto out;
+ }
+
+ msleep(1);
+
+ intr = wl1251_reg_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR);
+ }
+
+ wl1251_reg_write32(wl, ACX_REG_INTERRUPT_ACK,
+ WL1251_ACX_INTR_CMD_COMPLETE);
+
+out:
+ return ret;
+}
+
+/**
+ * send test command to firmware
+ *
+ * @wl: wl struct
+ * @buf: buffer containing the command, with all headers, must work with dma
+ * @len: length of the buffer
+ * @answer: is answer needed
+ */
+int wl1251_cmd_test(struct wl1251 *wl, void *buf, size_t buf_len, u8 answer)
+{
+ int ret;
+
+ wl1251_debug(DEBUG_CMD, "cmd test");
+
+ ret = wl1251_cmd_send(wl, CMD_TEST, buf, buf_len);
+
+ if (ret < 0) {
+ wl1251_warning("TEST command failed");
+ return ret;
+ }
+
+ if (answer) {
+ struct wl1251_command *cmd_answer;
+
+ /*
+ * The test command got in, we can read the answer.
+ * The answer would be a wl1251_command, where the
+ * parameter array contains the actual answer.
+ */
+ wl1251_mem_read(wl, wl->cmd_box_addr, buf, buf_len);
+
+ cmd_answer = buf;
+
+ if (cmd_answer->header.status != CMD_STATUS_SUCCESS)
+ wl1251_error("TEST command answer error: %d",
+ cmd_answer->header.status);
+ }
+
+ return 0;
+}
+
+/**
+ * read acx from firmware
+ *
+ * @wl: wl struct
+ * @id: acx id
+ * @buf: buffer for the response, including all headers, must work with dma
+ * @len: lenght of buf
+ */
+int wl1251_cmd_interrogate(struct wl1251 *wl, u16 id, void *buf, size_t len)
+{
+ struct acx_header *acx = buf;
+ int ret;
+
+ wl1251_debug(DEBUG_CMD, "cmd interrogate");
+
+ acx->id = id;
+
+ /* payload length, does not include any headers */
+ acx->len = len - sizeof(*acx);
+
+ ret = wl1251_cmd_send(wl, CMD_INTERROGATE, acx, sizeof(*acx));
+ if (ret < 0) {
+ wl1251_error("INTERROGATE command failed");
+ goto out;
+ }
+
+ /* the interrogate command got in, we can read the answer */
+ wl1251_mem_read(wl, wl->cmd_box_addr, buf, len);
+
+ acx = buf;
+ if (acx->cmd.status != CMD_STATUS_SUCCESS)
+ wl1251_error("INTERROGATE command error: %d",
+ acx->cmd.status);
+
+out:
+ return ret;
+}
+
+/**
+ * write acx value to firmware
+ *
+ * @wl: wl struct
+ * @id: acx id
+ * @buf: buffer containing acx, including all headers, must work with dma
+ * @len: length of buf
+ */
+int wl1251_cmd_configure(struct wl1251 *wl, u16 id, void *buf, size_t len)
+{
+ struct acx_header *acx = buf;
+ int ret;
+
+ wl1251_debug(DEBUG_CMD, "cmd configure");
+
+ acx->id = id;
+
+ /* payload length, does not include any headers */
+ acx->len = len - sizeof(*acx);
+
+ ret = wl1251_cmd_send(wl, CMD_CONFIGURE, acx, len);
+ if (ret < 0) {
+ wl1251_warning("CONFIGURE command NOK");
+ return ret;
+ }
+
+ return 0;
+}
+
+int wl1251_cmd_vbm(struct wl1251 *wl, u8 identity,
+ void *bitmap, u16 bitmap_len, u8 bitmap_control)
+{
+ struct wl1251_cmd_vbm_update *vbm;
+ int ret;
+
+ wl1251_debug(DEBUG_CMD, "cmd vbm");
+
+ vbm = kzalloc(sizeof(*vbm), GFP_KERNEL);
+ if (!vbm) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ /* Count and period will be filled by the target */
+ vbm->tim.bitmap_ctrl = bitmap_control;
+ if (bitmap_len > PARTIAL_VBM_MAX) {
+ wl1251_warning("cmd vbm len is %d B, truncating to %d",
+ bitmap_len, PARTIAL_VBM_MAX);
+ bitmap_len = PARTIAL_VBM_MAX;
+ }
+ memcpy(vbm->tim.pvb_field, bitmap, bitmap_len);
+ vbm->tim.identity = identity;
+ vbm->tim.length = bitmap_len + 3;
+
+ vbm->len = cpu_to_le16(bitmap_len + 5);
+
+ ret = wl1251_cmd_send(wl, CMD_VBM, vbm, sizeof(*vbm));
+ if (ret < 0) {
+ wl1251_error("VBM command failed");
+ goto out;
+ }
+
+out:
+ kfree(vbm);
+ return 0;
+}
+
+int wl1251_cmd_data_path(struct wl1251 *wl, u8 channel, bool enable)
+{
+ struct cmd_enabledisable_path *cmd;
+ int ret;
+ u16 cmd_rx, cmd_tx;
+
+ wl1251_debug(DEBUG_CMD, "cmd data path");
+
+ cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+ if (!cmd) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ cmd->channel = channel;
+
+ if (enable) {
+ cmd_rx = CMD_ENABLE_RX;
+ cmd_tx = CMD_ENABLE_TX;
+ } else {
+ cmd_rx = CMD_DISABLE_RX;
+ cmd_tx = CMD_DISABLE_TX;
+ }
+
+ ret = wl1251_cmd_send(wl, cmd_rx, cmd, sizeof(*cmd));
+ if (ret < 0) {
+ wl1251_error("rx %s cmd for channel %d failed",
+ enable ? "start" : "stop", channel);
+ goto out;
+ }
+
+ wl1251_debug(DEBUG_BOOT, "rx %s cmd channel %d",
+ enable ? "start" : "stop", channel);
+
+ ret = wl1251_cmd_send(wl, cmd_tx, cmd, sizeof(*cmd));
+ if (ret < 0) {
+ wl1251_error("tx %s cmd for channel %d failed",
+ enable ? "start" : "stop", channel);
+ return ret;
+ }
+
+ wl1251_debug(DEBUG_BOOT, "tx %s cmd channel %d",
+ enable ? "start" : "stop", channel);
+
+out:
+ kfree(cmd);
+ return ret;
+}
+
+int wl1251_cmd_join(struct wl1251 *wl, u8 bss_type, u8 channel,
+ u16 beacon_interval, u8 dtim_interval)
+{
+ struct cmd_join *join;
+ int ret, i;
+ u8 *bssid;
+
+ join = kzalloc(sizeof(*join), GFP_KERNEL);
+ if (!join) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ wl1251_debug(DEBUG_CMD, "cmd join%s ch %d %d/%d",
+ bss_type == BSS_TYPE_IBSS ? " ibss" : "",
+ channel, beacon_interval, dtim_interval);
+
+ /* Reverse order BSSID */
+ bssid = (u8 *) &join->bssid_lsb;
+ for (i = 0; i < ETH_ALEN; i++)
+ bssid[i] = wl->bssid[ETH_ALEN - i - 1];
+
+ join->rx_config_options = wl->rx_config;
+ join->rx_filter_options = wl->rx_filter;
+
+ /*
+ * FIXME: disable temporarily all filters because after commit
+ * 9cef8737 "mac80211: fix managed mode BSSID handling" broke
+ * association. The filter logic needs to be implemented properly
+ * and once that is done, this hack can be removed.
+ */
+ join->rx_config_options = 0;
+ join->rx_filter_options = WL1251_DEFAULT_RX_FILTER;
+
+ join->basic_rate_set = RATE_MASK_1MBPS | RATE_MASK_2MBPS |
+ RATE_MASK_5_5MBPS | RATE_MASK_11MBPS;
+
+ join->beacon_interval = beacon_interval;
+ join->dtim_interval = dtim_interval;
+ join->bss_type = bss_type;
+ join->channel = channel;
+ join->ctrl = JOIN_CMD_CTRL_TX_FLUSH;
+
+ ret = wl1251_cmd_send(wl, CMD_START_JOIN, join, sizeof(*join));
+ if (ret < 0) {
+ wl1251_error("failed to initiate cmd join");
+ goto out;
+ }
+
+out:
+ kfree(join);
+ return ret;
+}
+
+int wl1251_cmd_ps_mode(struct wl1251 *wl, u8 ps_mode)
+{
+ struct wl1251_cmd_ps_params *ps_params = NULL;
+ int ret = 0;
+
+ wl1251_debug(DEBUG_CMD, "cmd set ps mode");
+
+ ps_params = kzalloc(sizeof(*ps_params), GFP_KERNEL);
+ if (!ps_params) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ ps_params->ps_mode = ps_mode;
+ ps_params->send_null_data = 1;
+ ps_params->retries = 5;
+ ps_params->hang_over_period = 128;
+ ps_params->null_data_rate = 1; /* 1 Mbps */
+
+ ret = wl1251_cmd_send(wl, CMD_SET_PS_MODE, ps_params,
+ sizeof(*ps_params));
+ if (ret < 0) {
+ wl1251_error("cmd set_ps_mode failed");
+ goto out;
+ }
+
+out:
+ kfree(ps_params);
+ return ret;
+}
+
+int wl1251_cmd_read_memory(struct wl1251 *wl, u32 addr, void *answer,
+ size_t len)
+{
+ struct cmd_read_write_memory *cmd;
+ int ret = 0;
+
+ wl1251_debug(DEBUG_CMD, "cmd read memory");
+
+ cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+ if (!cmd) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ WARN_ON(len > MAX_READ_SIZE);
+ len = min_t(size_t, len, MAX_READ_SIZE);
+
+ cmd->addr = addr;
+ cmd->size = len;
+
+ ret = wl1251_cmd_send(wl, CMD_READ_MEMORY, cmd, sizeof(*cmd));
+ if (ret < 0) {
+ wl1251_error("read memory command failed: %d", ret);
+ goto out;
+ }
+
+ /* the read command got in, we can now read the answer */
+ wl1251_mem_read(wl, wl->cmd_box_addr, cmd, sizeof(*cmd));
+
+ if (cmd->header.status != CMD_STATUS_SUCCESS)
+ wl1251_error("error in read command result: %d",
+ cmd->header.status);
+
+ memcpy(answer, cmd->value, len);
+
+out:
+ kfree(cmd);
+ return ret;
+}
+
+int wl1251_cmd_template_set(struct wl1251 *wl, u16 cmd_id,
+ void *buf, size_t buf_len)
+{
+ struct wl1251_cmd_packet_template *cmd;
+ size_t cmd_len;
+ int ret = 0;
+
+ wl1251_debug(DEBUG_CMD, "cmd template %d", cmd_id);
+
+ WARN_ON(buf_len > WL1251_MAX_TEMPLATE_SIZE);
+ buf_len = min_t(size_t, buf_len, WL1251_MAX_TEMPLATE_SIZE);
+ cmd_len = ALIGN(sizeof(*cmd) + buf_len, 4);
+
+ cmd = kzalloc(cmd_len, GFP_KERNEL);
+ if (!cmd) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ cmd->size = cpu_to_le16(buf_len);
+
+ if (buf)
+ memcpy(cmd->data, buf, buf_len);
+
+ ret = wl1251_cmd_send(wl, cmd_id, cmd, cmd_len);
+ if (ret < 0) {
+ wl1251_warning("cmd set_template failed: %d", ret);
+ goto out;
+ }
+
+out:
+ kfree(cmd);
+ return ret;
+}
diff --git a/drivers/net/wireless/wl12xx/cmd.h b/drivers/net/wireless/wl12xx/wl1251_cmd.h
index aa307dcd081..dff798ad0ef 100644
--- a/drivers/net/wireless/wl12xx/cmd.h
+++ b/drivers/net/wireless/wl12xx/wl1251_cmd.h
@@ -1,5 +1,5 @@
/*
- * This file is part of wl12xx
+ * This file is part of wl1251
*
* Copyright (c) 1998-2007 Texas Instruments Incorporated
* Copyright (C) 2008 Nokia Corporation
@@ -22,37 +22,32 @@
*
*/
-#ifndef __WL12XX_CMD_H__
-#define __WL12XX_CMD_H__
+#ifndef __WL1251_CMD_H__
+#define __WL1251_CMD_H__
-#include "wl12xx.h"
+#include "wl1251.h"
-int wl12xx_cmd_send(struct wl12xx *wl, u16 type, void *buf, size_t buf_len);
-int wl12xx_cmd_test(struct wl12xx *wl, void *buf, size_t buf_len, u8 answer);
-int wl12xx_cmd_interrogate(struct wl12xx *wl, u16 ie_id, u16 ie_len,
- void *answer);
-int wl12xx_cmd_configure(struct wl12xx *wl, void *ie, int ie_len);
-int wl12xx_cmd_vbm(struct wl12xx *wl, u8 identity,
+struct acx_header;
+
+int wl1251_cmd_send(struct wl1251 *wl, u16 type, void *buf, size_t buf_len);
+int wl1251_cmd_test(struct wl1251 *wl, void *buf, size_t buf_len, u8 answer);
+int wl1251_cmd_interrogate(struct wl1251 *wl, u16 id, void *buf, size_t len);
+int wl1251_cmd_configure(struct wl1251 *wl, u16 id, void *buf, size_t len);
+int wl1251_cmd_vbm(struct wl1251 *wl, u8 identity,
void *bitmap, u16 bitmap_len, u8 bitmap_control);
-int wl12xx_cmd_data_path(struct wl12xx *wl, u8 channel, u8 enable);
-int wl12xx_cmd_join(struct wl12xx *wl, u8 bss_type, u8 dtim_interval,
- u16 beacon_interval, u8 wait);
-int wl12xx_cmd_ps_mode(struct wl12xx *wl, u8 ps_mode);
-int wl12xx_cmd_read_memory(struct wl12xx *wl, u32 addr, u32 len, void *answer);
-int wl12xx_cmd_template_set(struct wl12xx *wl, u16 cmd_id,
+int wl1251_cmd_data_path(struct wl1251 *wl, u8 channel, bool enable);
+int wl1251_cmd_join(struct wl1251 *wl, u8 bss_type, u8 channel,
+ u16 beacon_interval, u8 dtim_interval);
+int wl1251_cmd_ps_mode(struct wl1251 *wl, u8 ps_mode);
+int wl1251_cmd_read_memory(struct wl1251 *wl, u32 addr, void *answer,
+ size_t len);
+int wl1251_cmd_template_set(struct wl1251 *wl, u16 cmd_id,
void *buf, size_t buf_len);
/* unit ms */
-#define WL12XX_COMMAND_TIMEOUT 2000
-
-#define WL12XX_MAX_TEMPLATE_SIZE 300
+#define WL1251_COMMAND_TIMEOUT 2000
-struct wl12xx_cmd_packet_template {
- __le16 size;
- u8 template[WL12XX_MAX_TEMPLATE_SIZE];
-} __attribute__ ((packed));
-
-enum wl12xx_commands {
+enum wl1251_commands {
CMD_RESET = 0,
CMD_INTERROGATE = 1, /*use this to read information elements*/
CMD_CONFIGURE = 2, /*use this to write information elements*/
@@ -100,9 +95,15 @@ enum wl12xx_commands {
#define MAX_CMD_PARAMS 572
-struct wl12xx_command {
+struct wl1251_cmd_header {
u16 id;
u16 status;
+ /* payload */
+ u8 data[0];
+} __attribute__ ((packed));
+
+struct wl1251_command {
+ struct wl1251_cmd_header header;
u8 parameters[MAX_CMD_PARAMS];
};
@@ -144,6 +145,8 @@ enum {
#define MAX_READ_SIZE 256
struct cmd_read_write_memory {
+ struct wl1251_cmd_header header;
+
/* The address of the memory to read from or write to.*/
u32 addr;
@@ -211,6 +214,8 @@ struct basic_scan_channel_parameters {
#define SCAN_MAX_NUM_OF_CHANNELS 16
struct cmd_scan {
+ struct wl1251_cmd_header header;
+
struct basic_scan_parameters params;
struct basic_scan_channel_parameters channels[SCAN_MAX_NUM_OF_CHANNELS];
} __attribute__ ((packed));
@@ -227,6 +232,8 @@ enum {
struct cmd_join {
+ struct wl1251_cmd_header header;
+
u32 bssid_lsb;
u16 bssid_msb;
u16 beacon_interval; /* in TBTTs */
@@ -261,5 +268,140 @@ struct cmd_join {
u8 reserved;
} __attribute__ ((packed));
+struct cmd_enabledisable_path {
+ struct wl1251_cmd_header header;
+
+ u8 channel;
+ u8 padding[3];
+} __attribute__ ((packed));
+
+#define WL1251_MAX_TEMPLATE_SIZE 300
+
+struct wl1251_cmd_packet_template {
+ struct wl1251_cmd_header header;
+
+ __le16 size;
+ u8 data[0];
+} __attribute__ ((packed));
+
+#define TIM_ELE_ID 5
+#define PARTIAL_VBM_MAX 251
+
+struct wl1251_tim {
+ u8 identity;
+ u8 length;
+ u8 dtim_count;
+ u8 dtim_period;
+ u8 bitmap_ctrl;
+ u8 pvb_field[PARTIAL_VBM_MAX]; /* Partial Virtual Bitmap */
+} __attribute__ ((packed));
+
+/* Virtual Bit Map update */
+struct wl1251_cmd_vbm_update {
+ struct wl1251_cmd_header header;
+ __le16 len;
+ u8 padding[2];
+ struct wl1251_tim tim;
+} __attribute__ ((packed));
+
+enum wl1251_cmd_ps_mode {
+ STATION_ACTIVE_MODE,
+ STATION_POWER_SAVE_MODE
+};
+
+struct wl1251_cmd_ps_params {
+ struct wl1251_cmd_header header;
+
+ u8 ps_mode; /* STATION_* */
+ u8 send_null_data; /* Do we have to send NULL data packet ? */
+ u8 retries; /* Number of retires for the initial NULL data packet */
+
+ /*
+ * TUs during which the target stays awake after switching
+ * to power save mode.
+ */
+ u8 hang_over_period;
+ u16 null_data_rate;
+ u8 pad[2];
+} __attribute__ ((packed));
+
+struct wl1251_cmd_trigger_scan_to {
+ struct wl1251_cmd_header header;
+
+ u32 timeout;
+};
+
+/* HW encryption keys */
+#define NUM_ACCESS_CATEGORIES_COPY 4
+#define MAX_KEY_SIZE 32
+
+/* When set, disable HW encryption */
+#define DF_ENCRYPTION_DISABLE 0x01
+/* When set, disable HW decryption */
+#define DF_SNIFF_MODE_ENABLE 0x80
+
+enum wl1251_cmd_key_action {
+ KEY_ADD_OR_REPLACE = 1,
+ KEY_REMOVE = 2,
+ KEY_SET_ID = 3,
+ MAX_KEY_ACTION = 0xffff,
+};
+
+enum wl1251_cmd_key_type {
+ KEY_WEP_DEFAULT = 0,
+ KEY_WEP_ADDR = 1,
+ KEY_AES_GROUP = 4,
+ KEY_AES_PAIRWISE = 5,
+ KEY_WEP_GROUP = 6,
+ KEY_TKIP_MIC_GROUP = 10,
+ KEY_TKIP_MIC_PAIRWISE = 11,
+};
+
+/*
+ *
+ * key_type_e key size key format
+ * ---------- --------- ----------
+ * 0x00 5, 13, 29 Key data
+ * 0x01 5, 13, 29 Key data
+ * 0x04 16 16 bytes of key data
+ * 0x05 16 16 bytes of key data
+ * 0x0a 32 16 bytes of TKIP key data
+ * 8 bytes of RX MIC key data
+ * 8 bytes of TX MIC key data
+ * 0x0b 32 16 bytes of TKIP key data
+ * 8 bytes of RX MIC key data
+ * 8 bytes of TX MIC key data
+ *
+ */
+
+struct wl1251_cmd_set_keys {
+ struct wl1251_cmd_header header;
+
+ /* Ignored for default WEP key */
+ u8 addr[ETH_ALEN];
+
+ /* key_action_e */
+ u16 key_action;
+
+ u16 reserved_1;
+
+ /* key size in bytes */
+ u8 key_size;
+
+ /* key_type_e */
+ u8 key_type;
+ u8 ssid_profile;
+
+ /*
+ * TKIP, AES: frame's key id field.
+ * For WEP default key: key id;
+ */
+ u8 id;
+ u8 reserved_2[6];
+ u8 key[MAX_KEY_SIZE];
+ u16 ac_seq_num16[NUM_ACCESS_CATEGORIES_COPY];
+ u32 ac_seq_num32[NUM_ACCESS_CATEGORIES_COPY];
+} __attribute__ ((packed));
+
-#endif /* __WL12XX_CMD_H__ */
+#endif /* __WL1251_CMD_H__ */
diff --git a/drivers/net/wireless/wl12xx/debugfs.c b/drivers/net/wireless/wl12xx/wl1251_debugfs.c
index cdb368ce4da..a00723059f8 100644
--- a/drivers/net/wireless/wl12xx/debugfs.c
+++ b/drivers/net/wireless/wl12xx/wl1251_debugfs.c
@@ -1,5 +1,5 @@
/*
- * This file is part of wl12xx
+ * This file is part of wl1251
*
* Copyright (C) 2009 Nokia Corporation
*
@@ -21,15 +21,16 @@
*
*/
-#include "debugfs.h"
+#include "wl1251_debugfs.h"
#include <linux/skbuff.h>
-#include "wl12xx.h"
-#include "acx.h"
+#include "wl1251.h"
+#include "wl1251_acx.h"
+#include "wl1251_ps.h"
/* ms */
-#define WL12XX_DEBUGFS_STATS_LIFETIME 1000
+#define WL1251_DEBUGFS_STATS_LIFETIME 1000
/* debugfs macros idea from mac80211 */
@@ -37,7 +38,7 @@
static ssize_t name## _read(struct file *file, char __user *userbuf, \
size_t count, loff_t *ppos) \
{ \
- struct wl12xx *wl = file->private_data; \
+ struct wl1251 *wl = file->private_data; \
char buf[buflen]; \
int res; \
\
@@ -47,7 +48,7 @@ static ssize_t name## _read(struct file *file, char __user *userbuf, \
\
static const struct file_operations name## _ops = { \
.read = name## _read, \
- .open = wl12xx_open_file_generic, \
+ .open = wl1251_open_file_generic, \
};
#define DEBUGFS_ADD(name, parent) \
@@ -70,11 +71,11 @@ static ssize_t sub## _ ##name## _read(struct file *file, \
char __user *userbuf, \
size_t count, loff_t *ppos) \
{ \
- struct wl12xx *wl = file->private_data; \
+ struct wl1251 *wl = file->private_data; \
char buf[buflen]; \
int res; \
\
- wl12xx_debugfs_update_stats(wl); \
+ wl1251_debugfs_update_stats(wl); \
\
res = scnprintf(buf, buflen, fmt "\n", \
wl->stats.fw_stats->sub.name); \
@@ -83,7 +84,7 @@ static ssize_t sub## _ ##name## _read(struct file *file, \
\
static const struct file_operations sub## _ ##name## _ops = { \
.read = sub## _ ##name## _read, \
- .open = wl12xx_open_file_generic, \
+ .open = wl1251_open_file_generic, \
};
#define DEBUGFS_FWSTATS_ADD(sub, name) \
@@ -92,21 +93,30 @@ static const struct file_operations sub## _ ##name## _ops = { \
#define DEBUGFS_FWSTATS_DEL(sub, name) \
DEBUGFS_DEL(sub## _ ##name)
-static void wl12xx_debugfs_update_stats(struct wl12xx *wl)
+static void wl1251_debugfs_update_stats(struct wl1251 *wl)
{
+ int ret;
+
mutex_lock(&wl->mutex);
- if (wl->state == WL12XX_STATE_ON &&
+ ret = wl1251_ps_elp_wakeup(wl);
+ if (ret < 0)
+ goto out;
+
+ if (wl->state == WL1251_STATE_ON &&
time_after(jiffies, wl->stats.fw_stats_update +
- msecs_to_jiffies(WL12XX_DEBUGFS_STATS_LIFETIME))) {
- wl12xx_acx_statistics(wl, wl->stats.fw_stats);
+ msecs_to_jiffies(WL1251_DEBUGFS_STATS_LIFETIME))) {
+ wl1251_acx_statistics(wl, wl->stats.fw_stats);
wl->stats.fw_stats_update = jiffies;
}
+ wl1251_ps_elp_sleep(wl);
+
+out:
mutex_unlock(&wl->mutex);
}
-static int wl12xx_open_file_generic(struct inode *inode, struct file *file)
+static int wl1251_open_file_generic(struct inode *inode, struct file *file)
{
file->private_data = inode->i_private;
return 0;
@@ -211,7 +221,7 @@ DEBUGFS_READONLY_FILE(excessive_retries, 20, "%u",
static ssize_t tx_queue_len_read(struct file *file, char __user *userbuf,
size_t count, loff_t *ppos)
{
- struct wl12xx *wl = file->private_data;
+ struct wl1251 *wl = file->private_data;
u32 queue_len;
char buf[20];
int res;
@@ -224,10 +234,10 @@ static ssize_t tx_queue_len_read(struct file *file, char __user *userbuf,
static const struct file_operations tx_queue_len_ops = {
.read = tx_queue_len_read,
- .open = wl12xx_open_file_generic,
+ .open = wl1251_open_file_generic,
};
-static void wl12xx_debugfs_delete_files(struct wl12xx *wl)
+static void wl1251_debugfs_delete_files(struct wl1251 *wl)
{
DEBUGFS_FWSTATS_DEL(tx, internal_desc_overflow);
@@ -325,7 +335,7 @@ static void wl12xx_debugfs_delete_files(struct wl12xx *wl)
DEBUGFS_DEL(excessive_retries);
}
-static int wl12xx_debugfs_add_files(struct wl12xx *wl)
+static int wl1251_debugfs_add_files(struct wl1251 *wl)
{
int ret = 0;
@@ -426,19 +436,19 @@ static int wl12xx_debugfs_add_files(struct wl12xx *wl)
out:
if (ret < 0)
- wl12xx_debugfs_delete_files(wl);
+ wl1251_debugfs_delete_files(wl);
return ret;
}
-void wl12xx_debugfs_reset(struct wl12xx *wl)
+void wl1251_debugfs_reset(struct wl1251 *wl)
{
memset(wl->stats.fw_stats, 0, sizeof(*wl->stats.fw_stats));
wl->stats.retry_count = 0;
wl->stats.excessive_retries = 0;
}
-int wl12xx_debugfs_init(struct wl12xx *wl)
+int wl1251_debugfs_init(struct wl1251 *wl)
{
int ret;
@@ -469,7 +479,7 @@ int wl12xx_debugfs_init(struct wl12xx *wl)
wl->stats.fw_stats_update = jiffies;
- ret = wl12xx_debugfs_add_files(wl);
+ ret = wl1251_debugfs_add_files(wl);
if (ret < 0)
goto err_file;
@@ -492,9 +502,9 @@ err:
return ret;
}
-void wl12xx_debugfs_exit(struct wl12xx *wl)
+void wl1251_debugfs_exit(struct wl1251 *wl)
{
- wl12xx_debugfs_delete_files(wl);
+ wl1251_debugfs_delete_files(wl);
kfree(wl->stats.fw_stats);
wl->stats.fw_stats = NULL;
diff --git a/drivers/net/wireless/wl12xx/debugfs.h b/drivers/net/wireless/wl12xx/wl1251_debugfs.h
index 562cdcbcc87..6dc3d080853 100644
--- a/drivers/net/wireless/wl12xx/debugfs.h
+++ b/drivers/net/wireless/wl12xx/wl1251_debugfs.h
@@ -1,5 +1,5 @@
/*
- * This file is part of wl12xx
+ * This file is part of wl1251
*
* Copyright (C) 2009 Nokia Corporation
*
@@ -21,13 +21,13 @@
*
*/
-#ifndef WL12XX_DEBUGFS_H
-#define WL12XX_DEBUGFS_H
+#ifndef WL1251_DEBUGFS_H
+#define WL1251_DEBUGFS_H
-#include "wl12xx.h"
+#include "wl1251.h"
-int wl12xx_debugfs_init(struct wl12xx *wl);
-void wl12xx_debugfs_exit(struct wl12xx *wl);
-void wl12xx_debugfs_reset(struct wl12xx *wl);
+int wl1251_debugfs_init(struct wl1251 *wl);
+void wl1251_debugfs_exit(struct wl1251 *wl);
+void wl1251_debugfs_reset(struct wl1251 *wl);
-#endif /* WL12XX_DEBUGFS_H */
+#endif /* WL1251_DEBUGFS_H */
diff --git a/drivers/net/wireless/wl12xx/event.c b/drivers/net/wireless/wl12xx/wl1251_event.c
index 99529ca89a7..00076c4a8a2 100644
--- a/drivers/net/wireless/wl12xx/event.c
+++ b/drivers/net/wireless/wl12xx/wl1251_event.c
@@ -1,5 +1,5 @@
/*
- * This file is part of wl12xx
+ * This file is part of wl1251
*
* Copyright (c) 1998-2007 Texas Instruments Incorporated
* Copyright (C) 2008 Nokia Corporation
@@ -22,16 +22,16 @@
*
*/
-#include "wl12xx.h"
-#include "reg.h"
-#include "spi.h"
-#include "event.h"
-#include "ps.h"
+#include "wl1251.h"
+#include "wl1251_reg.h"
+#include "wl1251_io.h"
+#include "wl1251_event.h"
+#include "wl1251_ps.h"
-static int wl12xx_event_scan_complete(struct wl12xx *wl,
+static int wl1251_event_scan_complete(struct wl1251 *wl,
struct event_mailbox *mbox)
{
- wl12xx_debug(DEBUG_EVENT, "status: 0x%x, channels: %d",
+ wl1251_debug(DEBUG_EVENT, "status: 0x%x, channels: %d",
mbox->scheduled_scan_status,
mbox->scheduled_scan_channels);
@@ -39,40 +39,41 @@ static int wl12xx_event_scan_complete(struct wl12xx *wl,
mutex_unlock(&wl->mutex);
ieee80211_scan_completed(wl->hw, false);
mutex_lock(&wl->mutex);
+ wl1251_debug(DEBUG_MAC80211, "mac80211 hw scan completed");
wl->scanning = false;
}
return 0;
}
-static void wl12xx_event_mbox_dump(struct event_mailbox *mbox)
+static void wl1251_event_mbox_dump(struct event_mailbox *mbox)
{
- wl12xx_debug(DEBUG_EVENT, "MBOX DUMP:");
- wl12xx_debug(DEBUG_EVENT, "\tvector: 0x%x", mbox->events_vector);
- wl12xx_debug(DEBUG_EVENT, "\tmask: 0x%x", mbox->events_mask);
+ wl1251_debug(DEBUG_EVENT, "MBOX DUMP:");
+ wl1251_debug(DEBUG_EVENT, "\tvector: 0x%x", mbox->events_vector);
+ wl1251_debug(DEBUG_EVENT, "\tmask: 0x%x", mbox->events_mask);
}
-static int wl12xx_event_process(struct wl12xx *wl, struct event_mailbox *mbox)
+static int wl1251_event_process(struct wl1251 *wl, struct event_mailbox *mbox)
{
int ret;
u32 vector;
- wl12xx_event_mbox_dump(mbox);
+ wl1251_event_mbox_dump(mbox);
vector = mbox->events_vector & ~(mbox->events_mask);
- wl12xx_debug(DEBUG_EVENT, "vector: 0x%x", vector);
+ wl1251_debug(DEBUG_EVENT, "vector: 0x%x", vector);
if (vector & SCAN_COMPLETE_EVENT_ID) {
- ret = wl12xx_event_scan_complete(wl, mbox);
+ ret = wl1251_event_scan_complete(wl, mbox);
if (ret < 0)
return ret;
}
if (vector & BSS_LOSE_EVENT_ID) {
- wl12xx_debug(DEBUG_EVENT, "BSS_LOSE_EVENT");
+ wl1251_debug(DEBUG_EVENT, "BSS_LOSE_EVENT");
if (wl->psm_requested && wl->psm) {
- ret = wl12xx_ps_set_mode(wl, STATION_ACTIVE_MODE);
+ ret = wl1251_ps_set_mode(wl, STATION_ACTIVE_MODE);
if (ret < 0)
return ret;
}
@@ -81,47 +82,47 @@ static int wl12xx_event_process(struct wl12xx *wl, struct event_mailbox *mbox)
return 0;
}
-int wl12xx_event_unmask(struct wl12xx *wl)
+int wl1251_event_unmask(struct wl1251 *wl)
{
int ret;
- ret = wl12xx_acx_event_mbox_mask(wl, ~(wl->event_mask));
+ ret = wl1251_acx_event_mbox_mask(wl, ~(wl->event_mask));
if (ret < 0)
return ret;
return 0;
}
-void wl12xx_event_mbox_config(struct wl12xx *wl)
+void wl1251_event_mbox_config(struct wl1251 *wl)
{
- wl->mbox_ptr[0] = wl12xx_reg_read32(wl, REG_EVENT_MAILBOX_PTR);
+ wl->mbox_ptr[0] = wl1251_reg_read32(wl, REG_EVENT_MAILBOX_PTR);
wl->mbox_ptr[1] = wl->mbox_ptr[0] + sizeof(struct event_mailbox);
- wl12xx_debug(DEBUG_EVENT, "MBOX ptrs: 0x%x 0x%x",
+ wl1251_debug(DEBUG_EVENT, "MBOX ptrs: 0x%x 0x%x",
wl->mbox_ptr[0], wl->mbox_ptr[1]);
}
-int wl12xx_event_handle(struct wl12xx *wl, u8 mbox_num)
+int wl1251_event_handle(struct wl1251 *wl, u8 mbox_num)
{
struct event_mailbox mbox;
int ret;
- wl12xx_debug(DEBUG_EVENT, "EVENT on mbox %d", mbox_num);
+ wl1251_debug(DEBUG_EVENT, "EVENT on mbox %d", mbox_num);
if (mbox_num > 1)
return -EINVAL;
/* first we read the mbox descriptor */
- wl12xx_spi_mem_read(wl, wl->mbox_ptr[mbox_num], &mbox,
+ wl1251_mem_read(wl, wl->mbox_ptr[mbox_num], &mbox,
sizeof(struct event_mailbox));
/* process the descriptor */
- ret = wl12xx_event_process(wl, &mbox);
+ ret = wl1251_event_process(wl, &mbox);
if (ret < 0)
return ret;
/* then we let the firmware know it can go on...*/
- wl12xx_reg_write32(wl, ACX_REG_INTERRUPT_TRIG, INTR_TRIG_EVENT_ACK);
+ wl1251_reg_write32(wl, ACX_REG_INTERRUPT_TRIG, INTR_TRIG_EVENT_ACK);
return 0;
}
diff --git a/drivers/net/wireless/wl12xx/event.h b/drivers/net/wireless/wl12xx/wl1251_event.h
index 1f4c2f7438a..be0ac54d624 100644
--- a/drivers/net/wireless/wl12xx/event.h
+++ b/drivers/net/wireless/wl12xx/wl1251_event.h
@@ -1,5 +1,5 @@
/*
- * This file is part of wl12xx
+ * This file is part of wl1251
*
* Copyright (c) 1998-2007 Texas Instruments Incorporated
* Copyright (C) 2008 Nokia Corporation
@@ -22,8 +22,8 @@
*
*/
-#ifndef __WL12XX_EVENT_H__
-#define __WL12XX_EVENT_H__
+#ifndef __WL1251_EVENT_H__
+#define __WL1251_EVENT_H__
/*
* Mbox events
@@ -114,8 +114,8 @@ struct event_mailbox {
u8 padding[19];
} __attribute__ ((packed));
-int wl12xx_event_unmask(struct wl12xx *wl);
-void wl12xx_event_mbox_config(struct wl12xx *wl);
-int wl12xx_event_handle(struct wl12xx *wl, u8 mbox);
+int wl1251_event_unmask(struct wl1251 *wl);
+void wl1251_event_mbox_config(struct wl1251 *wl);
+int wl1251_event_handle(struct wl1251 *wl, u8 mbox);
#endif
diff --git a/drivers/net/wireless/wl12xx/wl1251_init.c b/drivers/net/wireless/wl12xx/wl1251_init.c
new file mode 100644
index 00000000000..b2ee4f468fc
--- /dev/null
+++ b/drivers/net/wireless/wl12xx/wl1251_init.c
@@ -0,0 +1,413 @@
+/*
+ * This file is part of wl1251
+ *
+ * Copyright (C) 2009 Nokia Corporation
+ *
+ * Contact: Kalle Valo <kalle.valo@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+
+#include "wl1251_init.h"
+#include "wl12xx_80211.h"
+#include "wl1251_acx.h"
+#include "wl1251_cmd.h"
+#include "wl1251_reg.h"
+
+int wl1251_hw_init_hwenc_config(struct wl1251 *wl)
+{
+ int ret;
+
+ ret = wl1251_acx_feature_cfg(wl);
+ if (ret < 0) {
+ wl1251_warning("couldn't set feature config");
+ return ret;
+ }
+
+ ret = wl1251_acx_default_key(wl, wl->default_key);
+ if (ret < 0) {
+ wl1251_warning("couldn't set default key");
+ return ret;
+ }
+
+ return 0;
+}
+
+int wl1251_hw_init_templates_config(struct wl1251 *wl)
+{
+ int ret;
+ u8 partial_vbm[PARTIAL_VBM_MAX];
+
+ /* send empty templates for fw memory reservation */
+ ret = wl1251_cmd_template_set(wl, CMD_PROBE_REQ, NULL,
+ sizeof(struct wl12xx_probe_req_template));
+ if (ret < 0)
+ return ret;
+
+ ret = wl1251_cmd_template_set(wl, CMD_NULL_DATA, NULL,
+ sizeof(struct wl12xx_null_data_template));
+ if (ret < 0)
+ return ret;
+
+ ret = wl1251_cmd_template_set(wl, CMD_PS_POLL, NULL,
+ sizeof(struct wl12xx_ps_poll_template));
+ if (ret < 0)
+ return ret;
+
+ ret = wl1251_cmd_template_set(wl, CMD_QOS_NULL_DATA, NULL,
+ sizeof
+ (struct wl12xx_qos_null_data_template));
+ if (ret < 0)
+ return ret;
+
+ ret = wl1251_cmd_template_set(wl, CMD_PROBE_RESP, NULL,
+ sizeof
+ (struct wl12xx_probe_resp_template));
+ if (ret < 0)
+ return ret;
+
+ ret = wl1251_cmd_template_set(wl, CMD_BEACON, NULL,
+ sizeof
+ (struct wl12xx_beacon_template));
+ if (ret < 0)
+ return ret;
+
+ /* tim templates, first reserve space then allocate an empty one */
+ memset(partial_vbm, 0, PARTIAL_VBM_MAX);
+ ret = wl1251_cmd_vbm(wl, TIM_ELE_ID, partial_vbm, PARTIAL_VBM_MAX, 0);
+ if (ret < 0)
+ return ret;
+
+ ret = wl1251_cmd_vbm(wl, TIM_ELE_ID, partial_vbm, 1, 0);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+int wl1251_hw_init_rx_config(struct wl1251 *wl, u32 config, u32 filter)
+{
+ int ret;
+
+ ret = wl1251_acx_rx_msdu_life_time(wl, RX_MSDU_LIFETIME_DEF);
+ if (ret < 0)
+ return ret;
+
+ ret = wl1251_acx_rx_config(wl, config, filter);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+int wl1251_hw_init_phy_config(struct wl1251 *wl)
+{
+ int ret;
+
+ ret = wl1251_acx_pd_threshold(wl);
+ if (ret < 0)
+ return ret;
+
+ ret = wl1251_acx_slot(wl, DEFAULT_SLOT_TIME);
+ if (ret < 0)
+ return ret;
+
+ ret = wl1251_acx_group_address_tbl(wl);
+ if (ret < 0)
+ return ret;
+
+ ret = wl1251_acx_service_period_timeout(wl);
+ if (ret < 0)
+ return ret;
+
+ ret = wl1251_acx_rts_threshold(wl, RTS_THRESHOLD_DEF);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+int wl1251_hw_init_beacon_filter(struct wl1251 *wl)
+{
+ int ret;
+
+ ret = wl1251_acx_beacon_filter_opt(wl);
+ if (ret < 0)
+ return ret;
+
+ ret = wl1251_acx_beacon_filter_table(wl);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+int wl1251_hw_init_pta(struct wl1251 *wl)
+{
+ int ret;
+
+ ret = wl1251_acx_sg_enable(wl);
+ if (ret < 0)
+ return ret;
+
+ ret = wl1251_acx_sg_cfg(wl);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+int wl1251_hw_init_energy_detection(struct wl1251 *wl)
+{
+ int ret;
+
+ ret = wl1251_acx_cca_threshold(wl);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+int wl1251_hw_init_beacon_broadcast(struct wl1251 *wl)
+{
+ int ret;
+
+ ret = wl1251_acx_bcn_dtim_options(wl);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+int wl1251_hw_init_power_auth(struct wl1251 *wl)
+{
+ return wl1251_acx_sleep_auth(wl, WL1251_PSM_CAM);
+}
+
+int wl1251_hw_init_mem_config(struct wl1251 *wl)
+{
+ int ret;
+
+ ret = wl1251_acx_mem_cfg(wl);
+ if (ret < 0)
+ return ret;
+
+ wl->target_mem_map = kzalloc(sizeof(struct wl1251_acx_mem_map),
+ GFP_KERNEL);
+ if (!wl->target_mem_map) {
+ wl1251_error("couldn't allocate target memory map");
+ return -ENOMEM;
+ }
+
+ /* we now ask for the firmware built memory map */
+ ret = wl1251_acx_mem_map(wl, wl->target_mem_map,
+ sizeof(struct wl1251_acx_mem_map));
+ if (ret < 0) {
+ wl1251_error("couldn't retrieve firmware memory map");
+ kfree(wl->target_mem_map);
+ wl->target_mem_map = NULL;
+ return ret;
+ }
+
+ return 0;
+}
+
+static int wl1251_hw_init_txq_fill(u8 qid,
+ struct acx_tx_queue_qos_config *config,
+ u32 num_blocks)
+{
+ config->qid = qid;
+
+ switch (qid) {
+ case QOS_AC_BE:
+ config->high_threshold =
+ (QOS_TX_HIGH_BE_DEF * num_blocks) / 100;
+ config->low_threshold =
+ (QOS_TX_LOW_BE_DEF * num_blocks) / 100;
+ break;
+ case QOS_AC_BK:
+ config->high_threshold =
+ (QOS_TX_HIGH_BK_DEF * num_blocks) / 100;
+ config->low_threshold =
+ (QOS_TX_LOW_BK_DEF * num_blocks) / 100;
+ break;
+ case QOS_AC_VI:
+ config->high_threshold =
+ (QOS_TX_HIGH_VI_DEF * num_blocks) / 100;
+ config->low_threshold =
+ (QOS_TX_LOW_VI_DEF * num_blocks) / 100;
+ break;
+ case QOS_AC_VO:
+ config->high_threshold =
+ (QOS_TX_HIGH_VO_DEF * num_blocks) / 100;
+ config->low_threshold =
+ (QOS_TX_LOW_VO_DEF * num_blocks) / 100;
+ break;
+ default:
+ wl1251_error("Invalid TX queue id: %d", qid);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int wl1251_hw_init_tx_queue_config(struct wl1251 *wl)
+{
+ struct acx_tx_queue_qos_config *config;
+ struct wl1251_acx_mem_map *wl_mem_map = wl->target_mem_map;
+ int ret, i;
+
+ wl1251_debug(DEBUG_ACX, "acx tx queue config");
+
+ config = kzalloc(sizeof(*config), GFP_KERNEL);
+ if (!config) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ for (i = 0; i < MAX_NUM_OF_AC; i++) {
+ ret = wl1251_hw_init_txq_fill(i, config,
+ wl_mem_map->num_tx_mem_blocks);
+ if (ret < 0)
+ goto out;
+
+ ret = wl1251_cmd_configure(wl, ACX_TX_QUEUE_CFG,
+ config, sizeof(*config));
+ if (ret < 0)
+ goto out;
+ }
+
+out:
+ kfree(config);
+ return ret;
+}
+
+static int wl1251_hw_init_data_path_config(struct wl1251 *wl)
+{
+ int ret;
+
+ /* asking for the data path parameters */
+ wl->data_path = kzalloc(sizeof(struct acx_data_path_params_resp),
+ GFP_KERNEL);
+ if (!wl->data_path) {
+ wl1251_error("Couldnt allocate data path parameters");
+ return -ENOMEM;
+ }
+
+ ret = wl1251_acx_data_path_params(wl, wl->data_path);
+ if (ret < 0) {
+ kfree(wl->data_path);
+ wl->data_path = NULL;
+ return ret;
+ }
+
+ return 0;
+}
+
+
+int wl1251_hw_init(struct wl1251 *wl)
+{
+ struct wl1251_acx_mem_map *wl_mem_map;
+ int ret;
+
+ ret = wl1251_hw_init_hwenc_config(wl);
+ if (ret < 0)
+ return ret;
+
+ /* Template settings */
+ ret = wl1251_hw_init_templates_config(wl);
+ if (ret < 0)
+ return ret;
+
+ /* Default memory configuration */
+ ret = wl1251_hw_init_mem_config(wl);
+ if (ret < 0)
+ return ret;
+
+ /* Default data path configuration */
+ ret = wl1251_hw_init_data_path_config(wl);
+ if (ret < 0)
+ goto out_free_memmap;
+
+ /* RX config */
+ ret = wl1251_hw_init_rx_config(wl,
+ RX_CFG_PROMISCUOUS | RX_CFG_TSF,
+ RX_FILTER_OPTION_DEF);
+ /* RX_CONFIG_OPTION_ANY_DST_ANY_BSS,
+ RX_FILTER_OPTION_FILTER_ALL); */
+ if (ret < 0)
+ goto out_free_data_path;
+
+ /* TX queues config */
+ ret = wl1251_hw_init_tx_queue_config(wl);
+ if (ret < 0)
+ goto out_free_data_path;
+
+ /* PHY layer config */
+ ret = wl1251_hw_init_phy_config(wl);
+ if (ret < 0)
+ goto out_free_data_path;
+
+ /* Beacon filtering */
+ ret = wl1251_hw_init_beacon_filter(wl);
+ if (ret < 0)
+ goto out_free_data_path;
+
+ /* Bluetooth WLAN coexistence */
+ ret = wl1251_hw_init_pta(wl);
+ if (ret < 0)
+ goto out_free_data_path;
+
+ /* Energy detection */
+ ret = wl1251_hw_init_energy_detection(wl);
+ if (ret < 0)
+ goto out_free_data_path;
+
+ /* Beacons and boradcast settings */
+ ret = wl1251_hw_init_beacon_broadcast(wl);
+ if (ret < 0)
+ goto out_free_data_path;
+
+ /* Enable data path */
+ ret = wl1251_cmd_data_path(wl, wl->channel, 1);
+ if (ret < 0)
+ goto out_free_data_path;
+
+ /* Default power state */
+ ret = wl1251_hw_init_power_auth(wl);
+ if (ret < 0)
+ goto out_free_data_path;
+
+ wl_mem_map = wl->target_mem_map;
+ wl1251_info("%d tx blocks at 0x%x, %d rx blocks at 0x%x",
+ wl_mem_map->num_tx_mem_blocks,
+ wl->data_path->tx_control_addr,
+ wl_mem_map->num_rx_mem_blocks,
+ wl->data_path->rx_control_addr);
+
+ return 0;
+
+ out_free_data_path:
+ kfree(wl->data_path);
+
+ out_free_memmap:
+ kfree(wl->target_mem_map);
+
+ return ret;
+}
diff --git a/drivers/net/wireless/wl12xx/wl1251_init.h b/drivers/net/wireless/wl12xx/wl1251_init.h
new file mode 100644
index 00000000000..b3b25ec885e
--- /dev/null
+++ b/drivers/net/wireless/wl12xx/wl1251_init.h
@@ -0,0 +1,41 @@
+/*
+ * This file is part of wl1251
+ *
+ * Copyright (C) 2009 Nokia Corporation
+ *
+ * Contact: Kalle Valo <kalle.valo@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef __WL1251_INIT_H__
+#define __WL1251_INIT_H__
+
+#include "wl1251.h"
+
+int wl1251_hw_init_hwenc_config(struct wl1251 *wl);
+int wl1251_hw_init_templates_config(struct wl1251 *wl);
+int wl1251_hw_init_rx_config(struct wl1251 *wl, u32 config, u32 filter);
+int wl1251_hw_init_phy_config(struct wl1251 *wl);
+int wl1251_hw_init_beacon_filter(struct wl1251 *wl);
+int wl1251_hw_init_pta(struct wl1251 *wl);
+int wl1251_hw_init_energy_detection(struct wl1251 *wl);
+int wl1251_hw_init_beacon_broadcast(struct wl1251 *wl);
+int wl1251_hw_init_power_auth(struct wl1251 *wl);
+int wl1251_hw_init_mem_config(struct wl1251 *wl);
+int wl1251_hw_init(struct wl1251 *wl);
+
+#endif
diff --git a/drivers/net/wireless/wl12xx/wl1251_io.c b/drivers/net/wireless/wl12xx/wl1251_io.c
new file mode 100644
index 00000000000..f1c232e0887
--- /dev/null
+++ b/drivers/net/wireless/wl12xx/wl1251_io.c
@@ -0,0 +1,196 @@
+/*
+ * This file is part of wl12xx
+ *
+ * Copyright (C) 2008 Nokia Corporation
+ *
+ * Contact: Kalle Valo <kalle.valo@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include "wl1251.h"
+#include "wl1251_reg.h"
+#include "wl1251_io.h"
+
+/* FIXME: this is static data nowadays and the table can be removed */
+static enum wl12xx_acx_int_reg wl1251_io_reg_table[ACX_REG_TABLE_LEN] = {
+ [ACX_REG_INTERRUPT_TRIG] = (REGISTERS_BASE + 0x0474),
+ [ACX_REG_INTERRUPT_TRIG_H] = (REGISTERS_BASE + 0x0478),
+ [ACX_REG_INTERRUPT_MASK] = (REGISTERS_BASE + 0x0494),
+ [ACX_REG_HINT_MASK_SET] = (REGISTERS_BASE + 0x0498),
+ [ACX_REG_HINT_MASK_CLR] = (REGISTERS_BASE + 0x049C),
+ [ACX_REG_INTERRUPT_NO_CLEAR] = (REGISTERS_BASE + 0x04B0),
+ [ACX_REG_INTERRUPT_CLEAR] = (REGISTERS_BASE + 0x04A4),
+ [ACX_REG_INTERRUPT_ACK] = (REGISTERS_BASE + 0x04A8),
+ [ACX_REG_SLV_SOFT_RESET] = (REGISTERS_BASE + 0x0000),
+ [ACX_REG_EE_START] = (REGISTERS_BASE + 0x080C),
+ [ACX_REG_ECPU_CONTROL] = (REGISTERS_BASE + 0x0804)
+};
+
+static int wl1251_translate_reg_addr(struct wl1251 *wl, int addr)
+{
+ /* If the address is lower than REGISTERS_BASE, it means that this is
+ * a chip-specific register address, so look it up in the registers
+ * table */
+ if (addr < REGISTERS_BASE) {
+ /* Make sure we don't go over the table */
+ if (addr >= ACX_REG_TABLE_LEN) {
+ wl1251_error("address out of range (%d)", addr);
+ return -EINVAL;
+ }
+ addr = wl1251_io_reg_table[addr];
+ }
+
+ return addr - wl->physical_reg_addr + wl->virtual_reg_addr;
+}
+
+static int wl1251_translate_mem_addr(struct wl1251 *wl, int addr)
+{
+ return addr - wl->physical_mem_addr + wl->virtual_mem_addr;
+}
+
+void wl1251_mem_read(struct wl1251 *wl, int addr, void *buf, size_t len)
+{
+ int physical;
+
+ physical = wl1251_translate_mem_addr(wl, addr);
+
+ wl->if_ops->read(wl, physical, buf, len);
+}
+
+void wl1251_mem_write(struct wl1251 *wl, int addr, void *buf, size_t len)
+{
+ int physical;
+
+ physical = wl1251_translate_mem_addr(wl, addr);
+
+ wl->if_ops->write(wl, physical, buf, len);
+}
+
+u32 wl1251_mem_read32(struct wl1251 *wl, int addr)
+{
+ return wl1251_read32(wl, wl1251_translate_mem_addr(wl, addr));
+}
+
+void wl1251_mem_write32(struct wl1251 *wl, int addr, u32 val)
+{
+ wl1251_write32(wl, wl1251_translate_mem_addr(wl, addr), val);
+}
+
+u32 wl1251_reg_read32(struct wl1251 *wl, int addr)
+{
+ return wl1251_read32(wl, wl1251_translate_reg_addr(wl, addr));
+}
+
+void wl1251_reg_write32(struct wl1251 *wl, int addr, u32 val)
+{
+ wl1251_write32(wl, wl1251_translate_reg_addr(wl, addr), val);
+}
+
+/* Set the partitions to access the chip addresses.
+ *
+ * There are two VIRTUAL partitions (the memory partition and the
+ * registers partition), which are mapped to two different areas of the
+ * PHYSICAL (hardware) memory. This function also makes other checks to
+ * ensure that the partitions are not overlapping. In the diagram below, the
+ * memory partition comes before the register partition, but the opposite is
+ * also supported.
+ *
+ * PHYSICAL address
+ * space
+ *
+ * | |
+ * ...+----+--> mem_start
+ * VIRTUAL address ... | |
+ * space ... | | [PART_0]
+ * ... | |
+ * 0x00000000 <--+----+... ...+----+--> mem_start + mem_size
+ * | | ... | |
+ * |MEM | ... | |
+ * | | ... | |
+ * part_size <--+----+... | | {unused area)
+ * | | ... | |
+ * |REG | ... | |
+ * part_size | | ... | |
+ * + <--+----+... ...+----+--> reg_start
+ * reg_size ... | |
+ * ... | | [PART_1]
+ * ... | |
+ * ...+----+--> reg_start + reg_size
+ * | |
+ *
+ */
+void wl1251_set_partition(struct wl1251 *wl,
+ u32 mem_start, u32 mem_size,
+ u32 reg_start, u32 reg_size)
+{
+ struct wl1251_partition partition[2];
+
+ wl1251_debug(DEBUG_SPI, "mem_start %08X mem_size %08X",
+ mem_start, mem_size);
+ wl1251_debug(DEBUG_SPI, "reg_start %08X reg_size %08X",
+ reg_start, reg_size);
+
+ /* Make sure that the two partitions together don't exceed the
+ * address range */
+ if ((mem_size + reg_size) > HW_ACCESS_MEMORY_MAX_RANGE) {
+ wl1251_debug(DEBUG_SPI, "Total size exceeds maximum virtual"
+ " address range. Truncating partition[0].");
+ mem_size = HW_ACCESS_MEMORY_MAX_RANGE - reg_size;
+ wl1251_debug(DEBUG_SPI, "mem_start %08X mem_size %08X",
+ mem_start, mem_size);
+ wl1251_debug(DEBUG_SPI, "reg_start %08X reg_size %08X",
+ reg_start, reg_size);
+ }
+
+ if ((mem_start < reg_start) &&
+ ((mem_start + mem_size) > reg_start)) {
+ /* Guarantee that the memory partition doesn't overlap the
+ * registers partition */
+ wl1251_debug(DEBUG_SPI, "End of partition[0] is "
+ "overlapping partition[1]. Adjusted.");
+ mem_size = reg_start - mem_start;
+ wl1251_debug(DEBUG_SPI, "mem_start %08X mem_size %08X",
+ mem_start, mem_size);
+ wl1251_debug(DEBUG_SPI, "reg_start %08X reg_size %08X",
+ reg_start, reg_size);
+ } else if ((reg_start < mem_start) &&
+ ((reg_start + reg_size) > mem_start)) {
+ /* Guarantee that the register partition doesn't overlap the
+ * memory partition */
+ wl1251_debug(DEBUG_SPI, "End of partition[1] is"
+ " overlapping partition[0]. Adjusted.");
+ reg_size = mem_start - reg_start;
+ wl1251_debug(DEBUG_SPI, "mem_start %08X mem_size %08X",
+ mem_start, mem_size);
+ wl1251_debug(DEBUG_SPI, "reg_start %08X reg_size %08X",
+ reg_start, reg_size);
+ }
+
+ partition[0].start = mem_start;
+ partition[0].size = mem_size;
+ partition[1].start = reg_start;
+ partition[1].size = reg_size;
+
+ wl->physical_mem_addr = mem_start;
+ wl->physical_reg_addr = reg_start;
+
+ wl->virtual_mem_addr = 0;
+ wl->virtual_reg_addr = mem_size;
+
+ wl->if_ops->write(wl, HW_ACCESS_PART0_SIZE_ADDR, partition,
+ sizeof(partition));
+}
diff --git a/drivers/net/wireless/wl12xx/wl1251_io.h b/drivers/net/wireless/wl12xx/wl1251_io.h
new file mode 100644
index 00000000000..b89d2ac62ef
--- /dev/null
+++ b/drivers/net/wireless/wl12xx/wl1251_io.h
@@ -0,0 +1,64 @@
+/*
+ * This file is part of wl12xx
+ *
+ * Copyright (C) 2008 Nokia Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+#ifndef __WL1251_IO_H__
+#define __WL1251_IO_H__
+
+#include "wl1251.h"
+
+#define HW_ACCESS_MEMORY_MAX_RANGE 0x1FFC0
+
+#define HW_ACCESS_PART0_SIZE_ADDR 0x1FFC0
+#define HW_ACCESS_PART0_START_ADDR 0x1FFC4
+#define HW_ACCESS_PART1_SIZE_ADDR 0x1FFC8
+#define HW_ACCESS_PART1_START_ADDR 0x1FFCC
+
+#define HW_ACCESS_REGISTER_SIZE 4
+
+#define HW_ACCESS_PRAM_MAX_RANGE 0x3c000
+
+static inline u32 wl1251_read32(struct wl1251 *wl, int addr)
+{
+ u32 response;
+
+ wl->if_ops->read(wl, addr, &response, sizeof(u32));
+
+ return response;
+}
+
+static inline void wl1251_write32(struct wl1251 *wl, int addr, u32 val)
+{
+ wl->if_ops->write(wl, addr, &val, sizeof(u32));
+}
+
+/* Memory target IO, address is translated to partition 0 */
+void wl1251_mem_read(struct wl1251 *wl, int addr, void *buf, size_t len);
+void wl1251_mem_write(struct wl1251 *wl, int addr, void *buf, size_t len);
+u32 wl1251_mem_read32(struct wl1251 *wl, int addr);
+void wl1251_mem_write32(struct wl1251 *wl, int addr, u32 val);
+/* Registers IO */
+u32 wl1251_reg_read32(struct wl1251 *wl, int addr);
+void wl1251_reg_write32(struct wl1251 *wl, int addr, u32 val);
+
+void wl1251_set_partition(struct wl1251 *wl,
+ u32 part_start, u32 part_size,
+ u32 reg_start, u32 reg_size);
+
+#endif
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/wl1251_main.c
index 603d6114882..7148934e464 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/wl1251_main.c
@@ -1,5 +1,5 @@
/*
- * This file is part of wl12xx
+ * This file is part of wl1251
*
* Copyright (C) 2008-2009 Nokia Corporation
*
@@ -26,65 +26,57 @@
#include <linux/firmware.h>
#include <linux/delay.h>
#include <linux/irq.h>
-#include <linux/spi/spi.h>
#include <linux/crc32.h>
#include <linux/etherdevice.h>
-#include <linux/spi/wl12xx.h>
-#include "wl12xx.h"
-#include "wl12xx_80211.h"
-#include "reg.h"
#include "wl1251.h"
-#include "spi.h"
-#include "event.h"
-#include "tx.h"
-#include "rx.h"
-#include "ps.h"
-#include "init.h"
-#include "debugfs.h"
-
-static void wl12xx_disable_interrupts(struct wl12xx *wl)
+#include "wl12xx_80211.h"
+#include "wl1251_reg.h"
+#include "wl1251_io.h"
+#include "wl1251_cmd.h"
+#include "wl1251_event.h"
+#include "wl1251_tx.h"
+#include "wl1251_rx.h"
+#include "wl1251_ps.h"
+#include "wl1251_init.h"
+#include "wl1251_debugfs.h"
+#include "wl1251_boot.h"
+
+void wl1251_enable_interrupts(struct wl1251 *wl)
{
- disable_irq(wl->irq);
+ wl->if_ops->enable_irq(wl);
}
-static void wl12xx_power_off(struct wl12xx *wl)
+void wl1251_disable_interrupts(struct wl1251 *wl)
{
- wl->set_power(false);
+ wl->if_ops->disable_irq(wl);
}
-static void wl12xx_power_on(struct wl12xx *wl)
+static void wl1251_power_off(struct wl1251 *wl)
{
- wl->set_power(true);
+ wl->set_power(false);
}
-static irqreturn_t wl12xx_irq(int irq, void *cookie)
+static void wl1251_power_on(struct wl1251 *wl)
{
- struct wl12xx *wl;
-
- wl12xx_debug(DEBUG_IRQ, "IRQ");
-
- wl = cookie;
-
- schedule_work(&wl->irq_work);
-
- return IRQ_HANDLED;
+ wl->set_power(true);
}
-static int wl12xx_fetch_firmware(struct wl12xx *wl)
+static int wl1251_fetch_firmware(struct wl1251 *wl)
{
const struct firmware *fw;
+ struct device *dev = wiphy_dev(wl->hw->wiphy);
int ret;
- ret = request_firmware(&fw, wl->chip.fw_filename, &wl->spi->dev);
+ ret = request_firmware(&fw, WL1251_FW_NAME, dev);
if (ret < 0) {
- wl12xx_error("could not get firmware: %d", ret);
+ wl1251_error("could not get firmware: %d", ret);
return ret;
}
if (fw->size % 4) {
- wl12xx_error("firmware size is not multiple of 32 bits: %zu",
+ wl1251_error("firmware size is not multiple of 32 bits: %zu",
fw->size);
ret = -EILSEQ;
goto out;
@@ -94,7 +86,7 @@ static int wl12xx_fetch_firmware(struct wl12xx *wl)
wl->fw = kmalloc(wl->fw_len, GFP_KERNEL);
if (!wl->fw) {
- wl12xx_error("could not allocate memory for the firmware");
+ wl1251_error("could not allocate memory for the firmware");
ret = -ENOMEM;
goto out;
}
@@ -109,20 +101,21 @@ out:
return ret;
}
-static int wl12xx_fetch_nvs(struct wl12xx *wl)
+static int wl1251_fetch_nvs(struct wl1251 *wl)
{
const struct firmware *fw;
+ struct device *dev = wiphy_dev(wl->hw->wiphy);
int ret;
- ret = request_firmware(&fw, wl->chip.nvs_filename, &wl->spi->dev);
+ ret = request_firmware(&fw, WL1251_NVS_NAME, dev);
if (ret < 0) {
- wl12xx_error("could not get nvs file: %d", ret);
+ wl1251_error("could not get nvs file: %d", ret);
return ret;
}
if (fw->size % 4) {
- wl12xx_error("nvs size is not multiple of 32 bits: %zu",
+ wl1251_error("nvs size is not multiple of 32 bits: %zu",
fw->size);
ret = -EILSEQ;
goto out;
@@ -132,7 +125,7 @@ static int wl12xx_fetch_nvs(struct wl12xx *wl)
wl->nvs = kmalloc(wl->nvs_len, GFP_KERNEL);
if (!wl->nvs) {
- wl12xx_error("could not allocate memory for the nvs file");
+ wl1251_error("could not allocate memory for the nvs file");
ret = -ENOMEM;
goto out;
}
@@ -147,74 +140,66 @@ out:
return ret;
}
-static void wl12xx_fw_wakeup(struct wl12xx *wl)
+static void wl1251_fw_wakeup(struct wl1251 *wl)
{
u32 elp_reg;
elp_reg = ELPCTRL_WAKE_UP;
- wl12xx_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, elp_reg);
- elp_reg = wl12xx_read32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR);
+ wl1251_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, elp_reg);
+ elp_reg = wl1251_read32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR);
- if (!(elp_reg & ELPCTRL_WLAN_READY)) {
- wl12xx_warning("WLAN not ready");
- elp_reg = ELPCTRL_WAKE_UP_WLAN_READY;
- wl12xx_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, elp_reg);
- }
+ if (!(elp_reg & ELPCTRL_WLAN_READY))
+ wl1251_warning("WLAN not ready");
}
-static int wl12xx_chip_wakeup(struct wl12xx *wl)
+static int wl1251_chip_wakeup(struct wl1251 *wl)
{
int ret = 0;
- wl12xx_power_on(wl);
- msleep(wl->chip.power_on_sleep);
- wl12xx_spi_reset(wl);
- wl12xx_spi_init(wl);
+ wl1251_power_on(wl);
+ msleep(WL1251_POWER_ON_SLEEP);
+ wl->if_ops->reset(wl);
/* We don't need a real memory partition here, because we only want
* to use the registers at this point. */
- wl12xx_set_partition(wl,
+ wl1251_set_partition(wl,
0x00000000,
0x00000000,
REGISTERS_BASE,
REGISTERS_DOWN_SIZE);
/* ELP module wake up */
- wl12xx_fw_wakeup(wl);
+ wl1251_fw_wakeup(wl);
/* whal_FwCtrl_BootSm() */
/* 0. read chip id from CHIP_ID */
- wl->chip.id = wl12xx_reg_read32(wl, CHIP_ID_B);
+ wl->chip_id = wl1251_reg_read32(wl, CHIP_ID_B);
/* 1. check if chip id is valid */
- switch (wl->chip.id) {
+ switch (wl->chip_id) {
case CHIP_ID_1251_PG12:
- wl12xx_debug(DEBUG_BOOT, "chip id 0x%x (1251 PG12)",
- wl->chip.id);
-
- wl1251_setup(wl);
-
+ wl1251_debug(DEBUG_BOOT, "chip id 0x%x (1251 PG12)",
+ wl->chip_id);
break;
- case CHIP_ID_1271_PG10:
case CHIP_ID_1251_PG10:
case CHIP_ID_1251_PG11:
default:
- wl12xx_error("unsupported chip id: 0x%x", wl->chip.id);
+ wl1251_error("unsupported chip id: 0x%x", wl->chip_id);
ret = -ENODEV;
goto out;
}
if (wl->fw == NULL) {
- ret = wl12xx_fetch_firmware(wl);
+ ret = wl1251_fetch_firmware(wl);
if (ret < 0)
goto out;
}
/* No NVS from netlink, try to get it from the filesystem */
if (wl->nvs == NULL) {
- ret = wl12xx_fetch_nvs(wl);
+ ret = wl1251_fetch_nvs(wl);
if (ret < 0)
goto out;
}
@@ -223,88 +208,180 @@ out:
return ret;
}
-static void wl12xx_filter_work(struct work_struct *work)
+static void wl1251_irq_work(struct work_struct *work)
{
- struct wl12xx *wl =
- container_of(work, struct wl12xx, filter_work);
+ u32 intr;
+ struct wl1251 *wl =
+ container_of(work, struct wl1251, irq_work);
int ret;
mutex_lock(&wl->mutex);
- if (wl->state == WL12XX_STATE_OFF)
+ wl1251_debug(DEBUG_IRQ, "IRQ work");
+
+ if (wl->state == WL1251_STATE_OFF)
goto out;
- ret = wl12xx_cmd_join(wl, wl->bss_type, 1, 100, 0);
+ ret = wl1251_ps_elp_wakeup(wl);
if (ret < 0)
goto out;
-out:
- mutex_unlock(&wl->mutex);
-}
+ wl1251_reg_write32(wl, ACX_REG_INTERRUPT_MASK, WL1251_ACX_INTR_ALL);
+
+ intr = wl1251_reg_read32(wl, ACX_REG_INTERRUPT_CLEAR);
+ wl1251_debug(DEBUG_IRQ, "intr: 0x%x", intr);
+
+ if (wl->data_path) {
+ wl->rx_counter =
+ wl1251_mem_read32(wl, wl->data_path->rx_control_addr);
+
+ /* We handle a frmware bug here */
+ switch ((wl->rx_counter - wl->rx_handled) & 0xf) {
+ case 0:
+ wl1251_debug(DEBUG_IRQ, "RX: FW and host in sync");
+ intr &= ~WL1251_ACX_INTR_RX0_DATA;
+ intr &= ~WL1251_ACX_INTR_RX1_DATA;
+ break;
+ case 1:
+ wl1251_debug(DEBUG_IRQ, "RX: FW +1");
+ intr |= WL1251_ACX_INTR_RX0_DATA;
+ intr &= ~WL1251_ACX_INTR_RX1_DATA;
+ break;
+ case 2:
+ wl1251_debug(DEBUG_IRQ, "RX: FW +2");
+ intr |= WL1251_ACX_INTR_RX0_DATA;
+ intr |= WL1251_ACX_INTR_RX1_DATA;
+ break;
+ default:
+ wl1251_warning("RX: FW and host out of sync: %d",
+ wl->rx_counter - wl->rx_handled);
+ break;
+ }
-int wl12xx_plt_start(struct wl12xx *wl)
-{
- int ret;
+ wl->rx_handled = wl->rx_counter;
- wl12xx_notice("power up");
- if (wl->state != WL12XX_STATE_OFF) {
- wl12xx_error("cannot go into PLT state because not "
- "in off state: %d", wl->state);
- return -EBUSY;
+ wl1251_debug(DEBUG_IRQ, "RX counter: %d", wl->rx_counter);
}
- wl->state = WL12XX_STATE_PLT;
+ intr &= wl->intr_mask;
- ret = wl12xx_chip_wakeup(wl);
- if (ret < 0)
- return ret;
+ if (intr == 0) {
+ wl1251_debug(DEBUG_IRQ, "INTR is 0");
+ wl1251_reg_write32(wl, ACX_REG_INTERRUPT_MASK,
+ ~(wl->intr_mask));
+
+ goto out_sleep;
+ }
- ret = wl->chip.op_boot(wl);
+ if (intr & WL1251_ACX_INTR_RX0_DATA) {
+ wl1251_debug(DEBUG_IRQ, "WL1251_ACX_INTR_RX0_DATA");
+ wl1251_rx(wl);
+ }
+
+ if (intr & WL1251_ACX_INTR_RX1_DATA) {
+ wl1251_debug(DEBUG_IRQ, "WL1251_ACX_INTR_RX1_DATA");
+ wl1251_rx(wl);
+ }
+
+ if (intr & WL1251_ACX_INTR_TX_RESULT) {
+ wl1251_debug(DEBUG_IRQ, "WL1251_ACX_INTR_TX_RESULT");
+ wl1251_tx_complete(wl);
+ }
+
+ if (intr & (WL1251_ACX_INTR_EVENT_A | WL1251_ACX_INTR_EVENT_B)) {
+ wl1251_debug(DEBUG_IRQ, "WL1251_ACX_INTR_EVENT (0x%x)", intr);
+ if (intr & WL1251_ACX_INTR_EVENT_A)
+ wl1251_event_handle(wl, 0);
+ else
+ wl1251_event_handle(wl, 1);
+ }
+
+ if (intr & WL1251_ACX_INTR_INIT_COMPLETE)
+ wl1251_debug(DEBUG_IRQ, "WL1251_ACX_INTR_INIT_COMPLETE");
+
+ wl1251_reg_write32(wl, ACX_REG_INTERRUPT_MASK, ~(wl->intr_mask));
+
+out_sleep:
+ wl1251_ps_elp_sleep(wl);
+
+out:
+ mutex_unlock(&wl->mutex);
+}
+
+static int wl1251_join(struct wl1251 *wl, u8 bss_type, u8 channel,
+ u16 beacon_interval, u8 dtim_period)
+{
+ int ret;
+
+ ret = wl1251_acx_frame_rates(wl, DEFAULT_HW_GEN_TX_RATE,
+ DEFAULT_HW_GEN_MODULATION_TYPE,
+ wl->tx_mgmt_frm_rate,
+ wl->tx_mgmt_frm_mod);
if (ret < 0)
- return ret;
+ goto out;
- wl12xx_notice("firmware booted in PLT mode (%s)", wl->chip.fw_ver);
- ret = wl->chip.op_plt_init(wl);
+ ret = wl1251_cmd_join(wl, bss_type, channel, beacon_interval,
+ dtim_period);
if (ret < 0)
- return ret;
+ goto out;
- return 0;
+ /*
+ * FIXME: we should wait for JOIN_EVENT_COMPLETE_ID but to simplify
+ * locking we just sleep instead, for now
+ */
+ msleep(10);
+
+out:
+ return ret;
}
-int wl12xx_plt_stop(struct wl12xx *wl)
+static void wl1251_filter_work(struct work_struct *work)
{
- wl12xx_notice("power down");
+ struct wl1251 *wl =
+ container_of(work, struct wl1251, filter_work);
+ int ret;
- if (wl->state != WL12XX_STATE_PLT) {
- wl12xx_error("cannot power down because not in PLT "
- "state: %d", wl->state);
- return -EBUSY;
- }
+ mutex_lock(&wl->mutex);
- wl12xx_disable_interrupts(wl);
- wl12xx_power_off(wl);
+ if (wl->state == WL1251_STATE_OFF)
+ goto out;
- wl->state = WL12XX_STATE_OFF;
+ ret = wl1251_ps_elp_wakeup(wl);
+ if (ret < 0)
+ goto out;
- return 0;
-}
+ ret = wl1251_join(wl, wl->bss_type, wl->channel, wl->beacon_int,
+ wl->dtim_period);
+ if (ret < 0)
+ goto out_sleep;
+out_sleep:
+ wl1251_ps_elp_sleep(wl);
-static int wl12xx_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
+out:
+ mutex_unlock(&wl->mutex);
+}
+
+static int wl1251_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
{
- struct wl12xx *wl = hw->priv;
+ struct wl1251 *wl = hw->priv;
skb_queue_tail(&wl->tx_queue, skb);
- schedule_work(&wl->tx_work);
+ /*
+ * The chip specific setup must run before the first TX packet -
+ * before that, the tx_work will not be initialized!
+ */
+
+ ieee80211_queue_work(wl->hw, &wl->tx_work);
/*
* The workqueue is slow to process the tx_queue and we need stop
* the queue here, otherwise the queue will get too long.
*/
- if (skb_queue_len(&wl->tx_queue) >= WL12XX_TX_QUEUE_MAX_LENGTH) {
+ if (skb_queue_len(&wl->tx_queue) >= WL1251_TX_QUEUE_MAX_LENGTH) {
ieee80211_stop_queues(wl->hw);
/*
@@ -318,62 +395,62 @@ static int wl12xx_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
return NETDEV_TX_OK;
}
-static int wl12xx_op_start(struct ieee80211_hw *hw)
+static int wl1251_op_start(struct ieee80211_hw *hw)
{
- struct wl12xx *wl = hw->priv;
+ struct wl1251 *wl = hw->priv;
int ret = 0;
- wl12xx_debug(DEBUG_MAC80211, "mac80211 start");
+ wl1251_debug(DEBUG_MAC80211, "mac80211 start");
mutex_lock(&wl->mutex);
- if (wl->state != WL12XX_STATE_OFF) {
- wl12xx_error("cannot start because not in off state: %d",
+ if (wl->state != WL1251_STATE_OFF) {
+ wl1251_error("cannot start because not in off state: %d",
wl->state);
ret = -EBUSY;
goto out;
}
- ret = wl12xx_chip_wakeup(wl);
+ ret = wl1251_chip_wakeup(wl);
if (ret < 0)
- return ret;
+ goto out;
- ret = wl->chip.op_boot(wl);
+ ret = wl1251_boot(wl);
if (ret < 0)
goto out;
- ret = wl->chip.op_hw_init(wl);
+ ret = wl1251_hw_init(wl);
if (ret < 0)
goto out;
- ret = wl12xx_acx_station_id(wl);
+ ret = wl1251_acx_station_id(wl);
if (ret < 0)
goto out;
- wl->state = WL12XX_STATE_ON;
+ wl->state = WL1251_STATE_ON;
- wl12xx_info("firmware booted (%s)", wl->chip.fw_ver);
+ wl1251_info("firmware booted (%s)", wl->fw_ver);
out:
if (ret < 0)
- wl12xx_power_off(wl);
+ wl1251_power_off(wl);
mutex_unlock(&wl->mutex);
return ret;
}
-static void wl12xx_op_stop(struct ieee80211_hw *hw)
+static void wl1251_op_stop(struct ieee80211_hw *hw)
{
- struct wl12xx *wl = hw->priv;
+ struct wl1251 *wl = hw->priv;
- wl12xx_info("down");
+ wl1251_info("down");
- wl12xx_debug(DEBUG_MAC80211, "mac80211 stop");
+ wl1251_debug(DEBUG_MAC80211, "mac80211 stop");
mutex_lock(&wl->mutex);
- WARN_ON(wl->state != WL12XX_STATE_ON);
+ WARN_ON(wl->state != WL1251_STATE_ON);
if (wl->scanning) {
mutex_unlock(&wl->mutex);
@@ -382,9 +459,9 @@ static void wl12xx_op_stop(struct ieee80211_hw *hw)
wl->scanning = false;
}
- wl->state = WL12XX_STATE_OFF;
+ wl->state = WL1251_STATE_OFF;
- wl12xx_disable_interrupts(wl);
+ wl1251_disable_interrupts(wl);
mutex_unlock(&wl->mutex);
@@ -395,9 +472,8 @@ static void wl12xx_op_stop(struct ieee80211_hw *hw)
mutex_lock(&wl->mutex);
/* let's notify MAC80211 about the remaining pending TX frames */
- wl12xx_tx_flush(wl);
-
- wl12xx_power_off(wl);
+ wl1251_tx_flush(wl);
+ wl1251_power_off(wl);
memset(wl->bssid, 0, ETH_ALEN);
wl->listen_int = 1;
@@ -412,22 +488,22 @@ static void wl12xx_op_stop(struct ieee80211_hw *hw)
wl->elp = false;
wl->psm = 0;
wl->tx_queue_stopped = false;
- wl->power_level = WL12XX_DEFAULT_POWER_LEVEL;
+ wl->power_level = WL1251_DEFAULT_POWER_LEVEL;
+ wl->channel = WL1251_DEFAULT_CHANNEL;
- wl12xx_debugfs_reset(wl);
+ wl1251_debugfs_reset(wl);
mutex_unlock(&wl->mutex);
}
-static int wl12xx_op_add_interface(struct ieee80211_hw *hw,
+static int wl1251_op_add_interface(struct ieee80211_hw *hw,
struct ieee80211_if_init_conf *conf)
{
- struct wl12xx *wl = hw->priv;
- DECLARE_MAC_BUF(mac);
+ struct wl1251 *wl = hw->priv;
int ret = 0;
- wl12xx_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %s",
- conf->type, print_mac(mac, conf->mac_addr));
+ wl1251_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %pM",
+ conf->type, conf->mac_addr);
mutex_lock(&wl->mutex);
@@ -446,7 +522,7 @@ static int wl12xx_op_add_interface(struct ieee80211_hw *hw,
if (memcmp(wl->mac_addr, conf->mac_addr, ETH_ALEN)) {
memcpy(wl->mac_addr, conf->mac_addr, ETH_ALEN);
SET_IEEE80211_PERM_ADDR(wl->hw, wl->mac_addr);
- ret = wl12xx_acx_station_id(wl);
+ ret = wl1251_acx_station_id(wl);
if (ret < 0)
goto out;
}
@@ -456,13 +532,13 @@ out:
return ret;
}
-static void wl12xx_op_remove_interface(struct ieee80211_hw *hw,
+static void wl1251_op_remove_interface(struct ieee80211_hw *hw,
struct ieee80211_if_init_conf *conf)
{
- wl12xx_debug(DEBUG_MAC80211, "mac80211 remove interface");
+ wl1251_debug(DEBUG_MAC80211, "mac80211 remove interface");
}
-static int wl12xx_build_null_data(struct wl12xx *wl)
+static int wl1251_build_null_data(struct wl1251 *wl)
{
struct wl12xx_null_data_template template;
@@ -478,12 +554,12 @@ static int wl12xx_build_null_data(struct wl12xx *wl)
template.header.frame_ctl = cpu_to_le16(IEEE80211_FTYPE_DATA |
IEEE80211_STYPE_NULLFUNC);
- return wl12xx_cmd_template_set(wl, CMD_NULL_DATA, &template,
+ return wl1251_cmd_template_set(wl, CMD_NULL_DATA, &template,
sizeof(template));
}
-static int wl12xx_build_ps_poll(struct wl12xx *wl, u16 aid)
+static int wl1251_build_ps_poll(struct wl1251 *wl, u16 aid)
{
struct wl12xx_ps_poll_template template;
@@ -492,41 +568,45 @@ static int wl12xx_build_ps_poll(struct wl12xx *wl, u16 aid)
template.aid = aid;
template.fc = cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_PSPOLL);
- return wl12xx_cmd_template_set(wl, CMD_PS_POLL, &template,
+ return wl1251_cmd_template_set(wl, CMD_PS_POLL, &template,
sizeof(template));
}
-static int wl12xx_op_config(struct ieee80211_hw *hw, u32 changed)
+static int wl1251_op_config(struct ieee80211_hw *hw, u32 changed)
{
- struct wl12xx *wl = hw->priv;
+ struct wl1251 *wl = hw->priv;
struct ieee80211_conf *conf = &hw->conf;
int channel, ret = 0;
channel = ieee80211_frequency_to_channel(conf->channel->center_freq);
- wl12xx_debug(DEBUG_MAC80211, "mac80211 config ch %d psm %s power %d",
+ wl1251_debug(DEBUG_MAC80211, "mac80211 config ch %d psm %s power %d",
channel,
conf->flags & IEEE80211_CONF_PS ? "on" : "off",
conf->power_level);
mutex_lock(&wl->mutex);
- if (channel != wl->channel) {
- /* FIXME: use beacon interval provided by mac80211 */
- ret = wl12xx_cmd_join(wl, wl->bss_type, 1, 100, 0);
- if (ret < 0)
- goto out;
+ ret = wl1251_ps_elp_wakeup(wl);
+ if (ret < 0)
+ goto out;
+ if (channel != wl->channel) {
wl->channel = channel;
+
+ ret = wl1251_join(wl, wl->bss_type, wl->channel,
+ wl->beacon_int, wl->dtim_period);
+ if (ret < 0)
+ goto out_sleep;
}
- ret = wl12xx_build_null_data(wl);
+ ret = wl1251_build_null_data(wl);
if (ret < 0)
- goto out;
+ goto out_sleep;
if (conf->flags & IEEE80211_CONF_PS && !wl->psm_requested) {
- wl12xx_info("psm enabled");
+ wl1251_debug(DEBUG_PSM, "psm enabled");
wl->psm_requested = true;
@@ -535,49 +615,53 @@ static int wl12xx_op_config(struct ieee80211_hw *hw, u32 changed)
* If we're not, we'll enter it when joining an SSID,
* through the bss_info_changed() hook.
*/
- ret = wl12xx_ps_set_mode(wl, STATION_POWER_SAVE_MODE);
+ ret = wl1251_ps_set_mode(wl, STATION_POWER_SAVE_MODE);
} else if (!(conf->flags & IEEE80211_CONF_PS) &&
wl->psm_requested) {
- wl12xx_info("psm disabled");
+ wl1251_debug(DEBUG_PSM, "psm disabled");
wl->psm_requested = false;
if (wl->psm)
- ret = wl12xx_ps_set_mode(wl, STATION_ACTIVE_MODE);
+ ret = wl1251_ps_set_mode(wl, STATION_ACTIVE_MODE);
}
if (conf->power_level != wl->power_level) {
- ret = wl12xx_acx_tx_power(wl, conf->power_level);
+ ret = wl1251_acx_tx_power(wl, conf->power_level);
if (ret < 0)
goto out;
wl->power_level = conf->power_level;
}
+out_sleep:
+ wl1251_ps_elp_sleep(wl);
+
out:
mutex_unlock(&wl->mutex);
+
return ret;
}
-#define WL12XX_SUPPORTED_FILTERS (FIF_PROMISC_IN_BSS | \
+#define WL1251_SUPPORTED_FILTERS (FIF_PROMISC_IN_BSS | \
FIF_ALLMULTI | \
FIF_FCSFAIL | \
FIF_BCN_PRBRESP_PROMISC | \
FIF_CONTROL | \
FIF_OTHER_BSS)
-static void wl12xx_op_configure_filter(struct ieee80211_hw *hw,
+static void wl1251_op_configure_filter(struct ieee80211_hw *hw,
unsigned int changed,
unsigned int *total,
int mc_count,
struct dev_addr_list *mc_list)
{
- struct wl12xx *wl = hw->priv;
+ struct wl1251 *wl = hw->priv;
- wl12xx_debug(DEBUG_MAC80211, "mac80211 configure filter");
+ wl1251_debug(DEBUG_MAC80211, "mac80211 configure filter");
- *total &= WL12XX_SUPPORTED_FILTERS;
- changed &= WL12XX_SUPPORTED_FILTERS;
+ *total &= WL1251_SUPPORTED_FILTERS;
+ changed &= WL1251_SUPPORTED_FILTERS;
if (changed == 0)
/* no filters which we support changed */
@@ -585,8 +669,8 @@ static void wl12xx_op_configure_filter(struct ieee80211_hw *hw,
/* FIXME: wl->rx_config and wl->rx_filter are not protected */
- wl->rx_config = WL12XX_DEFAULT_RX_CONFIG;
- wl->rx_filter = WL12XX_DEFAULT_RX_FILTER;
+ wl->rx_config = WL1251_DEFAULT_RX_CONFIG;
+ wl->rx_filter = WL1251_DEFAULT_RX_FILTER;
if (*total & FIF_PROMISC_IN_BSS) {
wl->rx_config |= CFG_BSSID_FILTER_EN;
@@ -618,7 +702,8 @@ static void wl12xx_op_configure_filter(struct ieee80211_hw *hw,
}
/* HW encryption */
-static int wl12xx_set_key_type(struct wl12xx *wl, struct acx_set_key *key,
+static int wl1251_set_key_type(struct wl1251 *wl,
+ struct wl1251_cmd_set_keys *key,
enum set_key_cmd cmd,
struct ieee80211_key_conf *mac80211_key,
const u8 *addr)
@@ -648,95 +733,116 @@ static int wl12xx_set_key_type(struct wl12xx *wl, struct acx_set_key *key,
mac80211_key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
break;
default:
- wl12xx_error("Unknown key algo 0x%x", mac80211_key->alg);
+ wl1251_error("Unknown key algo 0x%x", mac80211_key->alg);
return -EOPNOTSUPP;
}
return 0;
}
-static int wl12xx_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
+static int wl1251_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
struct ieee80211_key_conf *key)
{
- struct wl12xx *wl = hw->priv;
- struct acx_set_key wl_key;
+ struct wl1251 *wl = hw->priv;
+ struct wl1251_cmd_set_keys *wl_cmd;
const u8 *addr;
int ret;
static const u8 bcast_addr[ETH_ALEN] =
{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
- wl12xx_debug(DEBUG_MAC80211, "mac80211 set key");
+ wl1251_debug(DEBUG_MAC80211, "mac80211 set key");
- memset(&wl_key, 0, sizeof(wl_key));
+ wl_cmd = kzalloc(sizeof(*wl_cmd), GFP_KERNEL);
+ if (!wl_cmd) {
+ ret = -ENOMEM;
+ goto out;
+ }
addr = sta ? sta->addr : bcast_addr;
- wl12xx_debug(DEBUG_CRYPT, "CMD: 0x%x", cmd);
- wl12xx_dump(DEBUG_CRYPT, "ADDR: ", addr, ETH_ALEN);
- wl12xx_debug(DEBUG_CRYPT, "Key: algo:0x%x, id:%d, len:%d flags 0x%x",
+ wl1251_debug(DEBUG_CRYPT, "CMD: 0x%x", cmd);
+ wl1251_dump(DEBUG_CRYPT, "ADDR: ", addr, ETH_ALEN);
+ wl1251_debug(DEBUG_CRYPT, "Key: algo:0x%x, id:%d, len:%d flags 0x%x",
key->alg, key->keyidx, key->keylen, key->flags);
- wl12xx_dump(DEBUG_CRYPT, "KEY: ", key->key, key->keylen);
+ wl1251_dump(DEBUG_CRYPT, "KEY: ", key->key, key->keylen);
+
+ if (is_zero_ether_addr(addr)) {
+ /* We dont support TX only encryption */
+ ret = -EOPNOTSUPP;
+ goto out;
+ }
mutex_lock(&wl->mutex);
+ ret = wl1251_ps_elp_wakeup(wl);
+ if (ret < 0)
+ goto out_unlock;
+
switch (cmd) {
case SET_KEY:
- wl_key.key_action = KEY_ADD_OR_REPLACE;
+ wl_cmd->key_action = KEY_ADD_OR_REPLACE;
break;
case DISABLE_KEY:
- wl_key.key_action = KEY_REMOVE;
+ wl_cmd->key_action = KEY_REMOVE;
break;
default:
- wl12xx_error("Unsupported key cmd 0x%x", cmd);
+ wl1251_error("Unsupported key cmd 0x%x", cmd);
break;
}
- ret = wl12xx_set_key_type(wl, &wl_key, cmd, key, addr);
+ ret = wl1251_set_key_type(wl, wl_cmd, cmd, key, addr);
if (ret < 0) {
- wl12xx_error("Set KEY type failed");
- goto out;
+ wl1251_error("Set KEY type failed");
+ goto out_sleep;
}
- if (wl_key.key_type != KEY_WEP_DEFAULT)
- memcpy(wl_key.addr, addr, ETH_ALEN);
+ if (wl_cmd->key_type != KEY_WEP_DEFAULT)
+ memcpy(wl_cmd->addr, addr, ETH_ALEN);
- if ((wl_key.key_type == KEY_TKIP_MIC_GROUP) ||
- (wl_key.key_type == KEY_TKIP_MIC_PAIRWISE)) {
+ if ((wl_cmd->key_type == KEY_TKIP_MIC_GROUP) ||
+ (wl_cmd->key_type == KEY_TKIP_MIC_PAIRWISE)) {
/*
* We get the key in the following form:
* TKIP (16 bytes) - TX MIC (8 bytes) - RX MIC (8 bytes)
* but the target is expecting:
* TKIP - RX MIC - TX MIC
*/
- memcpy(wl_key.key, key->key, 16);
- memcpy(wl_key.key + 16, key->key + 24, 8);
- memcpy(wl_key.key + 24, key->key + 16, 8);
+ memcpy(wl_cmd->key, key->key, 16);
+ memcpy(wl_cmd->key + 16, key->key + 24, 8);
+ memcpy(wl_cmd->key + 24, key->key + 16, 8);
} else {
- memcpy(wl_key.key, key->key, key->keylen);
+ memcpy(wl_cmd->key, key->key, key->keylen);
}
- wl_key.key_size = key->keylen;
+ wl_cmd->key_size = key->keylen;
- wl_key.id = key->keyidx;
- wl_key.ssid_profile = 0;
+ wl_cmd->id = key->keyidx;
+ wl_cmd->ssid_profile = 0;
- wl12xx_dump(DEBUG_CRYPT, "TARGET KEY: ", &wl_key, sizeof(wl_key));
+ wl1251_dump(DEBUG_CRYPT, "TARGET KEY: ", wl_cmd, sizeof(*wl_cmd));
- if (wl12xx_cmd_send(wl, CMD_SET_KEYS, &wl_key, sizeof(wl_key)) < 0) {
- wl12xx_error("Set KEY failed");
- ret = -EOPNOTSUPP;
- goto out;
+ ret = wl1251_cmd_send(wl, CMD_SET_KEYS, wl_cmd, sizeof(*wl_cmd));
+ if (ret < 0) {
+ wl1251_warning("could not set keys");
+ goto out_sleep;
}
-out:
+out_sleep:
+ wl1251_ps_elp_sleep(wl);
+
+out_unlock:
mutex_unlock(&wl->mutex);
+
+out:
+ kfree(wl_cmd);
+
return ret;
}
-static int wl12xx_build_basic_rates(char *rates)
+static int wl1251_build_basic_rates(char *rates)
{
u8 index = 0;
@@ -748,7 +854,7 @@ static int wl12xx_build_basic_rates(char *rates)
return index;
}
-static int wl12xx_build_extended_rates(char *rates)
+static int wl1251_build_extended_rates(char *rates)
{
u8 index = 0;
@@ -765,7 +871,7 @@ static int wl12xx_build_extended_rates(char *rates)
}
-static int wl12xx_build_probe_req(struct wl12xx *wl, u8 *ssid, size_t ssid_len)
+static int wl1251_build_probe_req(struct wl1251 *wl, u8 *ssid, size_t ssid_len)
{
struct wl12xx_probe_req_template template;
struct wl12xx_ie_rates *rates;
@@ -792,31 +898,30 @@ static int wl12xx_build_probe_req(struct wl12xx *wl, u8 *ssid, size_t ssid_len)
/* Basic Rates */
rates = (struct wl12xx_ie_rates *)ptr;
rates->header.id = WLAN_EID_SUPP_RATES;
- rates->header.len = wl12xx_build_basic_rates(rates->rates);
+ rates->header.len = wl1251_build_basic_rates(rates->rates);
size += sizeof(struct wl12xx_ie_header) + rates->header.len;
ptr += sizeof(struct wl12xx_ie_header) + rates->header.len;
/* Extended rates */
rates = (struct wl12xx_ie_rates *)ptr;
rates->header.id = WLAN_EID_EXT_SUPP_RATES;
- rates->header.len = wl12xx_build_extended_rates(rates->rates);
+ rates->header.len = wl1251_build_extended_rates(rates->rates);
size += sizeof(struct wl12xx_ie_header) + rates->header.len;
- wl12xx_dump(DEBUG_SCAN, "PROBE REQ: ", &template, size);
+ wl1251_dump(DEBUG_SCAN, "PROBE REQ: ", &template, size);
- return wl12xx_cmd_template_set(wl, CMD_PROBE_REQ, &template,
+ return wl1251_cmd_template_set(wl, CMD_PROBE_REQ, &template,
size);
}
-static int wl12xx_hw_scan(struct wl12xx *wl, u8 *ssid, size_t len,
+static int wl1251_hw_scan(struct wl1251 *wl, u8 *ssid, size_t len,
u8 active_scan, u8 high_prio, u8 num_channels,
u8 probe_requests)
{
+ struct wl1251_cmd_trigger_scan_to *trigger = NULL;
+ struct cmd_scan *params = NULL;
int i, ret;
- u32 split_scan = 0;
u16 scan_options = 0;
- struct cmd_scan *params;
- struct wl12xx_command *cmd_answer;
if (wl->scanning)
return -EINVAL;
@@ -864,33 +969,38 @@ static int wl12xx_hw_scan(struct wl12xx *wl, u8 *ssid, size_t len,
memset(params->params.ssid, 0, 32);
}
- ret = wl12xx_build_probe_req(wl, ssid, len);
+ ret = wl1251_build_probe_req(wl, ssid, len);
if (ret < 0) {
- wl12xx_error("PROBE request template failed");
+ wl1251_error("PROBE request template failed");
goto out;
}
- ret = wl12xx_cmd_send(wl, CMD_TRIGGER_SCAN_TO, &split_scan,
- sizeof(u32));
+ trigger = kzalloc(sizeof(*trigger), GFP_KERNEL);
+ if (!trigger)
+ goto out;
+
+ trigger->timeout = 0;
+
+ ret = wl1251_cmd_send(wl, CMD_TRIGGER_SCAN_TO, trigger,
+ sizeof(*trigger));
if (ret < 0) {
- wl12xx_error("Split SCAN failed");
+ wl1251_error("trigger scan to failed for hw scan");
goto out;
}
- wl12xx_dump(DEBUG_SCAN, "SCAN: ", params, sizeof(*params));
+ wl1251_dump(DEBUG_SCAN, "SCAN: ", params, sizeof(*params));
wl->scanning = true;
- ret = wl12xx_cmd_send(wl, CMD_SCAN, params, sizeof(*params));
+ ret = wl1251_cmd_send(wl, CMD_SCAN, params, sizeof(*params));
if (ret < 0)
- wl12xx_error("SCAN failed");
+ wl1251_error("SCAN failed");
- wl12xx_spi_mem_read(wl, wl->cmd_box_addr, params, sizeof(*params));
+ wl1251_mem_read(wl, wl->cmd_box_addr, params, sizeof(*params));
- cmd_answer = (struct wl12xx_command *) params;
- if (cmd_answer->status != CMD_STATUS_SUCCESS) {
- wl12xx_error("TEST command answer error: %d",
- cmd_answer->status);
+ if (params->header.status != CMD_STATUS_SUCCESS) {
+ wl1251_error("TEST command answer error: %d",
+ params->header.status);
wl->scanning = false;
ret = -EIO;
goto out;
@@ -902,15 +1012,15 @@ out:
}
-static int wl12xx_op_hw_scan(struct ieee80211_hw *hw,
+static int wl1251_op_hw_scan(struct ieee80211_hw *hw,
struct cfg80211_scan_request *req)
{
- struct wl12xx *wl = hw->priv;
+ struct wl1251 *wl = hw->priv;
int ret;
u8 *ssid = NULL;
size_t ssid_len = 0;
- wl12xx_debug(DEBUG_MAC80211, "mac80211 hw scan");
+ wl1251_debug(DEBUG_MAC80211, "mac80211 hw scan");
if (req->n_ssids) {
ssid = req->ssids[0].ssid;
@@ -918,85 +1028,117 @@ static int wl12xx_op_hw_scan(struct ieee80211_hw *hw,
}
mutex_lock(&wl->mutex);
- ret = wl12xx_hw_scan(hw->priv, ssid, ssid_len, 1, 0, 13, 3);
+
+ ret = wl1251_ps_elp_wakeup(wl);
+ if (ret < 0)
+ goto out;
+
+ ret = wl1251_hw_scan(hw->priv, ssid, ssid_len, 1, 0, 13, 3);
+
+ wl1251_ps_elp_sleep(wl);
+
+out:
mutex_unlock(&wl->mutex);
return ret;
}
-static int wl12xx_op_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
+static int wl1251_op_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
{
- struct wl12xx *wl = hw->priv;
+ struct wl1251 *wl = hw->priv;
int ret;
- ret = wl12xx_acx_rts_threshold(wl, (u16) value);
+ mutex_lock(&wl->mutex);
+
+ ret = wl1251_ps_elp_wakeup(wl);
+ if (ret < 0)
+ goto out;
+ ret = wl1251_acx_rts_threshold(wl, (u16) value);
if (ret < 0)
- wl12xx_warning("wl12xx_op_set_rts_threshold failed: %d", ret);
+ wl1251_warning("wl1251_op_set_rts_threshold failed: %d", ret);
+
+ wl1251_ps_elp_sleep(wl);
+
+out:
+ mutex_unlock(&wl->mutex);
return ret;
}
-static void wl12xx_op_bss_info_changed(struct ieee80211_hw *hw,
+static void wl1251_op_bss_info_changed(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_bss_conf *bss_conf,
u32 changed)
{
- enum acx_ps_mode mode;
- struct wl12xx *wl = hw->priv;
+ enum wl1251_cmd_ps_mode mode;
+ struct wl1251 *wl = hw->priv;
struct sk_buff *beacon;
int ret;
- wl12xx_debug(DEBUG_MAC80211, "mac80211 bss info changed");
+ wl1251_debug(DEBUG_MAC80211, "mac80211 bss info changed");
mutex_lock(&wl->mutex);
+ ret = wl1251_ps_elp_wakeup(wl);
+ if (ret < 0)
+ goto out;
+
if (changed & BSS_CHANGED_ASSOC) {
if (bss_conf->assoc) {
+ wl->beacon_int = bss_conf->beacon_int;
+ wl->dtim_period = bss_conf->dtim_period;
+
+ /* FIXME: call join */
+
wl->aid = bss_conf->aid;
- ret = wl12xx_build_ps_poll(wl, wl->aid);
+ ret = wl1251_build_ps_poll(wl, wl->aid);
if (ret < 0)
- goto out;
+ goto out_sleep;
- ret = wl12xx_acx_aid(wl, wl->aid);
+ ret = wl1251_acx_aid(wl, wl->aid);
if (ret < 0)
- goto out;
+ goto out_sleep;
/* If we want to go in PSM but we're not there yet */
if (wl->psm_requested && !wl->psm) {
mode = STATION_POWER_SAVE_MODE;
- ret = wl12xx_ps_set_mode(wl, mode);
+ ret = wl1251_ps_set_mode(wl, mode);
if (ret < 0)
- goto out;
+ goto out_sleep;
}
+ } else {
+ /* use defaults when not associated */
+ wl->beacon_int = WL1251_DEFAULT_BEACON_INT;
+ wl->dtim_period = WL1251_DEFAULT_DTIM_PERIOD;
}
}
if (changed & BSS_CHANGED_ERP_SLOT) {
if (bss_conf->use_short_slot)
- ret = wl12xx_acx_slot(wl, SLOT_TIME_SHORT);
+ ret = wl1251_acx_slot(wl, SLOT_TIME_SHORT);
else
- ret = wl12xx_acx_slot(wl, SLOT_TIME_LONG);
+ ret = wl1251_acx_slot(wl, SLOT_TIME_LONG);
if (ret < 0) {
- wl12xx_warning("Set slot time failed %d", ret);
- goto out;
+ wl1251_warning("Set slot time failed %d", ret);
+ goto out_sleep;
}
}
if (changed & BSS_CHANGED_ERP_PREAMBLE) {
if (bss_conf->use_short_preamble)
- wl12xx_acx_set_preamble(wl, ACX_PREAMBLE_SHORT);
+ wl1251_acx_set_preamble(wl, ACX_PREAMBLE_SHORT);
else
- wl12xx_acx_set_preamble(wl, ACX_PREAMBLE_LONG);
+ wl1251_acx_set_preamble(wl, ACX_PREAMBLE_LONG);
}
if (changed & BSS_CHANGED_ERP_CTS_PROT) {
if (bss_conf->use_cts_prot)
- ret = wl12xx_acx_cts_protect(wl, CTSPROTECT_ENABLE);
+ ret = wl1251_acx_cts_protect(wl, CTSPROTECT_ENABLE);
else
- ret = wl12xx_acx_cts_protect(wl, CTSPROTECT_DISABLE);
+ ret = wl1251_acx_cts_protect(wl, CTSPROTECT_DISABLE);
if (ret < 0) {
- wl12xx_warning("Set ctsprotect failed %d", ret);
+ wl1251_warning("Set ctsprotect failed %d", ret);
goto out;
}
}
@@ -1004,20 +1146,23 @@ static void wl12xx_op_bss_info_changed(struct ieee80211_hw *hw,
if (changed & BSS_CHANGED_BSSID) {
memcpy(wl->bssid, bss_conf->bssid, ETH_ALEN);
- ret = wl12xx_build_null_data(wl);
+ ret = wl1251_build_null_data(wl);
if (ret < 0)
goto out;
if (wl->bss_type != BSS_TYPE_IBSS) {
- ret = wl12xx_cmd_join(wl, wl->bss_type, 5, 100, 1);
+ ret = wl1251_join(wl, wl->bss_type, wl->channel,
+ wl->beacon_int, wl->dtim_period);
if (ret < 0)
- goto out;
+ goto out_sleep;
+ wl1251_warning("Set ctsprotect failed %d", ret);
+ goto out_sleep;
}
}
if (changed & BSS_CHANGED_BEACON) {
beacon = ieee80211_beacon_get(hw, vif);
- ret = wl12xx_cmd_template_set(wl, CMD_BEACON, beacon->data,
+ ret = wl1251_cmd_template_set(wl, CMD_BEACON, beacon->data,
beacon->len);
if (ret < 0) {
@@ -1025,7 +1170,7 @@ static void wl12xx_op_bss_info_changed(struct ieee80211_hw *hw,
goto out;
}
- ret = wl12xx_cmd_template_set(wl, CMD_PROBE_RESP, beacon->data,
+ ret = wl1251_cmd_template_set(wl, CMD_PROBE_RESP, beacon->data,
beacon->len);
dev_kfree_skb(beacon);
@@ -1033,19 +1178,23 @@ static void wl12xx_op_bss_info_changed(struct ieee80211_hw *hw,
if (ret < 0)
goto out;
- ret = wl12xx_cmd_join(wl, wl->bss_type, 1, 100, 0);
+ ret = wl1251_join(wl, wl->bss_type, wl->beacon_int,
+ wl->channel, wl->dtim_period);
if (ret < 0)
goto out;
}
+out_sleep:
+ wl1251_ps_elp_sleep(wl);
+
out:
mutex_unlock(&wl->mutex);
}
/* can't be const, mac80211 writes to this */
-static struct ieee80211_rate wl12xx_rates[] = {
+static struct ieee80211_rate wl1251_rates[] = {
{ .bitrate = 10,
.hw_value = 0x1,
.hw_value_short = 0x1, },
@@ -1088,7 +1237,7 @@ static struct ieee80211_rate wl12xx_rates[] = {
};
/* can't be const, mac80211 writes to this */
-static struct ieee80211_channel wl12xx_channels[] = {
+static struct ieee80211_channel wl1251_channels[] = {
{ .hw_value = 1, .center_freq = 2412},
{ .hw_value = 2, .center_freq = 2417},
{ .hw_value = 3, .center_freq = 2422},
@@ -1105,28 +1254,28 @@ static struct ieee80211_channel wl12xx_channels[] = {
};
/* can't be const, mac80211 writes to this */
-static struct ieee80211_supported_band wl12xx_band_2ghz = {
- .channels = wl12xx_channels,
- .n_channels = ARRAY_SIZE(wl12xx_channels),
- .bitrates = wl12xx_rates,
- .n_bitrates = ARRAY_SIZE(wl12xx_rates),
+static struct ieee80211_supported_band wl1251_band_2ghz = {
+ .channels = wl1251_channels,
+ .n_channels = ARRAY_SIZE(wl1251_channels),
+ .bitrates = wl1251_rates,
+ .n_bitrates = ARRAY_SIZE(wl1251_rates),
};
-static const struct ieee80211_ops wl12xx_ops = {
- .start = wl12xx_op_start,
- .stop = wl12xx_op_stop,
- .add_interface = wl12xx_op_add_interface,
- .remove_interface = wl12xx_op_remove_interface,
- .config = wl12xx_op_config,
- .configure_filter = wl12xx_op_configure_filter,
- .tx = wl12xx_op_tx,
- .set_key = wl12xx_op_set_key,
- .hw_scan = wl12xx_op_hw_scan,
- .bss_info_changed = wl12xx_op_bss_info_changed,
- .set_rts_threshold = wl12xx_op_set_rts_threshold,
+static const struct ieee80211_ops wl1251_ops = {
+ .start = wl1251_op_start,
+ .stop = wl1251_op_stop,
+ .add_interface = wl1251_op_add_interface,
+ .remove_interface = wl1251_op_remove_interface,
+ .config = wl1251_op_config,
+ .configure_filter = wl1251_op_configure_filter,
+ .tx = wl1251_op_tx,
+ .set_key = wl1251_op_set_key,
+ .hw_scan = wl1251_op_hw_scan,
+ .bss_info_changed = wl1251_op_bss_info_changed,
+ .set_rts_threshold = wl1251_op_set_rts_threshold,
};
-static int wl12xx_register_hw(struct wl12xx *wl)
+static int wl1251_register_hw(struct wl1251 *wl)
{
int ret;
@@ -1137,22 +1286,24 @@ static int wl12xx_register_hw(struct wl12xx *wl)
ret = ieee80211_register_hw(wl->hw);
if (ret < 0) {
- wl12xx_error("unable to register mac80211 hw: %d", ret);
+ wl1251_error("unable to register mac80211 hw: %d", ret);
return ret;
}
wl->mac80211_registered = true;
- wl12xx_notice("loaded");
+ wl1251_notice("loaded");
return 0;
}
-static int wl12xx_init_ieee80211(struct wl12xx *wl)
+int wl1251_init_ieee80211(struct wl1251 *wl)
{
+ int ret;
+
/* The tx descriptor buffer and the TKIP space */
wl->hw->extra_tx_headroom = sizeof(struct tx_double_buffer_desc)
- + WL12XX_TKIP_IV_SPACE;
+ + WL1251_TKIP_IV_SPACE;
/* unit us */
/* FIXME: find a proper value */
@@ -1163,48 +1314,46 @@ static int wl12xx_init_ieee80211(struct wl12xx *wl)
wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
wl->hw->wiphy->max_scan_ssids = 1;
- wl->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &wl12xx_band_2ghz;
+ wl->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &wl1251_band_2ghz;
- SET_IEEE80211_DEV(wl->hw, &wl->spi->dev);
+ ret = wl1251_register_hw(wl);
+ if (ret)
+ goto out;
- return 0;
+ wl1251_debugfs_init(wl);
+ wl1251_notice("initialized");
+
+ ret = 0;
+
+out:
+ return ret;
}
+EXPORT_SYMBOL_GPL(wl1251_init_ieee80211);
-#define WL12XX_DEFAULT_CHANNEL 1
-static int __devinit wl12xx_probe(struct spi_device *spi)
+struct ieee80211_hw *wl1251_alloc_hw(void)
{
- struct wl12xx_platform_data *pdata;
struct ieee80211_hw *hw;
- struct wl12xx *wl;
- int ret, i;
+ struct wl1251 *wl;
+ int i;
static const u8 nokia_oui[3] = {0x00, 0x1f, 0xdf};
- pdata = spi->dev.platform_data;
- if (!pdata) {
- wl12xx_error("no platform data");
- return -ENODEV;
- }
-
- hw = ieee80211_alloc_hw(sizeof(*wl), &wl12xx_ops);
+ hw = ieee80211_alloc_hw(sizeof(*wl), &wl1251_ops);
if (!hw) {
- wl12xx_error("could not alloc ieee80211_hw");
- return -ENOMEM;
+ wl1251_error("could not alloc ieee80211_hw");
+ return ERR_PTR(-ENOMEM);
}
wl = hw->priv;
memset(wl, 0, sizeof(*wl));
wl->hw = hw;
- dev_set_drvdata(&spi->dev, wl);
- wl->spi = spi;
wl->data_in_count = 0;
skb_queue_head_init(&wl->tx_queue);
- INIT_WORK(&wl->tx_work, wl12xx_tx_work);
- INIT_WORK(&wl->filter_work, wl12xx_filter_work);
- wl->channel = WL12XX_DEFAULT_CHANNEL;
+ INIT_WORK(&wl->filter_work, wl1251_filter_work);
+ wl->channel = WL1251_DEFAULT_CHANNEL;
wl->scanning = false;
wl->default_key = 0;
wl->listen_int = 1;
@@ -1212,23 +1361,24 @@ static int __devinit wl12xx_probe(struct spi_device *spi)
wl->rx_handled = 0;
wl->rx_current_buffer = 0;
wl->rx_last_id = 0;
- wl->rx_config = WL12XX_DEFAULT_RX_CONFIG;
- wl->rx_filter = WL12XX_DEFAULT_RX_FILTER;
+ wl->rx_config = WL1251_DEFAULT_RX_CONFIG;
+ wl->rx_filter = WL1251_DEFAULT_RX_FILTER;
wl->elp = false;
wl->psm = 0;
wl->psm_requested = false;
wl->tx_queue_stopped = false;
- wl->power_level = WL12XX_DEFAULT_POWER_LEVEL;
-
- /* We use the default power on sleep time until we know which chip
- * we're using */
- wl->chip.power_on_sleep = WL12XX_DEFAULT_POWER_ON_SLEEP;
+ wl->power_level = WL1251_DEFAULT_POWER_LEVEL;
+ wl->beacon_int = WL1251_DEFAULT_BEACON_INT;
+ wl->dtim_period = WL1251_DEFAULT_DTIM_PERIOD;
for (i = 0; i < FW_TX_CMPLT_BLOCK_SIZE; i++)
wl->tx_frames[i] = NULL;
wl->next_tx_complete = 0;
+ INIT_WORK(&wl->irq_work, wl1251_irq_work);
+ INIT_WORK(&wl->tx_work, wl1251_tx_work);
+
/*
* In case our MAC address is not correctly set,
* we use a random but Nokia MAC.
@@ -1236,123 +1386,45 @@ static int __devinit wl12xx_probe(struct spi_device *spi)
memcpy(wl->mac_addr, nokia_oui, 3);
get_random_bytes(wl->mac_addr + 3, 3);
- wl->state = WL12XX_STATE_OFF;
+ wl->state = WL1251_STATE_OFF;
mutex_init(&wl->mutex);
wl->tx_mgmt_frm_rate = DEFAULT_HW_GEN_TX_RATE;
wl->tx_mgmt_frm_mod = DEFAULT_HW_GEN_MODULATION_TYPE;
- /* This is the only SPI value that we need to set here, the rest
- * comes from the board-peripherals file */
- spi->bits_per_word = 32;
-
- ret = spi_setup(spi);
- if (ret < 0) {
- wl12xx_error("spi_setup failed");
- goto out_free;
- }
-
- wl->set_power = pdata->set_power;
- if (!wl->set_power) {
- wl12xx_error("set power function missing in platform data");
- return -ENODEV;
- }
-
- wl->irq = spi->irq;
- if (wl->irq < 0) {
- wl12xx_error("irq missing in platform data");
- return -ENODEV;
- }
-
- ret = request_irq(wl->irq, wl12xx_irq, 0, DRIVER_NAME, wl);
- if (ret < 0) {
- wl12xx_error("request_irq() failed: %d", ret);
- goto out_free;
+ wl->rx_descriptor = kmalloc(sizeof(*wl->rx_descriptor), GFP_KERNEL);
+ if (!wl->rx_descriptor) {
+ wl1251_error("could not allocate memory for rx descriptor");
+ ieee80211_free_hw(hw);
+ return ERR_PTR(-ENOMEM);
}
- set_irq_type(wl->irq, IRQ_TYPE_EDGE_RISING);
-
- disable_irq(wl->irq);
-
- ret = wl12xx_init_ieee80211(wl);
- if (ret)
- goto out_irq;
-
- ret = wl12xx_register_hw(wl);
- if (ret)
- goto out_irq;
-
- wl12xx_debugfs_init(wl);
-
- wl12xx_notice("initialized");
-
- return 0;
-
- out_irq:
- free_irq(wl->irq, wl);
-
- out_free:
- ieee80211_free_hw(hw);
-
- return ret;
+ return hw;
}
+EXPORT_SYMBOL_GPL(wl1251_alloc_hw);
-static int __devexit wl12xx_remove(struct spi_device *spi)
+int wl1251_free_hw(struct wl1251 *wl)
{
- struct wl12xx *wl = dev_get_drvdata(&spi->dev);
-
ieee80211_unregister_hw(wl->hw);
- wl12xx_debugfs_exit(wl);
+ wl1251_debugfs_exit(wl);
- free_irq(wl->irq, wl);
kfree(wl->target_mem_map);
kfree(wl->data_path);
kfree(wl->fw);
wl->fw = NULL;
kfree(wl->nvs);
wl->nvs = NULL;
- ieee80211_free_hw(wl->hw);
-
- return 0;
-}
-
-static struct spi_driver wl12xx_spi_driver = {
- .driver = {
- .name = "wl12xx",
- .bus = &spi_bus_type,
- .owner = THIS_MODULE,
- },
+ kfree(wl->rx_descriptor);
+ wl->rx_descriptor = NULL;
- .probe = wl12xx_probe,
- .remove = __devexit_p(wl12xx_remove),
-};
-
-static int __init wl12xx_init(void)
-{
- int ret;
-
- ret = spi_register_driver(&wl12xx_spi_driver);
- if (ret < 0) {
- wl12xx_error("failed to register spi driver: %d", ret);
- goto out;
- }
-
-out:
- return ret;
-}
-
-static void __exit wl12xx_exit(void)
-{
- spi_unregister_driver(&wl12xx_spi_driver);
+ ieee80211_free_hw(wl->hw);
- wl12xx_notice("unloaded");
+ return 0;
}
+EXPORT_SYMBOL_GPL(wl1251_free_hw);
-module_init(wl12xx_init);
-module_exit(wl12xx_exit);
-
+MODULE_DESCRIPTION("TI wl1251 Wireles LAN Driver Core");
MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Kalle Valo <Kalle.Valo@nokia.com>, "
- "Luciano Coelho <luciano.coelho@nokia.com>");
+MODULE_AUTHOR("Kalle Valo <kalle.valo@nokia.com>");
diff --git a/drivers/net/wireless/wl12xx/init.h b/drivers/net/wireless/wl12xx/wl1251_netlink.h
index c8b6cd0b7c3..ee36695e134 100644
--- a/drivers/net/wireless/wl12xx/init.h
+++ b/drivers/net/wireless/wl12xx/wl1251_netlink.h
@@ -1,5 +1,5 @@
/*
- * This file is part of wl12xx
+ * This file is part of wl1251
*
* Copyright (C) 2009 Nokia Corporation
*
@@ -21,20 +21,10 @@
*
*/
-#ifndef __WL12XX_INIT_H__
-#define __WL12XX_INIT_H__
+#ifndef __WL1251_NETLINK_H__
+#define __WL1251_NETLINK_H__
-#include "wl12xx.h"
+int wl1251_nl_register(void);
+void wl1251_nl_unregister(void);
-int wl12xx_hw_init_hwenc_config(struct wl12xx *wl);
-int wl12xx_hw_init_templates_config(struct wl12xx *wl);
-int wl12xx_hw_init_mem_config(struct wl12xx *wl);
-int wl12xx_hw_init_rx_config(struct wl12xx *wl, u32 config, u32 filter);
-int wl12xx_hw_init_phy_config(struct wl12xx *wl);
-int wl12xx_hw_init_beacon_filter(struct wl12xx *wl);
-int wl12xx_hw_init_pta(struct wl12xx *wl);
-int wl12xx_hw_init_energy_detection(struct wl12xx *wl);
-int wl12xx_hw_init_beacon_broadcast(struct wl12xx *wl);
-int wl12xx_hw_init_power_auth(struct wl12xx *wl);
-
-#endif
+#endif /* __WL1251_NETLINK_H__ */
diff --git a/drivers/net/wireless/wl12xx/ps.c b/drivers/net/wireless/wl12xx/wl1251_ps.c
index 83a10117330..c53e28727ed 100644
--- a/drivers/net/wireless/wl12xx/ps.c
+++ b/drivers/net/wireless/wl12xx/wl1251_ps.c
@@ -1,5 +1,5 @@
/*
- * This file is part of wl12xx
+ * This file is part of wl1251
*
* Copyright (C) 2008 Nokia Corporation
*
@@ -21,26 +21,27 @@
*
*/
-#include "reg.h"
-#include "ps.h"
-#include "spi.h"
+#include "wl1251_reg.h"
+#include "wl1251_ps.h"
+#include "wl1251_cmd.h"
+#include "wl1251_io.h"
-#define WL12XX_WAKEUP_TIMEOUT 2000
+#define WL1251_WAKEUP_TIMEOUT 2000
/* Routines to toggle sleep mode while in ELP */
-void wl12xx_ps_elp_sleep(struct wl12xx *wl)
+void wl1251_ps_elp_sleep(struct wl1251 *wl)
{
if (wl->elp || !wl->psm)
return;
- wl12xx_debug(DEBUG_PSM, "chip to elp");
+ wl1251_debug(DEBUG_PSM, "chip to elp");
- wl12xx_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, ELPCTRL_SLEEP);
+ wl1251_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, ELPCTRL_SLEEP);
wl->elp = true;
}
-int wl12xx_ps_elp_wakeup(struct wl12xx *wl)
+int wl1251_ps_elp_wakeup(struct wl1251 *wl)
{
unsigned long timeout;
u32 elp_reg;
@@ -48,13 +49,13 @@ int wl12xx_ps_elp_wakeup(struct wl12xx *wl)
if (!wl->elp)
return 0;
- wl12xx_debug(DEBUG_PSM, "waking up chip from elp");
+ wl1251_debug(DEBUG_PSM, "waking up chip from elp");
- timeout = jiffies + msecs_to_jiffies(WL12XX_WAKEUP_TIMEOUT);
+ timeout = jiffies + msecs_to_jiffies(WL1251_WAKEUP_TIMEOUT);
- wl12xx_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, ELPCTRL_WAKE_UP);
+ wl1251_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, ELPCTRL_WAKE_UP);
- elp_reg = wl12xx_read32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR);
+ elp_reg = wl1251_read32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR);
/*
* FIXME: we should wait for irq from chip but, as a temporary
@@ -62,40 +63,36 @@ int wl12xx_ps_elp_wakeup(struct wl12xx *wl)
*/
while (!(elp_reg & ELPCTRL_WLAN_READY)) {
if (time_after(jiffies, timeout)) {
- wl12xx_error("elp wakeup timeout");
+ wl1251_error("elp wakeup timeout");
return -ETIMEDOUT;
}
msleep(1);
- elp_reg = wl12xx_read32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR);
+ elp_reg = wl1251_read32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR);
}
- wl12xx_debug(DEBUG_PSM, "wakeup time: %u ms",
+ wl1251_debug(DEBUG_PSM, "wakeup time: %u ms",
jiffies_to_msecs(jiffies) -
- (jiffies_to_msecs(timeout) - WL12XX_WAKEUP_TIMEOUT));
+ (jiffies_to_msecs(timeout) - WL1251_WAKEUP_TIMEOUT));
wl->elp = false;
return 0;
}
-static int wl12xx_ps_set_elp(struct wl12xx *wl, bool enable)
+static int wl1251_ps_set_elp(struct wl1251 *wl, bool enable)
{
int ret;
if (enable) {
- wl12xx_debug(DEBUG_PSM, "sleep auth psm/elp");
+ wl1251_debug(DEBUG_PSM, "sleep auth psm/elp");
- /*
- * FIXME: we should PSM_ELP, but because of firmware wakeup
- * problems let's use only PSM_PS
- */
- ret = wl12xx_acx_sleep_auth(wl, WL12XX_PSM_PS);
+ ret = wl1251_acx_sleep_auth(wl, WL1251_PSM_ELP);
if (ret < 0)
return ret;
- wl12xx_ps_elp_sleep(wl);
+ wl1251_ps_elp_sleep(wl);
} else {
- wl12xx_debug(DEBUG_PSM, "sleep auth cam");
+ wl1251_debug(DEBUG_PSM, "sleep auth cam");
/*
* When the target is in ELP, we can only
@@ -104,9 +101,9 @@ static int wl12xx_ps_set_elp(struct wl12xx *wl, bool enable)
* changing the power authorization.
*/
- wl12xx_ps_elp_wakeup(wl);
+ wl1251_ps_elp_wakeup(wl);
- ret = wl12xx_acx_sleep_auth(wl, WL12XX_PSM_CAM);
+ ret = wl1251_acx_sleep_auth(wl, WL1251_PSM_CAM);
if (ret < 0)
return ret;
}
@@ -114,18 +111,25 @@ static int wl12xx_ps_set_elp(struct wl12xx *wl, bool enable)
return 0;
}
-int wl12xx_ps_set_mode(struct wl12xx *wl, enum acx_ps_mode mode)
+int wl1251_ps_set_mode(struct wl1251 *wl, enum wl1251_cmd_ps_mode mode)
{
int ret;
switch (mode) {
case STATION_POWER_SAVE_MODE:
- wl12xx_debug(DEBUG_PSM, "entering psm");
- ret = wl12xx_cmd_ps_mode(wl, STATION_POWER_SAVE_MODE);
+ wl1251_debug(DEBUG_PSM, "entering psm");
+
+ ret = wl1251_acx_wake_up_conditions(wl,
+ WAKE_UP_EVENT_DTIM_BITMAP,
+ wl->listen_int);
if (ret < 0)
return ret;
- ret = wl12xx_ps_set_elp(wl, true);
+ ret = wl1251_cmd_ps_mode(wl, STATION_POWER_SAVE_MODE);
+ if (ret < 0)
+ return ret;
+
+ ret = wl1251_ps_set_elp(wl, true);
if (ret < 0)
return ret;
@@ -133,12 +137,18 @@ int wl12xx_ps_set_mode(struct wl12xx *wl, enum acx_ps_mode mode)
break;
case STATION_ACTIVE_MODE:
default:
- wl12xx_debug(DEBUG_PSM, "leaving psm");
- ret = wl12xx_ps_set_elp(wl, false);
+ wl1251_debug(DEBUG_PSM, "leaving psm");
+ ret = wl1251_ps_set_elp(wl, false);
+ if (ret < 0)
+ return ret;
+
+ ret = wl1251_acx_wake_up_conditions(wl,
+ WAKE_UP_EVENT_DTIM_BITMAP,
+ wl->listen_int);
if (ret < 0)
return ret;
- ret = wl12xx_cmd_ps_mode(wl, STATION_ACTIVE_MODE);
+ ret = wl1251_cmd_ps_mode(wl, STATION_ACTIVE_MODE);
if (ret < 0)
return ret;
diff --git a/drivers/net/wireless/wl12xx/ps.h b/drivers/net/wireless/wl12xx/wl1251_ps.h
index 5d7c5255383..db036fe12f2 100644
--- a/drivers/net/wireless/wl12xx/ps.h
+++ b/drivers/net/wireless/wl12xx/wl1251_ps.h
@@ -1,8 +1,8 @@
-#ifndef __WL12XX_PS_H__
-#define __WL12XX_PS_H__
+#ifndef __WL1251_PS_H__
+#define __WL1251_PS_H__
/*
- * This file is part of wl12xx
+ * This file is part of wl1251
*
* Copyright (c) 1998-2007 Texas Instruments Incorporated
* Copyright (C) 2008 Nokia Corporation
@@ -25,12 +25,12 @@
*
*/
-#include "wl12xx.h"
-#include "acx.h"
+#include "wl1251.h"
+#include "wl1251_acx.h"
-int wl12xx_ps_set_mode(struct wl12xx *wl, enum acx_ps_mode mode);
-void wl12xx_ps_elp_sleep(struct wl12xx *wl);
-int wl12xx_ps_elp_wakeup(struct wl12xx *wl);
+int wl1251_ps_set_mode(struct wl1251 *wl, enum wl1251_cmd_ps_mode mode);
+void wl1251_ps_elp_sleep(struct wl1251 *wl);
+int wl1251_ps_elp_wakeup(struct wl1251 *wl);
-#endif /* __WL12XX_PS_H__ */
+#endif /* __WL1251_PS_H__ */
diff --git a/drivers/net/wireless/wl12xx/wl1251_reg.h b/drivers/net/wireless/wl12xx/wl1251_reg.h
new file mode 100644
index 00000000000..bdd561001dc
--- /dev/null
+++ b/drivers/net/wireless/wl12xx/wl1251_reg.h
@@ -0,0 +1,644 @@
+/*
+ * This file is part of wl12xx
+ *
+ * Copyright (c) 1998-2007 Texas Instruments Incorporated
+ * Copyright (C) 2008 Nokia Corporation
+ *
+ * Contact: Kalle Valo <kalle.valo@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef __REG_H__
+#define __REG_H__
+
+#include <linux/bitops.h>
+
+#define REGISTERS_BASE 0x00300000
+#define DRPW_BASE 0x00310000
+
+#define REGISTERS_DOWN_SIZE 0x00008800
+#define REGISTERS_WORK_SIZE 0x0000b000
+
+#define HW_ACCESS_ELP_CTRL_REG_ADDR 0x1FFFC
+
+/* ELP register commands */
+#define ELPCTRL_WAKE_UP 0x1
+#define ELPCTRL_WAKE_UP_WLAN_READY 0x5
+#define ELPCTRL_SLEEP 0x0
+/* ELP WLAN_READY bit */
+#define ELPCTRL_WLAN_READY 0x2
+
+/* Device Configuration registers*/
+#define SOR_CFG (REGISTERS_BASE + 0x0800)
+#define ECPU_CTRL (REGISTERS_BASE + 0x0804)
+#define HI_CFG (REGISTERS_BASE + 0x0808)
+#define EE_START (REGISTERS_BASE + 0x080C)
+
+#define CHIP_ID_B (REGISTERS_BASE + 0x5674)
+
+#define CHIP_ID_1251_PG10 (0x7010101)
+#define CHIP_ID_1251_PG11 (0x7020101)
+#define CHIP_ID_1251_PG12 (0x7030101)
+
+#define ENABLE (REGISTERS_BASE + 0x5450)
+
+/* Power Management registers */
+#define ELP_CFG_MODE (REGISTERS_BASE + 0x5804)
+#define ELP_CMD (REGISTERS_BASE + 0x5808)
+#define PLL_CAL_TIME (REGISTERS_BASE + 0x5810)
+#define CLK_REQ_TIME (REGISTERS_BASE + 0x5814)
+#define CLK_BUF_TIME (REGISTERS_BASE + 0x5818)
+
+#define CFG_PLL_SYNC_CNT (REGISTERS_BASE + 0x5820)
+
+/* Scratch Pad registers*/
+#define SCR_PAD0 (REGISTERS_BASE + 0x5608)
+#define SCR_PAD1 (REGISTERS_BASE + 0x560C)
+#define SCR_PAD2 (REGISTERS_BASE + 0x5610)
+#define SCR_PAD3 (REGISTERS_BASE + 0x5614)
+#define SCR_PAD4 (REGISTERS_BASE + 0x5618)
+#define SCR_PAD4_SET (REGISTERS_BASE + 0x561C)
+#define SCR_PAD4_CLR (REGISTERS_BASE + 0x5620)
+#define SCR_PAD5 (REGISTERS_BASE + 0x5624)
+#define SCR_PAD5_SET (REGISTERS_BASE + 0x5628)
+#define SCR_PAD5_CLR (REGISTERS_BASE + 0x562C)
+#define SCR_PAD6 (REGISTERS_BASE + 0x5630)
+#define SCR_PAD7 (REGISTERS_BASE + 0x5634)
+#define SCR_PAD8 (REGISTERS_BASE + 0x5638)
+#define SCR_PAD9 (REGISTERS_BASE + 0x563C)
+
+/* Spare registers*/
+#define SPARE_A1 (REGISTERS_BASE + 0x0994)
+#define SPARE_A2 (REGISTERS_BASE + 0x0998)
+#define SPARE_A3 (REGISTERS_BASE + 0x099C)
+#define SPARE_A4 (REGISTERS_BASE + 0x09A0)
+#define SPARE_A5 (REGISTERS_BASE + 0x09A4)
+#define SPARE_A6 (REGISTERS_BASE + 0x09A8)
+#define SPARE_A7 (REGISTERS_BASE + 0x09AC)
+#define SPARE_A8 (REGISTERS_BASE + 0x09B0)
+#define SPARE_B1 (REGISTERS_BASE + 0x5420)
+#define SPARE_B2 (REGISTERS_BASE + 0x5424)
+#define SPARE_B3 (REGISTERS_BASE + 0x5428)
+#define SPARE_B4 (REGISTERS_BASE + 0x542C)
+#define SPARE_B5 (REGISTERS_BASE + 0x5430)
+#define SPARE_B6 (REGISTERS_BASE + 0x5434)
+#define SPARE_B7 (REGISTERS_BASE + 0x5438)
+#define SPARE_B8 (REGISTERS_BASE + 0x543C)
+
+enum wl12xx_acx_int_reg {
+ ACX_REG_INTERRUPT_TRIG,
+ ACX_REG_INTERRUPT_TRIG_H,
+
+/*=============================================
+ Host Interrupt Mask Register - 32bit (RW)
+ ------------------------------------------
+ Setting a bit in this register masks the
+ corresponding interrupt to the host.
+ 0 - RX0 - Rx first dubble buffer Data Interrupt
+ 1 - TXD - Tx Data Interrupt
+ 2 - TXXFR - Tx Transfer Interrupt
+ 3 - RX1 - Rx second dubble buffer Data Interrupt
+ 4 - RXXFR - Rx Transfer Interrupt
+ 5 - EVENT_A - Event Mailbox interrupt
+ 6 - EVENT_B - Event Mailbox interrupt
+ 7 - WNONHST - Wake On Host Interrupt
+ 8 - TRACE_A - Debug Trace interrupt
+ 9 - TRACE_B - Debug Trace interrupt
+ 10 - CDCMP - Command Complete Interrupt
+ 11 -
+ 12 -
+ 13 -
+ 14 - ICOMP - Initialization Complete Interrupt
+ 16 - SG SE - Soft Gemini - Sense enable interrupt
+ 17 - SG SD - Soft Gemini - Sense disable interrupt
+ 18 - -
+ 19 - -
+ 20 - -
+ 21- -
+ Default: 0x0001
+*==============================================*/
+ ACX_REG_INTERRUPT_MASK,
+
+/*=============================================
+ Host Interrupt Mask Set 16bit, (Write only)
+ ------------------------------------------
+ Setting a bit in this register sets
+ the corresponding bin in ACX_HINT_MASK register
+ without effecting the mask
+ state of other bits (0 = no effect).
+==============================================*/
+ ACX_REG_HINT_MASK_SET,
+
+/*=============================================
+ Host Interrupt Mask Clear 16bit,(Write only)
+ ------------------------------------------
+ Setting a bit in this register clears
+ the corresponding bin in ACX_HINT_MASK register
+ without effecting the mask
+ state of other bits (0 = no effect).
+=============================================*/
+ ACX_REG_HINT_MASK_CLR,
+
+/*=============================================
+ Host Interrupt Status Nondestructive Read
+ 16bit,(Read only)
+ ------------------------------------------
+ The host can read this register to determine
+ which interrupts are active.
+ Reading this register doesn't
+ effect its content.
+=============================================*/
+ ACX_REG_INTERRUPT_NO_CLEAR,
+
+/*=============================================
+ Host Interrupt Status Clear on Read Register
+ 16bit,(Read only)
+ ------------------------------------------
+ The host can read this register to determine
+ which interrupts are active.
+ Reading this register clears it,
+ thus making all interrupts inactive.
+==============================================*/
+ ACX_REG_INTERRUPT_CLEAR,
+
+/*=============================================
+ Host Interrupt Acknowledge Register
+ 16bit,(Write only)
+ ------------------------------------------
+ The host can set individual bits in this
+ register to clear (acknowledge) the corresp.
+ interrupt status bits in the HINT_STS_CLR and
+ HINT_STS_ND registers, thus making the
+ assotiated interrupt inactive. (0-no effect)
+==============================================*/
+ ACX_REG_INTERRUPT_ACK,
+
+/*===============================================
+ Host Software Reset - 32bit RW
+ ------------------------------------------
+ [31:1] Reserved
+ 0 SOFT_RESET Soft Reset - When this bit is set,
+ it holds the Wlan hardware in a soft reset state.
+ This reset disables all MAC and baseband processor
+ clocks except the CardBus/PCI interface clock.
+ It also initializes all MAC state machines except
+ the host interface. It does not reload the
+ contents of the EEPROM. When this bit is cleared
+ (not self-clearing), the Wlan hardware
+ exits the software reset state.
+===============================================*/
+ ACX_REG_SLV_SOFT_RESET,
+
+/*===============================================
+ EEPROM Burst Read Start - 32bit RW
+ ------------------------------------------
+ [31:1] Reserved
+ 0 ACX_EE_START - EEPROM Burst Read Start 0
+ Setting this bit starts a burst read from
+ the external EEPROM.
+ If this bit is set (after reset) before an EEPROM read/write,
+ the burst read starts at EEPROM address 0.
+ Otherwise, it starts at the address
+ following the address of the previous access.
+ TheWlan hardware hardware clears this bit automatically.
+
+ Default: 0x00000000
+*================================================*/
+ ACX_REG_EE_START,
+
+/* Embedded ARM CPU Control */
+
+/*===============================================
+ Halt eCPU - 32bit RW
+ ------------------------------------------
+ 0 HALT_ECPU Halt Embedded CPU - This bit is the
+ compliment of bit 1 (MDATA2) in the SOR_CFG register.
+ During a hardware reset, this bit holds
+ the inverse of MDATA2.
+ When downloading firmware from the host,
+ set this bit (pull down MDATA2).
+ The host clears this bit after downloading the firmware into
+ zero-wait-state SSRAM.
+ When loading firmware from Flash, clear this bit (pull up MDATA2)
+ so that the eCPU can run the bootloader code in Flash
+ HALT_ECPU eCPU State
+ --------------------
+ 1 halt eCPU
+ 0 enable eCPU
+ ===============================================*/
+ ACX_REG_ECPU_CONTROL,
+
+ ACX_REG_TABLE_LEN
+};
+
+#define ACX_SLV_SOFT_RESET_BIT BIT(1)
+#define ACX_REG_EEPROM_START_BIT BIT(1)
+
+/* Command/Information Mailbox Pointers */
+
+/*===============================================
+ Command Mailbox Pointer - 32bit RW
+ ------------------------------------------
+ This register holds the start address of
+ the command mailbox located in the Wlan hardware memory.
+ The host must read this pointer after a reset to
+ find the location of the command mailbox.
+ The Wlan hardware initializes the command mailbox
+ pointer with the default address of the command mailbox.
+ The command mailbox pointer is not valid until after
+ the host receives the Init Complete interrupt from
+ the Wlan hardware.
+ ===============================================*/
+#define REG_COMMAND_MAILBOX_PTR (SCR_PAD0)
+
+/*===============================================
+ Information Mailbox Pointer - 32bit RW
+ ------------------------------------------
+ This register holds the start address of
+ the information mailbox located in the Wlan hardware memory.
+ The host must read this pointer after a reset to find
+ the location of the information mailbox.
+ The Wlan hardware initializes the information mailbox pointer
+ with the default address of the information mailbox.
+ The information mailbox pointer is not valid
+ until after the host receives the Init Complete interrupt from
+ the Wlan hardware.
+ ===============================================*/
+#define REG_EVENT_MAILBOX_PTR (SCR_PAD1)
+
+
+/* Misc */
+
+#define REG_ENABLE_TX_RX (ENABLE)
+/*
+ * Rx configuration (filter) information element
+ * ---------------------------------------------
+ */
+#define REG_RX_CONFIG (RX_CFG)
+#define REG_RX_FILTER (RX_FILTER_CFG)
+
+
+#define RX_CFG_ENABLE_PHY_HEADER_PLCP 0x0002
+
+/* promiscuous - receives all valid frames */
+#define RX_CFG_PROMISCUOUS 0x0008
+
+/* receives frames from any BSSID */
+#define RX_CFG_BSSID 0x0020
+
+/* receives frames destined to any MAC address */
+#define RX_CFG_MAC 0x0010
+
+#define RX_CFG_ENABLE_ONLY_MY_DEST_MAC 0x0010
+#define RX_CFG_ENABLE_ANY_DEST_MAC 0x0000
+#define RX_CFG_ENABLE_ONLY_MY_BSSID 0x0020
+#define RX_CFG_ENABLE_ANY_BSSID 0x0000
+
+/* discards all broadcast frames */
+#define RX_CFG_DISABLE_BCAST 0x0200
+
+#define RX_CFG_ENABLE_ONLY_MY_SSID 0x0400
+#define RX_CFG_ENABLE_RX_CMPLT_FCS_ERROR 0x0800
+#define RX_CFG_COPY_RX_STATUS 0x2000
+#define RX_CFG_TSF 0x10000
+
+#define RX_CONFIG_OPTION_ANY_DST_MY_BSS (RX_CFG_ENABLE_ANY_DEST_MAC | \
+ RX_CFG_ENABLE_ONLY_MY_BSSID)
+
+#define RX_CONFIG_OPTION_MY_DST_ANY_BSS (RX_CFG_ENABLE_ONLY_MY_DEST_MAC\
+ | RX_CFG_ENABLE_ANY_BSSID)
+
+#define RX_CONFIG_OPTION_ANY_DST_ANY_BSS (RX_CFG_ENABLE_ANY_DEST_MAC | \
+ RX_CFG_ENABLE_ANY_BSSID)
+
+#define RX_CONFIG_OPTION_MY_DST_MY_BSS (RX_CFG_ENABLE_ONLY_MY_DEST_MAC\
+ | RX_CFG_ENABLE_ONLY_MY_BSSID)
+
+#define RX_CONFIG_OPTION_FOR_SCAN (RX_CFG_ENABLE_PHY_HEADER_PLCP \
+ | RX_CFG_ENABLE_RX_CMPLT_FCS_ERROR \
+ | RX_CFG_COPY_RX_STATUS | RX_CFG_TSF)
+
+#define RX_CONFIG_OPTION_FOR_MEASUREMENT (RX_CFG_ENABLE_ANY_DEST_MAC)
+
+#define RX_CONFIG_OPTION_FOR_JOIN (RX_CFG_ENABLE_ONLY_MY_BSSID | \
+ RX_CFG_ENABLE_ONLY_MY_DEST_MAC)
+
+#define RX_CONFIG_OPTION_FOR_IBSS_JOIN (RX_CFG_ENABLE_ONLY_MY_SSID | \
+ RX_CFG_ENABLE_ONLY_MY_DEST_MAC)
+
+#define RX_FILTER_OPTION_DEF (CFG_RX_MGMT_EN | CFG_RX_DATA_EN\
+ | CFG_RX_CTL_EN | CFG_RX_BCN_EN\
+ | CFG_RX_AUTH_EN | CFG_RX_ASSOC_EN)
+
+#define RX_FILTER_OPTION_FILTER_ALL 0
+
+#define RX_FILTER_OPTION_DEF_PRSP_BCN (CFG_RX_PRSP_EN | CFG_RX_MGMT_EN\
+ | CFG_RX_RCTS_ACK | CFG_RX_BCN_EN)
+
+#define RX_FILTER_OPTION_JOIN (CFG_RX_MGMT_EN | CFG_RX_DATA_EN\
+ | CFG_RX_BCN_EN | CFG_RX_AUTH_EN\
+ | CFG_RX_ASSOC_EN | CFG_RX_RCTS_ACK\
+ | CFG_RX_PRSP_EN)
+
+
+/*===============================================
+ EEPROM Read/Write Request 32bit RW
+ ------------------------------------------
+ 1 EE_READ - EEPROM Read Request 1 - Setting this bit
+ loads a single byte of data into the EE_DATA
+ register from the EEPROM location specified in
+ the EE_ADDR register.
+ The Wlan hardware hardware clears this bit automatically.
+ EE_DATA is valid when this bit is cleared.
+
+ 0 EE_WRITE - EEPROM Write Request - Setting this bit
+ writes a single byte of data from the EE_DATA register into the
+ EEPROM location specified in the EE_ADDR register.
+ The Wlan hardware hardware clears this bit automatically.
+*===============================================*/
+#define ACX_EE_CTL_REG EE_CTL
+#define EE_WRITE 0x00000001ul
+#define EE_READ 0x00000002ul
+
+/*===============================================
+ EEPROM Address - 32bit RW
+ ------------------------------------------
+ This register specifies the address
+ within the EEPROM from/to which to read/write data.
+ ===============================================*/
+#define ACX_EE_ADDR_REG EE_ADDR
+
+/*===============================================
+ EEPROM Data - 32bit RW
+ ------------------------------------------
+ This register either holds the read 8 bits of
+ data from the EEPROM or the write data
+ to be written to the EEPROM.
+ ===============================================*/
+#define ACX_EE_DATA_REG EE_DATA
+
+/*===============================================
+ EEPROM Base Address - 32bit RW
+ ------------------------------------------
+ This register holds the upper nine bits
+ [23:15] of the 24-bit Wlan hardware memory
+ address for burst reads from EEPROM accesses.
+ The EEPROM provides the lower 15 bits of this address.
+ The MSB of the address from the EEPROM is ignored.
+ ===============================================*/
+#define ACX_EE_CFG EE_CFG
+
+/*===============================================
+ GPIO Output Values -32bit, RW
+ ------------------------------------------
+ [31:16] Reserved
+ [15: 0] Specify the output values (at the output driver inputs) for
+ GPIO[15:0], respectively.
+ ===============================================*/
+#define ACX_GPIO_OUT_REG GPIO_OUT
+#define ACX_MAX_GPIO_LINES 15
+
+/*===============================================
+ Contention window -32bit, RW
+ ------------------------------------------
+ [31:26] Reserved
+ [25:16] Max (0x3ff)
+ [15:07] Reserved
+ [06:00] Current contention window value - default is 0x1F
+ ===============================================*/
+#define ACX_CONT_WIND_CFG_REG CONT_WIND_CFG
+#define ACX_CONT_WIND_MIN_MASK 0x0000007f
+#define ACX_CONT_WIND_MAX 0x03ff0000
+
+/*===============================================
+ HI_CFG Interface Configuration Register Values
+ ------------------------------------------
+ ===============================================*/
+#define HI_CFG_UART_ENABLE 0x00000004
+#define HI_CFG_RST232_ENABLE 0x00000008
+#define HI_CFG_CLOCK_REQ_SELECT 0x00000010
+#define HI_CFG_HOST_INT_ENABLE 0x00000020
+#define HI_CFG_VLYNQ_OUTPUT_ENABLE 0x00000040
+#define HI_CFG_HOST_INT_ACTIVE_LOW 0x00000080
+#define HI_CFG_UART_TX_OUT_GPIO_15 0x00000100
+#define HI_CFG_UART_TX_OUT_GPIO_14 0x00000200
+#define HI_CFG_UART_TX_OUT_GPIO_7 0x00000400
+
+/*
+ * NOTE: USE_ACTIVE_HIGH compilation flag should be defined in makefile
+ * for platforms using active high interrupt level
+ */
+#ifdef USE_ACTIVE_HIGH
+#define HI_CFG_DEF_VAL \
+ (HI_CFG_UART_ENABLE | \
+ HI_CFG_RST232_ENABLE | \
+ HI_CFG_CLOCK_REQ_SELECT | \
+ HI_CFG_HOST_INT_ENABLE)
+#else
+#define HI_CFG_DEF_VAL \
+ (HI_CFG_UART_ENABLE | \
+ HI_CFG_RST232_ENABLE | \
+ HI_CFG_CLOCK_REQ_SELECT | \
+ HI_CFG_HOST_INT_ENABLE)
+
+#endif
+
+#define REF_FREQ_19_2 0
+#define REF_FREQ_26_0 1
+#define REF_FREQ_38_4 2
+#define REF_FREQ_40_0 3
+#define REF_FREQ_33_6 4
+#define REF_FREQ_NUM 5
+
+#define LUT_PARAM_INTEGER_DIVIDER 0
+#define LUT_PARAM_FRACTIONAL_DIVIDER 1
+#define LUT_PARAM_ATTN_BB 2
+#define LUT_PARAM_ALPHA_BB 3
+#define LUT_PARAM_STOP_TIME_BB 4
+#define LUT_PARAM_BB_PLL_LOOP_FILTER 5
+#define LUT_PARAM_NUM 6
+
+#define ACX_EEPROMLESS_IND_REG (SCR_PAD4)
+#define USE_EEPROM 0
+#define SOFT_RESET_MAX_TIME 1000000
+#define SOFT_RESET_STALL_TIME 1000
+#define NVS_DATA_BUNDARY_ALIGNMENT 4
+
+
+/* Firmware image load chunk size */
+#define CHUNK_SIZE 512
+
+/* Firmware image header size */
+#define FW_HDR_SIZE 8
+
+#define ECPU_CONTROL_HALT 0x00000101
+
+
+/******************************************************************************
+
+ CHANNELS, BAND & REG DOMAINS definitions
+
+******************************************************************************/
+
+
+enum {
+ RADIO_BAND_2_4GHZ = 0, /* 2.4 Ghz band */
+ RADIO_BAND_5GHZ = 1, /* 5 Ghz band */
+ RADIO_BAND_JAPAN_4_9_GHZ = 2,
+ DEFAULT_BAND = RADIO_BAND_2_4GHZ,
+ INVALID_BAND = 0xFE,
+ MAX_RADIO_BANDS = 0xFF
+};
+
+enum {
+ NO_RATE = 0,
+ RATE_1MBPS = 0x0A,
+ RATE_2MBPS = 0x14,
+ RATE_5_5MBPS = 0x37,
+ RATE_6MBPS = 0x0B,
+ RATE_9MBPS = 0x0F,
+ RATE_11MBPS = 0x6E,
+ RATE_12MBPS = 0x0A,
+ RATE_18MBPS = 0x0E,
+ RATE_22MBPS = 0xDC,
+ RATE_24MBPS = 0x09,
+ RATE_36MBPS = 0x0D,
+ RATE_48MBPS = 0x08,
+ RATE_54MBPS = 0x0C
+};
+
+enum {
+ RATE_INDEX_1MBPS = 0,
+ RATE_INDEX_2MBPS = 1,
+ RATE_INDEX_5_5MBPS = 2,
+ RATE_INDEX_6MBPS = 3,
+ RATE_INDEX_9MBPS = 4,
+ RATE_INDEX_11MBPS = 5,
+ RATE_INDEX_12MBPS = 6,
+ RATE_INDEX_18MBPS = 7,
+ RATE_INDEX_22MBPS = 8,
+ RATE_INDEX_24MBPS = 9,
+ RATE_INDEX_36MBPS = 10,
+ RATE_INDEX_48MBPS = 11,
+ RATE_INDEX_54MBPS = 12,
+ RATE_INDEX_MAX = RATE_INDEX_54MBPS,
+ MAX_RATE_INDEX,
+ INVALID_RATE_INDEX = MAX_RATE_INDEX,
+ RATE_INDEX_ENUM_MAX_SIZE = 0x7FFFFFFF
+};
+
+enum {
+ RATE_MASK_1MBPS = 0x1,
+ RATE_MASK_2MBPS = 0x2,
+ RATE_MASK_5_5MBPS = 0x4,
+ RATE_MASK_11MBPS = 0x20,
+};
+
+#define SHORT_PREAMBLE_BIT BIT(0) /* CCK or Barker depending on the rate */
+#define OFDM_RATE_BIT BIT(6)
+#define PBCC_RATE_BIT BIT(7)
+
+enum {
+ CCK_LONG = 0,
+ CCK_SHORT = SHORT_PREAMBLE_BIT,
+ PBCC_LONG = PBCC_RATE_BIT,
+ PBCC_SHORT = PBCC_RATE_BIT | SHORT_PREAMBLE_BIT,
+ OFDM = OFDM_RATE_BIT
+};
+
+/******************************************************************************
+
+Transmit-Descriptor RATE-SET field definitions...
+
+Define a new "Rate-Set" for TX path that incorporates the
+Rate & Modulation info into a single 16-bit field.
+
+TxdRateSet_t:
+b15 - Indicates Preamble type (1=SHORT, 0=LONG).
+ Notes:
+ Must be LONG (0) for 1Mbps rate.
+ Does not apply (set to 0) for RevG-OFDM rates.
+b14 - Indicates PBCC encoding (1=PBCC, 0=not).
+ Notes:
+ Does not apply (set to 0) for rates 1 and 2 Mbps.
+ Does not apply (set to 0) for RevG-OFDM rates.
+b13 - Unused (set to 0).
+b12-b0 - Supported Rate indicator bits as defined below.
+
+******************************************************************************/
+
+
+/*************************************************************************
+
+ Interrupt Trigger Register (Host -> WiLink)
+
+**************************************************************************/
+
+/* Hardware to Embedded CPU Interrupts - first 32-bit register set */
+
+/*
+ * Host Command Interrupt. Setting this bit masks
+ * the interrupt that the host issues to inform
+ * the FW that it has sent a command
+ * to the Wlan hardware Command Mailbox.
+ */
+#define INTR_TRIG_CMD BIT(0)
+
+/*
+ * Host Event Acknowlegde Interrupt. The host
+ * sets this bit to acknowledge that it received
+ * the unsolicited information from the event
+ * mailbox.
+ */
+#define INTR_TRIG_EVENT_ACK BIT(1)
+
+/*
+ * The host sets this bit to inform the Wlan
+ * FW that a TX packet is in the XFER
+ * Buffer #0.
+ */
+#define INTR_TRIG_TX_PROC0 BIT(2)
+
+/*
+ * The host sets this bit to inform the FW
+ * that it read a packet from RX XFER
+ * Buffer #0.
+ */
+#define INTR_TRIG_RX_PROC0 BIT(3)
+
+#define INTR_TRIG_DEBUG_ACK BIT(4)
+
+#define INTR_TRIG_STATE_CHANGED BIT(5)
+
+
+/* Hardware to Embedded CPU Interrupts - second 32-bit register set */
+
+/*
+ * The host sets this bit to inform the FW
+ * that it read a packet from RX XFER
+ * Buffer #1.
+ */
+#define INTR_TRIG_RX_PROC1 BIT(17)
+
+/*
+ * The host sets this bit to inform the Wlan
+ * hardware that a TX packet is in the XFER
+ * Buffer #1.
+ */
+#define INTR_TRIG_TX_PROC1 BIT(18)
+
+#endif
diff --git a/drivers/net/wireless/wl12xx/rx.c b/drivers/net/wireless/wl12xx/wl1251_rx.c
index 981ea259eb8..17c54b59ef8 100644
--- a/drivers/net/wireless/wl12xx/rx.c
+++ b/drivers/net/wireless/wl12xx/wl1251_rx.c
@@ -1,5 +1,5 @@
/*
- * This file is part of wl12xx
+ * This file is part of wl1251
*
* Copyright (c) 1998-2007 Texas Instruments Incorporated
* Copyright (C) 2008 Nokia Corporation
@@ -25,13 +25,15 @@
#include <linux/skbuff.h>
#include <net/mac80211.h>
-#include "wl12xx.h"
-#include "reg.h"
-#include "spi.h"
-#include "rx.h"
+#include "wl1251.h"
+#include "wl1251_reg.h"
+#include "wl1251_io.h"
+#include "wl1251_rx.h"
+#include "wl1251_cmd.h"
+#include "wl1251_acx.h"
-static void wl12xx_rx_header(struct wl12xx *wl,
- struct wl12xx_rx_descriptor *desc)
+static void wl1251_rx_header(struct wl1251 *wl,
+ struct wl1251_rx_descriptor *desc)
{
u32 rx_packet_ring_addr;
@@ -39,15 +41,17 @@ static void wl12xx_rx_header(struct wl12xx *wl,
if (wl->rx_current_buffer)
rx_packet_ring_addr += wl->data_path->rx_packet_ring_chunk_size;
- wl12xx_spi_mem_read(wl, rx_packet_ring_addr, desc,
- sizeof(struct wl12xx_rx_descriptor));
+ wl1251_mem_read(wl, rx_packet_ring_addr, desc, sizeof(*desc));
}
-static void wl12xx_rx_status(struct wl12xx *wl,
- struct wl12xx_rx_descriptor *desc,
+static void wl1251_rx_status(struct wl1251 *wl,
+ struct wl1251_rx_descriptor *desc,
struct ieee80211_rx_status *status,
u8 beacon)
{
+ u64 mactime;
+ int ret;
+
memset(status, 0, sizeof(struct ieee80211_rx_status));
status->band = IEEE80211_BAND_2GHZ;
@@ -62,32 +66,14 @@ static void wl12xx_rx_status(struct wl12xx *wl,
* this one must be atomic, while our SPI routines can sleep.
*/
if ((wl->bss_type == BSS_TYPE_IBSS) && beacon) {
- u64 mactime;
- int ret;
- struct wl12xx_command cmd;
- struct acx_tsf_info *tsf_info;
-
- memset(&cmd, 0, sizeof(cmd));
-
- ret = wl12xx_cmd_interrogate(wl, ACX_TSF_INFO,
- sizeof(struct acx_tsf_info),
- &cmd);
- if (ret < 0) {
- wl12xx_warning("ACX_FW_REV interrogate failed");
- return;
- }
-
- tsf_info = (struct acx_tsf_info *)&(cmd.parameters);
-
- mactime = tsf_info->current_tsf_lsb |
- (tsf_info->current_tsf_msb << 31);
-
- status->mactime = mactime;
+ ret = wl1251_acx_tsf_info(wl, &mactime);
+ if (ret == 0)
+ status->mactime = mactime;
}
status->signal = desc->rssi;
- status->qual = (desc->rssi - WL12XX_RX_MIN_RSSI) * 100 /
- (WL12XX_RX_MAX_RSSI - WL12XX_RX_MIN_RSSI);
+ status->qual = (desc->rssi - WL1251_RX_MIN_RSSI) * 100 /
+ (WL1251_RX_MAX_RSSI - WL1251_RX_MIN_RSSI);
status->qual = min(status->qual, 100);
status->qual = max(status->qual, 0);
@@ -118,8 +104,8 @@ static void wl12xx_rx_status(struct wl12xx *wl,
/* FIXME: set status->rate_idx */
}
-static void wl12xx_rx_body(struct wl12xx *wl,
- struct wl12xx_rx_descriptor *desc)
+static void wl1251_rx_body(struct wl1251 *wl,
+ struct wl1251_rx_descriptor *desc)
{
struct sk_buff *skb;
struct ieee80211_rx_status status;
@@ -127,12 +113,12 @@ static void wl12xx_rx_body(struct wl12xx *wl,
u16 length, *fc;
u32 curr_id, last_id_inc, rx_packet_ring_addr;
- length = WL12XX_RX_ALIGN(desc->length - PLCP_HEADER_LENGTH);
+ length = WL1251_RX_ALIGN(desc->length - PLCP_HEADER_LENGTH);
curr_id = (desc->flags & RX_DESC_SEQNUM_MASK) >> RX_DESC_PACKETID_SHIFT;
last_id_inc = (wl->rx_last_id + 1) % (RX_MAX_PACKET_ID + 1);
if (last_id_inc != curr_id) {
- wl12xx_warning("curr ID:%d, last ID inc:%d",
+ wl1251_warning("curr ID:%d, last ID inc:%d",
curr_id, last_id_inc);
wl->rx_last_id = curr_id;
} else {
@@ -140,18 +126,18 @@ static void wl12xx_rx_body(struct wl12xx *wl,
}
rx_packet_ring_addr = wl->data_path->rx_packet_ring_addr +
- sizeof(struct wl12xx_rx_descriptor) + 20;
+ sizeof(struct wl1251_rx_descriptor) + 20;
if (wl->rx_current_buffer)
rx_packet_ring_addr += wl->data_path->rx_packet_ring_chunk_size;
skb = dev_alloc_skb(length);
if (!skb) {
- wl12xx_error("Couldn't allocate RX frame");
+ wl1251_error("Couldn't allocate RX frame");
return;
}
rx_buffer = skb_put(skb, length);
- wl12xx_spi_mem_read(wl, rx_packet_ring_addr, rx_buffer, length);
+ wl1251_mem_read(wl, rx_packet_ring_addr, rx_buffer, length);
/* The actual lenght doesn't include the target's alignment */
skb->len = desc->length - PLCP_HEADER_LENGTH;
@@ -161,15 +147,16 @@ static void wl12xx_rx_body(struct wl12xx *wl,
if ((*fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_BEACON)
beacon = 1;
- wl12xx_rx_status(wl, desc, &status, beacon);
+ wl1251_rx_status(wl, desc, &status, beacon);
- wl12xx_debug(DEBUG_RX, "rx skb 0x%p: %d B %s", skb, skb->len,
+ wl1251_debug(DEBUG_RX, "rx skb 0x%p: %d B %s", skb, skb->len,
beacon ? "beacon" : "");
- ieee80211_rx(wl->hw, skb, &status);
+ memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status));
+ ieee80211_rx(wl->hw, skb);
}
-static void wl12xx_rx_ack(struct wl12xx *wl)
+static void wl1251_rx_ack(struct wl1251 *wl)
{
u32 data, addr;
@@ -181,28 +168,30 @@ static void wl12xx_rx_ack(struct wl12xx *wl)
data = INTR_TRIG_RX_PROC0;
}
- wl12xx_reg_write32(wl, addr, data);
+ wl1251_reg_write32(wl, addr, data);
/* Toggle buffer ring */
wl->rx_current_buffer = !wl->rx_current_buffer;
}
-void wl12xx_rx(struct wl12xx *wl)
+void wl1251_rx(struct wl1251 *wl)
{
- struct wl12xx_rx_descriptor rx_desc;
+ struct wl1251_rx_descriptor *rx_desc;
- if (wl->state != WL12XX_STATE_ON)
+ if (wl->state != WL1251_STATE_ON)
return;
+ rx_desc = wl->rx_descriptor;
+
/* We first read the frame's header */
- wl12xx_rx_header(wl, &rx_desc);
+ wl1251_rx_header(wl, rx_desc);
/* Now we can read the body */
- wl12xx_rx_body(wl, &rx_desc);
+ wl1251_rx_body(wl, rx_desc);
/* Finally, we need to ACK the RX */
- wl12xx_rx_ack(wl);
+ wl1251_rx_ack(wl);
return;
}
diff --git a/drivers/net/wireless/wl12xx/rx.h b/drivers/net/wireless/wl12xx/wl1251_rx.h
index 8a23fdea501..563a3fde40f 100644
--- a/drivers/net/wireless/wl12xx/rx.h
+++ b/drivers/net/wireless/wl12xx/wl1251_rx.h
@@ -1,5 +1,5 @@
/*
- * This file is part of wl12xx
+ * This file is part of wl1251
*
* Copyright (c) 1998-2007 Texas Instruments Incorporated
* Copyright (C) 2008 Nokia Corporation
@@ -22,11 +22,13 @@
*
*/
-#ifndef __WL12XX_RX_H__
-#define __WL12XX_RX_H__
+#ifndef __WL1251_RX_H__
+#define __WL1251_RX_H__
#include <linux/bitops.h>
+#include "wl1251.h"
+
/*
* RX PATH
*
@@ -43,12 +45,12 @@
* 4) The target prepares the next RX packet.
*/
-#define WL12XX_RX_MAX_RSSI -30
-#define WL12XX_RX_MIN_RSSI -95
+#define WL1251_RX_MAX_RSSI -30
+#define WL1251_RX_MIN_RSSI -95
-#define WL12XX_RX_ALIGN_TO 4
-#define WL12XX_RX_ALIGN(len) (((len) + WL12XX_RX_ALIGN_TO - 1) & \
- ~(WL12XX_RX_ALIGN_TO - 1))
+#define WL1251_RX_ALIGN_TO 4
+#define WL1251_RX_ALIGN(len) (((len) + WL1251_RX_ALIGN_TO - 1) & \
+ ~(WL1251_RX_ALIGN_TO - 1))
#define SHORT_PREAMBLE_BIT BIT(0)
#define OFDM_RATE_BIT BIT(6)
@@ -72,7 +74,7 @@
#define RX_DESC_MIC_FAIL 0x2000
#define RX_DESC_DECRYPT_FAIL 0x4000
-struct wl12xx_rx_descriptor {
+struct wl1251_rx_descriptor {
u32 timestamp; /* In microseconds */
u16 length; /* Paylod length, including headers */
u16 flags;
@@ -86,7 +88,7 @@ struct wl12xx_rx_descriptor {
u8 type;
/*
- * Recevied Rate:
+ * Received Rate:
* 0x0A - 1MBPS
* 0x14 - 2MBPS
* 0x37 - 5_5MBPS
@@ -117,6 +119,6 @@ struct wl12xx_rx_descriptor {
u8 snr; /* in dB */
} __attribute__ ((packed));
-void wl12xx_rx(struct wl12xx *wl);
+void wl1251_rx(struct wl1251 *wl);
#endif
diff --git a/drivers/net/wireless/wl12xx/wl1251_sdio.c b/drivers/net/wireless/wl12xx/wl1251_sdio.c
new file mode 100644
index 00000000000..9423f22bdce
--- /dev/null
+++ b/drivers/net/wireless/wl12xx/wl1251_sdio.c
@@ -0,0 +1,205 @@
+/*
+ * wl12xx SDIO routines
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ * Copyright (C) 2005 Texas Instruments Incorporated
+ * Copyright (C) 2008 Google Inc
+ * Copyright (C) 2009 Bob Copeland (me@bobcopeland.com)
+ */
+#include <linux/module.h>
+#include <linux/crc7.h>
+#include <linux/mod_devicetable.h>
+#include <linux/irq.h>
+#include <linux/mmc/sdio_func.h>
+#include <linux/mmc/sdio_ids.h>
+#include <linux/platform_device.h>
+
+#include "wl1251.h"
+#include "wl12xx_80211.h"
+#include "wl1251_reg.h"
+#include "wl1251_ps.h"
+#include "wl1251_io.h"
+#include "wl1251_tx.h"
+#include "wl1251_debugfs.h"
+
+#ifndef SDIO_VENDOR_ID_TI
+#define SDIO_VENDOR_ID_TI 0x104c
+#endif
+
+#ifndef SDIO_DEVICE_ID_TI_WL1251
+#define SDIO_DEVICE_ID_TI_WL1251 0x9066
+#endif
+
+static struct sdio_func *wl_to_func(struct wl1251 *wl)
+{
+ return wl->if_priv;
+}
+
+static void wl1251_sdio_interrupt(struct sdio_func *func)
+{
+ struct wl1251 *wl = sdio_get_drvdata(func);
+
+ wl1251_debug(DEBUG_IRQ, "IRQ");
+
+ /* FIXME should be synchronous for sdio */
+ ieee80211_queue_work(wl->hw, &wl->irq_work);
+}
+
+static const struct sdio_device_id wl1251_devices[] = {
+ { SDIO_DEVICE(SDIO_VENDOR_ID_TI, SDIO_DEVICE_ID_TI_WL1251) },
+ {}
+};
+MODULE_DEVICE_TABLE(sdio, wl1251_devices);
+
+
+void wl1251_sdio_read(struct wl1251 *wl, int addr, void *buf, size_t len)
+{
+ int ret;
+ struct sdio_func *func = wl_to_func(wl);
+
+ sdio_claim_host(func);
+ ret = sdio_memcpy_fromio(func, buf, addr, len);
+ if (ret)
+ wl1251_error("sdio read failed (%d)", ret);
+ sdio_release_host(func);
+}
+
+void wl1251_sdio_write(struct wl1251 *wl, int addr, void *buf, size_t len)
+{
+ int ret;
+ struct sdio_func *func = wl_to_func(wl);
+
+ sdio_claim_host(func);
+ ret = sdio_memcpy_toio(func, addr, buf, len);
+ if (ret)
+ wl1251_error("sdio write failed (%d)", ret);
+ sdio_release_host(func);
+}
+
+void wl1251_sdio_reset(struct wl1251 *wl)
+{
+}
+
+static void wl1251_sdio_enable_irq(struct wl1251 *wl)
+{
+ struct sdio_func *func = wl_to_func(wl);
+
+ sdio_claim_host(func);
+ sdio_claim_irq(func, wl1251_sdio_interrupt);
+ sdio_release_host(func);
+}
+
+static void wl1251_sdio_disable_irq(struct wl1251 *wl)
+{
+ struct sdio_func *func = wl_to_func(wl);
+
+ sdio_claim_host(func);
+ sdio_release_irq(func);
+ sdio_release_host(func);
+}
+
+void wl1251_sdio_set_power(bool enable)
+{
+}
+
+struct wl1251_if_operations wl1251_sdio_ops = {
+ .read = wl1251_sdio_read,
+ .write = wl1251_sdio_write,
+ .reset = wl1251_sdio_reset,
+ .enable_irq = wl1251_sdio_enable_irq,
+ .disable_irq = wl1251_sdio_disable_irq,
+};
+
+int wl1251_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id)
+{
+ int ret;
+ struct wl1251 *wl;
+ struct ieee80211_hw *hw;
+
+ hw = wl1251_alloc_hw();
+ if (IS_ERR(hw))
+ return PTR_ERR(hw);
+
+ wl = hw->priv;
+
+ sdio_claim_host(func);
+ ret = sdio_enable_func(func);
+ if (ret)
+ goto release;
+
+ sdio_set_block_size(func, 512);
+
+ SET_IEEE80211_DEV(hw, &func->dev);
+ wl->if_priv = func;
+ wl->if_ops = &wl1251_sdio_ops;
+ wl->set_power = wl1251_sdio_set_power;
+
+ sdio_release_host(func);
+ ret = wl1251_init_ieee80211(wl);
+ if (ret)
+ goto disable;
+
+ sdio_set_drvdata(func, wl);
+ return ret;
+
+disable:
+ sdio_claim_host(func);
+ sdio_disable_func(func);
+release:
+ sdio_release_host(func);
+ return ret;
+}
+
+static void __devexit wl1251_sdio_remove(struct sdio_func *func)
+{
+ struct wl1251 *wl = sdio_get_drvdata(func);
+
+ wl1251_free_hw(wl);
+
+ sdio_claim_host(func);
+ sdio_release_irq(func);
+ sdio_disable_func(func);
+ sdio_release_host(func);
+}
+
+static struct sdio_driver wl1251_sdio_driver = {
+ .name = "wl1251_sdio",
+ .id_table = wl1251_devices,
+ .probe = wl1251_sdio_probe,
+ .remove = __devexit_p(wl1251_sdio_remove),
+};
+
+static int __init wl1251_sdio_init(void)
+{
+ int err;
+
+ err = sdio_register_driver(&wl1251_sdio_driver);
+ if (err)
+ wl1251_error("failed to register sdio driver: %d", err);
+ return err;
+}
+
+static void __exit wl1251_sdio_exit(void)
+{
+ sdio_unregister_driver(&wl1251_sdio_driver);
+ wl1251_notice("unloaded");
+}
+
+module_init(wl1251_sdio_init);
+module_exit(wl1251_sdio_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Kalle Valo <kalle.valo@nokia.com>");
diff --git a/drivers/net/wireless/wl12xx/wl1251_spi.c b/drivers/net/wireless/wl12xx/wl1251_spi.c
new file mode 100644
index 00000000000..14eff2b3d4c
--- /dev/null
+++ b/drivers/net/wireless/wl12xx/wl1251_spi.c
@@ -0,0 +1,344 @@
+/*
+ * This file is part of wl1251
+ *
+ * Copyright (C) 2008 Nokia Corporation
+ *
+ * Contact: Kalle Valo <kalle.valo@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/irq.h>
+#include <linux/module.h>
+#include <linux/crc7.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/wl12xx.h>
+
+#include "wl1251.h"
+#include "wl1251_reg.h"
+#include "wl1251_spi.h"
+
+static irqreturn_t wl1251_irq(int irq, void *cookie)
+{
+ struct wl1251 *wl;
+
+ wl1251_debug(DEBUG_IRQ, "IRQ");
+
+ wl = cookie;
+
+ ieee80211_queue_work(wl->hw, &wl->irq_work);
+
+ return IRQ_HANDLED;
+}
+
+static struct spi_device *wl_to_spi(struct wl1251 *wl)
+{
+ return wl->if_priv;
+}
+
+static void wl1251_spi_reset(struct wl1251 *wl)
+{
+ u8 *cmd;
+ struct spi_transfer t;
+ struct spi_message m;
+
+ cmd = kzalloc(WSPI_INIT_CMD_LEN, GFP_KERNEL);
+ if (!cmd) {
+ wl1251_error("could not allocate cmd for spi reset");
+ return;
+ }
+
+ memset(&t, 0, sizeof(t));
+ spi_message_init(&m);
+
+ memset(cmd, 0xff, WSPI_INIT_CMD_LEN);
+
+ t.tx_buf = cmd;
+ t.len = WSPI_INIT_CMD_LEN;
+ spi_message_add_tail(&t, &m);
+
+ spi_sync(wl_to_spi(wl), &m);
+
+ wl1251_dump(DEBUG_SPI, "spi reset -> ", cmd, WSPI_INIT_CMD_LEN);
+}
+
+static void wl1251_spi_wake(struct wl1251 *wl)
+{
+ u8 crc[WSPI_INIT_CMD_CRC_LEN], *cmd;
+ struct spi_transfer t;
+ struct spi_message m;
+
+ cmd = kzalloc(WSPI_INIT_CMD_LEN, GFP_KERNEL);
+ if (!cmd) {
+ wl1251_error("could not allocate cmd for spi init");
+ return;
+ }
+
+ memset(crc, 0, sizeof(crc));
+ memset(&t, 0, sizeof(t));
+ spi_message_init(&m);
+
+ /*
+ * Set WSPI_INIT_COMMAND
+ * the data is being send from the MSB to LSB
+ */
+ cmd[2] = 0xff;
+ cmd[3] = 0xff;
+ cmd[1] = WSPI_INIT_CMD_START | WSPI_INIT_CMD_TX;
+ cmd[0] = 0;
+ cmd[7] = 0;
+ cmd[6] |= HW_ACCESS_WSPI_INIT_CMD_MASK << 3;
+ cmd[6] |= HW_ACCESS_WSPI_FIXED_BUSY_LEN & WSPI_INIT_CMD_FIXEDBUSY_LEN;
+
+ if (HW_ACCESS_WSPI_FIXED_BUSY_LEN == 0)
+ cmd[5] |= WSPI_INIT_CMD_DIS_FIXEDBUSY;
+ else
+ cmd[5] |= WSPI_INIT_CMD_EN_FIXEDBUSY;
+
+ cmd[5] |= WSPI_INIT_CMD_IOD | WSPI_INIT_CMD_IP | WSPI_INIT_CMD_CS
+ | WSPI_INIT_CMD_WSPI | WSPI_INIT_CMD_WS;
+
+ crc[0] = cmd[1];
+ crc[1] = cmd[0];
+ crc[2] = cmd[7];
+ crc[3] = cmd[6];
+ crc[4] = cmd[5];
+
+ cmd[4] |= crc7(0, crc, WSPI_INIT_CMD_CRC_LEN) << 1;
+ cmd[4] |= WSPI_INIT_CMD_END;
+
+ t.tx_buf = cmd;
+ t.len = WSPI_INIT_CMD_LEN;
+ spi_message_add_tail(&t, &m);
+
+ spi_sync(wl_to_spi(wl), &m);
+
+ wl1251_dump(DEBUG_SPI, "spi init -> ", cmd, WSPI_INIT_CMD_LEN);
+}
+
+static void wl1251_spi_reset_wake(struct wl1251 *wl)
+{
+ wl1251_spi_reset(wl);
+ wl1251_spi_wake(wl);
+}
+
+static void wl1251_spi_read(struct wl1251 *wl, int addr, void *buf,
+ size_t len)
+{
+ struct spi_transfer t[3];
+ struct spi_message m;
+ u8 *busy_buf;
+ u32 *cmd;
+
+ cmd = &wl->buffer_cmd;
+ busy_buf = wl->buffer_busyword;
+
+ *cmd = 0;
+ *cmd |= WSPI_CMD_READ;
+ *cmd |= (len << WSPI_CMD_BYTE_LENGTH_OFFSET) & WSPI_CMD_BYTE_LENGTH;
+ *cmd |= addr & WSPI_CMD_BYTE_ADDR;
+
+ spi_message_init(&m);
+ memset(t, 0, sizeof(t));
+
+ t[0].tx_buf = cmd;
+ t[0].len = 4;
+ spi_message_add_tail(&t[0], &m);
+
+ /* Busy and non busy words read */
+ t[1].rx_buf = busy_buf;
+ t[1].len = WL1251_BUSY_WORD_LEN;
+ spi_message_add_tail(&t[1], &m);
+
+ t[2].rx_buf = buf;
+ t[2].len = len;
+ spi_message_add_tail(&t[2], &m);
+
+ spi_sync(wl_to_spi(wl), &m);
+
+ /* FIXME: check busy words */
+
+ wl1251_dump(DEBUG_SPI, "spi_read cmd -> ", cmd, sizeof(*cmd));
+ wl1251_dump(DEBUG_SPI, "spi_read buf <- ", buf, len);
+}
+
+static void wl1251_spi_write(struct wl1251 *wl, int addr, void *buf,
+ size_t len)
+{
+ struct spi_transfer t[2];
+ struct spi_message m;
+ u32 *cmd;
+
+ cmd = &wl->buffer_cmd;
+
+ *cmd = 0;
+ *cmd |= WSPI_CMD_WRITE;
+ *cmd |= (len << WSPI_CMD_BYTE_LENGTH_OFFSET) & WSPI_CMD_BYTE_LENGTH;
+ *cmd |= addr & WSPI_CMD_BYTE_ADDR;
+
+ spi_message_init(&m);
+ memset(t, 0, sizeof(t));
+
+ t[0].tx_buf = cmd;
+ t[0].len = sizeof(*cmd);
+ spi_message_add_tail(&t[0], &m);
+
+ t[1].tx_buf = buf;
+ t[1].len = len;
+ spi_message_add_tail(&t[1], &m);
+
+ spi_sync(wl_to_spi(wl), &m);
+
+ wl1251_dump(DEBUG_SPI, "spi_write cmd -> ", cmd, sizeof(*cmd));
+ wl1251_dump(DEBUG_SPI, "spi_write buf -> ", buf, len);
+}
+
+static void wl1251_spi_enable_irq(struct wl1251 *wl)
+{
+ return enable_irq(wl->irq);
+}
+
+static void wl1251_spi_disable_irq(struct wl1251 *wl)
+{
+ return disable_irq(wl->irq);
+}
+
+static const struct wl1251_if_operations wl1251_spi_ops = {
+ .read = wl1251_spi_read,
+ .write = wl1251_spi_write,
+ .reset = wl1251_spi_reset_wake,
+ .enable_irq = wl1251_spi_enable_irq,
+ .disable_irq = wl1251_spi_disable_irq,
+};
+
+static int __devinit wl1251_spi_probe(struct spi_device *spi)
+{
+ struct wl12xx_platform_data *pdata;
+ struct ieee80211_hw *hw;
+ struct wl1251 *wl;
+ int ret;
+
+ pdata = spi->dev.platform_data;
+ if (!pdata) {
+ wl1251_error("no platform data");
+ return -ENODEV;
+ }
+
+ hw = wl1251_alloc_hw();
+ if (IS_ERR(hw))
+ return PTR_ERR(hw);
+
+ wl = hw->priv;
+
+ SET_IEEE80211_DEV(hw, &spi->dev);
+ dev_set_drvdata(&spi->dev, wl);
+ wl->if_priv = spi;
+ wl->if_ops = &wl1251_spi_ops;
+
+ /* This is the only SPI value that we need to set here, the rest
+ * comes from the board-peripherals file */
+ spi->bits_per_word = 32;
+
+ ret = spi_setup(spi);
+ if (ret < 0) {
+ wl1251_error("spi_setup failed");
+ goto out_free;
+ }
+
+ wl->set_power = pdata->set_power;
+ if (!wl->set_power) {
+ wl1251_error("set power function missing in platform data");
+ return -ENODEV;
+ }
+
+ wl->irq = spi->irq;
+ if (wl->irq < 0) {
+ wl1251_error("irq missing in platform data");
+ return -ENODEV;
+ }
+
+ ret = request_irq(wl->irq, wl1251_irq, 0, DRIVER_NAME, wl);
+ if (ret < 0) {
+ wl1251_error("request_irq() failed: %d", ret);
+ goto out_free;
+ }
+
+ set_irq_type(wl->irq, IRQ_TYPE_EDGE_RISING);
+
+ disable_irq(wl->irq);
+
+ ret = wl1251_init_ieee80211(wl);
+ if (ret)
+ goto out_irq;
+
+ return 0;
+
+ out_irq:
+ free_irq(wl->irq, wl);
+
+ out_free:
+ ieee80211_free_hw(hw);
+
+ return ret;
+}
+
+static int __devexit wl1251_spi_remove(struct spi_device *spi)
+{
+ struct wl1251 *wl = dev_get_drvdata(&spi->dev);
+
+ free_irq(wl->irq, wl);
+ wl1251_free_hw(wl);
+
+ return 0;
+}
+
+static struct spi_driver wl1251_spi_driver = {
+ .driver = {
+ .name = "wl12xx",
+ .bus = &spi_bus_type,
+ .owner = THIS_MODULE,
+ },
+
+ .probe = wl1251_spi_probe,
+ .remove = __devexit_p(wl1251_spi_remove),
+};
+
+static int __init wl1251_spi_init(void)
+{
+ int ret;
+
+ ret = spi_register_driver(&wl1251_spi_driver);
+ if (ret < 0) {
+ wl1251_error("failed to register spi driver: %d", ret);
+ goto out;
+ }
+
+out:
+ return ret;
+}
+
+static void __exit wl1251_spi_exit(void)
+{
+ spi_unregister_driver(&wl1251_spi_driver);
+
+ wl1251_notice("unloaded");
+}
+
+module_init(wl1251_spi_init);
+module_exit(wl1251_spi_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Kalle Valo <kalle.valo@nokia.com>");
diff --git a/drivers/net/wireless/wl12xx/wl1251_spi.h b/drivers/net/wireless/wl12xx/wl1251_spi.h
new file mode 100644
index 00000000000..2e273a97e7f
--- /dev/null
+++ b/drivers/net/wireless/wl12xx/wl1251_spi.h
@@ -0,0 +1,61 @@
+/*
+ * This file is part of wl1251
+ *
+ * Copyright (c) 1998-2007 Texas Instruments Incorporated
+ * Copyright (C) 2008 Nokia Corporation
+ *
+ * Contact: Kalle Valo <kalle.valo@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef __WL1251_SPI_H__
+#define __WL1251_SPI_H__
+
+#include "wl1251_cmd.h"
+#include "wl1251_acx.h"
+#include "wl1251_reg.h"
+
+#define WSPI_CMD_READ 0x40000000
+#define WSPI_CMD_WRITE 0x00000000
+#define WSPI_CMD_FIXED 0x20000000
+#define WSPI_CMD_BYTE_LENGTH 0x1FFE0000
+#define WSPI_CMD_BYTE_LENGTH_OFFSET 17
+#define WSPI_CMD_BYTE_ADDR 0x0001FFFF
+
+#define WSPI_INIT_CMD_CRC_LEN 5
+
+#define WSPI_INIT_CMD_START 0x00
+#define WSPI_INIT_CMD_TX 0x40
+/* the extra bypass bit is sampled by the TNET as '1' */
+#define WSPI_INIT_CMD_BYPASS_BIT 0x80
+#define WSPI_INIT_CMD_FIXEDBUSY_LEN 0x07
+#define WSPI_INIT_CMD_EN_FIXEDBUSY 0x80
+#define WSPI_INIT_CMD_DIS_FIXEDBUSY 0x00
+#define WSPI_INIT_CMD_IOD 0x40
+#define WSPI_INIT_CMD_IP 0x20
+#define WSPI_INIT_CMD_CS 0x10
+#define WSPI_INIT_CMD_WS 0x08
+#define WSPI_INIT_CMD_WSPI 0x01
+#define WSPI_INIT_CMD_END 0x01
+
+#define WSPI_INIT_CMD_LEN 8
+
+#define HW_ACCESS_WSPI_FIXED_BUSY_LEN \
+ ((WL1251_BUSY_WORD_LEN - 4) / sizeof(u32))
+#define HW_ACCESS_WSPI_INIT_CMD_MASK 0
+
+#endif /* __WL1251_SPI_H__ */
diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/wl1251_tx.c
index 62145e205a8..f8597061584 100644
--- a/drivers/net/wireless/wl12xx/tx.c
+++ b/drivers/net/wireless/wl12xx/wl1251_tx.c
@@ -1,5 +1,5 @@
/*
- * This file is part of wl12xx
+ * This file is part of wl1251
*
* Copyright (c) 1998-2007 Texas Instruments Incorporated
* Copyright (C) 2008 Nokia Corporation
@@ -25,13 +25,13 @@
#include <linux/kernel.h>
#include <linux/module.h>
-#include "wl12xx.h"
-#include "reg.h"
-#include "spi.h"
-#include "tx.h"
-#include "ps.h"
+#include "wl1251.h"
+#include "wl1251_reg.h"
+#include "wl1251_tx.h"
+#include "wl1251_ps.h"
+#include "wl1251_io.h"
-static bool wl12xx_tx_double_buffer_busy(struct wl12xx *wl, u32 data_out_count)
+static bool wl1251_tx_double_buffer_busy(struct wl1251 *wl, u32 data_out_count)
{
int used, data_in_count;
@@ -52,15 +52,15 @@ static bool wl12xx_tx_double_buffer_busy(struct wl12xx *wl, u32 data_out_count)
return false;
}
-static int wl12xx_tx_path_status(struct wl12xx *wl)
+static int wl1251_tx_path_status(struct wl1251 *wl)
{
u32 status, addr, data_out_count;
bool busy;
addr = wl->data_path->tx_control_addr;
- status = wl12xx_mem_read32(wl, addr);
+ status = wl1251_mem_read32(wl, addr);
data_out_count = status & TX_STATUS_DATA_OUT_COUNT_MASK;
- busy = wl12xx_tx_double_buffer_busy(wl, data_out_count);
+ busy = wl1251_tx_double_buffer_busy(wl, data_out_count);
if (busy)
return -EBUSY;
@@ -68,7 +68,7 @@ static int wl12xx_tx_path_status(struct wl12xx *wl)
return 0;
}
-static int wl12xx_tx_id(struct wl12xx *wl, struct sk_buff *skb)
+static int wl1251_tx_id(struct wl1251 *wl, struct sk_buff *skb)
{
int i;
@@ -81,7 +81,7 @@ static int wl12xx_tx_id(struct wl12xx *wl, struct sk_buff *skb)
return -EBUSY;
}
-static void wl12xx_tx_control(struct tx_double_buffer_desc *tx_hdr,
+static void wl1251_tx_control(struct tx_double_buffer_desc *tx_hdr,
struct ieee80211_tx_info *control, u16 fc)
{
*(u16 *)&tx_hdr->control = 0;
@@ -109,7 +109,7 @@ static void wl12xx_tx_control(struct tx_double_buffer_desc *tx_hdr,
#define MAX_MPDU_HEADER_AND_SECURITY (MAX_MPDU_SECURITY_LENGTH + \
WLAN_QOS_HDR_LEN)
#define HW_BLOCK_SIZE 252
-static void wl12xx_tx_frag_block_num(struct tx_double_buffer_desc *tx_hdr)
+static void wl1251_tx_frag_block_num(struct tx_double_buffer_desc *tx_hdr)
{
u16 payload_len, frag_threshold, mem_blocks;
u16 num_mpdus, mem_blocks_per_frag;
@@ -142,7 +142,7 @@ static void wl12xx_tx_frag_block_num(struct tx_double_buffer_desc *tx_hdr)
tx_hdr->num_mem_blocks = mem_blocks;
}
-static int wl12xx_tx_fill_hdr(struct wl12xx *wl, struct sk_buff *skb,
+static int wl1251_tx_fill_hdr(struct wl1251 *wl, struct sk_buff *skb,
struct ieee80211_tx_info *control)
{
struct tx_double_buffer_desc *tx_hdr;
@@ -153,7 +153,7 @@ static int wl12xx_tx_fill_hdr(struct wl12xx *wl, struct sk_buff *skb,
if (!skb)
return -EINVAL;
- id = wl12xx_tx_id(wl, skb);
+ id = wl1251_tx_id(wl, skb);
if (id < 0)
return id;
@@ -170,14 +170,14 @@ static int wl12xx_tx_fill_hdr(struct wl12xx *wl, struct sk_buff *skb,
/* FIXME: how to get the correct queue id? */
tx_hdr->xmit_queue = 0;
- wl12xx_tx_control(tx_hdr, control, fc);
- wl12xx_tx_frag_block_num(tx_hdr);
+ wl1251_tx_control(tx_hdr, control, fc);
+ wl1251_tx_frag_block_num(tx_hdr);
return 0;
}
/* We copy the packet to the target */
-static int wl12xx_tx_send_packet(struct wl12xx *wl, struct sk_buff *skb,
+static int wl1251_tx_send_packet(struct wl1251 *wl, struct sk_buff *skb,
struct ieee80211_tx_info *control)
{
struct tx_double_buffer_desc *tx_hdr;
@@ -196,12 +196,12 @@ static int wl12xx_tx_send_packet(struct wl12xx *wl, struct sk_buff *skb,
u8 *pos;
fc = *(u16 *)(skb->data + sizeof(*tx_hdr));
- tx_hdr->length += WL12XX_TKIP_IV_SPACE;
+ tx_hdr->length += WL1251_TKIP_IV_SPACE;
hdrlen = ieee80211_hdrlen(fc);
- pos = skb_push(skb, WL12XX_TKIP_IV_SPACE);
- memmove(pos, pos + WL12XX_TKIP_IV_SPACE,
+ pos = skb_push(skb, WL1251_TKIP_IV_SPACE);
+ memmove(pos, pos + WL1251_TKIP_IV_SPACE,
sizeof(*tx_hdr) + hdrlen);
}
@@ -211,7 +211,7 @@ static int wl12xx_tx_send_packet(struct wl12xx *wl, struct sk_buff *skb,
*/
if (unlikely((long)skb->data & 0x03)) {
int offset = (4 - (long)skb->data) & 0x03;
- wl12xx_debug(DEBUG_TX, "skb offset %d", offset);
+ wl1251_debug(DEBUG_TX, "skb offset %d", offset);
/* check whether the current skb can be used */
if (!skb_cloned(skb) && (skb_tailroom(skb) >= offset)) {
@@ -221,13 +221,13 @@ static int wl12xx_tx_send_packet(struct wl12xx *wl, struct sk_buff *skb,
skb_reserve(skb, offset);
memmove(skb->data, src, skb->len);
} else {
- wl12xx_info("No handler, fixme!");
+ wl1251_info("No handler, fixme!");
return -EINVAL;
}
}
/* Our skb->data at this point includes the HW header */
- len = WL12XX_TX_ALIGN(skb->len);
+ len = WL1251_TX_ALIGN(skb->len);
if (wl->data_in_count & 0x1)
addr = wl->data_path->tx_packet_ring_addr +
@@ -235,15 +235,15 @@ static int wl12xx_tx_send_packet(struct wl12xx *wl, struct sk_buff *skb,
else
addr = wl->data_path->tx_packet_ring_addr;
- wl12xx_spi_mem_write(wl, addr, skb->data, len);
+ wl1251_mem_write(wl, addr, skb->data, len);
- wl12xx_debug(DEBUG_TX, "tx id %u skb 0x%p payload %u rate 0x%x",
+ wl1251_debug(DEBUG_TX, "tx id %u skb 0x%p payload %u rate 0x%x",
tx_hdr->id, skb, tx_hdr->length, tx_hdr->rate);
return 0;
}
-static void wl12xx_tx_trigger(struct wl12xx *wl)
+static void wl1251_tx_trigger(struct wl1251 *wl)
{
u32 data, addr;
@@ -255,7 +255,7 @@ static void wl12xx_tx_trigger(struct wl12xx *wl)
data = INTR_TRIG_TX_PROC0;
}
- wl12xx_reg_write32(wl, addr, data);
+ wl1251_reg_write32(wl, addr, data);
/* Bumping data in */
wl->data_in_count = (wl->data_in_count + 1) &
@@ -263,7 +263,7 @@ static void wl12xx_tx_trigger(struct wl12xx *wl)
}
/* caller must hold wl->mutex */
-static int wl12xx_tx_frame(struct wl12xx *wl, struct sk_buff *skb)
+static int wl1251_tx_frame(struct wl1251 *wl, struct sk_buff *skb)
{
struct ieee80211_tx_info *info;
int ret = 0;
@@ -274,51 +274,53 @@ static int wl12xx_tx_frame(struct wl12xx *wl, struct sk_buff *skb)
if (info->control.hw_key) {
idx = info->control.hw_key->hw_key_idx;
if (unlikely(wl->default_key != idx)) {
- ret = wl12xx_acx_default_key(wl, idx);
+ ret = wl1251_acx_default_key(wl, idx);
if (ret < 0)
return ret;
}
}
- ret = wl12xx_tx_path_status(wl);
+ ret = wl1251_tx_path_status(wl);
if (ret < 0)
return ret;
- ret = wl12xx_tx_fill_hdr(wl, skb, info);
+ ret = wl1251_tx_fill_hdr(wl, skb, info);
if (ret < 0)
return ret;
- ret = wl12xx_tx_send_packet(wl, skb, info);
+ ret = wl1251_tx_send_packet(wl, skb, info);
if (ret < 0)
return ret;
- wl12xx_tx_trigger(wl);
+ wl1251_tx_trigger(wl);
return ret;
}
-void wl12xx_tx_work(struct work_struct *work)
+void wl1251_tx_work(struct work_struct *work)
{
- struct wl12xx *wl = container_of(work, struct wl12xx, tx_work);
+ struct wl1251 *wl = container_of(work, struct wl1251, tx_work);
struct sk_buff *skb;
bool woken_up = false;
int ret;
mutex_lock(&wl->mutex);
- if (unlikely(wl->state == WL12XX_STATE_OFF))
+ if (unlikely(wl->state == WL1251_STATE_OFF))
goto out;
while ((skb = skb_dequeue(&wl->tx_queue))) {
if (!woken_up) {
- wl12xx_ps_elp_wakeup(wl);
+ ret = wl1251_ps_elp_wakeup(wl);
+ if (ret < 0)
+ goto out;
woken_up = true;
}
- ret = wl12xx_tx_frame(wl, skb);
+ ret = wl1251_tx_frame(wl, skb);
if (ret == -EBUSY) {
/* firmware buffer is full, stop queues */
- wl12xx_debug(DEBUG_TX, "tx_work: fw buffer full, "
+ wl1251_debug(DEBUG_TX, "tx_work: fw buffer full, "
"stop queues");
ieee80211_stop_queues(wl->hw);
wl->tx_queue_stopped = true;
@@ -332,12 +334,12 @@ void wl12xx_tx_work(struct work_struct *work)
out:
if (woken_up)
- wl12xx_ps_elp_sleep(wl);
+ wl1251_ps_elp_sleep(wl);
mutex_unlock(&wl->mutex);
}
-static const char *wl12xx_tx_parse_status(u8 status)
+static const char *wl1251_tx_parse_status(u8 status)
{
/* 8 bit status field, one character per bit plus null */
static char buf[9];
@@ -365,7 +367,7 @@ static const char *wl12xx_tx_parse_status(u8 status)
return buf;
}
-static void wl12xx_tx_packet_cb(struct wl12xx *wl,
+static void wl1251_tx_packet_cb(struct wl1251 *wl,
struct tx_result *result)
{
struct ieee80211_tx_info *info;
@@ -375,7 +377,7 @@ static void wl12xx_tx_packet_cb(struct wl12xx *wl,
skb = wl->tx_frames[result->id];
if (skb == NULL) {
- wl12xx_error("SKB for packet %d is NULL", result->id);
+ wl1251_error("SKB for packet %d is NULL", result->id);
return;
}
@@ -396,14 +398,14 @@ static void wl12xx_tx_packet_cb(struct wl12xx *wl,
if (info->control.hw_key &&
info->control.hw_key->alg == ALG_TKIP) {
hdrlen = ieee80211_get_hdrlen_from_skb(skb);
- memmove(frame + WL12XX_TKIP_IV_SPACE, frame, hdrlen);
- skb_pull(skb, WL12XX_TKIP_IV_SPACE);
+ memmove(frame + WL1251_TKIP_IV_SPACE, frame, hdrlen);
+ skb_pull(skb, WL1251_TKIP_IV_SPACE);
}
- wl12xx_debug(DEBUG_TX, "tx status id %u skb 0x%p failures %u rate 0x%x"
+ wl1251_debug(DEBUG_TX, "tx status id %u skb 0x%p failures %u rate 0x%x"
" status 0x%x (%s)",
result->id, skb, result->ack_failures, result->rate,
- result->status, wl12xx_tx_parse_status(result->status));
+ result->status, wl1251_tx_parse_status(result->status));
ieee80211_tx_status(wl->hw, skb);
@@ -411,7 +413,7 @@ static void wl12xx_tx_packet_cb(struct wl12xx *wl,
wl->tx_frames[result->id] = NULL;
if (wl->tx_queue_stopped) {
- wl12xx_debug(DEBUG_TX, "cb: queue was stopped");
+ wl1251_debug(DEBUG_TX, "cb: queue was stopped");
skb = skb_dequeue(&wl->tx_queue);
@@ -420,10 +422,10 @@ static void wl12xx_tx_packet_cb(struct wl12xx *wl,
queue empty */
if (skb) {
- ret = wl12xx_tx_frame(wl, skb);
+ ret = wl1251_tx_frame(wl, skb);
if (ret == -EBUSY) {
/* firmware buffer is still full */
- wl12xx_debug(DEBUG_TX, "cb: fw buffer "
+ wl1251_debug(DEBUG_TX, "cb: fw buffer "
"still full");
skb_queue_head(&wl->tx_queue, skb);
return;
@@ -433,23 +435,23 @@ static void wl12xx_tx_packet_cb(struct wl12xx *wl,
}
}
- wl12xx_debug(DEBUG_TX, "cb: waking queues");
+ wl1251_debug(DEBUG_TX, "cb: waking queues");
ieee80211_wake_queues(wl->hw);
wl->tx_queue_stopped = false;
}
}
/* Called upon reception of a TX complete interrupt */
-void wl12xx_tx_complete(struct wl12xx *wl)
+void wl1251_tx_complete(struct wl1251 *wl)
{
int i, result_index, num_complete = 0;
struct tx_result result[FW_TX_CMPLT_BLOCK_SIZE], *result_ptr;
- if (unlikely(wl->state != WL12XX_STATE_ON))
+ if (unlikely(wl->state != WL1251_STATE_ON))
return;
/* First we read the result */
- wl12xx_spi_mem_read(wl, wl->data_path->tx_complete_addr,
+ wl1251_mem_read(wl, wl->data_path->tx_complete_addr,
result, sizeof(result));
result_index = wl->next_tx_complete;
@@ -459,7 +461,7 @@ void wl12xx_tx_complete(struct wl12xx *wl)
if (result_ptr->done_1 == 1 &&
result_ptr->done_2 == 1) {
- wl12xx_tx_packet_cb(wl, result_ptr);
+ wl1251_tx_packet_cb(wl, result_ptr);
result_ptr->done_1 = 0;
result_ptr->done_2 = 0;
@@ -480,41 +482,41 @@ void wl12xx_tx_complete(struct wl12xx *wl)
*/
if (result_index > wl->next_tx_complete) {
/* Only 1 write is needed */
- wl12xx_spi_mem_write(wl,
- wl->data_path->tx_complete_addr +
- (wl->next_tx_complete *
- sizeof(struct tx_result)),
- &result[wl->next_tx_complete],
- num_complete *
- sizeof(struct tx_result));
+ wl1251_mem_write(wl,
+ wl->data_path->tx_complete_addr +
+ (wl->next_tx_complete *
+ sizeof(struct tx_result)),
+ &result[wl->next_tx_complete],
+ num_complete *
+ sizeof(struct tx_result));
} else if (result_index < wl->next_tx_complete) {
/* 2 writes are needed */
- wl12xx_spi_mem_write(wl,
- wl->data_path->tx_complete_addr +
- (wl->next_tx_complete *
- sizeof(struct tx_result)),
- &result[wl->next_tx_complete],
- (FW_TX_CMPLT_BLOCK_SIZE -
- wl->next_tx_complete) *
- sizeof(struct tx_result));
-
- wl12xx_spi_mem_write(wl,
- wl->data_path->tx_complete_addr,
- result,
- (num_complete -
- FW_TX_CMPLT_BLOCK_SIZE +
- wl->next_tx_complete) *
- sizeof(struct tx_result));
+ wl1251_mem_write(wl,
+ wl->data_path->tx_complete_addr +
+ (wl->next_tx_complete *
+ sizeof(struct tx_result)),
+ &result[wl->next_tx_complete],
+ (FW_TX_CMPLT_BLOCK_SIZE -
+ wl->next_tx_complete) *
+ sizeof(struct tx_result));
+
+ wl1251_mem_write(wl,
+ wl->data_path->tx_complete_addr,
+ result,
+ (num_complete -
+ FW_TX_CMPLT_BLOCK_SIZE +
+ wl->next_tx_complete) *
+ sizeof(struct tx_result));
} else {
/* We have to write the whole array */
- wl12xx_spi_mem_write(wl,
- wl->data_path->tx_complete_addr,
- result,
- FW_TX_CMPLT_BLOCK_SIZE *
- sizeof(struct tx_result));
+ wl1251_mem_write(wl,
+ wl->data_path->tx_complete_addr,
+ result,
+ FW_TX_CMPLT_BLOCK_SIZE *
+ sizeof(struct tx_result));
}
}
@@ -523,7 +525,7 @@ void wl12xx_tx_complete(struct wl12xx *wl)
}
/* caller must hold wl->mutex */
-void wl12xx_tx_flush(struct wl12xx *wl)
+void wl1251_tx_flush(struct wl1251 *wl)
{
int i;
struct sk_buff *skb;
@@ -535,7 +537,7 @@ void wl12xx_tx_flush(struct wl12xx *wl)
while ((skb = skb_dequeue(&wl->tx_queue))) {
info = IEEE80211_SKB_CB(skb);
- wl12xx_debug(DEBUG_TX, "flushing skb 0x%p", skb);
+ wl1251_debug(DEBUG_TX, "flushing skb 0x%p", skb);
if (!(info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS))
continue;
diff --git a/drivers/net/wireless/wl12xx/tx.h b/drivers/net/wireless/wl12xx/wl1251_tx.h
index dc82691f4c1..7c1c1665c81 100644
--- a/drivers/net/wireless/wl12xx/tx.h
+++ b/drivers/net/wireless/wl12xx/wl1251_tx.h
@@ -1,5 +1,5 @@
/*
- * This file is part of wl12xx
+ * This file is part of wl1251
*
* Copyright (c) 1998-2007 Texas Instruments Incorporated
* Copyright (C) 2008 Nokia Corporation
@@ -22,8 +22,8 @@
*
*/
-#ifndef __WL12XX_TX_H__
-#define __WL12XX_TX_H__
+#ifndef __WL1251_TX_H__
+#define __WL1251_TX_H__
#include <linux/bitops.h>
@@ -73,10 +73,11 @@
#define TX_COMPLETE_REQUIRED_BIT 0x80
#define TX_STATUS_DATA_OUT_COUNT_MASK 0xf
-#define WL12XX_TX_ALIGN_TO 4
-#define WL12XX_TX_ALIGN(len) (((len) + WL12XX_TX_ALIGN_TO - 1) & \
- ~(WL12XX_TX_ALIGN_TO - 1))
-#define WL12XX_TKIP_IV_SPACE 4
+
+#define WL1251_TX_ALIGN_TO 4
+#define WL1251_TX_ALIGN(len) (((len) + WL1251_TX_ALIGN_TO - 1) & \
+ ~(WL1251_TX_ALIGN_TO - 1))
+#define WL1251_TKIP_IV_SPACE 4
struct tx_control {
/* Rate Policy (class) index */
@@ -208,8 +209,8 @@ struct tx_result {
u8 done_2;
} __attribute__ ((packed));
-void wl12xx_tx_work(struct work_struct *work);
-void wl12xx_tx_complete(struct wl12xx *wl);
-void wl12xx_tx_flush(struct wl12xx *wl);
+void wl1251_tx_work(struct work_struct *work);
+void wl1251_tx_complete(struct wl1251 *wl);
+void wl1251_tx_flush(struct wl1251 *wl);
#endif
diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl1271.h
index 48641437414..55818f94017 100644
--- a/drivers/net/wireless/wl12xx/wl12xx.h
+++ b/drivers/net/wireless/wl12xx/wl1271.h
@@ -1,10 +1,10 @@
/*
- * This file is part of wl12xx
+ * This file is part of wl1271
*
- * Copyright (c) 1998-2007 Texas Instruments Incorporated
+ * Copyright (C) 1998-2009 Texas Instruments. All rights reserved.
* Copyright (C) 2008-2009 Nokia Corporation
*
- * Contact: Kalle Valo <kalle.valo@nokia.com>
+ * Contact: Luciano Coelho <luciano.coelho@nokia.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -22,15 +22,17 @@
*
*/
-#ifndef __WL12XX_H__
-#define __WL12XX_H__
+#ifndef __WL1271_H__
+#define __WL1271_H__
#include <linux/mutex.h>
+#include <linux/completion.h>
+#include <linux/spinlock.h>
#include <linux/list.h>
#include <linux/bitops.h>
#include <net/mac80211.h>
-#define DRIVER_NAME "wl12xx"
+#define DRIVER_NAME "wl1271"
#define DRIVER_PREFIX DRIVER_NAME ": "
enum {
@@ -56,25 +58,25 @@ enum {
#define DEBUG_DUMP_LIMIT 1024
-#define wl12xx_error(fmt, arg...) \
+#define wl1271_error(fmt, arg...) \
printk(KERN_ERR DRIVER_PREFIX "ERROR " fmt "\n", ##arg)
-#define wl12xx_warning(fmt, arg...) \
+#define wl1271_warning(fmt, arg...) \
printk(KERN_WARNING DRIVER_PREFIX "WARNING " fmt "\n", ##arg)
-#define wl12xx_notice(fmt, arg...) \
+#define wl1271_notice(fmt, arg...) \
printk(KERN_INFO DRIVER_PREFIX fmt "\n", ##arg)
-#define wl12xx_info(fmt, arg...) \
+#define wl1271_info(fmt, arg...) \
printk(KERN_DEBUG DRIVER_PREFIX fmt "\n", ##arg)
-#define wl12xx_debug(level, fmt, arg...) \
+#define wl1271_debug(level, fmt, arg...) \
do { \
if (level & DEBUG_LEVEL) \
printk(KERN_DEBUG DRIVER_PREFIX fmt "\n", ##arg); \
} while (0)
-#define wl12xx_dump(level, prefix, buf, len) \
+#define wl1271_dump(level, prefix, buf, len) \
do { \
if (level & DEBUG_LEVEL) \
print_hex_dump(KERN_DEBUG, DRIVER_PREFIX prefix, \
@@ -84,7 +86,7 @@ enum {
0); \
} while (0)
-#define wl12xx_dump_ascii(level, prefix, buf, len) \
+#define wl1271_dump_ascii(level, prefix, buf, len) \
do { \
if (level & DEBUG_LEVEL) \
print_hex_dump(KERN_DEBUG, DRIVER_PREFIX prefix, \
@@ -94,35 +96,29 @@ enum {
true); \
} while (0)
-#define WL12XX_DEFAULT_RX_CONFIG (CFG_UNI_FILTER_EN | \
+#define WL1271_DEFAULT_RX_CONFIG (CFG_UNI_FILTER_EN | \
CFG_BSSID_FILTER_EN)
-#define WL12XX_DEFAULT_RX_FILTER (CFG_RX_PRSP_EN | \
- CFG_RX_MGMT_EN | \
- CFG_RX_DATA_EN | \
- CFG_RX_CTL_EN | \
- CFG_RX_BCN_EN | \
- CFG_RX_AUTH_EN | \
- CFG_RX_ASSOC_EN)
-
-
-struct boot_attr {
- u32 radio_type;
- u8 mac_clock;
- u8 arm_clock;
- int firmware_debug;
- u32 minor;
- u32 major;
- u32 bugfix;
-};
+#define WL1271_DEFAULT_RX_FILTER (CFG_RX_RCTS_ACK | CFG_RX_PRSP_EN | \
+ CFG_RX_MGMT_EN | CFG_RX_DATA_EN | \
+ CFG_RX_CTL_EN | CFG_RX_BCN_EN | \
+ CFG_RX_AUTH_EN | CFG_RX_ASSOC_EN)
+
+#define WL1271_FW_NAME "wl1271-fw.bin"
+#define WL1271_NVS_NAME "wl1271-nvs.bin"
+
+#define WL1271_BUSY_WORD_LEN 8
-enum wl12xx_state {
- WL12XX_STATE_OFF,
- WL12XX_STATE_ON,
- WL12XX_STATE_PLT,
+#define WL1271_ELP_HW_STATE_ASLEEP 0
+#define WL1271_ELP_HW_STATE_IRQ 1
+
+enum wl1271_state {
+ WL1271_STATE_OFF,
+ WL1271_STATE_ON,
+ WL1271_STATE_PLT,
};
-enum wl12xx_partition_type {
+enum wl1271_partition_type {
PART_DOWN,
PART_WORK,
PART_DRPW,
@@ -130,44 +126,25 @@ enum wl12xx_partition_type {
PART_TABLE_LEN
};
-struct wl12xx_partition {
+struct wl1271_partition {
u32 size;
u32 start;
};
-struct wl12xx_partition_set {
- struct wl12xx_partition mem;
- struct wl12xx_partition reg;
+struct wl1271_partition_set {
+ struct wl1271_partition mem;
+ struct wl1271_partition reg;
};
-struct wl12xx;
+struct wl1271;
/* FIXME: I'm not sure about this structure name */
-struct wl12xx_chip {
+struct wl1271_chip {
u32 id;
-
- const char *fw_filename;
- const char *nvs_filename;
-
char fw_ver[21];
-
- unsigned int power_on_sleep;
- int intr_cmd_complete;
- int intr_init_complete;
-
- int (*op_upload_fw)(struct wl12xx *wl);
- int (*op_upload_nvs)(struct wl12xx *wl);
- int (*op_boot)(struct wl12xx *wl);
- void (*op_set_ecpu_ctrl)(struct wl12xx *wl, u32 flag);
- void (*op_target_enable_interrupts)(struct wl12xx *wl);
- int (*op_hw_init)(struct wl12xx *wl);
- int (*op_plt_init)(struct wl12xx *wl);
-
- struct wl12xx_partition_set *p_table;
- enum wl12xx_acx_int_reg *acx_reg_table;
};
-struct wl12xx_stats {
+struct wl1271_stats {
struct acx_statistics *fw_stats;
unsigned long fw_stats_update;
@@ -175,7 +152,7 @@ struct wl12xx_stats {
unsigned int excessive_retries;
};
-struct wl12xx_debugfs {
+struct wl1271_debugfs {
struct dentry *rootdir;
struct dentry *fw_statistics;
@@ -276,7 +253,28 @@ struct wl12xx_debugfs {
struct dentry *excessive_retries;
};
-struct wl12xx {
+#define NUM_TX_QUEUES 4
+#define NUM_RX_PKT_DESC 8
+
+/* FW status registers */
+struct wl1271_fw_status {
+ u32 intr;
+ u8 fw_rx_counter;
+ u8 drv_rx_counter;
+ u8 reserved;
+ u8 tx_results_counter;
+ u32 rx_pkt_descs[NUM_RX_PKT_DESC];
+ u32 tx_released_blks[NUM_TX_QUEUES];
+ u32 fw_localtime;
+ u32 padding[2];
+} __attribute__ ((packed));
+
+struct wl1271_rx_mem_pool_addr {
+ u32 addr;
+ u32 addr_extra;
+};
+
+struct wl1271 {
struct ieee80211_hw *hw;
bool mac80211_registered;
@@ -285,7 +283,9 @@ struct wl12xx {
void (*set_power)(bool enable);
int irq;
- enum wl12xx_state state;
+ spinlock_t wl_lock;
+
+ enum wl1271_state state;
struct mutex mutex;
int physical_mem_addr;
@@ -293,11 +293,10 @@ struct wl12xx {
int virtual_mem_addr;
int virtual_reg_addr;
- struct wl12xx_chip chip;
+ struct wl1271_chip chip;
int cmd_box_addr;
int event_box_addr;
- struct boot_attr boot_attr;
u8 *fw;
size_t fw_len;
@@ -307,14 +306,26 @@ struct wl12xx {
u8 bssid[ETH_ALEN];
u8 mac_addr[ETH_ALEN];
u8 bss_type;
+ u8 ssid[IW_ESSID_MAX_SIZE + 1];
+ u8 ssid_len;
u8 listen_int;
int channel;
- void *target_mem_map;
- struct acx_data_path_params_resp *data_path;
+ struct wl1271_acx_mem_map *target_mem_map;
+
+ /* Accounting for allocated / available TX blocks on HW */
+ u32 tx_blocks_freed[NUM_TX_QUEUES];
+ u32 tx_blocks_available;
+ u8 tx_results_count;
+
+ /* Transmitted TX packets counter for chipset interface */
+ int tx_packets_count;
- /* Number of TX packets transferred to the FW, modulo 16 */
- u32 data_in_count;
+ /* Time-offset between host and chipset clocks */
+ int time_offset;
+
+ /* Session counter for the chipset */
+ int session_counter;
/* Frames scheduled for transmission, not handled yet */
struct sk_buff_head tx_queue;
@@ -326,25 +337,13 @@ struct wl12xx {
/* Pending TX frames */
struct sk_buff *tx_frames[16];
- /*
- * Index pointing to the next TX complete entry
- * in the cyclic XT complete array we get from
- * the FW.
- */
- u32 next_tx_complete;
-
/* FW Rx counter */
u32 rx_counter;
- /* Rx frames handled */
- u32 rx_handled;
-
- /* Current double buffer */
- u32 rx_current_buffer;
- u32 rx_last_id;
+ /* Rx memory pool address */
+ struct wl1271_rx_mem_pool_addr rx_mem_pool_addr;
/* The target interrupt mask */
- u32 intr_mask;
struct work_struct irq_work;
/* The mbox event mask */
@@ -362,15 +361,14 @@ struct wl12xx {
/* Default key (for WEP) */
u32 default_key;
- unsigned int tx_mgmt_frm_rate;
- unsigned int tx_mgmt_frm_mod;
-
unsigned int rx_config;
unsigned int rx_filter;
/* is firmware in elp mode */
bool elp;
+ struct completion *elp_compl;
+
/* we can be in psm, but not in elp, we have to differentiate */
bool psm;
@@ -380,30 +378,30 @@ struct wl12xx {
/* in dBm */
int power_level;
- struct wl12xx_stats stats;
- struct wl12xx_debugfs debugfs;
+ struct wl1271_stats stats;
+ struct wl1271_debugfs debugfs;
+
+ u32 buffer_32;
+ u32 buffer_cmd;
+ u8 buffer_busyword[WL1271_BUSY_WORD_LEN];
+ struct wl1271_rx_descriptor *rx_descriptor;
+
+ struct wl1271_fw_status *fw_status;
+ struct wl1271_tx_hw_res_if *tx_res_if;
};
-int wl12xx_plt_start(struct wl12xx *wl);
-int wl12xx_plt_stop(struct wl12xx *wl);
+int wl1271_plt_start(struct wl1271 *wl);
+int wl1271_plt_stop(struct wl1271 *wl);
-#define DEFAULT_HW_GEN_MODULATION_TYPE CCK_LONG /* Long Preamble */
-#define DEFAULT_HW_GEN_TX_RATE RATE_2MBPS
#define JOIN_TIMEOUT 5000 /* 5000 milliseconds to join */
-#define WL12XX_DEFAULT_POWER_LEVEL 20
+#define SESSION_COUNTER_MAX 7 /* maximum value for the session counter */
-#define WL12XX_TX_QUEUE_MAX_LENGTH 20
+#define WL1271_DEFAULT_POWER_LEVEL 0
-/* Different chips need different sleep times after power on. WL1271 needs
- * 200ms, WL1251 needs only 10ms. By default we use 200ms, but as soon as we
- * know the chip ID, we change the sleep value in the wl12xx chip structure,
- * so in subsequent power ons, we don't waste more time then needed. */
-#define WL12XX_DEFAULT_POWER_ON_SLEEP 200
+#define WL1271_TX_QUEUE_MAX_LENGTH 20
-#define CHIP_ID_1251_PG10 (0x7010101)
-#define CHIP_ID_1251_PG11 (0x7020101)
-#define CHIP_ID_1251_PG12 (0x7030101)
-#define CHIP_ID_1271_PG10 (0x4030101)
+/* WL1271 needs a 200ms sleep after power on */
+#define WL1271_POWER_ON_SLEEP 200 /* in miliseconds */
#endif
diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.c b/drivers/net/wireless/wl12xx/wl1271_acx.c
new file mode 100644
index 00000000000..f622a409261
--- /dev/null
+++ b/drivers/net/wireless/wl12xx/wl1271_acx.c
@@ -0,0 +1,961 @@
+/*
+ * This file is part of wl1271
+ *
+ * Copyright (C) 2008-2009 Nokia Corporation
+ *
+ * Contact: Luciano Coelho <luciano.coelho@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include "wl1271_acx.h"
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/crc7.h>
+#include <linux/spi/spi.h>
+
+#include "wl1271.h"
+#include "wl12xx_80211.h"
+#include "wl1271_reg.h"
+#include "wl1271_spi.h"
+#include "wl1271_ps.h"
+
+int wl1271_acx_wake_up_conditions(struct wl1271 *wl, u8 wake_up_event,
+ u8 listen_interval)
+{
+ struct acx_wake_up_condition *wake_up;
+ int ret;
+
+ wl1271_debug(DEBUG_ACX, "acx wake up conditions");
+
+ wake_up = kzalloc(sizeof(*wake_up), GFP_KERNEL);
+ if (!wake_up) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ wake_up->wake_up_event = wake_up_event;
+ wake_up->listen_interval = listen_interval;
+
+ ret = wl1271_cmd_configure(wl, ACX_WAKE_UP_CONDITIONS,
+ wake_up, sizeof(*wake_up));
+ if (ret < 0) {
+ wl1271_warning("could not set wake up conditions: %d", ret);
+ goto out;
+ }
+
+out:
+ kfree(wake_up);
+ return ret;
+}
+
+int wl1271_acx_sleep_auth(struct wl1271 *wl, u8 sleep_auth)
+{
+ struct acx_sleep_auth *auth;
+ int ret;
+
+ wl1271_debug(DEBUG_ACX, "acx sleep auth");
+
+ auth = kzalloc(sizeof(*auth), GFP_KERNEL);
+ if (!auth) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ auth->sleep_auth = sleep_auth;
+
+ ret = wl1271_cmd_configure(wl, ACX_SLEEP_AUTH, auth, sizeof(*auth));
+ if (ret < 0)
+ return ret;
+
+out:
+ kfree(auth);
+ return ret;
+}
+
+int wl1271_acx_fw_version(struct wl1271 *wl, char *buf, size_t len)
+{
+ struct acx_revision *rev;
+ int ret;
+
+ wl1271_debug(DEBUG_ACX, "acx fw rev");
+
+ rev = kzalloc(sizeof(*rev), GFP_KERNEL);
+ if (!rev) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ ret = wl1271_cmd_interrogate(wl, ACX_FW_REV, rev, sizeof(*rev));
+ if (ret < 0) {
+ wl1271_warning("ACX_FW_REV interrogate failed");
+ goto out;
+ }
+
+ /* be careful with the buffer sizes */
+ strncpy(buf, rev->fw_version, min(len, sizeof(rev->fw_version)));
+
+ /*
+ * if the firmware version string is exactly
+ * sizeof(rev->fw_version) long or fw_len is less than
+ * sizeof(rev->fw_version) it won't be null terminated
+ */
+ buf[min(len, sizeof(rev->fw_version)) - 1] = '\0';
+
+out:
+ kfree(rev);
+ return ret;
+}
+
+int wl1271_acx_tx_power(struct wl1271 *wl, int power)
+{
+ struct acx_current_tx_power *acx;
+ int ret;
+
+ wl1271_debug(DEBUG_ACX, "acx dot11_cur_tx_pwr");
+
+ if (power < 0 || power > 25)
+ return -EINVAL;
+
+ acx = kzalloc(sizeof(*acx), GFP_KERNEL);
+ if (!acx) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ acx->current_tx_power = power * 10;
+
+ ret = wl1271_cmd_configure(wl, DOT11_CUR_TX_PWR, acx, sizeof(*acx));
+ if (ret < 0) {
+ wl1271_warning("configure of tx power failed: %d", ret);
+ goto out;
+ }
+
+out:
+ kfree(acx);
+ return ret;
+}
+
+int wl1271_acx_feature_cfg(struct wl1271 *wl)
+{
+ struct acx_feature_config *feature;
+ int ret;
+
+ wl1271_debug(DEBUG_ACX, "acx feature cfg");
+
+ feature = kzalloc(sizeof(*feature), GFP_KERNEL);
+ if (!feature) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ /* DF_ENCRYPTION_DISABLE and DF_SNIFF_MODE_ENABLE are disabled */
+ feature->data_flow_options = 0;
+ feature->options = 0;
+
+ ret = wl1271_cmd_configure(wl, ACX_FEATURE_CFG,
+ feature, sizeof(*feature));
+ if (ret < 0) {
+ wl1271_error("Couldnt set HW encryption");
+ goto out;
+ }
+
+out:
+ kfree(feature);
+ return ret;
+}
+
+int wl1271_acx_mem_map(struct wl1271 *wl, struct acx_header *mem_map,
+ size_t len)
+{
+ int ret;
+
+ wl1271_debug(DEBUG_ACX, "acx mem map");
+
+ ret = wl1271_cmd_interrogate(wl, ACX_MEM_MAP, mem_map, len);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+int wl1271_acx_rx_msdu_life_time(struct wl1271 *wl, u32 life_time)
+{
+ struct acx_rx_msdu_lifetime *acx;
+ int ret;
+
+ wl1271_debug(DEBUG_ACX, "acx rx msdu life time");
+
+ acx = kzalloc(sizeof(*acx), GFP_KERNEL);
+ if (!acx) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ acx->lifetime = life_time;
+ ret = wl1271_cmd_configure(wl, DOT11_RX_MSDU_LIFE_TIME,
+ acx, sizeof(*acx));
+ if (ret < 0) {
+ wl1271_warning("failed to set rx msdu life time: %d", ret);
+ goto out;
+ }
+
+out:
+ kfree(acx);
+ return ret;
+}
+
+int wl1271_acx_rx_config(struct wl1271 *wl, u32 config, u32 filter)
+{
+ struct acx_rx_config *rx_config;
+ int ret;
+
+ wl1271_debug(DEBUG_ACX, "acx rx config");
+
+ rx_config = kzalloc(sizeof(*rx_config), GFP_KERNEL);
+ if (!rx_config) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ rx_config->config_options = config;
+ rx_config->filter_options = filter;
+
+ ret = wl1271_cmd_configure(wl, ACX_RX_CFG,
+ rx_config, sizeof(*rx_config));
+ if (ret < 0) {
+ wl1271_warning("failed to set rx config: %d", ret);
+ goto out;
+ }
+
+out:
+ kfree(rx_config);
+ return ret;
+}
+
+int wl1271_acx_pd_threshold(struct wl1271 *wl)
+{
+ struct acx_packet_detection *pd;
+ int ret;
+
+ wl1271_debug(DEBUG_ACX, "acx data pd threshold");
+
+ pd = kzalloc(sizeof(*pd), GFP_KERNEL);
+ if (!pd) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ /* FIXME: threshold value not set */
+
+ ret = wl1271_cmd_configure(wl, ACX_PD_THRESHOLD, pd, sizeof(*pd));
+ if (ret < 0) {
+ wl1271_warning("failed to set pd threshold: %d", ret);
+ goto out;
+ }
+
+out:
+ kfree(pd);
+ return 0;
+}
+
+int wl1271_acx_slot(struct wl1271 *wl, enum acx_slot_type slot_time)
+{
+ struct acx_slot *slot;
+ int ret;
+
+ wl1271_debug(DEBUG_ACX, "acx slot");
+
+ slot = kzalloc(sizeof(*slot), GFP_KERNEL);
+ if (!slot) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ slot->wone_index = STATION_WONE_INDEX;
+ slot->slot_time = slot_time;
+
+ ret = wl1271_cmd_configure(wl, ACX_SLOT, slot, sizeof(*slot));
+ if (ret < 0) {
+ wl1271_warning("failed to set slot time: %d", ret);
+ goto out;
+ }
+
+out:
+ kfree(slot);
+ return ret;
+}
+
+int wl1271_acx_group_address_tbl(struct wl1271 *wl)
+{
+ struct acx_dot11_grp_addr_tbl *acx;
+ int ret;
+
+ wl1271_debug(DEBUG_ACX, "acx group address tbl");
+
+ acx = kzalloc(sizeof(*acx), GFP_KERNEL);
+ if (!acx) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ /* MAC filtering */
+ acx->enabled = 0;
+ acx->num_groups = 0;
+ memset(acx->mac_table, 0, ADDRESS_GROUP_MAX_LEN);
+
+ ret = wl1271_cmd_configure(wl, DOT11_GROUP_ADDRESS_TBL,
+ acx, sizeof(*acx));
+ if (ret < 0) {
+ wl1271_warning("failed to set group addr table: %d", ret);
+ goto out;
+ }
+
+out:
+ kfree(acx);
+ return ret;
+}
+
+int wl1271_acx_service_period_timeout(struct wl1271 *wl)
+{
+ struct acx_rx_timeout *rx_timeout;
+ int ret;
+
+ rx_timeout = kzalloc(sizeof(*rx_timeout), GFP_KERNEL);
+ if (!rx_timeout) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ wl1271_debug(DEBUG_ACX, "acx service period timeout");
+
+ rx_timeout->ps_poll_timeout = RX_TIMEOUT_PS_POLL_DEF;
+ rx_timeout->upsd_timeout = RX_TIMEOUT_UPSD_DEF;
+
+ ret = wl1271_cmd_configure(wl, ACX_SERVICE_PERIOD_TIMEOUT,
+ rx_timeout, sizeof(*rx_timeout));
+ if (ret < 0) {
+ wl1271_warning("failed to set service period timeout: %d",
+ ret);
+ goto out;
+ }
+
+out:
+ kfree(rx_timeout);
+ return ret;
+}
+
+int wl1271_acx_rts_threshold(struct wl1271 *wl, u16 rts_threshold)
+{
+ struct acx_rts_threshold *rts;
+ int ret;
+
+ wl1271_debug(DEBUG_ACX, "acx rts threshold");
+
+ rts = kzalloc(sizeof(*rts), GFP_KERNEL);
+ if (!rts) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ rts->threshold = rts_threshold;
+
+ ret = wl1271_cmd_configure(wl, DOT11_RTS_THRESHOLD, rts, sizeof(*rts));
+ if (ret < 0) {
+ wl1271_warning("failed to set rts threshold: %d", ret);
+ goto out;
+ }
+
+out:
+ kfree(rts);
+ return ret;
+}
+
+int wl1271_acx_beacon_filter_opt(struct wl1271 *wl)
+{
+ struct acx_beacon_filter_option *beacon_filter;
+ int ret;
+
+ wl1271_debug(DEBUG_ACX, "acx beacon filter opt");
+
+ beacon_filter = kzalloc(sizeof(*beacon_filter), GFP_KERNEL);
+ if (!beacon_filter) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ beacon_filter->enable = 0;
+ beacon_filter->max_num_beacons = 0;
+
+ ret = wl1271_cmd_configure(wl, ACX_BEACON_FILTER_OPT,
+ beacon_filter, sizeof(*beacon_filter));
+ if (ret < 0) {
+ wl1271_warning("failed to set beacon filter opt: %d", ret);
+ goto out;
+ }
+
+out:
+ kfree(beacon_filter);
+ return ret;
+}
+
+int wl1271_acx_beacon_filter_table(struct wl1271 *wl)
+{
+ struct acx_beacon_filter_ie_table *ie_table;
+ int ret;
+
+ wl1271_debug(DEBUG_ACX, "acx beacon filter table");
+
+ ie_table = kzalloc(sizeof(*ie_table), GFP_KERNEL);
+ if (!ie_table) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ ie_table->num_ie = 0;
+ memset(ie_table->table, 0, BEACON_FILTER_TABLE_MAX_SIZE);
+
+ ret = wl1271_cmd_configure(wl, ACX_BEACON_FILTER_TABLE,
+ ie_table, sizeof(*ie_table));
+ if (ret < 0) {
+ wl1271_warning("failed to set beacon filter table: %d", ret);
+ goto out;
+ }
+
+out:
+ kfree(ie_table);
+ return ret;
+}
+
+int wl1271_acx_sg_enable(struct wl1271 *wl)
+{
+ struct acx_bt_wlan_coex *pta;
+ int ret;
+
+ wl1271_debug(DEBUG_ACX, "acx sg enable");
+
+ pta = kzalloc(sizeof(*pta), GFP_KERNEL);
+ if (!pta) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ pta->enable = SG_ENABLE;
+
+ ret = wl1271_cmd_configure(wl, ACX_SG_ENABLE, pta, sizeof(*pta));
+ if (ret < 0) {
+ wl1271_warning("failed to set softgemini enable: %d", ret);
+ goto out;
+ }
+
+out:
+ kfree(pta);
+ return ret;
+}
+
+int wl1271_acx_sg_cfg(struct wl1271 *wl)
+{
+ struct acx_bt_wlan_coex_param *param;
+ int ret;
+
+ wl1271_debug(DEBUG_ACX, "acx sg cfg");
+
+ param = kzalloc(sizeof(*param), GFP_KERNEL);
+ if (!param) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ /* BT-WLAN coext parameters */
+ param->min_rate = RATE_INDEX_24MBPS;
+ param->bt_hp_max_time = PTA_BT_HP_MAXTIME_DEF;
+ param->wlan_hp_max_time = PTA_WLAN_HP_MAX_TIME_DEF;
+ param->sense_disable_timer = PTA_SENSE_DISABLE_TIMER_DEF;
+ param->rx_time_bt_hp = PTA_PROTECTIVE_RX_TIME_DEF;
+ param->tx_time_bt_hp = PTA_PROTECTIVE_TX_TIME_DEF;
+ param->rx_time_bt_hp_fast = PTA_PROTECTIVE_RX_TIME_FAST_DEF;
+ param->tx_time_bt_hp_fast = PTA_PROTECTIVE_TX_TIME_FAST_DEF;
+ param->wlan_cycle_fast = PTA_CYCLE_TIME_FAST_DEF;
+ param->bt_anti_starvation_period = PTA_ANTI_STARVE_PERIOD_DEF;
+ param->next_bt_lp_packet = PTA_TIMEOUT_NEXT_BT_LP_PACKET_DEF;
+ param->wake_up_beacon = PTA_TIME_BEFORE_BEACON_DEF;
+ param->hp_dm_max_guard_time = PTA_HPDM_MAX_TIME_DEF;
+ param->next_wlan_packet = PTA_TIME_OUT_NEXT_WLAN_DEF;
+ param->antenna_type = PTA_ANTENNA_TYPE_DEF;
+ param->signal_type = PTA_SIGNALING_TYPE_DEF;
+ param->afh_leverage_on = PTA_AFH_LEVERAGE_ON_DEF;
+ param->quiet_cycle_num = PTA_NUMBER_QUIET_CYCLE_DEF;
+ param->max_cts = PTA_MAX_NUM_CTS_DEF;
+ param->wlan_packets_num = PTA_NUMBER_OF_WLAN_PACKETS_DEF;
+ param->bt_packets_num = PTA_NUMBER_OF_BT_PACKETS_DEF;
+ param->missed_rx_avalanche = PTA_RX_FOR_AVALANCHE_DEF;
+ param->wlan_elp_hp = PTA_ELP_HP_DEF;
+ param->bt_anti_starvation_cycles = PTA_ANTI_STARVE_NUM_CYCLE_DEF;
+ param->ack_mode_dual_ant = PTA_ACK_MODE_DEF;
+ param->pa_sd_enable = PTA_ALLOW_PA_SD_DEF;
+ param->pta_auto_mode_enable = PTA_AUTO_MODE_NO_CTS_DEF;
+ param->bt_hp_respected_num = PTA_BT_HP_RESPECTED_DEF;
+
+ ret = wl1271_cmd_configure(wl, ACX_SG_CFG, param, sizeof(*param));
+ if (ret < 0) {
+ wl1271_warning("failed to set sg config: %d", ret);
+ goto out;
+ }
+
+out:
+ kfree(param);
+ return ret;
+}
+
+int wl1271_acx_cca_threshold(struct wl1271 *wl)
+{
+ struct acx_energy_detection *detection;
+ int ret;
+
+ wl1271_debug(DEBUG_ACX, "acx cca threshold");
+
+ detection = kzalloc(sizeof(*detection), GFP_KERNEL);
+ if (!detection) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ detection->rx_cca_threshold = CCA_THRSH_DISABLE_ENERGY_D;
+ detection->tx_energy_detection = 0;
+
+ ret = wl1271_cmd_configure(wl, ACX_CCA_THRESHOLD,
+ detection, sizeof(*detection));
+ if (ret < 0) {
+ wl1271_warning("failed to set cca threshold: %d", ret);
+ return ret;
+ }
+
+out:
+ kfree(detection);
+ return ret;
+}
+
+int wl1271_acx_bcn_dtim_options(struct wl1271 *wl)
+{
+ struct acx_beacon_broadcast *bb;
+ int ret;
+
+ wl1271_debug(DEBUG_ACX, "acx bcn dtim options");
+
+ bb = kzalloc(sizeof(*bb), GFP_KERNEL);
+ if (!bb) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ bb->beacon_rx_timeout = BCN_RX_TIMEOUT_DEF_VALUE;
+ bb->broadcast_timeout = BROADCAST_RX_TIMEOUT_DEF_VALUE;
+ bb->rx_broadcast_in_ps = RX_BROADCAST_IN_PS_DEF_VALUE;
+ bb->ps_poll_threshold = CONSECUTIVE_PS_POLL_FAILURE_DEF;
+
+ ret = wl1271_cmd_configure(wl, ACX_BCN_DTIM_OPTIONS, bb, sizeof(*bb));
+ if (ret < 0) {
+ wl1271_warning("failed to set rx config: %d", ret);
+ goto out;
+ }
+
+out:
+ kfree(bb);
+ return ret;
+}
+
+int wl1271_acx_aid(struct wl1271 *wl, u16 aid)
+{
+ struct acx_aid *acx_aid;
+ int ret;
+
+ wl1271_debug(DEBUG_ACX, "acx aid");
+
+ acx_aid = kzalloc(sizeof(*acx_aid), GFP_KERNEL);
+ if (!acx_aid) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ acx_aid->aid = aid;
+
+ ret = wl1271_cmd_configure(wl, ACX_AID, acx_aid, sizeof(*acx_aid));
+ if (ret < 0) {
+ wl1271_warning("failed to set aid: %d", ret);
+ goto out;
+ }
+
+out:
+ kfree(acx_aid);
+ return ret;
+}
+
+int wl1271_acx_event_mbox_mask(struct wl1271 *wl, u32 event_mask)
+{
+ struct acx_event_mask *mask;
+ int ret;
+
+ wl1271_debug(DEBUG_ACX, "acx event mbox mask");
+
+ mask = kzalloc(sizeof(*mask), GFP_KERNEL);
+ if (!mask) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ /* high event mask is unused */
+ mask->high_event_mask = 0xffffffff;
+
+ mask->event_mask = event_mask;
+
+ ret = wl1271_cmd_configure(wl, ACX_EVENT_MBOX_MASK,
+ mask, sizeof(*mask));
+ if (ret < 0) {
+ wl1271_warning("failed to set acx_event_mbox_mask: %d", ret);
+ goto out;
+ }
+
+out:
+ kfree(mask);
+ return ret;
+}
+
+int wl1271_acx_set_preamble(struct wl1271 *wl, enum acx_preamble_type preamble)
+{
+ struct acx_preamble *acx;
+ int ret;
+
+ wl1271_debug(DEBUG_ACX, "acx_set_preamble");
+
+ acx = kzalloc(sizeof(*acx), GFP_KERNEL);
+ if (!acx) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ acx->preamble = preamble;
+
+ ret = wl1271_cmd_configure(wl, ACX_PREAMBLE_TYPE, acx, sizeof(*acx));
+ if (ret < 0) {
+ wl1271_warning("Setting of preamble failed: %d", ret);
+ goto out;
+ }
+
+out:
+ kfree(acx);
+ return ret;
+}
+
+int wl1271_acx_cts_protect(struct wl1271 *wl,
+ enum acx_ctsprotect_type ctsprotect)
+{
+ struct acx_ctsprotect *acx;
+ int ret;
+
+ wl1271_debug(DEBUG_ACX, "acx_set_ctsprotect");
+
+ acx = kzalloc(sizeof(*acx), GFP_KERNEL);
+ if (!acx) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ acx->ctsprotect = ctsprotect;
+
+ ret = wl1271_cmd_configure(wl, ACX_CTS_PROTECTION, acx, sizeof(*acx));
+ if (ret < 0) {
+ wl1271_warning("Setting of ctsprotect failed: %d", ret);
+ goto out;
+ }
+
+out:
+ kfree(acx);
+ return ret;
+}
+
+int wl1271_acx_statistics(struct wl1271 *wl, struct acx_statistics *stats)
+{
+ int ret;
+
+ wl1271_debug(DEBUG_ACX, "acx statistics");
+
+ ret = wl1271_cmd_interrogate(wl, ACX_STATISTICS, stats,
+ sizeof(*stats));
+ if (ret < 0) {
+ wl1271_warning("acx statistics failed: %d", ret);
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+int wl1271_acx_rate_policies(struct wl1271 *wl)
+{
+ struct acx_rate_policy *acx;
+ int ret = 0;
+
+ wl1271_debug(DEBUG_ACX, "acx rate policies");
+
+ acx = kzalloc(sizeof(*acx), GFP_KERNEL);
+
+ if (!acx) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ /* configure one default (one-size-fits-all) rate class */
+ acx->rate_class_cnt = 1;
+ acx->rate_class[0].enabled_rates = ACX_RATE_MASK_ALL;
+ acx->rate_class[0].short_retry_limit = ACX_RATE_RETRY_LIMIT;
+ acx->rate_class[0].long_retry_limit = ACX_RATE_RETRY_LIMIT;
+ acx->rate_class[0].aflags = 0;
+
+ ret = wl1271_cmd_configure(wl, ACX_RATE_POLICY, acx, sizeof(*acx));
+ if (ret < 0) {
+ wl1271_warning("Setting of rate policies failed: %d", ret);
+ goto out;
+ }
+
+out:
+ kfree(acx);
+ return ret;
+}
+
+int wl1271_acx_ac_cfg(struct wl1271 *wl)
+{
+ struct acx_ac_cfg *acx;
+ int i, ret = 0;
+
+ wl1271_debug(DEBUG_ACX, "acx access category config");
+
+ acx = kzalloc(sizeof(*acx), GFP_KERNEL);
+
+ if (!acx) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ /*
+ * FIXME: Configure each AC with appropriate values (most suitable
+ * values will probably be different for each AC.
+ */
+ for (i = 0; i < WL1271_ACX_AC_COUNT; i++) {
+ acx->ac = i;
+
+ /*
+ * FIXME: The following default values originate from
+ * the TI reference driver. What do they mean?
+ */
+ acx->cw_min = 15;
+ acx->cw_max = 63;
+ acx->aifsn = 3;
+ acx->reserved = 0;
+ acx->tx_op_limit = 0;
+
+ ret = wl1271_cmd_configure(wl, ACX_AC_CFG, acx, sizeof(*acx));
+ if (ret < 0) {
+ wl1271_warning("Setting of access category "
+ "config: %d", ret);
+ goto out;
+ }
+ }
+
+out:
+ kfree(acx);
+ return ret;
+}
+
+int wl1271_acx_tid_cfg(struct wl1271 *wl)
+{
+ struct acx_tid_config *acx;
+ int i, ret = 0;
+
+ wl1271_debug(DEBUG_ACX, "acx tid config");
+
+ acx = kzalloc(sizeof(*acx), GFP_KERNEL);
+
+ if (!acx) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ /* FIXME: configure each TID with a different AC reference */
+ for (i = 0; i < WL1271_ACX_TID_COUNT; i++) {
+ acx->queue_id = i;
+ acx->tsid = WL1271_ACX_AC_BE;
+ acx->ps_scheme = WL1271_ACX_PS_SCHEME_LEGACY;
+ acx->ack_policy = WL1271_ACX_ACK_POLICY_LEGACY;
+
+ ret = wl1271_cmd_configure(wl, ACX_TID_CFG, acx, sizeof(*acx));
+ if (ret < 0) {
+ wl1271_warning("Setting of tid config failed: %d", ret);
+ goto out;
+ }
+ }
+
+out:
+ kfree(acx);
+ return ret;
+}
+
+int wl1271_acx_frag_threshold(struct wl1271 *wl)
+{
+ struct acx_frag_threshold *acx;
+ int ret = 0;
+
+ wl1271_debug(DEBUG_ACX, "acx frag threshold");
+
+ acx = kzalloc(sizeof(*acx), GFP_KERNEL);
+
+ if (!acx) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ acx->frag_threshold = IEEE80211_MAX_FRAG_THRESHOLD;
+ ret = wl1271_cmd_configure(wl, ACX_FRAG_CFG, acx, sizeof(*acx));
+ if (ret < 0) {
+ wl1271_warning("Setting of frag threshold failed: %d", ret);
+ goto out;
+ }
+
+out:
+ kfree(acx);
+ return ret;
+}
+
+int wl1271_acx_tx_config_options(struct wl1271 *wl)
+{
+ struct acx_tx_config_options *acx;
+ int ret = 0;
+
+ wl1271_debug(DEBUG_ACX, "acx tx config options");
+
+ acx = kzalloc(sizeof(*acx), GFP_KERNEL);
+
+ if (!acx) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ acx->tx_compl_timeout = WL1271_ACX_TX_COMPL_TIMEOUT;
+ acx->tx_compl_threshold = WL1271_ACX_TX_COMPL_THRESHOLD;
+ ret = wl1271_cmd_configure(wl, ACX_TX_CONFIG_OPT, acx, sizeof(*acx));
+ if (ret < 0) {
+ wl1271_warning("Setting of tx options failed: %d", ret);
+ goto out;
+ }
+
+out:
+ kfree(acx);
+ return ret;
+}
+
+int wl1271_acx_mem_cfg(struct wl1271 *wl)
+{
+ struct wl1271_acx_config_memory *mem_conf;
+ int ret;
+
+ wl1271_debug(DEBUG_ACX, "wl1271 mem cfg");
+
+ mem_conf = kzalloc(sizeof(*mem_conf), GFP_KERNEL);
+ if (!mem_conf) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ /* memory config */
+ mem_conf->num_stations = cpu_to_le16(DEFAULT_NUM_STATIONS);
+ mem_conf->rx_mem_block_num = ACX_RX_MEM_BLOCKS;
+ mem_conf->tx_min_mem_block_num = ACX_TX_MIN_MEM_BLOCKS;
+ mem_conf->num_ssid_profiles = ACX_NUM_SSID_PROFILES;
+ mem_conf->total_tx_descriptors = ACX_TX_DESCRIPTORS;
+
+ ret = wl1271_cmd_configure(wl, ACX_MEM_CFG, mem_conf,
+ sizeof(*mem_conf));
+ if (ret < 0) {
+ wl1271_warning("wl1271 mem config failed: %d", ret);
+ goto out;
+ }
+
+out:
+ kfree(mem_conf);
+ return ret;
+}
+
+int wl1271_acx_init_mem_config(struct wl1271 *wl)
+{
+ int ret;
+
+ ret = wl1271_acx_mem_cfg(wl);
+ if (ret < 0)
+ return ret;
+
+ wl->target_mem_map = kzalloc(sizeof(struct wl1271_acx_mem_map),
+ GFP_KERNEL);
+ if (!wl->target_mem_map) {
+ wl1271_error("couldn't allocate target memory map");
+ return -ENOMEM;
+ }
+
+ /* we now ask for the firmware built memory map */
+ ret = wl1271_acx_mem_map(wl, (void *)wl->target_mem_map,
+ sizeof(struct wl1271_acx_mem_map));
+ if (ret < 0) {
+ wl1271_error("couldn't retrieve firmware memory map");
+ kfree(wl->target_mem_map);
+ wl->target_mem_map = NULL;
+ return ret;
+ }
+
+ /* initialize TX block book keeping */
+ wl->tx_blocks_available = wl->target_mem_map->num_tx_mem_blocks;
+ wl1271_debug(DEBUG_TX, "available tx blocks: %d",
+ wl->tx_blocks_available);
+
+ return 0;
+}
+
+int wl1271_acx_init_rx_interrupt(struct wl1271 *wl)
+{
+ struct wl1271_acx_rx_config_opt *rx_conf;
+ int ret;
+
+ wl1271_debug(DEBUG_ACX, "wl1271 rx interrupt config");
+
+ rx_conf = kzalloc(sizeof(*rx_conf), GFP_KERNEL);
+ if (!rx_conf) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ rx_conf->threshold = WL1271_RX_INTR_THRESHOLD_DEF;
+ rx_conf->timeout = WL1271_RX_INTR_TIMEOUT_DEF;
+ rx_conf->mblk_threshold = USHORT_MAX; /* Disabled */
+ rx_conf->queue_type = RX_QUEUE_TYPE_RX_LOW_PRIORITY;
+
+ ret = wl1271_cmd_configure(wl, ACX_RX_CONFIG_OPT, rx_conf,
+ sizeof(*rx_conf));
+ if (ret < 0) {
+ wl1271_warning("wl1271 rx config opt failed: %d", ret);
+ goto out;
+ }
+
+out:
+ kfree(rx_conf);
+ return ret;
+}
diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.h b/drivers/net/wireless/wl12xx/wl1271_acx.h
new file mode 100644
index 00000000000..9068daaf0dd
--- /dev/null
+++ b/drivers/net/wireless/wl12xx/wl1271_acx.h
@@ -0,0 +1,1221 @@
+/*
+ * This file is part of wl1271
+ *
+ * Copyright (C) 1998-2009 Texas Instruments. All rights reserved.
+ * Copyright (C) 2008-2009 Nokia Corporation
+ *
+ * Contact: Luciano Coelho <luciano.coelho@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef __WL1271_ACX_H__
+#define __WL1271_ACX_H__
+
+#include "wl1271.h"
+#include "wl1271_cmd.h"
+
+/*************************************************************************
+
+ Host Interrupt Register (WiLink -> Host)
+
+**************************************************************************/
+/* HW Initiated interrupt Watchdog timer expiration */
+#define WL1271_ACX_INTR_WATCHDOG BIT(0)
+/* Init sequence is done (masked interrupt, detection through polling only ) */
+#define WL1271_ACX_INTR_INIT_COMPLETE BIT(1)
+/* Event was entered to Event MBOX #A*/
+#define WL1271_ACX_INTR_EVENT_A BIT(2)
+/* Event was entered to Event MBOX #B*/
+#define WL1271_ACX_INTR_EVENT_B BIT(3)
+/* Command processing completion*/
+#define WL1271_ACX_INTR_CMD_COMPLETE BIT(4)
+/* Signaling the host on HW wakeup */
+#define WL1271_ACX_INTR_HW_AVAILABLE BIT(5)
+/* The MISC bit is used for aggregation of RX, TxComplete and TX rate update */
+#define WL1271_ACX_INTR_DATA BIT(6)
+/* Trace meassge on MBOX #A */
+#define WL1271_ACX_INTR_TRACE_A BIT(7)
+/* Trace meassge on MBOX #B */
+#define WL1271_ACX_INTR_TRACE_B BIT(8)
+
+#define WL1271_ACX_INTR_ALL 0xFFFFFFFF
+#define WL1271_ACX_ALL_EVENTS_VECTOR (WL1271_ACX_INTR_WATCHDOG | \
+ WL1271_ACX_INTR_INIT_COMPLETE | \
+ WL1271_ACX_INTR_EVENT_A | \
+ WL1271_ACX_INTR_EVENT_B | \
+ WL1271_ACX_INTR_CMD_COMPLETE | \
+ WL1271_ACX_INTR_HW_AVAILABLE | \
+ WL1271_ACX_INTR_DATA)
+
+#define WL1271_INTR_MASK (WL1271_ACX_INTR_EVENT_A | \
+ WL1271_ACX_INTR_EVENT_B | \
+ WL1271_ACX_INTR_DATA)
+
+/* Target's information element */
+struct acx_header {
+ struct wl1271_cmd_header cmd;
+
+ /* acx (or information element) header */
+ u16 id;
+
+ /* payload length (not including headers */
+ u16 len;
+};
+
+struct acx_error_counter {
+ struct acx_header header;
+
+ /* The number of PLCP errors since the last time this */
+ /* information element was interrogated. This field is */
+ /* automatically cleared when it is interrogated.*/
+ u32 PLCP_error;
+
+ /* The number of FCS errors since the last time this */
+ /* information element was interrogated. This field is */
+ /* automatically cleared when it is interrogated.*/
+ u32 FCS_error;
+
+ /* The number of MPDUs without PLCP header errors received*/
+ /* since the last time this information element was interrogated. */
+ /* This field is automatically cleared when it is interrogated.*/
+ u32 valid_frame;
+
+ /* the number of missed sequence numbers in the squentially */
+ /* values of frames seq numbers */
+ u32 seq_num_miss;
+} __attribute__ ((packed));
+
+struct acx_revision {
+ struct acx_header header;
+
+ /*
+ * The WiLink firmware version, an ASCII string x.x.x.x,
+ * that uniquely identifies the current firmware.
+ * The left most digit is incremented each time a
+ * significant change is made to the firmware, such as
+ * code redesign or new platform support.
+ * The second digit is incremented when major enhancements
+ * are added or major fixes are made.
+ * The third digit is incremented for each GA release.
+ * The fourth digit is incremented for each build.
+ * The first two digits identify a firmware release version,
+ * in other words, a unique set of features.
+ * The first three digits identify a GA release.
+ */
+ char fw_version[20];
+
+ /*
+ * This 4 byte field specifies the WiLink hardware version.
+ * bits 0 - 15: Reserved.
+ * bits 16 - 23: Version ID - The WiLink version ID
+ * (1 = first spin, 2 = second spin, and so on).
+ * bits 24 - 31: Chip ID - The WiLink chip ID.
+ */
+ u32 hw_version;
+} __attribute__ ((packed));
+
+enum wl1271_psm_mode {
+ /* Active mode */
+ WL1271_PSM_CAM = 0,
+
+ /* Power save mode */
+ WL1271_PSM_PS = 1,
+
+ /* Extreme low power */
+ WL1271_PSM_ELP = 2,
+};
+
+struct acx_sleep_auth {
+ struct acx_header header;
+
+ /* The sleep level authorization of the device. */
+ /* 0 - Always active*/
+ /* 1 - Power down mode: light / fast sleep*/
+ /* 2 - ELP mode: Deep / Max sleep*/
+ u8 sleep_auth;
+ u8 padding[3];
+} __attribute__ ((packed));
+
+enum {
+ HOSTIF_PCI_MASTER_HOST_INDIRECT,
+ HOSTIF_PCI_MASTER_HOST_DIRECT,
+ HOSTIF_SLAVE,
+ HOSTIF_PKT_RING,
+ HOSTIF_DONTCARE = 0xFF
+};
+
+#define DEFAULT_UCAST_PRIORITY 0
+#define DEFAULT_RX_Q_PRIORITY 0
+#define DEFAULT_NUM_STATIONS 1
+#define DEFAULT_RXQ_PRIORITY 0 /* low 0 .. 15 high */
+#define DEFAULT_RXQ_TYPE 0x07 /* All frames, Data/Ctrl/Mgmt */
+#define TRACE_BUFFER_MAX_SIZE 256
+
+#define DP_RX_PACKET_RING_CHUNK_SIZE 1600
+#define DP_TX_PACKET_RING_CHUNK_SIZE 1600
+#define DP_RX_PACKET_RING_CHUNK_NUM 2
+#define DP_TX_PACKET_RING_CHUNK_NUM 2
+#define DP_TX_COMPLETE_TIME_OUT 20
+#define FW_TX_CMPLT_BLOCK_SIZE 16
+
+#define TX_MSDU_LIFETIME_MIN 0
+#define TX_MSDU_LIFETIME_MAX 3000
+#define TX_MSDU_LIFETIME_DEF 512
+#define RX_MSDU_LIFETIME_MIN 0
+#define RX_MSDU_LIFETIME_MAX 0xFFFFFFFF
+#define RX_MSDU_LIFETIME_DEF 512000
+
+struct acx_rx_msdu_lifetime {
+ struct acx_header header;
+
+ /*
+ * The maximum amount of time, in TU, before the
+ * firmware discards the MSDU.
+ */
+ u32 lifetime;
+} __attribute__ ((packed));
+
+/*
+ * RX Config Options Table
+ * Bit Definition
+ * === ==========
+ * 31:14 Reserved
+ * 13 Copy RX Status - when set, write three receive status words
+ * to top of rx'd MPDUs.
+ * When cleared, do not write three status words (added rev 1.5)
+ * 12 Reserved
+ * 11 RX Complete upon FCS error - when set, give rx complete
+ * interrupt for FCS errors, after the rx filtering, e.g. unicast
+ * frames not to us with FCS error will not generate an interrupt.
+ * 10 SSID Filter Enable - When set, the WiLink discards all beacon,
+ * probe request, and probe response frames with an SSID that does
+ * not match the SSID specified by the host in the START/JOIN
+ * command.
+ * When clear, the WiLink receives frames with any SSID.
+ * 9 Broadcast Filter Enable - When set, the WiLink discards all
+ * broadcast frames. When clear, the WiLink receives all received
+ * broadcast frames.
+ * 8:6 Reserved
+ * 5 BSSID Filter Enable - When set, the WiLink discards any frames
+ * with a BSSID that does not match the BSSID specified by the
+ * host.
+ * When clear, the WiLink receives frames from any BSSID.
+ * 4 MAC Addr Filter - When set, the WiLink discards any frames
+ * with a destination address that does not match the MAC address
+ * of the adaptor.
+ * When clear, the WiLink receives frames destined to any MAC
+ * address.
+ * 3 Promiscuous - When set, the WiLink receives all valid frames
+ * (i.e., all frames that pass the FCS check).
+ * When clear, only frames that pass the other filters specified
+ * are received.
+ * 2 FCS - When set, the WiLink includes the FCS with the received
+ * frame.
+ * When cleared, the FCS is discarded.
+ * 1 PLCP header - When set, write all data from baseband to frame
+ * buffer including PHY header.
+ * 0 Reserved - Always equal to 0.
+ *
+ * RX Filter Options Table
+ * Bit Definition
+ * === ==========
+ * 31:12 Reserved - Always equal to 0.
+ * 11 Association - When set, the WiLink receives all association
+ * related frames (association request/response, reassocation
+ * request/response, and disassociation). When clear, these frames
+ * are discarded.
+ * 10 Auth/De auth - When set, the WiLink receives all authentication
+ * and de-authentication frames. When clear, these frames are
+ * discarded.
+ * 9 Beacon - When set, the WiLink receives all beacon frames.
+ * When clear, these frames are discarded.
+ * 8 Contention Free - When set, the WiLink receives all contention
+ * free frames.
+ * When clear, these frames are discarded.
+ * 7 Control - When set, the WiLink receives all control frames.
+ * When clear, these frames are discarded.
+ * 6 Data - When set, the WiLink receives all data frames.
+ * When clear, these frames are discarded.
+ * 5 FCS Error - When set, the WiLink receives frames that have FCS
+ * errors.
+ * When clear, these frames are discarded.
+ * 4 Management - When set, the WiLink receives all management
+ * frames.
+ * When clear, these frames are discarded.
+ * 3 Probe Request - When set, the WiLink receives all probe request
+ * frames.
+ * When clear, these frames are discarded.
+ * 2 Probe Response - When set, the WiLink receives all probe
+ * response frames.
+ * When clear, these frames are discarded.
+ * 1 RTS/CTS/ACK - When set, the WiLink receives all RTS, CTS and ACK
+ * frames.
+ * When clear, these frames are discarded.
+ * 0 Rsvd Type/Sub Type - When set, the WiLink receives all frames
+ * that have reserved frame types and sub types as defined by the
+ * 802.11 specification.
+ * When clear, these frames are discarded.
+ */
+struct acx_rx_config {
+ struct acx_header header;
+
+ u32 config_options;
+ u32 filter_options;
+} __attribute__ ((packed));
+
+struct acx_packet_detection {
+ struct acx_header header;
+
+ u32 threshold;
+} __attribute__ ((packed));
+
+
+enum acx_slot_type {
+ SLOT_TIME_LONG = 0,
+ SLOT_TIME_SHORT = 1,
+ DEFAULT_SLOT_TIME = SLOT_TIME_SHORT,
+ MAX_SLOT_TIMES = 0xFF
+};
+
+#define STATION_WONE_INDEX 0
+
+struct acx_slot {
+ struct acx_header header;
+
+ u8 wone_index; /* Reserved */
+ u8 slot_time;
+ u8 reserved[6];
+} __attribute__ ((packed));
+
+
+#define ADDRESS_GROUP_MAX (8)
+#define ADDRESS_GROUP_MAX_LEN (ETH_ALEN * ADDRESS_GROUP_MAX)
+
+struct acx_dot11_grp_addr_tbl {
+ struct acx_header header;
+
+ u8 enabled;
+ u8 num_groups;
+ u8 pad[2];
+ u8 mac_table[ADDRESS_GROUP_MAX_LEN];
+} __attribute__ ((packed));
+
+
+#define RX_TIMEOUT_PS_POLL_MIN 0
+#define RX_TIMEOUT_PS_POLL_MAX (200000)
+#define RX_TIMEOUT_PS_POLL_DEF (15)
+#define RX_TIMEOUT_UPSD_MIN 0
+#define RX_TIMEOUT_UPSD_MAX (200000)
+#define RX_TIMEOUT_UPSD_DEF (15)
+
+struct acx_rx_timeout {
+ struct acx_header header;
+
+ /*
+ * The longest time the STA will wait to receive
+ * traffic from the AP after a PS-poll has been
+ * transmitted.
+ */
+ u16 ps_poll_timeout;
+
+ /*
+ * The longest time the STA will wait to receive
+ * traffic from the AP after a frame has been sent
+ * from an UPSD enabled queue.
+ */
+ u16 upsd_timeout;
+} __attribute__ ((packed));
+
+#define RTS_THRESHOLD_MIN 0
+#define RTS_THRESHOLD_MAX 4096
+#define RTS_THRESHOLD_DEF 2347
+
+struct acx_rts_threshold {
+ struct acx_header header;
+
+ u16 threshold;
+ u8 pad[2];
+} __attribute__ ((packed));
+
+struct acx_beacon_filter_option {
+ struct acx_header header;
+
+ u8 enable;
+
+ /*
+ * The number of beacons without the unicast TIM
+ * bit set that the firmware buffers before
+ * signaling the host about ready frames.
+ * When set to 0 and the filter is enabled, beacons
+ * without the unicast TIM bit set are dropped.
+ */
+ u8 max_num_beacons;
+ u8 pad[2];
+} __attribute__ ((packed));
+
+/*
+ * ACXBeaconFilterEntry (not 221)
+ * Byte Offset Size (Bytes) Definition
+ * =========== ============ ==========
+ * 0 1 IE identifier
+ * 1 1 Treatment bit mask
+ *
+ * ACXBeaconFilterEntry (221)
+ * Byte Offset Size (Bytes) Definition
+ * =========== ============ ==========
+ * 0 1 IE identifier
+ * 1 1 Treatment bit mask
+ * 2 3 OUI
+ * 5 1 Type
+ * 6 2 Version
+ *
+ *
+ * Treatment bit mask - The information element handling:
+ * bit 0 - The information element is compared and transferred
+ * in case of change.
+ * bit 1 - The information element is transferred to the host
+ * with each appearance or disappearance.
+ * Note that both bits can be set at the same time.
+ */
+#define BEACON_FILTER_TABLE_MAX_IE_NUM (32)
+#define BEACON_FILTER_TABLE_MAX_VENDOR_SPECIFIC_IE_NUM (6)
+#define BEACON_FILTER_TABLE_IE_ENTRY_SIZE (2)
+#define BEACON_FILTER_TABLE_EXTRA_VENDOR_SPECIFIC_IE_SIZE (6)
+#define BEACON_FILTER_TABLE_MAX_SIZE ((BEACON_FILTER_TABLE_MAX_IE_NUM * \
+ BEACON_FILTER_TABLE_IE_ENTRY_SIZE) + \
+ (BEACON_FILTER_TABLE_MAX_VENDOR_SPECIFIC_IE_NUM * \
+ BEACON_FILTER_TABLE_EXTRA_VENDOR_SPECIFIC_IE_SIZE))
+
+struct acx_beacon_filter_ie_table {
+ struct acx_header header;
+
+ u8 num_ie;
+ u8 table[BEACON_FILTER_TABLE_MAX_SIZE];
+ u8 pad[3];
+} __attribute__ ((packed));
+
+enum {
+ SG_ENABLE = 0,
+ SG_DISABLE,
+ SG_SENSE_NO_ACTIVITY,
+ SG_SENSE_ACTIVE
+};
+
+struct acx_bt_wlan_coex {
+ struct acx_header header;
+
+ /*
+ * 0 -> PTA enabled
+ * 1 -> PTA disabled
+ * 2 -> sense no active mode, i.e.
+ * an interrupt is sent upon
+ * BT activity.
+ * 3 -> PTA is switched on in response
+ * to the interrupt sending.
+ */
+ u8 enable;
+ u8 pad[3];
+} __attribute__ ((packed));
+
+#define PTA_ANTENNA_TYPE_DEF (0)
+#define PTA_BT_HP_MAXTIME_DEF (2000)
+#define PTA_WLAN_HP_MAX_TIME_DEF (5000)
+#define PTA_SENSE_DISABLE_TIMER_DEF (1350)
+#define PTA_PROTECTIVE_RX_TIME_DEF (1500)
+#define PTA_PROTECTIVE_TX_TIME_DEF (1500)
+#define PTA_TIMEOUT_NEXT_BT_LP_PACKET_DEF (3000)
+#define PTA_SIGNALING_TYPE_DEF (1)
+#define PTA_AFH_LEVERAGE_ON_DEF (0)
+#define PTA_NUMBER_QUIET_CYCLE_DEF (0)
+#define PTA_MAX_NUM_CTS_DEF (3)
+#define PTA_NUMBER_OF_WLAN_PACKETS_DEF (2)
+#define PTA_NUMBER_OF_BT_PACKETS_DEF (2)
+#define PTA_PROTECTIVE_RX_TIME_FAST_DEF (1500)
+#define PTA_PROTECTIVE_TX_TIME_FAST_DEF (3000)
+#define PTA_CYCLE_TIME_FAST_DEF (8700)
+#define PTA_RX_FOR_AVALANCHE_DEF (5)
+#define PTA_ELP_HP_DEF (0)
+#define PTA_ANTI_STARVE_PERIOD_DEF (500)
+#define PTA_ANTI_STARVE_NUM_CYCLE_DEF (4)
+#define PTA_ALLOW_PA_SD_DEF (1)
+#define PTA_TIME_BEFORE_BEACON_DEF (6300)
+#define PTA_HPDM_MAX_TIME_DEF (1600)
+#define PTA_TIME_OUT_NEXT_WLAN_DEF (2550)
+#define PTA_AUTO_MODE_NO_CTS_DEF (0)
+#define PTA_BT_HP_RESPECTED_DEF (3)
+#define PTA_WLAN_RX_MIN_RATE_DEF (24)
+#define PTA_ACK_MODE_DEF (1)
+
+struct acx_bt_wlan_coex_param {
+ struct acx_header header;
+
+ /*
+ * The minimum rate of a received WLAN packet in the STA,
+ * during protective mode, of which a new BT-HP request
+ * during this Rx will always be respected and gain the antenna.
+ */
+ u32 min_rate;
+
+ /* Max time the BT HP will be respected. */
+ u16 bt_hp_max_time;
+
+ /* Max time the WLAN HP will be respected. */
+ u16 wlan_hp_max_time;
+
+ /*
+ * The time between the last BT activity
+ * and the moment when the sense mode returns
+ * to SENSE_INACTIVE.
+ */
+ u16 sense_disable_timer;
+
+ /* Time before the next BT HP instance */
+ u16 rx_time_bt_hp;
+ u16 tx_time_bt_hp;
+
+ /* range: 10-20000 default: 1500 */
+ u16 rx_time_bt_hp_fast;
+ u16 tx_time_bt_hp_fast;
+
+ /* range: 2000-65535 default: 8700 */
+ u16 wlan_cycle_fast;
+
+ /* range: 0 - 15000 (Msec) default: 1000 */
+ u16 bt_anti_starvation_period;
+
+ /* range 400-10000(Usec) default: 3000 */
+ u16 next_bt_lp_packet;
+
+ /* Deafult: worst case for BT DH5 traffic */
+ u16 wake_up_beacon;
+
+ /* range: 0-50000(Usec) default: 1050 */
+ u16 hp_dm_max_guard_time;
+
+ /*
+ * This is to prevent both BT & WLAN antenna
+ * starvation.
+ * Range: 100-50000(Usec) default:2550
+ */
+ u16 next_wlan_packet;
+
+ /* 0 -> shared antenna */
+ u8 antenna_type;
+
+ /*
+ * 0 -> TI legacy
+ * 1 -> Palau
+ */
+ u8 signal_type;
+
+ /*
+ * BT AFH status
+ * 0 -> no AFH
+ * 1 -> from dedicated GPIO
+ * 2 -> AFH on (from host)
+ */
+ u8 afh_leverage_on;
+
+ /*
+ * The number of cycles during which no
+ * TX will be sent after 1 cycle of RX
+ * transaction in protective mode
+ */
+ u8 quiet_cycle_num;
+
+ /*
+ * The maximum number of CTSs that will
+ * be sent for receiving RX packet in
+ * protective mode
+ */
+ u8 max_cts;
+
+ /*
+ * The number of WLAN packets
+ * transferred in common mode before
+ * switching to BT.
+ */
+ u8 wlan_packets_num;
+
+ /*
+ * The number of BT packets
+ * transferred in common mode before
+ * switching to WLAN.
+ */
+ u8 bt_packets_num;
+
+ /* range: 1-255 default: 5 */
+ u8 missed_rx_avalanche;
+
+ /* range: 0-1 default: 1 */
+ u8 wlan_elp_hp;
+
+ /* range: 0 - 15 default: 4 */
+ u8 bt_anti_starvation_cycles;
+
+ u8 ack_mode_dual_ant;
+
+ /*
+ * Allow PA_SD assertion/de-assertion
+ * during enabled BT activity.
+ */
+ u8 pa_sd_enable;
+
+ /*
+ * Enable/Disable PTA in auto mode:
+ * Support Both Active & P.S modes
+ */
+ u8 pta_auto_mode_enable;
+
+ /* range: 0 - 20 default: 1 */
+ u8 bt_hp_respected_num;
+} __attribute__ ((packed));
+
+#define CCA_THRSH_ENABLE_ENERGY_D 0x140A
+#define CCA_THRSH_DISABLE_ENERGY_D 0xFFEF
+
+struct acx_energy_detection {
+ struct acx_header header;
+
+ /* The RX Clear Channel Assessment threshold in the PHY */
+ u16 rx_cca_threshold;
+ u8 tx_energy_detection;
+ u8 pad;
+} __attribute__ ((packed));
+
+#define BCN_RX_TIMEOUT_DEF_VALUE 10000
+#define BROADCAST_RX_TIMEOUT_DEF_VALUE 20000
+#define RX_BROADCAST_IN_PS_DEF_VALUE 1
+#define CONSECUTIVE_PS_POLL_FAILURE_DEF 4
+
+struct acx_beacon_broadcast {
+ struct acx_header header;
+
+ u16 beacon_rx_timeout;
+ u16 broadcast_timeout;
+
+ /* Enables receiving of broadcast packets in PS mode */
+ u8 rx_broadcast_in_ps;
+
+ /* Consecutive PS Poll failures before updating the host */
+ u8 ps_poll_threshold;
+ u8 pad[2];
+} __attribute__ ((packed));
+
+struct acx_event_mask {
+ struct acx_header header;
+
+ u32 event_mask;
+ u32 high_event_mask; /* Unused */
+} __attribute__ ((packed));
+
+#define CFG_RX_FCS BIT(2)
+#define CFG_RX_ALL_GOOD BIT(3)
+#define CFG_UNI_FILTER_EN BIT(4)
+#define CFG_BSSID_FILTER_EN BIT(5)
+#define CFG_MC_FILTER_EN BIT(6)
+#define CFG_MC_ADDR0_EN BIT(7)
+#define CFG_MC_ADDR1_EN BIT(8)
+#define CFG_BC_REJECT_EN BIT(9)
+#define CFG_SSID_FILTER_EN BIT(10)
+#define CFG_RX_INT_FCS_ERROR BIT(11)
+#define CFG_RX_INT_ENCRYPTED BIT(12)
+#define CFG_RX_WR_RX_STATUS BIT(13)
+#define CFG_RX_FILTER_NULTI BIT(14)
+#define CFG_RX_RESERVE BIT(15)
+#define CFG_RX_TIMESTAMP_TSF BIT(16)
+
+#define CFG_RX_RSV_EN BIT(0)
+#define CFG_RX_RCTS_ACK BIT(1)
+#define CFG_RX_PRSP_EN BIT(2)
+#define CFG_RX_PREQ_EN BIT(3)
+#define CFG_RX_MGMT_EN BIT(4)
+#define CFG_RX_FCS_ERROR BIT(5)
+#define CFG_RX_DATA_EN BIT(6)
+#define CFG_RX_CTL_EN BIT(7)
+#define CFG_RX_CF_EN BIT(8)
+#define CFG_RX_BCN_EN BIT(9)
+#define CFG_RX_AUTH_EN BIT(10)
+#define CFG_RX_ASSOC_EN BIT(11)
+
+#define SCAN_PASSIVE BIT(0)
+#define SCAN_5GHZ_BAND BIT(1)
+#define SCAN_TRIGGERED BIT(2)
+#define SCAN_PRIORITY_HIGH BIT(3)
+
+struct acx_feature_config {
+ struct acx_header header;
+
+ u32 options;
+ u32 data_flow_options;
+} __attribute__ ((packed));
+
+struct acx_current_tx_power {
+ struct acx_header header;
+
+ u8 current_tx_power;
+ u8 padding[3];
+} __attribute__ ((packed));
+
+enum acx_wake_up_event {
+ WAKE_UP_EVENT_BEACON_BITMAP = 0x01, /* Wake on every Beacon*/
+ WAKE_UP_EVENT_DTIM_BITMAP = 0x02, /* Wake on every DTIM*/
+ WAKE_UP_EVENT_N_DTIM_BITMAP = 0x04, /* Wake on every Nth DTIM */
+ WAKE_UP_EVENT_N_BEACONS_BITMAP = 0x08, /* Wake on every Nth Beacon */
+ WAKE_UP_EVENT_BITS_MASK = 0x0F
+};
+
+struct acx_wake_up_condition {
+ struct acx_header header;
+
+ u8 wake_up_event; /* Only one bit can be set */
+ u8 listen_interval;
+ u8 pad[2];
+} __attribute__ ((packed));
+
+struct acx_aid {
+ struct acx_header header;
+
+ /*
+ * To be set when associated with an AP.
+ */
+ u16 aid;
+ u8 pad[2];
+} __attribute__ ((packed));
+
+enum acx_preamble_type {
+ ACX_PREAMBLE_LONG = 0,
+ ACX_PREAMBLE_SHORT = 1
+};
+
+struct acx_preamble {
+ struct acx_header header;
+
+ /*
+ * When set, the WiLink transmits the frames with a short preamble and
+ * when cleared, the WiLink transmits the frames with a long preamble.
+ */
+ u8 preamble;
+ u8 padding[3];
+} __attribute__ ((packed));
+
+enum acx_ctsprotect_type {
+ CTSPROTECT_DISABLE = 0,
+ CTSPROTECT_ENABLE = 1
+};
+
+struct acx_ctsprotect {
+ struct acx_header header;
+ u8 ctsprotect;
+ u8 padding[3];
+} __attribute__ ((packed));
+
+struct acx_tx_statistics {
+ u32 internal_desc_overflow;
+} __attribute__ ((packed));
+
+struct acx_rx_statistics {
+ u32 out_of_mem;
+ u32 hdr_overflow;
+ u32 hw_stuck;
+ u32 dropped;
+ u32 fcs_err;
+ u32 xfr_hint_trig;
+ u32 path_reset;
+ u32 reset_counter;
+} __attribute__ ((packed));
+
+struct acx_dma_statistics {
+ u32 rx_requested;
+ u32 rx_errors;
+ u32 tx_requested;
+ u32 tx_errors;
+} __attribute__ ((packed));
+
+struct acx_isr_statistics {
+ /* host command complete */
+ u32 cmd_cmplt;
+
+ /* fiqisr() */
+ u32 fiqs;
+
+ /* (INT_STS_ND & INT_TRIG_RX_HEADER) */
+ u32 rx_headers;
+
+ /* (INT_STS_ND & INT_TRIG_RX_CMPLT) */
+ u32 rx_completes;
+
+ /* (INT_STS_ND & INT_TRIG_NO_RX_BUF) */
+ u32 rx_mem_overflow;
+
+ /* (INT_STS_ND & INT_TRIG_S_RX_RDY) */
+ u32 rx_rdys;
+
+ /* irqisr() */
+ u32 irqs;
+
+ /* (INT_STS_ND & INT_TRIG_TX_PROC) */
+ u32 tx_procs;
+
+ /* (INT_STS_ND & INT_TRIG_DECRYPT_DONE) */
+ u32 decrypt_done;
+
+ /* (INT_STS_ND & INT_TRIG_DMA0) */
+ u32 dma0_done;
+
+ /* (INT_STS_ND & INT_TRIG_DMA1) */
+ u32 dma1_done;
+
+ /* (INT_STS_ND & INT_TRIG_TX_EXC_CMPLT) */
+ u32 tx_exch_complete;
+
+ /* (INT_STS_ND & INT_TRIG_COMMAND) */
+ u32 commands;
+
+ /* (INT_STS_ND & INT_TRIG_RX_PROC) */
+ u32 rx_procs;
+
+ /* (INT_STS_ND & INT_TRIG_PM_802) */
+ u32 hw_pm_mode_changes;
+
+ /* (INT_STS_ND & INT_TRIG_ACKNOWLEDGE) */
+ u32 host_acknowledges;
+
+ /* (INT_STS_ND & INT_TRIG_PM_PCI) */
+ u32 pci_pm;
+
+ /* (INT_STS_ND & INT_TRIG_ACM_WAKEUP) */
+ u32 wakeups;
+
+ /* (INT_STS_ND & INT_TRIG_LOW_RSSI) */
+ u32 low_rssi;
+} __attribute__ ((packed));
+
+struct acx_wep_statistics {
+ /* WEP address keys configured */
+ u32 addr_key_count;
+
+ /* default keys configured */
+ u32 default_key_count;
+
+ u32 reserved;
+
+ /* number of times that WEP key not found on lookup */
+ u32 key_not_found;
+
+ /* number of times that WEP key decryption failed */
+ u32 decrypt_fail;
+
+ /* WEP packets decrypted */
+ u32 packets;
+
+ /* WEP decrypt interrupts */
+ u32 interrupt;
+} __attribute__ ((packed));
+
+#define ACX_MISSED_BEACONS_SPREAD 10
+
+struct acx_pwr_statistics {
+ /* the amount of enters into power save mode (both PD & ELP) */
+ u32 ps_enter;
+
+ /* the amount of enters into ELP mode */
+ u32 elp_enter;
+
+ /* the amount of missing beacon interrupts to the host */
+ u32 missing_bcns;
+
+ /* the amount of wake on host-access times */
+ u32 wake_on_host;
+
+ /* the amount of wake on timer-expire */
+ u32 wake_on_timer_exp;
+
+ /* the number of packets that were transmitted with PS bit set */
+ u32 tx_with_ps;
+
+ /* the number of packets that were transmitted with PS bit clear */
+ u32 tx_without_ps;
+
+ /* the number of received beacons */
+ u32 rcvd_beacons;
+
+ /* the number of entering into PowerOn (power save off) */
+ u32 power_save_off;
+
+ /* the number of entries into power save mode */
+ u16 enable_ps;
+
+ /*
+ * the number of exits from power save, not including failed PS
+ * transitions
+ */
+ u16 disable_ps;
+
+ /*
+ * the number of times the TSF counter was adjusted because
+ * of drift
+ */
+ u32 fix_tsf_ps;
+
+ /* Gives statistics about the spread continuous missed beacons.
+ * The 16 LSB are dedicated for the PS mode.
+ * The 16 MSB are dedicated for the PS mode.
+ * cont_miss_bcns_spread[0] - single missed beacon.
+ * cont_miss_bcns_spread[1] - two continuous missed beacons.
+ * cont_miss_bcns_spread[2] - three continuous missed beacons.
+ * ...
+ * cont_miss_bcns_spread[9] - ten and more continuous missed beacons.
+ */
+ u32 cont_miss_bcns_spread[ACX_MISSED_BEACONS_SPREAD];
+
+ /* the number of beacons in awake mode */
+ u32 rcvd_awake_beacons;
+} __attribute__ ((packed));
+
+struct acx_mic_statistics {
+ u32 rx_pkts;
+ u32 calc_failure;
+} __attribute__ ((packed));
+
+struct acx_aes_statistics {
+ u32 encrypt_fail;
+ u32 decrypt_fail;
+ u32 encrypt_packets;
+ u32 decrypt_packets;
+ u32 encrypt_interrupt;
+ u32 decrypt_interrupt;
+} __attribute__ ((packed));
+
+struct acx_event_statistics {
+ u32 heart_beat;
+ u32 calibration;
+ u32 rx_mismatch;
+ u32 rx_mem_empty;
+ u32 rx_pool;
+ u32 oom_late;
+ u32 phy_transmit_error;
+ u32 tx_stuck;
+} __attribute__ ((packed));
+
+struct acx_ps_statistics {
+ u32 pspoll_timeouts;
+ u32 upsd_timeouts;
+ u32 upsd_max_sptime;
+ u32 upsd_max_apturn;
+ u32 pspoll_max_apturn;
+ u32 pspoll_utilization;
+ u32 upsd_utilization;
+} __attribute__ ((packed));
+
+struct acx_rxpipe_statistics {
+ u32 rx_prep_beacon_drop;
+ u32 descr_host_int_trig_rx_data;
+ u32 beacon_buffer_thres_host_int_trig_rx_data;
+ u32 missed_beacon_host_int_trig_rx_data;
+ u32 tx_xfr_host_int_trig_rx_data;
+} __attribute__ ((packed));
+
+struct acx_statistics {
+ struct acx_header header;
+
+ struct acx_tx_statistics tx;
+ struct acx_rx_statistics rx;
+ struct acx_dma_statistics dma;
+ struct acx_isr_statistics isr;
+ struct acx_wep_statistics wep;
+ struct acx_pwr_statistics pwr;
+ struct acx_aes_statistics aes;
+ struct acx_mic_statistics mic;
+ struct acx_event_statistics event;
+ struct acx_ps_statistics ps;
+ struct acx_rxpipe_statistics rxpipe;
+} __attribute__ ((packed));
+
+#define ACX_MAX_RATE_CLASSES 8
+#define ACX_RATE_MASK_UNSPECIFIED 0
+#define ACX_RATE_MASK_ALL 0x1eff
+#define ACX_RATE_RETRY_LIMIT 10
+
+struct acx_rate_class {
+ u32 enabled_rates;
+ u8 short_retry_limit;
+ u8 long_retry_limit;
+ u8 aflags;
+ u8 reserved;
+};
+
+struct acx_rate_policy {
+ struct acx_header header;
+
+ u32 rate_class_cnt;
+ struct acx_rate_class rate_class[ACX_MAX_RATE_CLASSES];
+} __attribute__ ((packed));
+
+#define WL1271_ACX_AC_COUNT 4
+
+struct acx_ac_cfg {
+ struct acx_header header;
+ u8 ac;
+ u8 cw_min;
+ u16 cw_max;
+ u8 aifsn;
+ u8 reserved;
+ u16 tx_op_limit;
+} __attribute__ ((packed));
+
+enum wl1271_acx_ac {
+ WL1271_ACX_AC_BE = 0,
+ WL1271_ACX_AC_BK = 1,
+ WL1271_ACX_AC_VI = 2,
+ WL1271_ACX_AC_VO = 3,
+ WL1271_ACX_AC_CTS2SELF = 4,
+ WL1271_ACX_AC_ANY_TID = 0x1F,
+ WL1271_ACX_AC_INVALID = 0xFF,
+};
+
+enum wl1271_acx_ps_scheme {
+ WL1271_ACX_PS_SCHEME_LEGACY = 0,
+ WL1271_ACX_PS_SCHEME_UPSD_TRIGGER = 1,
+ WL1271_ACX_PS_SCHEME_LEGACY_PSPOLL = 2,
+ WL1271_ACX_PS_SCHEME_SAPSD = 3,
+};
+
+enum wl1271_acx_ack_policy {
+ WL1271_ACX_ACK_POLICY_LEGACY = 0,
+ WL1271_ACX_ACK_POLICY_NO_ACK = 1,
+ WL1271_ACX_ACK_POLICY_BLOCK = 2,
+};
+
+#define WL1271_ACX_TID_COUNT 7
+
+struct acx_tid_config {
+ struct acx_header header;
+ u8 queue_id;
+ u8 channel_type;
+ u8 tsid;
+ u8 ps_scheme;
+ u8 ack_policy;
+ u8 padding[3];
+ u32 apsd_conf[2];
+} __attribute__ ((packed));
+
+struct acx_frag_threshold {
+ struct acx_header header;
+ u16 frag_threshold;
+ u8 padding[2];
+} __attribute__ ((packed));
+
+#define WL1271_ACX_TX_COMPL_TIMEOUT 5
+#define WL1271_ACX_TX_COMPL_THRESHOLD 5
+
+struct acx_tx_config_options {
+ struct acx_header header;
+ u16 tx_compl_timeout; /* msec */
+ u16 tx_compl_threshold; /* number of packets */
+} __attribute__ ((packed));
+
+#define ACX_RX_MEM_BLOCKS 64
+#define ACX_TX_MIN_MEM_BLOCKS 64
+#define ACX_TX_DESCRIPTORS 32
+#define ACX_NUM_SSID_PROFILES 1
+
+struct wl1271_acx_config_memory {
+ struct acx_header header;
+
+ u8 rx_mem_block_num;
+ u8 tx_min_mem_block_num;
+ u8 num_stations;
+ u8 num_ssid_profiles;
+ u32 total_tx_descriptors;
+} __attribute__ ((packed));
+
+struct wl1271_acx_mem_map {
+ struct acx_header header;
+
+ void *code_start;
+ void *code_end;
+
+ void *wep_defkey_start;
+ void *wep_defkey_end;
+
+ void *sta_table_start;
+ void *sta_table_end;
+
+ void *packet_template_start;
+ void *packet_template_end;
+
+ /* Address of the TX result interface (control block) */
+ u32 tx_result;
+ u32 tx_result_queue_start;
+
+ void *queue_memory_start;
+ void *queue_memory_end;
+
+ u32 packet_memory_pool_start;
+ u32 packet_memory_pool_end;
+
+ void *debug_buffer1_start;
+ void *debug_buffer1_end;
+
+ void *debug_buffer2_start;
+ void *debug_buffer2_end;
+
+ /* Number of blocks FW allocated for TX packets */
+ u32 num_tx_mem_blocks;
+
+ /* Number of blocks FW allocated for RX packets */
+ u32 num_rx_mem_blocks;
+
+ /* the following 4 fields are valid in SLAVE mode only */
+ u8 *tx_cbuf;
+ u8 *rx_cbuf;
+ void *rx_ctrl;
+ void *tx_ctrl;
+} __attribute__ ((packed));
+
+enum wl1271_acx_rx_queue_type {
+ RX_QUEUE_TYPE_RX_LOW_PRIORITY, /* All except the high priority */
+ RX_QUEUE_TYPE_RX_HIGH_PRIORITY, /* Management and voice packets */
+ RX_QUEUE_TYPE_NUM,
+ RX_QUEUE_TYPE_MAX = USHORT_MAX
+};
+
+#define WL1271_RX_INTR_THRESHOLD_DEF 0 /* no pacing, send interrupt on
+ * every event */
+#define WL1271_RX_INTR_THRESHOLD_MIN 0
+#define WL1271_RX_INTR_THRESHOLD_MAX 15
+
+#define WL1271_RX_INTR_TIMEOUT_DEF 5
+#define WL1271_RX_INTR_TIMEOUT_MIN 1
+#define WL1271_RX_INTR_TIMEOUT_MAX 100
+
+struct wl1271_acx_rx_config_opt {
+ struct acx_header header;
+
+ u16 mblk_threshold;
+ u16 threshold;
+ u16 timeout;
+ u8 queue_type;
+ u8 reserved;
+} __attribute__ ((packed));
+
+enum {
+ ACX_WAKE_UP_CONDITIONS = 0x0002,
+ ACX_MEM_CFG = 0x0003,
+ ACX_SLOT = 0x0004,
+ ACX_AC_CFG = 0x0007,
+ ACX_MEM_MAP = 0x0008,
+ ACX_AID = 0x000A,
+ /* ACX_FW_REV is missing in the ref driver, but seems to work */
+ ACX_FW_REV = 0x000D,
+ ACX_MEDIUM_USAGE = 0x000F,
+ ACX_RX_CFG = 0x0010,
+ ACX_TX_QUEUE_CFG = 0x0011, /* FIXME: only used by wl1251 */
+ ACX_STATISTICS = 0x0013, /* Debug API */
+ ACX_PWR_CONSUMPTION_STATISTICS = 0x0014,
+ ACX_FEATURE_CFG = 0x0015,
+ ACX_TID_CFG = 0x001A,
+ ACX_PS_RX_STREAMING = 0x001B,
+ ACX_BEACON_FILTER_OPT = 0x001F,
+ ACX_NOISE_HIST = 0x0021,
+ ACX_HDK_VERSION = 0x0022, /* ??? */
+ ACX_PD_THRESHOLD = 0x0023,
+ ACX_TX_CONFIG_OPT = 0x0024,
+ ACX_CCA_THRESHOLD = 0x0025,
+ ACX_EVENT_MBOX_MASK = 0x0026,
+ ACX_CONN_MONIT_PARAMS = 0x002D,
+ ACX_CONS_TX_FAILURE = 0x002F,
+ ACX_BCN_DTIM_OPTIONS = 0x0031,
+ ACX_SG_ENABLE = 0x0032,
+ ACX_SG_CFG = 0x0033,
+ ACX_BEACON_FILTER_TABLE = 0x0038,
+ ACX_ARP_IP_FILTER = 0x0039,
+ ACX_ROAMING_STATISTICS_TBL = 0x003B,
+ ACX_RATE_POLICY = 0x003D,
+ ACX_CTS_PROTECTION = 0x003E,
+ ACX_SLEEP_AUTH = 0x003F,
+ ACX_PREAMBLE_TYPE = 0x0040,
+ ACX_ERROR_CNT = 0x0041,
+ ACX_IBSS_FILTER = 0x0044,
+ ACX_SERVICE_PERIOD_TIMEOUT = 0x0045,
+ ACX_TSF_INFO = 0x0046,
+ ACX_CONFIG_PS_WMM = 0x0049,
+ ACX_ENABLE_RX_DATA_FILTER = 0x004A,
+ ACX_SET_RX_DATA_FILTER = 0x004B,
+ ACX_GET_DATA_FILTER_STATISTICS = 0x004C,
+ ACX_RX_CONFIG_OPT = 0x004E,
+ ACX_FRAG_CFG = 0x004F,
+ ACX_BET_ENABLE = 0x0050,
+ ACX_RSSI_SNR_TRIGGER = 0x0051,
+ ACX_RSSI_SNR_WEIGHTS = 0x0051,
+ ACX_KEEP_ALIVE_MODE = 0x0052,
+ ACX_SET_KEEP_ALIVE_CONFIG = 0x0054,
+ ACX_BA_SESSION_RESPONDER_POLICY = 0x0055,
+ ACX_BA_SESSION_INITIATOR_POLICY = 0x0056,
+ ACX_PEER_HT_CAP = 0x0057,
+ ACX_HT_BSS_OPERATION = 0x0058,
+ ACX_COEX_ACTIVITY = 0x0059,
+ DOT11_RX_MSDU_LIFE_TIME = 0x1004,
+ DOT11_CUR_TX_PWR = 0x100D,
+ DOT11_RX_DOT11_MODE = 0x1012,
+ DOT11_RTS_THRESHOLD = 0x1013,
+ DOT11_GROUP_ADDRESS_TBL = 0x1014,
+
+ MAX_DOT11_IE = DOT11_GROUP_ADDRESS_TBL,
+
+ MAX_IE = 0xFFFF
+};
+
+
+int wl1271_acx_wake_up_conditions(struct wl1271 *wl, u8 wake_up_event,
+ u8 listen_interval);
+int wl1271_acx_sleep_auth(struct wl1271 *wl, u8 sleep_auth);
+int wl1271_acx_fw_version(struct wl1271 *wl, char *buf, size_t len);
+int wl1271_acx_tx_power(struct wl1271 *wl, int power);
+int wl1271_acx_feature_cfg(struct wl1271 *wl);
+int wl1271_acx_mem_map(struct wl1271 *wl,
+ struct acx_header *mem_map, size_t len);
+int wl1271_acx_rx_msdu_life_time(struct wl1271 *wl, u32 life_time);
+int wl1271_acx_rx_config(struct wl1271 *wl, u32 config, u32 filter);
+int wl1271_acx_pd_threshold(struct wl1271 *wl);
+int wl1271_acx_slot(struct wl1271 *wl, enum acx_slot_type slot_time);
+int wl1271_acx_group_address_tbl(struct wl1271 *wl);
+int wl1271_acx_service_period_timeout(struct wl1271 *wl);
+int wl1271_acx_rts_threshold(struct wl1271 *wl, u16 rts_threshold);
+int wl1271_acx_beacon_filter_opt(struct wl1271 *wl);
+int wl1271_acx_beacon_filter_table(struct wl1271 *wl);
+int wl1271_acx_sg_enable(struct wl1271 *wl);
+int wl1271_acx_sg_cfg(struct wl1271 *wl);
+int wl1271_acx_cca_threshold(struct wl1271 *wl);
+int wl1271_acx_bcn_dtim_options(struct wl1271 *wl);
+int wl1271_acx_aid(struct wl1271 *wl, u16 aid);
+int wl1271_acx_event_mbox_mask(struct wl1271 *wl, u32 event_mask);
+int wl1271_acx_set_preamble(struct wl1271 *wl, enum acx_preamble_type preamble);
+int wl1271_acx_cts_protect(struct wl1271 *wl,
+ enum acx_ctsprotect_type ctsprotect);
+int wl1271_acx_statistics(struct wl1271 *wl, struct acx_statistics *stats);
+int wl1271_acx_rate_policies(struct wl1271 *wl);
+int wl1271_acx_ac_cfg(struct wl1271 *wl);
+int wl1271_acx_tid_cfg(struct wl1271 *wl);
+int wl1271_acx_frag_threshold(struct wl1271 *wl);
+int wl1271_acx_tx_config_options(struct wl1271 *wl);
+int wl1271_acx_mem_cfg(struct wl1271 *wl);
+int wl1271_acx_init_mem_config(struct wl1271 *wl);
+int wl1271_acx_init_rx_interrupt(struct wl1271 *wl);
+
+#endif /* __WL1271_ACX_H__ */
diff --git a/drivers/net/wireless/wl12xx/wl1271_boot.c b/drivers/net/wireless/wl12xx/wl1271_boot.c
new file mode 100644
index 00000000000..8228ef474a7
--- /dev/null
+++ b/drivers/net/wireless/wl12xx/wl1271_boot.c
@@ -0,0 +1,541 @@
+/*
+ * This file is part of wl1271
+ *
+ * Copyright (C) 2008-2009 Nokia Corporation
+ *
+ * Contact: Luciano Coelho <luciano.coelho@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/gpio.h>
+
+#include "wl1271_acx.h"
+#include "wl1271_reg.h"
+#include "wl1271_boot.h"
+#include "wl1271_spi.h"
+#include "wl1271_event.h"
+
+static struct wl1271_partition_set part_table[PART_TABLE_LEN] = {
+ [PART_DOWN] = {
+ .mem = {
+ .start = 0x00000000,
+ .size = 0x000177c0
+ },
+ .reg = {
+ .start = REGISTERS_BASE,
+ .size = 0x00008800
+ },
+ },
+
+ [PART_WORK] = {
+ .mem = {
+ .start = 0x00040000,
+ .size = 0x00014fc0
+ },
+ .reg = {
+ .start = REGISTERS_BASE,
+ .size = 0x0000b000
+ },
+ },
+
+ [PART_DRPW] = {
+ .mem = {
+ .start = 0x00040000,
+ .size = 0x00014fc0
+ },
+ .reg = {
+ .start = DRPW_BASE,
+ .size = 0x00006000
+ }
+ }
+};
+
+static void wl1271_boot_set_ecpu_ctrl(struct wl1271 *wl, u32 flag)
+{
+ u32 cpu_ctrl;
+
+ /* 10.5.0 run the firmware (I) */
+ cpu_ctrl = wl1271_reg_read32(wl, ACX_REG_ECPU_CONTROL);
+
+ /* 10.5.1 run the firmware (II) */
+ cpu_ctrl |= flag;
+ wl1271_reg_write32(wl, ACX_REG_ECPU_CONTROL, cpu_ctrl);
+}
+
+static void wl1271_boot_fw_version(struct wl1271 *wl)
+{
+ struct wl1271_static_data static_data;
+
+ wl1271_spi_mem_read(wl, wl->cmd_box_addr,
+ &static_data, sizeof(static_data));
+
+ strncpy(wl->chip.fw_ver, static_data.fw_version,
+ sizeof(wl->chip.fw_ver));
+
+ /* make sure the string is NULL-terminated */
+ wl->chip.fw_ver[sizeof(wl->chip.fw_ver) - 1] = '\0';
+}
+
+static int wl1271_boot_upload_firmware_chunk(struct wl1271 *wl, void *buf,
+ size_t fw_data_len, u32 dest)
+{
+ int addr, chunk_num, partition_limit;
+ u8 *p;
+
+ /* whal_FwCtrl_LoadFwImageSm() */
+
+ wl1271_debug(DEBUG_BOOT, "starting firmware upload");
+
+ wl1271_debug(DEBUG_BOOT, "fw_data_len %zd chunk_size %d",
+ fw_data_len, CHUNK_SIZE);
+
+
+ if ((fw_data_len % 4) != 0) {
+ wl1271_error("firmware length not multiple of four");
+ return -EIO;
+ }
+
+ wl1271_set_partition(wl, dest,
+ part_table[PART_DOWN].mem.size,
+ part_table[PART_DOWN].reg.start,
+ part_table[PART_DOWN].reg.size);
+
+ /* 10.1 set partition limit and chunk num */
+ chunk_num = 0;
+ partition_limit = part_table[PART_DOWN].mem.size;
+
+ while (chunk_num < fw_data_len / CHUNK_SIZE) {
+ /* 10.2 update partition, if needed */
+ addr = dest + (chunk_num + 2) * CHUNK_SIZE;
+ if (addr > partition_limit) {
+ addr = dest + chunk_num * CHUNK_SIZE;
+ partition_limit = chunk_num * CHUNK_SIZE +
+ part_table[PART_DOWN].mem.size;
+
+ /* FIXME: Over 80 chars! */
+ wl1271_set_partition(wl,
+ addr,
+ part_table[PART_DOWN].mem.size,
+ part_table[PART_DOWN].reg.start,
+ part_table[PART_DOWN].reg.size);
+ }
+
+ /* 10.3 upload the chunk */
+ addr = dest + chunk_num * CHUNK_SIZE;
+ p = buf + chunk_num * CHUNK_SIZE;
+ wl1271_debug(DEBUG_BOOT, "uploading fw chunk 0x%p to 0x%x",
+ p, addr);
+ wl1271_spi_mem_write(wl, addr, p, CHUNK_SIZE);
+
+ chunk_num++;
+ }
+
+ /* 10.4 upload the last chunk */
+ addr = dest + chunk_num * CHUNK_SIZE;
+ p = buf + chunk_num * CHUNK_SIZE;
+ wl1271_debug(DEBUG_BOOT, "uploading fw last chunk (%zd B) 0x%p to 0x%x",
+ fw_data_len % CHUNK_SIZE, p, addr);
+ wl1271_spi_mem_write(wl, addr, p, fw_data_len % CHUNK_SIZE);
+
+ return 0;
+}
+
+static int wl1271_boot_upload_firmware(struct wl1271 *wl)
+{
+ u32 chunks, addr, len;
+ u8 *fw;
+
+ fw = wl->fw;
+ chunks = be32_to_cpup((u32 *) fw);
+ fw += sizeof(u32);
+
+ wl1271_debug(DEBUG_BOOT, "firmware chunks to be uploaded: %u", chunks);
+
+ while (chunks--) {
+ addr = be32_to_cpup((u32 *) fw);
+ fw += sizeof(u32);
+ len = be32_to_cpup((u32 *) fw);
+ fw += sizeof(u32);
+
+ if (len > 300000) {
+ wl1271_info("firmware chunk too long: %u", len);
+ return -EINVAL;
+ }
+ wl1271_debug(DEBUG_BOOT, "chunk %d addr 0x%x len %u",
+ chunks, addr, len);
+ wl1271_boot_upload_firmware_chunk(wl, fw, len, addr);
+ fw += len;
+ }
+
+ return 0;
+}
+
+static int wl1271_boot_upload_nvs(struct wl1271 *wl)
+{
+ size_t nvs_len, burst_len;
+ int i;
+ u32 dest_addr, val;
+ u8 *nvs_ptr, *nvs, *nvs_aligned;
+
+ nvs = wl->nvs;
+ if (nvs == NULL)
+ return -ENODEV;
+
+ nvs_ptr = nvs;
+
+ nvs_len = wl->nvs_len;
+
+ /* Update the device MAC address into the nvs */
+ nvs[11] = wl->mac_addr[0];
+ nvs[10] = wl->mac_addr[1];
+ nvs[6] = wl->mac_addr[2];
+ nvs[5] = wl->mac_addr[3];
+ nvs[4] = wl->mac_addr[4];
+ nvs[3] = wl->mac_addr[5];
+
+ /*
+ * Layout before the actual NVS tables:
+ * 1 byte : burst length.
+ * 2 bytes: destination address.
+ * n bytes: data to burst copy.
+ *
+ * This is ended by a 0 length, then the NVS tables.
+ */
+
+ /* FIXME: Do we need to check here whether the LSB is 1? */
+ while (nvs_ptr[0]) {
+ burst_len = nvs_ptr[0];
+ dest_addr = (nvs_ptr[1] & 0xfe) | ((u32)(nvs_ptr[2] << 8));
+
+ /* FIXME: Due to our new wl1271_translate_reg_addr function,
+ we need to add the REGISTER_BASE to the destination */
+ dest_addr += REGISTERS_BASE;
+
+ /* We move our pointer to the data */
+ nvs_ptr += 3;
+
+ for (i = 0; i < burst_len; i++) {
+ val = (nvs_ptr[0] | (nvs_ptr[1] << 8)
+ | (nvs_ptr[2] << 16) | (nvs_ptr[3] << 24));
+
+ wl1271_debug(DEBUG_BOOT,
+ "nvs burst write 0x%x: 0x%x",
+ dest_addr, val);
+ wl1271_reg_write32(wl, dest_addr, val);
+
+ nvs_ptr += 4;
+ dest_addr += 4;
+ }
+ }
+
+ /*
+ * We've reached the first zero length, the first NVS table
+ * is 7 bytes further.
+ */
+ nvs_ptr += 7;
+ nvs_len -= nvs_ptr - nvs;
+ nvs_len = ALIGN(nvs_len, 4);
+
+ /* FIXME: The driver sets the partition here, but this is not needed,
+ since it sets to the same one as currently in use */
+ /* Now we must set the partition correctly */
+ wl1271_set_partition(wl,
+ part_table[PART_WORK].mem.start,
+ part_table[PART_WORK].mem.size,
+ part_table[PART_WORK].reg.start,
+ part_table[PART_WORK].reg.size);
+
+ /* Copy the NVS tables to a new block to ensure alignment */
+ nvs_aligned = kmemdup(nvs_ptr, nvs_len, GFP_KERNEL);
+
+ /* And finally we upload the NVS tables */
+ /* FIXME: In wl1271, we upload everything at once.
+ No endianness handling needed here?! The ref driver doesn't do
+ anything about it at this point */
+ wl1271_spi_mem_write(wl, CMD_MBOX_ADDRESS, nvs_aligned, nvs_len);
+
+ kfree(nvs_aligned);
+ return 0;
+}
+
+static void wl1271_boot_enable_interrupts(struct wl1271 *wl)
+{
+ enable_irq(wl->irq);
+ wl1271_reg_write32(wl, ACX_REG_INTERRUPT_MASK,
+ WL1271_ACX_INTR_ALL & ~(WL1271_INTR_MASK));
+ wl1271_reg_write32(wl, HI_CFG, HI_CFG_DEF_VAL);
+}
+
+static int wl1271_boot_soft_reset(struct wl1271 *wl)
+{
+ unsigned long timeout;
+ u32 boot_data;
+
+ /* perform soft reset */
+ wl1271_reg_write32(wl, ACX_REG_SLV_SOFT_RESET, ACX_SLV_SOFT_RESET_BIT);
+
+ /* SOFT_RESET is self clearing */
+ timeout = jiffies + usecs_to_jiffies(SOFT_RESET_MAX_TIME);
+ while (1) {
+ boot_data = wl1271_reg_read32(wl, ACX_REG_SLV_SOFT_RESET);
+ wl1271_debug(DEBUG_BOOT, "soft reset bootdata 0x%x", boot_data);
+ if ((boot_data & ACX_SLV_SOFT_RESET_BIT) == 0)
+ break;
+
+ if (time_after(jiffies, timeout)) {
+ /* 1.2 check pWhalBus->uSelfClearTime if the
+ * timeout was reached */
+ wl1271_error("soft reset timeout");
+ return -1;
+ }
+
+ udelay(SOFT_RESET_STALL_TIME);
+ }
+
+ /* disable Rx/Tx */
+ wl1271_reg_write32(wl, ENABLE, 0x0);
+
+ /* disable auto calibration on start*/
+ wl1271_reg_write32(wl, SPARE_A2, 0xffff);
+
+ return 0;
+}
+
+static int wl1271_boot_run_firmware(struct wl1271 *wl)
+{
+ int loop, ret;
+ u32 chip_id, interrupt;
+
+ wl1271_boot_set_ecpu_ctrl(wl, ECPU_CONTROL_HALT);
+
+ chip_id = wl1271_reg_read32(wl, CHIP_ID_B);
+
+ wl1271_debug(DEBUG_BOOT, "chip id after firmware boot: 0x%x", chip_id);
+
+ if (chip_id != wl->chip.id) {
+ wl1271_error("chip id doesn't match after firmware boot");
+ return -EIO;
+ }
+
+ /* wait for init to complete */
+ loop = 0;
+ while (loop++ < INIT_LOOP) {
+ udelay(INIT_LOOP_DELAY);
+ interrupt = wl1271_reg_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR);
+
+ if (interrupt == 0xffffffff) {
+ wl1271_error("error reading hardware complete "
+ "init indication");
+ return -EIO;
+ }
+ /* check that ACX_INTR_INIT_COMPLETE is enabled */
+ else if (interrupt & WL1271_ACX_INTR_INIT_COMPLETE) {
+ wl1271_reg_write32(wl, ACX_REG_INTERRUPT_ACK,
+ WL1271_ACX_INTR_INIT_COMPLETE);
+ break;
+ }
+ }
+
+ if (loop >= INIT_LOOP) {
+ wl1271_error("timeout waiting for the hardware to "
+ "complete initialization");
+ return -EIO;
+ }
+
+ /* get hardware config command mail box */
+ wl->cmd_box_addr = wl1271_reg_read32(wl, REG_COMMAND_MAILBOX_PTR);
+
+ /* get hardware config event mail box */
+ wl->event_box_addr = wl1271_reg_read32(wl, REG_EVENT_MAILBOX_PTR);
+
+ /* set the working partition to its "running" mode offset */
+ wl1271_set_partition(wl,
+ part_table[PART_WORK].mem.start,
+ part_table[PART_WORK].mem.size,
+ part_table[PART_WORK].reg.start,
+ part_table[PART_WORK].reg.size);
+
+ wl1271_debug(DEBUG_MAILBOX, "cmd_box_addr 0x%x event_box_addr 0x%x",
+ wl->cmd_box_addr, wl->event_box_addr);
+
+ wl1271_boot_fw_version(wl);
+
+ /*
+ * in case of full asynchronous mode the firmware event must be
+ * ready to receive event from the command mailbox
+ */
+
+ /* enable gpio interrupts */
+ wl1271_boot_enable_interrupts(wl);
+
+ /* unmask all mbox events */
+ wl->event_mask = 0xffffffff;
+
+ ret = wl1271_event_unmask(wl);
+ if (ret < 0) {
+ wl1271_error("EVENT mask setting failed");
+ return ret;
+ }
+
+ wl1271_event_mbox_config(wl);
+
+ /* firmware startup completed */
+ return 0;
+}
+
+static int wl1271_boot_write_irq_polarity(struct wl1271 *wl)
+{
+ u32 polarity, status, i;
+
+ wl1271_reg_write32(wl, OCP_POR_CTR, OCP_REG_POLARITY);
+ wl1271_reg_write32(wl, OCP_CMD, OCP_CMD_READ);
+
+ /* Wait until the command is complete (ie. bit 18 is set) */
+ for (i = 0; i < OCP_CMD_LOOP; i++) {
+ polarity = wl1271_reg_read32(wl, OCP_DATA_READ);
+ if (polarity & OCP_READY_MASK)
+ break;
+ }
+ if (i == OCP_CMD_LOOP) {
+ wl1271_error("OCP command timeout!");
+ return -EIO;
+ }
+
+ status = polarity & OCP_STATUS_MASK;
+ if (status != OCP_STATUS_OK) {
+ wl1271_error("OCP command failed (%d)", status);
+ return -EIO;
+ }
+
+ /* We use HIGH polarity, so unset the LOW bit */
+ polarity &= ~POLARITY_LOW;
+
+ wl1271_reg_write32(wl, OCP_POR_CTR, OCP_REG_POLARITY);
+ wl1271_reg_write32(wl, OCP_DATA_WRITE, polarity);
+ wl1271_reg_write32(wl, OCP_CMD, OCP_CMD_WRITE);
+
+ return 0;
+}
+
+int wl1271_boot(struct wl1271 *wl)
+{
+ int ret = 0;
+ u32 tmp, clk, pause;
+
+ if (REF_CLOCK == 0 || REF_CLOCK == 2)
+ /* ref clk: 19.2/38.4 */
+ clk = 0x3;
+ else if (REF_CLOCK == 1 || REF_CLOCK == 3)
+ /* ref clk: 26/52 */
+ clk = 0x5;
+
+ wl1271_reg_write32(wl, PLL_PARAMETERS, clk);
+
+ pause = wl1271_reg_read32(wl, PLL_PARAMETERS);
+
+ wl1271_debug(DEBUG_BOOT, "pause1 0x%x", pause);
+
+ pause &= ~(WU_COUNTER_PAUSE_VAL); /* FIXME: This should probably be
+ * WU_COUNTER_PAUSE_VAL instead of
+ * 0x3ff (magic number ). How does
+ * this work?! */
+ pause |= WU_COUNTER_PAUSE_VAL;
+ wl1271_reg_write32(wl, WU_COUNTER_PAUSE, pause);
+
+ /* Continue the ELP wake up sequence */
+ wl1271_reg_write32(wl, WELP_ARM_COMMAND, WELP_ARM_COMMAND_VAL);
+ udelay(500);
+
+ wl1271_set_partition(wl,
+ part_table[PART_DRPW].mem.start,
+ part_table[PART_DRPW].mem.size,
+ part_table[PART_DRPW].reg.start,
+ part_table[PART_DRPW].reg.size);
+
+ /* Read-modify-write DRPW_SCRATCH_START register (see next state)
+ to be used by DRPw FW. The RTRIM value will be added by the FW
+ before taking DRPw out of reset */
+
+ wl1271_debug(DEBUG_BOOT, "DRPW_SCRATCH_START %08x", DRPW_SCRATCH_START);
+ clk = wl1271_reg_read32(wl, DRPW_SCRATCH_START);
+
+ wl1271_debug(DEBUG_BOOT, "clk2 0x%x", clk);
+
+ /* 2 */
+ clk |= (REF_CLOCK << 1) << 4;
+ wl1271_reg_write32(wl, DRPW_SCRATCH_START, clk);
+
+ wl1271_set_partition(wl,
+ part_table[PART_WORK].mem.start,
+ part_table[PART_WORK].mem.size,
+ part_table[PART_WORK].reg.start,
+ part_table[PART_WORK].reg.size);
+
+ /* Disable interrupts */
+ wl1271_reg_write32(wl, ACX_REG_INTERRUPT_MASK, WL1271_ACX_INTR_ALL);
+
+ ret = wl1271_boot_soft_reset(wl);
+ if (ret < 0)
+ goto out;
+
+ /* 2. start processing NVS file */
+ ret = wl1271_boot_upload_nvs(wl);
+ if (ret < 0)
+ goto out;
+
+ /* write firmware's last address (ie. it's length) to
+ * ACX_EEPROMLESS_IND_REG */
+ wl1271_debug(DEBUG_BOOT, "ACX_EEPROMLESS_IND_REG");
+
+ wl1271_reg_write32(wl, ACX_EEPROMLESS_IND_REG, ACX_EEPROMLESS_IND_REG);
+
+ tmp = wl1271_reg_read32(wl, CHIP_ID_B);
+
+ wl1271_debug(DEBUG_BOOT, "chip id 0x%x", tmp);
+
+ /* 6. read the EEPROM parameters */
+ tmp = wl1271_reg_read32(wl, SCR_PAD2);
+
+ ret = wl1271_boot_write_irq_polarity(wl);
+ if (ret < 0)
+ goto out;
+
+ /* FIXME: Need to check whether this is really what we want */
+ wl1271_reg_write32(wl, ACX_REG_INTERRUPT_MASK,
+ WL1271_ACX_ALL_EVENTS_VECTOR);
+
+ /* WL1271: The reference driver skips steps 7 to 10 (jumps directly
+ * to upload_fw) */
+
+ ret = wl1271_boot_upload_firmware(wl);
+ if (ret < 0)
+ goto out;
+
+ /* 10.5 start firmware */
+ ret = wl1271_boot_run_firmware(wl);
+ if (ret < 0)
+ goto out;
+
+ /* set the wl1271 default filters */
+ wl->rx_config = WL1271_DEFAULT_RX_CONFIG;
+ wl->rx_filter = WL1271_DEFAULT_RX_FILTER;
+
+ wl1271_event_mbox_config(wl);
+
+out:
+ return ret;
+}
diff --git a/drivers/net/wireless/wl12xx/wl1271_boot.h b/drivers/net/wireless/wl12xx/wl1271_boot.h
new file mode 100644
index 00000000000..b0d8fb46a43
--- /dev/null
+++ b/drivers/net/wireless/wl12xx/wl1271_boot.h
@@ -0,0 +1,72 @@
+/*
+ * This file is part of wl1271
+ *
+ * Copyright (C) 2008-2009 Nokia Corporation
+ *
+ * Contact: Luciano Coelho <luciano.coelho@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef __BOOT_H__
+#define __BOOT_H__
+
+#include "wl1271.h"
+
+int wl1271_boot(struct wl1271 *wl);
+
+#define WL1271_NO_SUBBANDS 8
+#define WL1271_NO_POWER_LEVELS 4
+#define WL1271_FW_VERSION_MAX_LEN 20
+
+struct wl1271_static_data {
+ u8 mac_address[ETH_ALEN];
+ u8 padding[2];
+ u8 fw_version[WL1271_FW_VERSION_MAX_LEN];
+ u32 hw_version;
+ u8 tx_power_table[WL1271_NO_SUBBANDS][WL1271_NO_POWER_LEVELS];
+};
+
+/* number of times we try to read the INIT interrupt */
+#define INIT_LOOP 20000
+
+/* delay between retries */
+#define INIT_LOOP_DELAY 50
+
+#define REF_CLOCK 2
+#define WU_COUNTER_PAUSE_VAL 0x3FF
+#define WELP_ARM_COMMAND_VAL 0x4
+
+#define OCP_CMD_LOOP 32
+
+#define OCP_CMD_WRITE 0x1
+#define OCP_CMD_READ 0x2
+
+#define OCP_READY_MASK BIT(18)
+#define OCP_STATUS_MASK (BIT(16) | BIT(17))
+
+#define OCP_STATUS_NO_RESP 0x00000
+#define OCP_STATUS_OK 0x10000
+#define OCP_STATUS_REQ_FAILED 0x20000
+#define OCP_STATUS_RESP_ERROR 0x30000
+
+#define OCP_REG_POLARITY 0x30032
+
+#define CMD_MBOX_ADDRESS 0x407B4
+
+#define POLARITY_LOW BIT(1)
+
+#endif
diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.c b/drivers/net/wireless/wl12xx/wl1271_cmd.c
new file mode 100644
index 00000000000..2a4351ff54d
--- /dev/null
+++ b/drivers/net/wireless/wl12xx/wl1271_cmd.c
@@ -0,0 +1,813 @@
+/*
+ * This file is part of wl1271
+ *
+ * Copyright (C) 2009 Nokia Corporation
+ *
+ * Contact: Luciano Coelho <luciano.coelho@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/crc7.h>
+#include <linux/spi/spi.h>
+#include <linux/etherdevice.h>
+
+#include "wl1271.h"
+#include "wl1271_reg.h"
+#include "wl1271_spi.h"
+#include "wl1271_acx.h"
+#include "wl12xx_80211.h"
+#include "wl1271_cmd.h"
+
+/*
+ * send command to firmware
+ *
+ * @wl: wl struct
+ * @id: command id
+ * @buf: buffer containing the command, must work with dma
+ * @len: length of the buffer
+ */
+int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len)
+{
+ struct wl1271_cmd_header *cmd;
+ unsigned long timeout;
+ u32 intr;
+ int ret = 0;
+
+ cmd = buf;
+ cmd->id = id;
+ cmd->status = 0;
+
+ WARN_ON(len % 4 != 0);
+
+ wl1271_spi_mem_write(wl, wl->cmd_box_addr, buf, len);
+
+ wl1271_reg_write32(wl, ACX_REG_INTERRUPT_TRIG, INTR_TRIG_CMD);
+
+ timeout = jiffies + msecs_to_jiffies(WL1271_COMMAND_TIMEOUT);
+
+ intr = wl1271_reg_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR);
+ while (!(intr & WL1271_ACX_INTR_CMD_COMPLETE)) {
+ if (time_after(jiffies, timeout)) {
+ wl1271_error("command complete timeout");
+ ret = -ETIMEDOUT;
+ goto out;
+ }
+
+ msleep(1);
+
+ intr = wl1271_reg_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR);
+ }
+
+ wl1271_reg_write32(wl, ACX_REG_INTERRUPT_ACK,
+ WL1271_ACX_INTR_CMD_COMPLETE);
+
+out:
+ return ret;
+}
+
+int wl1271_cmd_cal_channel_tune(struct wl1271 *wl)
+{
+ struct wl1271_cmd_cal_channel_tune *cmd;
+ int ret = 0;
+
+ cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+ if (!cmd)
+ return -ENOMEM;
+
+ cmd->test.id = TEST_CMD_CHANNEL_TUNE;
+
+ cmd->band = WL1271_CHANNEL_TUNE_BAND_2_4;
+ /* set up any channel, 7 is in the middle of the range */
+ cmd->channel = 7;
+
+ ret = wl1271_cmd_test(wl, cmd, sizeof(*cmd), 0);
+ if (ret < 0)
+ wl1271_warning("TEST_CMD_CHANNEL_TUNE failed");
+
+ kfree(cmd);
+ return ret;
+}
+
+int wl1271_cmd_cal_update_ref_point(struct wl1271 *wl)
+{
+ struct wl1271_cmd_cal_update_ref_point *cmd;
+ int ret = 0;
+
+ cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+ if (!cmd)
+ return -ENOMEM;
+
+ cmd->test.id = TEST_CMD_UPDATE_PD_REFERENCE_POINT;
+
+ /* FIXME: still waiting for the correct values */
+ cmd->ref_power = 0;
+ cmd->ref_detector = 0;
+
+ cmd->sub_band = WL1271_PD_REFERENCE_POINT_BAND_B_G;
+
+ ret = wl1271_cmd_test(wl, cmd, sizeof(*cmd), 0);
+ if (ret < 0)
+ wl1271_warning("TEST_CMD_UPDATE_PD_REFERENCE_POINT failed");
+
+ kfree(cmd);
+ return ret;
+}
+
+int wl1271_cmd_cal_p2g(struct wl1271 *wl)
+{
+ struct wl1271_cmd_cal_p2g *cmd;
+ int ret = 0;
+
+ cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+ if (!cmd)
+ return -ENOMEM;
+
+ cmd->test.id = TEST_CMD_P2G_CAL;
+
+ cmd->sub_band_mask = WL1271_CAL_P2G_BAND_B_G;
+
+ ret = wl1271_cmd_test(wl, cmd, sizeof(*cmd), 0);
+ if (ret < 0)
+ wl1271_warning("TEST_CMD_P2G_CAL failed");
+
+ kfree(cmd);
+ return ret;
+}
+
+int wl1271_cmd_cal(struct wl1271 *wl)
+{
+ /*
+ * FIXME: we must make sure that we're not sleeping when calibration
+ * is done
+ */
+ int ret;
+
+ wl1271_notice("performing tx calibration");
+
+ ret = wl1271_cmd_cal_channel_tune(wl);
+ if (ret < 0)
+ return ret;
+
+ ret = wl1271_cmd_cal_update_ref_point(wl);
+ if (ret < 0)
+ return ret;
+
+ ret = wl1271_cmd_cal_p2g(wl);
+ if (ret < 0)
+ return ret;
+
+ return ret;
+}
+
+int wl1271_cmd_join(struct wl1271 *wl, u8 bss_type, u8 dtim_interval,
+ u16 beacon_interval, u8 wait)
+{
+ static bool do_cal = true;
+ unsigned long timeout;
+ struct wl1271_cmd_join *join;
+ int ret, i;
+ u8 *bssid;
+
+ /* FIXME: remove when we get calibration from the factory */
+ if (do_cal) {
+ ret = wl1271_cmd_cal(wl);
+ if (ret < 0)
+ wl1271_warning("couldn't calibrate");
+ else
+ do_cal = false;
+ }
+
+
+ join = kzalloc(sizeof(*join), GFP_KERNEL);
+ if (!join) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ wl1271_debug(DEBUG_CMD, "cmd join");
+
+ /* Reverse order BSSID */
+ bssid = (u8 *) &join->bssid_lsb;
+ for (i = 0; i < ETH_ALEN; i++)
+ bssid[i] = wl->bssid[ETH_ALEN - i - 1];
+
+ join->rx_config_options = wl->rx_config;
+ join->rx_filter_options = wl->rx_filter;
+
+ join->basic_rate_set = RATE_MASK_1MBPS | RATE_MASK_2MBPS |
+ RATE_MASK_5_5MBPS | RATE_MASK_11MBPS;
+
+ join->beacon_interval = beacon_interval;
+ join->dtim_interval = dtim_interval;
+ join->bss_type = bss_type;
+ join->channel = wl->channel;
+ join->ssid_len = wl->ssid_len;
+ memcpy(join->ssid, wl->ssid, wl->ssid_len);
+ join->ctrl = WL1271_JOIN_CMD_CTRL_TX_FLUSH;
+
+ /* increment the session counter */
+ wl->session_counter++;
+ if (wl->session_counter >= SESSION_COUNTER_MAX)
+ wl->session_counter = 0;
+
+ join->ctrl |= wl->session_counter << WL1271_JOIN_CMD_TX_SESSION_OFFSET;
+
+
+ ret = wl1271_cmd_send(wl, CMD_START_JOIN, join, sizeof(*join));
+ if (ret < 0) {
+ wl1271_error("failed to initiate cmd join");
+ goto out_free;
+ }
+
+ timeout = msecs_to_jiffies(JOIN_TIMEOUT);
+
+ /*
+ * ugly hack: we should wait for JOIN_EVENT_COMPLETE_ID but to
+ * simplify locking we just sleep instead, for now
+ */
+ if (wait)
+ msleep(10);
+
+out_free:
+ kfree(join);
+
+out:
+ return ret;
+}
+
+/**
+ * send test command to firmware
+ *
+ * @wl: wl struct
+ * @buf: buffer containing the command, with all headers, must work with dma
+ * @len: length of the buffer
+ * @answer: is answer needed
+ */
+int wl1271_cmd_test(struct wl1271 *wl, void *buf, size_t buf_len, u8 answer)
+{
+ int ret;
+
+ wl1271_debug(DEBUG_CMD, "cmd test");
+
+ ret = wl1271_cmd_send(wl, CMD_TEST, buf, buf_len);
+
+ if (ret < 0) {
+ wl1271_warning("TEST command failed");
+ return ret;
+ }
+
+ if (answer) {
+ struct wl1271_command *cmd_answer;
+
+ /*
+ * The test command got in, we can read the answer.
+ * The answer would be a wl1271_command, where the
+ * parameter array contains the actual answer.
+ */
+ wl1271_spi_mem_read(wl, wl->cmd_box_addr, buf, buf_len);
+
+ cmd_answer = buf;
+
+ if (cmd_answer->header.status != CMD_STATUS_SUCCESS)
+ wl1271_error("TEST command answer error: %d",
+ cmd_answer->header.status);
+ }
+
+ return 0;
+}
+
+/**
+ * read acx from firmware
+ *
+ * @wl: wl struct
+ * @id: acx id
+ * @buf: buffer for the response, including all headers, must work with dma
+ * @len: lenght of buf
+ */
+int wl1271_cmd_interrogate(struct wl1271 *wl, u16 id, void *buf, size_t len)
+{
+ struct acx_header *acx = buf;
+ int ret;
+
+ wl1271_debug(DEBUG_CMD, "cmd interrogate");
+
+ acx->id = id;
+
+ /* payload length, does not include any headers */
+ acx->len = len - sizeof(*acx);
+
+ ret = wl1271_cmd_send(wl, CMD_INTERROGATE, acx, sizeof(*acx));
+ if (ret < 0) {
+ wl1271_error("INTERROGATE command failed");
+ goto out;
+ }
+
+ /* the interrogate command got in, we can read the answer */
+ wl1271_spi_mem_read(wl, wl->cmd_box_addr, buf, len);
+
+ acx = buf;
+ if (acx->cmd.status != CMD_STATUS_SUCCESS)
+ wl1271_error("INTERROGATE command error: %d",
+ acx->cmd.status);
+
+out:
+ return ret;
+}
+
+/**
+ * write acx value to firmware
+ *
+ * @wl: wl struct
+ * @id: acx id
+ * @buf: buffer containing acx, including all headers, must work with dma
+ * @len: length of buf
+ */
+int wl1271_cmd_configure(struct wl1271 *wl, u16 id, void *buf, size_t len)
+{
+ struct acx_header *acx = buf;
+ int ret;
+
+ wl1271_debug(DEBUG_CMD, "cmd configure");
+
+ acx->id = id;
+
+ /* payload length, does not include any headers */
+ acx->len = len - sizeof(*acx);
+
+ ret = wl1271_cmd_send(wl, CMD_CONFIGURE, acx, len);
+ if (ret < 0) {
+ wl1271_warning("CONFIGURE command NOK");
+ return ret;
+ }
+
+ return 0;
+}
+
+int wl1271_cmd_data_path(struct wl1271 *wl, u8 channel, bool enable)
+{
+ struct cmd_enabledisable_path *cmd;
+ int ret;
+ u16 cmd_rx, cmd_tx;
+
+ wl1271_debug(DEBUG_CMD, "cmd data path");
+
+ cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+ if (!cmd) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ cmd->channel = channel;
+
+ if (enable) {
+ cmd_rx = CMD_ENABLE_RX;
+ cmd_tx = CMD_ENABLE_TX;
+ } else {
+ cmd_rx = CMD_DISABLE_RX;
+ cmd_tx = CMD_DISABLE_TX;
+ }
+
+ ret = wl1271_cmd_send(wl, cmd_rx, cmd, sizeof(*cmd));
+ if (ret < 0) {
+ wl1271_error("rx %s cmd for channel %d failed",
+ enable ? "start" : "stop", channel);
+ goto out;
+ }
+
+ wl1271_debug(DEBUG_BOOT, "rx %s cmd channel %d",
+ enable ? "start" : "stop", channel);
+
+ ret = wl1271_cmd_send(wl, cmd_tx, cmd, sizeof(*cmd));
+ if (ret < 0) {
+ wl1271_error("tx %s cmd for channel %d failed",
+ enable ? "start" : "stop", channel);
+ return ret;
+ }
+
+ wl1271_debug(DEBUG_BOOT, "tx %s cmd channel %d",
+ enable ? "start" : "stop", channel);
+
+out:
+ kfree(cmd);
+ return ret;
+}
+
+int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode)
+{
+ struct wl1271_cmd_ps_params *ps_params = NULL;
+ int ret = 0;
+
+ /* FIXME: this should be in ps.c */
+ ret = wl1271_acx_wake_up_conditions(wl, WAKE_UP_EVENT_DTIM_BITMAP,
+ wl->listen_int);
+ if (ret < 0) {
+ wl1271_error("couldn't set wake up conditions");
+ goto out;
+ }
+
+ wl1271_debug(DEBUG_CMD, "cmd set ps mode");
+
+ ps_params = kzalloc(sizeof(*ps_params), GFP_KERNEL);
+ if (!ps_params) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ ps_params->ps_mode = ps_mode;
+ ps_params->send_null_data = 1;
+ ps_params->retries = 5;
+ ps_params->hang_over_period = 128;
+ ps_params->null_data_rate = 1; /* 1 Mbps */
+
+ ret = wl1271_cmd_send(wl, CMD_SET_PS_MODE, ps_params,
+ sizeof(*ps_params));
+ if (ret < 0) {
+ wl1271_error("cmd set_ps_mode failed");
+ goto out;
+ }
+
+out:
+ kfree(ps_params);
+ return ret;
+}
+
+int wl1271_cmd_read_memory(struct wl1271 *wl, u32 addr, void *answer,
+ size_t len)
+{
+ struct cmd_read_write_memory *cmd;
+ int ret = 0;
+
+ wl1271_debug(DEBUG_CMD, "cmd read memory");
+
+ cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+ if (!cmd) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ WARN_ON(len > MAX_READ_SIZE);
+ len = min_t(size_t, len, MAX_READ_SIZE);
+
+ cmd->addr = addr;
+ cmd->size = len;
+
+ ret = wl1271_cmd_send(wl, CMD_READ_MEMORY, cmd, sizeof(*cmd));
+ if (ret < 0) {
+ wl1271_error("read memory command failed: %d", ret);
+ goto out;
+ }
+
+ /* the read command got in, we can now read the answer */
+ wl1271_spi_mem_read(wl, wl->cmd_box_addr, cmd, sizeof(*cmd));
+
+ if (cmd->header.status != CMD_STATUS_SUCCESS)
+ wl1271_error("error in read command result: %d",
+ cmd->header.status);
+
+ memcpy(answer, cmd->value, len);
+
+out:
+ kfree(cmd);
+ return ret;
+}
+
+int wl1271_cmd_scan(struct wl1271 *wl, u8 *ssid, size_t len,
+ u8 active_scan, u8 high_prio, u8 num_channels,
+ u8 probe_requests)
+{
+
+ struct wl1271_cmd_trigger_scan_to *trigger = NULL;
+ struct wl1271_cmd_scan *params = NULL;
+ int i, ret;
+ u16 scan_options = 0;
+
+ if (wl->scanning)
+ return -EINVAL;
+
+ params = kzalloc(sizeof(*params), GFP_KERNEL);
+ if (!params)
+ return -ENOMEM;
+
+ params->params.rx_config_options = cpu_to_le32(CFG_RX_ALL_GOOD);
+ params->params.rx_filter_options =
+ cpu_to_le32(CFG_RX_PRSP_EN | CFG_RX_MGMT_EN | CFG_RX_BCN_EN);
+
+ if (!active_scan)
+ scan_options |= WL1271_SCAN_OPT_PASSIVE;
+ if (high_prio)
+ scan_options |= WL1271_SCAN_OPT_PRIORITY_HIGH;
+ params->params.scan_options = scan_options;
+
+ params->params.num_channels = num_channels;
+ params->params.num_probe_requests = probe_requests;
+ params->params.tx_rate = cpu_to_le32(RATE_MASK_2MBPS);
+ params->params.tid_trigger = 0;
+ params->params.scan_tag = WL1271_SCAN_DEFAULT_TAG;
+
+ for (i = 0; i < num_channels; i++) {
+ params->channels[i].min_duration =
+ cpu_to_le32(WL1271_SCAN_CHAN_MIN_DURATION);
+ params->channels[i].max_duration =
+ cpu_to_le32(WL1271_SCAN_CHAN_MAX_DURATION);
+ memset(&params->channels[i].bssid_lsb, 0xff, 4);
+ memset(&params->channels[i].bssid_msb, 0xff, 2);
+ params->channels[i].early_termination = 0;
+ params->channels[i].tx_power_att = WL1271_SCAN_CURRENT_TX_PWR;
+ params->channels[i].channel = i + 1;
+ }
+
+ if (len && ssid) {
+ params->params.ssid_len = len;
+ memcpy(params->params.ssid, ssid, len);
+ }
+
+ ret = wl1271_cmd_build_probe_req(wl, ssid, len);
+ if (ret < 0) {
+ wl1271_error("PROBE request template failed");
+ goto out;
+ }
+
+ trigger = kzalloc(sizeof(*trigger), GFP_KERNEL);
+ if (!trigger) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ /* disable the timeout */
+ trigger->timeout = 0;
+
+ ret = wl1271_cmd_send(wl, CMD_TRIGGER_SCAN_TO, trigger,
+ sizeof(*trigger));
+ if (ret < 0) {
+ wl1271_error("trigger scan to failed for hw scan");
+ goto out;
+ }
+
+ wl1271_dump(DEBUG_SCAN, "SCAN: ", params, sizeof(*params));
+
+ wl->scanning = true;
+
+ ret = wl1271_cmd_send(wl, CMD_SCAN, params, sizeof(*params));
+ if (ret < 0) {
+ wl1271_error("SCAN failed");
+ goto out;
+ }
+
+ wl1271_spi_mem_read(wl, wl->cmd_box_addr, params, sizeof(*params));
+
+ if (params->header.status != CMD_STATUS_SUCCESS) {
+ wl1271_error("Scan command error: %d",
+ params->header.status);
+ wl->scanning = false;
+ ret = -EIO;
+ goto out;
+ }
+
+out:
+ kfree(params);
+ return ret;
+}
+
+int wl1271_cmd_template_set(struct wl1271 *wl, u16 template_id,
+ void *buf, size_t buf_len)
+{
+ struct wl1271_cmd_template_set *cmd;
+ int ret = 0;
+
+ wl1271_debug(DEBUG_CMD, "cmd template_set %d", template_id);
+
+ WARN_ON(buf_len > WL1271_CMD_TEMPL_MAX_SIZE);
+ buf_len = min_t(size_t, buf_len, WL1271_CMD_TEMPL_MAX_SIZE);
+
+ cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+ if (!cmd) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ cmd->len = cpu_to_le16(buf_len);
+ cmd->template_type = template_id;
+ cmd->enabled_rates = ACX_RATE_MASK_UNSPECIFIED;
+ cmd->short_retry_limit = ACX_RATE_RETRY_LIMIT;
+ cmd->long_retry_limit = ACX_RATE_RETRY_LIMIT;
+
+ if (buf)
+ memcpy(cmd->template_data, buf, buf_len);
+
+ ret = wl1271_cmd_send(wl, CMD_SET_TEMPLATE, cmd, sizeof(*cmd));
+ if (ret < 0) {
+ wl1271_warning("cmd set_template failed: %d", ret);
+ goto out_free;
+ }
+
+out_free:
+ kfree(cmd);
+
+out:
+ return ret;
+}
+
+static int wl1271_build_basic_rates(char *rates)
+{
+ u8 index = 0;
+
+ rates[index++] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_1MB;
+ rates[index++] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_2MB;
+ rates[index++] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_5MB;
+ rates[index++] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_11MB;
+
+ return index;
+}
+
+static int wl1271_build_extended_rates(char *rates)
+{
+ u8 index = 0;
+
+ rates[index++] = IEEE80211_OFDM_RATE_6MB;
+ rates[index++] = IEEE80211_OFDM_RATE_9MB;
+ rates[index++] = IEEE80211_OFDM_RATE_12MB;
+ rates[index++] = IEEE80211_OFDM_RATE_18MB;
+ rates[index++] = IEEE80211_OFDM_RATE_24MB;
+ rates[index++] = IEEE80211_OFDM_RATE_36MB;
+ rates[index++] = IEEE80211_OFDM_RATE_48MB;
+ rates[index++] = IEEE80211_OFDM_RATE_54MB;
+
+ return index;
+}
+
+int wl1271_cmd_build_null_data(struct wl1271 *wl)
+{
+ struct wl12xx_null_data_template template;
+
+ if (!is_zero_ether_addr(wl->bssid)) {
+ memcpy(template.header.da, wl->bssid, ETH_ALEN);
+ memcpy(template.header.bssid, wl->bssid, ETH_ALEN);
+ } else {
+ memset(template.header.da, 0xff, ETH_ALEN);
+ memset(template.header.bssid, 0xff, ETH_ALEN);
+ }
+
+ memcpy(template.header.sa, wl->mac_addr, ETH_ALEN);
+ template.header.frame_ctl = cpu_to_le16(IEEE80211_FTYPE_DATA |
+ IEEE80211_STYPE_NULLFUNC);
+
+ return wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, &template,
+ sizeof(template));
+
+}
+
+int wl1271_cmd_build_ps_poll(struct wl1271 *wl, u16 aid)
+{
+ struct wl12xx_ps_poll_template template;
+
+ memcpy(template.bssid, wl->bssid, ETH_ALEN);
+ memcpy(template.ta, wl->mac_addr, ETH_ALEN);
+ template.aid = aid;
+ template.fc = cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_PSPOLL);
+
+ return wl1271_cmd_template_set(wl, CMD_TEMPL_PS_POLL, &template,
+ sizeof(template));
+
+}
+
+int wl1271_cmd_build_probe_req(struct wl1271 *wl, u8 *ssid, size_t ssid_len)
+{
+ struct wl12xx_probe_req_template template;
+ struct wl12xx_ie_rates *rates;
+ char *ptr;
+ u16 size;
+
+ ptr = (char *)&template;
+ size = sizeof(struct ieee80211_header);
+
+ memset(template.header.da, 0xff, ETH_ALEN);
+ memset(template.header.bssid, 0xff, ETH_ALEN);
+ memcpy(template.header.sa, wl->mac_addr, ETH_ALEN);
+ template.header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_PROBE_REQ);
+
+ /* IEs */
+ /* SSID */
+ template.ssid.header.id = WLAN_EID_SSID;
+ template.ssid.header.len = ssid_len;
+ if (ssid_len && ssid)
+ memcpy(template.ssid.ssid, ssid, ssid_len);
+ size += sizeof(struct wl12xx_ie_header) + ssid_len;
+ ptr += size;
+
+ /* Basic Rates */
+ rates = (struct wl12xx_ie_rates *)ptr;
+ rates->header.id = WLAN_EID_SUPP_RATES;
+ rates->header.len = wl1271_build_basic_rates(rates->rates);
+ size += sizeof(struct wl12xx_ie_header) + rates->header.len;
+ ptr += sizeof(struct wl12xx_ie_header) + rates->header.len;
+
+ /* Extended rates */
+ rates = (struct wl12xx_ie_rates *)ptr;
+ rates->header.id = WLAN_EID_EXT_SUPP_RATES;
+ rates->header.len = wl1271_build_extended_rates(rates->rates);
+ size += sizeof(struct wl12xx_ie_header) + rates->header.len;
+
+ wl1271_dump(DEBUG_SCAN, "PROBE REQ: ", &template, size);
+
+ return wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4,
+ &template, size);
+}
+
+int wl1271_cmd_set_default_wep_key(struct wl1271 *wl, u8 id)
+{
+ struct wl1271_cmd_set_keys *cmd;
+ int ret = 0;
+
+ wl1271_debug(DEBUG_CMD, "cmd set_default_wep_key %d", id);
+
+ cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+ if (!cmd) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ cmd->id = id;
+ cmd->key_action = KEY_SET_ID;
+ cmd->key_type = KEY_WEP;
+
+ ret = wl1271_cmd_send(wl, CMD_SET_KEYS, cmd, sizeof(*cmd));
+ if (ret < 0) {
+ wl1271_warning("cmd set_default_wep_key failed: %d", ret);
+ goto out;
+ }
+
+out:
+ kfree(cmd);
+
+ return ret;
+}
+
+int wl1271_cmd_set_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type,
+ u8 key_size, const u8 *key, const u8 *addr)
+{
+ struct wl1271_cmd_set_keys *cmd;
+ int ret = 0;
+
+ cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+ if (!cmd) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ if (key_type != KEY_WEP)
+ memcpy(cmd->addr, addr, ETH_ALEN);
+
+ cmd->key_action = action;
+ cmd->key_size = key_size;
+ cmd->key_type = key_type;
+
+ /* we have only one SSID profile */
+ cmd->ssid_profile = 0;
+
+ cmd->id = id;
+
+ /* FIXME: this is from wl1251, needs to be checked */
+ if (key_type == KEY_TKIP) {
+ /*
+ * We get the key in the following form:
+ * TKIP (16 bytes) - TX MIC (8 bytes) - RX MIC (8 bytes)
+ * but the target is expecting:
+ * TKIP - RX MIC - TX MIC
+ */
+ memcpy(cmd->key, key, 16);
+ memcpy(cmd->key + 16, key + 24, 8);
+ memcpy(cmd->key + 24, key + 16, 8);
+
+ } else {
+ memcpy(cmd->key, key, key_size);
+ }
+
+ wl1271_dump(DEBUG_CRYPT, "TARGET KEY: ", cmd, sizeof(*cmd));
+
+ ret = wl1271_cmd_send(wl, CMD_SET_KEYS, cmd, sizeof(*cmd));
+ if (ret < 0) {
+ wl1271_warning("could not set keys");
+ goto out;
+ }
+
+out:
+ kfree(cmd);
+
+ return ret;
+}
diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.h b/drivers/net/wireless/wl12xx/wl1271_cmd.h
new file mode 100644
index 00000000000..951a8447a51
--- /dev/null
+++ b/drivers/net/wireless/wl12xx/wl1271_cmd.h
@@ -0,0 +1,464 @@
+/*
+ * This file is part of wl1271
+ *
+ * Copyright (C) 1998-2009 Texas Instruments. All rights reserved.
+ * Copyright (C) 2009 Nokia Corporation
+ *
+ * Contact: Luciano Coelho <luciano.coelho@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef __WL1271_CMD_H__
+#define __WL1271_CMD_H__
+
+#include "wl1271.h"
+
+struct acx_header;
+
+int wl1271_cmd_send(struct wl1271 *wl, u16 type, void *buf, size_t buf_len);
+int wl1271_cmd_join(struct wl1271 *wl, u8 bss_type, u8 dtim_interval,
+ u16 beacon_interval, u8 wait);
+int wl1271_cmd_test(struct wl1271 *wl, void *buf, size_t buf_len, u8 answer);
+int wl1271_cmd_interrogate(struct wl1271 *wl, u16 id, void *buf, size_t len);
+int wl1271_cmd_configure(struct wl1271 *wl, u16 id, void *buf, size_t len);
+int wl1271_cmd_data_path(struct wl1271 *wl, u8 channel, bool enable);
+int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode);
+int wl1271_cmd_read_memory(struct wl1271 *wl, u32 addr, void *answer,
+ size_t len);
+int wl1271_cmd_scan(struct wl1271 *wl, u8 *ssid, size_t len,
+ u8 active_scan, u8 high_prio, u8 num_channels,
+ u8 probe_requests);
+int wl1271_cmd_template_set(struct wl1271 *wl, u16 template_id,
+ void *buf, size_t buf_len);
+int wl1271_cmd_build_null_data(struct wl1271 *wl);
+int wl1271_cmd_build_ps_poll(struct wl1271 *wl, u16 aid);
+int wl1271_cmd_build_probe_req(struct wl1271 *wl, u8 *ssid, size_t ssid_len);
+int wl1271_cmd_set_default_wep_key(struct wl1271 *wl, u8 id);
+int wl1271_cmd_set_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type,
+ u8 key_size, const u8 *key, const u8 *addr);
+
+enum wl1271_commands {
+ CMD_INTERROGATE = 1, /*use this to read information elements*/
+ CMD_CONFIGURE = 2, /*use this to write information elements*/
+ CMD_ENABLE_RX = 3,
+ CMD_ENABLE_TX = 4,
+ CMD_DISABLE_RX = 5,
+ CMD_DISABLE_TX = 6,
+ CMD_SCAN = 8,
+ CMD_STOP_SCAN = 9,
+ CMD_START_JOIN = 11,
+ CMD_SET_KEYS = 12,
+ CMD_READ_MEMORY = 13,
+ CMD_WRITE_MEMORY = 14,
+ CMD_SET_TEMPLATE = 19,
+ CMD_TEST = 23,
+ CMD_NOISE_HIST = 28,
+ CMD_LNA_CONTROL = 32,
+ CMD_SET_BCN_MODE = 33,
+ CMD_MEASUREMENT = 34,
+ CMD_STOP_MEASUREMENT = 35,
+ CMD_DISCONNECT = 36,
+ CMD_SET_PS_MODE = 37,
+ CMD_CHANNEL_SWITCH = 38,
+ CMD_STOP_CHANNEL_SWICTH = 39,
+ CMD_AP_DISCOVERY = 40,
+ CMD_STOP_AP_DISCOVERY = 41,
+ CMD_SPS_SCAN = 42,
+ CMD_STOP_SPS_SCAN = 43,
+ CMD_HEALTH_CHECK = 45,
+ CMD_DEBUG = 46,
+ CMD_TRIGGER_SCAN_TO = 47,
+ CMD_CONNECTION_SCAN_CFG = 48,
+ CMD_CONNECTION_SCAN_SSID_CFG = 49,
+ CMD_START_PERIODIC_SCAN = 50,
+ CMD_STOP_PERIODIC_SCAN = 51,
+ CMD_SET_STA_STATE = 52,
+
+ NUM_COMMANDS,
+ MAX_COMMAND_ID = 0xFFFF,
+};
+
+#define MAX_CMD_PARAMS 572
+
+enum cmd_templ {
+ CMD_TEMPL_NULL_DATA = 0,
+ CMD_TEMPL_BEACON,
+ CMD_TEMPL_CFG_PROBE_REQ_2_4,
+ CMD_TEMPL_CFG_PROBE_REQ_5,
+ CMD_TEMPL_PROBE_RESPONSE,
+ CMD_TEMPL_QOS_NULL_DATA,
+ CMD_TEMPL_PS_POLL,
+ CMD_TEMPL_KLV,
+ CMD_TEMPL_DISCONNECT,
+ CMD_TEMPL_PROBE_REQ_2_4, /* for firmware internal use only */
+ CMD_TEMPL_PROBE_REQ_5, /* for firmware internal use only */
+ CMD_TEMPL_BAR, /* for firmware internal use only */
+ CMD_TEMPL_CTS, /*
+ * For CTS-to-self (FastCTS) mechanism
+ * for BT/WLAN coexistence (SoftGemini). */
+ CMD_TEMPL_MAX = 0xff
+};
+
+/* unit ms */
+#define WL1271_COMMAND_TIMEOUT 2000
+#define WL1271_CMD_TEMPL_MAX_SIZE 252
+
+struct wl1271_cmd_header {
+ u16 id;
+ u16 status;
+ /* payload */
+ u8 data[0];
+} __attribute__ ((packed));
+
+#define WL1271_CMD_MAX_PARAMS 572
+
+struct wl1271_command {
+ struct wl1271_cmd_header header;
+ u8 parameters[WL1271_CMD_MAX_PARAMS];
+} __attribute__ ((packed));
+
+enum {
+ CMD_MAILBOX_IDLE = 0,
+ CMD_STATUS_SUCCESS = 1,
+ CMD_STATUS_UNKNOWN_CMD = 2,
+ CMD_STATUS_UNKNOWN_IE = 3,
+ CMD_STATUS_REJECT_MEAS_SG_ACTIVE = 11,
+ CMD_STATUS_RX_BUSY = 13,
+ CMD_STATUS_INVALID_PARAM = 14,
+ CMD_STATUS_TEMPLATE_TOO_LARGE = 15,
+ CMD_STATUS_OUT_OF_MEMORY = 16,
+ CMD_STATUS_STA_TABLE_FULL = 17,
+ CMD_STATUS_RADIO_ERROR = 18,
+ CMD_STATUS_WRONG_NESTING = 19,
+ CMD_STATUS_TIMEOUT = 21, /* Driver internal use.*/
+ CMD_STATUS_FW_RESET = 22, /* Driver internal use.*/
+ MAX_COMMAND_STATUS = 0xff
+};
+
+
+/*
+ * CMD_READ_MEMORY
+ *
+ * The host issues this command to read the WiLink device memory/registers.
+ *
+ * Note: The Base Band address has special handling (16 bits registers and
+ * addresses). For more information, see the hardware specification.
+ */
+/*
+ * CMD_WRITE_MEMORY
+ *
+ * The host issues this command to write the WiLink device memory/registers.
+ *
+ * The Base Band address has special handling (16 bits registers and
+ * addresses). For more information, see the hardware specification.
+ */
+#define MAX_READ_SIZE 256
+
+struct cmd_read_write_memory {
+ struct wl1271_cmd_header header;
+
+ /* The address of the memory to read from or write to.*/
+ u32 addr;
+
+ /* The amount of data in bytes to read from or write to the WiLink
+ * device.*/
+ u32 size;
+
+ /* The actual value read from or written to the Wilink. The source
+ of this field is the Host in WRITE command or the Wilink in READ
+ command. */
+ u8 value[MAX_READ_SIZE];
+};
+
+#define CMDMBOX_HEADER_LEN 4
+#define CMDMBOX_INFO_ELEM_HEADER_LEN 4
+
+enum {
+ BSS_TYPE_IBSS = 0,
+ BSS_TYPE_STA_BSS = 2,
+ BSS_TYPE_AP_BSS = 3,
+ MAX_BSS_TYPE = 0xFF
+};
+
+#define WL1271_JOIN_CMD_CTRL_TX_FLUSH 0x80 /* Firmware flushes all Tx */
+#define WL1271_JOIN_CMD_TX_SESSION_OFFSET 1
+
+struct wl1271_cmd_join {
+ struct wl1271_cmd_header header;
+
+ u32 bssid_lsb;
+ u16 bssid_msb;
+ u16 beacon_interval; /* in TBTTs */
+ u32 rx_config_options;
+ u32 rx_filter_options;
+
+ /*
+ * The target uses this field to determine the rate at
+ * which to transmit control frame responses (such as
+ * ACK or CTS frames).
+ */
+ u32 basic_rate_set;
+ u8 dtim_interval;
+ /*
+ * bits 0-2: This bitwise field specifies the type
+ * of BSS to start or join (BSS_TYPE_*).
+ * bit 4: Band - The radio band in which to join
+ * or start.
+ * 0 - 2.4GHz band
+ * 1 - 5GHz band
+ * bits 3, 5-7: Reserved
+ */
+ u8 bss_type;
+ u8 channel;
+ u8 ssid_len;
+ u8 ssid[IW_ESSID_MAX_SIZE];
+ u8 ctrl; /* JOIN_CMD_CTRL_* */
+ u8 reserved[3];
+} __attribute__ ((packed));
+
+struct cmd_enabledisable_path {
+ struct wl1271_cmd_header header;
+
+ u8 channel;
+ u8 padding[3];
+} __attribute__ ((packed));
+
+struct wl1271_cmd_template_set {
+ struct wl1271_cmd_header header;
+
+ u16 len;
+ u8 template_type;
+ u8 index; /* relevant only for KLV_TEMPLATE type */
+ u32 enabled_rates;
+ u8 short_retry_limit;
+ u8 long_retry_limit;
+ u8 aflags;
+ u8 reserved;
+ u8 template_data[WL1271_CMD_TEMPL_MAX_SIZE];
+} __attribute__ ((packed));
+
+#define TIM_ELE_ID 5
+#define PARTIAL_VBM_MAX 251
+
+struct wl1271_tim {
+ u8 identity;
+ u8 length;
+ u8 dtim_count;
+ u8 dtim_period;
+ u8 bitmap_ctrl;
+ u8 pvb_field[PARTIAL_VBM_MAX]; /* Partial Virtual Bitmap */
+} __attribute__ ((packed));
+
+enum wl1271_cmd_ps_mode {
+ STATION_ACTIVE_MODE,
+ STATION_POWER_SAVE_MODE
+};
+
+struct wl1271_cmd_ps_params {
+ struct wl1271_cmd_header header;
+
+ u8 ps_mode; /* STATION_* */
+ u8 send_null_data; /* Do we have to send NULL data packet ? */
+ u8 retries; /* Number of retires for the initial NULL data packet */
+
+ /*
+ * TUs during which the target stays awake after switching
+ * to power save mode.
+ */
+ u8 hang_over_period;
+ u32 null_data_rate;
+} __attribute__ ((packed));
+
+/* HW encryption keys */
+#define NUM_ACCESS_CATEGORIES_COPY 4
+#define MAX_KEY_SIZE 32
+
+/* When set, disable HW encryption */
+#define DF_ENCRYPTION_DISABLE 0x01
+/* When set, disable HW decryption */
+#define DF_SNIFF_MODE_ENABLE 0x80
+
+enum wl1271_cmd_key_action {
+ KEY_ADD_OR_REPLACE = 1,
+ KEY_REMOVE = 2,
+ KEY_SET_ID = 3,
+ MAX_KEY_ACTION = 0xffff,
+};
+
+enum wl1271_cmd_key_type {
+ KEY_NONE = 0,
+ KEY_WEP = 1,
+ KEY_TKIP = 2,
+ KEY_AES = 3,
+ KEY_GEM = 4
+};
+
+/* FIXME: Add description for key-types */
+
+struct wl1271_cmd_set_keys {
+ struct wl1271_cmd_header header;
+
+ /* Ignored for default WEP key */
+ u8 addr[ETH_ALEN];
+
+ /* key_action_e */
+ u16 key_action;
+
+ u16 reserved_1;
+
+ /* key size in bytes */
+ u8 key_size;
+
+ /* key_type_e */
+ u8 key_type;
+ u8 ssid_profile;
+
+ /*
+ * TKIP, AES: frame's key id field.
+ * For WEP default key: key id;
+ */
+ u8 id;
+ u8 reserved_2[6];
+ u8 key[MAX_KEY_SIZE];
+ u16 ac_seq_num16[NUM_ACCESS_CATEGORIES_COPY];
+ u32 ac_seq_num32[NUM_ACCESS_CATEGORIES_COPY];
+} __attribute__ ((packed));
+
+
+#define WL1271_SCAN_MAX_CHANNELS 24
+#define WL1271_SCAN_DEFAULT_TAG 1
+#define WL1271_SCAN_CURRENT_TX_PWR 0
+#define WL1271_SCAN_OPT_ACTIVE 0
+#define WL1271_SCAN_OPT_PASSIVE 1
+#define WL1271_SCAN_OPT_PRIORITY_HIGH 4
+#define WL1271_SCAN_CHAN_MIN_DURATION 30000 /* TU */
+#define WL1271_SCAN_CHAN_MAX_DURATION 60000 /* TU */
+
+struct basic_scan_params {
+ u32 rx_config_options;
+ u32 rx_filter_options;
+ /* Scan option flags (WL1271_SCAN_OPT_*) */
+ u16 scan_options;
+ /* Number of scan channels in the list (maximum 30) */
+ u8 num_channels;
+ /* This field indicates the number of probe requests to send
+ per channel for an active scan */
+ u8 num_probe_requests;
+ /* Rate bit field for sending the probes */
+ u32 tx_rate;
+ u8 tid_trigger;
+ u8 ssid_len;
+ /* in order to align */
+ u8 padding1[2];
+ u8 ssid[IW_ESSID_MAX_SIZE];
+ /* Band to scan */
+ u8 band;
+ u8 use_ssid_list;
+ u8 scan_tag;
+ u8 padding2;
+} __attribute__ ((packed));
+
+struct basic_scan_channel_params {
+ /* Duration in TU to wait for frames on a channel for active scan */
+ u32 min_duration;
+ u32 max_duration;
+ u32 bssid_lsb;
+ u16 bssid_msb;
+ u8 early_termination;
+ u8 tx_power_att;
+ u8 channel;
+ /* FW internal use only! */
+ u8 dfs_candidate;
+ u8 activity_detected;
+ u8 pad;
+} __attribute__ ((packed));
+
+struct wl1271_cmd_scan {
+ struct wl1271_cmd_header header;
+
+ struct basic_scan_params params;
+ struct basic_scan_channel_params channels[WL1271_SCAN_MAX_CHANNELS];
+} __attribute__ ((packed));
+
+struct wl1271_cmd_trigger_scan_to {
+ struct wl1271_cmd_header header;
+
+ u32 timeout;
+};
+
+struct wl1271_cmd_test_header {
+ u8 id;
+ u8 padding[3];
+};
+
+enum wl1271_channel_tune_bands {
+ WL1271_CHANNEL_TUNE_BAND_2_4,
+ WL1271_CHANNEL_TUNE_BAND_5,
+ WL1271_CHANNEL_TUNE_BAND_4_9
+};
+
+#define WL1271_PD_REFERENCE_POINT_BAND_B_G 0
+
+#define TEST_CMD_P2G_CAL 0x02
+#define TEST_CMD_CHANNEL_TUNE 0x0d
+#define TEST_CMD_UPDATE_PD_REFERENCE_POINT 0x1d
+
+struct wl1271_cmd_cal_channel_tune {
+ struct wl1271_cmd_header header;
+
+ struct wl1271_cmd_test_header test;
+
+ u8 band;
+ u8 channel;
+
+ u16 radio_status;
+} __attribute__ ((packed));
+
+struct wl1271_cmd_cal_update_ref_point {
+ struct wl1271_cmd_header header;
+
+ struct wl1271_cmd_test_header test;
+
+ s32 ref_power;
+ s32 ref_detector;
+ u8 sub_band;
+ u8 padding[3];
+} __attribute__ ((packed));
+
+#define MAX_TLV_LENGTH 400
+#define MAX_NVS_VERSION_LENGTH 12
+
+#define WL1271_CAL_P2G_BAND_B_G BIT(0)
+
+struct wl1271_cmd_cal_p2g {
+ struct wl1271_cmd_header header;
+
+ struct wl1271_cmd_test_header test;
+
+ u16 len;
+ u8 buf[MAX_TLV_LENGTH];
+ u8 type;
+ u8 padding;
+
+ s16 radio_status;
+ u8 nvs_version[MAX_NVS_VERSION_LENGTH];
+
+ u8 sub_band_mask;
+ u8 padding2;
+} __attribute__ ((packed));
+
+#endif /* __WL1271_CMD_H__ */
diff --git a/drivers/net/wireless/wl12xx/wl1271_debugfs.c b/drivers/net/wireless/wl12xx/wl1271_debugfs.c
new file mode 100644
index 00000000000..c1805e5f896
--- /dev/null
+++ b/drivers/net/wireless/wl12xx/wl1271_debugfs.c
@@ -0,0 +1,518 @@
+/*
+ * This file is part of wl1271
+ *
+ * Copyright (C) 2009 Nokia Corporation
+ *
+ * Contact: Luciano Coelho <luciano.coelho@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include "wl1271_debugfs.h"
+
+#include <linux/skbuff.h>
+
+#include "wl1271.h"
+#include "wl1271_acx.h"
+#include "wl1271_ps.h"
+
+/* ms */
+#define WL1271_DEBUGFS_STATS_LIFETIME 1000
+
+/* debugfs macros idea from mac80211 */
+
+#define DEBUGFS_READONLY_FILE(name, buflen, fmt, value...) \
+static ssize_t name## _read(struct file *file, char __user *userbuf, \
+ size_t count, loff_t *ppos) \
+{ \
+ struct wl1271 *wl = file->private_data; \
+ char buf[buflen]; \
+ int res; \
+ \
+ res = scnprintf(buf, buflen, fmt "\n", ##value); \
+ return simple_read_from_buffer(userbuf, count, ppos, buf, res); \
+} \
+ \
+static const struct file_operations name## _ops = { \
+ .read = name## _read, \
+ .open = wl1271_open_file_generic, \
+};
+
+#define DEBUGFS_ADD(name, parent) \
+ wl->debugfs.name = debugfs_create_file(#name, 0400, parent, \
+ wl, &name## _ops); \
+ if (IS_ERR(wl->debugfs.name)) { \
+ ret = PTR_ERR(wl->debugfs.name); \
+ wl->debugfs.name = NULL; \
+ goto out; \
+ }
+
+#define DEBUGFS_DEL(name) \
+ do { \
+ debugfs_remove(wl->debugfs.name); \
+ wl->debugfs.name = NULL; \
+ } while (0)
+
+#define DEBUGFS_FWSTATS_FILE(sub, name, buflen, fmt) \
+static ssize_t sub## _ ##name## _read(struct file *file, \
+ char __user *userbuf, \
+ size_t count, loff_t *ppos) \
+{ \
+ struct wl1271 *wl = file->private_data; \
+ char buf[buflen]; \
+ int res; \
+ \
+ wl1271_debugfs_update_stats(wl); \
+ \
+ res = scnprintf(buf, buflen, fmt "\n", \
+ wl->stats.fw_stats->sub.name); \
+ return simple_read_from_buffer(userbuf, count, ppos, buf, res); \
+} \
+ \
+static const struct file_operations sub## _ ##name## _ops = { \
+ .read = sub## _ ##name## _read, \
+ .open = wl1271_open_file_generic, \
+};
+
+#define DEBUGFS_FWSTATS_ADD(sub, name) \
+ DEBUGFS_ADD(sub## _ ##name, wl->debugfs.fw_statistics)
+
+#define DEBUGFS_FWSTATS_DEL(sub, name) \
+ DEBUGFS_DEL(sub## _ ##name)
+
+static void wl1271_debugfs_update_stats(struct wl1271 *wl)
+{
+ int ret;
+
+ mutex_lock(&wl->mutex);
+
+ ret = wl1271_ps_elp_wakeup(wl, false);
+ if (ret < 0)
+ goto out;
+
+ if (wl->state == WL1271_STATE_ON &&
+ time_after(jiffies, wl->stats.fw_stats_update +
+ msecs_to_jiffies(WL1271_DEBUGFS_STATS_LIFETIME))) {
+ wl1271_acx_statistics(wl, wl->stats.fw_stats);
+ wl->stats.fw_stats_update = jiffies;
+ }
+
+ wl1271_ps_elp_sleep(wl);
+
+out:
+ mutex_unlock(&wl->mutex);
+}
+
+static int wl1271_open_file_generic(struct inode *inode, struct file *file)
+{
+ file->private_data = inode->i_private;
+ return 0;
+}
+
+DEBUGFS_FWSTATS_FILE(tx, internal_desc_overflow, 20, "%u");
+
+DEBUGFS_FWSTATS_FILE(rx, out_of_mem, 20, "%u");
+DEBUGFS_FWSTATS_FILE(rx, hdr_overflow, 20, "%u");
+DEBUGFS_FWSTATS_FILE(rx, hw_stuck, 20, "%u");
+DEBUGFS_FWSTATS_FILE(rx, dropped, 20, "%u");
+DEBUGFS_FWSTATS_FILE(rx, fcs_err, 20, "%u");
+DEBUGFS_FWSTATS_FILE(rx, xfr_hint_trig, 20, "%u");
+DEBUGFS_FWSTATS_FILE(rx, path_reset, 20, "%u");
+DEBUGFS_FWSTATS_FILE(rx, reset_counter, 20, "%u");
+
+DEBUGFS_FWSTATS_FILE(dma, rx_requested, 20, "%u");
+DEBUGFS_FWSTATS_FILE(dma, rx_errors, 20, "%u");
+DEBUGFS_FWSTATS_FILE(dma, tx_requested, 20, "%u");
+DEBUGFS_FWSTATS_FILE(dma, tx_errors, 20, "%u");
+
+DEBUGFS_FWSTATS_FILE(isr, cmd_cmplt, 20, "%u");
+DEBUGFS_FWSTATS_FILE(isr, fiqs, 20, "%u");
+DEBUGFS_FWSTATS_FILE(isr, rx_headers, 20, "%u");
+DEBUGFS_FWSTATS_FILE(isr, rx_mem_overflow, 20, "%u");
+DEBUGFS_FWSTATS_FILE(isr, rx_rdys, 20, "%u");
+DEBUGFS_FWSTATS_FILE(isr, irqs, 20, "%u");
+DEBUGFS_FWSTATS_FILE(isr, tx_procs, 20, "%u");
+DEBUGFS_FWSTATS_FILE(isr, decrypt_done, 20, "%u");
+DEBUGFS_FWSTATS_FILE(isr, dma0_done, 20, "%u");
+DEBUGFS_FWSTATS_FILE(isr, dma1_done, 20, "%u");
+DEBUGFS_FWSTATS_FILE(isr, tx_exch_complete, 20, "%u");
+DEBUGFS_FWSTATS_FILE(isr, commands, 20, "%u");
+DEBUGFS_FWSTATS_FILE(isr, rx_procs, 20, "%u");
+DEBUGFS_FWSTATS_FILE(isr, hw_pm_mode_changes, 20, "%u");
+DEBUGFS_FWSTATS_FILE(isr, host_acknowledges, 20, "%u");
+DEBUGFS_FWSTATS_FILE(isr, pci_pm, 20, "%u");
+DEBUGFS_FWSTATS_FILE(isr, wakeups, 20, "%u");
+DEBUGFS_FWSTATS_FILE(isr, low_rssi, 20, "%u");
+
+DEBUGFS_FWSTATS_FILE(wep, addr_key_count, 20, "%u");
+DEBUGFS_FWSTATS_FILE(wep, default_key_count, 20, "%u");
+/* skipping wep.reserved */
+DEBUGFS_FWSTATS_FILE(wep, key_not_found, 20, "%u");
+DEBUGFS_FWSTATS_FILE(wep, decrypt_fail, 20, "%u");
+DEBUGFS_FWSTATS_FILE(wep, packets, 20, "%u");
+DEBUGFS_FWSTATS_FILE(wep, interrupt, 20, "%u");
+
+DEBUGFS_FWSTATS_FILE(pwr, ps_enter, 20, "%u");
+DEBUGFS_FWSTATS_FILE(pwr, elp_enter, 20, "%u");
+DEBUGFS_FWSTATS_FILE(pwr, missing_bcns, 20, "%u");
+DEBUGFS_FWSTATS_FILE(pwr, wake_on_host, 20, "%u");
+DEBUGFS_FWSTATS_FILE(pwr, wake_on_timer_exp, 20, "%u");
+DEBUGFS_FWSTATS_FILE(pwr, tx_with_ps, 20, "%u");
+DEBUGFS_FWSTATS_FILE(pwr, tx_without_ps, 20, "%u");
+DEBUGFS_FWSTATS_FILE(pwr, rcvd_beacons, 20, "%u");
+DEBUGFS_FWSTATS_FILE(pwr, power_save_off, 20, "%u");
+DEBUGFS_FWSTATS_FILE(pwr, enable_ps, 20, "%u");
+DEBUGFS_FWSTATS_FILE(pwr, disable_ps, 20, "%u");
+DEBUGFS_FWSTATS_FILE(pwr, fix_tsf_ps, 20, "%u");
+/* skipping cont_miss_bcns_spread for now */
+DEBUGFS_FWSTATS_FILE(pwr, rcvd_awake_beacons, 20, "%u");
+
+DEBUGFS_FWSTATS_FILE(mic, rx_pkts, 20, "%u");
+DEBUGFS_FWSTATS_FILE(mic, calc_failure, 20, "%u");
+
+DEBUGFS_FWSTATS_FILE(aes, encrypt_fail, 20, "%u");
+DEBUGFS_FWSTATS_FILE(aes, decrypt_fail, 20, "%u");
+DEBUGFS_FWSTATS_FILE(aes, encrypt_packets, 20, "%u");
+DEBUGFS_FWSTATS_FILE(aes, decrypt_packets, 20, "%u");
+DEBUGFS_FWSTATS_FILE(aes, encrypt_interrupt, 20, "%u");
+DEBUGFS_FWSTATS_FILE(aes, decrypt_interrupt, 20, "%u");
+
+DEBUGFS_FWSTATS_FILE(event, heart_beat, 20, "%u");
+DEBUGFS_FWSTATS_FILE(event, calibration, 20, "%u");
+DEBUGFS_FWSTATS_FILE(event, rx_mismatch, 20, "%u");
+DEBUGFS_FWSTATS_FILE(event, rx_mem_empty, 20, "%u");
+DEBUGFS_FWSTATS_FILE(event, rx_pool, 20, "%u");
+DEBUGFS_FWSTATS_FILE(event, oom_late, 20, "%u");
+DEBUGFS_FWSTATS_FILE(event, phy_transmit_error, 20, "%u");
+DEBUGFS_FWSTATS_FILE(event, tx_stuck, 20, "%u");
+
+DEBUGFS_FWSTATS_FILE(ps, pspoll_timeouts, 20, "%u");
+DEBUGFS_FWSTATS_FILE(ps, upsd_timeouts, 20, "%u");
+DEBUGFS_FWSTATS_FILE(ps, upsd_max_sptime, 20, "%u");
+DEBUGFS_FWSTATS_FILE(ps, upsd_max_apturn, 20, "%u");
+DEBUGFS_FWSTATS_FILE(ps, pspoll_max_apturn, 20, "%u");
+DEBUGFS_FWSTATS_FILE(ps, pspoll_utilization, 20, "%u");
+DEBUGFS_FWSTATS_FILE(ps, upsd_utilization, 20, "%u");
+
+DEBUGFS_FWSTATS_FILE(rxpipe, rx_prep_beacon_drop, 20, "%u");
+DEBUGFS_FWSTATS_FILE(rxpipe, descr_host_int_trig_rx_data, 20, "%u");
+DEBUGFS_FWSTATS_FILE(rxpipe, beacon_buffer_thres_host_int_trig_rx_data,
+ 20, "%u");
+DEBUGFS_FWSTATS_FILE(rxpipe, missed_beacon_host_int_trig_rx_data, 20, "%u");
+DEBUGFS_FWSTATS_FILE(rxpipe, tx_xfr_host_int_trig_rx_data, 20, "%u");
+
+DEBUGFS_READONLY_FILE(retry_count, 20, "%u", wl->stats.retry_count);
+DEBUGFS_READONLY_FILE(excessive_retries, 20, "%u",
+ wl->stats.excessive_retries);
+
+static ssize_t tx_queue_len_read(struct file *file, char __user *userbuf,
+ size_t count, loff_t *ppos)
+{
+ struct wl1271 *wl = file->private_data;
+ u32 queue_len;
+ char buf[20];
+ int res;
+
+ queue_len = skb_queue_len(&wl->tx_queue);
+
+ res = scnprintf(buf, sizeof(buf), "%u\n", queue_len);
+ return simple_read_from_buffer(userbuf, count, ppos, buf, res);
+}
+
+static const struct file_operations tx_queue_len_ops = {
+ .read = tx_queue_len_read,
+ .open = wl1271_open_file_generic,
+};
+
+static void wl1271_debugfs_delete_files(struct wl1271 *wl)
+{
+ DEBUGFS_FWSTATS_DEL(tx, internal_desc_overflow);
+
+ DEBUGFS_FWSTATS_DEL(rx, out_of_mem);
+ DEBUGFS_FWSTATS_DEL(rx, hdr_overflow);
+ DEBUGFS_FWSTATS_DEL(rx, hw_stuck);
+ DEBUGFS_FWSTATS_DEL(rx, dropped);
+ DEBUGFS_FWSTATS_DEL(rx, fcs_err);
+ DEBUGFS_FWSTATS_DEL(rx, xfr_hint_trig);
+ DEBUGFS_FWSTATS_DEL(rx, path_reset);
+ DEBUGFS_FWSTATS_DEL(rx, reset_counter);
+
+ DEBUGFS_FWSTATS_DEL(dma, rx_requested);
+ DEBUGFS_FWSTATS_DEL(dma, rx_errors);
+ DEBUGFS_FWSTATS_DEL(dma, tx_requested);
+ DEBUGFS_FWSTATS_DEL(dma, tx_errors);
+
+ DEBUGFS_FWSTATS_DEL(isr, cmd_cmplt);
+ DEBUGFS_FWSTATS_DEL(isr, fiqs);
+ DEBUGFS_FWSTATS_DEL(isr, rx_headers);
+ DEBUGFS_FWSTATS_DEL(isr, rx_mem_overflow);
+ DEBUGFS_FWSTATS_DEL(isr, rx_rdys);
+ DEBUGFS_FWSTATS_DEL(isr, irqs);
+ DEBUGFS_FWSTATS_DEL(isr, tx_procs);
+ DEBUGFS_FWSTATS_DEL(isr, decrypt_done);
+ DEBUGFS_FWSTATS_DEL(isr, dma0_done);
+ DEBUGFS_FWSTATS_DEL(isr, dma1_done);
+ DEBUGFS_FWSTATS_DEL(isr, tx_exch_complete);
+ DEBUGFS_FWSTATS_DEL(isr, commands);
+ DEBUGFS_FWSTATS_DEL(isr, rx_procs);
+ DEBUGFS_FWSTATS_DEL(isr, hw_pm_mode_changes);
+ DEBUGFS_FWSTATS_DEL(isr, host_acknowledges);
+ DEBUGFS_FWSTATS_DEL(isr, pci_pm);
+ DEBUGFS_FWSTATS_DEL(isr, wakeups);
+ DEBUGFS_FWSTATS_DEL(isr, low_rssi);
+
+ DEBUGFS_FWSTATS_DEL(wep, addr_key_count);
+ DEBUGFS_FWSTATS_DEL(wep, default_key_count);
+ /* skipping wep.reserved */
+ DEBUGFS_FWSTATS_DEL(wep, key_not_found);
+ DEBUGFS_FWSTATS_DEL(wep, decrypt_fail);
+ DEBUGFS_FWSTATS_DEL(wep, packets);
+ DEBUGFS_FWSTATS_DEL(wep, interrupt);
+
+ DEBUGFS_FWSTATS_DEL(pwr, ps_enter);
+ DEBUGFS_FWSTATS_DEL(pwr, elp_enter);
+ DEBUGFS_FWSTATS_DEL(pwr, missing_bcns);
+ DEBUGFS_FWSTATS_DEL(pwr, wake_on_host);
+ DEBUGFS_FWSTATS_DEL(pwr, wake_on_timer_exp);
+ DEBUGFS_FWSTATS_DEL(pwr, tx_with_ps);
+ DEBUGFS_FWSTATS_DEL(pwr, tx_without_ps);
+ DEBUGFS_FWSTATS_DEL(pwr, rcvd_beacons);
+ DEBUGFS_FWSTATS_DEL(pwr, power_save_off);
+ DEBUGFS_FWSTATS_DEL(pwr, enable_ps);
+ DEBUGFS_FWSTATS_DEL(pwr, disable_ps);
+ DEBUGFS_FWSTATS_DEL(pwr, fix_tsf_ps);
+ /* skipping cont_miss_bcns_spread for now */
+ DEBUGFS_FWSTATS_DEL(pwr, rcvd_awake_beacons);
+
+ DEBUGFS_FWSTATS_DEL(mic, rx_pkts);
+ DEBUGFS_FWSTATS_DEL(mic, calc_failure);
+
+ DEBUGFS_FWSTATS_DEL(aes, encrypt_fail);
+ DEBUGFS_FWSTATS_DEL(aes, decrypt_fail);
+ DEBUGFS_FWSTATS_DEL(aes, encrypt_packets);
+ DEBUGFS_FWSTATS_DEL(aes, decrypt_packets);
+ DEBUGFS_FWSTATS_DEL(aes, encrypt_interrupt);
+ DEBUGFS_FWSTATS_DEL(aes, decrypt_interrupt);
+
+ DEBUGFS_FWSTATS_DEL(event, heart_beat);
+ DEBUGFS_FWSTATS_DEL(event, calibration);
+ DEBUGFS_FWSTATS_DEL(event, rx_mismatch);
+ DEBUGFS_FWSTATS_DEL(event, rx_mem_empty);
+ DEBUGFS_FWSTATS_DEL(event, rx_pool);
+ DEBUGFS_FWSTATS_DEL(event, oom_late);
+ DEBUGFS_FWSTATS_DEL(event, phy_transmit_error);
+ DEBUGFS_FWSTATS_DEL(event, tx_stuck);
+
+ DEBUGFS_FWSTATS_DEL(ps, pspoll_timeouts);
+ DEBUGFS_FWSTATS_DEL(ps, upsd_timeouts);
+ DEBUGFS_FWSTATS_DEL(ps, upsd_max_sptime);
+ DEBUGFS_FWSTATS_DEL(ps, upsd_max_apturn);
+ DEBUGFS_FWSTATS_DEL(ps, pspoll_max_apturn);
+ DEBUGFS_FWSTATS_DEL(ps, pspoll_utilization);
+ DEBUGFS_FWSTATS_DEL(ps, upsd_utilization);
+
+ DEBUGFS_FWSTATS_DEL(rxpipe, rx_prep_beacon_drop);
+ DEBUGFS_FWSTATS_DEL(rxpipe, descr_host_int_trig_rx_data);
+ DEBUGFS_FWSTATS_DEL(rxpipe, beacon_buffer_thres_host_int_trig_rx_data);
+ DEBUGFS_FWSTATS_DEL(rxpipe, missed_beacon_host_int_trig_rx_data);
+ DEBUGFS_FWSTATS_DEL(rxpipe, tx_xfr_host_int_trig_rx_data);
+
+ DEBUGFS_DEL(tx_queue_len);
+ DEBUGFS_DEL(retry_count);
+ DEBUGFS_DEL(excessive_retries);
+}
+
+static int wl1271_debugfs_add_files(struct wl1271 *wl)
+{
+ int ret = 0;
+
+ DEBUGFS_FWSTATS_ADD(tx, internal_desc_overflow);
+
+ DEBUGFS_FWSTATS_ADD(rx, out_of_mem);
+ DEBUGFS_FWSTATS_ADD(rx, hdr_overflow);
+ DEBUGFS_FWSTATS_ADD(rx, hw_stuck);
+ DEBUGFS_FWSTATS_ADD(rx, dropped);
+ DEBUGFS_FWSTATS_ADD(rx, fcs_err);
+ DEBUGFS_FWSTATS_ADD(rx, xfr_hint_trig);
+ DEBUGFS_FWSTATS_ADD(rx, path_reset);
+ DEBUGFS_FWSTATS_ADD(rx, reset_counter);
+
+ DEBUGFS_FWSTATS_ADD(dma, rx_requested);
+ DEBUGFS_FWSTATS_ADD(dma, rx_errors);
+ DEBUGFS_FWSTATS_ADD(dma, tx_requested);
+ DEBUGFS_FWSTATS_ADD(dma, tx_errors);
+
+ DEBUGFS_FWSTATS_ADD(isr, cmd_cmplt);
+ DEBUGFS_FWSTATS_ADD(isr, fiqs);
+ DEBUGFS_FWSTATS_ADD(isr, rx_headers);
+ DEBUGFS_FWSTATS_ADD(isr, rx_mem_overflow);
+ DEBUGFS_FWSTATS_ADD(isr, rx_rdys);
+ DEBUGFS_FWSTATS_ADD(isr, irqs);
+ DEBUGFS_FWSTATS_ADD(isr, tx_procs);
+ DEBUGFS_FWSTATS_ADD(isr, decrypt_done);
+ DEBUGFS_FWSTATS_ADD(isr, dma0_done);
+ DEBUGFS_FWSTATS_ADD(isr, dma1_done);
+ DEBUGFS_FWSTATS_ADD(isr, tx_exch_complete);
+ DEBUGFS_FWSTATS_ADD(isr, commands);
+ DEBUGFS_FWSTATS_ADD(isr, rx_procs);
+ DEBUGFS_FWSTATS_ADD(isr, hw_pm_mode_changes);
+ DEBUGFS_FWSTATS_ADD(isr, host_acknowledges);
+ DEBUGFS_FWSTATS_ADD(isr, pci_pm);
+ DEBUGFS_FWSTATS_ADD(isr, wakeups);
+ DEBUGFS_FWSTATS_ADD(isr, low_rssi);
+
+ DEBUGFS_FWSTATS_ADD(wep, addr_key_count);
+ DEBUGFS_FWSTATS_ADD(wep, default_key_count);
+ /* skipping wep.reserved */
+ DEBUGFS_FWSTATS_ADD(wep, key_not_found);
+ DEBUGFS_FWSTATS_ADD(wep, decrypt_fail);
+ DEBUGFS_FWSTATS_ADD(wep, packets);
+ DEBUGFS_FWSTATS_ADD(wep, interrupt);
+
+ DEBUGFS_FWSTATS_ADD(pwr, ps_enter);
+ DEBUGFS_FWSTATS_ADD(pwr, elp_enter);
+ DEBUGFS_FWSTATS_ADD(pwr, missing_bcns);
+ DEBUGFS_FWSTATS_ADD(pwr, wake_on_host);
+ DEBUGFS_FWSTATS_ADD(pwr, wake_on_timer_exp);
+ DEBUGFS_FWSTATS_ADD(pwr, tx_with_ps);
+ DEBUGFS_FWSTATS_ADD(pwr, tx_without_ps);
+ DEBUGFS_FWSTATS_ADD(pwr, rcvd_beacons);
+ DEBUGFS_FWSTATS_ADD(pwr, power_save_off);
+ DEBUGFS_FWSTATS_ADD(pwr, enable_ps);
+ DEBUGFS_FWSTATS_ADD(pwr, disable_ps);
+ DEBUGFS_FWSTATS_ADD(pwr, fix_tsf_ps);
+ /* skipping cont_miss_bcns_spread for now */
+ DEBUGFS_FWSTATS_ADD(pwr, rcvd_awake_beacons);
+
+ DEBUGFS_FWSTATS_ADD(mic, rx_pkts);
+ DEBUGFS_FWSTATS_ADD(mic, calc_failure);
+
+ DEBUGFS_FWSTATS_ADD(aes, encrypt_fail);
+ DEBUGFS_FWSTATS_ADD(aes, decrypt_fail);
+ DEBUGFS_FWSTATS_ADD(aes, encrypt_packets);
+ DEBUGFS_FWSTATS_ADD(aes, decrypt_packets);
+ DEBUGFS_FWSTATS_ADD(aes, encrypt_interrupt);
+ DEBUGFS_FWSTATS_ADD(aes, decrypt_interrupt);
+
+ DEBUGFS_FWSTATS_ADD(event, heart_beat);
+ DEBUGFS_FWSTATS_ADD(event, calibration);
+ DEBUGFS_FWSTATS_ADD(event, rx_mismatch);
+ DEBUGFS_FWSTATS_ADD(event, rx_mem_empty);
+ DEBUGFS_FWSTATS_ADD(event, rx_pool);
+ DEBUGFS_FWSTATS_ADD(event, oom_late);
+ DEBUGFS_FWSTATS_ADD(event, phy_transmit_error);
+ DEBUGFS_FWSTATS_ADD(event, tx_stuck);
+
+ DEBUGFS_FWSTATS_ADD(ps, pspoll_timeouts);
+ DEBUGFS_FWSTATS_ADD(ps, upsd_timeouts);
+ DEBUGFS_FWSTATS_ADD(ps, upsd_max_sptime);
+ DEBUGFS_FWSTATS_ADD(ps, upsd_max_apturn);
+ DEBUGFS_FWSTATS_ADD(ps, pspoll_max_apturn);
+ DEBUGFS_FWSTATS_ADD(ps, pspoll_utilization);
+ DEBUGFS_FWSTATS_ADD(ps, upsd_utilization);
+
+ DEBUGFS_FWSTATS_ADD(rxpipe, rx_prep_beacon_drop);
+ DEBUGFS_FWSTATS_ADD(rxpipe, descr_host_int_trig_rx_data);
+ DEBUGFS_FWSTATS_ADD(rxpipe, beacon_buffer_thres_host_int_trig_rx_data);
+ DEBUGFS_FWSTATS_ADD(rxpipe, missed_beacon_host_int_trig_rx_data);
+ DEBUGFS_FWSTATS_ADD(rxpipe, tx_xfr_host_int_trig_rx_data);
+
+ DEBUGFS_ADD(tx_queue_len, wl->debugfs.rootdir);
+ DEBUGFS_ADD(retry_count, wl->debugfs.rootdir);
+ DEBUGFS_ADD(excessive_retries, wl->debugfs.rootdir);
+
+out:
+ if (ret < 0)
+ wl1271_debugfs_delete_files(wl);
+
+ return ret;
+}
+
+void wl1271_debugfs_reset(struct wl1271 *wl)
+{
+ memset(wl->stats.fw_stats, 0, sizeof(*wl->stats.fw_stats));
+ wl->stats.retry_count = 0;
+ wl->stats.excessive_retries = 0;
+}
+
+int wl1271_debugfs_init(struct wl1271 *wl)
+{
+ int ret;
+
+ wl->debugfs.rootdir = debugfs_create_dir(KBUILD_MODNAME, NULL);
+
+ if (IS_ERR(wl->debugfs.rootdir)) {
+ ret = PTR_ERR(wl->debugfs.rootdir);
+ wl->debugfs.rootdir = NULL;
+ goto err;
+ }
+
+ wl->debugfs.fw_statistics = debugfs_create_dir("fw-statistics",
+ wl->debugfs.rootdir);
+
+ if (IS_ERR(wl->debugfs.fw_statistics)) {
+ ret = PTR_ERR(wl->debugfs.fw_statistics);
+ wl->debugfs.fw_statistics = NULL;
+ goto err_root;
+ }
+
+ wl->stats.fw_stats = kzalloc(sizeof(*wl->stats.fw_stats),
+ GFP_KERNEL);
+
+ if (!wl->stats.fw_stats) {
+ ret = -ENOMEM;
+ goto err_fw;
+ }
+
+ wl->stats.fw_stats_update = jiffies;
+
+ ret = wl1271_debugfs_add_files(wl);
+
+ if (ret < 0)
+ goto err_file;
+
+ return 0;
+
+err_file:
+ kfree(wl->stats.fw_stats);
+ wl->stats.fw_stats = NULL;
+
+err_fw:
+ debugfs_remove(wl->debugfs.fw_statistics);
+ wl->debugfs.fw_statistics = NULL;
+
+err_root:
+ debugfs_remove(wl->debugfs.rootdir);
+ wl->debugfs.rootdir = NULL;
+
+err:
+ return ret;
+}
+
+void wl1271_debugfs_exit(struct wl1271 *wl)
+{
+ wl1271_debugfs_delete_files(wl);
+
+ kfree(wl->stats.fw_stats);
+ wl->stats.fw_stats = NULL;
+
+ debugfs_remove(wl->debugfs.fw_statistics);
+ wl->debugfs.fw_statistics = NULL;
+
+ debugfs_remove(wl->debugfs.rootdir);
+ wl->debugfs.rootdir = NULL;
+
+}
diff --git a/drivers/net/wireless/wl12xx/wl1271_debugfs.h b/drivers/net/wireless/wl12xx/wl1271_debugfs.h
new file mode 100644
index 00000000000..00a45b2669a
--- /dev/null
+++ b/drivers/net/wireless/wl12xx/wl1271_debugfs.h
@@ -0,0 +1,33 @@
+/*
+ * This file is part of wl1271
+ *
+ * Copyright (C) 2009 Nokia Corporation
+ *
+ * Contact: Luciano Coelho <luciano.coelho@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef WL1271_DEBUGFS_H
+#define WL1271_DEBUGFS_H
+
+#include "wl1271.h"
+
+int wl1271_debugfs_init(struct wl1271 *wl);
+void wl1271_debugfs_exit(struct wl1271 *wl);
+void wl1271_debugfs_reset(struct wl1271 *wl);
+
+#endif /* WL1271_DEBUGFS_H */
diff --git a/drivers/net/wireless/wl12xx/wl1271_event.c b/drivers/net/wireless/wl12xx/wl1271_event.c
new file mode 100644
index 00000000000..f3afd4a6ff3
--- /dev/null
+++ b/drivers/net/wireless/wl12xx/wl1271_event.c
@@ -0,0 +1,125 @@
+/*
+ * This file is part of wl1271
+ *
+ * Copyright (C) 2008-2009 Nokia Corporation
+ *
+ * Contact: Luciano Coelho <luciano.coelho@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include "wl1271.h"
+#include "wl1271_reg.h"
+#include "wl1271_spi.h"
+#include "wl1271_event.h"
+#include "wl1271_ps.h"
+
+static int wl1271_event_scan_complete(struct wl1271 *wl,
+ struct event_mailbox *mbox)
+{
+ wl1271_debug(DEBUG_EVENT, "status: 0x%x",
+ mbox->scheduled_scan_status);
+
+ if (wl->scanning) {
+ mutex_unlock(&wl->mutex);
+ ieee80211_scan_completed(wl->hw, false);
+ mutex_lock(&wl->mutex);
+ wl->scanning = false;
+ }
+
+ return 0;
+}
+
+static void wl1271_event_mbox_dump(struct event_mailbox *mbox)
+{
+ wl1271_debug(DEBUG_EVENT, "MBOX DUMP:");
+ wl1271_debug(DEBUG_EVENT, "\tvector: 0x%x", mbox->events_vector);
+ wl1271_debug(DEBUG_EVENT, "\tmask: 0x%x", mbox->events_mask);
+}
+
+static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox)
+{
+ int ret;
+ u32 vector;
+
+ wl1271_event_mbox_dump(mbox);
+
+ vector = mbox->events_vector & ~(mbox->events_mask);
+ wl1271_debug(DEBUG_EVENT, "vector: 0x%x", vector);
+
+ if (vector & SCAN_COMPLETE_EVENT_ID) {
+ ret = wl1271_event_scan_complete(wl, mbox);
+ if (ret < 0)
+ return ret;
+ }
+
+ if (vector & BSS_LOSE_EVENT_ID) {
+ wl1271_debug(DEBUG_EVENT, "BSS_LOSE_EVENT");
+
+ if (wl->psm_requested && wl->psm) {
+ ret = wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE);
+ if (ret < 0)
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+int wl1271_event_unmask(struct wl1271 *wl)
+{
+ int ret;
+
+ ret = wl1271_acx_event_mbox_mask(wl, ~(wl->event_mask));
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+void wl1271_event_mbox_config(struct wl1271 *wl)
+{
+ wl->mbox_ptr[0] = wl1271_reg_read32(wl, REG_EVENT_MAILBOX_PTR);
+ wl->mbox_ptr[1] = wl->mbox_ptr[0] + sizeof(struct event_mailbox);
+
+ wl1271_debug(DEBUG_EVENT, "MBOX ptrs: 0x%x 0x%x",
+ wl->mbox_ptr[0], wl->mbox_ptr[1]);
+}
+
+int wl1271_event_handle(struct wl1271 *wl, u8 mbox_num)
+{
+ struct event_mailbox mbox;
+ int ret;
+
+ wl1271_debug(DEBUG_EVENT, "EVENT on mbox %d", mbox_num);
+
+ if (mbox_num > 1)
+ return -EINVAL;
+
+ /* first we read the mbox descriptor */
+ wl1271_spi_mem_read(wl, wl->mbox_ptr[mbox_num], &mbox,
+ sizeof(struct event_mailbox));
+
+ /* process the descriptor */
+ ret = wl1271_event_process(wl, &mbox);
+ if (ret < 0)
+ return ret;
+
+ /* then we let the firmware know it can go on...*/
+ wl1271_reg_write32(wl, ACX_REG_INTERRUPT_TRIG, INTR_TRIG_EVENT_ACK);
+
+ return 0;
+}
diff --git a/drivers/net/wireless/wl12xx/wl1271_event.h b/drivers/net/wireless/wl12xx/wl1271_event.h
new file mode 100644
index 00000000000..2cdce7c34bf
--- /dev/null
+++ b/drivers/net/wireless/wl12xx/wl1271_event.h
@@ -0,0 +1,110 @@
+/*
+ * This file is part of wl1271
+ *
+ * Copyright (C) 1998-2009 Texas Instruments. All rights reserved.
+ * Copyright (C) 2008-2009 Nokia Corporation
+ *
+ * Contact: Luciano Coelho <luciano.coelho@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef __WL1271_EVENT_H__
+#define __WL1271_EVENT_H__
+
+/*
+ * Mbox events
+ *
+ * The event mechanism is based on a pair of event buffers (buffers A and
+ * B) at fixed locations in the target's memory. The host processes one
+ * buffer while the other buffer continues to collect events. If the host
+ * is not processing events, an interrupt is issued to signal that a buffer
+ * is ready. Once the host is done with processing events from one buffer,
+ * it signals the target (with an ACK interrupt) that the event buffer is
+ * free.
+ */
+
+enum {
+ MEASUREMENT_START_EVENT_ID = BIT(8),
+ MEASUREMENT_COMPLETE_EVENT_ID = BIT(9),
+ SCAN_COMPLETE_EVENT_ID = BIT(10),
+ SCHEDULED_SCAN_COMPLETE_EVENT_ID = BIT(11),
+ AP_DISCOVERY_COMPLETE_EVENT_ID = BIT(12),
+ PS_REPORT_EVENT_ID = BIT(13),
+ PSPOLL_DELIVERY_FAILURE_EVENT_ID = BIT(14),
+ DISCONNECT_EVENT_COMPLETE_ID = BIT(15),
+ JOIN_EVENT_COMPLETE_ID = BIT(16),
+ CHANNEL_SWITCH_COMPLETE_EVENT_ID = BIT(17),
+ BSS_LOSE_EVENT_ID = BIT(18),
+ REGAINED_BSS_EVENT_ID = BIT(19),
+ ROAMING_TRIGGER_MAX_TX_RETRY_EVENT_ID = BIT(20),
+ SOFT_GEMINI_SENSE_EVENT_ID = BIT(22),
+ SOFT_GEMINI_PREDICTION_EVENT_ID = BIT(23),
+ SOFT_GEMINI_AVALANCHE_EVENT_ID = BIT(24),
+ PLT_RX_CALIBRATION_COMPLETE_EVENT_ID = BIT(25),
+ DBG_EVENT_ID = BIT(26),
+ HEALTH_CHECK_REPLY_EVENT_ID = BIT(27),
+ PERIODIC_SCAN_COMPLETE_EVENT_ID = BIT(28),
+ PERIODIC_SCAN_REPORT_EVENT_ID = BIT(29),
+ BA_SESSION_TEAR_DOWN_EVENT_ID = BIT(30),
+ EVENT_MBOX_ALL_EVENT_ID = 0x7fffffff,
+};
+
+struct event_debug_report {
+ u8 debug_event_id;
+ u8 num_params;
+ u16 pad;
+ u32 report_1;
+ u32 report_2;
+ u32 report_3;
+} __attribute__ ((packed));
+
+#define NUM_OF_RSSI_SNR_TRIGGERS 8
+
+struct event_mailbox {
+ u32 events_vector;
+ u32 events_mask;
+ u32 reserved_1;
+ u32 reserved_2;
+
+ u8 dbg_event_id;
+ u8 num_relevant_params;
+ u16 reserved_3;
+ u32 event_report_p1;
+ u32 event_report_p2;
+ u32 event_report_p3;
+
+ u8 number_of_scan_results;
+ u8 scan_tag;
+ u8 reserved_4[2];
+ u32 compl_scheduled_scan_status;
+
+ u16 scheduled_scan_attended_channels;
+ u8 soft_gemini_sense_info;
+ u8 soft_gemini_protective_info;
+ s8 rssi_snr_trigger_metric[NUM_OF_RSSI_SNR_TRIGGERS];
+ u8 channel_switch_status;
+ u8 scheduled_scan_status;
+ u8 ps_status;
+
+ u8 reserved_5[29];
+} __attribute__ ((packed));
+
+int wl1271_event_unmask(struct wl1271 *wl);
+void wl1271_event_mbox_config(struct wl1271 *wl);
+int wl1271_event_handle(struct wl1271 *wl, u8 mbox);
+
+#endif
diff --git a/drivers/net/wireless/wl12xx/wl1271_init.c b/drivers/net/wireless/wl12xx/wl1271_init.c
new file mode 100644
index 00000000000..490df217605
--- /dev/null
+++ b/drivers/net/wireless/wl12xx/wl1271_init.c
@@ -0,0 +1,397 @@
+/*
+ * This file is part of wl1271
+ *
+ * Copyright (C) 2009 Nokia Corporation
+ *
+ * Contact: Luciano Coelho <luciano.coelho@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+
+#include "wl1271_init.h"
+#include "wl12xx_80211.h"
+#include "wl1271_acx.h"
+#include "wl1271_cmd.h"
+#include "wl1271_reg.h"
+
+static int wl1271_init_hwenc_config(struct wl1271 *wl)
+{
+ int ret;
+
+ ret = wl1271_acx_feature_cfg(wl);
+ if (ret < 0) {
+ wl1271_warning("couldn't set feature config");
+ return ret;
+ }
+
+ ret = wl1271_cmd_set_default_wep_key(wl, wl->default_key);
+ if (ret < 0) {
+ wl1271_warning("couldn't set default key");
+ return ret;
+ }
+
+ return 0;
+}
+
+static int wl1271_init_templates_config(struct wl1271 *wl)
+{
+ int ret;
+
+ /* send empty templates for fw memory reservation */
+ ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4, NULL,
+ sizeof(struct wl12xx_probe_req_template));
+ if (ret < 0)
+ return ret;
+
+ ret = wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, NULL,
+ sizeof(struct wl12xx_null_data_template));
+ if (ret < 0)
+ return ret;
+
+ ret = wl1271_cmd_template_set(wl, CMD_TEMPL_PS_POLL, NULL,
+ sizeof(struct wl12xx_ps_poll_template));
+ if (ret < 0)
+ return ret;
+
+ ret = wl1271_cmd_template_set(wl, CMD_TEMPL_QOS_NULL_DATA, NULL,
+ sizeof
+ (struct wl12xx_qos_null_data_template));
+ if (ret < 0)
+ return ret;
+
+ ret = wl1271_cmd_template_set(wl, CMD_TEMPL_PROBE_RESPONSE, NULL,
+ sizeof
+ (struct wl12xx_probe_resp_template));
+ if (ret < 0)
+ return ret;
+
+ ret = wl1271_cmd_template_set(wl, CMD_TEMPL_BEACON, NULL,
+ sizeof
+ (struct wl12xx_beacon_template));
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+static int wl1271_init_rx_config(struct wl1271 *wl, u32 config, u32 filter)
+{
+ int ret;
+
+ ret = wl1271_acx_rx_msdu_life_time(wl, RX_MSDU_LIFETIME_DEF);
+ if (ret < 0)
+ return ret;
+
+ ret = wl1271_acx_rx_config(wl, config, filter);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+static int wl1271_init_phy_config(struct wl1271 *wl)
+{
+ int ret;
+
+ ret = wl1271_acx_pd_threshold(wl);
+ if (ret < 0)
+ return ret;
+
+ ret = wl1271_acx_slot(wl, DEFAULT_SLOT_TIME);
+ if (ret < 0)
+ return ret;
+
+ ret = wl1271_acx_group_address_tbl(wl);
+ if (ret < 0)
+ return ret;
+
+ ret = wl1271_acx_service_period_timeout(wl);
+ if (ret < 0)
+ return ret;
+
+ ret = wl1271_acx_rts_threshold(wl, RTS_THRESHOLD_DEF);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+static int wl1271_init_beacon_filter(struct wl1271 *wl)
+{
+ int ret;
+
+ ret = wl1271_acx_beacon_filter_opt(wl);
+ if (ret < 0)
+ return ret;
+
+ ret = wl1271_acx_beacon_filter_table(wl);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+static int wl1271_init_pta(struct wl1271 *wl)
+{
+ int ret;
+
+ ret = wl1271_acx_sg_enable(wl);
+ if (ret < 0)
+ return ret;
+
+ ret = wl1271_acx_sg_cfg(wl);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+static int wl1271_init_energy_detection(struct wl1271 *wl)
+{
+ int ret;
+
+ ret = wl1271_acx_cca_threshold(wl);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+static int wl1271_init_beacon_broadcast(struct wl1271 *wl)
+{
+ int ret;
+
+ ret = wl1271_acx_bcn_dtim_options(wl);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+static int wl1271_init_general_parms(struct wl1271 *wl)
+{
+ struct wl1271_general_parms *gen_parms;
+ int ret;
+
+ gen_parms = kzalloc(sizeof(*gen_parms), GFP_KERNEL);
+ if (!gen_parms)
+ return -ENOMEM;
+
+ gen_parms->id = TEST_CMD_INI_FILE_GENERAL_PARAM;
+
+ gen_parms->ref_clk = REF_CLK_38_4_E;
+ /* FIXME: magic numbers */
+ gen_parms->settling_time = 5;
+ gen_parms->clk_valid_on_wakeup = 0;
+ gen_parms->dc2dcmode = 0;
+ gen_parms->single_dual_band = 0;
+ gen_parms->tx_bip_fem_autodetect = 1;
+ gen_parms->tx_bip_fem_manufacturer = 1;
+ gen_parms->settings = 1;
+
+ ret = wl1271_cmd_test(wl, gen_parms, sizeof(*gen_parms), 0);
+ if (ret < 0) {
+ wl1271_warning("CMD_INI_FILE_GENERAL_PARAM failed");
+ return ret;
+ }
+
+ kfree(gen_parms);
+ return 0;
+}
+
+static int wl1271_init_radio_parms(struct wl1271 *wl)
+{
+ /*
+ * FIXME: All these magic numbers should be moved to some place where
+ * they can be configured (separate file?)
+ */
+
+ struct wl1271_radio_parms *radio_parms;
+ int ret;
+ u8 compensation[] = { 0xec, 0xf6, 0x00, 0x0c, 0x18, 0xf8, 0xfc, 0x00,
+ 0x08, 0x10, 0xf0, 0xf8, 0x00, 0x0a, 0x14 };
+
+ u8 tx_rate_limits_normal[] = { 0x1e, 0x1f, 0x22, 0x24, 0x28, 0x29 };
+ u8 tx_rate_limits_degraded[] = { 0x1b, 0x1c, 0x1e, 0x20, 0x24, 0x25 };
+
+ u8 tx_channel_limits_11b[] = { 0x22, 0x50, 0x50, 0x50,
+ 0x50, 0x50, 0x50, 0x50,
+ 0x50, 0x50, 0x22, 0x50,
+ 0x22, 0x50 };
+
+ u8 tx_channel_limits_ofdm[] = { 0x20, 0x50, 0x50, 0x50,
+ 0x50, 0x50, 0x50, 0x50,
+ 0x50, 0x50, 0x20, 0x50,
+ 0x20, 0x50 };
+
+ u8 tx_pdv_rate_offsets[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+
+ u8 tx_ibias[] = { 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x27 };
+
+ radio_parms = kzalloc(sizeof(*radio_parms), GFP_KERNEL);
+ if (!radio_parms)
+ return -ENOMEM;
+
+ radio_parms->id = TEST_CMD_INI_FILE_RADIO_PARAM;
+
+ /* Static radio parameters */
+ radio_parms->rx_trace_loss = 10;
+ radio_parms->tx_trace_loss = 10;
+ memcpy(radio_parms->rx_rssi_and_proc_compens, compensation,
+ sizeof(compensation));
+
+ /* We don't set the 5GHz -- N/A */
+
+ /* Dynamic radio parameters */
+ radio_parms->tx_ref_pd_voltage = cpu_to_le16(0x24e);
+ radio_parms->tx_ref_power = 0x78;
+ radio_parms->tx_offset_db = 0x0;
+
+ memcpy(radio_parms->tx_rate_limits_normal, tx_rate_limits_normal,
+ sizeof(tx_rate_limits_normal));
+ memcpy(radio_parms->tx_rate_limits_degraded, tx_rate_limits_degraded,
+ sizeof(tx_rate_limits_degraded));
+
+ memcpy(radio_parms->tx_channel_limits_11b, tx_channel_limits_11b,
+ sizeof(tx_channel_limits_11b));
+ memcpy(radio_parms->tx_channel_limits_ofdm, tx_channel_limits_ofdm,
+ sizeof(tx_channel_limits_ofdm));
+ memcpy(radio_parms->tx_pdv_rate_offsets, tx_pdv_rate_offsets,
+ sizeof(tx_pdv_rate_offsets));
+ memcpy(radio_parms->tx_ibias, tx_ibias,
+ sizeof(tx_ibias));
+
+ radio_parms->rx_fem_insertion_loss = 0x14;
+
+ ret = wl1271_cmd_test(wl, radio_parms, sizeof(*radio_parms), 0);
+ if (ret < 0)
+ wl1271_warning("CMD_INI_FILE_RADIO_PARAM failed");
+
+ kfree(radio_parms);
+ return ret;
+}
+
+int wl1271_hw_init(struct wl1271 *wl)
+{
+ int ret;
+
+ ret = wl1271_init_general_parms(wl);
+ if (ret < 0)
+ return ret;
+
+ ret = wl1271_init_radio_parms(wl);
+ if (ret < 0)
+ return ret;
+
+ /* Template settings */
+ ret = wl1271_init_templates_config(wl);
+ if (ret < 0)
+ return ret;
+
+ /* Default memory configuration */
+ ret = wl1271_acx_init_mem_config(wl);
+ if (ret < 0)
+ return ret;
+
+ /* RX config */
+ ret = wl1271_init_rx_config(wl,
+ RX_CFG_PROMISCUOUS | RX_CFG_TSF,
+ RX_FILTER_OPTION_DEF);
+ /* RX_CONFIG_OPTION_ANY_DST_ANY_BSS,
+ RX_FILTER_OPTION_FILTER_ALL); */
+ if (ret < 0)
+ goto out_free_memmap;
+
+ /* PHY layer config */
+ ret = wl1271_init_phy_config(wl);
+ if (ret < 0)
+ goto out_free_memmap;
+
+ /* Beacon filtering */
+ ret = wl1271_init_beacon_filter(wl);
+ if (ret < 0)
+ goto out_free_memmap;
+
+ /* Configure TX patch complete interrupt behavior */
+ ret = wl1271_acx_tx_config_options(wl);
+ if (ret < 0)
+ goto out_free_memmap;
+
+ /* RX complete interrupt pacing */
+ ret = wl1271_acx_init_rx_interrupt(wl);
+ if (ret < 0)
+ goto out_free_memmap;
+
+ /* Bluetooth WLAN coexistence */
+ ret = wl1271_init_pta(wl);
+ if (ret < 0)
+ goto out_free_memmap;
+
+ /* Energy detection */
+ ret = wl1271_init_energy_detection(wl);
+ if (ret < 0)
+ goto out_free_memmap;
+
+ /* Beacons and boradcast settings */
+ ret = wl1271_init_beacon_broadcast(wl);
+ if (ret < 0)
+ goto out_free_memmap;
+
+ /* Default fragmentation threshold */
+ ret = wl1271_acx_frag_threshold(wl);
+ if (ret < 0)
+ goto out_free_memmap;
+
+ /* Default TID configuration */
+ ret = wl1271_acx_tid_cfg(wl);
+ if (ret < 0)
+ goto out_free_memmap;
+
+ /* Default AC configuration */
+ ret = wl1271_acx_ac_cfg(wl);
+ if (ret < 0)
+ goto out_free_memmap;
+
+ /* Configure TX rate classes */
+ ret = wl1271_acx_rate_policies(wl);
+ if (ret < 0)
+ goto out_free_memmap;
+
+ /* Enable data path */
+ ret = wl1271_cmd_data_path(wl, wl->channel, 1);
+ if (ret < 0)
+ goto out_free_memmap;
+
+ /* Configure for ELP power saving */
+ ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_ELP);
+ if (ret < 0)
+ goto out_free_memmap;
+
+ /* Configure HW encryption */
+ ret = wl1271_init_hwenc_config(wl);
+ if (ret < 0)
+ goto out_free_memmap;
+
+ return 0;
+
+ out_free_memmap:
+ kfree(wl->target_mem_map);
+
+ return ret;
+}
diff --git a/drivers/net/wireless/wl12xx/wl1271_init.h b/drivers/net/wireless/wl12xx/wl1271_init.h
new file mode 100644
index 00000000000..bd8ff0fa227
--- /dev/null
+++ b/drivers/net/wireless/wl12xx/wl1271_init.h
@@ -0,0 +1,115 @@
+/*
+ * This file is part of wl1271
+ *
+ * Copyright (C) 2009 Nokia Corporation
+ *
+ * Contact: Luciano Coelho <luciano.coelho@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef __WL1271_INIT_H__
+#define __WL1271_INIT_H__
+
+#include "wl1271.h"
+
+int wl1271_hw_init_power_auth(struct wl1271 *wl);
+int wl1271_hw_init(struct wl1271 *wl);
+
+/* These are not really a TEST_CMD, but the ref driver uses them as such */
+#define TEST_CMD_INI_FILE_RADIO_PARAM 0x19
+#define TEST_CMD_INI_FILE_GENERAL_PARAM 0x1E
+
+struct wl1271_general_parms {
+ u8 id;
+ u8 padding[3];
+
+ u8 ref_clk;
+ u8 settling_time;
+ u8 clk_valid_on_wakeup;
+ u8 dc2dcmode;
+ u8 single_dual_band;
+
+ u8 tx_bip_fem_autodetect;
+ u8 tx_bip_fem_manufacturer;
+ u8 settings;
+} __attribute__ ((packed));
+
+enum ref_clk_enum {
+ REF_CLK_19_2_E,
+ REF_CLK_26_E,
+ REF_CLK_38_4_E,
+ REF_CLK_52_E
+};
+
+#define RSSI_AND_PROCESS_COMPENSATION_SIZE 15
+#define NUMBER_OF_SUB_BANDS_5 7
+#define NUMBER_OF_RATE_GROUPS 6
+#define NUMBER_OF_CHANNELS_2_4 14
+#define NUMBER_OF_CHANNELS_5 35
+
+struct wl1271_radio_parms {
+ u8 id;
+ u8 padding[3];
+
+ /* Static radio parameters */
+ /* 2.4GHz */
+ u8 rx_trace_loss;
+ u8 tx_trace_loss;
+ s8 rx_rssi_and_proc_compens[RSSI_AND_PROCESS_COMPENSATION_SIZE];
+
+ /* 5GHz */
+ u8 rx_trace_loss_5[NUMBER_OF_SUB_BANDS_5];
+ u8 tx_trace_loss_5[NUMBER_OF_SUB_BANDS_5];
+ s8 rx_rssi_and_proc_compens_5[RSSI_AND_PROCESS_COMPENSATION_SIZE];
+
+ /* Dynamic radio parameters */
+ /* 2.4GHz */
+ s16 tx_ref_pd_voltage;
+ s8 tx_ref_power;
+ s8 tx_offset_db;
+
+ s8 tx_rate_limits_normal[NUMBER_OF_RATE_GROUPS];
+ s8 tx_rate_limits_degraded[NUMBER_OF_RATE_GROUPS];
+
+ s8 tx_channel_limits_11b[NUMBER_OF_CHANNELS_2_4];
+ s8 tx_channel_limits_ofdm[NUMBER_OF_CHANNELS_2_4];
+ s8 tx_pdv_rate_offsets[NUMBER_OF_RATE_GROUPS];
+
+ u8 tx_ibias[NUMBER_OF_RATE_GROUPS];
+ u8 rx_fem_insertion_loss;
+
+ u8 padding2;
+
+ /* 5GHz */
+ s16 tx_ref_pd_voltage_5[NUMBER_OF_SUB_BANDS_5];
+ s8 tx_ref_power_5[NUMBER_OF_SUB_BANDS_5];
+ s8 tx_offset_db_5[NUMBER_OF_SUB_BANDS_5];
+
+ s8 tx_rate_limits_normal_5[NUMBER_OF_RATE_GROUPS];
+ s8 tx_rate_limits_degraded_5[NUMBER_OF_RATE_GROUPS];
+
+ s8 tx_channel_limits_ofdm_5[NUMBER_OF_CHANNELS_5];
+ s8 tx_pdv_rate_offsets_5[NUMBER_OF_RATE_GROUPS];
+
+ /* FIXME: this is inconsistent with the types for 2.4GHz */
+ s8 tx_ibias_5[NUMBER_OF_RATE_GROUPS];
+ s8 rx_fem_insertion_loss_5[NUMBER_OF_SUB_BANDS_5];
+
+ u8 padding3[2];
+} __attribute__ ((packed));
+
+#endif
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c
new file mode 100644
index 00000000000..4102d590b79
--- /dev/null
+++ b/drivers/net/wireless/wl12xx/wl1271_main.c
@@ -0,0 +1,1397 @@
+/*
+ * This file is part of wl1271
+ *
+ * Copyright (C) 2008-2009 Nokia Corporation
+ *
+ * Contact: Luciano Coelho <luciano.coelho@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/firmware.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/spi/spi.h>
+#include <linux/crc32.h>
+#include <linux/etherdevice.h>
+#include <linux/spi/wl12xx.h>
+
+#include "wl1271.h"
+#include "wl12xx_80211.h"
+#include "wl1271_reg.h"
+#include "wl1271_spi.h"
+#include "wl1271_event.h"
+#include "wl1271_tx.h"
+#include "wl1271_rx.h"
+#include "wl1271_ps.h"
+#include "wl1271_init.h"
+#include "wl1271_debugfs.h"
+#include "wl1271_cmd.h"
+#include "wl1271_boot.h"
+
+static int wl1271_plt_init(struct wl1271 *wl)
+{
+ int ret;
+
+ ret = wl1271_acx_init_mem_config(wl);
+ if (ret < 0)
+ return ret;
+
+ ret = wl1271_cmd_data_path(wl, wl->channel, 1);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+static void wl1271_disable_interrupts(struct wl1271 *wl)
+{
+ disable_irq(wl->irq);
+}
+
+static void wl1271_power_off(struct wl1271 *wl)
+{
+ wl->set_power(false);
+}
+
+static void wl1271_power_on(struct wl1271 *wl)
+{
+ wl->set_power(true);
+}
+
+static void wl1271_fw_status(struct wl1271 *wl, struct wl1271_fw_status *status)
+{
+ u32 total = 0;
+ int i;
+
+ /*
+ * FIXME: Reading the FW status directly from the registers seems to
+ * be the right thing to do, but it doesn't work. And in the
+ * reference driver, there is a workaround called
+ * USE_SDIO_24M_WORKAROUND, which reads the status from memory
+ * instead, so we do the same here.
+ */
+
+ wl1271_spi_mem_read(wl, STATUS_MEM_ADDRESS, status, sizeof(*status));
+
+ wl1271_debug(DEBUG_IRQ, "intr: 0x%x (fw_rx_counter = %d, "
+ "drv_rx_counter = %d, tx_results_counter = %d)",
+ status->intr,
+ status->fw_rx_counter,
+ status->drv_rx_counter,
+ status->tx_results_counter);
+
+ /* update number of available TX blocks */
+ for (i = 0; i < NUM_TX_QUEUES; i++) {
+ u32 cnt = status->tx_released_blks[i] - wl->tx_blocks_freed[i];
+ wl->tx_blocks_freed[i] = status->tx_released_blks[i];
+ wl->tx_blocks_available += cnt;
+ total += cnt;
+ }
+
+ /* if more blocks are available now, schedule some tx work */
+ if (total && !skb_queue_empty(&wl->tx_queue))
+ schedule_work(&wl->tx_work);
+
+ /* update the host-chipset time offset */
+ wl->time_offset = jiffies_to_usecs(jiffies) - status->fw_localtime;
+}
+
+#define WL1271_IRQ_MAX_LOOPS 10
+static void wl1271_irq_work(struct work_struct *work)
+{
+ u32 intr, ctr = WL1271_IRQ_MAX_LOOPS;
+ int ret;
+ struct wl1271 *wl =
+ container_of(work, struct wl1271, irq_work);
+
+ mutex_lock(&wl->mutex);
+
+ wl1271_debug(DEBUG_IRQ, "IRQ work");
+
+ if (wl->state == WL1271_STATE_OFF)
+ goto out;
+
+ ret = wl1271_ps_elp_wakeup(wl, true);
+ if (ret < 0)
+ goto out;
+
+ wl1271_reg_write32(wl, ACX_REG_INTERRUPT_MASK, WL1271_ACX_INTR_ALL);
+
+ intr = wl1271_reg_read32(wl, ACX_REG_INTERRUPT_CLEAR);
+ if (!intr) {
+ wl1271_debug(DEBUG_IRQ, "Zero interrupt received.");
+ goto out_sleep;
+ }
+
+ intr &= WL1271_INTR_MASK;
+
+ do {
+ wl1271_fw_status(wl, wl->fw_status);
+
+
+ if (intr & (WL1271_ACX_INTR_EVENT_A |
+ WL1271_ACX_INTR_EVENT_B)) {
+ wl1271_debug(DEBUG_IRQ,
+ "WL1271_ACX_INTR_EVENT (0x%x)", intr);
+ if (intr & WL1271_ACX_INTR_EVENT_A)
+ wl1271_event_handle(wl, 0);
+ else
+ wl1271_event_handle(wl, 1);
+ }
+
+ if (intr & WL1271_ACX_INTR_INIT_COMPLETE)
+ wl1271_debug(DEBUG_IRQ,
+ "WL1271_ACX_INTR_INIT_COMPLETE");
+
+ if (intr & WL1271_ACX_INTR_HW_AVAILABLE)
+ wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_HW_AVAILABLE");
+
+ if (intr & WL1271_ACX_INTR_DATA) {
+ u8 tx_res_cnt = wl->fw_status->tx_results_counter -
+ wl->tx_results_count;
+
+ wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_DATA");
+
+ /* check for tx results */
+ if (tx_res_cnt)
+ wl1271_tx_complete(wl, tx_res_cnt);
+
+ wl1271_rx(wl, wl->fw_status);
+ }
+
+ intr = wl1271_reg_read32(wl, ACX_REG_INTERRUPT_CLEAR);
+ intr &= WL1271_INTR_MASK;
+ } while (intr && --ctr);
+
+out_sleep:
+ wl1271_reg_write32(wl, ACX_REG_INTERRUPT_MASK,
+ WL1271_ACX_INTR_ALL & ~(WL1271_INTR_MASK));
+ wl1271_ps_elp_sleep(wl);
+
+out:
+ mutex_unlock(&wl->mutex);
+}
+
+static irqreturn_t wl1271_irq(int irq, void *cookie)
+{
+ struct wl1271 *wl;
+ unsigned long flags;
+
+ wl1271_debug(DEBUG_IRQ, "IRQ");
+
+ wl = cookie;
+
+ /* complete the ELP completion */
+ spin_lock_irqsave(&wl->wl_lock, flags);
+ if (wl->elp_compl) {
+ complete(wl->elp_compl);
+ wl->elp_compl = NULL;
+ }
+
+ schedule_work(&wl->irq_work);
+ spin_unlock_irqrestore(&wl->wl_lock, flags);
+
+ return IRQ_HANDLED;
+}
+
+static int wl1271_fetch_firmware(struct wl1271 *wl)
+{
+ const struct firmware *fw;
+ int ret;
+
+ ret = request_firmware(&fw, WL1271_FW_NAME, &wl->spi->dev);
+
+ if (ret < 0) {
+ wl1271_error("could not get firmware: %d", ret);
+ return ret;
+ }
+
+ if (fw->size % 4) {
+ wl1271_error("firmware size is not multiple of 32 bits: %zu",
+ fw->size);
+ ret = -EILSEQ;
+ goto out;
+ }
+
+ wl->fw_len = fw->size;
+ wl->fw = kmalloc(wl->fw_len, GFP_KERNEL);
+
+ if (!wl->fw) {
+ wl1271_error("could not allocate memory for the firmware");
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ memcpy(wl->fw, fw->data, wl->fw_len);
+
+ ret = 0;
+
+out:
+ release_firmware(fw);
+
+ return ret;
+}
+
+static int wl1271_fetch_nvs(struct wl1271 *wl)
+{
+ const struct firmware *fw;
+ int ret;
+
+ ret = request_firmware(&fw, WL1271_NVS_NAME, &wl->spi->dev);
+
+ if (ret < 0) {
+ wl1271_error("could not get nvs file: %d", ret);
+ return ret;
+ }
+
+ if (fw->size % 4) {
+ wl1271_error("nvs size is not multiple of 32 bits: %zu",
+ fw->size);
+ ret = -EILSEQ;
+ goto out;
+ }
+
+ wl->nvs_len = fw->size;
+ wl->nvs = kmalloc(wl->nvs_len, GFP_KERNEL);
+
+ if (!wl->nvs) {
+ wl1271_error("could not allocate memory for the nvs file");
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ memcpy(wl->nvs, fw->data, wl->nvs_len);
+
+ ret = 0;
+
+out:
+ release_firmware(fw);
+
+ return ret;
+}
+
+static void wl1271_fw_wakeup(struct wl1271 *wl)
+{
+ u32 elp_reg;
+
+ elp_reg = ELPCTRL_WAKE_UP;
+ wl1271_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, elp_reg);
+}
+
+static int wl1271_setup(struct wl1271 *wl)
+{
+ wl->fw_status = kmalloc(sizeof(*wl->fw_status), GFP_KERNEL);
+ if (!wl->fw_status)
+ return -ENOMEM;
+
+ wl->tx_res_if = kmalloc(sizeof(*wl->tx_res_if), GFP_KERNEL);
+ if (!wl->tx_res_if) {
+ kfree(wl->fw_status);
+ return -ENOMEM;
+ }
+
+ INIT_WORK(&wl->irq_work, wl1271_irq_work);
+ INIT_WORK(&wl->tx_work, wl1271_tx_work);
+ return 0;
+}
+
+static int wl1271_chip_wakeup(struct wl1271 *wl)
+{
+ int ret = 0;
+
+ wl1271_power_on(wl);
+ msleep(WL1271_POWER_ON_SLEEP);
+ wl1271_spi_reset(wl);
+ wl1271_spi_init(wl);
+
+ /* We don't need a real memory partition here, because we only want
+ * to use the registers at this point. */
+ wl1271_set_partition(wl,
+ 0x00000000,
+ 0x00000000,
+ REGISTERS_BASE,
+ REGISTERS_DOWN_SIZE);
+
+ /* ELP module wake up */
+ wl1271_fw_wakeup(wl);
+
+ /* whal_FwCtrl_BootSm() */
+
+ /* 0. read chip id from CHIP_ID */
+ wl->chip.id = wl1271_reg_read32(wl, CHIP_ID_B);
+
+ /* 1. check if chip id is valid */
+
+ switch (wl->chip.id) {
+ case CHIP_ID_1271_PG10:
+ wl1271_warning("chip id 0x%x (1271 PG10) support is obsolete",
+ wl->chip.id);
+
+ ret = wl1271_setup(wl);
+ if (ret < 0)
+ goto out;
+ break;
+ case CHIP_ID_1271_PG20:
+ wl1271_debug(DEBUG_BOOT, "chip id 0x%x (1271 PG20)",
+ wl->chip.id);
+
+ ret = wl1271_setup(wl);
+ if (ret < 0)
+ goto out;
+ break;
+ default:
+ wl1271_error("unsupported chip id: 0x%x", wl->chip.id);
+ ret = -ENODEV;
+ goto out;
+ }
+
+ if (wl->fw == NULL) {
+ ret = wl1271_fetch_firmware(wl);
+ if (ret < 0)
+ goto out;
+ }
+
+ /* No NVS from netlink, try to get it from the filesystem */
+ if (wl->nvs == NULL) {
+ ret = wl1271_fetch_nvs(wl);
+ if (ret < 0)
+ goto out;
+ }
+
+out:
+ return ret;
+}
+
+static void wl1271_filter_work(struct work_struct *work)
+{
+ struct wl1271 *wl =
+ container_of(work, struct wl1271, filter_work);
+ int ret;
+
+ mutex_lock(&wl->mutex);
+
+ if (wl->state == WL1271_STATE_OFF)
+ goto out;
+
+ ret = wl1271_ps_elp_wakeup(wl, false);
+ if (ret < 0)
+ goto out;
+
+ /* FIXME: replace the magic numbers with proper definitions */
+ ret = wl1271_cmd_join(wl, wl->bss_type, 1, 100, 0);
+ if (ret < 0)
+ goto out_sleep;
+
+out_sleep:
+ wl1271_ps_elp_sleep(wl);
+
+out:
+ mutex_unlock(&wl->mutex);
+}
+
+int wl1271_plt_start(struct wl1271 *wl)
+{
+ int ret;
+
+ mutex_lock(&wl->mutex);
+
+ wl1271_notice("power up");
+
+ if (wl->state != WL1271_STATE_OFF) {
+ wl1271_error("cannot go into PLT state because not "
+ "in off state: %d", wl->state);
+ ret = -EBUSY;
+ goto out;
+ }
+
+ wl->state = WL1271_STATE_PLT;
+
+ ret = wl1271_chip_wakeup(wl);
+ if (ret < 0)
+ goto out;
+
+ ret = wl1271_boot(wl);
+ if (ret < 0)
+ goto out;
+
+ wl1271_notice("firmware booted in PLT mode (%s)", wl->chip.fw_ver);
+
+ ret = wl1271_plt_init(wl);
+ if (ret < 0)
+ goto out;
+
+out:
+ mutex_unlock(&wl->mutex);
+
+ return ret;
+}
+
+int wl1271_plt_stop(struct wl1271 *wl)
+{
+ int ret = 0;
+
+ mutex_lock(&wl->mutex);
+
+ wl1271_notice("power down");
+
+ if (wl->state != WL1271_STATE_PLT) {
+ wl1271_error("cannot power down because not in PLT "
+ "state: %d", wl->state);
+ ret = -EBUSY;
+ goto out;
+ }
+
+ wl1271_disable_interrupts(wl);
+ wl1271_power_off(wl);
+
+ wl->state = WL1271_STATE_OFF;
+
+out:
+ mutex_unlock(&wl->mutex);
+
+ return ret;
+}
+
+
+static int wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
+{
+ struct wl1271 *wl = hw->priv;
+
+ skb_queue_tail(&wl->tx_queue, skb);
+
+ /*
+ * The chip specific setup must run before the first TX packet -
+ * before that, the tx_work will not be initialized!
+ */
+
+ schedule_work(&wl->tx_work);
+
+ /*
+ * The workqueue is slow to process the tx_queue and we need stop
+ * the queue here, otherwise the queue will get too long.
+ */
+ if (skb_queue_len(&wl->tx_queue) >= WL1271_TX_QUEUE_MAX_LENGTH) {
+ ieee80211_stop_queues(wl->hw);
+
+ /*
+ * FIXME: this is racy, the variable is not properly
+ * protected. Maybe fix this by removing the stupid
+ * variable altogether and checking the real queue state?
+ */
+ wl->tx_queue_stopped = true;
+ }
+
+ return NETDEV_TX_OK;
+}
+
+static int wl1271_op_start(struct ieee80211_hw *hw)
+{
+ struct wl1271 *wl = hw->priv;
+ int ret = 0;
+
+ wl1271_debug(DEBUG_MAC80211, "mac80211 start");
+
+ mutex_lock(&wl->mutex);
+
+ if (wl->state != WL1271_STATE_OFF) {
+ wl1271_error("cannot start because not in off state: %d",
+ wl->state);
+ ret = -EBUSY;
+ goto out;
+ }
+
+ ret = wl1271_chip_wakeup(wl);
+ if (ret < 0)
+ goto out;
+
+ ret = wl1271_boot(wl);
+ if (ret < 0)
+ goto out;
+
+ ret = wl1271_hw_init(wl);
+ if (ret < 0)
+ goto out;
+
+ wl->state = WL1271_STATE_ON;
+
+ wl1271_info("firmware booted (%s)", wl->chip.fw_ver);
+
+out:
+ if (ret < 0)
+ wl1271_power_off(wl);
+
+ mutex_unlock(&wl->mutex);
+
+ return ret;
+}
+
+static void wl1271_op_stop(struct ieee80211_hw *hw)
+{
+ struct wl1271 *wl = hw->priv;
+ int i;
+
+ wl1271_info("down");
+
+ wl1271_debug(DEBUG_MAC80211, "mac80211 stop");
+
+ mutex_lock(&wl->mutex);
+
+ WARN_ON(wl->state != WL1271_STATE_ON);
+
+ if (wl->scanning) {
+ mutex_unlock(&wl->mutex);
+ ieee80211_scan_completed(wl->hw, true);
+ mutex_lock(&wl->mutex);
+ wl->scanning = false;
+ }
+
+ wl->state = WL1271_STATE_OFF;
+
+ wl1271_disable_interrupts(wl);
+
+ mutex_unlock(&wl->mutex);
+
+ cancel_work_sync(&wl->irq_work);
+ cancel_work_sync(&wl->tx_work);
+ cancel_work_sync(&wl->filter_work);
+
+ mutex_lock(&wl->mutex);
+
+ /* let's notify MAC80211 about the remaining pending TX frames */
+ wl1271_tx_flush(wl);
+ wl1271_power_off(wl);
+
+ memset(wl->bssid, 0, ETH_ALEN);
+ memset(wl->ssid, 0, IW_ESSID_MAX_SIZE + 1);
+ wl->ssid_len = 0;
+ wl->listen_int = 1;
+ wl->bss_type = MAX_BSS_TYPE;
+
+ wl->rx_counter = 0;
+ wl->elp = false;
+ wl->psm = 0;
+ wl->tx_queue_stopped = false;
+ wl->power_level = WL1271_DEFAULT_POWER_LEVEL;
+ wl->tx_blocks_available = 0;
+ wl->tx_results_count = 0;
+ wl->tx_packets_count = 0;
+ wl->time_offset = 0;
+ wl->session_counter = 0;
+ for (i = 0; i < NUM_TX_QUEUES; i++)
+ wl->tx_blocks_freed[i] = 0;
+
+ wl1271_debugfs_reset(wl);
+ mutex_unlock(&wl->mutex);
+}
+
+static int wl1271_op_add_interface(struct ieee80211_hw *hw,
+ struct ieee80211_if_init_conf *conf)
+{
+ struct wl1271 *wl = hw->priv;
+ DECLARE_MAC_BUF(mac);
+ int ret = 0;
+
+ wl1271_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %s",
+ conf->type, print_mac(mac, conf->mac_addr));
+
+ mutex_lock(&wl->mutex);
+
+ switch (conf->type) {
+ case NL80211_IFTYPE_STATION:
+ wl->bss_type = BSS_TYPE_STA_BSS;
+ break;
+ case NL80211_IFTYPE_ADHOC:
+ wl->bss_type = BSS_TYPE_IBSS;
+ break;
+ default:
+ ret = -EOPNOTSUPP;
+ goto out;
+ }
+
+ /* FIXME: what if conf->mac_addr changes? */
+
+out:
+ mutex_unlock(&wl->mutex);
+ return ret;
+}
+
+static void wl1271_op_remove_interface(struct ieee80211_hw *hw,
+ struct ieee80211_if_init_conf *conf)
+{
+ wl1271_debug(DEBUG_MAC80211, "mac80211 remove interface");
+}
+
+#if 0
+static int wl1271_op_config_interface(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_if_conf *conf)
+{
+ struct wl1271 *wl = hw->priv;
+ struct sk_buff *beacon;
+ DECLARE_MAC_BUF(mac);
+ int ret;
+
+ wl1271_debug(DEBUG_MAC80211, "mac80211 config_interface bssid %s",
+ print_mac(mac, conf->bssid));
+ wl1271_dump_ascii(DEBUG_MAC80211, "ssid: ", conf->ssid,
+ conf->ssid_len);
+
+ mutex_lock(&wl->mutex);
+
+ ret = wl1271_ps_elp_wakeup(wl, false);
+ if (ret < 0)
+ goto out;
+
+ memcpy(wl->bssid, conf->bssid, ETH_ALEN);
+
+ ret = wl1271_cmd_build_null_data(wl);
+ if (ret < 0)
+ goto out_sleep;
+
+ wl->ssid_len = conf->ssid_len;
+ if (wl->ssid_len)
+ memcpy(wl->ssid, conf->ssid, wl->ssid_len);
+
+ if (wl->bss_type != BSS_TYPE_IBSS) {
+ /* FIXME: replace the magic numbers with proper definitions */
+ ret = wl1271_cmd_join(wl, wl->bss_type, 5, 100, 1);
+ if (ret < 0)
+ goto out_sleep;
+ }
+
+ if (conf->changed & IEEE80211_IFCC_BEACON) {
+ beacon = ieee80211_beacon_get(hw, vif);
+ ret = wl1271_cmd_template_set(wl, CMD_TEMPL_BEACON,
+ beacon->data, beacon->len);
+
+ if (ret < 0) {
+ dev_kfree_skb(beacon);
+ goto out_sleep;
+ }
+
+ ret = wl1271_cmd_template_set(wl, CMD_TEMPL_PROBE_RESPONSE,
+ beacon->data, beacon->len);
+
+ dev_kfree_skb(beacon);
+
+ if (ret < 0)
+ goto out_sleep;
+
+ /* FIXME: replace the magic numbers with proper definitions */
+ ret = wl1271_cmd_join(wl, wl->bss_type, 1, 100, 0);
+
+ if (ret < 0)
+ goto out_sleep;
+ }
+
+out_sleep:
+ wl1271_ps_elp_sleep(wl);
+
+out:
+ mutex_unlock(&wl->mutex);
+
+ return ret;
+}
+#endif
+
+static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed)
+{
+ struct wl1271 *wl = hw->priv;
+ struct ieee80211_conf *conf = &hw->conf;
+ int channel, ret = 0;
+
+ channel = ieee80211_frequency_to_channel(conf->channel->center_freq);
+
+ wl1271_debug(DEBUG_MAC80211, "mac80211 config ch %d psm %s power %d",
+ channel,
+ conf->flags & IEEE80211_CONF_PS ? "on" : "off",
+ conf->power_level);
+
+ mutex_lock(&wl->mutex);
+
+ ret = wl1271_ps_elp_wakeup(wl, false);
+ if (ret < 0)
+ goto out;
+
+ if (channel != wl->channel) {
+ u8 old_channel = wl->channel;
+ wl->channel = channel;
+
+ /* FIXME: use beacon interval provided by mac80211 */
+ ret = wl1271_cmd_join(wl, wl->bss_type, 1, 100, 0);
+ if (ret < 0) {
+ wl->channel = old_channel;
+ goto out_sleep;
+ }
+ }
+
+ ret = wl1271_cmd_build_null_data(wl);
+ if (ret < 0)
+ goto out_sleep;
+
+ if (conf->flags & IEEE80211_CONF_PS && !wl->psm_requested) {
+ wl1271_info("psm enabled");
+
+ wl->psm_requested = true;
+
+ /*
+ * We enter PSM only if we're already associated.
+ * If we're not, we'll enter it when joining an SSID,
+ * through the bss_info_changed() hook.
+ */
+ ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE);
+ } else if (!(conf->flags & IEEE80211_CONF_PS) &&
+ wl->psm_requested) {
+ wl1271_info("psm disabled");
+
+ wl->psm_requested = false;
+
+ if (wl->psm)
+ ret = wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE);
+ }
+
+ if (conf->power_level != wl->power_level) {
+ ret = wl1271_acx_tx_power(wl, conf->power_level);
+ if (ret < 0)
+ goto out;
+
+ wl->power_level = conf->power_level;
+ }
+
+out_sleep:
+ wl1271_ps_elp_sleep(wl);
+
+out:
+ mutex_unlock(&wl->mutex);
+
+ return ret;
+}
+
+#define WL1271_SUPPORTED_FILTERS (FIF_PROMISC_IN_BSS | \
+ FIF_ALLMULTI | \
+ FIF_FCSFAIL | \
+ FIF_BCN_PRBRESP_PROMISC | \
+ FIF_CONTROL | \
+ FIF_OTHER_BSS)
+
+static void wl1271_op_configure_filter(struct ieee80211_hw *hw,
+ unsigned int changed,
+ unsigned int *total,
+ int mc_count,
+ struct dev_addr_list *mc_list)
+{
+ struct wl1271 *wl = hw->priv;
+
+ wl1271_debug(DEBUG_MAC80211, "mac80211 configure filter");
+
+ *total &= WL1271_SUPPORTED_FILTERS;
+ changed &= WL1271_SUPPORTED_FILTERS;
+
+ if (changed == 0)
+ return;
+
+ /* FIXME: wl->rx_config and wl->rx_filter are not protected */
+ wl->rx_config = WL1271_DEFAULT_RX_CONFIG;
+ wl->rx_filter = WL1271_DEFAULT_RX_FILTER;
+
+ /*
+ * FIXME: workqueues need to be properly cancelled on stop(), for
+ * now let's just disable changing the filter settings. They will
+ * be updated any on config().
+ */
+ /* schedule_work(&wl->filter_work); */
+}
+
+static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta,
+ struct ieee80211_key_conf *key_conf)
+{
+ struct wl1271 *wl = hw->priv;
+ const u8 *addr;
+ int ret;
+ u8 key_type;
+
+ static const u8 bcast_addr[ETH_ALEN] =
+ { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+
+ wl1271_debug(DEBUG_MAC80211, "mac80211 set key");
+
+ addr = sta ? sta->addr : bcast_addr;
+
+ wl1271_debug(DEBUG_CRYPT, "CMD: 0x%x", cmd);
+ wl1271_dump(DEBUG_CRYPT, "ADDR: ", addr, ETH_ALEN);
+ wl1271_debug(DEBUG_CRYPT, "Key: algo:0x%x, id:%d, len:%d flags 0x%x",
+ key_conf->alg, key_conf->keyidx,
+ key_conf->keylen, key_conf->flags);
+ wl1271_dump(DEBUG_CRYPT, "KEY: ", key_conf->key, key_conf->keylen);
+
+ if (is_zero_ether_addr(addr)) {
+ /* We dont support TX only encryption */
+ ret = -EOPNOTSUPP;
+ goto out;
+ }
+
+ mutex_lock(&wl->mutex);
+
+ ret = wl1271_ps_elp_wakeup(wl, false);
+ if (ret < 0)
+ goto out_unlock;
+
+ switch (key_conf->alg) {
+ case ALG_WEP:
+ key_type = KEY_WEP;
+
+ key_conf->hw_key_idx = key_conf->keyidx;
+ break;
+ case ALG_TKIP:
+ key_type = KEY_TKIP;
+
+ key_conf->hw_key_idx = key_conf->keyidx;
+ break;
+ case ALG_CCMP:
+ key_type = KEY_AES;
+
+ key_conf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
+ break;
+ default:
+ wl1271_error("Unknown key algo 0x%x", key_conf->alg);
+
+ ret = -EOPNOTSUPP;
+ goto out_sleep;
+ }
+
+ switch (cmd) {
+ case SET_KEY:
+ ret = wl1271_cmd_set_key(wl, KEY_ADD_OR_REPLACE,
+ key_conf->keyidx, key_type,
+ key_conf->keylen, key_conf->key,
+ addr);
+ if (ret < 0) {
+ wl1271_error("Could not add or replace key");
+ goto out_sleep;
+ }
+ break;
+
+ case DISABLE_KEY:
+ ret = wl1271_cmd_set_key(wl, KEY_REMOVE,
+ key_conf->keyidx, key_type,
+ key_conf->keylen, key_conf->key,
+ addr);
+ if (ret < 0) {
+ wl1271_error("Could not remove key");
+ goto out_sleep;
+ }
+ break;
+
+ default:
+ wl1271_error("Unsupported key cmd 0x%x", cmd);
+ ret = -EOPNOTSUPP;
+ goto out_sleep;
+
+ break;
+ }
+
+out_sleep:
+ wl1271_ps_elp_sleep(wl);
+
+out_unlock:
+ mutex_unlock(&wl->mutex);
+
+out:
+ return ret;
+}
+
+static int wl1271_op_hw_scan(struct ieee80211_hw *hw,
+ struct cfg80211_scan_request *req)
+{
+ struct wl1271 *wl = hw->priv;
+ int ret;
+ u8 *ssid = NULL;
+ size_t ssid_len = 0;
+
+ wl1271_debug(DEBUG_MAC80211, "mac80211 hw scan");
+
+ if (req->n_ssids) {
+ ssid = req->ssids[0].ssid;
+ ssid_len = req->ssids[0].ssid_len;
+ }
+
+ mutex_lock(&wl->mutex);
+
+ ret = wl1271_ps_elp_wakeup(wl, false);
+ if (ret < 0)
+ goto out;
+
+ ret = wl1271_cmd_scan(hw->priv, ssid, ssid_len, 1, 0, 13, 3);
+
+ wl1271_ps_elp_sleep(wl);
+
+out:
+ mutex_unlock(&wl->mutex);
+
+ return ret;
+}
+
+static int wl1271_op_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
+{
+ struct wl1271 *wl = hw->priv;
+ int ret;
+
+ mutex_lock(&wl->mutex);
+
+ ret = wl1271_ps_elp_wakeup(wl, false);
+ if (ret < 0)
+ goto out;
+
+ ret = wl1271_acx_rts_threshold(wl, (u16) value);
+ if (ret < 0)
+ wl1271_warning("wl1271_op_set_rts_threshold failed: %d", ret);
+
+ wl1271_ps_elp_sleep(wl);
+
+out:
+ mutex_unlock(&wl->mutex);
+
+ return ret;
+}
+
+static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_bss_conf *bss_conf,
+ u32 changed)
+{
+ enum wl1271_cmd_ps_mode mode;
+ struct wl1271 *wl = hw->priv;
+ int ret;
+
+ wl1271_debug(DEBUG_MAC80211, "mac80211 bss info changed");
+
+ mutex_lock(&wl->mutex);
+
+ ret = wl1271_ps_elp_wakeup(wl, false);
+ if (ret < 0)
+ goto out;
+
+ if (changed & BSS_CHANGED_ASSOC) {
+ if (bss_conf->assoc) {
+ wl->aid = bss_conf->aid;
+
+ ret = wl1271_cmd_build_ps_poll(wl, wl->aid);
+ if (ret < 0)
+ goto out_sleep;
+
+ ret = wl1271_acx_aid(wl, wl->aid);
+ if (ret < 0)
+ goto out_sleep;
+
+ /* If we want to go in PSM but we're not there yet */
+ if (wl->psm_requested && !wl->psm) {
+ mode = STATION_POWER_SAVE_MODE;
+ ret = wl1271_ps_set_mode(wl, mode);
+ if (ret < 0)
+ goto out_sleep;
+ }
+ }
+ }
+ if (changed & BSS_CHANGED_ERP_SLOT) {
+ if (bss_conf->use_short_slot)
+ ret = wl1271_acx_slot(wl, SLOT_TIME_SHORT);
+ else
+ ret = wl1271_acx_slot(wl, SLOT_TIME_LONG);
+ if (ret < 0) {
+ wl1271_warning("Set slot time failed %d", ret);
+ goto out_sleep;
+ }
+ }
+
+ if (changed & BSS_CHANGED_ERP_PREAMBLE) {
+ if (bss_conf->use_short_preamble)
+ wl1271_acx_set_preamble(wl, ACX_PREAMBLE_SHORT);
+ else
+ wl1271_acx_set_preamble(wl, ACX_PREAMBLE_LONG);
+ }
+
+ if (changed & BSS_CHANGED_ERP_CTS_PROT) {
+ if (bss_conf->use_cts_prot)
+ ret = wl1271_acx_cts_protect(wl, CTSPROTECT_ENABLE);
+ else
+ ret = wl1271_acx_cts_protect(wl, CTSPROTECT_DISABLE);
+ if (ret < 0) {
+ wl1271_warning("Set ctsprotect failed %d", ret);
+ goto out_sleep;
+ }
+ }
+
+out_sleep:
+ wl1271_ps_elp_sleep(wl);
+
+out:
+ mutex_unlock(&wl->mutex);
+}
+
+
+/* can't be const, mac80211 writes to this */
+static struct ieee80211_rate wl1271_rates[] = {
+ { .bitrate = 10,
+ .hw_value = 0x1,
+ .hw_value_short = 0x1, },
+ { .bitrate = 20,
+ .hw_value = 0x2,
+ .hw_value_short = 0x2,
+ .flags = IEEE80211_RATE_SHORT_PREAMBLE },
+ { .bitrate = 55,
+ .hw_value = 0x4,
+ .hw_value_short = 0x4,
+ .flags = IEEE80211_RATE_SHORT_PREAMBLE },
+ { .bitrate = 110,
+ .hw_value = 0x20,
+ .hw_value_short = 0x20,
+ .flags = IEEE80211_RATE_SHORT_PREAMBLE },
+ { .bitrate = 60,
+ .hw_value = 0x8,
+ .hw_value_short = 0x8, },
+ { .bitrate = 90,
+ .hw_value = 0x10,
+ .hw_value_short = 0x10, },
+ { .bitrate = 120,
+ .hw_value = 0x40,
+ .hw_value_short = 0x40, },
+ { .bitrate = 180,
+ .hw_value = 0x80,
+ .hw_value_short = 0x80, },
+ { .bitrate = 240,
+ .hw_value = 0x200,
+ .hw_value_short = 0x200, },
+ { .bitrate = 360,
+ .hw_value = 0x400,
+ .hw_value_short = 0x400, },
+ { .bitrate = 480,
+ .hw_value = 0x800,
+ .hw_value_short = 0x800, },
+ { .bitrate = 540,
+ .hw_value = 0x1000,
+ .hw_value_short = 0x1000, },
+};
+
+/* can't be const, mac80211 writes to this */
+static struct ieee80211_channel wl1271_channels[] = {
+ { .hw_value = 1, .center_freq = 2412},
+ { .hw_value = 2, .center_freq = 2417},
+ { .hw_value = 3, .center_freq = 2422},
+ { .hw_value = 4, .center_freq = 2427},
+ { .hw_value = 5, .center_freq = 2432},
+ { .hw_value = 6, .center_freq = 2437},
+ { .hw_value = 7, .center_freq = 2442},
+ { .hw_value = 8, .center_freq = 2447},
+ { .hw_value = 9, .center_freq = 2452},
+ { .hw_value = 10, .center_freq = 2457},
+ { .hw_value = 11, .center_freq = 2462},
+ { .hw_value = 12, .center_freq = 2467},
+ { .hw_value = 13, .center_freq = 2472},
+};
+
+/* can't be const, mac80211 writes to this */
+static struct ieee80211_supported_band wl1271_band_2ghz = {
+ .channels = wl1271_channels,
+ .n_channels = ARRAY_SIZE(wl1271_channels),
+ .bitrates = wl1271_rates,
+ .n_bitrates = ARRAY_SIZE(wl1271_rates),
+};
+
+static const struct ieee80211_ops wl1271_ops = {
+ .start = wl1271_op_start,
+ .stop = wl1271_op_stop,
+ .add_interface = wl1271_op_add_interface,
+ .remove_interface = wl1271_op_remove_interface,
+ .config = wl1271_op_config,
+/* .config_interface = wl1271_op_config_interface, */
+ .configure_filter = wl1271_op_configure_filter,
+ .tx = wl1271_op_tx,
+ .set_key = wl1271_op_set_key,
+ .hw_scan = wl1271_op_hw_scan,
+ .bss_info_changed = wl1271_op_bss_info_changed,
+ .set_rts_threshold = wl1271_op_set_rts_threshold,
+};
+
+static int wl1271_register_hw(struct wl1271 *wl)
+{
+ int ret;
+
+ if (wl->mac80211_registered)
+ return 0;
+
+ SET_IEEE80211_PERM_ADDR(wl->hw, wl->mac_addr);
+
+ ret = ieee80211_register_hw(wl->hw);
+ if (ret < 0) {
+ wl1271_error("unable to register mac80211 hw: %d", ret);
+ return ret;
+ }
+
+ wl->mac80211_registered = true;
+
+ wl1271_notice("loaded");
+
+ return 0;
+}
+
+static int wl1271_init_ieee80211(struct wl1271 *wl)
+{
+ /*
+ * The tx descriptor buffer and the TKIP space.
+ *
+ * FIXME: add correct 1271 descriptor size
+ */
+ wl->hw->extra_tx_headroom = WL1271_TKIP_IV_SPACE;
+
+ /* unit us */
+ /* FIXME: find a proper value */
+ wl->hw->channel_change_time = 10000;
+
+ wl->hw->flags = IEEE80211_HW_SIGNAL_DBM |
+ IEEE80211_HW_NOISE_DBM;
+
+ wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
+ wl->hw->wiphy->max_scan_ssids = 1;
+ wl->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &wl1271_band_2ghz;
+
+ SET_IEEE80211_DEV(wl->hw, &wl->spi->dev);
+
+ return 0;
+}
+
+static void wl1271_device_release(struct device *dev)
+{
+
+}
+
+static struct platform_device wl1271_device = {
+ .name = "wl1271",
+ .id = -1,
+
+ /* device model insists to have a release function */
+ .dev = {
+ .release = wl1271_device_release,
+ },
+};
+
+#define WL1271_DEFAULT_CHANNEL 0
+static int __devinit wl1271_probe(struct spi_device *spi)
+{
+ struct wl12xx_platform_data *pdata;
+ struct ieee80211_hw *hw;
+ struct wl1271 *wl;
+ int ret, i;
+ static const u8 nokia_oui[3] = {0x00, 0x1f, 0xdf};
+
+ pdata = spi->dev.platform_data;
+ if (!pdata) {
+ wl1271_error("no platform data");
+ return -ENODEV;
+ }
+
+ hw = ieee80211_alloc_hw(sizeof(*wl), &wl1271_ops);
+ if (!hw) {
+ wl1271_error("could not alloc ieee80211_hw");
+ return -ENOMEM;
+ }
+
+ wl = hw->priv;
+ memset(wl, 0, sizeof(*wl));
+
+ wl->hw = hw;
+ dev_set_drvdata(&spi->dev, wl);
+ wl->spi = spi;
+
+ skb_queue_head_init(&wl->tx_queue);
+
+ INIT_WORK(&wl->filter_work, wl1271_filter_work);
+ wl->channel = WL1271_DEFAULT_CHANNEL;
+ wl->scanning = false;
+ wl->default_key = 0;
+ wl->listen_int = 1;
+ wl->rx_counter = 0;
+ wl->rx_config = WL1271_DEFAULT_RX_CONFIG;
+ wl->rx_filter = WL1271_DEFAULT_RX_FILTER;
+ wl->elp = false;
+ wl->psm = 0;
+ wl->psm_requested = false;
+ wl->tx_queue_stopped = false;
+ wl->power_level = WL1271_DEFAULT_POWER_LEVEL;
+
+ /* We use the default power on sleep time until we know which chip
+ * we're using */
+ for (i = 0; i < FW_TX_CMPLT_BLOCK_SIZE; i++)
+ wl->tx_frames[i] = NULL;
+
+ spin_lock_init(&wl->wl_lock);
+
+ /*
+ * In case our MAC address is not correctly set,
+ * we use a random but Nokia MAC.
+ */
+ memcpy(wl->mac_addr, nokia_oui, 3);
+ get_random_bytes(wl->mac_addr + 3, 3);
+
+ wl->state = WL1271_STATE_OFF;
+ mutex_init(&wl->mutex);
+
+ wl->rx_descriptor = kmalloc(sizeof(*wl->rx_descriptor), GFP_KERNEL);
+ if (!wl->rx_descriptor) {
+ wl1271_error("could not allocate memory for rx descriptor");
+ ret = -ENOMEM;
+ goto out_free;
+ }
+
+ /* This is the only SPI value that we need to set here, the rest
+ * comes from the board-peripherals file */
+ spi->bits_per_word = 32;
+
+ ret = spi_setup(spi);
+ if (ret < 0) {
+ wl1271_error("spi_setup failed");
+ goto out_free;
+ }
+
+ wl->set_power = pdata->set_power;
+ if (!wl->set_power) {
+ wl1271_error("set power function missing in platform data");
+ ret = -ENODEV;
+ goto out_free;
+ }
+
+ wl->irq = spi->irq;
+ if (wl->irq < 0) {
+ wl1271_error("irq missing in platform data");
+ ret = -ENODEV;
+ goto out_free;
+ }
+
+ ret = request_irq(wl->irq, wl1271_irq, 0, DRIVER_NAME, wl);
+ if (ret < 0) {
+ wl1271_error("request_irq() failed: %d", ret);
+ goto out_free;
+ }
+
+ set_irq_type(wl->irq, IRQ_TYPE_EDGE_RISING);
+
+ disable_irq(wl->irq);
+
+ ret = platform_device_register(&wl1271_device);
+ if (ret) {
+ wl1271_error("couldn't register platform device");
+ goto out_irq;
+ }
+ dev_set_drvdata(&wl1271_device.dev, wl);
+
+ ret = wl1271_init_ieee80211(wl);
+ if (ret)
+ goto out_platform;
+
+ ret = wl1271_register_hw(wl);
+ if (ret)
+ goto out_platform;
+
+ wl1271_debugfs_init(wl);
+
+ wl1271_notice("initialized");
+
+ return 0;
+
+ out_platform:
+ platform_device_unregister(&wl1271_device);
+
+ out_irq:
+ free_irq(wl->irq, wl);
+
+ out_free:
+ kfree(wl->rx_descriptor);
+ wl->rx_descriptor = NULL;
+
+ ieee80211_free_hw(hw);
+
+ return ret;
+}
+
+static int __devexit wl1271_remove(struct spi_device *spi)
+{
+ struct wl1271 *wl = dev_get_drvdata(&spi->dev);
+
+ ieee80211_unregister_hw(wl->hw);
+
+ wl1271_debugfs_exit(wl);
+ platform_device_unregister(&wl1271_device);
+ free_irq(wl->irq, wl);
+ kfree(wl->target_mem_map);
+ kfree(wl->fw);
+ wl->fw = NULL;
+ kfree(wl->nvs);
+ wl->nvs = NULL;
+
+ kfree(wl->rx_descriptor);
+ wl->rx_descriptor = NULL;
+
+ kfree(wl->fw_status);
+ kfree(wl->tx_res_if);
+
+ ieee80211_free_hw(wl->hw);
+
+ return 0;
+}
+
+
+static struct spi_driver wl1271_spi_driver = {
+ .driver = {
+ .name = "wl1271",
+ .bus = &spi_bus_type,
+ .owner = THIS_MODULE,
+ },
+
+ .probe = wl1271_probe,
+ .remove = __devexit_p(wl1271_remove),
+};
+
+static int __init wl1271_init(void)
+{
+ int ret;
+
+ ret = spi_register_driver(&wl1271_spi_driver);
+ if (ret < 0) {
+ wl1271_error("failed to register spi driver: %d", ret);
+ goto out;
+ }
+
+out:
+ return ret;
+}
+
+static void __exit wl1271_exit(void)
+{
+ spi_unregister_driver(&wl1271_spi_driver);
+
+ wl1271_notice("unloaded");
+}
+
+module_init(wl1271_init);
+module_exit(wl1271_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Luciano Coelho <luciano.coelho@nokia.com>");
diff --git a/drivers/net/wireless/wl12xx/wl1271_ps.c b/drivers/net/wireless/wl12xx/wl1271_ps.c
new file mode 100644
index 00000000000..1dc74b0c773
--- /dev/null
+++ b/drivers/net/wireless/wl12xx/wl1271_ps.c
@@ -0,0 +1,142 @@
+/*
+ * This file is part of wl1271
+ *
+ * Copyright (C) 2008-2009 Nokia Corporation
+ *
+ * Contact: Luciano Coelho <luciano.coelho@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include "wl1271_reg.h"
+#include "wl1271_ps.h"
+#include "wl1271_spi.h"
+
+#define WL1271_WAKEUP_TIMEOUT 500
+
+/* Routines to toggle sleep mode while in ELP */
+void wl1271_ps_elp_sleep(struct wl1271 *wl)
+{
+ /*
+ * FIXME: due to a problem in the firmware (causing a firmware
+ * crash), ELP entry is prevented below. Remove the "true" to
+ * re-enable ELP entry.
+ */
+ if (true || wl->elp || !wl->psm)
+ return;
+
+ /*
+ * Go to ELP unless there is work already pending - pending work
+ * will immediately wakeup the chipset anyway.
+ */
+ if (!work_pending(&wl->irq_work) && !work_pending(&wl->tx_work)) {
+ wl1271_debug(DEBUG_PSM, "chip to elp");
+ wl1271_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, ELPCTRL_SLEEP);
+ wl->elp = true;
+ }
+}
+
+int wl1271_ps_elp_wakeup(struct wl1271 *wl, bool chip_awake)
+{
+ DECLARE_COMPLETION_ONSTACK(compl);
+ unsigned long flags;
+ int ret;
+ u32 start_time = jiffies;
+ bool pending = false;
+
+ if (!wl->elp)
+ return 0;
+
+ wl1271_debug(DEBUG_PSM, "waking up chip from elp");
+
+ /*
+ * The spinlock is required here to synchronize both the work and
+ * the completion variable in one entity.
+ */
+ spin_lock_irqsave(&wl->wl_lock, flags);
+ if (work_pending(&wl->irq_work) || chip_awake)
+ pending = true;
+ else
+ wl->elp_compl = &compl;
+ spin_unlock_irqrestore(&wl->wl_lock, flags);
+
+ wl1271_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, ELPCTRL_WAKE_UP);
+
+ if (!pending) {
+ ret = wait_for_completion_timeout(
+ &compl, msecs_to_jiffies(WL1271_WAKEUP_TIMEOUT));
+ if (ret == 0) {
+ wl1271_error("ELP wakeup timeout!");
+ ret = -ETIMEDOUT;
+ goto err;
+ } else if (ret < 0) {
+ wl1271_error("ELP wakeup completion error.");
+ goto err;
+ }
+ }
+
+ wl->elp = false;
+
+ wl1271_debug(DEBUG_PSM, "wakeup time: %u ms",
+ jiffies_to_msecs(jiffies - start_time));
+ goto out;
+
+err:
+ spin_lock_irqsave(&wl->wl_lock, flags);
+ wl->elp_compl = NULL;
+ spin_unlock_irqrestore(&wl->wl_lock, flags);
+ return ret;
+
+out:
+ return 0;
+}
+
+int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode)
+{
+ int ret;
+
+ switch (mode) {
+ case STATION_POWER_SAVE_MODE:
+ wl1271_debug(DEBUG_PSM, "entering psm");
+ ret = wl1271_cmd_ps_mode(wl, STATION_POWER_SAVE_MODE);
+ if (ret < 0)
+ return ret;
+
+ wl1271_ps_elp_sleep(wl);
+ if (ret < 0)
+ return ret;
+
+ wl->psm = 1;
+ break;
+ case STATION_ACTIVE_MODE:
+ default:
+ wl1271_debug(DEBUG_PSM, "leaving psm");
+ ret = wl1271_ps_elp_wakeup(wl, false);
+ if (ret < 0)
+ return ret;
+
+ ret = wl1271_cmd_ps_mode(wl, STATION_ACTIVE_MODE);
+ if (ret < 0)
+ return ret;
+
+ wl->psm = 0;
+ break;
+ }
+
+ return ret;
+}
+
+
diff --git a/drivers/net/wireless/wl12xx/wl1271_ps.h b/drivers/net/wireless/wl12xx/wl1271_ps.h
new file mode 100644
index 00000000000..de2bd3c7dc9
--- /dev/null
+++ b/drivers/net/wireless/wl12xx/wl1271_ps.h
@@ -0,0 +1,35 @@
+/*
+ * This file is part of wl1271
+ *
+ * Copyright (C) 2008-2009 Nokia Corporation
+ *
+ * Contact: Luciano Coelho <luciano.coelho@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef __WL1271_PS_H__
+#define __WL1271_PS_H__
+
+#include "wl1271.h"
+#include "wl1271_acx.h"
+
+int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode);
+void wl1271_ps_elp_sleep(struct wl1271 *wl);
+int wl1271_ps_elp_wakeup(struct wl1271 *wl, bool chip_awake);
+
+
+#endif /* __WL1271_PS_H__ */
diff --git a/drivers/net/wireless/wl12xx/reg.h b/drivers/net/wireless/wl12xx/wl1271_reg.h
index e421643215c..f8ed4a4fc69 100644
--- a/drivers/net/wireless/wl12xx/reg.h
+++ b/drivers/net/wireless/wl12xx/wl1271_reg.h
@@ -1,10 +1,10 @@
/*
* This file is part of wl12xx
*
- * Copyright (c) 1998-2007 Texas Instruments Incorporated
- * Copyright (C) 2008 Nokia Corporation
+ * Copyright (C) 1998-2009 Texas Instruments. All rights reserved.
+ * Copyright (C) 2009 Nokia Corporation
*
- * Contact: Kalle Valo <kalle.valo@nokia.com>
+ * Contact: Luciano Coelho <luciano.coelho@nokia.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -26,7 +26,6 @@
#define __REG_H__
#include <linux/bitops.h>
-#include "wl12xx.h"
#define REGISTERS_BASE 0x00300000
#define DRPW_BASE 0x00310000
@@ -35,6 +34,7 @@
#define REGISTERS_WORK_SIZE 0x0000b000
#define HW_ACCESS_ELP_CTRL_REG_ADDR 0x1FFFC
+#define STATUS_MEM_ADDRESS 0x40400
/* ELP register commands */
#define ELPCTRL_WAKE_UP 0x1
@@ -43,6 +43,25 @@
/* ELP WLAN_READY bit */
#define ELPCTRL_WLAN_READY 0x2
+/*===============================================
+ Host Software Reset - 32bit RW
+ ------------------------------------------
+ [31:1] Reserved
+ 0 SOFT_RESET Soft Reset - When this bit is set,
+ it holds the Wlan hardware in a soft reset state.
+ This reset disables all MAC and baseband processor
+ clocks except the CardBus/PCI interface clock.
+ It also initializes all MAC state machines except
+ the host interface. It does not reload the
+ contents of the EEPROM. When this bit is cleared
+ (not self-clearing), the Wlan hardware
+ exits the software reset state.
+===============================================*/
+#define ACX_REG_SLV_SOFT_RESET (REGISTERS_BASE + 0x0000)
+
+#define WL1271_SLV_REG_DATA (REGISTERS_BASE + 0x0008)
+#define WL1271_SLV_REG_ADATA (REGISTERS_BASE + 0x000c)
+#define WL1271_SLV_MEM_DATA (REGISTERS_BASE + 0x0018)
/*
* Interrupt registers.
* 64 bit interrupt sources registers ws ced.
@@ -96,6 +115,9 @@
#define HOST_MASK_CLR_L (REGISTERS_BASE + 0x0440)
#define HOST_MASK_CLR_H (REGISTERS_BASE + 0x0444)
+#define ACX_REG_INTERRUPT_TRIG (REGISTERS_BASE + 0x0474)
+#define ACX_REG_INTERRUPT_TRIG_H (REGISTERS_BASE + 0x0478)
+
/* Host Interrupts*/
#define HINT_MASK (REGISTERS_BASE + 0x0494)
#define HINT_MASK_SET (REGISTERS_BASE + 0x0498)
@@ -107,67 +129,6 @@
#define HINT_ACK (REGISTERS_BASE + 0x04A8)
#define HINT_TRIG (REGISTERS_BASE + 0x04AC)
-/* Device Configuration registers*/
-#define SOR_CFG (REGISTERS_BASE + 0x0800)
-#define ECPU_CTRL (REGISTERS_BASE + 0x0804)
-#define HI_CFG (REGISTERS_BASE + 0x0808)
-#define EE_START (REGISTERS_BASE + 0x080C)
-
-#define CHIP_ID_B (REGISTERS_BASE + 0x5674)
-
-#define CHIP_ID_1251_PG10 (0x7010101)
-#define CHIP_ID_1251_PG11 (0x7020101)
-#define CHIP_ID_1251_PG12 (0x7030101)
-
-#define ENABLE (REGISTERS_BASE + 0x5450)
-
-/* Power Management registers */
-#define ELP_CFG_MODE (REGISTERS_BASE + 0x5804)
-#define ELP_CMD (REGISTERS_BASE + 0x5808)
-#define PLL_CAL_TIME (REGISTERS_BASE + 0x5810)
-#define CLK_REQ_TIME (REGISTERS_BASE + 0x5814)
-#define CLK_BUF_TIME (REGISTERS_BASE + 0x5818)
-
-#define CFG_PLL_SYNC_CNT (REGISTERS_BASE + 0x5820)
-
-/* Scratch Pad registers*/
-#define SCR_PAD0 (REGISTERS_BASE + 0x5608)
-#define SCR_PAD1 (REGISTERS_BASE + 0x560C)
-#define SCR_PAD2 (REGISTERS_BASE + 0x5610)
-#define SCR_PAD3 (REGISTERS_BASE + 0x5614)
-#define SCR_PAD4 (REGISTERS_BASE + 0x5618)
-#define SCR_PAD4_SET (REGISTERS_BASE + 0x561C)
-#define SCR_PAD4_CLR (REGISTERS_BASE + 0x5620)
-#define SCR_PAD5 (REGISTERS_BASE + 0x5624)
-#define SCR_PAD5_SET (REGISTERS_BASE + 0x5628)
-#define SCR_PAD5_CLR (REGISTERS_BASE + 0x562C)
-#define SCR_PAD6 (REGISTERS_BASE + 0x5630)
-#define SCR_PAD7 (REGISTERS_BASE + 0x5634)
-#define SCR_PAD8 (REGISTERS_BASE + 0x5638)
-#define SCR_PAD9 (REGISTERS_BASE + 0x563C)
-
-/* Spare registers*/
-#define SPARE_A1 (REGISTERS_BASE + 0x0994)
-#define SPARE_A2 (REGISTERS_BASE + 0x0998)
-#define SPARE_A3 (REGISTERS_BASE + 0x099C)
-#define SPARE_A4 (REGISTERS_BASE + 0x09A0)
-#define SPARE_A5 (REGISTERS_BASE + 0x09A4)
-#define SPARE_A6 (REGISTERS_BASE + 0x09A8)
-#define SPARE_A7 (REGISTERS_BASE + 0x09AC)
-#define SPARE_A8 (REGISTERS_BASE + 0x09B0)
-#define SPARE_B1 (REGISTERS_BASE + 0x5420)
-#define SPARE_B2 (REGISTERS_BASE + 0x5424)
-#define SPARE_B3 (REGISTERS_BASE + 0x5428)
-#define SPARE_B4 (REGISTERS_BASE + 0x542C)
-#define SPARE_B5 (REGISTERS_BASE + 0x5430)
-#define SPARE_B6 (REGISTERS_BASE + 0x5434)
-#define SPARE_B7 (REGISTERS_BASE + 0x5438)
-#define SPARE_B8 (REGISTERS_BASE + 0x543C)
-
-enum wl12xx_acx_int_reg {
- ACX_REG_INTERRUPT_TRIG,
- ACX_REG_INTERRUPT_TRIG_H,
-
/*=============================================
Host Interrupt Mask Register - 32bit (RW)
------------------------------------------
@@ -196,7 +157,7 @@ enum wl12xx_acx_int_reg {
21- -
Default: 0x0001
*==============================================*/
- ACX_REG_INTERRUPT_MASK,
+#define ACX_REG_INTERRUPT_MASK (REGISTERS_BASE + 0x04DC)
/*=============================================
Host Interrupt Mask Set 16bit, (Write only)
@@ -206,7 +167,7 @@ enum wl12xx_acx_int_reg {
without effecting the mask
state of other bits (0 = no effect).
==============================================*/
- ACX_REG_HINT_MASK_SET,
+#define ACX_REG_HINT_MASK_SET (REGISTERS_BASE + 0x04E0)
/*=============================================
Host Interrupt Mask Clear 16bit,(Write only)
@@ -216,7 +177,7 @@ enum wl12xx_acx_int_reg {
without effecting the mask
state of other bits (0 = no effect).
=============================================*/
- ACX_REG_HINT_MASK_CLR,
+#define ACX_REG_HINT_MASK_CLR (REGISTERS_BASE + 0x04E4)
/*=============================================
Host Interrupt Status Nondestructive Read
@@ -227,7 +188,7 @@ enum wl12xx_acx_int_reg {
Reading this register doesn't
effect its content.
=============================================*/
- ACX_REG_INTERRUPT_NO_CLEAR,
+#define ACX_REG_INTERRUPT_NO_CLEAR (REGISTERS_BASE + 0x04E8)
/*=============================================
Host Interrupt Status Clear on Read Register
@@ -238,7 +199,7 @@ enum wl12xx_acx_int_reg {
Reading this register clears it,
thus making all interrupts inactive.
==============================================*/
- ACX_REG_INTERRUPT_CLEAR,
+#define ACX_REG_INTERRUPT_CLEAR (REGISTERS_BASE + 0x04F8)
/*=============================================
Host Interrupt Acknowledge Register
@@ -250,40 +211,13 @@ enum wl12xx_acx_int_reg {
HINT_STS_ND registers, thus making the
assotiated interrupt inactive. (0-no effect)
==============================================*/
- ACX_REG_INTERRUPT_ACK,
+#define ACX_REG_INTERRUPT_ACK (REGISTERS_BASE + 0x04F0)
-/*===============================================
- Host Software Reset - 32bit RW
- ------------------------------------------
- [31:1] Reserved
- 0 SOFT_RESET Soft Reset - When this bit is set,
- it holds the Wlan hardware in a soft reset state.
- This reset disables all MAC and baseband processor
- clocks except the CardBus/PCI interface clock.
- It also initializes all MAC state machines except
- the host interface. It does not reload the
- contents of the EEPROM. When this bit is cleared
- (not self-clearing), the Wlan hardware
- exits the software reset state.
-===============================================*/
- ACX_REG_SLV_SOFT_RESET,
-
-/*===============================================
- EEPROM Burst Read Start - 32bit RW
- ------------------------------------------
- [31:1] Reserved
- 0 ACX_EE_START - EEPROM Burst Read Start 0
- Setting this bit starts a burst read from
- the external EEPROM.
- If this bit is set (after reset) before an EEPROM read/write,
- the burst read starts at EEPROM address 0.
- Otherwise, it starts at the address
- following the address of the previous access.
- TheWlan hardware hardware clears this bit automatically.
+#define RX_DRIVER_DUMMY_WRITE_ADDRESS (REGISTERS_BASE + 0x0534)
+#define RX_DRIVER_COUNTER_ADDRESS (REGISTERS_BASE + 0x0538)
- Default: 0x00000000
-*================================================*/
- ACX_REG_EE_START,
+/* Device Configuration registers*/
+#define SOR_CFG (REGISTERS_BASE + 0x0800)
/* Embedded ARM CPU Control */
@@ -305,10 +239,89 @@ enum wl12xx_acx_int_reg {
1 halt eCPU
0 enable eCPU
===============================================*/
- ACX_REG_ECPU_CONTROL,
+#define ACX_REG_ECPU_CONTROL (REGISTERS_BASE + 0x0804)
+
+#define HI_CFG (REGISTERS_BASE + 0x0808)
+
+/*===============================================
+ EEPROM Burst Read Start - 32bit RW
+ ------------------------------------------
+ [31:1] Reserved
+ 0 ACX_EE_START - EEPROM Burst Read Start 0
+ Setting this bit starts a burst read from
+ the external EEPROM.
+ If this bit is set (after reset) before an EEPROM read/write,
+ the burst read starts at EEPROM address 0.
+ Otherwise, it starts at the address
+ following the address of the previous access.
+ TheWlan hardware hardware clears this bit automatically.
+
+ Default: 0x00000000
+*================================================*/
+#define ACX_REG_EE_START (REGISTERS_BASE + 0x080C)
+
+#define OCP_POR_CTR (REGISTERS_BASE + 0x09B4)
+#define OCP_DATA_WRITE (REGISTERS_BASE + 0x09B8)
+#define OCP_DATA_READ (REGISTERS_BASE + 0x09BC)
+#define OCP_CMD (REGISTERS_BASE + 0x09C0)
+
+#define WL1271_HOST_WR_ACCESS (REGISTERS_BASE + 0x09F8)
+
+#define CHIP_ID_B (REGISTERS_BASE + 0x5674)
+
+#define CHIP_ID_1271_PG10 (0x4030101)
+#define CHIP_ID_1271_PG20 (0x4030111)
+
+#define ENABLE (REGISTERS_BASE + 0x5450)
+
+/* Power Management registers */
+#define ELP_CFG_MODE (REGISTERS_BASE + 0x5804)
+#define ELP_CMD (REGISTERS_BASE + 0x5808)
+#define PLL_CAL_TIME (REGISTERS_BASE + 0x5810)
+#define CLK_REQ_TIME (REGISTERS_BASE + 0x5814)
+#define CLK_BUF_TIME (REGISTERS_BASE + 0x5818)
+
+#define CFG_PLL_SYNC_CNT (REGISTERS_BASE + 0x5820)
+
+/* Scratch Pad registers*/
+#define SCR_PAD0 (REGISTERS_BASE + 0x5608)
+#define SCR_PAD1 (REGISTERS_BASE + 0x560C)
+#define SCR_PAD2 (REGISTERS_BASE + 0x5610)
+#define SCR_PAD3 (REGISTERS_BASE + 0x5614)
+#define SCR_PAD4 (REGISTERS_BASE + 0x5618)
+#define SCR_PAD4_SET (REGISTERS_BASE + 0x561C)
+#define SCR_PAD4_CLR (REGISTERS_BASE + 0x5620)
+#define SCR_PAD5 (REGISTERS_BASE + 0x5624)
+#define SCR_PAD5_SET (REGISTERS_BASE + 0x5628)
+#define SCR_PAD5_CLR (REGISTERS_BASE + 0x562C)
+#define SCR_PAD6 (REGISTERS_BASE + 0x5630)
+#define SCR_PAD7 (REGISTERS_BASE + 0x5634)
+#define SCR_PAD8 (REGISTERS_BASE + 0x5638)
+#define SCR_PAD9 (REGISTERS_BASE + 0x563C)
+
+/* Spare registers*/
+#define SPARE_A1 (REGISTERS_BASE + 0x0994)
+#define SPARE_A2 (REGISTERS_BASE + 0x0998)
+#define SPARE_A3 (REGISTERS_BASE + 0x099C)
+#define SPARE_A4 (REGISTERS_BASE + 0x09A0)
+#define SPARE_A5 (REGISTERS_BASE + 0x09A4)
+#define SPARE_A6 (REGISTERS_BASE + 0x09A8)
+#define SPARE_A7 (REGISTERS_BASE + 0x09AC)
+#define SPARE_A8 (REGISTERS_BASE + 0x09B0)
+#define SPARE_B1 (REGISTERS_BASE + 0x5420)
+#define SPARE_B2 (REGISTERS_BASE + 0x5424)
+#define SPARE_B3 (REGISTERS_BASE + 0x5428)
+#define SPARE_B4 (REGISTERS_BASE + 0x542C)
+#define SPARE_B5 (REGISTERS_BASE + 0x5430)
+#define SPARE_B6 (REGISTERS_BASE + 0x5434)
+#define SPARE_B7 (REGISTERS_BASE + 0x5438)
+#define SPARE_B8 (REGISTERS_BASE + 0x543C)
+
+#define PLL_PARAMETERS (REGISTERS_BASE + 0x6040)
+#define WU_COUNTER_PAUSE (REGISTERS_BASE + 0x6008)
+#define WELP_ARM_COMMAND (REGISTERS_BASE + 0x6100)
+#define DRPW_SCRATCH_START (DRPW_BASE + 0x002C)
- ACX_REG_TABLE_LEN
-};
#define ACX_SLV_SOFT_RESET_BIT BIT(1)
#define ACX_REG_EEPROM_START_BIT BIT(1)
diff --git a/drivers/net/wireless/wl12xx/wl1271_rx.c b/drivers/net/wireless/wl12xx/wl1271_rx.c
new file mode 100644
index 00000000000..ad8b6904c5e
--- /dev/null
+++ b/drivers/net/wireless/wl12xx/wl1271_rx.c
@@ -0,0 +1,200 @@
+/*
+ * This file is part of wl1271
+ *
+ * Copyright (C) 2009 Nokia Corporation
+ *
+ * Contact: Luciano Coelho <luciano.coelho@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include "wl1271.h"
+#include "wl1271_acx.h"
+#include "wl1271_reg.h"
+#include "wl1271_rx.h"
+#include "wl1271_spi.h"
+
+static u8 wl1271_rx_get_mem_block(struct wl1271_fw_status *status,
+ u32 drv_rx_counter)
+{
+ return status->rx_pkt_descs[drv_rx_counter] & RX_MEM_BLOCK_MASK;
+}
+
+static u32 wl1271_rx_get_buf_size(struct wl1271_fw_status *status,
+ u32 drv_rx_counter)
+{
+ return (status->rx_pkt_descs[drv_rx_counter] & RX_BUF_SIZE_MASK) >>
+ RX_BUF_SIZE_SHIFT_DIV;
+}
+
+/* The values of this table must match the wl1271_rates[] array */
+static u8 wl1271_rx_rate_to_idx[] = {
+ /* MCS rates are used only with 11n */
+ WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS7 */
+ WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS6 */
+ WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS5 */
+ WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS4 */
+ WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS3 */
+ WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS2 */
+ WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS1 */
+ WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS0 */
+
+ 11, /* WL1271_RATE_54 */
+ 10, /* WL1271_RATE_48 */
+ 9, /* WL1271_RATE_36 */
+ 8, /* WL1271_RATE_24 */
+
+ /* TI-specific rate */
+ WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_22 */
+
+ 7, /* WL1271_RATE_18 */
+ 6, /* WL1271_RATE_12 */
+ 3, /* WL1271_RATE_11 */
+ 5, /* WL1271_RATE_9 */
+ 4, /* WL1271_RATE_6 */
+ 2, /* WL1271_RATE_5_5 */
+ 1, /* WL1271_RATE_2 */
+ 0 /* WL1271_RATE_1 */
+};
+
+static void wl1271_rx_status(struct wl1271 *wl,
+ struct wl1271_rx_descriptor *desc,
+ struct ieee80211_rx_status *status,
+ u8 beacon)
+{
+ memset(status, 0, sizeof(struct ieee80211_rx_status));
+
+ if ((desc->flags & WL1271_RX_DESC_BAND_MASK) == WL1271_RX_DESC_BAND_BG)
+ status->band = IEEE80211_BAND_2GHZ;
+ else
+ wl1271_warning("unsupported band 0x%x",
+ desc->flags & WL1271_RX_DESC_BAND_MASK);
+
+ /*
+ * FIXME: Add mactime handling. For IBSS (ad-hoc) we need to get the
+ * timestamp from the beacon (acx_tsf_info). In BSS mode (infra) we
+ * only need the mactime for monitor mode. For now the mactime is
+ * not valid, so RX_FLAG_TSFT should not be set
+ */
+ status->signal = desc->rssi;
+
+ /* FIXME: Should this be optimized? */
+ status->qual = (desc->rssi - WL1271_RX_MIN_RSSI) * 100 /
+ (WL1271_RX_MAX_RSSI - WL1271_RX_MIN_RSSI);
+ status->qual = min(status->qual, 100);
+ status->qual = max(status->qual, 0);
+
+ /*
+ * FIXME: In wl1251, the SNR should be divided by two. In wl1271 we
+ * need to divide by two for now, but TI has been discussing about
+ * changing it. This needs to be rechecked.
+ */
+ status->noise = desc->rssi - (desc->snr >> 1);
+
+ status->freq = ieee80211_channel_to_frequency(desc->channel);
+
+ if (desc->flags & WL1271_RX_DESC_ENCRYPT_MASK) {
+ status->flag |= RX_FLAG_IV_STRIPPED | RX_FLAG_MMIC_STRIPPED;
+
+ if (likely(!(desc->flags & WL1271_RX_DESC_DECRYPT_FAIL)))
+ status->flag |= RX_FLAG_DECRYPTED;
+
+ if (unlikely(desc->flags & WL1271_RX_DESC_MIC_FAIL))
+ status->flag |= RX_FLAG_MMIC_ERROR;
+ }
+
+ status->rate_idx = wl1271_rx_rate_to_idx[desc->rate];
+
+ if (status->rate_idx == WL1271_RX_RATE_UNSUPPORTED)
+ wl1271_warning("unsupported rate");
+}
+
+static void wl1271_rx_handle_data(struct wl1271 *wl, u32 length)
+{
+ struct ieee80211_rx_status rx_status;
+ struct wl1271_rx_descriptor *desc;
+ struct sk_buff *skb;
+ u16 *fc;
+ u8 *buf;
+ u8 beacon = 0;
+
+ skb = dev_alloc_skb(length);
+ if (!skb) {
+ wl1271_error("Couldn't allocate RX frame");
+ return;
+ }
+
+ buf = skb_put(skb, length);
+ wl1271_spi_reg_read(wl, WL1271_SLV_MEM_DATA, buf, length, true);
+
+ /* the data read starts with the descriptor */
+ desc = (struct wl1271_rx_descriptor *) buf;
+
+ /* now we pull the descriptor out of the buffer */
+ skb_pull(skb, sizeof(*desc));
+
+ fc = (u16 *)skb->data;
+ if ((*fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_BEACON)
+ beacon = 1;
+
+ wl1271_rx_status(wl, desc, &rx_status, beacon);
+
+ wl1271_debug(DEBUG_RX, "rx skb 0x%p: %d B %s", skb, skb->len,
+ beacon ? "beacon" : "");
+
+ memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status));
+ ieee80211_rx(wl->hw, skb);
+}
+
+void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_status *status)
+{
+ struct wl1271_acx_mem_map *wl_mem_map = wl->target_mem_map;
+ u32 buf_size;
+ u32 fw_rx_counter = status->fw_rx_counter & NUM_RX_PKT_DESC_MOD_MASK;
+ u32 drv_rx_counter = wl->rx_counter & NUM_RX_PKT_DESC_MOD_MASK;
+ u32 mem_block;
+
+ while (drv_rx_counter != fw_rx_counter) {
+ mem_block = wl1271_rx_get_mem_block(status, drv_rx_counter);
+ buf_size = wl1271_rx_get_buf_size(status, drv_rx_counter);
+
+ if (buf_size == 0) {
+ wl1271_warning("received empty data");
+ break;
+ }
+
+ wl->rx_mem_pool_addr.addr =
+ (mem_block << 8) + wl_mem_map->packet_memory_pool_start;
+ wl->rx_mem_pool_addr.addr_extra =
+ wl->rx_mem_pool_addr.addr + 4;
+
+ /* Choose the block we want to read */
+ wl1271_spi_reg_write(wl, WL1271_SLV_REG_DATA,
+ &wl->rx_mem_pool_addr,
+ sizeof(wl->rx_mem_pool_addr), false);
+
+ wl1271_rx_handle_data(wl, buf_size);
+
+ wl->rx_counter++;
+ drv_rx_counter = wl->rx_counter & NUM_RX_PKT_DESC_MOD_MASK;
+ }
+
+ wl1271_reg_write32(wl, RX_DRIVER_COUNTER_ADDRESS, wl->rx_counter);
+
+ /* This is a workaround for some problems in the chip */
+ wl1271_reg_write32(wl, RX_DRIVER_DUMMY_WRITE_ADDRESS, 0x1);
+
+}
diff --git a/drivers/net/wireless/wl12xx/wl1271_rx.h b/drivers/net/wireless/wl12xx/wl1271_rx.h
new file mode 100644
index 00000000000..d1ca60e43a2
--- /dev/null
+++ b/drivers/net/wireless/wl12xx/wl1271_rx.h
@@ -0,0 +1,121 @@
+/*
+ * This file is part of wl1271
+ *
+ * Copyright (C) 1998-2009 Texas Instruments. All rights reserved.
+ * Copyright (C) 2008-2009 Nokia Corporation
+ *
+ * Contact: Luciano Coelho <luciano.coelho@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef __WL1271_RX_H__
+#define __WL1271_RX_H__
+
+#include <linux/bitops.h>
+
+#define WL1271_RX_MAX_RSSI -30
+#define WL1271_RX_MIN_RSSI -95
+
+#define WL1271_RX_ALIGN_TO 4
+#define WL1271_RX_ALIGN(len) (((len) + WL1271_RX_ALIGN_TO - 1) & \
+ ~(WL1271_RX_ALIGN_TO - 1))
+
+#define SHORT_PREAMBLE_BIT BIT(0)
+#define OFDM_RATE_BIT BIT(6)
+#define PBCC_RATE_BIT BIT(7)
+
+#define PLCP_HEADER_LENGTH 8
+#define RX_DESC_PACKETID_SHIFT 11
+#define RX_MAX_PACKET_ID 3
+
+#define NUM_RX_PKT_DESC_MOD_MASK 7
+#define WL1271_RX_RATE_UNSUPPORTED 0xFF
+
+#define RX_DESC_VALID_FCS 0x0001
+#define RX_DESC_MATCH_RXADDR1 0x0002
+#define RX_DESC_MCAST 0x0004
+#define RX_DESC_STAINTIM 0x0008
+#define RX_DESC_VIRTUAL_BM 0x0010
+#define RX_DESC_BCAST 0x0020
+#define RX_DESC_MATCH_SSID 0x0040
+#define RX_DESC_MATCH_BSSID 0x0080
+#define RX_DESC_ENCRYPTION_MASK 0x0300
+#define RX_DESC_MEASURMENT 0x0400
+#define RX_DESC_SEQNUM_MASK 0x1800
+#define RX_DESC_MIC_FAIL 0x2000
+#define RX_DESC_DECRYPT_FAIL 0x4000
+
+/*
+ * RX Descriptor flags:
+ *
+ * Bits 0-1 - band
+ * Bit 2 - STBC
+ * Bit 3 - A-MPDU
+ * Bit 4 - HT
+ * Bits 5-7 - encryption
+ */
+#define WL1271_RX_DESC_BAND_MASK 0x03
+#define WL1271_RX_DESC_ENCRYPT_MASK 0xE0
+
+#define WL1271_RX_DESC_BAND_BG 0x00
+#define WL1271_RX_DESC_BAND_J 0x01
+#define WL1271_RX_DESC_BAND_A 0x02
+
+#define WL1271_RX_DESC_STBC BIT(2)
+#define WL1271_RX_DESC_A_MPDU BIT(3)
+#define WL1271_RX_DESC_HT BIT(4)
+
+#define WL1271_RX_DESC_ENCRYPT_WEP 0x20
+#define WL1271_RX_DESC_ENCRYPT_TKIP 0x40
+#define WL1271_RX_DESC_ENCRYPT_AES 0x60
+#define WL1271_RX_DESC_ENCRYPT_GEM 0x80
+
+/*
+ * RX Descriptor status
+ *
+ * Bits 0-2 - status
+ * Bits 3-7 - reserved
+ */
+#define WL1271_RX_DESC_STATUS_MASK 0x07
+
+#define WL1271_RX_DESC_SUCCESS 0x00
+#define WL1271_RX_DESC_DECRYPT_FAIL 0x01
+#define WL1271_RX_DESC_MIC_FAIL 0x02
+#define WL1271_RX_DESC_DRIVER_RX_Q_FAIL 0x03
+
+#define RX_MEM_BLOCK_MASK 0xFF
+#define RX_BUF_SIZE_MASK 0xFFF00
+#define RX_BUF_SIZE_SHIFT_DIV 6
+
+struct wl1271_rx_descriptor {
+ u16 length;
+ u8 status;
+ u8 flags;
+ u8 rate;
+ u8 channel;
+ s8 rssi;
+ u8 snr;
+ u32 timestamp;
+ u8 packet_class;
+ u8 process_id;
+ u8 pad_len;
+ u8 reserved;
+} __attribute__ ((packed));
+
+void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_status *status);
+
+#endif
diff --git a/drivers/net/wireless/wl12xx/spi.c b/drivers/net/wireless/wl12xx/wl1271_spi.c
index abdf171a47e..4a12880c16a 100644
--- a/drivers/net/wireless/wl12xx/spi.c
+++ b/drivers/net/wireless/wl12xx/wl1271_spi.c
@@ -1,9 +1,9 @@
/*
- * This file is part of wl12xx
+ * This file is part of wl1271
*
- * Copyright (C) 2008 Nokia Corporation
+ * Copyright (C) 2008-2009 Nokia Corporation
*
- * Contact: Kalle Valo <kalle.valo@nokia.com>
+ * Contact: Luciano Coelho <luciano.coelho@nokia.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -22,39 +22,26 @@
*/
#include <linux/module.h>
+#include <linux/platform_device.h>
#include <linux/crc7.h>
#include <linux/spi/spi.h>
-#include "wl12xx.h"
+#include "wl1271.h"
#include "wl12xx_80211.h"
-#include "reg.h"
-#include "spi.h"
-#include "ps.h"
+#include "wl1271_spi.h"
-static int wl12xx_translate_reg_addr(struct wl12xx *wl, int addr)
+static int wl1271_translate_reg_addr(struct wl1271 *wl, int addr)
{
- /* If the address is lower than REGISTERS_BASE, it means that this is
- * a chip-specific register address, so look it up in the registers
- * table */
- if (addr < REGISTERS_BASE) {
- /* Make sure we don't go over the table */
- if (addr >= ACX_REG_TABLE_LEN) {
- wl12xx_error("address out of range (%d)", addr);
- return -EINVAL;
- }
- addr = wl->chip.acx_reg_table[addr];
- }
-
return addr - wl->physical_reg_addr + wl->virtual_reg_addr;
}
-static int wl12xx_translate_mem_addr(struct wl12xx *wl, int addr)
+static int wl1271_translate_mem_addr(struct wl1271 *wl, int addr)
{
return addr - wl->physical_mem_addr + wl->virtual_mem_addr;
}
-void wl12xx_spi_reset(struct wl12xx *wl)
+void wl1271_spi_reset(struct wl1271 *wl)
{
u8 *cmd;
struct spi_transfer t;
@@ -62,7 +49,7 @@ void wl12xx_spi_reset(struct wl12xx *wl)
cmd = kzalloc(WSPI_INIT_CMD_LEN, GFP_KERNEL);
if (!cmd) {
- wl12xx_error("could not allocate cmd for spi reset");
+ wl1271_error("could not allocate cmd for spi reset");
return;
}
@@ -77,10 +64,10 @@ void wl12xx_spi_reset(struct wl12xx *wl)
spi_sync(wl->spi, &m);
- wl12xx_dump(DEBUG_SPI, "spi reset -> ", cmd, WSPI_INIT_CMD_LEN);
+ wl1271_dump(DEBUG_SPI, "spi reset -> ", cmd, WSPI_INIT_CMD_LEN);
}
-void wl12xx_spi_init(struct wl12xx *wl)
+void wl1271_spi_init(struct wl1271 *wl)
{
u8 crc[WSPI_INIT_CMD_CRC_LEN], *cmd;
struct spi_transfer t;
@@ -88,7 +75,7 @@ void wl12xx_spi_init(struct wl12xx *wl)
cmd = kzalloc(WSPI_INIT_CMD_LEN, GFP_KERNEL);
if (!cmd) {
- wl12xx_error("could not allocate cmd for spi init");
+ wl1271_error("could not allocate cmd for spi init");
return;
}
@@ -131,7 +118,7 @@ void wl12xx_spi_init(struct wl12xx *wl)
spi_sync(wl->spi, &m);
- wl12xx_dump(DEBUG_SPI, "spi init -> ", cmd, WSPI_INIT_CMD_LEN);
+ wl1271_dump(DEBUG_SPI, "spi init -> ", cmd, WSPI_INIT_CMD_LEN);
}
/* Set the SPI partitions to access the chip addresses
@@ -167,45 +154,47 @@ void wl12xx_spi_init(struct wl12xx *wl)
* | |
*
*/
-void wl12xx_set_partition(struct wl12xx *wl,
+int wl1271_set_partition(struct wl1271 *wl,
u32 mem_start, u32 mem_size,
u32 reg_start, u32 reg_size)
{
- u8 tx_buf[sizeof(u32) + 2 * sizeof(struct wl12xx_partition)];
- struct wl12xx_partition *partition;
+ struct wl1271_partition *partition;
struct spi_transfer t;
struct spi_message m;
+ size_t len, cmd_len;
u32 *cmd;
- size_t len;
int addr;
+ cmd_len = sizeof(u32) + 2 * sizeof(struct wl1271_partition);
+ cmd = kzalloc(cmd_len, GFP_KERNEL);
+ if (!cmd)
+ return -ENOMEM;
+
spi_message_init(&m);
memset(&t, 0, sizeof(t));
- memset(tx_buf, 0, sizeof(tx_buf));
- cmd = (u32 *) tx_buf;
- partition = (struct wl12xx_partition *) (tx_buf + sizeof(u32));
+ partition = (struct wl1271_partition *) (cmd + 1);
addr = HW_ACCESS_PART0_SIZE_ADDR;
- len = 2 * sizeof(struct wl12xx_partition);
+ len = 2 * sizeof(struct wl1271_partition);
*cmd |= WSPI_CMD_WRITE;
*cmd |= (len << WSPI_CMD_BYTE_LENGTH_OFFSET) & WSPI_CMD_BYTE_LENGTH;
*cmd |= addr & WSPI_CMD_BYTE_ADDR;
- wl12xx_debug(DEBUG_SPI, "mem_start %08X mem_size %08X",
+ wl1271_debug(DEBUG_SPI, "mem_start %08X mem_size %08X",
mem_start, mem_size);
- wl12xx_debug(DEBUG_SPI, "reg_start %08X reg_size %08X",
+ wl1271_debug(DEBUG_SPI, "reg_start %08X reg_size %08X",
reg_start, reg_size);
/* Make sure that the two partitions together don't exceed the
* address range */
if ((mem_size + reg_size) > HW_ACCESS_MEMORY_MAX_RANGE) {
- wl12xx_debug(DEBUG_SPI, "Total size exceeds maximum virtual"
+ wl1271_debug(DEBUG_SPI, "Total size exceeds maximum virtual"
" address range. Truncating partition[0].");
mem_size = HW_ACCESS_MEMORY_MAX_RANGE - reg_size;
- wl12xx_debug(DEBUG_SPI, "mem_start %08X mem_size %08X",
+ wl1271_debug(DEBUG_SPI, "mem_start %08X mem_size %08X",
mem_start, mem_size);
- wl12xx_debug(DEBUG_SPI, "reg_start %08X reg_size %08X",
+ wl1271_debug(DEBUG_SPI, "reg_start %08X reg_size %08X",
reg_start, reg_size);
}
@@ -213,23 +202,23 @@ void wl12xx_set_partition(struct wl12xx *wl,
((mem_start + mem_size) > reg_start)) {
/* Guarantee that the memory partition doesn't overlap the
* registers partition */
- wl12xx_debug(DEBUG_SPI, "End of partition[0] is "
+ wl1271_debug(DEBUG_SPI, "End of partition[0] is "
"overlapping partition[1]. Adjusted.");
mem_size = reg_start - mem_start;
- wl12xx_debug(DEBUG_SPI, "mem_start %08X mem_size %08X",
+ wl1271_debug(DEBUG_SPI, "mem_start %08X mem_size %08X",
mem_start, mem_size);
- wl12xx_debug(DEBUG_SPI, "reg_start %08X reg_size %08X",
+ wl1271_debug(DEBUG_SPI, "reg_start %08X reg_size %08X",
reg_start, reg_size);
} else if ((reg_start < mem_start) &&
((reg_start + reg_size) > mem_start)) {
/* Guarantee that the register partition doesn't overlap the
* memory partition */
- wl12xx_debug(DEBUG_SPI, "End of partition[1] is"
+ wl1271_debug(DEBUG_SPI, "End of partition[1] is"
" overlapping partition[0]. Adjusted.");
reg_size = mem_start - reg_start;
- wl12xx_debug(DEBUG_SPI, "mem_start %08X mem_size %08X",
+ wl1271_debug(DEBUG_SPI, "mem_start %08X mem_size %08X",
mem_start, mem_size);
- wl12xx_debug(DEBUG_SPI, "reg_start %08X reg_size %08X",
+ wl1271_debug(DEBUG_SPI, "reg_start %08X reg_size %08X",
reg_start, reg_size);
}
@@ -244,36 +233,46 @@ void wl12xx_set_partition(struct wl12xx *wl,
wl->virtual_mem_addr = 0;
wl->virtual_reg_addr = mem_size;
- t.tx_buf = tx_buf;
- t.len = sizeof(tx_buf);
+ t.tx_buf = cmd;
+ t.len = cmd_len;
spi_message_add_tail(&t, &m);
spi_sync(wl->spi, &m);
+
+ kfree(cmd);
+
+ return 0;
}
-void wl12xx_spi_read(struct wl12xx *wl, int addr, void *buf,
- size_t len)
+void wl1271_spi_read(struct wl1271 *wl, int addr, void *buf,
+ size_t len, bool fixed)
{
struct spi_transfer t[3];
struct spi_message m;
- char busy_buf[TNETWIF_READ_OFFSET_BYTES];
- u32 cmd;
+ u8 *busy_buf;
+ u32 *cmd;
- cmd = 0;
- cmd |= WSPI_CMD_READ;
- cmd |= (len << WSPI_CMD_BYTE_LENGTH_OFFSET) & WSPI_CMD_BYTE_LENGTH;
- cmd |= addr & WSPI_CMD_BYTE_ADDR;
+ cmd = &wl->buffer_cmd;
+ busy_buf = wl->buffer_busyword;
+
+ *cmd = 0;
+ *cmd |= WSPI_CMD_READ;
+ *cmd |= (len << WSPI_CMD_BYTE_LENGTH_OFFSET) & WSPI_CMD_BYTE_LENGTH;
+ *cmd |= addr & WSPI_CMD_BYTE_ADDR;
+
+ if (fixed)
+ *cmd |= WSPI_CMD_FIXED;
spi_message_init(&m);
memset(t, 0, sizeof(t));
- t[0].tx_buf = &cmd;
+ t[0].tx_buf = cmd;
t[0].len = 4;
spi_message_add_tail(&t[0], &m);
/* Busy and non busy words read */
t[1].rx_buf = busy_buf;
- t[1].len = TNETWIF_READ_OFFSET_BYTES;
+ t[1].len = WL1271_BUSY_WORD_LEN;
spi_message_add_tail(&t[1], &m);
t[2].rx_buf = buf;
@@ -284,27 +283,32 @@ void wl12xx_spi_read(struct wl12xx *wl, int addr, void *buf,
/* FIXME: check busy words */
- wl12xx_dump(DEBUG_SPI, "spi_read cmd -> ", &cmd, sizeof(cmd));
- wl12xx_dump(DEBUG_SPI, "spi_read buf <- ", buf, len);
+ wl1271_dump(DEBUG_SPI, "spi_read cmd -> ", cmd, sizeof(*cmd));
+ wl1271_dump(DEBUG_SPI, "spi_read buf <- ", buf, len);
}
-void wl12xx_spi_write(struct wl12xx *wl, int addr, void *buf,
- size_t len)
+void wl1271_spi_write(struct wl1271 *wl, int addr, void *buf,
+ size_t len, bool fixed)
{
struct spi_transfer t[2];
struct spi_message m;
- u32 cmd;
+ u32 *cmd;
- cmd = 0;
- cmd |= WSPI_CMD_WRITE;
- cmd |= (len << WSPI_CMD_BYTE_LENGTH_OFFSET) & WSPI_CMD_BYTE_LENGTH;
- cmd |= addr & WSPI_CMD_BYTE_ADDR;
+ cmd = &wl->buffer_cmd;
+
+ *cmd = 0;
+ *cmd |= WSPI_CMD_WRITE;
+ *cmd |= (len << WSPI_CMD_BYTE_LENGTH_OFFSET) & WSPI_CMD_BYTE_LENGTH;
+ *cmd |= addr & WSPI_CMD_BYTE_ADDR;
+
+ if (fixed)
+ *cmd |= WSPI_CMD_FIXED;
spi_message_init(&m);
memset(t, 0, sizeof(t));
- t[0].tx_buf = &cmd;
- t[0].len = sizeof(cmd);
+ t[0].tx_buf = cmd;
+ t[0].len = sizeof(*cmd);
spi_message_add_tail(&t[0], &m);
t[1].tx_buf = buf;
@@ -313,46 +317,66 @@ void wl12xx_spi_write(struct wl12xx *wl, int addr, void *buf,
spi_sync(wl->spi, &m);
- wl12xx_dump(DEBUG_SPI, "spi_write cmd -> ", &cmd, sizeof(cmd));
- wl12xx_dump(DEBUG_SPI, "spi_write buf -> ", buf, len);
+ wl1271_dump(DEBUG_SPI, "spi_write cmd -> ", cmd, sizeof(*cmd));
+ wl1271_dump(DEBUG_SPI, "spi_write buf -> ", buf, len);
}
-void wl12xx_spi_mem_read(struct wl12xx *wl, int addr, void *buf,
+void wl1271_spi_mem_read(struct wl1271 *wl, int addr, void *buf,
size_t len)
{
int physical;
- physical = wl12xx_translate_mem_addr(wl, addr);
+ physical = wl1271_translate_mem_addr(wl, addr);
- wl12xx_spi_read(wl, physical, buf, len);
+ wl1271_spi_read(wl, physical, buf, len, false);
}
-void wl12xx_spi_mem_write(struct wl12xx *wl, int addr, void *buf,
+void wl1271_spi_mem_write(struct wl1271 *wl, int addr, void *buf,
size_t len)
{
int physical;
- physical = wl12xx_translate_mem_addr(wl, addr);
+ physical = wl1271_translate_mem_addr(wl, addr);
+
+ wl1271_spi_write(wl, physical, buf, len, false);
+}
+
+void wl1271_spi_reg_read(struct wl1271 *wl, int addr, void *buf, size_t len,
+ bool fixed)
+{
+ int physical;
+
+ physical = wl1271_translate_reg_addr(wl, addr);
+
+ wl1271_spi_read(wl, physical, buf, len, fixed);
+}
+
+void wl1271_spi_reg_write(struct wl1271 *wl, int addr, void *buf, size_t len,
+ bool fixed)
+{
+ int physical;
+
+ physical = wl1271_translate_reg_addr(wl, addr);
- wl12xx_spi_write(wl, physical, buf, len);
+ wl1271_spi_write(wl, physical, buf, len, fixed);
}
-u32 wl12xx_mem_read32(struct wl12xx *wl, int addr)
+u32 wl1271_mem_read32(struct wl1271 *wl, int addr)
{
- return wl12xx_read32(wl, wl12xx_translate_mem_addr(wl, addr));
+ return wl1271_read32(wl, wl1271_translate_mem_addr(wl, addr));
}
-void wl12xx_mem_write32(struct wl12xx *wl, int addr, u32 val)
+void wl1271_mem_write32(struct wl1271 *wl, int addr, u32 val)
{
- wl12xx_write32(wl, wl12xx_translate_mem_addr(wl, addr), val);
+ wl1271_write32(wl, wl1271_translate_mem_addr(wl, addr), val);
}
-u32 wl12xx_reg_read32(struct wl12xx *wl, int addr)
+u32 wl1271_reg_read32(struct wl1271 *wl, int addr)
{
- return wl12xx_read32(wl, wl12xx_translate_reg_addr(wl, addr));
+ return wl1271_read32(wl, wl1271_translate_reg_addr(wl, addr));
}
-void wl12xx_reg_write32(struct wl12xx *wl, int addr, u32 val)
+void wl1271_reg_write32(struct wl1271 *wl, int addr, u32 val)
{
- wl12xx_write32(wl, wl12xx_translate_reg_addr(wl, addr), val);
+ wl1271_write32(wl, wl1271_translate_reg_addr(wl, addr), val);
}
diff --git a/drivers/net/wireless/wl12xx/spi.h b/drivers/net/wireless/wl12xx/wl1271_spi.h
index fd3227e904a..2c996845864 100644
--- a/drivers/net/wireless/wl12xx/spi.h
+++ b/drivers/net/wireless/wl12xx/wl1271_spi.h
@@ -1,10 +1,10 @@
/*
- * This file is part of wl12xx
+ * This file is part of wl1271
*
- * Copyright (c) 1998-2007 Texas Instruments Incorporated
- * Copyright (C) 2008 Nokia Corporation
+ * Copyright (C) 1998-2009 Texas Instruments. All rights reserved.
+ * Copyright (C) 2008-2009 Nokia Corporation
*
- * Contact: Kalle Valo <kalle.valo@nokia.com>
+ * Contact: Luciano Coelho <luciano.coelho@nokia.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -22,12 +22,10 @@
*
*/
-#ifndef __WL12XX_SPI_H__
-#define __WL12XX_SPI_H__
+#ifndef __WL1271_SPI_H__
+#define __WL1271_SPI_H__
-#include "cmd.h"
-#include "acx.h"
-#include "reg.h"
+#include "wl1271_reg.h"
#define HW_ACCESS_MEMORY_MAX_RANGE 0x1FFC0
@@ -65,45 +63,51 @@
#define WSPI_INIT_CMD_LEN 8
-#define TNETWIF_READ_OFFSET_BYTES 8
#define HW_ACCESS_WSPI_FIXED_BUSY_LEN \
- ((TNETWIF_READ_OFFSET_BYTES - 4) / sizeof(u32))
+ ((WL1271_BUSY_WORD_LEN - 4) / sizeof(u32))
#define HW_ACCESS_WSPI_INIT_CMD_MASK 0
/* Raw target IO, address is not translated */
-void wl12xx_spi_read(struct wl12xx *wl, int addr, void *buf, size_t len);
-void wl12xx_spi_write(struct wl12xx *wl, int addr, void *buf, size_t len);
+void wl1271_spi_write(struct wl1271 *wl, int addr, void *buf,
+ size_t len, bool fixed);
+void wl1271_spi_read(struct wl1271 *wl, int addr, void *buf,
+ size_t len, bool fixed);
/* Memory target IO, address is tranlated to partition 0 */
-void wl12xx_spi_mem_read(struct wl12xx *wl, int addr, void *buf, size_t len);
-void wl12xx_spi_mem_write(struct wl12xx *wl, int addr, void *buf, size_t len);
-u32 wl12xx_mem_read32(struct wl12xx *wl, int addr);
-void wl12xx_mem_write32(struct wl12xx *wl, int addr, u32 val);
+void wl1271_spi_mem_read(struct wl1271 *wl, int addr, void *buf, size_t len);
+void wl1271_spi_mem_write(struct wl1271 *wl, int addr, void *buf, size_t len);
+u32 wl1271_mem_read32(struct wl1271 *wl, int addr);
+void wl1271_mem_write32(struct wl1271 *wl, int addr, u32 val);
/* Registers IO */
-u32 wl12xx_reg_read32(struct wl12xx *wl, int addr);
-void wl12xx_reg_write32(struct wl12xx *wl, int addr, u32 val);
+void wl1271_spi_reg_read(struct wl1271 *wl, int addr, void *buf, size_t len,
+ bool fixed);
+void wl1271_spi_reg_write(struct wl1271 *wl, int addr, void *buf, size_t len,
+ bool fixed);
+u32 wl1271_reg_read32(struct wl1271 *wl, int addr);
+void wl1271_reg_write32(struct wl1271 *wl, int addr, u32 val);
/* INIT and RESET words */
-void wl12xx_spi_reset(struct wl12xx *wl);
-void wl12xx_spi_init(struct wl12xx *wl);
-void wl12xx_set_partition(struct wl12xx *wl,
- u32 part_start, u32 part_size,
- u32 reg_start, u32 reg_size);
+void wl1271_spi_reset(struct wl1271 *wl);
+void wl1271_spi_init(struct wl1271 *wl);
+int wl1271_set_partition(struct wl1271 *wl,
+ u32 part_start, u32 part_size,
+ u32 reg_start, u32 reg_size);
-static inline u32 wl12xx_read32(struct wl12xx *wl, int addr)
+static inline u32 wl1271_read32(struct wl1271 *wl, int addr)
{
- u32 response;
+ wl1271_spi_read(wl, addr, &wl->buffer_32,
+ sizeof(wl->buffer_32), false);
- wl12xx_spi_read(wl, addr, &response, sizeof(u32));
-
- return response;
+ return wl->buffer_32;
}
-static inline void wl12xx_write32(struct wl12xx *wl, int addr, u32 val)
+static inline void wl1271_write32(struct wl1271 *wl, int addr, u32 val)
{
- wl12xx_spi_write(wl, addr, &val, sizeof(u32));
+ wl->buffer_32 = val;
+ wl1271_spi_write(wl, addr, &wl->buffer_32,
+ sizeof(wl->buffer_32), false);
}
-#endif /* __WL12XX_SPI_H__ */
+#endif /* __WL1271_SPI_H__ */
diff --git a/drivers/net/wireless/wl12xx/wl1271_tx.c b/drivers/net/wireless/wl12xx/wl1271_tx.c
new file mode 100644
index 00000000000..ff221258b94
--- /dev/null
+++ b/drivers/net/wireless/wl12xx/wl1271_tx.c
@@ -0,0 +1,378 @@
+/*
+ * This file is part of wl1271
+ *
+ * Copyright (C) 2009 Nokia Corporation
+ *
+ * Contact: Luciano Coelho <luciano.coelho@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+
+#include "wl1271.h"
+#include "wl1271_spi.h"
+#include "wl1271_reg.h"
+#include "wl1271_ps.h"
+#include "wl1271_tx.h"
+
+static int wl1271_tx_id(struct wl1271 *wl, struct sk_buff *skb)
+{
+ int i;
+
+ for (i = 0; i < FW_TX_CMPLT_BLOCK_SIZE; i++)
+ if (wl->tx_frames[i] == NULL) {
+ wl->tx_frames[i] = skb;
+ return i;
+ }
+
+ return -EBUSY;
+}
+
+static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra)
+{
+ struct wl1271_tx_hw_descr *desc;
+ u32 total_len = skb->len + sizeof(struct wl1271_tx_hw_descr) + extra;
+ u32 total_blocks, excluded;
+ int id, ret = -EBUSY;
+
+ /* allocate free identifier for the packet */
+ id = wl1271_tx_id(wl, skb);
+ if (id < 0)
+ return id;
+
+ /* approximate the number of blocks required for this packet
+ in the firmware */
+ /* FIXME: try to figure out what is done here and make it cleaner */
+ total_blocks = (skb->len) >> TX_HW_BLOCK_SHIFT_DIV;
+ excluded = (total_blocks << 2) + (skb->len & 0xff) + 34;
+ total_blocks += (excluded > 252) ? 2 : 1;
+ total_blocks += TX_HW_BLOCK_SPARE;
+
+ if (total_blocks <= wl->tx_blocks_available) {
+ desc = (struct wl1271_tx_hw_descr *)skb_push(
+ skb, total_len - skb->len);
+
+ desc->extra_mem_blocks = TX_HW_BLOCK_SPARE;
+ desc->total_mem_blocks = total_blocks;
+ desc->id = id;
+
+ wl->tx_blocks_available -= total_blocks;
+
+ ret = 0;
+
+ wl1271_debug(DEBUG_TX,
+ "tx_allocate: size: %d, blocks: %d, id: %d",
+ total_len, total_blocks, id);
+ } else
+ wl->tx_frames[id] = NULL;
+
+ return ret;
+}
+
+static int wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb,
+ u32 extra, struct ieee80211_tx_info *control)
+{
+ struct wl1271_tx_hw_descr *desc;
+ int pad;
+
+ desc = (struct wl1271_tx_hw_descr *) skb->data;
+
+ /* configure packet life time */
+ desc->start_time = jiffies_to_usecs(jiffies) - wl->time_offset;
+ desc->life_time = TX_HW_MGMT_PKT_LIFETIME_TU;
+
+ /* configure the tx attributes */
+ desc->tx_attr = wl->session_counter << TX_HW_ATTR_OFST_SESSION_COUNTER;
+ /* FIXME: do we know the packet priority? can we identify mgmt
+ packets, and use max prio for them at least? */
+ desc->tid = 0;
+ desc->aid = TX_HW_DEFAULT_AID;
+ desc->reserved = 0;
+
+ /* align the length (and store in terms of words) */
+ pad = WL1271_TX_ALIGN(skb->len);
+ desc->length = pad >> 2;
+
+ /* calculate number of padding bytes */
+ pad = pad - skb->len;
+ desc->tx_attr |= pad << TX_HW_ATTR_OFST_LAST_WORD_PAD;
+
+ wl1271_debug(DEBUG_TX, "tx_fill_hdr: pad: %d", pad);
+ return 0;
+}
+
+static int wl1271_tx_send_packet(struct wl1271 *wl, struct sk_buff *skb,
+ struct ieee80211_tx_info *control)
+{
+
+ struct wl1271_tx_hw_descr *desc;
+ int len;
+
+ /* FIXME: This is a workaround for getting non-aligned packets.
+ This happens at least with EAPOL packets from the user space.
+ Our DMA requires packets to be aligned on a 4-byte boundary.
+ */
+ if (unlikely((long)skb->data & 0x03)) {
+ int offset = (4 - (long)skb->data) & 0x03;
+ wl1271_debug(DEBUG_TX, "skb offset %d", offset);
+
+ /* check whether the current skb can be used */
+ if (!skb_cloned(skb) && (skb_tailroom(skb) >= offset)) {
+ unsigned char *src = skb->data;
+
+ /* align the buffer on a 4-byte boundary */
+ skb_reserve(skb, offset);
+ memmove(skb->data, src, skb->len);
+ } else {
+ wl1271_info("No handler, fixme!");
+ return -EINVAL;
+ }
+ }
+
+ len = WL1271_TX_ALIGN(skb->len);
+
+ /* perform a fixed address block write with the packet */
+ wl1271_spi_reg_write(wl, WL1271_SLV_MEM_DATA, skb->data, len, true);
+
+ /* write packet new counter into the write access register */
+ wl->tx_packets_count++;
+ wl1271_reg_write32(wl, WL1271_HOST_WR_ACCESS, wl->tx_packets_count);
+
+ desc = (struct wl1271_tx_hw_descr *) skb->data;
+ wl1271_debug(DEBUG_TX, "tx id %u skb 0x%p payload %u (%u words)",
+ desc->id, skb, len, desc->length);
+
+ return 0;
+}
+
+/* caller must hold wl->mutex */
+static int wl1271_tx_frame(struct wl1271 *wl, struct sk_buff *skb)
+{
+ struct ieee80211_tx_info *info;
+ u32 extra = 0;
+ int ret = 0;
+ u8 idx;
+
+ if (!skb)
+ return -EINVAL;
+
+ info = IEEE80211_SKB_CB(skb);
+
+ if (info->control.hw_key &&
+ info->control.hw_key->alg == ALG_TKIP)
+ extra = WL1271_TKIP_IV_SPACE;
+
+ if (info->control.hw_key) {
+ idx = info->control.hw_key->hw_key_idx;
+
+ /* FIXME: do we have to do this if we're not using WEP? */
+ if (unlikely(wl->default_key != idx)) {
+ ret = wl1271_cmd_set_default_wep_key(wl, idx);
+ if (ret < 0)
+ return ret;
+ }
+ }
+
+ ret = wl1271_tx_allocate(wl, skb, extra);
+ if (ret < 0)
+ return ret;
+
+ ret = wl1271_tx_fill_hdr(wl, skb, extra, info);
+ if (ret < 0)
+ return ret;
+
+ ret = wl1271_tx_send_packet(wl, skb, info);
+ if (ret < 0)
+ return ret;
+
+ return ret;
+}
+
+void wl1271_tx_work(struct work_struct *work)
+{
+ struct wl1271 *wl = container_of(work, struct wl1271, tx_work);
+ struct sk_buff *skb;
+ bool woken_up = false;
+ int ret;
+
+ mutex_lock(&wl->mutex);
+
+ if (unlikely(wl->state == WL1271_STATE_OFF))
+ goto out;
+
+ while ((skb = skb_dequeue(&wl->tx_queue))) {
+ if (!woken_up) {
+ ret = wl1271_ps_elp_wakeup(wl, false);
+ if (ret < 0)
+ goto out;
+ woken_up = true;
+ }
+
+ ret = wl1271_tx_frame(wl, skb);
+ if (ret == -EBUSY) {
+ /* firmware buffer is full, stop queues */
+ wl1271_debug(DEBUG_TX, "tx_work: fw buffer full, "
+ "stop queues");
+ ieee80211_stop_queues(wl->hw);
+ wl->tx_queue_stopped = true;
+ skb_queue_head(&wl->tx_queue, skb);
+ goto out;
+ } else if (ret < 0) {
+ dev_kfree_skb(skb);
+ goto out;
+ } else if (wl->tx_queue_stopped) {
+ /* firmware buffer has space, restart queues */
+ wl1271_debug(DEBUG_TX,
+ "complete_packet: waking queues");
+ ieee80211_wake_queues(wl->hw);
+ wl->tx_queue_stopped = false;
+ }
+ }
+
+out:
+ if (woken_up)
+ wl1271_ps_elp_sleep(wl);
+
+ mutex_unlock(&wl->mutex);
+}
+
+static void wl1271_tx_complete_packet(struct wl1271 *wl,
+ struct wl1271_tx_hw_res_descr *result)
+{
+
+ struct ieee80211_tx_info *info;
+ struct sk_buff *skb;
+ u32 header_len;
+ int id = result->id;
+
+ /* check for id legality */
+ if (id >= TX_HW_RESULT_QUEUE_LEN || wl->tx_frames[id] == NULL) {
+ wl1271_warning("TX result illegal id: %d", id);
+ return;
+ }
+
+ skb = wl->tx_frames[id];
+ info = IEEE80211_SKB_CB(skb);
+
+ /* update packet status */
+ if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) {
+ if (result->status == TX_SUCCESS)
+ info->flags |= IEEE80211_TX_STAT_ACK;
+ if (result->status & TX_RETRY_EXCEEDED) {
+ /* FIXME */
+ /* info->status.excessive_retries = 1; */
+ wl->stats.excessive_retries++;
+ }
+ }
+
+ /* FIXME */
+ /* info->status.retry_count = result->ack_failures; */
+ wl->stats.retry_count += result->ack_failures;
+
+ /* get header len */
+ if (info->control.hw_key &&
+ info->control.hw_key->alg == ALG_TKIP)
+ header_len = WL1271_TKIP_IV_SPACE +
+ sizeof(struct wl1271_tx_hw_descr);
+ else
+ header_len = sizeof(struct wl1271_tx_hw_descr);
+
+ wl1271_debug(DEBUG_TX, "tx status id %u skb 0x%p failures %u rate 0x%x"
+ " status 0x%x",
+ result->id, skb, result->ack_failures,
+ result->rate_class_index, result->status);
+
+ /* remove private header from packet */
+ skb_pull(skb, header_len);
+
+ /* return the packet to the stack */
+ ieee80211_tx_status(wl->hw, skb);
+ wl->tx_frames[result->id] = NULL;
+}
+
+/* Called upon reception of a TX complete interrupt */
+void wl1271_tx_complete(struct wl1271 *wl, u32 count)
+{
+ struct wl1271_acx_mem_map *memmap =
+ (struct wl1271_acx_mem_map *)wl->target_mem_map;
+ u32 i;
+
+ wl1271_debug(DEBUG_TX, "tx_complete received, packets: %d", count);
+
+ /* read the tx results from the chipset */
+ wl1271_spi_mem_read(wl, memmap->tx_result,
+ wl->tx_res_if, sizeof(*wl->tx_res_if));
+
+ /* verify that the result buffer is not getting overrun */
+ if (count > TX_HW_RESULT_QUEUE_LEN) {
+ wl1271_warning("TX result overflow from chipset: %d", count);
+ count = TX_HW_RESULT_QUEUE_LEN;
+ }
+
+ /* process the results */
+ for (i = 0; i < count; i++) {
+ struct wl1271_tx_hw_res_descr *result;
+ u8 offset = wl->tx_results_count & TX_HW_RESULT_QUEUE_LEN_MASK;
+
+ /* process the packet */
+ result = &(wl->tx_res_if->tx_results_queue[offset]);
+ wl1271_tx_complete_packet(wl, result);
+
+ wl->tx_results_count++;
+ }
+
+ /* write host counter to chipset (to ack) */
+ wl1271_mem_write32(wl, memmap->tx_result +
+ offsetof(struct wl1271_tx_hw_res_if,
+ tx_result_host_counter),
+ wl->tx_res_if->tx_result_fw_counter);
+}
+
+/* caller must hold wl->mutex */
+void wl1271_tx_flush(struct wl1271 *wl)
+{
+ int i;
+ struct sk_buff *skb;
+ struct ieee80211_tx_info *info;
+
+ /* TX failure */
+/* control->flags = 0; FIXME */
+
+ while ((skb = skb_dequeue(&wl->tx_queue))) {
+ info = IEEE80211_SKB_CB(skb);
+
+ wl1271_debug(DEBUG_TX, "flushing skb 0x%p", skb);
+
+ if (!(info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS))
+ continue;
+
+ ieee80211_tx_status(wl->hw, skb);
+ }
+
+ for (i = 0; i < FW_TX_CMPLT_BLOCK_SIZE; i++)
+ if (wl->tx_frames[i] != NULL) {
+ skb = wl->tx_frames[i];
+ info = IEEE80211_SKB_CB(skb);
+
+ if (!(info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS))
+ continue;
+
+ ieee80211_tx_status(wl->hw, skb);
+ wl->tx_frames[i] = NULL;
+ }
+}
diff --git a/drivers/net/wireless/wl12xx/wl1271_tx.h b/drivers/net/wireless/wl12xx/wl1271_tx.h
new file mode 100644
index 00000000000..4a614067ddb
--- /dev/null
+++ b/drivers/net/wireless/wl12xx/wl1271_tx.h
@@ -0,0 +1,130 @@
+/*
+ * This file is part of wl1271
+ *
+ * Copyright (C) 1998-2009 Texas Instruments. All rights reserved.
+ * Copyright (C) 2009 Nokia Corporation
+ *
+ * Contact: Luciano Coelho <luciano.coelho@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef __WL1271_TX_H__
+#define __WL1271_TX_H__
+
+#define TX_HW_BLOCK_SPARE 2
+#define TX_HW_BLOCK_SHIFT_DIV 8
+
+#define TX_HW_MGMT_PKT_LIFETIME_TU 2000
+/* The chipset reference driver states, that the "aid" value 1
+ * is for infra-BSS, but is still always used */
+#define TX_HW_DEFAULT_AID 1
+
+#define TX_HW_ATTR_SAVE_RETRIES BIT(0)
+#define TX_HW_ATTR_HEADER_PAD BIT(1)
+#define TX_HW_ATTR_SESSION_COUNTER (BIT(2) | BIT(3) | BIT(4))
+#define TX_HW_ATTR_RATE_POLICY (BIT(5) | BIT(6) | BIT(7) | \
+ BIT(8) | BIT(9))
+#define TX_HW_ATTR_LAST_WORD_PAD (BIT(10) | BIT(11))
+#define TX_HW_ATTR_TX_CMPLT_REQ BIT(12)
+
+#define TX_HW_ATTR_OFST_SAVE_RETRIES 0
+#define TX_HW_ATTR_OFST_HEADER_PAD 1
+#define TX_HW_ATTR_OFST_SESSION_COUNTER 2
+#define TX_HW_ATTR_OFST_RATE_POLICY 5
+#define TX_HW_ATTR_OFST_LAST_WORD_PAD 10
+#define TX_HW_ATTR_OFST_TX_CMPLT_REQ 12
+
+#define TX_HW_RESULT_QUEUE_LEN 16
+#define TX_HW_RESULT_QUEUE_LEN_MASK 0xf
+
+#define WL1271_TX_ALIGN_TO 4
+#define WL1271_TX_ALIGN(len) (((len) + WL1271_TX_ALIGN_TO - 1) & \
+ ~(WL1271_TX_ALIGN_TO - 1))
+#define WL1271_TKIP_IV_SPACE 4
+
+struct wl1271_tx_hw_descr {
+ /* Length of packet in words, including descriptor+header+data */
+ u16 length;
+ /* Number of extra memory blocks to allocate for this packet in
+ addition to the number of blocks derived from the packet length */
+ u8 extra_mem_blocks;
+ /* Total number of memory blocks allocated by the host for this packet.
+ Must be equal or greater than the actual blocks number allocated by
+ HW!! */
+ u8 total_mem_blocks;
+ /* Device time (in us) when the packet arrived to the driver */
+ u32 start_time;
+ /* Max delay in TUs until transmission. The last device time the
+ packet can be transmitted is: startTime+(1024*LifeTime) */
+ u16 life_time;
+ /* Bitwise fields - see TX_ATTR... definitions above. */
+ u16 tx_attr;
+ /* Packet identifier used also in the Tx-Result. */
+ u8 id;
+ /* The packet TID value (as User-Priority) */
+ u8 tid;
+ /* Identifier of the remote STA in IBSS, 1 in infra-BSS */
+ u8 aid;
+ u8 reserved;
+} __attribute__ ((packed));
+
+enum wl1271_tx_hw_res_status {
+ TX_SUCCESS = 0,
+ TX_HW_ERROR = 1,
+ TX_DISABLED = 2,
+ TX_RETRY_EXCEEDED = 3,
+ TX_TIMEOUT = 4,
+ TX_KEY_NOT_FOUND = 5,
+ TX_PEER_NOT_FOUND = 6,
+ TX_SESSION_MISMATCH = 7
+};
+
+struct wl1271_tx_hw_res_descr {
+ /* Packet Identifier - same value used in the Tx descriptor.*/
+ u8 id;
+ /* The status of the transmission, indicating success or one of
+ several possible reasons for failure. */
+ u8 status;
+ /* Total air access duration including all retrys and overheads.*/
+ u16 medium_usage;
+ /* The time passed from host xfer to Tx-complete.*/
+ u32 fw_handling_time;
+ /* Total media delay
+ (from 1st EDCA AIFS counter until TX Complete). */
+ u32 medium_delay;
+ /* LS-byte of last TKIP seq-num (saved per AC for recovery). */
+ u8 lsb_security_sequence_number;
+ /* Retry count - number of transmissions without successful ACK.*/
+ u8 ack_failures;
+ /* The rate that succeeded getting ACK
+ (Valid only if status=SUCCESS). */
+ u8 rate_class_index;
+ /* for 4-byte alignment. */
+ u8 spare;
+} __attribute__ ((packed));
+
+struct wl1271_tx_hw_res_if {
+ u32 tx_result_fw_counter;
+ u32 tx_result_host_counter;
+ struct wl1271_tx_hw_res_descr tx_results_queue[TX_HW_RESULT_QUEUE_LEN];
+} __attribute__ ((packed));
+
+void wl1271_tx_work(struct work_struct *work);
+void wl1271_tx_complete(struct wl1271 *wl, u32 count);
+void wl1271_tx_flush(struct wl1271 *wl);
+
+#endif
diff --git a/drivers/net/wireless/wl3501_cs.c b/drivers/net/wireless/wl3501_cs.c
index e3e96bb2c24..a83a5621ec4 100644
--- a/drivers/net/wireless/wl3501_cs.c
+++ b/drivers/net/wireless/wl3501_cs.c
@@ -1348,7 +1348,6 @@ static int wl3501_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
if (rc) {
++dev->stats.tx_dropped;
netif_stop_queue(dev);
- rc = NETDEV_TX_OK;
} else {
++dev->stats.tx_packets;
dev->stats.tx_bytes += skb->len;
@@ -1358,7 +1357,7 @@ static int wl3501_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
netif_stop_queue(dev);
}
spin_unlock_irqrestore(&this->lock, flags);
- return rc;
+ return NETDEV_TX_OK;
}
static int wl3501_open(struct net_device *dev)
diff --git a/drivers/net/wireless/zd1201.c b/drivers/net/wireless/zd1201.c
index 4430b8d92e2..dae1bfb7655 100644
--- a/drivers/net/wireless/zd1201.c
+++ b/drivers/net/wireless/zd1201.c
@@ -789,7 +789,7 @@ static int zd1201_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
if (!zd->mac_enabled || zd->monitor) {
dev->stats.tx_dropped++;
kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
}
netif_stop_queue(dev);
@@ -826,7 +826,7 @@ static int zd1201_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
}
kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
}
static void zd1201_tx_timeout(struct net_device *dev)
diff --git a/drivers/net/wireless/zd1211rw/zd_chip.c b/drivers/net/wireless/zd1211rw/zd_chip.c
index 2c813d87092..5e110a2328a 100644
--- a/drivers/net/wireless/zd1211rw/zd_chip.c
+++ b/drivers/net/wireless/zd1211rw/zd_chip.c
@@ -1278,11 +1278,11 @@ int zd_chip_control_leds(struct zd_chip *chip, enum led_status status)
other_led = chip->link_led == LED1 ? LED2 : LED1;
switch (status) {
- case LED_OFF:
+ case ZD_LED_OFF:
ioreqs[0].value = FW_LINK_OFF;
ioreqs[1].value = v[1] & ~(LED1|LED2);
break;
- case LED_SCANNING:
+ case ZD_LED_SCANNING:
ioreqs[0].value = FW_LINK_OFF;
ioreqs[1].value = v[1] & ~other_led;
if (get_seconds() % 3 == 0) {
@@ -1291,7 +1291,7 @@ int zd_chip_control_leds(struct zd_chip *chip, enum led_status status)
ioreqs[1].value |= chip->link_led;
}
break;
- case LED_ASSOCIATED:
+ case ZD_LED_ASSOCIATED:
ioreqs[0].value = FW_LINK_TX;
ioreqs[1].value = v[1] & ~other_led;
ioreqs[1].value |= chip->link_led;
diff --git a/drivers/net/wireless/zd1211rw/zd_chip.h b/drivers/net/wireless/zd1211rw/zd_chip.h
index ee42751d5cb..678c139a840 100644
--- a/drivers/net/wireless/zd1211rw/zd_chip.h
+++ b/drivers/net/wireless/zd1211rw/zd_chip.h
@@ -897,9 +897,9 @@ int zd_chip_lock_phy_regs(struct zd_chip *chip);
int zd_chip_unlock_phy_regs(struct zd_chip *chip);
enum led_status {
- LED_OFF = 0,
- LED_SCANNING = 1,
- LED_ASSOCIATED = 2,
+ ZD_LED_OFF = 0,
+ ZD_LED_SCANNING = 1,
+ ZD_LED_ASSOCIATED = 2,
};
int zd_chip_control_leds(struct zd_chip *chip, enum led_status status);
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c
index 3bd3c779fff..55b7fbdc85d 100644
--- a/drivers/net/wireless/zd1211rw/zd_mac.c
+++ b/drivers/net/wireless/zd1211rw/zd_mac.c
@@ -711,7 +711,8 @@ int zd_mac_rx(struct ieee80211_hw *hw, const u8 *buffer, unsigned int length)
memcpy(skb_put(skb, length), buffer, length);
- ieee80211_rx_irqsafe(hw, skb, &stats);
+ memcpy(IEEE80211_SKB_RXCB(skb), &stats, sizeof(stats));
+ ieee80211_rx_irqsafe(hw, skb);
return 0;
}
@@ -1012,7 +1013,7 @@ static void link_led_handler(struct work_struct *work)
spin_unlock_irq(&mac->lock);
r = zd_chip_control_leds(chip,
- is_associated ? LED_ASSOCIATED : LED_SCANNING);
+ is_associated ? ZD_LED_ASSOCIATED : ZD_LED_SCANNING);
if (r)
dev_dbg_f(zd_mac_dev(mac), "zd_chip_control_leds error %d\n", r);
@@ -1037,5 +1038,5 @@ static void housekeeping_disable(struct zd_mac *mac)
dev_dbg_f(zd_mac_dev(mac), "\n");
cancel_rearming_delayed_workqueue(zd_workqueue,
&mac->housekeeping.link_led_work);
- zd_chip_control_leds(&mac->chip, LED_OFF);
+ zd_chip_control_leds(&mac->chip, ZD_LED_OFF);
}
diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c
index 0e6e44689cc..38688847d56 100644
--- a/drivers/net/wireless/zd1211rw/zd_usb.c
+++ b/drivers/net/wireless/zd1211rw/zd_usb.c
@@ -36,58 +36,60 @@
static struct usb_device_id usb_ids[] = {
/* ZD1211 */
+ { USB_DEVICE(0x0105, 0x145f), .driver_info = DEVICE_ZD1211 },
+ { USB_DEVICE(0x0586, 0x3401), .driver_info = DEVICE_ZD1211 },
+ { USB_DEVICE(0x0586, 0x3402), .driver_info = DEVICE_ZD1211 },
+ { USB_DEVICE(0x0586, 0x3407), .driver_info = DEVICE_ZD1211 },
+ { USB_DEVICE(0x0586, 0x3409), .driver_info = DEVICE_ZD1211 },
+ { USB_DEVICE(0x079b, 0x004a), .driver_info = DEVICE_ZD1211 },
+ { USB_DEVICE(0x07b8, 0x6001), .driver_info = DEVICE_ZD1211 },
{ USB_DEVICE(0x0ace, 0x1211), .driver_info = DEVICE_ZD1211 },
{ USB_DEVICE(0x0ace, 0xa211), .driver_info = DEVICE_ZD1211 },
- { USB_DEVICE(0x126f, 0xa006), .driver_info = DEVICE_ZD1211 },
- { USB_DEVICE(0x6891, 0xa727), .driver_info = DEVICE_ZD1211 },
+ { USB_DEVICE(0x0b05, 0x170c), .driver_info = DEVICE_ZD1211 },
+ { USB_DEVICE(0x0b3b, 0x1630), .driver_info = DEVICE_ZD1211 },
+ { USB_DEVICE(0x0b3b, 0x5630), .driver_info = DEVICE_ZD1211 },
{ USB_DEVICE(0x0df6, 0x9071), .driver_info = DEVICE_ZD1211 },
{ USB_DEVICE(0x0df6, 0x9075), .driver_info = DEVICE_ZD1211 },
- { USB_DEVICE(0x157e, 0x300b), .driver_info = DEVICE_ZD1211 },
- { USB_DEVICE(0x079b, 0x004a), .driver_info = DEVICE_ZD1211 },
- { USB_DEVICE(0x1740, 0x2000), .driver_info = DEVICE_ZD1211 },
- { USB_DEVICE(0x157e, 0x3204), .driver_info = DEVICE_ZD1211 },
- { USB_DEVICE(0x0586, 0x3402), .driver_info = DEVICE_ZD1211 },
- { USB_DEVICE(0x0b3b, 0x5630), .driver_info = DEVICE_ZD1211 },
- { USB_DEVICE(0x0b05, 0x170c), .driver_info = DEVICE_ZD1211 },
+ { USB_DEVICE(0x126f, 0xa006), .driver_info = DEVICE_ZD1211 },
+ { USB_DEVICE(0x129b, 0x1666), .driver_info = DEVICE_ZD1211 },
+ { USB_DEVICE(0x13b1, 0x001e), .driver_info = DEVICE_ZD1211 },
{ USB_DEVICE(0x1435, 0x0711), .driver_info = DEVICE_ZD1211 },
- { USB_DEVICE(0x0586, 0x3409), .driver_info = DEVICE_ZD1211 },
- { USB_DEVICE(0x0b3b, 0x1630), .driver_info = DEVICE_ZD1211 },
- { USB_DEVICE(0x0586, 0x3401), .driver_info = DEVICE_ZD1211 },
{ USB_DEVICE(0x14ea, 0xab13), .driver_info = DEVICE_ZD1211 },
- { USB_DEVICE(0x13b1, 0x001e), .driver_info = DEVICE_ZD1211 },
- { USB_DEVICE(0x0586, 0x3407), .driver_info = DEVICE_ZD1211 },
- { USB_DEVICE(0x129b, 0x1666), .driver_info = DEVICE_ZD1211 },
{ USB_DEVICE(0x157e, 0x300a), .driver_info = DEVICE_ZD1211 },
- { USB_DEVICE(0x0105, 0x145f), .driver_info = DEVICE_ZD1211 },
+ { USB_DEVICE(0x157e, 0x300b), .driver_info = DEVICE_ZD1211 },
+ { USB_DEVICE(0x157e, 0x3204), .driver_info = DEVICE_ZD1211 },
+ { USB_DEVICE(0x1740, 0x2000), .driver_info = DEVICE_ZD1211 },
+ { USB_DEVICE(0x6891, 0xa727), .driver_info = DEVICE_ZD1211 },
/* ZD1211B */
+ { USB_DEVICE(0x0053, 0x5301), .driver_info = DEVICE_ZD1211B },
+ { USB_DEVICE(0x0411, 0x00da), .driver_info = DEVICE_ZD1211B },
+ { USB_DEVICE(0x0471, 0x1236), .driver_info = DEVICE_ZD1211B },
+ { USB_DEVICE(0x0471, 0x1237), .driver_info = DEVICE_ZD1211B },
+ { USB_DEVICE(0x050d, 0x705c), .driver_info = DEVICE_ZD1211B },
{ USB_DEVICE(0x054c, 0x0257), .driver_info = DEVICE_ZD1211B },
- { USB_DEVICE(0x0ace, 0x1215), .driver_info = DEVICE_ZD1211B },
- { USB_DEVICE(0x0ace, 0xb215), .driver_info = DEVICE_ZD1211B },
- { USB_DEVICE(0x157e, 0x300d), .driver_info = DEVICE_ZD1211B },
+ { USB_DEVICE(0x0586, 0x340a), .driver_info = DEVICE_ZD1211B },
+ { USB_DEVICE(0x0586, 0x340f), .driver_info = DEVICE_ZD1211B },
+ { USB_DEVICE(0x0586, 0x3410), .driver_info = DEVICE_ZD1211B },
+ { USB_DEVICE(0x0586, 0x3412), .driver_info = DEVICE_ZD1211B },
+ { USB_DEVICE(0x0586, 0x3413), .driver_info = DEVICE_ZD1211B },
{ USB_DEVICE(0x079b, 0x0062), .driver_info = DEVICE_ZD1211B },
- { USB_DEVICE(0x1582, 0x6003), .driver_info = DEVICE_ZD1211B },
- { USB_DEVICE(0x050d, 0x705c), .driver_info = DEVICE_ZD1211B },
+ { USB_DEVICE(0x07b8, 0x6001), .driver_info = DEVICE_ZD1211B },
+ { USB_DEVICE(0x07fa, 0x1196), .driver_info = DEVICE_ZD1211B },
+ { USB_DEVICE(0x083a, 0x4505), .driver_info = DEVICE_ZD1211B },
+ { USB_DEVICE(0x083a, 0xe501), .driver_info = DEVICE_ZD1211B },
{ USB_DEVICE(0x083a, 0xe503), .driver_info = DEVICE_ZD1211B },
{ USB_DEVICE(0x083a, 0xe506), .driver_info = DEVICE_ZD1211B },
- { USB_DEVICE(0x083a, 0x4505), .driver_info = DEVICE_ZD1211B },
- { USB_DEVICE(0x0471, 0x1236), .driver_info = DEVICE_ZD1211B },
- { USB_DEVICE(0x13b1, 0x0024), .driver_info = DEVICE_ZD1211B },
- { USB_DEVICE(0x0586, 0x340f), .driver_info = DEVICE_ZD1211B },
+ { USB_DEVICE(0x0ace, 0x1215), .driver_info = DEVICE_ZD1211B },
+ { USB_DEVICE(0x0ace, 0xb215), .driver_info = DEVICE_ZD1211B },
{ USB_DEVICE(0x0b05, 0x171b), .driver_info = DEVICE_ZD1211B },
- { USB_DEVICE(0x0586, 0x3410), .driver_info = DEVICE_ZD1211B },
{ USB_DEVICE(0x0baf, 0x0121), .driver_info = DEVICE_ZD1211B },
- { USB_DEVICE(0x0586, 0x3412), .driver_info = DEVICE_ZD1211B },
- { USB_DEVICE(0x0586, 0x3413), .driver_info = DEVICE_ZD1211B },
- { USB_DEVICE(0x0053, 0x5301), .driver_info = DEVICE_ZD1211B },
- { USB_DEVICE(0x0411, 0x00da), .driver_info = DEVICE_ZD1211B },
- { USB_DEVICE(0x2019, 0x5303), .driver_info = DEVICE_ZD1211B },
- { USB_DEVICE(0x129b, 0x1667), .driver_info = DEVICE_ZD1211B },
{ USB_DEVICE(0x0cde, 0x001a), .driver_info = DEVICE_ZD1211B },
- { USB_DEVICE(0x0586, 0x340a), .driver_info = DEVICE_ZD1211B },
- { USB_DEVICE(0x0471, 0x1237), .driver_info = DEVICE_ZD1211B },
- { USB_DEVICE(0x07fa, 0x1196), .driver_info = DEVICE_ZD1211B },
{ USB_DEVICE(0x0df6, 0x0036), .driver_info = DEVICE_ZD1211B },
- { USB_DEVICE(0x07b8, 0x6001), .driver_info = DEVICE_ZD1211B },
+ { USB_DEVICE(0x129b, 0x1667), .driver_info = DEVICE_ZD1211B },
+ { USB_DEVICE(0x13b1, 0x0024), .driver_info = DEVICE_ZD1211B },
+ { USB_DEVICE(0x157e, 0x300d), .driver_info = DEVICE_ZD1211B },
+ { USB_DEVICE(0x1582, 0x6003), .driver_info = DEVICE_ZD1211B },
+ { USB_DEVICE(0x2019, 0x5303), .driver_info = DEVICE_ZD1211B },
/* "Driverless" devices that need ejecting */
{ USB_DEVICE(0x0ace, 0x2011), .driver_info = DEVICE_INSTALLER },
{ USB_DEVICE(0x0ace, 0x20ff), .driver_info = DEVICE_INSTALLER },
diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c
index 8d88daeed0c..3700c49d76c 100644
--- a/drivers/net/xen-netfront.c
+++ b/drivers/net/xen-netfront.c
@@ -558,12 +558,12 @@ static int xennet_start_xmit(struct sk_buff *skb, struct net_device *dev)
spin_unlock_irq(&np->tx_lock);
- return 0;
+ return NETDEV_TX_OK;
drop:
dev->stats.tx_dropped++;
dev_kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
}
static int xennet_close(struct net_device *dev)
diff --git a/drivers/net/xtsonic.c b/drivers/net/xtsonic.c
index 5a4ad156f63..0c44135c0b1 100644
--- a/drivers/net/xtsonic.c
+++ b/drivers/net/xtsonic.c
@@ -239,7 +239,7 @@ out:
* Actually probing is superfluous but we're paranoid.
*/
-int __init xtsonic_probe(struct platform_device *pdev)
+int __devinit xtsonic_probe(struct platform_device *pdev)
{
struct net_device *dev;
struct sonic_local *lp;
diff --git a/drivers/net/yellowfin.c b/drivers/net/yellowfin.c
index a07580138e8..76764237cde 100644
--- a/drivers/net/yellowfin.c
+++ b/drivers/net/yellowfin.c
@@ -830,7 +830,7 @@ static int yellowfin_start_xmit(struct sk_buff *skb, struct net_device *dev)
if (skb_padto(skb, len)) {
yp->tx_skbuff[entry] = NULL;
netif_wake_queue(dev);
- return 0;
+ return NETDEV_TX_OK;
}
}
}
@@ -884,7 +884,7 @@ static int yellowfin_start_xmit(struct sk_buff *skb, struct net_device *dev)
printk(KERN_DEBUG "%s: Yellowfin transmit frame #%d queued in slot %d.\n",
dev->name, yp->cur_tx, entry);
}
- return 0;
+ return NETDEV_TX_OK;
}
/* The interrupt handler does all of the Rx thread work and cleans up
diff --git a/drivers/net/znet.c b/drivers/net/znet.c
index 0a6992d8611..7f9e14131a5 100644
--- a/drivers/net/znet.c
+++ b/drivers/net/znet.c
@@ -546,7 +546,7 @@ static int znet_send_packet(struct sk_buff *skb, struct net_device *dev)
if (length < ETH_ZLEN) {
if (skb_padto(skb, ETH_ZLEN))
- return 0;
+ return NETDEV_TX_OK;
length = ETH_ZLEN;
}
@@ -600,7 +600,7 @@ static int znet_send_packet(struct sk_buff *skb, struct net_device *dev)
printk(KERN_DEBUG "%s: Transmitter queued, length %d.\n", dev->name, length);
}
dev_kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
}
/* The ZNET interrupt handler. */
diff --git a/drivers/s390/net/claw.c b/drivers/s390/net/claw.c
index f370f8d460a..c63babefb69 100644
--- a/drivers/s390/net/claw.c
+++ b/drivers/s390/net/claw.c
@@ -350,6 +350,8 @@ claw_tx(struct sk_buff *skb, struct net_device *dev)
CLAW_DBF_TEXT_(4, trace, "clawtx%d", rc);
if (rc)
rc = NETDEV_TX_BUSY;
+ else
+ rc = NETDEV_TX_OK;
return rc;
} /* end of claw_tx */
diff --git a/drivers/s390/net/ctcm_main.c b/drivers/s390/net/ctcm_main.c
index 222e4739443..38b5079f159 100644
--- a/drivers/s390/net/ctcm_main.c
+++ b/drivers/s390/net/ctcm_main.c
@@ -880,7 +880,7 @@ static int ctcm_tx(struct sk_buff *skb, struct net_device *dev)
"%s(%s): NULL sk_buff passed",
CTCM_FUNTAIL, dev->name);
priv->stats.tx_dropped++;
- return 0;
+ return NETDEV_TX_OK;
}
if (skb_headroom(skb) < (LL_HEADER_LENGTH + 2)) {
CTCM_DBF_TEXT_(ERROR, CTC_DBF_ERROR,
@@ -888,7 +888,7 @@ static int ctcm_tx(struct sk_buff *skb, struct net_device *dev)
CTCM_FUNTAIL, dev->name, LL_HEADER_LENGTH + 2);
dev_kfree_skb(skb);
priv->stats.tx_dropped++;
- return 0;
+ return NETDEV_TX_OK;
}
/*
@@ -901,7 +901,7 @@ static int ctcm_tx(struct sk_buff *skb, struct net_device *dev)
priv->stats.tx_dropped++;
priv->stats.tx_errors++;
priv->stats.tx_carrier_errors++;
- return 0;
+ return NETDEV_TX_OK;
}
if (ctcm_test_and_set_busy(dev))
@@ -910,7 +910,7 @@ static int ctcm_tx(struct sk_buff *skb, struct net_device *dev)
dev->trans_start = jiffies;
if (ctcm_transmit_skb(priv->channel[WRITE], skb) != 0)
return NETDEV_TX_BUSY;
- return 0;
+ return NETDEV_TX_OK;
}
/* unmerged MPC variant of ctcm_tx */
@@ -1008,7 +1008,7 @@ done:
if (do_debug)
MPC_DBF_DEV_NAME(TRACE, dev, "exit");
- return 0; /* handle freeing of skb here */
+ return NETDEV_TX_OK; /* handle freeing of skb here */
}
diff --git a/drivers/s390/net/lcs.c b/drivers/s390/net/lcs.c
index 8c675905448..a70de9b4bf2 100644
--- a/drivers/s390/net/lcs.c
+++ b/drivers/s390/net/lcs.c
@@ -1553,24 +1553,24 @@ __lcs_start_xmit(struct lcs_card *card, struct sk_buff *skb,
struct net_device *dev)
{
struct lcs_header *header;
- int rc = 0;
+ int rc = NETDEV_TX_OK;
LCS_DBF_TEXT(5, trace, "hardxmit");
if (skb == NULL) {
card->stats.tx_dropped++;
card->stats.tx_errors++;
- return 0;
+ return NETDEV_TX_OK;
}
if (card->state != DEV_STATE_UP) {
dev_kfree_skb(skb);
card->stats.tx_dropped++;
card->stats.tx_errors++;
card->stats.tx_carrier_errors++;
- return 0;
+ return NETDEV_TX_OK;
}
if (skb->protocol == htons(ETH_P_IPV6)) {
dev_kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
}
netif_stop_queue(card->dev);
spin_lock(&card->lock);
diff --git a/drivers/s390/net/netiucv.c b/drivers/s390/net/netiucv.c
index 8c36eafcfbf..bb1183a2ed6 100644
--- a/drivers/s390/net/netiucv.c
+++ b/drivers/s390/net/netiucv.c
@@ -1376,14 +1376,14 @@ static int netiucv_tx(struct sk_buff *skb, struct net_device *dev)
if (skb == NULL) {
IUCV_DBF_TEXT(data, 2, "netiucv_tx: skb is NULL\n");
privptr->stats.tx_dropped++;
- return 0;
+ return NETDEV_TX_OK;
}
if (skb_headroom(skb) < NETIUCV_HDRLEN) {
IUCV_DBF_TEXT(data, 2,
"netiucv_tx: skb_headroom < NETIUCV_HDRLEN\n");
dev_kfree_skb(skb);
privptr->stats.tx_dropped++;
- return 0;
+ return NETDEV_TX_OK;
}
/**
@@ -1395,7 +1395,7 @@ static int netiucv_tx(struct sk_buff *skb, struct net_device *dev)
privptr->stats.tx_dropped++;
privptr->stats.tx_errors++;
privptr->stats.tx_carrier_errors++;
- return 0;
+ return NETDEV_TX_OK;
}
if (netiucv_test_and_set_busy(dev)) {
diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c
index 691cecd03b8..2cfc338c462 100644
--- a/drivers/s390/net/qeth_l2_main.c
+++ b/drivers/s390/net/qeth_l2_main.c
@@ -744,6 +744,7 @@ static int qeth_l2_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
card->stats.tx_bytes += tx_bytes;
if (new_skb != skb)
dev_kfree_skb_any(skb);
+ rc = NETDEV_TX_OK;
} else {
if (data_offset >= 0)
kmem_cache_free(qeth_core_header_cache, hdr);
diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c
index 54872406864..048defaea81 100644
--- a/drivers/s390/net/qeth_l3_main.c
+++ b/drivers/s390/net/qeth_l3_main.c
@@ -2793,6 +2793,7 @@ static int qeth_l3_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
card->perf_stats.sg_frags_sent += nr_frags + 1;
}
}
+ rc = NETDEV_TX_OK;
} else {
if (data_offset >= 0)
kmem_cache_free(qeth_core_header_cache, hdr);
diff --git a/drivers/ssb/pci.c b/drivers/ssb/pci.c
index 40ea4176224..593fc618a2e 100644
--- a/drivers/ssb/pci.c
+++ b/drivers/ssb/pci.c
@@ -169,8 +169,14 @@ err_pci:
/* Get the word-offset for a SSB_SPROM_XXX define. */
#define SPOFF(offset) (((offset) - SSB_SPROM_BASE) / sizeof(u16))
/* Helper to extract some _offset, which is one of the SSB_SPROM_XXX defines. */
-#define SPEX(_outvar, _offset, _mask, _shift) \
+#define SPEX16(_outvar, _offset, _mask, _shift) \
out->_outvar = ((in[SPOFF(_offset)] & (_mask)) >> (_shift))
+#define SPEX32(_outvar, _offset, _mask, _shift) \
+ out->_outvar = ((((u32)in[SPOFF((_offset)+2)] << 16 | \
+ in[SPOFF(_offset)]) & (_mask)) >> (_shift))
+#define SPEX(_outvar, _offset, _mask, _shift) \
+ SPEX16(_outvar, _offset, _mask, _shift)
+
static inline u8 ssb_crc8(u8 crc, u8 data)
{
@@ -480,6 +486,8 @@ static void sprom_extract_r8(struct ssb_sprom *out, const u16 *in)
SPEX(country_code, SSB_SPROM8_CCODE, 0xFFFF, 0);
SPEX(boardflags_lo, SSB_SPROM8_BFLLO, 0xFFFF, 0);
SPEX(boardflags_hi, SSB_SPROM8_BFLHI, 0xFFFF, 0);
+ SPEX(boardflags2_lo, SSB_SPROM8_BFL2LO, 0xFFFF, 0);
+ SPEX(boardflags2_hi, SSB_SPROM8_BFL2HI, 0xFFFF, 0);
SPEX(ant_available_a, SSB_SPROM8_ANTAVAIL, SSB_SPROM8_ANTAVAIL_A,
SSB_SPROM8_ANTAVAIL_A_SHIFT);
SPEX(ant_available_bg, SSB_SPROM8_ANTAVAIL, SSB_SPROM8_ANTAVAIL_BG,
@@ -490,12 +498,55 @@ static void sprom_extract_r8(struct ssb_sprom *out, const u16 *in)
SPEX(maxpwr_a, SSB_SPROM8_MAXP_A, SSB_SPROM8_MAXP_A_MASK, 0);
SPEX(itssi_a, SSB_SPROM8_MAXP_A, SSB_SPROM8_ITSSI_A,
SSB_SPROM8_ITSSI_A_SHIFT);
+ SPEX(maxpwr_ah, SSB_SPROM8_MAXP_AHL, SSB_SPROM8_MAXP_AH_MASK, 0);
+ SPEX(maxpwr_al, SSB_SPROM8_MAXP_AHL, SSB_SPROM8_MAXP_AL_MASK,
+ SSB_SPROM8_MAXP_AL_SHIFT);
SPEX(gpio0, SSB_SPROM8_GPIOA, SSB_SPROM8_GPIOA_P0, 0);
SPEX(gpio1, SSB_SPROM8_GPIOA, SSB_SPROM8_GPIOA_P1,
SSB_SPROM8_GPIOA_P1_SHIFT);
SPEX(gpio2, SSB_SPROM8_GPIOB, SSB_SPROM8_GPIOB_P2, 0);
SPEX(gpio3, SSB_SPROM8_GPIOB, SSB_SPROM8_GPIOB_P3,
SSB_SPROM8_GPIOB_P3_SHIFT);
+ SPEX(tri2g, SSB_SPROM8_TRI25G, SSB_SPROM8_TRI2G, 0);
+ SPEX(tri5g, SSB_SPROM8_TRI25G, SSB_SPROM8_TRI5G,
+ SSB_SPROM8_TRI5G_SHIFT);
+ SPEX(tri5gl, SSB_SPROM8_TRI5GHL, SSB_SPROM8_TRI5GL, 0);
+ SPEX(tri5gh, SSB_SPROM8_TRI5GHL, SSB_SPROM8_TRI5GH,
+ SSB_SPROM8_TRI5GH_SHIFT);
+ SPEX(rxpo2g, SSB_SPROM8_RXPO, SSB_SPROM8_RXPO2G, 0);
+ SPEX(rxpo5g, SSB_SPROM8_RXPO, SSB_SPROM8_RXPO5G,
+ SSB_SPROM8_RXPO5G_SHIFT);
+ SPEX(rssismf2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISMF2G, 0);
+ SPEX(rssismc2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISMC2G,
+ SSB_SPROM8_RSSISMC2G_SHIFT);
+ SPEX(rssisav2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISAV2G,
+ SSB_SPROM8_RSSISAV2G_SHIFT);
+ SPEX(bxa2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_BXA2G,
+ SSB_SPROM8_BXA2G_SHIFT);
+ SPEX(rssismf5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISMF5G, 0);
+ SPEX(rssismc5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISMC5G,
+ SSB_SPROM8_RSSISMC5G_SHIFT);
+ SPEX(rssisav5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISAV5G,
+ SSB_SPROM8_RSSISAV5G_SHIFT);
+ SPEX(bxa5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_BXA5G,
+ SSB_SPROM8_BXA5G_SHIFT);
+ SPEX(pa0b0, SSB_SPROM8_PA0B0, 0xFFFF, 0);
+ SPEX(pa0b1, SSB_SPROM8_PA0B1, 0xFFFF, 0);
+ SPEX(pa0b2, SSB_SPROM8_PA0B2, 0xFFFF, 0);
+ SPEX(pa1b0, SSB_SPROM8_PA1B0, 0xFFFF, 0);
+ SPEX(pa1b1, SSB_SPROM8_PA1B1, 0xFFFF, 0);
+ SPEX(pa1b2, SSB_SPROM8_PA1B2, 0xFFFF, 0);
+ SPEX(pa1lob0, SSB_SPROM8_PA1LOB0, 0xFFFF, 0);
+ SPEX(pa1lob1, SSB_SPROM8_PA1LOB1, 0xFFFF, 0);
+ SPEX(pa1lob2, SSB_SPROM8_PA1LOB2, 0xFFFF, 0);
+ SPEX(pa1hib0, SSB_SPROM8_PA1HIB0, 0xFFFF, 0);
+ SPEX(pa1hib1, SSB_SPROM8_PA1HIB1, 0xFFFF, 0);
+ SPEX(pa1hib2, SSB_SPROM8_PA1HIB2, 0xFFFF, 0);
+ SPEX(cck2gpo, SSB_SPROM8_CCK2GPO, 0xFFFF, 0);
+ SPEX32(ofdm2gpo, SSB_SPROM8_OFDM2GPO, 0xFFFFFFFF, 0);
+ SPEX32(ofdm5glpo, SSB_SPROM8_OFDM5GLPO, 0xFFFFFFFF, 0);
+ SPEX32(ofdm5gpo, SSB_SPROM8_OFDM5GPO, 0xFFFFFFFF, 0);
+ SPEX32(ofdm5ghpo, SSB_SPROM8_OFDM5GHPO, 0xFFFFFFFF, 0);
/* Extract the antenna gain values. */
SPEX(antenna_gain.ghz24.a0, SSB_SPROM8_AGAIN01,
diff --git a/drivers/staging/agnx/xmit.c b/drivers/staging/agnx/xmit.c
index 0e034081f3a..42db41070cf 100644
--- a/drivers/staging/agnx/xmit.c
+++ b/drivers/staging/agnx/xmit.c
@@ -384,7 +384,8 @@ void handle_rx_irq(struct agnx_priv *priv)
/* dump_ieee80211_hdr((struct ieee80211_hdr *)skb->data, "RX G"); */
} else
agnx_bug("Unknown packets type");
- ieee80211_rx_irqsafe(priv->hw, skb, &status);
+ memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status));
+ ieee80211_rx_irqsafe(priv->hw, skb);
rx_desc_reinit(priv, i);
} while (priv->rx.idx++);
diff --git a/drivers/staging/at76_usb/at76_usb.c b/drivers/staging/at76_usb/at76_usb.c
index 3f303ae97b4..7b8aa5edf42 100644
--- a/drivers/staging/at76_usb/at76_usb.c
+++ b/drivers/staging/at76_usb/at76_usb.c
@@ -3134,7 +3134,7 @@ static int at76_tx(struct sk_buff *skb, struct net_device *netdev)
netdev->name, __func__);
/* skip this packet */
dev_kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
}
if (priv->tx_urb->status == -EINPROGRESS) {
@@ -3142,14 +3142,14 @@ static int at76_tx(struct sk_buff *skb, struct net_device *netdev)
netdev->name, __func__);
/* skip this packet */
dev_kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
}
if (skb->len < ETH_HLEN) {
printk(KERN_ERR "%s: %s: skb too short (%d)\n",
netdev->name, __func__, skb->len);
dev_kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
}
at76_ledtrig_tx_activity(); /* tell ledtrigger we send a packet */
@@ -3173,7 +3173,7 @@ static int at76_tx(struct sk_buff *skb, struct net_device *netdev)
skb->data[ETH_HLEN + 1],
skb->data[ETH_HLEN + 2]);
dev_kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
}
} else {
/* add RFC 1042 header in front */
diff --git a/drivers/staging/dst/dcore.c b/drivers/staging/dst/dcore.c
index fad25b75304..84724187ec3 100644
--- a/drivers/staging/dst/dcore.c
+++ b/drivers/staging/dst/dcore.c
@@ -846,10 +846,9 @@ static dst_command_func dst_commands[] = {
/*
* Configuration parser.
*/
-static void cn_dst_callback(void *data)
+static void cn_dst_callback(struct cn_msg *msg)
{
struct dst_ctl *ctl;
- struct cn_msg *msg = data;
int err;
struct dst_ctl_ack ack;
struct dst_node *n = NULL, *tmp;
diff --git a/drivers/staging/epl/VirtualEthernetLinux.c b/drivers/staging/epl/VirtualEthernetLinux.c
index 077724a556c..7b7cce1b36e 100644
--- a/drivers/staging/epl/VirtualEthernetLinux.c
+++ b/drivers/staging/epl/VirtualEthernetLinux.c
@@ -223,7 +223,7 @@ static int VEthXmit(struct sk_buff *pSkb_p, struct net_device *pNetDevice_p)
}
Exit:
- return 0;
+ return NETDEV_TX_OK;
}
diff --git a/drivers/staging/otus/usbdrv.c b/drivers/staging/otus/usbdrv.c
index 540cbbb826f..7cd87caa681 100644
--- a/drivers/staging/otus/usbdrv.c
+++ b/drivers/staging/otus/usbdrv.c
@@ -659,7 +659,7 @@ int usbdrv_xmit_frame(struct sk_buff *skb, struct net_device *dev)
netif_stop_queue(dev);
}
- return 0;
+ return NETDEV_TX_OK;
}
@@ -796,13 +796,13 @@ int zfLnxVapXmitFrame(struct sk_buff *skb, struct net_device *dev)
if (vapId >= ZM_VAP_PORT_NUMBER)
{
dev_kfree_skb_irq(skb);
- return 0;
+ return NETDEV_TX_OK;
}
#if 1
if (vap[vapId].openFlag == 0)
{
dev_kfree_skb_irq(skb);
- return 0;
+ return NETDEV_TX_OK;
}
#endif
@@ -819,7 +819,7 @@ int zfLnxVapXmitFrame(struct sk_buff *skb, struct net_device *dev)
netif_stop_queue(dev);
}
- return 0;
+ return NETDEV_TX_OK;
}
static const struct net_device_ops vap_netdev_ops = {
diff --git a/drivers/staging/otus/wrap_pkt.c b/drivers/staging/otus/wrap_pkt.c
index 5db0004c873..89a6b92f597 100644
--- a/drivers/staging/otus/wrap_pkt.c
+++ b/drivers/staging/otus/wrap_pkt.c
@@ -156,10 +156,7 @@ void zfLnxRecvEth(zdev_t* dev, zbuf_t* buf, u16_t port)
switch(netif_rx(buf))
#endif
{
- case NET_RX_BAD:
case NET_RX_DROP:
- case NET_RX_CN_MOD:
- case NET_RX_CN_HIGH:
break;
default:
macp->drv_stats.net_stats.rx_packets++;
diff --git a/drivers/staging/rt2860/rt_main_dev.c b/drivers/staging/rt2860/rt_main_dev.c
index f298b9bcec3..35c59d5aa99 100644
--- a/drivers/staging/rt2860/rt_main_dev.c
+++ b/drivers/staging/rt2860/rt_main_dev.c
@@ -862,7 +862,7 @@ int rt28xx_packet_xmit(struct sk_buff *skb)
{
struct net_device *net_dev = skb->dev;
PRTMP_ADAPTER pAd = net_dev->ml_priv;
- int status = 0;
+ int status = NETDEV_TX_OK;
PNDIS_PACKET pPacket = (PNDIS_PACKET) skb;
{
@@ -892,7 +892,7 @@ int rt28xx_packet_xmit(struct sk_buff *skb)
STASendPackets((NDIS_HANDLE)pAd, (PPNDIS_PACKET) &pPacket, 1);
- status = 0;
+ status = NETDEV_TX_OK;
done:
return status;
@@ -923,7 +923,7 @@ INT rt28xx_send_packets(
if (!(net_dev->flags & IFF_UP))
{
RELEASE_NDIS_PACKET(pAd, (PNDIS_PACKET)skb_p, NDIS_STATUS_FAILURE);
- return 0;
+ return NETDEV_TX_OK;
}
NdisZeroMemory((PUCHAR)&skb_p->cb[CB_OFF], 15);
diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_tx.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_tx.c
index 1294e05fcf1..1b774601b4a 100644
--- a/drivers/staging/rtl8187se/ieee80211/ieee80211_tx.c
+++ b/drivers/staging/rtl8187se/ieee80211/ieee80211_tx.c
@@ -802,13 +802,13 @@ int ieee80211_xmit(struct sk_buff *skb,
if ((*ieee->hard_start_xmit)(txb, dev) == 0) {
stats->tx_packets++;
stats->tx_bytes += txb->payload_size;
- return 0;
+ return NETDEV_TX_OK;
}
ieee80211_txb_free(txb);
}
}
- return 0;
+ return NETDEV_TX_OK;
failed:
spin_unlock_irqrestore(&ieee->lock, flags);
diff --git a/drivers/staging/rtl8187se/r8180_core.c b/drivers/staging/rtl8187se/r8180_core.c
index 7e2fecae813..26a59118d34 100644
--- a/drivers/staging/rtl8187se/r8180_core.c
+++ b/drivers/staging/rtl8187se/r8180_core.c
@@ -3040,7 +3040,7 @@ int rtl8180_hard_start_xmit(struct sk_buff *skb,struct net_device *dev)
spin_unlock_irqrestore(&priv->tx_lock,flags);
dev_kfree_skb_any(skb);
- return 0;
+ return NETDEV_TX_OK;
}
rtl8180_tx(dev, skb->data, skb->len, priority,
@@ -3051,7 +3051,7 @@ int rtl8180_hard_start_xmit(struct sk_buff *skb,struct net_device *dev)
spin_unlock_irqrestore(&priv->tx_lock,flags);
dev_kfree_skb_any(skb);
- return 0;
+ return NETDEV_TX_OK;
}
// longpre 144+48 shortpre 72+24
diff --git a/drivers/staging/slicoss/slicoss.c b/drivers/staging/slicoss/slicoss.c
index ed47db5ce5f..b01a2822a8e 100644
--- a/drivers/staging/slicoss/slicoss.c
+++ b/drivers/staging/slicoss/slicoss.c
@@ -845,7 +845,7 @@ static int slic_xmit_start(struct sk_buff *skb, struct net_device *dev)
hcmd->paddrh, DONT_FLUSH);
}
xmit_done:
- return 0;
+ return NETDEV_TX_OK;
xmit_fail:
slic_xmit_fail(adapter, skb, offloadcmd, skbtype, status);
goto xmit_done;
diff --git a/drivers/staging/stlc45xx/stlc45xx.c b/drivers/staging/stlc45xx/stlc45xx.c
index a137c78fac0..12d414deaad 100644
--- a/drivers/staging/stlc45xx/stlc45xx.c
+++ b/drivers/staging/stlc45xx/stlc45xx.c
@@ -1429,7 +1429,8 @@ static int stlc45xx_rx_data(struct stlc45xx *stlc, struct sk_buff *skb)
stlc45xx_debug(DEBUG_RX, "rx data 0x%p %d B", skb->data, skb->len);
stlc45xx_dump(DEBUG_RX_CONTENT, skb->data, skb->len);
- ieee80211_rx(stlc->hw, skb, &status);
+ memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status));
+ ieee80211_rx(stlc->hw, skb);
return 0;
}
diff --git a/drivers/staging/winbond/wb35rx.c b/drivers/staging/winbond/wb35rx.c
index 3e8cf08b87e..b905e7b43a1 100644
--- a/drivers/staging/winbond/wb35rx.c
+++ b/drivers/staging/winbond/wb35rx.c
@@ -40,7 +40,8 @@ static void packet_came(struct ieee80211_hw *hw, char *pRxBufferAddress, int Pac
rx_status.phymode = MODE_IEEE80211B;
*/
- ieee80211_rx_irqsafe(hw, skb, &rx_status);
+ memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status));
+ ieee80211_rx_irqsafe(hw, skb);
}
static void Wb35Rx_adjust(PDESCRIPTOR pRxDes)
diff --git a/drivers/staging/wlan-ng/p80211netdev.c b/drivers/staging/wlan-ng/p80211netdev.c
index 90f499e00dc..c273c034a83 100644
--- a/drivers/staging/wlan-ng/p80211netdev.c
+++ b/drivers/staging/wlan-ng/p80211netdev.c
@@ -354,7 +354,7 @@ static int p80211knetdev_hard_start_xmit(struct sk_buff *skb,
p80211_metawep_t p80211_wep;
if (skb == NULL)
- return 0;
+ return NETDEV_TX_OK;
if (wlandev->state != WLAN_DEVICE_OPEN) {
result = 1;
diff --git a/drivers/usb/gadget/f_phonet.c b/drivers/usb/gadget/f_phonet.c
index 96fb118355b..d2de10b9dc4 100644
--- a/drivers/usb/gadget/f_phonet.c
+++ b/drivers/usb/gadget/f_phonet.c
@@ -35,6 +35,10 @@
#include "u_phonet.h"
#define PN_MEDIA_USB 0x1B
+#define MAXPACKET 512
+#if (PAGE_SIZE % MAXPACKET)
+#error MAXPACKET must divide PAGE_SIZE!
+#endif
/*-------------------------------------------------------------------------*/
@@ -45,6 +49,10 @@ struct phonet_port {
struct f_phonet {
struct usb_function function;
+ struct {
+ struct sk_buff *skb;
+ spinlock_t lock;
+ } rx;
struct net_device *dev;
struct usb_ep *in_ep, *out_ep;
@@ -52,7 +60,7 @@ struct f_phonet {
struct usb_request *out_reqv[0];
};
-static int phonet_rxq_size = 2;
+static int phonet_rxq_size = 17;
static inline struct f_phonet *func_to_pn(struct usb_function *f)
{
@@ -138,7 +146,7 @@ pn_hs_sink_desc = {
.bEndpointAddress = USB_DIR_OUT,
.bmAttributes = USB_ENDPOINT_XFER_BULK,
- .wMaxPacketSize = cpu_to_le16(512),
+ .wMaxPacketSize = cpu_to_le16(MAXPACKET),
};
static struct usb_endpoint_descriptor
@@ -256,25 +264,15 @@ out:
dev_kfree_skb(skb);
dev->stats.tx_dropped++;
}
- return 0;
+ return NETDEV_TX_OK;
}
static int pn_net_mtu(struct net_device *dev, int new_mtu)
{
- struct phonet_port *port = netdev_priv(dev);
- unsigned long flags;
- int err = -EBUSY;
-
if ((new_mtu < PHONET_MIN_MTU) || (new_mtu > PHONET_MAX_MTU))
return -EINVAL;
-
- spin_lock_irqsave(&port->lock, flags);
- if (!netif_carrier_ok(dev)) {
- dev->mtu = new_mtu;
- err = 0;
- }
- spin_unlock_irqrestore(&port->lock, flags);
- return err;
+ dev->mtu = new_mtu;
+ return 0;
}
static const struct net_device_ops pn_netdev_ops = {
@@ -308,21 +306,21 @@ static void pn_net_setup(struct net_device *dev)
static int
pn_rx_submit(struct f_phonet *fp, struct usb_request *req, gfp_t gfp_flags)
{
- struct sk_buff *skb;
- const size_t size = fp->dev->mtu;
+ struct net_device *dev = fp->dev;
+ struct page *page;
int err;
- skb = alloc_skb(size, gfp_flags);
- if (!skb)
+ page = __netdev_alloc_page(dev, gfp_flags);
+ if (!page)
return -ENOMEM;
- req->buf = skb->data;
- req->length = size;
- req->context = skb;
+ req->buf = page_address(page);
+ req->length = PAGE_SIZE;
+ req->context = page;
err = usb_ep_queue(fp->out_ep, req, gfp_flags);
if (unlikely(err))
- dev_kfree_skb_any(skb);
+ netdev_free_page(dev, page);
return err;
}
@@ -330,25 +328,37 @@ static void pn_rx_complete(struct usb_ep *ep, struct usb_request *req)
{
struct f_phonet *fp = ep->driver_data;
struct net_device *dev = fp->dev;
- struct sk_buff *skb = req->context;
+ struct page *page = req->context;
+ struct sk_buff *skb;
+ unsigned long flags;
int status = req->status;
switch (status) {
case 0:
- if (unlikely(!netif_running(dev)))
- break;
- if (unlikely(req->actual < 1))
+ spin_lock_irqsave(&fp->rx.lock, flags);
+ skb = fp->rx.skb;
+ if (!skb)
+ skb = fp->rx.skb = netdev_alloc_skb(dev, 12);
+ if (req->actual < req->length) /* Last fragment */
+ fp->rx.skb = NULL;
+ spin_unlock_irqrestore(&fp->rx.lock, flags);
+
+ if (unlikely(!skb))
break;
- skb_put(skb, req->actual);
- skb->protocol = htons(ETH_P_PHONET);
- skb_reset_mac_header(skb);
- __skb_pull(skb, 1);
- skb->dev = dev;
- dev->stats.rx_packets++;
- dev->stats.rx_bytes += skb->len;
-
- netif_rx(skb);
- skb = NULL;
+ skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, page, 0,
+ req->actual);
+ page = NULL;
+
+ if (req->actual < req->length) { /* Last fragment */
+ skb->protocol = htons(ETH_P_PHONET);
+ skb_reset_mac_header(skb);
+ pskb_pull(skb, 1);
+ skb->dev = dev;
+ dev->stats.rx_packets++;
+ dev->stats.rx_bytes += skb->len;
+
+ netif_rx(skb);
+ }
break;
/* Do not resubmit in these cases: */
@@ -366,8 +376,8 @@ static void pn_rx_complete(struct usb_ep *ep, struct usb_request *req)
break;
}
- if (skb)
- dev_kfree_skb_any(skb);
+ if (page)
+ netdev_free_page(dev, page);
if (req)
pn_rx_submit(fp, req, GFP_ATOMIC);
}
@@ -385,6 +395,10 @@ static void __pn_reset(struct usb_function *f)
usb_ep_disable(fp->out_ep);
usb_ep_disable(fp->in_ep);
+ if (fp->rx.skb) {
+ dev_kfree_skb_irq(fp->rx.skb);
+ fp->rx.skb = NULL;
+ }
}
static int pn_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
@@ -583,6 +597,7 @@ int __init phonet_bind_config(struct usb_configuration *c)
fp->function.set_alt = pn_set_alt;
fp->function.get_alt = pn_get_alt;
fp->function.disable = pn_disconnect;
+ spin_lock_init(&fp->rx.lock);
err = usb_add_function(c, &fp->function);
if (err)
diff --git a/drivers/usb/gadget/u_ether.c b/drivers/usb/gadget/u_ether.c
index 016f63b3902..aac69b591ae 100644
--- a/drivers/usb/gadget/u_ether.c
+++ b/drivers/usb/gadget/u_ether.c
@@ -487,7 +487,7 @@ static int eth_start_xmit(struct sk_buff *skb, struct net_device *net)
if (!in) {
dev_kfree_skb_any(skb);
- return 0;
+ return NETDEV_TX_OK;
}
/* apply outgoing CDC or RNDIS filters */
@@ -506,7 +506,7 @@ static int eth_start_xmit(struct sk_buff *skb, struct net_device *net)
type = USB_CDC_PACKET_TYPE_ALL_MULTICAST;
if (!(cdc_filter & type)) {
dev_kfree_skb_any(skb);
- return 0;
+ return NETDEV_TX_OK;
}
}
/* ignores USB_CDC_PACKET_TYPE_DIRECTED */
@@ -586,7 +586,7 @@ drop:
list_add(&req->list, &dev->tx_reqs);
spin_unlock_irqrestore(&dev->req_lock, flags);
}
- return 0;
+ return NETDEV_TX_OK;
}
/*-------------------------------------------------------------------------*/
diff --git a/drivers/video/uvesafb.c b/drivers/video/uvesafb.c
index ca5b4643a40..e98baf6916b 100644
--- a/drivers/video/uvesafb.c
+++ b/drivers/video/uvesafb.c
@@ -67,9 +67,8 @@ static DEFINE_MUTEX(uvfb_lock);
* find the kernel part of the task struct, copy the registers and
* the buffer contents and then complete the task.
*/
-static void uvesafb_cn_callback(void *data)
+static void uvesafb_cn_callback(struct cn_msg *msg)
{
- struct cn_msg *msg = data;
struct uvesafb_task *utask;
struct uvesafb_ktask *task;
diff --git a/drivers/w1/w1_netlink.c b/drivers/w1/w1_netlink.c
index fdf72851c57..52ccb3d3a96 100644
--- a/drivers/w1/w1_netlink.c
+++ b/drivers/w1/w1_netlink.c
@@ -306,9 +306,8 @@ static int w1_netlink_send_error(struct cn_msg *rcmsg, struct w1_netlink_msg *rm
return error;
}
-static void w1_cn_callback(void *data)
+static void w1_cn_callback(struct cn_msg *msg)
{
- struct cn_msg *msg = data;
struct w1_netlink_msg *m = (struct w1_netlink_msg *)(msg + 1);
struct w1_netlink_cmd *cmd;
struct w1_slave *sl;
diff --git a/firmware/Makefile b/firmware/Makefile
index 621de8e952f..317212ccc78 100644
--- a/firmware/Makefile
+++ b/firmware/Makefile
@@ -32,7 +32,7 @@ fw-shipped-$(CONFIG_ADAPTEC_STARFIRE) += adaptec/starfire_rx.bin \
adaptec/starfire_tx.bin
fw-shipped-$(CONFIG_ATARI_DSP56K) += dsp56k/bootstrap.bin
fw-shipped-$(CONFIG_ATM_AMBASSADOR) += atmsar11.fw
-fw-shipped-$(CONFIG_BNX2X) += bnx2x-e1-4.8.53.0.fw bnx2x-e1h-4.8.53.0.fw
+fw-shipped-$(CONFIG_BNX2X) += bnx2x-e1-5.0.21.0.fw bnx2x-e1h-5.0.21.0.fw
fw-shipped-$(CONFIG_BNX2) += bnx2/bnx2-mips-09-4.6.17.fw \
bnx2/bnx2-rv2p-09-4.6.15.fw \
bnx2/bnx2-mips-06-4.6.16.fw \
@@ -41,7 +41,10 @@ fw-shipped-$(CONFIG_CASSINI) += sun/cassini.bin
fw-shipped-$(CONFIG_COMPUTONE) += intelliport2.bin
fw-shipped-$(CONFIG_CHELSIO_T3) += cxgb3/t3b_psram-1.1.0.bin \
cxgb3/t3c_psram-1.1.0.bin \
- cxgb3/t3fw-7.4.0.bin
+ cxgb3/t3fw-7.4.0.bin \
+ cxgb3/ael2005_opt_edc.bin \
+ cxgb3/ael2005_twx_edc.bin \
+ cxgb3/ael2020_twx_edc.bin
fw-shipped-$(CONFIG_DVB_AV7110) += av7110/bootcode.bin
fw-shipped-$(CONFIG_DVB_TTUSB_BUDGET) += ttusb-budget/dspbootcode.bin
fw-shipped-$(CONFIG_E100) += e100/d101m_ucode.bin e100/d101s_ucode.bin \
diff --git a/firmware/WHENCE b/firmware/WHENCE
index 0f5649a08c0..d9e3a94cb4d 100644
--- a/firmware/WHENCE
+++ b/firmware/WHENCE
@@ -418,6 +418,23 @@ License: GPLv2 or OpenIB.org BSD license, no source visible
--------------------------------------------------------------------------
+Driver: cxgb3 - Chelsio Terminator 3 1G/10G Ethernet adapter
+
+File: cxgb3/ael2005_opt_edc.bin.ihex
+File: cxgb3/ael2005_twx_edc.bin.ihex
+File: cxgb3/ael2020_twx_edc.bin.ihex
+
+Licence:
+ * Copyright (c) 2007-2009 NetLogic Microsystems, Inc.
+ *
+ * Permission is hereby granted for the distribution of this firmware
+ * data in hexadecimal or equivalent format, provided this copyright
+ * notice is accompanying it.
+
+Found in hex form in kernel source.
+
+--------------------------------------------------------------------------
+
Driver: e100 -- Intel PRO/100 Ethernet NIC
File: e100/d101m_ucode.bin
diff --git a/firmware/bnx2x-e1-4.8.53.0.fw.ihex b/firmware/bnx2x-e1-4.8.53.0.fw.ihex
deleted file mode 100644
index f1edb1e7ad1..00000000000
--- a/firmware/bnx2x-e1-4.8.53.0.fw.ihex
+++ /dev/null
@@ -1,10364 +0,0 @@
-:10000000000028600000006000000630000028C8E2
-:100010000000160800002F000000009400004510AA
-:10002000000073C8000045A8000000C40000B978B3
-:100030000000A4680000BA400000007400015EB037
-:100040000000559000015F28000000B80001B4C016
-:100050000000D1F80001B580000000040002878094
-:10006000020400480000000F020400540000004594
-:1000700002040058000000840204005C0000000636
-:100080000204007000000004020400780000000078
-:100090000204007C121700000204008022170000F6
-:1000A00002040084321700000604008800000005E6
-:1000B0000204009C12150000020400A0221500009A
-:1000C000020400A432150000060400A80000000489
-:1000D000020400B802100000020400BC001000007E
-:1000E000020400C010100000020400C42010000030
-:1000F000020400C830100000060400CC0000000418
-:10010000020400DC00100000020400E012140000F1
-:10011000020400E422140000020400E8321400008B
-:10012000060400EC000000040104012400000000AB
-:1001300001040128000000000104012C000000005F
-:10014000010401300000000002040004000000FF70
-:1001500002040008000000FF0204000C000000FF81
-:1001600002040010000000FF02040014000000FF61
-:1001700002040018000000FF0204001C000000FF41
-:1001800002040020000000FF020400240000003EE2
-:1001900002040028000000000204002C0000003FC0
-:1001A000020400300000003F020400340000003F61
-:1001B00002040038000000000204003C0000003F80
-:1001C000020400400000003F020400440000003F21
-:1001D00002042008000004110204200C00000400A6
-:1001E000020420100000040402042014000004197A
-:1001F0000204201C0000FFFF020420200000FFFF7B
-:10020000020420240000FFFF020420280000FFFF5A
-:1002100006042038000000020204204000000034E0
-:100220000204204400000035060420480000007C41
-:100230000204223807FFFFFF0204223C0000003FB7
-:100240000204224007FFFFFF020422440000000FC7
-:1002500001042248000000000104224C00000000BC
-:10026000010422500000000001042254000000009C
-:1002700001042258000000000104225C000000007C
-:10028000010422600000000001042264000000005C
-:1002900001042268000000000104226C000000003C
-:1002A000010422700000000001042274000000001C
-:1002B00001042278000000000104227C00000000FC
-:1002C000020424BC000000010C042000000003E82C
-:1002D0000A042000000000010B0420000000000AB6
-:1002E0000205004400000020020500480000003222
-:1002F000020500900215002002050094021500205E
-:1003000002050098000000300205009C0810000063
-:10031000020500A000000033020500A40000003028
-:10032000020500A800000031020500AC0000000238
-:10033000020500B000000005020500B40000000640
-:10034000020500B800000002020500BC0000000227
-:10035000020500C000000000020500C40000000506
-:10036000020500C800000002020500CC00000002E7
-:10037000020500D000000002020500D400000001C8
-:1003800002050114000000010205011C000000012B
-:100390000205012000000002020502040000000125
-:1003A0000205020C0000004002050210000000409F
-:1003B0000205021C000000200205022000000013BC
-:1003C0000205022400000020060502400000000A89
-:1003D0000405028000200000020500500000000714
-:1003E0000205005400000007020500580000000844
-:1003F0000205005C00000008060500600000000423
-:10040000020500D800000006020500E00000000D13
-:10041000020500E40000002D020500E800000007CE
-:10042000020500EC00000027020500F000000007B4
-:10043000020500F400000027020500F80000000794
-:10044000020500FC00000027020500040000000176
-:1004500002050008000000010205000C0000000178
-:100460000205001000000001020500140000000158
-:1004700002050018000000010205001C0000000138
-:100480000205002000000001020500240000000118
-:1004900002050028000000010205002C00000001F8
-:1004A00002050030000000010205003400000001D8
-:1004B00002050038000000010205003C00000001B8
-:1004C00002050040000000010406100002000020A8
-:1004D000020600DC00000001010600D80000000058
-:1004E0000406020000030220020600DC00000000F7
-:1004F00002060068000000B802060078000001143F
-:10050000010600B800000000010600C8000000005D
-:100510000206006C000000B80206007C0000011416
-:10052000010600BC00000000010600CC0000000035
-:100530000718040000930000081807600014022345
-:10054000071C0000324F0000071C800033250C946C
-:10055000071D00000E4D195E081D1E005C4002259F
-:100560000118000000000000011800040000000055
-:1005700001180008000000000118000C0000000035
-:100580000118001000000000011800140000000015
-:1005900002180020000000010218002400000002E0
-:1005A00002180028000000030218002C00000000C0
-:1005B000021800300000000402180034000000019E
-:1005C00002180038000000000218003C0000000182
-:1005D000021800400000000402180044000000005F
-:1005E00002180048000000010218004C000000033F
-:1005F0000218005000000000021800540000000122
-:1006000002180058000000040218005C00000000FE
-:1006100002180060000000010218006400000003DE
-:1006200002180068000000000218006C00000001C1
-:10063000021800700000000402180074000000009E
-:1006400002180078000000040218007C000000037B
-:100650000618008000000002021800A400003FFFFE
-:10066000021800A8000003FF021802240000000086
-:1006700002180234000000000218024C00000000C2
-:10068000021802E4000000FF061810000000040039
-:10069000021B8BC000000001021B80000000003420
-:1006A000021B804000000018021B80800000000C2C
-:1006B000021B80C0000000200C1B83000007A1204B
-:1006C0000A1B8300000001380B1B83000000138805
-:1006D000021B83C0000001F4061A2000000000B2D3
-:1006E000061A23C8000000C1041A26CC0001022704
-:1006F000061A1020000000C8061A100000000002B0
-:10070000061A1C1800000004061A1C100000000243
-:10071000061A080000000002061A0808000000027D
-:10072000061A081000000004041A1FB00004022872
-:10073000041A4CB00008022C061A22C8000000203F
-:10074000061A40000000016C021A4B600000000015
-:10075000061A14000000000A061A145000000006D1
-:10076000061A150000000002041A150800050234DC
-:10077000061A151C00000007061A1570000000126A
-:10078000061A09C00000004C061A0800000000020A
-:10079000061A08200000000E041A1FB000020239D9
-:1007A000061A290800000002061A2348000000204B
-:1007B000061A45B00000016C021A4B6400000000EC
-:1007C000061A14280000000A061A14680000000621
-:1007D000061A153800000002041A15400005023BF5
-:1007E000061A155400000007061A15B8000000127A
-:1007F000061A0AF00000004C061A08080000000261
-:10080000061A08580000000E041A1FB80002024021
-:10081000061A2910000000020200A2800000000158
-:100820000200A294071D29110200A29800000000F6
-:100830000200A29C009C04240200A2A00000000070
-:100840000200A2A4000002090200A4FCFF000000B4
-:10085000020100B400000001020100B80000000124
-:10086000020100DC000000010201010000000001A3
-:1008700002010104000000010201007C00300000C0
-:1008800002010084000000280201008C000000002A
-:1008900002010130000000040201025C00000001BE
-:1008A000020103280000000002010554000000308E
-:1008B000020100C400000001020100CC00000001A0
-:1008C000020100F800000001020100F00000000138
-:1008D00002010080003000000201008800000028B2
-:1008E0000201009000000000020101340000000439
-:1008F000020102DC000000010201032C00000000E4
-:100900000201056400000030020100C8000000017F
-:10091000020100D000000001020100FC0000000103
-:10092000020100F400000001020C10000000002091
-:10093000020C200800000A11020C200C00000A0022
-:10094000020C201000000A04020C201C0000FFFF13
-:10095000020C20200000FFFF020C20240000FFFFFB
-:10096000020C20280000FFFF020C2038000000C607
-:10097000020C203C00000000020C2040000000346B
-:10098000020C204400000035060C20480000001C2A
-:10099000020C20B800000001060C20BC0000005F23
-:1009A000020C223807FFFFFF020C223C0000003F30
-:1009B000020C224007FFFFFF020C22440000000F40
-:1009C000010C224800000000010C224C0000000035
-:1009D000010C225000000000010C22540000000015
-:1009E000010C225800000000010C225C00000000F5
-:1009F000010C226000000000010C226400000000D5
-:100A0000010C226800000000010C226C00000000B4
-:100A1000010C227000000000010C22740000000094
-:100A2000010C227800000000010C227C0000000074
-:100A3000020C24BC000000010C0C2000000003E8A4
-:100A40000A0C2000000000010B0C20000000000A2E
-:100A5000020C400800000A11020C400C00000A00C1
-:100A6000020C401000000A04020C401400000A218D
-:100A7000020C401C0000FFFF020C40200000FFFFA2
-:100A8000020C40240000FFFF020C40280000FFFF82
-:100A9000020C403800000046020C403C00000005FB
-:100AA000020C404000000034020C404400000035BD
-:100AB000060C40480000005C020C41B80000000138
-:100AC000060C41BC0000001F020C423807FFFFFF6C
-:100AD000020C423C0000003F020C424007FFFFFFB7
-:100AE000020C42440000000F010C424800000000CC
-:100AF000010C424C00000000010C425000000000BC
-:100B0000010C425400000000010C4258000000009B
-:100B1000010C425C00000000010C4260000000007B
-:100B2000010C426400000000010C4268000000005B
-:100B3000010C426C00000000010C4270000000003B
-:100B4000010C427400000000010C4278000000001B
-:100B5000010C427C00000000010C428000000000FB
-:100B6000020C44C0000000010C0C4000000003E82F
-:100B70000A0C4000000000010B0C40000000000ABD
-:100B8000020D004400000032020D008C021500200E
-:100B9000020D009002150020020D009408100000C4
-:100BA000020D009800000033020D009C00000002BE
-:100BB000020D00A000000000020D00A400000005CE
-:100BC000020D00A800000005060D00AC00000002A8
-:100BD000020D00B400000002020D00B80000000386
-:100BE000020D00BC00000002020D00C00000000168
-:100BF000020D00C800000002020D00CC000000023F
-:100C0000020D010800000001020D015C000000015E
-:100C1000020D016400000001020D016800000002E5
-:100C2000020D020400000001020D020C0000002071
-:100C3000020D021000000040020D021400000040EE
-:100C4000020D022000000003020D02240000001823
-:100C5000060D028000000012040D03000024024271
-:100C6000020D004C00000001020D005000000002C7
-:100C7000020D005400000008020D0058000000089A
-:100C8000060D005C00000004020D00C4000000041A
-:100C9000020D011400000009020D011800000029D6
-:100CA000020D011C0000000A020D01200000002AB4
-:100CB000020D012400000007020D0128000000279A
-:100CC000020D012C00000007020D0130000000277A
-:100CD000020D01340000000C020D01380000002C50
-:100CE000020D013C0000000C020D01400000002C30
-:100CF000020D01440000000C020D01480000002C10
-:100D0000020D000400000001020D000800000001B7
-:100D1000020D000C00000001020D00100000000197
-:100D2000020D001400000001020D00180000000177
-:100D3000020D001C00000001020D00200000000157
-:100D4000020D002400000001020D00280000000137
-:100D5000020D002C00000001020D00300000000117
-:100D6000020D003400000001020D003800000001F7
-:100D7000020D003C00000001020E004C0000003299
-:100D8000020E009402150020020E009802150020A9
-:100D9000020E009C00000030020E00A008100000AF
-:100DA000020E00A400000033020E00A80000003074
-:100DB000020E00AC00000031020E00B00000000284
-:100DC000020E00B400000004020E00B80000000093
-:100DD000020E00BC00000002020E00C00000000273
-:100DE000020E00C400000000020E00C80000000255
-:100DF000020E00CC00000007020E00D0000000022E
-:100E0000020E00D400000002020E00D80000000113
-:100E1000020E00E400000001020E01440000000187
-:100E2000020E014C00000001020E01500000000201
-:100E3000020E020400000001020E020C000000403D
-:100E4000020E021000000040020E021C000000040E
-:100E5000020E022000000020020E02240000000EFC
-:100E6000020E02280000001B060E03000000001204
-:100E7000040E0280001B0266020E005400000010E7
-:100E8000020E005800000007020E005C0000000F78
-:100E9000020E006000000010060E00640000000456
-:100EA000020E00DC00000003020E01100000000F23
-:100EB000020E01140000002F020E01180000000EA7
-:100EC000020E011C0000002E020E000400000001B2
-:100ED000020E000800000001020E000C00000001DC
-:100EE000020E001000000001020E001400000001BC
-:100EF000020E001800000001020E001C000000019C
-:100F0000020E002000000001020E0024000000017B
-:100F1000020E002800000001020E002C000000015B
-:100F2000020E003000000001020E0034000000013B
-:100F3000020E003800000001020E003C000000011B
-:100F4000020E004000000001020E004400000001FB
-:100F50000730040000C30000083007680013028156
-:100F600007340000314C00000734800035EF0C548A
-:100F700007350000361319D00735800007112755B3
-:100F800008358EE04E24028301300000000000008E
-:100F900001300004000000000130000800000000E3
-:100FA0000130000C000000000130001000000000C3
-:100FB0000130001400000000023000200000000199
-:100FC000023000240000000202300028000000036C
-:100FD0000230002C0000000002300030000000044D
-:100FE0000230003400000001023000380000000030
-:100FF0000230003C0000000102300040000000040C
-:1010000002300044000000000230004800000001EF
-:101010000230004C000000030230005000000000CD
-:1010200002300054000000010230005800000004AB
-:101030000230005C0000000002300060000000018F
-:10104000023000640000000302300068000000006D
-:101050000230006C0000000102300070000000044B
-:10106000023000740000000002300078000000042C
-:101070000230007C00000003063000800000000207
-:10108000023000A400003FFF023000A8000003FF70
-:101090000230022400000000023002340000000090
-:1010A0000230024C00000000023002E40000FFFFAA
-:1010B000063020000000080002338BC00000000151
-:1010C000023380000000001A023380400000004E0E
-:1010D0000233808000000010023380C00000002036
-:1010E0000C3383000007A1200A338300000001387D
-:1010F0000B33830000001388023383C0000001F427
-:101100000C3383801DCD65000A3383800004C4B492
-:101110000B338380004C4B4006325000000000C26D
-:1011200006321020000000C8063210000000000245
-:101130000632464000000040063257F0000000042E
-:10114000063257D800000005043257EC0001028532
-:1011500006321C60000000200432283000020286A3
-:10116000023308000100000004330C000010028864
-:10117000023308000000000004330C400010029805
-:1011800006321400000000A0063219000000001012
-:10119000063219800000003006324740000000B4DB
-:1011A00002321D900000000006321B4000000004C7
-:1011B00006321B6000000020063253180000009821
-:1011C00006321680000000A0063219400000001010
-:1011D00006321A400000003006324A10000000B407
-:1011E00002321D940000000006321B500000000473
-:1011F00006321BE0000000200632557800000098FF
-:10120000072004000071000008200780001002A8D9
-:1012100007240000322900000724800023630C8B80
-:101220000824C930654002AA012000000000000027
-:101230000120000400000000012000080000000060
-:101240000120000C00000000012000100000000040
-:101250000120001400000000022000200000000116
-:1012600002200024000000020220002800000003E9
-:101270000220002C000000000220003000000004CA
-:1012800002200034000000010220003800000000AD
-:101290000220003C00000001022000400000000489
-:1012A000022000440000000002200048000000016D
-:1012B0000220004C0000000302200050000000004B
-:1012C0000220005400000001022000580000000429
-:1012D0000220005C0000000002200060000000010D
-:1012E00002200064000000030220006800000000EB
-:1012F0000220006C000000010220007000000004C9
-:1013000002200074000000000220007800000004A9
-:101310000220007C00000003062000800000000284
-:10132000022000A400003FFF022000A8000003FFED
-:10133000022002240000000002200234000000000D
-:101340000220024C00000000022002E40000FFFF27
-:10135000062020000000080002238BC000000001CE
-:1013600002238000000000100223804000000012D1
-:101370000223808000000030022380C00000000EA5
-:10138000022383C0000001F4062250000000004246
-:1013900006221020000000C80622100000000002F3
-:1013A00006222000000000C00622307000000080ED
-:1013B0000622428000000004062225C000000240F0
-:1013C00004222EC8000802AC02230800013FFFFFE0
-:1013D00004230C00001002B40223080000000000E7
-:1013E00004230C40001002C406221400000000A0D8
-:1013F00006221900000000100622198000000030AB
-:101400000222511800000000062223000000000EF6
-:1014100006223040000000060622241000000030A2
-:1014200006221680000000A00622194000000010CD
-:1014300006221A40000000300222511C0000000069
-:10144000062223380000000E062230580000000655
-:10145000062224D0000000300216100000000020F8
-:1014600002170008000000020217002C0000000311
-:101470000217003C000000040217004400000008AE
-:1014800002170048000000020217004C0000009004
-:1014900002170050000000900217005400800090D6
-:1014A0000217005808140000021700600000008AAC
-:1014B000021700640000008002170068000000901E
-:1014C0000217006C00000080021700700000000688
-:1014D00002170078000007D00217007C0000076C9C
-:1014E00002170038007C1004021700040000000FEF
-:1014F0000616402400000002021640700000001C86
-:10150000021642080000000102164210000000010D
-:1015100002164220000000010216422800000001CD
-:10152000021642300000000102164238000000019D
-:1015300002164260000000010C16401C0003D0900F
-:101540000A16401C0000009C0B16401C000009C439
-:101550000216403000000008021640340000000C63
-:10156000021640380000001002164044000000201F
-:101570000216400000000001021640D800000001E1
-:1015800002164008000000010216400C0000000195
-:101590000216401000000001021642400000000048
-:1015A00002164248000000000616427000000002C9
-:1015B00002164250000000000216425800000000CF
-:1015C00006164280000000020216600800000614A1
-:1015D0000216600C000006000216601000000604EF
-:1015E0000216601C0000FFFF021660200000FFFFD3
-:1015F000021660240000FFFF021660280000FFFFB3
-:1016000002166038000000200216603C0000002036
-:1016100002166040000000340216604400000035ED
-:1016200002166048000000230216604C00000024EF
-:1016300002166050000000250216605400000026CB
-:1016400002166058000000270216605C00000029A6
-:10165000021660600000002A021660640000002B81
-:10166000021660680000002C0216606C0000002D5D
-:101670000616607000000052021661B800000001FA
-:10168000061661BC0000001F0216623807FFFFFF4C
-:101690000216623C0000003F0216624007FFFFFF97
-:1016A000021662440000000F0116624800000000AC
-:1016B0000116624C0000000001166250000000009C
-:1016C000011662540000000001166258000000007C
-:1016D0000116625C0000000001166260000000005C
-:1016E000011662640000000001166268000000003C
-:1016F0000116626C0000000001166270000000001C
-:1017000001166274000000000116627800000000FB
-:101710000116627C00000000021664BC000000019B
-:101720000C166000000003E80A16600000000001CB
-:101730000B1660000000000A021680400000000640
-:101740000216804400000005021680480000000ACE
-:101750000216804C000000050216805400000002B2
-:10176000021680CC00000004021680D000000004A5
-:10177000021680D400000004021680D80000000485
-:10178000021680DC00000004021680E00000000465
-:10179000021680E400000004021680E80000000445
-:1017A0000216880400000004021680300000007C4D
-:1017B000021680340000003D021680380000003F11
-:1017C0000216803C0000009C021680F0000000071A
-:1017D000061680F4000000050216880C01010101C4
-:1017E00002168108000000000216810C00000004AF
-:1017F000021681100000000402168114000000028D
-:101800000216881008012004021681180000000545
-:101810000216811C00000005021681200000000550
-:1018200002168124000000050216882C20081001F1
-:1018300002168128000000080216812C0000000614
-:1018400002168130000000070216813400000000FB
-:1018500002168830010101200616813800000004BC
-:1018600002168834010101010616814800000004B7
-:101870000216883801010101061681580000000493
-:101880000216883C01010101061681680000000370
-:101890000216817400000001021688400101010156
-:1018A00002168178000000010216817C0000000110
-:1018B00002168180000000010216818400000001F0
-:1018C000021688440101010102168188000000010E
-:1018D0000216818C000000040216819000000004B2
-:1018E00002168194000000020216884808012004B4
-:1018F00002168198000000050216819C0000000578
-:10190000021681A000000005021681A40000000557
-:101910000216881420081001021681A80000000891
-:10192000021681AC00000006021681B0000000071C
-:10193000021681B40000000102168818010101207E
-:10194000021681B800000001021681BC00000001EF
-:10195000021681C000000001021681C400000001CF
-:101960000216881C01010101021681C80000000155
-:10197000021681CC00000001021681D00000000197
-:10198000021681D400000001021688200101010125
-:10199000021681D800000001021681DC000000015F
-:1019A000021681E000000001021681E4000000013F
-:1019B0000216882401010101021681E800000001DD
-:1019C000021681EC00000001021681F00000000107
-:1019D000021688280101010102168240FFFF003F24
-:1019E00006168244000000020216824CFFFF003FF0
-:1019F000021682500000010002168254000001000D
-:101A0000061682580000000202168260000000C024
-:101A100002168264000000C00216826800001E00E8
-:101A20000216826C00001E00021682700000400048
-:101A300002168274000040000216827800008000C6
-:101A40000216827C000080000216828000002000C6
-:101A5000021682840000200006168288000000071B
-:101A6000021682A400000001061682A80000000AE7
-:101A7000021681F400000C08021681F800000040F4
-:101A8000021681FC00000100021682000000002006
-:101A9000021682040000001702168208000000806F
-:101AA0000216820C000002000216821000000000E4
-:101AB00002168218FFFF01FF02168214FFFF01FFCA
-:101AC0000216823C00000013021680900000013FC5
-:101AD0000216806000000140021680640000014090
-:101AE000061680680000000202168070000000C028
-:101AF00006168074000000070216809C0000004853
-:101B0000021680A000000048061680A40000000213
-:101B1000021680AC00000048061680B000000007E6
-:101B2000021682380000800002168234000025E48C
-:101B30000216809400007FFF02168220000000073A
-:101B40000216821C00000007021682280000000016
-:101B500002168224FFFFFFFF021682300000000001
-:101B60000216822CFFFFFFFF021680EC000000FF30
-:101B700002140000000000010214000C000000012B
-:101B800002140040000000010214004400007FFF26
-:101B90000214000C0000000002140000000000000D
-:101BA0000214006C00000000021400040000000198
-:101BB00002140030000000010214000400000000C4
-:101BC0000214005C00000000021400080000000184
-:101BD000021400340000000102140008000000009C
-:101BE00002140060000000000202005800000032F1
-:101BF000020200A003150020020200A40315002029
-:101C0000020200A801000030020200AC081000002F
-:101C1000020200B000000033020200B400000030F5
-:101C2000020200B800000031020200BC0000000304
-:101C3000020200C000000006020200C4000000030F
-:101C4000020200C800000003020200CC00000002F3
-:101C5000020200D000000000020200D400000002D6
-:101C6000020200DC00000000020200E000000006AA
-:101C7000020200E400000004020200E8000000028A
-:101C8000020200EC00000002020200F0000000016D
-:101C9000020200FC00000006020201200000000019
-:101CA0000202013400000002020201B00000000143
-:101CB0000202020C000000010202021400000001F6
-:101CC00002020218000000020202040400000001E7
-:101CD0000202040C00000040020204100000004058
-:101CE0000202041C00000004020204200000002084
-:101CF0000202042400000002020204280000001F67
-:101D0000060205000000001204020480001F02D435
-:101D1000020200600000000F0202006400000007E1
-:101D2000020200680000000B0202006C0000000EBE
-:101D30000602007000000004020200F4000000042B
-:101D4000020200040000000102020008000000017D
-:101D50000202000C0000000102020010000000015D
-:101D6000020200140000000102020018000000013D
-:101D70000202001C0000000102020020000000011D
-:101D800002020024000000010202002800000001FD
-:101D90000202002C000000010202003000000001DD
-:101DA00002020034000000010202003800000001BD
-:101DB0000202003C0000000102020040000000019D
-:101DC000020200440000000102020048000000017D
-:101DD0000202004C0000000102020050000000015D
-:101DE00002020108000000C80202011800000002FF
-:101DF000020201C400000000020201CC0000000049
-:101E0000020201D400000002020201DC0000000214
-:101E1000020201E4000000FF020201EC000000FFEA
-:101E20000202010C000000C80202011C00000002B6
-:101E3000020201C800000000020201D00000000000
-:101E4000020201D800000002020201E000000002CC
-:101E5000020201E8000000FF020201F0000000FFA2
-:101E60000728040000B5000008280768001302F3E3
-:101E7000072C000033660000072C800038B30CDA12
-:101E8000072D00003BB11B07072D80002A2629F4EF
-:101E9000082DD6C0452802F50128000000000000EA
-:101EA00001280004000000000128000800000000D4
-:101EB0000128000C000000000128001000000000B4
-:101EC000012800140000000002280020000000018A
-:101ED000022800240000000202280028000000035D
-:101EE0000228002C0000000002280030000000043E
-:101EF0000228003400000001022800380000000021
-:101F00000228003C000000010228004000000004FC
-:101F100002280044000000000228004800000001E0
-:101F20000228004C000000030228005000000000BE
-:101F3000022800540000000102280058000000049C
-:101F40000228005C00000000022800600000000180
-:101F5000022800640000000302280068000000005E
-:101F60000228006C0000000102280070000000043C
-:101F7000022800740000000002280078000000041D
-:101F80000228007C000000030628008000000002F8
-:101F9000022800A400003FFF022800A8000003FF61
-:101FA0000228022400000000022802340000000081
-:101FB0000228024C00000000022802E40000FFFF9B
-:101FC0000628200000000800022B8BC00000000142
-:101FD000022B800000000000022B8040000000184F
-:101FE000022B80800000000C022B80C000000066E5
-:101FF0000C2B83000007A1200A2B8300000001386E
-:102000000B2B830000001388022B83C0000001F417
-:102010000C2B8340000001F40A2B834000000000D9
-:102020000B2B8340000000050A2B83800004C4B4FE
-:102030000C2B83801DCD65000B2B8380004C4B4007
-:10204000062A3D6000000004042A3D70000202F7E9
-:10205000062A300000000048062A1020000000C8B0
-:10206000062A100000000002062A31280000008E17
-:10207000022A336800000000042A3370000202F9CB
-:10208000042A3B90000402FB042A3E20000202FFC7
-:10209000022A151800000001022A18300000000072
-:1020A000022A183800000000042A18200002030148
-:1020B000062A4AC000000002062A4B000000000465
-:1020C000042A1F4800020303022B0800000000003E
-:1020D000042B0C0000100305022B08000100000077
-:1020E000042B0C4000080315022B0800020000001E
-:1020F000042B0C600008031D062A3BA000000014FE
-:10210000062A3C4000000024062A14000000000AB1
-:10211000062A145000000006062A3378000000FC4E
-:10212000022A3B5800000000042A3D7800020325E3
-:10213000042A3D8800100327022A15000000000031
-:10214000022A150800000001062A502000000002A3
-:10215000062A503000000002062A5000000000024B
-:10216000062A501000000002022A50400000000021
-:10217000062A50480000000E022A50B80000000154
-:10218000042A4AC800020337062A4B100000004206
-:10219000062A4D2000000004062A3BF0000000142F
-:1021A000062A3CD000000024062A14280000000A59
-:1021B000062A146800000006062A3768000000FCA2
-:1021C000022A3B5C00000000042A3D800002033923
-:1021D000042A3DC80010033B022A15040000000039
-:1021E000022A150C00000001062A502800000002F7
-:1021F000062A503800000002062A5008000000029B
-:10220000062A501800000002022A50440000000074
-:10221000062A50800000000E022A50BC0000000177
-:10222000042A4AD00002034B062A4C180000004240
-:10223000062A4D30000000040210100800000001C2
-:10224000021010000003D000021010040000003D36
-:10225000091018000200034D091011000020054D5F
-:102260000610118000000002091011880006056D9B
-:10227000061011A00000001806102400000000E065
-:102280000210201C000000000210202000000001AD
-:10229000021020C000000001021020040000000114
-:1022A000021020080000000109103C000005057321
-:1022B00009103C2000050578091038000005057D4F
-:1022C00002104028000000100210404400003FFFB0
-:1022D0000210405800280000021040840084924AF6
-:1022E0000210405800000000061080680000000442
-:1022F00002108000000010800610802800000002FC
-:102300000210803800000010021080400000FFFF23
-:10231000021080440000FFFF021080500000000007
-:102320000210810000000000061081200000000261
-:1023300002108008000002B50210801000000000AA
-:10234000061082000000004A021081080001FFFF11
-:1023500006108140000000020210800000001A8078
-:102360000610900000000024061091200000004A92
-:10237000061093700000004A061095C00000004A45
-:10238000021080040000108006108030000000025F
-:102390000210803C00000010021080480000FFFF87
-:1023A0000210804C0000FFFF02108054000000006B
-:1023B00002108104000000000610812800000002C5
-:1023C0000210800C000002B5021080140000000012
-:1023D000061084000000004A0210810C0001FFFF7B
-:1023E00006108148000000020210800400001A80DC
-:1023F0000610909000000024061092480000004A49
-:10240000061094980000004A061096E80000004A62
-:102410000212049000E383400212051400003C10F5
-:1024200002120494FFFFFFFF02120498FFFFFFFF58
-:102430000212049CFFFFFFFF021204A0FFFFFFFF38
-:10244000021204A4FFFFFFFF021204A8FFFFFFFF18
-:10245000021204ACFFFFFFFF021204B0FFFFFFFFF8
-:10246000021204B8FFFFFFFF021204BCFFFFFFFFD0
-:10247000021204C0FFFFFFFF021204C4FFFFFFFFB0
-:10248000021204C8FFFFFFFF021204CCFFFFFFFF90
-:10249000021204D0FFFFFFFF021204DCFFFFFFFF68
-:1024A000021204E0FFFFFFFF021204E4FFFFFFFF40
-:1024B000021204E8FFFFFFFF021204ECFFFFFFFF20
-:1024C000021204F0FFFFFFFF021204F4FFFFFFFF00
-:1024D000021204F8FFFFFFFF021204FCFFFFFFFFE0
-:1024E00002120500FFFFFFFF02120504FFFFFFFFBE
-:1024F00002120508FFFFFFFF0212050CFFFFFFFF9E
-:1025000002120510FFFFFFFF021204D4FFFF333059
-:10251000021204D8FFFF3340021204B4F00030006E
-:1025200002120390000000080212039C0000000841
-:10253000021203A000000008021203A4000000021F
-:10254000021203BC00000004021203C000000005D8
-:10255000021203C400000004021203D000000000B5
-:102560000212036C00000001021203680000003F29
-:10257000021201BC00000040021201C00000180855
-:10258000021201C400000803021201C8000008037F
-:10259000021201CC00000040021201D00000000332
-:1025A000021201D400000803021201D8000008033F
-:1025B000021201DC00000803021201E00001000326
-:1025C000021201E400000803021201E800000803FF
-:1025D000021201EC00000003021201F000000003EF
-:1025E000021201F400000003021201F800000003CF
-:1025F000021201FC000000030212020000000003AE
-:10260000021202040000000302120208000000038C
-:102610000212020C0000000302120210000000036C
-:10262000021202140000000302120218000000034C
-:102630000212021C0000000302120220000000032C
-:1026400002120224000000030212022800002403E8
-:102650000212022C0000002F0212023000000009BA
-:102660000212023400000019021202380000018434
-:102670000212023C00000183021202400000030625
-:102680000212024400000019021202480000000673
-:102690000212024C00000306021202500000030660
-:1026A00002120254000003060212025800000C86B7
-:1026B0000212025C00000306021202600000030620
-:1026C0000212026400000006021202680000000606
-:1026D0000212026C000000060212027000000006E6
-:1026E00002120274000000060212027800000006C6
-:1026F0000212027C000000060212028000000006A6
-:102700000212028400000006021202880000000685
-:102710000212028C00000006021202900000000665
-:102720000212029400000006021202980000000645
-:102730000212029C00000006021202A00000030622
-:10274000021202A400000013021202A800000006F8
-:10275000021202B000001004021202B400001004C1
-:102760000212032400106440021203280010644087
-:10277000021201B0000000010600A00000000016D7
-:102780000200A06CBF5C00000200A070FFF51FEF0C
-:102790000200A0740000FFFF0200A078500003E0D8
-:1027A0000200A07C000000000200A0800000A00049
-:1027B0000600A084000000050200A0980FE00000C1
-:1027C0000600A09C000000140200A0EC555400007C
-:1027D0000200A0F0555555550200A0F400005555D3
-:1027E0000200A0F8000000000200A0FC5554000008
-:1027F0000200A100555555550200A1040000555591
-:102800000200A108000000000200A22C000000004D
-:102810000600A230000000030200A06000000007D4
-:102820000200A10CBF5C00000200A110FFF51FEF29
-:102830000200A1140000FFFF0200A118500003E0F5
-:102840000200A11C000000000200A1200000A00066
-:102850000600A124000000050200A1380FE00000DE
-:102860000600A13C000000140200A18C5554000099
-:102870000200A190555555550200A19400005555F0
-:102880000200A198000000000200A19C5554000025
-:102890000200A1A0555555550200A1A400005555B0
-:1028A0000200A1A8000000000200A23C00000000FD
-:1028B0000600A240000000030200A0640000000720
-:1028C00000000000000000000000002E00000000DA
-:1028D00000000000000000000000000000000000F8
-:1028E00000000000000000000000000000000000E8
-:1028F00000000000000000000000000000000000D8
-:1029000000000000000000000000000000000000C7
-:1029100000000000000000000000000000000000B7
-:10292000002E005000000000000000000000000029
-:102930000000000000000000000000000000000097
-:102940000000000000000000000000000050008DAA
-:102950000000000000000000000000000000000077
-:102960000000000000000000000000000000000067
-:102970000000000000000000008D00920092009610
-:102980000096009A00000000000000000000000017
-:102990000000000000000000000000000000000037
-:1029A00000000000009A00DB00DB00E900E900F70E
-:1029B0000000000000000000000000000000000017
-:1029C0000000000000000000000000000000000007
-:1029D00000000000000000000000000000000000F7
-:1029E00000000000000000000000000000000000E7
-:1029F00000000000000000000000000000000000D7
-:102A000000000000000000000000000000000000C6
-:102A100000000000000000000000000000000000B6
-:102A200000000000000000000000000000000000A6
-:102A30000000000000000000000000000000000096
-:102A40000000000000000000000000000000000086
-:102A50000000000000000000000000000000000076
-:102A60000000000000000000000000000000000066
-:102A70000000000000000000000000000000000056
-:102A800000F700FE00000000000000000000000051
-:102A90000000000000000000000000000000000036
-:102AA0000000000000000000000000000000000026
-:102AB0000000000000000000000000000000000016
-:102AC0000000000000000000000000000000000006
-:102AD000000000000000000000FE01030103010EE1
-:102AE000010E0119000000000000000000000000BD
-:102AF00000000000000000000000000000000000D6
-:102B000000000000000000000000000000000000C5
-:102B100000000000000000000000000000000000B5
-:102B200000000000000000000000000000000000A5
-:102B30000119011A00000000000000000000000060
-:102B40000000000000000000000000000000000085
-:102B5000000000000000000000000000011A013E1B
-:102B60000000000000000000000000000000000065
-:102B70000000000000000000000000000000000055
-:102B80000000000000000000013E016400000000A1
-:102B90000000000000000000000000000000000035
-:102BA0000000000000000000000000000000000025
-:102BB00000000000016401A300000000000000000C
-:102BC0000000000000000000000000000000000005
-:102BD00000000000000000000000000000000000F5
-:102BE00001A301DE00000000000000000000000062
-:102BF00000000000000000000000000000000000D5
-:102C000000000000000000000000000001DE0224BF
-:102C10000224022C022C02340000000000000000FC
-:102C200000000000000000000000000000000000A4
-:102C300000000000000000000234027102710278FE
-:102C40000278027F00000000000000000000000089
-:102C50000000000000000000000000000000000074
-:102C600000000000027F0280000000000000000061
-:102C70000000000000000000000000000000000054
-:102C80000000000000000000000000000000000044
-:102C9000028002920000000000000000000000001E
-:102CA0000000000000000000000000000000000024
-:102CB000000000000000000000000000029202A7D7
-:102CC00002A702AA02AA02AD000000000000000054
-:102CD00000000000000000000000000000000000F4
-:102CE000000000000000000002AD02DB0000000058
-:102CF00000000000000000000000000000000000D4
-:102D000000000000000000000000000000000000C3
-:102D10000000000002DB0362000000000000000071
-:102D200000000000000000000000000000000000A3
-:102D30000000000000000000000000000000000093
-:102D4000036203690369036D036D037100000000F2
-:102D50000000000000000000000000000000000073
-:102D6000000000000000000000000000037103B03C
-:102D700003B003B803B803C0000000000000000067
-:102D80000000000000000000000000000000000043
-:102D9000000000000000000003C004130413042717
-:102DA0000427043B000000000000000000000000B9
-:102DB0000000000000000000000000000000000013
-:102DC00000000000043B044300000000000000007D
-:102DD00000000000000000000000000000000000F3
-:102DE00000000000000000000000000000000000E3
-:102DF000044304490000000000000000000000003F
-:102E000000000000000000000000000000000000C2
-:102E10000000000000000000000000000449044C15
-:102E200000000000000000000000000000000000A2
-:102E30000000000000000000000000000000000092
-:102E40000000000000000000044C045100000000DD
-:102E50000000000000000000000000000000000072
-:102E60000000000000000000000000000000000062
-:102E70000000000004510452045204640464047607
-:102E80000000000000000000000000000000000042
-:102E90000000000000000000000000000000000032
-:102EA000047604E3000000000000000000000000C1
-:102EB0000000000000000000000000000000000012
-:102EC00000000000000000000000000004E304E433
-:102ED00004E404F804F8050C000000000000000001
-:102EE00000000000000000000000000000000000E2
-:102EF00000000000000000000000000000000000D2
-:102F000000010000000204C00003098000040E401C
-:102F100000051300000617C000071C8000082140B0
-:102F200000092600000A2AC0000B2F80000C344044
-:102F3000000D3900000E3DC0000F428000104740D8
-:102F400000114C00001250C00013558000145A406C
-:102F500000155F00001663C00017688000186D4000
-:102F600000197200001A76C0001B7B80001C804094
-:102F7000001D8500001E89C0001F8E800020934028
-:102F80000000200000004000000060000000800001
-:102F90000000A0000000C0000000E00000010000F0
-:102FA00000012000000140000001600000018000DD
-:102FB0000001A0000001C0000001E00000020000CC
-:102FC00000022000000240000002600000028000B9
-:102FD0000002A0000002C0000002E00000030000A8
-:102FE0000003200000034000000360000003800095
-:102FF0000003A0000003C0000003E0000004000084
-:103000000004200000044000000460000004800070
-:103010000004A0000004C0000004E000000500005F
-:10302000000520000005400000056000000580004C
-:103030000005A0000005C0000005E000000600003B
-:103040000006200000064000000660000006800028
-:103050000006A0000006C0000006E0000007000017
-:103060000007200000074000000760000007800004
-:103070000007A0000007C0000007E00000080000F3
-:1030800000082000000840000008600000088000E0
-:103090000008A0000008C0000008E00000090000CF
-:1030A00000092000000940000009600000098000BC
-:1030B0000009A0000009C0000009E000000A0000AB
-:1030C000000A2000000A4000000A6000000A800098
-:1030D000000AA000000AC000000AE000000B000087
-:1030E000000B2000000B4000000B6000000B800074
-:1030F000000BA000000BC000000BE000000C000063
-:10310000000C2000000C4000000C6000000C80004F
-:10311000000CA000000CC000000CE000000D00003E
-:10312000000D2000000D4000000D6000000D80002B
-:10313000000DA000000DC000000DE000000E00001A
-:10314000000E2000000E4000000E6000000E800007
-:10315000000EA000000EC000000EE000000F0000F6
-:10316000000F2000000F4000000F6000000F8000E3
-:10317000000FA000000FC000000FE00000100000D2
-:1031800000102000001040000010600000108000BF
-:103190000010A0000010C0000010E00000110000AE
-:1031A000001120000011400000116000001180009B
-:1031B0000011A0000011C0000011E000001200008A
-:1031C0000012200000124000001260000012800077
-:1031D0000012A0000012C0000012E0000013000066
-:1031E0000013200000134000001360000013800053
-:1031F0000013A0000013C0000013E0000014000042
-:10320000001420000014400000146000001480002E
-:103210000014A0000014C0000014E000001500001D
-:10322000001520000015400000156000001580000A
-:103230000015A0000015C0000015E00000160000F9
-:1032400000162000001640000016600000168000E6
-:103250000016A0000016C0000016E00000170000D5
-:1032600000172000001740000017600000178000C2
-:103270000017A0000017C0000017E00000180000B1
-:10328000001820000018400000186000001880009E
-:103290000018A0000018C0000018E000001900008D
-:1032A000001920000019400000196000001980007A
-:1032B0000019A0000019C0000019E000001A000069
-:1032C000001A2000001A4000001A6000001A800056
-:1032D000001AA000001AC000001AE000001B000045
-:1032E000001B2000001B4000001B6000001B800032
-:1032F000001BA000001BC000001BE000001C000021
-:10330000001C2000001C4000001C6000001C80000D
-:10331000001CA000001CC000001CE000001D0000FC
-:10332000001D2000001D4000001D6000001D8000E9
-:10333000001DA000001DC000001DE000001E0000D8
-:10334000001E2000001E4000001E6000001E8000C5
-:10335000001EA000001EC000001EE000001F0000B4
-:10336000001F2000001F4000001F6000001F8000A1
-:10337000001FA000001FC000001FE0000020000090
-:10338000002020000020400000206000002080007D
-:103390000020A0000020C0000020E000002100006C
-:1033A0000021200000214000002160000021800059
-:1033B0000021A0000021C0000021E0000022000048
-:1033C0000022200000224000002260000022800035
-:1033D0000022A0000022C0000022E0000023000024
-:1033E0000023200000234000002360000023800011
-:1033F0000023A0000023C0000023E0000024000000
-:1034000000242000002440000024600000248000EC
-:103410000024A0000024C0000024E00000250000DB
-:1034200000252000002540000025600000258000C8
-:103430000025A0000025C0000025E00000260000B7
-:1034400000262000002640000026600000268000A4
-:103450000026A0000026C0000026E0000027000093
-:103460000027200000274000002760000027800080
-:103470000027A0000027C0000027E000002800006F
-:10348000002820000028400000286000002880005C
-:103490000028A0000028C0000028E000002900004B
-:1034A0000029200000294000002960000029800038
-:1034B0000029A0000029C0000029E000002A000027
-:1034C000002A2000002A4000002A6000002A800014
-:1034D000002AA000002AC000002AE000002B000003
-:1034E000002B2000002B4000002B6000002B8000F0
-:1034F000002BA000002BC000002BE000002C0000DF
-:10350000002C2000002C4000002C6000002C8000CB
-:10351000002CA000002CC000002CE000002D0000BA
-:10352000002D2000002D4000002D6000002D8000A7
-:10353000002DA000002DC000002DE000002E000096
-:10354000002E2000002E4000002E6000002E800083
-:10355000002EA000002EC000002EE000002F000072
-:10356000002F2000002F4000002F6000002F80005F
-:10357000002FA000002FC000002FE000003000004E
-:10358000003020000030400000306000003080003B
-:103590000030A0000030C0000030E000003100002A
-:1035A0000031200000314000003160000031800017
-:1035B0000031A0000031C0000031E0000032000006
-:1035C00000322000003240000032600000328000F3
-:1035D0000032A0000032C0000032E00000330000E2
-:1035E00000332000003340000033600000338000CF
-:1035F0000033A0000033C0000033E00000340000BE
-:1036000000342000003440000034600000348000AA
-:103610000034A0000034C0000034E0000035000099
-:103620000035200000354000003560000035800086
-:103630000035A0000035C0000035E0000036000075
-:103640000036200000364000003660000036800062
-:103650000036A0000036C0000036E0000037000051
-:10366000003720000037400000376000003780003E
-:103670000037A0000037C0000037E000003800002D
-:10368000003820000038400000386000003880001A
-:103690000038A0000038C0000038E0000039000009
-:1036A00000392000003940000039600000398000F6
-:1036B0000039A0000039C0000039E000003A0000E5
-:1036C000003A2000003A4000003A6000003A8000D2
-:1036D000003AA000003AC000003AE000003B0000C1
-:1036E000003B2000003B4000003B6000003B8000AE
-:1036F000003BA000003BC000003BE000003C00009D
-:10370000003C2000003C4000003C6000003C800089
-:10371000003CA000003CC000003CE000003D000078
-:10372000003D2000003D4000003D6000003D800065
-:10373000003DA000003DC000003DE000003E000054
-:10374000003E2000003E4000003E6000003E800041
-:10375000003EA000003EC000003EE000003F000030
-:10376000003F2000003F4000003F6000003F80001D
-:10377000003FA000003FC000003FE000003FE0012C
-:1037800000000000000001FF0000020000007FF8C0
-:1037900000007FF8000002920000350000000001E8
-:1037A0000000000300BEBC200000000300BEBC20DF
-:1037B000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF19
-:1037C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF09
-:1037D000FFFFFFFF00000000FFFFFFFF00000000F1
-:1037E000FFFFFFFF0000000300BEBC20FFFFFFFF44
-:1037F00000000000FFFFFFFF00000000FFFFFFFFD1
-:103800000000000300BEBC2000002000000040C0FB
-:1038100000006180000082400000A3000000C3C0DF
-:103820000000E4800001054000012600000146C0C0
-:1038300000016780000188400001A9000001C9C0A3
-:103840000001EA8000020B4000022C0000024CC084
-:1038500000026D8000028E400002AF000002CFC067
-:103860000002F0800003114000033200000352C048
-:1038700000037380000394400003B5000003D5C02B
-:103880000003F6800004174000043800000458C00C
-:103890000004798000049A40000080000001038049
-:1038A0000001870000020A8000028E0000031180E0
-:1038B000000395000004188000049C0000051F8090
-:1038C0000005A300000626800006AA0000072D8040
-:1038D0000007B100000834800008B80000093B80F0
-:1038E0000009BF00000A4280000AC600000B4980A0
-:1038F000000BCD00000C5080000CD400000D578050
-:10390000000DDB0000007FF800007FF8000003E5F9
-:10391000000015000000190000000000FFFFFFFF7D
-:103920004000000040000000400000004000000097
-:103930004000000040000000400000004000000087
-:103940004000000040000000400000004000000077
-:103950004000000040000000400000004000000067
-:103960004000000040000000400000004000000057
-:103970004000000040000000400000004000000047
-:103980004000000040000000400000004000000037
-:103990004000000040000000400000004000000027
-:1039A00000007FF800007FF8000003C80000150049
-:1039B000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF17
-:1039C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF07
-:1039D00040000000400000004000000040000000E7
-:1039E00040000000400000004000000040000000D7
-:1039F00040000000400000004000000040000000C7
-:103A000040000000400000004000000040000000B6
-:103A100040000000400000004000000040000000A6
-:103A20004000000040000000400000004000000096
-:103A30004000000040000000400000004000000086
-:103A40004000000040000000400000004000000076
-:103A500000001000000020800000310000004180C4
-:103A600000005200000062800000730000008380AC
-:103A7000000094000000A4800000B5000000C58094
-:103A80000000D6000000E6800000F700000107807B
-:103A90000001180000012880000139000001498060
-:103AA00000015A0000016A8000017B0000018B8048
-:103AB00000019C000001AC800001BD000001CD8030
-:103AC0000001DE000001EE800001FF0000007FF831
-:103AD00000007FF800000207000035001000000021
-:103AE000000028AD000000000001000100350804BE
-:103AF000CCCCCCC1FFFFFFFFFFFFFFFF7058103C95
-:103B000000000000CCCC0201CCCCCCCC00000000EA
-:103B1000FFFFFFFF400000004000000040000000E9
-:103B20004000000040000000400000004000000095
-:103B30004000000040000000400000004000000085
-:103B40004000000040000000400000004000000075
-:103B50004000000040000000400000004000000065
-:103B60004000000040000000400000004000000055
-:103B70004000000040000000400000004000000045
-:103B80004000000040000000400000004000000035
-:103B900040000000000E01B7011600D60000FFFF34
-:103BA000000000000000FFFF000000000000FFFF19
-:103BB000000000000000FFFF000000000000FFFF09
-:103BC000000000000000FFFF000000000000FFFFF9
-:103BD000000000000000FFFF0000000000100000D7
-:103BE00000000000007201BB012300F30000FFFF92
-:103BF000000000000000FFFF000000000000FFFFC9
-:103C0000000000000000FFFF000000000000FFFFB8
-:103C1000000000000000FFFF000000000000FFFFA8
-:103C2000000000000000FFFF000000000010000086
-:103C300000000000FFFFFFF3320FFFFF0C30C30C4A
-:103C4000C30C30C3CF3CF300F3CF3CF30000CF3CB8
-:103C5000CDCDCDCDFFFFFFF130EFFFFF0C30C30C1A
-:103C6000C30C30C3CF3CF300F3CF3CF30001CF3C97
-:103C7000CDCDCDCDFFFFFFF6305FFFFF0C30C30C85
-:103C8000C30C30C3CF3CF300F3CF3CF30002CF3C76
-:103C9000CDCDCDCDFFFFF4061CBFFFFF0C30C3051B
-:103CA000C30C30C3CF300014F3CF3CF30004CF3C3F
-:103CB000CDCDCDCDFFFFFFF2304FFFFF0C30C30C59
-:103CC000C30C30C3CF3CF300F3CF3CF30008CF3C30
-:103CD000CDCDCDCDFFFFFFFA302FFFFF0C30C30C51
-:103CE000C30C30C3CF3CF300F3CF3CF30010CF3C08
-:103CF000CDCDCDCDFFFFFFF731EFFFFF0C30C30C73
-:103D0000C30C30C3CF3CF300F3CF3CF30020CF3CD7
-:103D1000CDCDCDCDFFFFFFF5302FFFFF0C30C30C15
-:103D2000C30C30C3CF3CF300F3CF3CF30040CF3C97
-:103D3000CDCDCDCDFFFFFFF3310FFFFF0C30C30C16
-:103D4000C30C30C3CF3CF300F3CF3CF30000CF3CB7
-:103D5000CDCDCDCDFFFFFFF1310FFFFF0C30C30CF8
-:103D6000C30C30C3CF3CF300F3CF3CF30001CF3C96
-:103D7000CDCDCDCDFFFFFFF6305FFFFF0C30C30C84
-:103D8000C30C30C3CF3CF300F3CF3CF30002CF3C75
-:103D9000CDCDCDCDFFFFF4061CBFFFFF0C30C3051A
-:103DA000C30C30C3CF300014F3CF3CF30004CF3C3E
-:103DB000CDCDCDCDFFFFFFF2304FFFFF0C30C30C58
-:103DC000C30C30C3CF3CF300F3CF3CF30008CF3C2F
-:103DD000CDCDCDCDFFFFFFFA302FFFFF0C30C30C50
-:103DE000C30C30C3CF3CF300F3CF3CF30010CF3C07
-:103DF000CDCDCDCDFFFFFFF730EFFFFF0C30C30C73
-:103E0000C30C30C3CF3CF300F3CF3CF30020CF3CD6
-:103E1000CDCDCDCDFFFFFFF5304FFFFF0C30C30CF4
-:103E2000C30C30C3CF3CF300F3CF3CF30040CF3C96
-:103E3000CDCDCDCDFFFFFFF331EFFFFF0C30C30C35
-:103E4000C30C30C3CF3CF300F3CF3CF30000CF3CB6
-:103E5000CDCDCDCDFFFFFFF1310FFFFF0C30C30CF7
-:103E6000C30C30C3CF3CF300F3CF3CF30001CF3C95
-:103E7000CDCDCDCDFFFFFFF6305FFFFF0C30C30C83
-:103E8000C30C30C3CF3CF300F3CF3CF30002CF3C74
-:103E9000CDCDCDCDFFFFF4061CBFFFFF0C30C30519
-:103EA000C30C30C3CF300014F3CF3CF30004CF3C3D
-:103EB000CDCDCDCDFFFFFFF2304FFFFF0C30C30C57
-:103EC000C30C30C3CF3CF300F3CF3CF30008CF3C2E
-:103ED000CDCDCDCDFFFFFFFA302FFFFF0C30C30C4F
-:103EE000C30C30C3CF3CF300F3CF3CF30010CF3C06
-:103EF000CDCDCDCDFFFFFF97056FFFFF0C30C30C7D
-:103F0000C30C30C3CF3CC000F3CF3CF30020CF3C08
-:103F1000CDCDCDCDFFFFFFF5310FFFFF0C30C30C32
-:103F2000C30C30C3CF3CF300F3CF3CF30040CF3C95
-:103F3000CDCDCDCDFFFFFFF3320FFFFF0C30C30C13
-:103F4000C30C30C3CF3CF300F3CF3CF30000CF3CB5
-:103F5000CDCDCDCDFFFFFFF1310FFFFF0C30C30CF6
-:103F6000C30C30C3CF3CF300F3CF3CF30001CF3C94
-:103F7000CDCDCDCDFFFFFFF6305FFFFF0C30C30C82
-:103F8000C30C30C3CF3CF300F3CF3CF30002CF3C73
-:103F9000CDCDCDCDFFFFF4061CBFFFFF0C30C30518
-:103FA000C30C30C3CF300014F3CF3CF30004CF3C3C
-:103FB000CDCDCDCDFFFFFFF2304FFFFF0C30C30C56
-:103FC000C30C30C3CF3CF300F3CF3CF30008CF3C2D
-:103FD000CDCDCDCDFFFFFF8A042FFFFF0C30C30CEA
-:103FE000C30C30C3CF3CC000F3CF3CF30010CF3C38
-:103FF000CDCDCDCDFFFFFF9705CFFFFF0C30C30C1C
-:10400000C30C30C3CF3CC000F3CF3CF30020CF3C07
-:10401000CDCDCDCDFFFFFFF5310FFFFF0C30C30C31
-:10402000C30C30C3CF3CF300F3CF3CF30040CF3C94
-:10403000CDCDCDCDFFFFFFF3300FFFFF0C30C30C14
-:10404000C30C30C3CF3CF300F3CF3CF30000CF3CB4
-:10405000CDCDCDCDFFFFFFF1300FFFFF0C30C30CF6
-:10406000C30C30C3CF3CF300F3CF3CF30001CF3C93
-:10407000CDCDCDCDFFFFFFF6305FFFFF0C30C30C81
-:10408000C30C30C3CF3CF300F3CF3CF30002CF3C72
-:10409000CDCDCDCDFFFFF4061CBFFFFF0C30C30517
-:1040A000C30C30C3CF300014F3CF3CF30004CF3C3B
-:1040B000CDCDCDCDFFFFFFF2304FFFFF0C30C30C55
-:1040C000C30C30C3CF3CF300F3CF3CF30008CF3C2C
-:1040D000CDCDCDCDFFFFFFFA302FFFFF0C30C30C4D
-:1040E000C30C30C3CF3CF300F3CF3CF30010CF3C04
-:1040F000CDCDCDCDFFFFFF97040FFFFF0C30C30CDC
-:10410000C30C30C3CF3CC000F3CF3CF30020CF3C06
-:10411000CDCDCDCDFFFFFFF5300FFFFF0C30C30C31
-:10412000C30C30C3CF3CF300F3CF3CF30040CF3C93
-:10413000CDCDCDCDFFFFFFFF30CFFFFF0C30C30C47
-:10414000C30C30C3CF3CF3CCF3CF3CF30000CF3CE7
-:10415000CDCDCDCDFFFFFFFF30CFFFFF0C30C30C27
-:10416000C30C30C3CF3CF3CCF3CF3CF30001CF3CC6
-:10417000CDCDCDCDFFFFFFFF30CFFFFF0C30C30C07
-:10418000C30C30C3CF3CF3CCF3CF3CF30002CF3CA5
-:10419000CDCDCDCDFFFFFFFF30CFFFFF0C30C30CE7
-:1041A000C30C30C3CF3CF3CCF3CF3CF30004CF3C83
-:1041B000CDCDCDCDFFFFFFFF30CFFFFF0C30C30CC7
-:1041C000C30C30C3CF3CF3CCF3CF3CF30008CF3C5F
-:1041D000CDCDCDCDFFFFFFFF30CFFFFF0C30C30CA7
-:1041E000C30C30C3CF3CF3CCF3CF3CF30010CF3C37
-:1041F000CDCDCDCDFFFFFFFF30CFFFFF0C30C30C87
-:10420000C30C30C3CF3CF3CCF3CF3CF30020CF3C06
-:10421000CDCDCDCDFFFFFFFF30CFFFFF0C30C30C66
-:10422000C30C30C3CF3CF3CCF3CF3CF30040CF3CC6
-:10423000CDCDCDCDFFFFFFFF30CFFFFF0C30C30C46
-:10424000C30C30C3CF3CF3CCF3CF3CF30000CF3CE6
-:10425000CDCDCDCDFFFFFFFF30CFFFFF0C30C30C26
-:10426000C30C30C3CF3CF3CCF3CF3CF30001CF3CC5
-:10427000CDCDCDCDFFFFFFFF30CFFFFF0C30C30C06
-:10428000C30C30C3CF3CF3CCF3CF3CF30002CF3CA4
-:10429000CDCDCDCDFFFFFFFF30CFFFFF0C30C30CE6
-:1042A000C30C30C3CF3CF3CCF3CF3CF30004CF3C82
-:1042B000CDCDCDCDFFFFFFFF30CFFFFF0C30C30CC6
-:1042C000C30C30C3CF3CF3CCF3CF3CF30008CF3C5E
-:1042D000CDCDCDCDFFFFFFFF30CFFFFF0C30C30CA6
-:1042E000C30C30C3CF3CF3CCF3CF3CF30010CF3C36
-:1042F000CDCDCDCDFFFFFFFF30CFFFFF0C30C30C86
-:10430000C30C30C3CF3CF3CCF3CF3CF30020CF3C05
-:10431000CDCDCDCDFFFFFFFF30CFFFFF0C30C30C65
-:10432000C30C30C3CF3CF3CCF3CF3CF30040CF3CC5
-:10433000CDCDCDCDFFFFFFFF30CFFFFF0C30C30C45
-:10434000C30C30C3CF3CF3CCF3CF3CF30000CF3CE5
-:10435000CDCDCDCDFFFFFFFF30CFFFFF0C30C30C25
-:10436000C30C30C3CF3CF3CCF3CF3CF30001CF3CC4
-:10437000CDCDCDCDFFFFFFFF30CFFFFF0C30C30C05
-:10438000C30C30C3CF3CF3CCF3CF3CF30002CF3CA3
-:10439000CDCDCDCDFFFFFFFF30CFFFFF0C30C30CE5
-:1043A000C30C30C3CF3CF3CCF3CF3CF30004CF3C81
-:1043B000CDCDCDCDFFFFFFFF30CFFFFF0C30C30CC5
-:1043C000C30C30C3CF3CF3CCF3CF3CF30008CF3C5D
-:1043D000CDCDCDCDFFFFFFFF30CFFFFF0C30C30CA5
-:1043E000C30C30C3CF3CF3CCF3CF3CF30010CF3C35
-:1043F000CDCDCDCDFFFFFFFF30CFFFFF0C30C30C85
-:10440000C30C30C3CF3CF3CCF3CF3CF30020CF3C04
-:10441000CDCDCDCDFFFFFFFF30CFFFFF0C30C30C64
-:10442000C30C30C3CF3CF3CCF3CF3CF30040CF3CC4
-:10443000CDCDCDCD0010000000070100000281703D
-:10444000000B81980002025000010270000F0280F0
-:1044500000010370000800000008008000028100D5
-:10446000000B8128000201E0000102000007021099
-:1044700000020280000F0000000800F000028170BE
-:10448000000B81980002025000010270000B828034
-:1044900000080338001000000008010000028180BD
-:1044A000000B81A80002026000018280000E829849
-:1044B0000008038000028000000B8028000200E05A
-:1044C000000101000000811000000118CCCCCCCC10
-:1044D000CCCCCCCCCCCCCCCCCCCCCCCC000020002C
-:1044E000CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC0C
-:1044F00000002000CCCCCCCCCCCCCCCCCCCCCCCC0C
-:10450000CCCCCCCC0000200000000000000000005B
-:104510001F8B08000000000000FFFB51CFC0F0031C
-:104520008A45D91918FC3811FCA18059981918D856
-:10453000809803883D80B8819181A1919178FDDABE
-:10454000620876BF3003C36E20E611029A23821000
-:104550009F0254F306C85F0F15B312656038263A00
-:10456000F07EA706DE2A8D29364512C1DE86451E5D
-:10457000196F4793FF2289CADF4140FF40632965D5
-:1045800054BE9D22845EA604A1A5D1E4EDA1F2D77C
-:10459000A1FE9251C66EEE0DA83C00F85C49656024
-:1045A00003000000000000001F8B08000000000056
-:1045B00000FFED7D0B7854D5B5F03E73CE9C994944
-:1045C000CE4C4E4212F2224C1288A0210CAF808AAF
-:1045D0007F270122F539202858D40142087983D455
-:1045E0004BAFEDCD8424101135F447058B76885000
-:1045F000D1A20D34D260C10E20147B6D6FF0FAC0D1
-:10460000EAF50B4841312FB1207EC5CBBFD6DAE7A2
-:1046100064E64C2680D8DBAFFFFFFDB4B8D9E7ECE9
-:10462000B3F7DAEBB5D75A7BED3D92750293BFC76E
-:10463000D845FC03E54F4D8CB109C1F26766F680A1
-:104640002787B1C9BDFE3A473C63556D193BA29D12
-:104650008C25EC9921142850FED5232C5082DFBFE5
-:1046600065C397F0FFB619423E7C97D0E911E6C3C7
-:10467000FBE4D5026B873A939C310CEA8CB9194B59
-:10468000642C6B12A33F224B8D82FFE07325398F80
-:10469000B134FC2774754661AEC078C6321E535CD7
-:1046A000D4D0A93815783F847FC6D2BC25B731074E
-:1046B00063CF03BCC971F0BC5A3ADE61E5EF2EC28C
-:1046C000DFA1F33A6ACD58AE303E7732A789654113
-:1046D000BF3EE3F3AC46633D9BD9E34F46C33FEC9B
-:1046E000CC7E518C308F13B18C013CCB540E2F6398
-:1046F000BDB26754101F9B6A58A2322C580F2F85E9
-:1047000065873356035E97ED165C16F8FE396C2FFD
-:1047100031E6D7BE6BD6EA153E5962A3A10404B5B3
-:10472000E4F4EF6711CBBF11F1FE302BA0B24AEADF
-:10473000955580AFAA5A76FB95FEED673389E8540C
-:1047400029B9F65B61FCDE5AE66A86F19799D502D3
-:10475000AC2FFB91D3E5837A6663472183FAD03689
-:10476000818919C1EFAF009EDB917F001E2A2BA526
-:10477000DE420674ECDD2BB0E60C1C87F7BB6C77D1
-:1047800006F3650C0CE758662638E732413A89741F
-:10479000713007D2C1BC24F38942A8CE54DCF3B0F7
-:1047A0007F9FE29D87EDF4E7490BE638BD0057F2A5
-:1047B0005066A057B1B53A9D653256EA692944BEA4
-:1047C00038B5EC8D5558029E1324C0F77C8BA70892
-:1047D000FBA998579DCD80A7E659188D3FB42DFFB2
-:1047E0003309F80CBAF3C5C4213F31763C844FF04D
-:1047F000CFF1115A5D1C98DE972B8BB01F09F10584
-:104800007217011F3F42A026E0284D543A57FC2959
-:104810006BD8A0D0FA5B59C3C66900E511BC0C3F48
-:1048200061AC4308E54BBD1CBA3BFFB0943B303C48
-:10483000FFD3F30474127EAB00B7C81F1576D9BF3F
-:1048400012F861CAABE6C0F7803F2A360B7E0BD464
-:104850004DAFDBE87DF7265E0FD86537F24FD716F0
-:10486000A80BF0BDA5FDF11B91BF5E155933763B3A
-:1048700022CA84FAE5A4063B1B0F75C047B18D57C9
-:104880002B36EFBB1FBF2F69B3301BF457B17BF141
-:104890001D37427DF16133C326155B6BE514A82FEC
-:1048A000F10B2D58EF29E0F0F97689FEADD0BEC7A7
-:1048B000D19E381BE873BAC6CA9C326375F6F6C43B
-:1048C00059C067A5FE1D85F85DE976C185689FF230
-:1048D000EAD643C938AF17B97C976D8B664E1D7FFA
-:1048E000F0F764AB18F81EBC5F06F364D0EF62D635
-:1048F00054887AB062EB3AD9690FE2EB748D4AE3DF
-:10490000F4C9DF8B300E7C57F98AE0C229569A9899
-:1049100017E5B07BB76DCEF30ACEAF56CEB6E3BC8B
-:1049200056CBD86EB17FFE2E54CDA5FECD7221BCE4
-:104930002FDDB4592E0E91DBB26D838C706DC81AC9
-:10494000EC8D20D7417880D7B283F552D403A80FDD
-:1049500025BF3C2384CF2A8558E2CBB26D22731A3F
-:10496000F888D3DDF72EFC13F0E5DB6B27BCEA7487
-:10497000EBD3A71ADDCEA81A1DA5DEBC1911F8F8D5
-:1049800071A403C0D384788272AD069F6332CB9743
-:10499000A07F879BA902BB3C5F3699D97C0663F553
-:1049A000B007DDD2F55097D952E682F550FAB17BC7
-:1049B0002AD49304EF67389F7AC15BC2D7AB9624A1
-:1049C0000FE07995C0E6E0FC8F21D030AF55C9C02B
-:1049D0009F80F7A66979CF8B82067B3CD68B7FB10F
-:1049E0002683FA3943FD98A19FACCBF7A3164E322C
-:1049F000F4A31696E8FDFC8DFAB15D593F4D85375D
-:104A000018E1292CD5FB910468576FBFB279A937FB
-:104A10004F36C2737339F5133BD5C5BC0AAEE71ADE
-:104A20003FB076B708EF95EDB163D7B050BE2850D0
-:104A30000580DB0E5212CA173193A20C7C18EB8E44
-:104A400033D4A127F5E47541FD138895697C394578
-:104A500026BD909F62A5FA43290AE985876EF05E1C
-:104A600083EB208ECD92A12E7B47AB11F81AE01478
-:104A7000581296601724F57FBFDACCF150907A2156
-:104A8000FB187C5F65EACD8E85FA35A6FC6B116F4D
-:104A90002E81EBE528915563BB280B23FDB43A2307
-:104AA000EF795F089E1A8700FD8560BF8D666F12E3
-:104AB000F2D7F8DA677C12C0B76A08CC2705BA12B9
-:104AC0009E09F8603D5A3DA43809F1699141BE4301
-:104AD000C79761FC1C1AFF06C4A31BC74FE83FBE63
-:104AE000257392617C6B7A89617CAB0CE303BF4FC9
-:104AF000AD6DD6C607FCDDC0D834A199C6B7A49762
-:104B0000D0F8AB655662183FAA6FFC5B70FE9E81C1
-:104B1000E69F798371FEE9A5C6F9CB7CFEB36A5F97
-:104B2000D2C68FA2F9CF165EE2F34F2FE5F3B7F0AE
-:104B30007EFBC677F4E1FF5E9CBF7780F12D599331
-:104B40008DF31F5A6E9CBF858F5F54BB531B5FA1B3
-:104B5000F117093BF9FC8796D3F8B2C5EB423E92B8
-:104B600053A3AAFD684FA481400C261DE5A672043C
-:104B70001805A01F860A9904C743519CEFCE450132
-:104B8000BF29417DC7FC2051A0CF2A359E2FDB9E37
-:104B90002FA39EA5F7896837F13F456D22AD376C8D
-:104BA000BDC53F1CE0ED6E137D582F5A7F935FA467
-:104BB000F58EDBE560C605F0F95F9E1CD51C3AAFAB
-:104BC000F0725193F96487418E383CBE0236A21AC6
-:104BD000E06B47269810AC9F043D0AC62F3B0E7A27
-:104BE00014CB53666E8F9C003DCBE450B9A9E5F61B
-:104BF000888FBD9303F3BA5B83FFA4C4F17D72B9C0
-:104C0000E047FC9F5BB75446FDB4A8098CE91079D6
-:104C1000AFD2E8D4BBDBE26F16089F4EC4CF3D2471
-:104C20008A8CFD9766D72FDE30C8F0DD3CE66F48F2
-:104C300082F60BD7CE1FA2C2FC7F30C73216ED53CF
-:104C400090845413C9314B35816F31A7759D391547
-:104C50002AF7CC311BECFAB95E63FD0725C67AB79B
-:104C6000D96F36A1BDB144609BA1DFFBAA8DEFF5E2
-:104C7000713609719CAEDA7877277278EFC3722C9F
-:104C80003E5689AEF7ABFC5B1D9EAA87CD2C40EB50
-:104C9000654702433AFA12C85EF3AA7CDEE1F0DE11
-:104CA0006FB6BA3D00CFFD3F12099FE1F077BC1E01
-:104CB000ED36811DD7B1E14B33DAB7E1F30987FF58
-:104CC0008115E1F35165D4F7F37DE1CF399F84F38A
-:104CD00053555BFEA01321ED2A5ABE3FE844087FDE
-:104CE000956D9B61A82FF1CF35B45FBC61BEE1FD2E
-:104CF000A2A62586F70B1B971AEAF37D3F32B47FF5
-:104D00006045ADE1FD7DD58F18DEFFA0649DA13E1D
-:104D1000D7BBD1D0FE9E399B0DEF4DAF8FBC13E5B5
-:104D2000A8EE5D91E1BA715639F938DA836715C991
-:104D300085F4F8B42689E4E0748D93CAEEB6715612
-:104D40002FD783C50C4C9C5EE19CAF7132EA65465F
-:104D5000FAF3AFC2059F0FEA7F139C843F7183CCA7
-:104D600002C0C2028BEBE3E35E31E47DC765DE6F18
-:104D700000411FD7FFBDD811F97955F3FCA16A0492
-:104D8000FF2128B72C15D7B91E6D7D0F7F5F2E3000
-:104D90004FE873C656929CD769EB4CB9CCF541F9F4
-:104DA000CEE402F4BFCBE54076F5A5C66B01A4A224
-:104DB0009E44EB3C01F901A4C0C02F5906F9EEDC7A
-:104DC00027125C95A81340AFAE639EC126D43381F1
-:104DD00003E9778D4238DC49546F4BA075BDB3664B
-:104DE000FAA01312D2C743E5A73573A83C59E3A52F
-:104DF000F2444D0995C76BAAA9ECA85941E5C735FE
-:104E00003E2A3FAA69A4F2CF354D541EADD940E5E4
-:104E10007B357E2ABB6BDC54F6F92BBAFE8DD7ECC2
-:104E200055CDAF809587EA67B4B9D443DB769273EA
-:104E30005712CAF919E55C36DAE3678E8263993155
-:104E400030BEC2F96D603ABAC95E29F603FDC7F5F6
-:104E50007F6F8BE274B299D87470A6D923C37FE1B7
-:104E60005A9043750959061624D70C7B847E61ED50
-:104E7000437A5D8E4ECCDD9B3B13E871F299BFE522
-:104E800061BF75DAFA177540A47598059E7721BD44
-:104E900042F046EB5AEFAB9ABEBF0CFEBAFAF0D71F
-:104EA0009E8EFEFB4141A5FECFB45A988478DC1358
-:104EB000ED07E667670E3FEF40795C9664524F441A
-:104EC000C0835E56B464A84AE8FAD366AC9F691200
-:104ED000A6B7D07AEC8C99350AF94A554F0C43FAAB
-:104EE0002751A9F7B32C49564F80BC9EDE9615C3B7
-:104EF000D76F3F5F07B7C712BF825F48EDFFDEF095
-:104F00000CD48F0E0F63ADEC132BEA037897F5EDFD
-:104F1000FD7226FD95E2576C8FF91CDA0B16F87BB3
-:104F200091E20712D5F57EAB5A449F65343EDF6EA1
-:104F3000180FBE73EA3EF7C5CC4BF1ADC44E86C424
-:104F400011D669F1C6B26D36D5B8AEC41AEA556D40
-:104F5000C9AA619DC17F80FCB36A4142BE29D7B80E
-:104F6000A847521A0580AFDCE4A47EAB04DEAEC2D3
-:104F7000DA217BE151572BA7DB40F09DAE39EC9451
-:104F800040DE4BACE001027C252D23A7A29EEB6AFC
-:104F9000AD4B447BB04C3CF39027C2F73B4D028DA8
-:104FA000B7C46FEE35AEA31A7F30E8577F4E7E163A
-:104FB000534E86D43B4DDCCE0EEFF780D6EFE5F0B6
-:104FC00053B9FD48E18DCEFE78AA6CFB42F6921CE7
-:104FD000C1FFF28278D2F1576EF21C407D5ABAEDD1
-:104FE00018D9A39F9A7DD90F5F423FF59F9F9244A6
-:104FF00071527D5E3E3029619C055A7C17F8F79E00
-:105000000F613DFDECDFCD6C0DC0C72E402B786FDE
-:10501000D65F331333417DA1565BD05A4671DDCF45
-:105020004CDC8E2A621E07D18135E5A11DD9C54C05
-:10503000D3114F5DEC6DC7B8103A9C32C9A4671606
-:10504000361AED18B07F0DF5C51B8CF5623633119D
-:10505000F549F17A33F30B343FC3FBF74D2AE17F77
-:1050600031AB5E85EBAAA4F9230B5426A5027C156F
-:10507000BF79366F3EC65F4CDC0FD1E3234BE2387D
-:10508000FCA5F17ED90DEF3F691D77F78D48068BA2
-:105090007F15C689580C736D65FDF1FB6DE10F87B7
-:1050A000575FAFFBC5693438C46D82DB1F817F2F2A
-:1050B000687CA6EBEB5B44D5E017DC8DF510BF21D7
-:1050C00046D4E2B2221391EE5DAAD5678AA1F71405
-:1050D000B7F7EDB4B8EA80DE3F3779068913C84EDA
-:1050E000C86521ED7E6EF2D2F34EE1AD62B45B99FC
-:1050F00014C8453B14D618E25359E30731CA918BC3
-:10510000F1663B837514E86F41F8A09F55F692DB7A
-:10511000582EC6BB41DEA1BFC71C858705A8DB94FE
-:105120005686FD59928CF17C9BD358AFC27F201DCF
-:1051300046308A3F458F90C2F01860A80FED2EE3ED
-:10514000F351E88491DD1F203E76108B43695502B0
-:10515000228CCF26499D7DFE5626FA7B1C7E8A2F07
-:1051600040FBE52A6F5FA9C5CF977F503038EE121C
-:10517000FAA8EA3C68904121753DBE7F5E62FE71EF
-:10518000DF416F3A61550DD19B734DDE69480FD4F5
-:1051900093089F00E3780D76609A1A2AE70BC2F80D
-:1051A000E3AAE1886706FD5D6EF2DE2D26F487E353
-:1051B000AAFB4FEAD7FF8248F3BCEAFE87F5EBBFB4
-:1051C0003252FF15BF7979970FF8A9F4574F3A80FB
-:1051D00099D9675253A20BE85EBEB5C18172F9A995
-:1051E000E473205D3FF38BD323C9E71651974FB784
-:1051F00022E411FF101F9D7EE9D13BD0AE3AB7D516
-:10520000AC527C609B256001A6AC6C5DC2E5639BE3
-:10521000E518AFAFFE02F9B3AACDA82F4A5F7832E6
-:1052200011E3CD4049CD7F0E907F50B9E52F8568C1
-:105230007755B15ED27BE1DFE1F8E7E3C81E982F36
-:10524000C7F47FAFEFF3556978A96A7DF40B9184B9
-:10525000A583FCCDF0F6259ABDFFA4688FA738DFA3
-:10526000443611F94CC707F3737BBFEEC5A7738FA4
-:10527000013C9D5BFEDD21E484F227D77B675A1653
-:10528000FEFC35E7C0F2D40D7A31D4AED6D76767CD
-:105290009BE6A7ECE165B939E0403FB07CB3D9E5C6
-:1052A00043BABEFCFC2F9EC1B8CC0716D770E8BF2E
-:1052B000ECE583EFDD00F5B21DE6F8DBF8341421F0
-:1052C0003148972AF8BB626C900EA5BF3E283B4739
-:1052D000F1E73F8E0BD2A36CC73E998DEA8F8F29E1
-:1052E0002DFBE40E25025D5A8E15A23F51F7E257C1
-:1052F00032EAAFCF5E17D8E08C08F8DC7C90EC6225
-:10530000C413D151A3531FDDC2DA57015D50BFEA68
-:10531000740A7FFF2F9AFEC7FE9C39C4CFAFBC86AC
-:10532000FB287FB6B870FE25AF3CE8C0799C92AAF6
-:10533000395F3FDB90E886714BCCBE44954AFEBC9A
-:10534000E4B91F12BF2D3EF2C3448A7F3077B28981
-:105350006C055F32CE6FD1A6D934BF62E625BE2B75
-:105360007956F4E0FEE059894DDF11412E5224AE0A
-:105370008F4F355B704D65A770E1C07D85B745FFE8
-:10538000568AFF2DA5F8CA0FF5FD20B68CEA67AD49
-:105390009C4E5F88FABE1AAC3CA1FCBA65753BD244
-:1053A000E7F410F7608C1B5731C9A7E143B808FD3B
-:1053B0008A47A60DE6F4614E294FFB0EF4FD147CDE
-:1053C0008EEDDBCD6E5BAEE13B76312338FE726D48
-:1053D0007C803B0AEDD5538960FF45985FA1A4AF5F
-:1053E00037605785F057887C7379DFF208976F5DD7
-:1053F000DEFD33A6E3FBBFBEC3E507BF437B05E08D
-:105400000A0CA6F7FB6609A40F2C2C1049AEB7981E
-:1054100035B936BED7F904E09670DDEDE317EC3F01
-:105420008EF04F766CF17AF82E445F56E1788EFE5E
-:10543000FDE972BB5893FF04C928FF6C1397FB81E9
-:10544000FD091F8F4B98FDBF7806E515E413F7AFF4
-:10545000CB5F367B70DE9F6F3FF0DEBD20A79FB72E
-:10546000E8726AD49FE1725AB273028B24A79F63D9
-:105470001A42243985E711E554E9203EFE47E94FF9
-:105480001D7F3785E14FD78703E1315C1FFE5974DB
-:1054900046D487F0E71D96D79FFF74BED3F9ADF4CD
-:1054A000971543293EA6F3A5CE777D7CA9F35DBF72
-:1054B00078A3017FE1EF2D188301B83CBBCD1447E1
-:1054C00028DFC3F77FE1BB43A9E3094F6E5AC658F3
-:1054D000D3A1D4F8D0BA3FACDE12D6DE1D56F78485
-:1054E000B5F786D5AB0DEDCBDB0EC83CAF256068BC
-:1054F00027AE78867D322812BFFAB95FDAFA85ECDA
-:1055000043BE507AE97BF34AE6B3633C7CAF48F193
-:10551000911EC0F12A18A7677B861FF3241A6C3CE2
-:10552000EED4A3F63AD05E6C88E5F5DE047915EA90
-:105530003DFD79AF8DC7F57A3CBD8ED810FBEDD817
-:105540001E91F476879F4D8FE467C28A4272D4C160
-:10555000067ACFE3FDD344257D05C65F9A441786BE
-:10556000748A6AEF71609E41CF9EAC3BE7C0F34501
-:105570006F8AB48DD883767B0C92C72D2587F877F8
-:105580009F32DF5393317EBF87FB79456BC3EC11AC
-:10559000B696F8A958592EA33E05BFECB871FF8204
-:1055A000CB45A9D65FC926E37BFD7BDCC145FBBDAE
-:1055B000748BF1BD578B0734EB7232868DD1FC7141
-:1055C0001E8FD2F4F23431E7CE39408F9EC322C30E
-:1055D000FDFB337B44A2C799ED7CBF9EE2F6D72347
-:1055E0007FF7923ED4F1D489F2240FACAF3A5FFD3D
-:1055F000AFBC87916F767D98FB33283B777D90FD1C
-:105600005BACFFE6FDF40F59FFF6535EB7D13E49A0
-:10561000CFEB76E2F79EBD7F4C7F18EBBB2D149F3E
-:10562000EE79FDAB5CE49F9E959612D4773D438066
-:10563000FE681FECFD2AB783D6D77AA2DB1F259917
-:10564000DB477BFEF6B1108F25CC0AED86D7A34948
-:105650009EAA5EB3513CAD67EF5779A176FF779D67
-:105660004FA5B67FD963677376227CB17CDFA7EA4A
-:10567000B7D73F5F8BF917ADFBE485F07ECAEFBE6D
-:10568000C9453DDAB393DB43DDE68EE7707FEE6814
-:10569000FDDC9566C073370A550AAC9B0DCF14A08C
-:1056A000DCF4C7CB371427BC527CF4FC5F830FC1FA
-:1056B000CDF59DDD6F1570DE5F7FFC21EA85D72D6E
-:1056C000C497FA7C3F6FA9257BE572F37698799CA5
-:1056D000E4FF9D790B812B99F728F33F37BD7F2D90
-:1056E00039892EE172D09FCFF73E44F597ED2E8297
-:1056F000F70AF9FDF67FF2F97F6BBAEF04BA3B2E99
-:105700003FEFF27FF2790F4CF737EFD7E8AE627ECA
-:105710004BD5EFBE21F8BEAD9E5BFB4F2EEF03CD08
-:105720005FB7EBD7985C4D99189F43AF01D669C519
-:105730003EB311C3856B46CC54D1CE14C3F62BF5C2
-:1057400072AF99FB4D22EE5B629C6F088FF331CDF7
-:105750008FA22D3D185A528AC98E959455DCBE965B
-:105760005CED6EC0CB9A6B17B82877888D3DEAC583
-:105770007ADA6417C5AFC3FCC97A81B905B06FA5E1
-:105780006B6F398CFE8D79842960C9A5F21896ABB0
-:10579000B5B8A459950D7E8F9263ACDB9CC6BA4513
-:1057A000EBCFCA38FCD624E6C7F8B43872BF8A7982
-:1057B0006DE218890950B7B1261FFA179624E3F74E
-:1057C0001B31C01E12CFBD5A3CF6F6E1716CBB1BFB
-:1057D000F138D244716B4A2E25BCB8FC6B789E8D93
-:1057E000D588D755ED884F09FD5F6E7F91DFCC34AA
-:1057F0007F59D2BA904698DC36633BCD4FBE2C9D84
-:10580000385DD2CB353A2D33D045A74304FA18E89A
-:10581000A2E3F9DBD2279C2EE1F8DF6F7612FE07B8
-:10582000A2974E9734C5CD505ECD9ABF3015FD4935
-:10583000ACA77918ED336BFE8214EF663EA493EAB1
-:1058400062482FF4DB02E0B7FD7EFBF31427EA7A0F
-:10585000E9D81D084FD96F456605FC756FB7B300D1
-:105860007E2FF965F4434B5B458AFB3329907757CC
-:10587000C8BEAF6EF797FDCA4EF329DD69F1DF06AA
-:10588000DF97EEFA2497ECB095BDE4D7F85E1238B6
-:10589000DD7D1DB9B8AF5B2A71FF239C5F62659EF9
-:1058A00027D0B93B7A0EC66D846D3CDFB6B4E51ED9
-:1058B000B3C5907F66D6DB915EF0BD2850BE13C2A3
-:1058C000179AE7A9FB1D9D2F0A1CBE36B31FF3765E
-:1058D0004BB7EDE8C6F853E9518B0BC3D255DBBE8D
-:1058E000A0FD8D29BF7AD9D141FEB668883FF4F377
-:1058F000FBB789C41F95AD15E487409DF8A2B2257A
-:1059000072FCEB72FE69D9AFF6EEF2010ACB7EFDB6
-:105910008203E35BA7DBB73AC8FFDF76E9B85B3FFA
-:105920003FBFE5914BFAF9A7F11FE0BFDC2087C527
-:1059300049B60D227F04E0CB8B94EFADF35BD9CB5E
-:10594000679FC33874E7CECF9F4378CBFFFBCBE78D
-:10595000D09F60AFDBD4AD889797DEA5389EFEDD83
-:105960002C99C79DBB5F7C81E29FDD1F80DF017F9B
-:10597000BAF79E4A477FB27BC7D789182F59BE779F
-:10598000DA609CEFF257A70C6611F4885E22DFFA0A
-:10599000AF20FE1A4EAF03AD07C8EFE9027AA3DFCE
-:1059A000D917B769A9E07130A716AFD91E39CEDD76
-:1059B0002F3ED37AD79D378DC7D2EC72B22B88D3C6
-:1059C000BC03741C7D05F4DBFE88E67F46A65F17EA
-:1059D000FE03E8B42C8C7E675B17FDFC197CD73A7C
-:1059E00068C0384DE00AF0A6C7D1BF27BB7F22A30D
-:1059F0007CEDFC25C5C5906EB7C144BB5F3E9B8E58
-:105A0000FB0F9F9A7BEFE7E7322C2AC61B4AF7BEB3
-:105A10004FF2D3FDEA118A53332D9EDDCDFAFEF00D
-:105A2000F8A3965359B5C5CEE33B1AFE31FEE37495
-:105A3000D0732DCEC3F9588FFF0C14F7699579DE1A
-:105A4000881EDFAFD8F2A1164F09D24B9884743A62
-:105A500076C9FD081D0F2AE26162681C33727CADB5
-:105A60002FDEADD10BE987F1CBBE3825D4D3306E14
-:105A7000E517DE6711F441F7661EFFEC3647CEA34B
-:105A8000D2E39ABF0A9753FF95C5332F07FFB7C5D7
-:105A90008F5F7652BFE178EABC10598FBF2DF37546
-:105AA000FFAAF7C5CA0543BE41B9C97B04F9B1A233
-:105AB000F598CCCFA5F0F352FA7C3BB5BCD1CE978C
-:105AC000448A77AD6A39407A3C5C5FE8FBA6E1F036
-:105AD0009ED0E0AD6CE3EB44E74EBB5F817E3AF7CE
-:105AE000EF267EAEDC7E8CE26D87B6FD5AEE08595D
-:105AF00057719DF087C0DFF9CABE5C1EB7E579EC2F
-:105B0000E1E39CD1F461D59EC8E3546DFFC2304EF1
-:105B100099AF45E6EBFDA5C73B2DB9EFC1FE4EB7EA
-:105B20009B19E6799E6E11A7473A17F5AEB66EEA55
-:105B3000E77E70BDA47CFD23FC5CCCF8B7A3281FD6
-:105B40007EF991E91FC6C463098487FE5A6B399FA9
-:105B5000B6FEC49D8AF46E3D72AF88EBD42EC46F3E
-:105B6000889D9FF74EF5143BE885BC8F3CE3915D23
-:105B7000C3F5CDC4A32603FC30CE605C07EAA11FA9
-:105B80003CA782F96E088FE8289C8EF088AA49B558
-:105B900009FDE761563C745E40EFD7AC1ACF03B005
-:105BA0000BE39CD84FD24C1E474CBE8B973EFD3C1E
-:105BB0004E7194BF0EE659A078D32CF07D927D7D76
-:105BC000C64186E7BF2651DE7696C5786EAC4B554A
-:105BD0007C26D0DFCFE46C5937D949F907D7584232
-:105BE000F30F582017F9516FD7EF7D587E421A7E78
-:105BF00002FD881A7C595A7EC210D621A07DBDC9EB
-:105C0000CECF270E55E24DF8FDF39ABDA99F3FEC8C
-:105C1000775E31EC9CE2E5CE27C64FC95F3AD405EA
-:105C2000FCB47ACF14CC5F8FBF277F47AA8A791242
-:105C30007F9E82E757E25FC81F930CF513AB1F9C52
-:105C40004AF5FFC81F930EF56F1AFF8DD7CB04CA14
-:105C5000572D583D7A2AF2EB55CBF92CC08851CEFE
-:105C6000EF40BC75793EBA7B9113F31F7A658E5F66
-:105C7000E6C176432671BCA5291FED403C0D357564
-:105C8000D4227FFE7CEF57B1A8179C4C25FCA8AC12
-:105C90005E45FAC1A349172F9147179E4FA6EB9374
-:105CA000CD8AF70184E391F923E85CE0332533AD35
-:105CB0003C5FCF98C7C0D478A26791464F84D31A6F
-:105CC000928FBF58F4C9FC5C4C93A6AFA6AA389E2D
-:105CD000E02B172F5EF7EDE17A50E74BED5C69C8DA
-:105CE00079C687105E9FE27DC892D0FF3CE31D1607
-:105CF000CF0A7C9F5C7C3E1DF95B3F9F187ECE9156
-:105D000049BDA648F65FB376CE7120783D56EF2A9E
-:105D10001C37F377CE9D8741BE4617C92E4CCD1C4C
-:105D2000BD627C82C4CF15529E439546BF24139713
-:105D300043F610A37DD61E8BE046BFB9E74195F42C
-:105D4000775AD16DE457F54467B4603E50CFC3FC39
-:105D50005C29664CA31C0DD9131340BF0FE4E05C13
-:105D6000981C9C33AE73C6717B2E3ADB3AA83F5524
-:105D7000EB0F0CB0C4E0B9E01E91EBE59E1A27C111
-:105D80003184F9F6E1FA7EA5E36DB518CFFD02DEA8
-:105D90005F40BCE878FFE5C0F47B45A3DF2B91E8CA
-:105DA000177EFE74BEC5FB6B6C7FAAF8D02A7415F3
-:105DB000C3CF9D86D3B54A6ADA88AE78E29E2F6853
-:105DC0009DD1E9367A852B411A64A0E3EBD8EFE840
-:105DD0003D5F98105E9D7E4F0F90EFFD070B5FCFEC
-:105DE000C2C74B9CD391E28DB4FE60102E2158CFD8
-:105DF000B5E6D1F8834D3CDED3BFBD10713ED07FF8
-:105E0000E6A5F2307355DE2FE0FFFD50BEFF10F126
-:105E10003F2222FE3F46BC03FE3FC6F65780FF4F9F
-:105E20002E857FDDAE2FD3F44219EE2B01FFFCC58A
-:105E300039333113C62D1415E2FF255B456D1FD292
-:105E40007D5B7262508F2CB9BE7A9F19F870C9B30E
-:105E500002F16991765EFD73ED5C4B785E5FF11C3B
-:105E60001FE9C9CBE7F7F9490F956D333EBF10E441
-:105E7000DB74CAC7F5F1F393A22617E1F83FA368D4
-:105E8000FAA228D6D02E9C0E43AA4D863CF0E429D7
-:105E90007DFD909F976472BE4FF1B53F9819C6077C
-:105EA000DC52FCF800E263BC3015FBCDD7E456EFC2
-:105EB0006FE80AE33A9FE1339EFBCB6A349EFB1BFB
-:105EC000DE9462687FCD864CC3FB91FE6B0DEFAF15
-:105ED000DB36D6501FD57283A1FDE8B602437D4C58
-:105EE000E01643FB7187671AEA13DAEF35B49F783F
-:105EF0007481E1FDF51DA586F7377EBACC50BFA9A8
-:105F0000F75F0DED038BB85EDC5F939486E70A7450
-:105F1000BCEC5F2A9B547CBE34DBA4E6863E4F7407
-:105F20003B73B1CC73A37F3590BC4CB126A785AE33
-:105F3000CFF9CC6CD06B53ACC67A8155E39774E043
-:105F40001720FECD56A35CA556CF6B02B39BA52CA4
-:105F50001946F9D2205FB758B97EBBC57A65FAED0C
-:105F60004E6C7FAA3240E7ECC3E54B44F9CAA2D29B
-:105F700047FBA9CC45F9961B6D463E4D1A40AFCC68
-:105F8000B31ACFC38BEA619B649013FDF9F9A8D0D3
-:105F9000E7C2E2DB286F67A07EE5A405B76E017D4E
-:105FA00029277BA9D49FAF9A638A9897F790F53BEE
-:105FB000FA491BFAD94F0F217EBB92DE7E0AF3CC41
-:105FC0002AE7F592BF946C31E22558770DE67954B3
-:105FD0004E7E8E50E5FFDC54D3782BAEF7FA3C179B
-:105FE0007D303311F303D206F09F5ED5E6F15C4DB0
-:105FF000C9AD45C3B03FD5147ABF457AA0AA10FDFC
-:1060000098A15A1EF453A6C8F94A3FD5FA198C0A2A
-:1060100014ED035521FBA0ABF8238704F3F8779325
-:10602000F7A7C8170B46B7E7F173CB6ED74CB2ABE7
-:1060300054825FD743E98AE729D42BE94912736672
-:10604000F48767F03C6F6306BCAF8F33B914AAF7CF
-:106050000A389EE5C78C0D82F1EAFF5B24F8EAF767
-:106060005F4FF93C16A59AE2A7FA3C99B6DFAFC795
-:106070008BCF26CD8A413CD65FDB776E8761FDAC46
-:10608000E26DC77ECFAE37D3B8F50582E1BD3E6F76
-:1060900069C31D741E2B5DE1F32E867923DC9634D3
-:1060A0000E57FD73024B23B8FEF7D243E8BFEC8ACC
-:1060B0007661BC0DF0B189E8EDCE3867D2270FF3D9
-:1060C000AA18A434AF21FB25B21FFA9695AFDB4C7A
-:1060D0009D9588F654F23546B8C5F566F20717C5A2
-:1060E0002A94AFE0AF59A1D1D538EF554933EF9C91
-:1060F0000BF0D4BD23324CFD7176342D3D04DF15F9
-:10610000B746BBFCCEFE78EF72723801EEB7106E68
-:10611000714321CD9BDA21DC3F17D83319C877DED4
-:10612000E944FF1413C37D9770F8FFD3CAE3C4EFAB
-:1061300058559A879C547CEB9641581691DC1DB5B6
-:106140000EB8CE7F68E5EBFC87D608EBFCE5EEFDEC
-:10615000289FD37E084BD16DD2ECDAEAEC507B1944
-:10616000F4D649EC57AF8B313FCEC57E07B6CB3C5A
-:106170004DD91997B7CBD01E43FED3EDB1BF5A8D81
-:106180007664889EFD4AD3B35F5DA19EBD80ED4ECF
-:10619000DD1B8868C724C891F5DC381BC77F952AAA
-:1061A00033CAE31B209E9F6D8B6C1F0EB40E5DCE19
-:1061B000CFC88CD6F954D7EFDCDF60C532ED2F9C09
-:1061C000D9E07F241BF729E38751DEED40FDA4AE23
-:1061D000F8830DF1ABE36D88CD884FC0A3D3C6F92A
-:1061E000C4698B640F96031E4D063C0EC7F603D997
-:1061F0008357ADDF4B8CE76EBA357C839E9771BCBD
-:10620000AEBB3ECEC3B845E5EC73A4E7AF7A9C398C
-:10621000C67544F7BF611C01E7DF7DD77F6B71B79F
-:106220000E8A17D5BD7A4D0CC6A72A0AFAF48695B0
-:10623000DB8599A407BB7659DC0867571CCFE7ECD0
-:10624000DA35F110C6393EAF399C2985D82D5DAFBE
-:106250001CC933437F5D3B8FE4499420E7277ED1FF
-:10626000DF575CFCCF3C8F123C27D0C76F56BE0E69
-:10627000ADB7F1F8C9D398C7369AB1F7A363F9FA65
-:1062800091687A1C9F47BFE3F3A17E7F5470E5C7F6
-:10629000002B26DD554C66ABE58DA600968F0A6E69
-:1062A00011E355BE91FC3C4D52161B9101FD284750
-:1062B000DB03088EA3A3D78DDB29EAA7EA3E2C0BCC
-:1062C00014EF02C47B5CAF2B097DFC37878DB3A133
-:1062D0005F214DE17AB7777E941FEF294A34B98F59
-:1062E00080AA67670E2F8CC5F77F8BE6F2F258D233
-:1062F00089265C8E7039A038D49B665ADF960D7162
-:10630000272F82EF974D88E77EE905987DC839965B
-:10631000C7E367091407B9007881E714FA023EB5AC
-:106320004BCC173316F4B089B955F00BEC9342EE11
-:10633000D9C1FF6876FC604DFFF6384D3E33E0452D
-:106340007619DBD509EE0C5C4F7781FC0D03FAB4AE
-:10635000D558A97CAD464D1806F2B8A72689EAAFF4
-:10636000D738A90CD48CA0E7FB6B5C548F36B5A74B
-:10637000D37A2C55AF9B87FEF5FD120BBDB723BC1E
-:10638000C47B568E87C8F9972EE69300AE2F353D15
-:1063900052FBD638E2AFA7C600D431FDBFFFD98A81
-:1063A0003F644D053D98FAA3C35953418E9F12781F
-:1063B000FE021E188E742E552F9F32B7C4A2A9F06C
-:1063C0006B1BF34D4DC2BCC8DE3F158E61CCF6E8A9
-:1063D0009FA64E1D09F3C7FDFE14C6F6DADEABC755
-:1063E00073D8A9FB3FAB8B81F9C86DFC3E9F8982B6
-:1063F000A756407D339BF30B933CB598CFD97337A9
-:1064000073E2FEBE3ECE5E1BB71376DBB89D3951FC
-:10641000E0FCC1E6CA5A1E416F6EE8BA11DE3EEFDB
-:10642000C0D7748F0F8CB72FD5305E2FC51107FAE8
-:106430002E75FFD7B48E5CE9773D1F49FC7C84C480
-:10644000F32BBAE6266EA6FD78681FBA8FDA2347CB
-:10645000B6D7DED2D68106EDBEB79F65F07283A6B1
-:106460005724C6F5FF6BD105BF47B961DE38DA5F47
-:10647000AAD3E209933A7AE5F9767E2F5C3ED413EB
-:106480004E78043C0FD7A5D13355601ECCFF486031
-:1064900033840228DD36CFDBD84FD2C24DBE97D130
-:1064A0005ED86571A2D9A3E3ABEE03D98AFA216164
-:1064B000CF31DA8FAA133A64A4F7978F7C4D71CB52
-:1064C0003A737532D56D171BB0FEB4BD7A23D699D9
-:1064D000EFEBA96F003F0CD6CEE1E313D463BB9082
-:1064E000E829583B57EF067ED865E6F52F1F394B54
-:1064F000FCB1CB5C3D9F8DE1F57A98EFAE586FAA69
-:1065000009549052FB65FDE19BB0AEB7FF92DA777C
-:10651000DB546E3F2ADE0CA47F5F5D85BA3DA42E5E
-:10652000F13AB3F2529F5FC581AF297FB8720FE78E
-:1065300047C41BCE13EFCDC375E98C7AD451EBA4BD
-:10654000B87336D7D701039FE9E753B798BC2C2A15
-:1065500044CF5E085BFF42CED9B1A88490FEB43828
-:10656000763A03BB342B186FCD642E2A87310F95F2
-:10657000D9DB96EE47B42DBBAFD5897A2B3ED7FA3F
-:106580008097E868F41F9ED0F4E2FAE8FC1BA301B0
-:106590009EF582778D887AF165B34AE72F3A24B267
-:1065A000373BB5358CAD3053BD5C3BF76D5EE95D77
-:1065B0003312F5EE2293AB19D7B30C4FBE19BE2F91
-:1065C000DB9DE1AA65C1BCE7B2D896C4B14A30EF01
-:1065D00059AF3FAAF1D946B5C986F7D2E8FB439532
-:1065E0006DEBD2717FFBB37D1F903CBD1F95417C4D
-:1065F0005CD17A44F6DA69BF4CC6F3299FD9FAD642
-:106600003F5AF7BE6C19740BEAF52FEB4D74B8794D
-:10661000203DF406E83F3738C8876AAC54FEC25DB7
-:106620007D2D9ADE055129D36C60B4BF90E9569157
-:106630008FE6ADB9A6C10A7CF482AC8E443E9B17AE
-:10664000954B7C5B162B72BE64B907DD92B6CF0DFD
-:10665000F5D43565D3BE533CBEC8686F546D5288BF
-:106660000FC00EC8473EA8DC60F2E17EA2C9DA4E38
-:10667000E77DE74531CD8F369E4F5CAFE93BDF6C60
-:106680001EDFBDDC39C592F351741E51AFBF1FE54B
-:1066900024BE28917CB4FF5572DE41E718BFFB3859
-:1066A00056C379C8FEE32804873E4E79701CD25742
-:1066B000E51FEC273FF88D6B757BD64D71ACE53B44
-:1066C000B4FC059B7B30F6F3B4A62718FAB18077AB
-:1066D00029A3AFEE9340CF1CECD333F90D53D390E5
-:1066E000BEC1F76C92410FB925A0D3C128ADEEFB16
-:1066F0007EE4F65161ED33F5FACC86A993FBC3F342
-:10670000B42D58B7427BE91B4B5F1DE1A373F5A184
-:10671000FDC5E9E3DF4BFDE9FC971AB5F0A00FF8E2
-:10672000EF60AC271FF37C7A673327CAE166498D97
-:106730007285D021358AAF3725E7AF35E03F88F73E
-:106740005C03FD4FD5380DFB8A8B8B96D17998541D
-:106750009D5ECCC7CF776DCA32EC27FE7F38AE1670
-:106760000EF700704CFD07C331C2305E108E1C0363
-:106770007C570B87183B6B7A06DA6B8F98280F28AB
-:10678000D1E4B366A25DF66F268AA70C673C0F883A
-:1067900029E30DFBB4997B2CF331FE9E29B1C3D2C2
-:1067A000589427B7B316D7A99F48645FC173AB3914
-:1067B0000E876E72E3FD4F2095D45F66B9B7821FD6
-:1067C000F2E6FB82FA3ED37095E5E3BDA09BA3E71A
-:1067D000DF188DFB66731EAAC23C98E795F12F3532
-:1067E0003083BC921DD2202C253BE3ABA8871B70C5
-:1067F000BF767014B75B04F670C3E1E448EFB9BC30
-:106800009E5BF3F0348C1B34AF745E8BFE53B3CDC0
-:10681000DFB21FF3761E53E8DED6AC47FD8D9950EC
-:1068200017D79968BD1463FDDB9A71DFFDC96C173A
-:10683000DA11CD68BF60FB4714F26B56D538D3F040
-:106840007E923A6D1DD8B276B28A79C1F58A1487E4
-:10685000EBDD2A73F55C3C7731EED18D0DD6EB5133
-:106860008FB91A07A9BC9E948CEB9A33D33A467B16
-:106870000FC868AE75A6A8B1C1FAF06FC0FA203D86
-:10688000B3B1C19D86FD2E2BD5FA3B88718A17E2E4
-:1068900034BC68EF33FBF4D2C606CCCB126B83F565
-:1068A000A930DFADCF723D3518FA47FB0BE6E3C3E5
-:1068B0007B057B874B744ECA06633B607EB691991D
-:1068C000B4DFD70C7A11EF2BEE1DC9DFEBFB34F2EE
-:1068D0007013EDD3607B5C6F6CC9BCBD3C83DF572C
-:1068E00020DB158A37C07A3015F39E14A6FF71F3AA
-:1068F000B8A4B68F1185F70184F0A375ED323AF78D
-:10690000691D66DC9F97D38C75897916A0BF27AA6D
-:10691000C6E737466BF94183580ADA6DC34D3E131B
-:10692000B61BC9FC545EC702648F8D621D541F8D57
-:106930005E63161E5B72D241AB71CC2DF238AA4752
-:10694000443B3171AE1E47F24E41BE74476B7661D7
-:106950000AEF3F7EC62CCAF7F569EFCD33863D318D
-:106960000DE6B57EC6DDCE50FB4E5F2F75FBAD4804
-:1069700083F9CB6821A2BDA0DB7545365E4F98E553
-:106980007E7A14C611DBCD26BC9FAD588B63166F83
-:10699000C84F44BBAC68DF5CB287D74473BB6CD1D3
-:1069A000FA19B277149EF79A4F767FFEBA0931181A
-:1069B000A76FB0B962AE47FEFD23BFDFF54AEDB168
-:1069C000E6C46B0A501E9BC1AFC6FB8F0E9ADDCA90
-:1069D00018E48B75C3C8CE6C8EF2D6C742BFCDFF0C
-:1069E000EA74D541FD6736F7F823384E43147F8F9C
-:1069F000F726216FF6EDF73F2F5C8C1E78FCF0FD3B
-:106A0000FE83B191EFF1BD43C35FD0FEF090DDD9BD
-:106A100060F6C4DC87F0BDCBE779D6EA89512F1147
-:106A200067FBB486E70376D6B85840E6F7D162BD77
-:106A3000A4683FDDAF5CD22250DC7C096B223D3A7A
-:106A40004C89D5EEA731E6C59616BD4DED4B5B7969
-:106A5000FB32D642ED757AE1BDB501831D3ACEF029
-:106A6000FD1DD1DC6FDDAC781F43FBFF9119D9C44C
-:106A70004FC06711F32DE207D877B9319AAF1F37AE
-:106A800062DBC8F628F163B87DB85CE0E7B307C203
-:106A900053D57993613D0ADE9F21D37AD4ADF9496C
-:106AA00087937CEB6F84F97F9FF54A24A7DABD2397
-:106AB00075825F42F9FABE33ECDE1B2D0F68BAA671
-:106AC00025FE43CBEFF93E6B79C30DFDDCCE02F41E
-:106AD000DD61ED9E1214A4487919D0AF411FDC3A54
-:106AE000C258BFDD65ACDF3929F23D7D6B6BD4B494
-:106AF000D07BAAD60E708EF32D8D5E577FDF120BE2
-:106B0000CFEB7B0BE95E81F994B47FC1F3FA141BE0
-:106B1000F3A01ED9BFCF46FB21558ABC1943165599
-:106B2000E0EFE2BDF08A9D9F3740FF17E3058A99A9
-:106B3000B70FDE97C4F751123C495A3CC3953463F2
-:106B4000D4B7871BFD2ACA0B96D846DC770DE627FB
-:106B50001AEFEDE88AFE380FFD6398CF6C8C4FE892
-:106B6000715A7D3EFF287F2C5ABBCF399C6E6B3407
-:106B7000F9A80BA3733DD23907DF73B9F952BB876C
-:106B8000FF29C143796889261E17ACB3B98E529C80
-:106B900044F30FEAB4B806F37D5DEF56C2EC9510EE
-:106BA000FF227DEDD7F5F539E477F338882D6A15A6
-:106BB000AEC30D36BD6EA6FAD3E6A600F9FDAF5AF8
-:106BC0009C181F83EFDD1867F3CD1D417E5D5D06C8
-:106BD0004BC17B0EDEB0CBB4FED6BD6A69C6F5D81C
-:106BE0006DF376DB42F249BAECEFD1F9A608FDF974
-:106BF0000CFD0DF976FDC1F8AD8877FDFD1BF6A7FC
-:106C00000222FFCE49F91B69ED1F7BA19EB8CB4242
-:106C1000714FFDF70FCACFE7D1FD8C7A7F13144E69
-:106C200087CE1AD5908F5D8E7A3707E5A09DF467E1
-:106C300045CB2083DED4F569C5F91B68BF2C4857C6
-:106C40002D2E21B5935EAA38FFBF68BC3B909E34C1
-:106C50004E12E9F781C74935E8E3E038930C70F745
-:106C60001F6732C1A18FC3DAA20CE79FEBCC3CAE09
-:106C7000726698332636821ED14B7183C970FF60CD
-:106C80009DE4B262FF75CA4E35347F287C5F00EF09
-:106C9000C56421F0D5C17A86C1720BF3525E403DC6
-:106CA000F6132207A2D9A562BF62C2F8E9F92EC67F
-:106CB000FE45B9BD107D7233F22DD88B3F583B7E17
-:106CC000950FEC49C9EC6947BA4A769313F3686BA0
-:106CD0001513C545EB92AC64FFAD12CA559473BD54
-:106CE0005FA9432238F47D8F81E6299F77D03CC38A
-:106CF000EF3BFB9F1B4FA176FDEE573B30D7930F29
-:106D0000FD5B54930B455D4E53D82721F40FEF479D
-:106D1000DA2045EC27BC9D8EFF01E96CEE70203D2A
-:106D2000BAE3A58879101B95EF9807312F4C1F27E0
-:106D30001CCD0EE0F74287232383F4E54605F5A535
-:106D4000FDCC9FDC4ED2CBB4EFADAF7FE684A9562D
-:106D50009E4F6CBC576F20FED3F1627DF341C6F3AA
-:106D600053BD947F72393C4882CB43FB007629E2C5
-:106D7000BE36584286FC384931E64F35481EE2633C
-:106D8000F34DD556DA27495B69C57D92D592330616
-:106D9000FDD8DE37C1FE83F9353A79BE6A78FF6BDC
-:106DA000F01E66B4731553C4FB79A306B0AFBA34B2
-:106DB000FAACD97769FE01F5E1C175372A4E5271F7
-:106DC000DD359B39BC03AD4B7ABF03E1EBD17DFCD4
-:106DD000F71B2C39563FAEFFE1E3354A1E4F3EBC50
-:106DE0006F047870DFAC31CD4DF86D542515FDD5AD
-:106DF000E81151CC1AEA6F65CCA2F767E2E3F1CC57
-:106E0000226B8C8F9C97A3E369B7F21DED1D6F1861
-:106E10005F0E7F8FE2E8217CD9A94CE8CF97BB9128
-:106E2000171338FCA1F7A65A338645BC7FB21F7FE3
-:106E300086F14DDE6446E7F70643B919FA6ED5EEE2
-:106E400043AAC0B50BFCF4F27B14A6C2FAE677E4C1
-:106E50005F4039C96BDFCFCFD1B426F07B1EB5EFD1
-:106E6000C3C75D62E7FEC812BB4A65CC51F72FF17C
-:106E7000F7375ADBA39C785EB1352EB21F9363D7E8
-:106E8000F3689AB473081DB44FA1B7CF9BC7DCCD8C
-:106E90000AC53D1BADE07F25F4B5FFA9B63F0282D0
-:106EA0000BE3DCF9DBEB9AF9F9513E7F8CAB62FB2B
-:106EB000C4C48E5C41FC0E74DBC60CF7DB55583B3A
-:106EC000B251CEE79ABC997618A7EA684722D65BFA
-:106ED000DF3E9D4E7E6F1DB7377B774753DCA03F6B
-:106EE0007D6AF979F2F329CC37A83FDDCAA500AD58
-:106EF000ABE5E7D3996F1CCDDB678D0BBEBFD3C26B
-:106F0000D8A4B1C8001C4F889F48F430DB4D067AE6
-:106F1000803C5E67D7E88178EAA3B776EF4BA77627
-:106F2000BFE071CD5F612AF7D7F5FBA58E67F7E566
-:106F30005BD07D5BE536F713784F0B3B2252BEE604
-:106F4000C229FCFEC48516770CDA570BFF53146A6E
-:106F5000697F93F3FD220D7F9DCC45F70EF8D6DABD
-:106F6000F8BE4E987F96F154FEB83FC2F78BDA44D4
-:106F7000CA1B5F3045F161BF79ED05BFC4FDF9E281
-:106F8000C6683A77BEF07BAE9368D72D7CC2E6C464
-:106F9000DF7B59FE41667E32F4BBFCC90CD507DFAE
-:106FA00045AFF024595DA0271FDB53887E45833011
-:106FB0007FBE3006FCCAC70EACC2B898F4CD94CFE1
-:106FC0006D507FF4B1775661BCE9B718E7263BF600
-:106FD000DD42B4635F42D0F4FD3FC0C14B874D5AE0
-:106FE000FDC4AAA9A0F2AF4D6835292AFA65275633
-:106FF000E139D9C438F718138CF78EFDB342EC6F22
-:10700000C113A3CE6D80F7E7ED17C8BE003A69DF64
-:107010000B374F01BBBB78B25E972D588F8F6686BA
-:1070200038BE3933383EDAD9AD7A7C8B45DD8C7188
-:10703000F7E305D55324E83FC3A1AECE19C9D8C4A0
-:10704000F5F9AA1BC6CF76C4DD8CF198D6BE7D8338
-:10705000F8D5181F6B65DE0366787FD3E3436EB601
-:107060000262E30779C6A830FF41D629ABA7DFF457
-:107070001DE46344BFF3590DF60492934388D2F4A0
-:1070800015FCDEC23EF94EE37CDB571FD1C1CFC3F6
-:10709000E8F5245E6F5D19595FDC12C3F9BA352A31
-:1070A000F2FB664D3F00BE03147F6D8BF60FCF08D9
-:1070B000EA0F901FEB2492A7755C7F801CCDB493E0
-:1070C000DC46ECEFDBCA6BAB76AF79ABE48EC6F88F
-:1070D00082AEC7308286E3CCB53B0DFA39AF7D0175
-:1070E000E9D751312A87C7C9F19330C5A84798B568
-:1070F0003D3B74DFFE77DA3C33AED3E33F013974B6
-:10710000DF69F98EFC4B9E9F2DC7387F88BD1D9C83
-:10711000C7548A67F4EB17FA736AFDBB72AE045F5B
-:10712000EA65F0154FF8BADC3C83FD19E32FFDFB4F
-:1071300093B57DC126E33A224786F3A4CE27807F0C
-:107140005388FE2CD6F4A99E07D1BD6B24E54F06CB
-:10715000C7E5E73181BEBFC4DF5DF2813E453D96A4
-:1071600027B96FC5F679ED712ADAEFC06FF51ABF4E
-:1071700049C86F3A9D5BE3AAF369BEEB04B24BFAD0
-:10718000D941DA3A9AD724D0EF990D9EE715E787CF
-:10719000C0A7EB7BE8BF55EB7F3CE7E767FBF8F95F
-:1071A0003E941FCD9F67AE0EBA5F3D1CFE852873CF
-:1071B0000921EBD5AB368AEBEB78BB5AFED7ED85D0
-:1071C000F201D725077D37F868C0E184768B511E20
-:1071D000505FB57C42F764B6B6890C7FB200E78D8C
-:1071E0007A234FD793BE95870A24B25B827AD94916
-:1071F000F68BAE3703566BB0FDB9B52B0BEB51AF29
-:107200006AF7ECC78BA0C5C706E1487370BB7792DD
-:107210009745FCDDB81CBB5DD723348F8D2B0AE866
-:107220005E852A6D3D9DD4E1A3785334E27142100E
-:107230001FFA7A7DA7A5E315EDBC97811FF53AD813
-:107240002595A6AC60FFF87E6608DFE739381F8415
-:10725000D3E7BBEA27C0830FF1F0430DEF0950C716
-:107260007B2D9804EB17E6FDCC505C6B3242E05668
-:10727000B83E4E104D5C8F5D462EE20731EDF7585B
-:10728000EC24CF417C70BBE5018716E7D5EE293FA2
-:10729000680239A17D363ECFEE5DC9D4EF6CADDD1D
-:1072A000DF4B2F6FD6F296747BB1E2B5D4CD46F8A2
-:1072B000797FBB1C1C2F7947DD63D08E19EE515CA2
-:1072C000E81FE4B5CFDC8FF924D97BF00704827C7A
-:1072D0009EDDC2E514B84BC3CB9BDB43FBAD74D83A
-:1072E0007539FBBBCC23FB28E757A4CB7D21725A11
-:1072F000E35038BE607E16C4A764D4A37AF9F7833E
-:10730000C3B31FCF2595033E506DEB786B6D99BFCE
-:10731000D286727C94B9508EBB5BE69B46215D3170
-:1073200011CC19A21FD6F379E87628F0650BF2E5A7
-:107330003AC7101A6FF85177740EBC1F8E7613C6B9
-:107340007D5BEC7EF423FC0EEF2E07E27356EF1408
-:10735000DC4FAD8CAEAEB5853CEF6BDF06ED898FB3
-:10736000BD22EE1F953FC0F8BDF1DA7CA0A9CF0287
-:10737000E355C820A759540F20DE5A65DEBEF73EFC
-:10738000FAA5115629F27BF960FDBE95F8F36D530D
-:107390001CD217FD24B493CB454F1AEE7BB2C11615
-:1073A00017AE03E07710BF1FB431C906FDFF1E4AB8
-:1073B000D4D3D3C4A5748E6B5A9640FB44BA7F8F46
-:1073C0007A0BFDA43BBF174DFCC82E3C380CE3D311
-:1073D00009D19C4ED08F55EBC76A1D1B94BFFF4847
-:1073E0001F49FE8EBEBE1D1404EAE7E04DD735D717
-:1073F00085F841D81FEAFF83C28CB4A5C8FF9A1F45
-:1074000047F6617C70DD457B65AC21CEE6D3E0EBD1
-:1074100048473E0AB547D13EEDB3677DF357DF0CD1
-:107420007A76E2F496005E715FCB8A6EFE17E86FA3
-:107430001AD8B336C0C33E8D2F0E66F844DC4F3DDC
-:10744000385CA0FBDC0F457973AA95E038895A5C5B
-:107450002051CB334F8CE2E50F62B81EFC3C86AF67
-:10746000D737A8BC9EE8881C4798ADBDFFA989EB1B
-:10747000F735F991F3D14F68FAF5AAEDDE1C21FC3E
-:10748000BEEE138E09DA7DDD946FC7E3FD0B34FE8B
-:10749000063B87E814B4ABF87E9D6E879E6D9F4DCA
-:1074A000F51382F7BD7B042C3D4F909FF4AE48F15D
-:1074B000A1E2586F22E6A55544458ECB0CD2F0F4DC
-:1074C000590DA338EF29DCCFCBE6BFB785F5251BD7
-:1074D0009EA47B1D4A999FE2BD451B1A68BFAEC89A
-:1074E0002F30A780FE9987C781353A946E110D71B0
-:1074F000E7C552B51C9B13E45BFC1DAED0F7259B82
-:10750000C619EA576F971618F23B827AA790ECBF1C
-:10751000F07E753E0FB74F8FD7380DF1EE051B8605
-:1075200017F2CD78DE7E2173D17C17366619EF1104
-:107530006E4CB8B27B82C11EF545845326FDA83F30
-:107540003F0EF8F785C4F7177C3A8CE0F88BC37BC5
-:107550005D8C018E68E633C4CF26F3DF29B4F1F8E1
-:1075600023F08FEF5276407ECC77F507AE1DC01F1B
-:10757000C8FD87FA037993B9FE654D02E5E04C9C9E
-:107580006AB4CF66C7F0756E764CB4C13E2B9A676D
-:107590006C37576B37576B77B9384AA85D2664A1AB
-:1075A0003EE3FDE9BF1F9571FA6DCAFFDC10C3ED24
-:1075B000D79FAA6E6F0CF4BB563B77D06FDEDAEF25
-:1075C0004AAD35F7E585525EE0E66F1EACC3DF09D4
-:1075D000E9DD01F63FE8C1FC67DFA07BBAF4EF6E9E
-:1075E0005FD132B408F054A9C973B98BCFAFDC15A1
-:1075F0009087413F29E51CAEB4967D8214F25D5A16
-:10760000096FB722C66CF02F7FA2D5FF35C649653A
-:107610005A49401806ED52366D1124EC0F7F570B76
-:10762000E049A966FED0DF934A19CFED9ADBC76F18
-:107630001616E604F1D0689A91A3625C3531DA85BA
-:10764000EBCC47AAB70EF150FE5180CE494CFCA8B6
-:107650005D42BBBD5B75D7237FEB78708A6A0AAE4B
-:10766000A3D11F71389BFAFC62BEBE30F6A86647F4
-:1076700037EB76E961C6ED425AA712578E30FC3ED1
-:1076800061629CB64E2432EF4E85DA3732A227A3D0
-:10769000F924AECC6EE6762CA7F7B42CCF167C3E40
-:1076A0006DF0C8B178DF47D6DA8084BF3BFEDA26BA
-:1076B00053C4FB519A35FCC33C9EC5F9E9F3B89C11
-:1076C0005ED0DB9907884FE8F2103D3DB2DFC1D8AC
-:1076D000E3F43EFFD9F87BE9FECA7A997E4F4EC7A4
-:1076E0007FB7EA6941BCA6B46C160837DA787ADC51
-:1076F0000E9FA35C1E978DE73A0794FB153B8716F8
-:1077000085CA7DBD4CF4D91C96E7AFDBF77F88E1D5
-:10771000EBEA9058CF3EC44B65DB3A8AEF2CD9C2D6
-:107720007FF76740FC5C21FE8412EE0794CFE1FBFB
-:107730005EF9CF4A44FFB27AFEFBACE5DB77F0B8E6
-:10774000CE8F990BF54379CB0EA128077F0773875E
-:10775000B028049FA9E57ECA83BFC6AECB1FD75B06
-:10776000E1FC8E7162B4530ED9B87EE8CC577CB878
-:107770001FDC69F69663BBCEE46817E677E9F8FF8D
-:10778000FD8E9BE9DCB57DA7258065A3A939C98A53
-:10779000FB0ED7CA2EE4AB6ED57B12E91327795ABC
-:1077A000F1FBD878BBAB16BE755AD85855B9723CA8
-:1077B0004C0CE38F893FE67293A43AF4BC86B12463
-:1077C00037AA9DEB2D13D76787CC7C1E3B1987F713
-:1077D0000731EEB3248787E368DC94F2009D1FCA6B
-:1077E00038BDD370CE30C85FEEBF7D1B7EFF3F2C0F
-:1077F000A14B2800800000001F8B08000000000043
-:1078000000FFD57D7B7C54C5F5F8DCBDFB0AD90DA6
-:107810009BF73BDC100C28246C9E0401D924848740
-:10782000206E0228C86B7947926C02D2FED0FA6DA6
-:10783000168331E56B6BD41645A92E8896B65A830C
-:10784000A2060DB82822D64723A58A2DDAA5202224
-:1078500084641BFBC056CB6FCE9999ECDE9B0D0F59
-:107860006BFBF97CE18FC9DC799F73E69C33E79C65
-:10787000991D33B5CDA88C22A4A69A38BC342DFD11
-:10788000E90EE98485900BF06F2221836C3221F19F
-:1078900084A43CBD4D522C58BE7F5A1CD6272605C9
-:1078A000BE4BD8AE8696AFA0A95B22848C25E4A0FF
-:1078B0008178CC3184B4E82A47D968FD9684487B26
-:1078C000132D3B667345DB687F96639D07ACB4EA76
-:1078D00098633EA38BF64BDAE9C76442DE3012129E
-:1078E00041DB1D8C60EDD36D74902242261B89070D
-:1078F000BF1B3D2314DADFC1A183B0BF97B7EAA64F
-:107900007A697BC320B2D81932EF749B0EDBA56C69
-:10791000DD21E9E8F7B8485A1E323F51EF015B59C3
-:1079200026CC67CCD44E8443DD563DAEA7C2E81CBE
-:10793000B66654B0DE68E88FD67BEDE64F8C7EFAF3
-:10794000FDC72FBD6F2450BF5572B4C1FC5BDF373C
-:10795000CEC9A1A9E7E7324920643A61FF36BFF0FA
-:10796000BE51A1DFA7EFA670A2F5EA76EFD22FA352
-:107970006957A9C5238D2624F3CC6B8B4821FDDEE6
-:10798000662211746EDD3657918DCEFBCD5D530EA0
-:10799000495184589F33F92015F021C49FE1B40662
-:1079A000E725523A30CE2F722AFDB310B246EF557A
-:1079B00099F0DD955945EBB7C630F8CC1FCCE042C5
-:1079C0002CEC7B155F97800B1D7F0A8C5F91E5DCAB
-:1079D00001FD542446D89B32619EF9AF9929DCEB16
-:1079E000EC923D82568D2B67F00C9D57654EB87911
-:1079F0006DC0F1E263D9F844EFCF807109F1B2EFC5
-:107A0000326921F9C1F67338BEE9771FFB4E863A19
-:107A10007382F3D7E26F834DC2FA61E86C11ACA3B5
-:107A2000F698CFC7E8AC530F749679E630E243D0AE
-:107A3000CDCFB6EA3115FDD5D98CD85F9D4D8F706D
-:107A4000D90C781A4C53032C9AA61BCC5E0F85C711
-:107A50009BF3261F9272297E6E31FA207D43B7B4C4
-:107A600016CADF4861E3B7E8746B21DF729785348B
-:107A7000215E1D6E98CF6B3747217E6AE71ABD26BF
-:107A8000DACF8F9F9758DE63F112FA67AD6BF6720B
-:107A90006847E222EC4F02FE5C078C73ACFDE94ABA
-:107AA000796EBF51A1DFA7B7B1FD27F050DBC6E863
-:107AB0004BEC0701D7203CBDAAFD24F0317FB08DEF
-:107AC000D105A5178077CDCE08DB49331BEB02012A
-:107AD000FA8C56E5EBDB936D274704F335F007D0BE
-:107AE000C10E628179D6F279CED3B9EE83FD5567A6
-:107AF000F61F3450D4161F0DE07E1F887E6BD6FF14
-:107B00003AFB640121AB930E612AF6AD61A87A7F3E
-:107B10006FE5786F8294B67B82D34D4D611BEECBBF
-:107B20009A930DB89F2D53195FB31C238E503C13AD
-:107B3000F243BEDE7BB17D4564DB6499C2BDE27178
-:107B4000C9D644FACF4FA4AB24E26CA3FD7DB6F5B1
-:107B5000F5A82500DFAF2EC8A498AE3782AD7737E1
-:107B6000E73B5D3B29C091DE1B8C24CC7A2FB73FCD
-:107B7000E23B22013C6B38ECBB9E2E1FFB29A51774
-:107B8000CFCEC1F6ABE892CF3E3DEBF64FE9BCBBA2
-:107B9000764CB4CB40364D4EA49F407C847D3BA5B3
-:107BA0009F38994C9528DE37B4BD1E358EB6FBFC48
-:107BB00097A3F3816FBFCDF7FD99E7E5F50097BB7C
-:107BC0007EF6EC75505EE395624D30CECEC7FF95E4
-:107BD00042FBA9DE510F10264DBF7CD5E8A7F574F6
-:107BE000DE6DECFBCEC136A8F7F913F75F07F06E38
-:107BF0006A6BC2F2334F6CC3FC6B3F7B76DF3F682E
-:107C0000BD5A67941DEA9D797E3FE2A5D6A577C04F
-:107C10007A07A2EBCDBBF6337ED926E17E2373191A
-:107C20001F13742DE8F7F39F2D1E1B2A37C4F71678
-:107C300023973B83981C39CBF76F4D99A505D2B399
-:107C4000CF44CC85F5BA8DFEEC6898CF2846171F37
-:107C50007178D4B6AD31B82DD81EFBF980EE7B48D3
-:107C600073287D9EA2F44E6BEDB85000E3FD0AEB45
-:107C7000D37A251114BE372F382EC17C22473518F0
-:107C80006A709EBF64E574D5A1E5C5EB183D6AE94D
-:107C9000E00B9B05EB8B7D90B2BB324D413E60B259
-:107CA000333ECED69752ED6AB2D2EFD7AF73D965D5
-:107CB0008AC7974F1F9E9C4AF33F1B211520FE65E4
-:107CC00089C9398F05C7A95B5F464ED0F9EAA2D9A9
-:107CD0007E49B011FDB5C807B631BAD713BD05F25C
-:107CE000FA00F289BA162E0777B0791273206396DC
-:107CF00015DB59AE8D09CE83B6B358301FC8B829ED
-:107D000007E48E672ECA1DC588F33D23F801F1E410
-:107D10002ECC09EEB7041D7101FE138C34B5307EF4
-:107D20005349FB4F8F2E4D8A2E0AA6098358B91648
-:107D30004EB7F0F21F453B92A2015E3B6355F260E5
-:107D400020BEF2DACDDD4C6EBF721CE9D00D740896
-:107D5000E3BB4EAAE4F67264AE940EF71C473A5C9D
-:107D6000DECEF8ABBBBDD4B88CA69B253217E6EFB0
-:107D7000E6F4047464A7F99BA2A3717DEEEBFCD931
-:107D8000C0A7BA39DD75EF61F4F6864EE701F8BC9D
-:107D9000B17DE43690075AF928553B11DF6E8A6FA2
-:107DA00093047AD6BAC3A067D555133BEC57F76E48
-:107DB000BE1F1A08EE07777BE572E82F356E9A5DD5
-:107DC00096502F999C4AF3EE5A5204FB2D656BD9BD
-:107DD0001EA00BD22E91AB205FEDDC0DEDAF8FAB73
-:107DE000B3CB9920F7B6279969FDEB471463FBCD18
-:107DF000E94A29F4E7A920B627216F70A13CDB9C52
-:107E00003CD20EF2CEEDDA887A175106D9A19CB891
-:107E1000F46BA1BEDBB3806C92C2ECE33D9203CB6A
-:107E2000BD91DE08DA7E7A3BD37FDCED6C1F9F13B9
-:107E3000F011A9A173118CD7FD828978A4209DBD72
-:107E4000B9670A93B32F9A50CE9E6D749013543431
-:107E50008F8C5610AF028E35AD993AA05B42669971
-:107E6000601ECBF83C5A0D4C6E44733990752F9BB5
-:107E7000C772BE1F9647EB786AE4FBAF95C9059BB6
-:107E80002717E4E0393E1E924502977374E8BAE57D
-:107E90003EDC27B54FB3FEE24C8EBCDB42E855E832
-:107EA000475A7A6CE2E3A66C3D20013349D95AA5C2
-:107EB000DAE7D757135F3D5DE7F55B75BE89B9A873
-:107EC00037DD82FC7C83916C97FAF7774F34E35B64
-:107ED00015B1CE3C09E4D7CD16D43FFAF6E9208798
-:107EE0002E02F4B87CC9DE84AB7016EA68BDD309F3
-:107EF000563BE0ED471C8E5A7DABAFBD460F9CD183
-:107F0000EAC9254369E9864173019E545FB798A188
-:107F10009D8DB6A7F512B68F7B6213F2AB26ECF7F8
-:107F2000F6681BEB27D659D8002C2ECBB98EC92763
-:107F3000AB3DDC7AD2A3859EBD284F07F433DB82AC
-:107F4000FBE1C7AF484B19BD514128013DB2FD418E
-:107F5000E8FE7852417A443DCADDE0F486A747B690
-:107F60005FDC54AF023D9BD2E35AA6275B08DB4F90
-:107F70008C2E23A73279007C2B549F15FB54BBEF2A
-:107F800005FDF6EDFBCBDCEFDD06B61FBB291C8043
-:107F9000DEFBE8FC6546E79B36D0FD48CB37D1FDDC
-:107FA000D814C2FFB5E71F98279C0704BF3D66732E
-:107FB00076005F746F7FAB19C996F347F7CB3FC864
-:107FC000BE98DE6586CAB45F33DDAFA1F463A6E078
-:107FD000B6E663EA013911B95EAD4789F4836826D4
-:107FE000BFBEB1DE3842D2A3DEC3F155AB737D0014
-:107FF0007C1EF4464A1124633DD31B1340E600DE89
-:10800000B6477A413F4E4820AEE7C2CC673FDF67B4
-:10801000029FE2FC9010C5EAF7F27DFF29AFF74F0F
-:108020009E869C4B703F283AD771220F2C8F443B81
-:108030003A2F2C17F3E93BD798D97C13EECADEBE52
-:1080400029048FC17D75753EE037EB5E9F7EA925C3
-:10805000388E908B5ABA81F983FC81F5548E1AB808
-:108060005EEB7E7E3ED3D07104DF5F7BA8B882B426
-:10807000D5E0FB2BEEC7355602FA222507472C9D8B
-:1080800057FDBEE16C1F8D086443FBEA58D74D31A4
-:10809000B4DF3193F8FEA0DFABE09CA0271E530CA9
-:1080A000E0DDE0F587E0F9D318D67F8FD5EC91E9D4
-:1080B000FEB823D6150DED3D65C4EE03397307E513
-:1080C00027B06F89AF08F84D3DF147019CC7585D57
-:1080D000F13140BF726736C9A2FC57F2E7C2F763BD
-:1080E0001151B984F6F371FB6F9F7985B65AF8CABE
-:1080F000B985DF03FA7A312203E8E218D5973B51BC
-:10810000DF560683BEDD4B94C1B630FC57A40BCCC2
-:108110003AB3BE20983F66559F2F447A4D0CC36FEB
-:10812000FDF914E28985FE099EBF7B6214F65D1F8E
-:108130003082EA567F3E8378687F1FEB48755B98F4
-:108140007137C5307ADB4DC8D470E5F7F171760F21
-:1081500065FB30B04DF2027FAC5EBFE1CF32E50788
-:10816000D5EBAC3E4C6931E86FD5368F4F47F3C73E
-:108170000C8C1FD17FB3CDC541B947EBE9C7030EC6
-:108180003CF4204BF9E0522EB79635BCF925D813B4
-:10819000AAF5C43C9EF6B3DCEC3C984A8B3EB32C6B
-:1081A0008F02B6BFF23BB725805C4A5CD0CAEC3286
-:1081B00064920DF45EC93143BE1079313D4B8FFAA4
-:1081C00031E29FE2EB8B18E74CC0F782C104F580E7
-:1081D00005B7457A3D217CD0CCE1A1A59B4FB87E67
-:1081E000A5ED7F766C1981FE3AA29C73813E16DC68
-:1081F000764EC5CFBA25FF538F025DADB1DA9F64CD
-:10820000DD653843E8FE3B62BCF33AC4534F5E671A
-:10821000F6FA4CA0DF40C68760CFEA30D93C0A941A
-:108220001B11CFA2DD9F1A29E3CB0EE6979E1E36C7
-:1082300019E86B19B13703DE97B544124F083F03B5
-:108240000518E8C37D9E603F4B3BDE3C0AFCDCAD7D
-:10825000F7239D2C355B108FEEF37A9C0769317400
-:10826000F9457B8AFB23518EDB607D9E7BC6479F51
-:108270001A493F26D2EFB87ED7EDF0FDA1C828E21B
-:1082800000FA784BF60EA7F3EF352B836328BCEA90
-:108290008D940E4663374E7388FE43D2AC6AFC77EA
-:1082A000BCF525CC67B9D9650439BEC241CFA73228
-:1082B000E0C957641B158AEFF1F28591978FEF455E
-:1082C0007CBF7F6CA4F41F661FDDC7E1DF23EAA536
-:1082D000B07DF27106A97E0ED26B684ADB7D3C94BC
-:1082E000E7F3793E9BD74B60F91D7C9F7C9CCBEAE2
-:1082F00069C7F1C530FE363BD6B115E045DBF98CD8
-:108300004017FB22BCA8B716527E07FC6D6D3AEAF7
-:10831000AD94AFEDC07AD9C4178DF54C28574803FA
-:10832000E57BB0CF8B1484CFA6524A27B43CB0D79C
-:1083300064DBAE04F12AF0A9C5637B8CF4EFC9C3FA
-:1083400051923ED48E42E5617B0CB3A318617FD27B
-:108350009918999E360CF18574225F3EBE6E8C6032
-:1083600078A0FBF4B518D47B7D39A1FBE504C79751
-:10837000E0671F0F52E3B58AE3E16D5E6F518C8DAC
-:10838000C94F7B00F7DDC731AC7E5C169343420FCB
-:10839000FF0387CB4D9A54C8953153D5FAC54D1C70
-:1083A0009F37C54409BC7E08F315F288F2175F3485
-:1083B000DD0F0B5E35217F211B03D9B0FF68BD6344
-:1083C000586E0A2C8AA572E426AADF18F3B1DD22C2
-:1083D00068DFEF3C3F4AD08595809C3E25D65318F8
-:1083E000407E4FE51DAE6B29A17C43BA34FE37D0E9
-:1083F0003AC994D6870C56D8F94EA60302ED8F20C1
-:108400000AF447E1FEE750B86BC73BC6E9E09F318D
-:10841000921EF19647F2709FBDFF857521EDF29C8B
-:10842000CDECD151BEFFB8CE7501FAE9BAFD2DD41D
-:10843000CB8F197DD9AD9630E546DF630F49C1F288
-:10844000C53F973D46CA2F767776FDE466BAEEA51E
-:108450009DB21D865C7AE75FDF1D037A75A7C10EAA
-:10846000E7462ADFEFD5C3BC1B981E794CA7A6832D
-:10847000B3DF559F73D26219BEA8DE83FA9CE03B3E
-:10848000427EDF4A7C57815C5F461C4648FFB466EB
-:10849000D50C42E1B7C2B20EF9D1E76BA7A11EBC61
-:1084A0009278B07C598BE14FA1F26145AB3ABFEABB
-:1084B0006175FE56AF3ADF677F2E0F2FDFA7C732F9
-:1084C0003A3E4BD93EE03FB0C1E4053D485BAF9832
-:1084D000D7CBA43CB113F82495FB60475817E1486B
-:1084E00004BEBE6E6F69E2C5EC7CF5E7AF21DE101D
-:1084F0007D23A837E4126F6CFF7ECB63158423F4D1
-:10850000ABF071E0BC71B62CFC3A26C60A3D651092
-:10851000F627BE8B7E82E345E13CEACF9B07988F2E
-:1085200005DB9F5D197E9C1BFAC6B1A9E464B07D92
-:108530001C936BFC1C2DE8A3FE7C127E1779A1070F
-:1085400007DBA531FD8AA4D94E4506F994B0638BAB
-:10855000FD704222E664B43BDDCFCFEBF65CB05F4A
-:108560009F003D08F6E314659F9F4E71D9F7C666DC
-:10857000EB8706F78B761D94AECEF843F8EEB25833
-:108580006B1C8E6B27761857D0FBA2DB2B06BBE843
-:108590007CFF786779A26B54283FF530BF8951E89A
-:1085A0005F16959C251A39BCACFD2DD4BBA8BE9591
-:1085B0000D4CE7D3BDB723BDAF24CE04A0F39EBDC1
-:1085C000C3335CFF86FC15F399E559622098A79B9D
-:1085D00098EEBF2A3E9F591D4CEFD3991D061CC72C
-:1085E00041145B021EA5D97C29F3D4D3FC84BEF9C7
-:1085F00083918E90F17CFE12B4A7F09DC053B2D44B
-:108600009504F336C1B874BC08E24D82B469AC5D20
-:108610008174A2E4D4B379303C4F260D69505F6772
-:10862000F6CB6C9D740609D0BE0F5E98B7F2FCC6FF
-:10863000D9BD8B56C0778B15F98891CF63472CE550
-:108640008766E42F6658B7C9E2FB1CFD643CF594CD
-:1086500029B88F3D4309DA3B06913602E35A2CE7ED
-:108660003CB0581BB149908FB0F5FAE0FC70CE6673
-:10867000F1E846239FDC190B7C527A6725E085F2EE
-:108680006566FF19A85CEFC373B7E073317C7E4D5C
-:108690009CCF2513068758E2C0F11EB0AE9C414026
-:1086A0008459D649D07E4BD454F4EF2500E0697943
-:1086B000EC54BD8A6FC53BD5F9C4B9EA7CB24B9D79
-:1086C00037D3933FE88B92CF99742116CF5923C0AB
-:1086D000DE62E0FCA299CFEB08A4743DEF713EFD91
-:1086E0008DF513BBFABCEE8E3112B4E32598CDD0D4
-:1086F0003FD557DE8B65FACA271E289703C8CFF3EC
-:1087000026B6F9C0AED37C8364BF8B7E6FB62A1BBE
-:10871000F494543DD32466C7D1DB4AF5B47C5B8620
-:10872000CDBE89E6EBC17E1D0BF3B7D53C8DF64976
-:1087300013AB4702CDE08FDCB6C966837A71E58161
-:10874000C946D08B5710DB761286BEBFA2FB86CE01
-:10875000F709C853BC489C5E220F29F3710DBC7CFD
-:1087600007FC9DC5F2138BE15CCAFE6575E4753AA2
-:10877000C0EEE090512ED677E4BD6EA1E365CDCE7C
-:10878000433BBCB39CF97309DFF76334FB6A5C902D
-:10879000CEB13C8FE7877570BB6E9C89F96B6D74A9
-:1087A00088626636C0FA718CFEED44FC63FBF25AB7
-:1087B00012FC07FD9507FB473E3429581CDC677403
-:1087C000A87CB3BDA996D61BA3F7ED877D3C8EA7E9
-:1087D000793C7DA3F40694BF9D3A8B62D4B17D6D44
-:1087E000CE0213865306B814DB7ED004FD4C907C79
-:1087F00098664CBDBF09A65FC5ED47D14946EF0657
-:10880000BA8EA6128A67B477FCF920D8A5E5074985
-:1088100001E0E98841C839079ED3157A1CFB1A3A52
-:10882000986C40FDFC2F932AF03B01D58CCEBBD237
-:10883000C61621BE0F2C5F75283F6AE364E437B388
-:10884000A632BF6AFD5CB3579240CE10E677D2BB2A
-:10885000326F0AB197083FC4FB0632775798F3444A
-:108860006D1CD34FAB66303B6FFD46A3CA7F531DD3
-:10887000C7EC5E33E3268F8C4379C4FCA779715C27
-:108880006F1B4146009F0AE1234550AFABF4ED81D9
-:10889000F88CBA9CF399398E0203EAFD9CDF08BE7E
-:1088A000EE1CC4F6F33C42D281AE679306E4FF8728
-:1088B0004B6F457E7313F118006F1F95B17802312D
-:1088C000EF5953D57AD21CA73A7FF35CAD1EC5F0A1
-:1088D00021C69DE7529757093D78AA5A0F5EF0FFCF
-:1088E000BE8A46B99AF854DD8521E0E760F600C0FB
-:1088F0000BF373E8916EDC1B993FBCBE3DEF8D38E6
-:10890000D8677712BECF7649CBD1FFB24B5A1182CE
-:10891000FFD45AAF047264B855D87D98DEE4347938
-:10892000F783DFC359831291BCCEE3490E403C4923
-:108930007E90BEAD65561657411CB5309F345BA482
-:108940001DF4FE165D3EDA655BA2AC2A3BFAA60D6D
-:108950004A05D413F658C544F26D9C6EC29D77D774
-:10896000C531FEBA59627671CF3C339E2BE3B39C7E
-:108970002A3F41BC4C8E829D70649C22EAA3FD6319
-:10898000B3C1955C4053AF44971117D25E261BD1FB
-:10899000AEA8E14FF1B176B4EBC70FCE413BFD9CE1
-:1089A0008E3CB42F124B84FD2A29D8FF9CD9DBF4CE
-:1089B00010A753DFB14DBFDC12A4BB7BE2B85C8DC6
-:1089C000249140AF7D76BAE74C68A77B5CE7FC5FFB
-:1089D000A0CB5AA30FED7121F48ADF07928BAB383D
-:1089E000BD18CA9CF356D0F9F5BC6BB4C3F9191D78
-:1089F0006DB4FFE7F744A39D515F45503E6D2C6574
-:108A00007CA407EC5F741D9F4557E3F960A3D48AEB
-:108A1000F2A33B6632D2F16ACB013C07576FA574D3
-:108A200018229F56EF50E76B48279EDF6B9FEE475B
-:108A3000CFC817051F76EF56B723C3D47C378FCB2B
-:108A40008B7CA77D56054C7DAE3D8B9DC3E9418651
-:108A5000AEA3E81D23B7EF2EB09D8A0056FB947499
-:108A600031FDADC77A5A66FB9FC983223E8E566E92
-:108A70001571BDED3ACABFE0FC2AF4B022C2F2077C
-:108A8000741D72922E38DF42DE4EE87F424E087C23
-:108A90009596105242F743A7E04F43C950C037EDB7
-:108AA0001FF78904914331D8BF07CE7DE3F878944E
-:108AB0001E3C20B73D3AB317E8AB596A4039690606
-:108AC0003D9FA69B2417CA8397AA3D32C07B2C6981
-:108AD000983583D61B6FEE8C0438513A39124A3FD1
-:108AE0004DC497B14B52D111967745BF1D968E84D8
-:108AF0003CF37DC4F498E974C5D04F05387E687A9C
-:108B00004062E7C829961FEBA1FDDBBA69482753ED
-:108B100089570FF3ABB0A9F13F25499D9FA6F4A358
-:108B20000F8CC37070784E1FA12E77087E47D4FC3F
-:108B30002E937C857A18F9C1C1EF805D21723D19B1
-:108B400001FA0DD544711F6AE9E0EBB86FDD6FF2F1
-:108B5000755C18BF490FB7135F4BFC2B9F96FAD378
-:108B600059F71BEBE5A4107A14FBE265038B7F90A9
-:108B70005E65FEA9123319E503FA2A647645B13F12
-:108B8000AE05FA8C09D25D31FF9E11CFE96C081950
-:108B9000027436A13DC22753BCE4F1FEAE05BACB48
-:108BA0000FEA23E25CD154D28FBE32A52CD45F7081
-:108BB000DF097DA4406A6BD267021FB9A709E61BD3
-:108BC000424F43E38B802F517AC27DDA4FCEAACB3E
-:108BD00035F426F02EF4E552D28074365BA760EAB5
-:108BE000AB5C85F2B5DC325B0FEDDFAC62F43609CD
-:108BF000E8310BEAABE9A5DCACCE6BE9918EA80BB2
-:108C00001D574B9F03D1DB10A037215F632F4D6FA2
-:108C1000D3E3BF757A9B1E7F117AD3D299E05FBBF5
-:108C2000226CE5A03FD7574B280F0ADE1DD604F96A
-:108C3000E17599A84FEF8AB6A37E5DDFC0CA0B3BF2
-:108C40001D32C4BD64ADE3E599CE72C8D7AFA7E5C8
-:108C5000B4EBA2232C2E66D89DAC3CEFAE86D7ADEC
-:108C6000A0677858FB973F6F96A368B9B799B72F5D
-:108C70006D2D877C7D0B6BFF19F8A946437C9AB755
-:108C800009BE5F7D6FA69D1DAB99FE3E91AF7797A4
-:108C9000F4DCEBD8AE95B55B75D03C88E0F99FE984
-:108CA000E5D7F1754EDCCAD61977E2FAA90AA58B89
-:108CB00015010FEA6FA774B5C5C8DF06383F974A9C
-:108CC000AD69904EA1EC175287D9DE220F657ECC9C
-:108CD000ED74887BE299FD45F8FF20CEA032449FD9
-:108CE000B8279ED96345BD84188A01A08747ACA8E0
-:108CF0005F0BFFA4EF212281BC8735723D24ACBFFE
-:108D0000724A5603EA115386083FA55FBF948E9BB3
-:108D100077E18BC9E1EC433FE2E39EE671137D7A94
-:108D2000B237530774B10B88240580F4DEAF417F5E
-:108D3000DB057E4826A43CA404F0CAF25BE37FBDB9
-:108D4000A9653C85AFAE41EF01A1962161DCC9CC9C
-:108D50004EE21B1CD57FFE53F4C467C4382636FF91
-:108D6000954D541E23D1317E3687E38F8CBF0AE99F
-:108D70007736C7D3CF057F2A2005C09FE670BCDDBC
-:108D800064A67A34F2C35683866F3C130F726ACBA3
-:108D900080FABBBA5CC357AAF9B82BB9DE7E2B099F
-:108DA000A07E724AF2627A7A0BD3DB6B2C4750BFFB
-:108DB000E97984E9EDB5C48FFA8FD6BE59B3539DD6
-:108DC000AF6B53E7EBDBD5F99E1C0F8ED3B3A5AE8B
-:108DD00018EC8AD50FBF8B76EC6AC15FBC6AFE4285
-:108DE0001571C65F1EBA06ED51DF986F3C4D4F6F8F
-:108DF000C5AAB8D0DF029CFAEC352FB2F81437615F
-:108E000076821EEB88F9704E251A79A4E527799CA5
-:108E10009F08FB86E02F7984C9237A8E7DD7418213
-:108E20007C5CABD7F5C473BD979FD384FE9307FAE0
-:108E30000FD0D3350D48644139647FDB2487C89F48
-:108E4000798566C073BE99EE6780976CC971595475
-:108E5000F4F005CA9981CF7BEA720DBD88F3D62D57
-:108E60009C5E668127858EFF7BC981E7BAC3B732D6
-:108E70007A99635987F4FAD16A462FE2DC77E5E7FD
-:108E80003C87FC4DCE797D741241F55E9A1E4917E0
-:108E9000E77CE68FAF97181DD4557DF818E8CF8290
-:108EA0002F1C6E24F1FA103ED134CD64063B4A9358
-:108EB000819D83AAA67F5CBC3484CF38224A1313D9
-:108EC0004059EE8847FB6C5DA47A9C66A9F3BB7F92
-:108ED00080F3D24F23D14ED4FB304195A477EB7071
-:108EE0008CDB3E6B607E52319F550777EEF3C37E7D
-:108EF0005CFFEB083D959F3592F7C55A5AB6C4E41E
-:108F0000CA86716A743E23B36376A25F578C3BB006
-:108F10005DD683F2D5F81A93C3016910C6E1D2EF8A
-:108F2000D9A1FEB5D1898C4FDF11EB2A48880FCA31
-:108F30004B613FA45296A4C604FD26C1F8066637CD
-:108F4000F90B715C32BE6163887D9EB60F1B8F5634
-:108F500096C0F8F5F729CE61DE07A31DE5309FD353
-:108F6000DC8F7B9AFBFD4E47313FE0CCBEFA2C757F
-:108F7000F1F434F7139E8E51FB8744BDA509CC8EC6
-:108F800072B2D16CDEA807BF3A316F1C4649EC21A2
-:108F90005303C6932C6078EAD913BD6D5388FFA59F
-:108FA0002EA1F4FB309F7FD89C3743BABCF5B83173
-:108FB000D40EDF23B1F3770FA7979E08968A71EB43
-:108FC000122ABF0F78EC99E7473CF6E5C78ABC1335
-:108FD000FBEF99C0F86B5FFE3B2C4FB8DD43D8F533
-:108FE00007F2F769FD7B54D0B0734004B3CF6BFD3B
-:108FF000F30B053FE3FEF9059C1F2DEC607E8245D7
-:1090000066D29C4ACB177724B2736E94275BE59F98
-:10901000F7445E513C86A0CB9EF4CE3E7FF62321E2
-:10902000FEEC3AEECFAC13EBDBAD5EDF0309DFBA4B
-:109030003FFB818430FE6C6DDCC38BA0470C0BE2E0
-:1090400061AD8DC1AD42AE2D077B6FEF728271E8CD
-:109050006BDF5AD604F6E0B53F000B2AF231D4A7F5
-:10906000EB389C075A57BC534714959D7D105142CD
-:10907000E69FEC8A51E551430F89034DAD4E51B542
-:109080004F6F18AAAA3F64FD35AAF24C4FBE2A9F23
-:10909000D572ADAAFE55AD65AAFCF087AF57D5CF06
-:1090A000234307A3FDEC900CB62172B5B74A553E99
-:1090B00072E72DAAF69F9186CDE369BDDD42FE7968
-:1090C0001C9DA38A8371CE396D4B55ED9BA4B6626E
-:1090D0001FF0469FE49368BD151C5FCB3B99FF6270
-:1090E00074FB6A55FF67A3D83D18AD5F96762EA333
-:1090F0001ED62E9147A4FE7EDAEA8EFB9B21EEA8B7
-:10910000BFBF96F24DDA6E353DBF80FEA6D56F8E9D
-:1091100026703F5D0A496174ADA50B0BEA7FBD5B0C
-:1091200065B427E691EC87C623BC0CC4ABF4C75FDB
-:109130002F6176AEDEA7AD7688FF59F5D632A4470B
-:1091400053929A2E2214355D448E50D385D5AEA607
-:1091500083C1256A3AD0C23DDAA1A60BE2A7FF433C
-:10916000E02DE02AE01E3B554D375A78E79300DAB0
-:10917000D9DD5EC9EE2361FCE2EDDB705D97D21FA5
-:10918000F5896AF8161C703459106E2CBE4CE861D3
-:1091900026AEFF68FD1342AF894BE47A15EF47F81E
-:1091A000179A250FEA517DFEC2125F862F13F4A78E
-:1091B00006C2EC44CEA4C4F07646FC3E909D51C05D
-:1091C00075F620262F6B8803EDE12B880BF9DDC99E
-:1091D000CA5BD13EB4CAF263F4BB9EAD627A52352B
-:1091E000F1229FBFE2B802AA879210FBAB168E5203
-:1091F00087E4B302BFE1F22085740879E0C27813F6
-:109200004A86E662951F47ADE782DF30847F09BD5D
-:10921000578C27E029F89A18CF441AE424D8171A53
-:109220003E474668FD486A3B8DB0F3E06021FE2270
-:10923000AD5D26440F6E91E938F290CC2642F1578D
-:109240006073A0DDAF8874CE87EF25E6B626BDC279
-:10925000ED1357933EFBC480F2EA12FEE8591EC993
-:10926000FF68667F3FB4F06BD3E59FF8036D3C5E0B
-:109270005210EF552F0F8F077AEA6FA7B41F7D8525
-:10928000F623EB02B1A1F6C3BEFB06921FD7731300
-:1092900071DC4D42F41037699B3C3F13ECC4544ED3
-:1092A0004641CAEC58A45DAB07EBD18EACA32B01B1
-:1092B000BAAF21217EDACC6039E6E5FE7911377448
-:1092C000297DE242A28DC73FB07827C2F9A0385F5E
-:1092D0000E749E13711470CF16FC21224EA8399182
-:1092E0009F8373492EF44FF7DBA644B41FD0FD29AA
-:1092F00085EEC7BEB8222CEFB71F35EB177114B23D
-:10930000B510ED42CB42D77B19F0107ACB6FA83E57
-:1093100080F7341215A6D70D3AF681038A0B3B5518
-:10932000719EF5467A80017BC18B3C8EAF4DADAF0F
-:109330003F9BC8E393F839E752F01A181F3CEE4EF2
-:10934000E0E332F530117727E0F8427FB8EF51C102
-:10935000B5EFBCD807F73DE1E02EE072AEA8F329E7
-:10936000C0976C3D9200F0EE8872EE83FAE947FDFB
-:10937000A7245D705E157217C6CBF6B6CB783FCFCB
-:109380003D81C55BB9F7C8C81ABA3B4CE837AD6E2A
-:109390007F1DF5C2AE46CA68A91E76A6910EA9BF6A
-:1093A00088BD4003EF81CE47623D1F68D62FE2752E
-:1093B000E83A7F7F0938FC3E1C1C2AE45183E19E79
-:1093C000575F9C913E905115421FDA756CE6F4B0E0
-:1093D00056EF3C01FD1DEF4CDB0CFD55C81D07533E
-:1093E000003EEB24BC7F35D1C4EECB26F3FB7425C5
-:1093F000FE063BDC374E4AB3E0FDA9E1DF919DE07C
-:1094000017FE78DD6D31704F4CF43F5CD2E1FD4EBC
-:10941000429EFBE48E42F0572EB06FA2B98526160D
-:109420009791F9DD485F16E523AF1A8919F6A36114
-:109430006803DE6B0944CB68B78C93C924A03B3129
-:109440006F711F567C87FBFA70EF527C9FD81428EF
-:10945000584BD30E4E0F62DD13CB03050D9620FC47
-:10946000455CA6163E5B383CDCF1C666D017BBCD2A
-:10947000E2FCC95262D3239F596766FBE6D855E2E6
-:10948000FCEDB3C2B9D41DE1183C06F6DFFB32791E
-:1094900092267FB1390647E3FA15D4C7D7D958BB0E
-:1094A0006E1E07BFEEA3B244885F8E6F0A1F6FA6C1
-:1094B00024B1735C2DF7EF8BEFB57A1FC68DD542C3
-:1094C000BC7641F0FB95C66B8B78FC01E110AD27B3
-:1094D000FAD178EFDC79B17AAFFC4B0E7BBEBE3EA1
-:1094E0004927E20FD1EF4DCF5B61E30B4B93D8F9E6
-:1094F0002A1807E8C77BC37DF1857B4A13C945CE8F
-:10950000FBEEF30E55DC9F8837779F9F84717EFDBD
-:10951000FAA5FD2996605CE140F0DF92C8E6E58699
-:1095200078BF82D0EF0AFBDE374E1C8FDFF347C1D6
-:109530003EFD45BB8CF7EA7F714837757B9879D73C
-:109540002731B85D13AFC77D33D2471CDBC28C2FE8
-:10955000EA89FB35E29EAA767EBBCBFC8B60FE10CF
-:10956000471C6EBCA59C8EC4BC77C7307CB8F799ED
-:10957000F09E05ED17E3BD77C7F857E2BEB0A9F13D
-:109580007C3BB7D7ECBEDE9F81F7BCA6313BC34026
-:10959000F4E08D72FD04F5D89B69654A3FC5FA0673
-:1095A000C916B2FF2E450F41B8EB5478ED0F772363
-:1095B000E257F4FBF961BE4F89C302E7B7255CBEF1
-:1095C0002DD95183FAAF381F7DFEB08CF1179F1350
-:1095D000E627F9BC55C2F3CF521721EB291F5AF9E0
-:1095E00064413388B92549845C17C3BEDF09E94665
-:1095F000B59F7CF9BDFDEC872454AEAE200D2857F5
-:1096000056FE58DDAE9ADCFB67D09FB4FEFBE1DC72
-:109610002E27D6B139899E4740EF2926C5201FD66F
-:109620003EF985314A19781F9CA67C77981EF8AFC1
-:1096300019D3AE461BA6BF48723C9644F1B727C962
-:10964000B50DD29EF759FFBDB5BD4C7E6C8D43B9AB
-:10965000D564FD2EF2757908E3EBF7C03B09141EC3
-:109660002613D39712740D7214EA2D5EA487E3F1CA
-:109670006BAA6662DE9E04741FF7CB295331CEEFCE
-:1096800097910E80F7A652471ED8253655B27B9982
-:109690006613F3B37B7F31F63570830C6BBBBF0C65
-:1096A000CEC1B68EFD3EB0F7B4E8FE7C10E2575A4C
-:1096B000AE63F18B093AFFFED490F1E223BD49E09D
-:1096C000878F1F69C4388F38B934AF21245ECACD63
-:1096D00071D1DB9E8576C21E83B01BB645E0BDA866
-:1096E000DAA183818F5C43189E45DC1BCC2154DFBB
-:1096F000EDA27084A04B91BFA64DF219A2F0FD120D
-:10970000F4E3D4DEE54B980F72EAE77AF48389F943
-:10971000C5BD9A5C06FE2E219FE64B366647E3FAEE
-:10972000FC3C22FE317FD95C4E27F3B81E3F3F92AE
-:10973000C17B29B16740BB5BCC244A47B7D4FCF25C
-:10974000B6225C678D211AF405E1F71958CF086F2E
-:10975000FF723F6565F78DA54036747286C2E76279
-:10976000FB30C0F9B23B9BDDBB23C38803FC8CEE0E
-:109770007DC3B7817DC23488F9AF297F3297E4A3D6
-:109780005E6D8673D4ADAF44F0F8222FBF4FECC8A6
-:1097900083F89CFAAAB47C8C13391AC07737BA0DB7
-:1097A000FE0CDCC794EF4854360EDAF2FD197AB895
-:1097B000AF9942F5359A2FD9722FCB0FF5AFD4D18F
-:1097C000FC922D4FCDD0D3FDE1BEC67F0AF2355BB2
-:1097D00076B17CBE7FA54CF3CD5B5E65F5E160495B
-:1097E00009ECC12D07677868FF67A2B9BCB7FBF128
-:1097F0009EB5FBE5E1BA503B6B6332E35B67B89D16
-:10980000F84C26595C05F01E11BEFEB2641D0F5ABD
-:1098100069C554AC57B42749E1DB25F3716EE5F710
-:10982000A32746929608E6B7F344513C1CE8188EED
-:109830007EC7AF9362989E6EF3E3FB38A21F014F81
-:10984000D19F187735C867E0CB9A78ACEC64863F37
-:109850003ACE461C679883DD2BAE4ACB03FC51BC45
-:10986000E939DEF4ECFCBB8DCD8FF61B9D8B72A02D
-:1098700000ECF807BEA2F53383F3D6D24941329308
-:109880002FB736317F6B203A0BE96962247F67A5D9
-:1098900050BD8E660E87C6E4687E6F46C02B51C2EF
-:1098A000719A381CD3FC78CFF24AD75DF11F5A77F2
-:1098B00008BE1CF05ECA81F6ABB7B3F5C4F07BCD31
-:1098C000FE8C18D4F7EE57F5776683A67D09C1B8EC
-:1098D00036774C16B6BF278298F13BD9DED72E33A8
-:1098E00097E9ADA0CF8A772C88E73A12EA47EC7B5C
-:1098F000AFA28DC56706D739A390AFD3C6D769632A
-:10990000EBF4AAE8951C0964CCB6F6A7E33EF8F799
-:10991000F5372A9FF7A7DAE7E1FA837D3D105ED697
-:10992000733AF9D6F022E6A981671F9C35F313F04C
-:1099300084FD8DED46A9E952CCB326599C9335FBA5
-:109940003BF31B8E57CADAD5DDCEE2B989A2A6EB6E
-:10995000BADD993A882B10ED6AC127101FB4FF3D7C
-:109960009ACCED8969246D80F8C4C7938BC2DA0D57
-:10997000F1BBF69CD813CDE2D5B5F68A9E787B274D
-:10998000DCAFF49C63EF0A8CD3D86FC0CFF49C2576
-:10999000D82E285FD4F9739C3FF6B73F0532607E1E
-:1099A00085A6B2E7153BD547B61C437E5D38B8ECBB
-:1099B000B64C9A7F35F98FC8CF0B53CBBEC8A4FCE9
-:1099C0007C7FB29FE547967D3114F25BFCACFE4490
-:1099D000C7F3C0EF89C73F63527250AF782D59412A
-:1099E000B8C9E53A027464022586AEC7F4AA09E351
-:1099F000F6045C074A0B4DBA8670F76FDFEEA307DB
-:109A0000E65729813F15B0F3713B805FAFB203F495
-:109A100044B17BDF3D7BFF8EF75D3E487675021ECD
-:109A2000EA23BB1665D2FC5D919FA01F4F72D03D0B
-:109A300001F615C54616D0F94A5D9B9CA03F91D50D
-:109A400076B31EE1CAED5E748D1728FC5ED9F7F37C
-:109A5000EFA5B2619C308FB19C0FD4EFFBF26FE0A9
-:109A6000F7AD3F63B183F97A6CC796DB40FF1ADB31
-:109A7000F1F6974C0EB3FB3962DE63C1AE49BF9776
-:109A8000B49B70FE633BAE5E01F5C7FDB6230BE8E9
-:109A900064C2315F13B0859EBD2FA5AAEEE590CFBD
-:109AA0002E1AD739A0DF4DC0E353AA540D4678F4DF
-:109AB00032787C85F167DDF1879BFD68FC54DF7FA0
-:109AC000A2FA3AFA917BC9203BF833C47D7AADBD46
-:109AD000F468255D1FFD3E21406710A24F4F3C6F8B
-:109AE000A68C24982F25D1AA7CB9395955BFC29686
-:109AF000A92A9F9274B5AA7C9A92A7CA4F1F315681
-:109B000055FF067BA92A7F63C93455FD4A47A52A1C
-:109B10009FE76B53D52F38D4AE2E3F4264C043FE2F
-:109B200051FBEB90169D74A0D9B5F874C3EB908EE1
-:109B3000FD0B0387D65E7CEDF9B6D7E1BBB0176BA2
-:109B4000EF3309FBF1CDB2C56B0C6F274ED2670521
-:109B5000DF1F9075EC3ED318ABEBEA94A2E07DA634
-:109B600089602FA648A8587CEE47E3004F0B983D2C
-:109B7000ED282006E3BEAD68873C6A6878E60F2CC6
-:109B80000E201DF8DE84C05CD5BA279E77A9D65D6D
-:109B90004A6ED5E0698D2A5F61BB5D557F4AD2066A
-:109BA00055F934E5071A3CDDAFCADF60DFA2C1D347
-:109BB000360D9E7EAE2A17F4DDC1ED5AFBC01E4560
-:109BC000D3F1FECE72C0C375A703888F92CED67232
-:109BD000C0D3B547DB105F853E6739B0CBE2430D9C
-:109BE000AF43EAA3E73168F75A6312A6071A15B420
-:109BF0006B1D6C1C81E9A1463B7EFF756309A6EFD6
-:109C0000343A307DAF712AA69D8D4E4CDB1ADBB005
-:109C1000FE738DEDCC2E16DBF7DE453AD807BA750C
-:109C20007E377882173F927703F0CBEE41FE6EC805
-:109C3000DF45EC374CA2F925C044E8BEFC294F377C
-:109C4000A43A028057371CCA8A82F1186D3A471E1F
-:109C5000E8E177A44CF8A13E9D90BB3738936CD1D6
-:109C60002C6FA6794436C6B34DF8A18312D73320A2
-:109C70004AD0A933E106C8F744B07277CA841B40C2
-:109C80000FFFC6FE73473FFFF91D2961FCE7CF9C1C
-:109C900056AC60D739FCD5702BC0E330B76F39486C
-:109CA0009E61094D4BF5790690B34707B8B7F08030
-:109CB000AEB409E0D0A6B3CFC178EFEB0D04E8B79E
-:109CC0004A62E75F51CF95CAE441CF0D263C4F1D54
-:109CD000D13956605C9914780CE0BC3DA512E1DEE8
-:109CE000630D6400FCBC294E968F0F3C26D943F2CD
-:109CF00006069F07526EFCB6E1F35838F83C9162B5
-:109D000063FAB6CF910E7A80C81FA974D4C17E3E83
-:109D100052EAB80AEFCF384D6CFF3AADDEABD03E19
-:109D2000E4289A1362E719926A60F7D1E16222D8B7
-:109D30003B6F91719F6BE1392195E97B482770CE8C
-:109D40009C1789E782233AF69E81B6FE020ED7B3AE
-:109D500083C2DBE316A632BDA26C56DD332FD0FEE4
-:109D60007AD64560D73DCEE1A88FF53450E82A3445
-:109D70003DDD708E959BEC1C24E8BF9D0F7FD1F2DA
-:109D8000673A6EFBEBEF68FD4FD645DA5186D8AEE9
-:109D900041F8DDC22B2F8C35A3FEB4B02ABD0CE4F4
-:109DA000E27CEE075C64D527A03B501F6D8427172B
-:109DB000975BF29A2904C9CAB84A233C25559DB637
-:109DC000A619D2D5C3EE37C21329B5A37635831AA7
-:109DD0005B47B77011F23FFFBB8D745E8BD7CB0A28
-:109DE0003BCF89FBAE355714CF22E8F7088F3BA253
-:109DF00040C0F3EA220E6FD16E1187D78914AE3FAF
-:109E0000E6909C0B6A3FD66740EF5D0BDFCD1EC02E
-:109E1000CFA02EE7FAE3074636AEF6FD1231EEE2AA
-:109E20005476FE3A62A49409FAE42D4C0EE4CEFD79
-:109E3000E2AE22BAFEDC0E9B0EE31516D7BD00780B
-:109E4000E86DE778349076D84FB33C4B3EF91D224D
-:109E5000264E758FF752F2D2DE692B0F9597857ECD
-:109E60006779A8BC2C09B496835C14F251F84F7D35
-:109E70008DD59C2F37203F3DD0B81EF3071B3D9852
-:109E80001E6A6CE17CB915CBDF697C98F3652FE71E
-:109E9000CB3BF17B47E35C4CF735BA583ECA19958A
-:109EA0000AFBC4ECC2F8C437B69808F8E77A3B4C12
-:109EB000189F4177C4638FC641FC9109EF716AE333
-:109EC00090B47CBE8F1E76F77B372505C6E98B1FC5
-:109ED000027D71C8C0F474982856E04BF98FFEE4F7
-:109EE00006D0AF0F2B8A15F4E982D4CD2CEF50ACFD
-:109EF000069A2F7C94E75D8AD504AC22F521E45BB9
-:109F0000873D8A3582E68B1F7D88957B093AF3C7AA
-:109F10003DBAF5060FF059221D80FD516ECE9C44CE
-:109F2000C50595D7A507605F4C495A3209F6C5CEDD
-:109F30001405E9639AB2E100E4A78FD8A687ABFACB
-:109F40000E4BDE4668571657A9877693D2D66C8497
-:109F5000769387DDAF0F6D3775D4AE8D909F61DF3F
-:109F6000A607FD7427F0B1F8603F222FCA059F169F
-:109F70007172A33B9C280F72DB9D280F045CCA669C
-:109F800057DE0DF6CFFA76C926C13C664B7D410AF5
-:109F90001093E886F74929BFBE3EF597D60DB45D0C
-:109FA0003DE4AFC5FC0F377CBBFCFBA6D430FCFB0B
-:109FB00043BEDF41DE43DCFB8746F60ECC331C2E6E
-:109FC000F51D4BACF88E2A715941CF7A9ECBF39791
-:109FD00020A5E59FF1B48B7F7F40E770C138AB527D
-:109FE000B91FB23F7FA84965FB5F738F648072CE53
-:109FF0001FEA526DAAF73CEA08BBBF76A9383B6D51
-:10A000009CB836EE6435693BE8C8EC1F6F520BF71D
-:10A01000DCB2FAC77F8B786A6D1C78DFB96A10E30F
-:10A02000A77381D750BA6E491D904FDE7B0938DC8B
-:10A030001B0E0EFDD643589C7BBF38241EEFAE5D31
-:10A040001771C5B3778D79FCBB767D822EFAAFAFE1
-:10A0500095C15FCFE04FF5BBC7607E158BAD04ECBB
-:10A0600056A1FCE77717E13F5A7EF66DF1C99B17C1
-:10A07000D7E1BB6561F8D8F3E1F898B8CFAF4D856B
-:10A080009E0AF7F3201E12DE3982737E65A26B1FD3
-:10A09000F4D35316F89B0ECEA171ECDDF083D1AE54
-:10A0A000FDF05D32B2B80611977C5AE7F915E86DFC
-:10A0B000EF3DFA19F2B36E1016748FBC41F3A097FE
-:10A0C000FDC3E67C13E04746F88DA1EF8F0F147FA8
-:10A0D000FB1B2EFFFAA76CDF8938D49E6D5F66A04C
-:10A0E000FDEE12FB62207854C8E3FD703FA4B72454
-:10A0F00012E56797447CF0DE71576902EA2D5DE94D
-:10A10000463DA4DFF6B9B82B3D1BFBD79E8FBB9213
-:10A110004BCC6CDCC953217D2FF95421C8BDDFF035
-:10A12000F8CB76A3A7E03DB00F8F8D40FFFE8D9258
-:10A13000BF10E0A03D5777BDB5A04CC9ED7FBEA6CE
-:10A14000EB9B04EBAB3DAEBB1BBE5DE979BB76FD83
-:10A15000DF08C4B98F5BFF1581F7EFAEFCFCDD199A
-:10A1600093AB805EE16A021219D345F5099ABF5498
-:10A17000FCD639899ED33343CEE5256FB3382E9E66
-:10A180006ACFE7FDDE095CED51C70D96FA8A305EB5
-:10A1900045F647E1BD601D7B6F43C473BDC9CFF376
-:10A1A000F4BC3E240DED709D19AAF3FA1D1F2DFA83
-:10A1B0001EF281088CEF78A6FD443CCCF58F9DF112
-:10A1C0003F794509D277BDED6F24F49DC0DAF5BD26
-:10A1D000AA7CD786E0FB56701FABF65F32CA252AF1
-:10A1E000C75A104FE435E3DA10F94ADAFEDC07EF1C
-:10A1F000D194DF5502C050BE36CF74D07695FC3C6A
-:10A200004448E48D0EDAAE929F1F8967252B8FE7B5
-:10A21000F53D9FB07CBA28FFE34CAC7F95E86F1CFE
-:10A220002B4F1679DEDFD5229F782396678AF62595
-:10A230002C9F23C6AF64EDADACFEE4ADFF9C097A64
-:10A240008DE0F733D2B89CE0EF5251FEEF4C2BBAC1
-:10A2500068BC8EBA9CCB07F10E55C51DD322DF8595
-:10A260007DDC2661EC61ED9D06B4E79F8D69CB0D29
-:10A27000BD2F2FE27A9CE5568CF3AA7B71F8769974
-:10A28000C73B811EB39CFBE92B640BFA617AEF6537
-:10A290007C7E203D70E5FA9755F8EC57CEDFD3462B
-:10A2A00047251DEFDC0F13F17E0219D689F102EE6E
-:10A2B0003449C427E0BD6A11571797451C707E8E3C
-:10A2C0007B2982BDA77AB213F9EFCA97987DBB6E3E
-:10A2D000CBEB28EF96CA0ADA97BE1EEA5A07F0E9D6
-:10A2E000B6B2772F57AEDF87FBF431C5C6FD60816C
-:10A2F00051A1F0BCB33FFC3D69F11785BFBAFC3FEB
-:10A300000C7FAD5D5DDCD75F7D85F17FDD56E607B7
-:10A31000B6733CFD49A71473783D02F03AB7A233F7
-:10A320003B5A8620EE4E8C77AB90DF2982F3566F36
-:10A33000839500DEBBA5CEDC0FC3E05F7BAE389F0C
-:10A34000415471693BFBC3F7E94BD0F7D3FF4DFA9A
-:10A350004ED4FB8D76F01B1F65EFE51577FEC9180F
-:10A360001A1FF44E1A3B070F6E677E311117172C18
-:10A37000B7323C71FF535DD53BE3C1FF24F6C3C444
-:10A3800048D206FE044AD7764ED776A06B41BF412D
-:10A390003F146D1706BE41FA252C2E91C3E9B7FD77
-:10A3A000E1FAE125E0FAE17F13AEBBA93E8CFEDBCA
-:10A3B0001722D04EA385F33F385C05BC23D32F0E64
-:10A3C000E7C8F4FF0C9C23D315959D43C07B20F96F
-:10A3D000A4C58F9877987D5AF44DF6E923199C4FC0
-:10A3E000E9FD188FABC57B4C7A3FBC27A45F1CEFFF
-:10A3F000EAF2FF30DEB570D3A6B5DC9FABFD5E9808
-:10A400003E20BFFB56E0F87FCD4FB0B061BFAA7CC5
-:10A41000F1FAB754E54B3CEF5F965F41D8FBFF5B29
-:10A42000FE05E15798F9FC2A1DF81FB5F24137C423
-:10A43000F923A0C71B5FFE7AD48730F9EA6C8CB78A
-:10A44000BA8DAFE58BF17FFFE47B94BEBE6860F60A
-:10A45000D663FB3F372839FDE965E1791D7184D06A
-:10A46000D9C2F5EF1B40CF5A48D8FB54DAFA0FA6F1
-:10A47000337B30C64951BE30D74C0C71941FCC9DF4
-:10A48000CBEE4BCF0507630CA63E172D9FA9273EA9
-:10A49000788FBBD2A2F799D0EFA9BEFF6EE2EF751D
-:10A4A00093B858D53D78D921639CDF9C12E62FBD27
-:10A4B000C5D286F787E71DBAEBDCF7602F6FF4147F
-:10A4C000B1B87771FFF0F7BA2BF1833E087A2A9C76
-:10A4D000FB24EE5F5F6340FFBAB6DD2ABE9F66CA0B
-:10A4E000128BA3D9C3E233C5FEA4EB3B64CA67F762
-:10A4F00060E0F7482A1B0CBEE1B9A067EF473DBBFF
-:10A50000BE64432EE0AF7E9274DC941B3CEFD4AF6C
-:10A51000FF0BB6D7F2676D7AB9F6D54F1A0F21BD8A
-:10A520008873D1B1461FE6B5F6D60513FF17FD9324
-:10A5300063FFE26D8274DC578E0FC7D075FB1B3B47
-:10A54000FF2D7B82B02308BB82D64E21F88878BFCE
-:10A55000D2976EE3EFB296A2DF83E8592AF8EDC1F5
-:10A56000FEFCF9D7E917D727D5E5FF61FE7CB9F4E2
-:10A570005F9BC4E4AA96EE8F56FD0CEDCF82BEB56C
-:10A58000F4BF006252E8F80BEA25BC273E7755ABD2
-:10A59000619CF4CDE97DB5E56406839B462E5CB1F4
-:10A5A0003C50783C878CE70B93BCC60E760F8187B6
-:10A5B000AFD3D5EF0353BC48191797ABEAF2FFFAB4
-:10A5C00039E0E4A26F2617894A9F48CBE8B76EE5C9
-:10A5D00012EB56FE9BEB0EB9A7B448D605EFE3404D
-:10A5E000FC35C481F678D9FDD4EACC56FCDD0352A3
-:10A5F0001288027E77EB5E99FD9E8EDEA14F0E796A
-:10A600003FAD8BF83E007A5C359EBD3BA48D9B76BA
-:10A61000F378EAD596DD78BF51FB0E9A88CB76F3B6
-:10A62000FEB4EFA189F6E29D03ED7B685332781CFE
-:10A63000763EC967712917E7A3DD20CF43FC35DDDE
-:10A640005F35A25DE1C6C74AEEF3A405F13227A348
-:10A650001FDF99977171BEA32EFF2FD3AF6CDD81E1
-:10A66000F7D8AE947E47643ADC407F822FF7F19BA7
-:10A67000574CC86FC43BF33D6B9EC1F7877ABE242D
-:10A68000E897BDD43BE313BBD835C40927BD4D566D
-:10A690008AD771C73C68AF1B7BC485F776C7BCE31C
-:10A6A00080887F9277C029C3BC853E23F49B20FF1E
-:10A6B000E2F7D9789CD5E5F2B92BF537FEA7FC8CEB
-:10A6C000E25E5DB7C15704BFE7E0D91381BF03A1C4
-:10A6D0009DFF9319BA8BBE93DC11E57A12F0348B8F
-:10A6E000CB09F15E7285CCDE49EFED94D15EB8EE18
-:10A6F0007F7EFBAB47954BDB15EA6DBD61CF6522D5
-:10A70000ADD7B17B2DF9E50AC649C2790DEC87C2F8
-:10A710009EA8AD7F4A297B2903ED5BE3F13DDADE9C
-:10A7200087D97C06C257FDFA008E3F60391FBF7E75
-:10A730006F912DF49D95F3197DE743DB297310DFAD
-:10A74000974B17FFD7CE2D3365E291A87CCD91BCF6
-:10A750004CEF254CFF5D403A315D440298BA08BB8E
-:10A76000CFB094D8315D4E9C98AE555C5D191837CA
-:10A770001448C0F8D317FF390AE8E6DC75E35A211C
-:10A7800046F1DBF22369F5BE9E3C85BD97F4C23FDE
-:10A790007F07F4D9F33F86CBE21B47A21C6448181D
-:10A7A0003FD37BA532BBD754F25DDC17E2FD5D32AF
-:10A7B00089F9E1962766E2FE09F2CDC46D826F82C7
-:10A7C0003F39E7B88EC5C3DC2AE17BC6ED7E1D6E3E
-:10A7D000B19C15995EF8DDB9F6DDAC3CA72EDA2BFD
-:10A7E000D17CCED80856BE26DA0BF74F16123FEEB4
-:10A7F000CBC570FB4486FB4B8C2F8ADF0BA02782D6
-:10A80000A1126DBFA2C3CCEE5110FF30E0FFB970B2
-:10A810007E0A174F3384F1F1D14319BF1F5DA6B6ED
-:10A82000870CE5E5F72965DF0778B40C71640D81C5
-:10A83000FA319D9B1E2C043B908E809FE6B3B1B7EE
-:10A84000A35F53B47B51291B01F59F9558BCBF678B
-:10A850002FBF6F4C0209A1FEB1B54A792ED42B1A35
-:10A86000C2F8D3407085DF517486392F8AF8D1D170
-:10A87000706643BB3CC177D29E95587EF2E35B6F16
-:10A88000DC68415F8207F4E31715D744186FB49171
-:10A89000100BCCFFA7FC7E1B69C800BBE8AAC74C05
-:10A8A0003AD02F3EA2E218EEF7FC819EB721FD9828
-:10A8B0009E9B21FD233D37437A9C9E9B213D41CFAA
-:10A8C000CD90AE386F87C7CCC989218EB9D0BFF083
-:10A8D000F769E75B3984F1D7BEF1F71A71FCFB1415
-:10A8E00017C2B70FDF7B08FEDEEDB3D18194988BE2
-:10A8F000D05BCFDEBFA39F7420B808FFA3B67C0A4D
-:10A90000C76BEE6E3DCAFFDC767FD4CA907A2B8788
-:10A9100018B17DCE0B27A3A0FF6E5B1F7C1D125DBF
-:10A92000F24C1DCBAF7CFCB91B378E82F93BBE0FBE
-:10A930007441F7F96A4873DB7FFB00FC5E2AED1F68
-:10A94000E3247AA4C0663C2F68D6A1858358D7B388
-:10A95000D19D9BA0FDB32F0C859550BE43D8BE0161
-:10A960003A92C2AD7703AEE74653A010EE0BDD7806
-:10A97000410E1BA77D9F528A704E067A43FEDDCAA8
-:10A9800053465F026FDF747F6BFB23E2FD15E0A58A
-:10A990000AC8A5AFA2402FACE4F104EDBB87FD06C9
-:10A9A000D6E9392413F8BDDAD131EAFDB78BE34992
-:10A9B000A4397B8D4EC0D7B37B4F0D83F789297E99
-:10A9C00086C17BC5DB865C45427FEF3167EC978FA4
-:10A9D0003C1887F5F1F769E7916D15103733DFBC47
-:10A9E000FF0D58D242DBF10A889B599C241D8474C8
-:10A9F00089923919E265C47D8365234A0FC2969A0C
-:10AA000061AF447DAE14984C887C283747F247D814
-:10AA1000853C8A55E5A724A5AAEA4F53B254E5D34D
-:10AA2000478C54958B7167D80B54F546C70486C282
-:10AA3000798EAE83BD03FFA48CF186392F1CB97EBD
-:10AA400024CDCF7C6A0EBE43F92C2F9FF95CB91739
-:10AA5000F0D143E169A40AD5E9921F6C7E103AD384
-:10AA60009C176AF73E71D0A15CC679E112E7848138
-:10AA7000DE4F16EDB5E704CA371F00BE39FAC5D957
-:10AA800036F0DB3E3BF6CB148847FDCD10FEAE0C16
-:10AA90003F3F0C44377DFB435218DDBC259327C351
-:10AAA000D00D44F2323A64E9CCC3EC7EDE95F2B5C7
-:10AAB0004F81AFA1BDC043427F7F576BDF1B6DB499
-:10AAC000FFE636B047BD2BC30DA5BE7B932BE16FD0
-:10AAD0003948EF64F9B6BB93E3F0BB07F46137B7CD
-:10AAE000F70D52B83E55BBFFEEE4C2603959775CB2
-:10AAF000559FDC2935ABF21B33D5F97B4B9B43DBF0
-:10AB00000FA48FAD7C7889D19503F76EA5B0BF37C0
-:10AB10002CE6F3FF010980D5200080000000000032
-:10AB20001F8B08000000000000FFB5190B5454658E
-:10AB3000FABBF7CE0B1960782810427798440A8444
-:10AB4000895728B08DA01ED7DA1A4C8F545693E53A
-:10AB500003794DE0B6F4D8E318AD8FB6076D5B69A5
-:10AB60006B355696E7E439B144462536AE5B49EB82
-:10AB7000D654A266E499D8424C70267A6D9D5AF755
-:10AB8000FBFEFF5E672E605B9DD64EE79FEFFFFFEB
-:10AB9000FB7FEF279014CA70CE0008F6ACCC7099FA
-:10ABA0000106F7D61AE41880D3F4EFE2F0DAB8F928
-:10ABB0007A8303CF5700383ACCE3CF01D601140390
-:10ABC0005C29817BA2F3145960E760FF65F1BD2F1A
-:10ABD000010849009E178DDEED5684E35C06676E22
-:10ABE000F89E8DF04E0618D972FFEFBF2AC2F525E8
-:10ABF000B0E30E8CC4430DBD9BD7755C1471CD9F23
-:10AC000004D7D17779968098806B7055B407E200AD
-:10AC10009A6A633C623E9E67860E992E04C8F1A62E
-:10AC2000B59B52018E8A22C039440778A014EFE305
-:10AC30001B045F24A739EFA4DFB9C867CC2FC7E78F
-:10AC40004532B035BF3294E9C67BD77E87E71CBF5B
-:10AC500003A291CE3F804A8F034C5C2E04BBBD19EA
-:10AC6000FE3F233F4DBD1218909F61F01DBA5A6000
-:10AC7000D7CCA925002BE9A74CFB1D0690D86F194E
-:10AC8000707F95B2BFB27CE5A5108BF056FD4020D9
-:10AC90009BBD0FA7F1FFD57F6F3798F17CF553DA95
-:10ACA0007D420F53902FE5FB3AF0B377EB77E23D0F
-:10ACB00053F85E23DCFD9984EF367669BF5F24C7C5
-:10ACC000240DE6E08F0228382DB16D91DE6B36F150
-:10ACD000F7E64ADFBD7B09EAB1E925C96EC4ADD10B
-:10ACE000DDD3E200F98339A8E4D4F1F26BDA8C7A8F
-:10ACF0002A0CC3A7764BF3BD745F17CAA89E315EBA
-:10AD0000CE60C9E2F82C1C5F73C5D70B01F135F793
-:10AD1000E8D0D07E00CF4611E4083CCFED31AEF252
-:10AD20009AC3F4072D9CC7FC9E2F1366E7F2751D8E
-:10AD3000D101ED1C2F70BF9821803E09F141B56013
-:10AD4000DF8E4B5F4F7225C9BF4F009F5CC09E587E
-:10AD50006442FD5CC19FA37D3324E08F946C1DE1B0
-:10AD600059A8C8FD8AD27F7C23E0778B7B164F439E
-:10AD70000AE050D7B23ED40C6C906D0CDF12F0E8B4
-:10AD8000492F7DF1CEF416A4F3324960F6DF171F88
-:10AD90001A16107F5F45B4D026B0F7EFA4F755BE62
-:10ADA000FAF4CE7437E36B8E6510F526382E904E8C
-:10ADB000478F974758AE3A1854F52B7177217F9CEF
-:10ADC0002BDD3EFB12F4DBD1A5603122BD974B6831
-:10ADD0003808C3ABDC8FAB49D63351AE823F81E834
-:10ADE0006C96176E91F1BBE4D67B41971821371D05
-:10ADF000F733552FAA1CC7D3A1E22DF73B90BFD143
-:10AE00001D02B39F46BBCCECB3B1FCE4834B107F77
-:10AE1000A35FB20B48CFB2EEBD47487E1D6B3B40EF
-:10AE2000771E40E7DA6EB62E33997D521EE38BD93A
-:10AE3000AD8846417CAD5660C6A7357C1EE67B0CCE
-:10AE4000BC513F7C06CE043818EB7C9EF85BF3FBCC
-:10AE5000CFFB9610B51BCAE3991F90AD9D1BA63F73
-:10AE6000DF006046FA43DBA3BD4F303C68AF25618D
-:10AE70007B3DB127EB700B9E9F7853CFCC755FC5A0
-:10AE8000C3A76E4178CDF66826E71309E049A5F31C
-:10AE900027A67B3D7861A518EA6F21B977C6D8B798
-:10AEA000E3F9F147A73FBB13E1DA67A7D9894CF271
-:10AEB0001F19E57D3C1D01DA7F3E957D07291CEFBA
-:10AEC0000AC52FA56766DC574EE7CF24DA098FAA9B
-:10AED000BFA147A31C80F2FA127C791634BD93827D
-:10AEE0006750C487EBC49DC704B4CBDB0CAE83C4EE
-:10AEF000F7EA47FE7AA80CF9A97AE6370FCF44FAA9
-:10AF00006ADF9B0CF44E58AFE3E2406C2097FCDF05
-:10AF1000C6FD5F914FDD8E28CBC71171A6A1235EC0
-:10AF2000033775A75A3E8E883775C0650CF5828E3B
-:10AF3000F8A957FCAA5E741D25BA1A20C0E3228422
-:10AF40000C64570592E0A07810BAC7C8E43FD6CE8B
-:10AF5000466591D1512F828BE27941229852C86F78
-:10AF60005D5C7EC17BA63F7117CA66923541F5FBD9
-:10AF7000AC853322EDB3BFF115B2CFCD46669FC38A
-:10AF8000513C2F8DC5F31F399E7DBFC2F405F38759
-:10AF900033F9A4F5DF5A38171C14EF0ADAE4C29B20
-:10AFA000706D51F4722CC5295849EE1DF7EF3AC067
-:10AFB000E4B9F5E6A38477BF99E90F0E70B90705E8
-:10AFC0009E27D5F7569842A02B247AB7317AD5FD23
-:10AFD000C12D87F35CF8FEE00B397980F6BC4CF2AA
-:10AFE0000FFE05E5732AC67FEC365C3BF7BF3B8559
-:10AFF000F2E0587AEB5B47D97B2A3C2CF038544F6F
-:10B000007CE0FEF799CE64A213C3088B0F0377CDC3
-:10B0100060F29B2BE5C691FE8327B4F48DA5537D8A
-:10B020005FA54F7D5FBD37CD2A32398E18FC7994EC
-:10B03000F75FCC90357C8DC4FAF3E2CDB46FE17547
-:10B040004402C211F656433F51BF35268CDB485FA0
-:10B050004D8D606F03B6EFA1B889ABCF85E7F529B9
-:10B060002F2B7203A709ED78B162679094C8EC6E3C
-:10B070001170BB5EACC4EDABA0430FE82F47C475A5
-:10B08000BF35A0FD0D773CA07745C65DCF51F1746B
-:10B09000CE4F8FBB9E4AC8A6F83D6231B3BA669EBA
-:10B0A00055D0B17BE9904EF7F0DCEE433BF0741ADB
-:10B0B000ED6D48CFE3A2738115E5536FF0E5911F65
-:10B0C000A8DF3D2EBAD8FEB0706005E91B74BE3C07
-:10B0D00056EFC41B40C03A2338D9EE77505DF625B1
-:10B0E000B0B812D4434D27E22DAA12DD9DE6703C84
-:10B0F00054E367510EEEA35C2B685FF557B49BA237
-:10B100007CEDFD303F5AF8B895FB5D51A2E8EE9812
-:10B11000C05F6E57F4DC061D12F7679E47CB14B96B
-:10B1200063DD2245D62D8D4A9C0FC69A3C12F25300
-:10B13000B61BF5827099CEB797568C02D08AFA9DCD
-:10B14000053EFE5EB7369E530E59CAF2720ECBCB49
-:10B15000B31475AF17DC407A3551FEC2F52EC12FFE
-:10B16000D1FA2B08B1D501161DADA806B6CE012720
-:10B170005BE7819BADF3A19DAD0BA083AD97829F53
-:10B18000AD7081AF0D583EB8DD3288F9187EBD52E2
-:10B19000A4BC5CB464E27AFC71455E67970746F92B
-:10B1A000929F2F8F79E04A61749D4D2E53B399DDA4
-:10B1B000AB7231927DE27751E04DA1B50202EC9D78
-:10B1C0008BC990F19DD920EB08AE020783E7FE48BA
-:10B1D0007994065C3A57EE0472A99AD84E7628768E
-:10B1E000524C365D1CD6D787561E1754BD01D24926
-:10B1F000F960BC3E2183E82C8AAEFC5CC690F1DA93
-:10B20000B6F79D3A8CA34585952D36840F593FE5B9
-:10B210007059E5F399081FD976D2A99B49765E59F2
-:10B22000A8B76315BA6ED83907CF4D18FCA3504E96
-:10B23000924D82525C5D51B179807E6794ACEB7423
-:10B24000E857C6DB80C5195714809FD5B36865E4FD
-:10B250002735BC7E5D63E17ADB6B70BD4A7EDA60C8
-:10B26000F2C5CAC8D39A757393295F6E30F0F73F61
-:10B270009A2CE7BC827232223E5341984F3CF744ED
-:10B28000211C10E496566B18FF8FC0F7CF1FC277B2
-:10B290006B8AEB5D16CF4D5940FA4F53F2796767D1
-:10B2A000598A5D24FC16863F1093D5D28A470752EF
-:10B2B0009C1FD27BC1186E771F5AB95ECEB69A32E8
-:10B2C0001D1F5827D80FAEFB7A978FE2D02748086A
-:10B2D000BEF399D53540743489818C42D4D71DD1C1
-:10B2E000C70C6427AA1D0BA8BCA5C87F9B03BC067E
-:10B2F000E61FE59633F5982DEC07C1E5F81ECAA5C3
-:10B30000C8E9ACD2E371498D7B1FADA5AEF62A3CEE
-:10B31000213C41A2A7490AAD20BB3815FF9EE1138D
-:10B32000E6A753B93D2AF1AB674FEF6D691C744234
-:10B33000841F36EDF9E6AB0F50DF4DA3663B5D0F82
-:10B34000FBDF9616EA0BB01AD4C417D52F67751B0E
-:10B350007DD45F95ED3E7F39DDAB78AFDF4671FA86
-:10B36000E2FE401B95CBC19EC369DC2FD43AFE6B35
-:10B37000E1E7E493B9120575ACCB5E90BC46E4AB53
-:10B3800099EA0B05F6207CDC84761347F779BFA990
-:10B39000F6950DBDAF19A82FC1673CC46FAD42FF34
-:10B3A000AAAD375C4AF562AD57DB2FD6F57BD713D4
-:10B3B000DD753BB4FB6ABFD9A47C5F4FF59A8DEA7B
-:10B3C0003EEDBD26EA37F3A8FED3EE67662AFDA65A
-:10B3D00092FF40A933572A77883F33EBFF0C5E2357
-:10B3E000F2D6FC688BDD4270BAD9CEE26DFD0666FE
-:10B3F000C7EA7DD89AC86C44F5DBDA8DC0EA675598
-:10B400008EF94F1B1DA48FFCA793595D8CF53CABA7
-:10B4100047309EF0FE1E6522A0DD3D171FCA1411A5
-:10B42000CF733DD976AAB75F5EEB807F9D17A64F9D
-:10B43000ADF7E74A3BAB0CD447DD887D146E35F79A
-:10B440003ED96642B87913D00D242D3B8EEAA6E290
-:10B45000FD1278E91DF03E508E6B971A4F52B0BE28
-:10B460008F9047943C09E409FA79A3A2B7E8EC0469
-:10B47000CD798CFD1CCDF771A599DAEF3D0E7F6E6D
-:10B4800009C573FE7DBCE302CDFD36C16DF791CDDC
-:10B4900004F03FBC57AE88B1C2BF82CD1D12E71782
-:10B4A00068EE6F889DB79FECBBFC0BDD183B704BC3
-:10B4B000647765018047502FB386B5E7C507DB2168
-:10B4C00016F1471DD48D99577880EA16A3ACDD5F3D
-:10B4D000AEDAC55498AA99439C913BB7FBD1219110
-:10B4E000D945099CF7707911C9590F5E79BCDC46C2
-:10B4F00069A5FB6603F38B59BD2D768A47939D5A48
-:10B50000F927D768E59FEAD2CA3B6D9556DEE96E0A
-:10B51000ADBCCF6DD5CAD7EAD1CACFB67196E6FE1B
-:10B52000B4F64A0D3C7DF302CDFDF3BD0B3570CE74
-:10B530008EAB34F767742CD39CE777AFD69CAB7691
-:10B5400036D60E2EF4358FB13311C408FDAB7A56C2
-:10B55000EDA070FFAD1A3CFF6FFD6F1FA3FFA7C8E2
-:10B56000D731DEBD153B7437B9EB65D13CAE9D9943
-:10B570002794EB59BFF6B69C5815437795FCE654D3
-:10B58000F21B94FF91C3160EDBFDF67D14CF0A8EDD
-:10B5900038AB88AEA2807B1F85F392A1F6AA38BA99
-:10B5A000EF00D932858F9CE8FEE5A502E8347E8560
-:10B5B000F094B03CAFF0AC93E2F072D977DE36167F
-:10B5C0006EC9E94BC2F320A194E7856A4714E822CB
-:10B5D000E452A1EC0325E92961F9ABF323EC07C0A0
-:10B5E00040FD8068F2B65927AA77EC9B25568FB9A3
-:10B5F000587DF686E06273A545267F06C5F7DF25F0
-:10B60000BBDECEC4B8764AB4CBAC9E13026DC45434
-:10B610009018A3A4E5A9AF76501F87ED2CCD2BFF82
-:10B6200074476DB52797916F0994F0B699FEF56749
-:10B63000BA8E64A2FC0704CBFA42FCF6AD5927335C
-:10B64000287F1925944401CD4F1C47E9FCCCDC240C
-:10B6500019F9C3781B10650F89C273ABC0FA9093B8
-:10B66000F4D8CC08FFDDA867790B94BEEC1A455ED0
-:10B670006A5FB654C13F804FACC2787E4DF71B4C19
-:10B680002E7529C3CA1CCA6DB7E0FB374C3517505D
-:10B690005F0A8E423BEFE7D53E2D4DFA297955EDF5
-:10B6A0006BCF76BF2E6548D32FC3CEC409E7916315
-:10B6B000E75E61BEF9FB039BA2591E1AD894CEE641
-:10B6C0008BE1F74FB1F7AF71BFA3B193EB5ADFD75F
-:10B6D000D8DFF59E8F34E781A4903E0DF90FEC4A38
-:10B6E0009D7735CA6FE4056309F5ABA8B7385B7180
-:10B6F000F8FDC03DD3E710BEFFCDE7A74CBEFD6B04
-:10B70000FD6CEEA6F2796CED110607D606D83A96D6
-:10B710004FB5BF5557C3DF209BEAE59030C93ED1F6
-:10B72000BCE6311BEF83FA674FA9A47CDC9F6ED087
-:10B73000F1358BC3A9A5260ECF9B4F6B506FDE480A
-:10B74000FD6DBF000E01ED61A9E07CEC7AE4BB3A2F
-:10B75000D9956BA37A7275284F87FED0941FB8567F
-:10B76000407DBE1EEFCA27FE052C065313189D59B7
-:10B77000D4370C899E3C0163C14D4F765753FD3F32
-:10B7800034C9738A3276ADADAB9AFA832103F78F51
-:10B790005B9E7C84F9C3B716D74C7AE71341F2312C
-:10B7A0007B7E49F06E67F616302C8CF8BB823AAF80
-:10B7B000A17E9BFA9B60145F67DBF8DF5F2AC7AC52
-:10B7C0004B6D3CAEDD426B31E9E5EE2CFA7BCAE80D
-:10B7D0006623905F203E8748F87AF85C760AF2404C
-:10B7E000750D566FAC5F2878D5E8A3F8A1CE751615
-:10B7F000DBACECBD241B9FD724DD67F4B6B1FCEEB7
-:10B80000CFA8463ADBF558EF50DF7010D81C6D8496
-:10B81000E661117A596CE3FD17DC08C0CF93B7D10C
-:10B820007943EFC0318A27DF67BAAE24390C8872BA
-:10B8300009C59386D8BDACDE6BB6C9EC3BA497F1C5
-:10B840008F71E14ED2CF2F380F5C45FA6D300578FD
-:10B85000DDAACC03CF26B791E5FE8772D9FCCB9E3B
-:10B8600041F4A9F422FDCDB688B99D4A7FF89D1F09
-:10B87000F60B75AEA5C2835B3664919FA15EF8BCE2
-:10B880005112AE5B38C1F70F2AFA3E96E2F410FE71
-:10B89000D56E3EF70BDB4DFBCD4749CFBD66162776
-:10B8A000CFF6FD583E1BF6F43279209FD7127F1158
-:10B8B0007CDE1BC9E748CFE18772E59FCF5F309DF3
-:10B8C000FF1D29B8ED9B0C19BF6FD8FDC611B2BB87
-:10B8D00006751EDFA59D33182761FF9A30D11C1D08
-:10B8E000B34F445D6654BF9FAAD37E8F0539CDA95F
-:10B8F000BBC9DFA97E71F0BF8BA9F9B84BE96B8496
-:10B90000C0EB2C1F103EF287F58287E545758ED17E
-:10B910002660DE23DDBA5A589E90CE35DBC99EBB29
-:10B92000D006FDE4073A47349B5F8FE9A3BF35B8E3
-:10B930007691FCD6BC53994C7D76E79B0B947E8D1B
-:10B94000E7A962C52E8B093FD19F1BC7ECB548A163
-:10B95000AFC484F55026857C8FC4E715CAFC63D339
-:10B96000EB9A3EEFBF32596853001E000000000002
-:10B9700000000000000000001F8B08000000000015
-:10B9800000FFFB51CFC0F0038AC515191844D41924
-:10B99000184C341818566820C46989B5B829D39F43
-:10B9A000C9C2C0900DC4B9409C0FC47C4C0C0CFCA7
-:10B9B0004CC4EB171445B0F50419188480FC6F02D1
-:10B9C0000C0CD7851818BE8B30300803F92E40F1C7
-:10B9D0000420CE01626FA0580B905E04C4DD402CA1
-:10B9E000228ADF7C5102F26B8551F937D1F87B84D2
-:10B9F000F0EB5710C12FAF47401E1B16D1223F3E20
-:10BA00002229D03B10585F01955F26C7C0D0270F71
-:10BA10008C7FA8B80192FC4B20BB5C0EC2F69660EE
-:10BA2000602806F20D15B09BEB03942F01CA7D85AB
-:10BA3000CA0300CCCCBA8C680300000000000000F0
-:10BA40001F8B08000000000000FFE57D0B78144507
-:10BA5000B670F574F7CC2499994C12F2E03D490088
-:10BA600011030E2144C0709924C0A2460D021A147D
-:10BA7000750292849097887EECAEFE330189A0A86F
-:10BA8000F1B9AC17DD416137B2E8060C1835E0605A
-:10BA900000B32EBAC145C0E72680BC362443F0B9B6
-:10BAA000CB5E6F9D53D533DD9D09C4C7DE7FEFFFAD
-:10BAB0008F9F5FA5BAAAEB71DEE7D4E942328F27E8
-:10BAC000640A21DFC18F969F8B8490F850596F20B4
-:10BAD0002E924188D766F46D4CA6CF88237AE6680B
-:10BAE0005A981DD1375843EFE9CBD59EA434691835
-:10BAF000210F791C5812E223844EB55A2005F51601
-:10BB0000A83B93E07D3A3E21FDE8F80F46E2F8308D
-:10BB10002D99181A671031E07B53ADF989B01E4298
-:10BB20006A47E6C3FC163B21FD7B9F9F8E88EBA7EF
-:10BB3000EF0DC1F724FA9EB5EFEF2965570EFD13FF
-:10BB4000F6DF6DF66D1408F1EFFCC77158EF9986BA
-:10BB5000390E135D6F76B7D93F05EABE6C9F89B683
-:10BB6000E76EFBC026D1FEE5DB4409DA0D3B23F08E
-:10BB7000FDCE75820FEA95A6D647AEA4F5C03691E4
-:10BB80003C0FD3F82D069240C87133613F8715EB07
-:10BB90004511AC5ABE7ED76D305F49A38944D0F7BA
-:10BBA0008F37882EA82FD928F8089DAFFCB5078CB1
-:10BBB00003E878C53EA13EC241EB1B1F333AE83E85
-:10BBC00097EFFCD8D646E17CDA63260E23EEA3A4D9
-:10BBD0003E8D9052DF96E903E8FBA59B052780BECA
-:10BBE00074DDD94E585F69833C5CA4E32DAE8B2293
-:10BBF0008E916CEEEF08CCD77C14E7DB260F83F92F
-:10BC00004ACEDF650424E56E93912ECAE93A60DFDF
-:10BC1000CABCA73D6B713E059EE52FD2F968BF8A6D
-:10BC20009705276CB1C240DCB08ECED7220A5EB039
-:10BC3000C0FEAA8D23ACEA7D146E877D94FAD61BD4
-:10BC4000A75B607DEB8D4569A1F116D7FDA7767DD9
-:10BC50006B5313DD69BDE3F3B487827444A85E4A75
-:10BC6000880BE94FF219818E95E7E78518C4F7E252
-:10BC70003A9138CCA1F1153AF07EC0E9748795F17C
-:10BC800001C7DB123BE02C84B76E3BC7A314C8543A
-:10BC90008FAF948F003EE87A6A3D762C1FF72461BF
-:10BCA000F9A4C781707BDA3312CBB51E273E7FC65D
-:10BCB0003301CB751E1796CF796660E9F3E463BF55
-:10BCC000E73D05586EF0B8F1F96F3D2558D679AAD1
-:10BCD000F0F926CF322C377BBCF8FC65CF2A2CEB51
-:10BCE0003DB5586E057CD1B2C1E3C37EDB3D7558CE
-:10BCF000367AEAF1F9EB9E462CD77038DAB248B6BC
-:10BD000044E16073113B453B89CD7365CBB41E9B09
-:10BD1000CFEA09F3BCD9465A4F70D33A85CB80326B
-:10BD20007FB689D60754B1F621F7921C33AD0FF1D7
-:10BD3000B2F69435AE9C085A4FA965ED23D67973B7
-:10BD400022697D848FB58FDAECCF89A2F551F5ACED
-:10BD50007D4C13C9B5D0FA183FABA7EF73E55A690C
-:10BD60003DBD95D5333FF1E6DA683DB38DBD3FA9C2
-:10BD7000C3273A2C3DF1B055762C2014574DDEB92F
-:10BD80002E89CA9BAD46C75DC449C87BDEF92E89A2
-:10BD9000CA8706D985ED6DDEC5AC6E74617BB77759
-:10BDA00029F6DF2EBBB15DAABE0FDBB71BDDD89E27
-:10BDB000505D83ED8DB217DB47563F8AED8D462FE0
-:10BDC000B64FAA5E8BF5D7651FB6E755AFC7FEAF76
-:10BDD0001B7DD8FEF8FD9B5C5369FD05C1BD1DE4CC
-:10BDE000DE0AC15D4252819EEA9340EED570F9F9B8
-:10BDF0001C101D6DAFE96F443EDCFA6EE60BC0BF50
-:10BE0000F8EB07F5A2DF3E988CE3BC89E3C8741C0D
-:10BE1000F1E2E3A4BF3741334EFA7B25CA382D380F
-:10BE20004E44DFC6D9FADE24ED7ADE2B55C6D90F93
-:10BE3000FCB4C2DAB77DA5FF394BBB9E3F9729E31F
-:10BE40007C84EB89E9DB7A1A3ED0C2A7E183207CAF
-:10BE50008EE238F17D5B4FC6412D7C320E06E1D378
-:10BE600081E3F4EFDB380D07B5F069381884CF971C
-:10BE7000089FC17DDB57C6212D7C320E05E1F35FA3
-:10BE8000B89EE4BE8DB3FD532D7CB67F1A848F49D6
-:10BE900080F50CEFDBBE323FD3C227F3B3207CEC3E
-:10BEA00038CEA57D1B67FB675AF86CFF2C089FFEF8
-:10BEB00038CEE8BEED2BF3AF5AF864FE35089F1478
-:10BEC00001E033B66FEB69FC5C0B9FC6CF83F0B922
-:10BED0000CC719DFB7F54C38AE85CF84E341F86461
-:10BEE000E0BE26F66D9CC6E35AF8341E0FC26732D8
-:10BEF0008E33B96FFB9A70420B9F092782F0998E9F
-:10BF0000E364BBEB985146C7B1F63ECEEB67B4F0A5
-:10BF100079FD4C103ED7E338D3E838A9171F675294
-:10BF2000A7163E933A83F029C071AEEADB38AF77AB
-:10BF30006AE1F37A67103E8538CEB57DDBD7A42E53
-:10BF40002D7C267531F88C3B50956BA3ED54173A38
-:10BF500045FACA951D2E9740EBA29DD545BB93800F
-:10BF60005D222AF606697589F47DCBE698F4078987
-:10BF7000DAEEC8B913E8C74AAD31B5DD113D21523B
-:10BF800063E7C4B86235F5B8190334FDE3F35334FD
-:10BF9000ED8905A334EDFDDDE99AFAC092499AFED8
-:10BFA00083AB7234F5A1CBAED6F44FF6DEA0A9A7D1
-:10BFB000AEBA59D37F78ED7C4DFB256B4B35ED97B1
-:10BFC000FA9668EA97D5FD42D37F74FD724DFBE582
-:10BFD0008D0F6ADAC7FA1FD7D4C7B53CA3E93FBEB5
-:10BFE000F5794DFB15873769DA27B66DD5D4AF3CA7
-:10BFF000F9BACECEB3D88F5FC6EB22D03D61767F43
-:10C000007FE6F7F8AD46AC1B0758D08EDF652D7282
-:10C010001CA3F835BEB5C0D18FE217700A7E45F675
-:10C0200080924BDAE8F37B26B92FB1D3E7F718DD1E
-:10C0300097DBC3D8A7941E049204A5C300A5BEFD38
-:10C040000199D163CEC0F323DAE9FB9586C0881845
-:10C050005ACF12B31B817E770ACC2F8A144915F46C
-:10C060008B3411F40B1E48CE7CC1ABA2D75583296B
-:10C070001F0AA17157C9EE24B033DEAA6EF7821DE4
-:10C08000523398EE6B0021CD42BBDF4BFDB4070667
-:10C090001725B9E9782623B5D3D5F31BE9FC693810
-:10C0A0007F0BD0EB7B307F7CCFF94D291334F39B92
-:10C0B000879468E6371BE9FC7642DEAF3EC5E7A70A
-:10C0C000489844C85F845338BF694809CEFF8091BF
-:10C0D000FA2BEAF92383F31F86FD7FD6DBFE532676
-:10C0E00069F73FA454BB7F23DBFF91EAB37CFE4892
-:10C0F000DCFF51E12CDBFF9052B67F131B3738BFBA
-:10C100002D08FF93307F672FF39B52B3B4FB1F5A68
-:10C11000A6DDBF89CDDF5DFD2D9FDF82F39F13BEBE
-:10C1200065FB1F5A86F31B4D6E27D08F7160649597
-:10C130008FCE4F1D6107490472A1F340393216FDBD
-:10C14000E49784145CC73D918CDEBE8AA4F486F229
-:10C15000C6CBFC581F956C99D4EFE2B4BE7873B689
-:10C1600011E412B6537F65215FEA1D8D22D2377923
-:10C17000D2E41B4ED7DBD9287AA17EC793937D20CA
-:10C18000FF2A4DE4F67C784F227E78FEF953A39F78
-:10C1900057EF4B5F2EAC958FB7A9F82DE847E59088
-:10C1A00091551698D7AEA91FA17E10A1FEC527D420
-:10C1B000CF2094248FCA6CBECFA8BF04F536EA2FD7
-:10C1C000413B21D5B85FE2757D308CAE3F9F283F63
-:10C1D00017EEF32664293A9EC4F8F7C81AC107F887
-:10C1E000B87D5914057E683D85DE384D9DEE0FFB08
-:10C1F00007AE127CCF0B38861BE033938F4760BDB0
-:10C20000B45E6067EF1CA2E8EF4F51B060D5408A82
-:10C210008BD038B3884B4EA4EFCF595A2843E8A2AD
-:10C220005510062F01FA5920539711E0E78D276921
-:10C230009C38E87A6FB6B3F167BAE4636DAAF51477
-:10C24000C866573E5D4F41A188EB9F3543DBFED169
-:10C25000CE2897610C2D573D81F3CCC9D7B6DF545A
-:10C26000A0ADCF756BEB54EFC9A0F76E29D13FA7F6
-:10C2700060A1FB9C17842B5D285DE7AD1C0EB756B3
-:10C28000C95E0D5EC16D55DA21A0E026B82F7C5F36
-:10C29000ECD9FFF665DA7AA1575B5FB04A373EA763
-:10C2A0009BE31CFF47803E687902E883C2F318A72E
-:10C2B0008F905CD5D2C78DC16D30FA50F6715C623B
-:10C2C0002838BE8ED1C7C2DAA8F0F45018A4079758
-:10C2D0009ABE147AB88DD3C3A79C1E8AD76AE96A1E
-:10C2E0002EF1AD4CA2EFDFB26617E2E9A050C8E82C
-:10C2F000E1970A3DB469E8C1CDE9418FBFDB383D24
-:10C30000DCF673460F7A7CB6717A685B7B4E262921
-:10C310003DF14AF1A0A9533CE8F06E37023D507C54
-:10C3200084A587F9C17DD38DD3FA02DED6035F9C45
-:10C330001EB03D05C04E104EF87E6ACFFE544E68CA
-:10C34000EAC56BC3E3BFB2313BEE986A5DE5F557D2
-:10C35000C51D53F55B5C3753535FE49BABE95FBC92
-:10C36000B650D3BEB07691A67DC1AA3B35F542EF5B
-:10C37000CF35FD6F5F56AD69BFB56AB5A6FD969224
-:10C38000C734F5B9EE5F6BFADF54B05ED33E27FFDA
-:10C39000454DFBAC195B34F599AED734FD0D3B2F01
-:10C3A000BD1EE831EBA048C0FE38E67120DD1FF766
-:10C3B0008CC4F2A4C7897C71DA3301CB7D8DCD4F5B
-:10C3C0005C49BB7C192888264C7F16911842F62CB4
-:10C3D0007757AFCA027D4E50EFFE717951B5771095
-:10C3E00095530607C2396FAD91F8C711228052E20A
-:10C3F000F307C4507B561B6D8FEBBD3D6FAD14B67C
-:10C400003DAB4D0A3B6EE5E38543ED61E233217EB2
-:10C410002603C13EEAE2F6B9BEBD4C20F9EAE78444
-:10C420002C47FE8F3130FD5C666472A26C6BFF1C82
-:10C430006283BA7F44D585E6ABA7CC9508F491AA70
-:10C44000E1E3E2B59769E43C81E86D3CD0D938CDB1
-:10C45000F3C575576ADEEBD825E2BA2B4086507DCE
-:10C460003D8CE4070CA097FDCD43668D8675BACE52
-:10C470001A405E35C6A3FDD8E19911774C023CE61F
-:10C480006379D25380E5718F1BCB639E122C8F781A
-:10C49000AAB06CF32CC3F2338F17CB4F3CABB0FC7C
-:10C4A000C8538BE561CF5A2C0F7A7C581EF0D461AB
-:10C4B000F9BEA71ECB564F23969D1E17960ABF297D
-:10C4C000F0D0D3DD49AEA74F03FD5D80CEE2C407B7
-:10C4D000AA570D0AD159E28A87ABBD59A171F3D68B
-:10C4E0009A389D2468E86108F864E3815E4C9C5E9C
-:10C4F000C2B7E7AD952FD89ED526871DBFF2F97F2D
-:10C500000DBDCDF991F416A2A7813A7A4ABD183D26
-:10C510004D12C787E8698EC1CEF41FA7A787601F99
-:10C5200061FC8F6230EAC6ABEC3A57148B67F37349
-:10C53000076AD1B278369F7B051DAE15ED3FDF4807
-:10C54000C073F7C8BF8F80787DF761AA28937BDF1F
-:10C550009F9E5E7A87BB0BFDA0221F55A2E37AB691
-:10C56000474432B84618C80C924EC8EAE1BF75CEAF
-:10C570004FC3BA4462E17D9F736698F32802674F08
-:10C58000891787EB0AEB576360BCE3CFFC2313CA20
-:10C59000398614E6DF348B68DF13FF0B4E806F5053
-:10C5A0001F999C4910070F0C37DAD13EF059B4F0AF
-:10C5B000F3D27A66087EAB298C5A51DFD72621FC4C
-:10C5C000867D35A27F1FE07731397F3178CEF70D38
-:10C5D000F897C0F362F2F1627291B81C2F37D2FD66
-:10C5E00077ED1C9DFEA003E4E085E1AD9C5FE9D7FB
-:10C5F000F3BC287D2F3AEE4A50E8B87508A1F388BD
-:10C60000A21DC7EF6EB884C92FC5EEDB66F2F50533
-:10C61000AF6792B5E33DC5F94F19AFBBE5051BF810
-:10C620005B4B920CF66361F0A094E5F5C9768BDA6A
-:10C63000FE6CD4D6BB6B8519F568273AA2678F06C6
-:10C640003D61B71F1B06723B094B659C254946FBA4
-:10C65000312AF74ED7A546333FCFC7E4C1E6189439
-:10C6600017A73D66ECFF53AFA7B77194F510D24002
-:10C670008E9A411ED3B6D4DEFBF74ACFD217463C82
-:10C68000F76D92BF02FBD04CFFFF0EFC0D22615DE7
-:10C6900019B7B25EF49A2E87E79B35F3D1F71CCA1F
-:10C6A00019EB772917E21B891C57E896EA8B635C24
-:10C6B0009F2CAE8BB06BEDCF184DBDB2B1BF5D639B
-:10C6C0008FC21F54FE922A4102FA29E3E4D325596E
-:10C6D0005609747D6F429010E85660FDCACD6D46D4
-:10C6E000B703CE9519DE7A5B1FC5DF4C89927C8932
-:10C6F000B916CF614BEA2F9D0A7AE64CC38A0488AB
-:10C700001B2C16BBEFC90FF3BE2C3179BFC827070E
-:10C71000B4F63DA70F42C7559E635C94588EABEAB2
-:10C720001D06168FD18F9B00E3C65F1C3E159BF73D
-:10C730004F073B410FA78AC6B34637CA45FA5F6623
-:10C74000084E0AFCDE14F313243A7E695D3BC62DC5
-:10C750004ECADE11BFBC80BCECB93F4BD2F128D52C
-:10C76000BEBCA415E6993F814F441C377D4CE5F8CB
-:10C77000A93FC904E410394F7B65624886FB3B063C
-:10C7800062C80CF93BF31B16E701BC4F81BF47E5BC
-:10C79000E61D24DF867820B599E0DF9C218619000C
-:10C7A000A733E47DDB38151E7225238733958294E9
-:10C7B0001E4CC1F1DDFDC1EF3215D4B48A63E0B97E
-:10C7C000A4F83FC2771847720B98B750C09E7B8978
-:10C7D000B91AE897FA511A3F8DFA519A3AF5A334EB
-:10C7E000F522724302E425143D29139F8070D2B4D0
-:10C7F0008F92EC88C762525503F6D1AF79FC6DBEBB
-:10C800009D4803E93ECB5F7D36B390EEE76A89C56C
-:10C81000FD9473F545B10C0EA5253EA3CBD2737FD5
-:10C82000471BC6DD48253F8CC7CECF6F36621E053D
-:10C83000B44A99DCF449E97DFF890DA22BC206FDBB
-:10C84000E87365BDC9DF7FFFFAFD12F238EEA3B4CD
-:10C850006E2601FAEB9127C0F723D7092E5F187EC9
-:10C860002AE474AFE8A73B017EE343F1ACFB74F527
-:10C87000D51CBE4AFD295DFB0F962FFD8846BEBC28
-:10C8800029BAEF93C6337902F017A400F2D70F1E2E
-:10C890003FA9C7F8AB811F7FB2F10769F99E8EFFF0
-:10C8A000D44FBAFE613DD6BF3EDCFACB5F7D69BB9B
-:10C8B00097EA97D23F3C652394DF4E49B5094E8AEB
-:10C8C000F7B28D2B6D2E903B92D7067C71CA27CE86
-:10C8D00008470F87B87CA506884580782BFC49C798
-:10C8E0003FBDE9A1EBC09EF86AA36CC7386A9DC939
-:10C8F0006FA2F45CD1B0288F8CC17A3BAB3F70162D
-:10C90000E8BFB2513EA2A6D3D2DF3D95007935945F
-:10C9100052061A92A0F4A37F52B1E1F3E9606F547A
-:10C920009200F2ABFE3D98FF9B58D48785C6E89EE7
-:10C93000ED18984980F7D9AFB2E1A1B3A20DFE6A14
-:10C94000C33890BE7F09F7375A246B3F3C27B98222
-:10C950005C01F2548107F1317F63C58BBF1AD34E5E
-:10C96000D7D3B1E14F36410527C54FEAAE5FF09B03
-:10C97000D71DBDCBEF4ECA876ABB56D14F8E46EE50
-:10C980002735B1B24CF6DBAEA4F2A46CBDECF4D208
-:10C99000C7652FBDF0DB67207EFDA1C9399C8EBF26
-:10C9A000F8A53D0727D1FAE22D72BF3CB60D8B905A
-:10C9B00010C24B25FD7F597A080FA5AFEC313A46DE
-:10C9C000B3E7F7C686F0B178CB2E2319DD131EB975
-:10C9D000F5BB8C6D963078A96F9F0E76DF8A17BFF6
-:10C9E0003682BC3BB5532089C961E0B97E0FDA8538
-:10C9F0000027C423C753106FBAFE95142FA05F14ED
-:10CA00003CE9DB37717902E339D2909E5F7E9DCE9F
-:10CA10005FF291C909FB2F79F92E1BECE38454C511
-:10CA2000E8FAD9950920DF4A646F821D4BF6BCE411
-:10CA3000B9BB91DE8AF7DF9DC0E292AEFE06D495C7
-:10CA4000DEFEB0BF85EBE6E0FE8A881BE9AEE45966
-:10CA500031DF47CB2F2532634B18BEB8566672F2D2
-:10CA6000C4F35423D0FD9D50F4C0FB22D70377625A
-:10CA7000DCF36EBE176A3162FD4B33C3D330D9C0CD
-:10CA8000E52CD32B417ADDF000EA8BD3835D8970EE
-:10CA9000BE5619D20FA837C4FDD312197E989EC175
-:10CAA000F7A89EC985E7D0BF5576458CD1BC877A5B
-:10CAB00045997F299F9FAE3B12ECB51309E1FD8F8D
-:10CAC0009FCB0ADF53BB42455F2AFE66FCBE613541
-:10CAD000E36F85DF7D336740FB170718FFC07BA03E
-:10CAE00067E9BAFC89D8BE6BB680F2C044FCE1F8B5
-:10CAF0007A83CCF95ADBAED0095DB72444ABE805A4
-:10CB0000C68F45F8A35E2F7A92BEA7929795309F65
-:10CB1000ADE7780ADF1673FE9F216BF99FAC8BEFB0
-:10CB2000533E6599ECFBED33C0AF943FBD0EE0572B
-:10CB3000391FF6FDB7CDCD076FA67CFAB77A854FC2
-:10CB4000B5F253CFA7255BEF26409F7A3EFDDBA0D1
-:10CB50002A12964FE9F3B07C3AA8ED7F547E2AF072
-:10CB6000AB02F84585E0A7C8C3DEE0A8978756D991
-:10CB700011561ED2DF0192D993FE14BA53E8ADF4D8
-:10CB8000F7E54341EE04E952A1BB205D2A74A7DF1B
-:10CB9000AF167EFAF64932C175E5BF26A3FF5CD613
-:10CBA000C4F242E97B7B0766209C5CA8C648EDDEA8
-:10CBB00081FDD4759FAE5EAFEBEFD2D5F375FDDD91
-:10CBC000BA7A95A67F5963B39120FEFD9A7EE2B2B0
-:10CBD00067C8D1B870F4EA637E59C359A317E8C295
-:10CBE00012C0F7E5E5C40B7986811D22C605BA2877
-:10CBF0008C6B207EB139D9E7A5726365048B3F74D5
-:10CC0000D903B6585AAE8C61F540BCB106E49EF229
-:10CC10003C10C1E28A5DF9015B8CCA9F6A6F1251B8
-:10CC20006EB7F9C88C707E16D528C8476DA4B77644
-:10CC300076EE354DB40C590671A55AD10936F81D5A
-:10CC4000D537D9E0DCA9AB29F5FA02FA7CE11F451A
-:10CC50004C7BE98AB48D817511AF4BEAAFF26F4E10
-:10CC600012EFD359747F0B9A989F73C71A9D3D4258
-:10CC7000D6203D1559961A419E527FE288F6BC8611
-:10CC8000F145291FAF649DB65D799FD201FAF3A5E6
-:10CC90001BB4ED6EEE0F7FA0F0C9583296FBA32CAB
-:10CCA0000EC3E5F23431EDFA028A8FAE1691986820
-:10CCB000BDBB49447C746F167C104F23DE78E4B70B
-:10CCC0000A124079A8C0A903F8C9D8BBBCEAD8F6B3
-:10CCD00069E62F816EB67F3CE63F69D9B1FDC3118D
-:10CCE0006F40FDD543433E263DFBE7EE8CC073FF0E
-:10CCF000AE9D56A4F7AE1DEF0EF925D45F33396112
-:10CD00009D5D3BBF1E03F4D3B5DC5402F2AE6B3025
-:10CD10008BC7AED8F1F59836D4AFF733FD6164FE1A
-:10CD20006177D33F3E13FA4149770576C3CE28E4B5
-:10CD3000A7CAD72330DFBB6BC7D7996ECB4FB79F3E
-:10CD40000A9EE7D16525055B617D312C8FA1F28DAF
-:10CD5000892F54D3F9CB1B761917D0F6DC37FF395E
-:10CD600006E468D756660F75CA6DCF411E4394F12D
-:10CD7000DC7299E2AB13988A3ACDBF3366E402DFE6
-:10CD8000F484CB3F313ED65778A4FCAF8187E06274
-:10CD9000F2CEEA330BB0EF6F3FFB18E39A26A44BB9
-:10CDA00065BF7FABAF467BE562FBCEFE7F6EDF8269
-:10CDB000BF2FFB76FF9BEFFB38D7BB7A3EE849E7F6
-:10CDC0003BEEC1FA4B5627AEB78FF4EE85FDC7FF99
-:10CDD000FBEEFF7BE37D2BC5BBEDE2FBFECDFF5AF7
-:10CDE000BCFFF1368E773B7ED7F3E63F717DDF5790
-:10CDF000CEBDF96F8EF7DEF6AFD8F5AD862A7B068D
-:10CE00005D5F01A9B582613137BEDB92E1806CD7ED
-:10CE100073FD308F0ECE4BC3F84D0123F30B4D90B5
-:10CE200047077EFB1C41890BA21F751DB71FAE1B58
-:10CE3000548276C875AE8799DD2055B566D3FEADB0
-:10CE4000390B9C987349D20FBBA13E7B32AF6BFD6F
-:10CE5000C9F704E212A81D7F5DCE352D60D75EEFC5
-:10CE600012D1EEA525DABB1F0C99CE9E4FD0FA3D0C
-:10CE700073DDDAFA4D05DAFA1C3EDE8D84ADFFC6AD
-:10CE80007CC107715553F613F11067352D948990C5
-:10CE90000CF942552BC1BF9893AF7D7F1FF8C1E3BA
-:10CEA0007F3C1C534D0A1C97205C48B6E8DC48FACE
-:10CEB0000047BEEED6D9637D90CF4C242783E38D07
-:10CEC000E54E8C83737F5BE6EFCB9655ADC0CFB25A
-:10CED000CECF56FCE5DEE04DB8FF8DE3A484E02F15
-:10CEE000BB44F4BF659DFFADE0E5FBE243C1E38FCA
-:10CEF000C5CB973ABC0CB2B808F0ABCCFD85A916EF
-:10CF000027AB0FCA2778DEC8FD05A99F8B78D342CF
-:10CF100079DF8BCCE66C385F338F1430DE71FD1A0D
-:10CF200011F583394DC075E54F90318FF873437E0D
-:10CF300026E03B6FDC1515BF60CB70023C1771B863
-:10CF400017912AB45FC9F9EFBECBCA84730682F683
-:10CF5000EF221721D752BFAD284BF0475278154B1F
-:10CF6000C41B9D0E716F811CD1C4BDB575F8FD4702
-:10CF700042689C8BF5EF4DBEFCD4E55FA93C3B328B
-:10CF80008CFA411E9EBB4958DC56F1AF6F6F627040
-:10CF9000AC2C137C2948777E395F75EEF81CE7834B
-:10CFA000BFDE3B0EE564F6A3A3A3D1EF7739D06FC4
-:10CFB000A8E47E43B7D7110D71AEEEA6547E3E9B1A
-:10CFC0006B53CB55A5DCCFFDEEBF407E212DBBA61C
-:10CFD0000AB522F8712480F15CEFD408B2314CFE1E
-:10CFE000EBFF311938FD54611C007E6226E091FD93
-:10CFF0008AE9ABD1B12ABCADB9F69434A6271EE0BC
-:10D000007744750EF963E10B7E3EC0757F44DBF417
-:10D01000FC30FBAD35B13856DE5BDFE2779C373450
-:10D0200025CB00971BA68A9A73FB5526EE978D2376
-:10D03000E3605D796F5D659B087869119DF0DD6641
-:10D0400065D359A33BCC79B01E9E303EC4D58FCA60
-:10D05000CE2280E7D1872308F8D1EFF273C634F8E7
-:10D060006E220D433A2E882BFE9AC3B5D364C77245
-:10D07000565EB61C4FE74D6BB08F85A3D401BC7FC5
-:10D08000271821E3218987BDA7F41B50C6FAB51BD9
-:10D09000ED15E1F63F3C82EDBF9838EF9920FCFB9F
-:10D0A000E12DFB51AB3F07EC83A93CAED283AE0927
-:10D0B000F247F70CC107FA1BFC61ACE7B1EF84DF64
-:10D0C00055BEB3BE81E95985EEF570DECBE1ACCC3F
-:10D0D0007FDCC4E2AF7FE2FCA5C05981AF7EBD4AD0
-:10D0E0007F2AAFA6A8E351D7378E7D19EC9B8A26FD
-:10D0F000C16EA04355486D46E0C3CAC6C764386FC9
-:10D1000099EB60E312297F8C3A9FA0D3C4F23B9A3B
-:10D11000D3AFBC0DE8E4DC1A13E842E2BAE3AC0D8D
-:10D12000E4F0BB06E79FE17B6AEF7B22D9780179C7
-:10D13000F5B1A7CE3555528F9B8CEB9C55962D4360
-:10D14000F8EC96B25D72A28A9E3A4DB1D8AE3C1F01
-:10D1500050E64887E7743E5C87F7111381EF42D2AF
-:10D16000EA5BF1FBD45BAA62181D96D4EF32623DF4
-:10D1700019FB2BF329F3E8F969769E36EF78416EB7
-:10D18000DB20804B9EC9BFD419864E1F332BE78E00
-:10D19000DF534FB828DD8EF9FF484F2C55F4441B60
-:10D1A000E6B92BEFCF35333E57E989C4707A62492F
-:10D1B000B52311F0B064476A2230C9923F4E4B0844
-:10D1C000A7273EF0B073E343FCBBEEAED9544F5CEF
-:10D1D000AED213B323904EF4EFE59A95738D8BE89E
-:10D1E00009056FFFC3F2E603D01361F8FB46B3569F
-:10D1F0004FDCD854887AE2C6D9A2E6FBAA6BCD17D9
-:10D20000D313D90973B12E3BA3C2D0CF07DCBF39EA
-:10D21000C4F3FB611ED0176BCC76849B5E6FF42643
-:10D22000D7C7F655AEFF5F82B322D797CC61F743DD
-:10D23000F4A44382F4BC642E95EB02D02393EB4B11
-:10D240006EE5714E9D9CCD07399BA196B3ECFD0A0E
-:10D2500037D30B958DC9BF9A47DB6FAE959D66DAC4
-:10D26000FFE690DCCD54CBDD356609E1DC43EE967C
-:10D2700030B97BAE691CDA4FBDEDEF532E6FA93C80
-:10D280001BE60C431F05F3A234DFDF1D1DFB76DA1E
-:10D290002BC02FEF8A787EFB39B703F68D7D3B03D9
-:10D2A000ECE9537C3DDBB8FCEBF4F85C53A91CC8FB
-:10D2B000BD83D9D3E59B45845F4503E3FF8A619134
-:10D2C0003E07AD4F4FFF16CF6117EF60E7B0740711
-:10D2D00079D92AFC2F7EB7AD06CE0516AF17F01C04
-:10D2E00019BE5F0078167378163917E3394AF1DAF8
-:10D2F000F0E73FE5BCDFA2A6F5180F5FE4D3F62BFD
-:10D300001F76F529F047F24C0C0F79AF08BEF5C92E
-:10D3100090CFA0EBE75C8DE747E5F5DAE707F97E0C
-:10D32000178AFEB457E8FBE4CFCCBFD3C3FBA01EE3
-:10D330002E253F122EFB295C32FEF570E90D0ED42E
-:10D34000BEC7F3013D3C0E2B72259D64001F7E6E0F
-:10D3500070A15CF1BE43E142E7BBE3B1E19AFB405F
-:10D360008E73B8BC6B70D7F4877E1502F62B5EB750
-:10D37000654F02ADCFAB2763E178A178AD560F07BB
-:10D38000F57E8303F5FABCAA2D02E4C72EE4DFFB89
-:10D3900095F81EC37B546E5D46F53CEDBF20DDE481
-:10D3A0008673F0FD1101949B0ADDC64730FB258E84
-:10D3B000CBA1A3030253513F350A76E4477F04D340
-:10D3C00057144F70BF4BF3C4AFA773BCB0B8522310
-:10D3D000C36325C51BF0F3F4265EAF6376E02D4AE8
-:10D3E000BD5EF0390490ABBB64765F8C40E2048E86
-:10D3F00004957E84F3D5EC04159E77B433FADF28C8
-:10D4000038F1818FFEF743F0DC2BDD333BA6AFF420
-:10D41000AEC0293E428BE7FD11AD79E3FAC1F99B1D
-:10D42000E0C47B739A62F09CE8582DBBFF2595BF42
-:10D43000A7E70BF03BD4F7D1CC8485437EF38C086F
-:10D44000CC0FC57953985DA6964FFA7B80BE6FFED0
-:10D45000512569457B2C94C7E87EDE04E3CD10346A
-:10D46000F94E1009033AFF09C6BFD57C81F14992F4
-:10D470001DF396EFB22BCFEDECBB2C5E6F1E9C79AB
-:10D48000681E85EFB955A2135CA89B0C8E835920AA
-:10D490006F1E9409F0CBB97DB28BE98128D43B850E
-:10D4A000EF1EC5EFD90A590E1A29BC8FE997A37C44
-:10D4B0003D1F51BDED82580AA91F0FF7E0CC76EE53
-:10D4C0009AE680784BC6FE9570CE392BD77EF02039
-:10D4D000E07335BB07E9C8AA5CF4D3EEBA53407ECB
-:10D4E0003B4CF106EFCF999D7CF0209DF7D655F18E
-:10D4F000786E39CF157F239C63CEDB273A1DB4DFCE
-:10D5000082EBAD1638C7BC66A448DC2AF8DC4A5A60
-:10D5100031BE33AFEACE39B0EE12AA0FC56428F798
-:10D520004F4B84FA3A01DFAFF4BA8DF0BD66EBDA07
-:10D53000B3C60C3A7F11ED0760AF5CC7FA556E10A9
-:10D540009C90FA5DD4F418CACBA20D025E34D34A83
-:10D55000ED5F331BD767A6E3B6AEA3EFD37A31BC3A
-:10D560000FE36E88B911CE272BE93AF1FD09D57882
-:10D570002E5D44DFA3CDA475C39D38DEA275028164
-:10D58000EF034B26243F3201C6DB273BA1FDD0AE83
-:10D590005F1B61DDB7D1F9FAD3F117886DD3A03FD6
-:10D5A000F9A560C7FB87EA4660DCAD0B360C2F544B
-:10D5B0000DC73AE6133B100C923A1F654704FB4E29
-:10D5C000B86859750DECABCD1B9F6C40BA3A6B0433
-:10D5D0003D7E8CC2DB4D873C6A64792ECDDEA3C6CE
-:10D5E00036951CFD282215DFBFA3311BF3261692AA
-:10D5F0007CCC9B7057337BA47D65840FE26AEDB2CF
-:10D600007D083C6F5E69C2E79D2F31FDD339B80DAF
-:10D61000E3DB27D6C904BE5F5CB12EF569C0E389A0
-:10D62000CD32D29BF82CCB1B287E89C5C99AD7B1A5
-:10D63000714F2C35B27BB5A09DD68B5F54F20AB4E6
-:10D6400072ACC8518A724A2F97F4726BD193D54647
-:10D6500020D91EF26AE9749457A554EF00A1F59001
-:10D6600057836A306EAA975795C4A2C8A974885F79
-:10D6700016960FBE6D2DD0F1ADEC838156FF6B5F1A
-:10D680003E057AB7CC4AE04985647F5A6074418090
-:10D690005FE6356DF912F8A0645E04DEC7751CF014
-:10D6A000007CB3260ECFAF8B7C85086F252FB77813
-:10D6B000AD96CE95F8E35CB7485C6AFD5512455CC3
-:10D6C000AA7E87EEA3F44AE7B9BD51F081A83C7465
-:10D6D0005FFBDEBB33B06EC7752DE3F6C11A2BD2EC
-:10D6E000F3A19F9F5D09F47ADBBD02017B9D78DD8C
-:10D6F00035A00F2BD60A0E880F17DFCBDE2FA6EF33
-:10D70000C3BA0FFD9AD115A56F07D07FC5BAC7F66A
-:10D7100062FF0D8203C63FB4BE10ED8912AF48B060
-:10D720007D433BFA0F544F619E59B3574C00FAAFFB
-:10D73000B8DF64075349A123852EDBF97D08C4ECCB
-:10D740001C338BBEB70A1615DF931EC50221A84FE6
-:10D75000814E2ABD8CCEDA5F929D403617A74BF6DC
-:10D760001DFC09AE5FC567E74C87EF748AA97E048C
-:10D770003A6D5E976B043BE2844FC0FC8A9E74490D
-:10D780002C6A3B4AA1CB670526AF7BD0A38E0E7BCC
-:10D79000D01DA74B85FE2851A35F59B64F26F0FD3B
-:10D7A000BD9E1EDD72FD8D90FF51F832DD0F5D6F65
-:10D7B0006ECDCFD15E57E048EB09502F9258DE8FE7
-:10D7C000C20FE512CB0FFBDEEBD3CDBF2982E7877B
-:10D7D000013F882C7FC94FE77D7BF30B982F79663B
-:10D7E00053FB7568DFBC41E900E0BFD94AFCE87F24
-:10D7F000F8500E953688986F4D247FE62C95DFAE55
-:10D80000E4BF2CFE8315E15DBAD5E4CBA3EF976EA0
-:10D810003F3A06F311960730BFC7BB4960E71FDEEA
-:10D82000B631F0FD50A9C4F270F476C1F04816E7A5
-:10D83000EA782DAA00EC36A18EDDB3575A7F936C9F
-:10D8400052C5750745CA382FED87E7635E8A67B80A
-:10D850001F01D6A7BEDF4DC9BFE97891D15F69A38B
-:10D860008CF65C69DD964EC8C32C3D6C423FB7B266
-:10D87000EEAC11FCD8DC3FBC84F7F355368A9A3CF9
-:10D88000BC1EF96F75A2DF04F95B0DE5787E43EBF2
-:10D89000ED58AF0F9F077AB13CADC57FD8B1DD4BD6
-:10D8A00041B8F895DFD9F0BEBED68D36FCEEA9EEB4
-:10D8B000C2F9A73DF2DDEA575F30DFED34FC4109E4
-:10D8C000EBBA485DBE601D936B747D99F961E2C44B
-:10D8D000417BEBA52F9F837CEC8EAD7F7B0ED65BCF
-:10D8E000F65FE79E83BC1AB233C20EF648E5A60F78
-:10D8F000309F5579AF2492D97F9D2FFE0EF3803B48
-:10D900003F343961B4CE1D278680BDD1B9E5DB0433
-:10D91000C8EF5DBA631AC673966ECB4D2461E205FB
-:10D920004A0974EBEB431EB21E5FCD0DCD98FF7319
-:10D9300086E21BE443307FB1BE9CE5833A78DEE2A9
-:10D94000E6F0F9DE3DF2141B665D3F19E46203B3B5
-:10D950000B2E9AAF7880E2F1F23EE06FF36A2E4F21
-:10D96000C2E3EF0CFC41F15413A9CD57FCB261E1C5
-:10D970006F9E81B686B85EF315FD7D809B924F3E0B
-:10D980002BD2F55824F0CDD6DF637E28E02DCF01D1
-:10D99000F2F9CB2110173E290730FE10D861C2EFF3
-:10D9A0002C4B771C42FEE9DCB61FF3B509CFEBEE3A
-:10D9B00024C11FCBC3E5B19ECA0D5696E7C8E10F3F
-:10D9C00079900E1B3EE7F98E8C8E953CC8DEF21FD7
-:10D9D0005B2253F87D2A2C4FB37CC3C73CAF308405
-:10D9E0002F6102E0A9FD8279A50A1CEC00872BD4E7
-:10D9F000F9BCE1F34C8379DF1C5F803F90D3C17C9D
-:10DA00005D5A1F04F99B3EE11009230F3AD7B33C3E
-:10DA1000E04E39FCF7CC4A7E6FB39E4F7D7DCBEB59
-:10DA2000BDD8FABF2F7C1A221D38AE1E4E1DE7C38B
-:10DA3000CBF1E39CEF7FF0F7216582FEFB93CF8172
-:10DA40001ECB1BDA8D789F89E23FF1FD76F0785A84
-:10DA5000C72611F33E6BEA9B518EEBE545053F2748
-:10DA6000D1AFF71BBEDE8A46A6273AB65A7D163AD4
-:10DA70004EC75BAF213D576C6EC7BCD3BD75AF18A9
-:10DA8000DB54E7CBA0277CAAF577BCBC6B0CCA6D36
-:10DA90007EBF987E1E63149BA7B229FC3C959BCF4A
-:10DAA0006AE659ECAD37DA2D179FEFB4E4BA09C630
-:10DAB0003BDDCAECA5D3F5E20C5F98F94F71BD4987
-:10DAC000482D3B0FA5FA12EF59B3B27BD5445B2426
-:10DAD000DA5F4BAD130E47F783D288792F2BAA79E3
-:10DAE0009ECC7DCE24C0F70AEBD504D6BB12E0ABAA
-:10DAF000F2E365BB9B80DD2627E567A8CF5994F547
-:10DB00001BFB19884F85FFA5D61989E07F12C93BF9
-:10DB100008D6715DCAD712E8BF560F8BDF93F34763
-:10DB200087C1F356C9BE278E8EDB3A557042E8B5E1
-:10DB300027DDFB347186992EED7DB1F80D1CDD5F7C
-:10DB4000B7D380F6A0D5E0B7D32EC41AD19A840EED
-:10DB5000AC8338A404FC1402F3211EF49867C1FDC1
-:10DB6000C83642CD53E8E79434F79F444F9074F79A
-:10DB7000A19003C328BD5A38BD2A71392BFB9B8E57
-:10DB8000DB86F7ACC4A4916A20DF355637DA0D4F37
-:10DB9000F0FB69E86F24E441C49248A7FAFE263AF4
-:10DBA000AFE6FB383AAFA61EE3D2D6E36648C7C25B
-:10DBB000E99738BE8EE9A205E11033CDA0F86B7964
-:10DBC000C31342EB8E89274E3FB45F6BC1EF012830
-:10DBD0007B79D5FBB058B4EBA6EBD3C889E8B43653
-:10DBE000AF81AD53F3DC4E1C02EEDFA57D4ED7AB0B
-:10DBF000A917467179271109E49DC5DC4A38FCBB99
-:10DC000035F0BE5FDA373801F043B85FED2590CFCD
-:10DC100012CDF741E7D7F4B7437480CDAF1D870C21
-:10DC2000B2ABBF43BD9CEBBF5196FC2551949E32D5
-:10DC30008756616276561249C3EFA59BFAA17C4ACA
-:10DC40005996837927422DA3AB616B08F2CDB000C2
-:10DC5000CF9BBA3F12ED5193997823D2E17B36E204
-:10DC600095D361161FCF43702C37D0A1A45594D6FD
-:10DC7000E87B4D811CC3428A847A68A2E35746B987
-:10DC8000AAA3289FD6CC742719C6C2F6DE5EB93B7C
-:10DC90000BB9F65288081AAAF7EE69198C2204EF1C
-:10DCA000F120DEBD7B80C66B953A15ECF09D7F6D53
-:10DCB00064B0EE3253795F9BC2EA8F3EB47725DCC5
-:10DCC00037936ECF7F14F649CCF65178DEE58FD5C9
-:10DCD000DCF3DD9B7E51D63972833F17EE05BE3AE9
-:10DCE000C0EEF51D6E0D7E778F7A78A345A9FBD126
-:10DCF0008FC86FD88F72ADBC7E3FB61BA04ECBA134
-:10DD000071FEDC81749F2F471D9A9674291DAFA167
-:10DD100030093ED97F35EAD01EF8EE3004878F57A0
-:10DD2000EE1E148283B4FCC33D2D93D570F8700FA2
-:10DD3000D8217D85C3AB0F7D8870E8EBBE295D6C73
-:10DD400007BC5C936DC0FBD6AE386CC1F80AFD45CC
-:10DD5000A03EE2E3ACEFE5BB6CC51FA1E3EC54D3FE
-:10DD600097F29E4257BDD14D2AB18F62F76C6AE996
-:10DD7000A72BCAF536ACAB25CA758F351EF78FF7C2
-:10DD8000005CE3763BA78E0BD135B1B8C7C1FDEE81
-:10DD9000A32CF35BA354F2F29AEC25620AC4C98166
-:10DDA00017E243FB895FE68D1841F719EF3260DE19
-:10DDB000FC288BFB20CC632B08F82177EC0AE21EB1
-:10DDC000278821BE50E6ABD9C1FCF59A42836F3952
-:10DDD0003BEF1560BC107DB4E9E823C0E8A3B11D9A
-:10DDE000E9A3A2A99DD14763754E64063B37033F63
-:10DDF000BF9604C602DE3BA2BE9A2651FA1F1A1530
-:10DE0000A801BA91BDE7A6E55D8A703D1D163F7C6D
-:10DE10007DCABE7AC36F6D4BCA4369E04FEE33E0F3
-:10DE200079970237A55F8C85E5C5B658DD5F03FCA1
-:10DE30002A27B4ED85ED6F6D791FF3366CFB6ED834
-:10DE400005EFDB66530C3942F3D6EE5B8EF767D7EE
-:10DE500006D87DD8D124E005BDDE3B3C18FF04E1A7
-:10DE600001764F1AC0A31DF96513FF5E2CAB5170EC
-:10DE7000819E1F1AC5EE0D89B4B0F3EB211611D7A0
-:10DE800039C4C2CE59E2F7BD2582BF9575BF01FBEB
-:10DE9000C74399A6DEFFFDBCBFA489AF2BF854E8A9
-:10DEA000894AD228B87FE44C8C3BD1A2A19FD8A844
-:10DEB00014D578CA7B8F7888F30EAA47AFD83DFF78
-:10DEC0002ED0AB947EBE00FC04FB8D9623006E4AE0
-:10DED0007FA0CF70F8A1EF0D87F9601EB017B6ECE8
-:10DEE0005E22E23D1A7DC46B26DC1B49FB6746912E
-:10DEF000AAADF4FDCC685A423D8ED713797D202B14
-:10DF0000533F711A04FA7C3D8FBB4EB6F0FC31C909
-:10DF10003EEA86D15067765C565224EA05856FE169
-:10DF20000E0838B796F8F9754A20C5007853F858A6
-:10DF30000A18FC56AAB452248701F218DEF1D07DEB
-:10DF40004BBDCB9DAB2F65DF71EA9FCFE4EBF9C1F1
-:10DF5000F6F5173DBEEF9E09F02D37B73D7203ADC4
-:10DF6000575C7A0ECF079747555C79A17B2FF4EB6E
-:10DF70007FE7FCDB5140874DDF98C27E0F55C3E140
-:10DF8000D6E229C0F732F9BD2E2451C93356E5B186
-:10DF9000421BB7CB109529F81CEDACFF401108F8D7
-:10DFA000F44AB1F07E54329E1F4ED1E5ADFE879FFC
-:10DFB000C5F932C130002571C92836CF37CC4E3271
-:10DFC000D3FFE09C691A3F177B4772AFB0D2F1DEF6
-:10DFD00021EC7C3533AEAA19EAC4C4C6CF26DAFBDD
-:10DFE0000A32136BA7C6C2B8D1C918DFCA35EBDA3B
-:10DFF00053BD12C869929A8C7989D388CA3E637AD4
-:10E0000003EDEE08BA2E90E3D78C2C744EE5EDE7C5
-:10E01000E8FF434DE4F6992A7FE32AC75CE7548D75
-:10E02000FD528BF701FDE99FE2EDE1F22C3EE3FCAE
-:10E03000DFE2C977C2F9B31E9E390EE17EABA3279A
-:10E04000DCF570D4C35D81AB1E8ED99F38A7C68620
-:10E0500081931E2ED348ED48D0630ADCF57079C752
-:10E06000CCE8E29D3413DEABF88EC4E0F80E352325
-:10E07000A11EA49B6811EF01CE8CE2F53747B0BA20
-:10E0800082EFA864C4B71EAE7A3866C6F1F7E358CB
-:10E09000FFBD002F09E502E247A19BCCD4AADD31E8
-:10E0A0002A7A50ECEB691C2ED4BE46FB3937DE8A47
-:10E0B0007126B0AFA72584E0965BCED6953BDCF207
-:10E0C0003CF8A9F475BCBF720AE13FFF143C2FCAAB
-:10E0D000E45505CE53BED1DAC9D39AA69F8238C380
-:10E0E0005093FB7EA0CF801083E77514EE477470C9
-:10E0F000D7BE67D7D6F570F803FC31B127BC143A08
-:10E10000FBC0C2E34E03C820B097C7BC96110DF206
-:10E110009B34C5868D4B5C71383F380EA757A4637E
-:10E1200081B883CFEDA93F428EEDA35A5225C73661
-:10E130008BEED396F89E724CC1D3648E87C9C4BB54
-:10E140000BE24B9389F445D01F480EEDBF5BD9E736
-:10E15000403210F67983C5C1E43FDF6770DFD4BC7D
-:10E1600084F9B3F8FC59660B7E5F4302524710CE28
-:10E170002978DF91D7181B5A8792BF4F86541166B2
-:10E18000CFCDC37BAE295CC87751A17598AC828492
-:10E19000F7FDF0759CA9337B218FAD5B7447819DA2
-:10E1A000D721EC1B83FB93FC2340FFE9DBCF35EE4B
-:10E1B000AE8076DAAF08FBF1F52F1659FC21B0C31B
-:10E1C000E47B3EB9773B95B235EA09857EB3E0FB47
-:10E1D000D4CB81DEFD0361DD5340D5D172E759F622
-:10E1E0001D437663BA04F3ECE96679FF39C42581EF
-:10E1F0007DABA7DFEF4BA7A178456008F8298A5DC2
-:10E2000036D5EA1E69A5CF57F3EF669BCE8E18056B
-:10E2100078F9C1F474404B4F0A1D51BA1A0FF0EC53
-:10E22000CAF8FC6930C7DFCD3897007A51B1DF43B7
-:10E23000768A6B02ACA7373B7E89D53DC57A013B18
-:10E240005EB1672EE68790DDD441A674741BC7CB00
-:10E250003C73ABCCEECD0F60FEFDEA48E55E3B477C
-:10E2600024D891B7AD4ED95407E786D52CFE7E6BE6
-:10E2700095ACF183DD90DD86EFB3FB666F5FA66D35
-:10E28000FF4C60FE7EA157FB9C581234F7EDF69CC4
-:10E29000D7E035C0BCC323313F413FAF7E7FFA7921
-:10E2A000F5F3ADE67ED56A63ED48A7CA2E596065E1
-:10E2B000F650F7AAC7EBE0CABADEE0E7360F48939C
-:10E2C00054F7ABB5AD8E2C08776F8C329E02EF7988
-:10E2D000C4CFE20055F2DFC3DD839BE566F181DE4A
-:10E2E000E61D16988A76A0E149BF08F6FCB0004109
-:10E2F000FB3B2BE0322CD0F801CC4FEEE107C0BD48
-:10E3000026B45ED6B08BF901F5D5E84F94517F0263
-:10E31000F4CC7A389B1EC0179486FE41D0DF85FC72
-:10E32000A92CB8CF92FBC312A597D45AD67FA3F5D8
-:10E330005DE36A09FC5577924C2963E3C3EFD798F4
-:10E34000A95F55934C2208F5AB5E78F8FDE96BC0E8
-:10E350005F8E7509707F28ADD758FAF7DDBFDEF8FC
-:10E36000F0FE1AB86F94FA65EBAC2A7FB737FE78E7
-:10E37000048C910BF047BA3D7F23F0A112AF688A5D
-:10E38000E07C1F11A4BB6880974227572F9B8F7E8C
-:10E3900045C425E787409E5816C7FF162B8FC346F6
-:10E3A000B1F79F12DD5B90BFDF3A3F02E2CBEF8C0B
-:10E3B0003C8AFE5C9395C5E7F7794AD07E52F0B966
-:10E3C000CB2A703FC93F10F8EDDAF1CD71E09764C8
-:10E3D000C902DE43DA24FB9E4CCF007934DBBE82D7
-:10E3E0006E296BA211BF136B8AF00FBC5B65A7355A
-:10E3F000F1FB4C9BCEEE1DA8CE631E66CDDD6545C0
-:10E40000FAF38B307E56C6EEC3A0EF7BD32F21FDEF
-:10E41000E112407F90F3FB13F0FCA8618F0DE24204
-:10E420001DFC7E82330DCD09F36959BEE52F36F010
-:10E43000D7DEE7703823B5E23D4A65DB44BCFF8395
-:10E44000CE9B700BC4A71B1664B2EFF7D877678A10
-:10E45000FE4CFF67F3C07C1634C4EFC8147B72B265
-:10E46000D9EB83F535558B182F9EACBB376C0ABFA3
-:10E47000374C6F5F9EB42A71E904CC875A6A67F300
-:10E48000F4C64F59DFC4129F8ADFB224BF08EBCF16
-:10E49000FA2681C01597675A529EC8033F9EC8CE80
-:10E4A000E130AC4476A3FDCACF9FE86F37DC43BEB2
-:10E4B0009357DE6C3837EB4A2466FBFD970960778B
-:10E4C000B9FBB1E022D3078A7D37E51B6D7C556F20
-:10E4D000E7E6348DBD7F204178B37FA722C0EE559B
-:10E4E000EB61FF06A687B57B09790CE190BE2DF59F
-:10E4F0001AB84729FD8F063BCCDB027C110FF83C94
-:10E5000087F7FC5410FF8DD05ED120DAFDB07E92EB
-:10E510007119F09562372870693CDF6C1E43D79102
-:10E5200075D6605F4E877833F005FACFE3FEBC2FD7
-:10E530000EF4575340C27382ACB3BBA316A8E46079
-:10E54000D379033E7FF3FC5BDAE781D8CBE0BD2DC6
-:10E5500006E617EFDEFBF728904B6F9EEFC6F182C1
-:10E5600076434FBB18E1916B15837167B55D4CC461
-:10E57000AC0390B7352D9AAA31A177BB37FB137244
-:10E58000BF95F4B41F72C01E11C3D8111CCE743EC7
-:10E5900009F8486F575C6EE3F1E6C1241DEEA36CE9
-:10E5A0003C1FB718BF1F6E8AB22F477DCCECA5AEBB
-:10E5B000DDA71FBF069EEF13D9FD11E745E4A7B7FE
-:10E5C000762E1EDAA6E25B2A39114F5FF53FDBF9A2
-:10E5D00006EDFFD59E481647979C97A9BF7708F58B
-:10E5E000F77178F907B0F338EF00B8D7E907DB2FF8
-:10E5F0001D3DFCFA3C1BDAC381E9A01E46AC6B371B
-:10E6000002FE5BACF9D7D990DFEAA3002E5E92330D
-:10E61000904C80F37A92037415A82676F027B6B54D
-:10E62000180C80978C8DC998A7B3899F572EAAAFD5
-:10E630003526ABE862113FEF3A297B87C4AA9E1FBB
-:10E64000B031F972724FE96F304FE34313191EC6B0
-:10E65000DE6CB0317DFB8AD17BCD66E877C480DF8C
-:10E660000DEDDEFBFA5EB8CF78D161C75888FF3D6B
-:10E67000627360BFC67D9B6A20CFB7F113D052543E
-:10E68000AF6C28140D74DE378883C5EF0E18D01FC9
-:10E690000FC63D892B0EF6F9105FCF1B2D06CDF965
-:10E6A000D81BFCDEDD7B6D32B62FB18988C7AD2D5E
-:10E6B0003971A0375AACEEBB6DA02F8EB5D5C01204
-:10E6C00094789F62AF4D3CB0F59AD1F4CF891D0686
-:10E6D0003BA0DB71E07911F6EB3849488C407AD8E1
-:10E6E0006F743C8F7ABC373AD878741D6F01BF2A9B
-:10E6F000F0A79AFFA1345A7FA3558A85FC2E05FE08
-:10E70000CA3E94F91DF5C4B5DE82ACE4DA7A81B86C
-:10E71000B3925F3ACE4E947F2F01E9D268733D6A7F
-:10E7200063F60EDAD727F730BBE815AE474952E15A
-:10E7300050809F82A77A1B8B332AEBE96DFEDFDBCB
-:10E74000989E54CAEF4BD79B648717E9661BCB0F83
-:10E750007778FDE654C8236B4CC57FCF499567FB9E
-:10E760007BA4E793DA7B051BDB0C06F80EAC628713
-:10E770001083E66D1FEDEB209D49F5487F8D8709DD
-:10E78000F27169DD9D2CEE48E50DBF7F0DCFD18183
-:10E790007FF8797A7F8196139BD6AF1888F0F5DBE6
-:10E7A00080AF4270A27C036555AD11E875D1525619
-:10E7B00016F373E9456BDDC89F45EB587EE11E5BA0
-:10E7C00032AEE70CA75762881C00F9272E0E7F6532
-:10E7D000DD799C6E4F353CD10CF352FAFA13E0739D
-:10E7E00052E3634FC372157A3DB541C6714A22B5F3
-:10E7F000E7F6AD7CBC6D0718BD4FDC20E7C0FD5FC0
-:10E8000013BDC40E71EC37366C14417EBF01F49C0D
-:10E81000CCF81CF4EDC93D0F46FD02F45CBB814011
-:10E82000BCFC152329D9A2E28BDDEB5FD5F06F6923
-:10E830005DF53518976F8B1540CE2B7CABC0FD1561
-:10E84000A3F32AE4FFEB74FC3F95BD2F473BB0DFF9
-:10E85000139CFF9F9841F99F3E8AD91023C038AF7F
-:10E8600018C3DF07F7F50FA4BFA05C6DEB2157BFFE
-:10E870006672B5CD964AE7AFB8B61BE30CC1F57129
-:10E88000BA7962AA4237C902C0BF96627018C08BBB
-:10E89000C215E899DACDB7DF90865CD922E1390F4D
-:10E8A0003F47E2F91FCA77020ABF86E499C2B76EF2
-:10E8B0007334D8D553AB56805D1F97E745FA3C2596
-:10E8C000B887C6527D760AF8388C3C38C1E5C75700
-:10E8D000B2FB62F7EE0F007A2EA11E22EC87AC137A
-:10E8E000EC8017A5DDB18EDDC33A3C5AD09CBF2B1E
-:10E8F000F51F0CEF408FFB418747637C3A60843CF7
-:10E90000D5113EA6C7889083FC400C570F003E5B94
-:10E9100044F5D7CD2AFD754AAE453A55E0707934B5
-:10E92000935F5FC5B07DFF95D38515E285AA732FF0
-:10E93000EA904802E36751607C2EC2F8A7F64CBA11
-:10E940000AE9FDDAF0F46E07FF2A16FE3DA7F54846
-:10E950009F3133ECF81DCB1392332246631FF9B07D
-:10E96000DCBDF157E8D701FD02BFF746FF2540FFA8
-:10E97000240CDDFB28DDABF0A7D001A58B6BA255E5
-:10E98000F2414F17CA79A302975774E7954F47335F
-:10E9900079B080978E5EF26694FDFC603C9FEC81BE
-:10E9A000E7F90CCF21BE027C2BF2E16717E1AF3D06
-:10E9B000D1766CAFF97401E6A9D4F273AB7A3E9FBD
-:10E9C000B2EEA5D182E67C4B7FEE34CAE2BE2B5A72
-:10E9D000773EEA480BD1C7346ECF2ED968C273FF99
-:10E9E0002DD00278DBCDFEBD6CE53DBB440D4F0A5A
-:10E9F000EA15D14C8E2BF4E1586624C3A8FFF255DA
-:10EA000072E16EC8FFF959AB376F34DDC716A377D3
-:10EA1000F6B5E80738AF82F1AFCA33D8211F24C654
-:10EA2000651720DE81240A7CB88FCD332ED5791965
-:10EA3000FAC90EE73890070F737C29F855E0D09B90
-:10EA40009EEB0DAF7B387CE279BB5E8E1473FE9E2D
-:10EA5000C2FB5D5C8E7845E0271B712F1761FD5965
-:10EA60004CFE05E54816C173C9977572E4E59F5ED3
-:10EA70008EBCAC912313DAC2CA11FA0BCBFFF11B87
-:10EA800016A21D4B0E87B7637746333D1C0FFA93D2
-:10EA9000F68BF7B2F3DE8739DD528AC4BCC9DA0DD2
-:10EAA00026CC1357E4906D36C9817FAFD906FA168C
-:10EAB0007ACD761F9E0CE7C54946079C5F9F92035F
-:10EAC00088F753D401AF45FAC8C7FBC7C3C82302B0
-:10EAD000F112EF4783D0EF9C2636219F2C994650A8
-:10EAE0007FEEDE7805D255495E8A00745B5A1723A3
-:10EAF000407BEC54BB01E494B28F2B9619C8B071E3
-:10EB0000C80707D472E40A6F15FEBBCD43E3DC49A6
-:10EB1000720C21471F3DFB3375BCA88DD6D5F12261
-:10EB20005A7FE0FBC48B8E46071E8078D13F6CAEC7
-:10EB30007698779425FF28EAB7C42A91A8E4D6C529
-:10EB4000ECB71F4A2F953C2E455AA9344ED0C481AC
-:10EB50006FAB73601CF82B584FC580E34FC37078C0
-:10EB6000AF46587B9BADA31F970BE41382F8E89741
-:10EB70005F2542FC45913B067BACE22F0B9097A1B1
-:10EB8000F0DB7F031C7DB5D7008000000000000093
-:10EB90001F8B08000000000000FFCD7D097894D590
-:10EBA000D5F07DE79D2DCB2493C9427626ECBB039F
-:10EBB00009ABB14E086090040710448D380990B03D
-:10EBC000640391D2D6968120068A182BB554B10ED3
-:10EBD00014FA51451BB61ADBA013401A143456AD73
-:10EBE000D8AFA561911D8980FDD38AE53BE7DC7B29
-:10EBF00033F34E26026A9FE70F0FCFCD5DDE7BCF4A
-:10EC00003DFB3D77492D63793B22199B90B350ED35
-:10EC100006A9C9CC3C161B831F2F6343793E7A0893
-:10EC2000E659986B20636BF27579DE018C5DC79FA6
-:10EC30003BFD69A2153E8E676CFED630EB4933B5BD
-:10EC400067D7E17F795D8C265F599F643DD9C79F67
-:10EC50009F8FBF24C1FF334CCF12182B63E2A7E173
-:10EC6000CBDFFF7018B4C7DF55C6DE54DD89568090
-:10EC7000A7DCDC12D5DDCED833F9C713DC91D45232
-:10EC800087DF3D22C67871B9E3BDDE718C79DE5530
-:10EC9000D916C80F36193D4A34FCE264766B82E817
-:10ECA0000F7E9406C5671904F97F43552C6397FEC0
-:10ECB000ADA3F4C59FB8F232E0FB8A7A9D6339B404
-:10ECC000AB685018CB62CCD19579CD198CD58547DE
-:10ECD0000D62D05FCEBE48A701CA2F2966AF298337
-:10ECE000D100088741C23FA2357D1BD4573798D841
-:10ECF0006AC85ECA61AC19E1D53BA2D9003F7E0764
-:10ED00001D7EA60FCC00CA6B1D2E0B639BC278FF25
-:10ED10009BC2647B7B3483B4DB92D1EC04C0A7D765
-:10ED200033160DF481C48369F6926E03F499301F93
-:10ED30003DF318804ED9AD3E15F1D2ADD5AE6391FD
-:10ED4000FE71F4AD8CE6DB4D6FD73960FC3A81F78C
-:10ED50009D4D3B543DE073D898DA6A15D2D228F71E
-:10ED600058C4F3A8ECAA6A2C8FCDF7A86E689FA5AB
-:10ED700054EDB3005ED878E6D802E5CC07838F84E3
-:10ED8000FA16D61805D998232DCE28281F75C6D96E
-:10ED90003800E61DED620AF6C7D8321ABF5FA4CB71
-:10EDA00085FDB238A75200FD0CFB0723BCC87E7658
-:10EDB000368D56EC006F5CF318C51EC05F304DE217
-:10EDC000ABF5CCFE53ECD77348E740BADAEB987357
-:10EDD00023B4EFFA72BF312CCADFBED2AAD078B703
-:10EDE000BBDDB94646F379D80ADF8F9CEEDD6700BC
-:10EDF0007886CFF1EC33DA03E63397517F292D1E65
-:10EE00009A47D211770EA68B2D31D4CFA833BEC628
-:10EE100001D0AE4B15CC07CAD39A3F5410AF6955F9
-:10EE2000CD0AD27167D35E8237B5793F4F8111EA3F
-:10EE300020DD01725517308FC5161DCD63B145A178
-:10EE400074E5C599892EA87FC4EA5E6C19EA9FC74C
-:10EE5000CA1C776215F4BFBEA95BFB7C7B02BCB702
-:10EE6000C1678827D9DF72AB91FA69B2B87F84F3A2
-:10EE7000AB9CDE7200796F47D39FA3482E1AE288BD
-:10EE8000BE09878E133D129600CEA078FDA1850A9B
-:10EE900083AAF5854033A5239E27B8DD8E31998856
-:10EEA0006F809FF8C71A3109F8F2628CBB06C791D0
-:10EEB000ED2714D922505FB4E7C577CF2E658E5960
-:10EEC0003D00CFFB8B77B26E4877F712A47B7BBBFC
-:10EED000818F87213F318BB316FBBBA4B0E938CEBD
-:10EEE0004B9842F94B069E97F8FAAB95E3EB11EB82
-:10EEF000A4C596788E272BF0F14B61BC5DB01E7ACD
-:10EF0000D7CABFB30B7E61CD9C5F701EA8BF64BB28
-:10EF1000DDA2DFDB9DEE5C3DE793CD08E7C811DEA7
-:10EF20007DC8B7C3F33CFB90FFD398E0933CCE275A
-:10EF3000C1FCBECF6AA37E469D696588F72C85B962
-:10EF400002E92ED3D710AEA1C8DFA3897F401EB639
-:10EF5000E378C352AA54038012C7AC135877C6DEB5
-:10EF6000B6DAA95DE608E73EE437ABD345F27C208C
-:10EF7000C24AE52B33387FC0F77F40FC05CBD32E48
-:10EF800094A3017E398A437E8CECC88FBF13F0BCFA
-:10EF90002DE4A563FFEE3F61FF71CD3AA7029D0C02
-:10EFA0003F12E965D074F8A22A15E18F63C0FF0013
-:10EFB000A06D8E3507E52CA5CCA1205D9B225C873A
-:10EFC000ADD40F23BDB93247E7AD86EFE6463B89A6
-:10EFD0007EDFD83EEC676636CC6F1FC01EFC15E1A5
-:10EFE000037BB0B608F5F46FFF69443D6A97F2D72A
-:10EFF0003424A238803FAE48BDE0A7F771D20B4160
-:10F00000F40ED673C1F4F6EB05AD9E037C5DE0F41F
-:10F010007067229FC5352F52B97ED0EAB5CEE8D1B0
-:10F02000413F083A5C8A707E81F85C0C3288E37A52
-:10F0300046B33E58DE991D0E8B89A476FF453B1CD6
-:10F040001613DFD10EEBCCAD0715C04779836A5795
-:10F05000610AD58FD99C48FF17EB148709E5A441B5
-:10F06000257E78716538D94B09EF67BBA307B1DB03
-:10F070002015F2CFDCDDC98E56C688F1ED9087F100
-:10F080002F5979D6687527C504E893171BBE084326
-:10F090003CF74F64034EC6620BA7D60E830829F0D7
-:10F0A000BD097F5310AF836B5414AC69EE9D269558
-:10F0B000E8D61DFB1BCE5AFE9C0D70BDBC6DB4CEB8
-:10F0C0001DC837F55767EC05F82B23B85DBEB4F7BC
-:10F0D0005A2FE433597FF79262D27B3F072B1913E3
-:10F0E000A01FDFEE7382EB6156683DD51F87762A3D
-:10F0F000D723008551E63E7AF427D47087AAF527F6
-:10F100008839AA7B027E107F8DE184BFEA9E20773A
-:10F110001904E748EC7FBFC5C892A0FC0AC823B613
-:10F1200093707F03784707E2D10F6FAAF55484E00C
-:10F130000BD50F5F3B5D900ED0BF6AD1D33C2EB193
-:10F140007007D2B3CEE864487FCF51E11F08BA55AB
-:10F15000089EBBD430F4881BE6F7E29154077E7F0B
-:10F16000A9FE4A982E12FD46F7149C979AD61A8546
-:10F17000F6705FC395BE2D0348BF4DC5F22B874E79
-:10F18000D8DC03BED1FC6684A687767E95FAC89A41
-:10F1900040FF50617C7EC17CA43434FE4B1944F2A4
-:10F1A000C7501F7AD299B71AE6BD72A0E0A77B9923
-:10F1B0001DE53E98DE46ABAB2226406EFF15EDAA5C
-:10F1C00042B8709C942134CF85981F747866A6410C
-:10F1D00087F31BC3D06E4A7F0FFDEFB0217EFF4E39
-:10F1E000CEAF7DFE3DAF0D3AC468BE3FC67100F89C
-:10F1F000E53A80AF128CC1EA8CC079FB881EE562CB
-:10F200007EE5E6489F0AF361BB0C175AA41EE8D6B8
-:10F21000117EA04F0DC2E719ED38E246FAFE35D255
-:10F22000518DF8D1375BD15F85F9ACC67A36A2280B
-:10F2300011E7DF2FD2B905F5FC4BCB18F1F3A55739
-:10F240009877134C76FB7E1DF1CB46D68FF8BE9F88
-:10F25000EEF20C5724C9F33A843BABB956877AB720
-:10F26000A7D7AE437DDAB7B94EA7233E70FF2286FB
-:10F27000FCE49957F4005FFF6D55EA37E4076F68C7
-:10F280007EEF40AFCD81F49278CB167C908D7843A1
-:10F2900083D0AABFD062F6E30DE8C3526C1DFB63B6
-:10F2A000AC251DF1D4F8FAE95E2DD05FC51BA76728
-:10F2B000205E2AFE60222618F387BED1C8EF9FE5A4
-:10F2C00084F6672E2CAD72E8C19F7A25A61BD985DE
-:10F2D00032D66C443FA1BC6E81431FA0CFA5FF7600
-:10F2E000C8D09C8FFD1F1AAAB26580E72B8EE15D06
-:10F2F00058083BD1EE2FA1BF06B02F47D811CFAF92
-:10F30000674573FFD146F620B8FDA1A5731C637A4B
-:10F3100074DEDFA1C161D3BDF07D7E901F743486A1
-:10F32000DBB5B6186E8741213B11CE8BBFB7783D58
-:10F33000507471C847510CFDCC5D1F647A808F2ECC
-:10F34000B2E647FE8872763592D671F9833FCA5C81
-:10F3500066F1CBE51D23F8DCEF78ED70941DDAE75C
-:10F360006FDF17E709C0DF1D4C7FB59DAF33705CC1
-:10F3700046E3337D4B2FA407FBE3D9043BA4F9AF4D
-:10F38000BF15C7F9204187745E24F4DBEFB028C0B5
-:10F39000DFCE5F52417C24F3E56D66E68D0DC8EB50
-:10F3A0009B8DB8042E6F8B645E68B737C612477AA0
-:10F3B000269925A39EE9145F3789CFE07289CF4350
-:10F3C00083CFA6A35FF15927FE706F1B6FD7CEF7CF
-:10F3D0004BC14FD7FBF3EF7CA53EEC0AF15D848D6A
-:10F3E000D3E98A636417F4F7F28DBE1ED610EDE4FC
-:10F3F000FA32184F6F5F2B8DC07E7FDF66CA0B0518
-:10F4000097DEA6FB767ECA21802AC01FDCA6BA53EF
-:10F410006DC21F9C0CF98ABE57C6D1BA5AF28BD066
-:10F420007B77304F23CA6F307F487AF7B001DDFA1F
-:10F43000A372662948B78B3176CE37421EA47C046E
-:10F44000E331389D6064EE50EB80AF62245EC39878
-:10F4500007F4E1231B0D64DF0F5FFBF8DE4CE0F7E0
-:10F46000D31B0CD6E530E49C17F6A53E03F57306D6
-:10F470009BAC0AE44FDB7D3D50EE4B5F505DC80F07
-:10F48000A7373C923013D2F320BF650047E946030B
-:10F4900095CFD9F828959F15725DFA427C7FD49755
-:10F4A00087F7AF4E403ACEF9EA89694897ED466B47
-:10F4B000FFC190966D531C6302F03D6F739826BF99
-:10F4C0005DC7E6E03C245D99E26EAF47133FD5A6E9
-:10F4D000FB76711F9FD6DF04FF72AAA0E3C4293018
-:10F4E000EF8AA157C8AFDF77209CECC99B912AF91E
-:10F4F0008FBEC1FFEF9DDB209FFB95DE41BE9DA02F
-:10F50000F3584167B05CA4B74BCC3C9FFBBA9EFC60
-:10F51000CF5C8B4AF886F69163A1FE7BA2BD0FF407
-:10F520002CCA2153B3D78D847663A30D0CEDD0F78D
-:10F530007CF3F219D8C93BDBF4C75B02E6339AD5FA
-:10F54000F6417F38871982CA9D7A2CCF356BCBC79D
-:10F55000F6B8FB2CFA0F63ADDA72C9778FD8B4FA1C
-:10F5600062DF81733F9B00F32B39A492FF7C237DE4
-:10F57000FC2EC2AF473ABF5DB80DBE3B2CB072F84F
-:10F58000DAE91549C857231486F1ACD3D742CBE347
-:10F590001FA45E6640DF3E7EFA1638E6B6E751DC11
-:10F5A000EF19B1A03D8FF0DFBC1EFB7A3D759B8D3E
-:10F5B000C73382ED46B0DCFCB7EC46FEE0B7D23D87
-:10F5C000164A7F83E985ED5CEF06EB89603B21E11C
-:10F5D0000A86B7BC4DA7B10F5FA11E191A68278C08
-:10F5E0006427BEC3F570836D68C7F530F831842F8A
-:10F5F000CF303DADC3C1DF6AC4760322EDB139001F
-:10F60000D20A6BB708B27F16F77E5B401CAAFFB622
-:10F610005A1DEA8DF6F88C411BA791EBD577849D96
-:10F62000A813FA1CD6ABB4CEDF18EE4ED4E3B8C99B
-:10F6300046C7968C8EF8F948B4EFCCCF957EACBE19
-:10F6400086FBB18F585D9A3819EB93A889FBA25FAE
-:10F650008EF2EDD91B4EF3FC54710D4239D433E7D1
-:10F66000DF6D01F4A93670F883E1898FE576923178
-:10F6700017F907B27CF6E8D07A5C89D553FB9C6712
-:10F68000EF4F47FFEDD3C607D251BF7E1A14E7ED07
-:10F690004C1E9E16F2FAA4B02331222EF014CA1189
-:10F6A000E441DA9DDBE1FB554B5D24573F5D3A9D1C
-:10F6B000D267962EA1FA13B60C1ADF9AF367577722
-:10F6C000C0D3C9352AD989D94657AF18F8EEA459FD
-:10F6D00047F18513559179BB22B19CD17A72F6B36B
-:10F6E00013B67802E27E276C7AA24367F38C8FFD13
-:10F6F00066FABD9CB544A1BD6AE7D7231DECB52DC4
-:10F7000016E37FAC2501DB552ACDBDB6291DC7B751
-:10F7100032677C2CF29791F547B9A90BE7F628B828
-:10F720005D4A2CE7C3BFA11F0BFD7E8A762B849E0A
-:10F73000B10B3A2FB438EDB1A4EF22C95F27B881DD
-:10F740005FBE8C727647B8605DD613D3615D787CFE
-:10F750006EB1C52AF8C3A9F0758EAB5F6C88F85BF3
-:10F7600067F19E6038DE11780D8E03C954C681861C
-:10F77000C6F2F9BC6DB36AE24218FF0E15FFF979C3
-:10F780002CD7A31BC35B3C2ACAC3037C3DDE25DB0D
-:10F79000A3607C2B25BF3607E35F77C5F2B8A52DA4
-:10F7A000CF9D88EBF6E444A303E336372B8F03EABF
-:10F7B0009C7C5FC0AD2338D6377BC27A015C09CD13
-:10F7C000EE1C23A45371310DF8EDC2AA9621DDA0E1
-:10F7D0001D21236B7FB857918B6C689229F42840C8
-:10F7E0001A8672678C724F45BA0C9B55558D71FA0B
-:10F7F0009432BEFF70567177B5019F9C7D2B3CA45F
-:10F800003F5C22E8CF94D1C968FAB3361B08AEAC8E
-:10F81000CD3F9F817C9FB5F92EBD12A08796C71A58
-:10F8200068FE67DF9AD795E2169F9858CF107AEA5C
-:10F8300087825F1E1074D8690CCD7F8B45BB6FAC7F
-:10F84000CF5B405569F5F9E2D880385B45F965D260
-:10F85000E79363ED34CEF3FABA03C980CFE767319B
-:10F8600087078AE66DDD48F1D79DC6BAF1B8EFE4A7
-:10F87000A9D031A4FBFE037F38908C7EE42CFB6082
-:10F88000F423DABF3FF4D24A2C7F7E0E1B8CF84F54
-:10F89000F23EAD603CE69F61B584AF7F6E31B165ED
-:10F8A00018B77DBF6EFC0F21BFBE4CC750BF04CF41
-:10F8B0001B4632E81231F519742338FD510F4ABA4C
-:10F8C000030319911E926E88BFED90EEDFF21AC10C
-:10F8D0002FE19A2AE2DEF3B66E1F8F7C925C6653AC
-:10F8E000304E20E1BA913D7931F6DBD993EFD00E5D
-:10F8F000BF121B222E1DC20EEF880D618783ED2FD4
-:10F90000B3387763BB1BD9E1E182FF36C606ED7FD2
-:10F91000E07E5908BA0D8DED100FDF1F1B62FFE36B
-:10F9200046F1F0DEB172FF431B0F7FC9C8F56FAD22
-:10F930008D3D3C2984BC7413E3EBD6B51AD17EC649
-:10F94000352821F5D9628B51EE1F7E1C1BB05F124A
-:10F95000AC8F43E0F728B6EFBBCDB7175B0D89E955
-:10F960001181EE5BBFEBB0DE0D31CE29813FFB2272
-:10F9700046FBA6F62A46FA0AF25E1E14F42914374C
-:10F98000B0384F93DDBAC1BED59DD61CF283E43E9C
-:10F99000D554ABD64F8C8B93ED9C9F239C699DD8FF
-:10F9A000897F093CC1FCDB70DCB8454CB31F23F7F1
-:10F9B00061E2AA3C8A310BCD11A3F86AD758F7321D
-:10F9C00003B46B1DC91C9B201F5D68CD417D6A9BE4
-:10F9D000E368C4FD9A9517793C7EE502E65D4EFD2D
-:10F9E000F0F93277372FCA17D22D302E1011C7E118
-:10F9F0008888E3720676D21CC7E10A8F0BB0939217
-:10FA00001EBA753E95E8DA1ADA4E05D0D546DF778C
-:10FA100042D7EF502EED7137E71FF78CBB05BE19AB
-:10FA20001877737CF3144C4BECDF048F9789F30F3A
-:10FA30001E0FF82C2BEE26F8ECEA2DEE8F1E8850C8
-:10FA4000BE5DDCA5235E27C485D0776BF2757D484B
-:10FA50005FB3704728BB3A232EF2BF7D5E6486A059
-:10FA6000F72D9D1779F1272D46A4B3DCF790F0060A
-:10FA70009F1391E5150D4A26AE3F73F65DA375C041
-:10FA8000A5C67FD33AA0E3790F3EEE42E403806738
-:10FA9000AC3AA0CE07F277799B9156EA2AB3FF22BF
-:10FAA0001BE3F64D06E6B5537B33B6EFC778FB7E16
-:10FAB000DB563663DCAA1FD37BC47A54B9CEFDA8CB
-:10FAC0006894E37E4D2A5B8DF9ADBCBE8A9997613F
-:10FAD0005C3A7A848ED903F019E30C67F6007CC691
-:10FAE000E6D93479B94E9E2FC68D77256BBEEF329D
-:10FAF000BD9BA67D92BB9FA63E65CE104D3EAD6AD6
-:10FB000094A67D57B0CF81F90CCFDD9AF6DD6B2638
-:10FB10006BF23D6B1FD0B43FCDAA9ECDC6797A9CC7
-:10FB2000CD3D00CE5902CEDEEB8B35DFF5D7D50DBE
-:10FB3000F3A120F9141FEEFFCD166C324BC473FAFB
-:10FB40007AE769FA3DFF6A5E9302F89D5D6B3819AA
-:10FB5000189F217C007E4BEA15F61C8C5BBA5E5B1D
-:10FB60003FA7E1E9952990CEF56ACBE7E1BE9C82FB
-:10FB7000FCAD2DDFAD733D82EB9DED7122CE28E211
-:10FB80003DAC037F44D2B89737F07897EAE91DC4BB
-:10FB90001F5A3AB16FC92F76C12FA6442DBF84D901
-:10FBA000B5FC527A70E7301FEB88FF883E417CE459
-:10FBB000817F017897F895F8B738B47CF55DE19DC1
-:10FBC00031AF91DB0D6DF93FE2B4F1B57E91EEE31B
-:10FBD000A8B7AED42F5271BF8DE5F17DFB2BF55741
-:10FBE000071DB26BF6D73ADB4F3A1717185717FBBA
-:10FBF0004997703FF1367613FB89FBFE85F800D9F3
-:10FC0000771B801FD80887B97DFF30CCBF7F14AC2D
-:10FC100037650A76E3CB38B227FE7DD76AF87A5883
-:10FC2000F45F5C08AFDC8793E772E4F92116C9E75B
-:10FC300029FB013CA8F143F1FC9F2D02D7ADDBF776
-:10FC40002FA4F5963C3FC4C4B9BF107E3FE9EF3AFC
-:10FC5000FC3589FC81F0786ECF23316DF707C4F94C
-:10FC60002E69CF3BEB47EEB775962A7B55DA3F6C92
-:10FC700055C21D9B42D8935EF1DF72FD75A6431CF1
-:10FC8000BA577CE0FAEBD12B07D0AE00DEFB62B9AD
-:10FC9000C502F65AF1DBEB5F444411BFB61E54BDFA
-:10FCA000BDA1E0B2D91E6D033C368469ED884CAB32
-:10FCB000CCC903F4B158AF3DE727F71183DB676385
-:10FCC000FB80FD27F84EE38FAC1CC2FDB5EC786ECF
-:10FCD000DFBF88E4FEC11491AF0C5A1755D670BF30
-:10FCE0006C23F8E90D01FD4C89B750FBA511395380
-:10FCF000E2298EC0D7BB2B3314F227562A0AF921EA
-:10FD000067A24753FDB5B89CC9C43F629C29E8BBB4
-:10FD1000C1FFDA6E1C1EBB388F23FB37C7F3F6E634
-:10FD2000F8D1944E89B78AB8B3B51FF2476584936A
-:10FD3000FA35AAA1F7A5A6C7F379ADB530E9276AC8
-:10FD4000E2FEE384DEC438BF89FBA3F96313FC71D0
-:10FD50007EA6667F688C13F17D853E77A29EBA539E
-:10FD6000D0BDB378BFB38F753F6E27758CF7FB128C
-:10FD700043C6FB1DE328DE0F5FEA715EC1717FA4FD
-:10FD80004384CD2F3F8FC4B7DB8354D44FF54677E0
-:10FD900035AEBB5A7783FF0EC57DBC2DB41F30F046
-:10FDA000507707AEAF5666B0BD16E4B7658CA17F3D
-:10FDB0005FDFA25B1E06F56B3CCC8AF52337F0753E
-:10FDC0005BE97ABB03A7698075B065885F1FAC8B60
-:10FDD0008F21BCD7B74C6EC4FD8135F7321B9AA179
-:10FDE0005A569B1B85FED0061672DDF89490B30917
-:10FDF000397B55D417F1E8DF87A0D353824EA00F8B
-:10FE0000D6229D87B7BAAFF0FD38AE4F4825E2FA4B
-:10FE100074BFCE1B6A3D3F373A771DF2C1406FE891
-:10FE2000F5C35A0BE7B77511AEE7A8DD2E7EEEB528
-:10FE300054EADF593AA607BA4F11749DB2819FDF89
-:10FE400060D7AE5F57A59FC8A87F867AA5F45E8B62
-:10FE500017E343A50D191E82CBA5387AA2BE687898
-:10FE6000DF85F9D2AC2C2BC6239C7F65CAA93EE462
-:10FE70006232AEBFF4EC94D42764C7E368DF69B2A2
-:10FE8000E0B7B5163B3F470D288E00FC976E58B67D
-:10FE900017CFEF7CF46B46FB4B47D4D661D8D954CF
-:10FEA00040CE922198EA5921C52BF8FED5BDA21F5C
-:10FEB000CFBF615CB37FDCA90D07693E470CCC6303
-:10FEC000063EBAB4E73E3BFADB2BE3CD14C793FB07
-:10FED000B24755F7E36484F4AD1508DAFD0D115609
-:10FEE0008C7FFC43F05D46827B1FD2C7BD7C7C05C6
-:10FEF000DAC19665A674C4A37B79921A0770BAD743
-:10FF00002A34EFD1CB938C787E61E68AC1E3504FDF
-:10FF10000D61CE9518DF7928968594D3F3F17C9DF9
-:10FF2000585C6560C6689A8411E32F176B148ABF0A
-:10FF3000E0FE5B01D0678E985FF9AAF7A3883FECDB
-:10FF4000F06F181ECBE53F73AA4A491EC1CE6BE481
-:10FF5000A78CD51993A09F796B6039DB8DECFDF1EF
-:10FF60000EFE43C079EFF23A6D7D255BF3399D7F3C
-:10FF700061E0EF5BD02E68EB3F95F2E8600EA4AB3A
-:10FF80007BB1C58CE784460BBC14AD51ACA85F6651
-:10FF9000AE688CBF0FF2339B5407F2B4C40BEBE88E
-:10FFA000EFD3398FCB4D3D693D70D96EEF82EDDCDB
-:10FFB000515CFF2B7AF7702C7F28D63D1CD7F1AD12
-:10FFC0009F58189E9B39D606FE18C61ECD6C10C5CC
-:10FFD0001FAC6CD0A4003B5A64B02660BCDFC316D3
-:10FFE0002632BEB7650E9C77A5790DF98195E80795
-:10FFF000F2F9911FF8502C67D5D6D7153A9FC3EA6E
-:020000021000EC
-:100000000DE4079A851F78D65E9B00AE17733D6E90
-:1000100020392DDE16437E68F18A5C23F26FF1AE43
-:1000200018D243E0077ED863989F8EC756641E4857
-:10003000847E8BEB321CAA967E5AFFB8E698A45BAE
-:1000400047BF4F4BB793A1E806F4D294A72408FF0B
-:100050004ED08B3D164B7E47E182B77A9A019ECBFC
-:10006000556174EEA833FF83A5C6D1BE9E5C17E62A
-:1000700025B7AFDF68DFFCCA9AA144B7607AE5FD17
-:1000800067E670B427ECAF16867AECA1EEECE1C916
-:1000900050FEB0C2E5EBA1EAF17928A759095C6FDF
-:1000A000BEB714666864ECFDA566E6ECC5D8074BE0
-:1000B000AD94FF686922E53F5E6AA7F493A57D28A9
-:1000C0003D29E26852CE8001885F472570F91A9574
-:1000D00020E2DE6C5122AA8CBCFF7C305467C5A1A3
-:1000E000D2278C4D63EC1E272023C0DF997E6F043E
-:1000F00012B93DDF62B08E4B44FF719542FABED813
-:1001000075BBA63DF825463CFFCDFA64FACBE99CC9
-:1001100098DD3819F8F0FEFC584DFB6935299AFC3A
-:10012000E4043BCD7B525E774DF90385FD35F9A2A2
-:100130003640029E2F30DBF8FEAAD8B767CCC6D770
-:10014000EB56DEF66AD5F02EDF0778AF1E32507D13
-:10015000303D245D67ADD731378036733DCC0DFA25
-:100160003D593B93E4EAFC110BD9FD95DB32DF1DD1
-:1001700001F963DB0CB4BF7E6C45EC5ADC3F3EB644
-:100180002D3E8A41EA5EA9321FFAC17AAB9105E899
-:10019000B7DC15CBE8FC5691D7E440F92FDAEFF93C
-:1001A00095CCDBD11F4420513E3E54BD3E85E8E74F
-:1001B00024FCBE14E6DD02F933A0AFF1C8F8CC167A
-:1001C0000ED71985ADC0FCD9B0BFF5FA3EC071B1EC
-:1001D000A0B64487EB01F5503CE9CB1D2A43BE2D68
-:1001E0005C60A0FDBBB91FA91B31CF9421299CDE07
-:1001F0002A9D47642F99A87FD60A1C02ED16FDD6CA
-:10020000B489D6774CE4770FF4AE16FC897C74265B
-:10021000863963085885E03DF77EFC46ACF7E3D3AA
-:100220003B08E7FDA5DEB53201F8EB5C897710E904
-:10023000B5C7E249AE82F17ED2C8F59607E540F136
-:10024000EB4BBF9C2D273E9D69702438485F652588
-:10025000A1BE3AB9C640E79899DE193589D63F3B29
-:10026000888FE53827F5F67108DFC99A0C86FB966A
-:10027000C56B54F20790FF787B2FE7FFA755371B1C
-:100280000EFDD6286ED6A523DF3CB260389D639A5A
-:1002900021D641C17AE0339055772F7F7EDE1E7ED6
-:1002A000CE8665B5E8EF1D18388F157CBC44DEBFDF
-:1002B0003C0750D6ED4F47D1E5BEDCD43D1AEDF0FA
-:1002C000D90F55E2B3B3DD6A8725023D2FE8F60E5C
-:1002D000FB3EE4CF17784EE921FF54B87B6702AEAE
-:1002E00057746BD2956E783EF6C4DADBE1BB73AF20
-:1002F000181C24E64BE2497FCC7B696ED7C0F38E95
-:100300001DF5972F99EFBF389314C0E77C7BDD383C
-:10031000EB005C77BB841DE2F8B1E3E62AE0C5BAE6
-:100320004EC143C3ECC450CB6A3C773D13C4243068
-:100330004E7842EC8F1F107A45FA09115D787EA63F
-:100340008EF3377B5521BF0D7E34FABF529C4F94FC
-:100350007A5FEAEB32564BFBC14712F839C6B98ACD
-:1003600097DA55E0CE2EA8A8122B0F42976D35795B
-:10037000BD19D49735D00F48EE62E7FB43C6579EB0
-:1003800045B62D65CD7C7E41EDCE19BC25CD191D20
-:10039000ED4D8975E30A1BF56F7060FCA454C869C4
-:1003A00079ADE2F5F17990DD94F18AD9C26E06DB80
-:1003B000A70EF628C80ECD0EB2B3AC566B5701DEB1
-:1003C000481C47C21B0CA72BC24278980770A1BDDE
-:1003D0002D717B0F4C24B8150750B2033CA5CC35CA
-:1003E0002606E701F53E7B47F882E7D5015E31CF6F
-:1003F00060B84B1C9FFB70FF18CF8751BC29681E4B
-:10040000921EC1FE9AA44B8987E3B7A441217A7E4C
-:10041000DAEE07328A1B497E8105509DF67BD74470
-:10042000D467A5EB40FF66F8F947F2D33C56178531
-:10043000FC52C17C2B9350BE7C75D346A2DFBEE13B
-:100440007D23CA49A1CDD7531783285CFBD3BCB405
-:1004500080F544109E6F44D76F8A379C955EC6BD69
-:10046000004FB337ABCEB0419A76E21C9187E4607F
-:100470008EC763C4F8C61CB1EEBF119C957A7E6E20
-:10048000FC86F076E2277D5BB8F3BA68FD62BF9F19
-:10049000D5333A949E6AF7AF82ECFADF0C3C7E21AA
-:1004A000F5F155BD93E225502EFCAE2A2B8F9B070C
-:1004B000E9F1B42CD2E325C2AECB714EADDF49F1E8
-:1004C000B7D968F703CA3F5DB793E2FEC6576647E0
-:1004D000A1FF7D6AFDCCB578BEEBD4B69964E74B3D
-:1004E0009F9376DE6D0CF41F72D717BDF863E4DFBF
-:1004F000AD61149F2FD9EF16EB1ED0ABD0CEBE9EB0
-:10050000EB51B68EEBD552B48703C81EF6C6768B78
-:100510004BDCBD510E02CAC94E2E9EE9FEDD1EE81F
-:1005200077F1CB110E0FA1C2EAD391DF6EF5A13D99
-:100530002C5FF8F1513CE70EF6FFA31F48FB0FD9E3
-:100540008D7AF7922E286FC2EE97AB1BD3ADE827BA
-:10055000083BF15FC0BF3934FE8710FE8B11FF01ED
-:10056000FB20C76B389E6706E1FFC41A4E9795DBE8
-:10057000BA47E1FAF1784D77F2B38E6FEB49F89F05
-:10058000B51AF0CFE35F5A3FAB06F08FEB08C43FDC
-:10059000C05BBCDF2EF0EFE0F8AFE178676B783A34
-:1005A000AB039E3D748E61F1AF4D0EF41BCE84F90A
-:1005B000C89F3AB35D65D5017E98F483BE60B5BF30
-:1005C000427F4DE27F6EAFE641A87F0A9FFE531443
-:1005D000D261EE761EA4EF807FE6EC82FEB87FFC4F
-:1005E00076BFE9952EF1017ED34DD2A982B918D9F3
-:1005F000C5863F1DC17583E2844F6D788F46DCD779
-:10060000A8D7DED7C0331985368C2F38CC6684271F
-:1006100035F81E8A9B611CF99F3D3F9FB190E4BC59
-:100620005573BE6D22F319BAA0FF58A7D0FDC6F2CC
-:10063000453951390CE3D45504C7E92E8AE6FC78D4
-:10064000B9AA23FFB1CCC8FD48B93FF9AEF00FDE1F
-:10065000EDC2D725EF75B1D27797C218D9814B1665
-:10066000A317EF23C07A2A11C7F7EC3111DD8E22D0
-:100670004C807FD528E2366002914F1F649C4F1F4B
-:100680008C6CA23839AC545E40BBF8D0129383FC1A
-:10069000DAB8688AD73E20F4DD83912B5D681F1E8F
-:1006A0008A343A31857E3D7888CE301A8687F10DBE
-:1006B000C946BAAF53686E790597BE0F279E78D4A6
-:1006C0000CA0DE06EE37C655E0D75DD7633BD2C53A
-:1006D0004F1F6D9CA7323C74DCA355E04B713A2947
-:1006E0009E6382BEC3018E2B682FB1DC6EE5F19D47
-:1006F0000D40278B9FBEC1E5CCC3F703CAF05CE376
-:1007000028C6196404E15F932F33F2FAF0C4AF26D0
-:10071000ACCB66ECCFCC3E10E956863A04D7F74511
-:10072000D15E8C97DF83F1251BA67AE297C97AE622
-:10073000D1F1B42612CFCC8978D34481CFA92398A4
-:100740002F1AF0EE3BA88D77DDE7D3F97A037EEF21
-:10075000D1FB1A913F7566BBC10AE3B8F29421B888
-:100760002E295B7E73F0A6259AF3D7A5425EC7CFEC
-:1007700085B5FE80C7211E046145BCCDD0B3FDEA1E
-:1007800010CE0788974A9BDD43ED1628140F95710C
-:100790003649FFC1D07D201D1F14F0413F3551F86F
-:1007A000BD3134BDFA26CAF5731DADABE70BB99B5D
-:1007B0002FE56D9B56DEC627DAA9BD827E30E0EDBF
-:1007C0004191762617E344FFE312B95C64DDE278D9
-:1007D0002CB2359DCEB708792937F1FEE5F8F788B8
-:1007E000744CA28DFA95F000BF1EC77E74A00190D4
-:1007F0005F4FD656937F348705C4B533FCED245F35
-:1008000077CCB7EB11DD754C8DADB310F5CAF7C2DF
-:100810001CA8471F34D6F5AC8AECD84EEEDB14B2D8
-:100820006603233D29E261C2FE8C5523E97C40A189
-:10083000C2EF0F5ECAB17874D118A73110690B638B
-:10084000143A3FF137B17FF250F4E28928D785514D
-:10085000463DA633582BF5FB776BB7E8FB18DE3324
-:100860005631760E038FC877C2B8D5A877787E8DBB
-:10087000339BA24A227FC72127E0E1DE6B407FCA7B
-:100880007F2FDF09FD5F7A4BD4B33BE9FB4B8F0B26
-:100890003EF6E4F2FCCF657D1ECFAF92F5F93CFF4A
-:1008A000A4EC5FE49F0EAA5F1654FF4B9E5FBC3E14
-:1008B0003FDF837EEB68CED285A314D2537B84BE08
-:1008C000285CEE23FC16EAF6F27434F3E9B26EDC2F
-:1008D0006E53A26B0FDA1FD572D282F6F7D564275A
-:1008E000E59F4F702F4BC475D424C563447DFBA195
-:1008F00097ECC1C44ECE1FEDE9C2E3F89B92A0BFB6
-:10090000A17EFB05FDAC4E8CBFF57E1C491CAE8064
-:100910007E9EF926F0FCA7233C1BBE493FB392B54F
-:10092000FD487F484975BE86F36327E334E745E613
-:10093000FFC4118DF12786E74500F5F397D7A5672A
-:1009400042FFF35F7D3DBD04FD2561E72BDA74CCEA
-:1009500089F734DB18A5E71B3F31E27DB38A5D8D53
-:10096000C671D0AE12D2DC00B8CA049C60E7F49322
-:1009700003EC7383D01B8C3DCDF7375F3DAB477ADB
-:10098000CED7D59D7A0EEDF62825E43ECD66F1DD75
-:10099000D14ECE17EF157AE86A9AB311E7F96B8C4E
-:1009A00021403EB7BA93FB60491C5F85C2EECD1C67
-:1009B0006631DB01CF433FE4FB54251B3286603CAC
-:1009C000F8CD84D1EF247E6D3CB595C7531B783CA0
-:1009D000B5D0D6BC089437332695AD31DFC1D88465
-:1009E0005F48390391856FF34C325F9D3F269BC76B
-:1009F000BB307F76FD636B506E9AC2B91FFBD0F09F
-:100A000081E1A8175A3222745690E737E38B8C495C
-:100A100043B1FC8E71589E63B2F42A22FC32E28B01
-:100A200037E35DC7905FB03DC641DC465FFC7D307B
-:100A30000FF7DB2A9DA7750F8A7087DA77FA87C0D0
-:100A4000AB31C94A69139019FD1709871C1FFCF9BE
-:100A500045CDD0DFC9E5498357DB719F25C7903469
-:100A6000D43F7E4682FB72E0F82775AC172E296EC4
-:100A7000168E4B020E03EE5D03BE5DD92A7306ACE3
-:100A8000F3268F89D0E4EFCD8F65CEC038EDBD2938
-:100A90009AFCF4C2EE9AF60FCCEAAFA92F30356774
-:100AA0005505F8B19DFB491E82A7D26209477FEE2A
-:100AB000EF0D5FFCE541F4FF36AB0EF455E7EED9E0
-:100AC000F297DBA1D5653C4E45F1473BC5CBCEC97E
-:100AD000F3287AA73E705FE8226BA6F33E9DED03F4
-:100AE000C975EE7CEB7E3A77F65DEF03F54A12EBC3
-:100AF000DD216C08DAC3CB551F51BCAE2292CFEF7B
-:100B0000E2EBC78CB80F8AFB8AD781DFEFC20FD127
-:100B10003F6CF3503C3BB7FE18ED9B1D48E47ABA9E
-:100B20002275811EEF1D55428A76681CE8AB68E08D
-:100B300097E646367017EEBB6658B81FDE3699B199
-:100B400058E42B1EDF694A88A17BD7F36BF2A8BC5F
-:100B5000A22D9CFA7F4F6D1E47E7095F5368FFA1E6
-:100B600020E5A1E5787EB829DC33E01118B7E077FD
-:100B700077E521DE2A76F1F3B505EA9FB316405AF0
-:100B8000569B47DF17A8AC49017F61422EB7BF05CE
-:100B900068F321AF0EB3AC46BBAB1A7DBD9E473D9B
-:100BA00063B4909E896E7B80C6AF6C33D3F7F72415
-:100BB000717FD7D0C2E11ADBE6A272C90F5393BA94
-:100BC00069D60F86F8CD7A7C97C3D0C2A8FDDD6DBB
-:100BD000FD2895F37DBBCFAFE93EAE21FEEAB81408
-:100BE00098F7DB718A95DC90203D7CA56A78340B00
-:100BF000A1A7DAC769E3E7F44C6DFCDC5E618A7398
-:100C00007E12C031F1B1163DEE07B148B315F13592
-:100C100071C4607B49807CA97BEF37227D0CEBDEC1
-:100C200037A29D36419A1B505F2ECE3304EBE90567
-:100C300049524F2FA354DA1D767506F9A933AC82B9
-:100C40000185FCCC10FA547EDF4C6B1AA0E36E1EBB
-:100C5000C77F34C5BD02F545730E9BBE83F4667332
-:100C60003AEEC37C57F0039DCD0AF9892D741E75A9
-:100C7000E208BB0EE3FFAB045C528E6F348FC5A25B
-:100C8000FD7B2A5B82FDBE77E79DCD4EE8AFF14745
-:100C90009999680FE4B8CF25F17B29CCDA7A0DD782
-:100CA00083956F44D851DE0B703186FB9D7B4CB42D
-:100CB0004E8172DACFA87CC3B409EF895446C17A59
-:100CC00015C6CF7D33CC877CDCF866981EED46EFE9
-:100CD00074F77348CFDC377B8FC1F5A1B3C1A4672C
-:100CE000E4F7389F273DDB09BC37D25BC17C26E5A2
-:100CF000D35DC3E5A548F069B1903FB790A32B55EC
-:100D00005D480EAF3C0640E33EE963CAC05DE8279C
-:100D1000D82DF47E9394CB025C0F417941FF183AB1
-:100D2000FF2BFD8D60392C6BB352BFE56D7621EF43
-:100D300036CA4BB92B167263127EC62CC1E7BB5361
-:100D4000DCEF205E0AAA41EEA3681F3F0BE5C9CF86
-:100D500037462BF217F04D624980FC5437DECFD076
-:100D60003F31C5B9886F66411AE89FCC6EF74FAC2A
-:100D7000E31200FE892B327478DFA99D7FDBF9E650
-:100D8000E6F87F8F9097E2485F4FF4670D55610E4C
-:100D90003C877E398EEFF72C5CC5F1B8D0E0CA45B0
-:100DA000FF62E12F158A97A1DF817A69D8912A63C2
-:100DB000601CE5FEB641CC0E7898D2D683D23713AC
-:100DC000DC47110F456DD304BE067DA3FDC5A14EC2
-:100DD0001E4732784D8E8D19184772AB48E733693C
-:100DE000CCFA4CE07EDE7A1DC5C3E4BEA38C2B9901
-:100DF000F0BC7C801DFD425F9B4EEF3704C79972AB
-:100E0000B8DDBFB0D94076BFACF1CFC374507F2EF0
-:100E1000C3D905EDC9977A771BF2F5BCC9DE570D2A
-:100E2000909FFFE4CEA891763F3EEBF4BE9E6847CC
-:100E3000EB008F18EFAA5BA3E679B9BF13C1F7C91E
-:100E4000387F4B7E0EE6F3796DDD889FAE5499C8EE
-:100E50000E5D01BE65017648DA1DA9E7A5FD917C0E
-:100E60005DAEE7FAAB3C32DAEBC908B43B935C39D0
-:100E7000C8777DF8791ABFDDD9B47614CAC1A53810
-:100E80003AB728ED46B01CBCB6141CD35E1DED8EDF
-:100E9000D4EB52CF4BBB35FAE52F77FE15CD558AF3
-:100EA0007B4032E0EB6E3DB75F77EB2DC43F63E3F1
-:100EB00026E9916F6E5E8F1E137AF498468F5674F2
-:100EC00062070627DF9A1C7415EDF34CDC7F443D66
-:100ED0001FD8DFA329A3C7E03CC627733BFB5DC136
-:100EE000DD99FE1F9F7C6BFA7F58B288F7DD40FFCB
-:100EF000172673FD1FACEF9995BFA773694F5F2F3E
-:100F0000DA83A30CEC03DAC18608FB16610FC85E16
-:100F100084477BBFCE1E5C4D9B5988780A610F1EAB
-:100F20004AFE16F640F2A1941B2927522E82E5486C
-:100F3000CAC5849FC23A11E9F41EBF5750AEF76C80
-:100F4000A3FD467BC46094CF763F6E9742F2D6C134
-:100F50004E08F9F1CB8BD66E48B990F222E5A75C2A
-:100F6000C8C5EC20B9D8A7D63D330AF7CB92DD6BC4
-:100F700093E3FD7252B623D83E74CA57185964B32E
-:100F8000E3AA18F25539A4817C65EA441E9E49BE45
-:100F900035BF68D94DF2D36FFEFBFCF49B4EF8E9E8
-:100FA0007FBE0D3F75F4633FCEB2033C57B240DFC6
-:100FB00066F8F96DC23B8CFB0FDDF97A00D6970419
-:100FC0007793318DE23E13AEB32A8A2F0ABE947412
-:100FD00096FEC06C11773893E27A07E1C5F5C082BE
-:100FE0009BD37B4467535CB311D727B3210DF40324
-:100FF0003AF37F9B6F51EFBD7193743E96FC9DFB5E
-:101000008DC79243FB8DC7B1FC9BD2B5209789F861
-:10101000DE8F0B30DE38E1299167CB0A108FD34683
-:10102000C8FA9F3CE9EC81FA81C9B838C539DE536A
-:1010300045DEB3F4F018683FE119E68F9B43FDD815
-:10104000ECE8F6B888C2FCED95E71F3BBC86E8519A
-:10105000CBE5CCDDA2E7FB3F229F05794B407E44E8
-:10106000507E036F1FA56F6181E745909F94219C7F
-:10107000CEAE00FF0186DF7F05ED85556118D7A84C
-:101080008CDBF8D615D46BF50AED45B5E381D514A4
-:101090003853C5FBB9945F73D8093EC203BB78BE11
-:1010A0004F4AED931EBDE837E0DCBDA14E71D2B9C9
-:1010B00083118AB75B46477CF749D1DA27FCD16BAD
-:1010C000BF67781EEF56BE6FBFCFD68DBEF7996E45
-:1010D00061FCFBB2439F7FFE5E0AE7EF3159D121ED
-:1010E000EBC7A5A8BC1F1137A0F1A1684A5DE87B3A
-:1010F000B013C5B8CDB85F42F8DCF624E2B7D92802
-:10110000F1FDF293C8776319D3C4CF607CCADF9F27
-:10111000F272418D9E4FD71984AFAF9BEF8014A917
-:10112000BFFDF8F204D1CBF435F87684C0B75DFB8F
-:10113000BDEFEBE835ACC3F7826FE7483E766AF85F
-:101140003D5AEF22FE8C8E53ACE84757B8C2D6E02A
-:101150007AC12F9FBF27BE6C96FB031DE4EFB5023B
-:1011600094BF0A8947CFEB4FA2FCBA74EDEDB93CAE
-:10117000B6F33573F601BC52C80FBE7FE4F9FA2707
-:10118000312E097C41F594D707C01D2C8F7541F98C
-:10119000EC20F915F247FA03ED01E0A927EAB7B808
-:1011A00063467B009FFC4CD0E9A2B827DA3C9AFB4F
-:1011B00093CDDD78BA2385FB8FCF097C6E12ED9B32
-:1011C000C303F090AAE11F1FAE5B02E64D78BA3F61
-:1011D0004ECEFB93827CD063CD365EBF2DE5A32738
-:1011E0003DD9FE7C707FAFA67C528078F1F7FFF18D
-:1011F00061F423EE1778DB9172E4B02752D039C145
-:10120000FF4E21F007BD63518EFCA174E48F1F7661
-:10121000E44F4FD0F7F44E7767DF7B3A7EEF0CFA5E
-:101220009EE13DEA9BFF5ED02D3F88AE7941741D63
-:1012300013942F9479AF46FF4ABD5C5CFFF4E30939
-:101240007118DF54E838BF9F9F4F93BD996F95FC8D
-:101250007BE630F2AB9F9FCF129E27D709BA79CE9B
-:101260003D897A7812EAE151FEFC14D443943F5F41
-:1012700080FB617E7B7581EAEFAB91ED2F92FD7A69
-:101280006085ECEF33CA4B3A32CF25B277F70BBD0E
-:10129000C33CADA4F7E735F0EF3F7DFEF3C35F2B12
-:1012A0000FB54178D91094F704B55F7703FBB622E8
-:1012B000E8FBC782EAD704E5D707E56BB4DF17CDB3
-:1012C00052480E8B46F0FDC960B90CE68F2F52DAFA
-:1012D000E363EDF65C8924FF4E235713AA79FEFAE7
-:1012E000F3FF29A8890CC8A7B0891EB2EF305AC0F5
-:1012F000FD41D0B91E15F8C1D089DEBCD899DEEC0D
-:10130000136CEF79FD3FF0D724DA2FD2F825FB5488
-:101310006DBE51957047BDBB2832605F955926E27E
-:10132000BABAF3FD9B8889635203FC224FF84467E5
-:10133000C03C65FB715F5D5771BCF8D4F0899B714F
-:101340007F68B4D8D7B4F114ECA58AF6BA52C46F4A
-:10135000C6E1395D6C17EEEBB930D00F6275BD7028
-:101360009E8D3F52F9BB50D5401FC05311B3D37966
-:10137000D39978EABE3BD447472FF90D7CB7EF47A6
-:10138000EA12B4D34797C4D239A645A9DCEFDC17DB
-:10139000DD356136E41B231E267DDBF8C4584AF791
-:1013A000AACE95AD56E83A357962645FAC8F263C9B
-:1013B0003936C44F5C06FC9D996A2738DC366B428F
-:1013C0003DFADBAB0DB45F082D7E45FCF3A469301C
-:1013D000AEB78B96F5A7FDB0E29F4F1A87F7B08A9C
-:1013E0001F37D03E498BCE4A7122F7EAB1742E6A7C
-:1013F000D60A917AEEA2F4CDFFFCBA1AEF69B5BE17
-:10140000A0D0FB0E775CAD7B67109E9BACE94EF7DE
-:101410002EDE8075009EFB3EBEBEB717CF219F0813
-:10142000ABA273A4D09EEE8B955EB3BF3B310BDBBA
-:10143000ABD6E5D0FE1494A3FF7C6A95BA09EF41C0
-:10144000154559C2F1FCF6A9AF18C5754E3D6EA2FF
-:1014500077228E47BA67AC8FA3FBB8E8E9B3538A0B
-:101460003D4A013C4CDAD067626212969B047DFBD8
-:101470004415011E8A74EDFC43F6A42486E727A5D3
-:10148000F699B805E671EA97BDE97CD8C154E7E45E
-:1014900054C0D72FD29C5352E3115E6EB7DEFC0FBF
-:1014A000DF8FFCE385E204E4AF8752395FBFD1569A
-:1014B0009C10F8BE77C9453DF1C19B46FB227A27B7
-:1014C000303C4DC17536F0412CC6CD6789750BF0A7
-:1014D000F3929D21FCABE1A92AD1ABF1A7F1D94848
-:1014E0005F3F5F0F7F17F519AD37205FB121732D77
-:1014F000DAB993A625EC440FD67EFE91ED0B233C82
-:1015000019B68579C332307EEA1C87FCCD12EB7A9E
-:101510004DB604C8A168FF770F3FE7FB77688FEBF4
-:10152000BEBF7BFED712B89F21DB9746593CE85CD3
-:101530009CB658F4488FA3FAA5A7F03C5AC90B06ED
-:10154000B203252FC43FD68AFA07F806E36BC1F32E
-:10155000FA63AA81C7313A934BCF18AD5CB231130D
-:1015600071BE9DC965CD86DC899B233B97CB522BF1
-:10157000D74FE35EE0EF51960EB5E8717F73F40B41
-:101580006F6DA17B740BC286E0BD89D2174C44AF4E
-:10159000168BC563BD0DEF1358F431903E9BCAED19
-:1015A00069BD909F5C95E9CD4328A57B1272DFF061
-:1015B000EC92679EC5E397E79877DA70C0DF6527FE
-:1015C000E7D3CBBB548A3F06EF23961FDC69CC617F
-:1015D00037B18F7883FDC332D622DEDF0DFD7DF07B
-:1015E000FEE1ABA9C1FB8706BA4F5E2AF60F73373F
-:1015F000280477E9127ECF3F3796C78D4F2E05FA24
-:101600001B69DE1EEB103C0FCDED4E2953BC66F876
-:10161000F5AE0D0B288ED913F184716EF16EE2894F
-:1016200030473AAEF34B5E0823FC96FE6AEE5F7ECF
-:101630009985F7FA0AE202D7D5FB912F387E19DE99
-:101640001F94FD9C5EF6637AA731F745581FC37C53
-:101650004A63D8ABF76720BD92D2719F53B62B5D1A
-:10166000FEA35EBC1DACAF611D5DB44AE5EFC7ECE7
-:1016700036911D04594F6401F72C67AD38683472F8
-:101680003BC6128709FFDAEEBF9F761CEAF1EA6ECD
-:10169000A5B88726F127EF5115E9F8FB74853A853F
-:1016A000EE578126A37B499753B95F7B3A959F6795
-:1016B000284A77D0FD9CF2B526C7F20CDE4FFB7DA1
-:1016C0004F58DF95EB9A4B683FF3F7268AAB54AE41
-:1016D00008738645F1F3173B06D0F96ABD11F05146
-:1016E00066E7FAE2B2986FA57DD25D749F41CF8E16
-:1016F000E8A1BEDCC2F563790CE03D92338A6E1836
-:10170000BE67C7E8DC24F69B3428607C4594433FE1
-:10171000F6287FBF4D3A5683711B6CDF7710E2319C
-:1017200076DA7484EF1595E41990B47604FA7DAFF7
-:10173000A899B8DE2E5AB56F1CEADFF9DB07E38DF6
-:101740000956F4EA07643FE60BFAB7887367C59059
-:10175000C777B622D2B83CB9551E2F8A485334EF0A
-:1017600010C9FAF255061EBF073D8F8AA57CD9C75E
-:10177000D46FB9A53901F56FF96EC330D4D351696F
-:101780005C2E8B97A5651F01BE2A3644D3BB8365AB
-:101790009E0223E6CB6A15CAFBBF8B4F473E3DBF77
-:1017A000E2B528E49F1361BE9E68975A178439E812
-:1017B000DEA195C7EBCEAFE849F79566599B2DF8AA
-:1017C0009EC1AC45DD6DA8BF8F5A7D46AC3F5A9790
-:1017D000A1C3BCD36ACDC6BC537F1BE5CF8BF32D11
-:1017E000F4837CA5703A976DDB67C4BF4F3244CC5D
-:1017F000F7E22B1FF4C2F84F797A732FB42BC0078E
-:10180000BD5210CF2F2964972BB6F1F3EE920F2A19
-:10181000900F40EEE6093EA8D8F5DAF7511E2A905F
-:10182000FE433AF211F0F37E2ADFB1711CE3DFEFE1
-:10183000473E91760CF22B0C368CDFF17C661AA7B2
-:101840003F948FE1E59E01FC1C5DFB39048D1C7407
-:10185000465F571AB787C5CB4CA46F5D695C1E5AAB
-:1018600056ED8E42FA5D7C65DF01DC6729DF0156AB
-:10187000DA1E421E043E2A71FE51043FF9179538C4
-:10188000DF28FFFCDBF95EC86125E3F393F3ADD4F9
-:101890008BF9CB7AF1FD24C12F654CE06B576F2E8D
-:1018A0007742CE508EE9BD0E313FB74DFB0EE5F7C6
-:1018B000C5FCDC2265D6BA28C40FD217F50F3E103E
-:1018C0006994FA049A5CDCBE91CEF14B7A49F857E0
-:1018D000093840DF39636C7E3AB674F24E6495E0A5
-:1018E0009B638F7749AF07FC9DDF4ACF6C11BFEA3E
-:1018F00003C6937C23C7CB7D79D2DD386FE8DF87C1
-:10190000FDCB718F7A22F4D8CF51C6E543C22FE5C3
-:1019100032B7FAA1BB074761BB8B96EE0370DE9C22
-:101920008EABD2ACF4BD13FD05F8DE59AF50DCFA36
-:101930009858E71F7BFCB5A8E2017E7E7F427C279A
-:10194000F90C7F303E26E16DB2F1387030DC520F79
-:1019500049B8739FB8EF6E2C97F0E3BE51209F4AB1
-:101960003C4A7E95F7F582F996784EDA4FB573FECC
-:10197000AE4C3D46E7773A9407F727FCA213E25CAA
-:10198000796B3CE371FF1589FB35F78A188B0CB432
-:101990003FD28EC0CF1A7D80FD69BFA716E73C8B72
-:1019A00074BB90D68DFA3FC7EA8C39D06FD999E6CF
-:1019B00071F8CE9DF443EFB8EA53A3315EB58B9F27
-:1019C0007793FC5276613FC941B9B8FF54B4EA83BA
-:1019D00082E1C8EFBF35D0BE4ED1E3638DE8DFCFE3
-:1019E000DD327318A201EF41A05E3FBB796826BFCC
-:1019F00059604D9886F721363F33ED01289F55AF4A
-:101A0000D2BB0DD80FCA6FD1A399145F3D11D65226
-:101A1000300AFDF81FA856F4E36FDF32F4316C7F13
-:101A2000BBA56B0C3DB6B13996F24E7D34D907E9B2
-:101A3000F7CA7380D5E2DEC75F84DE3FDC9E2AE210
-:101A4000FC5F752FDC8F6FDD1846EFAC141AED7557
-:101A50003E1C6F4F175A67541AF1EA23DD5B25BF0E
-:101A60006C8E9199938650B93909CA0F1A9A1F45FD
-:101A70003B72F051CB607C3F92A9D78615737F9A59
-:101A8000EF3BC66ADF2D91707C24C60FEE4F7EDFE0
-:101A900084EB081BDD4FA4EFCFAEF8ED34B48367C1
-:101AA000B7F6B4E1BC4FEF09A3FB03A70DDA77CF7C
-:101AB0006EF5DE57F07D29796FF5749AD68F93FC19
-:101AC0007EC37B377FD39E83BCD1B9A50B4B19DD79
-:101AD000FB7E398DD1F76322BEDA89E7084B6A4D68
-:101AE00056BC077312F91EF7B376ABFCFEA599CB73
-:101AF000C1C9DD9974BFB7E46F3C5F52A778F13E6E
-:101B0000F2FEA79FA0F30AB3C1CFC4AB09EDFEF369
-:101B1000BAA7A7A1385C76B857E27DFECB5BF9F98E
-:101B20008A0EEF321CDC7920C9DEB9DFFC5DFBCB0D
-:101B3000320E119FAEBDCF2FF12CD74F6F023F8CCD
-:101B400018E2C7DB674BE790BF7C61A99BD24BCA09
-:101B5000B1B5B7231F5BA2E9BEC01FEB9F51F1BD1A
-:101B6000A8F25D83AFE13A78546434BD93F2D9D2E0
-:101B700025B48F7A616915A592DE320E77C7AE461D
-:101B8000FAEEB3FACC06BC9FFB4664B4B003B69041
-:101B900074EDECDEB19CD7B91F70FA4AB8CF6D9DD9
-:101BA0001985F36A7C3EB66124D23522DA8A7E5FDB
-:101BB000A93847726A3DF7ABCF98A37F930FF43DE6
-:101BC000B3614A02BE3737BBF1DE69585EB247B136
-:101BD000E27AC0B1675214AEDB3ED5B744E1FDA84E
-:101BE0004FD7CB7B555EFA3B54A3F2D8146C3FCA57
-:101BF000A767F60CBE758D7C32F2829EEEBF9E8783
-:101C0000728A935C0BA73809FCC4E2B991D9AFF38F
-:101C1000F84AFB3A57ACF36E17F37E34DD26F73102
-:101C2000A83C77042F3FBD61E744ECEFEC668315D9
-:101C3000E1FE6CB381FA9F07EB331DC07B662B5F1F
-:101C4000F7601ED7CB67B7F2F5CDBC3ABEBE295FB1
-:101C50006070F2FBA25A7ECC0D6847EFFB74F25E17
-:101C6000C83C279FDF3CB09738DF60BE8D6175743C
-:101C70008FEC9B9E170DE6DBF9925F857E68E7D7B8
-:101C8000CEF844E013E51DF955F2C3BCF57CDFDE68
-:101C900056373807F94EF247F03B59D546C6DF575D
-:101CA000D485D37BB89322ED06B40F53E25AC620F5
-:101CB0005A3E4EE77E809AAB73E2BD37566D0AF905
-:101CC000CECE8A74EE57457465C4EFDE742B3FCFD9
-:101CD00029EE7FC914269286767B5284ED0B3B3425
-:101CE000793AFDAE7BF4C0CF936EB73DDADDC1D853
-:101CF0002FD30BEED1C37C2665DA767783FCF3BF56
-:101D00009AC0F3B7D9861A20BF4C9978CF18C8D794
-:101D1000A73B9F4A0F18E7EC962E69383F28FF191A
-:101D200096D7C5BB7F8E69A5B80F7649691DB424C7
-:101D3000C3DFFEFD3D96A37FB4FBF32D0696EE18A0
-:101D40008079097FE8B425DDF9ABF4F88EE5C58C20
-:101D50003D4EE7F53CFC1E0EFCB8CC09784F8AF3EB
-:101D60005BB1BC975313742FC7C1EF9FC9FB52F2ED
-:101D70003E545FFF7DB20DB7729FEC9281FF1D2A2A
-:101D8000C5A9BD0FA634FC89DEF9A9F6B09630A22C
-:101D900083F69E4D39BE53771BDD0BA2FB874C6F3C
-:101DA000277D3357FA3B68AC87F9DF296089FCFC53
-:101DB000C1A3821F4F2F653D7A80E89F7FB739CA44
-:101DC0000E705C98E8EB85FA2032DCFD27C4D7E979
-:101DD0000DD5A90BE3F01EAAC9910FEDCF78F97DBF
-:101DE000CE32E1B7B2CDF1422FA8BE3BA15D534642
-:101DF000DF4D6887DE177C7521C397FE23D42B192E
-:101E00007C9D04EDE83C5DDEF2BBE2B1DD85ED4F8B
-:101E1000F4980D709B0006BCA7351EFA1C61A3F751
-:101E2000AA984AFBCF5EFE7E929E79A26CF8EED510
-:101E300033E9E23E11DD13947492F8EF4017181A5B
-:101E4000FD599D991910EEBE6C03FDFD2F491FF938
-:101E5000CEE2C2DD3CFE427724451EE348A7CDE238
-:101E6000EF9F75B08B6F91BF0A62E9D1E89F0D3388
-:101E700043DBC9111B8DD8F5776D2FFF9D2EFC928A
-:101E8000C16C70E03B92A5A2CD58B5D08EEF5B2D12
-:101E90008C37D37B250B5FE84EFCC196FC9005B6D2
-:101EA000631B62895F5666A884FFB9F58CDE1D2A24
-:101EB000A84FA6F394F9F5364AA3DA12A9FCEC6F01
-:101EC000DEC9E27A89D3A7E07FBA8CA6734BFFD331
-:101ED0009B52D6D97BA79166BACFBBF020B76B0BCC
-:101EE000A7CABFC7C2EFAFBB0438AEC81A8A0BB9C6
-:101EF0003ADC53E7EF57BAF0BE007EE734507D6717
-:101F0000EF574AFC9A04DD82DFB39C7A303391DECE
-:101F10007F14EF594E17ED9AC5BDB3CEDEB5BC4F59
-:101F2000B47B226A5C13F2DD746769C8772DF59E75
-:101F30003007FACF86D4487A47E13E37F8979AF5CA
-:101F40004C8B1EF1302D9BBF733975BAB6DE90FDF8
-:101F500039E97343768777920CA88F4D2E6DFBEC91
-:101F6000AEC20EF5657DBFF65DD15423D94F3DBE9F
-:101F70003B0BF969E25D51F40FD1FFBFECB410FFE8
-:101F80009BC43BB8CD2C2B11F5C2ADBE27FBFFDBAC
-:101F9000FBB1C1EFC406BF03DB7FEB424D7E60DDCA
-:101FA0000F35ED6FAB5FAEA91FEC5BADA9CF6CFA3F
-:101FB00099263FB4F9394DFBE1473669EA47B6BC8B
-:101FC000A4A9BFFDCC0E4DFE8ED63F68DADFD9B690
-:101FD0005793CF61EF68DAE79A3FD0E4C75AFF57CB
-:101FE000D3FEAEC4139AFAF1F6F39AFA097DAE68FD
-:101FF000F2058E2F35ED3F37BA577745BF22EA0CF1
-:10200000F1AD3A4361F844F9E5A62966D4076BBA05
-:102010000A7D24F86FB9B0D3AC07A37BAC63D56C51
-:102020001FF15F3DFFBBA0C1764F7FDEE5C4F81F07
-:102030007B8DDF6B8B067F521F307E8CD3CC02FFF3
-:10204000EE5D6C9E55938F77256ADA77996ED7D4BB
-:1020500027B9FB68EA53E63834F9B4AA119AF65D59
-:10206000973835F90C4F9EA67DF71A9726DFB37681
-:10207000BAA67DEFF56E4D7D5FEF1C4D7DFFAD5532
-:102080009AFCC0BA259AF6B7D57B34F5837D359A8C
-:10209000FACCA65A4D7E68F37A4DFBE147BC9AFA1A
-:1020A000912D5B35F5B79FA9D3E4EF68ADD7B4BFE9
-:1020B000B3CDA7C9E7B0839AF6B9E6F735F9B1D63B
-:1020C0004F34EDEF4A3CA6A91F6F3FABA9977ECED8
-:1020D000843E9F6BCB85DF53E0F897E6FBF6F76E07
-:1020E0007728741FEA5CD76EF27DC5963015FD2403
-:1020F00017C5996C781011F515DE27B7F1F33985FE
-:1021000014AF8A237F884C941DCF0B81DF1085ABE1
-:10211000B68C0CF4AB23FCFE5BEAF5CC9BF7DFDA64
-:1021200084FFDCD5EEBE88F231AF6EFB387A9F9823
-:102130007956221CF2FDBF7783DE6D95E978F3199D
-:10214000A60FF0170F86D5A60EF99A38C178F305B9
-:1021500086EFC1B6F72BE222F8C7BD1706F4BF160B
-:10216000D617F8F7236B979AE96FC7FF6CA995F21A
-:10217000EB962652FEFF003A29BF47008000000080
-:102180001F8B08000000000000FFED7D0B78544518
-:102190009670DDEEDB8F249DD07975779EDC3C490F
-:1021A00048089DF0D8003E3A216040C0E635044919
-:1021B000A4C1A84143BA81F84F7475BB311002B273
-:1021C000B391D11095C1860164199D092EA3D1093F
-:1021D0009AF09AE03A4C601CC5D91937A0A3E28E58
-:1021E000101EE3CFEE8FC37FCEA97B93BE9D0E382A
-:1021F000FE3AFFF73FFAFBB4385575AB4E559D7369
-:10220000EA3CAA2AAD5E898922636DDE1C4A9FF3EF
-:10221000DA9998C9D8366F31C1DBBD0E82FDDE7206
-:102220004A777A9D94BFCB5B41F01EAF8BD2BDDE67
-:102230001A4AF7793D54FE92B781E09F7A7D94B6B1
-:102240007B9B29FF156F0BC107BC6D04BFEAF553DB
-:10225000DAE1DD4BE91BDE762AEFF47610FCA6B757
-:102260008BE02E6F0FC187BCBD041FF19E26F8982E
-:10227000B78FD21EEF6794BEEDEDA7F277BC57097A
-:10228000BE8EBFDB19FC2ACD9FE431263097E67A5B
-:102290001EC2CCC92632F600FE4B82FFE24688CC35
-:1022A000C2D8FD8CFF3ED7B09A76139477FEF23FEA
-:1022B0008502C674A58C8D1F0F6962F6CEC634C622
-:1022C00026B075E64F7218D34057D76307FB094E07
-:1022D000191319D6C3DF752DFEDFC7583CFCBF9418
-:1022E000E5784C836953091442FBBE55827F771A07
-:1022F00055D7203EAB8D1CBF695A1395573E2CF81D
-:102300000D02635522F3E98B18FB7D5854011BC164
-:10231000D8258F2E47C47221DC0E8304F88F3A44EF
-:102320000E7E5D2C8EB1A59D861D9BD206F1AA84E2
-:10233000EF35F0FD2B561A0CAB643D3AC403F21D89
-:10234000DA18C69EB7B8A64B90FF608AC6A787F674
-:1023500099C99FED8C64EC2D8B6B06E65FF2DC7700
-:102360000C1B7FC06CCFC67E661BBAE21741FFFD17
-:10237000C7B5F69DD2F0F3E16E29676CDC0DCADFBC
-:102380003C97EC023CCAFFA275E1FC9FD04556F891
-:10239000F3012F49E0784A1A553ADBEA5A82F87C71
-:1023A00019E9B9470353F8E56DABF6AC812155AE99
-:1023B000CA1AE182EFEE822563198CCD65928E41B7
-:1023C000F97CE6389A064D2D642E8217311FA56FD1
-:1023D000C5BBAAB19DC5CC4FB06BB22135D4B88274
-:1023E000F172CB78B9657C94F471ABAB8EE3E520E8
-:1023F000BC4E4CBA231BC7A5E0F59655A27A73587C
-:10240000FF76C4EFCB83173F113286D2C7774017D0
-:1024100026681EEB313DAC73A38ED1F78D8F087EFD
-:10242000A46B852E2A9991B7FB18E40B817402F4F2
-:102430005184FCD29F3A3792E8E449091A7C7092A1
-:10244000D6A71F0BE3D4F8B3052DD1875E00FC1E81
-:102450008803FA481F9E0EEA9A210DE01FA0AF677D
-:10246000B0BDF3AFFF5D0ECE97FBCD4912CE57A3A3
-:1024700006D601E8D8F7B6D6BE5B92991460ED9403
-:10248000317EA46B26DAED73C7E07AB1A54EA8DFE2
-:10249000AD650DFBF387F6FB2AAE17B47FC2A62B02
-:1024A000F753BB9CCF95F29FE2FAC563CAEBAD5ED2
-:1024B000F569AD16F03F71E89C5E1A13621C0D6F52
-:1024C000E76606E0EFEE3833DD6142E4FAF2E74515
-:1024D0000EE69F94E944A11FAD3ED2B5C314881700
-:1024E000EF17E8F9E74437D140CF1944CF9FF8E020
-:1024F000D3390669C42248FB606ABA2075BD60D62C
-:1025000023DD2C67764AAB9993D20760F9917E9DC3
-:10251000BEA7F438EF0FB276CAAF2BBED782F47CD9
-:10252000BFC6958A702DEBA57C37EB2FB3C1FC2D70
-:102530006C5E7BD40658CF6F796A5A02CCEF3CFFB1
-:10254000B2A398CEDD257CE293883F7A10AF3EC1DE
-:10255000B33E11FABFFBA592F549903F47CBD78513
-:10256000FD2B5F17457E048F1BF8A1978FCB41E3AE
-:10257000D24695ABF8A1F209E610A09DFE8306FFB6
-:10258000CEB400FE287EE8DF93508E89FDF7E07A16
-:10259000BBDF34C4E07A3F08E21BC72938186B80E0
-:1025A000FE90D62A63882A88DE1F62E176ACF7B9EE
-:1025B0004CDF9FA730A2EFCF05E66040BF1774A69F
-:1025C0006601E55AAACB5604F8AC60BE2606E56E55
-:1025D000CD4B05384F2325D7A744D71FB53715A6B0
-:1025E000A1FCF7A70A28FFF719EC8D69AAFD845D05
-:1025F0008F4021E361389F3FC076C70EC54B283E10
-:10260000F69F421463063DF3198B88BFD944E4EB6F
-:10261000443DF157234E6D06F6E3943CA6A1ED9F91
-:1026200090F1EDF94A4B74EF83F1EC1642F5C3F7E4
-:102630002B43F8603F243F2C8CFAD1A7713E56FA09
-:1026400063A6BE6427D0756A844B978682C116C77D
-:10265000E58B99CB979EB44F33717DE64CDEA8C8CD
-:10266000656A8FDDC6E5D1099DE443F844499A1DAA
-:1026700024D7809CBDABF897A7118FBB8CA62E2DBD
-:10268000A4EC16DD9FFA947D307D70FFBD4BD97FA1
-:102690006FE1FBEF1C99B5EF12BBBAF17BC6EC3AC8
-:1026A000C42F97FD5E998F6DB8DF2AF271C87E0B3B
-:1026B00003EBC5F913252B8374B5C0C7BF3A25DCDE
-:1026C0008F7CC436E7D2F8F4B2FC0CFEDE5AC15857
-:1026D000A651C613FE4B70195966CE209C54635602
-:1026E000C1291E9BAAFEC80649559EE6CB51956797
-:1026F00034DB5570564BB1AAFEA836870ACEF59743
-:10270000ABEAE7ED75AAE031ED15AAFA633B5CAAE6
-:10271000F2C2AE1A55F9B81E8F0A9ED0DBA0AAFFEE
-:1027200077A77DAAF2497DCDAAF2299FB5A8E05BE3
-:10273000FBDB54F56FBFEA579597B07F56954F3541
-:10274000EE57C1D3CCAFABEABF80FB16F0CF1DB6BE
-:102750006E55FE0CE9B8EABB3B734EAAE017E47570
-:10276000F62D0E27BE682DE7FBD16CFB07AA765825
-:10277000E768BEFE613C6F7BCF1F0B514E6ED7F4F6
-:10278000A721DD4A5A7322F27166F1DC4340662CC0
-:10279000DBB1AA14C55B4EF95387301DEDDC5F8AAF
-:1027A0006C925F71F210A605AE8BA5D01CB3D74416
-:1027B0001FC6B4C85338D58AA834CC3D8CE944DF51
-:1027C000AAA928575F785C3F1AF9282A46A14F0723
-:1027D000D1677D8286F8B97EB1C98FF2C732C52430
-:1027E000329013961F5AD6B1024C8B9A316DF61A5D
-:1027F000995F0FFA809751BAC96B66FE6C2067AF7C
-:102800008DE0FA93F795A7433B23AB4433AA99E6AF
-:10281000518F2548D0BEF5E5969C5D76C6D6EDB0C5
-:10282000CFD7E542FF199EC53BA2014E638E05300E
-:102830007F1698233699B1253BDF76FAF287C29747
-:10284000339D4D2417C4F65CD4FF947637967E6E84
-:10285000D79821DFF74BE71198F7ADF1E1F41DC2EE
-:1028600025995FA75D470BB60BF99EF6107CFC4CD3
-:102870001ADF7F97A4737D0A8784EB66E5CBC6AC2D
-:10288000A0A78C80B9DC3AA9E10CEAF0A2D927A074
-:102890007C62D7E07B902B89582983E0DBC3014E13
-:1028A0004058626C7F96EBC7D8AFD5C5D8D900FA2F
-:1028B00049A851C35B619ECF660EE2A35BAAF18972
-:1028C0003006DD8F9D763BF4B3AD0AC60BF0563D66
-:1028D000D737947AA3348CF6F72FD3F87ECEAECDCB
-:1028E000B7A39EF4A53C9EE7BCFD8B3ECE447BEB9C
-:1028F0002AA589351EC105F2CD5AE9B4FBA09EAECA
-:1029000011E62384DEF28B3491BED71D7E4490A065
-:10291000DEA76912C189957E1A77520DB41B80BF5C
-:102920004DF40966C8B73DE613103F9BD96967F0BF
-:102930001D335A88FED7C83C616BF8CBA28F410F7C
-:10294000D3799D76ACA7BB13E8331F27D46366B851
-:102950004EC9E347B010EBA3A4863E0D73DC409F45
-:102960008F4A7DD443FBC5DD26290BE8FB85C5A630
-:102970008A1D21DAFB549E9F0D31EAFE2D5A3E1F1F
-:102980008ADCBE6CE6EBA8F0F19A68A692E36B5283
-:10299000C65B6F84AFB5CDC85C01F86E857ECCD0C8
-:1029A000BEE1AB55661C3FE8D04EEA4FE4F264C787
-:1029B0008F72C86E0A5EC721F408943FA208E9A38B
-:1029C000CFDF087C68A8D2DB516FB2FE4393807BD7
-:1029D00073226B1150BE5853CA7A44DCD74457AEA9
-:1029E00033843E7933BA54D64FD99F83D74B773D42
-:1029F000E3FD129CEF7FD531D4C7561F8F8F710531
-:102A0000D0534C3AA7CB62D6A245FE98CCDA29BD6A
-:102A100085F5527A1BEBA7D4C1CC22A6A5CC4E6972
-:102A20001973523A9D79282D672D94CE64ED94CE7A
-:102A300062BD94823D43A99399C9EE9A07FB37A6DC
-:102A40000B9893D2EF310FA599E99C7E2B580BC1BF
-:102A500077B3764A3B80EF243DFA018C9476829CD2
-:102A6000C3F44D9073987679252665A31F2087D2ED
-:102A7000235E3BA5C7BCC594F6781D54EF6D6F3936
-:102A8000A5EF789D949EF05650DAEB7551BD53DE5C
-:102A90001A4ADFF57A287DCFDB40E969AF8FD2DFB4
-:102AA000799B291DA5077EC6F9CDE92B447D3EF50E
-:102AB00023BD4302F9EC91E5D26187E699DCF1B8D8
-:102AC0006E1A66403A285B2320FD5973340E3FA4EA
-:102AD0009B72560BF742BAE104D7DF0CD648D20FEF
-:102AE000AD6DF58204ED76087DDA0858CBE9E9A9E9
-:102AF000738D209F4B3AD9BA083BC2194F1981EE0A
-:102B000076E83CFD3BA0BC64A734D7087BD6E4C87C
-:102B100053FFB18FC3543EE9086B34033C2B3DFB9C
-:102B2000A93881E381C2EF7B3B73E6AECD443C25FF
-:102B3000C2F3C534302C51BF7EC444FA7561DBD971
-:102B4000420DC0931A4C45681706D4EB42BA1FAE2B
-:102B50005E70B9F2DDB65596469C870D9F805A0E81
-:102B600059A9197D85ABF3D5ED6ABE5EFF4C7B8319
-:102B7000FE03EB0937686F7F96A3327DC2FF7E3A72
-:102B80000FA66FDDF58FF66BC80F648EC1FD74570D
-:102B9000349733FDA09FEE04BC77C5C8F0C64C1A2D
-:102BA00017CA435CB70D9BD2FD3E80778539571F0E
-:102BB000C7F27FD4D87742D1AE70D7A65C8233C932
-:102BC0003FB121C69313938FFA3CDF975A931F0DA1
-:102BD0009302F8BF399DCBAFADB75CE9DD81764498
-:102BE000B38665C1773B9B976FCC81767EBC19F429
-:102BF000078047DC5ABD310BCAD3376A266A65198C
-:102C00008778FC7873F59E4DA85F258F8EC98676F0
-:102C1000336479991ADB57B806E8BC55AFB6A79567
-:102C2000F49F647EA98666CE826C4D95EDF41D3AC4
-:102C30005611B8DFFD4CC6EF57593CD5DDCEFD57D8
-:102C40008691E1FE2760FC2523B9BFC3B2CE48FEC2
-:102C50000E4BF27F9DBC03CA2DDB347654E9446BE6
-:102C6000ED5A1DEAFB8B593BF2E30E817FEF4BE1FE
-:102C70007A21280AE97303ECF2ADDED38B3203FC30
-:102C800084B60A9F80F67BC9C85AA10FF79FE40754
-:102C900005B4FB2D152EC11589F68187CACF65B9FC
-:102CA0007E920EF8D92AE1FB40FD92B912705DA127
-:102CB000DF8A76D2F35851607FA7B3F83CAC073B6C
-:102CC00099F4D5757AC22B78BE4E65971EC0F695DD
-:102CD000750C2EFF7E06B7AB773D015D201F4CE2E1
-:102CE00076F389DD89A43FCE690D77A0FD74E2A952
-:102CF000D165046F99EC403DF2C4EEC9D3319DB368
-:102D00006526D53B21B01EB487E76CB95BC4FCD403
-:102D10000CC00BDB3BA3277A9CB3E541F9FB47CB07
-:102D2000B0BC58E3FB09DA91C58DFB22D04E9E1C46
-:102D3000F94A12A627347DF5DDD0FF5D66F62BDC5F
-:102D40009E9D1BE3FEB11CFE31F7A9741DEAD7BF9F
-:102D50004B4FA7F59CCF1CC4075083ECBA5BF6F62B
-:102D60001E064D8ADDD6DE3F15CC5CE6E8301FC17D
-:102D7000B4B4CB5E86D357D6E33C82E9F45E4F19F8
-:102D8000AA2FE5A75B8E60BA24D7F53B9C9F17FF5F
-:102D9000E17BAFBC08F0C8C7EBCDA807653ED137D3
-:102DA0006327F9EB740CF9216B92A7458B046C74C3
-:102DB000C6A07C78F6695183FBB921AD250C61C3AF
-:102DC0007DE91AB40B7745B7D4D0B8B3C219CEE3B6
-:102DD000DBB00F215D64453B63909F802F691D3EF2
-:102DE00093E9D310ED3147637E18CF1FA817CEE1CA
-:102DF000F303F55AC204EA274620FB13D406DCBFCE
-:102E00006DF2FEDDC63C09381FD648CF0EF4EB64E8
-:102E10009570FE67919C2EB07AD344FA849CCD962F
-:102E200016CF9DB80E5697E8EB0BA43BD80607F4D7
-:102E300091748219DAD75B050E839C21BCF0877EE2
-:102E40000C8BC9427A8D82BFB502DA0BD033701C6D
-:102E5000F34C83DF2974179BC1C73542A6BFAC650D
-:102E6000BC3D05DFB80C2E9F016F4983F868657C77
-:102E7000601C9A007C02EAD1F806F066761BD20547
-:102E8000487A81A74C1203C75FAD7184A15D647A53
-:102E9000F5FBE84F8942390278FE53F72423F269A3
-:102EA000F0387232D208DF46D087516F9FE9E2FCDA
-:102EB000DB58E911C83E4218C79F2C3AD01F68352D
-:102EC000AD167401E3B526F37D7A66A5A71BE5CAA6
-:102ED000CCE2083BD2F79DAC7D9D99F3F7914CC0B5
-:102EE0006F141BF899D8C441BDF0474FBF7B1297B0
-:102EF0003499B597E4E2FEF9F8FDB370FDB63E3AB9
-:102F0000B307F14FCC79AA3B061A745E94D77D19AA
-:102F1000F7EBA46C133F0E1C479207E040BF448DB3
-:102F2000BA1CE841052B7465131AA271BFD144E4A1
-:102F3000CF9C817A4A9486E43BC829614148FD339D
-:102F400088AEE4F957D6E7AE8C4C5A37AB89AF035D
-:102F5000EBB71B1746CA8355D609FA6D04361F0115
-:102F600074DF58A6F50B68D762FD28ACCFE29D91BF
-:102F700043D769874E9A3903E5F4C31AF36E367462
-:102F80005E81DC7E4B7AEDC371540EF9A291FC7D1B
-:102F900001F86A43C1EAF5B859FD6DAC6BEE8CB42B
-:102FA000A1F989C90B66E23E9B58CB68FD83CB47EC
-:102FB0003DA65E57B237C7A3FF88F9BBBEC17ACE24
-:102FC0004CDE5586FA7CF0BA2A74971A1B7A5F1089
-:102FD00033395FA646D84F95935E21929EE04C11FF
-:102FE000E303EDA20D197C1FBAFD3513ED43EC236D
-:102FF000A31FB75C7B57EF93B9B00EA5573468AEEB
-:10300000B0A3EF1CFAE14C48A7FDEADDD5FF0AF5B5
-:10301000A67D651A87F96FB0BE19E810F1F5809D9D
-:1030200001F0DA2FF6B4A0A3A4B192D971DF55FA5A
-:10303000D923F7F30B9DDF49F23557643B490E82E4
-:10304000651E402F0069897E78197356B690DD6839
-:10305000CDCC07598D6EBDF625B45FFE49CFD0EFBC
-:1030600038AF42D295C0F8E7554ABA65E8C7175954
-:1030700039EA11F32BEC943FBFD2CEF38D3C7F4164
-:103080008583F217543A78BE09F2613E1656F87BF2
-:10309000BDD0EE42538CA4413F78A593975F355045
-:1030A000F93B600F6402C98787F949DEB77CA6E166
-:1030B000F1124FB85F005C0D91453D12CEDF7D1AD5
-:1030C0007B162486149199017EB6C2E9D742F9F3A2
-:1030D000CC9F8013F946F56A6736E4BF912C9A714C
-:1030E0007C6F38C06EC6F9AB1569DEE907F01B3599
-:1030F000C914CFD821FBAD7D2B8CE467055D87FC1F
-:10310000AC6C45A2ACC7F0F26DCBCD7ED4C7400EFF
-:10311000D23AF6DF27921E00F2F0ED1CD48B5ECA85
-:10312000B4874948B76A7EB3542F2FA1F62A99195C
-:10313000EDF25995BCBDC697347E0DEA55A679339C
-:10314000910E1AF7323BDAAFCF569F2A8B45789B08
-:10315000DDCEE5875A2E34566F392EE1783C1A734E
-:1031600016D5E77EAD464FE92EAD30C8CFB4DED2DE
-:10317000A0FC182A6FEC3DD84E4255A97D13D4B35C
-:10318000C038D18FBD4DCFF37DF7881467B0548B15
-:103190005DE68241FE4E91A7D0827C1845F245C57E
-:1031A0005FA35F52C33F92F914F85DC471F97631A1
-:1031B0003BC9955DEA7A20273528AF52DAD4F96702
-:1031C000B204C52FA59A87E079B67AB8DC0B1EE762
-:1031D000E0B8BAC246D1B8347C5C28D7203FD77457
-:1031E00088F2732B45BB24A1BC6B3F85E31FF5928E
-:1031F000C8BA009E555D3413E969D6660DB94366B9
-:10320000B35E920B371BB7E2DF081E67F0F8366437
-:103210006869DF1CD007D71B491F6C7DC4A4C1B8E7
-:1032200022E85BE1E8573897551A9E09F33022539C
-:10323000D6D7AF6BB93C6934119DEAAC8FE504FA7F
-:103240001F84D1A523B0BEEE7AECBC728A1BE9685C
-:10325000DCC172AC58966393FA607C2AFF73389392
-:1032600002E6F7D6FE18157CFBD54455FD12102E4C
-:1032700081E5538D79AAF269E6712AF80EDB1455BF
-:10328000FD19D254157C67CE9DAAFAB3EDF355F023
-:103290005DC54B54F5E73AEE5595CF2F7F4855BEA7
-:1032A000D0B946052FAAF87B55FDC5AE4655F99213
-:1032B0009A2755E5C1F693929666723FCF569BE7E3
-:1032C000A483E48B4B70460EAD67A914FB03D73D76
-:1032D0002A82EB53C1F51AE5F57841E0FDB1FE48CD
-:1032E0000DF29DE27F63ED912AFF5CD7E4C9C63EF3
-:1032F00013FA72ECEF23DDB213DC1FC5FCFC3BC5F7
-:103300007FD5FD04D483F65647A65B71BF43BFABA0
-:103310004B0FFDF935E4BFB736D70BB40F6EAEE7F0
-:103320007E95AB7AE68A0DC08385F37EE5788E8242
-:1033300027734470FF6018CFDF26FB959E43BF5272
-:1033400036633FB0287E7817B59B50ACF7A17F4617
-:10335000A8F6087A945B2E66364828079753FF979D
-:103360002BEC2358887956D256AF8D39A07D5BBDA2
-:103370006FAD1EC656973969CBB3D0BCCDC3C81F3D
-:10338000F368E6942D6B81E7FF2153A2754910F98C
-:103390003C3F5FF7C6B93DD05F6B95A508E56A7005
-:1033A0007992BBF3E2B11B943FBFF2D50FEEBFD1D0
-:1033B000F7751D679A02CA87F58B56243247001DA0
-:1033C0004886D07EF91FC874E59EAC273FD6335A95
-:1033D000D793C8CF1726FFD7C4BDF0DD79E9CA3D22
-:1033E000A8A743FE0F301FEAD1BC9ECFBC44E729FB
-:1033F00052F340BF47FD3B2C34DD1E94DB17AD95E7
-:10340000FDE8075A1DA997D0CE4F327E467EEA0EC0
-:103410001DB7AB83EDF7E707ECED76B2BFF7CBED69
-:10342000EC9653AD997FCF8C3E265AE4F84088F94C
-:10343000D046B50928AF12ABC54F02F9A23B524F97
-:103440007E048B49F63B986A547E01C56FD01D7986
-:10345000BF80746FE95A417E7AF417607B07E57587
-:1034600009F6172419FFB4E8E3D81BB5CF06F223F9
-:103470008410FD04E1A1F82782FBF1A33E81FBCC7F
-:10348000CA70D22782C77D39B3E450663CF248FF48
-:10349000C93B507E9FD2D17E381CBD8449E1CC1FF0
-:1034A000D07E6F26B7EF23726254F991F644E60F8F
-:1034B000F45FB364F32711320C5BCC487DDFC65157
-:1034C000D8DFDBBCBF133ABB8DF441D8F6D0FE7B0E
-:1034D0004FE6E7EE5C4669AB6C97B7011F63FA9C59
-:1034E000D74CFAD936E03F84B77B254AFDDE1C4A2B
-:1034F000777AED54BECB5B4CF01EAF83E0BDDE723D
-:103500004AF7799D94FF92B782E09F7A5D94B67BEB
-:103510006B28FF15AF87E003DE06825F457D5044D0
-:103520003F7533A56F785BA8BCD3DB46F09B5E3F4D
-:10353000A55DDEBD947FC8DB4EF0116F07C1C7BC2F
-:103540005D04F7787B287DDBDB4BF9EF784F13DCEC
-:103550002B8F93B1E65E2FFA2B5CA284FADDB3AE1B
-:103560006A33EAD7B6651A338AF336976605FA39AD
-:10357000B655F2789F6D9586FC40A087FA519FB3AF
-:103580002D7BFAF8342A5F40E55BB149304AACAB99
-:10359000B8FECA56EAA99E150F02C177DB6A2BFD59
-:1035A0005A805BB2C3A9DCBA4A24BBED798D273AB5
-:1035B0009BEB5D24BFAD3AAE3F28741021FBE9229E
-:1035C000B2444A976573FCA33242EF2319594AFC6F
-:1035D000A4B907C767AB82F121BE55F5468C5F5A87
-:1035E000EF83F149A43FAE3A047824C378117FC039
-:1035F00087FCC26C19D797AD55EB08AFE465F3941F
-:10360000786734DAE96D9EFAB9846FA5487ECD36C5
-:10361000D7A1E8FB504ECAE77CACF1E14E7FFE50EB
-:103620007C3282F0DFC6B8DD900CFAD2FE10E300E7
-:103630008B47A9C7FD788F1943FAF126CB7A62B27E
-:10364000C0F98F3D2C12FF6D67A0F7C177CF817E47
-:10365000E7433950BA6F15FAAB1ECD724DCC023C20
-:103660007E248D3F24021C53CEDB4FAF17F7A01EE4
-:103670000DEB7DAE09F2373EB8D989B671EC6669BB
-:103680002DB25BDBB25713D0FF952CA8D74749CB9F
-:10369000653CB63B787BCFD58BE44FB6AE3A90769F
-:1036A00084F75B86FD268EFA7D18BA613216481AB9
-:1036B0001419C955E245EC2FECA1CDE5D85FFC66A5
-:1036C00087D25F21F6F775E769E4E365565708BCD2
-:1036D0008693273793238BB322E3488E24B1249417
-:1036E00023CFEBB8DCF29DE4FA241D869934B41F95
-:1036F000257EAEC4D383E3E835323D241942C76149
-:10370000570DE8FD3EAAB7DDB1C949E74B303E0B86
-:1037100045AB756C05AEF3EA9270F3DA10F4A0A431
-:103720005B508E01DFDF8B4623B5B3B99CB7A3E1B5
-:10373000EDDCCA56115C6232FB42C86B257D5A6EC5
-:10374000E7812C4EB7490FBEB4F118AEEFDB3A3A21
-:1037500013F49CC6BF11ED04DF092DC9D7446DFBDE
-:103760008E3D017835CBE3794EEFCFB523FF407B1B
-:10377000F92857915FF2C97FC16605CCBBF2DD5ACB
-:10378000D98FFDA36B1BA229BE5CB52E0CF5A33609
-:1037900066247AB0EA3CD18501F46045BA0C411F39
-:1037A000FBB2F44A3CD5543211E3327C5F9E8A72FC
-:1037B00009F03E581D45FBE1D465EFDE3916E05BAC
-:1037C000AE8876D4CB9EABE5E71327FD5143E726C1
-:1037D000DE7C9CDB7DB7FDB7B21EF47B27C8E9B366
-:1037E00068E7417A4B33B377C1BADC526D22FFCD23
-:1037F000AD57C5B381761AB9A4C7A37DC1FD3553B2
-:10380000FAA13C80FE267DA6AE0F33AA453D23A13A
-:103810004F9D6FAB3A70661AF4D356CB3F6EBBF632
-:10382000FE71847DF51AF29300F529F49340FE4D64
-:10383000D19780E716371A19C973EB32A319E541FE
-:10384000B7259CE45FDB6213E9A11B325787A19E79
-:103850006CA8AA8FC674A4DEB7037DA7DDBBFF7D6D
-:103860009E2D81E42D3F7F8184590CFAC0BD7AAE34
-:10387000E4F8FAB64CCB4479A9A1F2C3BBFF7D8B27
-:103880000F7D07AC85F090342C910F7E00BE9BE23B
-:10389000D402DF2F40674E44F874AEAB07E54342D5
-:1038A0009CAF1B8BB69ACE56D2F9E2CA38E2335D92
-:1038B000B587E931BFB2C818C8E70A9FFCB5FCFF5D
-:1038C000B41CE7BB991CB859BB37E3F79FA573BE7F
-:1038D00019CE9E360C234F15FB18CF9A638A6C4B7A
-:1038E000FBEA597D48FDEAF66CCE67C57A7E3E64F8
-:1038F0004EC5F4728AC3F8FA443CC79693CDF9A931
-:10390000CD124971E2B674D6857103DF720DF7F7F7
-:10391000C4F1FFDA2AD3C93FD42A78A27D19783EB0
-:10392000C29586EBD706731409FDB7A672B9CEFC13
-:103930001E33C6ABA19D9A40FCC1DEF3A9E9989164
-:103940003E4CFE0B2DF19EA40FF0B7A35F1CFD179C
-:10395000C1DFDDDAAF866FBFAA864B984E054F35C3
-:10396000AAE16966356CC9E67AFA1D3675FE0C491E
-:103970000D27A71C09D3F073EDA6017FB344F0BB5C
-:1039800099017EA00D9A7601E725A5AF96FCB2AD10
-:10399000A9DCDF935CAFF67324B296B53102F96D02
-:1039A00054F9B6FC5502FA736CD5EA7C9807158C6D
-:1039B000CB8AF4BF24D7959F8D71E9027EEE3A4BF6
-:1039C000EBE9CDC575688B233E4A93CF050DDD1F0E
-:1039D000B7D0B89576900F7C01E345FA0F842FE6B7
-:1039E000BA2667C7733EF005EE97F97D3AE403A562
-:1039F000BFE1F841E1C762396EA29CABB922B7A51D
-:103A00009CABA997CFC775049DC7B9925C46E78167
-:103A1000AEF4AE090FC577C867BE6CCE77986E94CA
-:103A2000CFD720DFF9F49CEF30DFF0D52A6728FDEF
-:103A3000F0BCBCAF3CB437CCFC71C0F856B647AB59
-:103A40006077478239F0BCD343F80F74BA37333A02
-:103A5000475A2B0FE78B33BFDBD308E95B5A970B31
-:103A6000D76765D6593D8F33F5EB51FE9E97F7DF4B
-:103A70000D82DD385AC094DBA58D66BB11FDBDCC2F
-:103A80009FA1F257287E87D52BD2AC3180FF8801C9
-:103A90003F82D34CE74DE333C98F1135D571372BB6
-:103AA000043CF7CC986F04A2DC854E5590C78F6517
-:103AB00097FDD0973C385E03FAAB02CE2319440F32
-:103AC00023B97335954901E7CA5B65FFC5001F9BA4
-:103AD0009697607F3FCC96783C8679D672FF9FDAC6
-:103AE0005F66B86A53B533D87EB2AADF56D92F7253
-:103AF000F3F6D5FE37C3D5F461DACF0E6ADF1CB218
-:103B0000FDC176D57EBCAF111F6F433E18CEFFB509
-:103B10005F96A71B6C9E5EF47FE918D89514070684
-:103B2000FA98886A23FF69C3F979535DB2DA0FA660
-:103B3000637E921FCF47D690FC48603E8ADF59983B
-:103B400087F2D7474DE7F1BB60B9711379C1988708
-:103B5000A1DE00FDA9F2573FC2F7D346C1EE423CB9
-:103B600083C7F3FF8ADDAB891CDF4BFA734AB86465
-:103B7000B881DEDBEA7525E3F71BC23D3518EBFEA5
-:103B80003CBB2E763DE83D1B30C6087C7635BB71CC
-:103B9000BECF84FB24A78FF5711AA227CBDD961D1B
-:103BA000DA007AB2E85D69A8F75A34F2392FFCA13D
-:103BB000BF6CBD65E7A610FD2BFA9B025B2B008F47
-:103BC00000BA6D95F5E681FE9624EED006B4633119
-:103BD000B80AA93FE55CA3D25FD337EB6FABECF734
-:103BE00052FAB3DEA31E9F55EFA1F159E5FD47E957
-:103BF0006F2B8E2F045FDDB43FD98E1EE86FA97A3C
-:103C00007C568387C667D572FFE1407F4DDFACBF2E
-:103C100036F91E934DE6D3E1CEFD370E9CAB761AF6
-:103C200051AEB429FE40797FBB14B4BFAD96F737CF
-:103C3000E5FB4B71E9E4DFBDD433DF186A5FC3FDF8
-:103C40008CC97A2493F54826EB9108CF997AA63E41
-:103C50001EE8B0F0C5B6F922ECE3731E3A333E1508
-:103C6000E0192FF6CF17615F9AF3E2990349F0C983
-:103C7000CB2FBECCCB7F78E64A32949B7CEFCD2F06
-:103C800003382A96EFC70ADE4ABFB78DE27AA3BB94
-:103C9000E173EEBF04F98AFB5663AA87A17FF14264
-:103CA000727FD432A8EF4EE9B72C0F312F4AEA6E5B
-:103CB000384F7E46147928FFE6E1BF40B4CF53EE7B
-:103CC0006794ABEF6744456D22FD2F8CF9CD28EF4B
-:103CD000228C0EBA4FF8D628BE1F2C64F60A6E3717
-:103CE0004859F2390DBACF31BF586ED77CCBCFB11E
-:103CF0007CA1C6B11EEDD9DF4EAA8A47F558391707
-:103D00009737787F72D7F51B9C1F0EBE3F39E7238C
-:103D100081EBC223B8BFA53B57E2F7B902FC86A8E6
-:103D2000F70E379FB5A3B87D3F389F0E3E9F310EEB
-:103D30003E9FE6FEA8B5B0FEEEE87ECB13C49F5DC5
-:103D400021E76BC8BC06CD5FFD28A6D8795AA4B779
-:103D50009BCDB732AFCAF9C14641CAA2FDEA4F793D
-:103D60002AFD8331BB142A8E83F419B8BFEA6D4E45
-:103D700086FE195D9C3D07CF9537FE451BF25CDE44
-:103D80006E793ED64685D3B9CEC6283DD9DBDD5106
-:103D90003319FA9745D3749A97B2A8723A6FA98DDE
-:103DA00065ED688F069F23D78EB89BCE0169AD68FD
-:103DB00041403A702ED961A4F889B9E886E7C8C5B0
-:103DC0009B9D238F99C9CF9147E9257459B445EA42
-:103DD000439E237F6C14DFF7BB713C71883F8C27B7
-:103DE0006D701CA299C7D1313F02F2F56617237F8F
-:103DF000BA3CDEC7E47550EA1BCC1E86F240ABB776
-:103E00004BA8A768C3F93E61B069584E08BFC8F710
-:103E100047E9E8FB4F72CD34AF1A23D7CBE7FC5A02
-:103E200008E94F7A7594E24F0A4D67C3D1C93C0D3A
-:103E30003F47A7F0E102939ECEF72D30D94AD10F2C
-:103E4000B20008EFB39880FAB72DE2F78145BB0DB9
-:103E5000E9E737536EFFF96F18BAF9B97C3E35437D
-:103E600047F7E34E09CC618F197A7ED5E98C9E869F
-:103E70006E9ABB669D5987ECF7E2F2EF15617B867F
-:103E8000E353751689EC9F7746A15CA84E5B1F0F24
-:103E9000F0A2CA421DDDDF94E344EE082EC79FD195
-:103EA000BA4E8EA278D1E751A54847627F2AE2A395
-:103EB000C48902EABD372A9EEACDE1D7C5A0DE1843
-:103EC00094D3677FEF62B41EB6507A12DA4F2C306B
-:103ED0006E23CB07B4A302F3D17E6201EB272C2F14
-:103EE000B6F68590174A9A60DB92520D7C9E90D070
-:103EF00042A992FFAC435BEE0FB1AE57E575FDC62C
-:103F0000764C1B603B71D08E01FBE52ACEDB17D5CA
-:103F1000A72CE36148756517C98EB1E9153E9388F2
-:103F2000BF06611EAF04FB4575DEB0D5EB4BA1FBB0
-:103F3000FEF2386D2BD646A31D03551C489FDBBCF3
-:103F40006D29659983E3C8CE91E9138DB689A817C9
-:103F5000F35F725CCB0CF497249B34743E012653C0
-:103F6000752F616E59F4B4383445DDCC6E92D02E85
-:103F7000EF253D3FE1BA96F820E1F0628671ABA4EF
-:103F8000B87601EF030DF423DF6FAE97E3B9575C0A
-:103F900065348E04EBC0FECEC80E8DF3CD4579742A
-:103FA000E5698E51C28FD5E5C971FCDCC2FDD5E152
-:103FB0007E09E83AA9B6574038010C38F4C5275CA9
-:103FC0006F4C6B4279F25A04F98BB56D99CC07F2BC
-:103FD00027557445E5E03CFBA5FFA6C990070BDF1C
-:103FE000AD7C209CF4B336A16506D925F769582825
-:103FF0003FCF981CEEC728C8E1FC9F606B4DA91EFF
-:1040000087E9D344375F97CF6790B31DF4D9119FE9
-:104010002DFA581CD47B9A75A1E9739BDCEFC07E06
-:1040200021CF5F187319917FB582933B39F7EEDB8F
-:10403000B7CF82CE1346E75536C97A8DD24E444E5D
-:104040003B1546D81D0CCF450A6607DF07CC3E9BC3
-:104050000FD6ABF92B6D487BEBC11C791F496BB2B6
-:1040600061FDB24CBB0DFD94C1F7551AD326DA7031
-:104070007D1A670CD0A931705FE84ECB7E1FCF53FD
-:10408000997A742CF01C5970AAC77321B1372897FC
-:10409000CF97371DE2E7429B4C45BD780EA1C9146E
-:1040A0005744C7FE4CFC9CA952DF643A46F2DE64DA
-:1040B000E7F15613EE0F02A2C7E7A13BED18CD833F
-:1040C000526F5A0E97AB267B17C3FB5BE1763FD549
-:1040D0000B139D3E0DE01F16C7E8FE4F9891F35558
-:1040E00004AC8F3180EF957E6FCBD1D1BC352517D5
-:1040F000F596107E22DE04674DB6221BEDDB38DF1D
-:10410000D06F63B442DF9CAF1F97E75B69A7513E56
-:10411000FF7A4F43CEFCB258F41339D7E460BBA604
-:10412000E546B483B491E36FD8DE8661DB6B5E282D
-:10413000B7F738F28536B2C88CEDE9505E84A0C37B
-:1041400067E476FE57E3ED30B374DF97605A309F33
-:104150002D94DEA3A4468CA38F1BFADD3796BFEB0C
-:10416000D47E2490BF7B71FC2B93CF1E2BA11CEE21
-:104170003FDA2EDB278A9D6191DBDE2EF07BE83E65
-:1041800021DC4EEF36C87687254C3D0F83F741F989
-:104190003A5CAEE0E7E62EC7318A6B04F3F3E577CD
-:1041A0003E8A0EB44F50EF736473BB0453B44B1C80
-:1041B000B29F0D61F41BA09DA2F0FD805FB742FA93
-:1041C000A75B003F03C86F0DB42B247B88BE0DC9CD
-:1041D0007D69C8E7A9F23B0543F6D75C2EA7854762
-:1041E0003F4B43FE2E8BEB4FC0EF82F9FC8547AE71
-:1041F00026E0785E983170CE86E243AB17A7F37B5A
-:10420000D9C7FF1CED0AD1FECDEE7F459DDDB486FA
-:10421000F4C0E55C0FFC5BDF07DBBE8CEB9D1D8211
-:10422000DAEFA4CDE57AE75FE47DCC7A55A4F72DEB
-:10423000CE65B92E201FB60AE6E5287F531FE1E7B9
-:10424000E6563F5EFFD90321F84118EDFA734E8020
-:104250003D5CDCAC273F5AA3297DC48DE21CC3AF73
-:10426000B387CB71797D4B1E35F2F3242EAE175BED
-:104270005CF7D33995E0F323C3D53B24CB3DA5BEF2
-:1042800001DB4779629A47FE804B6823A0BF4D96B9
-:104290007BC17876E264C8F36304B9127568451887
-:1042A000B6AB93EDB1ED8A3FA3A2C8E808F85EB7BC
-:1042B000B8C8581A402F8D8C9FDF0D6EFFCEDC01E1
-:1042C0007D5AA5AFE8709F45DF509CF8A7013943A0
-:1042D0008A65B8CA8E51FA0F3E3F16705E2C8CF379
-:1042E00029B7675AF1DC18E8B76B2B968FC4F96DC4
-:1042F000155D2F58611EFA3F30D039E70F65BEECCF
-:1043000093F972B8F5F3B143A08C31F6043B829770
-:10431000D6804EC68F40FE68CCD494FB438CB35CF1
-:104320001E6708FDFAD6DCAFA75F97E686D0AF51CF
-:104330007F7604C51F0261D49B1D21F4EB1382EC30
-:104340000F90CFED9CD0491D7D300F276E1D616F02
-:1043500094E89E91C35E04F6C38B6732516F9F232E
-:104360000CBCC723DB318C60B02316225E739967C7
-:10437000DF0302C5515AEE48A3EE045C8F9BADA744
-:1043800024FB1137C23A61DCA1F5DAB219A1E20CC3
-:10439000FF38402728BA02EF07C02A04C49586C414
-:1043A000CB82E263184E1938FFAB1D5AFFAE62751F
-:1043B000FC6AE335EEBF30AC60FE27043C1FAA2E3A
-:1043C0009F5FAE0B8ECFA9E25A0B9DBA607C7C88B2
-:1043D0006FB28C6FCAB607290E3E2D45E4FDAC6462
-:1043E00064CF07C7BD0C85BD0E2DEAC3158CF4F74D
-:1043F000603F369E1725FF5E0563CF0974DE5A7D48
-:10440000DFE4E959E7F8FB1C2DE5D88F2D53C350A5
-:104410003F0EBEAFA0C49BF0984CE07D69E5DD2265
-:10442000CB620DE1C77CB753B9E29787FAA6124B6E
-:10443000C0B9EE556CA03EDDA3F2851EF7D6D65965
-:1044400014EF4F1CEF29EC82A2243BA37948AA6603
-:104450006407C03CA8E2FA86945D34CE4B358CC527
-:10446000F238A0AA3C017670A44F18BF2ACE0FE301
-:1044700054C1C176E7CDEC4D434AE60DE5F9CDFCDC
-:104480008D06395EF8466E641CE93B63D818D47714
-:104490002C8B9FA6F5B804EB817E59348442C5036A
-:1044A0003743FB6807BA905FE2D1DFC454EFCA30EC
-:1044B0008748F7C984628EB310EBE4F1E17C46FCD7
-:1044C0006D0807950BF859986C70E0BC1B0C00C385
-:1044D00090053D332640BE56F637AF1598883033E9
-:1044E000DB8DDC4FA8BC6BE3A7776D86EB0774FF11
-:1044F000BE30ECCFC7BF53FA19F28EDB0DBE27FBDF
-:10450000CD1CFC7D19F91D95FE879BFFE1DE6DFB3F
-:10451000C3D4772770BF6732D16BE520BD12BC4C86
-:10452000A647FC1EE5C2BD4AB1AD770CDE373CFBA9
-:1045300070841DFDE003E3F0DDA9E5EFD1FD75ED2D
-:104540000DE0619348BE0F8C4B6EEFAF1D17FD025F
-:10455000E4DA06BC3484E74F2A199D27B0B84ACF65
-:1045600089740E00C6A0921301EF13407B1B0EF15D
-:1045700073AF5BF19D0B71B05FD42BD06EB0554221
-:104580007E083B4849AB19BF1FACE0D5A8073D1AD0
-:10459000E952C3F5E8D9A63E11CF35E9E2FA45E480
-:1045A0001FE7682EC707E8379ED1F90B6D927CCEC6
-:1045B00071A4C4DF4DCBE4FB9BD2CF84D11A59FE4A
-:1045C000F7D2FB47B3234ED54B76C6F2F6C52F4440
-:1045D000FFFCEC11A7EAD3002ED867E170D2A92B1B
-:1045E0006966C6ECFBAC0BD19F3F3BEFD495748062
-:1045F0008BF6D978F9144646CEF87D090BD19F3158
-:1046000061B459D5FE5B38D7F1DF3CD51A3421CFE0
-:1046100063DF365A394FC9E83EADB3F397A7312E61
-:10462000E954F647872E48DF81220BDE23937F7102
-:1046300051140F9D29D3D99DF8EE5214FA2DBB6861
-:104640007E470DFAE99FFE6BFCF482437997CACC52
-:104650002A81FF1B1B982B2C2380EE9943739D9F6F
-:1046600003A6B881828FD2FF10BC6069C59840BC98
-:10467000B6513B0A5E170A0DA48705C7872E08FDB1
-:10468000DBF19C54C4CFD62FC275BA10D99F2A0033
-:104690001C9EB79ED6ED427CFF76C11E00EBF83A19
-:1046A00056EF2BA275FCA3D6513D7A02BEDBC5DFC7
-:1046B0006F6896E3504FC6BB7C689F01DDD1B9326D
-:1046C0005F8A9EFC4865E30547A03FB06E34F7CB98
-:1046D0005C92D3698616CF49A04BF70181AD85FA6C
-:1046E000EE6B97F5A89FCCEE3CA3473DBAEEC01900
-:1046F0003DDE4BAD4318DAA9DBA67784D2FFFE324C
-:104700005AABF2972976D7D194ECF5E877ABAB1694
-:10471000E81EDEEAD7B91F6EF5321C256377DFB2DB
-:104720009FFCB855CEEEF5982E657D47F1DD88C526
-:104730002EADEADCC0929A08553CBECA13AB8297F4
-:10474000B6C0EAC03EBBB42149F51DC35DCF82EFC0
-:10475000280EFED0FEAF90D771B16D732FFABB1645
-:10476000BBD47ACCECCEB5620CE2ED11EC1ACEFEE5
-:10477000127EB7848F10D200BD0AE67D5A07D7A3F8
-:10478000EA2A8C649F54220CF35A59ABF5E39373D5
-:104790004753F454EEEE10A8DC2D97BB6B046E5714
-:1047A000CBF275A98CE3928327A7D175529FA337CB
-:1047B0003300DFA515E5E7881E657D43195785C4DD
-:1047C000F58D0D29EFE9B0DDA5DF17586C1A8D4B7B
-:1047D000A5472DA951C3551E5D909ED5A743F9BD90
-:1047E000B4419DFFF3D1F2BE9EC7F2909FDE182D1B
-:1047F000889F1807E13FA5BC7702EF815DD23A0F91
-:10480000227DD6EABB0A70DFBBA47511AC94437E4F
-:104810001DDFAFB8BEA201CEC3EF1B750E33DEA7FE
-:10482000F5AD14886E97B000BD276DB03EC1DAA11A
-:1048300070BF2277C39CF5E40F3D2898516F281371
-:104840001D22DE836F1CC68F7E51E68313AC2F1FA3
-:10485000F1CA46228575CA9E3F82F699ECB796F951
-:10486000308E943D4E20BFC49D80714311A622C955
-:104870009139B03784419AAD6DAF20F93E566FE65D
-:10488000EF62DA58A0BC70FC331370BE1075B20B27
-:10489000937BE8FDBD396D9B2FA25CCCCC70143DA1
-:1048A00005F83D19C6FB7FF275C1BF16DAA9CB3FEB
-:1048B00046F2D30AE481FDD6D96439DAA1F6CF5A9B
-:1048C00051AE21C1CCCAA77E1394F832D015EDC3E6
-:1048D0005DA5A49F58E57E9F2D94B8DDFCA07C2E9D
-:1048E0008DF9D6E2F9FABED18CF295F41BFBABCA76
-:1048F0000431285E50371AE679A5AD4F75DEE95BC5
-:104900006CBF01E92CB87D18BE2A5E394D7B2D8A1B
-:10491000EE771DCCB0DEE8FE94D6A83EB7A4338770
-:1049200007DDBB53CB9FD9F6A4A07B771941F7EEE7
-:10493000F282EEDDA9EFF92D744E09BA77A7BEE732
-:1049400067B0CD54D50F93E6A9E0889CBB55F523FD
-:10495000EDCBD5E7AE8EFFBC4248C777067D7D2EF6
-:10496000988766E08DE298C17D242F0A2A431A3E7B
-:104970002ECC846973A1A10BE9A43991DBE786E30E
-:104980000FDBBAA01DE388978CE86FFC89E02F4508
-:10499000FBC4289F5319FD1853ED33AF1570BE5259
-:1049A000D2DBF25CB3F3617DF2F74A49FC1DE0DE35
-:1049B000D1B83E467C6C03F9E6557EAF78AC6C47C7
-:1049C00028ED3C5F5832350FBECF7FCC3183E2EC0F
-:1049D0001DFC7EF04E3D8FA7F85EE5E75BF33BFAEA
-:1049E000348E00FE3E99C7F590679CA5141FA9EB75
-:1049F000845D16F9A9EDAC1EEF65D4757647E17EAE
-:104A000056E03CAB47BFC960BEBCCF89FDE168AF93
-:104A1000FFAC3D743C6D6D9E9EF8E3982CD7AB1EA9
-:104A2000D672BB913966E1B971455E57EDE7E3ABEC
-:104A30005AA8E7E760311A1D426E839C3EAB96C3CD
-:104A40000EF57E708B7F3DCA0E90DFAA7A4B174C15
-:104A500027BBB712E436F231C87375797213C917E0
-:104A600090E7AA7C77DE803CCFBF0EDF9D766A425E
-:104A70008EF3708148F378DA3595E6FF199847F49C
-:104A8000A73D3364DEF87CDE6CBE5EC6B50F58B75A
-:104A9000E07ABF2EE0EBF6F230F2FA7D795D770A2C
-:104AA000BD45284CDDCE70A2DB254663099E7B38D0
-:104AB00096F26513C6E1AA7E2ED03DFD7FEB3E6ED9
-:104AC00041FD5FBFFFA805FD61EEF6A316B04D598D
-:104AD000AD4E5A8B7A3CD0851DF59EBA8E2EC27F84
-:104AE00065FBB86ECC5FD921D0FB3DEE0317A7D391
-:104AF00038595F13C60B770E83D78FF2B8FEBE37D7
-:104B00004FE27E3017F489FBFD0183DF2F201D80EB
-:104B10005C42BC5E17F0E535B673A3B122941EF576
-:104B20006FF27C1FD9A867E8AFAF85EF711CC75241
-:104B30008EE98D4847FB05B2B5DDED27174660FBD2
-:104B4000F53A86FA8582DF1729BD1FE2F83FA8D61D
-:104B5000A1A78035566B69BE3FA8D7523BDAFB74DC
-:104B6000042F5EC1CF551CAEFEA82909DAFDA05660
-:104B7000A07B0C53EFFBF3318417AFE0FA5A303DC2
-:104B80002BF41A4C9FC1F43B844E6BBE199D1EC979
-:104B900093EFD5E4B102DCE761DDA759917E1EE118
-:104BA000F7E32BAE1DD6A17F33BDC96C7F02E03188
-:104BB0005AFF7A0BCA89C3BCBCB07687C0E58D7436
-:104BC00037F26152B39EA1BDFB7E1E974BEFE37A95
-:104BD000C5E3D0FA058CAF31B1371DE5529A1C4FB1
-:104BE0007A45C72AF6535C90CB9B31AFD954EF96E8
-:104BF00037E571BD43918340E6AEFDE4976D4FC448
-:104C00007B142FCBE74153E5F6B232FAA7CF85F4F8
-:104C1000AA4C2F67643C14F8B24CFF6CDBCF681FC2
-:104C20009F2DC759663674D179CC3C83EB5394875A
-:104C3000B352DFABC57DAE39FDED7C3A678D3725CC
-:104C400026E2FBC9FC7778D2A7DBD660DC2F379C45
-:104C5000D631ECE053741E382C6BBC35549C434960
-:104C6000DD57257A8FB0EE6A3AA50A3CF7D0397D38
-:104C70001FD90117A7139F5CB5A9DE2DFC54C67B75
-:104C80008CF23E5D27F7F3809C168B8B06EB29F3A5
-:104C9000809E651C6F58D62E5AAF35AB5821A9752A
-:104CA000EC29FECE66ED4901DFBD58A473E84C3017
-:104CB000DFEF8D60251F8BFC1D245736C64D8C748D
-:104CC0002FFB84D74C70AFD746F029AF44E9AD61D4
-:104CD000CE887C6867E1114F16CEDBE1945627DE63
-:104CE00057BCF08E4EA66B33BF2F2ED3DAE54E2D78
-:104CF00033629CEB00E8E3C220FEF75C4DA4FBDDD1
-:104D0000BFC3FEA09F950DBF217967AFB9381DEDD8
-:104D1000A2C2DA334D08BB1BFE3C1DF5890F61FFB3
-:104D200020BD1EF47B9B8072E424BDD35D79358663
-:104D3000DA7959D33F1DF9CBF7A640F76F3EECB8AF
-:104D4000A8B7F2FD89DC73782F1CFDF2B3F2A3B98A
-:104D50001CE92CD4D0FA3A24D53BEBDDA3FF2B0A77
-:104D6000D7C3D820FD7A0A7EDFA365C8BF9B4AFB64
-:104D7000A3CC21E4EF69F4DF65F371B0ECA1E51594
-:104D80007A5F169E93AC90E938B8BC3C7FC03FA1D7
-:104D900073CAEFEB0801FEA12AC6DF3F05BBA72BB4
-:104DA0001CF8B8AA732AF967AA3CC20DFD33C3D117
-:104DB000E1D74DEB18F7CF2830DA8D817E4DB41B4B
-:104DC00099AA7F1F7F072B25F386F774DC7D891452
-:104DD000CFAF6B6614EF5A797534A5E75FDF2021FA
-:104DE000FF18C3FB5BE97E6BB686EC8C953EB5FE87
-:104DF00033A580CB8529057CDE5CF9602FE5B00109
-:104E00007B09ECA27BF3B95D147588A9ECA5E07C65
-:104E1000B2978CF23D1D1013AE5742E07D474169B9
-:104E20000D7E97CA5A88CED93BFCFE72F038D7E483
-:104E3000733E55F87A31F235D26F07E7EBE076E74B
-:104E40001594AC413EDA384C7CAB5CE6FB956D8C3E
-:104E5000E6CBDD1643F3F4056B7396025D7E0178B5
-:104E6000E03DD20B4E6744347C7FC1E58CC0F33DFE
-:104E70008A1CA86B0BA7EF3666CE8BC573A3CD48F3
-:104E8000F7D0DEF98EA9469CE77BDA38FF29FD7D55
-:104E9000D8B53816F96982AE5F6F87F2E4CE335128
-:104EA000A8F74D787D7E2CF2E17078FEFD1819CFC1
-:104EB00086C4121E9787BD70A26C4F007EEE27BA83
-:104EC000E89DFA871A18D16FF7ABFF56877C7CBE36
-:104ED00033C28CFBE6170723E8BDCA0B6F1AE83D07
-:104EE0009A5AF97DD52F747D7348BF7C5D4BF722AC
-:104EF000DD6FFE472BF2A3FB55039D3B7CA873C3DC
-:104F000045DCF76A3B679CC377566B5FFADBF2C3FD
-:104F1000CA8654D28B14F83FBC4627BEF37B5EE4AE
-:104F200072E2A18E7F217DF7A16B970BF07CCA17EF
-:104F300007FFC744946BEEB72E4F4479E6FEC5E5F4
-:104F40008958EE7E2DC2134A5FB95EC0FD3ECA7E0F
-:104F500099F6AEA8F20FAD90E9236D5D0BBD073D4C
-:104F6000E1E4027BE0BB0F13B2344EAC3FE1B76526
-:104F7000B1F7057CB7AE57A438E3F8936511D501B6
-:104F800074794F814EF12F7E23BF0E93DFC719F046
-:104F9000E3F4F2777F36F68AFC7DA31A81EEA183D3
-:104FA000FE32E45E1AADFF8A587ADF8889CE3BC7AD
-:104FB0008C47388BDE05623EE3D1CC003D6971AF92
-:104FC000A6CB007454D169E822FDBE573C43B0AC77
-:104FD0003FDD73F1D3C83421847F26E7D43494E3D2
-:104FE000C17E1AF84522DE8ABE55E971A520FEC1B0
-:104FF000FE9BA51577907F28D87F93D62B6A668F66
-:10500000C7F7DFE93A2F8CF76923F28BA287E2FA20
-:105010001D08C1FF6BC67039A6F0D5BA5E1EFF5DD4
-:10502000D75B6ACC84B456E6AB03B09DFAA0FD759D
-:105030009DF377A31F61DDB545116360BED6BD3B0F
-:105040008F3D81FC6F2E3566E177D7EE302ECC1F79
-:10505000A497E0FEA68CE1F272404F1866DFCB9772
-:10506000F1FA5BED7F3963E4F36CFF87EF7F6087D4
-:105070008F1DC3EDF025DC4FC2EDF0E07D4391C7FD
-:105080004ABB2E799D87CA63FE7748C05E2679ECBD
-:105090001A2351BDE4CEB9B16447BFBB2056320DCF
-:1050A0006D3F43B46B62F287B6AFE8716E9FE3A8C1
-:1050B00011ED1C8796FB491708F4BE99A2F7B99D1C
-:1050C00002E9E3EE4A9D1FEB2978F52EE07ED585B7
-:1050D0000E9D3F4C18D40F15FD71A0DC2E50B9A2C7
-:1050E0004F2A7A63AF93FB71178CE7E5B786B91641
-:1050F000E17C7DD81546F91326F17CC69C479300C8
-:105100005EF43D8111FFCBFAA442A7C1FAE6A5CE19
-:105110008C1BBED7B34DA64F85CF5283F843D9BF62
-:105120009AF339DDD7E1FE1D8BFBF77FAAF4F2E09D
-:105130007661FF7E08F16F461D12BE1FFF5BD1191D
-:10514000CA3EFF4AD60BFE5E59BFDE232588AF72EA
-:105150004E76B87DB54ED66F862B6FCEFF7AFCBCEF
-:10516000471EDFDF8A9F778EF9BF439F1DD00BF567
-:10517000A1C7794741C94FC6C0BC866B3D749E73B9
-:10518000B8F7CD1E95F555B07355747C3445AF41D5
-:10519000BBC85DC3FD03CDD1D2AFC97E39AEA5F783
-:1051A000571E92EF733E78D54C692DEAC9902ED9DF
-:1051B0007B92DED95D52A3C6BF197DB7F8FDAA3434
-:1051C0008AEB57B132F22B5575469BF1BC7F737C4D
-:1051D000FB31E42BDF6EADB43BB0FEC6D1727D2354
-:1051E000F7B7D544D3DF8F61417A40952758DF5711
-:1051F000EB0553643FD170FAC12FBAC3B85CE9D153
-:10520000129FD739F9DF55D07772B9E06E0823BF06
-:1052100009DA6B88D7670D821FDF3D5F29D7FB4C0A
-:10522000EC25FF13C5D3A0CAB9CEA72C0EB2DFD48C
-:10523000F1A395BB7E4B7233388E1473408E0B0DE9
-:10524000C48D26D2799095604FE29FBC724BD25D9F
-:1052500038FF801FF393DC71A8FC30977A3E22FB65
-:1052600073C9EB3CFE33247ED43C93C78FF0DD95AD
-:10527000107EC8A5238F1DC5BFA374B3B8515DC7E9
-:1052800049BA473244FF08D23BAE8D51FB19478AD9
-:10529000DC8F3BB25330A37F6AA43C8F7FB7319C35
-:1052A000F4EAE97FA88E4579A0ACD3F9B97C5ECF4A
-:1052B0007F70A504BF9BF807D11C06E3FAC507F56C
-:1052C000BF49E2B06494F0BBFA08B463CEFF6175E5
-:1052D00004CEEB2F20C5BF2FF1DA6931A43FD22BCA
-:1052E000CB2DD80FA30BC8BF2CFBA545D80F230788
-:1052F000FD39C1DF6D97BF6B063385FC98AFF3F8BE
-:105300007E73826B26C1CFA633FE1EA683FCCEFF22
-:1053100002748DFEA23C182CC69F7F1ACED661BCAB
-:10532000A839DEF536F1D1B31A09F908BEA73893CA
-:105330006FBF44FB234E19C6730AF4FC5D46EA0CAA
-:10534000D66BB4BC8E0960C7623C09B05980F1E6E7
-:105350003C39AE5310CE446CFF499D6B13BE97F998
-:1053600064B7685F4B4C608FC577BF83E34B828324
-:10537000C7C5953893121F1F2ECE24603F059CEEA3
-:10538000F8B91587807173259EC4BEE7A4205763C2
-:10539000B187CEF73F53C848AE7F8B719E25F92168
-:1053A000E24835C86324CFD571C54D39AF109DFE95
-:1053B000B5F1C43D63D8B71CFFE2F3138CF7F8E8EE
-:1053C0004B16B2B7BEFAEF51B4CF765EA6FDF042EF
-:1053D000BF41BE8FD0C7FDEC9D3AF22F5C00BB2DC4
-:1053E0003E609F3D9ACFDB3DD43995E8FF406F5931
-:1053F00004D63F2FE76F7C77C1FCD94897BD22BD0B
-:10540000078BE7E3D00E3BD02B4E40BDE55B5C97AE
-:10541000EF8F09B12EC6F0D0EF4CE4CB7C945FC087
-:10542000E963EA07DCFE72D7F3388A59960BEE720D
-:105430003DC9C163291641F19F5B43C5595EEFA782
-:105440007DA36A8540F71CBE719CA5A35BDEB78275
-:10545000FCD3E5D3496E0EE7B70E889BABCAB715F0
-:105460000C9C8723FF75548199C61DE3292CC1B379
-:1054700087CAF8BFC575B8736C083AFB16DB5F695D
-:10548000FF6EDB9F92F7DDB6BFE63B6E7F6DDE778A
-:105490001BE7DEF11DE37FF53B6EFFCC773C3FAFB2
-:1054A000E5FFFF73000370709C3FF85C4070BCDF49
-:1054B00070FC3E1F966D1036F777416A8C7AB542C4
-:1054C00000512D46EFA27708664DE271B08D65461A
-:1054D000FF0E61F07C80325F4B0BB91D61CEBFE8DF
-:1054E0008B85794E75F496C5A29F6C127F87FD82DD
-:1054F000FCCE2A13CDF4CE18D44CC0FBF1CD61A163
-:10550000E3AA61727BC3ED23CF1796DC31369EFE92
-:105510006C43C8FB1D2FC8FE47730723BF2413A588
-:105520008479D4AF9480FAD088233C3FAA8B397613
-:10553000105E52DA3CB207A534C46F8B1CEF8D9914
-:10554000999D86FEE818D00B311EF814C605298EE9
-:1055500065A67A4A7F1F8CE5FD6DD13181EE5BE552
-:10556000F2F34CACF9A02A9EF78EAEEBE36502C5D0
-:10557000F39623FEBFD274E5EF4C938918E637FF0C
-:105580008099E28C2726BD487F775689EFAD31F3AD
-:105590002A87D16E063CD61C1C47F4BBE4D0A4F786
-:1055A000F1E93377A6680F754F51F1179C96FD1DF1
-:1055B0008ABF40896BFD5EF6937C88FE17BA1F2276
-:1055C00051EA1DABF9B6F727EFD810FCBF45E0FE56
-:1055D00021DFAFB87F689CDE9E11786E72B33CAF5E
-:1055E000CBBA78DC42F1F7EC93C733EE116D97013B
-:1055F000F6D2714D63F4B8CF8F6B4A09C7B4C0E1DE
-:10560000D7E07DF0C5D5FB35CAFA85A2A3D6B1B2E5
-:105610001FA3A79FE27AFF1214E7FF602C3FBF3061
-:10562000AF90E3F101D82408AFC9121B517D1C7162
-:105630008B591B2A9E54057631E2B9AC99E3ADCC67
-:105640007755973415FB3973B4BF09D3A29AB4A91F
-:10565000E46FAFBDD884FA9BFBDAE563B793BF4C28
-:105660002FA13D714F9FDAEFB60AA3A5F18427FD64
-:105670009D5ADF0C91ECE3713344A29F98AA30B29B
-:105680005F63744C6B42782ED78B8ACAE3A622CC18
-:105690001644933E58D42345DF973FE8078B995132
-:1056A0001F8FF374B3F8AAE24FBB35CCF11AAEE703
-:1056B0005F1B5F5DF9CEBB74AE541997322F4A9CC5
-:1056C00074B8F8AA72CEC15D7E45752EC32DF64F13
-:1056D00047FFE3B88367F4F2394B33FE1D6125FEC3
-:1056E0003AEEF58B147755E2AC6ECF45D2ABE13B89
-:1056F0003D7E3F0E963F2106DF17E2F1D757F19E20
-:10570000941EEFFF99E9BED41BF2FDC54E183FE68B
-:10571000BFE9CDA1B4CB6BA7F490B7985277E7451A
-:105720008AD77E38561DEF53E27997B4CE3363D5CE
-:10573000E723090E8EF769C3B9BFC6DDA3A3BF97E0
-:10574000E17EC748F2BBA47319DDEBFAF2A46B2427
-:10575000E25D87F1B600BA38EFB087E13B61E79DC3
-:10576000F6308CB38DEB3EA7C7F32F7562AF1EFDED
-:10577000618071121E4D741FB8C8CFF77696D0DFC6
-:10578000E3BA695CACE36F1317FB9FE541012100AD
-:10579000800000001F8B08000000000000FFB5170C
-:1057A0005D4C5367F47CB7B7E596DF0B2A3F227256
-:1057B000C16298A2DCC240A7311674AC135C8A4A5D
-:1057C0000201B5662E92092DD9CCC2CBD23A8901FD
-:1057D000DDC3B2B864F3A92683E8B687FA93AD6E49
-:1057E000550B0B84252EE2C39C71C9520D3333BA7D
-:1057F0008162DCD85CD839DFBDB5BDD8BD2CDAA458
-:10580000393D3FDF39DFF9FF0A003007DAE756B9E3
-:1058100006E74CF8A5CFC6FF0F3DA44F8CE3DDBDD6
-:105820004BEB2617C4F1BB3EC9356903F85D9CCE2E
-:10583000942B00F687CE5A1C041FCFAC7621FCEDCA
-:10584000C2DFB54A3A80F7D24C2D20EEFD66A6960F
-:10585000F8DEAFD27A02E94FDB7BD78E975E047019
-:1058600096416B10F9552EC17182E0B8C3FA4645D6
-:105870005C6EC02538E9FC80AD349BE8C75CA5D9D7
-:105880007B13F4F539456700E939AFDAAC89F409DF
-:10589000BB19A006E90C5CC124F66B5581DBDF7FE8
-:1058A000D22A4F4A7A1CF1DB1DCC36E0DE50813C17
-:1058B000591EC7F7D38F02FC6E6622D40274E9B971
-:1058C000B86472D7AAA8AF3B3F6A8152A24C5B5C16
-:1058D000AB305EDF4BFDAC1260F8FCBEE268051732
-:1058E000952017A04D3F37E0DC5B9CB110C07F3D99
-:1058F00005CA98461391DF4A3F148E2A22DA69A717
-:105900005F78E5B6FCF7274CAB11BACDFE68C2BD97
-:10591000DA9D82C39AC9ED2E6DCE207931CE2F212A
-:10592000A5D34BB7AD22CC5128E413F417C25A02C9
-:10593000D2A8AD366EEF06047EB0A17C9B5388A43E
-:10594000A09DD6704A04506F955304DF8B087BCD21
-:105950008112467CF126E72B6F3611BF4FAE2A0429
-:10596000F4E3E7CB16794109BFDF6434218EAAF353
-:10597000D3FE523CAF763195DC6AEF34F2F19341BD
-:105980007EEED6E3B23334FC7221F75F36019ECB54
-:105990001D03388E7677F618CFED6E75DE61743F95
-:1059A000F8A07F33CA814D900789DE6B94A33A3B00
-:1059B0008DF11F007026D64337D5410D41C6E1E772
-:1059C000E813D54515062A58113F37BF7E4674F9AE
-:1059D000F9FA62F00CF117517D560DD828BF4D022F
-:1059E0009401E1F5922D419F5F15B99E0F6501FC71
-:1059F00028D717DE3EC8307E7D8F5F915A506E4AA1
-:105A0000AE97CAD2E3B8F732D6531640F5F06C031E
-:105A1000C5FB589881154D79F3F1BE28577DB16EBD
-:105A20009CAD4EBCA7E6DF31CCF9443AD5819A0D46
-:105A30009A5F2061BCFC17586010ED55353D1C493C
-:105A4000A3F8B9B2D53285ECD80EA523EE6D126B52
-:105A500018E12E3C40F80E1690F0E7F62B9D5B0007
-:105A6000ED54B7D8AF52DC5B3ACCAA1588DEDA40E9
-:105A7000F46B5950372912FFC47BA9C42F67AA556C
-:105A800021BEB39EF88D5F4444AAE7AD14A56578A6
-:105A9000B7CB288D7DB3C1EA0E501F5537A311F443
-:105AA0006F47873540FEB5849BCD90CEEB41A0BEBD
-:105AB0007B5BCFEDB7458F32A3489F095767915F56
-:105AC0000BCCD316156135EA2EC84178E1BE05B07E
-:105AD0001FBCE2B44546B9733E4CAC05E04B9FC4D5
-:105AE00061C827836339C0D7BE7C0EC33E85D32FE0
-:105AF000FACA398CF8540E477C6B35A8CA3C9E957F
-:105B0000E1FB02DD27A75970259B6F7EBD3E62F940
-:105B1000AA0BEF29A67B3EBAEA2E9693C8C7205A55
-:105B20002C14D66AFDC930675EE7C306B2E381E88C
-:105B3000613AA760BE610D46218430EFBFEB6FAACA
-:105B4000529B6FD902B893F167F4FA048722D03CD4
-:105B50007A4BD2FA7F78C55F3C9E5248B9B21EF3A9
-:105B6000E61937410AD28FD46B737FBE9EEB184F74
-:105B7000C0B8DDC078129CCF6FB5F8CB281FAD74CC
-:105B80008F24E7A7F4FAC40A30BB32B49C32BC4F6E
-:105B9000476C0E6020B2308F1D211649C53EDF19BB
-:105BA000DE744724D8C3E096717E3CD77DD8E646A4
-:105BB000A589F3B6338D26F9135C4AD5E22C593406
-:105BC000D86FD5F65A935D8B730C6EB56B75719467
-:105BD0009A05EBFBE879163888FDE7A918BB4E73E8
-:105BE0002CCF01D08BC3C7939F1E31D13C0F99EFAF
-:105BF0003D99E3D81F798A0C1D3994370C26F6415C
-:105C0000817E0724C06D9463911C616E25CA2D1995
-:105C10009F257D9FD8156E2F77579001BA5004FEAF
-:105C200083345F462D50771AED779D637090FA3B71
-:105C3000E00205F7FDE8F11B874F21DD738EC9B443
-:105C40008EBA8357F99EEF162778FF78C2772DBC5E
-:105C50001E8337357A88390249F23A40FB1DED6ED2
-:105C6000467F686E741F300552D06EC339ADAFBD2C
-:105C70000E4B40417CACE81D91F09DE719E4D11C2E
-:105C8000532616A511FF80190225DCAFA6BA84FDA4
-:105C9000845F85FC8EEDCFD8FEF1C0F45821D56B22
-:105CA0002753230ADF3FB78CFB052F921BDF2FED15
-:105CB000A16133CD1BDC4306B9DD8E863B343F71D9
-:105CC000CF18E94B0EDFE7F98028AF53DC2F067EB3
-:105CD0008D3D63E16D2C095809157338CF3655CACF
-:105CE0003CDFAD6EC6DC181F497075919F7091C97D
-:105CF000346FE7C7ABD1AEF541A39F412FE677C81C
-:105D0000A2D5C7D03A16F0A37C23A294F7A18B7B2F
-:105D1000FC0CFD1CAA62AA40F120218CC7163D3E56
-:105D20002F801F6E4BFCA9706CAE1AE035AC612B56
-:105D3000D653A35E0F00016EA7F9E3D408BD238EEE
-:105D40009A83F92A7F97F8F97D6755E0FCD414E827
-:105D500049D6AF6BEC75B36A0DC93DF3F7D32E7B13
-:105D600092F7D347F876223B7BED4C24BF30BE2B15
-:105D7000A9BFEF155DCB1C41F481C9B58FCE755914
-:105D800022ABA9BE1F98DC1C8FF191EEA1FD828B86
-:105D9000EF16F591008CCF8723E567CC949776A218
-:105DA000C7EE5B1297E3B8E969FCA10ACFDAEFA16D
-:105DB000CA9AA7FD7E86FA17ABCF577F6EB2BC1D7D
-:105DC000A2F997A47E7ED2E71FC01299F7CB933831
-:105DD00083B68764E0753CAAEFF57EA6FC487BC8D5
-:105DE000FF9D190695F85CEDCFD0F47FA6EB8BC133
-:105DF000511DF69B35B9F9F627F439FC8BC9718A28
-:105E0000EEBDF2A4004A82DFAB82A9A024F85D199E
-:105E1000CA31E0F6C862837CF578A9815F33B1C2EC
-:105E2000C05F73BDCA80BF145D67905FFF6BBD012B
-:105E3000DF30BDC520BFF1CF6D063CD6BF7558B968
-:105E400089E73649AF1BE40A3B8D7E15F518FD2A1C
-:105E5000EE35FA15D35BE237FAB7ACDFE85F4EF602
-:105E6000835C85DEA1FFFC9149FB60203CC3F334D9
-:105E7000359D02133447C4A8B61FC266BE17A6F0EC
-:105E8000FFE2A2843C2CA7D73FDA19092FB3D2B97D
-:105E90000F9D362BBDDB2E510D603EFE05D7762EB5
-:105EA00017E00E00000000000000000000000000ED
-:105EB0001F8B08000000000000FFE3E36660F8515C
-:105EC0000FC1D3B81818367221F84301B7334368AD
-:105ED0003E16060601207EC7C8C0F09E91043338E6
-:105EE00010EC7E20BB0A88277150CF7D43112FE52F
-:105EF000A19F5D5FA0763D1518787F83B083100366
-:105F0000839B300383B40884BF5F0455DE5108C10E
-:105F10007E2E41995D9F81FA018DEBBB318003009C
-:105F200000000000000000001F8B080000000000BF
-:105F300000FFE57D0B7C54D5B5F73E731E33939976
-:105F40004C260F4242004F08202A842140088838FE
-:105F50000990068D9A080888CA000142483211A9A2
-:105F6000975E6D672214D16A1B2D6DA397DA0141EC
-:105F7000A3450D18E840031D4C41BC5A8D0A4A5BED
-:105F8000B541313C0A4978E8C5D65BEF5E6BEF332B
-:105F900099736642A2B6DFFDBEDF177FFE36FBECCB
-:105FA00073F65E7BADFF5A7BEDB51F2359C613D345
-:105FB00015847C057FD71372482484F4EB4E3B0B89
-:105FC000683A8E107F8E39B0552024B4EFEFED245F
-:105FD0008590B34DB355732621FBC79843D7D3F2B1
-:105FE000B381FC8099964FDD79C421D17CD54E5187
-:105FF0008272D33E2B7EDFB1510840DE6B6EFDF125
-:10600000B534DFB553249B69D5246437915442DA03
-:106010002D84FDA9F1985F6A65D9AA4DFBEF82F640
-:10602000CA836662A5DFB737896EC8AFDC2A040869
-:106030006DAF6AF783CA005ADFB280D06855697EB7
-:10604000EB638A1A4FC803FBFEEC68B31372DA677E
-:1060500021AA82FD286F1C494845607BE100FA7D3A
-:10606000C536C165A2F5576C3CD701F45534C9C398
-:10607000445ADF8A061B5147B0B6BF22D05ECB0719
-:10608000D8DE4E7928B457FEE53D0A11A19FB21B18
-:10609000BEABA27440BFB5764FFBEAB13D8D9F55B4
-:1060A000CFD1F6E87BD52F0A2EE862B58978808EAD
-:1060B0008EDDD6B94FDBA17FB5CAF0F8C87E2CDCE7
-:1060C00005FDA8086C520AED40DF2665E9C8EEFA26
-:1060D0005634FC879EBEFAACFE9E8872637ADA471D
-:1060E000593ABC3B5F4188BB91D64BA480523AAA37
-:1060F000FBF907422221E3A17E91A896EEFAA9E4DA
-:106100001107FE23F49F940FFEBDF181AD99DD725E
-:106110005BE9049975CBEDBC93CB51EACA8DAC5FBA
-:106120004B7F0CF2A0F4D4F99C983EEE4BC37483E1
-:106130004F45BEFDDC3702D37A9F0B9F3FE9CBC3AF
-:1061400074A3CF8DE953BE224C03BE127C6FB36F94
-:106150002EA65B7C1E7CFE8CAF1CD3065F0D3E7FA3
-:10616000DEB71AD36D3E3F3E7FD1B71ED3465F1DCB
-:10617000A63B405E346DF205F0BD5DBE064C83BEAD
-:10618000467CBEC717C4F411CE47C764922F513E58
-:1061900038DCC449C54E928ADDF932CD2795B07CF2
-:1061A000EA1DFE7C85E6533D344FF932A032946FF0
-:1061B000A6F90135AC7CF0FDA4C042F383FDAC7CB4
-:1061C000C823EE022BCD0FA963E5C337FA0BE268B3
-:1061D0007E7880955FBD2D5460A3F9AB1B5979760D
-:1061E00033996AA7F9EC10CBE7BCE19E1A4FF3395B
-:1061F000AD2C9FFB817FAA83E673DBD8F793CE0497
-:1062000044D51E2D871DB2BA9850596DF4CF704BEE
-:1062100013695E51EF212ECA1FFFAD6E299DF24317
-:10622000766379C83F1FCB9B143796BFE32FC3FC1F
-:106230002ED983E5C7FD552CAF78B0FC73FFBD9810
-:106240000FCA7E2CB7D4FA585EF163F980DAF5589C
-:10625000FF1E3980E5236B1FC3F23D4A00CB1F5F51
-:10626000FBA47B1ACDAF113C3F073CD2B49C640128
-:106270009E1AD34A289ED609642EE0F707003A8A70
-:10628000CB75E90AEAE18E3FE43E0DFA8B7F299057
-:106290005FFACCC399F8FDAFB01E99D623F65E4FD6
-:1062A000CE9B79BA7A72DE2CD7EA6980F7D658FB92
-:1062B00056CF8E3727E9E979B342AB673BD213DF7C
-:1062C000B77EE5BC35594FCF5B955A3D7B909EC458
-:1062D000BED1D37444CF9FA62361FEB4203DFDFA06
-:1062E00046CFB8F7F4FC19F75E983F6F603DE97D43
-:1062F000ABA7E93D3D7F9ADE0BF3E708F66B50DF75
-:10630000FA35EE7D3D7FC6BD1FE6CF47484F66DFBD
-:10631000EAD9F5A19E3FBB3E0CF3E704D633AC6F40
-:10632000FDCAFD48CF9FDC8FC2FCE9C27AAEEA5BB2
-:106330003DBB3ED2F367D74761FE7C81F58CEA5BBB
-:10634000BF72FFA2E74FEE5FC2FC310950CF98BE8B
-:10635000D113FC54CF9FE0A761FED8B09EF17DA37E
-:1063600027AF5DCF9FBCF6307F520490FBC4BED5F3
-:10637000136CD7F327D81EE6CF20ACE7BABEF52BB7
-:10638000EF849E3F7927C2FC198EFDCAA77A0FF4CD
-:10639000105A4F7CCFF5EC39ABE7CF9EB361FE8C42
-:1063A000C67AA6D37AB27AAF6752879E3F933AC233
-:1063B000FCC9C37A66F4AD9E3D1D7AFEECE908F394
-:1063C000271FF97353DFFA35A953CF9F499D8C3F9F
-:1063D000630FD74C75D0723A16BA44FAC9B567DC68
-:1063E0006E81E64527CB8B4E1701BF44D4FC0DD2FE
-:1063F000EA16E9F7F66D89390F9348BFA3A014FA9E
-:10640000154FBDB148BF23212F4EE7E724BA93743F
-:10641000F9E4A201BAF7FB950CD195F79F7BB5AED5
-:106420003CDD93A3CB67944FD2BD3FA8A64097BF56
-:1064300062F50DBAF733FDB7EAF259EB6FD7BD3FFE
-:10644000AC6E91AEFCCAFA0A5DF9558195BAFC357D
-:106450000DFFAE7B7F54E303BAF2D1C18775E563CC
-:10646000428FEBF2630F3DA97B7F7CEB665DF98485
-:10647000A3CFEBCA27B6EDD0E5AF3DB9C7E0E7D96A
-:106480009DEDD7F0BC08B827CCEF4F57D0DF0BC538
-:106490002B985706D8D18FDF1FBF543D4EE5ABBCBC
-:1064A000B2584DA1F20599123AAEE70F28BFB28D4E
-:1064B0003EBF7792E74A277D7EAFE219ED8CE19FE0
-:1064C000523C08240D52D504A9B1FC4199E1B120F8
-:1064D000E3CBE1C7E8F75E53D7F0449AEF2FE6D756
-:1064E000035E9E124C88D33891D4C07B716682F3D0
-:1064F000820733739FF647E075FD20AA874277BD78
-:10650000EB654F1AF8199B6BDFF6831FB26E10ED27
-:10651000D700429E16DE0EF987D2EF072D4DF3D03D
-:10652000FACC0AF5D323DB5768FB23B1FD0668FFDD
-:10653000C51EDA370FC9D3B56F195CAE6BDFA2D0B9
-:10654000F69DD41FA8FD236F9F0A6112212F0B7F98
-:10655000C4F6CD83CBB1FD07153A5F896C3F2EDCC5
-:106560007E10F4771FB43F3E46FF874CD2F77F7012
-:1065700085BEFF0AEBFF2BB5C778FB71D8FF16E18C
-:1065800018EBFFE00AD67F33AB37DCBE23CCFF43EA
-:10659000D0FF377BEA7FD6647DFFAFA8D4F7DFCC8E
-:1065A000DA7FA7F6146FDF8EEDBF2B9C62FDBFA2D2
-:1065B00012DB57CC1E17E047C988AB09D0F6C9409B
-:1065C0006A98FA035C683B908E48A2A026E4516169
-:1065D00008D2716F1CC3DBE771146F686FFCF89C05
-:1065E00004A865CBA5F32E8EF515DBF215B04B583C
-:1065F0004EE72B4B38A9654111F14D369803C3285E
-:10660000BD1D41D10FF9B20DD705C0FE79CD644152
-:10661000097C2791103CFFF467A33647F6CB982EF0
-:10662000A993DBDB22F42D3C8F2A20236A287DD31B
-:106630000104E3BBF31FD37910A1F38B0FE83C8374
-:1066400050487E22B3F63EA2F325C8B7D1F9129482
-:1066500013528BDFD1EA0EA751FA4B38FD1F4B4C7A
-:106660005F3FBE4308F8A97E7EFEBD31384F5DB066
-:10667000DA4699DE4DC7427FB22E4FFBE5073975EA
-:10668000ED3607360BC85F15F8558AAA49C8E2F5FA
-:106690001994D7DDEFBF4FC59E4E597F1B71CBFDBF
-:1066A000E9FB77AE12063969BBB3DDE61C364EB89E
-:1066B000334CA8D724C39447C8AD4D63645A03290B
-:1066C00075CB1FB745B43BB3489F9F5DA2CF77C83A
-:1066D0006ED944E9EA2815C8265AEF9CB9FA72AD7A
-:1066E0001DBB2989C999B75792CAE89B03690E3C1B
-:1066F00076A29CE73AD9B71A3DDEC5329DC2823CEC
-:10670000FDFD08C8D59F82EFDDEE64FD36D23B5714
-:10671000B6B84B683FE72E1403806F23FD7FDA671E
-:10672000739BB269BAFEA7323145F7C748FF3C8F69
-:10673000B13F8D328CC3F3CB8DCF196EDAB9FC3FEC
-:10674000067CD0F404E083D27F9CE3A3DBAE327CF2
-:1067500078CD9E9B010F5D4F8804E5CAF1721BC77F
-:10676000CB923A3D2E08F1C820C76573859C8723DC
-:10677000703087E36059BD1E377712BF9C1E432ED1
-:10678000F3366CFA619A1ADDBF0F396EE63FB21F1D
-:10679000F913DD4F26A7BBB89CEEACD197DFC6E559
-:1067A0007A2797EBDCFAC70E50F3416E570332E8B5
-:1067B000BBF73E4D9E6D3A797AB83C8D74DEC5E5E7
-:1067C00079D7F7983C8DF4B67179B6D55F90C990BA
-:1067D000687A8DF42D581DD51F05E4B9D01F5B9E36
-:1067E000DE607EF2F188E7558D33928F47E8D98AD3
-:1067F00086525D7E79609EEEFD65F50B75E54BEA90
-:1068000096EBCA17AFBF5B975FE8FF9EEEFD05AB47
-:106810006B75E577D63CA42B9F5FFE982E3FCFF398
-:1068200084EEFD397337E9CA67973CA72B9F59B4AB
-:106830005D972F75EFD6BD6FDA77D52D80CF378E68
-:106840008804FC89CF5C27302EF8994B76C13BC772
-:106850007D2AE2BADD3702D3933E17E2FEB42F0F52
-:10686000D38E608B1DC6093A2E2E2589D4CC9B6E03
-:10687000AE5D3F10C66982E3E916D3AC5AFF6442AD
-:106880007E6D5291DFC5F50A098D254480C186D3FE
-:10689000D1254694B7F5525E4F0D7F727479715BC6
-:1068A000ECE7DEC7175EE18C1177E9D65392017EE3
-:1068B0004F27F7BB8DE5950229897C4EC803A8D7E1
-:1068C000E7F8B85BA930FDAFDC915E401C900F0D7E
-:1068D000AFB95C7B8D14E4FD0127593A3D5E567FCC
-:1068E0008DCEBE1388CAF603BC8DD53D5FD170AD89
-:1068F000EEBB33FB45A4BB1A6CC54418164B5E3780
-:10690000811D0EB50C9E390AE874BF6182712AD8C8
-:106910000FFDC233BEA2E4E312C8AF04D393BEB9E5
-:1069200098B6FB3C981EF79563FAB1AF06D336DFF5
-:106930006A4C3FF2F931FDC0B71ED33FF9EA303D52
-:10694000EAABC7F43D5F00D3C3BE064CDFF135624E
-:10695000DAEA0B62DAE17363AAE95D6FB83BC9C793
-:10696000E1D380BF1838EB786055EDFAC9DD383BCC
-:106970006FBAAFD63FB09BCFC5F5668E87541D1E4C
-:10698000BE806033E2AC97F27A99E3B0A7EF6397E9
-:106990007B37FF6BF036DEC4FCCC6F8AB76E3C658C
-:1069A00018F094D51B9EFA89E3BBF134DEE4647ED3
-:1069B0000FC7D38FA01F31E61505E084F48BF0D705
-:1069C000DC3616A7E6EB09D45365716ADEF61AFACF
-:1069D0006E2BFA758111306E9C1FF1B7E110873F65
-:1069E0007FD44C277D3DF7CF88939EF9EEC6F9CD35
-:1069F000D2001DBCC646975BE3185FAD265244E843
-:106A0000B8F6D0B0675C8B46625E2249F07DC05517
-:106A10001A1FA35EEA2B037F7BE3EB9AF8CFB3A1A7
-:106A2000BEF627FF9E0BE97813F397E35A44F4DB95
-:106A300049E86917F0373C2E995D6910DFEE1AA618
-:106A400038D16F08D8F5FCF3D37C6E37FF1EA23C1B
-:106A50006AC571B72E0DF937F4F3E1E97DE05F6F98
-:106A6000F6BD377E2E0A0CF897F0B337FBD89B5D46
-:106A7000246EF5C520ED7FE7BE51390FAB60078767
-:106A8000B0795A0FFCD6D6A58CF47CFF6BE2B833F4
-:106A900055C371EB6042DBF988EBCBF9A62B1340B1
-:106AA0002EB41E9C1F74EDE47E7E2F723D9BA9AF19
-:106AB000CF6BAC2F4121C268DA6EBCA29004426A4F
-:106AC00044CFA322CE6F5C6D7E881BECB3B9D6A8F1
-:106AD000306F3CFD6648851AF5F185F3879E76C0D8
-:106AE0003C6C659AC9793C861CB5B4AA31D3698FD0
-:106AF0009CAF04F5F9F375425123CEE7D48459A332
-:106B0000609C713A8F0F05BB9F86A956CFCA34C5CA
-:106B1000799CDADDD30D59096CFE1760F6645B22AF
-:106B2000DA9BD33E0BBEFFCFA6A7A77A347A0869BB
-:106B3000229F58C09ED3B2AC9EDFEF511FA48B0A98
-:106B4000C43749B3FC39CC37ADF4FFAF8640BD1232
-:106B5000E6B57ABD8DA2DF3C1A9E6FD3B547BF5311
-:106B6000B5B557F8AE67BD9348BB867B2ABF57F9CA
-:106B7000FAF08A06AB53EFC726EAF2DE60BA53E7B3
-:106B8000D7C23FC071AF1124C05F25875FA7645F84
-:106B90000F78DA0CC14398BF08ECBD2A4B9BE25139
-:106BA000515D5A019F8BF234FCAB73FE4CEDD4A9BE
-:106BB000D765027A46BEA454E5F2A920E2CD444C42
-:106BC00034BF98BFBDA86945318C5BA74C6CFE50A3
-:106BD000464A1C303F2E2775B9104F3D4B4C45A0FF
-:106BE0009F67C93B8EB111FA784E54B0D2C5EBF510
-:106BF0007E3C9DDFEBF2CBEAF5F9A5E4D6545807CD
-:106C00005FBA41260101EC86BEFC98E8C47A9791F0
-:106C10009A75306EFF9CC7BB1639899441E9ABFA6F
-:106C2000CD2F7317523A2E896CFCD5D67197273128
-:106C3000FA2B660514377DFF93A6B1B7510B44BFFD
-:106C40000FAC83756D7F29716D25D1F2FBBAF41BF2
-:106C5000E9D5FC81A8F5644E474A83E00EC4B063D1
-:106C60008A24303DE3F6EE6AC9A98B83E4423E22D2
-:106C70000EF28DF194427478DA2C7A064BE3197E89
-:106C8000000F82D4A578BE4DFD6951F55F2DF5FB4F
-:106C900027D63F90D69FABAB3FF79F4AFFD028FA4D
-:106CA0000B62D55FF59B1776F9A93DA978E9670EC8
-:106CB00042C7C953525DAA8BCAB572EB0F1D6E9ABB
-:106CC0009E94FC0EC0EBA98058144BDEABC3F27649
-:106CD000DB0588BBC13F69FDA79FFF11C6233EDFCF
-:106CE0002A3B319ED6600E99A93E56372D2F26D9C4
-:106CF000983FC6F20F9E13211FD4E3AFE2D99FA5A0
-:106D0000C2FE0A8A141E5F0AA13F5BBDE5D3421C86
-:106D10009F4817EA91F13B68FF5212DABF854A4259
-:106D20007439A513E3045ECE176FD38FCE890EF8A6
-:106D3000571BCEDF8DEF9773FF74B9149FD26EA3EC
-:106D4000FF9E4026803DD4F84102CC3F5DF3DC2F0E
-:106D5000B28F517ACE6C79DD2144F049D3A3F38D03
-:106D60008B7FB547EDD9DE76503D8BF483B4F14A85
-:106D70000D72BFBA99A59572C8712DD5FBCA4DB2D7
-:106D8000CB4F1F57BEF0F4334F421CF38F66D73002
-:106D90005AFF8A170EBC3789E6576C97538A5937C2
-:106DA000EC426AB75CBCF4FFD539DD72A878F98093
-:106DB000A28E62CFEF4FEA96C78AEDFB15322A9A70
-:106DC0001F531BF72B6DF61872693C56087EC29A4A
-:106DD000E7FE4B81F8E2A97D02E99F19839F9B0E94
-:106DE000A01F007C4239723985E56678DF4BE502E9
-:106DF000F65A9393B1FC466E4FA03E7524E2F9C556
-:106E00003DB4FDF23F995DD0FFF217EF71403F4E68
-:106E100048350CD7BFFC612AD8AF72D99FEAC49419
-:106E20003D2F7FEABB88B7656F7F3715E349C49D67
-:106E30006EC2B1C79F0EFD5BB27136F66F29F120AD
-:106E4000EECA7F29960468FA99448AB6C7D08B0E99
-:106E5000AE17273653478CF6EF04CC1FC15EBF2315
-:106E6000E2BE2A42EE26A0FFDFE57DA11E02E63F3C
-:106E7000B330391D904C5CAFA8B71989D72D0FB628
-:106E8000827C4E0F72F78775162F91FC9C1FC2579C
-:106E9000B45EF1EDE9FD997C882AE5F2EFE8383F30
-:106EA000159EC3FBADB2DB9AADFB8E7C95D9DDFEA2
-:106EB0002ADE3EA53B0EC6E713A9B1FDD501B2A659
-:106EC000F7749C8EC057847E337DDFF210D36F4DF4
-:106ED000DF03A545507EF130D31FF80EC63F4A5759
-:106EE000A83F96EF9F25A03DA0F3E6587ABD45E662
-:106EF0007AAD2FD77042E996848408BC40FD49C81A
-:106F00007F5C5F59BA817E17612FBDD09E23BA3E48
-:106F10004D6F9771FD3F05FA7F4DB7FE938D4CEF96
-:106F20007BF69FFC2C6E23079E7912F495EAA75FEF
-:106F3000057D954BA0DF7FDDD6F2DEED544FFFDA05
-:106F4000A8E9A9DE7E1AF5B47CC778124B4FFF6A18
-:106F50007791987A4A9FC7D4537B1BE2F8FF94FD40
-:106F6000D4F89728EBF9A7D9C39EF868B4872F4ABD
-:106F70002AF2D3680FE9DF61921B8D3F0D771ADE8D
-:106F80002A7E5D7505D89D302E35DC8571A9E12EF0
-:106F90002A7EABE39FB1FCCF106BA274CDB7D44F68
-:106FA000817984A58BE0BC2B7F9688EBA6968B0419
-:106FB000F5BE80C8B86FF07D53CD78F043A7FCFDD7
-:106FC000B6B3F7527AE713BFCCD6E5EB64F4EBBF68
-:106FD000FCEAABC9B43FB773FECEA7ECBE89CA6367
-:106FE000AE2484E2289DF324E24F4882F8AC403E70
-:106FF0008EA0637EB93E0F7F5352BBEBE9EDFDAF30
-:107000003B0FF9A6E9DB3EB676F52EA443B179290C
-:10701000124FA52057CA3FEF38213004ED529B5440
-:107020001231AF7A9CDB9DB7A7CD1C0FFE4BFE9CA7
-:1070300051090CE783717EEBE5F6EBBC5F4D00BBBD
-:107040007EBE390BE7AFE70F2D8E8FB56FB285E3AC
-:10705000EC005F57E9B40B7522C57D27E942FFC5F7
-:107060006FB792AD31D6FDBE2F9BF8E483CB8DFE7A
-:1070700089546E73390EE7D14F137222E436EBA6B2
-:107080005392235A0EF0F771C43CEBDBF217700DEC
-:10709000FC6DB1B61596C488D7FD84F36FCA2B5F1B
-:1070A000E0FED569CDF912F0719A5DD4C5391ED4D0
-:1070B000F475241909744D7965F9A3E3298EBD8708
-:1070C0004417EC57F5369F533C31E6BB467E42FDF4
-:1070D000E0471E909DC8AF2372C912E0EB91D956CC
-:1070E00002EB96EF2AAEAA58744E37B378C83C52DA
-:1070F000F2D938E1FF3EFEE6CF890F15507E9CB7EE
-:10710000B3FDC0D1F8637A7FDE29046A05C0A1C847
-:10711000F2294200E26485C4F3E86401F5FDFA480F
-:10712000FB951F2C7D01F6D554370B4E132DAF96D2
-:10713000DA14C0B137B85D02FFFC4695B831DE20E5
-:10714000D58C9A1511D73A204BC8AF96BFDD7E2754
-:10715000F0F7C22C3301BADC23CF3960DCBFD03C5E
-:1071600016F5A0A77EFDC147A64C93A01E82F8305D
-:10717000E2A130C5A6CBCF9E4A06BAA8DCA698DB12
-:10718000EE71C590DF3285E1ACCFF6CDF2FF997D8F
-:107190009B4CED1BC3B51C69DF462B51F6AD7F2C14
-:1071A000FBB6B256ED0FB858B937AB3FC875E56BB3
-:1071B0004BFAC5B26FAFFAD8FCFD35BE0FBB7320DA
-:1071C000B56FA323ECDB406ADF62C46DD315CDFF3E
-:1071D000ECC5BE59FE77F4EF55B06F31FA3B52D192
-:1071E000DBB7A2E65AB46F450345DD7EA82C85CFF8
-:1071F000E77AB46F0B7F361BF3B2CB16033FC05751
-:10720000B06FAF713B07ED809D5BA438B1FDBEDA76
-:10721000B9D2BEDAB9FF253E6B766EE520769E23A5
-:107220001A87CCCEADCC64766EE55E66E7560E630B
-:1072300076CE68DF0AA2EC1BFBBE7A04FD1EE78B4C
-:1072400099BFB8839617CF955D16FA7EB1AA9D5F58
-:10725000A8191F69EF162912F239CADEB9CEE13931
-:1072600090DEECDD5B60EF86A21D1B0A7A64C4C76A
-:107270000D436DBAFD7247BE68FFF54BA02F7F101E
-:10728000719EFDBE89CD8BF67DD13E16F46E37A77B
-:10729000E75185C9B3C3E7477B3A7524D3F7AA43BF
-:1072A00071384E543709ACBFF70B0115C681BF5D6D
-:1072B000C2F9F29D7BD97C798E99F183FC9BC8CE73
-:1072C0005D50162C8CC0C3DC4B1518D79C2B110BB2
-:1072D000F8AF0B0EDD700AFCD60597D6A3BFBB0036
-:1072E0009EC3BE89ED6DEB3268BB772E1770DEA1B1
-:1072F000EDEF9817B6977A3F767E73EC7D1A533888
-:107300003D53EE1302B02FA7B77D102F72FD9B23C4
-:10731000B621BFC85B62CCF8A4F65E984F2EC69724
-:10732000AA55CC6F0EF389F24D15A2F944255DBC28
-:1073300030B59B2F77EEA4FD4DE9B9BF1ADFA2F758
-:10734000E1B8713EB380BFD7131F343E47F59FF3BA
-:107350009DFAA9B89FC7C88F46CDCE5C4346815ED3
-:10736000BE6FF23C3A1E70F49F942F94CEDBE60D74
-:10737000D39DE7D9C5F97293E7D8B45415F8486A94
-:107380000067B7976F3F904AFB778B3B330742E626
-:10739000B3FFA67820FED062ED423BA8E130CDCC11
-:1073A00070F8578EC323039CD370BC090A4ED4AF28
-:1073B00090C1CEF17D645ECA67D05F6F908F4F142D
-:1073C0009FA09F85DA780572A1FFBCA999C9C55B0A
-:1073D00023A05C6E265D0781EFD529822B44AB2A62
-:1073E0000C6EFF21ECB77AD54A9F839E970BAECDEA
-:1073F0008C1DF6F4D498389662E1183709468C9BB8
-:107400000BE0BD24D8B768C6F6EFFC1EB347463F75
-:10741000658AB9F508D033E5DF64B2091E06E87F56
-:10742000113830FA31517AF035F7FDA472FBFD2A9C
-:10743000C8C10EFCEE52C01FF286D8F8A3957B257A
-:10744000751AF24D9343908E2FE3981C60A9DFC804
-:10745000E75BB43CE01FDE6F1664F87E06954F32A2
-:107460002D9A6AFAE2A08677B31ACD2F8827A4470F
-:10747000D80DB06F91EB96D5C1B7914F37ACA2EE56
-:10748000991ACD274D3E60072FC7AF28FD09EE8F13
-:10749000B97FEA9BEA4F9A59AF3FFBAC5DAF8F864D
-:1074A00038DA5E01ED0A694ED4C50FF2CC6C5ED6B7
-:1074B00062F520CEBB5E935D9BD568FB7315970B81
-:1074C000CC5722CFEF4D850EC1BAB1D34A3ED1FA87
-:1074D0003D84E12C723C78D5EA41F9F554FF045E15
-:1074E0007F4FFE9896FF0EB407FB16557D7BC6F1C5
-:1074F000488B27F5D6AF6966663FBE69BFB476BED6
-:10750000EEBA8397B462FC4D5B7FD82C7A7E2EC393
-:10751000FCB848D0AD7350CA71FDF29F50FF58E5DA
-:1075200032F543FC2844F9FCEAB6A7315E7DF6F952
-:10753000633783FEACF8AD482C549F3AB6C5931020
-:10754000DB07A2809F50D124E27A169142B93323FF
-:10755000FC0C42D6307EBC148F76A7628739504C23
-:10756000BFAFD8F54936C4DD3A1E60F6CFFF3CC741
-:10757000A3BF2D1BD6FB2B24B68E6F94CFBD1C9FB3
-:107580006776DBE682FD161AD879D78AC639B23912
-:1075900022CE506596595C7BB70DF759FB9F13704F
-:1075A0009F32D01779CE52DBFF79E63966972B826E
-:1075B0007200CECD56346CEF803878C55133FAAFB7
-:1075C000DE86730AF8A7535F7A01FD236F50D4C596
-:1075D00041A3E28F0D62C80CF1B3A62AB403347F35
-:1075E0000CF38DB1E3F0BDC5C956BCB477979FB21B
-:1075F00070C5CBCF3AF0DC6CEB5607C6211B2E1FB3
-:10760000FF8F8A37363E74D978E3698E8F5F99F59C
-:10761000EB35A42119E39094BEDC9218718B30EE07
-:107620005FF8EC29580F3BB3E3AF4F01BD95FFB8AE
-:10763000F0D47DE08FEDB33A61BCF63E7F04D71302
-:10764000B4EF76733DEF78EE595C87E9F8A3D9057E
-:10765000B575EC3D3118D6233AB67F910A71DB55EA
-:107660007BA7E33C6DD5CEA9FD498C798096026E4F
-:10767000037D580732CAABA5A96530D07996CA1BDD
-:107680005CB670FCB8B18AC5E3551E37DE167BBD0B
-:107690002D2A4EDC34F396EB60FC6E925D2AE943B2
-:1076A000BCF83095E3E83EC86FDB439ABD8F29BF35
-:1076B000B3F00F2AA7F70DF2FBAC69C9AF9E84B2F5
-:1076C000A6E41EE3C5A13EF04D5BCFDB62767F6C86
-:1076D00006BDD9F16B8CCF83DCE85C8374BCF0D938
-:1076E0006088B39C94BBEEC2FD337BCDB82FAA62F9
-:1076F000EFFBA83F1D3BDFC6F532C2D7D53A48F8AD
-:107700008FAD83F0399C774B3C8B3373FE431C5A0F
-:1077100075E0731E6F6638D6E2D03DC59FD32D6CE1
-:107720003F91B6CE58B5E5CF0A31C4F5853C90D32C
-:10773000B1CBAE8B6A7C70021F2644AEA7C48EF319
-:1077400087D7DDB8BC407EE07F85D74B687E20C4FC
-:10775000CF03C2FB24863DE8D8C4D6613AE4D8FB07
-:107760000FB5F595148B414F037D5B57E98DFEAF47
-:10777000CB1F19269BE3A3F974E6CBD8767C824510
-:10778000F876FB612A85A8F57F0BACCF371D5360D7
-:10779000FEA18D635A7FCFF079F299E7453CEFB1B6
-:1077A000AEB105EDB8D15E5413161F34D23B83D36E
-:1077B0005B1D64E3C4991DF1013BADE7CC2BBB110C
-:1077C000CFD5DB8E297E5ADFC1869795B688FD52CC
-:1077D000304E0422E83FF3E2FE6CB67EC4E6E5C616
-:1077E00076E6F076BCCDB1DBF16E3BA76B6785BF6B
-:1077F0005161E7772EDFDE69C93D07EA3BDD2A13D9
-:10780000D8BF7FBA512C0AC4687F9245D6E2F24CA9
-:107810006FE87889E71DE3D9F946314941FF7A5588
-:107820007CDED18414481515E2146B6AD9FED2357A
-:10783000DF77A581BCD724DE86EB6D7506FE3A5353
-:107840009CF910BF704E2B19077035DA9B44B7496D
-:1078500047FFAAF8A2FE701E7F2DF7C788E4C2F387
-:1078600097A2A3B008FA233A4D4E6B8CF505D95E6A
-:10787000423C117C919DFAF392E4CBB12AD4A3ED62
-:10788000A3A9B4B41EC442A71BB70A4B79ECDDFC14
-:10789000594EEC77E7363E4F7013D599CAF683C13F
-:1078A000B8D1B923219B8CC60F899BE2D1C69F0B0F
-:1078B000DBF6EF077BB4D641DC8954CF285755312E
-:1078C0000BCE8D8EB1085980D3736FFE96D66B6D3B
-:1078D0001671FED069D7F685BA1341CF6CE411DC7E
-:1078E000FF0750FE2AB99B4EE3BE4002AFA476DFED
-:1078F0002B315DB4E3BCE7FC46160710C9D5BF9831
-:10790000CCE2702400F4F3F16405A7F33CA4F07E0C
-:107910009982E73A96BDF6726E88303944F22BB9F7
-:10792000487FBEB4DEEAC8867579E277B7C2399976
-:10793000325E5FBF12FDB953AA7E7ED0D3255C4F65
-:10794000FFBAB4F010D8BF32CF52B4EBFDE7EACFA4
-:10795000A51AF75921BDB02F8CEADD9342F4BEABD6
-:10796000F2E6C7D6C17C397AFF151901FBC92A484E
-:107970009C0BCEE7AC68D097EF03BB7915B093D8DA
-:107980002F17EFEB95BF6DC37F3179DC65F9EB0AFB
-:10799000C1FBDBE231AEB2ECB5C5689FCC697AFEC3
-:1079A0005A553D7F6D238C7CD4F339DEA5E79B3699
-:1079B000FFEC89CF0979FAF3BE463E4B84C71B0220
-:1079C0002C0E11B5BF2DB809E936F2D9C8D7760B00
-:1079D0005FF7E27CA57F25965466B281EE74298418
-:1079E0007A61D4A30C7B48807F0F4A09D4E257AE5A
-:1079F00078B4EF69BC3F4219FBCE067A2402BD2E53
-:107A0000D42338D10776DE463E70B65B41589F904E
-:107A1000AFAEE9599EF794FEFED822FAD546C0EFE4
-:107A200068D42B766E378904D664829EBA9C306EF9
-:107A300037FA2C6A9904F79F10B56C28DC7BE2C4F6
-:107A4000F4C77C1F4AE74882FB821B431753C13EA1
-:107A5000FD38A7EB66B07BDE25A404ECE0CD716CAD
-:107A60009EB298A77FB72ADCAE4E7BED7AF8BE595E
-:107A700056E15C7867F356CB30C80745BC7FC49BA2
-:107A8000587715B4DFD12C33BACA2C816110BFD816
-:107A90002B63BB1D6593F17C65D86F6B66FB403A29
-:107AA0009B3F712C8EB0E71DC19F5E05F1AC274C4A
-:107AB000B1F79F0CB79AF8FD35DF70FC6D8CDA7F5B
-:107AC00037DCCAF6C7FD7808ED4775E9793E0E3315
-:107AD0007DB896CBF9F74B6FC0FEEF6C1654184784
-:107AE0000AC53B6E1C45FB39F188C4E3302C2E39A6
-:107AF0008EBFBF9BB8D2801F13AF2302E8F3C43FF1
-:107B000012DCB735AE6629CEAB7EEBA038CF8675DA
-:107B1000528A5BB07367ECE8BF8F6F9574B84C9C6A
-:107B2000E6698179E684A304EDED84A3FAF23C12C0
-:107B300010B19D36FDF36B4FEAF305568E6F074982
-:107B4000057C6FF85244BA3ABB88EB015A6F67D98B
-:107B500000BCEFA6F3229CDAA5E9976251AC717ED6
-:107B600026E081F2EB0985E0F8F2C4523BC6EF5FF4
-:107B7000595A71058CEB9F7FCF7345AC73E011763A
-:107B80002981EDAF722750E229AED70A8CDF75E963
-:107B90002531F6EB6B38D670ADE1397D699C27D67F
-:107BA000BEC40FADCC0F29583A4250605EB64F208C
-:107BB000C0D78E073C973D37E3270F64003DDEE0DA
-:107BC00005F4B32DCD823B969FB1CAEA60F3BE07A0
-:107BD000FCB5B01FEF5EAA94601F7BAE7703CEABFF
-:107BE0006E87A02B7C67A95B88E7709758C866886A
-:107BF000674B75E9B7C603EEA7CE5847E97DB2C417
-:107C000084727E427621FDFE2A4230BEC0E3B50377
-:107C10006F269B22CF23FFC09AFFB095D6FBB0D52D
-:107C2000897249F6B804A0DFF5DFFFE500BDEEBCC0
-:107C30006446390EE0F31FEDBBAD9C4FA3E3DC6B54
-:107C400001FFA43C05F5C3E571A865C9702F01E5E6
-:107C50007B8C7554CD2F4DF250DB46E949B29BF039
-:107C60007E2EE276AB4E6DDF19E1EF45E8030909A0
-:107C700004F6A569F654681642F114FFE32CF610D9
-:107C8000CC3392CA69BF2909566261F5B54A67C209
-:107C9000E7AA719F3BC5652E1C6E22B8AF0D36D288
-:107CA00042FD9A9DD5ECF3DA4482F666ED635260AC
-:107CB0000DAD67A3D46685F849A65B2D80AD444918
-:107CC000928AE7BD0795337DB465FD3231ECAF5044
-:107CD000651FF30F7141ACF5BA8FC3FCF2BC00FC19
-:107CE000CA3ED4F50AB8352E2B6BCF75C082FE790B
-:107CF000D86E703FAC908FBB133F35B1FD02A1EB46
-:107D000071BF9DB68E66B41B540FDE1541AF3E9514
-:107D1000089ECF75D3FF72B52D7711F6838F93B977
-:107D2000C19A16F4DDC4912D80C76B5FC7BB38A222
-:107D3000ECC884373C6B80DE6F6A3F8C781813A2E6
-:107D4000FAC8E53352857B2A9CE13C94B75AF9FC8A
-:107D50008EDB9B94D271FDD1AFE53833F257D36BF4
-:107D6000A3BEE7AC76B598B1D60032C1D80E11BA31
-:107D7000E950B3C01EBD21827FDF994FF142E9BABD
-:107D800017F40EFCF38B8119809B0DCDDFB1827E41
-:107D90007CE3F1A3997E1DB1BFFA27A2A7C3CAF65F
-:107DA000873B800FD5FB2FF2F12384720ECB95EA2F
-:107DB00047643C44C3BD11E79A5EAC810B33B2F01B
-:107DC0007C1C01F98842230AD64C363A81AF9A7F4F
-:107DD000BD26ECCF26E2B99E554ED6DE1A59F3CB1E
-:107DE0005D16E8EFAAF882FE975B17F55EA2F3979F
-:107DF00088F3305EA90BE767DE4B0A09247F0B7E10
-:107E00000569EBB93A7EA5C4C5E05707E8D1F8FF8C
-:107E100027FB936DECCF836A777FAE259EDFB6514B
-:107E2000BB907B4F7D3AC305399C16890BBE5ED94A
-:107E3000937EE751FD06D72D4A9F0D7A3CB199EA12
-:107E4000B1295A8F5D7209DE5BE7DA6B437B67D439
-:107E5000EB8BBC5F5E1BE37B8DE8991107F37153DD
-:107E6000D760C05DB64A928B29B1D94191ADAFB60A
-:107E700026EBC691E8F1DD8F7652F32F35BFD2F8AD
-:107E80005ED8AFE4E38616CF148214FFB4DFF7C7E1
-:107E900079E6015FD738D9FC130E9A82BFFC03AB99
-:107EA000E70EA0CF46FB1007EB1A2342992C5E1277
-:107EB000D2E95B4FFA6533E84F6348C271CC4FC7D4
-:107EC000B16142CFF4F48B4B64F452AB027ECAC072
-:107ED0005CC21AAB26B8AF7B6036BB4766600EBB90
-:107EE000F7F1DFE3D87ACC7D716CDCD0D21F584B30
-:107EF000EE817EC912F19B73BE39DD402AC40FEFBB
-:107F00008F73DF0DFCB014B9B11F194EE21228DED9
-:107F100032A44601F6372455AA028B1B1236EE40D6
-:107F20004AEBCB2856F361DCCAA0B616E22019CD85
-:107F3000B1CFF56C8893BF5DBCAB29EA3CCA8638EB
-:107F4000E66F1F54687F938BD9799470DC86920F0B
-:107F5000FCED88BF0D3BDBF1195B0FF527323E1BB3
-:107F6000E75F2030E897C4F33F5488644DC2F9912D
-:107F7000DF04DF992C383FB2115723D8CF97E2584E
-:107F80005C759DE05A0FF99F485D16B86F47C3FFB7
-:107F90008F27DFEA92E82B8EEBCE67C39C95EAC36E
-:107FA000F320AF8EC9E787AFC51E740D6678738B5B
-:107FB000BAFDEF9ADC82B24E6E56888744DAEB78CF
-:107FC00005E7F71D429C0BE6431DCB0546A760E184
-:107FD000E703247D9C86DB436D1C78272E13E9B7CD
-:107FE00011FF18BC1FCCE2B2003D1AFDE173A4865C
-:107FF000739EC673A06959E1B84D3AEE932D51E0D6
-:108000008E2F72BED986FE97D7C1F4DF8887FE60B7
-:108010003C2E736E92F2AB15E4DB5FAE49047BDB62
-:10802000FFCEE30E90AF910F9D827FCC4158DFFAD7
-:10803000831C739F8896A6A50D28057F342D3D0DC2
-:1080400053ED79BD5D8A19073CCDF5EE1BE3B59E76
-:10805000580CF3C3D3D09FB39E77DE73A3BA776176
-:108060007CBC3E8EF1BB5ED1F8A826809E75E75D94
-:1080700009EC7E924476FF9093C97383CF522A49CC
-:1080800091EFB9D11FE947DC33E68111D82093ADD8
-:10809000886B16BFD1CE655043C7E497C8E8FAB9DC
-:1080A0006F4C29EC9F916DCC2E5DDC301DDB4B2598
-:1080B0000F588753BE2E2D31B920AE7376D19F1C39
-:1080C00070147C51466B2EE0FD88E8916DE331D44D
-:1080D0008DF3B76573954088422AA59E1A2426978A
-:1080E00019B8EEB8D01473FFB3DDC6E6DFCD714E1C
-:1080F0004CD3D20697968D8DCC0F44396978A47AEB
-:10810000985E36AEFB9C30C5470AB46FD4A74E9933
-:108110000461DD40B387299CFF9A3DD6F42105F424
-:108120000CD6014BA87DD4E43984BF9A8AF14AFC6D
-:10813000139A5FFD02E6038EEB0AD0DE51FD5F8FDE
-:10814000FA3282D96F2BD8D3883865E7DEF707C1BA
-:10815000FADF87DFBF100FEB407F91BAE2C17E9E4E
-:10816000BCFFDD783837F4E1FD2C5E7197611E3578
-:10817000C1C6ECFAA3B6926CE8D702DF7FE77A2299
-:10818000704956B3758DE501D1709E5C7F2F4F55B8
-:1081900063B2E19E1E3FD65BC5EFE732CAA192CB28
-:1081A00061F9B64D4A860AED7BDCB67E706E8FA013
-:1081B000BD3CD9148FF3118D9E45DBC6283077FA6C
-:1081C0004BB399AF7FB7CA6C5C7017C37A9687F3CD
-:1081D000CD48E7C17D36AC6FC9CFD8FE9485B4AD2C
-:1081E000D5D4BE7A9AD9790B633F967CA816F6A7A8
-:1081F000C25BF29080F36278FF7E3A4E79563F88F8
-:10820000EB5EC67E1AEFCD319E5FD5E653CBB8FC50
-:10821000CB8807F52FEA5C6B335B9F36C6FFCE1F1A
-:10822000CAB261FF6D3CFE914B26C079E81D87867E
-:10823000245CEE3EE533FC1E26B8571AD2933E82EC
-:1082400069B64D65F76434BF7D2FE0AA3AB81DEFDB
-:1082500019FBBAF6A6AAF99403F6306B7687FA9161
-:10826000AB013FA44CD0F997D59B2E286CBECBF820
-:1082700070077F7E07F4371BF659AB3F9A4CE57CBD
-:1082800047A57C31F21E32BF4D7FEEA6AFFDD5FA79
-:10829000A9F55B2BAFE2FBD18CDF69F8CFE6782C38
-:1082A000DB52BA6E0065D19ABD2706F3F368784EAB
-:1082B00047C397113FCB484961BA108193E647B154
-:1082C0005F9A3CCBEA16F2FEFBD3F8BA5E1AC48F73
-:1082D0007AC38D111F1D72DB60D067233E3A7AB8D6
-:1082E0005FE42736E62794A9EE4288675137769DEA
-:1082F00033C24F3929D51DBC0FF46C0BC379C4F8B8
-:10830000CB9CB9D7651CCF57C6ABFDE13E3D94DB96
-:1083100044D81760F6C37B5A3BED3EB76BA8047C8C
-:108320002FC2F4B4AFC435746877F9D2272E38C0A1
-:108330008FEE1C41308ED311AFA7F7773611E9F9D4
-:108340001D9743A5D4FA8F3F838DDAD28AFB1DDABD
-:10835000BFE471A02FCD45B1FAF927FE1DE1F786E4
-:10836000DDC5F54C9B972CE072BBAB99AD672FDA5E
-:10837000588AF230EED77A43701666D0AA3C8D63E5
-:108380001490BF513E4B5CDFC17D605172228FF073
-:108390007D011EDCA753562F62DCC328BF7CBB9334
-:1083A0009DA3576B701EB7428ABD0E79A5DDF4B54B
-:1083B000FA63ECC7C22601EDA491FE655B6AD70D96
-:1083C00020D07FD6BFE87E8406A25DE2FDD4FA55B8
-:1083D000465C78FF40D4FA50DBF524723FF5F2E6B4
-:1083E000C5B82FBF9AF69FB03812C68534FA357AD1
-:1083F0008DFD2814CFC81688E3AE165C609FA3EFEE
-:108400002773EBEE3F5CD8B07F20C8AF5D62FB66A0
-:10841000DBFD02CE0B3B3F206C7D60BD80EB693DF8
-:10842000CAAF99ED07EA598E350ADCE757B651888D
-:1084300029C765F5F9AEA111766A7960866BA88EB9
-:10844000DE46DC1FB2A2A154F77C809DC793B8FD25
-:10845000EE4DDF484D62CC3893A65F9ABE69FA971D
-:108460006F57D93C470A1CCCC804BBFE18CE4BA89A
-:108470005DBEDACED707E6D157AA9FB8A05B1F58DA
-:1084800092C7E4B3442CC6E73DD957CA079D7D1E69
-:1084900067D7EF7FF8B6FDD1FAA1E985D63FA35E95
-:1084A00018F9AFC5D58C7230F21FE882F9C11B7B79
-:1084B0006D810704D07746A77FAF15E9EC482B7094
-:1084C000C139C83FC00794CEEAF4DB315F239694EC
-:1084D000DA715EC7E74DE3FA163FC8E17ED64EABD0
-:1084E0007B2C3B4754920CB89852DB36D3E2A4F86D
-:1084F0007C647421DC2B3AE5B1B69910FA5EF2C8BF
-:108500009842B85F7ECAD6B6772D2EEAD7D58E2D83
-:1085100084FBE55780DD80F60796DB10573DE58943
-:10852000E7F27995BD3FCE5C329FDDCBCCCA2B29DB
-:108530008F2D743CAB3C3CFCF7A09F95ADC545101E
-:10854000B7A98488371DCFAADC8E902D9B8DE79329
-:10855000E87BDB6C9E5576F0EB2EADC5F1ADF2B04D
-:1085600084FA440EB1B8A844FB6AA5DFAD8DA37EA2
-:108570002FE5EFDA248B0BE6AFF4B91FE6B56B936A
-:10858000DCAA1AF15C931F7C0774AC35B175FBFD56
-:10859000AF0D4F68BBCC78BFDF4726C33CA4C5678F
-:1085A000C1D4589EAF38F17C44BE89C5358CE5BF37
-:1085B000D2EC2C51330017D5871416AFA67FE04FAD
-:1085C0005611A617D5849DEBAA3A4CF01C4BF5A189
-:1085D000423CC702FBFC3FD6E1F05F738EA51B5700
-:1085E0008C4F059230598AC0F534BB559717FB9BC9
-:1085F00046407F8818E78273186286A96607EDBF38
-:1086000078054D293F24A74B84FB5AEAA64E11E179
-:10861000BEA93532DF3F6262E7CCB5F69A387FB447
-:10862000F4B4BD6407C8FDEC5BADB936B67E81F32A
-:1086300061ADBF6B04371160DE7580E0F9809C147A
-:10864000D202FCB311771EE0ED3D7B12E7375B37BA
-:10865000A67F1990BACCA697558AF7571F5984FA66
-:10866000E04A30DD9349F36FD997B17C86E9422621
-:1086700085F0DBF67296BFC6746108CDBF6B5FCE26
-:10868000F2B0C04907B623F68A42FF486887E37D07
-:108690009BFB1AC0B76462F117E91505D753B47D87
-:1086A000216BE9440BF0F81ED84D88A7D416FCDAEC
-:1086B00006F1EA02B70AFB3D36F37B83BE69AAF1F5
-:1086C00055B49970FE0329F0FF43CE4F4D2EA4C937
-:1086D0007D0DEC8B258DEE6B601DEDB4DDD306F6C4
-:1086E00066EC1BAD53C07E37BDF3A75CBC9FFC0A94
-:1086F00056CFD837E89C90F6E7EC6F066D8A5C8F12
-:108700003E6DCFFF14BEA36240FF54509DE40EAAFD
-:10871000876BDC4455B260BEAC9F2F3611669FB6A6
-:10872000D94ACE825CC9C0108E5B45F6924EC86BAA
-:10873000F69CB426F5695F9B92BD5A847139292352
-:10874000787411D8FFDFB17B3D04B71BF773BE14FB
-:10875000BED78CED0FB1C1FE10D07F1749F3A7F241
-:10876000F8178B2F9394DC887930EF07FD7E1AEC95
-:10877000379F6063FB0768BF44B0AB63888AE958E2
-:1087800088676581283D98DF431A8FDE47EB7FDCE1
-:10879000CAE2499606A28B0F66C7B338CB4C078B4B
-:1087A0000FC6C98DB782FF10778E38C17FE8FCA550
-:1087B00022E1FE22C97923AE8F1D3411A0F7593969
-:1087C000E084F599AEAB247533E9AEAF93CB5BABE8
-:1087D000F77145BD0AE272731DCC3F7D369FE07E86
-:1087E000E8AE534A00D64D93322C3591F19F2BF9C8
-:1087F000770F390B32E321FEBC378E40FB13F6C5F1
-:1088000099400EBFDE9663053CBC043CA27C483216
-:108810003BEF86FA922E507A33F139DB272FA9638A
-:1088200012287F27DD6057E1BEA967AD8D37E07E56
-:10883000D0174C78BFEE4B8AAB14F22F9D579D603A
-:108840007F9FCD6C8CC3FEBC60C2FEBC14D775F597
-:108850004A4AF7C323587C4AB21109ECB2642A5041
-:10886000EFA6CF73E3D93C49B3D3CBE399FE3C2EBB
-:10887000103C0F2099F2517FB4FD3A9D5D04F7EB57
-:10888000F49BD52A028EE34AB5B851488478CFE4E8
-:1088900012827EDB64BB8CE772607F309C1B9BC2C4
-:1088A000EDEF940F2A713D814AE030DC7FD962E719
-:1088B000F768F175C5EB394EAE236D22F891D75D9F
-:1088C000222E88075D7F498AE9474EE7F53E23104F
-:1088D0002981BE977F51950077F944EFE74DAF2F7F
-:1088E0003C05E3E0548BE139F889488F1BCFF74F03
-:1088F000771AEE4F8EE7F3D6C16470E43E316D1DFA
-:1089000068BA38F209F4538B1417F065BBDDFD3EED
-:10891000AC7BFA5B6572B938E2333EB69F6FC4A593
-:10892000385CFFA1F8B4032EAEAEAFF35B69BFAF06
-:108930001ECAEA071C825DB9F29729C960E7CDF12A
-:10894000CCDE68A9863BC0973381E1CB39BA5B3F67
-:1089500057C567E27B9ABE01EEA09E3D72607EAC79
-:1089600075658AD75580D7ED7682F3B31FA55BE690
-:10897000829E69EDEC8967F837A6EB6A57EE87753A
-:108980001DFF676CBC9836E0921239DE7FE86438D0
-:10899000F3AA75336FA6FDF3DA655CBF49E5E78B93
-:1089A00022F1921E81170D771D7616EFD1F03375E7
-:1089B000F7BB223C9FFA1921CE4C129E8768F8998A
-:1089C000E267389C72888D13BDE1C7DDE59C06E641
-:1089D000310A3787186E0A283EF0F7B77AC08F1130
-:1089E000374FF58A9B2FF13CFCAABD532FBB6E1865
-:1089F000F4E9F77D1AD389B6D8FB828F727EEF56E1
-:108A0000EA6ECC067B7193899D7F9348C6AD14E7CF
-:108A1000BBE3B47BE56BB220BF5D62F6677BB31945
-:108A2000EDCF76BBC78371D7340B9ECB2692A70DB3
-:108A3000F6F5BB0658D4C8DFD1F82EC761A31C9A3F
-:108A40007802FCEFD798FCF36ECA811BEC487A19C8
-:108A500093C3B893CA2611E2428EFCFD80AF4FE06B
-:108A60004E2DC0C37105EF25AA3EAEA05DFCCDBE64
-:108A7000B70B21BEA9ED1F9EB0E7EDC28291F03E7B
-:108A8000C3D96BDCAE6A793C4A0176D2702FFDC443
-:108A9000F07926FDBDF225809FECEE72E37DEB734D
-:108AA000E084171D776E6D734D07B360BC6F7D4E0C
-:108AB000889D1F9B7DD43D1D4C65D47DEB1C0FB75D
-:108AC00091D65D7162F4FDDF747C3E160FF1FBD729
-:108AD000430AC4C11B959A6BD87CA2260BEC8FA6C7
-:108AE00077F847F9D6F8E108DD7DFFC3F8F8F38899
-:108AF0004B62F738B529B84EF82861DF35F271EBD3
-:108B00002BAEF739AB5E9C0FF6706CB91BD76D5767
-:108B100039457CFE1312B26481BC5C12AE7734CA54
-:108B2000EAD41342F77B442A1961A7E57BFAC58D85
-:108B300085F6EF70784C0EF02BA4AE43F0DD84493F
-:108B40003963C16EDBC7AC4D86714CA39BD255B463
-:108B5000D5DE4D87465727C7C91D8E8526C778F6AF
-:108B60001DD8A1E0B1760B7CAFE1A071EF3926FFF3
-:108B7000083C80FCBBF1202C80BCC6071B4FB5FC19
-:108B80003F1F0FA181209F1EF1007108C7B7C2438C
-:108B900016F055C303F5D7AE02FE68FE5AA3C2F61F
-:108BA0001D6A790D0745F67C7CCFA510DC3F44F6A5
-:108BB00059D9396D4F22AE57BCEC646D747ED83EE6
-:108BC00098BA9864B283F9EBDAEF898C0909E8570F
-:108BD0008EA106E10EF4E306A23D74717E9176410A
-:108BE000807B37716F7906F897A164D08B31E6E20C
-:108BF00010E07F876D4A06F88739B6C95980AF5DA6
-:108C00002356BD0E43D6AE01E52F6F51BBFD27CDD8
-:108C1000EEB5F06AB5F66F7430FB74BD9B9D0F0224
-:108C2000BB1D498766FF412C4087109A63FACA86AC
-:108C3000F6BAB90DEC39D041F9BA5F204DE01FE426
-:108C40009BDC2953C1CFEB179280CECEBD5F0C8643
-:108C5000386571F3AB4781DE626D3DD4A55F0F359A
-:108C6000FAD19ABFA3CD2B347F489BCF82DF04E596
-:108C7000D9FCB9D3CCD6AD26872C786EF9F1F3EABE
-:108C8000556EAEBF12ED4731EFC72DA415E9D2EEF8
-:108C90001DB999F3A3F8109D876643392137513EDA
-:108CA000DCC4EF1DB9C9A5BF57E196BCD8F78E68E3
-:108CB000F5F4F6BE717CB8D6B06EF46DD3433E7653
-:108CC000CFC87FFAD83C77D210D12FC1809A97CEE7
-:108CD000EE6970323E1C52628F57FBB9FE4E32B5C0
-:108CE00065C3B9E5FD7BFE8EE3E32B7BFEFE1EF83C
-:108CF00089134F4904F6B54E3A352E01D7E7F3D222
-:108D0000703D59ABD7FB69938DB0E7881FED77575E
-:108D10000E527ADC0AD067C1F4B7671EFF29D477F8
-:108D2000F1B84422CF4D142A9EA110C72DE4BFBF35
-:108D3000735060FE92567E90FFEEC5F31CB7B021D3
-:108D400042BB8FC41C21E79BF83D199A5C6F3A59CE
-:108D5000744ACA8E960FFCFD33E20B5A5CA199F35C
-:108D60008FB4FC11CFB77CA7E96E09FCF3EFA4899F
-:108D7000C41DD1EE0C95CEE023E21C2F3B0C7E4AA5
-:108D8000CB733FBD998E2BDE3744DC4AE86DDEFEA7
-:108D90007A36E45BC598F78F18F9FB9DE6BBF1FEC8
-:108DA0009121092AD2D35BFB93AEA638190D722705
-:108DB000CCCFCB65F77718E5FBCA9EFF486E1BD971
-:108DC00033BF7B92BF510EBF3D5380EB4EBDC9C335
-:108DD00088DB7DB49F7EDABF10EDA79FFA63AFF802
-:108DE0009C98FFBD2F0DF31A5EBD7B9F4E067F4EF4
-:108DF000C3E9F464869B89BB7F9A4CECDDF232F2C6
-:108E0000ED7307F36BE610D7EC9BE93F770AAE787A
-:108E1000B4177ED20AFBB34A388D730E17A2FF41F6
-:108E2000F87910E33836471C89E7DE7BFDDD9BA12E
-:108E3000F932985BE37805BFC702B8368E53456FA9
-:108E4000D449E0B2154AAB981DE37EBA469751CE9D
-:108E5000474809F6A3273A8D3830D2ABF9E7DAEF65
-:108E6000C0507E4C4FA2F5DDAAE663FFA2C661CEDC
-:108E7000979EC6DF9EFA959CC0E3DE1CFF174E4E00
-:108E80007B0BD8DB93BE19E5662CD7EC47213490D9
-:108E900083A91FFC912109A9A80F859714E2A6E3D5
-:108EA0000C19A83FFF4E8AAF40BCDDE364CF7AC205
-:108EB0005BF52513F12477E34E0E3E6603DCED9659
-:108EC000EA6C101FBDCE5EBA06546FDAA705B3F088
-:108ED0009E8736138190D9F4E6732D1047F01E2536
-:108EE000783EA0A079FF54C0E9EFA5569C47755E77
-:108EF00024E4B1083F33D8BCC6067E5830859D6F48
-:108F00003B984874FB90F72730BC068F9FBFD91D54
-:108F1000A3FC122F9F49DC29D9382EC763FCA3700C
-:108F2000BD09FB3F4D701D4801BF659E80F385CE96
-:108F3000BD130EA4507A3BEE4C443B333DF8E0DDCC
-:108F40004E2A88C6FF1E8BCFBB160A78CF40A1EAF7
-:108F5000C27C615926EEDF98F08FE499C5503E43FC
-:108F6000C6F9CD74B1528278D4D9342107E68B7B0F
-:108F700084B65AF81D5C7F296B8738FDC930FF7CA9
-:108F8000A738790CFE769CAAE587E1EF0312C33C73
-:108F90006DD5CE0BFBCDB47CD56C01F7EF4E77666B
-:108FA000107F047E0AD753798EA5B86CEE5F00B8A7
-:108FB0009E59A43F3738BBC4460291EB168213EF8B
-:108FC000213BC8F7697709FC5E7CAEE73770BCCF00
-:108FD000999BACFBAE94303FD3BB5364F771E4B3C1
-:108FE000DFA1D6F4EB46AE8737F0F9F13C4F868E21
-:108FF0008E6288D288403F5B47BEE5621B0ECFA5DC
-:10900000E20787E7D3F66E1C6198D78A956B111734
-:10901000696C1D6F36EC8213C16EEADFBB254F9F72
-:109020008FA1C797B5139A3D98BD57C475C3D9F999
-:1090300094CF0289F2D3BFAEBD9860721D8078D004
-:10904000AD97DC788F4E94BDF8A0E81BD98BDF502C
-:109050001DCCA37AFD64021F370791416037A68BB0
-:10906000DB7E0A38EAA4E3A639068EB471479BEF8B
-:1090700017523D06DC90336C9D65FAA534DCEFA4F5
-:10908000CDF7C37684FA25AE18FED26F12B274F70C
-:109090007A84ED4A845F22E77E7BBF643AF5479588
-:1090A0001CA06F20F18F457B8671C942D81805F14D
-:1090B000C1B47318E7F14A74FE8AE3F3D3882FB082
-:1090C0007F4252B77E18FD152DCE3CD6A9F9537AB2
-:1090D0009C84E38DB3D87DA51A4E0A819FA0FFB36F
-:1090E000448CEBF4861BADFDDEF012A2F6084C5664
-:1090F0008F78E1FAF775F1F2176D7C194A86F6055B
-:10910000271A3E34BC18C79BFF34C4837A1A6FBA3F
-:109110007A196F0E8C90D1AEF7E6D77CEAE4F3EAC9
-:109120000427A6375C351B7F97682CD811F037F9D8
-:10913000B8158E6BD5339C1C685B24C1FA9117EC73
-:109140004766B71CB478F0FF00C6C481D500800024
-:10915000000000001F8B08000000000000FFBD7C25
-:109160000B7C54D5B9EFB767EF7924334966924940
-:10917000323C841D082121090E21BC1137490811F8
-:10918000A20CA8888FD6011F6020094DADD5536F62
-:10919000332181526C3D58BDD67BF4F43758ED41F4
-:1091A0000D75080183277026A098F0D020F8C07AAA
-:1091B000DA6829451B92185A0F6ACFF57CDFB7F69B
-:1091C0004E662683A5F7DE73879F2ED65E6BAFF5BE
-:1091D000ADEFF95FDF5A9B4AC09F0A50B315209844
-:1091E0000650F9E1864A4806E83B20011403D4966C
-:1091F000C9411BFEB5B4FDB1C745DD0C5689DF5131
-:109200006126C0F5207E0B950EC5E60658E695BC96
-:10921000721680D62EDEBFE19225A862FD7AAFF9E4
-:10922000E31E9BE8FB35FF5F03C800B8517F7F1941
-:10923000FD0FFB2FD3A460185F5D363BBAFF8D97FF
-:10924000CA3F91A6022CD7629EC34F3E93A7F2223B
-:10925000CCBE24AC5744B78F7326B9CFD9F12FE3D6
-:1092600061FCD732C0C5F3656F51F7AFE977EDC840
-:10927000F2483D526601E8ACB77119DB5E6E017FC2
-:10928000C881254D50C4650052010A9DB8981958EF
-:10929000BF64010DF9086313E0F7B93A1D1386DFC7
-:1092A0003F88E30770DC308E1FC8013854EFE4FAC2
-:1092B0006BF51EAE5F93822FA4E37F87BFB0A8B883
-:1092C0009EC5EDDF51FC38DFE24B0A8F3B9BD69306
-:1092D0004F0B8371B49E3FF716FDE30D30DCBFB634
-:1092E000FD338BBFF0F2EBF95BF3E7A7A83C3FCD72
-:1092F000AB150CCFBB44011883EB5C9A1BCD5F63AD
-:109300009E58F9C6CA6FB9FE7EACFC56C4ACC79075
-:109310000FF4A2328D8AC3FF4B26D0A65F5E7E4338
-:10932000F2B1F8B3BD0523DB017EC9721A1E4F9757
-:1093300017742BBE42419719F5BA52B70BD4EF40C0
-:109340000ACAB9B213C28948D8F5E72B3E51A8F42E
-:109350004AF071943E037C6CC85B1E1E7FD125E4ED
-:109360006BDAF0BC8B146477113D1F0B8138EBA8CE
-:10937000A17114EA1F60396CD9615A15C2755C631A
-:10938000813B7D54268A32E094B87D93D3C4E3F6C2
-:10939000FFC56682AB015E3E985902489FD7EA3C02
-:1093A0000613014266E0F7BF4E52B9DFE6240824F7
-:1093B000E0FCA074DBC85E9412805CB43B65B4250D
-:1093C000D88843362B611FD961BF578106B4DB2F84
-:1093D0008DF70E056E0714C9E68F734C8D59F47E18
-:1093E000B87B1EF69B55A4A8DBB08BCBAA7E87DA90
-:1093F000FB0E589DF45EFFFEEF7798699CBF8017C7
-:109400002984D70E5881DAE73BCC41F21F8BE4E385
-:10941000B209EBFD030056EC3F7F55B814506ED7F0
-:109420004077A313CBB924C738F27B8DD69BCEFEF1
-:10943000C3310AE5B44097D302DD6F951E90D98FF2
-:109440009426C941C81AF653D7EA325A806C253A95
-:1094500016B4E17AB1FDDA4B4A5CBFB4481F77E13C
-:109460009F4121935C08D17ABBA84DF8A312D01478
-:10947000C0294B6D31EDE497909E45CEE8E773C966
-:1094800077A25EEF8EF14BF833D1BCF73BC5BC8BB6
-:10949000E4BF26F7E0FA5FB668EFCD437A074E9A4D
-:1094A000E1597C0EE7B13267245FDAD0AE83399799
-:1094B000B78BFD07133515E97999F4C741F5D19AB2
-:1094C0003AF5F2FDA7F60C94607778B97985021326
-:1094D000581D4F7B3286F93D82AF3AFF63F9D9229E
-:1094E00041931DF9BCB0DD5B46AE65041F3B918F17
-:1094F000F85EC980C6F35C291F0DFB78F95CA246B3
-:10950000FAFEF2B9D11ACDFF2AE96BFAB0FEEF3FAD
-:109510003B9848FE13F9A82AA817032E9BF759D6A3
-:109520005FA1F7A15139C16D586FD1F5FCE5C48138
-:10953000A3F9C4EFEB4DDE67691A65E3C41585E452
-:1095400037B7969CC577240DA407D17E24D509771B
-:10955000601940FB217D0BA402EB93194240F336C6
-:109560006AF034950BE6AB29C4EF411CB3DB41E351
-:10957000A929A4E7F0D78B337D8523F9DE528F0A22
-:1095800085F3B4D6DB34251B605FBD93EB6DF51E10
-:109590002E5FAD57B9DC742CF9C1208E53AB593412
-:1095A000256DF87D57AAB08F05E86788AE052005C0
-:1095B00003A8730B1ED6F55E91829B249213AE27EF
-:1095C000829F2897C19EDC08FE36294D9366B235EE
-:1095D000B0BC8BF24DFC3E06FFE0F35923FBA3DC4D
-:1095E000A3EAAA4B627EE6BAB42417963F74F852F7
-:1095F000A86C916E397C01B8EE12F55BE50B38FE74
-:10960000F4F0427810E3C374140CF1157FB713FD26
-:10961000333A2C40F2C180CA7659A4D3A37D2E4997
-:10962000E7703E329DAFC7E07BD6CA30E9D13EE855
-:109630004923BE17DB7C76B428A443C855936EF645
-:109640004838DE9C748B5726D226FAA66F44FE75E6
-:10965000A4E384D8BFA32363AC8AF6A6296FBC4FCA
-:1096600076ADD91C61812BCCBD3D11713C139E712F
-:1096700052BC229FF635F2BDF377C901F66B8873B1
-:10968000C88F759E4AF686719E6B2ED9BC56D27FC6
-:109690007A11EDF56062F254F2CFD05DC6EBB8D628
-:1096A00026D6916FF617BBD89F850F9FC0F7FE6D2A
-:1096B0001080FCE935DD1FCA80F4949AF2327B9069
-:1096C000CEC3D2E4142A9FFC5D720197A7927B89D6
-:1096D0003F074D7695E67DA75E2DCE467DD1DE72A5
-:1096E00098001DD682B71C0A9527EAA1381BF5E51C
-:1096F000AD7A1B9727EB9D5C9EAAF7707918DB4922
-:109700009F5EC776D2B737B09DEA5DD84EE5311C73
-:1097100097CAA2DB9378BC96DB922CB48E83C9D017
-:109720006CCC4FFA144E0CB78217E03F1EFB6AABAD
-:10973000ED2A8C97567FA1340DF9F4B3AF2A14ACFF
-:109740001F5B3CEEA1BF60BBF967A61FDB90DE9BF1
-:109750004E395A8F63DD9EAAFCD841FA792C119DAF
-:109760002399B5B94B433AA6936F1CCD6CD760369D
-:10977000D6D3F47AC07C5DD97C8095A53DF9E042D2
-:10978000257159AFB3217F57DAFDDFA3BA25B0ABFE
-:10979000A2EC2AAA6388247B97CC41B6F7B1927BCE
-:1097A00005C6BB950EFF7F12BF0D7BD1A43FA491D0
-:1097B0007F98A949E072B3BC8393A4E1E746BF95C3
-:1097C0008E45FF49FABADE25B37DCD982F6941C792
-:1097D00048FB35FACD38AB9691FC669E2F6FA2728E
-:1097E00059858BEBBE55B39AC8FECB1C977BBF94B3
-:1097F000DF7FD06566BD2D51B05F9C3868F49B8ECD
-:109800004A46B87BA02B31F82CE9F5697F6312D664
-:109810001779B28A64DD3703D75D3BB6517BE5EB40
-:10982000AD6C57DE242FE1F299A89069D8BED02103
-:1098300079C3642AF33F6A4AA376A7E425B62DD4F8
-:10984000A69D28A6F66CD9BB90EAA7D5320A51A7E7
-:109850009485F32E60BFC5B9295E1BBE772AFCD064
-:1098600045D2DF85B949DE04F2F34AF0E91AAA7B52
-:10987000ADDE0695D6F15869328DA34A5E13D65BEC
-:109880006E28FD1F4447892F052489DA5D0AE1D738
-:10989000277FF7C33227F66B192701D9CFA970DECE
-:1098A0009F88FE859D896A02F9698BB38CDE6BB156
-:1098B00048CE4D5CF79552FF408E597D1EC73D7EC8
-:1098C0009B9DE341E55B058C838EDF3686E342E5B5
-:1098D0005BF34BA83C6E1278BDF2ADCA0A6E3741FD
-:1098E000989C4AE5EDDFE2F7B697FEB0CC8DE31F1A
-:1098F0001BEF62DF82722A5622FC24F60789DEBF44
-:10990000BD9AFB7748990F9DC5FE170B528AAC385C
-:109910007FB93B21AA7FC55857547D49F6A86225D7
-:10992000C24F56166445D56F28968AB323FAFBE6D4
-:109930002744D55794B98AB323FADF54392AAABEEB
-:10994000F2A6ACA8FA42D31CE13FEA617E99B0F3DB
-:10995000F965D9208C89FCA953F47D03DBEF263B04
-:10996000EF12F8A9C885F809E552D655CC71B9D8D7
-:10997000AEFBAF00747B6692FF17BF2E1C8FDE8399
-:1099800020FE99497848FC1676231E207CA460DCD2
-:109990008EA0A7CC111DC72B40CD27FF5BD1B9846A
-:1099A000F154B96779199A31F231FABD0AF9618136
-:1099B0004362E82EEA32C7A5B7626CF4FB06AEAB91
-:1099C000D0E96B31F99B52098B05B46EC235C67A6A
-:1099D0000C3A2EB79E0AF98E3214FFDF5C572CFD2D
-:1099E000001B797F114BD7A04BC78188A71807763A
-:1099F000A6323EC49F3B1E3E30704F25FA3757A417
-:109A00007F7348EEE58597F76FC6B897C37BC6B8F6
-:109A1000C6FBD02CF3FCC6FB43CF5529FEF39DD8E3
-:109A20003F29CE73B714FFF973D1FD17286AA3033A
-:109A3000EDF82848DE00F1FBB8AA10242B3DAD3527
-:109A400051B9E843BF427874F1D9401395F37A8352
-:109A5000C7ADB8FEEB726595F20D061E8A5DD78C18
-:109A600054B14F3A7A49B5ABD8DE1250EDB4BF6865
-:109A70007958B5D33EAA45830ADA2F6A134D1B697C
-:109A8000BFA1E56389F59C54E1E7F352058E31CA25
-:109A900067657F5E2A96D5B69E47098BD47C316078
-:109AA00021307094705EC1489C7754093A68BEA317
-:109AB0000F071DBE083F7EA5386F14295B3AE9A742
-:109AC000A445FA91525B8216E93716395D51F5AF1C
-:109AD0009CAAD8C77B4645BD779D9A15D50FF16BDB
-:109AE0002EE1A0460BE42AE4474D895EC277B17CA3
-:109AF000FC177DFD5E8793E01398DDAAEC8F13972A
-:109B0000BCA5827FB1CF57A48A7DEA6F683D586EAD
-:109B10004F15F435C93E01E21037933EC4D6714F5C
-:109B2000BA8AC6C3913DA4775EBBE922426FF84E64
-:109B3000EAD5D729A8CFDEE9A6EF4EC4FA23A98B30
-:109B4000447D9E69CF04ACFF34B55CD4AF364D374D
-:109B50007B017E058BAF2BC37ABADBE74FC579FB60
-:109B6000CD8EAD12E219C52441917B78FFFB8805AB
-:109B7000E3290A16954C7321AD76ABD82FD724A0D4
-:109B8000FFA3FE259A4AFCAA4930E4DC9341711DEB
-:109B9000EECE3491BF30F66F760BBE87EFE7D8FC80
-:109BA000B5425FC2C92AFAA5FBF72FCA24BDD89EC9
-:109BB000EAE4F5E7EF99E7217F85747D97FAFD7F69
-:109BC000A46B533CBA9ACC629EDE96FC528ABBF9D7
-:109BD000E3511CD2B0BC70BBCFCF1342A82B8CCBAF
-:109BE000358F84F54697C54B387DFB907CAFAC6CC8
-:109BF000D4F313B25DE88D9C62DAB81BCB9FEBFA0D
-:109C0000F214CD3B83E61918B71CF5019C03E3560B
-:109C1000148A3AE9832C170D10DE1EF8569297F736
-:109C2000C763077EFB03ACBF7747BE9770F4078915
-:109C3000823FAB82131A7BB03ECD1ABC2A8C743E95
-:109C400094E67F96F4E0366B7012EB9B6363128DA3
-:109C50002F69C0FB10637F87FB38D5327124EE1F5C
-:109C6000392FD888CFB7CC117C36E6459EDA28EE5E
-:109C7000BC375B3C37E8C0F95B88FF063D4374C0E6
-:109C80005827C7031079A445B243E461FF60E2BCE2
-:109C9000492D191FD6F79C35F1BEAECFD85780E6B7
-:109CA000583D939B789E392736C94C6C00FFCCD425
-:109CB0005948AFB6ADE77DFA8CEEE87DFAAC4E7F41
-:109CC000A903DF9BF57EFC7CC83C7DDCD910942980
-:109CD0005ECFE989EE374FDFA7CF3B1FFDFCCD54A8
-:109CE0003DBE8D86D191798E3A7DFF33787C420AD4
-:109CF000E929F93A19F96E5165989D3AEC375AEB12
-:109D0000B15F0EF9471B9785A79D7711FD6DF5A8EB
-:109D1000D016F2931E2E0D7B2A3C0D77C2D4887983
-:109D200074BD37F838F8BEE0E3B49EDC9FCFC7BA05
-:109D3000B9D30C4175789D73753E0D82E0F3A0D3C5
-:109D4000C27C9ED9F5CBE9617C64F598408D585F63
-:109D5000829A086A843FB5E7A646D565433E3ACE67
-:109D600098AE8F9FE41D1D358E81370CF9BD9A5A30
-:109D7000DE493864BA631DE38E94D913A2C62D3E22
-:109D80001E2B27641CE17624F29F08D79F56A270F1
-:109D9000C62C77803800B33F546270C97699EC685E
-:109DA000EED9E8E7E6B4CBC8ED72FC84A93F9FEF9B
-:109DB000FEFBF9E9D2A2F9995611CDCF745F343F79
-:109DC000335745F36D943F9A2F63D64D896ABF6A26
-:109DD0006351547DFC8373A3FA6761008CAC4FDC44
-:109DE000BA24AAFFA4ED2BA2EA939FBA2DAA7F5E04
-:109DF000704D547BFECEAA2B927F61A82EAA1FB174
-:109E0000D7F40DF2BFBAED1FA2E6F9EF96FFA23428
-:109E10003D2FAFCB7F998E435C1AFAC7A2E138453C
-:109E2000E915F293AEF637BEA0FC4BA044E5BC5357
-:109E30006009781BB1ED09D927915F1B83AC36A16E
-:109E4000DF6832C13AF2F78F9A4C9C8734ECBC2A17
-:109E50004DE08BAA34E1F79F469BA6F866F0CFEC65
-:109E6000DE9E4478433699A09BE29AE265BF71C6B4
-:109E700001E16B713E7934705EAB3479F6B299A82A
-:109E800087F29B32EF1FE5D17E50717D8DC71F3F5A
-:109E900041F99F8B0E9B4AFA2AA7FA0314B7707DEB
-:109EA000A1E761245E79AF3E3C89F649467D95671E
-:109EB000E366EABFEA8E859368FF3AF4FC8E8E492A
-:109EC000651172885CDF8A38F8E87B69223F67C4D5
-:109ED00087DBAC6A630FCA6B9A2CFC3FC685EFA583
-:109EE000E1FA3F901E360B9C1530D3BA314E72DE2C
-:109EF000DF8580BA0ECB94E178A47E8D4AF5C184CB
-:109F000068DCF9261144FB085B2AC7FF5B0D7FBBA9
-:109F10002E8FF936E888EE3F78F744C1CF6F23D70C
-:109F200090DF672C621D06DDE7753FFCA9EE877B9D
-:109F3000C9FF46E49BD7ED783C89F0F5995C81A791
-:109F40008DE7CFE8727D264DE0E9F53B139C9179D2
-:109F5000C7EA902BAA5EDB36CA7936420FD71BEBD5
-:109F6000F04B0AAD63836E3FD59D3DC9B701E3F168
-:109F7000A7D370DC9A1D17BFBD8FDE370D648838FC
-:109F80001AE0F96E790F18D7DFF21544E1D297D2B3
-:109F9000447EE525A20BCB95583851DF56626C778D
-:109FA00051F9C6FC72B23B7C1E96B0BEAC13CC8499
-:109FB000D396FBB3CCC4F453E07D672F2E6D5F9A2C
-:109FC000CAF3DC043E33C5C577BF5D9D44FD86C63C
-:109FD00033C61943B959D42B57C09C41F99A6B2405
-:109FE000C60D389F8D9EFBEE18B399E2AF31DFBBF3
-:109FF000E0BFF00EEAC50AF0F2B8C6F800A9517E3B
-:10A00000F803CB901CED24BFBA2E5398F239756734
-:10A01000AC7CFED1DF30F0EB0790CEDF557DB15741
-:10A0200042BA7FBB7AE057FBF0F9AD4FA1DFC5B56F
-:10A0300066DBFD87D322CEC3CEDC7D91ED0CF1C86B
-:10A04000F34F92337AC9EA25FBF8A0EAA59C48BCF5
-:10A050007F226D6127BD07B3D3E29E47C4EE2BABD1
-:10A06000483FD96E55C699865EDEA7EB65DD0B933A
-:10A07000F9795DD2D07A44FD7999F3577507ACBC74
-:10A08000BF7F47D787AA17BF9819999F6B41BD54C7
-:10A0900073A8747249E79C2AF266CFF1C1A9D46F04
-:10A0A000A3ECEF213D3978E9E364AAEF79F34B5E45
-:10A0B0000FDC7465F4F723F322F95C9B34F02EF97E
-:10A0C00093EA7D5695F250A5FBF28EDD8EF59A4E01
-:10A0D000F43BB89E0BAE9E234FD37E6ABF04949789
-:10A0E000AA0927B073AF69958294C7AA6ADBBD65D8
-:10A0F0000CD6AB9A971793BAD6260B3F56D32205A8
-:10A10000693CF0A7317F8A74DB287D35EF1F0BB0E7
-:10A11000BDEFA818FF5C7D78EA59F44F7D2D9F9D17
-:10A12000233A36B459393F762E296C1983F35ED819
-:10A130002D8502EAB0DDF6B9C43E6A5DE8310BCD8B
-:10A14000BBEEB9E5D9040FFBF69DB4907F5CD7FA5E
-:10A1500058B9FEBC5884FB20DBC5FA9D1D9322F341
-:10A1600049F721FC83C8F881F40508F78290E309D8
-:10A170005D3EABDA273612BBD0AFED7D5A62BFE64B
-:10A180007493DF3BB8EBDFFF95E6DDFF2F9398FF7D
-:10A19000C557C67FF005184FD4E8F3C0F95316DA57
-:10A1A0001FD6B49ACFC53B17FABEDB77957BC6F0B6
-:10A1B000FE3616576FB18038B79900C1E7291E38AF
-:10A1C000062CAB919E1F5107A447710E58D660DD37
-:10A1D00046764671C2E308C6DB17D7B9159E0FF75E
-:10A1E000081BE39D57D6EAEDA56A8F85F270359E70
-:10A1F0005E0BE9754DF813715EDFF651B91667BF56
-:10A200005CED167ED3D003C3DEEBD2A7B05D98879A
-:10A21000E260C8C6765FB86680E253DD7ED40EDAAF
-:10A2200017B8FC034477606F824AEB2BDDF7C9CC8B
-:10A230009E8879FEA4DB8751AF79F9A3A966E2E78E
-:10A240009E8FA62A49C3CFFB321CEBE2E555AADD5F
-:10A25000224E6F4EF69D8FB683046F18E7AD69B737
-:10A26000F3F907DAC1968EE2483BB875DD0ED2F3FA
-:10A2700076D98B1601356DCBFD0DDC3FC94BE291D4
-:10A28000DB1606480F65A78FF513FE8AF3CDD4CFF2
-:10A290007D2652AEDB7F1BE991E2084F8ACC6BD45E
-:10A2A000987A7ED121915CB76B269AAF08D86FC996
-:10A2B0000E5F0FEF9F8A3354DAC71E9E510EC4A75C
-:10A2C0009F1E90385F6B4EF56FCD22F91E95B9BF7A
-:10A2D000E5F00B013A97EE9B06C5449FB1DE9F4E19
-:10A2E0000B838CE36C2E042F4DBB79FF2D1ED2DF28
-:10A2F0009FA61F617C61F78680FC4A23E206CAE7BD
-:10A30000D80B42611A2721D7572CE33C796E27F3EB
-:10A31000CB62F57B291F944D755C874DF1AD23FA17
-:10A320006CEE44B19F1E7B6579BA3EB27F85CE1B31
-:10A33000FD9C2FE9330B3DEDBB0A185FF31D9D39E2
-:10A34000D4A409BEC1762E6BDB3AA646C6DB44F028
-:10A35000DBE879DFFE5BBC44BF3951D7F78C44B6EC
-:10A360008BD8F9FF99F499E46E5AB3358BF84C7C8D
-:10A370005347F67B5AEF67F003147F2ED92B92AA2E
-:10A38000C5CB0F8D77973C4E72DD9CEACB7515F0EF
-:10A39000F1AC00C39EC4B87687FDFF5764FF1FE988
-:10A3A000FCDCA2F86DC4DF4D7ADD6CF1A94EB67FFE
-:10A3B0009F4AF30FAD6F74FCF5B5E9F6BA6582FFFD
-:10A3C0001BD7B74F5F9F3915F58DC64B06EE674E0D
-:10A3D0000E0648FF9A92A078133E3EEC2AF790DDD5
-:10A3E0006D39F4C538B2F7A624AF0728AF7560D62B
-:10A3F0002AB2FB2DA36F63FDFFF485BC2239629E58
-:10A40000136925ADE4BF7E69ACCBE2CFA575FC42F4
-:10A41000D723635DE96EDFABEE88BC118C755F916D
-:10A42000FE80BE9FF3EAF117F7739CFFEB87442F82
-:10A430009D27EED671B7023ED61B3B7855C6551AFE
-:10A440001CA37B1F8D1D26D846CBA6E454C4395DC2
-:10A45000B26C32367D9A0DB7E6746C4CED6FBAEB88
-:10A46000963421BDFB21200B7C169DAF004DD2A45C
-:10A47000C83CC56B55F1F314CFF81BC92EFF569E8F
-:10A48000624ED8B4DA92F2F7E72BCEBAA3F73D9F2B
-:10A49000BA55262A942BF431144E0C8ABC174CA7BB
-:10A4A0007D5333F112FF7B06D7CAF62DF5E5DA5C52
-:10A4B000684FEEFBB76D1D8B76972DD64FF546FA9C
-:10A4C0007BA7C03D43F98FD7A630EE463F27F3FE6A
-:10A4D000DFA9D31223B762C46BC0F78852A3F22757
-:10A4E000E1235F26937EED4A55DF22B90C74C97CC7
-:10A4F0004F2441E9B1B8E2D8D93EC203E8F78BD383
-:10A50000C53EC4D626CE176DAAC67E31C1E99C26AB
-:10A5100047D8C579B7C89F571FF9609C0531DC053E
-:10A52000D3F1E4021C7FC3DE96644AC3AD3FF3F669
-:10A530004CBA9253A2F81DE9B8FE4FA51D3936C298
-:10A54000A95B8353893FA1F08414F293850A049494
-:10A55000A238F1F1A922DE14D73CC587FF50D83EBE
-:10A560007D2DE1E5DAB0582FCD61C6A6BC36E07A84
-:10A570005F5B632A8D57FB6F074693BF7A295DE0C7
-:10A580009A172F4D11EF2BA050FFAC7497AEE741F7
-:10A5900013E50B5FD2F38C7D974CDCCF98BFB06D89
-:10A5A000A1EC443D28086F3FC479CD76AB4AF24D0B
-:10A5B000780E043FDA131877D61E5C0C14E7FA5DA8
-:10A5C000E095B07D57E2C06F491F060E58553A77A7
-:10A5D0004D706E87541C7F977E4F2B0F15B2C5317F
-:10A5E000FCDC982FA1FDE7941324BDE0F3DF0465A4
-:10A5F0003B5CE388E47712D35DA2EBD5AEC4B089AF
-:10A60000CE450626E15E87E91AA613785E83CE3C26
-:10A61000F6FBBB2C03E77EE066BA9CA4077920E832
-:10A6200084F6C92AF9D104A7C6EB4870AADE8034A3
-:10A6300092AEDAA908FCD06E1E25E73577D8AE6B4E
-:10A640001387EB36B4855D13403F8FFFD5363A8FC5
-:10A650001FAA9383993DFCFE2DE92F6C6B1ACBF951
-:10A66000BD808CA2B66399944AEB54797DE845B5D8
-:10A67000F422C107BAAF67B789F6A1FEA8E70EAA10
-:10A680003B443FAFD5695F92C5F64287D74378F028
-:10A690007E297CEE5AB4D7DEC77C2905B8AE5ED3DE
-:10A6A000A1079AB1DF9F568772E83EE97356FF1AF9
-:10A6B000D2CF573E5CF34821F9DB5D666F25F99DEB
-:10A6C0009EC0CF1887BF6856B745D81D8C1DC8E0FF
-:10A6D000FB8031F3D49ED9F433C2D7FDFB2595CE50
-:10A6E000BDFBCD03E388EE9AF63F5AE8BE64EDFE6B
-:10A6F0008F184F4B19FE1A9A6F765B03DF6B9B0323
-:10A70000DBF95E1BFA43BE9F18F2087F32783AE706
-:10A71000D98608393C912EEC0D06FCE3295EB5EB99
-:10A72000F67A90F6DD58EEEDB875228DBF57CF075B
-:10A7300018EF35C0A131C4F74DF01A97C6F3FEA04B
-:10A7400052417A96FFAEED4E2DA2FFA3E902BF3D26
-:10A750009A2E70667686BF89E85DDFF1B12599D6BD
-:10A760007936348EF6B921454D71C6F12343F61B77
-:10A77000634FB5CA8085FAD79E07F62B28EFA6143B
-:10A7800094DF4BEFB64D598DCFF7A24C5228AEE275
-:10A79000FE94E2EF5EB36F0CF56F78E7F3A9E4C7C0
-:10A7A0001E484FE7F57F7E60FD78E21BEA7F492275
-:10A7B000D9D96E60BF66D86901D929BE5F40FA5FFA
-:10A7C0004CF53CF6CBBB2CDD4BD82EF79A80EC1227
-:10A7D000F59FED01F5DF49F8AEC089F6C0EF4F6691
-:10A7E0003BDFD56DD21827A35F9FC4F5921BA9BE8E
-:10A7F000ABBBCCC9764EF7058AC85EC387789C1080
-:10A80000C024129D04BEA8FC883B99E936FCE5E70C
-:10A810006ED0E3869AE2C575D86539CA3E22E2A4B5
-:10A82000A81B71F4C933DB9E407B81EED428DC0F7A
-:10A83000EF0BBFFF5D3D56D5BD3E775933AEB3EE4E
-:10A8400084CCED07F57D5E58D793437A7E86E28609
-:10A850003A5DDCEFA5E733B04EF75D676A1B4B0945
-:10A8600063CDAED87E98CAB9BE502941C8F9ABBAFB
-:10A870000F9B8599E793FEB51EBA2E9FEECDF59FEF
-:10A88000B1420292D8FAE5C06F5FC4B53D7010F9CD
-:10A890001F274EE17258FF106F8D01CFC8F67EC999
-:10A8A000F023BD4B481FFB5AE5E13A1252838A4D13
-:10A8B000F577D23FDD16C0BA3F437B9F54E2C7997C
-:10A8C000FEF7493FFB4F7E994166B9F7B4D8C7B749
-:10A8D0005AB47CD29FD609B8B58DA3A7AFA58B3C3F
-:10A8E0004FB115E29E4B7EA5C7C19C003C22F1FEF4
-:10A8F0005C760651EE175A65CD82F8E73C0456CED9
-:10A90000237FA3E76FEF01FDA7E11F94CFBD7AF589
-:10A910001EC22B18B7EE7D62C4B9BF89F4696DBB46
-:10A9200004FF846B5FF74CFC7B09465EEBBEB61DF3
-:10A9300047C6A03CAB9E8BEEB761E89E7B88F7BD17
-:10A940001B9AA3EF1B7C95AEE396893091700BEABE
-:10A9500013FB07B3029D56D4DF5732FD9F105E7E76
-:10A96000C924F8847E95EDF213B71E674A843F1A16
-:10A97000B8007C8F286F67E830DDD799DB9CE5A5B0
-:10A9800039E62AA27D6E5B16C719508232DD3798F0
-:10A99000ADF9CB195F07B4D3742F649DEE27C1893D
-:10A9A0007F28BFA3AF6B9D8EE7EE0B46D33D07829A
-:10A9B0008D34CFDA9DE2FED1FA9DF1BF13A8D5C741
-:10A9C000D9F0D4C923940EAC0E45F7ABD5F953DBBF
-:10A9D00016FDBC057812189F117DCFFC4AEF43FC91
-:10A9E000C92CF0C5DBFA3846FBB519C27FD62079F1
-:10A9F00024DF0D4139487AB34E0A240B7C0B8ED5E7
-:10AA000048F75D86BEE8F765EFD6F97397AE2FBCC1
-:10AA10002E7CBFFA192948E78077FF249AFE7B42F3
-:10AA2000ABCB491F62F56A5DB399F16D156CB4103B
-:10AA3000BE8DD5ABAA217DD96EA13816AB4F357E20
-:10AA4000E932740B5CFE7F4BF77A7398F34CEBFFA3
-:10AA5000A7E4A53CD4BDADDFB1505E74A47D08F978
-:10AA600056197AA2AFEBEF5DCFED867CA7C01496A6
-:10AA70006F45DA15EE83A2F1F46ECB509E92F37C13
-:10AA8000839D13383F6EE851EC38E53A2E5FFC1495
-:10AA90007079A1ADD44EF8A2FFB8C92BA99C7F4C08
-:10AAA0002E443E4C3F2003E18DFEF6898F0790FE39
-:10AAB000A213C53752BE7CFA098C3FD8BEA7B3F8A3
-:10AAC00057E45F11E1A4917D2FECCA4EFBBD83C713
-:10AAD000E1F8DD7FBCE8F14AF2C3C7CB8A695C09C3
-:10AAE000DBE97E78911E871A8E17D97B22E2D1FD91
-:10AAF0001922DFBEC5F3FB47695FB078B7D94BF9C0
-:10AB00008EC566FFA604A4AFE805C9DB80B31DE9C6
-:10AB10003EF4248D8BF6A452BE66F1EEEF1DA2F634
-:10AB2000DA5D12D3DFDFBE287F17C5C7A0ECA5B85A
-:10AB3000D7DF7E57C1BD84730EDC537057C47C478A
-:10AB400052855F597C9599E371EF68FB2F2B29CFD4
-:10AB5000A9ED60FFD0FBEA1E0B7F57B04B020FAE92
-:10AB6000F388E7F0AF890FBDFB4E5A08E497B69E15
-:10AB7000B4F4C4F1CF467901B77161CEBF6EB7F0BE
-:10AB80003DCABD7FB0D07A6B9EFB88F369556D12CC
-:10AB9000FBA7AA67E4A04A799E03AF58483F6B9A87
-:10ABA00025C8CC8A6C37733BF951AAFFB159F865B7
-:10ABB00043EFD7E87A6EE8BD61076B74FF75D7D6AF
-:10ABC000683DBF17B42DA3F1FD7B9A57F33DA07BE1
-:10ABD000B6C7F75F861F5C4BFB528C2B6B9F8AEED0
-:10ABE00077DF907E07D8BFC7FAC95732F4F3D83C55
-:10ABF000C823FD1E0CAF19AFA03D7D7EB26A3CC4D8
-:10AC0000C93B1ED7F180118F07C3268E67B1FDFAAD
-:10AC1000DA2E5A288ED676FE99F16B79FB672C874F
-:10AC2000CAF60EBEAF7A3DF837101FAF6FB73B09BB
-:10AC30004757F608BB5FD26E0D06256A0F35917C2B
-:10AC4000FB0F8AEF3B02AF4A8CA340F77F6B757E08
-:10AC5000AED5F9B716F76763E8DE8ABEFFBE2F7779
-:10AC6000C711BAE251A33FDFD0753899F8B8048410
-:10AC70007F5A1212FEC99087115F46C6D1816F9329
-:10AC80003CD7B75BF9BEF852DD3F2D6D16DF93C59B
-:10AC9000FA8BFE517691FFDD2BE88D8DA735ADD176
-:10ACA000FDBB32D2D9DF0FEA78F813C3DFE8F2A890
-:10ACB0001C003BE5E797A8B237C86F752B347FE7D8
-:10ACC0005489CF633BD58929F1EE4B19E59B3ACEE8
-:10ACD00037EACB284F86FD43CEED8EC87DFC8D999B
-:10ACE00002AF54CD910324CF887DCFB2A2ACB8FB84
-:10ACF0001EC844BADF187BD74FA645EE7BB41D397A
-:10AD0000A4673FF23C5E49F78C6A9B857FE89B8D88
-:10AD1000E3A6108E07C6C5B5CDD620ED4F6A514FBC
-:10AD2000F87B30D20FB2BF766911E907EE1B1C9990
-:10AD300048CF723AAAC4F52F6FC3388EC32F2FFBAA
-:10AD40008CF5AA2B5BAC1BF996196F1F61EC1F6A7F
-:10AD50002E099C6A3CAF517A781F51D32EEE49B729
-:10AD60001EFA625C16D2DB7FE03FC6ADC67241A61A
-:10AD700088BFAD25A18FE9BECFE7BB6C71F1E8902C
-:10AD8000BF979AD80E6ACC3D198C57F6232E9C8516
-:10AD90007EF3ED4F79DFD17A28E14ECAC7F5ADF1E8
-:10ADA0008F777E839C1A6013E3DA4DD0C425E19E31
-:10ADB000481CB8D629EE0FDDABC749AA3F8C7A7D77
-:10ADC0002FF65D5014CFEE035BE64923EDDDF01B5B
-:10ADD000D5BABEAF2FD8B1858EE063F151B56E47BD
-:10ADE00088FC392EC6E2A21B33A3F5B4E1ED44C6BC
-:10ADF000B9FD5DB29372C4C8D75F8C26DC87F87E3C
-:10AE0000429C3CEBA7BA5EF6EAE7BE0DB365E69B53
-:10AE1000698E280D1C85FC637DE93FE908521CCB37
-:10AE20003FF8CA0492FFFA9DD1E745243F3FDFDF98
-:10AE30000AB2FCAA43763E4332DA5F3AF8CA14D229
-:10AE4000B386B7BFCC1172F922C7E2BE3C7D46295A
-:10AE50004962FF6B92C4FE77AFD2934CFBAEDAFD32
-:10AE6000B22FF2FEBC21E7BB75FD0145ECF3D765BF
-:10AE7000AA5C6F68177A613A204A9C7FA5C8F3984C
-:10AE800079FE11ED25A82FDF10B780E842D9D79AB7
-:10AE90000758EF6A4F9A989EDA938319D911EF05F4
-:10AEA00068DC4CF27B0D1B80FD881DC8BF2EA5EF12
-:10AEB0000FB1BEF4FD04C65947263C5229CEAD64FD
-:10AEC00020BFF5C0DB559323FDFF053DEE03F1C127
-:10AED0004328E70931BFCE874DB042CF13083DAEBE
-:10AEE000D2712CEEAF9AC88E63F757578A931B0E18
-:10AEF0005881F2C7B51F58F93ED0E707D6F2FE1DBC
-:10AF00002EF927939F01BFFF6A2A1F38B876323D7A
-:10AF1000FFFCE07D5773DE53DA1495AF08107D1EF9
-:10AF2000C2517F79F776C2975D0AE390A2AED3EF64
-:10AF3000D2F9EA9E56337F9B59BD77C6E38124C27E
-:10AF40004F454BE9BB9D3D9D0AEB1FE22A0347D9C4
-:10AF500019479D28661C85E3F8825C161FABA47117
-:10AF60004F9414533709DBC99F4D271CE518C6556C
-:10AF7000063DFF9C29F8D9DF91C0F9130926083D49
-:10AF800083EC28BA37B4BECE3864439B1CF5BD862B
-:10AF9000F1DEEE4C71AEB0D7D0B390A4B11EED1679
-:10AFA000E586B63D19B48EF5E610EB4943B359B4C6
-:10AFB000EF1225D0F9CD0CFED83840FC39468F5021
-:10AFC0002E4B2CC1B184DB770F9D07EAF73982E263
-:10AFD0005E5D63E744FE6E68B0738F3B5EFC394E86
-:10AFE000E73348DAD12CB1CF896DAFF3887CC6D175
-:10AFF00033C22F1E5DE89F1CCF3F06A044ECFB250B
-:10B000005D7EADE68A78E7861B3D22DFB4736CE097
-:10B0100028E971EFEE043E37EC7589FC6C694B97BB
-:10B0200042DF9FAC6F9566503C5A9FFB1E7F9F820C
-:10B03000F562F683E1FD7C6E5ADDBCBB5C8B43C7D9
-:10B04000B51E111F97E8DF018FD057BDFD1478D3CF
-:10B05000F57DDA23745E73AAD2EC14DF9989EF4A86
-:10B060006FD0FDF98DD79B19379D02D52CCE3FC4EB
-:10B0700039C532DD2FDFA0FBF911DF3B3F039BE930
-:10B080009C22F67B67C3AFDFAC8FBF02341E37F65E
-:10B09000BBF59B753C78B32FFAF9A54C1D07E6402C
-:10B0A0000EF9F310C617BE1F9197C0717A69E1A41B
-:10B0B000B83883BE0357F5EFC0A934E4DE90F71E1D
-:10B0C000C7BFA31D677ECDDF139C49800971CEC524
-:10B0D00086E39FE13F6E12F2D6CF2DAA9D824643B2
-:10B0E000EE17700716991F33E43E46E7FFFFF13D68
-:10B0F000A05C5022F325CFCAFE311E3A9FB0F53234
-:10B10000FEC615701CC4758DD3D735CE1A11DF2E2F
-:10B110008C5A1D577F87D7971A1071C4CD65479EEB
-:10B120009571627548E2EFFBAAC3625F5B5D26F62C
-:10B13000B539AD02A7AEBC490A6A12BBC3D3449F5E
-:10B14000A13FCB6C020F187A32C42F5D7FA89DF00F
-:10B15000C10D3A3E88D5A3C9D05D4EF9E65B34C92E
-:10B160004BF72A477C3FBF6ADAEBE4EE2FA73FA8F4
-:10B170006FFCEF22C4EAD1F73DFE120FE5D3BA0708
-:10B180005716E2B847F3FE388EF4A6E63276F32D72
-:10B190008F88133B1D81A37CDFA4453FEF6FC96BF4
-:10B1A000EB217E7402E3C75E57F7963A81ABF9BC98
-:10B1B000BF3A9CC0DF4356B7DBF9BBB0EAD686C4C2
-:10B1C00029E47FDB65AF1DEB95AD27CB889F95C547
-:10B1D000E23E4AAD5DDC8BB3B9FDB7107DD77B3B5A
-:10B1E000A2CFF92D3DBFA8FB063D8FF56B1B09A330
-:10B1F000A5FFF7F99B8D3A5FEABA2E664CC1A9FE0E
-:10B2000090E6AF267DEC7FFD450B1DD7D54E79A589
-:10B210009CAE886DF4A8DCEFFAE68E264AF31AF4A9
-:10B2200077643AF9F95173702CE3D2822BBB0FD3B8
-:10B23000B0FF8DA914A7FA3ABAA65A22F4BBB70EEA
-:10B24000FD731CF9358049B75B854B495AA1E3254D
-:10B2500061C7B5070E67503EA297ECB780CA7792D8
-:10B26000B3B1ACDE7D2A7912E196BDA21CC219ED04
-:10B2700032F703A527E7E6A448FA36337D17426282
-:10B280001C809E9C1B0B23DB1BFF5FDBFFD3A427D3
-:10B29000D5B69E28FB37F884BB7CFE3E3770D0CAFB
-:10B2A000F708E8BCC61521C757747F340B374B64C9
-:10B2B000A773E87C7A22413B05EEA0BA026125958E
-:10B2C000CE8BC3B2B87F3796FDF74C7DFE594AB896
-:10B2D00083EEE9CED1CF37E74237F75B00035C6AF4
-:10B2E000E0E4EF8B4BC0CBE56C5B7829C1F1825079
-:10B2F00088BF9F096728AE7336FD3BE638F21EE62D
-:10B300009B02E70C7EC8740E26EE1BC5AEA75BD76A
-:10B31000C7599AF03B041DE87EEE6C08F1B9FB3585
-:10B32000D0A39FBFC75FC73CDCF7D1B9DB35683B13
-:10B3300089CC8F20F79F4FEB91E3ADA767298B193D
-:10B34000CA9C449F14CE307D6DBFF275F4D36D4D11
-:10B35000CA57DF35D0F783E2E1734B6FFB1BEFD3A6
-:10B360007D6249D3F8BEB197BEC7A67D4E58E91D90
-:10B37000F2631300FEDDB3E637646FC6F71AE00729
-:10B38000BEE711FBBD062DF77CC6F03D35E3FEEDB3
-:10B39000CEE00A95EE6FAC72DBF8DFAD29B28D9B83
-:10B3A0004E79CA87D2FCBF21BDFA406A9EC4832869
-:10B3B000C1198C6375BDB283369BD62F69C6F7223F
-:10B3C000C0FA32F4EF0164007FB763B78AEF691EF9
-:10B3D000413DB4A5B2F6AB740F1A1E2E55092F6F5E
-:10B3E00071D9BCF45DAE95E8B50FD3DB6813F72FC8
-:10B3F0008CFB6BB17C6CB419794AAF8D7176CC77CC
-:10B400003E77DAFCFF9BE8BF3FA924937060FECB38
-:10B41000F33D7C3F29C15877898DEBC3F71A193763
-:10B4200036D17D6AA4AB311DF81EE2E1A49C14BAAA
-:10B430001FD5D825EE5337A607D87F9BFD12FBF307
-:10B44000C6CED24E8A07830E0BDFAB6E74F934AAD8
-:10B4500007D22144FE9FF83EDFE0BB6998EF21FD53
-:10B460005E5091EDD75751DE7F9A1B4AE9BD696165
-:10B470006D12F1C0F81E06E5E019954ECFA3EF7BE3
-:10B4800081E2E4FB17861C503158999DBA7C0DB9B6
-:10B49000388DEFF83525EA3B7E435E8F240AB99854
-:10B4A000E926CC447E57A57163E561F0FDBF008FAE
-:10B4B00040AEB13049000000000000000000000074
-:10B4C0001F8B08000000000000FF3B24C3C0F0A356
-:10B4D0001E81EF4A313030F1A28AD112EFE364606D
-:10B4E00010E062603005E2FB3C0C0C3380F44C2031
-:10B4F00016E566601003E21A20DE0DC47B80F819A1
-:10B5000050FC3910EF00E21B3C10FDBE4C0C0CFE51
-:10B51000401C08C4C140FC958181E11B03F1F67316
-:10B520000A33304C1547F02F03D99F24E9E7FFC1B8
-:10B5300086430CE96BDF71A07DF3AC107C46207B69
-:10B54000BE15AA9A0556F8CD588826BF088DBF1893
-:10B550008FFE720354FE5A4D34B3B581E90949CDCB
-:10B560003A4DFC6E41C7AA40FFA9013100ADF15F21
-:10B57000CA68030000000000000000000000000096
-:10B580001F8B08000000000000FFE57D097894D5BE
-:10B59000D5F07DE75D66269999BC816CAC4ED844A8
-:10B5A0000B7442421A10DB618B6811834B051798AC
-:10B5B00008644F2620F5C7DAEFCF40005151438B86
-:10B5C000355AB40304051B34D88041020EE0822DA5
-:10B5D000D5D86A5DDAD2A0C81A93801BFE5DFCCE76
-:10B5E00039F7BEC9FB4E2682B5FFFFF5FBFEF8F822
-:10B5F0005CEE7BF7B3DD73CE3DF78EE218C7948B1C
-:10B6000018FB12FFBEC798DDC6181BD79D32562304
-:10B61000D24A2DCFCD58D003FFCC62ACDCAD85979C
-:10B62000A7333665871AF95E12E43748613BE46D4B
-:10B630007B9D54DEBE9EE7236ECDCFA0FCA33AC80F
-:10B640004BD0DEDEF2C06550DEB943661BB1DB9144
-:10B65000713696C2D83107E37F5990CF66ACC0C926
-:10B66000B3E51BF6CDC5F6454D76E684FECA7715E3
-:10B67000CEBC0CF28507558655CA372FD3FA43BE88
-:10B68000382C3560BE63329F5F68A71CDE0CF53B2B
-:10B690003C2D2937B8183B55E5605E8DB16A774B74
-:10B6A000CAF5A3182B096FCFC57625F5920F973AE7
-:10B6B00065C7E697FBE1BAB64A3EBB97B1D22DF11A
-:10B6C000CC3B92CFE14BF8FF58A31CF91E942F8678
-:10B6D0007532E8B790D5E43219C75FAB79DDDDF09C
-:10B6E0003B55A5D33846BE7C2B8C03ED2A9E967C19
-:10B6F000B8C40A1B0B34C0F8EDBB9CB337B9707DDE
-:10B70000CBB4116E5CD7DD1AD62B0CE7EF747A71CF
-:10B710007E1BB45C282F59BF412B18D5DD5FE996FD
-:10B72000BED679D50E4D0D98CAA3D353558C794703
-:10B7300074E74B18F33740BF4C096BB346777FFF74
-:10B74000802532968CFDCBCCEBE8EE1F2049DF4301
-:10B750006FC13F015EA13D6E82AB81B7C53AFCDB94
-:10B76000DB8DB7B3BAC0A3D2996DEEDF481F403C62
-:10B77000C07C6A104E90AE11F3F34C649314E8DF72
-:10B78000E367BAC47A5F8F91D6A82C9FC1580B4249
-:10B79000A3FDCA78C86B6C11F331F69315D9FEA9D5
-:10B7A00090BF9F05E6E2BC57488122C413630D6930
-:10B7B00048BFAB24361BD7FF039C3494AFEA07F491
-:10B7C0000970AF9996BD4996C4DC93305FF0C4BD53
-:10B7D000E9D44F21F5A3423F43CFDF8F9E9B63E91E
-:10B7E00047CF2D32FAA9A47E9C17D64F4DEE04EB1D
-:10B7F0007C724B8C7EEEA47EDC17B62EFD8A89D639
-:10B80000F95C5146FD244EF5B100D4970D7A602DB8
-:10B810007E19CA5DF58963EF6566BA98BC12F9DFD7
-:10B820000D5C62A68B849C380B1D26FAFB58F2D067
-:10B83000937EEC5B220F834412351A5FEBAF915C71
-:10B8400098D4DF41F93BFABB482EDC312170B10EB0
-:10B85000F3C0B1593FC86B816FEB31E81AE629B1EB
-:10B86000344CBD364CA3CBEF56391C260FF8DB8881
-:10B8700023D03E68EB1C9108F9F5D2A45F205C361A
-:10B88000331BC1274E6695582FCECE483EDD9D9E78
-:10B89000BD296482D3EA41807FA9BBDFD56A200D30
-:10B8A000E96B2BBB2184F4B66A10ACA73F634F85CC
-:10B8B000AE8F8414683FA8200DE169D780BFCDE327
-:10B8C0006B30FE281AFF191C77078E3FAEE7F8F69B
-:10B8D000213996F11D838B2CE33B34181FE87D172B
-:10B8E000BB558C0FF09BC0D8F3A15B687CFBE022BA
-:10B8F0001AFF6E8D1559C68FEB1AFF051CF7A5DED2
-:10B90000D63F648275FD834BACEBD7F8FA5F650BCD
-:10B91000C5F871B4FE5F8716F0F50F2EE1EBB7F3B3
-:10B920007EBBC6F774C1FF751CF7ADDED63F74A2AF
-:10B9300075FD179559D76FE7E3BFCBCAC5F82E1A27
-:10B94000FFBD50195FFF456534BE660FF8908EB499
-:10B9500001719561189F0D0486482519E5A7746447
-:10B960001FC6A0FD3A3684E070471CA7BBCFE2801B
-:10B97000DE5CDDF28E8581A3409E55089A2FAD9F37
-:10B98000A4A19CA572907B0BC5541734C9B4DFB039
-:10B9900075F6F070986F7B931CC2FC827597876573
-:10B9A000DAEFD8BC3C6CA7B0087EFFF0A1D11BCD6C
-:10B9B000EB8A4E17D6A8C75A2D7CC4E7139ACC46FB
-:10B9C00056C2FCA621118CEBCE1F0339CA407EBEA5
-:10B9D0000F7214D3E32A8C07DF8F829C659A996FCC
-:10B9E00096F17D3CC4DE1C99827282FF1D5338BCE7
-:10B9F0008F2D91C208FFCFD62ED2503E2DAC890795
-:10BA0000A077CF2328F0D4B9CB1EDE28113CBD0887
-:10BA10009F1B891519FB33A0B51F80B6B0B6AFA523
-:10BA2000DD2D2CBC320DEACF5F933F4887F5DF3C1C
-:10BA3000DB3E56C6FD83F907D8888FD9005B0E63BD
-:10BA4000B31BD7AA032073E36CF5FD5653FB3901F2
-:10BA50006BFEE6226BBE5D0DAB36D4378A25B60190
-:10BA6000FABDB5D25A6E8C9328F5E17815E3FD2026
-:10BA700085CFF7564CC7E2679DF03A57E76D8DF9D1
-:10BA800004EF525984F6CBD66446F84FA67A019D4E
-:10BA9000AF3B7ABE7355873F0FE633F74E99E019F7
-:10BAA0003DFFD6BDF17EDB18486B3F569104A3D70E
-:10BAB000133DFF794BA3D7A3931E961F8AFECEE9B1
-:10BAC000249A9E824D93FA1E35D52B6FB8B2EF5152
-:10BAD000137D956E9965C91787E758EA17D6E65B17
-:10BAE000CA17D6145BCAE7AF5E64C9E787EEB4D461
-:10BAF0009FB77499A5FCD6CA7B2CE53717ADB5E482
-:10BB0000E7041EB1D4BF71F6064BB96DEF25D720FF
-:10BB10001F55BF2533DC373E751D7B00F5C14F5DDA
-:10BB20008A0FF171A22A8DF8E0549597D2F6A64CAF
-:10BB30004780CBC1025471162E6B08AD9E88729956
-:10BB400091FC2C5EB633141A08DAADE425F8C9B5B9
-:10BB50001A8B00094BAC4F171D77CAA6F2D6F39487
-:10BB6000D702A367F62C975B637F0F6ECCBF08E507
-:10BB70004E6FF200FE06E03ED721F6F7E8F232897A
-:10BB8000E599BF33B69CF8FC9C90B3651A9707659E
-:10BB9000CFF69BCC3C988F8CA8FCAAF11A00A82861
-:10BBA00027513B4F467A002EB0D0CB500B7FB7EDDC
-:10BBB00093695E152813C6A3C8C95B23A19C891C81
-:10BBC000187CDD689C87FF7E09F9AE2999F6F5B6E9
-:10BBD000AAE97D8F2A889F3C4A4F54CDA6F4585538
-:10BBE00080D2A3554594BE5F5549696BD5524A0F23
-:10BBF000578528FD53D56A4ADFABAAA1F49DAA5AFE
-:10BC00004AFF5015A6B4BDCA4FA9C10F5DF237490E
-:10BC1000E8ABC2AE809D87F267C55A5640DD16E29A
-:10BC2000735F1AF2F959D76723501F3FFB8E9DA10E
-:10BC3000BEDF1BBCA2E9AD773CFA495F290803FED1
-:10BC4000337B963BE3389E9C36369D813CBA67F841
-:10BC500013BEDB46515E4192810DC937CB1DA3DF78
-:10BC6000618CF0753E3C317FE7986B011FC71EFD6C
-:10BC70006B36F67B4EEC7F710764DA875964930F5D
-:10BC8000F165821BED6B9D3B84BC3F0FFC3EEA825D
-:10BC90005FCB6006E9044927FA3BDB68670AC2B15B
-:10BCA000393E0CC4CFCE1EDCE4417E5C9C66D38F53
-:10BCB000C68083919637A4EB2EF3FED364CD9FAD5F
-:10BCC00091A637903CF6265C3F1AE94AD78F0E437F
-:10BCD000FCA7516AF4B3384DD38F02BF9EDA3234D9
-:10BCE00081EFDF61BE0FD62712BD825D48F5FFD51B
-:10BCF000F3E9AD1F633E8C35B20F1C280FA06CE832
-:10BD0000F9ED9D1E78573ED1F2105FCDEA67A82F5E
-:10BD1000C4C1FF5F0EC17E15CA1BFD061BE490FD6A
-:10BD2000DBF8BDDE321EB4F31A3637B6EB9D6E1566
-:10BD300076CCA02B90571A1ACB64273A75EBBE929B
-:10BD400068C9079BFAE9967D06FF01FC0F82524104
-:10BD5000BA291354D4A1B8564B30BF23283F012F22
-:10BD60004189D72B77B46A012F91630BEA19B7E5A4
-:10BD70001874E7BDF18F20EF4FFE4665F762F9DFDB
-:10BD8000605650AE1AC520F76C909F2F72B735964B
-:10BD9000CE40B977D2C6F7F9052CCF83464F11AB09
-:10BDA000C9463DE723669B8EF4FF11FB9D27D364B4
-:10BDB0006FF86C1AAD73FE6AEB3E0BFA99255F586B
-:10BDC0006BCD17B06B5390DE0BD6A92C2C215F5A8C
-:10BDD000CBBD369DFA2D6495ABC8DE417B05C6BD53
-:10BDE0004D67CA00985FF9738F65E743FE3B36AE37
-:10BDF000A71BF67B711F3EFF92A4B0E687F20F1AD5
-:10BE0000337F7019C3F6E15528A7426EE6DBCC7A82
-:10BE1000E2EFEBCE3F7ABEC67ED2C38F20E6216F23
-:10BE200091FCE11876DA349B24F4AD10A537E0BA22
-:10BE30004D7A6BBE8083912F8FCADF1995FFA7E9DA
-:10BE40002D8959E8ED8814C8B72573FA427D41520F
-:10BE50003AB5C037E93FAD47FFE5FFD2FE0742FFE5
-:10BE6000D996FEEFFC97F63FACC7FC57C6EABFFC7D
-:10BE7000B96D3B43206F4A9E79C8C3601F3AA9D46D
-:10BE8000A4F800EF659B577A900E4E28210FD2F34D
-:10BE9000C9B03C3D163DEC467A203FA2DF25A15DAE
-:10BEA00085FF84FE4F3D75DF4CDC673EDBACEA640A
-:10BEB0002F6DB147ECC0AF158DC533D818CA1FE13F
-:10BEC000F9BBCFC8986FB2D267C9930FA5A0FF0D79
-:10BED0002845D81311D2972AEA3ECCC57D28C83A06
-:10BEE00089CFA2DBE1F8E7FA907CCCD7127A96C32F
-:10BEF0003C49CF0F0AB8041BEF3B23A3EF93B57265
-:10BF00003F6854FD22A1FFD4DBDC49C7C07462DF67
-:10BF100061DF417969C08385B9FE53BDF5E13147E1
-:10BF2000603E6D75BFF1482638197C76B661FE2FEC
-:10BF30009EF7F62E8FDB859DD7DD2E4CEDBC4D4256
-:10BF40006F6BE669991AF1A05E5CB641F585E07306
-:10BF5000D9B64D4F3C8A76EABB76DF70E8BF74DB1A
-:10BF60004B7F9800F9D2ED6AD20CBE0C9794D28D1B
-:10BF70009720FCBF746C371E4A7EF592E61DCDBF3C
-:10BF8000FFB84F373E4AB7EFD3D8E89EF098D2B00B
-:10BF90004F6B75C5C04BC3915CD4AFAAB77EAEA141
-:10BFA0003D7972AFC452D363C073C34BA427209CA6
-:10BFB000088F024F5D788BAA1F04BCA03C37F01499
-:10BFC0005DFE80903FD89F7714D1F3D3CFA35FF964
-:10BFD0003DBB0FD75FF4F4ED1E5CC771A592D3F59E
-:10BFE000632B53FC306E911A4AD129E5DF8B1EFF7B
-:10BFF00021D15BE11B3F4CE1F6A0BF9F8DF6A6501F
-:10C000003F5CDFC2F537D0FA0A5880E8AEE8313934
-:10C010002F0CE9A70A9BBE3D065F64C89C2F8E6F5C
-:10C0200004850BD6771CED12F4B3FE4E0E6F267FFF
-:10C03000C82286FCFF43C33FCE1653FE5307C79367
-:10C0400043B609BE026DCF4CAF7577B7207E4E0D5B
-:10C05000F2A7A21F2DC894908087F425F42BBF313E
-:10C060002D95E38779956CD10EF48029F81DEBB7F7
-:10C07000A87EE7184B3BF6657AF7F84BC4F830EF2B
-:10C0800038DCBF8FA7B0A28618EBBB5536F81EF67A
-:10C0900071137D99F89BF37BDD3D9CBF0D7E0FCF27
-:10C0A0009A8EE59FBCC9F907DBE1FE08F38AA4522A
-:10C0B000F9BEEB259207761689C5D775AAE06B6B9A
-:10C0C000B94127306F454A30D10BF6DF87E04FFE8C
-:10C0D000B38275D0CE242F83389EA7677F06DF16E4
-:10C0E0000AFE1F255BF99FADE77CDFBB7E15A27DB5
-:10C0F000AE4C0D3FF128F22BF067C88BFCAAE6E1AD
-:10C10000BA4FD71FF8C34DC0A7A71B0C3EB5CACF67
-:10C11000683E2D7A76B384F419CDA7A78B401B898E
-:10C12000C5A7F03D269F16B5FE3F959F06FCAE8F36
-:10C13000829F210F7B8363B43C3C63F3123CA3E5F5
-:10C1400021FCBDC9B27BD29F417706BD95FCB2FCF4
-:10C1500022F217187469D05D175D1A74D7C3FF6295
-:10C16000815F74F960A405A093BC5D2AD95565CDA3
-:10C17000FC3C0CDABD3C208BE0E4A76D8CD5BC3CCC
-:10C1800020C99C0F47E51BA2EAFBA3F27951F503F6
-:10C1900051F94A4BFDB2A6031A23FC472CF5EC4B90
-:10C1A0001F651FC4B0878CFD26D878460B215D0C17
-:10C1B000ECD450DEA9CB410545FFE01E99ECC50E3D
-:10C1C00080F12A18A7A33E3D1C02B9B1D2C9EDF0F7
-:10C1D0000EBDD3D307D295893CDF99ACAD42B96788
-:10C1E0007CEF74723F47475EA727D1E4A738D22C73
-:10C1F00093DC6E0DB3E9B1FC20B0A310DE5B596F88
-:10C20000E5DCFF394D760D5E8AF6688DEC431377D9
-:10C21000C1B21B3DE82AE9681E7ACD6CF8BEF05524
-:10C22000998E553AE23C63705E2CE457FA99EC899A
-:10C23000132CF4B389E8CF6CE676C5823551FA0841
-:10C240005B43F454E05AA2A13C053BE07DAB3F9731
-:10C25000F34589E8AF68BDB5DC688F275A68DF957C
-:10C26000D459CB03C23EDA65F04906CB2039838628
-:10C270000FDAE7422E4F93475D331BF0D1715066C2
-:10C28000789E79B659267C9CADE7E7972C944CFCB8
-:10C2900056C13A491E1A706A437ED27A97576D3B4F
-:10C2A000FE9C7D17D2CDCE3F8EF939A46D3BDF1DAC
-:10C2B000B11BF3CFBD3DF88FAC67FD297B9DE43703
-:10C2C000EED8EB267AEFD8F3DBC177617E979DFC41
-:10C2D000751D7B3F1F83F4D7B1DC5E84F2AE631023
-:10C2E000B787AAF77C3EA695F6D71584B7A3B2C642
-:10C2F000F5A3E6BF1E9692308555A1DEB0379EF8B5
-:10C3000029F8BC93FC0B1D7B3ECF0EB8FE75EBA944
-:10C3100010E7391D6E36FB599C5F22F78307778F34
-:10C32000DFB40CCFA31BF769F3A17CCA0B7F1F837B
-:10C3300072B4E359AE0FB5ABAD8FE3794587FCE13D
-:10C340003215E0DC8E4CD59FB1FB94119343A36270
-:10C35000C1E5EFE437B95078680AB74FFFFDE12136
-:10C36000F9B9BC73871D12AEFB8BC37F44B9B0D73C
-:10C370004E7469ACF774C332D257CEB7EEE1CA7FC0
-:10C38000173AB8D0754B910B59F7D47F737CFF5A8D
-:10C39000F6D2FCA2F9A0279DEFB983F2DBDC3E9A2E
-:10C3A000EF05D2FB82FF69787F16F0EE39FFBAAB5A
-:10C3B000FFCDD7DD3BDE5F9D2BF0AEE3797FF085CF
-:10C3C000BFD3FCBEAE9CDBF4DF94EE0DBDFE159B2F
-:10C3D000F7CD0CA83F9DD5B850B1B8B27CFFAB19D2
-:10C3E00050FACAC0038938DFC951E73746FAA6C2F6
-:10C3F000EDA6C9928DEC419628097B90DB51038410
-:10C40000FE30604901E9210306DECFF506C5BB0E0B
-:10C41000CF1F5F193CDF47B1146CEC3B01CCEB97AD
-:10C420008BBCD59EFCB9C4FC78343A60F0F70FA2FF
-:10C430005E3B70A04C7A2FA4A4EFBEE899CEBF97C4
-:10C440006916BBE74AAFD50ECA4DB2DA4B53457FEA
-:10C45000D3189FFF3497140E031C260FFA6912FAA3
-:10C4600047270F579904F95C165881F6C55497B5BC
-:10C47000BF063CC319F7CDE168570D380E599787B1
-:10C48000701C24939FF4BC70C47913DC32C2182F43
-:10C49000C3141F87639F721FF99D85BD4D474D9043
-:10C4A000575CAB5A909F15B497391CC8CE36ECE553
-:10C4B000DEE0CD84FDAD88210DF82B0365BFD3DA16
-:10C4C0001FD9DF065EBE2E3E0C3C7E53BCBC1B85D6
-:10C4D0009781AE450AF2EB74B417FA62FD0C9E1F09
-:10C4E0001852E8DC4DD80B57781729A4F70CCC501C
-:10C4F000105F858EA6ABF01CC4E193681E17B7D9F8
-:10C50000687F70644904F791B50AE5DFB0E9E3108C
-:10C51000DF332F7BEEF49D0CFDE67E8DC73DE5F10C
-:10C52000F38FBF7DF9E5448C1714782C84FFAF4658
-:10C530003FFF7A168903382D545828A10FFABD25DC
-:10C54000F6BEC5EF6DCDE3DF7753BAFB395FFDDE95
-:10C55000E4CABF3A7D0EE4D8FB00F35D980EA3E178
-:10C5600015B35DFD9D660EAFE021161EC2E32AE401
-:10C570003CD339E11D82FE9FFBD3B39968D74EEAC5
-:10C580001895C0E5EB30B21782C25E38CBBC093ECD
-:10C5900017CAD7A10974FE795076C78A2BDC2AEC1A
-:10C5A000ED5F627C09A41D75AC4646FB8D75921F3C
-:10C5B0003754E7609B63C4B7E4AB869F4AE00DFE47
-:10C5C000E46C3C8FE1E32F84A60966BCB5CD38A9A5
-:10C5D0008CE98907FC7BDF741EF54DE18BF63DC2CB
-:10C5E00077ABB335372F86FCB85DC06FE6FE2FC83A
-:10C5F000FF7969F3061BD2EFA57536CBF96AA92A34
-:10C60000ECB1B16C2CCE6BE67EA73B0BF17250F611
-:10C61000613C67B0F98C1688712E180D4FEC1FFD28
-:10C62000E95B559DF86BB7DA301FE1BAFB2307438E
-:10C630003B7A9756531A6B9E03EC7C9E0B59C3EDC5
-:10C6400063D2FFFDE03BA9C315998CF6671D137EED
-:10C650008F68FA6344C767B7B030EEAF68AFA25CCB
-:10C66000385BCF687F0790DC8F7637F0FBF7CC7EA6
-:10C670009C8B9BB6FF12F5828A6649C723860AA562
-:10C6800055433F6DB02951C67D38C36BC4BBEAA387
-:10C69000AF37F1C5565521F81E98B0FB661CF7E37D
-:10C6A000368DA19EE27FB1D383FBF8C7CD99C40735
-:10C6B000BDADEB5755ECAAA948372A9787D1F4307E
-:10C6C000AA3ECE92BF4C0EF447FE9A696F5DE28B94
-:10C6D00081BFEF6B923817BC40F916FEFF4CBEBD10
-:10C6E00069C8B7809C67E2A3BE5A0FF9961A4BBE81
-:10C6F0002D96BCA908F7C57B86A6225E17BFAA2681
-:10C70000C7926FDBAAF839E733224EB9A311E4DBF5
-:10C71000B74DF2AD11E45B8C7890BF5FA87C0BFF46
-:10C72000D7F0DF36946F31D6AB6B56F936A6F908E1
-:10C73000C9B7318D364B3CAF5D3B9F7C9392AF4781
-:10C74000FDF8A0EA8B8F413FDB843EFE8C884BC412
-:10C750007150CEE56A3A8D7FA172EEE20B9573FFC0
-:10C76000457036E4DCE21D8CE29C7BD22197738B12
-:10C7700077819C93901EB99C5BBC8771BF5C947C55
-:10C780001BD943BE31AA5F11E1ED834DE90FDF02F2
-:10C79000FD8DF5AB3E07D41FDB2DEFC699E55DAEF1
-:10C7A000A610DC7AC8BB831726EF76087907726C6F
-:10C7B00008CAD768FAF0355BE3C1778F3F5EFF2B7D
-:10C7C000E497DFCA74DEF8868D9F0FBD36FE7816BB
-:10C7D000D2D763623E8B84DC6BAF0A51FF535EE4B9
-:10C7E000EB2B77F138F18A46AE1F56D44B612FFC04
-:10C7F0003377C2171ACEBF788FC452213FCBCEEB0E
-:10C80000B3278DF3323623C3440F0B724AC9CFBF0F
-:10C8100040610EF4E397BA724FA2FE5B9AC3FDFE2D
-:10C82000A5E27BF1ABADABD0FF5DFC8844E7A5464C
-:10C830007CAB11E7DB236EA27919F977A3E32766B6
-:10C840008AB8A999BF94C21B62C47F946EB1E67F77
-:10C8500022F86F96DC4AF062AFCB31E3388C7A5D18
-:10C86000703A28E05427D37EDA0527809B37BD270E
-:10C870009C00D3333252BAE152FC5B586F56EFEB57
-:10C8800035E016BD6EC37F5D2AFAE90D0E069C7B6E
-:10C89000AC5FC01DEC029293D1F058A775F9B53387
-:10C8A000314E09E886E44CE8D70017182F6FD27094
-:10C8B000CB7D974705FD64D64C9A82E10CB330AE30
-:10C8C0001CCA0B6A17BDDC0FE031EE1DEF58DC4EC1
-:10C8D0002F9B600FE039EC566727C941830EDB358B
-:10C8E000AE071C14F0DDDDBF7232D9F94D928E7A9D
-:10C8F0004830E224B80601AE78FF28A870FC068113
-:10C900001E91FF0E3CF21987E31EC98BFE9D5C63EE
-:10C91000BF42BC40FDCC668E97605822BC64B14ECD
-:10C920003A7FA9A8957C11845FD306829F219FE15D
-:10C93000CF65C693897E9558F44B954CFB65A9A8A5
-:10C9400037D35EF307A4E7994FAA6C03811BFEFB64
-:10C950002A7A3E4F1C50349EDA04BCB6213C5D0856
-:10C96000B74EAE7745BEA0FB504679500959E03925
-:10C97000E5D1735F09AF7106BC908E51BE35E7CB30
-:10C98000982F689258DFF49EEBC5F35033BF17EF32
-:10C9900039C2FB7F4CF2B118EBBE60BAEE859E8BBC
-:10C9A000806EF1BCA437BA8E86533BD2F3B7BAE996
-:10C9B000F93567E7A14CA4E73D12F74334275ACE77
-:10C9C000353D761EF7B5D509740FEBEE7C55F56D48
-:10C9D000F4C690CB82EED17E30DF37BB041782F1F4
-:10C9E000A25B1C14EF47F318C2F553B37CDEE66478
-:10C9F000C9D767F5DEBFDB2EC58C2737F423233F6D
-:10CA00001AC7C3F8F926186F64F778D1FB83E12FB2
-:10CA100038DFBAFADBBFD9BA8C71BE6E3C5490B520
-:10CA2000105E8DB8A82352E0472AEA73D3254BFC49
-:10CA300015CC5CC8AD6FDC7FAA96DC7BFF2C4DA7C4
-:10CA4000FB74B7EBC6779DE8334F67E27C6FE2DBA0
-:10CA5000B8EF7FECE7E7985936F6D644DC3F26ABD3
-:10CA60000CE9EAE3432AF9A13F9ECAE36EAFF9ED70
-:10CA700001055D3ED7F0983876CD3889ECAC37B0FB
-:10CA8000EBF1A8873B987F04C12F13EFED65D4D558
-:10CA90004CF1025F8FDD12AEC6D437A533E935C441
-:10CAA000DB249921DE5AFC7DA7B8207FFB872C036D
-:10CAB0005DA0A01F50FBB1075932D69BE04F263333
-:10CAC000667CE3276F5E07F3187F48F679A1DEAC3A
-:10CAD000032E17037D7AE47A1B0B98E0358185AB32
-:10CAE000D1DF34FEA8FF3A9C7711E83B784FA4A829
-:10CAF0007943B507F3EB256A1F0C05723DB09E6DB7
-:10CB0000B56772BF857201EA6137C1F5BC5EB04E90
-:10CB1000F261887241F35A8A2F2AA893E842E1B65B
-:10CB2000B0C41CBCDFB003FADDB61EDA67E1FE0557
-:10CB3000EDB1DFBA336F5E877207E649EDEBF9B905
-:10CB40007C01B4F322BFD42DA2FE8AD74B0CEFB3E5
-:10CB500014D5F37DA9E890EAC3F2C67D8FD07E3B61
-:10CB600003C6EB978EFB50642ADD0BCA9474BA2F70
-:10CB7000191A4CF8EB601C7F6CFA20F20B52BCAB1C
-:10CB800097C0A098E363FE641F42F2B3C0B74CEBBA
-:10CB90000BFDBC96939C6E23BA3A43E7ED4701DE4A
-:10CBA0000180F71B225EE540CE075AAB695FFCC2ED
-:10CBB0003E949F9B344DA2388E852C8FE238668E32
-:10CBC000E7FAE6EB973BC3E8E77B5DED1C88DF0FF8
-:10CBD0005C6EA7EFEDDBB81C6E1FD44AFEF6E3EBEC
-:10CBE0005586F758AAD7CB242F8ED7AB743F567EE5
-:10CBF0008CC731146EE3FAC781F5BCDFE3A8B7E157
-:10CC0000B9079643BE70AB11E7C0E5B4617F16E883
-:10CC10003CFEC290BBE562DD3DF6A175CB3424D964
-:10CC200068795B2EE471098B90BD1C2D77CBF11CCC
-:10CC3000DD837C191D27E6EAB663900E225F105D46
-:10CC4000571C5219DA31D2076DB91497B647A2733F
-:10CC50008BF1CD921FE31A8ADEB18749FF0EE7CF31
-:10CC6000FB11EE2FEFDA19862C1F433C809CCAB1D2
-:10CC700077FEE9A7F0FDE41B0E8C0802BAC927B8BD
-:10CC80001B71BE599B793C4FD61BEB52F03E2F9B3C
-:10CC9000DA97E44061ADCC0226397152F25F771326
-:10CCA000DF1F74D4770C7C66693505B8BF7ECBC1B5
-:10CCB000F755EF66156364D8EF843D04F6811FF5E0
-:10CCC0009BE25D6B5334131D14EF599B22C3F75540
-:10CCD000221EA61AF7576857ACF1718AF74AFA066E
-:10CCE000D338463F46BFDA2EDE6EE81E9EF6D67F6C
-:10CCF00031CE8FD6F9A986F222BA9F1EE3F7D24F22
-:10CD0000CEEFCFAD93605E39AFCB14AC9EF3C18C48
-:10CD1000A1E6731D2335FCCAD96FDA98DF04BF9CE6
-:10CD20003FC531BF09DF8DE380EF017F5737496190
-:10CD3000A784F9235A7916E575E4F30AE17FAE98E2
-:10CD4000CACFEB1A33DE58817C3F234B227A60A195
-:10CD500080D63789F4352FFAFD0BB378FB42688F04
-:10CD6000FCD8F808E74F90135E942315EBD7E652F2
-:10CD7000FD3AC98BFD376EC8277DA4284766545EEF
-:10CD80007784F4A3A2A62349C8C7C0B7EB501FA855
-:10CD90009868D7518E1BFC68F0F7EBE23E2B73E8E6
-:10CDA000A3F17EC6FF46E68BC1D7F2212ED783F5CD
-:10CDB0009C1F83399C5F5FDFA6E20A2F84BF899F97
-:10CDC0008F6FE1FC2A3F76432EDE872FDCCCEFC34A
-:10CDD0001F583F45437DFA7858A2FDA6277F73BDB3
-:10CDE000359ABFAB25BEEF7D5DFDD2E06F838FE14D
-:10CDF000EF6A1CAF0CF814EF4F46F3F54CB5E10F9A
-:10CE0000B7C37CAF791AD603F39DF2DD3B3DAD2667
-:10CE10003909F914CC17283C9ECB902BE50A8FFBDF
-:10CE2000FBDAF38B1A3F6CB7FA477E674FE4F1EBFE
-:10CE3000752AD1FDF9F8B3079F5D207F5E285F9DBD
-:10CE40008F3F8DF1E53DD67E7E27E82DBABF7680F7
-:10CE50006B04E0FA4AFD268AF3FDE8A92333113F6B
-:10CE6000A5BB81CE91BEEADD2C82724E09D37E55E0
-:10CE7000D228D33D01A644B2AF739BF998C76D95F4
-:10CE80003EE3267A2A79D61E9E01ED4B767E3086C9
-:10CE9000E2689677525C5AE829A12F875AC7201F6B
-:10CEA00094283C7E2C5A2E041CDC0FD7B62B7E36E1
-:10CEB000AE4FDAC2DF8F2869B851B59BCE256E74AC
-:10CEC000A8463D3AD70D011DE3FD5D9C9FF9DD02AB
-:10CED000236EAC6D2B9713254D2AD981255BB6B7F0
-:10CEE00063FC70C93B76F27705B79CA1FB10539E9B
-:10CEF000D946FE9460936C397FEB11B7B9458ED853
-:10CF000031EEB0B19CCE1D217F84F20DB1E397CFFD
-:10CF1000175F58FACC9E9D210061E9AF9EF4A07C7A
-:10CF200039D5B2D98370877EBF326EBA479C66C34B
-:10CF30003D5F19A7790AFF018C738F43D835469C52
-:10CF4000EB96BEA447C2FCB2F3629C7374E9E5DBC6
-:10CF50003E7D1CEF11B43D7BFA719C6FD93F3E7E44
-:10CF60001CE3C1D85E27ED77C1A7DEA2386CA3DD34
-:10CF700026B1DFB56F7D92E2D7DBDFB5FBB0B7F648
-:10CF80003DC707633C60FBF62F52D06FB964CF34C6
-:10CF9000F2EB2ED9312595C5D82F8C14E9367C01BA
-:10CFA000F1F3D1F83AD07880E2D63E027CA3FCEBD4
-:10CFB0008ABB6D28E771CC5E116F5B1FFB9E428FB1
-:10CFC000F8DAC6EBAEB91CE57E23D71FCF1B67FB93
-:10CFD00026E0F1DB1780BF7AC32F101B7F1FE13FD4
-:10CFE000004FFBA2F0F769E3C25F3C8A658D7D7B51
-:10CFF0008DB38D5C00DC8C7B100F38FC871CC988DE
-:10D00000E75F525C33E26D8617F79F4F07E3FD91B0
-:10D01000136AE75CBA5FB8C7AE63BC68C99EB789DC
-:10D020007FDA77BC417E6826EE23B4B3AE3F1E3F65
-:10D030002E8975D6B9797CAE803FC6EF7A3DF45D16
-:10D04000C4E9723A36E2777B8BDB959D5CCF36EE96
-:10D050006794D7FD51C4C376E34BCA413C1DF9CA5E
-:10D060007868030EBA90C3DD71E8B1E3A3BBEE2B81
-:10D07000087C21FE701FEA8A3387FCC0B1E4377A4E
-:10D080009BC59007ED1B78FC7ABB1AFB5EB011972D
-:10D09000FE8F683E0D5F583CFAF9E6FF75E1D381DB
-:10D0A000CA4F724F38B5FD2DB61C4F774ADFEC9E44
-:10D0B0006199147D6FCAEB1C87713B4734B483BB05
-:10D0C000EC6CB1DE36E1576F7B4AA678E5550D076B
-:10D0D000488E47CB8B0A7C2F25C67C33C57C2B9A88
-:10D0E000F83ED1F6AC3BEC827EDAF6EF227AAEA8BF
-:10D0F0003F42F1D22F6FF995D66A8A8BC07D226CA0
-:10D100009A7FDBD3FBC690DC16EFB2448F33498C99
-:10D11000136C8E3D4EB0FE8C659CD25083A6BBCE68
-:10D120003FDE29C57F23F677AA85EB83A71AE4E9BA
-:10D13000E118E30F73AAD677A160BFA4F767DCFC00
-:10D14000BD19D91347FAE51277CE3B0949986A14FD
-:10D15000AF55BD4CC477FD872F0DF15DEDBE8AE163
-:10D160007C57227C4D7E1E550F30D44BD5B4BC2C41
-:10D17000F42B44CB1B2DC9C6C226FC2F714F4FF593
-:10D18000D279476420E2F370C67115FBFD4B949F82
-:10D19000EA2F0A5B950AF3FB4B48F22D837ED9DF19
-:10D1A0003E1894E7EED97F971EF163D9E257AAB0F3
-:10D1B000771E46BB84BDE0A4F80679AF93DEF9087C
-:10D1C0003EEEA4F51ED8F1F913A45FFFC2CEF8B964
-:10D1D0000F582F20AF0A75DEC7F11D9F3FFE57D4B1
-:10D1E0009FB1318C5FF838D447BBA13E9EEC9C8E3A
-:10D1F0006713C6A05FA4F085BB66A23C2B8CE7F446
-:10D2000058F84C6AB81AFA3B96CCF3C7B60DA27719
-:10D21000254A9F7553DCE8811DCF55E0BED4FE4CF6
-:10D220003CC37DA9FD05A1E7FF52BC5355AB7ACDA8
-:10D23000F1E3C54CF19AEFF39462DE12AFC4C82F4C
-:10D24000417C84FEAAA604BA0704FAAFA59F8FD436
-:10D25000CE3B7C44C7A1FEFCFE53A43FCA83E87AC0
-:10D2600046F9BDCE21E25E39B47375D70F6A9D05CC
-:10D270003C5FD39FCB9316AAFFB053F88F4579CF6D
-:10D280007E79FD8784FCEEEE87B7AF10EFD044D3F4
-:10D29000EF46D16FE996BF5F1CEB9D9518F3A7EFA2
-:10D2A0003F9458C8867ACA7627BD7F85EF28E07DEF
-:10D2B000859D1A3FD72AF344E89D9BDD421E97C502
-:10D2C00045E8DD9DFE621E581FF3CCD1FA34BD9FA8
-:10D2D000F69C93615C59F90B6E3FE2BB7CE7E7C7B4
-:10D2E0007E9E857189F114175FFEC2FF223A28B72E
-:10D2F00047E6223F746EB7B38DC8E7DB5F1D8CFC39
-:10D30000DAA64606F7F98AF3BAF206BBF5FEBF586D
-:10D31000C7A9AADACBF0BEBB71AFB6A41739F357D1
-:10D3200027D7A35F71FA5F7212BF5BDF733A55357F
-:10D330003B13DF5930EA973862CBC577515E7C13D7
-:10D3400039EEEA713FF55D9CCF47AC2505FD3E15F2
-:10D35000A077A33C2FD9923E10FD04FB9DC63B0451
-:10D36000DE04DC8FF6AB5EB2A73135EF3327AA7C43
-:10D3700099CA30F4DF8CCC54601D1D1BCE14F467A9
-:10D380001847EA9C1D4BEE9D76C6D33A4A1CF69888
-:10D39000F79DCF09BA7A0F8DFE643E1EF28731EEFB
-:10D3A0007E354C72F88E382FD52B01BB08BF976E97
-:10D3B000999369797F45A9A17AC0A704CF62B64E37
-:10D3C000CB32C96F63BCE2A559994A267E57FE4FFE
-:10D3D00017BDCADD7866A124D20B150163B6AE9FD6
-:10D3E000E57E88A2E639107E1ACBD3151949A586A9
-:10D3F000F83D8E3550EA02758BBF5356C9504E9E8C
-:10D4000010E7F6E8EFC2B41B5E7792DC0F0D626C9A
-:10D41000783ABE07E14DD04DF053F1101EE6635748
-:10D420002A1997173374B493A550807D09F4545D7D
-:10D43000353D13E911FEFC180749A607CCCFA3BF61
-:10D44000FC05EA4140A7FC3DBFEFB270358018C330
-:10D4500081C9AF3A99F177E856BFC3CCF6C6A5713A
-:10D460009278E7681FC93117EBFEEB843C8A55942C
-:10D47000B7D509FFC8C1734497CE22A817C6BB58B9
-:10D48000241E52D728E59499FF3D599037D1A93EE3
-:10D49000D15A1ECD1720D7A2C66D20F841BF9F4498
-:10D4A000F5FB4954BF9F7C55BF069C828E8D3E7C08
-:10D4B000A76265559E801B1FCF21E006F01989EFFA
-:10D4C000E8315B9C4F9C87135CE3C46CEC581FF005
-:10D4D0005A1E974E78B92F616F27C641B3A45A865A
-:10D4E00076EF0A89EFD3F097E732B563BA83F8F0A5
-:10D4F0001E314EB980F30AC33FD5A3BE93F4AF1ECD
-:10D50000F59DBDD58F8B5DDFDDDB7CE263CF27B181
-:10D5100097FE6BE263F6FF75E552C50B6FBF86E7BA
-:10D52000B65DF24907D05BF5CCF238D433138FFDEA
-:10D53000A395BE703DD331D08AEF38A46FA0B7B8A1
-:10D5400061D6EFD174D21B7DE58B7540DED50FE03F
-:10D550007093187F6A1D3FF7BE6509F7D38179E89C
-:10D56000C7FA378BFA37390AC9DF70C4C6DFBFBACA
-:10D57000A596EB91B7FC58A6F3E91EEF51E13F8069
-:10D58000DF6E5D2A8523E9B1DED76275783F6E9E36
-:10D59000183FFABDAA00F3E6AE9663BD57C5E9D2BF
-:10D5A000B85717FD4EC5029627DE21B37E3FEBD458
-:10D5B000BBE467CDA8EE7D2CB416E81EF54FA07B2A
-:10D5C0003C97C7EB621417E2D1785C48CB203A4F06
-:10D5D00033E4DFD991DE04DCAF997F30FFAEF3EFA7
-:10D5E0008BAFF4A69AEF1D2AE7E22CEFF554ABBE01
-:10D5F00034946FEA39D05FC154D6CE0D615E533991
-:10D60000E8ADC4FC18BE49722A4D09A35C54F43C31
-:10D6100056887AAF78EFC3A8AF255DD5A567BE0E53
-:10D62000FF6F8E4B26BE5CBCD64BF7B63F8BCFDB75
-:10D6300089F4247B727C01574F7A08EDE0EBAEC68B
-:10D6400075A7F75C4FB5E6F391BE7D158080FC6F42
-:10D650003E07CE4FB67BDFF6E2FC7EA332F4BBF48E
-:10D66000848FEF4418CACF8607507C889C306304AF
-:10D670008EBF46BC6FBABA6A24A52BAA984879BC5B
-:10D68000DC8A2AAF487344EA17E974AA776F551AFF
-:10D69000E55755F92835E0EBF0D5D0FB938E617C4A
-:10D6A0007C872EF0976413F00B90FEE548ABA473D3
-:10D6B00045A75E19C177DFD840D87770597A0DC178
-:10D6C00057D319F935A13EE5ED988754AD9D41F842
-:10D6D00052F44A5608E56FC5078E225C9DDE4B2D3D
-:10D6E000EF5ADAD3C646BD7F1A056F83DEB671B82E
-:10D6F000DF2F717A8B86FBFD6A8B17E322EEBFB2B8
-:10D70000EB5D29823B98431CEEBFE6E7B43DE1DECA
-:10D71000327BBE09EEEEECE904F7FB049CEF1670D9
-:10D72000AD1678A816F0AC46B8537EA4C8FB443AB0
-:10D730009DD27BC4FBB72B111F90CA087780877DD1
-:10D740005488C9301EBA79F1CFEE1274ABDBC81F12
-:10D750002ABBF2FC08777B1287BBC3057820BA0688
-:10D76000B87BB13C44F0545D1CCE509FE341E415BE
-:10D77000847B267EE7F800B8F78D1F87F27082055C
-:10D78000CE5AD2E40B83FB237C7F4B127C1E0DBF51
-:10D79000248DBFAF6BF0776FFA71B588B7AE16EF17
-:10D7A00027221C51AF7908E0C3340E4FFE7DA4C878
-:10D7B000FB284D16F67F35E001CB1F16FA10C21973
-:10D7C000D31FC573FB3CC956B94F4538F5E1EFF29D
-:10D7D000B0A4101B98CD78682FFEA5859817F3C6C6
-:10D7E000F9AFD74A3FB2AE44BD03E97D18E96DDD1C
-:10D7F000ABAA0DCF3FE4A55759EE67CBB3FD895EC9
-:10D80000827F4042BDE63EC1876B915E687EDC1E32
-:10D810005E29E8E06EF1FEEE3D827EEE17FCFCA094
-:10D8200041373E7E3F64CD741EC798946113EF204C
-:10D830004698394E30D1D7C0349817D9365E4AE968
-:10D840009D4BF68E9DF8367E14F3237D25BE7367BF
-:10D8500098BF439BD70FF5A144E3DDD989DEC439D6
-:10D8600074313DA288F720656E4FB6C47CDFB5DA0F
-:10D87000B7DF817E99DEE613EFF3A7AF84F1E26BA9
-:10D88000DD6447F50DE4CD590879572DD8550CCBFB
-:10D89000B97C70C1BC0B4DF411DF8B5F47755D59CE
-:10D8A00080F44AF638A43FA91DEA44F802ACBDE86A
-:10D8B000BF7A48CDEB87FBC14389B1FD70B3E2B9B4
-:10D8C000BFC49375A9C59FB04EF5533B7DA255DEED
-:10D8D000AC13FB439FA956FE30F683CB447F9FC514
-:10D8E000077E140F7496726E2AC9CFA46B63EF0F74
-:10D8F000D5AA16C2F739AA4773BE0EE56B5C6FEE68
-:10D900002177189D839C0D8CD888FE2F83BE96337B
-:10D910002EE7428CEB93C6BA7E86F43E02F7019D59
-:10D92000E81EF701CCCBC334A29B945B6CE47F5818
-:10D9300025F8EC5EC15F6B045F3D807C3502DF81C2
-:10D94000F651FA13C14FEB90FF20DD129FCEF57810
-:10D95000F1BE9761C72C778CA5F71CAB5D36DA0F4B
-:10D960009477ED6117DA05FBC6EBE8F791DD597A9C
-:10D97000C08DE5590E3FC0434ACCD2915E3E732F15
-:10D98000B8E8ABE25B01FDF4AEB0A2727FA49E9456
-:10D99000C7DE1F45A753F49E80AA5FCBD03FFD7022
-:10D9A00052A513E1FC703C8FD3AACDCF26B8033E1D
-:10D9B000B6C59BE2A552675FD5F51E1F76FF702F97
-:10D9C000EF12EC12F2820D0CB16126F9502BDE7BC6
-:10D9D00064DE101B699213CB87E732F4EBF5940FEA
-:10D9E000BDC8CBCD5C5EAE9062CB4B437F37E46568
-:10D9F000B45C31D295174DB7DCA7545D3E46F26654
-:10DA0000646CFFC1EFE3EDFC1D6AE6F3E5A7F72CBC
-:10DA10000778FDDE0C2FD4830C7FC5F762AC275A44
-:10DA20003E9EB8CAD85703F43ED002CDFBF0F8AF03
-:10DA3000DC57ADFB41E1B9D5A40F149CCBA1B4A830
-:10DA4000763AF111C3D318939D7C7CFD0F3D88DF9E
-:10DA5000E3B5E27C7CBD1AC6B8A47D1BEF7A600EEC
-:10DA6000C075C1E3329D8FE33D0DD914DFC2B2BC56
-:10DA7000A4A71BEF231E0FDFEE31C73114FCD4E93E
-:10DA800047FDBF377A2C581FDB7F538DFF44BB8384
-:10DA9000F946A25D01FA5D6704F5BF9F38E9DD181C
-:10DAA000231FDA18EF33C78F18E95BF1D3CE21DCDF
-:10DAB000DF8AF73317D29DAB0F9DD7F4CE177CDCEE
-:10DAC00063E833C773D247459C35C07D96C57FCA8E
-:10DAD000CF498F097F1873F4521E27CABDBD947BAE
-:10DAE000783C13D36397FFD37EA4513DECB421B8A7
-:10DAF000FEF2DAD3ABDEA52FD6F3806211C7BD608C
-:10DB0000637C78790CBE5920EE072F10E75D067D07
-:10DB1000157FDFD0B3395D46D3ADF4D42544A71FBC
-:10DB20001F54C95F5B01F4877A98F4D4787A8F69BF
-:10DB3000D913973D780BC0F993433295979D731095
-:10DB40005DB6FF878FE2FC3B7FABD2EF267C727025
-:10DB50001AC5EBB78BF79EBBF8CEC5EDDA1B5C5C44
-:10DB6000AE149CBB97E8BB8BAEC2F335E4DB82738B
-:10DB70000F905E5680EFBD4EC0758F78799222E887
-:10DB80007702B61F92BB1CEA15B6723E61134315AD
-:10DB9000E48FDE10EFBB37063FDFE0F25AE2450BC1
-:10DBA0005BD750FF0CF4C324535CC802F1FB07851C
-:10DBB00078B884E57A88A521DF08F9D64DFFD677B5
-:10DBC000B0DB9DD6751AE9C2AE754EB0D861DDEBFB
-:10DBD000FC2EE773A16F14B6E6F07975ADE7E7E3C5
-:10DBE00063ADA77B1D13A97D7B62ECF1EF17E31FEB
-:10DBF000AB2AC29B5BAC44BCB75B10BE5DC3F7D520
-:10DC00000AD627F6914CEB2AAC2DB5C42B15D4E6D9
-:10DC1000D3FB7A85EBF3B5DB4CFB53175E42FE97E3
-:10DC2000270DEBC6CBFD6B2E23BCA8AEBC3B917E73
-:10DC30008F3D557CC77B5EEC97E3E984161A534908
-:10DC4000F2EA764FACFB4DF747E3A956E009EC80CA
-:10DC50002C139E0CFC44B73FB6B9FC8EF7F01CE2C7
-:10DC600011FE9A50EFF22B0A7FE9B1E1F7A4A0D799
-:10DC700063A00F042E087EDFB2C4CBF50A3F816F8C
-:10DC8000033EC677D0E7C208B727913793B13F4E1E
-:10DC90000FE7835BF7F8821E26C55ECF6B5DEB59FD
-:10DCA000CA42A0C79CD4B83ED1FB7AEE6221C70518
-:10DCB000ACA78B4FF32D7CFADA9A5B389F0AFC9F56
-:10DCC000DC7F0FD1F5B170BC0FE3547A5BCF6B48AA
-:10DCD00007E362D0C1B0101B95FD7F8F0E4E68FE2A
-:10DCE000118FE03E02FB15EED3C54FDE3FC63CBFB1
-:10DCF000B7E227FD9EF6A59A0B3BA70E4DF61DF445
-:10DD0000D27E27FBAA6149435D813F63FB12CFA30B
-:10DD10009FA19F6E45E2CFC6C4D28B5756052EC732
-:10DD2000F38BEAAAA2CBD18FAA0A3D97A19E9BCEE4
-:10DD30007F1723D67B7DCCCDF1BBB2AA92CE3F9884
-:10DD400023C4F494EE7700D8894CF2472B2EAB7E97
-:10DD5000A6A9011DFDDF9A78A7405502ABD3B3D029
-:10DD60005F94941132C1EF1F2E7EEEB2266DBF8EEE
-:10DD7000E71A76E81FFD608E81CA598BFFEC456576
-:10DD8000415FC093F11C731C6BF04B12F913CF462B
-:10DD9000F913CF5AE69104F3FE0A3B5B7178E81C55
-:10DDA0005261C28F2CE0015F681FBB5BE7EB5C1E1A
-:10DDB000EF217D60D54536B2EBD609FFF4CFD02FE9
-:10DDC0004D7051E8BC01C3E0B0BE96C0D7E1C4734A
-:10DDD0000C19EDAD08E5DDF862974C4F1F4A984FDE
-:10DDE000645E09F37D596415DA0F1D935AEF203FE5
-:10DDF000A03390E606BC7ED6AFE5B084E712798109
-:10DE00008B11CEB57228C30BF57F21776660BDC13B
-:10DE100050F44E1F9E5E84F71202A6F3CE21B48EFC
-:10DE2000EEBCDC337FD15225EAFCEF6F179BCB5F52
-:10DE300071FA2FC679543BF9FB60491F4874BE57ED
-:10DE4000DD75EE9447FBF26437C723D105D2D54187
-:10DE5000AE379D55BC097DC89F3D32F345CB3C7C18
-:10DE600096BC22ECD13AA0533CA732E86398E2B7C3
-:10DE7000211D0DAF81EF663CC6D077FBB8E879F085
-:10DE800098FAB9313F1897E8553E97CBF7E3287ACF
-:10DE9000D82DF1F9878AEDDC6E642119F13AC7209B
-:10DEA0003C6505CF2732E38FECB5778D7327B682BB
-:10DEB000E7759E0BDEC6CFB9A3E733A7F9EE163C94
-:10DEC000EF99D3DC6F3E9E7BCE29BAF8434C77ABFB
-:10DED0009DFBE3515EFC50227DF6A6B75E54E32124
-:10DEE000DDF1E6467A9F60AE9BEFBF7359A78AF8D3
-:10DEF0000F305DE3E756615ADF6DCC27F20D2AFA49
-:10DF00001D6E89846FB81A72B7BE18BE1AD5BDB916
-:10DF1000073B5F42B4051AF45C3A1B32DA35F95E0E
-:10DF2000E679DEAE0B0E4EF1FB478A83D6D5BD6E89
-:10DF300007C1C15827D4247C74C149BCCF66C0A591
-:10DF40006BDDF1375F85FEF8DEE4DC1CC7E80F7996
-:10DF50009C3C9F57349C3EC12290930BDDFE1FB921
-:10DF6000A1FC7AB7FF2E4CCB1C9D839521C437555D
-:10DF700098AF900317A5001C3E1A14B83819E1D1C8
-:10DF8000D2F782F4FEC34E2E0F0EA71B7A6DAB1B89
-:10DF9000E99BBDC8F55AE3F73256ED387EFF8D0098
-:10DFA0009F8F5EE5EFCD95CBDE6BEE22FFB2CC62AC
-:10DFB000D921467A58F80D1E76DBC47BD17C9DF3BF
-:10DFC000140EEF798DF174CF6EDE52D9F2BEFDBC26
-:10DFD000A53C7E95292D63AEB7D8092B045DF7ECDF
-:10DFE00007FD1AD1FDCC5F3A99DE2DD9A9E993C876
-:10DFF000CFF138A7B3F953FD32C6FD4F582D911F0D
-:10E0000069FC516F532BE4E787137DC8AEF3EF5CD7
-:10E010009C89EF9754B4703F67AABC28E33F207DEA
-:10E02000683FDFEF31BF08E1E4F27B5DA6F39A368B
-:10E03000B53243477ABED5E54779907FBDFF5DC4D1
-:10E04000A7E1E730F6DDE7400FC038CEFC5BBC3916
-:10E05000481FF90D4E3FA50EA6C4815CCB5798030F
-:10E06000D3548D294E4CE39803D3ECE5427FAA9D0F
-:10E0700045FA8327274FC3F7C4F39B9FFC14DB1794
-:10E080002A917D92899EF29B5FFD82EEC3F9F3286F
-:10E090004EF75B5B348BDD39BAC19AFF7693359FBF
-:10E0A00011B1E6330F5AF303706D267D73FF1E1E08
-:10E0B0009F527A9ADFEF7D1E60A0223CB6D9493E7E
-:10E0C0004E296DCEC67887D34FBB6D58BEFBEFDCB3
-:10E0D000EEEEDCEAA47725F7BD17C7E292F01D6AE1
-:10E0E000E7462C3F1DD7908DFE45A84F714BB0BB26
-:10E0F0008E40BB71E7A506BD8629BE69E73FF8FDE6
-:10E1000094CEADF630C6519CDEF5E4D3489FA7B758
-:10E110000E207DEC792964C37E43F770FC4F88F3B1
-:10E1200058E454E916AB3D7E42E8011D27B579E875
-:10E1300017BAB8D6BAEE4BC2D67CA7A87F1B337DE0
-:10E140004FC7F810EFAA34DC6737C57EBFFD73C137
-:10E15000174F3DA519742B8BF71E9937A5FBBEE20F
-:10E16000EEEE73DB2503808E4A111643BABF974645
-:10E170008DDB850FD17F92382FEBFCAD4CF03955FC
-:10E18000556489EFE8D2FBAA7C69534DFB5141ED00
-:10E19000BE947CD257F7A5DC66DA67CAB61E48B9CA
-:10E1A00019FA6BDBA2D0EFEB95CD79E2810949F842
-:10E1B0005D6EC0F96239FAE7DA1A5EF2603DD08B23
-:10E1C000C79AE3BD0A6BC7A54D35F1E9D7A54B83C7
-:10E1D0009FCA740E9FE7725A72F11E46692DFF1D89
-:10E1E000BED2861BAEBB1AE1BE9EDF4FCF56589EF5
-:10E1F0000CFC53B6FD86EF8F86EFC1C7C6F9703EA3
-:10E20000D9F8242DDEBBAD3F43F776EEB571FF4460
-:10E21000345C467B387EEFFD81AB08E512F4F7A253
-:10E220006D2CB53F68037DE4C4E4D06B374395D3D0
-:10E23000ACE10F57535C96959E803E25D4B73A3794
-:10E240004BBE8DF47579F6B5A85AFB97513C3A94BC
-:10E25000C7B4378AC3D67EA2F17CA547327EF76861
-:10E26000A4995EA2EBF59D11A2DFB72A5B0A72CDDD
-:10E27000A4EF971DADA178D8E871C819688A3BC191
-:10E28000FDD14B7CEC147A02931CD9225E7C28CF02
-:10E29000D3BBA748974010A597B2A95E84EBB56C95
-:10E2A0003AA6CF4B91076499CB03F2336D8B277954
-:10E2B000D0A6B73EF173A4A3FAD1741ED65FDCEFEB
-:10E2C0006EF346E8BD58E37771DA749E2F69765293
-:10E2D0003CD5E98F349297CB308E13EB3FEDB4D918
-:10E2E000405F3BBDBDEF648C0B6E6BE0EF8A9F6AB5
-:10E2F000E83B59FB8AFD379AEF8D7DF108FE13DF6D
-:10E300004FF5F88B3DB8DFACE071D3A97D2B332AF4
-:10E3100063E0C96897A45566A0BDD279ABCBB7912D
-:10E32000EB53E90AF9DDD3C8AF922FFC49F7E9793D
-:10E330007778A0BE1BEAFAE1FF3E07E58DE877FC9F
-:10E3400040F6DDA10FED3E1F5F9015A0FBE3F40347
-:10E350003630FE7C854514A0B7F9B8AF8CA13CC916
-:10E36000CFF9EB258A235CB0C6BA1E7CE7DABC1F66
-:10E3700016E12F290EC5B8B0064A8BD65BCB8B7140
-:10E38000FFF050BC17C5CB94D459CB198B901FAD5F
-:10E39000ACFE4B7B2CB87DCA8CF5F96B3C16B9A34F
-:10E3A00092DCF950CEA3F595A23700D29BC4FE1C97
-:10E3B000BC33276D01A41D4B27A42DC8C47BEE7C64
-:10E3C0001F23D38EF898BF8F573A954506F1777182
-:10E3D00018EE8FA5CD526434E61D2CE419CBBFE3B3
-:10E3E000FB20B86EF33D3163DDB85EF377F626C7E8
-:10E3F000AB71CF10D76B2E2F137028ABB75BFC3AE5
-:10E4000013EAA590FBDB787FA995DA55347E69B7CE
-:10E41000F42BF65FD8B79913F035A168838C8B790C
-:10E42000A84B8E872F89750FE5B080DF433714F432
-:10E43000437E7D10F5CFFE02C039249F849F804526
-:10E440001C305E5C66579ECAB397F3FC3E4FE08A71
-:10E45000DA8160AFA9013A879A2FE7BD8CF71B4795
-:10E4600026065E42BCCCB7F9072BC4B7FE11E417F1
-:10E470005DCAE1F0F0D8CA4B2A63D9C502BF3F9309
-:10E480001AE85C3EB48BEFA3EEAC4ED5ECF7FE8BF6
-:10E49000904709FB5BE95E4FE70E89EE133F221DB3
-:10E4A000A1FBB68F5CE96568C7A7019E50EE3E22CE
-:10E4B000B115F85E5E56E3AC452F219EB3E27C7841
-:10E4C000DE5FDE38492E77D1FAB9BE155FB901CFCC
-:10E4D0008352E78D1C8B740EEB9E772D7CFFD0E36F
-:10E4E000A5F1FAB938DED39687D2178FC2F1F316A9
-:10E4F000BD847C383A8EEEA1A702ACDC7D285D8D10
-:10E500007A541ACBD887FA60DA0CEF58F4B93FE4A2
-:10E51000E1E324DBE479B350CF1BCBF37D7E2CF910
-:10E52000371211AEA57152ED6C3ACE17BFA35EE85B
-:10E53000403F82CB84EF299519387EEA509E2669A8
-:10E54000118A0F3C64E0BD99C7E92DD119C9E925AD
-:10E550005F4C4A453BEE501B18D420BF0E0D34ECE7
-:10E56000CC888BF4F06123797D61F72DC9E0F75FEA
-:10E5700092061BFA0FAFD7A1FA133251AEBEC1F506
-:10E58000F14F5C7EF2575FA6C58EBF4F48E0780A18
-:10E590009E8B636193FF3838FB33D21383E73C2CA7
-:10E5A0006CDA27F0BD4D731C7759D17EFA1D847249
-:10E5B000D642F701CA1BAC71E797C5C51ED7A0F3B9
-:10E5C000E0391B0BF525321E88F6D721A973D5C279
-:10E5D00024BA174BE73BC1731A0B99C60F9EEB6326
-:10E5E000CD77CD3385FAE9AEC7ACF59A3EA77A2C44
-:10E5F000A7D583E3B4EBADB48F04CF29D4CED86FC5
-:10E600003AC2B6900AFCDCEEE5E51DE23CCFA86F0D
-:10E61000F4D73E5B13F7DEF8BBE86D552078002E8B
-:10E620008F369F217F7459F33E828B410FDDF08935
-:10E630006721137C52AA5B2236E0ED690F6EB87B2E
-:10E6400014D890C9FB051F8736DDED9F08E5F8BBA0
-:10E650000F26BE8ECFEAE27312330FD9642E174213
-:10E6600075774F9D68CA8BFA5DED439BAF980A346E
-:10E6700095358AB7BFE6C1275E594E4E8B1A11DF1A
-:10E68000DF3938CF6DCA3BA2F22EC88F36E5F5A828
-:10E69000F2A4A8F2B4A8FC405EBFCD1D192CFB402B
-:10E6A000DE3FF8D415F8FB9E6DFD2273F1058F3522
-:10E6B000F2B62BF0F77CCBB3F8EFD356344B3EC910
-:10E6C000243F2BBACEF35BB5F9A3100E2D2FA31C5C
-:10E6D000286B9274D4EB5D0DDB2394C7765E53BB3D
-:10E6E000066E3F96351CA176BDF63FD2467C7CEF88
-:10E6F000C8F7A9DEF9CE9FD80CEBEF5BF5761E7557
-:10E70000440A2C4E48EE7E7FBD6DFBDBDDBF2F0A39
-:10E71000DFDBFBF90F901C8DBA071EC4F9B8BAF9FC
-:10E72000C480E3BD23CFD27BB47F1CDDFC16AA03DB
-:10E73000F14BCE2C53A0DD9FCB8F8F437D0BDFB4ED
-:10E74000C57DE36752F812DC8F1E65814B70DC5B80
-:10E75000CB87EFC39F4C38ACB63E86EF956F78F011
-:10E76000E52B1498DF6177EB20FC09B74D096FF0BA
-:10E770007C722B7F5145FF1DE1E7F0A0D64136C8E2
-:10E780003F99C0A6537E78EB63987F3DE104AF3F8D
-:10E79000BA7590ACA30972F28AA990DFACC7E6F70C
-:10E7A000DA04AE371BF39B36DCFF53840B2BE3FB01
-:10E7B0000D5E3376803C9D5B726ADB6680C7DC1F32
-:10E7C000C5939CDBDC76DD55790487501EC611A607
-:10E7D0000A78D37E48725D217DA21FEE817DBAF159
-:10E7E000E91EDCE2A5FDE2D2CAEDA837A4CE1D45A4
-:10E7F000FB45A1C72FE9C9DD69381952A82FE93AAD
-:10E8000097EBB28DE22352EF72931EF5A0F83D0311
-:10E81000E03BA20F97C0CB36B19E6D09DCBFF680FE
-:10E82000671AF5F39EE47FC42163CA424EF2A7C57E
-:10E8300091BE72F306902B20D7D78979AF5B7B0905
-:10E84000F9296E463FF128FCEEEFD76754B7FEBFBB
-:10E850002E03F2AE6EBB6EDD2C7F3FF3B9F6BA0D20
-:10E86000BCDC905BEBD2797B63BF4AADE6E3A43EB0
-:10E8700078C9465C47BCC2287E7BE1EC111B97D16E
-:10E88000FE7F2DAD9FF9FDFDD00E3F5A3CC4867A28
-:10E89000A9819FC2E1FE5712603D3789DFEF35F055
-:10E8A000648C4FB7E2517F90417F403B353140EB64
-:10E8B000077D620C0F6EE0FA04D21633C19729ADC2
-:10E8C000E3F0FBFF2038B5FD2BE0F44F9F7747C9FD
-:10E8D0002190370CFB2F5F7ADC72FFED3F01D123D3
-:10E8E0002A700080000000001F8B0800000000005C
-:10E8F00000FFC57D0B7854D5B5F03E73CEBC929920
-:10E9000064264C9249C8E38440081071124344F0D5
-:10E9100031848851693B50D4D87A71203C022699C1
-:10E92000A8D5624BFF0C12790918342250C181021C
-:10E93000C55BF506458C1A70448A7AAFF68EADB782
-:10E94000576C7FFF08888F4A32A2F5D297FDD75ABD
-:10E950007BEF64CE24A9B4B6BDF93EDCEEB3CFD9CB
-:10E960007BEDB5D76BAFB5F61EA6F54C0A5CC0D8EB
-:10E9700066256ACEAE642C7C48F1ED61F007CF6766
-:10E980003B19FBF7B4A0D595C9D89FF1EF0AC6E6AD
-:10E990007EBF29275806ED8D2318CB612CF5BBCF00
-:10E9A000D4DE00D5B94B3F7A7C0F7C3FF77BA98C36
-:10E9B000E903EF438F8CC1F7EFBC6D5BCF2E84D2A0
-:10E9C000D2193579A0BC86F956C07BEF98584327F9
-:10E9D000F4F70EBE7A096355DFBBE5353691B1DB3E
-:10E9E0005D2A6393185BABF873988A250BDBE0BB59
-:10E9F000F02C4B644F11637D1153D80CFD75B82377
-:10EA00005B17C1B81DD795F9C2D05F1F637E86EF33
-:10EA10002D4BA5F73ADC3D4CC3F64B741740C20EA4
-:10EA20007EA1FA19D4E3375A22BB14785ECEC2769F
-:10EA30006C5F323E1286FAF3300E7D7F634A640FBC
-:10EA4000B6CF828FA0DE71A3371286FEEC2C624710
-:10EA5000783A76FA73321C8CE5AAAC05E1EF28828D
-:10EA60003A94592BD9CD0107E2CF3F719673000F2D
-:10EA70005F7799683EA9953D4FFF37F4C7D6DB7D98
-:10EA800063A0B0E1AB586FCF2678993B5885F86604
-:10EA90001AFC03B8EA1FC889ACC3E7CC5785EBB1B1
-:10EAA000DAE99F47F0FF205547F81FB6B335B60A9D
-:10EAB0002815D666CB00FC0B7858FB43000C633757
-:10EAC000E3008097FFD770D6A9C3F32B5D0AAD078B
-:10EAD000FCF96D558CCD67BC7DFEF2D477958958D5
-:10EAE000AA516B1A3C5B73A5BFC746EFB13F8FE2DB
-:10EAF000A50DFA0B32F1B725EE44BA09E27769D8D1
-:10EB0000FFEF9DBA03EBF0FD445C76F8BE74E0FBCA
-:10EB10003A17A3F9CF5539FCAC355547FC4AFCC828
-:10EB2000B24EC2D7FE903F713C394E72BFF7BAFC6D
-:10EB30003722BE00EFD1740FE245A5754D86D7632D
-:10EB4000896FB043FBDC56D57D37E033B8CC49F351
-:10EB500095F0DE9C1DBF8C150FEEFF746A739586D1
-:10EB6000F35FC6E99D2DB702E212F16219A8035DB9
-:10EB70002C64F163266588E75AF445847F5147C2C7
-:10EB8000F7F4DF2FAC89EF497E61BA9204BFA02B66
-:10EB90005DD170DD820A5F378B253E375036186EA7
-:10EBA00089CFD582EE245D24E37B35E27BD2607C85
-:10EBB0007B2C3DF9D86F709995F094DC3F6311FA86
-:10EBC000EE213BF00FD0DD1645217ADD72576A64E5
-:10EBD00025F2A73DBE17F1193A7C15AD77EF9214D7
-:10EBE0009DC12BDB2C30419433879D9C8F4B7A4AFF
-:10EBF000909F7A61CE7E589FDED7D59D614502C138
-:10EC000058F3EBEA2EA4FFDE67AFE6FDAC48D5195A
-:10EC1000D4438861183714FE432B03BC9E34C52CA3
-:10EC2000345E17E057C209FF7AE15F43C580BCE854
-:10EC3000C3061CBF8BCB0798E1121AE7DB296C1DBA
-:10EC40008CDB6C52FC26686F5E3A3EB292C3614325
-:10EC50003E6A1420359B589B5231C0F7CDA6132530
-:10EC6000B795F1360DDEBB85F17581F78E2A005F11
-:10EC7000A36D7D4C45BA45FA87F6A5D85E3480FF72
-:10EC8000E6F5BFF913C2DF7CC048178D8F19E7B1D5
-:10EC900034919E8A06E824B592E389D5B0C81880DD
-:10ECA000D729EAA9B5B1888A785A56CD4E02E966C5
-:10ECB0001EE99981F4E3ACEC64F3A10C7DC0FC1176
-:10ECC000807B4AF7CE9746C2FBEEDA583E4E37B409
-:10ECD000ECB68B4E5D34B0BE12CE4BBA37A9CC41E8
-:10ECE000E3D177008A7FBF83DE1B37FB82C4F26EDD
-:10ECF000FA2ED3A412BDF6E023E41BCD9FA3C038A7
-:10ED00009B978C32E17AA6827C43B9BCB07DECAE95
-:10ED10001584677F09CAB707D380CE099FBE2A949E
-:10ED20002FA5EEEA5FBBA0BFA7DCD5FF8D258E1314
-:10ED300070E2F44790BE48A6E764BD23DFCB2E6E99
-:10ED4000296F710CFF1EF017E12DBE359DCB0F4DC5
-:10ED5000A1FAA2FF30EF5C47F0694437B76D2F226C
-:10ED600079DCC0DA89DE1A59C482F4BBC8C6C2692C
-:10ED700040178BE0B57428176FB1323D61FD9644A2
-:10ED80008CF546210F6E6131FAFE967D49ED352CEA
-:10ED9000EA84F6261B8BA662D9696C6F667141EF17
-:10EDA0007FB6263E671D7CBE378B7577D744D4204F
-:10EDB000CC7BAB1D745706BED04EEB3365F94E5A73
-:10EDC000CFF40A7FD13DA84F5E35FB7601DDBE272B
-:10EDD000D64BE2E75E57F5BB88F714D544F38FDFD7
-:10EDE0006325FC9C02BD8DEB7F9F9BDD3C1BCADE37
-:10EDF00056DD3B7A34A2C95530DB3918CFEB9EB3D0
-:10EE00003720DDB8DD26C2B77C7ECC65A67AD5DD9D
-:10EE100002FF2B5223BB8A08DD13919EAA46497D2F
-:10EE2000CA26CE82FABB6656D709F5E6EB1D41EC41
-:10EE3000AF07ED07A817B8B9DE28705B687EB22E61
-:10EE4000E72BE906C6A1FE522EE2A584638C5BC8BF
-:10EE500041B6897F27F4EFE625293B49FFF6D3AF7A
-:10EE60008911FD96052C88D7E7845C794ECA9536C2
-:10EE70002B972B9A6BEE32A83FF741996F1DE095C7
-:10EE80009582DE83EF1B3F4AD1919E5EF9E85FEFEA
-:10EE9000FD19B49FFDC0A25BA17D01D218ACDB734C
-:10EEA0000A9747607F30D48F8DC0F6386EE3C1B1CA
-:10EEB000647F1CB408FB46C8CFC6B4E0D685D04FEB
-:10EEC000E393993EA064F6BC39F2E85E6C3F64F7C8
-:10EED000ED817E1B53385E1B9F1B49DF3F610F4E48
-:10EEE00077C33C73AD919F3C8172E3052BD97B675F
-:10EEF000597411C27FB6D3AEE07B27705EE95042F1
-:10EF00009B82F3EA76923D047C9AB310BE3BB936FD
-:10EF10009BCF4BE0E9E48609C4179BCD7CBCF0B3E2
-:10EF20000ABD7FC21C989103F5134F97FB564053BF
-:10EF30005FC012B5003D87EEE3765EBD49DF8178A4
-:10EF4000628753095EB91EA18D8B67627B68E9F207
-:10EF5000AFA37C1C8ECF51DEB304B9D9CBE205C878
-:10EF60004FDB1A467546519F748FF3915A655E5870
-:10EF70007CA01B177FF79499E3357EC84CF47CBEC8
-:10EF8000FDE37CB52AAE7F709C10C86526F98FE43E
-:10EF900072425D1DAACEC8FE0C3D972DEC3A63FB74
-:10EFA000EBCEE01D6EA0BFE6FBFFE79D6584DF387A
-:10EFB000C945D69E497C79CAEC9F8B74EBAE895AC1
-:10EFC000E627E8F30D82AFEAADC2FE63514B221F84
-:10EFD000CAF6AA6A23DDCB72BDA07F678CCBF7C1CE
-:10EFE000ED26C11FDFB4A21E9BC2416685A8471C47
-:10EFF000D8BF4EFD4FF9206AA9877AE1F2A8659142
-:10F0000028914F00DF511BCCFBD45627E76F4003FC
-:10F01000F6B36832237DB94805FBB5029FEB5D3D31
-:10F02000B02EA79F7673FAFA236005F03D8F89F71B
-:10F03000AC60EF821C7BA64D89E27E60DE16EB2E73
-:10F040007B11F2B55F75E27A6E57488ECD6B9B5699
-:10F05000B215EA4B0F5C40EB9F3699D3E5D2889B03
-:10F06000F4E214211FEBAD110BD9DF3F5118F2016F
-:10F07000F44F7674237C945331180F28D70DF41075
-:10F0800049A8835D34A593CB5506F29C25D84B52F5
-:10F09000DEA31C6749F69F913EC2521F71B9C7F4A7
-:10F0A0006C947B522EDFEB0A74B949AE8DCEC6F557
-:10F0B00085F5E47273BF42786D622DA44FA41EE8FB
-:10F0C0001F57E891D36A98EB2BEB262A5F7717D16D
-:10F0D000784B5927E913A95786A383D7BF840E7E9F
-:10F0E000867400ED8D1FB0E865305EE372166D9A90
-:10F0F000C84BE744D28F5C4FDAB89EC432E53CF48B
-:10F1000065B27E4CD687C97A30DBC2F59D5C6769F3
-:10F11000CF644FE776C094E51195C1FC36A6F93F60
-:10F12000CE9C3460D784DEB2D9F40BB11E60A3E06C
-:10F13000BDC569D36ECA86F690C6FCC857A980972C
-:10F140009DF07CBBB07B6BB339DD7B2D9C7ECD5AB3
-:10F1500080953B705D62B4CF8D673217D2A3C4E750
-:10F1600076277C5781DF71FDD4FFBD8DB5A5247C4A
-:10F170005FFD9C9DE4EAE7CF3A2356B24782856E55
-:10F18000E82FEB5756B2537B9F73923EED15FAD0A2
-:10F1900083F628D1CB2AAE5F715D272135558F6468
-:10F1A00048FBCA352351044AFBACC9CDEDACC1F6CE
-:10F1B00090682F8A5DCFE9CA4AFBCCCFDD3D7762EC
-:10F1C0001DE061689FFF8F58E7D081E9E5DF87E7A1
-:10F1D000A180C3C7B11F2C477AB5AADFB9DE06F4F8
-:10F1E00035435D1EBF0BE6D194EF70A19EAB29FCA9
-:10F1F000F52F6F84FA8707CCCC8AEBBC677A1D1B8E
-:10F2000035BCFC5D12319FE849E0975BF619EB4D88
-:10F210009DC67AA8CB582FC8707A4E4F20D9E1FBF3
-:10F2200033D0B5D5DAF2C14E80D7FABC95F4D1A768
-:10F23000EE607106CA5B53FC18E2D95AF8F144F447
-:10F240006F84BA3F51B0B402EDC4CA38FE91AF3FEB
-:10F25000B7CF2B740D81B701FC319B89F00CD63AE6
-:10F260002F49CE85049F782CFE0F5F84F92F9A9D3D
-:10F27000E2BA9B9EF8674EAA427B926064A12D572A
-:10F280007F88FB2D786F09AEFFE959F01EC0D5B01D
-:10F2900085EBC346164B43BE6D06BBD3064B7C477E
-:10F2A000065F875BDAE25551F8DF8E8CDA7108A7CA
-:10F2B000F6272D80F4B11AFB4DB093AFCDE07AE084
-:10F2C000967D76D729031EDD867AA82BC7752A91ED
-:10F2D000FF84FC61798A96B81F7A57095E8BF86BB8
-:10F2E000B2F558A6C1F857FCE93392F78B97CDA732
-:10F2F0007DC4805D6D25F9B4F8AE203D7F692BDFBC
-:10F30000179EDE6AD711EFA7B7F3FDE3E23C47C4CF
-:10F3100006FF7B859BDBDB8BE13B45198CC764BC1F
-:10F32000BDFFF0555EA4A3F7191F2FDCC9ED8FF7C1
-:10F330005D80AF62FE0EF6F77E17D8EF0AE2F9AAFB
-:10F340000F512E2EDEAEFAD04E60879CE48F59BC52
-:10F35000FDCA710B1DD8DFA723A6A15F68C795E87A
-:10F3600089C2F70211EED7895D01CFB51D17931D34
-:10F370007774BB95C3E9B6EDC5795CF12795F84A7A
-:10F3800033B120DAC71D16FF38E467FDE13D337065
-:10F390005DDE9F956BA2F71F57980BF1E15E968596
-:10F3A000CF172B5A00F9B761CB929989F64E6A862E
-:10F3B0004AEB35AD7079568F83F8E97AD4A34DDBEB
-:10F3C000817F70FCD96FFFF2464F223FDD5EC54C56
-:10F3D00009F6CBC35F237AC2BF28E06BB1C0D75711
-:10F3E000E52B6BAAE48B961294A38BEF6E29710D1B
-:10F3F0006157F4F3C5C39C0FEFCB50B8FF202FC368
-:10F40000B0CF186E5FE62835915EB1F9987F0F9402
-:10F41000D9B02DC6FDF7810C8DDA0F64707B5FFBD0
-:10F42000DD6DFB5E87794DCD086ECF807A21F39735
-:10F43000E3BAEB71573598B18862B2BBD8C3566E48
-:10F44000C76ADC8EDE9CC9F6AE4BD88F77627F9997
-:10F450002417F6623FBDC7FF780CF1DA5CF0F14487
-:10F46000B40F42E73EB3A01FCDD1AD903C77F80278
-:10F470000CE925D43D8B2D281B90C3211FD713C920
-:10F48000F3FA5306DFEF843C71EAE7FD119C7F3B02
-:10F49000DC9C3EB72D4B213FE4364FC48E40FFB578
-:10F4A0007C2AEDA525C2EF67DBFD945F45FA8E2827
-:10F4B000AE3158D7397FF435CC8DA830CE87BB8B91
-:10F4C000C9DFD977609A4F8536C7EE1FAD198578A9
-:10F4D000EA32FBF07D87AF270DE7F7E1EE9369385D
-:10F4E000BF86DD2ACDBB21F249D6C2B201B9F033C5
-:10F4F00025F83ACA01E6521C38BE940F1FEEFE34BE
-:10F500006B8183FB0B487F560E8D97A7DCD37E8ED5
-:10F51000DF5F71395F978F1EB74650EE7D6407FD40
-:10F5200096206F3F72727D772A43EEEF3A0B50DFE1
-:10F53000F4D76F2A35A19CF88E8BCFDF63E92C407E
-:10F540007EFC8D62EC67E91A138B806C5FB206500B
-:10F5500003F2E8A3479F294079FFE19E670AE62767
-:10F56000C097FC9D2C7BE578C26F26FDA81E4B340E
-:10F570000FC79BEFB3727FE5307E54F93EDBC2FDCF
-:10F58000A17D3EAB8E7428BFEB6B48F1A37DDBC73A
-:10F590006C24FFE6770BBFACDF3FDA83FB18F97D05
-:10F5A00052FF151E4E4F4A9742FE83D4B238C9E32C
-:10F5B000BF59DE7B603D13E43DACF3BF215F34D91E
-:10F5C000E2C74632A20F0BE2CDD2ECD0503F65AD80
-:10F5D000E4F415BFC344FB2A4BAED781F2EC8A9208
-:10F5E00094361330A227256D22C601F2734BE9FD34
-:10F5F0007035A7FB7016237F5B0E6B51485EBBB85E
-:10F60000DF3E6F3273AD83EAAC11DC9EF132DF1660
-:10F61000B598D65D41FF90C487D40B483F281F3F63
-:10F62000526C443F4AB74276A76AEA9C8BFD0E476C
-:10F630004F1347C8FD3FA7A7FEFA3F899E268F18A4
-:10F640008E9E823AD193D736343D093FF179BFCFB0
-:10F65000C201DCBF660B7CDD27E44EFC0E9BF49BF5
-:10F660002B38DF99A2BF9936475445FDE1337F9C83
-:10F67000E8FF7D18EC5FDC27E5A0FD0EE5C895F3FB
-:10F68000745A3716EB417F41EAC536D28FF79A623A
-:10F690004568AF648F6FD98F74913DB7AC6225ED2B
-:10F6A000FFF2DCA80F50B7921F745975E0D488049C
-:10F6B0007BE110DFCF34DFE5A7E7D3BBB97D101ABC
-:10F6C0006D217B38D4A584719D9B039608DA416B2C
-:10F6D00015EE5F096FB0EB3CEEA3AFA0B8CF0F748F
-:10F6E0001E178A48FF6FCF8EEF23BD3538C8EF91C4
-:10F6F0001C3F3AF885CAC71FC368FC8E721EAFEA6A
-:10F70000B85AE7FE15B17E1DB3FC396EB407D618A2
-:10F71000F959C685FA9C8018186FFE7A3BAD43AE46
-:10F72000CAF1CCD26D5CFF0C960BE467CE9A2C1616
-:10F7300046C46FFAF91C2405D67345BB8C3739CB08
-:10F7400002456879BFBBE9B7AFA400BD66A19F8E33
-:10F750006FCAC268F7937F98D7C97DFCA00900C91A
-:10F76000C5D6FF5C577369425DBC3FF0FDDC6B6B37
-:10F77000F248EFF6B723D8A08F65DD6FD7311E357D
-:10F78000D0AE81BD6BEB52F8F761C7B5578E063C22
-:10F790002872FCFF5CEB477FA19D19C64B844F4B41
-:10F7A000EADF0CFD3B74F97EBCF64A78E1C10A59E8
-:10F7B000BF66AD1FE0BBCF6CEC8F502ABEC78A1C62
-:10F7C000EFD6AC6DEBD6E70DD8056027EC1A913972
-:10F7D000601FAC7E7B66FB853056AAEB530BEA5D5F
-:10F7E000A9E7431E85EC8F647E3D20E4C3DF2C57E0
-:10F7F000F54176F4811124577B66204BC2FE83E4E9
-:10F8000076687980A13D07F64817C2DB7BFCE3D31D
-:10F810002F427BEFECDF1F1BA9E37BB7CE45BB3745
-:10F82000744E23BA0DED53230AD0AD4DF00BE871A1
-:10F830008A0B487A5AEA1274EA0E338C73741C529B
-:10F84000268589BE5A0AAE83B5CCF7F85F4238E404
-:10F85000BE3279DEBF1EC1F70FA1D2EAAD25D8FFB7
-:10F860006E85A19DB0AEF444D602DA37BD9BB530AB
-:10F87000E1BB255D0F123E97EC330F89C75F8FE028
-:10F8800071DEE6679FF6A3DCF828A2904C68D022D0
-:10F890006BA740BDA1C1849620AB8CCCBB91E21C70
-:10F8A00075163606E67704ED268463DF37C353709A
-:10F8B000DEF04F8147DB028B489F6EABB339284E99
-:10F8C000543AFF56C2832BC58F7858575A9D83E30D
-:10F8D00034CF9AE1A2F808D871D8DE7CD7B7C82F08
-:10F8E00024E15AD765AE453BA70AECB9A700EEFC68
-:10F8F0008C6B6A7DC0C723D5FDE5B73B305E3EB457
-:10F900001CFF6E26A78B362510FE4625F94159A20D
-:10F910005FB3B08BDB8D9F8DB018E22B9F8DE0F62F
-:10F92000ECA5E1D874249FC35A4F2ADAD321E6FF0D
-:10F9300004F7CF2CE0D0F7D03A7179E469D5C93F0C
-:10F9400066F3F4DC7B21B65FAAD1FE85693D0FE04A
-:10F95000B8BD6B3DBE754CF001D6EF2AA37D4FBDFF
-:10F9600027A87832F9BC707D7B9FBDAA1CFD88D288
-:10F97000EE5AFBA89DF4E65AA77E7F2DCAD3DF6915
-:10F980003C1FC0168F4D877E96FE3E83C65D6B8FF3
-:10F99000ACC5F50FEF54A9BDD8117460BF4BBEB90B
-:10F9A0006522D22B73444A508F9A3DED0CE918B66C
-:10F9B0002BE42FB179020CE3C4D3C3F33405F5452E
-:10F9C000923D331DFD55B45FF190BFB65AF0C71894
-:10F9D000A082D3366285B63F8F18B06F5EF9E31C04
-:10F9E0000D1F4ABBC764E3FEF39ABA1486F62D5B7B
-:10F9F000153F66427FBD27C6D00E6EEA54689CA6AE
-:10FA0000D2272DB86FB9A593F37748EC33007F0563
-:10FA100068578CF1A40A7BA08DFB3958ECD848C4F8
-:10FA2000F3637C3D1983F712FCAB8CADE0F240F43C
-:10FA30006711718626E157024D48ED3E8FB45BEFAA
-:10FA400016FDB7F3528CBB5989F955C46BB962F0F6
-:10FA500087CBF22AF17DFA91F80CE4DF38D017FA5F
-:10FA600097B62AB36EFD29CC6FEBA4F13E34C1BC2E
-:10FA7000404E6A053E075204BC57767D3203E98644
-:10FA8000D532E2D7E6AE696A9383C76FD05EC84EBF
-:10FA90006DD989EDD93797927EC6F8C86C78FE3556
-:10FAA0000FE7B31C07F7D779EF0E1761BC33FD489A
-:10FAB000E0D69FE2F817A490BF351BD6C69941E562
-:10FAC0001AF46F7959F98BA87FBD33F50A8447C6BC
-:10FAD000F5302E38AB8CE438D5337C8A7F179437D9
-:10FAE00078DC340EECEF6A115E7C1E710CC419D107
-:10FAF0006F87E3621C0FCBDE9CA8467E7ED0E77B3F
-:10FB0000904EBBAC2EC4D7CCAE97DF427D3BD3C664
-:10FB10003A29EE9A64B7C4D3BE19443AED3B737ADE
-:10FB2000C73D08D775077D94CF92648F5C7139B754
-:10FB3000CB3FDA93AA233FEC12721BEC471E7F796E
-:10FB40009CEF2393EDC8EFF6AF2FB723FBEB7F7746
-:10FB50003B92C317DEC3F328A47C0F897D5F5FC38C
-:10FB6000D934D45F2B3DD2AE4DCAF7D82DF23DBA71
-:10FB700087CEF7D076F2F80F864149EEBA2D22AE45
-:10FB8000E5F7CE43FF87BB84E4C02B7B53C34837E4
-:10FB9000673BED6497696E4B14E16A7BDA1AC13CEE
-:10FBA000883645E0EB90885759441C2CA344478382
-:10FBB000E2A02540723FFCA499C7ABD2228FEE850C
-:10FBC0007AE3E11C11CF62D47FF8D954C277638AFB
-:10FBD0009E8EFD37FEFB088671AA3E180FD7F909E5
-:10FBE0007B70BB87E25ABC7FF68255E7F1B3688928
-:10FBF0001BF0B033C2EDBF93A5A6A805E6BD93895F
-:10FC00003C9FF532AEC5E7D9B761248FCBA03182D6
-:10FC1000FBB2B5DC5F542FE35587B91FAE5EC4A5B8
-:10FC20004ECE5EF408A658B4292DB5B84FFB7CDD46
-:10FC300034F29FDF79FF2C2AEBD718FDFD8BD03FE4
-:10FC40005F3C103F967EF7F9CC67E1F6F380FFD07A
-:10FC500004F68CBE46AB46FD59C45C77A33ED0C3C8
-:10FC6000B07A1743D906251AF10A6019DED3D67A7D
-:10FC70005270BD57B799486F85DB4C7E7C4FD2CB15
-:10FC8000AB1EAE67DFF570BD03A88EE038B26C33F3
-:10FC90008B7883E86F053345B13429BC5CEDD26ABB
-:10FCA00087D2DFB2BF36738B6D1ADACDF926F277C1
-:10FCB0007F6EF1D791BF38A384D6A9CDD9B2A696CD
-:10FCC000B7132F7D6E8F07A8FD328D1B964CCF404A
-:10FCD00079FA8287C71792F1B6B0DD584F8EC32CE0
-:10FCE0008918EBF52C3836A798C70D129FBF20F462
-:10FCF000C4E7EB8A04BE7D1694BB72FE2BF238DE9D
-:10FD00004CF9BC1C955F5D8774300AE3CA45587294
-:10FD1000BF2ACC84E01F75994721FA4882B7CDCD20
-:10FD2000E929BC96FB21FF5AF893E1FED09325F810
-:10FD3000D8EFC5B865BDCB4271E8F3F597A4641A56
-:10FD4000F7B7FDF5BFFFFE96EFE7D7AA22BFC6457E
-:10FD50007269BE8BCFE5A4E2DB1BC5E70EB01F7056
-:10FD60001E6BD50A9423D3BFE9A079341F063982CC
-:10FD700071ACE53D05A8D79BAB7B4A305E938C5FA9
-:10FD8000845693F20CDE9BEF81FD08DA0D6B8CF14B
-:10FD9000B8C1F1557F616626EE7B4EEE7F19F5D72F
-:10FDA0007E3BE92FF8BF17ADC8FFCF16915C8B38AB
-:10FDB0008363312E144A89EEF87111DA31DC8E6AD0
-:10FDC000EAB6EE443B717E5B427C0FFFB3DE18EF78
-:10FDD000636B32C8EFCE3A8CCF1B1E4EFA6E50FCCE
-:10FDE000AF9DD665B325380EF91DF410E51D9C595D
-:10FDF0006262B8BEF5AA6F112AA93376A37D7EC6CA
-:10FE0000C9D76B46A6D43F3EB2BFFAEB83D6D957CB
-:10FE100082EB5C6F62C1C47E9A709D617D1BC53AA6
-:10FE20009F79FAE2125CE78FF75F5C82EBBCD9DC6A
-:10FE3000EE47BE297507AF41FC9CBA3240F615E685
-:10FE4000EF201F9D2F3DDE94448F37FDE3E8B12E58
-:10FE5000311F32593F36F4E3CBA81F3D163D0FE565
-:10FE6000C17C9BF52FEA49FC1BD29F67B392FFE34D
-:10FE7000F01F3FDD48F918DD2AD927B2BFC35AB0B9
-:10FE800018EDA3C36F797D6165F8FED385FDE5B5F7
-:10FE9000B130FA59E4BE40DA97C9F278B998CF0385
-:10FEA00099FEDF8CF81BE23CD27FDC20DEB1453EC0
-:10FEB000E576EF6EC5C7FDC79DE44F6E3E34CF8536
-:10FEC000FEE20F22DC7FDCFC7439F98F97445E8AF6
-:10FED000623E19EB565CB81F59B2FBDD34CC03907F
-:10FEE000FB5ED8E7DE9F49F935C6FDEF07919369C0
-:10FEF00098370070BF8F70A77AE216A4FB66D8FF10
-:10FF000061DE60B3163F86FD367B18D905955DC668
-:10FF1000FDA08CEF6E0B5848EE6EEB562228AFB367
-:10FF20002CC1A23CD46B2CCF753A7580CF2299FEA0
-:10FF300017907E07E2EAFE5D5897FEA79EADE94462
-:10FF4000BF3D66E677A13CDBEA14F24C23F9F6DB11
-:10FF500087DD91750976C36F23DC4E5822F3C134D7
-:10FF600016D560BD16CDF11FC7F546791F4D92F726
-:10FF7000897519AFBF8545492F35B19EFEBCB0C408
-:10FF8000F792E3F9180737F4C35ACA75F493DDE41E
-:10FF9000F0519CABEBCF56637B98EF9B811F96553E
-:10FFA0000CD0AF5C0749BFCDC21F1D6A38B10AE94A
-:10FFB00037D4A5B8707FDDE8E3F4DB08FB2FCC9BDA
-:10FFC0004DE677D669CC131D8EFF7FDDCF779CFF82
-:10FFD0007F3DAC9CFAC7F85BDFEF973F9CEFE5FCF9
-:10FFE000A5FFBE7F9EDD0AE7CBA47925EF5B93FDDD
-:10FFF000EE72DF79BEF2F08B247C7CF10FC6C77005
-:020000022000DC
-:10000000F230256BE8FD42725CE3AF9687FFE0F8C3
-:10001000C623871E4A3381A8585214F672BBCE6F8E
-:100020008817CF501D7E1E3755793E4572DC5D9F87
-:1000300021E2EE9C9F5F7A5AA5F56A12F1E1A64390
-:100040004E1FBEDAE0584CF1D9E4F8E952B67F060B
-:100050002E51721CB511F9B8F8CBE3A91765393DDB
-:10006000249F745684790AC9795A2F393E1D114C40
-:1000700058EFEA32D8080C41D7362DCC32129E4FB9
-:10008000CBE2F6F44B229FC86BE1E705EE73A6FACC
-:10009000711FE335F17CA77C4F607AD62494EF0280
-:1000A0009FCFDEC04C809747CC9D244FC24D0E1F82
-:1000B000CA3FE9C791FDEF10718BF3A5F36F671984
-:1000C000E9BCBFFE4FE2FB8592BEFFDAB8DD16C089
-:1000D0008D811F18D1EF6B18672A1A4CB7C3F533FF
-:1000E0001CFD2ECB0ADC9E4578F14FA4FCE6F39470
-:1000F0002FA995F193E82F6207AC3AFA376DE2FC2D
-:100100000B5B9F23F6EBBEAA599497CDCF8FC87394
-:1001100036C3D98F1BFBF99FDB8FFDF5BF93FDC85D
-:10012000DC81769CE7A9697ECAFB5FED04F8715F0C
-:10013000F8A875C8F32CF2DCC597F95DF6F6C3CDC7
-:10014000E96AEFB070FF63E5E793FF34F9F9FB3438
-:10015000F4A30EDF4F58E47BC6FC229EC67625F83A
-:10016000B743319EAFF79280573E7F44E8C5F46CA9
-:10017000FF515CA78F8FDB6C2C1D4C9E4A2E179B6A
-:10018000030E8A2F3477F2BC97E6E58CE47733FAD6
-:100190004FCBD0AF388BA1BD373523F833FC7EF57C
-:1001A000DB8EB09A8E7EF7D90CEDBBDEE3BCFEA9E8
-:1001B0003BF8736C0F2DEFA17846C7EC8F28EFAAA0
-:1001C000EACF9FAEAAAD2478C98FE0B11ACFAD7C3B
-:1001D00091C5E30FB2FC43BF3CF1935FFFE3069E82
-:1001E0009F1DF2F85DE88F907EF1543D467EA6E6B5
-:1001F00003DC68AB52F97CD8F7F3889E9A0F4C2B3E
-:1002000047FF29EBB497A39D5BF52B07EDF73EBEA7
-:100210002B97F224EA3DC10F513E3A2B2357A35DA1
-:100220005A08E3A0BDFBF1FEABCB116E29FF36A34C
-:10023000FF1CC6DFEC34FAC7998DE7D92FDD9B4F41
-:10024000FBCB6247F053EC6FB39DC311DE23CEA30B
-:1002500008BF7932FF4BBECF564D344EF6B76D1402
-:100260002F977261B399056DC503F2E478962EF26B
-:100270004C445E63F72C9EA722EA0E8F31BFF381B8
-:10028000CC2B8F233CC7B3B4AF961FE618942F40F6
-:10029000FD627E18C505589CFC2DA9E7B81D3DCA16
-:1002A00065217A7202DF519C06E809EDF94BE3B152
-:1002B000E9789E6B7447F452C4F3E17326C2933617
-:1002C000EB358AD3A42B7CBCE2F53D6BC7A21FC6DD
-:1002D000F5E665B8A47ABBAB1A513A3523909F4D29
-:1002E000FB8C96521CAFFABFCC3C9FF2502AF917F8
-:1002F0003A0A1A299FB2F76DABE13C4E7219667744
-:1003000053FEE4A8AE5F50BCC0794019322F76721C
-:10031000B683F0D61C8ECDA01C9B4B3D2467B54305
-:10032000BFA238B5B6564309C4DACC7E139E430B40
-:10033000AF60E4EF1CD3E132E17A158AFC98BEC3CA
-:100340007F9818A4FD8A8C0F44787E93B96715EEC8
-:10035000C3B4153D9787713D0EB84DCD65D85FBCD0
-:1003600099FC2D875219D24F6157F1DD53A15EB828
-:10037000C645F1B0BEE76E2924FF2ACC73CC10F33A
-:100380002CCA36F3FE0FA59A509F699B980F47D54C
-:10039000DC59D504F78350877E468A3C55193F4582
-:1003A0003F14EAA9F4ECE0D7303FB6FF1CD2B214F8
-:1003B0007E0E49E3FE12E7B2B71FC7F33D3B2CFCAC
-:1003C0009CE791C3136693DF6FADA6E03A7CEEE63F
-:1003D000F99437669B0CE74206F07F84F256471D7E
-:1003E000FA05D76B3016F6AF9939BD686B3D3BD136
-:1003F000BFB8382D4879BA97B545558A9FB94E3D53
-:1004000050AB27EC73B6703DD3BC8FEFCB93F73571
-:100410005FA65F6ECB36DA2DFDF57F92DDF283FEAF
-:10042000F1FFC6FD0A33EEF392ED97E47DDD203B4C
-:100430003CA9BFE1EC18998F523D300EB7A79DD271
-:100440004E0A1BF275AA1DE27CA1CDD8FFE5235C04
-:10045000345F99BF93B5525F8179FAF11F30F2D7BB
-:10046000C93CA27035CFF7099B6C74EED0CBDA296A
-:100470007F68248B2A0AF9D37AE87C6D36E611C1AD
-:1004800077EBB24751BFDB996F8D4AF25257106E2E
-:100490003BE69F50BE6A64EB221CE73A078D63C7B8
-:1004A000FC938B3085C0BF15E5EBF4061E5FC805D5
-:1004B0007D8CF49B3B9AD3A1BD8EE7A1C83C1399D8
-:1004C0001722F1502DF09B3B765111CAC1B54AF06D
-:1004D0005171AE99CBFF0D4E715E19EC6BCFC079A7
-:1004E000E43EC6FB0F3798F8796437AF778CD1F9C3
-:1004F00079A02FF839BB8E729E7732283F2509AF3D
-:10050000323FE5C9B4E011E497E4F3CB924E12D642
-:100510008FCE476F3BC4EDFAEA060BCDA36FC9350A
-:10052000E497EC5B6262A8FFABBBAD9CEE92C6DBCE
-:1005300056676151EC578BD8517ECAF5FF32BB1616
-:10054000D6B514FDBE475A6B2F3A05383EDA1AA0CD
-:10055000B2CFAE74AA17D2F9D2B928A99ED8F2F9AF
-:10056000B55A0EE6DBC40B142099E7B77E3493EA44
-:1005700099F177B0FEEA16CFD73490C37D63E23BA2
-:100580001478FFFF797FC4DB911673197BF7A1877D
-:1005900066861D5F41DFFD9125E7719C41BDD3C497
-:1005A0007A56C5C85F24F45D2597875E8785EC255C
-:1005B000AFC83F6535221F15233B505F99534E71DD
-:1005C0007B07D30FC4B03D8F9FCF8276A2FF956388
-:1005D000B87FDA26E882E549BF544F18E5DBCA2226
-:1005E000377DDF2F8F0F5823DC3FC6C77FE3E90B32
-:1005F00028BE25F36A1973E5CFB980F26C0CF5FBC0
-:10060000ECE21CA6E6CAC773EC2BCDC2EE15F5369C
-:100610006730C58BF3443E047BEE8D2BBF5B867C3D
-:1006200074E6E0F747A35CBBCA02FB8221E4D8EE84
-:100630001C2EC7FACC8E350A7C57E30C8EF0C2FA1A
-:10064000BF953A77061E29A81B31CD82471758F867
-:100650005115F19A29E8C43D87C3E7AE0928987778
-:10066000BAD2CEC7CD0C6A7E3AF7109CA35C077055
-:10067000AF54B8BC868FD2C98E2AD5D3F11C61A3E2
-:1006800038D7AA0AB97149E72615EDF59FB7BE35E7
-:1006900055D306E0FB858887FFA2C8783EA2DCCB55
-:1006A000ED6259CE56F50B90FE56ADF0BC36F31206
-:1006B0007CCEE9F8CAB4659598A77D556A4B25FAB2
-:1006C00069073D4F87E76509752B7FAFD1162FC0AE
-:1006D00073E60BEDC149888FCFE7BD7B27CA873B07
-:1006E00073DF7807F324DE300B3991AF88F5EE988D
-:1006F0009E06EB79ACD82DF23C6C440FC7C6723F16
-:10070000647F1EDB3885F2FA66CEE1E749AF65B15A
-:10071000B61EF89E9C15D03E637211D9913345DE0A
-:10072000C58CB70269E8179871435C43393A9C5D00
-:100730007495D7ACF724F0C3D5BAB17E6DA9B1FEDC
-:10074000359FB1FE8DC97F1A9B587FD9EE9F8DF4DE
-:10075000F4BCC2F33EC3973017D1BD4709A3FD32A5
-:10076000E1995C710E97E727FEABD8773D3399513D
-:100770007BD63EDB2E3C3720FDD7AA689FE065B6CE
-:10078000C20C7EEF03EABBB822F21C3D14D3610712
-:100790006F75713F2EBC6B817E0ECED3893FAA460A
-:1007A000DA52904EB21C267639F252A58DEC9A237D
-:1007B00082EEE4B9EA2A8D0530CF02869C83E51BE0
-:1007C00066D78BE8A70E7FC818E7DB691AE55B8A56
-:1007D00031185B41F587045D1F91F2FF079A585766
-:1007E000E04018EFECFA5C1E872E65745EFE6C65C7
-:1007F00009D525DD4BFE01AE1E8DA14145F427E94B
-:10080000F9A74E0BD1837ABF49F8BB34130259EADA
-:10081000927080B8C9423DC9C8FE9571BA7C9B6C84
-:10082000D7FCF87E0E93757EDE2B4BD4A1296AAAE5
-:1008300040FDFCF2EF487F3B7C419C8725CD46E79D
-:100840009386E3A35D827F7625F1914BBB9AF8E80E
-:10085000A7CE923B08EE6B9C2ED4AFA53097BA0C76
-:100860002AFD232AF03BCE4F6A8A4F47BEF966ED38
-:10087000F1A95A829C86EF9BF8F7A9C6EFBDF07DDF
-:1008800046C2F769F07DD9E0EF773B6D51D344EC78
-:10089000A74AEF217D18A5C95E23E6AD66F1EFAE4C
-:1008A0001179B1A3D3E07DD45BA5C63C1336D967DB
-:1008B000A3FCE4A4BC92AB94E539C85757DB9ABAC1
-:1008C0007BA0BF97C53A5E650A7EE682E72FCF2DF3
-:1008D000398AFC576B8B6898D7772D8BAEC2C5EDE4
-:1008E0009B167CC45D4CF2E159E4936635383603BF
-:1008F000EA67CCEDA36F2D22FE79CE9B39185E49B5
-:1009000027125EA417A43F492FC970F7AFE7D73B62
-:1009100029116F3BD851584ABB8AB1169E77ADE773
-:100920000FCC0B886886AD6534DA352F2F0993DC40
-:10093000B8CAFD00E565BD9C1BFC4F946775177E2A
-:1009400052A0E1CBDE796371DF00F0C6FE37E1959E
-:10095000F6E3A0BCE30F2D86BCE3E1F84C8E1B420E
-:10096000BB50C5FCE49D94471C9AE3F0E1799110DB
-:10097000E6C15652FC8AECC2E7146E6F87159BB035
-:10098000E3CE373F99717BAFA9DFDE33E4D77794AD
-:1009900073B83B6ED5E5FD35DC5E9CC7B83D394B81
-:1009A000B42F7451BBCCC3EFD8C9FD861D4F8FD572
-:1009B000B15FB003C97E60E9C2CE2C32DE9B837F7B
-:1009C0004AD640DEF86633B75FB7997C5594E76244
-:1009D000E1F7E29C91FE8C317CFC64FF626E8E62DA
-:1009E000884FF7D7FF4EFEC55277303F07FA5B5866
-:1009F000E62F504C0817F733027D3E1C6398FED655
-:100A0000321AEDFEAB59CB9BA662A2CFE21CA4CF5B
-:100A100009409FC506FA1C9D93C9E524C225E9B388
-:100A20009F2E4B93F3CA8217603F1DEECE5F35A316
-:100A3000BDDC6DF5F1BC5A9E27982C0712E059A039
-:100A400071783CAA4AF04CC27193E1391F3E49A427
-:100A5000CF6CC6F961387EC9D658D85931C02F2F0E
-:100A6000DB8335087F3FDFACE2FBA34170AB0EA216
-:100A7000AFEB6FE47194502AD747184FC981F167E3
-:100A800089F1AF5FCBE9F0FA7FB110DD02F8518454
-:100A90007FB6689FD5DD447954B36BCC2712ED0047
-:100AA00019B7A913EFCDF1949B9105E6CC34C64B51
-:100AB000EA6EE2F19AEB588B19E1BD7E8EB19F3A56
-:100AC000B6FE13CC0BABBBC9F83C98D31F67198B90
-:100AD0007196A3C28FD007FC82FCF4D3CCC50FDF84
-:100AE0000AF43BF6876515E877BA326BC9EE4D50CC
-:100AF000FFF1B6F154FF69D6B7BFF306B6EF28A1F0
-:100B00007A0D26B9E13E08F911F54DD58DD714C1FE
-:100B1000B847EDA2DF5BF939026F4AB06316BCE754
-:100B20009D388AF2216B84BCE95BC8DBAFBDD0C9BC
-:100B3000535E6FD6C9DF5893C2EFF579ADFCBF2B7A
-:100B4000303FB76694A8573C3F1EEB47954FE81ED1
-:100B500080DE268786F86FCEE57EDA09A54A741C0A
-:100B6000E0A52643F4DFC4E735B3E2D15CE48F9A15
-:100B70006ADECF04DFB4B5C5F89EE92CD57B736D72
-:100B800069280F259FB5E770FD2CEDA980E0FB6774
-:100B9000FCEFB68D807E0336C587530C4C7E97DF05
-:100BA0005FE5E0E7CB02FE220DFDBCD3FD3C7FB349
-:100BB000DAB62207F7E75F0F5A2A715E2E5BF9510A
-:100BC000B46FD2274F9B44F9BE3666463D0774DFAB
-:100BD000417C78F1270569486C0E23DD4BBA9A25D4
-:100BE000E9BDC648D7C0AFDB7232BF5C5E1BE8DA36
-:100BF0003E40D7C3D9B900D78F09AEA946FDD53F2E
-:100C00004E125F268F3B9CBCC0BF44793A005F27E1
-:100C1000F15F1E66C515237FB64BFEEC42382CA64D
-:100C2000189DB329547CE3E960EA307686842F1F4F
-:100C30007DAE1583E1C23F4DDA7FFCCF83FBF23CF2
-:100C4000D10EDFF959C6005C30FE2B240F577178A6
-:100C5000B62B2D5CBE087B5CEEE79BE57CBB8CF382
-:100C6000AD4AE1E7DEBDE87721DF7BF9F87EB8CF5A
-:100C7000631DE47C42426FCFB1059C1698DB75EE94
-:100C80007AA29F1B58F869B48F963983FF17F174C5
-:100C9000C4143E84FB9C85CC4FF157A08F77721211
-:100CA000EC0D096F329E9A8791A7C9F349C6CFC050
-:100CB000BAC5C8BE93E7D8FAE77B9EF3947689C796
-:100CC00062F4776508FF5486F0472145A17E9EC9EE
-:100CD000527CB82F98EE53C8BE98C96C249767D63B
-:100CE000727D9EE1E0F687D4FBC3F1C7159733927E
-:100CF00057331B993837C7E7954C87D9ACE70E2C8B
-:100D000067DAF4AD0B90EFD14ED107E09FE9E07EBA
-:100D1000ECEC5C213F58CF24D4F3FDF5417ABE675B
-:100D200012CA9FE4FBC9669EE3FED28C738CCA99FB
-:100D3000BE7727A19ECFA8ED998472CCE9F27B7390
-:100D4000270DDC1F988CC7D1B92619873B2FFA4C89
-:100D5000E61F193F6B7306C7E238D2CF714689553B
-:100D6000E14B151E97E83F588474EC76154D43FF10
-:100D7000C51C1BE82318BACB15BC3017E9ED8F0052
-:100D80000F6E0EF155C0E37535C17B343E2CE1E1A9
-:100D90003681872B855E3DFBB04AF1891A7FE94396
-:100DA000184208BD626611E2573FE94579BFD8593C
-:100DB00030A0A2F8FE634EB23316BF5A4FF195B180
-:100DC0005B4C4C4FD093E32229867B3226ECCB3010
-:100DD000D42FE8CC35BC7F61D728437B7974BCA184
-:100DE000FDA2572A0CF549B12986F72F7EABDA50C0
-:100DF000BFA4E71AC3FB533F986DA883C6D070DE2B
-:100E00007B9F55D83698F765F16F19BEFFCDB6199F
-:100E1000AF60BCF3A4D8F7B2B03F560A785820E9C7
-:100E2000F6DC7C637F5125AA5421DFF3BF05EB7903
-:100E3000BEF634C05C62BF0BDB8DF6C4E22DC67A11
-:100E400043F7A655281B07E779B454E35539C97908
-:100E50001E35AE7926A4CF502ED817E31011EC62C0
-:100E6000CC331B8ECFBF6CFD4BD8E82F5B7FFEFED3
-:100E7000160BD9F58B5F7DAA2A0A8FAC5EE3FADBED
-:100E800075E3FAA7961AD7DFE933AE7FFA64E3FA7F
-:100E9000BBFDC6F51F516B5CFFCC8071FDB3EB8CC5
-:100EA000EB9F1334AEFFC806E3FAE7B718D7BB7061
-:100EB00099713D8BC24B0DEDC9EB2FE565F19ADBC6
-:100EC0008CEF017A4D097420E96841A081F277C660
-:100ED000B47FCF304E323DC0BED144F7BFC13E6E6D
-:100EE0009B72FEF401D28AFCBDC9F4F16FB9C2EE67
-:100EF000147401FAA813E50AD8174F61593756D868
-:100F0000FB81A1ED0B29BF12F579E2BE7838B93625
-:100F1000484F897DF2B07A0AF7C9F6817DF270F404
-:100F20007B1CB38FC88E5A4F7EA51B5D1C8E4FF164
-:100F3000D125E8CF7D82F4F271007032C07B1CE7CE
-:100F400003E31F4F9940FE8D6FB328D9EDFF82193F
-:100F50009630D8CD98A8ADE23D4F3A95F5426F2F27
-:100F600014FE8F85F6E05BB9DCEF519885E3E6C5AA
-:100F7000E8BC147B6DC479DD237102E30820784F4F
-:100F8000611C01CA5E3BA79BD352AEF899EE49C0E3
-:100F9000E7FCE94A29D9B56A0AE53DCDBF4121FD03
-:100FA00034FF7F781917FA2CB95CB94CE2B35DD8DD
-:100FB00003DC2E48C7C39A1477624107E1CDE7C22C
-:100FC0007586FEB81FFF47FC7CCDE30AD32667D0A9
-:100FD00031335A675C6F3C0FA5DA389C8F9B990DB3
-:100FE000F1398105C90EBC5703D1C6FB1BCFFB7B72
-:100FF0006314FAD354F5FF7CAD06E3CF382EFA9F85
-:101000001D3E86FE66D5EB63E8BF1AF4FCC014BA39
-:1010100024A3BFCEF87BF88778917EC23C412FBBDA
-:101020009D8CFBBD92FC86235590C098BF63E6E77C
-:10103000C3BDDA16BE9F3CE65B634D9837636637E7
-:101040009EE7FB327B08F36D4F27E4C7C3BA0C79E8
-:101050008FE9B43CAEEF57B6365C8671A25E1107DD
-:10106000BBA7357819AEB7AAF9282F0EEF5772270C
-:101070007C6FF1407B029F6A8E0643DDEC08105EB8
-:1010800056B5B610DD98C53D50ABF36E730513FC35
-:1010900012178E14F6862DCC5C594C98C6F0F7C109
-:1010A0007486F3555DDAE9C47DA8D50BFD25CA2BFE
-:1010B000AD9025FAADD7B4B610DCAB9460103BB35D
-:1010C0008E66513BE0DBAAE1595478BEF52A92675F
-:1010D00016E76D3EBCF76738FC59BDDAE78972C880
-:1010E0003FD22887EE6FB55D8EF85AD9BA8CC69379
-:1010F000786B6F755D8EF58DAD5ED1BE82DA4DB5C4
-:10110000BA82F4711A6821867116ADC789713DB033
-:101110003319C603CD5E5B0499C8EAE1F0B2A305BA
-:10112000441F735D1C06F48DE5037DBCB3CC4CFB02
-:10113000D3DBF31DF4FEEDAF8F79D10F7C60011E80
-:1011400051FF8AF9F48F23F06711728869C100F2A8
-:10115000952557237F74866B36ADE3DFDA9FC4BBDA
-:10116000C5CE281FD492EF20BBEB7CE10C8D14F789
-:101170005009BC27E30FF04472F47681A7DBEFE25D
-:101180007EBEDBEF6094C7CE96C15FD5005D8D1447
-:10119000F2259B05A86C6F05C15282EB6563410B7C
-:1011A000E875D6492FDBD1BF83ED7ECD8DA1EA4D09
-:1011B000359E59586E9C7CAA1DD9F1BE4B3F8B6160
-:1011C00089BE74C497AB8145F0CC1FC58E3D781D98
-:1011D00035AFA789F6B43A5E4F17EDE9015ECFF758
-:1011E0003FA9D4206049F1977C47C6D5A351BE2DB5
-:1011F00060FC7CB2B8E7603B13F2C29131AB06DB16
-:101200006F6274BE40B6FF50B4E7384EAC29463921
-:101210003CC7F8FD5681876CC789F6E9149F31B643
-:10122000CBF84AA6E3EC2BF47D99B1FD41F1BDD397
-:101230007136361DDB471BC7DF20DA531D3CEF0834
-:10124000C4213F472FDAEF15ED766CC7F14B8DEDDA
-:101250006BC5F82B9500AD433F9F89F8E48E569DF2
-:10126000EAC97CF6EAC80C7E8E59F0996B191BF21C
-:10127000DCFCAB2379BE4C9ADEE3F70F210F657BD4
-:10128000864BA3B8AFEAB5101D591D428E083EEC3F
-:1012900097234A8B8F1317F7977F193D03E17E8EB3
-:1012A000F2AC00FE909EF3BE6362C1047996DB98B7
-:1012B000C28209EF7B176418EA5937E51ADEF7CCCA
-:1012C00019656877548E37B4B3583EF1C76D82AE56
-:1012D00052CA2A0CEDF2BE02A6733E9276B579F49C
-:1012E00014C37B674BF574A4EDD357CBFBAB7C36B3
-:1012F000940BB7394765231FFEA475321ADF20EF20
-:101300006CA27489D24B47C956B6EAA25E4AF5C7A9
-:10131000DC3CAF7A65AB8FD78B189D6F5ED95A4B8B
-:10132000F5C7812FB1FCD7563F957BA00E160EFB5B
-:1013300011F4AF433F3BA17FAC3F02FD63B91DFAFF
-:10134000C7F287D03FB66F857EB1FE10C085E583BA
-:10135000D00F3E7F00FAC7FAA6D600D5EF6BADA33B
-:10136000FA86D62095F7B636D0F3B5AD2D545FDDAD
-:10137000BA8CCA7B5AC354AE6C5D43ED16A1371FBD
-:1013800013E71F1F9BC6CF7D27AF7F469EF2D5EE8A
-:10139000BBA804455E65C893C8C8C37D75A7312F37
-:1013A00010F14770D8391E93E1182BE018CF622B4B
-:1013B00052B9DCA038EB982EDFDDA9C0A7235BF87B
-:1013C000BA1775C5A93DA7818F3756CC9379C22C22
-:1013D000AF8A1FEFC5F77A9558752A8F37931F8309
-:1013E00079013F55E2DC339179C484706993417F80
-:1013F00027CCB31F5F6E0E27E26D28782BF2787C26
-:1014000043ADECE4F79BD4B64791CD52FC2D74BFAD
-:1014100089AD2E10D5A0F40482744FC2F8733360E6
-:10142000930572EDDCE54C8732AFD1B8FFCA5D5051
-:1014300061D8E7A8E73632FD22E8B7CCB84F4A19A1
-:101440007D9BE13B5BDEF70CED16CFDD86F6F9B751
-:1014500014ADF2223E47328A3B59D7AF603900D7EC
-:10146000C28E4D045750E0BD57D1F9FDEDFBC5EFDD
-:101470004408FBFFC72E812FDB7ADAD78E75F36A1B
-:10148000497AD884FAE7E3A7D2498EEE7DC444FEB8
-:10149000ED712C6242793301CC486CBF006F7256FB
-:1014A000E9CA1C15EBE54C57B17E118BD3BE08EC95
-:1014B000FF3AA417B0FF1FB143FD4C7EF0C73CBFFD
-:1014C0002B4A7ABA44AC6789DC076DD192FDC373AD
-:1014D000F3C85F633C07D626F6012BDC55D918EF1D
-:1014E000ED1D26FFCEE9FDD6D405B01ECE9C3A2ACE
-:1014F000E5F30DBA69C873D1CBBE2ABF6C013D625A
-:10150000E4976508FF99CA9F67A1BBAA79749CF804
-:10151000A6CD2CE5989E8E726CA0EE4B27BBA23B0D
-:1015200087F0A389F5D9DB1AA4FC00394FED77D3F6
-:101530005C980F5622F24FF7B5DE3AB526211F66AA
-:10154000B7A0DF5216AB453D5A5A66F245A827AF01
-:10155000C17F611FDDEEC773FA5A05F3A1181EC7DC
-:10156000DAE9BCBAF6854A7940DA914B980E76B042
-:10157000C31165E1B2817E99F0837C47C8F5CF5CE9
-:1015800035340FAD40DA473ED4DDEC33873F867407
-:10159000F7598799B3E509637BA983919E5B546AE8
-:1015A00089E80AA623B4D33D8BDA0E85E515211C04
-:1015B000D3BDF3508F1F4C25BA4DDD524557C37B29
-:1015C0004CC1F57900C7991EFDA0491A57F05ED3AA
-:1015D00004CB2EB41BC7225E709CD1A584C7856244
-:1015E000BEFB5A57109E9E15F368CBEFC73B87870B
-:1015F000F9FC78CFE9A20EE9BF31CE734365F53728
-:10160000F0DEC6953155D874467CAE33C726CE532E
-:1016100006E002389F453855849BFCBF7C7E4D8F89
-:1016200070BF19C8B15A8ABB4E32B1C4B8AB2CA333
-:1016300042FECDC87311BC4EEFDCA90B2E4AACDFC5
-:101640004474FDB8C2E71F766A3C2FCDEFD713FD77
-:10165000C4EBE47E599C7F4811F0F6DFE3369EE749
-:10166000613A586C0BE62D0DB71FFE252ECAA4C497
-:10167000FD30E81818579D64A33C9F75328F4B7F4F
-:1016800043C77C332CF1FC8A4DD0E96AA731AFE423
-:101690005C1EB777CE89F5E8B371BEC6B8647956DB
-:1016A000C2BD17DDF5E4FF9171CCBE6E9E0F2EFD1D
-:1016B0006B4B0409F41DE578E87B58A5F8E592EE3C
-:1016C0006BF97DA1871EA07B56A12F1DE9A15EBCF1
-:1016D0005FBFC6E8EF59B03BB02A451FEC575AC46C
-:1016E000C2E4D748F62725FB917E9B27F6693E5634
-:1016F0008E71CA93EB8B8FA5E07EA688D1B9DB9162
-:10170000EA93748F3158FBED784F292BE3F7F424DB
-:10171000AFFB250516C2F33EB9AE631CE467D837AC
-:1017200089F3FFBE17CF7E7D0CF4F396AE18CE8101
-:10173000BCA59B098FE381AEB1EC64AC76A8FBA09D
-:10174000B2F34D5FEDBCC0A5C6DFD768EAEA3996B3
-:10175000AA93BCCBCA0778FA8EFD3EAD8CF8274E13
-:10176000BF075157C4E141B8F1FCCB7ED3277313B7
-:10177000E9607CBEC6ED837CD35793BF3546B8CEB7
-:1017800094BD99750D876B1CC2D51B3D919568B7AB
-:1017900048B8F60F73BFFAA55F154F938DFA200175
-:1017A0004F53FF129EF65B86866796C0CF4F8EF230
-:1017B000FB4206B77F45FDD56184F7CC63B1EB51A1
-:1017C0003C02BCB3087FDE5359143315F8EBAC145C
-:1017D000F45929E48E8FCEA8B0D0DB17537E5EA7D4
-:1017E000C6DB43772E8AE07902DF8B0B0AD1DFE07C
-:1017F0003C6EA57B9E42497922B25C2FE6B13F57F1
-:1018000019120FABF3B9BC78F1B5F9D4DFBD6F593C
-:1018100019CA83ED22DFF55E57A70DEFEF9578C467
-:101820007A0594214B7C112ABA7B2B3FB3E98E2198
-:10183000C633F1F1EE4BE21B399E2C57E49772BB95
-:101840005439AAE23987FB2E7D93EED9BAAF5223E1
-:1018500099FB37E37F7D12FEA36F667D9DD3CB8A14
-:101860007CF4A32AEFA57D03EA2125FEB332C49FB1
-:101870002548F30FBD6D653B95C1786A14F42BE7DD
-:1018800027E72FE1765EB680CE99E07A20E0ABC5FF
-:10189000FB524FA40BBD87F3223D71A9C6CF894CE3
-:1018A000D2685DEF9B3C85CEF5EC17F914F14B2C1B
-:1018B00043FE2EC333026FF79EFB450CEFA90D7755
-:1018C0009BE95E05A6F578BF0974147A5DA37B9A3F
-:1018D000819E6AF1DEA8175F3B9B86FBE803F966F1
-:1018E00082FB403E97877DE7D45A3A6FF3DA672E42
-:1018F0003581FE9FCE57855D128BE1399A8D15FC9F
-:10190000DC8043D8018ED74E3520FC8EC9DFB32A48
-:10191000097A764FBE95BEDB688967F9300E744848
-:101920006551EEDFA1FBEFFACF0BBA381E9A2B8F71
-:10193000929DE0E8E6F7E23D9DAF135C08F7417841
-:101940009E32EE33573DB657C278A306BE77BAF83B
-:101950007AA64CE2F7D0DC77E9CF5D78EF5EBAC2C9
-:10196000E8FEE84B0ACC06395E5FC4D7A1B3321655
-:101970001B85FCE5D228AFB6337A9B0DED7AC917EB
-:10198000A347A9F4DD6A9197BE7A7229F199A4E37D
-:10199000B905C157916E36025F3C49764E2C309D99
-:1019A000F0E32AC7FCE3C795581DB73F2C2ED42F70
-:1019B000A5269381DF8A0B38DDC812EC52B277EE90
-:1019C00010B42CF57D5BC4C630BFFFB7E766A5A396
-:1019D0005DDA9627ED3CBF0DF1B55D09A417E1383E
-:1019E000FFA5D2BEEFC5D74E34E0B86D302FE4DB93
-:1019F0007B7EEA588FF6499BCB4F7C2AC7D7DC26E3
-:101A0000B11EBC9FFD16FF2BE86F8CBBF97D4447D0
-:101A1000A65C6343FA87F74CD8CF7BADF80B1AD896
-:101A20004F0DF90716BA66CFC0EF16B1E02AB46BB6
-:101A30001775A8867B17EE11F262E1B914164DD81E
-:101A40001F2C9CFC2D3A37B6F05C1A8B82BD758F2B
-:101A500038177D8F3857C40A383D3B44E915E5DF18
-:101A6000CCF7BE24BD95F9CBBDF339DFB302E8B79F
-:101A700049E9B114C1101BA7FC9ECEEBBCD7EA62AA
-:101A8000D192047807CD73048B268CD3FFDE391BEB
-:101A9000CD67607D39FD0ECCD7417878AFD54B78D6
-:101AA0001CBEFF91063C0EF43FCA80C7C1FD97D013
-:101AB000F8EFB5967E49FF1386E95F37C03FD0EF58
-:101AC000681AB7F7C8FC1FA702DF1D89DEBDEDF954
-:101AD0004AFC1D332BFD7E01EBEAACA673848F33E9
-:101AE0003A677AE7E1DFBD83F99A77EEB2F8708C56
-:101AF0003E737CAE6F083D339AB9C2789F972CC76E
-:101B00001714D37C929FDBB4880BF3326DA59A0B2C
-:101B10007F1FD1C66291BB71DF5269233927E3422F
-:101B2000B2DF3FE5A9F23C3BC907796FCB12919731
-:101B300057EC085E81EBBED4D4DEFC13F8F683D2FA
-:101B4000363A37CC989BF633326EA3E12FBF15A3FC
-:101B50005F30C0F0FCCD137A70067EF74310271873
-:101B6000C7512FD81DC4BCB50D62DFB8C11EF3FA32
-:101B700012E4E60D05DA57B317DA93E876D22FF7B9
-:101B80004639DDDE50807E2235F6C4FC22CCB7ED2E
-:101B900011F776E9168A77551EA3FBFEE6CB7DFF8B
-:101BA0009AE4BC8E7C37DAD132CE94867977686B32
-:101BB0006CE4F7BED5A7F27AFD7F8CA07310B0FF5E
-:101BC000492D43F9B25FE5FE2011DF3A2BE6D067DD
-:101BD000DB5840F9F7221FE46CF74B74AFE4D935BA
-:101BE0006368FDEB5FF83EDD0BB73F97EBB1BE439B
-:101BF0004ED263F5565F15DE5BB83F97DBAB9D5A5F
-:101C000034AD22C17E5D9D574DF2F9E335634C89B9
-:101C1000F18FEF0A79B051FA37B578159E67F9B8A8
-:101C200032FA33D2A307ECF43B51A683BFABA2FB3D
-:101C30002D375AE97701AA0F8EDB5C87FBC3348D01
-:101C4000F2914D07ED04CF9975FC7E2DFC16E55DF4
-:101C5000D3C191F4FB56F5A971CA276C4AF195607E
-:101C6000DCAFFEE054BAD7FFE486710528FF4E646E
-:101C7000EA0574AFF1063CF409F54363F9F3B517CF
-:101C8000D37955E7C6D4E0507E10A98F92EFEFDAF2
-:101C90009F5BDEDB85F81967F3A1FC7D4FF1F1B89E
-:101CA000EF2BF1D93AC515F9F9D27AD769FA7DBC8B
-:101CB000FA8E776F62F4DC43742BF773C9E3D50BAC
-:101CC0007DB5DF129F8BBF4B56BF52E05DFC4E626D
-:101CD000BDA99C7EAF4FE27D63D23DB74F08FD2486
-:101CE000CB93AF69745F20D81105E81F3A79D84AC1
-:101CF000747672E3043AAF2EC7AB079CB8802F4FBF
-:101D000064E813715D9F16F2AA7E25DFA7CAE7304B
-:101D10007E0C7FE7307E48A5BCAE3E573C0DE3927B
-:101D2000F23D59EF9F4FB74ABF97B53FF7455A6FFE
-:101D3000A02786F4647AC1497A3AF4827517AEE72F
-:101D4000C7952C8CFECFF05BFCF7C78E1CB292FDC2
-:101D5000DC779CEF6F07DD9FE68817E0FDA1A117F8
-:101D600046921CEBCB8FEFE0F6B69DDFABF846F06A
-:101D70006211FFCD11F711E6A09DF7F9217B14ED5B
-:101D80003C28299E1066BBBDF4FC702A43FF0F94CB
-:101D900014CF63CA012FFDEE0C6B17DFC7E8FB3BC6
-:101DA0000B8263512EDF590CFD3BF0FB53F4DEE751
-:101DB000A38217520C8AB15C315E2EF59B1F2CA4B6
-:101DC000E7CA675EFE7B2AEDA23D46ED216BF0621D
-:101DD0009AC7AF9C6CE710F3FCAAF7EE1D2D1841D3
-:101DE000EB28E1063C93DD988C97B30526F17B3B0D
-:101DF0001C1FC974D9BF9E5F021FFA5FE8BCF621A1
-:101E0000BE8EEBC659B81C593B81EC63D69662C8AE
-:101E10009F5B7188DFC3D0BBC149EBDC67F63F84B1
-:101E2000FA28FE8699F17BEDC022403FC5E4A1F976
-:101E3000E523914FBF642DCFB3FBE8D1F70BE63913
-:101E4000F05CF2FB8673C9D25F089DA4A13FC6E196
-:101E5000D3D3E697717B5D25F8F8EF7A6D34EBF418
-:101E6000BB6BE10DE3C81F71D2A21FA4DF875B77B4
-:101E70008109E94A2D17F277139F9FBC2F4BDE7B18
-:101E8000958C9F8AC262927F4D2C7833DEA17E8230
-:101E9000E959C26146F7FF917BDF8469889A9FE226
-:101EA000B6AC85F4C2E07BF62C5FF2BB6CFFBBF5F1
-:101EB0002A5C2BF4EF9587D350AF7EE0E2FB463AE5
-:101EC0007D8F7A5DE5F36CC30F30AF8305A6144EAA
-:101ED000A27692871F28BC5DCAB941F3477AC17EBA
-:101EE000F03DE8EB9A42EE7F63AE0C71C82B6CC1FB
-:101EF0003C4DA99F428A66C273F3A7DC7A1AD2E3EB
-:101F0000A9B5C5192B300FC6AD6725DAD5A1A38CAD
-:101F1000CE8BEB78DFF8C5F8FB32FE89E8F7DB9F64
-:101F200061F43B24C3F3E4B49EB989ED730AB99E0E
-:101F30009B5F28F699854CE45726E38DAFFB62B191
-:101F4000EE6A79F072DA8726BDB7784BBAA087A41B
-:101F5000E7EDCF7F97F2A01E36DE1349B15F18EF91
-:101F600083572C61E5422C5328AFBD611397730D45
-:101F7000AFCE2CB98BD7E95E85693BEFA1DFE35982
-:101F8000B0EBCA12C6E516AD83A4C70505FE12B4B0
-:101F9000E3E25B5517F245C31695E051CD3ED756A7
-:101FA000787E7A8B99ECBB0601CFE9BC601AAD9BB9
-:101FB000C6340BE0FDB4164C23FB75ABF8DDA1A4D1
-:101FC00079C07B6F6A1543E0C7C6D799F0533C04CC
-:101FD0001DBC61A2755A80BF0B8970EC54C8BF79D3
-:101FE0003A3F7833D64FC1FE1FCFE9AB9B96D07DE9
-:101FF00036C9F83E6D0B127D2E16F391F84C1E4734
-:10200000E2B30FF189F6D22B5348EF851E5491624B
-:10201000D98BDD9FD2BE7CDAA12BDF998ACF3781A5
-:10202000DDA2A39E1DF5B36FA39E5BA3528C7AFE27
-:10203000A1E22C96A4AF71FF39FFF53969A6043DE2
-:10204000A93EC8F1A43AE7A42DA4F7CF7E1DE9EB81
-:1020500084EECBAA4878EFF1C2FEB88361BDEA37BF
-:10206000FD210DC769586FA679C975E9C379A07CB0
-:102070006B4F8D20FDF7E5C5A95FB94EFDF48DEBE3
-:1020800020E909DEFBAF429718274CF2E85451B023
-:10209000CA37049D2C7A00C6C5FEB638E9FED2F3D5
-:1020A0001D57E2A37FBD055F531DD7714711F9D1BD
-:1020B0004D6F6874C8E044FB5505C8C7F5A02FD024
-:1020C0006F51AFC4DFA17B640F59E91EE6FA4DB72B
-:1020D000DC8CE3D51FB79AB0FDD4E1AB26125C4986
-:1020E000EB0A782A188ADEFB8AE205BE04FC813DF1
-:1020F00041FC2DE7930037C101FB29BA8FA8AF0837
-:10210000D633410EBC59C8ED2E78DF6521FAE6F7CB
-:1021100061F5CFD795345F57D27CDF6444DFCC17AD
-:10212000A4F92C78DB6AC2E70BEEBFB604F73DA733
-:10213000D64DA7799DCAF04F44FE3A5500FD0F21B8
-:102140002F17DC0FF32CFB0BF36CB7D37A0D3BCFBF
-:102150008CF80EF617E6F989A04339CFF7343D0D18
-:10216000F3F943CFAA0CFD2EA1FCC0C6A9BC4EBFFB
-:10217000131732737A086D4AA57CDFDE6EFEFB040E
-:10218000520EC078E7490F26A28753D5FAE6C9D088
-:10219000DFFF073F3717B700800000001F8B0800E4
-:1021A0000000000000FFCD7D0B7854D5B5FF3E73D5
-:1021B00066269364924C12088140983C09908449A9
-:1021C00002888A767804D1020D4F798993071042EC
-:1021D0005EA0B5696BCD4002A2450D352A5AD401E7
-:1021E00081A2A20D0A0A15BC032A6245C5578BB607
-:1021F000E526405179C6A05EAEB5D7FFFAAD7D4E5B
-:1022000072CE9054DBDEFB7DFF7C1FDF669FFD5AA4
-:102210007BEDB5D75EAFBDE7C23DAACBEF16E2E4DA
-:10222000DD056FFFBC17A5F7AA2E81FC58DFCD0294
-:10223000F98FC32CFE144A938BA670FE659B6BA589
-:1022400022C489A6BFFD41A1FC857D36B7A0F20B53
-:102250002945F7CE467E8FEA5A41ED2F0C689F251F
-:102260008673B9D844E5EA5D239A502E1E1EE6CA4D
-:10227000A0F2F20D61426409FEFB56687F23E93B40
-:10228000520BA56B556F7834A54D2FFD44C9A56F32
-:1022900056378F57F3AB24F7DD347EB95558EDF937
-:1022A000A8DC9E392D4788F37B6D1303D9323F2379
-:1022B00087CB3FB052798D5DF85AF87BAD7D6A0EC1
-:1022C0008FE2B6D2388BA90F914AE9FA18EF60EA8B
-:1022D0007F318D9342E37D8BBF1F5C0EDF0ECBE71A
-:1022E0000B8AA89F7B6D62F673D95DF5F434DB4DE4
-:1022F0001DF6466D7B573B558825C63CE1A122243F
-:10230000BF14794757BE32A4BC2AA47C47BFCFA7CD
-:1023100014392F1F7F03C61FD185C7120D8F3B2C89
-:10232000F41DEB728F12D844FF2DB1BAEDCB09FE2C
-:10233000E7C6889BD14FA95538AECD47BD0E9E5FED
-:1023400089553486E5E3BB87EBE9F3A6FE1AC3E2C1
-:10235000281FD1CEE353BD8976439EDA9BE09AAB2A
-:10236000C1A3A74BB785BB4EEAF3A07F552DB1A6FD
-:102370007CCDEEBEAE93067C2FC57FFAD2BF49342A
-:10238000FB91C08BFCABDADD7A3092E8A74DF1CD42
-:102390007553BF170E7E1D9DEDE6751F5944EB9BCF
-:1023A000AFA63E7F98E6DBBE47F56C42BF6FD8FD17
-:1023B0004A0CFDE79B8B0F6EA7EFD52FA789BBDDDE
-:1023C0005DF30FC5E385DD17A353E9FBF943F60879
-:1023D000318CE6B9377EAC9DE862475C7BB778AF5D
-:1023E000D5D65DEFEFBCB5357AAAA1DE79D11A3D1D
-:1023F000CD402F25BB2FD68B5CC69F5FCDEFC2EFA4
-:10240000897DBDC7AAF4BDF4F7FDC65A28BD5FC3D8
-:10241000DBBD36F7136B096EFF9E30CF1682FBFCD7
-:102420001BB32D687FFE8D722DBDCDCBE95F4F2490
-:1024300063FC688BA4777DBC356E0BF7536A697BB0
-:10244000EC1ADA8FA5BFEB93D290D2555E6AC9CF52
-:10245000C43A6FB7B52F00DCE715B14689EBEAE760
-:102460007EB79BDB9FDFF3C963E00F27EE1D904F24
-:10247000644DF941B93E2A3FFF5141A68BFA3D7F99
-:102480004F5F0FF8C2769BFB36A6B7BBA23CD8F7CE
-:102490007A7F18A716FDEFB962A40FE947125ECA4A
-:1024A000E7FAE4B87E25BFABDF688BFBBED1E0174F
-:1024B000BFB779B650B2FCEF697D62313FECE76E91
-:1024C000D6A1744D98709BF8C94A86BB4478EC221B
-:1024D0004D960B03BD958922FEBEB0C9FC7D11F15E
-:1024E000097C5FBCDEFCBD5C34AD6EA5F92D09989E
-:1024F000BF0BDA3FFE04EC6BFDAFC55E14057AFF3F
-:1025000036CC544FF835FE401F095F25B41FC1C7B4
-:102510009E5102819558DFBB549E67E8BCDE75A7CB
-:1025200070BB8722FF6741AB615D8F5B843591F0A3
-:102530007ADC2E1C89F9E8470885FAF5EF0B0B6C5D
-:10254000A126770FFE2AB9047CAF31C22208BE5BF8
-:102550005DE07C42ACD8F74932FA295D53E86D352D
-:10256000C077C1E67DE8E7D4BEFD5DE2D754EFF861
-:10257000D840D35882EBF8DDAAA7A11BB84EAFB163
-:10258000884001E1E32E2102F1947FF293E4625A44
-:1025900097CFB67C925C62A47F45CC36D2A39E12C4
-:1025A00024BC3EEF61EFD2FC8ED35C309FD07A5DCD
-:1025B000EB6B8657C767B82A6ABBA387CF40F7542F
-:1025C0009EF5775578B1EFF7D902A0CFC88D5F3C63
-:1025D000380FF4B9D7E64AA1B16BF6A95E95E62D9E
-:1025E000F6A8810C9C637B4F4457E09CD953E05282
-:1025F0000DF3AED9A316E17C39BFFB62426936F711
-:1026000033C5ED44FB073CA0DF9EE0F89B5BFDF784
-:10261000F89FD7CCFFCE657F907003F8C0C6539962
-:10262000E0EFC407FFE6A6799ECFFCC68EBC10ADD6
-:1026300023417F045FB49BE0BC10F82A5A105C8EE3
-:10264000BDAA37D0CD3A44A5D8194FFF327C130923
-:10265000BE842EF8089EA894115D7056BBDBED3841
-:10266000672F38A273C14F694293F212B4F3C90DB8
-:10267000FE5A3A49107F1DBF67E1CA70C80B4D8AE8
-:10268000278CBE97ED55F9DC2ADB1B19C016183FC5
-:10269000C8C9F9D247D54018E527A8A3FF309BEA5F
-:1026A0002FBE47F5D08E14FB37DEF6071BD6758399
-:1026B0004DA01C88035C4B34B896ECFDE1670A8D95
-:1026C000B378DF2D0730CEE207140F17A8F3EDE83B
-:1026D00077C9438A88574067B6E3463A5BD864CEE9
-:1026E0002F12AD0B5415FCC1FC9DF09E5C41FD9674
-:1026F000EF0E73DD8DF102A1E542BC4AF0D468FF14
-:10270000CFCA583BF700D5CFDA68673C9C0F17E279
-:1027100008F6ABB53541200DB626631DCFEFF96B3A
-:1027200032D6B1E677FF9529BA59BFCEFDB437AAA4
-:10273000D7A94821AE4E51C4B7A9A0FB8B538ABA82
-:10274000A96F1B20F7C5369BBF9F87CA0F6CFC8AF9
-:10275000F9C1853DBE81AE6EE8B76BBFFAC32D8966
-:102760004883E102E9F016D70DD827240F62BE3561
-:102770009B564FDB44F9F0976C38B9444D8693F77C
-:102780000BF6C74243BFFA3ED906BE807484E40FFD
-:10279000B601F21C3DAA9D7BDBF6774CC9E8069E8C
-:1027A000A36E1BD7B30D105CEF5977D15CD05B845F
-:1027B000C51F0DBE2DBC5E772FC2B3A2D157435D9E
-:1027C000AD82EF89A289D3FEA285D34785F0395126
-:1027D0005F785CC0B3100362813FDEF38CCFBECC68
-:1027E000377FACAD217835E8C41F2B025BE8FFEAE8
-:1027F0004687506320EDB546A35154CEB4FB065234
-:10280000B9ED03D5A240DE1DA0AFA7C785FDF7A592
-:1028100073468C71FDF61F2E9988FEAA76A9228C2C
-:10282000FA3BB7D326824ED4A7FD027C1CFEC29E83
-:1028300002BEB4571190976B288FEF35A3ADDE80A1
-:10284000012F77A4D8180FD52999F29CB67A0F4D8D
-:10285000A27ECFBB4AEC90EB6D87CB26E2BCB125C4
-:1028600096D801D7FEC3631D2958B7582BEF9BD5C7
-:102870007BF5718FB8D07F54EC070C6F63B645447D
-:1028800053BBC6A3610146A643F2A1300DAF8DC173
-:10289000F10E7737EBE317E393C4282ADFA94E0440
-:1028A0009CE75C252EACA32D96E8EE0A6A6FF34EEA
-:1028B000BC9AFA0D8B8D8B077C6B52D2783DBF8A08
-:1028C000AD6538BF22F1C2CFFBB7B608F9C6FE65C9
-:1028D0002AE3BEE921DECF350E397ED43E95CF51B5
-:1028E00071A543E3DBEFBB4A699C05C9BE47410FB5
-:1028F0009DFC6DC4AB02FC39CB6261F9ACF135E7EC
-:102900005AF021BDFC6C8AA4377D3D56F5B2BAC0A1
-:102910003F1ED5E87395ABC8916F98A7ADB745C377
-:1029200057910378DA612F3A84F3A59DBEE3DC3C2E
-:102930009038CD013D85EA59D0CFA97ADA3176F4C5
-:102940003BC301FC2EEA553201ED168BDAD5D86F68
-:102950008BD7AB2268E0AB8D3639EEA24B11221833
-:10296000DF35EE225A3F6E7F295A04E9DC6D0C9761
-:10297000F51AA3E4FE792345EE9F0FB5F9B469F982
-:102980007F99AF7BCC7CFD5CEC1FB69648FEFE4683
-:102990000AF55BA5B44E48A1F9AD4EECB003BFA754
-:1029A000EA5D22986980F7B279C68BA061DCCE7AA5
-:1029B000971C3C9FAEF57033FC5DF375321E4ED50F
-:1029C00027321E7BEE3FC984C7AEFE534D78BCBC98
-:1029D000FF4C1EFF547DD677F43FB487FEDD26F80A
-:1029E000BBFA4DE771C56EDF40F0973B5DC40F98B1
-:1029F0006E885F50B95DF13D7E35E4DB8FC204E443
-:102A0000BEAFC27D835C06FEF00DCE65D6E782497F
-:102A1000E0B77ED1CC69CDEE8B13D0DE4D7C01FBCF
-:102A2000492FAF11ED0C27F885E88335B4BAB97C8E
-:102A3000B76F10F4221D8E4E79E675A7DF42FB209A
-:102A40006CDFDFA3B18F2F58DBA778286DD9AB4699
-:102A50001AF7757CAAA4A7B103BEC86DA5EFD56807
-:102A6000477CEFB697970E027EAAC3DA7301F7810F
-:102A700097FF968B73E4AB7D4B07E2FB36AACFF250
-:102A800087BDBDDA63E82F5DB8FC96515DA933556B
-:102A9000EEFFD0EFDBF635F4031CDB89BD09920BAA
-:102AA000ABEB2A0A4EC6830D79EF07FF12C4B75865
-:102AB0001FDA3D5D1D03F9EE439279283F7C8F9428
-:102AC0001B860F10014B0AE4BE0F67834F548FB073
-:102AD000BBA00A47E41D61793B6284C3A550FDBFDA
-:102AE000F797E3DB212FA4A17D613CE8F9CA64F1EB
-:102AF000EFC96D1B42F64FF0BDEAED345E95DA3A50
-:102B0000659CC2FB283F157CFBAD2FDED6F4D704B5
-:102B1000ACCF019C6B04CFFB5A3F65A9BE2B50CFB5
-:102B2000E768BDE70AAA377356DF64E847C59A7EAF
-:102B300026261152AE647E94033BC8E5E7B6D483E3
-:102B40005E527C3EE0C1DFD7E1C1F935344938FA45
-:102B5000125E456220751A8D3B21D5A2DB0F14C091
-:102B60003D449BE333FD5A96C7F2391988031DFD96
-:102B7000B3E34E4BF54E06FC7AFD0F67CDCBF175F6
-:102B8000736EE8F2BCDDDEB20C70B65739597FFCCB
-:102B90000045D4EE89596141351A7A8A730DF4F9EA
-:102BA000A3910B0EF6267C8C8FF2CD43FFB36FBC46
-:102BB0007E35F2CA8178F772D07371EB48D6EFC2D6
-:102BC0007D37A3BCD2E11B9840533C37C037280661
-:102BD000877C51BC5C27519453D42DFC129E6245D6
-:102BE0008EDF18E52B473FC596238F5D816FD62377
-:102BF0006C6F108DBDB99F737651DE9DFCAFE3E124
-:102C000098368FFD3671ED259ADFFE75319E06826E
-:102C1000B7ECCE1B17D450BAD0529410544D70DF7D
-:102C2000964A5D57FA8B07F62579EE9C4D83BB4E8D
-:102C300083DBEACA34EEE750B81B7479E5170AEB78
-:102C400083FC47F917FDB181BB291F66B9F8C17430
-:102C50009C5B3916B6936C88A0BD457AE43B1A9C00
-:102C60008FD2BE73C4F1F735F89E1821DB273E687A
-:102C700009C07E5034760FAFD313D54E8F4A6315FB
-:102C80000BB71D7250A9F0B2FEFCD7317FDBD74ADB
-:102C9000F36A4EF5DD07BCDD1C6F49FE80E1F00DE7
-:102CA0009D0A796BB49CC73F9037791ED384CBC6FD
-:102CB0004299586B81FC31CD25A7B25091FB63BA84
-:102CC000F0DA30DE4CE1E37AEF9DB77BA14FBC0731
-:102CD0005D88E0BE51F8F9FB1C11E0749E0872FD9E
-:102CE0009B442BE7757C137DDCDC4BD2C7277D54DE
-:102CF000C6FF56C0FD6E64EE803A9AC7D48706655B
-:102D0000B07ED5DC9BF1F35D704FD5E886F6EF6FB2
-:102D1000B18ED8BF33A89F693784ECDFF1BDF5F5DC
-:102D2000CCF847FBE84847A7FEE4EC4B78B84E5B8D
-:102D3000D2EBBC4B597F12C2C5F2D18FB47D5BA8D8
-:102D40003A452F5A9F236ED297089689639625623B
-:102D5000BEAFAF106F15D03ABE3E46150D5CD3CB5B
-:102D6000EDA668FD4DE93FE133D85B0F8B60AFE125
-:102D7000D4AEF092EFD518827B8ABABD3196CA27BD
-:102D8000F627BDC6C0EFAEEFB5C30AFDEE8674F3FD
-:102D9000F749D966FD67B2685231FE94E1E67AFBE5
-:102DA0008127A2B3F753A5FE22868821DFF27A0B92
-:102DB0008B713E1D932EDA2F101C1169BE8FB12E20
-:102DC000CB27FF7501C61556399FEAB755B6EB1DDF
-:102DD00027798B28509CACA7932253CA25C87F4AD9
-:102DE000F203D2D3F56E4ECFD2798FF2F3F51ECE29
-:102DF00017A4159D40BF256B3EB7627DEE0C97F87A
-:102E00002E6F699A00B02A76B71C445A162C9A8005
-:102E10006376D1A1DA8348EFECD4DB6A59BED3E103
-:102E2000BE45A3D35BA2A6FD3087D6E1963DAA8717
-:102E3000F303A64D9FDC0B791BE77BA2A3AA4B44AF
-:102E400033245754ABDE2F0197776FDBC1789ADFBD
-:102E500027F5A318EECFEABD0CF799FA899C4E4AE4
-:102E60002BFA1BE8CC2B3E67796CF2F6366B12D549
-:102E70002FF42A5EECDB6BBD2210A0FDB7DE26CF5F
-:102E800081F5740E601F8FC999F6E8AD027CDA6790
-:102E90004BA37166DEB0A410E34C19556C45BD1B05
-:102EA000BF211920A58B4EBF8BEEF5F95769EB7644
-:102EB000EE6585F1D8B1332D0672C1F25D697D9062
-:102EC00012BFD4F5DD48E0ADE39285E1EC381AC1DC
-:102ED000FA86DE6EF9AE48E63BCB07D803C260B790
-:102EE0003C43EB2C0CF2E699677EE2369E2B67E2C0
-:102EF0005ABEFA18FCED2F92BF916473EA11F0BF2D
-:102F0000FEFD3CA093F39A9C4D7A4624CEBF6ACD39
-:102F1000AE08FE84FC990869CF1DF96CD258EC2FDD
-:102F20008C471C4EE8FC2BF3D987527FEEEE1A6FCC
-:102F30005BCBC28F1FA1FCB980C56FA3F3E99C686E
-:102F400039FF3BF0DFCD4EB6EBDDA9103C387FB743
-:102F5000F4E37C96628DA8C3F92B02BCBFB314B70F
-:102F6000B58EF855E5730FF703FDBD44381845E5F8
-:102F70002FAD8B647EF692CD73AC0EFD3D2AFBFB2C
-:102F8000CDBD3F3DBE1BE93D55F93FC5F2A4C5315E
-:102F9000FECB7EB56408DAD3F92EFA527F4FBFA874
-:102FA00004C3693FE734EF5FD997E01BB6A1CDD2E8
-:102FB0008FD2BCCD4A03D2A1036E3804BBF30D6996
-:102FC0006E6E5FB03D454DC236EC17F8F8077CEEEB
-:102FD0009BE581ECE6CFC7F6135D72C110A5E5F461
-:102FE0004682352CF968BE8FF1D7C4F3D9B577FA8C
-:102FF000FBF304E6411207E02EB67BF81C0AF83713
-:10300000623DCFF9B23CACD715F91F069D9DF32563
-:1030100078702EBD407AFC55A87FCCCAF37C71F342
-:10302000BBD1B0EBC4907E1C0E7F485EFB04D4AFD6
-:103030001AE0167E6A3FE0B1EB26023FD53B776D82
-:10304000E47E2A1D1EE8B9E5BB2E1E4C829C78BD8D
-:10305000F064800E77CAFC2FC77B3D2A4DB57CE318
-:1030600097327FA488F345A4755A51BF54CA470FBD
-:1030700069E79F68CD65FEC8A4EDEE5AAF5F523197
-:10308000CAD7A7F8FBC2AEAD9F9B74DE55A561AB56
-:10309000D865FB2363E725335EBEE77967D7CE2D7E
-:1030A000BDBF87ECC21F4EFDC06C033BFA06BB3CA4
-:1030B000A7B7107F01BDE8E7348DFB0BEC5F6AEF2B
-:1030C000053F4D52959C9D848FA487C258CEF8BE73
-:1030D000E3CF8E59CDE7B62E67D544483EC8670585
-:1030E000B55F18E5BB0BF35BA89DF3C2EACE861C67
-:1030F0003223CA7B37BE573ADA9331073A3FEF455E
-:10310000BE5A25B92BCD207739E3BED7F95917E53B
-:103110006DC67CBE6FFDB19104670C525DCF22ADD0
-:10312000A35B7E9CBABD05FCF88130C98FA30A98C9
-:103130001FE9F30BEDFF15DAF73EE233AFD179E289
-:1031400023DC8F738EB1F27ABE6AA93C48E770A186
-:103150001C01846C8D1DCE796F14E16FBC5315BEBC
-:103160006EF4453DA5F57A1EF899D02BD254AFB038
-:1031700057AC1DFBF7FBCE5BD5D6478DD0F9A9BB6D
-:10318000977076376F39CF5BC247F4015EC62ADF8E
-:103190006FBE0E5BD141ACC338671E9F8BE39C535F
-:1031A0008FF904C37F18DF43E7193A1FE1F87EF275
-:1031B000D28F15E1B760FF7D6E67FBDA5E5BEBD304
-:1031C000BF257CEE5D92ED819DE805F05EF0CF6855
-:1031D0003BCBB37BA3841F7C65EFD48400EC452FED
-:1031E000414F04DFE82D6479B8ACBF770E95537F6B
-:1031F000FDC2685FC05E342F42EB9F0646FB157D23
-:10320000B87D8352FB660EDAAF8864BE733420F952
-:1032100078736C709E4ADF9B3FCF14A8775404D616
-:10322000A4A2DEEDD25F43E54935D46FF3922112BB
-:10323000CEFF51F9DC68CEF3F68D73321F67FB4C7D
-:10324000F3546F5FF8AF7A69EBD5BC5196F7833DC5
-:1032500014E52994A7F4639BAC3F57ABF7914697CD
-:10326000B4CF990FF8A6445A41E7FDD24BC2D29988
-:103270002979FBC2EFF3485906DB28E7565C9FC269
-:10328000F4A3D9CB666B7C5BEF0F0D1C23212FCBF6
-:10329000BF390BB784839E679687B741EE3B5ABE12
-:1032A000320A7AFB4C9F1A0C835C39A3D0DB29AF1E
-:1032B000A5625CAF1CB74CD7FF82A5C0EBCBED0E6F
-:1032C0007137CBF7C102A33EA5AF6F55CB9878A35A
-:1032D000DE5C6127FE42F02CD1F66D9AD3D73B7DA0
-:1032E00004F4E9EBE38DFAF4A7650FE4F2FED2C62D
-:1032F0003B5BEF8D3F990EB96D22A7FA789D7A0F4F
-:10330000D64DE757A097DB25BD086BFB478B29DF20
-:10331000307B8807F6EA89D31C4C6F1D2DE12C1FEA
-:1033200037CC8EF0C26ED7B02B8CED06376BFB839B
-:10333000F428A61BFFBE28EEA7D22EF395CF65304A
-:10334000DDBC600F3CB915E52F87B37FB6325A8ECE
-:103350005BF9BB248D2EBD29AB7AB15F8EE9A53216
-:10336000C21DC3E5BF8F677A7A36DC57007C127DB9
-:10337000B25DBCD21ECC8C25FC1FD3E80F7A23FB98
-:10338000F56AA3986E8596F7FD3C9EF538927F7995
-:103390003CDF7D4339EFB37BFB2EC43E5A1EC9F0A0
-:1033A0001C73C9F26395B1BC0FE6DFB7F430FCC5FE
-:1033B000C78AECBC5F8EED5559DEFA739D1A849F67
-:1033C0005BA7CF9A25C7DF86F9A8BAE1A3E4DDD4CD
-:1033D000CFFC955593D06E7EC5ED5370DEF69AF610
-:1033E00029FB6943F7F3FC4AB37FD497EE9D8CF930
-:1033F000D56407761CA47E1E9C736A11D6D39FEEFB
-:103400009B86F53E6F6F7DE14F0477EB8A3FB25E9E
-:10341000747DB46F26BE5FD8F31BAE5FBDF2BF16DE
-:1034200041CEAFB64A7AD1CFE31A8D7E45866F1E64
-:10343000EA57AE7C9DF581C8EC23927FDEFEFDF855
-:10344000CEE9BD5B5E50A8DDD288BDD59CAA815C6B
-:103450009C6B679460B492067C4A3DEDAC2B188D52
-:1034600075F159A49CB8745B881F184B91A0D97F43
-:10347000A8DDD21619BF42F2821DF4195A7F297DA8
-:10348000E77ADFF37B856891DF6377DF7BB55CF7F5
-:10349000607038FCAE199BB0EEE776FD26D3E87776
-:1034A0000D4D2F8757CEFFACB65FCEEAFB65B6BD9C
-:1034B000D35E00B9EBFC337D4C7476FEC9C19C3FF2
-:1034C000ADB42B114A977F57785A46727C8DB765F9
-:1034D00024E4E707B5EF4BE35B4682AFE97C4E3867
-:1034E0005A7259FFCF6AC985BEABF34751D492C90E
-:1034F000DF032D9968FF8245DA53F88FE0A8783A08
-:1035000069E3DDD20FE1B70C477EE826E4F5711AD6
-:10351000C2251FE969BE8FA54B3BE6F939F69BBD75
-:10352000547FD07ABBA97C70C09CDF9A2EEDE70354
-:1035300043E26FFAA9EDFBC3708E3C21BAF5D73F89
-:10354000A38DF3D4539D713CAAA6CF0AB74E1F6E2C
-:1035500029DFDB80EF8F3AF17D6B12F1E5A59863EF
-:103560002ACF5F9E674F49FBCD0B79BE249C17E79E
-:10357000811782FF8558CA6743BE9278D5F33A3ED9
-:1035800043E7BFF2A34549B0DF7E94AEDBF93C7D53
-:1035900040973ADE1A6CA4EF64433F2E2F386985BA
-:1035A000DEEC492CB31AECDAEBF31CD8578B37E47A
-:1035B000398C74D6B0ADE010491CE2EC36AB072074
-:1035C000375803F7427E6FD8A6B6F805973BBC5430
-:1035D000FFACF3C0DBA8B768436C3EE46DBDFDE211
-:1035E000F52312CB0C700EDD665E879C16737ED8B9
-:1035F0006E73FE04CE80DEFF7CBBBCA0395F70C85A
-:103600009CFFE4835B67819CCB55FFBD2AF4893F17
-:103610004D3884F3F1D3175E8CC6FA2CFD4BD9419B
-:10362000E849A17122B46E0AF408FF5685E9E3B2B5
-:1036300078911EF8811E0F819D61A4930AE13F6875
-:103640004DB9BCFE19D132CB4B745559B7BCE064AF
-:103650004157BF57B6ACB343CE0B1DB7A7FD2F9C48
-:103660005E37EC6AC5A364D9557563C509F82DD6D4
-:10367000BE3B01F457FC4B85E58AE2E707BD0ABE75
-:10368000DFB663CE0D9CCE9AC8F8D0ED7D8BF72ABD
-:10369000C128CABB4649BA5DB85E617DBDA4D11CD4
-:1036A0004757B63624DEA6D95CBE78F7FEFF869F64
-:1036B000BEDCF118C7335C1E271878057A5BC5A7F6
-:1036C00082ED3D159BBF0D3397CB792DD4E7E1BF3C
-:1036D00096E3E1AE92553ACFB793C8D0F9F04B5785
-:1036E000516A06E1FDAAE68DAA949BBDC5EC9775CB
-:1036F000DA39CEB0CA21829104CFA128BBD745DFE9
-:103700002FAE8F6279615118C99FF99C8A708E43E0
-:10371000F4C4A0DDA977549683AAE2251EAA1E57F9
-:1037200002B0C556C1488AFC1332BF04DE2655D20A
-:103730008FD7003FD6CD98174D526FABB406F70325
-:103740002F9DE7C03673BD4A9AE7D138C859E6EFD6
-:10375000D5A29DEBD7ECFE36CCF8DD60DF657D525F
-:10376000D76B55C83304A77A4704CBB3C49823401A
-:1037700057AB14EFC30E15299DE3A0EF254E962FEE
-:10378000E66E94E747338C839083D70D66B967AEB6
-:10379000E2CD04BEC4BA70D6A7A9DC1FDE8BE564F7
-:1037A0009643484E6639AA7D8E9DE3129BF35A825A
-:1037B00090C79A1F48F1D00A327FE4F3E89E7096D2
-:1037C0007B9AA74AB9A7795D1F6EFF3140EB0B3991
-:1037D0005AE2B9F99E1C1EB79F2ADB893E520F2080
-:1037E000B93A137A02C1E541B92E4767C5FA4AB022
-:1037F000EEFAFC9B63DBA3E0C712E5F1DF4B6ED86A
-:10380000A29D87EDEBC203F0539C548A0E5A0CF62E
-:10381000A95B32E4F93172AC77AB568FFD1965962E
-:10382000A977FF80E0297BD0E26E48E95A07E1F5ED
-:103830006662FE27D785E783EE468E95F6A7637905
-:10384000929F470E171CBF73BBD6EFED1916539A04
-:103850001841F448FD9C2C94F6EDA8E1456C07A4B2
-:1038600035BAB9BB38903519F29C2AB317FDFE9AC8
-:103870006EE0E9A48BF152DE3DB94CD924E1F2723D
-:10388000BCDFC85F85B3FDF0A476DEE8EB4174349D
-:1038900082CF718D9FADD3E8665DCF7463A28BB983
-:1038A00090B7413773E4B9D84957DAFA12DDF07AA4
-:1038B000B7135D48BA11E26BB42F744B793B44DF08
-:1038C000EAD4B77BD0B7880E9EC8E86DA817420728
-:1038D000C21A18F18FFC2C25A362472AB40449565A
-:1038E000E147DC2CCE46C6D75DD6C04A82A7BF557D
-:1038F000AECB00ABA43B3A65FC11F95CDF8BF8D989
-:10390000E2FB170B2FD52F4E126CB74A27F926264C
-:103910008EDB09A47007AAB0E7508AF6C531B2FF62
-:1039200062A26FC4B3517F5E4B9CC6DC46C27F2A45
-:10393000587E40FBE87C6EEFB7C8F65E2BA503D33C
-:10394000E43E6A5F15C6F82BBE734026E864D25881
-:10395000339D24664A39414F1B33DDBADC90087E23
-:1039600050D23898CF9986F0A2AA5DD8A7CF487DCB
-:10397000A378F54D934700BE67E33DD8C2A7A7ECF7
-:1039800060FF4A49E39C1F7F083D655B387FDF98F5
-:10399000E97B0F783FADB817ECA20F25335FB12755
-:1039A000527B5FCBD473BFA3748A7FC7DB9023A6FF
-:1039B000CC50B9FE1421EDB9A2518E33D9FFB935DF
-:1039C00091FA9B3C5AE1F094B67057F232F855B434
-:1039D000F53DA6D17743B898FD9C13700DC84CCD2A
-:1039E000861F8224D46EE4E401995AFD31CA06C8C8
-:1039F0004303C7C9FDA7D7473FE8372D53EEB7CFDD
-:103A0000B47DA7E709AF5CBF6C4D585B5A34525B7D
-:103A10007010A5F3B2C69E039F99942A26AC07DEC8
-:103A20007FAA8A4D0C6F7B31F385A84C37F8828FC3
-:103A30001459A6FB6D8399EEDBC6B4B7DD49F9B620
-:103A40002D39D27EA7E9F30B5D82E582B63192EF84
-:103A5000B56F8964FE73CCD51A1527ED5DACDF9781
-:103A60006A24F1D7BA867BE1372E75DADB707E2CBB
-:103A70007C603AFBFB4B9B49BF475CFD5AB37E4FD2
-:103A80007A78586637FA7AA85E0E9A011D95AD5578
-:103A9000980E073678EC7D99CF292ECCAFCC194CF7
-:103AA00007FF2FF384735CF0657AFB3784F791B0DE
-:103AB0001F0B0EBA1A3AC8D70BE3163715B37E1A86
-:103AC00099ED63FE355025BC101DCFD4E86F12EC84
-:103AD000A0E04BD6D6BED897AF6568DFE35C994EC1
-:103AE000A6EB70BE6FD066736502BEB655E1169C3C
-:103AF000B793564AFAA67DE7C0BD80BBAC2202FC54
-:103B0000E0B8D67EFE0A6BD146CAF777086B541C24
-:103B1000E82B8FE93B90E5FB0CEBF7E92FC428C8B5
-:103B20000DA56BD749B834FA10D623E3E3699C4F4F
-:103B3000B7A4E4C3AEA0D353206B6C76E608035D54
-:103B4000CC50981E683E87609F9D9755928F72FA61
-:103B5000BE1FF432696C301D71D8856A25C7AB76FB
-:103B6000240A0FE2873A443BCB231D248F803FEA8F
-:103B70007C46E72744175E4742D77AEB7C656B3D6E
-:103B8000814678DE56EFE0F4A97A97B0124FD85EFE
-:103B90009FC8F967EBDD9CB6D467F1F7E7EA3D9C77
-:103BA000DF593F8AF32FD47B39BFBB7E22A7BFAB3F
-:103BB0002FE2EF841FE64B3ADFD1F9934E5F3A9F35
-:103BC0000AA5AB058466DC33A0F6CC0F753E887978
-:103BD00058F2BBF893BECEA94A913F11FC50B4CE27
-:103BE00001FF2854CF3EF322E1B9A3DCC9F1A11DA6
-:103BF00042F2C10EA783CF8D64BBD80DFB40C33208
-:103C00006FDB9D8673785EB922AC06BABDA9365CBF
-:103C1000580D747D735DAC293FBFEEFDD7FA50FFA0
-:103C20003F8BF12DC2FA1CBBE3D4A37FA4EF8FDF3F
-:103C3000713A03EB4E706C7908E3DE1EA1C1D12A04
-:103C4000E1BADDCEF2D2C008A94FE1CF6188732D71
-:103C50004E897DFB3704E7316D1D06DA5DB346C141
-:103C60002EB34A75ADA42A1F63BDE8FB9FB5F52AA4
-:103C7000A90B637C96346AFBD418FF4CF83CDE57E2
-:103C8000B05CA77885801FE9F82FEC419211C471D0
-:103C9000C51150681C8594ADF9B017AE79FD28E4C4
-:103CA00074A5EE10CBD53E8793E32884DF76D6D873
-:103CB0009F527790EB89D6FEA638C8C8E15E3BF8E4
-:103CC00005681BEB56927540609F8B2685EFF1943B
-:103CD00069DFCBD628A6F8E27B3355E68B8732AC7A
-:103CE0009C0ECA149A13A589CF299D5E897F703CCA
-:103CF0006359539E7D91812F9768DF4BB32CA67833
-:103D0000C74319322E6A109805A57767A5DA1732CE
-:103D1000DF7373DCBD5EBF242B7F75EA70F483E82C
-:103D2000A0AEF68F645AB9DDA10C9784C741E7595C
-:103D300014C7E9747B2EE872CCA7F8EF950C3FEB23
-:103D40005915CF3EFD2CFC7B157F0AE3F3A9629841
-:103D500066DFC80E8C9CCEF28FD7A98C84FC2DD741
-:103D60007FFCD37F89467C54CD4E6957A5B40D693D
-:103D7000F5EDE56C57ABF6D0FE88039F35FBCD5FC4
-:103D80007DF64FD1ADAC97F893B4F85B8EF7AADE11
-:103D90007982E3C0F4B8AFD07635CA37ACA7EA7100
-:103DA00001BA3FB6709F8DF74DCD1E85F5989A5D8F
-:103DB0001713C0E76AF6AD4AE82E2E27B45F3D5EC2
-:103DC00040B7BFD588B59FC37F4884C3F80FADFF08
-:103DD000766654AF53430562D5AE603B8855701C80
-:103DE000C7722D8EB32390C17EE19EE4ED9AF5C497
-:103DF000F049BFEDB0BA6310AF7C418889DDAD53A7
-:103E0000FC20797E9FA37D04BFF085ED2ACB91171E
-:103E1000B647F17EA8DE7EFF41C4DB556F56D88DD4
-:103E200057258E30DEAA77AAC261E00F35B00BC5E8
-:103E3000F70CE7D2A7A36A415F4B5A14EF16F8AD0F
-:103E40001DEE98DE0678DA35FA5A1AD63292D74540
-:103E500083FF14F89A41CE5CB2F77E8E13A47AE702
-:103E600059AEF96D24C7B3510F6F03CE331B0AD877
-:103E70004FBDA4654735CB05DB235D10694EDBCC18
-:103E8000F729BED1C6FB4693D3CEC04F82F6CFAA48
-:103E90002C0F034EECCBD35A3CABDECE3248B6B33C
-:103EA0006878FB0DF6E788AEFA4B5ADAA2D3A9FE82
-:103EB00027BBDFE7D43948EEE325CE23B938473FA7
-:103EC000D919C9F7ED3ED9F9EB092FD178E75AC6D0
-:103ED000F4520CFB6CE0201BD73FB741C601F32521
-:103EE00011D60F5A783E67B62729AC2703DF849F87
-:103EF000333B9F8FB6F03EF6FF7B71ABB3156BC8BB
-:103F00007D84EBB24780FE5BB5FB11ED9AFDE57F4A
-:103F1000A7FF6AED7B9B52A48D23EF3B083D0EC2A9
-:103F2000A5ED3BD5C9FB6E79949DEF2F2C18E6BE0D
-:103F3000711EF8E89B328E51F4773F04FD6FC13B50
-:103F4000F16C6F596E73F741FE8BC336F6132C2854
-:103F5000F01CF5A17E8C9DED4A22B17504ECAD6D8F
-:103F60002952BEA85C433B9350DC8FE8CD4FF8ACA0
-:103F70000C58848FF29307A5F2BA3E526EF1DAD94B
-:103F8000FF13E4FB92C7ECC28F7B2FFEE7A47E5D9C
-:103F9000992AFD0E8F607F515A1917CC8C87DD4E00
-:103FA000A39BCA69546EA09FCA4DC14CC84F67ED10
-:103FB000D21E8972E84D95F9B25E8346A7E807FDE7
-:103FC000B6A5B8CEB3BCBB2B4A40EFB0BC1825EDAC
-:103FD00021BF09DF146638AF6F1A24E9B841F3072F
-:103FE000FAB748F80017E4F825F6A64CC8B9FAB8AD
-:103FF0004BA29B78BCB3DA784B229AA4FF448BC7C0
-:10400000437D1EDF26D8BFD3FE6418CBCBA7FB1E93
-:104010007901E39F7E7230C711B4A50416EDE6F274
-:10402000708EE3AE782A2C08783F7B328AED589F59
-:10403000D9A41CF6595402CB6187A21E5C80FE3ABB
-:10404000368729E0A39F29C29E88F22DBD590EA86C
-:10405000A8AF633F4905B117C8AF944E84DCF7D9C8
-:1040600096C16C27FAEC0D952F29D0F735F8EE1391
-:104070004D0B7EC6F2BFF43F9E7EEA6F83BBF3AF6B
-:10408000546C36DBC3F4F5D7CBEF1824ED03770C73
-:10409000927AC9CA412EE97F8B6C793095E729F96C
-:1040A00003AD03EB7FB41F13606F3FD6B22741719E
-:1040B00002CFC1CC5F03EFDBA49E757ABB8DFD42BE
-:1040C000152F4679D9FE74E7157CEFB042957278CA
-:1040D0008545DEDBABD0EE99564467B27D8BF0CDE3
-:1040E0007A6DFB16551B478EFBD9D601D29F10D493
-:1040F000F22FE4F03DB84971E2E6692C5F6DC80526
-:104100005E2F6E8EE4F8791AC78BB8878A9FFD5CA4
-:10411000E2336611EB0774AE317FAED4F873D59DF0
-:1041200057C7E05E817847E5FB1217AD9E3EE0BFC2
-:10413000A1F87A4FE3634B5F7894F94125ED17C4FA
-:10414000592DD5FCCB4B9F52589E5CBAFAEA879802
-:10415000EFBE6D13B85F70B6E5FE68E37AECD5F894
-:1041600067577B0FD75F4AF565FB37A3199EAD36BE
-:104170000FE0095DC7EFDDFE29F55F6A5FD142F20E
-:1041800045EEE5F3BF288EDCF627F095EDE16C6790
-:10419000A3F5E77B46676C2D8B30FF33CF8433BFAD
-:1041A00039132BF7FD27749EFAED80E787F7B15D91
-:1041B000EDBDE902E7D0E280B95F1DAEFD1ADFAFC9
-:1041C0008AF7C4C04F5345EB81FE687D7EC4EDDFA6
-:1041D000B171FBD0F93C8E76230CFBF49948A69B79
-:1041E00033FDE4BA9C7976109F676DB192DE09DEEB
-:1041F00064E84B6762658A1B3EA0870A97A48733F1
-:10420000635AD81E7046D9C1699B4DB6ABA8D3FC82
-:10421000DA447F89A01FD026ECA98EB54720C7803D
-:10422000CF8FCCE73488FBCEA17673D029CEBFBE2A
-:1042300059F2DC8478053ECF7E1BF6E3B4F03D7383
-:104240009F264F566EBFDC4F8875AADCAEB03FEBA1
-:104250009276FE02EA5EBADD9FE872A95FF1226EF5
-:104260006B69E3B225A0FBA5B5EBE681EEF5792CF1
-:10427000D5EE5FB7292AC3D3164EFB27FBF2F174A4
-:10428000FCAA598A1E9F275CFAF9457B382CCB2D56
-:10429000E988B24DD45F65A3B296C749D1F55B39C1
-:1042A0003F1D4FB8CD02FB5E9B76DFB9A7F9EB70DF
-:1042B000F6044F5296E44F6D29F29E6FFB5BF2BEFF
-:1042C000F6C56F0A62E2FE813CC891FA7A7F047FEC
-:1042D000166810728FC6E796C2AE4E70666E30FBDF
-:1042E00073B2369BF343B69BF3D93BCDF9DCBDE605
-:1042F000BCE75573DE85717B77E109FA36E203A1ED
-:104300006F2385BEEDCE94FA36F2D0B79142DFC668
-:1043100077E8DBC843DF461EFA36F2D0B79142DFBA
-:10432000C6F7391A9E2A357B29D681E3D4F684EB69
-:10433000F100BC5F2ECC49603E2AAC521FBDB024B8
-:104340009BE5C74E3BD35407DB99F438A7B7A27C53
-:10435000E3B27AC37F7B6475DF146EC7F6E79ADF3A
-:1043600049FB73657EB813F68ED6559FAC86D8137D
-:1043700088F24D44FD0BB6F6ADC06F55DD2BEC6FEA
-:104380006F5DE17EE70772FDD8EEA2C72D15E3DC75
-:1043900003DF267D49C66F7B1C463B6AA85F48AC9D
-:1043A00035E4213F359BF3A17E20F035AF695F35C1
-:1043B000311D3C6E6BEF0BBE7FE24907DFF33AA184
-:1043C000D9EDC46C17CB63BA3CDF298FDDA36CC277
-:1043D000F9BD242B8EDB771CCA30DDD30B4D4B2F60
-:1043E000E5B3BCDA995FAB58304ED98C15FB59AFA9
-:1043F0004E8CE673E9160DB64190FF0D700F0E441A
-:1044000098E868E8B6B810BF653F53FD61BB5343F9
-:10441000FC96434CE5D3D71698EFB5175D6D2A1F70
-:1044200068EF8C877348FF96069F4BD6B9E8CCE7B8
-:10443000F986D64B563C7F84BF56BC25E5D3329ACD
-:1044400087B7407B9F231FFE39EF14E0AFBCC51632
-:104450008BF3BE543B87449DF95C2EB70ABF2BAE4D
-:104460008BEECA5DC21B4BEDBFB43625331DDD712B
-:10447000345925142D19722437087DE58D2746827D
-:10448000AEAAD48DC92E2ABF55096CC545ECD3718F
-:104490003B12AEA4F2FFB4F81EC9A2754AB605EFEE
-:1044A0009D0F3EBA234DE0BD91136B9F8FE6B83C44
-:1044B0008DFE926DAE08D0C1C62695F514D8CDD428
-:1044C000B82E3AD9D8141F01BDA67C8CE297727120
-:1044D000B449DF0BC547A19AFD8E9BE67BF1902A7C
-:1044E000EF406AF35CEE92F545BA6CAFDFB3D7E705
-:1044F0007B52D3472B36BE96790B7D3F3B787F2E80
-:10450000AE8457D6EFE6792FB56CDFDA97D27B1DF4
-:10451000BE5D98D7F2B7C6455F49E37CB95DC687F3
-:10452000FFB5F989C7FCC44FEF6C7AC20EFB418519
-:104530003560871E5CFEE4463BE218AEDBB691BFF9
-:104540002FDA56CCF600FDBEDAA77A7CB3868FF25E
-:10455000B1CA0617CDB3FF60C94FCA23641C4BA173
-:104560003AFA35DC13B8B84DC9C3BC6614EDB0E3F4
-:104570001EFF3B1ADF09DD371D87A717F686BDAB87
-:1045800045F120DFD33E9989CB72440FD32FB9393F
-:104590009D716908EBD51F0AD2BE708E6487E8D77B
-:1045A000875569CF433C12AD73B93DD86B3AE4856A
-:1045B00097E5FB0F55740E8DCA87DE2EC4559416F1
-:1045C0008D564D745E333ED2B40F660BC3BEA2FE51
-:1045D00066897EA6FC8C4969A6FA37CE181AE2676E
-:1045E000CEEF2A67FE7595E95D97AADBFD6E85E340
-:1045F0007BC69ABF537A3BD3D90DA6F655629AE98A
-:104600005D97259BDF653C1395D9A18F956BF7418D
-:1046100066FBDAB4EFADFC9D2662DAAF03D33C7FD4
-:1046200094E7A58DFD08BA1D7D36FE9FD6DD79196C
-:10463000D1198F89F85BD83B7C6679E408EBA942F5
-:10464000AE4395668FAACA92F6A82AFF113BE29B59
-:1046500009FFD62442497593C2F646AAEF488A93C9
-:10466000F9DBF17DA7F95E07FABB84F2436A31F604
-:1046700057687935CD1BE74235EC47B083E9FD6BD0
-:10468000FDEAF4197ACF3EB41FDF6037EFE78A6D99
-:104690003B0EF623BC4C2F8ACD437C4965CB545B43
-:1046A00071F6E574A6F3FD8BE516B67F751C7E8565
-:1046B000E9ACA3DCEA91F1DDFF181FD55E696F0D4F
-:1046C000A5BF45341FF89917ED543C0145D6035E4C
-:1046D000FA812E43F092D40DBE743C75E22DA47C79
-:1046E00031FE331CF1114A007CF232BCE878D4FA76
-:1046F0005FE4132C67123C018627A43F312A74FF24
-:10470000DDC2EF20746C50844BF96E3C4CBB24ED41
-:104710003603D3E4BCDB77291EC8EBB32E59F97BF3
-:1047200027BD14C938F51993CCFBB3937E8AE47E78
-:1047300099792981DBFD6FD3D177D18FEE9F098DD8
-:10474000FFD6EF5D2D1AACDD4B1A21467CFB4FC422
-:10475000AFEB72404FE749E779E3D2F0EF4CEDF66B
-:104760001C5E1E95CAF1DA3ECD8EA8F3639FD64E2D
-:104770001FB798CADD05A0EFFE09B017AF6E4C4B0E
-:1047800036BE17E35B65633B6FF28A784E8BC35D81
-:104790000938478A57C8774D8EDFD52701FE88E351
-:1047A000AB6CBD2651D7C77F3A3C59E4205FC8E9BE
-:1047B000897561B38D76783D6D1A2CED35FA397EA9
-:1047C000CE72387A36F6DFAA5DD108055ABAEAFD0C
-:1047D000912E3ACF57597C8F0F667FEF463ECF859B
-:1047E0006B632EEC70BA3C51B1AAB00FCEFDCAFF7C
-:1047F00079E5319CFBBE15B604C8A39F7DA00A8451
-:10480000CED079C672C4A7E192AE3FDD12C9F710CF
-:104810003F558417FEA625EAFE5C97E95CDD3B0B5D
-:10482000E3FFDE41E38EC0B881AD8918D7E3CFC482
-:10483000B8BE151931DDD957F4B466BD94F3B6EAA4
-:10484000F664CDEE0CF91E79C8F7706241BE471EC2
-:10485000F23D52C8F7F8BE4DF32F0C6C68CF837E43
-:10486000EA1F2BB26AF9BC7566417EBF4589F080AC
-:10487000FFDCA278FA70BCC166F9DEC4F29075D58F
-:10488000D36BDA490633D0ED0F2E3984316E6E8C3E
-:104890008835E5C739FA9AEA17BA524CE5D7250E9A
-:1048A00036955FEFCE33E57F9875A5A9FE64CF18E6
-:1048B00053FE47A3AE37D59FEA9D6ACA4F9F38C7BC
-:1048C000547F6651B1A9FCC6D94B4CE5737CCB4CE7
-:1048D000F979E53F35D5BFA97685A9DC2B5C569CD7
-:1048E000777BA17711DE5F86DE45E92D6F65388D18
-:1048F000EB3A7A9CA5DB77794E697250BFA1DE3620
-:10490000D025EED7800E0768F767BEC0B9D21B7EF0
-:10491000C9A022F5DE237D4137A1F542CB47471ED2
-:10492000B8E8A6352C7A2A7AA695F8C4E82B0E1496
-:10493000A4517EF5538533ADC45F465F7DE0F954E5
-:10494000CA373DB54A960F3B7011E5514FDF20F352
-:10495000D3058B1A8F0CF97A869FE631FA07A96B7B
-:104960003DD26ED26DBC69A73D88F080784DE001E4
-:104970006990E813E901A24FA4AF127D96A50B71CF
-:1049800090E813E921D23FF1FDF7A47F223D4CFAD4
-:1049900027D2B749FF447A84F44FA4EFD5CFE6F489
-:1049A000837A1FB7FB437D39A747EB6BF9FBC7F54C
-:1049B000759CFEB9DECFDF5D43743B4390ED31BAA9
-:1049C000FFAB1A7E47D8ED76DBCE1AFDC28A579E22
-:1049D000A7BABFB2A156B446629FB65A634F39BA5E
-:1049E000FC903DF35BAB386590BF5E0FF7260DE1A1
-:1049F000F1FBBB986F6BDF8F89E903F2699D0A5267
-:104A00007D29289F995FBA2A86F8C70FBEA9B5816C
-:104A10005E3EB4747F7FFB0B8D4EDA877833878CD4
-:104A2000E8F2BBEB7EEFCEF81A835F1EFE6C3D8E84
-:104A300047F7C7F39F213E47F793EBF141D76AEF62
-:104A400023E97E703DFE47EFB7F09260BE77CD1A46
-:104A50002BCB2D515611C4387A9CCF358E963CC441
-:104A60003B5C53E9E438B73EF41DEF23523D2FDEA3
-:104A700099DBFC25D5CFEDF2BBF7D1E641E53C8FC4
-:104A8000C24B3EB6D75EA3C51DA0BD4396F33B7592
-:104A9000881183FC4129DBE11E55A87D7E571C004F
-:104AA000EA47CAFA41F497FE158D17DDB58F06C4A3
-:104AB000B5E4216E6C40B593E3C6368C09F2BDB9FE
-:104AC000E9B1D7DED3AA224E38E6C7D8474FA7FAB6
-:104AD0006602CFEFEE730FF0507E5A5C5A6FA4530C
-:104AE00043DEB5EB667DE6625D757CE978D7D74B32
-:104AF000C7B7219E8AF1FC5DEB17BA6EA1EBA5AF9B
-:104B000053E1A52EFC037F97AF4FD7FAC13EFBFFC1
-:104B1000CBFA0CB7B6F07DCCB04A8707707DD77A58
-:104B2000DDDC2E26E03E78F125F741A44BD27C5FF8
-:104B3000807F968A31135CC0914BCD819D27B4DE76
-:104B4000F2EF59EFE1907A07E20AD67C9D7679BDC3
-:104B5000DD21F51A620BD67E2DED4C37E27C3DE46B
-:104B6000B6B11FEDCD703D1EC3EBCCA3751CA7F1F4
-:104B7000A343A296CF0F12D7FC58DFF1DA528FCBA6
-:104B80005ECC72EE78A7596E9CF04D5123C69DD035
-:104B90002B448ED6FCE13768FD5E279AB8DFD07BC8
-:104BA000F23768F269E83DF9E78668F2658A4801FC
-:104BB0009F1A2F3C122EEDBD83F12ED96F92462FF6
-:104BC000696E558C063D089F15CCF155BC77908BCE
-:104BD00071FD9CBF5E0438FDA108723F938991224C
-:104BE000FF23216CF29D03793FB35AF5FD27E42C96
-:104BF000FD5EE6C270DFABD877AF444E998FF728E1
-:104C0000C6158C4B47BB03E3DD2C9F1C70A4B1BCC5
-:104C1000847D658BEBDA7F6FD0F9926E95F7069104
-:104C2000E2DE603A6D96D7E9FC41FE86AC1502EDF6
-:104C300026B8CD71387AFB1FBAC60A6B41CFFCFD8E
-:104C400087B97BFAC3AEF366ECA0F1B083BF197BE2
-:104C5000C578CCF7CDD83E169986D939CD7931BDF6
-:104C60003B794EA7E7AEF126086B7CCF78D6F11AD8
-:104C70008A4F1DCFFF025E2F7487D72F060B29376F
-:104C8000474A3EA2E3B72AACF31E671F635C44A504
-:104C900043E2E933808C7BB87557F13C3EA917FDA0
-:104CA00081EF4575A3B83CD40E2536C7705E7FC72B
-:104CB000ECCC83EF4627127CD7397CEA50C2CBD9A3
-:104CC000FC60264930E2930D0D7CEFFADCB3AA07B5
-:104CD000F27FA5EA5EEB014F7953653FA0F8E695B8
-:104CE00064F809C5E6EEE3A32B1D12AFBAFEB3329A
-:104CF000AD88F7A7701524CAF7D5E43D725D1EE8AC
-:104D00001F26E38BF5FBCC3DC9072323241FEB1F94
-:104D100026F9AEBE9ED48EF349D4CF48E25349F76C
-:104D200045B03EB0DBE54D1A0A7FCA786192A7759F
-:104D3000BDBFA3977C3FF05A91F9D068CA8F3F64FA
-:104D400013012AEF182F4CF164856F94F2BB16FA09
-:104D5000FD98B044D2AF0CFC20DC1D617A6F343278
-:104D60002BCE948FF2F433D58F19956A2A8FF50ED6
-:104D70003195C74FCC37E57B175D65AADF67F658DD
-:104D800053BEAFEF0653FDA4F269A6BCCE9792E4E2
-:104D90002731A076AEA9FDC0BA1253FD147F85F964
-:104DA000FD54BFF74856029E77947F696B9687BC87
-:104DB000AF6A1196915DEF90FC3A5ADE0799E85C74
-:104DC000C4EF916434FDCC0C8FFA8D8A732629468A
-:104DD000E1F724AE739BF96061A2393FDE95F72AB3
-:104DE000966E9C2B34FE28A8809E926AADA6EFF3A7
-:104DF000866A7C3457E4B29EFE5DEBEF1B625AFF7D
-:104E0000507C5D4E0FCFE705DDD29E6F9C17ECF90D
-:104E100046BCC09E6FCCC39E6FAC0F7BBEB11CF670
-:104E20007C6379C121331D8C3862A6832B8E9AE96D
-:104E300040A7CFD0F5BAB2D54C1FC2A7F8947FB027
-:104E40005E577F6AA69FD0F521098BD76F825311D9
-:104E50008FA4FCFBEBB52E64BD3AD787F00DF9F6B5
-:104E6000DAE050BE275B78481578B7E4516D9ED7DD
-:104E70000DADE527C3B65B7DBFE67DAED155435F83
-:104E800049571D879E0F071F7D34A4FFD7FBF902EA
-:104E9000A83F3BFE62B21DF4D12EDF456B031FEE2F
-:104EA000DD15B7497ABABC77F23395E3188E599A73
-:104EB00014F0EB8218DF36F0CB9BB36B15F8671359
-:104EC00045D18E4588CBF98FB064E4170C94F77701
-:104ED00045762BDF7FD0F9E282241917D83254F3BC
-:104EE000F37A64DCCEF343A5DD24CAE3E238E3E2DF
-:104EF0006C79BF83D499E40539C0C7E1F041C0475C
-:104F0000B385DF696CB5B9396EC4FF862AE0F783D3
-:104F10001C0BF9728026DF357CE47000FE41EB85C6
-:104F2000E99C1D1C7098E25B876E7399F2392D899C
-:104F3000A6FAC376BB4DE579C12C5379C1218F29DF
-:104F40003FE2C82853FD2B8E7A4DF92B5B279AEA56
-:104F50005FFD6991299F24DA1F067E072A528F3E42
-:104F6000333455E2C92D387E6FC19DB1F2DEA7A65C
-:104F70005FEB72BA1EF7ECD3E83954DE1F68F771A5
-:104F80001C75435FE1E17B180E4D9F12663DC0A783
-:104F9000C52D77DEA3F09BE396F578E54E7D41D3F2
-:104FA0000F7439DD10AFEC35C62B2F08EBFE3DE05A
-:104FB000FFD2D63D14FE817639DF869FDAF9DE888E
-:104FC0000E57283C33B538DA2D8EEEEFF5D8B225E2
-:104FD0009D256514FD1DF4FE98CDD3CA6FDD5F36A7
-:104FE0009EA7D54FF4D5F00BBB67A5FBBBC75B30C5
-:104FF0004CCE67BEC572F3D46C8ECF32BD83DF3B1F
-:105000005BEAFD51B94AB7F35B1023E3A7448CDD9B
-:105010000DFAED793C89CF44BB68E4FB475A9CFF0D
-:105020004D6B5BEE194445F3ED4DDA7B60011BE8F7
-:1050300061D25892C3F284D8B66557B393E4A2C73D
-:10504000EAAC6C3FE9BFDD358B24B8CEFB1B0349CE
-:10505000EF017D40B681BEB42147E571AEC19E1B14
-:1050600081FDF64D679C3DFB0584D0CE0BA94F75A5
-:10507000436F4C87FA3CFEAFE3ED43F1A4EBAD4246
-:105080008B334CD7E0D2F1D76977D0F0A7DF7F70B0
-:105090002FB3156D72F23D8A8988DBD2D7AF2547D1
-:1050A000D265AD860FD4033FEAA95EA19A1D03FB2A
-:1050B000728770C7B8BAA1433DFDBFC28B8EFF9EF9
-:1050C000EE57F5C41F42F9C277DDB7EA894EFFD922
-:1050D0007B57063E21E368B47509A45BD83F7D6722
-:1050E00094793F6FCC96768D71DABEA2F3DD996725
-:1050F000E61702F6F18655AAC62FE4395E9C52C423
-:10510000EF118B3A17CB33E51A2FD6CFD7850FC8BF
-:10511000F7E0AEF516255C45F992669BD848A015D8
-:10512000FBBB8FF366BF931B71FE9E44C0CD263739
-:105130001AB7B44909EC4FB9FCBDECC54EF97E5C19
-:10514000E8BBD98B35FD172F2A60DF86FA65EECFD5
-:10515000D6CE6B8FF07C2BE167BDA50B7E8DDE027A
-:10516000F21D31E8C3AAB4F3709C968E3737FC2445
-:10517000F15D79C26F4416CEF3466BB771749DF83A
-:10518000D5FD2A9D7EC2C31CAF1F1A1770D6FF4AD9
-:1051900074777E1ADD7FD3D33EE8F4DF7C875FA887
-:1051A000C369891E053E04FFBFDBE857F9F3488257
-:1051B00090FD2731F08FB46AFD898DB9DDDD4FF4A4
-:1051C000ADD8C5F110AB2CBEFF405CF219EA1FEF61
-:1051D000B0DEE53C9080FBF89334BBD3E5F3D6E436
-:1051E000B0D1F27E40875FE5F5EE9828EF73131F8C
-:1051F00015D877BA1F7FAA08F642AAFB497C6B46EE
-:1052000031FE753F49717014C339B361B10D4F4818
-:10521000B63E7C7B6184BBCB7FD23A40C6E7F4E4E8
-:1052200047997EC9C3FDCDB87415F7732C3B45CAA9
-:105230006B8DF72C039D0DD9266C9867ABADFBDF0A
-:1052400019989223F7D152F8D27B1BE27E5628ACF4
-:10525000072C57841E07C47C5ECF5F6CD2F2853268
-:105260007FCB2A996FD5DEC5DAAAD93B304FA498F7
-:105270000FF4F0ED9A3D04F3408A79E03BF81AF21E
-:10528000E06BC883AF210FBE86147C0DDF4B445109
-:10529000729E2AFD3DE30DFB03FE9EF106B909FE59
-:1052A0001E631EFE1E637DF87B8CE5F0F718CBE1D4
-:1052B000EF31E6E1EF31D687BFC79887BFC7581FE8
-:1052C000FE1E631EFE1E637DF87B8CE5F0F718CB97
-:1052D000E1EF31E6E1EF31D687BFC7587E739D62BB
-:1052E000F207DDACBD3B50BA3E8EE9A339B52829A3
-:1052F00087D6F73F23FFE7C7B654ACF3DE25FC6E35
-:1053000060558447AE73D344B9EE1621D7B97D0EEC
-:10531000AFF3ED76992F94F1C2A1F403BFCAF874EC
-:10532000E957410ABF0A52F85590C2AF32DE2AFD52
-:105330002A48E157C177F85590C2AF82147E15A470
-:10534000F0AB20855F0529FC2A6807BF0A52F85593
-:10535000F01D7E15A4F0ABE0FB318203FE151D2E7F
-:10536000C8F9E9263D94E8D0A487BA4C79C8F9C6B3
-:10537000FA90F38DE590F38DE590F38D79C8F9C639
-:10538000FA90F38DF91BF188716F29EF1BDB41DE79
-:1053900037E6739AFCAFC1863579C3F95791B646A3
-:1053A000298F292E92EB729E9A05FF586BB8921C9A
-:1053B000EB213976C56F678DBF92F889166F972BF1
-:1053C000DA2D586FF67BD3BAF98282E38373FE3B02
-:1053D00091CB757F2BFFD1BAE7ED14AC376CCB9036
-:1053E00070E9ED3DC2A522D5EB77E5BBAF173ABE1C
-:1053F0005E8FF9A5010E5228F310079177BB331F7A
-:10540000F1ED5B2D8A8C0B5D29E37243E9AA49E338
-:105410004B5B2D3B0E4450BBF662C5837B07995610
-:1054200071C8960F3CD5E6439EA8CB89D5E2836B25
-:10543000AF423C900EB76E7F243EC1F7DD46B70BFE
-:105440007B198D73CD17C28EDF5B986497F204DAF7
-:1054500041DF1CEA57BC9B0CF4BD32479E7B3EFFEC
-:10546000B2ABCAE8FBD0EDB557E11EDDA408D9EE1A
-:10547000378F47331EA7342A9BF0FEC9E8EDC28B55
-:10548000FBB1BFD4E01EBADD652FE3715D7CFF4E3A
-:10549000EFB7784332DF172C16ADE313D927A1F00D
-:1054A000FBE63ADE687EAF627EC4E20FC18EFC2F5F
-:1054B000DFC32171F1FBDCC3B966786C21E2DBC488
-:1054C0005EF90EE4E4E1C5AB7A135CBE807C07F2C2
-:1054D0009A2F6A5FE3FC66F90E2493CF48868FCF3C
-:1054E000C3417E85DFFF98E2DF68E9E5C6BDE015D0
-:1054F000B604D4DF2E3C500B060979AF559F57B642
-:1055000038620957402FE2957803FD11E798017A38
-:10551000C9F3D8F87D90A956970DFC4697738A5D1C
-:1055200072EC4275740CDFF70B91132E36F6E6B869
-:105530008D7F3D8EA483EF932FDF15CE72858FF87C
-:1055400007F8E6B93C197759B9ECC39196D4AE384F
-:1055500092D32981AD78DFF374EA8EE8510ACB113A
-:1055600087C05FDB1A9FE77B82C5AB5EE3FB10174A
-:105570001B1F8896F7AAA47FA54CC39B6E6F5AA8E1
-:10558000AD4F99163F74BC5EBECF4BE730BFF7718D
-:10559000B1D1C67246A8BC2884EB0F88732B6FB4B8
-:1055A000F1DDD3C56B8B57278AEE7E77C52BE3CF12
-:1055B000B5719734DA384EA85C7B472BF477589650
-:1055C0006A72E8D26DE6EF277242E44FFDFD44AD0A
-:1055D0004EF15BAFCC6439A8D6C671EEF35748B92B
-:1055E00048EC1001DC6798BF629C05EF58CCDFE502
-:1055F000F528DDD0D13B9A7C34098312DEA75E8A80
-:1056000060BE32ED523FCECFBA94C8E98D97B2E476
-:1056100077AC1DD14B6BA1BC5FFFBE2617CD441CE0
-:105620006501E4B23E4CD71D44D7182257E35743D7
-:10563000BCCA2B30C34FB2F956214E73D246C1F7C4
-:105640009126437EA282D990A70AB02F520AF93E32
-:10565000C64485EFB74C1EBE4CDB07B42F04F311D4
-:105660007EF7C3377E6A00F137B37D3B2C58777DD8
-:105670003FF8FC6DFC0EE664BF62C77B813E4DCFF8
-:10568000D6E93D745F2C88D4EC634E69FFEAB48F91
-:1056900001587E9C27F246C4B32E802DB39FB6B02E
-:1056A00084AAA86C599E9C1B79632394AC7FD36E0B
-:1056B00032DF6291F79F48FEE3787571A4B00FE581
-:1056C0008BD72AF98897D7E1FA7AD8D849C37A775D
-:1056D000D14149E7FECCEE03BD60F95D1926FF4CD0
-:1056E000685A4AF8C63E5A10D3FA63FCD2D0845C9A
-:1056F000E11D9F8877C8F5F98A20E202E76AF9DBA5
-:105700009EBDF28F6B9C8C27CE8FCDED7723E23F31
-:10571000FE65FE385FB11A7F37AA4DF17973E53D1A
-:10572000C80958DFC8EC767EC76066A64B9E2F215D
-:105730007696DB72DDF25D84107B4B69B63C6F843C
-:10574000D59D3C8FFD3A6EB657EAF33E6E33DF339C
-:10575000D5D3EA5C6937F8BFBA27F1A045DEFB7FF5
-:10576000C412D8F122D16BA0B76F01E6FB08E2BDED
-:10577000197E1FCF4F7F47A3934F69EF65E8F474FD
-:10578000ACEE22DF972871DADDAA819ECAD6287C8A
-:105790001FB1A44EDE27F6AD51E4BDFC1EEC578FC1
-:1057A000CFF99ADF517AFC1711B250C3EF7CFB910D
-:1057B000D71C295DF8FD53DDAF6C927F0633106F67
-:1057C0003FB7369CDF41FE7A58D18F017F64B687A0
-:1057D000D76912F134D49F1AE3FB29BE97882307B7
-:1057E000616F5CF0F3B7F87DE19ABD29FCEE61F1E1
-:1057F000EEBCD57847E5EB61BE3B72897E8B9D2E72
-:105800003BE490EAC6583E9717F4D1EEA98B76F6A2
-:10581000E7E9EBF360AE94078A3C729C0B9A3E4535
-:1058200008B34D35D593E77FE83ED4EDA2A1F695B8
-:10583000D0F72ABECB9E027B89DD6057D5ED31B60D
-:10584000ACE373709ECFB777FFBB8DAFEB76474D60
-:105850009F5DD8A9CF664FE803B97F9DE2821DBD49
-:10586000CCE9BE11F1F565876C88F01493E2DCF2A7
-:10587000DD92BBE4BB2525B7E6313F9B8F35C9C719
-:10588000BD8751BC8FCB0294C6F7BCDFE7AD7B650B
-:10589000C01ED053D0CBF7E0CB5C5E7B9C412E2A60
-:1058A0006D524CEF18E8F91773A51D723EA919C087
-:1058B000DF4DB7A6D8F186D07C128F1037F8BA46E4
-:1058C000277A3BAAC771259352C541F9AE14C19DF1
-:1058D00022C733FE4E514993F93D06AACF72DDFE31
-:1058E000DC28EEAFD845F34E41EA6238090F8CA7A9
-:1058F000F67BA83F378FC3EB511A0CD86037988FCF
-:105900007816CACF75056C18A7A451BE8FE25B2B21
-:10591000C7F1AD89B5E7402EB0BAEC038CF260A3B5
-:105920007CCF78BEF6FB11042FCBCB658427DCF34C
-:10593000D2EF7D86E2AB5883BFAC29D62C5F36AD63
-:10594000B3617DE6F4F05EC3971A1D97348EE1FBD8
-:10595000F565562FDF97F069F8FEEBB2F0BBE12753
-:1059600099D3FC902D05798D2F7D093CF7069E82F9
-:1059700019FC3ED2B2708E679EE36AE2F976E2FBD2
-:1059800001C20FE4155711E39BE8C48F38C0B2661B
-:10599000F3FA76C11325DF656F2EE6FDB7C8EAB3CB
-:1059A000BB8C70ACDF9F81FB5B7368DFE3FD27E19D
-:1059B000F2F17DCC530FDCC8BFFB063881E7288F9E
-:1059C0007B02DE3B22BA61BAD6E9674181DCCFFABD
-:1059D0007851C3ACD20E3FECBBF6A9F720E4F30636
-:1059E0005A6FD8FF7BDAA7765C00A471ED65F2DD13
-:1059F000BAD07DABEF577D9FEAFB56DFCF8FD98AB8
-:105A000082894A17DFA1F3BDF6B96EF03449837776
-:105A1000AEB6AE84D75785C1AE376298DCDFF3539C
-:105A2000CDFB1FFDA1DF54BD7C6C3003F73DF5FAC3
-:105A3000FAB8F3E3643BEC03D05BEA304B67FDE577
-:105A40005CDF62E21FA59DFC63FBAA04F08F1D0AC8
-:105A5000FBE196DF23E5BEE5CFC87BE16796BFF8A3
-:105A6000F62CAA77FAC18D0B8CF72FCA82925F2C85
-:105A700024790BFC6391260F6CCCF4E50D33ECE735
-:105A8000B2FB9FC9C4FE98DB92770A6FA8D1BCF91C
-:105A9000BDA33F3FF3D28757B9BBCE5D7D1E256BBB
-:105AA000DEB5153B8D7893F47E7756079F5BA5385E
-:105AB000B7E853696331F36191487A8FD2B5EEA1AB
-:105AC000F450DCA8B09C575A3732A0FE2FF2EBD22C
-:105AD000B553F98D287DBDF4775FF47357877FA6A2
-:105AE000B64E73357A9E3D4CEEC3B9E529F645BCFA
-:105AF000FF53ECF8BDCD395AF99C32F3F7CEF5726D
-:105B000075F2FBD5D827B89F84F5EA586B93F6CB8E
-:105B1000ED97AD5732E4021D8EC59A9D72A1666F56
-:105B20005CA4C9CBB45E8B8DEBB5F871B95EA5CF23
-:105B3000BEF517BC5346F3D3DEA393EF0A94B4EC3F
-:105B4000E0759BB3669D2D85EAFD64588A29FEA801
-:105B5000B436CF053BFDDC351B6DE0073F1926F160
-:105B6000164AF7F3B5F8621DAF388F14833F47AF7D
-:105B70000F3EB883C6B9755978B4F177ED021A3D76
-:105B800097D6C6C661BCD2DAE27BA17FE9E740E8DE
-:105B9000FE3B112EF74509F587FD79628C87EF559D
-:105BA000CFD77E372FB4FE431ADDFDDA26DFBF4C98
-:105BB0008A6C7992E33B6A223CE013E9E9AD018CFF
-:105BC0000B7A06DC768B7C2F33BDB2F573C041A215
-:105BD0003CC7F520C57B5B10ED1328BFC922EF79C8
-:105BE000A5AA32DDA7E107A637948B5EADFC1E5F48
-:105BF000E7BB5121F46A179BD7E0DD1F7B2FC1EF74
-:105C0000A6E9F4A9F7A3D3A74EBF3DCD6FD7F79C64
-:105C1000DF8914CDCE92E54976D0B80BEE1BC4BF18
-:105C20006BF15DF3B46BEF3576CE374CFEDEC765B6
-:105C3000F34D97FA52CFF36D2E4CE866BEA1F3D424
-:105C4000F7891E43DFE94F6992FE94130A9D63D4DE
-:105C5000EEC4B2708EABD3E7A5DBF5BFEFBD878F87
-:105C600086C569F6AAD628C897F3B5DF51114199C0
-:105C7000C7F7A986EFFAF9AFBF5FA7F3E993B5DAE3
-:105C8000F9285AEFC17E1675697C0FF558D389281B
-:105C9000BC1373628C844F6F77AB4DDE73165176F5
-:105CA00037DECFBBE9D63CFEBD94858D7D589FBDC8
-:105CB000A92E8DF9C24D7E581745A71EB048E38323
-:105CC00091B716AFBE02F5D7A7F0EFC22D747A4E8A
-:105CD000ADE7F6433D9013239BA7DA53591E96FA7E
-:105CE00082EE17BB5511457C4F0D7C12FBCBB23FAA
-:105CF0001DE7CFE2F5523F9864116BE03F1DD8508D
-:105D000034A12FF8C4C38AFC3D9A0DE6F7BC860E79
-:105D10002AFA027C26F45DBC5B6D2D5EE8A782E466
-:105D20000ED8D1163A8B589EBF45E393C79ADBF83D
-:105D3000BD7E1DAF8FE0BF78A72AC47E146A271AE4
-:105D4000A8D907FF1FAF8F7B3D0080000000000037
-:105D50001F8B08000000000000FFB57C0B5C546541
-:105D6000DAF87BCE992BCCC080C84512878B84850E
-:105D700034C080D7DA518150BBA0BBB9BA218E653F
-:105D8000CA650650DB5D77D7FE8CA1A6667DFA4515
-:105D9000A665ED80976AC376483428A8C90B99593F
-:105DA0007F62376A2FB9635BE62D40BAFCEDBF6DA9
-:105DB0007DCFF3BCE7301751DBFDBE6FFCF97B797B
-:105DC000DFF35E9FFBF3BCCF3963348C751B186324
-:105DD0002A8B8E413968488964998C8D09695F6185
-:105DE0004C89C3F625DB45C64640FB7C93C8621947
-:105DF0002BD731FA7D8FBF1F31761F3C37C3F3425B
-:105E0000A934D607FDD737CCA072C9D6C26DAEF182
-:105E10008C250925B1936360C0E36AB6078A25CE55
-:105E20001977302BCCD3A48DD225C373B52B29C7BA
-:105E3000E09F6F49E343490CC69D69D4CF77437B0C
-:105E400081694E41148C5FBA332A5B32FBFB5D6F74
-:105E500011181BC958A573461C4B61CCF1DDE167D5
-:105E60004CA9B01F98D304F37FE50977BBA08BA39F
-:105E7000AE2D4982233CAAB3A758A07F95D8316F95
-:105E800012CC734E70EF4DA0FEE63853C0FAA1E578
-:105E9000E93AC6CCE98C39FFCF8734CFE7E2893BBA
-:105EA00016C07887737F04CE53F5F81FF201326C69
-:105EB0009D68CFB2E4E1BC8D7B4D121C747B6356B0
-:105EC000099CE3BEC7C746DA332F9FF7B668B6A86A
-:105ED00004DACBDB18C157695FE88ED420DCED5EB5
-:105EE000A6316169629A6828CF486C9507CADB526F
-:105EF000D8A2B9067FBB0DE100EB9E89DC9254026B
-:105F0000ED157B9F48324379D6C8EBA57B7F7A9C01
-:105F10004540FFDD5A0DE2D5AE621A0B8CBBD7258A
-:105F2000D8DC50B2F268C61210A36E7D9991B159B7
-:105F300096709AAF627B0E63B9FE7DC1736A3FAB08
-:105F400062C5B88F31F503D9CBA1FC8BCA7B1FE2A8
-:105F5000F32FB57A8B2B19F16226BCFC658B548428
-:105F6000EDAEFB053656C0FA7E631AAC5F16C96A01
-:105F7000717CA1F4579B04CF571C10B2B5307B78CD
-:105F800066B7E61E039116D159B589D3D98A7675BD
-:105F90005122E07F458B402D0E9557331CBE2A2F92
-:105FA0004D66E680FD56B6B668CCB08EA319CE0914
-:105FB000FD1D9E539AA5785EB685B17CC027FE89EB
-:105FC000F86B3EA5B937003FD5AD1C2ECE56DEBED0
-:105FD0003803903B99B66213D2A0DE2650BD3E6BCB
-:105FE000C2FC35AAC07AFEFC3569589A084E4C3579
-:105FF000905402F0DC94D1A341FC3BD7CAF3425D3C
-:106000001DB05E0D12E548DE9E6AC0F1661AAF3C17
-:1060100077B646D178AF336C03BB0936516D50610A
-:1060200059EF344460B9B356CC50597173611609B5
-:10603000E0DF111691C52261CAAA5E3D4012503BB5
-:10604000705884F6DC48FB83489F710CB802E83333
-:1060500091790506F4DFDFF9592ECE7FCB18DF17D3
-:106060000CB6AE5E337D7E01D0C3268B7C8E4C5F3A
-:106070002ED2F1C84340AFB0BFA7D56C833E07CF47
-:1060800057C2E6423BCCC208CFDF84B9F7C0DFAFCE
-:10609000316F22CECF74DE541CF79ACCA7255AC399
-:1060A0000601F6F59B14FB63B88F3B05F5F86C1100
-:1060B00071208DC57EFD6AFE9C6D79C2A603FC4FE2
-:1060C000E7E867A345E66240A29A51F106A463C1DE
-:1060D0006663AB60FD07330FDDCB802E1E1ED03113
-:1060E0002D9CAF5ECFCF3D7D20EC9400FD468F2AE6
-:1060F000165916F437AB5829F43F94297A55D89F8E
-:10610000E9DCD89FE90A6DBE0C599681FCD0887AEB
-:106110001BF5EF78F31B01CA44E9E2E1483857E286
-:106120002F054B3DF4291B3CFDF4FF85B2F452537F
-:10613000CBEFA1FC75A4BD19517772B0F8941D5036
-:10614000F6B0C9A3B364F2F902F7DFF1AB6F22A294
-:1061500045FFBEFA074EEF7BD98AA5CE22C0B8E92B
-:106160001D92579B75F97EFAE361E3A9D48FE1395B
-:10617000FB0DA25B10B0FFE10F717FD37506AF146A
-:1061800081E3D4177C3AFF38661E1D75FA4646280F
-:10619000F83E91B158DC3C8C1FB8687037C1B96FBC
-:1061A00091F94FA1AF1E8B48F8E991F1A4C091E994
-:1061B000B222917EEBD58A5EF085B34C3F7FD6E864
-:1061C00038FF0C5E126D38FF60B9D6CD608AC18E83
-:1061D00054D2275792A77F0079CA40D7BC976AFB51
-:1061E00033C20FF94A07FC78970C2FC03FC3F9253B
-:1061F00079FEBB64B8DD6510399C7E120227996E6A
-:1062000014BA50F62F98635869B41F9FECD7DD4736
-:106210002393098FE3FF83E3EF13C2DF3727D60110
-:106220001BB151FF984578FC5FC09F57B4FE0BF837
-:10623000EB0EC59F577F3DE2EF71D1D284FC800801
-:10624000C8A1D226C2F9580623FE2F93C22C9BE088
-:106250007C76E4FF9B88EF8F22DF2BFC3EA6D837AD
-:106260001EF5E449C69EC17DF9440FB5A766A71087
-:106270009F5FC7BA13B01DF09C3717F12ED876E890
-:10628000242C7DFB5E86F55D1506CB1E386FBF5B4B
-:1062900074A961FE8628F78EA5B06EC35D991617A6
-:1062A000B63396D58672A03CCC827ABE218ACB8545
-:1062B0008605E9A4870F7E2725ADC2732C08B33469
-:1062C00041FF866CDF2313A0DE30D66C7141D757B7
-:1062D0000596BE1DC7CFD1D13A0D7338DD363C329D
-:1062E000DA8D7A05F4CFF37AA83F591EC6F09C0DDB
-:1062F0008DB68468A0CB9722ECA3B361FFA3244E94
-:10630000D70DC9D00EE536A164C17D38DF78BE6FE8
-:10631000DF82B017F7C22CFA341059D07E7295B1D3
-:1063200009E5A5429777A5737937C6756A07C2C98B
-:10633000359D65D4C2FC7F93E94B81BB60636C558E
-:10634000B41FFE0A9DC5C8701756737A734D97E542
-:10635000623573D70B085FE60B07F8966941414237
-:106360006934D9ADB8EFFAE5801709F7CFE17F526C
-:1063700064E59E61F8E747282CF3884C04E48F32EB
-:10638000C6F9A30CE908E96F15D05100FD31DF759E
-:1063900051A7C3653A82F16B8D25D370BDCF853F80
-:1063A000E463E3897F4AF3875B67563697030BF410
-:1063B000F699D89FED8E14515FAE30F1F54E647FA3
-:1063C000361AF5C5C95FBD791D96C7234A6ECB86BF
-:1063D000FEDB167C5D84E2FC6F093E359EE36F0BAD
-:1063E000FEFF68B443CA56BF49F4FE43F759281963
-:1063F00032504EAF047DA615B0E474B0F23E467440
-:1064000090C86A896EE365FD050CA3473975F300F2
-:10641000D88ECABCF0FF4797746C89CE5F9FC6A226
-:1064200082EA33740941FD0B4DC941CF6F8D1F17AF
-:10643000F47CA6393BA83E3B635250FFDB2DD38250
-:10644000EA774E9C19D47F8E6D4E50DDC64C241FCA
-:106450003AEA8A733F01BBE1B5BA92DC4F5497E345
-:1064600063AAF6D07EB305E824DB3B5F3509EA91E9
-:10647000875626437D53CB115E4F3CF44532E06690
-:1064800073CBD1F92AD0DB536F3CF4450AD41F6D8E
-:10649000E9E2CFA7C062A340ACB6BC39DF05F89AE9
-:1064A0009B62DF8AF89A77A9F6288AF9F7D7CCBDDC
-:1064B0002F5942B930677406EC2737C5FE103EBF2E
-:1064C0002BF69E759100FB1F7D5BAB463CBF985D34
-:1064D000B215E9A1FF22A7F353889791FF7E099691
-:1064E00003D9618A9CBD923C54F8AD03F4C61215E1
-:1064F000C24947A5B7CE44E5A1BA782A8FD499D925
-:10650000128063575D0695C7EA2CD47EBC6E229537
-:1065100027EA6C54BE5B574C65775D09950AFFB25C
-:10652000BD960D6A2442972AEAB4CE4F8F57D263A4
-:106530002028D969059FD0F94DBDAD399BCE759DF9
-:1065400009E959693FDAF9815904FA9D6AD5113D83
-:106550004F35749B75565E47B9B8FB22F38A11BC60
-:106560009F2AB05F8C271BFD98A90E03F54B1B8457
-:106570007E59D8EFCD0494F7536B3516B4639E5013
-:1065800033971EF66F14DF90701DE320CA6CD80598
-:1065900018D53A905771A06BF139F4633A28770F08
-:1065A000F2F54647D72E47F934BACC60A9E7F29501
-:1065B000E44BE2086F02EE2F71A586DA8D628F1927
-:1065C000E5605F9D7716D269812CE70A345CEF3075
-:1065D00011E4BD807CFB6D5722DAF3EDDC9E2FD0F9
-:1065E00096EC44FAAE5671FE65317AF71E5C47D5DB
-:1065F0005DF12CF4EB894DB46C4268C51F64696091
-:10660000B717D61467A2DCED615B88AFC15EFD13DE
-:10661000D2DB8F3381DF459948609EF8E2F0A64DCA
-:1066200002DAADD7E7215DCED59A0F30E0075FF6ED
-:1066300000D1FBDC48731E7A0ABEECAF793DCE7CFC
-:106640004080E7263630BF00EA55CFE94D9F04F081
-:10665000A9D3131554AF694B307D12C0A755F80765
-:10666000FA47B7092A94BB0E792BA704FB05C4B7D8
-:10667000B3F8730DDFDF8006EDD88BD966A26FB05B
-:106680009749EF0FCC34BA9B60BF71236AB357A010
-:10669000FD9469CEC37E49EA8108F463FABF5515BB
-:1066A000BBC9EF1988F8C9783F7D3DD321517B28BC
-:1066B000DDB5E6707FAF26CDB019F1501DAFD351D7
-:1066C000D971B188919D56928676B94DC3FDCBD0D4
-:1066D000F17B73B81E495EAF21B940A208B66C0BBE
-:1066E000634ADDC52632D6F88BB021BF07C0C93456
-:1066F00063653FC8356247415A507F1BF61F7A8E4B
-:10670000F61CF38F4F7949BB63AD4A5E0FE96529EB
-:1067100073A33F182AC7AB72A365B9C0F1FC748C90
-:10672000BE11F19C26017DE750C94C50268633B23C
-:1067300037135FD7BB913E77EB39FDA789BCDC2DC2
-:10674000F2FE9A30E6427A57FC874DB9F629B979BC
-:10675000348F97E6915AB291AE139887D657EC24AE
-:10676000A51FD8437A1202AA8174C4D754491C16B3
-:106770009E2772A615E58C44FEB0B14F03E4775F07
-:1067800078C4AA40FC55E37843E0B8E9344E19EFE9
-:106790005C25B24F47905C243A72A689E42F564B91
-:1067A000EC8880FE16EBD6A09E53C6F5821CFC1426
-:1067B000F0F047908B587E08F210D7FF33C8432C77
-:1067C000FF0AF210DB4F823CC4D207F210DB3F0617
-:1067D0007988E5BCBB8D56E49F9AB669ECD3207EE0
-:1067E00050DB7D01F5DE69C3D39143A6A3DEE4E16E
-:1067F0009FAFCBE17E45EF2D1C9FFDA0BFD1FF00D9
-:10680000BA5C6B8ABEB21EEF37B2F91E80D3B67C7B
-:106810006E87F427F0FAD21C35D56D22DB8EE3B7F4
-:10682000E56BF8FA2962393EB745F3797BD345B277
-:106830009FA64E9EB624079EDB62A13DC75FEFBDBB
-:10684000813FB78DE2ED437A567E3E25D7A4F8EF1F
-:10685000E9DC2F65642701BDD3FC4AFFF726723EB1
-:106860000CEDEF4E138BDDC3C0E32D996F892FD054
-:106870009E463E480EE08B6A33F18542870AFD55FD
-:10688000E57238A769653A07DD42F0431D83723A25
-:106890004E4FF625C0C5C6E03CBB05995F42F901E5
-:1068A0004AD4070A3F287CA0D07B22F09910ED3F04
-:1068B000C7CD21F4AA948FCAE7E88E35FE9CF0DAA2
-:1068C000A136A1DF7733CC87E313C5C177EF46FE4E
-:1068D0008C359AD1F52C7CC8503B9C1CEBFAEFC24E
-:1068E00043910B5780C76570D0F0F25F8503C939BB
-:1068F00094E348BFC3C8ADFD39D1B25DCEE9F744DA
-:106900008E6D1FD251BFA057A1DFD0AF67C3DAD9B8
-:10691000DBF2397F287454053A10EB8978CED4CB5A
-:10692000E59E729EA1732E6324FFD2C2787B289EBF
-:10693000957305C8BFC33901F11FC6B87D711DD855
-:1069400017E84F4DC935D33EFA477E56B695F9CF75
-:106950007F470E6F7F4A94881E14FD32D42E488BD9
-:10696000E66406E91D66423FAF534BFCEE057FE649
-:106970002518873E219BE43FBF20E37170FE58112C
-:10698000EDBBBEAF0D2ED4637DA3064E0A30BE6FA5
-:106990003B18366497D86E1340EFDE073A06F5D4FD
-:1069A00005907B2C9DB173721CA1CF73F124FA73F7
-:1069B000353B24A603504A3BBE9A87F4B4B4536DCA
-:1069C000A2B8D0F6C78E213D9E6E15CC6897F4B55F
-:1069D000C2F1A1BFB3C1E8D643FF22A863FF650699
-:1069E0008DDBCCD7A3F883435EEF537D750AC68554
-:1069F00066EC5013DC973E2FB9D13E3BBC7DA50A17
-:106A0000EBA7DD028B837145D2EAAE04A8573E2D79
-:106A100058B430CE61283A8BF182CAE799C50BF39E
-:106A200057B618C9CF5DDAA0FED817605F94BBB720
-:106A30006AD0EE29DF19DC5EB93BB80EF822F9EF17
-:106A40006886F600F9FC6D8E3186ECCD712C1BED5D
-:106A50004DD6C0E3B98A7CBFDC6E757139BA82CB82
-:106A60006DC6BE8C457F5FEAFC2AE96303AFCF9118
-:106A7000EBA7A0FEF9571C2F0A5CAAE5B53F4F60B3
-:106A8000560F9CB7BA536F42FFBFBAFDEF1118B74C
-:106A9000AF09F3517C9FBD2299D0DEDBD826B91017
-:106AA000BECE0EFD2E11E0567DE03D8DD988705F83
-:106AB0004EF6CAADCCB51EE3DC5E5164DD4447DD65
-:106AC00014A766B681A5384F5FBBDE847640F52BF0
-:106AD0001F74DD8DF50302D3231E47FB884E96EE0F
-:106AE0004086A52DDD26E4FBE94442BC229E3D9173
-:106AF00084AF658877C433E01DF12C213E71BC5111
-:106B0000E3E6742251FDF4731CBF0ADE8BA4CD1A98
-:106B10006CAF6CE4789EB163CFB630A2033593E9D5
-:106B200080F07E7A27C7BBA6739D6614D26F630878
-:106B30001DB46B87E800F777191D84E0BF02F08D64
-:106B40007220940E42F1DF93C3E506D8DFA79F427F
-:106B5000FBDB087E01F3C7234656F51E8D81F5CA7F
-:106B6000A2CF3B9743FBD8F89758DA088A7F15E401
-:106B700062FC6BE63BEB105D3DB35EC8467AA957FD
-:106B8000FBF63C81718BA8708AE3F427CFD9F932E8
-:106B90009CBB20FA9BA416D87FCD6B5ABADE28C9BD
-:106BA0001587EC358C9729F174C033C5C99C1D5AE3
-:106BB0001E176B2DB405FA73FD09FC5C859A81B232
-:106BC000E5E817C07CB88E60E37E5E55078F172816
-:106BD0007E59951237680E8E1B08A677A85F452E42
-:106BE0008F5FA5C6DD6C463BBC7E01B387A55E4DBD
-:106BF0003FF078CCD3B2DF7445FBF10A7A42B11B87
-:106C0000992B386EA1C8A96513F91E8FFEE2B86AE8
-:106C100004C6FD760B848F8A0E904F70DE0AB7DAB9
-:106C20006D1602F849EEFF19D21BC0ED8CABF6A031
-:106C30002821DD1968BF0E993EAB918EE0BC95D638
-:106C40003722F09C0E59AE38DA8D147FAB645B8A24
-:106C500090EE2A613DEF30F454F95C0BF929D7A28C
-:106C600027C5CEAC6E0DEEB7317748CE8CFF1EE057
-:106C7000BB016439D77B2E99FE3223F1DE6F9099E8
-:106C800023919F87F49FC0ED3745FE5CBF1D583CA4
-:106C900060DE716E1D5305AC7FE373A6A0FA784FDA
-:106CA0007C50FF9BDACC41CFB3BD1941CF738F59D4
-:106CB00082EA79DD1383FA4FF8D016549FE42B0E45
-:106CC000EA3FE54C49507D3013CE7395FBC15BE341
-:106CD00085A0FE33CDFAA0F967674405D5070D32CC
-:106CE0007C64BB52B1775FCEE5F66E68A9C0F776DB
-:106CF0004BF03A8ABF7EE7C4E0F5E6D882D7FBA125
-:106D000078D90BFA54057EC273A05FB1FC1DF8134D
-:106D10002AF0139AC19FC0FA8BE04F60E9017F020D
-:106D2000DB5F027F02EBADE04F60FD20F83F586F64
-:106D3000AB2BA6F295BA126ABF16FCBAE4758FC9DE
-:106D4000EB1E97D7FD77E174429EEF5D79BE6E9C96
-:106D50002FCDFFDC593C56BC04FC3C2DFAACC68759
-:106D60007EC30A5F11C62D06DE9218C6A599DD7D89
-:106D7000AC2E06F5D9088A33B39281B731AE527D75
-:106D800020D5B4C98CFAEC0FEFE2F3BE56C98C7C67
-:106D900079A8EDEF1138CF854B61745F4A7A10EF17
-:106DA0001BBF6154DF04CF310E3AB3050408E93745
-:106DB0000FE9B70B694ADD4DF7BD25CD2D1AC45338
-:106DC00015F2293C7FCBA30E7EFE5C63D07313F6D5
-:106DD00087B24AE5A638C2B936653E2FF577A4F1E9
-:106DE0007BCF73CF1D5E3F05F56FCBE211787F5EE1
-:106DF000D5FC5EECBD57C1C7E7075FC8A4FBCA76E8
-:106E000098CFE09FCFD9AE96EB7CFF8EB496A26868
-:106E1000541CCD021B0BC505B685EE5FAADAF63809
-:106E2000506E5565DCAD66009F7E8F24C737F8BD78
-:106E300091C3C4B81DE7F92202EF575FF71CBDC329
-:106E400086F8ED381C81EBF6B74A41FED3682BB7C4
-:106E50008F475B3584BF0BAD8723F05E77A3E730A8
-:106E600087BBCA4BE73F24D7FBA12478B74974FE00
-:106E70008A4B62D03D768655A27966B68D35E2B9E9
-:106E80007A3C7CBD1CAB99B7A72D5E82FB3F1EBF31
-:106E9000204F227B100435CAF11B66EF413BA4CA88
-:106EA00023D986F3EF0AE479BBD49C4EDF4ADBDFBB
-:106EB00085F2F878F1886CD2118A9F69E5766F9136
-:106EC000C69E867AA4C76036229D3F589C6A44FCC1
-:106ED0001EC212DB8B7769EC06BCC7E6EBF598BAED
-:106EE0002390EE7A5A7325B47794F9F2E57587E822
-:106EF0007B086F2EC253B9BBD180F3F8F1C7DB73A7
-:106F0000AC26EA7FDCFDDE3CB4AB7A32C2C92EE9A6
-:106F1000D230F2A7AB9AB95DDCD391D818784F92F2
-:106F20006395FDF20C91F0DAD7A696FBDDBD8705DF
-:106F3000F553D3392FEC0EDE8FC97DEA51B4C71D4E
-:106F40004F4B0CF5A2435D1B8BE7FF6C67F0FECA4D
-:106F500065383BD4DED8D8007A75B40FF18D81E85E
-:106F6000BC5DE11333E153C1634F06B7E77AE2F941
-:106F7000BDA4A3650FD1F5E5F1A4EE64F41F127F63
-:106F8000A9A378E7B5FC67C56E08F0AF18FA8BEADD
-:106F9000E2D43C31C56F1FBC966BABB68E44BFAB21
-:106FA00084FCCA1E06F62CACE9447B3A92F21FB66A
-:106FB000E1BA83AD6ABABF76EADA667D0276D9A015
-:106FC000051805F63DB8532DDF7BD90C68D72E95F3
-:106FD000EDDACFCCF67C09F4AF738D48E7736486A5
-:106FE000911FD327CBBDCF5B92EF24BBE1986442C6
-:106FF0007F688687DBC18E666ED7567B92FF632AD9
-:10700000DAEDCD6ACCD4608A1DE294ED90D3B2DD86
-:107010007B7ACD8086FC9B4E813D968C792A5BBB2A
-:1070200012E1B9337316D9B34EA999EC8965DB83A4
-:10703000ED07B06F82EA55CF85DA17727CCB13DC8F
-:10704000AEF887DBAC4376C638F4670AA5A971C8E9
-:107050000F2FC87855FC9B95E32D94B7B351659ECF
-:10706000A5C421105E359DFB2B70DF6E479885FC13
-:107070008D55AF105CFBBFE47E4C7F3C2378F4332E
-:107080000EDFFE364EE7356AC18DF9483540B6341D
-:107090009F4E70AFC138B36B3082E41363C5C8171D
-:1070A0002B16707FD586315F286B157E08D1ABB764
-:1070B000A87C5254809C68B3A650BF020DB3A33E77
-:1070C0005B69B4907E1BA3E3767AE16A4F36D2C344
-:1070D00018F0C7B501F1F831860101FBED7E80C7DC
-:1070E000FF9578C21C95491D15A01F195B43FD959E
-:1070F000F941A2F0F1D79ADF04F31BFCF303BC23A0
-:1071000011DE5F582DA4B793E628F7FFB5C497CAE0
-:10711000792E00BD611C1863348837C7CE37C89FED
-:1071200073B2EEF538AE2882EFA308F783F5305E30
-:10713000FE5196E7B179BCBC4D2E15F9D590677B11
-:10714000DF0AF59579F63F5949AE99883E57CAB49A
-:1071500002F64C9C6F18F9BBE21D89F0FA05F003AA
-:10716000F2FBC25AC19C16642F713AAFE14DEC3C60
-:10717000F3F44E4538B86CDD1998D7C6387F2D5AD0
-:10718000A537A705DE0720BDA3FF5102FFF2D12FCF
-:10719000E3BF7253C56D9457B52AD68CF71735C81F
-:1071A0000F29D7A6FF50BA87DF4EA4B76AA6B5A0AD
-:1071B0007EA9690B7D6E51A13DFE4D085F24C97407
-:1071C000DA6817E87EBDF15B158FA3950A1437BB0B
-:1071D0000B1A914EE987FDCAA7B9717ECCB3A0FB0B
-:1071E000AE861839EF2B86EEE17E229FFF2E95F7B3
-:1071F0000DE4EFA36A4F32C6718E3AF93DD502E62F
-:10720000A17BDD52D64D656F78F5012F4DEE1A8DBD
-:107210007EF807762DC5911AD7361951CE66B1B5CD
-:1072200026BC1F033679EEFBDC2BDB1BA1F7689431
-:107230009F95E7C7F3CABC92F83CA0833380A3F8BC
-:107240009CCBC757BD7F2002E17EFEFEFDF37ECAC8
-:10725000D00F02B905F354D6B664D0BD8C8B7567D8
-:10726000E4FBF1ABE053C11FB49983F00A67B90E98
-:10727000E0339F0DE4636ED3B5F0A9C039493DF00A
-:10728000630425E8319243A17856E05ECD6AD53C8F
-:10729000FE56FBEE02E8FFB3B5A219EDCACBF07EB5
-:1072A0000DFC78F5FC91D728903F7B257C29785AF6
-:1072B000C8BC54FF308A8FFB70A144F1C3FF697CC6
-:1072C00035E4D94BF2AEC2B7A17C7A25BE5CB42AB4
-:1072D000847F43F874882F2DF02F007FF65511C45A
-:1072E0008F0A7E1D66F09351FF75182D6E76393E1C
-:1072F000D1DFC5FD54B60AEC49E187F0AB8FFCE362
-:10730000507C01ADD8501F54E705F3A982C72BC9A3
-:107310002D45EE7DC4BC474D02DD67703EFE85966F
-:10732000F2E994FB0CE5DEE2D13CAE6F42CB8FC0BC
-:107330006EC17BA24D193D23D1DEEBD528F3F07B46
-:10734000D78FD6748FC67CCD8FA6F1B257C3F34CBE
-:1073500094BA2D8CC7033F4AD0BA106E1F09E3A61A
-:10736000A31DF091F0CB3B783D4E63C6FA82B8E99D
-:1073700026A8F7AA95F8E183B2FC7653F9D18209E1
-:1073800005D44F6047101E668195D03A82105D0C7F
-:10739000FBF9E8E76373F05E4039FF03793C8EF454
-:1073A0001BF91C43F1F65F09146F5F04AAC384F74D
-:1073B00002D39F284E81F693BF4ECDA6FBCA15C1BE
-:1073C000EBA3FE4DA638E5569AE7964B03EAC5991E
-:1073D000FE7D0DE9CD828BBC7DC9D8A07C665BF4B7
-:1073E00038EE27BB5323518F297A6DF0D87E436046
-:1073F0001CF5AC1C771EAA8F7B2429502FBEB1F739
-:10740000E1749CA75CE3CAB218308FF9A924B41FB9
-:10741000CAF73E944E76EDDE8DE9E89F94373D9CA9
-:107420006EA37AB89DFC23153FF7F97D93766D0A1C
-:10743000B0A36F9DC0EDFB52DD1B8568DFCEBAF1B6
-:10744000F37518B71FFB6B81E2700B59F73AD4B78D
-:1074500065199CAF58838EE43FCC47F7A47BC6DD0B
-:10746000BE1BE5FEF18CBFAB97A0FECD53D17C6572
-:10747000CCBD390EE36F1B048ABFF9FB8FA67BD707
-:10748000C56B054D7C0CEA519E77FDC7BC2882E395
-:107490003D1BB2BBB0BD6C356F9FA575B7F6E03C28
-:1074A0004F6828CF0A14654A49C03DF61FF3F83DDE
-:1074B000DDA2CD72BEB1BCCED86DB18D81E7FCA38B
-:1074C0008C7F56FE01C9833B65BCDCB6FABD23F157
-:1074D000306FA4DAFE67942BEF3E7E3A0DE55941FA
-:1074E000F4D94CA4F3B11AFB931578EE262DC52BD5
-:1074F000AD5989521CF4CFB97FDA63582E5ABDF8C2
-:10750000C90A8CFB6ED7911FA6EC6F856016D15F00
-:107510003DDCF8D37B106E671EE779A42B1AAF8F82
-:10752000BB5AFEE2B3753C1FFCF93A1D952FD49966
-:1075300098198EB8AF2E9EEABFAF3353C9E673FADF
-:1075400052F2A6AE345FEEA530CA5BB66ED0511EC5
-:107550007DAED6F6551EC06BEC0DCEA68DF2B9C62B
-:10756000C2F86C57F20C848375E3F22E34614FE558
-:1075700071FFEAED9E0D496487AF3EF54C053CCFA7
-:10758000CC2FF90EC7EB765EA478C1E1F687CA105E
-:10759000DEE54D5A7E3EF9DC671E4F8F7B12E3BC61
-:1075A0006FA9C97FAFD979EA998D50DEBB79B92629
-:1075B00090DE7FE879BF95F7732DBEBA121CFE7579
-:1075C000BE7A3889F8A709F82AF3DFE7AB9AD56BBA
-:1075D000087E73F34BC6E6C3FECFA85D49C84F676C
-:1075E000C6DD4C74EEEA1408FE8A1C57C6A7E6F303
-:1075F000FBE82AD1B399EC48598E7F059E23C2F748
-:107600008DF6CFD2D18EFEAA6DC155CF7DB00E3D85
-:10761000228C9BE9A80C7D9EAFB1A7625E71BEC8AB
-:10762000EDE7D0E7B7E72B71781EB7C59F1090A79D
-:10763000E2848D4546A3FE13BC6120979D6DB79EE5
-:1076400055A1FF067EE1C7C17628FB3840AF5F69D0
-:10765000BFD72AAB711E955FEE4EF85064DE003D39
-:107660003EC917C6BC01EB0EF92BD0A6A1FB9E04A8
-:10767000920B8837CC87EA6B1FD784F5B31A8EC775
-:10768000BE83E097F1B80C93F2FDE73CDB7E3E0B46
-:10769000E56CE879AB5F394FF4E1687BE8A240E73D
-:1076A0009F79569575EDF3BFB1F77C16E2EFACDA32
-:1076B000978FFE579FC6978578A87E95CBF37F1549
-:1076C0000E4A7BC5060D8F130A26F2230BA50B1459
-:1076D00007E83BC6E300D5EDBB489E0E76F0784C3C
-:1076E0008DD85D1487F18BDA535D28CF06E3B95F3F
-:1076F00006F3DB28CF2155D683AA81A43920D71ED3
-:1077000019A207EE0F9E41FED5E03C1E07E561651C
-:107710008533B42BCE213F437BD9AAE4F548E767F4
-:10772000DC2373503EBE9DF58F6A8ADFBD1E6E92CC
-:10773000C88E9530C778084E43E7704B3CD18729F7
-:10774000767138B305F4ABD198EF24BFFA38BF9FF8
-:10775000ABB981F3137B85F39373ED1B9AF880F932
-:107760007E25F393624FCE7AFD1FC4970FE7DA9E12
-:1077700040BE0C475988F3C547521EB5F21E8772AA
-:107780001F69E890FDF862899ED7B4490CEFE5586F
-:10779000BC91F20A8AD916CAB79CC53C53795E8F50
-:1077A000EFD129F07CF6EB522EE6A1813D4DF7DBBF
-:1077B0004561F634CCD3EA150519AE1EEB9C007D6D
-:1077C000F67E3EF757A74A02E9B1818470B253664C
-:1077D000CE7796E27E957E5A91EB339887EC2CE635
-:1077E0001EC8C27B55E61DC8C2FB56A5DFBCD7C369
-:1077F0006B492F328F755EC03AA7F379BCF30BBC8F
-:107800001F07795223DFC3164ADF6E437F6B45277C
-:10781000BF7FEC15933FC03C3317C019F17A1EF0BF
-:107820006A43FD6367361BF2CFF8916EE49F9A7D41
-:1078300002C37CBDEA766D13C685AAD5BE58A4E7FF
-:107840008D6DEF6B909E6BF05E763C8E6772BCDC4C
-:107850004479BF3526C6EFF5DAAEFF00E376CE6396
-:107860005C8B3A55EF513C00E536AE57D5DA42FE17
-:10787000BF8379C9FF773407D3CD603C8FE787F2A8
-:10788000C9E97C73107FCCDCCEF9631EE6731B68FC
-:1078900038C55F67C6C7915DE21FC7F16093CEAF81
-:1078A000433BA63F45A07CFCFE30D75AB48F5CE931
-:1078B000DCAEE97FED052BBDF7A3735B7F8CF93C54
-:1078C000B2DD3B73C3569514B09F991D3CDED81FA3
-:1078D000C6CA0F12DEEDD7213E7CB92567F231BE54
-:1078E000A31978770AC683441E1F0D3D875D8E6BF2
-:1078F0001C67FCFD2865DFB31313B93C636EA2A3BC
-:107900002E39BF5BC9D751C6DF324150EED1B89F87
-:107910002458AEFA5E1ADED7609E2BDED760F93BA4
-:10792000391F16EF6BB0FEA29C0F8BF735D88EF780
-:1079300035586F95F361F1BE06EB785F83E52B72E6
-:107940003EEC71DC2AE5F16D7C0AE9A20B796D94BD
-:10795000BFDE1B1D521F15DCBF375A08AE8F12A8A1
-:10796000BF69C2C6A730FF7893922FC5CC46B4C377
-:107970002AC2F9FB1AA9067BEC04F4F38B77ED45D8
-:107980007F1EF89BDE9F2B885E504AEF97C46819D4
-:10799000CAA3DB27D8474F80F1C78ECD48DB4A7298
-:1079A000524FF7ECBD3FBB3192E27A6F494C8225D2
-:1079B000A765E4AEB5427D9A4120FA85F96E2A5159
-:1079C000FC4C986746C762AB8ACB0713DACB85922B
-:1079D0006309AEB322419F8B72F888D59E81FB511B
-:1079E000E05D346A591ADA455D6AF307189F75BD80
-:1079F000A366E85729713CA5DF93D669F9B8BF990A
-:107A000019A96B73707E60369477360D6BC6FDD9FD
-:107A1000C470A19EE4975985F2207F02A79BE96676
-:107A20006E1F7B35665534FAF561D362F05EB74B55
-:107A3000C6F33119CFC7653CE33D57818ADF7361D7
-:107A400089F75C5886E6A32DCF2FB14D20780F24FF
-:107A500005E6B3CD92DF97000AA1F7D49C721CF320
-:107A60004B59EE34E695DCCAC779689E2A398E7781
-:107A70005E1D7C6FA88CF38F6754CEBD89CB6B16CF
-:107A8000A9E179BFD73117E615CF7D3981E2507D65
-:107A90006ED1A506BCCF055E4779C65EE6FE2E8B8D
-:107AA000E77C33777F1CF5AB97E3A9CEE8EE747CD7
-:107AB000AFA34FE62FA57EF03B9E97E4CC81BA8121
-:107AC000DE23A1F339E776A74741BD4FD08B485F4E
-:107AD000CE26FEBC47E63F678A3C9F7C1EA6F32469
-:107AE000213EFA3B5F4EC2F7103719BC4BB9FCF789
-:107AF000A693DC66DE74CC6F3A2F784E62BEF1AD91
-:107B00006D29A5986F7F5EED7906EBB3DBD2785DCA
-:107B10006839690A7C3ED29384F9C8B7B6A59662E3
-:107B20003EF2F9912DCF445902EAEA974EE273CD25
-:107B30008369A5989F3C5BEB3E568774F37B4E5F51
-:107B4000FA7D074E237CAADAB9FD3E7DDF810B2F3B
-:107B5000A17E3E60A4BC8275139209DFF5EDCF6E65
-:107B6000467AEB6B51133F6C6A7EFF99DF503F2DD5
-:107B70008559666B3D560CC994B41DBA1BF7353B4D
-:107B8000DCF325D6174FBC89F6317B04E7EBA51350
-:107B9000734A914FFB0EECFB05EAB3D99160D8E232
-:107BA0007E5ED0137E2AF78F2BC0B8409FB1BB0CEE
-:107BB000E7AFFE9D96E71FEC8F9B8E7182FF9CC006
-:107BC000F3312A6ED89284FA567CE5F9BDBFC1F82C
-:107BD000E6EFF474DF5313CDEDBD4AA9317F39E1EF
-:107BE0006FD75ECC5BE97B5E4FF7AF151893B3E2BE
-:107BF0007BAC63293EFFEA3FFF5E8678289476EEF1
-:107C0000C5F62F77EB4584438FC6167933F2618F23
-:107C10009AFCCE0AB95ED13B82EF27DC5744F88B41
-:107C2000D99284FAB672C4AFEEC07DCF96B63C83CB
-:107C30007E0F7B564B770E679F07B8C1B8B37BD4D6
-:107C4000984903FB30AA905ECE0B5BCA9EC4F9F73D
-:107C5000F07EE7F55B089EAE3DD7335C0FFA31D47A
-:107C6000C7E785AD41ED67F73C9B857EE9B9DFCD80
-:107C700026FF54A173855F2A776B83F422498258CB
-:107C80008C5BCA3F938B1902E259E70EEEE87B92B8
-:107C9000F9C79F6B567B3500A30A2D5B8BF9CD0A84
-:107CA0003F5426DE5A8CE7AB141BD3D17EA9C8F50E
-:107CB00095215F9CD5335D3CF47B5BD65B95AD6BCA
-:107CC000E6A01D7CA5FDFC4596475FC97CF8559B49
-:107CD000DE1D78DF185AFEB58E994FA8FCF585B5E4
-:107CE0005AB2E595F9DED6781CE8AF554773F971BD
-:107CF00012FA37831CFB93ACEF16AD0AEEFFEE04CD
-:107D00009E4F59ADF1A5A3FE53E67F7B8289DB87A9
-:107D10002A5F3ACAABD071B32559DEBC2090BCA90A
-:107D20006C154ED1FB2408D2583F3C2B752E37E6FC
-:107D3000130D8787F87C190F12E6F170BEAA6CD676
-:107D4000DBF4304F55982F02ED2587D117817650FF
-:107D5000DF2B126B92D117A3CC9FE25F4F89535652
-:107D600078D436FD70EBC171D04F5E867F03285604
-:107D70004FE47C53DE164EEB31932F1FE9B67C6740
-:107D8000F0383CA729801FFBDA76C506FAEB0CF722
-:107D90004DF751A7886FFAFFF931BD075E29B2B5DB
-:107DA000784F794EE0EF83409DDE073927DF775625
-:107DB0007E6D0843FA39F79583F8B84FF0919C7BB4
-:107DC000B1CD4672AC4FED2339B76B6211AF47F9B5
-:107DD000CA506EBD38F1A7243FFA127C65F89ED2D6
-:107DE00066A58E2FCC811DD0D1B690E4C96C89E7F1
-:107DF00051B05D6A138F1371782F93E1C4D886DE7A
-:107E00003AF243D466B4973A272AF7421AFFF92583
-:107E10003F3FF531F3BE56E4CF7203C57DC0BE6A65
-:107E20007E09EDC005B1168CA787C24DB95F8C895C
-:107E3000FE6629E2E91DA37DECC43CBCCFF4919F12
-:107E400001D44EF67CF56B5AF237FBD5037B517E9D
-:107E5000B98DF67113019E0E4DF77A547117D4BE89
-:107E60002E34ED6721BD911CE1F4D697B98BBF0785
-:107E700022DF4F4E92F100FA8C35227D081CCF870D
-:107E8000DBF69F4079D3D79D4A723A949FCEB63D98
-:107E9000168172E343D0EFAE8078C0878B9FA57CBC
-:107EA00080F9980702E53D6B83CF37F8ED8FC92F36
-:107EB000649B03DA911E1B82EBA17041BAF406F1B8
-:107EC000818BF67D3FF21BC0A76A7A7735C261A825
-:107ED0003E17EA5240FD50483DA43F2BE1F6C3FD5A
-:107EE0001318CDEB18EDED253F7E1FCFEFAD07BD8D
-:107EF00046F503E1743F2DEE03BD15C3F516EA8B7D
-:107F0000AA886E8A5FF51DD0D2BDCA83ED9F25E198
-:107F1000F9811E294E53D5FE722CFAF7EB2698698B
-:107F20007ED08FB1941773A03D16FD11A5DD217A87
-:107F3000D2E5F70CB2507E28ED4EC99B4E79E54252
-:107F400077163E5F27CB1987087509EB8CCEE110B9
-:107F500038DFB37689E47C28DE56C9F40AF2218B37
-:107F6000F2395EE1F103451E54C872E510B667723E
-:107F7000FE3729F75278CF847C3F8C9CF85A8123B6
-:107F8000ABA5F8CEFD13CDBC2E8FA77979FC89E780
-:107F9000EDBD7A3E2B2513C79995F745FDF228D5FF
-:107FA0002F5F500EC4931C78501D0BE7AA7C46B07F
-:107FB000D4C3908AD23545D09D2D532D2FA2B81A07
-:107FC000E6E71A2EDF57281D454EE4F8AD14B91F19
-:107FD0005EB957A0FBA5736A7E6F07F286DE0F5865
-:107FE00056B0A608F9EFBE18A726D05FBED6FC4B48
-:107FF0001B82EBCB6AD714C50DC3E795ABB6768D64
-:108000006497CF57616F2C8A355FDEAEECFB9C5EC8
-:10801000D9E774F5C84078CC5F533412CA65BA7F8B
-:10802000171EFCDCE7DAB55ECA572D5D43F7C4B70F
-:108030005CAA0D8AB35E6BBE0AE6A67B902BED3F71
-:10804000B47408DE5E8C2B31E0AF3DC467C03701ED
-:10805000EBC5CBF43A149F285F3C06FD53665F3CAA
-:1080600026303E115AE29B3322E58AB8A8043E2C02
-:10807000B30C030FA5FFD1893CCE1A3F91D3F1A8D1
-:10808000D9553B5E6214D7E941F97BA5F74CFE2236
-:10809000EFEF07BF6732239CF7EBD49B30FED3DFB3
-:1080A000F90DC587FBD719E6F37B07034B80E75D26
-:1080B000F1E39B02E3C0AB26713B24DCCAED9D9A41
-:1080C0000CF5D5E34B99C6A1F812D91B99E174DFE1
-:1080D000D2D7F605E9B7FE8E3C13DE8BF475BB0DE7
-:1080E000C86F35FFFC7FB1A887FB3A3EA5BCB4BE84
-:1080F0006F3FA37CB58D72DEE0A13639DFABDB6C60
-:10810000C4F6FEE2BF1761BF4D72E98F2FF0F898F9
-:10811000522AF18300FFF93BD4537B4C1B1FC554FB
-:1081200099CAB02D24BFC07F8E46BDE18F2B98E346
-:10813000868BC304C615D2543CAE8025C615D2D258
-:10814000785C01EB1857C012E30AD88E7105AC6356
-:108150005C01EB1857C03AC615B0C4B802B67F2907
-:10816000BFE7D10F828BC73D0D24F757627E33C026
-:108170006F6527BFBF5AB947A27B617CCF03F5DF8C
-:1081800065793BAD72DE8E672BDD07D61C902C889F
-:10819000227C1FC4958EF93B0347311E54D32258CD
-:1081A000D698B17D3EED636347DE07A5D8BE476D27
-:1081B00011CD444F1C9F8D825B8F7CD5B187E257D8
-:1081C00005719D94EF5FD32C308CBBCED3723FD919
-:1081D00029416B0EDDAB921DEDD47693FF52F59CD9
-:1081E000600E7CEFBB66E2459213CA7DF552FE88B5
-:1081F000393D7AF392203D6BE37957F827ECC72994
-:10820000E777931D1260172DC57B6C6C97BEA5F7A1
-:108210004D9CE0E08E10AE9D7755D9D1B21EF3B5DE
-:108220007E68FE55E124F9DE3A9BBF4752FCF89286
-:108230007D0760BDC12D5AB2536E9F60BF6D521E47
-:10824000E619D828EE72B4534F7ED6275BAF0F8A5B
-:10825000BB144AD751DC63855A20FD7DC46A9F3B1D
-:1082600009E87246F1BD146F99116F243E56E8F08B
-:10827000496BC94F70DE15E3F977980AB5ECE7341E
-:108280009F9CCFA5E0A9B05E70E3F72C16330BBD21
-:108290003FB008C0877151E5FB1F8B18CFAF50E886
-:1082A0006AC55681E88ABEBC10F0BD8445F83D1011
-:1082B000D07FF76AB9FD9B28F27BF2C44D3C8FE278
-:1082C0003E66A7FC9165487D12E9D7D77CD06E0F3A
-:1082D000BF2E89DBF7E6389C7FF17135E50717C6BD
-:1082E000DD9E6E273D5F40F91382F76EE9FB1BAF01
-:1082F000263F83F3278EAAB9DC0178929FD585F4B7
-:108300004AF11E3B95C7EBCAA99C22BF1F16FA5E15
-:10831000437FE7CB2D38BEB0C66041F85FF13DC06A
-:10832000B0ABBFFFE694F3EB12C59E5C33C2E36BC8
-:108330008305E15118D749EF89A5CAF33F9C5BB289
-:1083400009F1698B602E5C1FEF69B6007C8BF040F1
-:1083500002C6D13D367CCF66A05330513EF56572E2
-:1083600074EB3ACC53A949134C18AF2D0ADB5218C1
-:108370000BF317A524D377766ADA781CB60F4A4E2A
-:108380000753DC92C0C7AA62317ECFF1E8CBB53F7C
-:108390003D29CFDF3E5BE6B3FE8E2F781EF1B5E3BD
-:1083A000B4BBE9FB1C4C4FEFAFD30FF635FBC6D186
-:1083B00014AF55E868B039AE09E9A845D613A5A5AC
-:1083C000EFA9D18E68CCB337231CCA965C5C174BDF
-:1083D000E71C3E4EA6E4DF87C6C902E5EDFF46DE98
-:1083E000FD89BA5A2ADFAD5B4565779D8B9E07E80C
-:1083F0008B2308BF1F106F7D7BD230F156A6334709
-:1084000092BE05BEE7F1ED90F82AF0BB18C0EF333D
-:108410003AA2EED980F64883C682F7CD98FFBCD247
-:1084200040F2E1FD49C3C65915F819282E3BC8F49E
-:10843000398887E919A92A119EFF6D921014E74423
-:10844000BEC17322DF60897CA352F9F9E6690DA3EE
-:10845000EF94A17DE022FB404FF85DBF06E40AD413
-:10846000EF65A620B9722144AE8023F3337A5FAC66
-:1084700043CB3609FEFCCFE9505CCA1946CE78B82A
-:108480009C191DE6799EBEB3501D46F9C5C0EF4448
-:10849000674737F2BCBD25AC84D61D46DED07B3E97
-:1084A000F78E1838F914F4BFF76103D939EB139636
-:1084B000E6FF77E4CD9F2771783C81DF73505DED57
-:1084C0007B0E9B05BC8F5DB1906523BE95EF39C4D3
-:1084D000C118F27BFFF5EF398C983C12BFE7E00A38
-:1084E000FA9E43DC15BEE7306AB27161E0F71C46C4
-:1084F0004D1EB130F87B0EC685F89DB2FFC1EF3935
-:10850000A44FCEBBFC7B0E374E36FFA0EF39803D2B
-:108510009B89E34FE4D8C66399289F3BF4FDE5E3CC
-:10852000F23D6497682FC5B228C2A5A276D16DC569
-:10853000F26DD1733FB6035F4C4478153D967D03D1
-:108540007E972551EBA1BCF227ADB64938FF6BB938
-:10855000B6C9F83C34DE5F2F9F0FF6730BF60BCDD8
-:108560001F53E8E2AEC95C0ECD93CBA9F5C3BFC7DC
-:108570003F6F32BF4FBED6BE61BF77E07ACAFED929
-:1085800096C556DC0FECF74EDC27ECB7044B66883B
-:108590000E7A0FF8727A75C9FB62742E908FB33F12
-:1085A000E1F62895E92A7714DA0DA31E7047E17EDB
-:1085B00047350EE8F17D90DFBA06F4683FFC76F5AA
-:1085C000801EDB7F6BE3F9DAA1F36F9FCCFD91F4A2
-:1085D000A903347E0CFCDD4DFEC14014DA6DE9E5E3
-:1085E0004734AE147A4F6DF62741769399F87B8C19
-:1085F000DC36E60191213D8CD9C1781E63410CE93E
-:10860000B94A1DEF5AF9C0FD22D2D13837EC3B8070
-:10861000FEAEDFAE1A0C7EAFD74BE3AAE425C05EF8
-:108620000B7AEE643CBF74942C8FD05EC4EFD939C2
-:10863000CB8FD077A6C08E0B998FBE7930944F59CF
-:10864000ADB3BFE63353BE6250BFA577FF663DFAB8
-:10865000B5E5A55B35E4172F69598FA5C3F19E26B3
-:108660008E917D19D41FECCBA0FA65FB0CD947F590
-:10867000FD17D7C70DB32ED0C156A413850E8EAAF1
-:108680003DE3D04F3DEA0CB3F0F71D3CF45D9A2674
-:10869000F9BDF45DFF39DDCAF365395DC0F81D3FF2
-:1086A0008C8EEAA9BFF21DAF6B958A1C1CFACE8D89
-:1086B00086B9285E39CB4872AE46F6FFAA9798C8AD
-:1086C0001E51F8BA5AE539B51EFBC51879FE9B8ACA
-:1086D000D1F7AB7AC45194CF4D3FACCF4AA5FBAC98
-:1086E000D87A8F17E71DB85DA0EFB9158473B95A12
-:1086F0002896389E85E74744FE5D81A7517E4898BD
-:1087000047C1BF37302597BF3F10CFF877DB98CAF6
-:108710001CF29D36391E7AEDEFB4F1EF92CDE7F7FA
-:10872000720D5125A5CBF1F9821BE8F9C1EF521F5B
-:10873000B1E2FE2A94EFB4717BBF614E063D7F55D6
-:1087400030AF413DE17A805DE93B6D7AE4FB80EF3B
-:10875000B3BD87F8BAD6F7D994EF0F1C5D70C32369
-:108760007B391CBD78EF5533CB18E4AFFF17313C94
-:108770009ED2C05600000000000000000000000073
-:088780000408350000000000B0
-:00000001FF
diff --git a/firmware/bnx2x-e1-5.0.21.0.fw.ihex b/firmware/bnx2x-e1-5.0.21.0.fw.ihex
new file mode 100644
index 00000000000..c51afd44a23
--- /dev/null
+++ b/firmware/bnx2x-e1-5.0.21.0.fw.ihex
@@ -0,0 +1,10184 @@
+:10000000000028B0000000600000068800002918E9
+:100010000000161400002FA800000098000045C042
+:100020000000738800004660000000CC0000B9F0BA
+:1000300000009A4C0000BAC0000000940001551066
+:10004000000057B8000155A8000000B80001AD68D5
+:100050000000CE1C0001AE280000000400027C4815
+:10006000020400480000000F020400540000004594
+:1000700002040058000000840204005C0000000636
+:100080000204007000000004020400780000000078
+:100090000204007C121700000204008022170000F6
+:1000A00002040084321700000604008800000005E6
+:1000B0000204009C12150000020400A0221500009A
+:1000C000020400A432150000060400A80000000489
+:1000D000020400B802100000020400BC001000007E
+:1000E000020400C010100000020400C42010000030
+:1000F000020400C830100000060400CC0000000418
+:10010000020400DC00100000020400E012140000F1
+:10011000020400E422140000020400E8321400008B
+:10012000060400EC000000040104012400000000AB
+:1001300001040128000000000104012C000000005F
+:10014000010401300000000002040004000000FF70
+:1001500002040008000000FF0204000C000000FF81
+:1001600002040010000000FF02040014000000FF61
+:1001700002040018000000FF0204001C000000FF41
+:1001800002040020000000FF020400240000003EE2
+:1001900002040028000000000204002C0000003FC0
+:1001A000020400300000003F020400340000003F61
+:1001B00002040038000000000204003C0000003F80
+:1001C000020400400000003F020400440000003F21
+:1001D00002042008000004110204200C00000400A6
+:1001E000020420100000040402042014000004197A
+:1001F0000204201C0000FFFF020420200000FFFF7B
+:10020000020420240000FFFF020420280000FFFF5A
+:1002100006042038000000020204204000000034E0
+:100220000204204400000035060420480000007C41
+:100230000204223807FFFFFF0204223C0000003FB7
+:100240000204224007FFFFFF020422440000000FC7
+:1002500001042248000000000104224C00000000BC
+:10026000010422500000000001042254000000009C
+:1002700001042258000000000104225C000000007C
+:10028000010422600000000001042264000000005C
+:1002900001042268000000000104226C000000003C
+:1002A000010422700000000001042274000000001C
+:1002B00001042278000000000104227C00000000FC
+:1002C000020424BC000000010C042000000003E82C
+:1002D0000A042000000000010B0420000000000AB6
+:1002E0000205004400000020020500480000003222
+:1002F000020500900215002002050094021500205E
+:1003000002050098000000300205009C0810000063
+:10031000020500A000000033020500A40000003028
+:10032000020500A800000031020500AC0000000238
+:10033000020500B000000005020500B40000000640
+:10034000020500B800000002020500BC0000000227
+:10035000020500C000000000020500C40000000506
+:10036000020500C800000002020500CC00000002E7
+:10037000020500D000000002020500D400000001C8
+:1003800002050114000000010205011C000000012B
+:100390000205012000000002020502040000000125
+:1003A0000205020C0000004002050210000000409F
+:1003B0000205021C000000200205022000000013BC
+:1003C0000205022400000020060502400000000A89
+:1003D0000405028000200000020500500000000714
+:1003E0000205005400000007020500580000000844
+:1003F0000205005C00000008060500600000000423
+:10040000020500D800000006020500E00000000D13
+:10041000020500E40000002D020500E800000007CE
+:10042000020500EC00000027020500F000000007B4
+:10043000020500F400000027020500F80000000794
+:10044000020500FC00000027020500040000000176
+:1004500002050008000000010205000C0000000178
+:100460000205001000000001020500140000000158
+:1004700002050018000000010205001C0000000138
+:100480000205002000000001020500240000000118
+:1004900002050028000000010205002C00000001F8
+:1004A00002050030000000010205003400000001D8
+:1004B00002050038000000010205003C00000001B8
+:1004C00002050040000000010406100002000020A8
+:1004D000020600DC00000001010600D80000000058
+:1004E0000406020000030220020600DC00000000F7
+:1004F00002060068000000B802060078000001143F
+:10050000010600B800000000010600C8000000005D
+:100510000206006C000000B80206007C0000011416
+:10052000010600BC00000000010600CC0000000035
+:100530000718040000960000081807600014022342
+:10054000071C000034B80000071C800034E90D2FA0
+:10055000071D000009DD1A6A081D14005D800225D0
+:100560000118000000000000011800040000000055
+:1005700001180008000000000118000C0000000035
+:100580000118001000000000011800140000000015
+:1005900002180020000000010218002400000002E0
+:1005A00002180028000000030218002C00000000C0
+:1005B000021800300000000402180034000000019E
+:1005C00002180038000000000218003C0000000182
+:1005D000021800400000000402180044000000005F
+:1005E00002180048000000010218004C000000033F
+:1005F0000218005000000000021800540000000122
+:1006000002180058000000040218005C00000000FE
+:1006100002180060000000010218006400000003DE
+:1006200002180068000000000218006C00000001C1
+:10063000021800700000000402180074000000009E
+:1006400002180078000000040218007C000000037B
+:100650000618008000000002021800A400003FFFFE
+:10066000021800A8000003FF021802240000000086
+:1006700002180234000000000218024C00000000C2
+:10068000021802E4000000FF061810000000040039
+:10069000021B8BC000000001021B80000000003420
+:1006A000021B804000000018021B80800000000C2C
+:1006B000021B80C0000000200C1B83000007A1204B
+:1006C0000A1B8300000001380B1B83000000138805
+:1006D000021B83C0000001F4061A2000000000B2D3
+:1006E000061A23C800000181041A29CC0001022740
+:1006F000061A1020000000C8061A100000000002B0
+:10070000061A1E3800000002061A1E300000000201
+:10071000061A080000000002061A0808000000027D
+:10072000061A081000000004041A1FB00005022871
+:10073000041A4CB00008022D061A22C8000000203E
+:10074000061A400000000124021A4920000000009F
+:10075000061A14000000000A061A145000000006D1
+:10076000061A150000000002041A150800050235DB
+:10077000061A151C00000009061A15800000001456
+:10078000061A09C000000048061A0800000000020E
+:10079000061A08200000000E041A1FB00002023AD8
+:1007A000061A2C2800000002061A23480000002028
+:1007B000061A449000000124021A49240000000097
+:1007C000061A14280000000A061A14680000000621
+:1007D000061A154000000002041A15480005023CE4
+:1007E000061A155C00000009061A15D00000001456
+:1007F000061A0AE000000048061A08080000000275
+:10080000061A08580000000E041A1FB80002024120
+:10081000061A2C30000000020200A2800000000135
+:100820000200A294071D29110200A29800000000F6
+:100830000200A29C009C04240200A2A00000000070
+:100840000200A2A4000002090200A4FCFF000000B4
+:10085000020100B400000001020100B80000000124
+:10086000020100DC000000010201010000000001A3
+:1008700002010104000000010201007C00300000C0
+:1008800002010084000000280201008C000000002A
+:1008900002010130000000040201025C00000001BE
+:1008A000020103280000000002010554000000308E
+:1008B000020100C400000001020100CC00000001A0
+:1008C000020100F800000001020100F00000000138
+:1008D00002010080003000000201008800000028B2
+:1008E0000201009000000000020101340000000439
+:1008F000020102DC000000010201032C00000000E4
+:100900000201056400000030020100C8000000017F
+:10091000020100D000000001020100FC0000000103
+:10092000020100F400000001020C10000000002091
+:10093000020C200800000A11020C200C00000A0022
+:10094000020C201000000A04020C201C0000FFFF13
+:10095000020C20200000FFFF020C20240000FFFFFB
+:10096000020C20280000FFFF060C203800000002C7
+:10097000020C204000000034020C2044000000352E
+:10098000020C204800000020020C204C0000002136
+:10099000020C205000000022020C20540000002312
+:1009A000020C205800000024020C205C00000025EE
+:1009B000020C206000000026020C206400000027CA
+:1009C000020C206800000028020C206C00000029A6
+:1009D000020C20700000002A020C20740000002B82
+:1009E000060C207800000056020C21D00000000107
+:1009F000020C21D400000001020C21D800000001EB
+:100A0000020C21DC00000001020C21E000000001CA
+:100A1000020C21E400000001020C21E800000001AA
+:100A2000020C21EC00000001020C21F0000000018A
+:100A3000020C21F400000001060C21F80000001057
+:100A4000020C223807FFFFFF020C223C0000003F8F
+:100A5000020C224007FFFFFF020C22440000000F9F
+:100A6000010C224800000000010C224C0000000094
+:100A7000010C225000000000010C22540000000074
+:100A8000010C225800000000010C225C0000000054
+:100A9000010C226000000000010C22640000000034
+:100AA000010C226800000000010C226C0000000014
+:100AB000010C227000000000010C227400000000F4
+:100AC000010C227800000000010C227C00000000D4
+:100AD000020C24BC000000010C0C2000000003E804
+:100AE0000A0C2000000000010B0C20000000000A8E
+:100AF000020C400800000365020C400C0000035487
+:100B0000020C401000000358020C40140000037552
+:100B1000020C401C0000FFFF020C40200000FFFF01
+:100B2000020C40240000FFFF020C40280000FFFFE1
+:100B3000020C403800000046020C403C000000055A
+:100B4000060C40400000005E020C41B800000001AD
+:100B5000060C41BC0000001F020C423807FFFFFFDB
+:100B6000020C423C0000003F020C424007FFFFFF26
+:100B7000020C42440000000F010C4248000000003B
+:100B8000010C424C00000000010C4250000000002B
+:100B9000010C425400000000010C4258000000000B
+:100BA000010C425C00000000010C426000000000EB
+:100BB000010C426400000000010C426800000000CB
+:100BC000010C426C00000000010C427000000000AB
+:100BD000010C427400000000010C4278000000008B
+:100BE000010C427C00000000010C4280000000006B
+:100BF000020C44C0000000010C0C4000000003E89F
+:100C00000A0C4000000000010B0C40000000000A2C
+:100C1000020D004400000032020D008C021500207D
+:100C2000020D009002150020020D00940810000033
+:100C3000020D009800000033020D009C000000022D
+:100C4000020D00A000000000020D00A4000000053D
+:100C5000020D00A800000005060D00AC0000000217
+:100C6000020D00B400000002020D00B800000003F5
+:100C7000020D00BC00000002020D00C000000001D7
+:100C8000020D00C800000002020D00CC00000002AE
+:100C9000020D010800000001020D015C00000001CE
+:100CA000020D016400000001020D01680000000255
+:100CB000020D020400000001020D020C00000020E1
+:100CC000020D021000000040020D0214000000405E
+:100CD000020D022000000003020D02240000001893
+:100CE000060D028000000012040D030000240243E0
+:100CF000020D004C00000001020D00500000000237
+:100D0000020D005400000008020D00580000000809
+:100D1000060D005C00000004020D00C40000000489
+:100D2000020D011400000009020D01180000002945
+:100D3000020D011C0000000A020D01200000002A23
+:100D4000020D012400000007020D01280000002709
+:100D5000020D012C00000007020D013000000027E9
+:100D6000020D01340000000C020D01380000002CBF
+:100D7000020D013C0000000C020D01400000002C9F
+:100D8000020D01440000000C020D01480000002C7F
+:100D9000020D000400000001020D00080000000127
+:100DA000020D000C00000001020D00100000000107
+:100DB000020D001400000001020D001800000001E7
+:100DC000020D001C00000001020D002000000001C7
+:100DD000020D002400000001020D002800000001A7
+:100DE000020D002C00000001020D00300000000187
+:100DF000020D003400000001020D00380000000167
+:100E0000020D003C00000001020E004C0000003208
+:100E1000020E009402150020020E00980215002018
+:100E2000020E009C00000030020E00A0081000001E
+:100E3000020E00A400000033020E00A800000030E3
+:100E4000020E00AC00000031020E00B000000002F3
+:100E5000020E00B400000004020E00B80000000002
+:100E6000020E00BC00000002020E00C000000002E2
+:100E7000020E00C400000000020E00C800000002C4
+:100E8000020E00CC00000007020E00D0000000029D
+:100E9000020E00D400000002020E00D80000000183
+:100EA000020E00E400000001020E014400000001F7
+:100EB000020E014C00000001020E01500000000271
+:100EC000020E020400000001020E020C00000040AD
+:100ED000020E021000000040020E021C000000047E
+:100EE000020E022000000020020E02240000000E6C
+:100EF000020E02280000001B060E03000000001274
+:100F0000040E0280001B0267020E00540000000C59
+:100F1000020E005800000007020E005C0000000FE7
+:100F2000020E006000000010060E006400000004C5
+:100F3000020E00DC00000003020E01100000000F92
+:100F4000020E01140000002F020E01180000000E16
+:100F5000020E011C0000002E020E00040000000121
+:100F6000020E000800000001020E000C000000014B
+:100F7000020E001000000001020E0014000000012B
+:100F8000020E001800000001020E001C000000010B
+:100F9000020E002000000001020E002400000001EB
+:100FA000020E002800000001020E002C00000001CB
+:100FB000020E003000000001020E003400000001AB
+:100FC000020E003800000001020E003C000000018B
+:100FD000020E004000000001020E0044000000016B
+:100FE0000730040000C900000830076800130282BF
+:100FF00007340000341200000734800037B70D05B5
+:10100000073500002E7D1AF308356F405218028410
+:10101000013000000000000001300004000000006A
+:1010200001300008000000000130000C000000004A
+:10103000013000100000000001300014000000002A
+:1010400002300020000000010230002400000002F5
+:1010500002300028000000030230002C00000000D5
+:1010600002300030000000040230003400000001B3
+:1010700002300038000000000230003C0000000197
+:101080000230004000000004023000440000000074
+:1010900002300048000000010230004C0000000354
+:1010A0000230005000000000023000540000000137
+:1010B00002300058000000040230005C0000000014
+:1010C00002300060000000010230006400000003F4
+:1010D00002300068000000000230006C00000001D7
+:1010E00002300070000000040230007400000000B4
+:1010F00002300078000000040230007C0000000391
+:101100000630008000000002023000A400003FFF13
+:10111000023000A8000003FF02300224000000009B
+:1011200002300234000000000230024C00000000D7
+:10113000023002E40000FFFF06302000000008003B
+:1011400002338BC000000001023380000000001A4F
+:10115000023380400000004E023380800000001007
+:10116000023380C0000000200C3383000007A12060
+:101170000A338300000001380B338300000013881A
+:10118000023383C0000001F40C3383801DCD650061
+:101190000A3383800004C4B40B338380004C4B407B
+:1011A00006321AA0000000C206321020000000C85B
+:1011B0000632100000000002063214000000004059
+:1011C00006325098000000040632508000000005EE
+:1011D00004325094000102860632500000000020C4
+:1011E00004322830000202870233080001000000A8
+:1011F00004330C00001002890233080000000000D4
+:1012000004330C400010029906321500000000B4AF
+:1012100002321DC80000000006324000000000D865
+:10122000063217D0000000B402321DCC00000000CE
+:1012300006324360000000D807200400009200003E
+:1012400008200780001002A9072400002CCF00000E
+:10125000072480002AE50B340824DC6062DA02AB44
+:101260000120000000000000012000040000000038
+:1012700001200008000000000120000C0000000018
+:1012800001200010000000000120001400000000F8
+:1012900002200020000000010220002400000002C3
+:1012A00002200028000000030220002C00000000A3
+:1012B0000220003000000004022000340000000181
+:1012C00002200038000000000220003C0000000165
+:1012D0000220004000000004022000440000000042
+:1012E00002200048000000010220004C0000000322
+:1012F0000220005000000000022000540000000105
+:1013000002200058000000040220005C00000000E1
+:1013100002200060000000010220006400000003C1
+:1013200002200068000000000220006C00000001A4
+:101330000220007000000004022000740000000081
+:1013400002200078000000040220007C000000035E
+:101350000620008000000002022000A400003FFFE1
+:10136000022000A8000003FF022002240000000069
+:1013700002200234000000000220024C00000000A5
+:10138000022002E40000FFFF062020000000080009
+:1013900002238BC000000001022380000000001027
+:1013A00002238040000000120223808000000030F1
+:1013B000022380C00000000E022383C0000001F45D
+:1013C000062250000000004206221020000000C843
+:1013D000062210000000000206222000000000C0CB
+:1013E000062225C00000024004222EC8000802ADDB
+:1013F00002230800013FFFFF04230C00001002B588
+:10140000022308000000000004230C40001002C565
+:1014100006223040000000A00622354000000010E7
+:10142000062236C000000030062240000000020004
+:10143000062235C00000002006223840000000309F
+:1014400006223000000000080222511800000000AF
+:10145000062223000000000E0622241000000030A7
+:10146000062232C0000000A00622358000000010D5
+:1014700006223780000000300622480000000200EB
+:10148000062236400000002006223900000000300D
+:1014900006223020000000080222511C000000003B
+:1014A000062223380000000E062224D0000000305F
+:1014B00002161000000000280217000800000002B9
+:1014C0000217002C000000030217003C000000047B
+:1014D0000217004400000008021700480000000244
+:1014E0000217004C0000009002170050000000900E
+:1014F00002170054008000900217005808140000E2
+:10150000021700600000008A0217006400000080DB
+:1015100002170068000000810217006C00000080C4
+:10152000021700700000000602170078000007D0C4
+:101530000217007C0000076C02170038007C1004C2
+:10154000021700040000000F0616402400000002ED
+:10155000021640700000001C021642080000000144
+:101560000216421000000001021642200000000195
+:10157000021642280000000102164230000000015D
+:10158000021642380000000102164260000000010D
+:101590000C16401C0003D0900A16401C0000009C52
+:1015A0000B16401C000009C4021640300000000861
+:1015B000021640340000000C0216403800000010F3
+:1015C0000216404400000020021640000000000106
+:1015D000021640D800000001021640080000000179
+:1015E0000216400C0000000102164010000000012D
+:1015F00002164240000000000216424800000000AF
+:101600000616427000000002021642500000000060
+:101610000216425800000000061642800000000238
+:1016200002166008000006140216600C0000060096
+:1016300002166010000006040216601C0000FFFF86
+:10164000021660200000FFFF021660240000FFFF6A
+:10165000021660280000FFFF02166038000000201C
+:101660000216603C000000200216604000000034BA
+:101670000216604400000035021660480000002396
+:101680000216604C00000024021660500000002585
+:101690000216605400000026021660580000002761
+:1016A0000216605C00000029021660600000002A3B
+:1016B000021660640000002B021660680000002C17
+:1016C0000216606C0000002D0616607000000052CB
+:1016D000021661B800000001061661BC0000001F80
+:1016E0000216623807FFFFFF0216623C0000003F4F
+:1016F0000216624007FFFFFF021662440000000F5F
+:1017000001166248000000000116624C0000000053
+:101710000116625000000000011662540000000033
+:1017200001166258000000000116625C0000000013
+:1017300001166260000000000116626400000000F3
+:1017400001166268000000000116626C00000000D3
+:1017500001166270000000000116627400000000B3
+:1017600001166278000000000116627C0000000093
+:10177000021664BC000000010C166000000003E8C3
+:101780000A166000000000010B1660000000000A4D
+:10179000021680400000000602168044000000058A
+:1017A000021680480000000A0216804C0000000566
+:1017B0000216805400000002021680CC00000004D3
+:1017C000021680D000000004021680D4000000043D
+:1017D000021680D800000004021680DC000000041D
+:1017E000021680E000000004021680E400000004FD
+:1017F000021680E8000000040216880400000004BD
+:10180000021680300000007C021680340000003D8B
+:10181000021680380000003F0216803C0000009C49
+:10182000021680F000000007061680F40000000594
+:101830000216880C01010101021681080000000057
+:101840000216810C00000004021681100000000442
+:1018500002168114000000020216881008012004FC
+:1018600002168118000000050216811C0000000508
+:1018700002168120000000050216812400000005E8
+:101880000216882C2008100102168128000000088A
+:101890000216812C000000060216813000000007AD
+:1018A0000216813400000000021688300101012078
+:1018B0000616813800000004021688340101010177
+:1018C0000616814800000004021688380101010153
+:1018D00006168158000000040216883C010101012F
+:1018E00006168168000000030216817400000001E2
+:1018F00002168840010101010216817800000001F2
+:101900000216817C000000010216818000000001A7
+:1019100002168184000000010216884401010101C1
+:1019200002168188000000010216818C000000046C
+:10193000021681900000000402168194000000024B
+:10194000021688480801200402168198000000054C
+:101950000216819C00000005021681A0000000050F
+:10196000021681A400000005021688142008100148
+:10197000021681A800000008021681AC00000006D3
+:10198000021681B000000007021681B400000001B9
+:101990000216881801010120021681B8000000011A
+:1019A000021681BC00000001021681C00000000187
+:1019B000021681C4000000010216881C0101010109
+:1019C000021681C800000001021681CC000000014F
+:1019D000021681D000000001021681D4000000012F
+:1019E0000216882001010101021681D800000001C1
+:1019F000021681DC00000001021681E000000001F7
+:101A0000021681E400000001021688240101010190
+:101A1000021681E800000001021681EC00000001BE
+:101A2000021681F000000001021688280101010160
+:101A300002168240FFFF003F0616824400000002AB
+:101A40000216824CFFFF003F021682500000010088
+:101A5000021682540000010006168258000000029F
+:101A600002168260000000C002168264000000C0FE
+:101A70000216826800001E000216826C00001E0022
+:101A800002168270000040000216827400004000BE
+:101A900002168278000080000216827C000080001E
+:101AA00002168280000020000216828400002000BE
+:101AB0000616828800000007021682A400000001BA
+:101AC000061682A80000000A021681F400000C0825
+:101AD000021681F800000040021681FC000001009F
+:101AE0000216820000000020021682040000001787
+:101AF00002168208000000800216820C000002001C
+:101B0000021682100000000002168218FFFF01FF7B
+:101B100002168214FFFF01FF0216823C0000001330
+:101B2000021680900000013F021680600000014014
+:101B30000216806400000140061680680000000262
+:101B400002168070000000C00616807400000007B6
+:101B50000216809C00000048021680A00000004889
+:101B6000061680A400000002021680AC00000048A7
+:101B7000061680B0000000070216823800008000C0
+:101B800002168234000025E40216809400007FFFD4
+:101B900002168220000000070216821C00000007C7
+:101BA000021682280000000002168224FFFFFFFFB9
+:101BB00002168230000000000216822CFFFFFFFF99
+:101BC000021680EC000000FF02140000000000017B
+:101BD0000214000C0000000102140040000000018B
+:101BE0000214004400007FFF0214000C00000000FB
+:101BF00002140000000000000214006C000000004D
+:101C00000214000400000001021400300000000172
+:101C100002140004000000000214005C0000000038
+:101C2000021400080000000102140034000000014A
+:101C30000214000800000000021400600000000010
+:101C40000202005800000032020200A0031500202A
+:101C5000020200A403150020020200A801000030C7
+:101C6000020200AC08100000020200B000000033C5
+:101C7000020200B400000030020200B8000000318F
+:101C8000020200BC00000003020200C000000006C7
+:101C9000020200C400000003020200C800000003AA
+:101CA000020200CC00000002020200D0000000008E
+:101CB000020200D400000002020200DC000000006A
+:101CC000020200E000000006020200E4000000043E
+:101CD000020200E800000002020200EC0000000224
+:101CE000020200F000000001020200FC00000006F9
+:101CF0000202012000000000020201340000000284
+:101D0000020201B0000000010202020C000000010A
+:101D10000202021400000001020202180000000288
+:101D200002020404000000010202040C0000004052
+:101D300002020410000000400202041C0000000423
+:101D4000020204200000002002020424000000021D
+:101D5000020204280000001F060205000000001215
+:101D600004020480001F02D5020200600000000F80
+:101D70000202006400000007020200680000000B7D
+:101D80000202006C0000000E060200700000000459
+:101D9000020200F40000000402020004000000013E
+:101DA00002020008000000010202000C0000000115
+:101DB00002020010000000010202001400000001F5
+:101DC00002020018000000010202001C00000001D5
+:101DD00002020020000000010202002400000001B5
+:101DE00002020028000000010202002C0000000195
+:101DF0000202003000000001020200340000000175
+:101E000002020038000000010202003C0000000154
+:101E10000202004000000001020200440000000134
+:101E200002020048000000010202004C0000000114
+:101E3000020200500000000102020108000000C878
+:101E40000202011800000002020201C400000000AA
+:101E5000020201CC00000000020201D400000002D6
+:101E6000020201DC00000002020201E4000000FFA7
+:101E7000020201EC000000FF0202010C000000C899
+:101E80000202011C00000002020201C80000000062
+:101E9000020201D000000000020201D8000000028E
+:101EA000020201E000000002020201E8000000FF5F
+:101EB000020201F0000000FF0728040000B4000047
+:101EC00008280768001302F4072C000035D700002B
+:101ED000072C80003A590D76072D00003B741C0D2D
+:101EE000072D8000226C2AEB082DC6F0472202F64F
+:101EF000012800000000000001280004000000008C
+:101F000001280008000000000128000C000000006B
+:101F1000012800100000000001280014000000004B
+:101F20000228002000000001022800240000000216
+:101F300002280028000000030228002C00000000F6
+:101F400002280030000000040228003400000001D4
+:101F500002280038000000000228003C00000001B8
+:101F60000228004000000004022800440000000095
+:101F700002280048000000010228004C0000000375
+:101F80000228005000000000022800540000000158
+:101F900002280058000000040228005C0000000035
+:101FA0000228006000000001022800640000000315
+:101FB00002280068000000000228006C00000001F8
+:101FC00002280070000000040228007400000000D5
+:101FD00002280078000000040228007C00000003B2
+:101FE0000628008000000002022800A400003FFF35
+:101FF000022800A8000003FF0228022400000000BD
+:1020000002280234000000000228024C00000000F8
+:10201000022802E40000FFFF06282000000008005C
+:10202000022B8BC000000001022B8000000000008A
+:10203000022B804000000018022B80800000000C62
+:10204000022B80C0000000660C2B83000007A1203B
+:102050000A2B8300000001380B2B8300000013883B
+:10206000022B83C0000001F40C2B8340000001F41C
+:102070000A2B8340000000000B2B8340000000056A
+:102080000A2B83800004C4B40C2B83801DCD650013
+:102090000B2B8380004C4B40062A3C400000000480
+:1020A000042A3C50000202F8062A300000000048D2
+:1020B000062A1020000000C8062A100000000002B6
+:1020C000062A31280000008E022A33680000000032
+:1020D000042A3370000202FA042A3A70000402FC57
+:1020E000042A3D0000020300042A15000002030236
+:1020F000062A150800000100022A197000000000DD
+:10210000022A197800000000042A19600002030462
+:10211000062A4AC000000002062A4B000000000404
+:10212000042A1F4800020306022B080000000000DA
+:10213000042B0C0000100308022B08000100000013
+:10214000042B0C4000080318022B080002000000BA
+:10215000042B0C6000080320062A3A8000000014BB
+:10216000062A3B2000000024062A14000000000A72
+:10217000062A145000000006062A3378000000D812
+:10218000022A3A3800000000042A3C5800020328C2
+:10219000042A3C680010032A062A5020000000028E
+:1021A000062A503000000002062A500000000002FB
+:1021B000062A501000000002022A504000000000D1
+:1021C000062A50480000000E022A50B80000000104
+:1021D000042A4AC80002033A062A4B1000000042B3
+:1021E000062A4D2000000004062A3AD00000001400
+:1021F000062A3BB000000024062A14280000000A2A
+:10220000062A146800000006062A36D8000000D806
+:10221000022A3A3C00000000042A3C600002033C11
+:10222000042A3CA80010033E062A502800000002A1
+:10223000062A503800000002062A5008000000025A
+:10224000062A501800000002022A50440000000034
+:10225000062A50800000000E022A50BC0000000137
+:10226000042A4AD00002034E062A4C1800000042FD
+:10227000062A4D3000000004021010080000000182
+:102280000210101000000264021010000003D000C1
+:10229000021010040000003D091018000200035055
+:1022A00009101100002005500610118000000002E6
+:1022B0000910118800060570061011A00000001812
+:1022C000021010100000000006102400000000E0C2
+:1022D0000210201C0000000002102020000000015D
+:1022E000021020C0000000010210200400000001C4
+:1022F000021020080000000109103C0000050576CE
+:1023000009103C200005057B0910380000050580F8
+:1023100002104028000000100210404400003FFF5F
+:102320000210405800280000021040840084924AA5
+:1023300002104058000000000610806800000004F1
+:1023400002108000000010800610802800000002AB
+:102350000210803800000010021080400000FFFFD3
+:10236000021080440000FFFF0210805000000000B7
+:102370000210810000000000061081200000000211
+:1023800002108008000002B502108010000000005A
+:10239000061082000000004A021081080001FFFFC1
+:1023A00006108140000000020210800000001A8028
+:1023B0000610900000000024061091200000004A42
+:1023C000061093700000004A061095C00000004AF5
+:1023D000021080040000108006108030000000020F
+:1023E0000210803C00000010021080480000FFFF37
+:1023F0000210804C0000FFFF02108054000000001B
+:102400000210810400000000061081280000000274
+:102410000210800C000002B50210801400000000C1
+:10242000061084000000004A0210810C0001FFFF2A
+:1024300006108148000000020210800400001A808B
+:102440000610909000000024061092480000004AF8
+:10245000061094980000004A061096E80000004A12
+:102460000212049000E383400212051400003C10A5
+:10247000021205200000000202120494FFFFFFFF79
+:1024800002120498FFFFFFFF0212049CFFFFFFFFF0
+:10249000021204A0FFFFFFFF021204A4FFFFFFFFD0
+:1024A000021204A8FFFFFFFF021204ACFFFFFFFFB0
+:1024B000021204B0FFFFFFFF021204B8FFFFFFFF8C
+:1024C000021204BCFFFFFFFF021204C0FFFFFFFF68
+:1024D000021204C4FFFFFFFF021204C8FFFFFFFF48
+:1024E000021204CCFFFFFFFF021204D0FFFFFFFF28
+:1024F000021204DCFFFFFFFF021204E0FFFFFFFFF8
+:10250000021204E4FFFFFFFF021204E8FFFFFFFFD7
+:10251000021204ECFFFFFFFF021204F0FFFFFFFFB7
+:10252000021204F4FFFFFFFF021204F8FFFFFFFF97
+:10253000021204FCFFFFFFFF02120500FFFFFFFF76
+:1025400002120504FFFFFFFF02120508FFFFFFFF55
+:102550000212050CFFFFFFFF02120510FFFFFFFF35
+:10256000021204D4FFFF3330021204D8FFFF3340BD
+:10257000021204B4F00030000212039000000008C0
+:102580000212039C00000008061203A000000002D3
+:10259000021203BC00000004021203C40000000485
+:1025A000021203D000000000021203DC0000000051
+:1025B0000212036C00000001021203680000003FD9
+:1025C000021201BC00000040021201C00000180805
+:1025D000021201C400000803021201C8000008032F
+:1025E000021201CC00000040021201D000000003E2
+:1025F000021201D400000803021201D800000803EF
+:10260000021201DC00000803021201E000010003D5
+:10261000021201E400000803021201E800000803AE
+:10262000021201EC00000003021201F0000000039E
+:10263000021201F400000003021201F8000000037E
+:10264000021201FC0000000302120200000000035D
+:10265000021202040000000302120208000000033C
+:102660000212020C0000000302120210000000031C
+:1026700002120214000000030212021800000003FC
+:102680000212021C000000030212022000000003DC
+:102690000212022400000003021202280000240398
+:1026A0000212022C0000002F02120230000000096A
+:1026B00002120234000000190212023800000184E4
+:1026C0000212023C000001830212024000000306D5
+:1026D0000212024400000019021202480000000623
+:1026E0000212024C00000306021202500000030610
+:1026F00002120254000003060212025800000C8667
+:102700000212025C000003060212026000000306CF
+:1027100002120264000000060212026800000006B5
+:102720000212026C00000006021202700000000695
+:102730000212027400000006021202780000000675
+:102740000212027C00000006021202800000000655
+:102750000212028400000006021202880000000635
+:102760000212028C00000006021202900000000615
+:1027700002120294000000060212029800000006F5
+:102780000212029C00000006021202A000000306D2
+:10279000021202A400000013021202A800000006A8
+:1027A000021202B000001004021202B40000100471
+:1027B0000212032400106440021203280010644037
+:1027C000021201B0000000010600A0000000001687
+:1027D0000200A06CBF5C00000200A070FFF51FEFBC
+:1027E0000200A0740000FFFF0200A078500003E088
+:1027F0000200A07C000000000200A0800000A000F9
+:102800000600A084000000050200A0980FE0000070
+:102810000600A09C000000140200A0EC555400002B
+:102820000200A0F0555555550200A0F40000555582
+:102830000200A0F8000000000200A0FC55540000B7
+:102840000200A100555555550200A1040000555540
+:102850000200A108000000000200A22C00000000FD
+:102860000600A230000000030200A0600000000784
+:102870000200A10CBF5C00000200A110FFF51FEFD9
+:102880000200A1140000FFFF0200A118500003E0A5
+:102890000200A11C000000000200A1200000A00016
+:1028A0000600A124000000050200A1380FE000008E
+:1028B0000600A13C000000140200A18C5554000049
+:1028C0000200A190555555550200A19400005555A0
+:1028D0000200A198000000000200A19C55540000D5
+:1028E0000200A1A0555555550200A1A40000555560
+:1028F0000200A1A8000000000200A23C00000000AD
+:102900000600A240000000030200A06400000007CF
+:1029100000000000000000000000002E0000000089
+:1029200000000000000000000000000000000000A7
+:102930000000000000000000000000000000000097
+:102940000000000000000000000000000000000087
+:102950000000000000000000000000000000000077
+:102960000000000000000000000000000000000067
+:10297000002E0050000000000000000000000000D9
+:102980000000000000000000000000000000000047
+:102990000000000000000000000000000050008D5A
+:1029A0000000000000000000000000000000000027
+:1029B0000000000000000000000000000000000017
+:1029C0000000000000000000008D009200920096C0
+:1029D0000096009A000000000000000000000000C7
+:1029E00000000000000000000000000000000000E7
+:1029F00000000000009A00DB00DB00E900E900F7BE
+:102A000000000000000000000000000000000000C6
+:102A100000000000000000000000000000000000B6
+:102A200000000000000000000000000000000000A6
+:102A30000000000000000000000000000000000096
+:102A40000000000000000000000000000000000086
+:102A50000000000000000000000000000000000076
+:102A60000000000000000000000000000000000066
+:102A70000000000000000000000000000000000056
+:102A80000000000000000000000000000000000046
+:102A90000000000000000000000000000000000036
+:102AA0000000000000000000000000000000000026
+:102AB0000000000000000000000000000000000016
+:102AC0000000000000000000000000000000000006
+:102AD00000F700FE00000000000000000000000001
+:102AE00000000000000000000000000000000000E6
+:102AF00000000000000000000000000000000000D6
+:102B000000000000000000000000000000000000C5
+:102B100000000000000000000000000000000000B5
+:102B2000000000000000000000FE01030103010E90
+:102B3000010E01190000000000000000000000006C
+:102B40000000000000000000000000000000000085
+:102B50000000000000000000000000000000000075
+:102B60000000000000000000000000000000000065
+:102B70000000000000000000000000000000000055
+:102B80000119011A00000000000000000000000010
+:102B90000000000000000000000000000000000035
+:102BA000000000000000000000000000011A0152B7
+:102BB0000000000000000000000000000000000015
+:102BC0000000000000000000000000000000000005
+:102BD000000000000000000001520176000000002B
+:102BE00000000000000000000000000000000000E5
+:102BF00000000000000000000000000000000000D5
+:102C000000000000017601B5000000000000000097
+:102C100000000000000000000000000000000000B4
+:102C200000000000000000000000000000000000A4
+:102C300001B501F0000000000000000000000000ED
+:102C40000000000000000000000000000000000084
+:102C500000000000000000000000000001F002354C
+:102C6000023502380238023B00000000000000007C
+:102C70000000000000000000000000000000000054
+:102C80000000000000000000023B02760276028095
+:102C90000280028A00000000000000000000000026
+:102CA0000000000000000000000000000000000024
+:102CB00000000000028A028B0000000000000000FB
+:102CC0000000000000000000000000000000000004
+:102CD00000000000000000000000000000000000F4
+:102CE000028B029D000000000000000000000000B8
+:102CF00000000000000000000000000000000000D4
+:102D0000000000000000000000000000029D02B270
+:102D100002B202B502B502B80000000000000000D7
+:102D200000000000000000000000000000000000A3
+:102D3000000000000000000002B802E600000000F1
+:102D40000000000000000000000000000000000083
+:102D50000000000000000000000000000000000073
+:102D60000000000002E6036D00000000000000000B
+:102D70000000000000000000000000000000000053
+:102D80000000000000000000000000000000000043
+:102D9000036D0374037403780378037C0000000060
+:102DA0000000000000000000000000000000000023
+:102DB000000000000000000000000000037C03BBD6
+:102DC00003BB03C303C303CB0000000000000000EB
+:102DD00000000000000000000000000000000000F3
+:102DE000000000000000000003CB041F041F04319A
+:102DF0000431044300000000000000000000000057
+:102E000000000000000000000000000000000000C2
+:102E1000000000000443044D00000000000000001A
+:102E200000000000000000000000000000000000A2
+:102E30000000000000000000000000000000000092
+:102E4000044D0453000000000000000000000000DA
+:102E50000000000000000000000000000000000072
+:102E600000000000000000000000000004530456B1
+:102E70000000000000000000000000000000000052
+:102E80000000000000000000000000000000000042
+:102E900000000000000000000456045B0000000079
+:102EA0000000000000000000000000000000000022
+:102EB0000000000000000000000000000000000012
+:102EC00000000000045B045C045C046E046E04807B
+:102ED00000000000000000000000000000000000F2
+:102EE00000000000000000000000000000000000E2
+:102EF000048004ED0000000000000000000000005D
+:102F000000000000000000000000000000000000C1
+:102F100000000000000000000000000004ED04EECE
+:102F200004EE050205020516000000000000000086
+:102F30000000000000000000000000000000000091
+:102F40000000000000000000000000000000000081
+:102F50000000000000000000000000000000000071
+:102F60000000000000000000000000000000000061
+:102F70000000000000000000000000000000000051
+:102F80000000000000000000000000000000000041
+:102F90000000000000000000000000000000000031
+:102FA000000000000000000000010000000204C05A
+:102FB0000003098000040E4000051300000617C03E
+:102FC00000071C800008214000092600000A2AC0D2
+:102FD000000B2F80000C3440000D3900000E3DC066
+:102FE000000F42800010474000114C00001250C0FA
+:102FF0000013558000145A4000155F00001663C08E
+:103000000017688000186D4000197200001A76C021
+:10301000001B7B80001C8040001D8500001E89C0B5
+:10302000001F8E8000209340000020000000400020
+:1030300000006000000080000000A0000000C00050
+:103040000000E0000001000000012000000140003D
+:1030500000016000000180000001A0000001C0002C
+:103060000001E00000020000000220000002400019
+:1030700000026000000280000002A0000002C00008
+:103080000002E000000300000003200000034000F5
+:1030900000036000000380000003A0000003C000E4
+:1030A0000003E000000400000004200000044000D1
+:1030B00000046000000480000004A0000004C000C0
+:1030C0000004E000000500000005200000054000AD
+:1030D00000056000000580000005A0000005C0009C
+:1030E0000005E00000060000000620000006400089
+:1030F00000066000000680000006A0000006C00078
+:103100000006E00000070000000720000007400064
+:1031100000076000000780000007A0000007C00053
+:103120000007E00000080000000820000008400040
+:1031300000086000000880000008A0000008C0002F
+:103140000008E0000009000000092000000940001C
+:1031500000096000000980000009A0000009C0000B
+:103160000009E000000A0000000A2000000A4000F8
+:10317000000A6000000A8000000AA000000AC000E7
+:10318000000AE000000B0000000B2000000B4000D4
+:10319000000B6000000B8000000BA000000BC000C3
+:1031A000000BE000000C0000000C2000000C4000B0
+:1031B000000C6000000C8000000CA000000CC0009F
+:1031C000000CE000000D0000000D2000000D40008C
+:1031D000000D6000000D8000000DA000000DC0007B
+:1031E000000DE000000E0000000E2000000E400068
+:1031F000000E6000000E8000000EA000000EC00057
+:10320000000EE000000F0000000F2000000F400043
+:10321000000F6000000F8000000FA000000FC00032
+:10322000000FE0000010000000102000001040001F
+:1032300000106000001080000010A0000010C0000E
+:103240000010E000001100000011200000114000FB
+:1032500000116000001180000011A0000011C000EA
+:103260000011E000001200000012200000124000D7
+:1032700000126000001280000012A0000012C000C6
+:103280000012E000001300000013200000134000B3
+:1032900000136000001380000013A0000013C000A2
+:1032A0000013E0000014000000142000001440008F
+:1032B00000146000001480000014A0000014C0007E
+:1032C0000014E0000015000000152000001540006B
+:1032D00000156000001580000015A0000015C0005A
+:1032E0000015E00000160000001620000016400047
+:1032F00000166000001680000016A0000016C00036
+:103300000016E00000170000001720000017400022
+:1033100000176000001780000017A0000017C00011
+:103320000017E000001800000018200000184000FE
+:1033300000186000001880000018A0000018C000ED
+:103340000018E000001900000019200000194000DA
+:1033500000196000001980000019A0000019C000C9
+:103360000019E000001A0000001A2000001A4000B6
+:10337000001A6000001A8000001AA000001AC000A5
+:10338000001AE000001B0000001B2000001B400092
+:10339000001B6000001B8000001BA000001BC00081
+:1033A000001BE000001C0000001C2000001C40006E
+:1033B000001C6000001C8000001CA000001CC0005D
+:1033C000001CE000001D0000001D2000001D40004A
+:1033D000001D6000001D8000001DA000001DC00039
+:1033E000001DE000001E0000001E2000001E400026
+:1033F000001E6000001E8000001EA000001EC00015
+:10340000001EE000001F0000001F2000001F400001
+:10341000001F6000001F8000001FA000001FC000F0
+:10342000001FE000002000000020200000204000DD
+:1034300000206000002080000020A0000020C000CC
+:103440000020E000002100000021200000214000B9
+:1034500000216000002180000021A0000021C000A8
+:103460000021E00000220000002220000022400095
+:1034700000226000002280000022A0000022C00084
+:103480000022E00000230000002320000023400071
+:1034900000236000002380000023A0000023C00060
+:1034A0000023E0000024000000242000002440004D
+:1034B00000246000002480000024A0000024C0003C
+:1034C0000024E00000250000002520000025400029
+:1034D00000256000002580000025A0000025C00018
+:1034E0000025E00000260000002620000026400005
+:1034F00000266000002680000026A0000026C000F4
+:103500000026E000002700000027200000274000E0
+:1035100000276000002780000027A0000027C000CF
+:103520000027E000002800000028200000284000BC
+:1035300000286000002880000028A0000028C000AB
+:103540000028E00000290000002920000029400098
+:1035500000296000002980000029A0000029C00087
+:103560000029E000002A0000002A2000002A400074
+:10357000002A6000002A8000002AA000002AC00063
+:10358000002AE000002B0000002B2000002B400050
+:10359000002B6000002B8000002BA000002BC0003F
+:1035A000002BE000002C0000002C2000002C40002C
+:1035B000002C6000002C8000002CA000002CC0001B
+:1035C000002CE000002D0000002D2000002D400008
+:1035D000002D6000002D8000002DA000002DC000F7
+:1035E000002DE000002E0000002E2000002E4000E4
+:1035F000002E6000002E8000002EA000002EC000D3
+:10360000002EE000002F0000002F2000002F4000BF
+:10361000002F6000002F8000002FA000002FC000AE
+:10362000002FE0000030000000302000003040009B
+:1036300000306000003080000030A0000030C0008A
+:103640000030E00000310000003120000031400077
+:1036500000316000003180000031A0000031C00066
+:103660000031E00000320000003220000032400053
+:1036700000326000003280000032A0000032C00042
+:103680000032E0000033000000332000003340002F
+:1036900000336000003380000033A0000033C0001E
+:1036A0000033E0000034000000342000003440000B
+:1036B00000346000003480000034A0000034C000FA
+:1036C0000034E000003500000035200000354000E7
+:1036D00000356000003580000035A0000035C000D6
+:1036E0000035E000003600000036200000364000C3
+:1036F00000366000003680000036A0000036C000B2
+:103700000036E0000037000000372000003740009E
+:1037100000376000003780000037A0000037C0008D
+:103720000037E0000038000000382000003840007A
+:1037300000386000003880000038A0000038C00069
+:103740000038E00000390000003920000039400056
+:1037500000396000003980000039A0000039C00045
+:103760000039E000003A0000003A2000003A400032
+:10377000003A6000003A8000003AA000003AC00021
+:10378000003AE000003B0000003B2000003B40000E
+:10379000003B6000003B8000003BA000003BC000FD
+:1037A000003BE000003C0000003C2000003C4000EA
+:1037B000003C6000003C8000003CA000003CC000D9
+:1037C000003CE000003D0000003D2000003D4000C6
+:1037D000003D6000003D8000003DA000003DC000B5
+:1037E000003DE000003E0000003E2000003E4000A2
+:1037F000003E6000003E8000003EA000003EC00091
+:10380000003EE000003F0000003F2000003F40007D
+:10381000003F6000003F8000003FA000003FC0006C
+:10382000003FE000003FE00100000000000001FF59
+:103830000000020000007FF800007FF80000026F27
+:1038400000001500000000010000000300BEBC20C5
+:103850000000000300BEBC2000000001FFFFFFFFCE
+:10386000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF68
+:10387000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF58
+:1038800000000000FFFFFFFF00000000FFFFFFFF40
+:103890000000000300BEBC20FFFFFFFF000000008F
+:1038A000FFFFFFFF00000000FFFFFFFF000000031D
+:1038B00000BEBC2000002000000040C0000061806D
+:1038C000000082400000A3000000C3C00000E480AC
+:1038D0000001054000012600000146C0000167808C
+:1038E000000188400001A9000001C9C00001EA8070
+:1038F00000020B4000022C0000024CC000026D8050
+:1039000000028E400002AF000002CFC00002F08033
+:103910000003114000033200000352C00003738013
+:10392000000394400003B5000003D5C00003F680F7
+:103930000004174000043800000458C000047980D7
+:1039400000049A400000800000010380000187000D
+:1039500000020A8000028E0000031180000395001F
+:103960000004188000049C0000051F800005A300CF
+:10397000000626800006AA0000072D800007B1007F
+:10398000000834800008B80000093B800009BF002F
+:10399000000A4280000AC600000B4980000BCD00DF
+:1039A000000C5080000CD400000D5780000DDB008F
+:1039B00000007FF800007FF800000174000015008F
+:1039C0000000190000000000FFFFFFFF40000000A2
+:1039D00040000000400000004000000040000000E7
+:1039E00040000000400000004000000040000000D7
+:1039F00040000000400000004000000040000000C7
+:103A000040000000400000004000000040000000B6
+:103A100040000000400000004000000040000000A6
+:103A20004000000040000000400000004000000096
+:103A30004000000040000000400000004000000086
+:103A400040000000400000004000000000007FF83F
+:103A500000007FF80000050900003500FFFFFFFFB0
+:103A6000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF66
+:103A7000FFFFFFFFFFFFFFFFFFFFFFFF4000000012
+:103A80004000000040000000400000004000000036
+:103A90004000000040000000400000004000000026
+:103AA0004000000040000000400000004000000016
+:103AB0004000000040000000400000004000000006
+:103AC00040000000400000004000000040000000F6
+:103AD00040000000400000004000000040000000E6
+:103AE00040000000400000004000000040000000D6
+:103AF00040000000400000004000000000001000F6
+:103B000000002080000031000000418000005200D1
+:103B100000006280000073000000838000009400B9
+:103B20000000A4800000B5000000C5800000D600A1
+:103B30000000E6800000F700000107800001180087
+:103B400000012880000139000001498000015A006D
+:103B500000016A8000017B0000018B8000019C0055
+:103B60000001AC800001BD000001CD800001DE003D
+:103B70000001EE800001FF0000007FF800007FF8E8
+:103B8000000004480000150010000000000028ADEF
+:103B9000000000000001000100150005CCCCCCC1E4
+:103BA000FFFFFFFFFFFFFFFF7058103C0000000009
+:103BB0000000000000000001CCCC0201CCCCCCCC39
+:103BC00000000000FFFFFFFF400000004000000079
+:103BD00040000000400000004000000040000000E5
+:103BE00040000000400000004000000040000000D5
+:103BF00040000000400000004000000040000000C5
+:103C000040000000400000004000000040000000B4
+:103C100040000000400000004000000040000000A4
+:103C20004000000040000000400000004000000094
+:103C30004000000040000000400000004000000084
+:103C40004000000040000000000E01B7011600D641
+:103C50000000FFFF000000000000FFFF0000000068
+:103C60000000FFFF000000000000FFFF0000000058
+:103C70000000FFFF000000000000FFFF0000000048
+:103C80000000FFFF000000000000FFFF0000000038
+:103C90000010000000000000007201BB012300F3CF
+:103CA0000000FFFF000000000000FFFF0000000018
+:103CB0000000FFFF000000000000FFFF0000000008
+:103CC0000000FFFF000000000000FFFF00000000F8
+:103CD0000000FFFF000000000000FFFF00000000E8
+:103CE0000010000000000000FFFFFFF3318FFFFF16
+:103CF0000C30C30CC30C30C3CF3CF300F3CF3CF308
+:103D00000000CF3CCDCDCDCDFFFFFFF130EFFFFF69
+:103D10000C30C30CC30C30C3CF3CF300F3CF3CF3E7
+:103D20000001CF3CCDCDCDCDFFFFFFF6305FFFFFD3
+:103D30000C30C30CC30C30C3CF3CF300F3CF3CF3C7
+:103D40000002CF3CCDCDCDCDFFFFF4061CBFFFFF61
+:103D50000C30C305C30C30C3CF300014F3CF3CF399
+:103D60000004CF3CCDCDCDCDFFFFFFF2304FFFFFA4
+:103D70000C30C30CC30C30C3CF3CF300F3CF3CF387
+:103D80000008CF3CCDCDCDCDFFFFFFFA302FFFFF98
+:103D90000C30C30CC30C30C3CF3CF300F3CF3CF367
+:103DA0000010CF3CCDCDCDCDFFFFFFF731EFFFFFB2
+:103DB0000C30C30CC30C30C3CF3CF300F3CF3CF347
+:103DC0000020CF3CCDCDCDCDFFFFFFF5302FFFFF45
+:103DD0000C30C30CC30C30C3CF3CF300F3CF3CF327
+:103DE0000040CF3CCDCDCDCDFFFFFFF3310FFFFF26
+:103DF0000C30C30CC30C30C3CF3CF300F3CF3CF307
+:103E00000000CF3CCDCDCDCDFFFFFFF1310FFFFF47
+:103E10000C30C30CC30C30C3CF3CF300F3CF3CF3E6
+:103E20000001CF3CCDCDCDCDFFFFFFF6305FFFFFD2
+:103E30000C30C30CC30C30C3CF3CF300F3CF3CF3C6
+:103E40000002CF3CCDCDCDCDFFFFF4061CBFFFFF60
+:103E50000C30C305C30C30C3CF300014F3CF3CF398
+:103E60000004CF3CCDCDCDCDFFFFFFF2304FFFFFA3
+:103E70000C30C30CC30C30C3CF3CF300F3CF3CF386
+:103E80000008CF3CCDCDCDCDFFFFFFFA302FFFFF97
+:103E90000C30C30CC30C30C3CF3CF300F3CF3CF366
+:103EA0000010CF3CCDCDCDCDFFFFFFF730EFFFFFB2
+:103EB0000C30C30CC30C30C3CF3CF300F3CF3CF346
+:103EC0000020CF3CCDCDCDCDFFFFFFF5304FFFFF24
+:103ED0000C30C30CC30C30C3CF3CF300F3CF3CF326
+:103EE0000040CF3CCDCDCDCDFFFFFFF331EFFFFF45
+:103EF0000C30C30CC30C30C3CF3CF300F3CF3CF306
+:103F00000000CF3CCDCDCDCDFFFFFFF1310FFFFF46
+:103F10000C30C30CC30C30C3CF3CF300F3CF3CF3E5
+:103F20000001CF3CCDCDCDCDFFFFFFF6305FFFFFD1
+:103F30000C30C30CC30C30C3CF3CF300F3CF3CF3C5
+:103F40000002CF3CCDCDCDCDFFFFF4061CBFFFFF5F
+:103F50000C30C305C30C30C3CF300014F3CF3CF397
+:103F60000004CF3CCDCDCDCDFFFFFFF2304FFFFFA2
+:103F70000C30C30CC30C30C3CF3CF300F3CF3CF385
+:103F80000008CF3CCDCDCDCDFFFFFFFA302FFFFF96
+:103F90000C30C30CC30C30C3CF3CF300F3CF3CF365
+:103FA0000010CF3CCDCDCDCDFFFFFF97056FFFFFBC
+:103FB0000C30C30CC30C30C3CF3CC000F3CF3CF378
+:103FC0000020CF3CCDCDCDCDFFFFFFF5310FFFFF62
+:103FD0000C30C30CC30C30C3CF3CF300F3CF3CF325
+:103FE0000040CF3CCDCDCDCDFFFFFFF3320FFFFF23
+:103FF0000C30C30CC30C30C3CF3CF300F3CF3CF305
+:104000000000CF3CCDCDCDCDFFFFFFF1310FFFFF45
+:104010000C30C30CC30C30C3CF3CF300F3CF3CF3E4
+:104020000001CF3CCDCDCDCDFFFFFFF6305FFFFFD0
+:104030000C30C30CC30C30C3CF3CF300F3CF3CF3C4
+:104040000002CF3CCDCDCDCDFFFFF4061CBFFFFF5E
+:104050000C30C305C30C30C3CF300014F3CF3CF396
+:104060000004CF3CCDCDCDCDFFFFFFF2304FFFFFA1
+:104070000C30C30CC30C30C3CF3CF300F3CF3CF384
+:104080000008CF3CCDCDCDCDFFFFFF8A042FFFFF31
+:104090000C30C30CC30C30C3CF3CC000F3CF3CF397
+:1040A0000010CF3CCDCDCDCDFFFFFF9705CFFFFF5B
+:1040B0000C30C30CC30C30C3CF3CC000F3CF3CF377
+:1040C0000020CF3CCDCDCDCDFFFFFFF5310FFFFF61
+:1040D0000C30C30CC30C30C3CF3CF300F3CF3CF324
+:1040E0000040CF3CCDCDCDCDFFFFFFF3300FFFFF24
+:1040F0000C30C30CC30C30C3CF3CF300F3CF3CF304
+:104100000000CF3CCDCDCDCDFFFFFFF1300FFFFF45
+:104110000C30C30CC30C30C3CF3CF300F3CF3CF3E3
+:104120000001CF3CCDCDCDCDFFFFFFF6305FFFFFCF
+:104130000C30C30CC30C30C3CF3CF300F3CF3CF3C3
+:104140000002CF3CCDCDCDCDFFFFF4061CBFFFFF5D
+:104150000C30C305C30C30C3CF300014F3CF3CF395
+:104160000004CF3CCDCDCDCDFFFFFFF2304FFFFFA0
+:104170000C30C30CC30C30C3CF3CF300F3CF3CF383
+:104180000008CF3CCDCDCDCDFFFFFFFA302FFFFF94
+:104190000C30C30CC30C30C3CF3CF300F3CF3CF363
+:1041A0000010CF3CCDCDCDCDFFFFFF97040FFFFF1B
+:1041B0000C30C30CC30C30C3CF3CC000F3CF3CF376
+:1041C0000020CF3CCDCDCDCDFFFFFFF5300FFFFF61
+:1041D0000C30C30CC30C30C3CF3CF300F3CF3CF323
+:1041E0000040CF3CCDCDCDCDFFFFFFFF30CFFFFF57
+:1041F0000C30C30CC30C30C3CF3CF3CCF3CF3CF337
+:104200000000CF3CCDCDCDCDFFFFFFFF30CFFFFF76
+:104210000C30C30CC30C30C3CF3CF3CCF3CF3CF316
+:104220000001CF3CCDCDCDCDFFFFFFFF30CFFFFF55
+:104230000C30C30CC30C30C3CF3CF3CCF3CF3CF3F6
+:104240000002CF3CCDCDCDCDFFFFFFFF30CFFFFF34
+:104250000C30C30CC30C30C3CF3CF3CCF3CF3CF3D6
+:104260000004CF3CCDCDCDCDFFFFFFFF30CFFFFF12
+:104270000C30C30CC30C30C3CF3CF3CCF3CF3CF3B6
+:104280000008CF3CCDCDCDCDFFFFFFFF30CFFFFFEE
+:104290000C30C30CC30C30C3CF3CF3CCF3CF3CF396
+:1042A0000010CF3CCDCDCDCDFFFFFFFF30CFFFFFC6
+:1042B0000C30C30CC30C30C3CF3CF3CCF3CF3CF376
+:1042C0000020CF3CCDCDCDCDFFFFFFFF30CFFFFF96
+:1042D0000C30C30CC30C30C3CF3CF3CCF3CF3CF356
+:1042E0000040CF3CCDCDCDCDFFFFFFFF30CFFFFF56
+:1042F0000C30C30CC30C30C3CF3CF3CCF3CF3CF336
+:104300000000CF3CCDCDCDCDFFFFFFFF30CFFFFF75
+:104310000C30C30CC30C30C3CF3CF3CCF3CF3CF315
+:104320000001CF3CCDCDCDCDFFFFFFFF30CFFFFF54
+:104330000C30C30CC30C30C3CF3CF3CCF3CF3CF3F5
+:104340000002CF3CCDCDCDCDFFFFFFFF30CFFFFF33
+:104350000C30C30CC30C30C3CF3CF3CCF3CF3CF3D5
+:104360000004CF3CCDCDCDCDFFFFFFFF30CFFFFF11
+:104370000C30C30CC30C30C3CF3CF3CCF3CF3CF3B5
+:104380000008CF3CCDCDCDCDFFFFFFFF30CFFFFFED
+:104390000C30C30CC30C30C3CF3CF3CCF3CF3CF395
+:1043A0000010CF3CCDCDCDCDFFFFFFFF30CFFFFFC5
+:1043B0000C30C30CC30C30C3CF3CF3CCF3CF3CF375
+:1043C0000020CF3CCDCDCDCDFFFFFFFF30CFFFFF95
+:1043D0000C30C30CC30C30C3CF3CF3CCF3CF3CF355
+:1043E0000040CF3CCDCDCDCDFFFFFFFF30CFFFFF55
+:1043F0000C30C30CC30C30C3CF3CF3CCF3CF3CF335
+:104400000000CF3CCDCDCDCDFFFFFFFF30CFFFFF74
+:104410000C30C30CC30C30C3CF3CF3CCF3CF3CF314
+:104420000001CF3CCDCDCDCDFFFFFFFF30CFFFFF53
+:104430000C30C30CC30C30C3CF3CF3CCF3CF3CF3F4
+:104440000002CF3CCDCDCDCDFFFFFFFF30CFFFFF32
+:104450000C30C30CC30C30C3CF3CF3CCF3CF3CF3D4
+:104460000004CF3CCDCDCDCDFFFFFFFF30CFFFFF10
+:104470000C30C30CC30C30C3CF3CF3CCF3CF3CF3B4
+:104480000008CF3CCDCDCDCDFFFFFFFF30CFFFFFEC
+:104490000C30C30CC30C30C3CF3CF3CCF3CF3CF394
+:1044A0000010CF3CCDCDCDCDFFFFFFFF30CFFFFFC4
+:1044B0000C30C30CC30C30C3CF3CF3CCF3CF3CF374
+:1044C0000020CF3CCDCDCDCDFFFFFFFF30CFFFFF94
+:1044D0000C30C30CC30C30C3CF3CF3CCF3CF3CF354
+:1044E0000040CF3CCDCDCDCD000C0000000700C07A
+:1044F00000028130000B81580002021000010230DE
+:10450000000F024000010330000800000008008096
+:1045100000028100000B8128000201E0000102007E
+:104520000007021000020280000F0000000800F0E7
+:1045300000028170000B819800020250000102709D
+:10454000000B828000080338001000000008010002
+:1045500000028180000B81A80002026000018280BD
+:10456000000E82980008038000028000000B802863
+:10457000000200E0000101000000811000000118AD
+:10458000CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC6B
+:1045900000002000CCCCCCCCCCCCCCCCCCCCCCCC6B
+:1045A000CCCCCCCC00002000CCCCCCCCCCCCCCCC5B
+:1045B000CCCCCCCCCCCCCCCC00002000000000007B
+:1045C0001F8B080000000000000BFB51CFC0F00360
+:1045D0008A7BD81818367020F843015F646260B88F
+:1045E0000CC45781588099812198918121849178B8
+:1045F000FD49A208F62B210606316106866841A016
+:10460000B9C208F1A3403556220C0C7FA1628D403F
+:10461000369B2875DC3FD0789314A6D87A09047BA2
+:1046200033167964BC054D9E4F1295BF9580FE816F
+:10463000C68F1551F9620A103A1F2AFE044D5E1CFE
+:104640002A7F19EAAFA78AD8CDBD02950700C8E92D
+:10465000674460030000000000000000000000004C
+:104660001F8B080000000000000BED7D0B7854D577
+:10467000B5F03E73CE9C9949662627214F1E6112E4
+:1046800020828638BC0228BD4E0844AC5C0DF8423E
+:104690008B3ABC43DE50B4B4B55F2610224F6FF0A6
+:1046A00047452FD8E161458B3660A4D1021D4010EB
+:1046B0007BBDB7C1528BD5FA4554500C24728BD2B6
+:1046C0005B7BFDD75A7BEFCC39930960FFF6FEF791
+:1046D000BFDF1F3FBFC33E673FD65EAFBDD6DA6BBD
+:1046E000EFB1B334A60F64EC6BFCBB81B11A1B6352
+:1046F000F0AAFBF9949DDD5FEA662C6FA36FB93BCE
+:1047000015DEB7E6EC4AF43196B577BD3211DE67B7
+:104710006D6A5266E747DB8F76C1C731F0BE75BD63
+:104720005204EFB3DE6C5266E1D361636D509F6952
+:10473000BE24864F16602C9DB141E398F80BB8B3A8
+:104740000A19EB8FFF842ECE1B89D01963392B6C8D
+:10475000E19002EF8365539997B16D0057560AB403
+:1047600053BF3A60C7BAB5DAC97627634ECDA97D83
+:104770009DCB58F60C6663F01CB894BFC7BFAFE181
+:10478000FF9C90B53C8899CA3958F6A49E8221991D
+:104790008779BE56E3C1DBA5970E8FCE533E37D542
+:1047A000F9D2DD5ACFF7F2B978D127FAC3D0FA6936
+:1047B000AC3798B1704CFDAA90AEB16BE1090868B6
+:1047C000CEEFD97E2A2B2A443ADCC726D2B346F351
+:1047D000DD8578A9396A672180BBA6F65409965908
+:1047E000ABC286E4F46C3F9CD9891E454CD14EE1A6
+:1047F0007CBDCC8BF3532B7D4F94009EE726062681
+:1048000061BFEB1283F494EF33674FC90C023CC5D0
+:104810000BF2430CE87E7EA3E27740F3D34A58B70D
+:10482000033D2A6EAF2DB811EAFD560FDE8CED2A3E
+:1048300067B41D217AB0DA3CC4539BCEF967606B34
+:10484000D1A71AD00D582C9494827461ECA4890ECF
+:10485000F87772A828ABBDE3F172CFB9D88F86BDC7
+:104860008469BEF27D4EE8E8A0C131E3B14282879F
+:1048700031E471D6AEC4A3EBC0578A8E6A05BD8FF2
+:10488000F7F79F4788CB21E00EE95BE5D1C3CB80EA
+:10489000BEC52FDB2337003DAAB6286107946DFB08
+:1048A0005D01A4CFB9ED5006BA443C3AD53F6B3810
+:1048B000A95CE3687BE47A2877BDACB2ADD8EDD0D3
+:1048C000041BCADD29013B1B0D65C0C77C172F5691
+:1048D0006D39701FF657D6EA602EE8BFEA9505B726
+:1048E0005C0FE505C06F58A5EA997ABD2F9417862D
+:1048F00095662C774E64C41FA1143DFC0C8CD7E93F
+:104900006D4BBF03E4E54C9D93F90094E59EB6F42E
+:10491000DB818FCAC3BB4AB05DF94EC58F682F7E5D
+:10492000F999235938AFE780AF808F2A7624329FD8
+:10493000C41FFC7F0AA672037C5F0CF344F95FC0BE
+:104940009A4A988AE3AFD77D9E28BECED419344EBA
+:10495000B73C3D07E340BBEA17153F4EB1DAC682CC
+:104960002857E75E71CDD8E6C6F9D5EB791E9CD7FE
+:10497000C33AD65B109EB507555679788B5E02DF39
+:10498000CB376DD1E7E723DE40EFE5235C7DAC70EC
+:104990006D540388DFC5C9CEAD2AE087B90399D32A
+:1049A000E3F0CF993A506379D17239CA37E993B0BD
+:1049B0003ECD54BF4449267EADD8A1329F859F3855
+:1049C000FD43C738FD43FB3CE16772A2F45B6C70AA
+:1049D0003D29E9B73859D053EB2A8C07CF23480F2C
+:1049E00080A709F105CFB5023EEF0456A4015DBCD6
+:1049F000016628ECF2FCD96467B3188CFD169B178E
+:104A0000D0C64359678B989F3143AB0A4C82F2570B
+:104A1000ACF44D9C0F637E5F29E0B951613370DEC9
+:104A2000871158984F63964EF86B9A5CB84D5504B1
+:104A3000CCA9589EFF93D539D4FE38B5D7A0FDF048
+:104A4000DEDB1B25E32CED8D9232D9FE3DACC79CFD
+:104A5000976EDF54729D75FC9272D9FE231ADF7D2A
+:104A600069F88D1B2758C7BFB192DAD73838BDBA5D
+:104A7000929DE1AD506E70F9031AD24D63117CAF77
+:104A8000A5E46DC57AAAE407D61650A1BD7B67F2EE
+:104A9000C8D5CCCC1713FF88E379405ACC7C91342D
+:104AA0002EC1C28FC981144B197A324E5D13D54382
+:104AB00001AF93E0D1FBEAA42F8AFA3A09DE07F7A7
+:104AC000BBA8FCE0751CDE07FBBA49CE10069605B4
+:104AD000653D78AD615A8F004E856532764109BAE1
+:104AE0009431E6F73E1BBE4F50592DCE27C1C14829
+:104AF0001F3D9C53B82D64C2CFCA01405F28A72A2E
+:104B00003AC7A3C0EBC303E667CE328DD338409FCC
+:104B1000B1359FBF9FE3C6F14AD315D4837A579E20
+:104B2000E1EE398E23779C651C6776198D931333DC
+:104B30008E23BB2C661CE78CADE2BD1867D0A5C6E2
+:104B40007938F73AEB7CB2CB699C82D8F96497C785
+:104B50008C93C0E703EFC5387EC45FAFF31934C14F
+:104B60003A9F819534CEF538CE18D37C0656C68C44
+:104B7000E3A671F03D8E0386948F6500DD1D5DF325
+:104B800089FEBF7491BDA03B82CF62BFEC5D17234D
+:104B90007DE283713350AFC0E20CF2AB292934CEF1
+:104BA0001709407FB799CE5C1FD113F4CF3C012287
+:104BB0000B0344A07FAA058FCEDD392DBB1E9FAD10
+:104BC000C599B3D02ED9E0F10F01D139D75AACCF66
+:104BD0008963DFCC6BB29F6AB7F0AFD07B13D9D0BB
+:104BE0005A18BF05958DA97C0AF41703BD7512F4F8
+:104BF000173E4F0BFBF423D06F4C37C35B4FF3389A
+:104C0000A5713C9EDAC4D7912FD61FB383B187C359
+:104C10001CCF07B8EF14D398D704C69F49CE6A04B7
+:104C20003DBA5E7184B7123D02FD6CC0E76C631F34
+:104C3000C095A80776E61F843D0A7FFD6C60CBDE39
+:104C4000B372D761ACF6B6326BC06298EF8C96F552
+:104C5000F67E503E676FBFCFEF36F533C37E12E767
+:104C6000ED84FFB09FBB83768B7DFA9D326BF9DEBE
+:104C7000187BB552C915F410E3FAC276A4D79DE9A2
+:104C80001C9E7BF139123F1B44AFFB0CDE56C25316
+:104C9000F3433B8BD07AD49EC6F2111F696417058B
+:104CA000E5BA1203DF7D7667A014E879DFF755C215
+:104CB000632CBCEDFB130336B097DA37FEBB1DED5A
+:104CC000EFCBC17FFF52EB7716E2E349BC4A3EB817
+:104CD0006B46519F8F4CF5EE0EDED4E72313BF7C5D
+:104CE000A76C9AA57C6FEDDD96FAF72F9D65F93ECE
+:104CF0002BB4D0F27DCECA4596F2BCA6EF5BEA2F6C
+:104D0000D8586FF9BE30BCCAF2BD62C77A4BB9AA97
+:104D1000F9494BFD9AD62D96EFB6FDC36E45795CE9
+:104D2000FE5B95A17D76C17DEA11B4AF2E189A1F66
+:104D3000EB5423AF811C7E529749FC7DA6CE47CF12
+:104D400073ADA39C688FD724803CC35ABF5FF943DF
+:104D500068E504D423501F74F841E5C350089CA7AC
+:104D600037141FF1BDBA516711605585A574F375ED
+:104D7000971AFDAEB5C3F751BD7F57376A71BF6B48
+:104D8000ED5ADC7E3B95AE3CB4EF42EF3818DA8149
+:104D9000BDD90FF0D70FD78BDEBE77D85859B3499E
+:104DA000EF9C526CC407772A134FA17EAED4B9BCD6
+:104DB00057EECE9A88FE60A51EC9AB755F62BC66D1
+:104DC000002603FBC9A5792D0CF78BCA2FD16F9054
+:104DD00045EE97B0E0C7A89F3B0EA8A46759E450E2
+:104DE000F66DC371FCC0297CCF5AD3687D7CBB2E85
+:104DF000D0E723F0E74ED44DA1E7EFEB4AFB7C046C
+:104E0000BAE6BDBA19547EBF2E48CFF6BA327A9EA2
+:104E1000ACABA5EF1FD52DA5F2A9BA103D3FA95BFC
+:104E200049CF33754DF4BDA36E2395CFD585E9D910
+:104E3000ED07087B94A50AFB4FD8EBB07250F9BC84
+:104E400098830AFFE67EAB3F13E5FABCFB8B3CB4CC
+:104E500073CF9F00C3248E7F289FB1FCD63BFD02F9
+:104E6000B4DECF0F03FD47F5FCEE4AE0F471D9D86C
+:104E70001406FA67D5109D69307EC22FAF217B19C9
+:104E8000DE6B8CF465D83FCD13A77F9C73C6E5E934
+:104E9000D4CD1F4FFDB910E30F770A7D987048AD50
+:104EA000E574DBE647BA99F0C7EDB297853E8FC14E
+:104EB00023D972593DF179364DE2B32D1BE3001B26
+:104EC00094D26136E083F32D0E9AD7F9BD896186BD
+:104ED0006D313832FE5278E37054EC701966FD5033
+:104EE000D59C6C58F5459661D617E78F6EF3A2DC1A
+:104EF0002FCEB4191F8D42FE0808FEE07C27FBAFC1
+:104F00006ACE31DC967EACE5F34DCA14F48340B929
+:104F100027DD1EC73F90CFC599BAF111C8F7991D7B
+:104F20008392705CF0E30C1CA7A3CE30F8B899868E
+:104F3000992F2B9726507D095F6FFDFEADE143CB86
+:104F4000E0432723D47F3DE89BFBD94CFB23C5736B
+:104F5000D85EFB17B8EE38E0FFAF291EA05159F616
+:104F60005BD3AC861CD7E2FB9D96F1A09D4FFAD097
+:104F7000B85EF54E778D9D32C505AA710CF28F9CF7
+:104F800044E720F49804FD756AEE950A8C33C5E673
+:104F9000A3EF35821FAB9CED7A105E9D6DE1F4E8C6
+:104FA0006D9C3375477D1AE88F32277864304E59EF
+:104FB000F3B049A81FCFB62C4F0F02DF56A8E71F4A
+:104FC0002C8DD37EA54DE1F084ED5DEDA6F9C838BA
+:104FD0000A63D0AF330A3F72FA295339565FCBE7E1
+:104FE000A3D82FF047F5CE6325D703FCD5AD9FEBB3
+:104FF00008C7145BF0515B5A74FE0ACE1FFA29DF12
+:10500000F1818EF3FBC41ECAFBE125F4544F38DD59
+:105010009914B793F085581BDA31B3BBE38ABEBB52
+:10502000DE05D1FCF45FEC6C35C0C1BE825AF0DD08
+:105030002EBECE65A55EC4D7EC960A8A2F7E6A93F3
+:1050400076535321F2C759669B82F33BCBDEF28E37
+:1050500032E1AFC5C6ED7EB692DB3121F80FE1013A
+:105060007BD662D72CD8682DCF67D3D3516FCCDFD6
+:1050700060676140D142B48B247FC0BCB7DBB8BD50
+:10508000BB80D536A23DA739B87F30DB605A3F8060
+:10509000ABEAE79B0BD1EEFF85CD46F49171868597
+:1050A000291CEEF2D4B01E80EF1FB68CBAF37AE45E
+:1050B0003E47B811D76596C4FCCFB09EF89CB3D2DA
+:1050C0000ADFE5E08F8597B165163864BF120E756B
+:1050D000871208C7E1BB3724DF093D92A25AEDFCD5
+:1050E0008C98F27B3611BF54998A743E6B3843B664
+:1050F00024FAEE8F607C64B7C3BF1CE8FB80ADB4BC
+:105100001DF533D80505CC54EF015B90DE77286F91
+:10511000CE47FB94699102F4EF614DD1901F74C1A9
+:105120000F6A82B700E3B11E06EB27C8A503E1832F
+:105130007E1A3D65535901C65F414EA1BF75DE928F
+:10514000A30A945DEE1686FD3932ADF16597CF5A0C
+:10515000AEC17F201D86328AE3240EB57E87058B83
+:1051600021BF79FCD6F7FFD18DA708F1AD97581A6A
+:105170009E4E774485F1D938ADC36C37573B39FC27
+:10518000E49743FD25C29EAF66BE10C58933391F23
+:105190002CB9C946F02CF1F8FC21F8AE680186F272
+:1051A00087B16AF33A56731144AE8FA9AC75E9C85A
+:1051B0009735173516067D5F600B7AD43188BF00AE
+:1051C000D9B94E40D6D700B2E69E62B17B59FF14E2
+:1051D000B1BEF637CCF2DA1FE93C264A67A917ECD4
+:1051E000422F82BEC850D3500F7695905FC2DA49E5
+:1051F0004FC87A7AB45E7F84A3B77AAE68BD9C78D4
+:10520000FD55FDFC853D21C07FF9CF1EF302F1D98C
+:10521000A75A53BA1FDE573EB3C28B7CFC8916F2E5
+:10522000E2BC3F0DAB53E2F1F39DAA22FCB1805BDF
+:10523000417F58D0E9CCF36B6E41BC7FF18CDDC06F
+:105240002A353B1C110710B1BA6521E7A71D8E0F47
+:1052500078F9E1CF919E35AD56792B7FF6B1748CFC
+:10526000770286B8DFC822643F576FFFB804ED911C
+:105270001AD6457A22B61D8E7F3185D6AF597A521D
+:10528000CFEF72FFA546F07D4DCB9ACF552F96AD4F
+:10529000F25D26FC911B554F2AC595C6B2B1483721
+:1052A000890716E6F6F0F2E79E28F800E0E8D8FE57
+:1052B0002F5EC51237E2FAE17CF39C1FBFEAEB5D7B
+:1052C000AF9F13FE7CB45D98DAF95AB9FDCEF6F2C1
+:1052D00067A53DE2457FA9728BDD0F92C92A5FD891
+:1052E000F693A790AFDF71509CA1E285C36F5F0773
+:1052F000E58A5DF6D4A97C1A6E253D4A8F1AF87F9F
+:10530000E9C828FECB5F3AACFB86F3F70FA544E96A
+:1053100050B1EB80CE86F7C45B71F301BDDD1D8714
+:105320001ECD1F94A0BDBDFCB92F7594AB4FF72BBC
+:105330002C23A767FBB22D87C99E433C11FD047D3A
+:10534000BAE9D5834E915B5E1D4DF50C5CBF7AA327
+:10535000D3D5B8F6A5111FBFF82AC6EF7FEFF0E34B
+:10536000FCCB5EFCAE17E7715AABE5FCBC79457A25
+:1053700000C62DB387D20D7AF2F7654F3F407CB659
+:10538000E0D803E9140F60812C1BADA1A12C9CDF98
+:10539000BC4D77D0FCE6B320F15BD966B5348CF117
+:1053A0002C8D4DD915471EDE14F2707AAB03D71E33
+:1053B000761A152CFA876FA9B44FC0D8228A373CC9
+:1053C00020F721D8622A5F70723A6D536D32BEE1C8
+:1053D000B4F0E9F687DB903E67060432303E097888
+:1053E00008097C29A877D4639333387D984F2B1410
+:1053F000ED402F16E37BACDF660FB80A2CEDC43A04
+:10540000C6C75F22C607B813D01E3B9D0EF64D9C43
+:10541000F97DA94ABD0CF68689BF4C72CDE57CFBAF
+:105420002A2ED752CEC3D3A6E0F73F1EE7F283ED74
+:10543000705D07B82219F4FDC0ED0AE901078BC4BD
+:1054400093E7ED7621CFD6EF727F12E0D6707D8A9A
+:10545000F209F49F42F8273B6DFE066867D2CB3510
+:10546000381ED5D3A3EF4DEBFA0221FFAFAB627F1D
+:1054700054C83FDBC4E5BE77BB37C4FD037BF827C8
+:105480004FA1BC827CE23A53F982BD14E7FDD9CE2C
+:10549000436FDF037CFD59B39453ABDE8C95D3B2DD
+:1054A000DD63583C39FDCCED6771E514DEC79553DB
+:1054B000773BF1F1DF5B6F4ABC9D8BD19B520FF6BE
+:1054C00086BF583DB856F5C5D583F0779C15F6E4F0
+:1054D0003BC96F92CFCA7F5A3590E246921F25BFD3
+:1054E00075F3A3E4B7D8795AF116FBFD15A16F2423
+:1054F0009DEDCB58C883F1D27D2AF9D79D00532367
+:10550000D0B773674E18E3CE2B5C3C7ED1697479BB
+:1055100053E0B9229997BBD2F446D40FF27D978B12
+:10552000C7B73B4BBBBCC926BFE283BDAAD707DFC9
+:10553000DBC36C4A3C7F03342FC1D1CE7AFBCEE370
+:10554000C1935577F652F4DB9B54DACF9E5B7F977D
+:1055500017F7813BF70EFA27D44FF3DE000313E071
+:10556000ED443B3009A717D0302F618EA0F7272CD0
+:10557000F4F80498DF9CBDDC5F98BB36C6BE772F7D
+:10558000D151DF807D7FD21AD7E67C532EFA29DBFA
+:1055900064FD5ECED612DDCA63F82828FCC0B19A3D
+:1055A000E0A3116C84F0C378FC42E8ABC96AFE3F0B
+:1055B000A19DD17994C715CFEF5509FFE7772A61EF
+:1055C0008CFB507C773CD2BF4B67267FB903F94DEB
+:1055D000EF5D8E3B5EFE43E10FA14AE59E770BFE39
+:1055E000199E1D7BDEC9FB05967FFEBBEC7759CF6C
+:1055F000FAC5FBFF44FBC79DFB1D0447E7FED7B37D
+:105600007F88E5571D7E84B3739983F6CF42FB3DB7
+:10561000E121F87D00D01BD7CD7D5F16B4D3BAD37E
+:1056200040749AADF1FD8EF37BFFFCBE82F9077BDF
+:105630001D3E9C47CD7E9E1752F3AA8BE22E9DFB0A
+:10564000BE2C0CBAFF76F3A9D65990F8CFC366ECFE
+:10565000467E4DE6FB0035BF18BFAD1EF7C35B0E9F
+:10566000E8B8BF52FCCBBF14A07EE9DCCDED84735B
+:10567000F6F6A7711FB44A1BBCCC8E728F365B5FE7
+:10568000B03BEDF32686F2E3E185E3A113F080F36E
+:1056900002BC94A15EEC0D1F0D1AF737FFFBE1E38E
+:1056A000F3FB70FCCABD63496EA2785102FCBD27B2
+:1056B000EC5468FEFCFDFE2F0BD0EEF9ACB99ED683
+:1056C000F1CBCD7BDBFFB8792B912B99F7C1FFE6AE
+:1056D000FC3F45E3EB52AC1CF4E4F39F3F48E51775
+:1056E0003D7E82F70AE5FFE4FF34BAEF06BA7B2F6E
+:1056F0004F77C5FEDF75DE97A3FB1B82EE1E03F31B
+:105700000A3AF7FD85E2E572FE979BB7EFFFD17984
+:105710004BFB67B5CDDF940BF5D7B2489B0FE05C30
+:1057200031747A138699C04D288D678F94DAB97FCA
+:10573000A42A3C0EC306F0B81013FE04A580F9306D
+:105740008E329FEC3ACDDD487626D3FC6D01C0C782
+:10575000EAAB67FB2957838D3C11C472FF097E8A2F
+:105760006FC6F8550D0A0B2860EF69577FFB28DAE2
+:10577000F9F6A1B688A3809E1FE0F36111C7B21BA2
+:10578000BAC59F70C7F8032E9FF5BB43F4E76423A7
+:105790009B72314FC1AD196118DF5DD444F3710FB5
+:1057A00061ACC9B40FE860A6F6D05F3E06604DF666
+:1057B000E337C55F7D37FE46B605107FC36C14D74F
+:1057C000A2A43EC2873FBC9AFC4CEE3F46F1D9D81A
+:1057D0008678D418F87F7C7EE43732E12F6AA20BFA
+:1057E0006DA82DE0B2D6137ED165E9C3E9915D299C
+:1057F000E8B3D8420F89FF3874B1D043E2F79BD2A7
+:1058000025961EB178BFDDCEE36DB174B2E477A406
+:10581000713F24027EC8EB3BB751BCE3ECF31FDCC5
+:1058200082F52B7EA13227F4736EA78745507EB593
+:10583000B08EFE54798B1A37CE2BEDF28A9F7968A1
+:10584000BCF2DD8EF054685FBEE7C302B29B967572
+:105850001DE9877181E7154EBF507B01EEDB956B2B
+:10586000DC3F88ED6F939DC7053A5E499C81F10747
+:105870006507CF572C6FBECBEE30F1DBFFB2F3BC28
+:1058800057A847F21C7A4EA1F5A6277CDC2FE878B2
+:105890004EE1F0B5DAC398F758BE638B1E44BF7271
+:1058A000C7E714C72EFED90BDE76F21755ABFFBC47
+:1058B00043257AC293E817EBC756B754919F50DD42
+:1058C0002CFCC4183FAAE267FBF6840035152F3D77
+:1058D000EBC5F8CB99B667BCE49FEEE0FEA7E6D631
+:1058E000E2FBA797F34B9B57C5F54BCFE03FC09F1B
+:1058F00038608FF1E777F4B9B2FDCB172E3C8D718C
+:10590000D28EDD9F3D8D7057FEE7BF3F8DF63DDBAC
+:10591000EF329E81F9D63CFF5B8A37C976EF0A39B0
+:105920003D378085B2A0DEB9771C943F726EDFE907
+:105930006CF4E7CEEDFA533AFAF54BF64DCEC0795A
+:105940002F79B93883C59177F944BE0C5F419C30FB
+:10595000960E875A0E911F72F68483FCBEEEF842B3
+:1059600073158FD7F8445C6167FC38ACF487AB5B88
+:105970003E2CE1F131E1175F2E8E701CE878ED15B9
+:10598000D06BA78813C5D0EB2CFE03E8F2650CBDE5
+:105990002EB0E08FB3701FB2A54FAF7184C815E071
+:1059A00049C6778FD803361DE5607762379DA622FA
+:1059B0009D5EB8908DF1F04FEC5D64F774ED731857
+:1059C000E8DF97EFFB1DC9C5B9978F51FC94893863
+:1059D000EB39D6FDC7E3628A98DF760F8F3F087CEC
+:1059E000637CC2E7A5F7220EC1F955C6277A8B4B17
+:1059F0008CD545DE93883B576D7F576731711E65A7
+:105A00001CD2E9034B7C5CCE3BB63F03F130D61C85
+:105A10005F8B1FF7917E73944E3CAE26E367E7B62B
+:105A200088B81BBCEF3F12FD411EC7A8092BBF63FE
+:105A300071E450C6D746EA317218BEB2B8DAE5E072
+:105A4000FD6BF13144E7EB83C44BC757F1F5F03FF1
+:105A5000EA5CAEA7D8825375D37EF6FD629F45E21D
+:105A60004BC2DB21F2F03A9E57291ED4D87C88F431
+:105A700069AC3C57F7720EE23E9DC75BAB5B0F14FF
+:105A8000A0DEE938F80AF15DF5CE0FF410F4736486
+:105A9000C74B3AB727399FA39E0E9BF474C78B0759
+:105AA0000A78DC8FE7DDC6F65F21FAAFD96BEDBF70
+:105AB00066E7E796FE2B42CDB4FF75B971CE6881DB
+:105AC000BB70BE67DAEC0CF5DD9966754A389E1D31
+:105AD000A8DB2DFBA08DC7745AAF46BF9540F9B91E
+:105AE0004B8E4D793709F7E940CCD0FE6DA9E77CA4
+:105AF000D5F2A3403FA44BCBB17B545C37F6201EBC
+:105B00004D7670E1F1DA620FC86BE17BA5A391AD30
+:105B100062F5C0D813360BDC304E06EAE306E80720
+:105B2000F3E9317F08F747556FC9148447356C8610
+:105B30002BEEFAC9FBB3BB4B19DAE576C39AAF9CDF
+:105B4000395DC4D122D6BCF54C9D0DC57D70664B28
+:105B5000F0E37EC0E26181118731AF7E5E26C589A8
+:105B6000B36EE3EDCE1AEE90EDDAE8BE6DE245E8F5
+:105B70001FF3606CE1F533A15DA2D6ACE03E003CC2
+:105B800019D2E5015B70AB9E86F574E603D5F8B4D7
+:105B9000AE68947F21CEBDC8FE64BDDEF683E539D4
+:105BA0002455C03F48EC070F60ED0AEE076FF2F096
+:105BB000F34803DDA974DE689BB0DB7CB8EF8AF59F
+:105BC0006AADEBF665CF23ADB496538B8B160DF40F
+:105BD00033F661E383C51AE883D4BB8A76F5337064
+:105BE0005F7A4331E6DDA73E5B34220BCA77398604
+:105BF0004FA2EFBF2E1A910DE55AE7B849F4BD4206
+:105C0000A1BCC07D7A6771283F2A9F6960DC62BEB3
+:105C100005C8ED4194DBB3A51D8DF8B5EA8E2F7450
+:105C20007E1E8695E2FC078CE3F3EFEF7E6F17CEC6
+:105C300077A0ADBD1EF9EFC7FBBE4CC67A3E66D05D
+:105C40003C0DD660E0BE3CBC1AF7F525F27F62F34E
+:105C50006024BF6F4B0CFE06E158357BE81325A886
+:105C6000532BFDC447B1FBC4CC4825BACC157441B5
+:105C7000389DA63CE4056A88F25EF04402E5F5B082
+:105C800049068EA7842AD5AFAFF9E6709DD645BEEA
+:105C900081380F663A2F7506E15D9718A467EC7995
+:105CA000A9837A6907BECF9A7F311BE721CF4115BF
+:105CB0002F70537CE0FC5E1676C49123F9DC5AC742
+:105CC000D2B4C1BD7FFF8D23F81FD87FEE2F7DBBDF
+:105CD0008F427FD7CED5FD98C276EDD2D169DA2832
+:105CE000C627847685A05F26D214E5EC41C6CFE7AF
+:105CF000389400FA8F9DDF35480FF79F3B95FC8C59
+:105D0000CEC49C66CCA3E8FC21CF0780955E417988
+:105D100018B03729827E10F0F31731FCFC8575BD71
+:105D2000B18EDBF9B5AFB59DFA33447F60F0A4A323
+:105D3000FCF0BF4E95DBDB9D753E8203CCC303B800
+:105D4000AE5EE978590E110F17F401BCF77398F0A5
+:105D50003ED0D12BFD721D9C7EF48CA5DF7C676D3F
+:105D600036CA7379697309BAA8BFD5835761BDD3A1
+:105D7000F38F34DAA15ED5CCDA3C64F69E74E5E7A5
+:105D8000B1D2F7CEAAB763BC02E9E2EB49BF6B9789
+:105D9000FAD3B43E167A8E72403FD7EEFDDC8670A1
+:105DA0004B3A3E21F2FC63DBFF834311E356D6DB23
+:105DB000314ED2AA933D1B5B6F0A1EAA1A132D17F0
+:105DC000380B69DC0C1B8F77F4ACCFD7BF68BF4EA4
+:105DD0003A97D51B1F1618BC3FC0FBB7117E89F739
+:105DE0005B1C42DFF6C4FB34AC0778A7E715E0FD87
+:105DF000CE4BE15DDACF15421F54E0FE09F0CDC76E
+:105E000081E9E98361DC12D54D7CBFF01995E40D81
+:105E1000EA4FCD4A8FEA8F85E36B0FE03C176E5651
+:105E2000883FE78AF3A59F897CFED83CA8F93342D6
+:105E3000B4AFD3231F2A1CE3CFC5E4B95747F97485
+:105E400020CF4FE3E7B5542107C50BF293D00EDA0C
+:105E50006FF7FD9AECEB3754B6350EDE89B9D2A256
+:105E6000E501B5364B7E2C9B9B6CE977D2827CDAC0
+:105E7000EF5EECF15DD29F1AB8D4BA5EE784ACE76E
+:105E80008B06ADB49E2F1AD2D4D752FFAA8DB996E5
+:105E9000EFC3C2575BBE5FB363A4A53CBCF93A4BEA
+:105EA000FD6B5B275ACA2322DFB6D41F7574BAA5CF
+:105EB0003CA6ED1E4BFDB127665BBE8F6F2FB77CF6
+:105EC000BFFE93C596F2B7BA7E60B54F6C8CF421D5
+:105ED0004B50483FBE56372E1BF3B0D9686512E2CF
+:105EE000B358E411BEB648B7195E7CE6D90CD0535E
+:105EF00007E74DA5F5FEB545E9011F3D0B03E8CFCA
+:105F00003075C2E878799A938DF1D9E67CA862A7BA
+:105F1000DDA2CF261BD6F2CB926F0672BE79354634
+:105F20009FD96B2744C022647D170ECEC0F140BEBE
+:105F3000F609BDB6EF0AF5DA4194C3D3E991462CD0
+:105F40004BF962625D2D127C04CF808EF990933CF8
+:105F5000B4FE06F0A58FDE87349093894E7FFFC391
+:105F6000381F9B3F15996FD28CD2D7786EA5587F7A
+:105F7000D950DB37597FA57C67DA44BE5A0ACF5720
+:105F80007B725E5E1233E1F55D874DD8CD4DFC69C5
+:105F90001C7575E7A9E69ADF7F92A099F2E3940554
+:105FA00053293F24B3173DA867E6DEB41DF4AF9E26
+:105FB000E5A3A77CDF38C31637EFEB9CD09BD2BE9E
+:105FC0001A16B5AFCE211DCE66BEF538E62555CFE3
+:105FD000EC22FB2AD3D6B4E808CEEB57AA8857FAAE
+:105FE000F8792A6117CFBBE9D14547701FFA5F875F
+:105FF000905E92E36CAA9B7293663A37DEBF173FBE
+:10600000699893AF0F4FD70DBD692EE5691BFC7CD6
+:10601000A8E83F3B54558276F240915FFAB82D7E56
+:106020007E4B8293CF2B03498EF01A6E928FB3F37F
+:10603000DFF36A308FA76CC10427EED35EDB56C84E
+:10604000FDBC801FCF9D6647EE7D1CEB67676A94A1
+:10605000DF1A3B7EC6CCE0CA1C985F438ACDEFA610
+:10606000729782F51D0F31D607EA37FCA74AF03444
+:106070001C1C4FF91E0E772D43FB55CEEB50CA5317
+:10608000841FB52591D63D26F6C1657CF542E6DC38
+:1060900036B42B2E6CB0D37817608E06F47FA145F2
+:1060A000A57DD6232909111B94D5951E52A9D9681F
+:1060B0006B42FDF92D9EB02F278A176DE3043AFF3E
+:1060C000E2E8CFE7DF90E20EBB7368DE29386F09A4
+:1060D000A79CF7805EFCCA1B041EB3AEEA3E97C1C4
+:1060E000908F5543A37EE725F37397E1BA71825EE3
+:1060F000D6F934664EBFF56E3C2F745C65980AE2A3
+:106100006B6FA2F9CF87F9637C3716BF677D395F64
+:10611000D85482F3068453DD5842F3A07AD0AEEA15
+:10612000C70A7B2A07F9303885E8DAD746E70063E3
+:10613000E12E71F238EB8D4E1E0FD033F36EDADEA6
+:10614000079F83492E6E76F6BACEDFE2E47A889E08
+:10615000577E9F40C4B2CEAB011BD941B17081DEE6
+:10616000BADB69B26BD4A4870AB0DFDEEDB15D079C
+:1061700074B4C7DC8CEC64A92F7BB3C7D00E437E0C
+:106180009376D802A755EFC2FCCAC5FCCAE3CD2F4F
+:106190008E9EADC17AA7EF89C4B563D2F4F87A6850
+:1061A000B3C07F8DA1338A2BF5120F7FC229EDC1B9
+:1061B000BD0774C42BCC13F19A09FE7109E9197B50
+:1061C000DCBCEFCBF919B96BF2771FC5FEC08E4569
+:1061D000EE39DFE44B4AB9841D615FFA2B97198FC2
+:1061E0008FC4F007E06DBD93DB7FF4EC81B754C042
+:1061F0009BCD82B7C79D97B4FFB8BEED2BCE0F9C49
+:10620000137802BDFB7DECFFEC6DE7EE44DFB0EAF6
+:10621000B6AF845FCBEBA70BFD0C7EEF3F7CECA30E
+:10622000FA4B709CA8FFDB5E887ECFF297AF4A42A4
+:10623000FB69D29EBB0D7C9E4F1D4CEBCFD93D8E92
+:10624000008E733685E7D39DDD33F608C6073EAB77
+:106250003B9A6BD6CF675F3C5668877ECEEE3E5644
+:10626000A851FE6ED8628F577DFD9B423C2725F3D7
+:106270009EBBE9ECE47A7D838BC71DD2D2F546CC78
+:10628000E7EE4848A6793F966E7B245E3C05D51D17
+:10629000EDAB7B74DA475C3CCCB7DC8DF1941C83AE
+:1062A000F264972B81AC79B80F32CDE9C7387D6A9B
+:1062B0002E1B9A9384A1C62073030B395E6BA2E355
+:1062C000A0096DC6013463649C452BE6FAB1EB0E60
+:1062D0009DF2BA1235DF1333A19C3943A3F549C6A9
+:1062E0005DFE9C9042F0C9B84B373C6FD869DD58D1
+:1062F0009C136C2A82768BC7A7503BEFB4B789DE1C
+:106300009D3E5BC88EF3D1BA28FEF24F7543D3068B
+:10631000031E8D2CDB4D64837C05D832E5E77B358D
+:10632000164A027B640DF0EF60E0DF963A27D56FE6
+:10633000043BCE48A17B0CA2F77098F87E779D4174
+:10634000F57E529749ED1EADF3D1B37BDD67BC1DE1
+:1063500095E3E8C3BFD7735D1DBFEF4396FF7D3460
+:10636000D85540EFD4B14055C04BAA381F2EBF3F7F
+:1063700055F7C6A049830532009F7D2B8D2DAB2F8D
+:10638000016FAA239C8C478007BA58685226E6E121
+:10639000753D52928CE717EA274D1A0678C4FDE73F
+:1063A000EBC09570AD6D084D007EA8F4D5635C2EF2
+:1063B000AB5569C6F526AB757D11C6F9A11E9DEBDF
+:1063C00093FDBA5C5C3F251E7A52C91D8EC17FBE0B
+:1063D0006FCEF62586E39DFF1CEAE27A6AB068B7C5
+:1063E00046EC7B774D73D33D0989875CC42F597B7D
+:1063F000AFA1FD37772FFBBEB1FD241EFA13C5698F
+:10640000DD4AD301DC4764F3B8BD28F9A9B7765853
+:106410005FBF82FA9D7E8DE2B660A6D2FCCE4EEBC7
+:106420004FF8C6FAE67B3C3AF5F876D46817B753CE
+:1064300057D8E3EB6F8D71FB60745B17ED37E2BDEE
+:106440004A88EFACE34D0AFAD367159E2FD117F0B7
+:10645000B11BCA59139AE8DEA56DCEE0752E80EF08
+:106460008FC689BC15008E2BFFF7D9D84EE2432D7D
+:10647000D09DA84FB2F67EC0CFE1D8DA75CC4FFBE5
+:10648000CEAA17283EA8EAA539BC5CB702E3876903
+:10649000DED22DC8272CF4C2A4D7C0E7794C9C2BA0
+:1064A000C637A8F7D6B84439F47C4300F8648D9D0C
+:1064B00097BFB3EAB9063C77BCC65EBA10CF256376
+:1064C000B901FA5F93DC9C6983B2BBFED986A30352
+:1064D000B02CEB3F4B7C76A78B9FEF61EED22CC4A8
+:1064E0007B77D980F2705359E365E6E44F39BFAA50
+:1064F000437F3AD20FF8A57A2FBF87A61B6FADEB6B
+:10650000155C4F7E5277D4D7A0093991FA03D6E5AE
+:10651000AB3219F9157A5809E72A781FC7CA74737C
+:106520003EC9AD898A585FA0BD392E1873EE8C8E96
+:10653000B2E0FADAC0F33662E9FA46425143C218D1
+:106540003C2F1A5CADA21E7CC16E50DE7BBB467A2E
+:10655000BB43E6BDD7DAC97EAB14E750EDCB82ABC7
+:1065600087A15CDCABF9310E5091D35484F64BC556
+:106570002B39FE7A16CDA3AD486E4E1FE98EE6D1BB
+:10658000CAF2721137CA48AE4D4ECEC7FD92F5D948
+:10659000B89F51CD9AEEFB01C2FBA6CA90DF3F3DEA
+:1065A000303E09EF05AA8232C6A9AA5A8EE941A84F
+:1065B0005790C0EFA3A96E01BE71F37B6202798C84
+:1065C0006DD18C04D4F33F09D45E8D26EC13AEA3B9
+:1065D000935C40D767730306D2F9A5556F3538BF72
+:1065E0000565DD18C64660F99D06E4B38A1136CA12
+:1065F0008364A1775E0B0C16FBB1507EC89531D930
+:106600001C97CE12EB78CD26379DD78275F971E4B1
+:10661000EFEA8DB610EE6FD99C6D744EE725975C4E
+:10662000FFADE79B36285C1F86E6F138E7929B5268
+:10663000BE4DE79B56E41AA14BC45BCB2E26D03946
+:1066400026592E48F051FF655A88F679CA2E7AE904
+:10665000FCD3DF6E3CA7E53C55CFF1DC048F1CAFCB
+:10666000323A1ED1F5D0C85F3D3E18E8B66497DDDA
+:10667000E630F1DD925D62FFDC15C8C07ED2748E1B
+:106680006786FE1BF01ADD41C3CB210DD681755202
+:10669000BE431D0D932620DDA2DF9955FE03E83F82
+:1066A000AF4B90E50BF1EB27C4D4CF95FDFF85EA06
+:1066B000C7C29396102D3BA1BEF617477719E15B31
+:1066C0006F8BE92F4596F51593FA47F9EAA155DE48
+:1066D000C321E0AB75C94D45A8FFBBE6311FDE7392
+:1066E00085FCEA37E9DB875C5CCF965DCCB5D03BB7
+:1066F0008AF73C0B5D4ED7655AF62517CC5C42FBFA
+:10670000A70FA1B0603F2CC4CFC16CEAC7C2A6B826
+:10671000CDFF87E3AF85E3BA5EE0F887FF62387CA0
+:1067200096F1A2700CB6C0F7D7C2B1F5CEBC6FE738
+:106730004095C794903317D7851FF1BC35357992B2
+:10674000AF1EF74B7EA451DC7D08E3F928B91A3B54
+:10675000AA8D44F9690A60DC822DE3F60ABC5F6900
+:106760001F49EB10F90B83F63A66615E456E59607E
+:10677000213E59FF7CDA8F91FB984CC4F5E4FECBA7
+:10678000108315E1BD7C6F27CCA2752AB77466050E
+:10679000C6BF55CFE8045C0F1FB38543385EE85190
+:1067A0003E5E9A2DDCEC447BC93BD8C0F52ECDCBA8
+:1067B000F51F5B9D4FEBDF565BEED58B008E154AC8
+:1067C00051C21B88E7E45C8A63E37BBC0767AB5874
+:1067D000B7D464BF81EBD456B16E2D17FA5DBE4FAE
+:1067E0004C299D8576C4F2D545939DE3510F0556FE
+:1067F000F681F566D9EAA21599E371BDF1E53A6132
+:106800007D599650B4C20993D95AEFEB6B2447CB0C
+:1068100043FE02AB35E989A21568A734B81797A3E0
+:106820009D03DF0FA35FF86C8AD43BFC7BAED4538F
+:10683000A897408FA9F5DDE510EAA5DC6EBD5344AD
+:106840007A67FBD32A95CB603CB47B601E21BCBF2A
+:10685000AB6B8846FE910B604980B26B582EED6B96
+:10686000C1BC5902C6F587F1EF725F421F62A37D7A
+:1068700009AC8F787465F1FAFA347E9E59F7B8C97D
+:106880006F93FB1CAAD8574B1079248A318DCED92F
+:106890003AD78E5C8C7E9473B075FF588FC9375190
+:1068A00063F34FDC11B2BB1A12449CB90FCBA47B2B
+:1068B0000DC47BC6FC23F1997E774311DD77E76138
+:1068C00006E63B670623CC6C2FC9A703D6519F4928
+:1068D0006E1C6E168897EF704F22B787DD1735EE66
+:1068E000272A60DFE03AEA1176B8B08FECF21EA2F8
+:1068F000987557DA4B7671DFDD929B2666E0B921F9
+:10690000D51D70A29D73C01849FB292AF3DF5A6474
+:10691000B2771A2237513C5133020CED9CFDC2CEA6
+:10692000510D3F33DB398D75E080C35AB5AD308FE3
+:10693000EE9779CA15710E42FA3E66F3A3DE38343B
+:10694000B23CA4603C71292339DD56983E11F7030F
+:10695000B668A549F7A2BC1C87F17C9C6E7CFF79C8
+:10696000B982F1EF0BCED224D407EB9299C58F2ACE
+:106970004EE4FEC89309DCEE947E4223C013013836
+:10698000B48B57D37D3B43845DAACF9C44F12D4CFF
+:10699000D3C178A583D5860C77F43E3947A6CD922E
+:1069A0009FA85D2CA0F8DF930936CBFED1C3E23E51
+:1069B000405976B25A1EE7059E8EE7BFCD12703A57
+:1069C000C01EF2917D12B33FDFD33E227B45D2A79A
+:1069D000DB4E51F8B9CDDEECA39A8B368B9E8D9EA3
+:1069E00037D7492F9F13E7F9659E865BE8B3C6CC7E
+:1069F00060D3F539D1F3FB9AC8D7582BCEEDB34C01
+:106A0000ADCB7C4E3E11E331F0BD41E46D24C69C1C
+:106A1000BB77B99790BFE01AAA59CE69395990DA75
+:106A2000397CD6F75A66EC79FE50779E16E5156AE2
+:106A3000EC49850EEF737BB79FC8933A9BF87E2194
+:106A4000CA2FD8BB3F77D23E023FC729E359DFD4D4
+:106A50003EDE8F76D518F40BA78CC07EBF23D6A35D
+:106A60002C569AC537079B19E5F524F8DB19BF1397
+:106A70008CEC2D55EAB9D00B0DE847A599ED3B9369
+:106A8000BD3670CD0B0D0DDCEFA0F27756AD263D77
+:106A9000B8C225CB2BA80CEB5504FD1EB6C7E143AD
+:106AA0007E82F601941B76671ED9CB6A2EB8B4009D
+:106AB000F724BC9F10E3F97B1C5BD19E05BFF64E0B
+:106AC00097894FCF7A4E64B3FCB8FD852CFD657F66
+:106AD000B3FE60FC16CC0392DF2779374654DECE36
+:106AE00087ED58FFB6F743D0FF632F3BE8DE107900
+:106AF0000F722CBF162672BB01F58639DF529F3903
+:106B00003780CC29E5D3919960C9D396F2AA5D1C50
+:106B10004AF229DBED4FC8E1F77369018AAB6917C7
+:106B2000F349FE9F14746DAC332E334E4A2FE38C21
+:106B3000A47E7A1FA750E80926F6B334C37CCF4B56
+:106B40006FF21ABB7F17ABDFE453EAB7DDA2FF3B5E
+:106B500012ADF1E1F28DCD4790857E600BCE481CE1
+:106B6000837959EF797129AEB4450A50DE1EE8F9F0
+:106B7000BE1A27B7C0C5F727F2762C3A88EC3A3709
+:106B800031D884F6CC7D89226E9F09EB9A8AEB1668
+:106B9000CF2B5A87DF31FE1CF43D3119F5D4B412E6
+:106BA0008A3F6F4B2C7D1DDBAD9A5E48B10209F721
+:106BB0009A3A9E0F27F5A51BF105F51D5A2DE1CD3B
+:106BC000E10E44D0BE684CFCF564F4B1548DCB4169
+:106BD000E59ABD24074ECD4F7CE574DB7CB8BE3B07
+:106BE000C1BFC375AFDE6DA378D272BCA73707CF24
+:106BF000034C35505E177B7233D825F4A376315D94
+:106C0000E85FEBBD377FFB7152A97D8FFB750E8D61
+:106C10008F607F9A9F517E0B22E143935E95EB7AC2
+:106C20006CBBD8FE253E257E1D5A90F0AAA3DD1030
+:106C300007AECDDD7119AE0F33A4FE4C7E3B2F02A3
+:106C40006FAB94762FDA27A0173727A25E1CDEF5EC
+:106C50006F8A8FF4693AB76742F23E01CBFD453245
+:106C60002EAFBAB95D23E15FFCC6634EF33E512CF3
+:106C7000BCB1EBA53BDF9A47E1EC9F10739F6F3DE2
+:106C80001F472B25BEB14F0838514EEA8D9106DAC9
+:106C90002B0D9AEF7701CAFFB093DD0C76B8657CB7
+:106CA000F95C27EEEF3D2CECA8D8EF1E71DF71ECFC
+:106CB000FB8F05FED61DB89BF4706FF4C303CF485D
+:106CC0005F4F2E33F0FC8C5DC0EBBD4CBFBDF1D1EE
+:106CD0002307785C571BE70CA38B153B9E6A2F0D8F
+:106CE000E0792F7504237B571DC0C7075A1A181760
+:106CF000F68E4E61434DEBECAAC1D3F9FDCB69068C
+:106D00009DBF533DB6D27876A6C4536BA2CDB23F99
+:106D10009F29F966C8EF693FC9C4371FA17E89E57D
+:106D20009B56E4E1340E87999EAB06E766C4A34FF9
+:106D3000542F72BEBA1C5F144EE0FC9E01CF2D3062
+:106D40008F16719F4615E20AFC9DCABBDCCC80758C
+:106D5000ED2B4FD117085F61DB419EEFDE9246CEEF
+:106D60005FE584F8F2B2C8CDE9B2C8CDE3A84927FF
+:106D7000023FC57BC35BDA127C0A7C6A4989AFA7F4
+:106D80000BDC52CE44FE84D65E80F688AC5F38D3EE
+:106D90003A9ECFCDD7BF01B25DE8D614B4CBA66280
+:106DA0001780C7417E85E771B42686F17E7AB06A86
+:106DB000B5DB00AF3B84FFB703FCC269D06F7A023A
+:106DC0000BE2BCD3FA40399FDA0776B9A3FDBDC9FF
+:106DD00051C6260F2ADD8EFD4DCEC81AB13C87B7AD
+:106DE000C77E0E27B006E7C828DE6F7500CBA5E08A
+:106DF000F750DF45F9D1F7875176A15E7A7A7B812A
+:106E000082FB92B6403AAE231F1DFB01E5C12EC0A6
+:106E10007B8C9C78A5844A7E52E18952BAB7EC53A8
+:106E2000FC9885F71D950E738FC1FC30EB3DA46C6B
+:106E30003B3F3F23F1D5931FB8FE013843CE140BDF
+:106E40009C6C1CC2EDE4ED62F1DBFD147C2CE909C5
+:106E5000E8B9C623E88972DA22EEC5ECE61B71AF09
+:106E60004287B80F6A76A2B817CAE0FE95BCE7A4BD
+:106E7000450B24A27D3EBB3B3F2140E78F2A5D812D
+:106E8000A4F148B763DC7F3A5DC4EFA73B6D0F24E4
+:106E9000A1BC9E3EA62AF594DFC1F33E655EDD6986
+:106EA000BB6FCDD5F07DCE3FAB817AFA6CF50B3A56
+:106EB0005860D4BFA29FD4AAD23E64CEA3B3D4E17B
+:106EC000507F2E380CA88F6617BB4368C7B5FCBE31
+:106ED000F67D5CCFE63CEDF02D83715EDB38EA0B8E
+:106EE0002C9F5AEBF13928DE9AABE0FDF14BD6E747
+:106EF00018B40FB9948938F3C4926258839FC7A11C
+:106F0000E5FE8593EE9317DFAB1B27C1FCAE4E6BFE
+:106F1000B1212AFFB0B6BA11CFB3ADA82FCDC43876
+:106F2000C25AF7E4468C23A4A707DA6E80753DE2C7
+:106F3000BEB104CB2D4FC9FEA63462DCE017B660AB
+:106F40008E02DF4FBB679550FEF520D9FF92C60039
+:106F5000AC09B37F7CD51727305F7B5D6309DA0509
+:106F60004057615FAF21F8E64D90E526BD7830B41B
+:106F70004F649678AA3D1A97A0786D4BB77DBEA155
+:106F800004E3107326D6166BD07FE1BAA71AF3413B
+:106F9000C58E6D2A320250BE7EDDA6125CFF5A58A5
+:106FA000A002ED921BD63D5D8271F9D43ED6FE5310
+:106FB00055119767DB1AB1BFC29981110AB4FF97C7
+:106FC000752F35A21F9286F9B930DE05CF9F1A437F
+:106FD000FDA3FAF396E83D5AAB510EAA9CED47305B
+:106FE000549BBDB44BE779DB426FF4E7FCDC5D1EDC
+:106FF000DACEF3EB653993975B96C5D7438F7AB9B1
+:10700000BFD99210FFFBAB42EF4879493AC1023B2E
+:10701000E3C8CD16B7FBFF48EE5AFF6FE9B5E4CBE6
+:10702000E8B564A9D7043EF3AD7A1A8611FAFEEAF0
+:107030005CD40F0B30D9CA642F14B64DA775E47B0E
+:107040005E6E3F331F6F9F56CCF39DBA5E49E4F7E7
+:10705000A43ADBF2CCFBA2C7053E8A1F9EFA049D30
+:10706000776FB3333AA7B2ABE89279A69518DF35BC
+:10707000F91F955A84FCFA4A8CEF8EC2FEDEA47387
+:10708000A6D80F9E43C17D0C8CCFA62D8F4F7F6954
+:107090004F555E3458A84FCF7537DA7F2A0B8DBA1B
+:1070A000FCBCA2FD59E30F3DFBD3C57E50CCFAA832
+:1070B000C787F3CF924F01DF36137FCD13FC26F73E
+:1070C00095CFED19B6D5BC8F2FCF87817EFE29FED7
+:1070D0000E4608F43CDA99855AE066AC5FD89642D1
+:1070E000FB4C923F245F48BAB6A4D452DCAEEB49C5
+:1070F00085CEEBC5C265F3703A166EE4F73366CC05
+:107100000CAAE6FBE4A53C40FF2DA2FFD1E3487E9C
+:1071100036737900B9B917E517EFDBC179F8DB0BE6
+:10712000CCBF3B21E1AF405E4C233A72FCBFECA2E6
+:10713000FDFED875328AFFBE97A16736D153DA417A
+:1071400095BDAE975E9EBF7822E2F561FC08F91FFF
+:10715000F549F387747F5C4BABCA141F9F37EAADC8
+:10716000C26E7DFCF5E1891AD963D1F5C3477699E2
+:10717000D49F11A7335ABF6BCDD793719F3955DC7C
+:10718000CF9CAAE211EC281C233C5C8F8D0BC68F90
+:107190008716B83D9C0E621E4F2E9DC83E84F97F17
+:1071A0004FACF3E3DA43F4FB4976C4E398283EA4FA
+:1071B0003EBBD5D1FEA238F762E14759063BA7DABC
+:1071C00036C8F4DDCDF5AE1C0FE06DC0FB98D3E002
+:1071D0008957FF5FF0E4887D77CE9727F7646CA12D
+:1071E000DF6D18141881FA46F217AC2762BEB6FBA1
+:1071F000A7BB39FF4F8F4387E982CFE66DE4F36F7A
+:10720000F98FE29B910F5ADE4A495E66E2F77AA156
+:107210005764BF529E643BF97D86E8EF5E8F979E70
+:10722000F5027F0847BCFC0AD90EE74BFA7A25D74E
+:10723000D730EF10D209E61DC273F8173C4A0C5E36
+:10724000C5FA20F05DA5039E018F3BECA1BE98AF6F
+:1072500095A6F27C98CBC92FCC47FC8E8087F44E44
+:107260006CFF6B057F6C11F7E81EB6813CA39CB9DF
+:1072700039BCE7F66451BF75A2DEE5F5E195C9CFEB
+:107280001691AF02F0533E66D5ABFDB658E1AF178D
+:10729000F00797E339C2D427987F3923BC45105FA4
+:1072A000295EBE9EB4E841B2DFBA9E64E4B70E0127
+:1072B0003BC207E59A52F74825272AA779CD0AD17C
+:1072C000B17003ACD38837A7C4DB1B3BCDE36EF0B2
+:1072D000782CF710540AFA0F81F5FDA700EF10E89B
+:1072E000E745829BC375F2F1E6EB313ED7BDDE0B7D
+:1072F000BEE8096744EFC7E1A4BC0AB4777CA3A346
+:107300007062FF94E7E32E5D86FD56FF66773F735C
+:10731000BF2F76F73B7BA20BF5D87AD0ABA40E82B9
+:1073200087F01CC9DCBDC906DEF700FE820DFD42F8
+:1073300039EE5C4DFEEE4F7B21DE779ED73D0EE8A9
+:107340004F93FE3BE071F3FACE8303F11E6DA6F17D
+:10735000F529ADE9F48F701FA2B775F56FC50F4021
+:10736000479A77D72E98972F8ABF96E659CB5CA875
+:107370002F4F303FEA4B39AF2133DBBD987F53238A
+:10738000F428E0C5867C90FACF3EB6DC67D2CF8287
+:107390007E43199737E99F0CC50D1228BFE32910CA
+:1073A0007A8B519CE0E4ABFB7ECAEFEDE0F4AA9946
+:1073B000C9E92BE5F52B4F30C58BF6E95D0F4DE4A0
+:1073C00097E146E89EE6CA0D7C1CA8D7CC486EDB48
+:1073D000B26762FE25F2D3989E744B2D6D76517B79
+:1073E000C1FF675F191E463E4CBBBDAB18DF033FB4
+:1073F000103C2DCD9E30FACB642F63FB7D0A5FBF1E
+:107400005890F03277A6E137F38984AF9BEE0CE811
+:107410003E3CFA7EC84CDE6F4D2BF4CBFB21F9A924
+:10742000BC9FF1FBA9057D80D5428E9151BD03E53E
+:107430008823258A47893FD9BEFA7EFEDB3D182F77
+:10744000403FAF86B553DCB4522DED8FFE1ACB70A2
+:10745000D0395BF07F49FF1C7631CD05ED5F872782
+:10746000AEEF93D545741E6AF22085E41C2449C60C
+:10747000CBE8F7C66EBD2191E7BD7DF5DDC1389F34
+:10748000B444CE77D08F53F4E3243B55E8C35F6711
+:10749000833E34F9A5871585FA39FCAD6BB62E57B6
+:1074A000A2F3C4FED06E38AC4CEB4FF6AC886B0048
+:1074B000DE2CF97851FE0D09B8DAB3F1BBD94F4291
+:1074C000BFA6DBCF62490FDF087ED5D829CD11BC1E
+:1074D00052BB3E947CE3F760DCC9E067B960FEFD17
+:1074E000918FD12FC809A95E846B8842F7471F4945
+:1074F00008E6F37B88F938E922EE952EF2B4D19EA6
+:10750000C7E7362F5F2F8627F1F5E5A1245E4EF7FA
+:10751000C68F933D21BED7887BBB5717C5CF071CAD
+:10752000E7B5C6396F15FB3EE06F8DF3A6F1FBE0C2
+:10753000799E32DF2702BB96F05BFCF04CDAF7BC99
+:10754000D0764712BF9F82CBFFC74AE0DFEE52F0F2
+:10755000594AF703867EAB52BEFF4746C08BF9619E
+:107560005509F1F3CFEF15705489F99FAEE3F74950
+:10757000CCC3FD48D017B70AFF6C41D36D2548EF47
+:1075800005E0BFE37EA4CC7B90F42DDBA45AF62368
+:10759000E6E17E649FBFC67FF0F7E23F8CB6F80F4E
+:1075A00072DC583FE2645DA665DF6476D320718F9C
+:1075B00007AF3F87F909EE392BFB59F64FD9CAB40B
+:1075C0002BBBE714FC86505CF874D2AFF2FDC93ACD
+:1075D000270B99E1F86430E58D8CF3061FF05AE033
+:1075E000486421331C6C02FF5D2F178F5B03DD4362
+:1075F000667B3A16AE55DEBFD64FCBED05CF79FF91
+:10760000257E5AE104AECFF05222CC81193BC96AE3
+:10761000376FF6F27572B337D16237CF9D69ADB768
+:1076200045D4DB22EA5DCEFF37DBCBCA20D41BBCBE
+:107630003FF97B3C3967DEA2BCD3F7BCDC0E389E39
+:1076400014D881F2B856E4E96FF9CBA1CC39685F60
+:10765000FCAB9DF2048A362F598E79D4EE66C5A014
+:10766000734AAD563EFAC7A5CD03E7023E5E1274DB
+:10767000AAF4F37954FA23FA6037E675F3F1FB378D
+:107680001F5034939EE85FC6EBEDF3DA2D71F703DC
+:107690005E7E8FC42FBD323E183E70532AD60F68CF
+:1076A000B8AEF4C5DFC10178FAD6323A07D57734DF
+:1076B000B7C7FE71F416057F974BCE73A56D5ABE02
+:1076C00001ED56A627FA514F671BC1D7719E95EF62
+:1076D000452218BE19FB5E9B86FE92DF081C457E84
+:1076E00095F3F2A9465F5C6F12DFE3F03575C721B1
+:1076F000B89E666C8DF05FB6723B56654719B773DE
+:1077000069BF367DD9505A2FE47CD25384BE4D6771
+:10771000C1DD646FB395B4DE39F9FA99BE8CFF8E82
+:107720009EA467347E326C24C64F06AD8D68B3A12B
+:10773000DDAB9B6C71EFDD3825F00EF3F800E71739
+:107740004B9F5ED71D51CFDE4B5C4AF27BE294F833
+:10775000FE1E638FD0F7A2CDA9F7905C36E8744F78
+:10776000A2C4BFDF28FD23C2D3B7798B82B83929E1
+:10777000F2194EAEFEA982F6D6771732438DC34F6B
+:10778000DDF2BA74F7C0B9267D03FD133DB6C4E43B
+:10779000A74BFFC49DC4F5F83CA3544D4AA37C619C
+:1077A0008AE32DDCCE7F8FA3577C5C21BE9432EE22
+:1077B000C754CEE0BF475AB459237A5734F0DF2379
+:1077C000ACDCB98BCEE3B187981FE5BDB2799732B7
+:1077D00017C6ADD8B94B9967C25FBFCA30E5755FB0
+:1077E000E59171EA08DD3B16CBD718DFC7F5FD88B8
+:1077F0008BCB7B47913B8471EB0E7BB012EB7564B6
+:1078000025FA717F54E2FBF55D37D2FD079EDD8ED0
+:10781000083E57DAB6663AA1DECAAB753FF291DF91
+:10782000080E45BCA468A52DD83E39D5E3C7B8B726
+:10783000CFC146D23A778578181BC30F631FE27217
+:10784000724F9257DA59946F3531C923ED0ED24FEA
+:1078500047EC7C1EBB1987779B373016E16147F9EF
+:10786000EF29F4AD8C2898A7123B6E949F02DF4A53
+:10787000FA06FC0DF6928E7ABD42E899A2CDDB9510
+:107880000F4D704F456304F973E71605E32AF09D29
+:10789000F40CD467980FD577278F2755C0F7792632
+:1078A000BD22E71147BFDC86F0B9DF6B7B8DEB971C
+:1078B000088F230B7863E9797F12B7DB4A6059A5FB
+:1078C000F77A6828FA9B477213A83F29EFB1F2793B
+:1078D000BFE0F3BE9BB62B3637C5DBC9FE92F0C9BD
+:1078E0007AC79326CE491A837868233C546DD268B0
+:1078F0003E93F5D2C18B4CF2B048F477F0AEF7E985
+:107900005EA00D3F3F46FC58D5A470BBBFE9987EF2
+:1079100007AE2BA1E754DC1FB9992FE5EC71715F1D
+:10792000D6CD2D5CFF56B5ECD2F07E49C9A739679C
+:107930000ED23D5B55CD0E86FBA5C07FDF43FCC458
+:10794000F2A9C48FD4AFBDD113F4103FA710D24514
+:107950009C3A9833DD13D5CFDBBC627FD4CDDF6F8B
+:1079600048E2E528FF04572559F4AB8BE422E7CC25
+:10797000C883980F5AE557E85C656AB1F87D321301
+:107980005CE6F331B1FA11E3E13C7ED29E3DDD7459
+:107990003EAE5BCF8BF64F20BDF9FB087FCF7271F7
+:1079A000BD96F0C7D2EF90B0C7E3F0593829CE3A70
+:1079B00026D7F59CA7776B788F92E49F9B91EE2654
+:1079C000FEF95912BF8FF767491AF5FF7811DFA743
+:1079D0007ADCCED7AFC7EB9D94BFF9FADD3C9FCCE4
+:1079E000738F1EC1E761DBEC4AFC7EB82F8763A56D
+:1079F0006D199DF703B96C4E22FEF132AE1FB93EF0
+:107A0000DCF012D767952137DD775A19BC7D2EE55A
+:107A1000D9A6BAFC743F68F035FD0E4F4FBEF2EDAB
+:107A20003E40BF8B7C7333973F4907D0A7C45F525A
+:107A30001E245EA3F8E47897F224E9B14DEE0B0022
+:107A4000BF70FB88FB23F94CA5FD9F3267E0089EC1
+:107A5000CB2C13FBA5F9E2775FE47EE96C4197023A
+:107A60005BE9AF719E3DF64BAFD0AEAE58FAAB615D
+:107A7000180F29CF3C4A4F29B7E0F759E4FB7D4165
+:107A8000F7C3E2F9B1E09B8AD1CD2497151FD592B7
+:107A90003CBBA770BDE67ECFAA8F195B27E6BB96DD
+:107AA000DA4F4E6C2EC1FDC6C93F560CF4877B835E
+:107AB00073019E5343FF68D321EF2CC4AFF87D2997
+:107AC000799EE70BA1273A76A8E2F7366BF54BD9FA
+:107AD000DF97EB8F458E2B74EF89F0A93A76168FDE
+:107AE000FF18FDBA1D49F4FB279FEDBCEDFB1FA756
+:107AF000E2EF8BDCE0473B21757929F14F579ACBB8
+:107B0000BF95C73DA7605CA7BEF99017CFFFFC6F7C
+:107B10005968C8A800800000000000001F8B080002
+:107B200000000000000BD57D097854D5D9F0B97359
+:107B3000670B994966267BC832091050499884849E
+:107B40007D9924844516270805641BF600D958DA68
+:107B500062A57F068388886D68AD225ABF01C16225
+:107B6000B53560A441020EB208553F470A165BB412
+:107B70002322B284648AADA55FF93EFEF3BEE79C82
+:107B8000CCDC9B09A85FDBE7FFC3E3733CF7DC7B3E
+:107B900096F7BCFBFB9E33975FEE5760B01362B65F
+:107BA00068084920E4CA6BF21AAF8990877FF1EA2E
+:107BB00088A185842CF74A71064248EBEEFFF89FB6
+:107BC000D478422A76D658245AAF7FF94D7D80BEAC
+:107BD000A7F16E67CF77C75AE0BDCB2F6C1941FA7A
+:107BE000D2F6C67A6CBFF2C276ACBFF58B570FFDEA
+:107BF000177DAFD215E380F7AEBC76580FCF2BDDE3
+:107C00005A67232D89FBA87EAA99969E976492486D
+:107C1000C878C2FE9EDA73586FCFA5F5463A2AFDA2
+:107C20009E4CD77B7B65D1EF1AF7681798E00D2F34
+:107C3000214574DC5FCC1DEC867A335D444AE8F95B
+:107C4000463DF1186DB4EC4648142DAF169B3C52DE
+:107C50002C5D5789692394577F15351DD65BAD0F71
+:107C6000E458613E7D8913EADD011E4530CE0A5D90
+:107C7000B509BFC77E3ED41102652EF1908B7DE819
+:107C8000FA09D979AB3F8CF76B841F7D6F50540193
+:107C900021D3667D2AC17CA2FBD6EA96E33C5F66CF
+:107CA000ED74D5E1ED0356D3F1E8B8B7E06F64A801
+:107CB0002CB298F07D0A102C539BCAD3ECB0FE78FE
+:107CC0008303D62FD6975AE1AE37D3E7F7AE763B8C
+:107CD00064BA8F6F5C3A35BA3BADFFA28FD45F8632
+:107CE000D76569AE8BF65FED31E138556B4AC867F1
+:107CF00074BE636017E9F78916123F84AEA74C4B38
+:107D0000E24D5012725A5700FDEFC276BB8138091E
+:107D1000C503FB9BD376ADA39F3CA573A714413F3E
+:107D20001BFD7A3B943BD9FCE9F7165301F6671922
+:107D300002DF1BC94AF8AE7DDD84F84D12F6EBD7A1
+:107D4000D942F3262498313597F55708701AEB99E4
+:107D50000EEF13BB1ED777055EC17DF4E4CDCE8553
+:107D6000F209365F0D7103BE24EA69897075679563
+:107D700053BC596429765B8A42656237D6AE86EB7E
+:107D80004E68A7F0BC6071624976C71132B8F37BC8
+:107D9000A214F07F6B5A9B3E40C77DF2C0A788B704
+:107DA000D580B730BEFB821ED621F076217C42F70B
+:107DB000E1A9FD9F22DE2E6C96103ED5CDC5FA05B9
+:107DC000B4BC5AE7249F69699DE3DF53526031E0F8
+:107DD000B5677F94651785539BC0CF864F2FCAF434
+:107DE0007976738A5D82E7FB199E1ED3683C00A7F3
+:107DF000633BEED95E2F85CF731DC247AA2048276B
+:107E0000D5B5C46BA0EDC53F5F7D6A1CAD5755105D
+:107E100007D079B50A8FB29E3FBF01F0C55A490A13
+:107E2000A3ECB0CE4F4677A7FD57579222A0D3D4EC
+:107E300051CEFD5027CD12E905F50AD74218FFDED5
+:107E4000F8A50E99F66F1DE56A82F1EE8D1FEE9092
+:107E5000697F4FA5376E30D2764F19B1EC0238E802
+:107E60001A4AB4B4FE5499DD422149E1B63319DA15
+:107E7000491FBD6317E0B17B6125F4579D3CD301D9
+:107E800078D289FEF7AFEB03F3ADB6777344D1F741
+:107E9000C7374B8857C4632230FF6A0A5FA88FF741
+:107EA0000EF5C27CAE71F80938B6E9FC73607E6DE0
+:107EB000AF1B8887B68F1FC5F0D53AAA11F9C7DB6B
+:107EC000FBC79C90F2427869DE67F041DDA6B548B9
+:107ED0000EE04BE47E03CC67019F4F838ECC75D1BF
+:107EE000EFAC63593F3D364BC82F7E0DF49400A58F
+:107EF00086977A8EE70DACB478F25C141FAEF1FD74
+:107F00004734A1FD2EE7F852B5D087F454F90AEBB7
+:107F10002FDEE0CC5F1586BFF1A504E978771499D0
+:107F20005B4E9FEFB6B2528DAFA7395D673DBF1272
+:107F3000F77D01DD77D8D7D4CDF439C08DE205C007
+:107F40008DEE23E2C1BDF14B70DF166C961EC07D35
+:107F5000F40C20504F8863EB54F77F96F3C5DD5146
+:107F6000AE4289F6174C303B7648301FA7260AEA06
+:107F7000F956C70E02DFBB76C2780949518EFA3036
+:107F80007E4588AB5043C7B9946866FBED7D5F3B87
+:107F90003917E8D18EED0932F111E43F24DB951B4E
+:107FA000FAAEAC07EBAF8CF737A1C19347B2193CDF
+:107FB000102E1C1EDE75DDA687F3D34F383CBC7730
+:107FC00091E9C0378EE989C908FD5BE838B4BFC4C0
+:107FD0001D435FD884F3ABC77D7BDB62C1B22CCE7F
+:107FE00055580B2CB8876B35C045AC530D8F451CCD
+:107FF0001E6F4D9B93AF013C9E627200DD3D794048
+:108000009A8F78ED3152A204BC677448E87E005D17
+:1080100010B716F7A3BAD6E58D8CF7E54867D5F10A
+:10802000518E2809F1DE89F2CF63F232BC67F22F5C
+:108030007A2C9357C027CB733BF303C16740BE0133
+:108040003E0BBAA81E11C881FDFDBA7CA54DC7E83C
+:10805000BC8DC201E848D08DF90D462F9BD6D98B37
+:10806000A17D13A5FBF0FD3EAEF720FD1ECFEEE691
+:10807000807E619E2E7388BF67585C362B8577B5EE
+:10808000C6B7419B15E2C7D56F3C96E38E807F82D1
+:108090001F1BB58CCF19BDD15ED62F1BCF48C16D2C
+:1080A0002EC0D203F2287A0D838FBA9F5E56215FCD
+:1080B0008D960B548E4FA29B14DB8390B11A772FB1
+:1080C0002BEDA7CA18384E779664AC09EA611E8971
+:1080D00020BB807E76447B816F252612F7DE08FD6B
+:1080E0002659191F10FBD26063749418C3DE2FB693
+:1080F00032FE50686578792F2FC5FC05FEDB35EE22
+:108100004F89DCB51C13DFD17961BB980FFD7E234D
+:1081100061F217E79BF870CE8E4D61FB11A2A3BBF5
+:108120000A609F7A6CF669E79B42E30879AADE7FD2
+:10813000983FD00FACA7BC6FD7EF351C66F4A8C62C
+:10814000C772CE1763AD84BDA7F3FD15E96A8599A3
+:10815000EC80F96D25CE383AAF9A43BD193D38838E
+:1081600039D0FF119BFB15D88F81A3389ED3E7939D
+:10817000E9F3E55AE231D03D59BE5BE70D1819CD60
+:10818000DCA2FF95D858FFED66A347A6787EC6E629
+:1081900076037E794A88C30772E907947F00FD1150
+:1081A0005F11F0971A1288013857CBFE1C42F77FF7
+:1081B000B0C9BD08C63BAFF167C073420288AFE7E4
+:1081C000A262F208EDAF49EF4BFF3ECCFBA44C7628
+:1081D000D07EAE13E77858C775BFC6E6A1EBF8B8F6
+:1081E000F977BF3A40BF9A7DE0DAEC87004A9BA25C
+:1081F000E73C4BCB59468D51DB3F048F73E6C8FCFF
+:10820000F5871C7F12EA99DE155C67F0027CD4EFDB
+:108210004DB0B1FDAFB9914A3C71E1CF191FADD15D
+:1082200006F5A042D6DCC8201E3AEEC71A52D11875
+:1082300041CF0C5819FF6AA2A81FA9FD738E67BB16
+:108240007524672BCC673BE583003FAD1DF945C521
+:108250004FB31C9B68B5293B781CF488E0CF24E41D
+:10826000FFE7748CEFD0BF29C60121F909EA09E8BC
+:108270008715168F4F43F946C56AB34FCEC3E7DA69
+:1082800061B0771E8B16F8E07C2E1717D4BEFD77F1
+:108290002986B66B897118FDEE0BD3C218100B8BB3
+:1082A000BFBB2A1194EFA4590D489F848CB2803E25
+:1082B0002E3927C8B7A26FA7CF69516F477CA1FBA2
+:1082C000EBB2B95E80FD9E15CBE03D6B55B4D71384
+:1082D000C6FFA671F8A8F16C37E0289DEF2712932E
+:1082E0002BEA715EB595DC07789714E3FA35F6BF93
+:1082F000EA9A829FB54981179F057C5C6176EC62A2
+:10830000DD66B8C2E8E51D31EE0D0DEE5F7BBE3FC8
+:10831000674D16E07D30E3F714CECB5B0C168F1D56
+:10832000DAF58AFD3F5F47195F4EA83EFF52CFD175
+:10833000C404F0776C007C58B0319A78FA84D60186
+:108340000A37E077F50D82FDCC6F79FB2CF0F36AEC
+:108350006D00F167BED184FB537D438BF3201B7509
+:10836000AD01F13D95BFFD629C2791BE1E1D66BD0E
+:10837000780F7D98449FE3FADDEFC3BA9F8E8E217C
+:108380004E462FDEDE74FED78DF6581B85578D9E28
+:10839000E2473FECC6650CD3AF489A59B9FF2D2789
+:1083A000FF0EF3596874EB41DE2F9A5EAB07BA9C5F
+:1083B00015EB2BB2F40DDFF761F2AD7BBEFEBE37DD
+:1083C000713EF4B19ED245043AFC9CC37F02E02486
+:1083D0005DDFC7A98C7E3ECE20157BA1BC9B96F4A9
+:1083E000BB8FB379BD80D5D5FD44D9183D7F9CC7DF
+:1083F000E4956725931FEAF7FEC1C773D99C5F0216
+:108400003CC573A78D3D7FD5E6FC0A9E537EF85F81
+:108410001C5F7D56DADFAC370D88AF647D3007F620
+:10842000B1635D397CBE8991E7956163FC98F62B59
+:10843000D98AF03D27EAED87A2BC60879009943F76
+:10844000033F5E994E801FD371A36CAC5F9F15DF15
+:1084500033E03AC846CAA729DEB617D9715F361588
+:1084600053FC043E71D060013E21F049E0911A7F37
+:10847000126D42FE31397C1FC86119E570A28DC9A9
+:10848000613DD039ED51CFF4C19EB8DF8867F2D796
+:10849000DFEF3D46B68F94DEED3694FBBEDC707A9E
+:1084A0001370167CF2E36E4ABCD8CDF9601F0EB78C
+:1084B0000E38DBD87BF13D98DC13F6C120BEAE57F9
+:1084C000383F17A5906303C72AF59257B85EF08A24
+:1084D0003546EC4B21AC5FC8BF4EFBFD1CDB6FFA91
+:1084E000DE6058CF2C43704E1C955FDFA17A91BEA1
+:1084F00000BF6B82EF3AF9294631B95BB3D24C40E9
+:108500002F28B55918FC0B8319D01FE913443E34AA
+:108510009F507E23DD79FFC02790426964690C93E8
+:108520003B924C07049AE943ECD01F85F7245B513A
+:1085300008DEEAF1CE4113D503A7DB242DEE573E2A
+:10854000C987FD9AF3C197E6D9B4CB6B16A347430D
+:10855000E5C87735EE59D04FEB832751EF3FA7F7AA
+:10856000E5349822B4EB7DCF3F2D85DAE7BE247B3E
+:10857000F494CF34F95B7F368DE2E57CBFEC80214B
+:10858000E7AFFDEB7B03419FF6EB1C60D7527D62AA
+:10859000B316E65DCBF4CF731AE5FE5FFD1EDB5F1D
+:1085A000517F90E30BD5B3B46440885F093D6129E6
+:1085B000F1F5027D620171EAA13CBF62C90442E1AA
+:1085C000B7C8B41AF9D8E595E3507F5E4C3CD8BEE5
+:1085D00060A3EE7CB87C59D4A0AC2FD9AAAC2FF5FF
+:1085E0002AEB42FF4A288DAC57BCC8F9D0552A2E39
+:1085F0006EA7576CE1785BFAE884A791FEFD3A62BA
+:10860000A0EFAD3E589C4422F42BCA9A1BD9C41B40
+:10861000268742FA470EF1F687FE6EA23FF079AE4A
+:108620009F407F60EFAE8E7226815D72B524F2BCF2
+:10863000B7F179D7DCE8A6E8FFF94E7A4E0C8E53F5
+:1086400073C38865E77998F0FBAB8B238FB3BB438B
+:108650009FB228E469E8FB7826FFB83D2FF0A1E639
+:1086600046323E1775A16787BE4BC3FEA860B35C58
+:108670008C0EF1235D37360F81FF9F49C49882FE2F
+:10868000B12DDC2E71E4819EFB19E851407F63EC33
+:108690008702748A0B1E1A9CA3CD0ED1877A1D14F3
+:1086A0008FAE04C2E4FB219B391EE5B28338605CC7
+:1086B00081DF731E2C8B75D3F9FE696D6992BB6FD8
+:1086C00038DFF4E0F8D57AA1BF9914F298A8E4F560
+:1086D00082E693A89F2D34BA7280C97C7EF041C493
+:1086E000EFC5C4950878DD7EB07786FB7F21A7C5EE
+:1086F0007CEEF7CCD3317D9C122DA5B7C97C3EF71B
+:10870000B730FD506374EA701C27B15B12D1E46688
+:10871000F3A5CC524BEBC33BE60FCE434286F1F9B7
+:108720004BF03D85EF705E92F9EE6498B701C6A5F7
+:10873000E345116F3294F5831D7628474A2E2D9B11
+:1087400007DBE7D1A4360DDED71803325B279D4146
+:10875000227CDF012FAC9B797DFD94EB7316C173F6
+:108760009319F9869ECFE316F03F23F21323ACDB77
+:1087700060F25D86759979E92961FAB6279B38EA36
+:10878000E96BDD482381714DA66B1E58AC855824DA
+:10879000A84759AEFBC0EEB866317934FD902FCAB8
+:1087A00071147EADD2BB8B615F281F667EA8AEDAE6
+:1087B000B53EB477045FB3F1F9D573BE9642181C89
+:1087C000E289EBB093F2859F98174F2031208EDD20
+:1087D00038FE3331634FC07C01F028AFC76ACF87C2
+:1087E000CB8B049756C1B792A62BEB296E65DD485B
+:1087F000CE59007F259F2BF9561CDA717DC02FA31F
+:10880000E3FC624A37362F813FD9711A853EE1E297
+:10881000767DB54D4FD01F986834927EA85F64C7AF
+:1088200031FDE213BAD3D4FE0B221FCE1FE9ECF5C3
+:10883000330AE70D1FC88E87E93E6D30DBD76941EB
+:108840006F9B21313D5DDBE8033FCFF63956C726EC
+:10885000688F72FEF8BFA1FD039980DE5403FE7598
+:10886000A4774B317CB73DC382EFC59706D12F1A51
+:108870007C8CA05ED4094F6FD2F95378BF00750A83
+:10888000DF9A8596E5AFD0F7535CD10E29AC7D27F2
+:10889000B4D3794A1C2FE0F9C80160C7B2BF1E2DBE
+:1088A000F97E27F8299C32CAB59A96FC23263A8F7E
+:1088B0001EEE7C07A06DCF161E47893778591C81A4
+:1088C000522D9DC754239B474D4BF17D45B4BDA709
+:1088D000BF3F817842F409FBCC4A68D250FB19BEF5
+:1088E0002B8946FFD569EE47229C1F0C54D1DBD063
+:1088F00010FE637BBEA853F1EF1CC0DC13588F67DA
+:1089000074E020E28FD1E71012FA83EF4B43FD2190
+:108910003F1A156A0ED11B5D5A81D1515F49DF3B69
+:10892000563E06F1B006EC27BA1F03B5BEC340DFC2
+:10893000437999CF4B32BF01E1B9699D5306B8170E
+:1089400011B7BC85D60719FD71400FC38C8175091D
+:10895000B4BFC1D3E72543FD20285945A86779C096
+:108960003F6F3569BCEB7013F31D4037D3A6333F1F
+:10897000EBD4E9462FF8EDA76A098B6F69DD59DF63
+:10898000A1EDDF99C5FCBB509F15E63F11F18CD3DB
+:10899000D41ED913C19E3C18C7E493F8BE66BD5ED1
+:1089A0001137DA1F67C2F6FF881BBD360EF1DF9D57
+:1089B00005F4F7701CD7ABFA903EC057C2E87E03AF
+:1089C000BCD75AFC4E577C41D9CEF9C254E74F75FB
+:1089D000A88F73FE20F8B00BE8907EE7979C3A8052
+:1089E000E747250CFEA78A97227F9846DCF89C2251
+:1089F00088CE15EE371A1BA6C7D071A6BA947ACDC9
+:108A0000B4E96A3D87E1AB1877865BD93E59E8A99E
+:108A100063957AEAACEFDFB4A2FC4D7AB1EA562650
+:108A2000C649D0DEAFA1FBC4E2245A163759AFF7CE
+:108A300082BE53D3BCE25802D0D15AC2E9688FB487
+:108A400010E3387BA44561FA43F74AAF047CBF3793
+:108A50005D931FF73588F1A1D33AEF61889B9C5E47
+:108A60004A574CE77944CFE28F47A38807FCCF02EF
+:108A70003FCD9399FF94A231C641D22CD10ED0CBD9
+:108A8000376A0AD0DFBA31C6EC08F76F6E5AE72EA4
+:108A90000BF7B3DA0DA4C0C2F126921D7B8CF3C391
+:108AA000A724E6EFF6CC30A2DD96D0C3A5882F240C
+:108AB000C8E42CF80DD7C6D951DE3EC5FD1A109F6B
+:108AC000EB4F4BAF4405627CD8F732598F7E461589
+:108AD000FF498873A07F3F213617FDF4D35BF277FF
+:108AE00022BF3145397A49A1FEA7BBB76B1781FE7A
+:108AF000D4B25DBBD014C2BBB3025FA34934E06BF8
+:108B000087DF6EAF01FD76DFD5B8CE015E56EA7D18
+:108B1000794489CFF8BC2B39B684E38BAEC4356376
+:108B2000119D4FFB7B7AE6C75A4B905E5FDB6F452A
+:108B3000BFA376324179B2BE98203EB46F97504FB2
+:108B4000FEC25A81FAFB7AA901E5449B6D34EEDF3F
+:108B500032D351B44F2B9ED39D0FD7BB96ED54D635
+:108B600097133FDAC795AF74C267E45F823F563709
+:108B700029BF233D95FC319FF3FD0297E3FE329818
+:108B8000FA74470F661F139F81AEA3E85D3DF7F7A8
+:108B9000CE627293BC2881BED56EBE24333A67FC88
+:108BA000B888F7A79643455C9F1A41F916D89142B9
+:108BB0003FA2EF63FDA8A6454ED684E655C8BF1375
+:108BC0007A99E0DB625F8A07812D4C48463CD76F7B
+:108BD000B24936EC2BED1FE9818EEBD1DBB07F0F74
+:108BE000D85F43F97874DF3D20673D1AA317F0681A
+:108BF00083548B7CDA4838BF96DCF5F0F16F3C1E6D
+:108C0000E4DB8349EDFD13B2805FFBA3011E141F5B
+:108C1000B2E3C3F0A49EF832F6480A7CC1F656EBE4
+:108C20003B11F145C817DF474CBF184F570CFD9457
+:108C300041E08696472566CF8D313DA985EFDFD18E
+:108C40008C437C184BBC5A985F9945B9CF63929579
+:108C5000F571F64E7820C3B84E0ECFF17D94ED4EEF
+:108C6000C1D78892AF65919BB8CFE4B1E3DF05FB34
+:108C70003E7A0DE9037A07D51091DED4FC6054BC2E
+:108C800049A11F85C53D46C527748E7BB4733FEE51
+:108C9000101258FC8AD4195FDA8EAD9193C3F04A52
+:108CA000E0F11B3C4F427A93C7570B995F2F24E7A3
+:108CB00019BE0CE0B521806FF4FD45024F32492604
+:108CC000E0C9F0E6289F4CE19ACFFB1902785310D7
+:108CD00092E73E8DC9AECF06FC706C94E5CE7A7BF0
+:108CE000A2CD8E78D25F23E4BB238EA07C6FACD75D
+:108CF000C2FCF70FECEE3629F06229E28544F1025E
+:108D0000E9AA935C54B6ABF046ECDF09AE2F8F2195
+:108D10009E9E301E656347415FF66531BC29234E38
+:108D2000C493B7B3C7F1F8B35B8BFD10A53C2C35EA
+:108D30002AF1408D5774444DF8B86A3CEB0A6F3203
+:108D4000016F843C8CBB33DE3CDE35DE3C7E3BBCBD
+:108D500051E38BE0277BA22CA5A097D65448C88767
+:108D6000FBBFD7B31EEABDABB2308F658FD5817A1A
+:108D70006B4D2D6B2FF43B65C873E9B19AB767B99A
+:108D80004AA15EB386C51B8A4EB33C989E6B597B45
+:108D9000FEC3B547CC20DF3DECFB372E6F906368F8
+:108DA000BB7703FFBEB8A114EA351BD9F75F40BCFF
+:108DB00088EEEF80B3DE7A787ED7E62C07333F99D2
+:108DC0003E3B92E3E91E69EF11FCAE817DB7E4B84A
+:108DD000B11B413D98E9AD23F83A473EC7D619FF8C
+:108DE000D9BD63ED147F17053DA8375DD4540E40FF
+:108DF0007ED3859D592C35A44149F106F98CD34881
+:108E0000F13A9BC51377D021DE8E677AA088C341E3
+:108E10005E40781EC0DBF14CDE8BF7126D84C58D91
+:108E2000B799D1AF2BE284BEA7890474066BE4F234
+:108E30003F62DC704C8F5A8C178EC914F1C2807659
+:108E40003E1D37FFD697A323F951FE938F7B89E709
+:108E50003988E715DE2C0DE0C51E4092540052F50E
+:108E60006F416FDA037E5426343C6410EC2BAB9FC9
+:108E70008B5FB6692335D297686AB51E103219D454
+:108E8000FEA25D4FF2135F6C4CE7F98FD1121FC841
+:108E900027A265F35F5C4FE5A014E24B5305DB1995
+:108EA000D60BE9740ADFA7CBF15CDFE84FFA03BF0A
+:108EB00099CAF7ED3BC65A1D93970D3A15FD5F43CE
+:108EC000FA7FA64BBD59D9AEE20F157CDCC55C5FBD
+:108ED0005E4A82A8175C94BC585E7A86E9CBCB4D7B
+:108EE000A751AF68DFC6F4C44A1240BD43EDF75B3B
+:108EF000BE5B59AF6A54D66B9A95F5F65C0F8ED36C
+:108F0000FE4CD500F0BF556C7D0FFDBB15824F7830
+:108F1000957C822A488C4F3C7D37FA6D3446CA27AF
+:108F20000A015CDD306FA43F71C6013F00217B8BDD
+:108F3000D61F834F52685DE38A49403FD6D8B80BAD
+:108F4000627C19E3B2EF39EDA17DE9B00B557C22CB
+:108F50005FF8637ADAD05F25F8463E617242AD175A
+:108F6000F54950DA3942AFC807BD82E2855F63F246
+:108F70006A34E17A8417E98FDA8BE3A3B201655C86
+:108F800032D4FBCF2834F27D27AA7DED9B707B7B0A
+:108F900049D9AEDA7761AF0CE0FB3E83B8BBC33E84
+:108FA0004C21AE6320174E7D54A1B0933EFAC368A6
+:108FB000E147417BE99BDB494EF9DBD8491DFB1DAD
+:108FC00045F5465A964E1ED7EB6710DF6E8AC2BC37
+:108FD000CD1A89ED6FE28CD319E17EC3537524411C
+:108FE0001B46EFF5E30C4688EFD5EB981D3179FC75
+:108FF000C703E687F18B178CC52E80D706C9FFBD46
+:109000003F825D7152269817D39280FB7DBD813ED1
+:10901000A77876FDB97B1C1EFAF8AA8EC50BBF9007
+:109020006A17432A9398C7E235BF8DD252F9752546
+:10903000FA10C683CFE8DDB301EF96BDB30FFD9103
+:1090400095A077F708F5DBB5DFD1837689FE2D266D
+:109050000783523707E625104F4E789C685622E367
+:10906000AF676CAEA5307F21E784DFFFDC8A31B1CA
+:10907000200AFE429CB1109F94284CBADB3A8F071D
+:10908000F900EBC3FCCCE7A294F105517E2F81F9E6
+:10909000BFF7012DD1F1D2ACCEEFC3FA2E717BEF29
+:1090A000128F535D8A6171AB871318FFDDC7BFDB79
+:1090B000CACB4B3CAE75C9A6B413C57BDBF877179A
+:1090C000EA8CC6F561FB687FDA50EBC53C289EF759
+:1090D000B19A30BB68BF75FBA6B0F8C1AE84E27D23
+:1090E00030AF841E4E7D0AC06F3F93BB1047867819
+:1090F000EF308BBB01E0556D274E8897127B407F88
+:109100003FC40DC1CE447D81E1497B142BC5BC76A3
+:109110002594EF4338AF0820DFEAA897337EB82BB9
+:10912000C185E3B64F15EDBCFE04AB13EE2F10FE68
+:10913000EBAEE258EAB815CC18F5EA28C6B7D4F178
+:10914000EAD9826FF178F52CCE8766B7307FF81CAC
+:1091500023D9D09DB6CF6D4962F6618C274711AFF8
+:10916000F6447FA33C05819FEDE9FE8E38EBB6B057
+:10917000386B158FD35589F53529D77724A1CB388E
+:10918000EB9184087156753C7F1FC8F39E2178AE21
+:10919000B4B0F597C995A57AE00F0B09E67FAF3C0F
+:1091A000B9A0DE48EB2B1F034F1FF221D44FAB3881
+:1091B000BCBA9A5F824B43EC0ABF7037620FB3832D
+:1091C00053DC36451D35DEB0FCC9EE15A98AEFD358
+:1091D0006BB315EF67AEB95BD19EE52950D47B6CBC
+:1091E0001CA278BF574389A2DE7BEBBD8AF7F34907
+:1091F000762CFA8F4EC8E01B217779272BDAEFD92E
+:10920000FD80E2FB2F48ED53C3E87B4D518CFF13EB
+:109210008FD3DF7740285F38B771BEE2FB7AA97140
+:10922000808FBEBFD0CFFCEBFD9A9729FABB1A33D3
+:109230009AD90D3C4E584BFF31FE6D9751FF699600
+:10924000C836A973DCB0A265CB86EE2452FC90C967
+:10925000F56554AE83DEA4D62B0C893C8E944A521D
+:109260006F85D155080F4CA8775D7F4E46FF593E5C
+:10927000C9797A18C24747BCF6CEFB759D30BFCE80
+:10928000F557CC0EF08F2D39B900F1CF90ACC483D7
+:1092900028BB120FA2FB28F1C0EC50EE7BEC20E5BE
+:1092A000BEABE16C752AF140C051C0396EAC122FD3
+:1092B000047C07D17F00DF02123C8EF9D15EC9E148
+:1092C0002311E2B2CDDB711D77D2D3F255F0EC7FE2
+:1092D000D4596F4238B17C29A11719B85EA2F69310
+:1092E00077F85712B9DEC3FB117EED0D9207F59C9E
+:1092F0008EF8D5205F862F0BF49D5AC2FC23AEB2A8
+:10930000C4C87E347CDE951F4DC051E831CB418FFF
+:10931000A1E32C226EE44B17B81EB3C4F424C6019B
+:10932000AFFE81C1B78278915F7FE3B836D50B4934
+:10933000987F510D47A945F299810E38DF4E252DB2
+:10934000826FBB31DF81A29D7180229EA0D43B89B8
+:10935000530AE74F420F15E309780ABE25C633903A
+:109360005A3919E840C5C7481F753C43E9E7107EE4
+:10937000111C2C2C6E31B0231EC1ECC2909F8BF9B6
+:1093800035E4CCAC7A02FAB645F831FC33E1B9F0F9
+:1093900063A8EDF93BC541EFF7488167B33AC73F92
+:1093A000453C952EF3B33FD28F8749F674186FF280
+:1093B0001BBD138826921FCE71F600ED47D604E33D
+:1093C000C2FD63C25FFDB614C0797F87381F21617B
+:1093D000FA4235691C3D330BFC9D546EC540C9FCF7
+:1093E0003CA459AD8FB2F8A186AE04F07B39098B4D
+:1093F0000F6685DAB12E77AE8BFC943BC9F75E49D8
+:1094000016712E2587B533FE26ECB5AEEC2311BFC1
+:109410003FA6A7302908E5A33426723F561EC9830C
+:10942000FE295D352526803D4EE9500AA7BB8EFCFE
+:10943000156CEF4477AAF58BF8BD6C2E443FCB82B8
+:10944000F0F57E0D78083DE2065D1BACF7478976A6
+:109450002CABBA9DFBD009CD857E451E628D9EE565
+:10946000FD9246A5FE7C3651C459999D71273875E9
+:10947000BD0F3C9F8BEFC3D7D587443E9780DF2736
+:10948000820F86E07D5E01CF0E7BAD03DEE723C158
+:109490005BC0E35A91FF45D827D97C3A11E09C1470
+:1094A000E3FA02F862FAD9C04549139A5799DC8A5F
+:1094B000799CD79B65B48FAA87B37C9EEAFD18245C
+:1094C000276D2D068C0356341F41FDACB58E32D26C
+:1094D0009E5DC3A963BD2A787765AF88F5DC52AD80
+:1094E0005FE487407C3FA9E8B67050B67338887C4B
+:1094F0009632B96F6C20CC2EF1F17D8FD2BAA29248
+:10950000E8F885BF4B8B01F894C92DC753010EAB0A
+:10951000253C6734D2403CE0DF4FE1E7CD06056AE9
+:109520001D160A8FE434139E1BEAFD5DD905F1CBAD
+:109530008F57AFB2C1B9A82B7574686A77F49634A7
+:109540002EC437B2F7931F14425C6D16E617CF3660
+:10955000B0787FD6F7A27D3D289F78534F8C406F1F
+:10956000BAEC5A3C5711B4CA686FC4CB6414E09784
+:1095700080737C345B87785EFCF39D12E42189E77D
+:1095800023EB83FD57D2F273D8F784D03A4796067F
+:10959000FBD79A427016F97D441BCC981C461F4796
+:1095A000383CAA13F41B401EB619B91DC8ED416220
+:1095B000D1221F59CDE3EBE77A11E2C77E7C66C862
+:1095C000A7AA8E72C60E04FF16E40FD0E22F16670C
+:1095D000AC15D76F47BD7935D7AFDA787EF6EA712B
+:1095E0002549604F25D447CE631A9DC4F4FC4A1E1A
+:1095F000F716CF2BB53ECC47AA847CE1B0FCA86F10
+:109600009A2F2CF2C4BB8483554BB4140ED512711F
+:10961000DDEEBD03FF2347B477AB9234B7CD635B78
+:10962000C8D727F2D3AA213F8D3E5ABDBF388944FF
+:10963000E8AF43DEDC18A2C80B13F9CDD53746607E
+:109640005E58E9A3AD78BE0FFAB19B4279695DC15E
+:10965000F948229B4735E48BF50F7FCEF847A8FFEA
+:1096600078DC875F0200C1CFD12CA31FF697273487
+:1096700063774498EF16BEFEBB13B4481FF7F88813
+:10968000737B84F1C57BE2FC07C0B93CB7F3FC9A5D
+:109690004A027360FE90771A69BCF549CCCE16F386
+:1096A0006EB20516733CC7F3171D758B721F5FE012
+:1096B000FBD8746F2003CF118D8B9C072FF6FBA670
+:1096C000D9FD26F0DBCA69F465F0B36B6B254B1846
+:1096D0007D75B5DF21386B14F97F9DE1ACC7FD15B1
+:1096E000FD097BE4F25619E3FB974F717A244E9300
+:1096F00044E96A1E975797098B135C6E90D00E99B8
+:10970000EF26640DE52BF3762EC738CDE25DFD37ED
+:10971000809882E76B29FF98974CC8085ACE5FAFB4
+:109720008CD32EDCDCC9FF46C2E522553BD1AE5EB0
+:10973000FCA4F2BB0AB2F9CFA0F754A8F49ADEDC7D
+:10974000BFB52F89DA09A0D70D200380AFAFDCF5B4
+:10975000A51E526DBBC2F32B949E7B6A81FF59B04C
+:109760003C91E43C08FCFDF7496E1F94ED1F303836
+:109770005CAFBCCEF8FD73F128670CC094E9FF1A0A
+:1097800066B278EBA3944D409CCD60607A8DD0E7B3
+:109790006479951C43DB077FBEDA06FEBFF897C7E6
+:1097A0008C057D3FE1E56827C06B53B1331FECFFAB
+:1097B0004DE526CC5B301A589CD7FBCBC16F81DBC3
+:1097C000BF67E39612B03F2D2D877DE01FD9A8F922
+:1097D000339E1BD93882E5B575E44FB694EF81F915
+:1097E000644C61F262539633DF12D62FE1FA593599
+:1097F0008759FBC1DE3F86F3EACF9E40F598AE2F36
+:109800001BFD707713B69F227F0AC60ED7435BA954
+:10981000DC81243C51BFBB51F2E9E87AAA9AF66098
+:10982000BCA2F2615FE24C902F2F6931DE23E61774
+:10983000FF664A09C475845C992959989F91EBD9B0
+:109840003388F86371A1E91C0F6670FD7A66348372
+:10985000EF7CE2C880EF1E309218F04FCF2C6D2CB9
+:1098600042B9B35C6705792EE21B5DEB0191FD44C3
+:10987000D52F9AD9F9572998039D5CA1760761FEE7
+:10988000A28879BFE6644E67395CDFEB499C104FD4
+:10989000AB3ED47B3BF8030CDD58DC95F21BE3A018
+:1098A00002D4778D60C72C3D10E5637E6A2F3FE7B9
+:1098B000EACC87FC8F9AC9690598877096F20D33B8
+:1098C0009C1F0C64209D527E22519996936C9EA001
+:1098D00085737EA9549FA2F5295B53276829BE573B
+:1098E0006707166B687D6D72216BBF3B7011EA1BB9
+:1098F0009247B2F682C06299D6B7274F647530ECB2
+:109900002862FD3A79CA040FEDFF8A95CB694700BA
+:10991000CFFD56BFD15B13EEA7DC06C90B143E5733
+:10992000B8BFF54A16993B19E0DD2780E7CAC47B2A
+:10993000FF87BF27F27DC53AC577243972FF45FC02
+:10994000BBA5FCBCEEC868B2318AC5A53C3114FE8B
+:10995000475B7A635C2D35D9C6FAB7D07E0A43FDE2
+:1099600008388AFEC4B8CB409E029FD5317FA968D3
+:109970002F4966FC9B8EB31EC7E9E964E75027A711
+:10998000E5C3BED1FDD2F2FDD232BB733B9B1FEDCE
+:10999000D79A877CBD3FF8BB8FDEA4EF6785E6AD25
+:1099A000C68FFB387E2CAD67F1C4A0B507E2D1C8E5
+:1099B00068A6E79142E53AB62733BEBF2DD9CAF073
+:1099C000A2633F92241CA79EC3318DC23DF79BAF7B
+:1099D0007B1E9FCF3F7BDD61FBE584FCBEA3CD7783
+:1099E000ED085F8FC8CF16FD5C59A7FA6E10CB93B8
+:1099F000AAB6F5C0EF1E8D22467C4E76747C9795F4
+:109A0000C7F44BD03BC57D0CC433029D04959C6BC1
+:109A100074DCAFD0C8F3053BD637A190AFCFC2D727
+:109A2000673186DDABD0418FA7831953CC9DF1B749
+:109A300003EE1DFDF52DE0FD29E83A527F401F5D44
+:109A4000EDC74FFFD97828E6A98267079C55F31325
+:109A5000F0047AC6EFFA2AF151CC7343C73EAAE864
+:109A60003AEB5B8E57CCBEAB7A90E7FDDA95F85CAB
+:109A7000D594A58178B9F86E2CF8D81342FEB67D3E
+:109A8000C9DC6E4B23695DE4BBBD919C10D14F874F
+:109A9000CFD5765BBB95E539ABFD06ED090E3F9C56
+:109AA000C3F35C63E7CF87AAF40D88BFEC3585BEAE
+:109AB0000BC91365DD90C2F85B673F5010CFCB1622
+:109AC0001A4A5EB33B28BA242F43FE5D185BB22AC4
+:109AD0008BD63F4AAE447E5DD8BDE4CB2CCABFFFD7
+:109AE000985CC5EAF7947C990DF5AD55ECFD91CEE7
+:109AF000D780BF134FD584512921FDE15CB29DE988
+:109B00001FA51A027864905738404E0A7876551689
+:109B10001A34B511CFB576E0018B4F0CE2F2799093
+:109B2000B0CB035A855DDE1EC3CE13B7833CA5EBD5
+:109B30000D26BBAF00FC6BA25BE764D1AE1E8EFEB0
+:109B4000440FFA90E4A4FA06F839EC16320BF2E767
+:109B50005A37B9403F22CB1C462DC293FB9DE8DA11
+:109B60006ED17E0E1C7AE9A1EE6C1817CC6330A77B
+:109B7000FF9A437FFF0AE2A235574C0E50FF06B70B
+:109B80003CB30AF4ABC12DEFFC9DC95B762E43CCF0
+:109B90007B30F80FE9F341CD069CFFE096BB16C180
+:109BA000FB437FD7D203F063F8395F3DB083F68380
+:109BB000BFE9AE388F41BE90BECD798C0E787C4E19
+:109BC00095A75884872905E17113F3A2DA124E6D27
+:109BD00008A09EA63CF742F5728CAF5E27DD1C10F4
+:109BE0002710E7B4D5FECAB3E5747DF4F9F0209DE3
+:109BF0004198BE3CF206B5EBC3F4EC626255D44B1F
+:109C00008D298AF7CB2C598AF631C97729DAC7D939
+:109C1000F315F5F17D062BDE9FE82856D4EF1B34B3
+:109C20004EF17EB9B35C51CFF7352ADEEF7FA259F2
+:109C3000D97EDA8EFBD0FF9CAB14F47887DF5D0F02
+:109C4000E5C0D686D2583BE9E4A72D0C78EBE1F9C4
+:109C5000D09BB5453E12E1BCCA3237FAF73B9D575F
+:109C60002966E7D7DB34ECBC86F0CB0E36B98B61C6
+:109C70009FDE9628D829B047188371B05F65739F1F
+:109C8000C0FCA8EB41827EAC267DE0474341CECFAD
+:109C90009651EF6DE279354DD37331DFFDAC14D8B9
+:109CA00007F179CF6C761E6038D57071DD10D394D2
+:109CB000609FDC8A751793A5AA7D5AA1A897591EA3
+:109CC00054BC3F26799DA27D9CFD31D53E6D51D47B
+:109CD000273A9E51EDD376D53EBDA4681F7E215014
+:109CE0000F6434B2D5239BE9FC879C6D28857D19D0
+:109CF0007ACE331BE8A5D0E7AE07765874B4F608E1
+:109D0000943E6A4F817FEAADBA642C8FD6D9D1BF19
+:109D100074BCAE0F9627EA1CF8FCB77583B07CB70D
+:109D2000CE89E57FD68DC5D25FE7C2B2B1AE11DF75
+:109D3000DF5BD78C2585603AC88BF8B88E7B13D251
+:109D4000C18E6FD304AA2182FAFD670E225F6CEBED
+:109D5000166883FAC3A465C2285A9F0FC614E85731
+:109D600050D2FDF4A43AFF2B05F22952D8739197F3
+:109D7000D0A871E6837EFDF833C7366BD3097964CA
+:109D80009D2BD962657523ADE366431F9E639B9D42
+:109D90006984FC0A44C610AC4F807A7B146BDFF0F8
+:109DA000CCB1091E9C1F8B1F4F09C58F1F4F8910F7
+:109DB0003FFED525BB19FC28A76EF636C3BA4E71F7
+:109DC000BF9193E4EBE6D1B2589BAF03B97856A5A7
+:109DD0004788B24653FC24E069A3C63115F380EFEF
+:109DE000D511C83B9F2C317BB4430F4C65F2A87D45
+:109DF000A201ED9DD31AE722CC6F9282CF03BC5E05
+:109E000049F910E1D76E0E66001C7E997286D51353
+:109E100082CF4B8EB0BA8EADF38594D35DAD7337E0
+:109E2000CCA7D33A53D87D31C4E74C07F92BEAA726
+:109E3000CB9D5520274E173B7BC17C4EB90C483F2C
+:109E40001E97D90BF99544EB2C9A1AE64FE99DAA77
+:109E5000C3EFA6E8199D9107E488E7C4CB52999E09
+:109E600085FB06F6DC8C68D4C34F6B229FF39ECD36
+:109E7000E173B55B64FFCA1CDE5E72BF19FB6B5FEA
+:109E80001D85F1DB76576FD483DA6B2994287DB476
+:109E90005FAABDF63AB61B44680BE39433399FFAC8
+:109EA00055CBAABF9EA1EF7FB23ADA813CDC723774
+:109EB000CAA707F8CBB3E38CA8B7CC9E9C5E02720E
+:109EC00069268F77CD316B1331ECA5B5EAE10AA095
+:109ED00085A6FC0D20FE17C797EBADB45E91B66268
+:109EE0000394CB7A6ED1C391CFCABE7B3680FA5829
+:109EF0004549AB08EDA5C07B75745E73D7C876661F
+:109F00003F897386CBBF517E85C0C3D33C4F86C289
+:109F100017EDC2B9A992C22E999BCAF4866B295C2F
+:109F20006FCB25B9B794719C3F033DB4CE7E2FA76C
+:109F30000B7FBBB29DEB6D1FEAD9B8EA7B26C4B894
+:109F40006E3E8FD37AE294408F7BC08CF89137FDC0
+:109F5000CB878BE8FAF35A2C1A8CC30B3EEE67F7CB
+:109F60007D155D70239F1BD81A78F10C413C6F065C
+:109F70003AB9939CBADFB30EE5C3E0BF50F9037C56
+:109F8000F1A6FB9333D81A1FF1FCA5AFAE82F3C73D
+:109F90005AE46B47EBD660FD789D07CB13751B39F0
+:109FA0007F6CC0F677EBB672FEE8E5FC71373E6F6A
+:109FB000A99B8EE5A13A37964931AEC454A00BA3B4
+:109FC0001BF3318F3D632032C4195A0C88A79402C9
+:109FD0009E7F361EF25F0C163867A7CE8351F3DBE7
+:109FE0008EFD6FEA748F45766A5158DE0BE86799EB
+:109FF0005DE3CF296237033F19B22D6522F08F53FD
+:10A0000076BB19F4D6A1A9A9ACEEB49B75B43E6C8D
+:10A010001BAFBBED6603AD0F4FED3E11F4DE531EDB
+:10A02000BB398AD6476CEBCEDABD0483D4A5DBEC12
+:10A030001381FF1413E928D043A9316B14A4C896E7
+:10A04000598A8F021D8C499E370AE8606F8A1DF17C
+:10A05000619C7DDD51A88FEFB35D0B476B9CA6FC27
+:10A06000F5F05D497CB916BE1B95B6623D7C37BAEA
+:10A07000E7166DF87763FBEE590FF5098EED5AD0B0
+:10A0800007F7A6B0F8A7E847D445BBE0AF224FAB2F
+:10A090005F8B0BF9785EB30BF978873F624AF9233F
+:10A0A000E0A7AB69962C12CC638AD4117C875CB88C
+:10A0B000EA9B945A289F9DBCED1EF33A4A5F3550A7
+:10A0C0001F82F527D645E6BBD35223F0DDDF733A76
+:10A0D00005B909F9CFBFD7B37B387EC3D757D33281
+:10A0E000CF3C0FED19B719E4EBC11426270F73F914
+:10A0F000F8675E7EC59FD7689CF360FF2B5279DCC2
+:10A10000B6335D57C23C28DDAACE0574D1CEE9BA7C
+:10A110003A95CB077EDF411561E787EE94AFB53402
+:10A12000DC7ECB82BC9CC6E39027AACE7F10F98D43
+:10A13000EABC5FCA17F15E17D2ACCC1BEDB03FBAD8
+:10A1400031BE07C715C1E87834B54B7EF6F81DD689
+:10A15000FD78A4752F252C9F59BD0EE24E40DA12D2
+:10A16000F9CD9DD71388BC9E4EEB6850DCBF20FC18
+:10A17000EC540F7A16E65336D74CC07F13CE27CE59
+:10A18000DC864FA8F9CE3F8B9FDD86DF34C23CD5FD
+:10A19000FC469C6F5697429F837351906F07F7B4AC
+:10A1A000809FFEA144F701C0DBF692E0571AB0CFC2
+:10A1B000E20388676956F721782EE959DC5DE4B13E
+:10A1C0005ED2787E0D7AD16FB72D423ED406C28121
+:10A1D000D2E35BB40EFED36116D7519817E9C3F0F2
+:10A1E000A7ABFCCC77B81ED2B9647425F214DBB7E8
+:10A1F000FF3D03FD5877C0F7AEE050260F0B40FE41
+:10A20000FFF541D1A8F2B44AC42715409E7522EA51
+:10A2100011ADE97A2D94FF6C3BB1353D07FB57DB5F
+:10A220008BAD29838C6CDCD163A16CD6BBB7CE031C
+:10A230003B69B001EDA4F7797EDFA4F337E3415E1B
+:10A240004D927D897952673BB3F5E4AC127B5E6732
+:10A250007B93AE6F14ACEF4E76A7CBE8B70118D561
+:10A26000F667E59AAF08E4430F5D7393C07D6377AB
+:10A27000B647890C6CA2E0ACE3089445179C98861D
+:10A2800033E052ED112807FF8599E777CA271A7244
+:10A29000A3F1083B0EDE5779BFC2A07798BDCACBA9
+:10A2A0004EF7B02DF328F3D48A7D45983F210762FD
+:10A2B000A0BC2605D0EF256BD8BD0BE2BE056AC752
+:10A2C000A6764F00BB97E54B8D843C233AB9B21F6D
+:10A2D0007C34E721A4FB28D47F3AECD8D735981FEB
+:10A2E000D0A475C60E073B764D2FC73A5AFF933F51
+:10A2F000E16707685963F98A84DFCF56B9E6BAA2E5
+:10A30000DEBA2E74BF0FE44157FE8F8C72A7929075
+:10A310008DB05F95E42DFDCA3039481AFFDC01F796
+:10A320007E94CF9503E0D0AED24E72D2F7CAB9BDBB
+:10A33000413C8FB03AB7B308F97CA293F65B9EC05C
+:10A34000DF2733587BBA687F80D57B89FEF64FC400
+:10A350007A8AA8F3FEEE12F52DAC9E25BEDFCBEA7D
+:10A36000B962FCF7D97866F67E69F7EF4D02FD43D6
+:10A37000F0F771DD95F7F2507E3FB1FBEDF34994B4
+:10A38000ED5C1E887B78CA7E302EFA3DA0E7460938
+:10A3900073DF2AD7EAD0BF7DD5D698177E1E59E441
+:10A3A0009FB84ACD4ED0F7AAF6F5DE21F37C1CD03B
+:10A3B000377EC4E3CA65B209E311D737333EDF9570
+:10A3C000BEB678CD1B8AFDECD4CEEF49C6401D1D2C
+:10A3D000EFDA134998DF4E7AFA310EBEBCBB24E2A5
+:10A3E000ED789E55E47BC5F7204EB04FE37F13C553
+:10A3F000EEA1BCE047FEBBF837CCDF5BF5CC119497
+:10A4000073F3653BE2F1F12CF70A804F9B99DD373E
+:10A41000B878CD21A4D7B5995C4FB004FB86C3F3BF
+:10A42000C1CEF0FFE11DE0FFC37F27FCD57E667142
+:10A430001E7AD937CC4B6B33B338A883EFD3798DE1
+:10A440007D0087D7D340E7D716F973AC32240DFBD4
+:10A450001359BED1BB4560075DAF35E3FD44B3562C
+:10A460007D9C177E1E45946AFDFF73A0A38410BCDB
+:10A470007675E7FA5E08BE2FDD01BE2FFD3BE19B3E
+:10A48000A40DE81D10373DCBEE0B1BE03FAF0FCF07
+:10A490007339D99DC9DDD866162752E76B9DEC6EDE
+:10A4A0006678C5E3315593DF1D06F118410F23A3EC
+:10A4B0004923F8D7295E3B385E3B00AF05FE86E2B4
+:10A4C00032F4BB08F415C25FC2EC620E277F67BC92
+:10A4D0003D7D07B89EFE77C2B589EABF18C77C3DAF
+:10A4E0000AFD276A38FF8DD3BB80B731EDF6703691
+:10A4F000A6FD6BE06C4CB32BF2D204BCBB924FEACE
+:10A50000FD11F38E40A745DF864E1F4DE77C4A1BA9
+:10A51000C03C51F5BEC7A675DAF7B8B4DBEFBBB2E5
+:10A52000FD5FBCEF6AB8A9CB4A1EDF543FCF4FD3C3
+:10A53000FC4BE1F8FF9BFF7C76ED6145FBDC3527AA
+:10A5400015EDF33C1F28EAC302FE524073E10F1FD2
+:10A55000712988FAE5B7F5AB77E54F9FF4DA120D6C
+:10A56000C4DB06F9993FBF2DDDBD01F0EB7D8DB752
+:10A57000DE4CE13AF05C23BBA7AB2207F38756F130
+:10A58000397E39EC6F9F3C44F1E64B62407FA7EF88
+:10A59000F05D5A7B6E673C28BEA121CEB03CB46210
+:10A5A000A355EB447F0D7146C29BC7D318DE61FEF5
+:10A5B0000FA5F7E946A28BA7743E7DBA84F94ED366
+:10A5C00009CB87A6A5CF4DDB2769890FEE352E373E
+:10A5D000697D068CF329CF2F1BF8BDC7243E4E7131
+:10A5E0008E5976CA98973675108B0F3E606AC47381
+:10A5F000A4334E3C7CED21DA4ED67B8A58BEB5386A
+:10A600007FF607CD3789FB3D9E46989F5DE27164DA
+:10A610004987F761A9BF9BCBD73B495E2743BE4B18
+:10A62000F003827AB7A03BBABE13860276BE027EE2
+:10A6300077A29CE87CBDF17CF3965278BFF2B41D02
+:10A64000E15233685D1EEC63CD28E953435EC8AE2A
+:10A65000A959F317ECA74C7EA51EDEBF7E96B9C2A2
+:10A6600007B6523BC51EEEAF0CCC01BABC93FD231E
+:10A67000E67DAECE87F8F449DD092CDF1FF14E11DF
+:10A68000E819813A7F44BFE4B7F50F08BF80F013A3
+:10A69000083E20EEE17B3D8DF305A3D41DEF4FD3A3
+:10A6A000B252F0CB039DF9EB9B77E0AF6FFE3BF925
+:10A6B000EBD7C5F3CA642617D5F8ADC66B81CF704A
+:10A6C0005F37FCDEC00354DF03B93A9378722B295D
+:10A6D0009F9DBEA4413754FAF678BDCC74218344C3
+:10A6E0003867F2CDF9B91DF74D2E95D13E10F90915
+:10A6F000621FAEA775D233BF4A4BB8EDBE29DBFF50
+:10A70000ED7AFC8539DF4EAE11853E604DEFB4EE3B
+:10A7100084F4DBAF5BD9FE2F5E77D8F99739B22688
+:10A7200074DE03F287218FB1DDCBCE33566435E082
+:10A730003DF164503006F4C6A50765C443A2756AAE
+:10A7400053C2EE976A25BE0F011F970C5B82E7E0AC
+:10A750003ADD0B656AC27371EAFBA144BE7035EF46
+:10A76000477D4F5435CF13AE56E5ED0C49E7E7086A
+:10A770000B4801CBAF50EAA5EAB2AD8E28FC926D32
+:10A7800037EBD00F5092BEF7479EB4D03E8CEDBC55
+:10A790006F13EEB06F13FE9DFBA6C657D9BC13CF47
+:10A7A000437D537C2576E73C98B7E0C3B320878B85
+:10A7B0008E3BEB80C10BF7F98B7BADDB2576FF4C35
+:10A7C000FBA704FD4677BA1779F069379EE71CF8B6
+:10A7D000AE536679042CDF40E829426F19DA1A94E7
+:10A7E000D9FDF5FC1C14CF0BFABAFCCBE1B7A09E47
+:10A7F00023FC6FFF2CBFB590737B8C8C3E847FB0A5
+:10A8000030E0423DAE4DE72B827BE83DFBA322EAE0
+:10A81000013F4967FBD4D5BDAD4931EE9FA4433B11
+:10A82000E7EFE2FED63299DDD37CDD2FA3FF6EF594
+:10A830000F7FF7EB67ED77B6EB6B2CD723DA45A2EA
+:10A84000ACD1B0731205A576CCDB037B09FC77C2D3
+:10A850009FA77EFF5066C9CE74F42F0DC3FB34AFA3
+:10A860006F65F3E96A5F6AD60471FC2EDBF9F8358F
+:10A87000078B2CE1F7607C9E2E097CB65C3486F653
+:10A88000F5EBEEFFF0E074857EF3FFBADD3049A60C
+:10A89000AA23958FB99297E9A784E9A9B3881FCB1A
+:10A8A000392488A59BB07CFAF9C481E542E2C2D282
+:10A8B00095E9FE281DF35B8289980FB9EF1F7D0192
+:10A8C0006FAE8D18DA00B973FF2A3DAD3DDF8EE320
+:10A8D000B7BFFE8F0CC86BB913FDF78B71B6A647D7
+:10A8E0008827FF67B18CF11392BC12E9A19CDF921B
+:10A8F0004046B1B8D88F12B3D83DF51DFC2F69BBC7
+:10A90000E07F106FCDFD54C3F243964A787F6B739E
+:10A910004083A495BB28CB0BF7F13437B1F6DC2A82
+:10A92000AB57A2F5DCC151AC7D85D50BE71E669314
+:10A9300000D2E35C38F520C33918C6DFC43DE554C6
+:10A9400063CF063D6B518B91E5EF93404FE0E37988
+:10A950005DD8376333985DDC2F9BF1ED7E254A3F50
+:10A96000444C06E3035599254B3368B92AC3190BA8
+:10A97000653F9B7FD34F0BD12F8FBFA3F2C5E0075D
+:10A98000317E28BE7B32B3241EDE7B5562F9E69E03
+:10A9900083FCF706483031FCFE505766696A061D95
+:10A9A0003F2B83303AEA02AEF07B73AE08F69CC8C8
+:10A9B00067EC073615FAC7D93D54AF4AAC5EF0BC18
+:10A9C000EDBEF57DD187EF01BDF6C94CF73D387F6F
+:10A9D0003D212698FFCF0DDE1DA87FD666803F72F1
+:10A9E000C9F3060DE8051F51B10AE74AFE5867C4CE
+:10A9F000F2636AE742F9276AE742F929B573A1FCD5
+:10AA00008CDAB9502EBAE12084F28FF7329CA3324F
+:10AA10008A42F136F57C877378768C7F508FE357C6
+:10AA200065BA11BE1DFBBD9F78211EF2AA35986A3A
+:10AA3000BB0DBE75CD673CDCDE8B9C9FD59FEF7B4D
+:10AA40005E9316E5785E73206671D87B9333F4D8F5
+:10AA50009EFBFA053C1FDA66E980AF53A24B9EA429
+:10AA600061F5C9CFF741F856653A97C23E52FAFEF2
+:10AA70000E9479CDBFFB099CE7A1FD631E41BB1479
+:10AA80007C0AF57CD53AD47010EB7AD5EADF04DF86
+:10AA9000BFFA7A36AC84F21BC2E806F0488AB4DE0C
+:10AAA0007508D7FB0CC14238A772DF2D3962DE7002
+:10AAB000556631C25927F04DC089EFD7B7A5EB8E47
+:10AAC0007836C75322EED700DE690739743306F4AF
+:10AAD000BA721EAF6F6EEAF93EACCF734226BDEC80
+:10AAE00088BF0ABA7B8EEF8F28730FEA5DB04FAF35
+:10AAF0001EBCD813EE5BA5FBD213EE5FDD9CD14BE1
+:10AB000091DF943BF8EFDB7E1A8FEFE3EF7CCE20F2
+:10AB1000DBCB209F64A6F1F03158D26CCBA76590B7
+:10AB20004F3237593A0EE53C7BD668C82311F9EE0F
+:10AB30000BFA141F07529AE028477DAC18984B98DF
+:10AB40003C283546F3CB9F85FC8953D4C7247757DF
+:10AB5000BC3FCEDE43D13EBECF3D8A7631EE0447C8
+:10AB60007FC57BFD6CC16CB0BFE83AD87DD7BB64B4
+:10AB7000CCBBCB7DFDF4BDF7D0FAA417A7E2FD7ED8
+:10AB8000AFF2F6497B4BF1F703DB293CF55491BA60
+:10AB900034E8B1A77E0A9DA9F4FBCA832F1C77DA9B
+:10ABA0006FA3DFDF41AF17FC75798BB108F8EBD7E6
+:10ABB000D5F3D5FBB23F839F0BE47A7F57F8D241A0
+:10ABC0000F929DE10BBF674B8D2F9059CAF08F9567
+:10ABD000934EB17360DF948F7D0E7C2CEC1C664726
+:10ABE000A9F2B7F5D33BDE5F05FEF7F76482E7EA2B
+:10ABF000F8F9BCC5F0FF7208CFC9C2ED8FC07D5215
+:10AC0000F4B907F44F3807EAA4FDFF3983EB4D95FB
+:10AC1000871F49290CB593D59F2ADE276BA50D8A7E
+:10AC2000FAFA2C657D73F186F0EFBBE2878BB7CE25
+:10AC3000D3BBF1FCA614F1F75AC57CCADE8AC2FC6C
+:10AC4000BC899077421F55177EA085F8EAC42EE490
+:10AC5000A7E03B3364521BA9FD6606F3DF4F782B58
+:10AC60000AF359BE69BF1F515862BEE06F98FCFCE1
+:10AC700028D6AF0DDF774326EBFF5AD1961F7E050E
+:10AC800071CFFD04F337AF5919DFCF6BFA42A3A19F
+:10AC900065BF6E0C5FF22C010DC893F68A680FE455
+:10ACA000E7D72C35635E67BFECE087C67C42623332
+:10ACB00037FFD848F7ED0F7098314C9EB6838D431F
+:10ACC000EBC9FFF138F2FBF16F45F934DF623DC9A2
+:10ACD000548742795DC2E87B0EE00D972BE03BAFD5
+:10ACE000798474C819E007B07EA84FCAFCF1FB4F05
+:10ACF000D2716B4E32FA864C39B5DD3E33CC6E27BD
+:10AD0000CF31BA34D27FA0CF2D3BDAA0077BEECE75
+:10AD1000F4DD8879335F97AE0B3295F67B043A3ECB
+:10AD2000359EEE4BCD7E76BFC4F5965E78AEB52BE4
+:10AD3000F95DB35583F427EA6D2DF258C057F5F944
+:10AD400070014F62C951DCE3B472F8DF26839C5C6A
+:10AD50007950CB923DBA1A67A386D8C3C679F590CD
+:10AD6000A182FD0E259B7FBB90CF07FF6A2BEECB08
+:10AD7000CA7511E41C95CBBA7890CBE5ECF715CEEB
+:10AD80001C4C2A01F89F9188CF8EE7AE589EF1FDAA
+:10AD9000AC3B786EC2FB4392FB68C3EF371476E49A
+:10ADA000D483537B811EF961D3FC337467C8A2CC72
+:10ADB0001E38DE34E241BDF78CD5950EFE86493C47
+:10ADC000DE7FC61A6C057E7C6678B404F17BDAFF00
+:10ADD0007A12765FDF199D2B9DDD0321F28AEFFE4B
+:10ADE00056F7B695C96B8BC743BC7A16B1801D79EF
+:10ADF0009FCCF45AF226A34BC1EF6A24BF0DE6E9BB
+:10AE0000CA9CFCFD4CFA5DD29A1FA15DD901372D79
+:10AE1000FF9DA6AFA9D776D8AFBB25763F8983E93A
+:10AE2000FBD5C3AEFE6C1A9C73A376B644E733BF62
+:10AE3000F930DEC3A3B6AB3BEC9BFFA57FB4B37D7B
+:10AE4000E4DA925914F27BABEDA40EBD5CE877BB5B
+:10AE5000589EFB91E14FB72DA7F5D5BBA2118E9758
+:10AE60009F3778807F5FDE61407BE7B22D786E157B
+:10AE7000D4F7E63A3C385A0E9EEF12F8BD4463FF11
+:10AE80003DC81DF25B1DDEB7F1C5CF0DF87B1E4B33
+:10AE90005FB86B07D84F5FA4DB5F7E05FC7B2F2775
+:10AEA000E07D0024997D3F91D323D0979DEE87FCD0
+:10AEB0000B33EA0D4B5F4B41FE25F6EFD2CFA3F0EB
+:10AEC0001CFCE513F7C7821FAC55B387FD8EA46C3D
+:10AED000F2001F5EBE230AF53EA277BF06EB2FFDF0
+:10AEE000C5C469FD61FCDF2510584F7BCB6BE87F43
+:10AEF0000CED6F64B97EBDA507E3031D7296E5CD29
+:10AF0000CE0DDDCBBC1FF0A78A887B1059DE6C818B
+:10AF10002CB1DF957C22F239F0DF66F238A9F09788
+:10AF2000C4116332D0A19BB07B1F9FE88DF7EA9ECE
+:10AF3000CFE4E79749909F7714F876AEFA00FA4B82
+:10AF40000C2C5FAF8B7B2D3FCC64E782171BFFA2DD
+:10AF5000F09B54AFB9A1ACF765BFB35C506FEFBFC6
+:10AF60008296AB389CFF91E4FA08D6B7AC71CBBEA1
+:10AF700077112ECF7DEF0F30EE0913FA69C8BB0CA5
+:10AF80007E6AFB65B131C8E30EDB1571F58BCFFC32
+:10AF90001EF3472EBE7E0FFEBED87CD97F11EEC7B2
+:10AFA0006A33FB3F7988967B4F9CC27D51CFB75364
+:10AFB0001C5E627CA512D6D11FF2575CED9948B792
+:10AFC0008CDECF6FCA45F8093F6DFBE5C8F6959852
+:10AFD000A7E85FCC4FF42FDEFBEF4CA6DF5FD3FB7F
+:10AFE000F3402EEF843844983E7F2DC69F073F756F
+:10AFF000BB339DE5735FB3D17A18DEFC5F8A9C0C8E
+:10B00000C3008000000000001F8B0800000000004B
+:10B01000000BAD580D6C14D7119EB77BB777C67770
+:10B02000F6818D7FE21FF6CEC4187CF816FFD5B1ED
+:10B030004D39FC832842CDF193D44A216C9A4028A3
+:10B04000C4F864438B92AAAC7B95F911515C358AA4
+:10B05000A04DAB83081455541817228A30BD04152F
+:10B06000701BD1438914925A68EB36D46D0CE7D229
+:10B07000A42D6A2477E6ED1E77EB9FB4897A966F4C
+:10B080003CEFCD9B37F3CDBC99F7DC01F8A906E87E
+:10B0900070823D37176907532238D401A0C13C4E56
+:10B0A000632ACE3F5770016C35240C21671EC063A4
+:10B0B000607E72736C500FB091FE9671BCE1B7F771
+:10B0C0005916C01330608732809B42EF1E49041826
+:10B0D0001FF8A15D7591509BE7760500D33E1026C1
+:10B0E0002B0126E9B3623A05B001C9D16752A46FBA
+:10B0F0000D603E7EB7404518F5DCF1B834210050B4
+:10B100002A331B972B811292C37925568B74D0A1B9
+:10B1100044D09E3D42C827E3BAE7A4581588A975D4
+:10B120007B04958F8FB3B7B7818FB68B5585DC00C5
+:10B1300089B912B06CA4F3957810F1D03E01E50402
+:10B14000EA49D8A16310F7AD6D15C283DC0FDBA807
+:10B150008EFB0AC0B87DB59538EE07584EE34ED346
+:10B160006E2F8E07ACF2297FACFC0559E0FED5E6C8
+:10B1700008E101FF743C36D07C1D40046222E18A64
+:10B180009F8D4EC4BDC9C41D202802C66597C9EF56
+:10B1900072BA626215DA9DE5D444F4A7E922C605C5
+:10B1A000F9265BEC4DA22C08B017E30BE7EDE30F9B
+:10B1B000EC201C0A2A6DA4A7D10C2F435D9B50AE36
+:10B1C0008F8581F675423FA787589CDBF16598E033
+:10B1D00034081E1B51849FD3360871BA0AC29CAE34
+:10B1E000867E4ED7C000A76B21CE292C8945C04B47
+:10B1F0003B7DC7733B13C9579E152691D67E0DC262
+:10B2000003AEE938EC31719A1D078D513E7E5E1C0C
+:10B2100056815AC0F54DC5A3B882E7F7543C1C943B
+:10B220008F18B70C8816105D0EBA487405252EEAE3
+:10B230005909B28DF8560872BEFD7FC4A141576D01
+:10B24000AA7F063C5A67CE8BEF9A7921128675A9A0
+:10B25000389D9165CE27E305686768E9F43826C70D
+:10B260006B335BFE2E7B008E46DB42B642E46B5AAC
+:10B270007ACA90FF99BCD1E09B5A7EE143FE54F418
+:10B2800031830FB4D4D81580DEDEC7436D8F00A89C
+:10B2900019595510A0C2512E50FEECF618F8ABBD4E
+:10B2A0007B140F9E23B5C4A5907F4E076286F88954
+:10B2B000652234206D93D49765B4B37475BCCF40C8
+:10B2C000B825BF03CFEF78DC0E8770FD7EC990777D
+:10B2D000E03A6775CA2F1CD732901F1CACEC61BED8
+:10B2E000D9F747FDC748BFDAFBB00664C739A67C6B
+:10B2F000D63E3FCE574F923C38CB81E25EE434F4E9
+:10B300008C0F5656525CCE1048349FEBAD21DCFEBC
+:10B31000921F3A43F209B7915F672807E7CF4EDFE4
+:10B320009783A7497EEA78E2433400D7BF25ABE78D
+:10B3300068BE2BF3D372AA4B7797BDD3A77B537903
+:10B34000CA70FF4DE87724085189D79166CF6DAC5C
+:10B35000A3803199C47826B6A21EC4A136A446ECB7
+:10B3600038FCA54D13F558A4486F8CEA5D97A49757
+:10B370002EC3752F6FB8251979566CE499598786B5
+:10B380002E0DBF5064B021483B575D97EEFFE3F7A9
+:10B39000885FD73D9742E2A9F374B407B248C86505
+:10B3A000A91BC973D678DE1113B3885FBC95E496E8
+:10B3B000BF3352467EAD18D1236ED233F45E916115
+:10B3C00087D91782FF645FA42FB48B549C01BACF36
+:10B3D000895107E2D5CDC297DDC4FF9C291ADAFF57
+:10B3E0006727E64736C9075D85E8D776D3AFCEE154
+:10B3F000137D6EA4DB5F7D7A2D54D171B0F3FA2DED
+:10B40000E30F9DFF9DAFDB53F59C7F6320D0CF2ED4
+:10B41000487E6212E541E78055AE0B0EFF8DEA4E85
+:10B42000577A9D47BB2664772EC7DBEC57402D0427
+:10B43000F53D6BAE253F5C64F790147530A43FE991
+:10B44000513CC49BE7072E7E0FD2E5E1D51C1EFBC5
+:10B45000E479FAE601B43D278557E0A42348B8070C
+:10B460004EE607C9BF80045B421CEF28CFE300E62D
+:10B4700006C37C3A3D77C227E03EA7872A14ACA0DA
+:10B4800070615F10FEB830655FB7799EDAC553AD65
+:10B4900012E6C1BD67C0834712BA875F8B3891EF50
+:10B4A0003E082401F7E80BF5DC1B13A2A4A771B832
+:10B4B000A680E27DD63C9F8E0201E4349C32E439C2
+:10B4C0002057A4F824BE0E333E9915F32CF36EE5F5
+:10B4D00021CBFAEC069F75BD168CFBEBA91E1BEB6E
+:10B4E000E7069758E4F767ADBA4679B93CBE6D2DCB
+:10B4F000E192B3BADA325F0F4E7E7FA82B762951E4
+:10B500005C0F1F1BFDBC017F783F80B048FE35E912
+:10B51000003FC278348EDB2C71CFD0311F512EE327
+:10B52000DDB4B8E3AF43B6F2CBBC661E1443717A08
+:10B530001EA470763DC091E7C1300A11CE6E298AF3
+:10B54000578E6938D5C3C26C9AAFBB264294E3DEEE
+:10B55000A3C4707C7EC88A777E8715EF42D58A6F38
+:10B56000D1762BBE25612BBE0BF65AF1F46A56FC40
+:10B57000CA0E345AE41FEE6FB1F08B8EACB1C82FF7
+:10B580008EAEB7F095AF3F61915F3AF00DCB7CE0A6
+:10B59000FC0ECB7C32AFA6C67D59ACDB223735EE34
+:10B5A00035D79EB7E84DC659C39FFF679C774D8935
+:10B5B000F3F3681B9DBBEB596387E9187E35D3A86D
+:10B5C0004BED62733C48F16EB62B14D3DFC939AD35
+:10B5D0006E3AEF661F0A997D08D43E1EF7909927B0
+:10B5E0004A5CB94C75B4FA66A8350BF95A3D7C999A
+:10B5F000CA71FD587F6BB6CCD344F6A03C33717949
+:10B60000B48181CD725E90CF4BE1B641EB15B35161
+:10B61000B8E9D36884974B4A2ADC7FBD39CF1A8CAE
+:10B62000BABE2E9801B6343C969BE3007E6E5FB3A3
+:10B6300031051BCCF700DECB41A27BB9E08C46BCC8
+:10B6400033DD27952322BF27A9FCDE7495A976A2B6
+:10B650001B9DF152EA5FC7F2D4235EACF377054538
+:10B66000E6F72CA647C8A90439C69BCE8D50D04F0B
+:10B67000F777FCF321ACBBC2F590E6E7E67B74B448
+:10B680005F35ED39E1558F919E51E6E9ABC1B5D7F4
+:10B690001B3F2AA5FEE3101109AC8381ACE06B349B
+:10B6A000AFED6F9ECBFB6A3EFA87755417647E7FC1
+:10B6B000D09E67FC3DF011297B24ED9C1EB0F3BEAB
+:10B6C00003E6FB68B38957F27DB4C9DC7F14556C7F
+:10B6D000C73ABDF9FC558ECBCE8271B0E5F07CE364
+:10B6E000F7A4A78B5DD587C8A7608DB27E298D276B
+:10B6F000DF4B45E2E7E98BEDA23F5B9FE1BE98A4FB
+:10B700003B0BC6F87BEEC1FA53461F995DBFC6FBE3
+:10B710006CCA6F43FFE8C14CDE5F460F96B4104D14
+:10B72000E9BFCBF56F0EDFB0E4C996BDEF5BF2EF7A
+:10B7300029ED0F96793D77C25E84FEEB6F14AEFA69
+:10B740003AE277E79CA39EDE8D18B79BDEBA947E23
+:10B75000FDC5456DB4DF7FF7F3AF1CDF917D71B0A0
+:10B760002D4CF9796BDF4DCEEBFB744EA7FA997C2B
+:10B770006726A9F41654D8303E136C8E72DC3B7DDC
+:10B780009F2D3EE35D32B232AF85FAEC48896433D7
+:10B7900068B9C11736380D7ED56AA209BBEB00BD6A
+:10B7A0003347180419E6C32616FAE953E8F70B796C
+:10B7B000EA27947F5D3B26AA6C781EBA02FA930CA6
+:10B7C000E3593C57FD17F9CFF07A57388FDB594EC4
+:10B7D000F78E3141AB62580BAA7D85EB6C1897B19F
+:10B7E00039DA5DEAC44B8EE71ABC649C8F46DF24CD
+:10B7F0003F0FCD1E55F0A19E0F9918E3F9FC4B1693
+:10B800003DC1F34D97D6BBF979EAA07717BD77E92B
+:10B81000BD91C83068868F71FFE64CA10B7D463D17
+:10B820006B3469BB78B89CD1FDE08803E83CE03E0E
+:10B830004181F61972444F209F87B6D33DE5D792D8
+:10B84000719FAFFE95234675639BF3631EA7129FFE
+:10B8500097EBC92DC3CA85EB725F724423649F1EA8
+:10B860002F5D87F6F5DBF1FE42EFE977711ECFDD44
+:10B870009D17171D3F94168F12330EF00C80319FC9
+:10B880007F8CE63B87476F511DB9E255BDE4FFA8A9
+:10B8900020D7531DE9CC7A53A2FA53E393F93AB473
+:10B8A00097FB8FF5E0FB8CE3ECF4FC09F3750B16CA
+:10B8B0009B6C7ABF09EA625ADFE9D425D28719C1A5
+:10B8C000EF7FB3F97F676BFC153FD2BB6EA594F693
+:10B8D00049EE8B76D4909EA4DF493B527A3E3BAF33
+:10B8E000B739272CE7F7F6D1FDE5744E105F95ECDC
+:10B8F000AF16D996F533AC7FDC8CDBBFF3432B7DE1
+:10B900004877847FF0C6DB726A3EC1FABFF501C595
+:10B910006BD8C5EBDC6CEBA7FAD9796998E3817E2B
+:10B920003E49FEA5F9F928ED93F4F3CED07BAFF8AC
+:10B93000E52FEE5FA2242E91DEC4B1FBA532AEEF5F
+:10B94000BC78F526E54FA7F9CE87B3D6F7BB630ED3
+:10B95000BE13E7A5D573AA710BF8344BBF3F3992DC
+:10B96000EB8B6DD6F578511670BFB3E6FBE13C9DCD
+:10B97000DB19DE9967E3026F95670BF07E467D0069
+:10B98000FB2ED5FD64DFDD7D43E0F9B8DB0B7C9E4B
+:10B99000ECA2FC67FA15DE0792FF478830EC6F983F
+:10B9A00007DD92FA6DCA0F507B785F1017B814CA82
+:10B9B000E3C1DFAC31DF4B469FA933FB4A1DE921D0
+:10B9C000FBFDD9BCDFD49AFBD63BF11EE3A392ADBD
+:10B9D00099FF2F31FFAF70F00A7F67FD0774153EA6
+:10B9E000C90014000000000000000000000000007A
+:10B9F0001F8B080000000000000BFB51CFC0F003BC
+:10BA00008AB7C9333098293130242A33309C01E277
+:10BA10002479841CADB02A0765FA5F303230BC024D
+:10BA2000E23740FC8E9174FD3F8510EC87BC0C0C16
+:10BA3000BF80FC8D405A4C8081E12690FD1B88BF61
+:10BA400003F9E27C0C0CCA406C06E4BB00E93C2024
+:10BA5000F607E23F407E1B1F6EF3FF0AE1B7FFAA25
+:10BA6000002A9F571095FF911FBFFE0E41FCF2BCAC
+:10BA700004ECC7864FA8911F1F3CEAB44F33D4C4CF
+:10BA8000371950F9A7651818EECA323028C843F89C
+:10BA9000D790E48D8062676420ECAD620C0C7BE58E
+:10BAA00018182E336037771B507E1F50DE0E6A0E3B
+:10BAB00000B5BC7B1E680300000000000000000011
+:10BAC0001F8B080000000000000BE57D0B7854D5AB
+:10BAD000B5F03E73CE9957662693848484F09824FB
+:10BAE000803C020E010248A893071425C008A868EC
+:10BAF000110651088F3C44ED976BDBCBF04AD1D255
+:10BB000036D6B6D25ED401E15EA45803448D1A60E5
+:10BB1000806051C106EB03ABD600B6080219A0EA5B
+:10BB200048F1F75F6BED7D92732633407BFBDFBFFF
+:10BB3000DFFF8FB5DB7DCEDEFBECBDDE6BEDB577D9
+:10BB40005496CE581FC6BEC1DF8D8C3D2031868FE6
+:10BB5000B4127EFFEB9B0CC6A65AE1BF64C6C6CBEF
+:10BB60000EC6463036C5C142166833A5081E766338
+:10BB7000ECCD4D5248C63ED02E58C8D822C67F5371
+:10BB800015D6245DCFD885D13BEB867918937C3EC2
+:10BB9000565B00A5C7CD666159B4F72BC9C558F2ED
+:10BBA00068136303789F6FE0DF149F9DC6D2EA6934
+:10BBB00013530DF5747F0F43FBEE33730DEFB30298
+:10BBC000830CEFB32B0A0CF55E353718DAF7A92D85
+:10BBD00031D47382371BDAE7AD9966A8F7ABBFD3D0
+:10BBE000D0FEBA75771BDE0F0C2D32BC1FBC65A9C9
+:10BBF000A13EA4E12143FBEB9B5618DE0F0B3F62F5
+:10BC0000783FFCE0CF0CF591ADBF36B41F7574A33F
+:10BC1000E1FD98B6AD86F7633FDD61A88F8BBC6C04
+:10BC2000687F63749FA15ECCDE30B42FB5FEC15037
+:10BC30001FEFFEC0D0FEDB99270CEF6FF27C667819
+:10BC4000AFD1C1A401170DCF277BFF66E8A7303F16
+:10BC5000009B3133ABA1D2CAEAA9B4B3062A1DAC0A
+:10BC600095CAEFF60EDC49F4F964B08E01DDAD0C37
+:10BC700046FE9406E59BA3F39203F9389A8F31A010
+:10BC8000DB297C6836C5EA08CB4067162B0BDA80C7
+:10BC9000145C51A0B734A0BB28A3D21D057A1B0E9B
+:10BCA0007417B552991A4DA5E769513795DDA23D34
+:10BCB000E8797A3493CA8C682E95DDA31E2A33A3C3
+:10BCC00083A8CC8A0EA0B247B480FA6547BD54F66B
+:10BCD0008CDE40CF7B454753D93B5A42CFFB447D56
+:10BCE000547AA2375399139D48656E741AB5CB8B5D
+:10BCF000FAA9EC1BBD939EF78BCEA4B27FF46E2AFB
+:10BD0000AF8B06A81C105D44E5C068059583A24B67
+:10BD1000A9DFE0680D95F9D187E8F990682D954382
+:10BD2000A32BA8BC3E1AA4D21B7D84DA0D8BAEA136
+:10BD3000B220FA337A3E3C5A4FE588E8AFE9F9C8B9
+:10BD4000E83A2A0BA31BA91C150D51393ABA95CA1A
+:10BD500031D12D54DE10DD41FDC6461BA82C8ABE14
+:10BD60004CCFC7459BA8FC16D25B1AD25D984A5FA0
+:10BD7000F4757A5E1C3D486549F42D7A5E1A6DA50E
+:10BD8000B22CFA477A3E3E7A94CA09D1E3547E3BFC
+:10BD9000DA46E5C4E8692A6F8A7E4AE5CDD10BD43C
+:10BDA0006F5234426579F4123D9F1C8D52A9C93BF4
+:10BDB000365A3DD3A6D15F2EFEFF2CF75F06835C7B
+:10BDC0006201D337503207D0C198CEF6B125483B37
+:10BDD00092932AD05512D0770AC8429487536AA406
+:10BDE000D0B773803EBAB5B5605D1D6DF158A07EC9
+:10BDF000178BA848BF1FB13627CAD3BD634EF66C58
+:10BE0000037A7D333DDC0B881B7F246F559C531ECA
+:10BE1000CADB334A1B3C9FD26D5F7AC081FD8137FC
+:10BE20000A90BCE1FB48DF408E38CE5D0A0BBA6059
+:10BE3000AA47708431D42E6C81FAAC72E62B80F65E
+:10BE400075632C3343F09DBA027F851FCA1FE7F844
+:10BE50006762F93A320FCC7FBF288F3013953FEEDF
+:10BE6000EDA672D67DFD383F950110B3AE0E87F476
+:10BE70000CDE8F3922BDFD43AEBD9FC2A0DFC8CE10
+:10BE8000F6CF30FF3BF83C58C206D4383ADBC1F35A
+:10BE9000A3D82ECEF30FE23D6F308120007D154CEC
+:10BEA000358736A37E629EE45B705E564FF2346740
+:10BEB000E2793DBC2C335FE9AB9F6788E6F7B0C4FD
+:10BEC0006636D0F8BECC6943687CC27730D51ADAC2
+:10BED0009C43A830D0CB5F119ED02FDFEE6FA7F52B
+:10BEE000413FBF13E1E3BE26B840BF2F089E0AF4CE
+:10BEF0001B72EDFD1297F54CCCC343E389E7D516D1
+:10BF00001694004E91CDCED0C61C5C9387E4678515
+:10BF10005B08D06E000CD0EB15290842C65A762774
+:10BF2000854DD0BE68B37323DA01ED25C18CA90815
+:10BF3000878D2ADB0C4D56ECFED1BBFF01F5A20D1F
+:10BF40002AB3407DE1C59F1732A0A3EB24897F3F30
+:10BF5000E8DBDB17C60F30EDE79370FC058C8FDF55
+:10BF60002E09B86E4E26BC7D5AB6A96E2C946DBBB8
+:10BF70002ACB19C8F19300D62CA0EF8576A660399C
+:10BF8000AB66BB99E834A87ED2A6E917E267A5B3F1
+:10BF90002E77AD2FC0BAC6FFB0EE8521B5B30EFF28
+:10BFA0002EDE62ACEBE0457650E4BC12DA487495C4
+:10BFB000CDE1A3C1CB97CDE127E055765E099ABAD2
+:10BFC00011BC42280792250FC1A1E2BC1296619CC8
+:10BFD0000A8023B260C5AE8733104E8BB7D8DC9F82
+:10BFE000E8BE5BD99062A8573765B93FD1E9D10B5C
+:10BFF000079F76E1FA97669ADC9F807C3BB3CC97EB
+:10C00000F609A0ECDCB289546AF451D990E37618B1
+:10C01000C631D62FD44B131B487F7A92670C494CFC
+:10C02000674B33CDEE4F80554F6FE1FAF6F432ABEC
+:10C030001BBF736699DBCDBF9B49A506AF25B576BF
+:10C040006AAFCD2FD1B8FFECF931D6C84E58519E0A
+:10C05000C3BBBCC4ED13F293F25733F149B3FA05F5
+:10C06000D28D15FEFDC6447444756DDCEA06396850
+:10C07000B91E9F6F337C0FFA79FEA2D32F89F95630
+:10C08000617FD1D1E5FD3800F1A995F01C801193B5
+:10C0900061BC76C5B106EDA8C9827EAAB11DC88370
+:10C0A0004A6B9B39008FCE36727C24FACEE9655BF1
+:10C0B000B251AE5558EBCD28AC2A1A0696213F9DB9
+:10C0C0006D5C9981FA65B17CE1BBFE38FD7FACF116
+:10C0D0006D488D18F56548CC13C635F0197374ACEE
+:10C0E0001BEA674CF02947D7711F97B8DEA9DA76AB
+:10C0F00064C258987F55D37933CE63B214785C4AC2
+:10C10000EF5CBF84EB8771166D39467CFEA91AEC93
+:10C11000FFBD9C2BC0B3CB3C1D997F49D2CD2F08CE
+:10C120008624F0EBDDA305BF32CFED1F007F9E7AA2
+:10C1300043658FC03CD8656805EF7B8BB7F730BF90
+:10C140000BE17577E362923FA750FEA01E66F5856E
+:10C15000481F67996922AEEF2C7BCB355C07BF7D0A
+:10C160009259C0074C59900716FA14C12D0BF5804F
+:10C17000A5A2AE551E8ACF95A0904BD237244F4230
+:10C1800012E9890AFE3CC8ACCB691D6BB83C0AC2F7
+:10C190003F58BFB7DE289F16AC33D6E7B369190AFC
+:10C1A000C897F93F576144906F7AF907F07B46E2F0
+:10C1B0007A7701ABA973C3FC9F30039E60FE77BB07
+:10C1C00099920DEBAB7CF189C2B9507F4DE27AECCC
+:10C1D000F432987E7F182795AF7F516DC8ECCBEF76
+:10C1E000BABE138DC36F1BCB683C9293C1459AFEB8
+:10C1F000651EA590A42518B989D79FDD28FB6C2E54
+:10C200006C07CF75F279DE1AE3FAAEB6FED8F532D6
+:10C21000F633A2B7455B6E614867DA7A347C69EB26
+:10C2200051B748BE501C3E6813F4AAC9B588809F18
+:10C2300066777C1E53BF1453FF26A6AED1B72AF8EB
+:10C240001BE8FE736924F2736402A79336AED744E9
+:10C250003B7367BB4B576A6711FC02EDBEB9523B9B
+:10C260005BE7788A29BD6BBBCA179F7D2108F4BDA7
+:10C27000E8B95FB818D0E329A53EC30BCF976C5E31
+:10C28000ED42387DAA045D4837A742F2C478F01A1F
+:10C290006392347BC32101DEAB34FA2F5A3E05F59D
+:10C2A000FB179B55F7238097EA2D96B005F05DD5D7
+:10C2B000B8B09C0DA5FA315EFFE179A48FEA26F5AE
+:10C2C000B81EAF8BFEEB17191E27E121DB84363039
+:10C2D0000B673328AB36FD7902DAD1D52C42F41C3A
+:10C2E000DB0FBF8FAE1DC8EBB9E6E4AEEF35BFB1D3
+:10C2F0009A3F62D58D3F3A8F7E6335538EEBE9A826
+:10C30000026919ECBC41266737F417D828360AE5CC
+:10C310008A0607164A27B9BCF299C7871E83799CFB
+:10C32000D9F4864BD2C1072C2482CB8586791FA7EE
+:10C330005D412F9C03FA64FDF5FD42D4CFD3041375
+:10C34000E80ED5665E2E51C3AEB100CF251B542F2B
+:10C3500050265BF2ECD3FFF96BE03BF6BEC5DB0F7A
+:10C36000E0BDF8D903EFDE00F5C5DBD56EE57C193D
+:10C370000E29A3131FD5F02FC66534F82FDA79C024
+:10C38000EC19C29F7F3FB5130F8BB7EF35B3215D1B
+:10C39000E156DAB0D7DCE688838F866313D09E59E6
+:10C3A000F9CC9766C4F7A9DD12EB9ED3B57FC5869D
+:10C3B0000364BF209C087F023F1DF8EA82A7F09427
+:10C3C0009747503B37CAEB447872A2AE1E4974FCC3
+:10C3D000DB97E1FB157FB47871FD15BFBDDF85EB01
+:10C3E00038A9D4707A7E6275860FBE5BA10633DCF5
+:10C3F00054F2E7154F3E4874B6E0C8836497017D58
+:10C400006499486704B3707DF7AEBF95D6379F0532
+:10C4100088DE2A9E90FD2194030A9BB83D0E3F3C86
+:10C4200027F8E1E4469094B0BE93281FD1CE7D4B0F
+:10C4300016F2F13EB2231F146B054B86EA9F5B395F
+:10C440009EEA4C262D2E6735D0E9A61F921C3DDDB5
+:10C45000CBD7DD9D4F70D0E426C953F9C8F8EE1C48
+:10C460003F5CFE523FA0BB527C8EED5B559F6DA89A
+:10C47000A19F9097FCFB0F88EFC3BCED687F9CCC1D
+:10C48000E07A22767D7F3469F211F4AB8EBE747C43
+:10C49000CDF97CD3C39CAF353E0FDD3211DFFFF504
+:10C4A0006DCE3FD80FF50FCC2BDC9DDEEF9D21919B
+:10C4B0001CB0B0703C7EDEA40A7E36BE07094DF685
+:10C4C0001BCC5B9192F57402E3A712FCC92E99FF75
+:10C4D00073E8A7B3A7ABF17BD4CEDCF93CA7936F8D
+:10C4E0001708FEDF8AFC9FD4C9FF6C7DFA35F96717
+:10C4F0004BD4D07FFE1AF915F833E8417E55FDB8CC
+:10C50000EECFB6ED7FF74EA0EBCF1A343E35CACD55
+:10C51000583EADD8F12043FA8CE5D3CF7AD6B0B8E7
+:10C520007C0ACFE3F269CFB6FF11B9A9C1ED480C7F
+:10C53000DC400E3EF5B22731FC62E560B5C9135709
+:10C540000EC2EF6D56D895EE347AD3E86CD16F2ACF
+:10C55000FBA0BCE9A0478DDE3AE851A3B7D8751A15
+:10C56000E116FB7E3DCA1B9D7DA0AE604127E039F0
+:10C57000B24B263FB1DD1371A5C27757DBD81CB48F
+:10C58000B3DBDDA29EC2EB9174731DCA05ED79C4C5
+:10C59000C6E30DEDFE882B45673F1F6B965D1E7849
+:10C5A000DF166213E3D9D52071E9FB6D2CD1FBE5D1
+:10C5B00004BFF1B2A377ED08F4AB642FDA6EF72C69
+:10C5C000BFDD85218BF6E6BCA933E1F9BDAFC91407
+:10C5D000D368B7BB86E2BCC06F57B200BEF3049EFF
+:10C5E0003F65C15F16C1BAE63573BBF89EB54678A4
+:10C5F000CC773C60463903F667271DE8E845DB2722
+:10C60000A8586F7CBF88AD257C2D8AA19F80F077CC
+:10C61000B264413FC3D830E16F9870BCA5424E8DE3
+:10C6200097F3A7CE04B8B71F949905EA179A6556F1
+:10C6300087EBDC268518F271309DE8B00AE403D35D
+:10C64000F9856790CECC89F9F7CCF31F157E0F9A48
+:10C650002C79E183A1FF01E59917DEEFFF0AD65F90
+:10C660007CAFF707AC6BFBD2DD5FCD46F9DEBEDBFE
+:10C67000C2284EB2FB77BDBF87F5972D5E8A73AC9B
+:10C68000B0F0F8D46E67A81FBEEF05F8467DB9EB91
+:10C69000CBA16DA46F56119ECA64EE475C68FEDBA9
+:10C6A0009FA46E58C2AA508FEE4E22FBBAFA655B69
+:10C6B000089DCEF65D5F16061CFFBCF554995980A7
+:10C6C000E8CFC966EE407A4D01C4C1F7AB5F19F3FC
+:10C6D000F472F87E65E35EF33C785FBAE7EBA1287D
+:10C6E00057DA7770FBE09CDAF624F3323655FEC554
+:10C6F0007215F0750E6DB51E2097E4778B838E78DA
+:10C7000070E170680738E0BA002E15280F13C16376
+:10C71000FEBF2C3CCECFC6EF2F691EC5E41C3D5C8E
+:10C72000241F7FEE0C59255A3F7FBEFBCBA12877F3
+:10C730003F6B584EFAFB6AEB5E8DEB4EFF7F69DD77
+:10C7400052F85AD6BDE95F76DD9CFE07C95C1FC56D
+:10C75000F241573A7FF1BB54FFADD34BF3BD46FED8
+:10C760006FF9975DFF3F88F71D12EDC75D0DEF274D
+:10C77000FE65D77D35BCBF26F0EE7463BCB77DD7B0
+:10C78000D7BD996EFD575BB749F957956F575EB79F
+:10C7900066F7B49A6ADC23607EEFB3FA5B73A0FCA1
+:10C7A000BDEF623774478107FCF1FC860285FB0D03
+:10C7B000168C3361C35B252D5ED46AD8C7ED594111
+:10C7C00076C614DF8FC93E604A4D6B31B46F2D9928
+:10C7D000E77D845A141C0D607DC6385137FA536FBB
+:10C7E0004ACC27811D3BA564D241B4EFA6FA64B2BE
+:10C7F000FFA024BBEF9DDE13F8F3D1463FE28E1875
+:10C800003FE0F699C6F7B78AF16E634BDD23005E11
+:10C81000B7F554DC2100D11DC5352AAEE78EBB2407
+:10C8200056AF8B57DE1A339E4B61224EF28FC1EF0B
+:10C830009E0EF82D2578B062D9BB995D03FC188750
+:10C8400077EB8C61218CC330C5CBE1775BA597E298
+:10C85000A0C2CF54457FD5B1A615F9566546FF5203
+:10C86000F31313C19909BF93C6C9ED84BBEA93C9F9
+:10C87000EFD48D47F0D0F0F1F7E241C3DF7F171F0F
+:10C8800085888F38FB670BADD65B71FFC23A4022BB
+:10C89000BF7DEA5A99F260ACF912C1D13F5AA5FDA9
+:10C8A0009D3F9BFC856838970F1F55F5101FD68B51
+:10C8B000F05928E0389FD590DDC92E7FF34D11EE59
+:10C8C0001B1184E0BD8FB1C9E087CC2F92C276588E
+:10C8D000FF028505930B30AE29B1E3FAB866C8585C
+:10C8E000C7DFB7323AC7B95AFB44F2E19F5D7E0C0D
+:10C8F000F2E8785FF057B054E8F38ADE4F9CD3CC6F
+:10C90000E158BD440AE5121D8555BF6E5FE77D41C4
+:10C91000D71F7F7F38C9B9E29F0E4926FFD53788D8
+:10C92000ECFD6A61EF5F087A92315E73A1392F19CD
+:10C93000E331170E96BAF472512B8F083FF20FCBEA
+:10C94000AC54B69749F532FA5B2C3285F470998D68
+:10C95000A1DC89EDF792A2C55D6ACC1497879F5C34
+:10C960008878E4BF05D035395587B7B5934F29434B
+:10C97000BBE2017FC775FB24FF5DF8A2DF8A703D33
+:10C98000626B9BE08FB3DE3704FCCAF77D65C63867
+:10C99000C1B4E61C15E132AD4C36E4DDEC57843F02
+:10C9A000359C0DC77995EFBBC93506F17250F6DAA3
+:10C9B00000BED5CDE7CD8138FB6DB1F0C4F1312E8D
+:10C9C0007C42F5CE47789EF8B18D05811F0E8BFD18
+:10C9D0001F78E543F90543F9303EF6B6C2F7150670
+:10C9E000AA3C2E3EBDBC584D87EFE637BA87A18AD8
+:10C9F000E921DA0F543DF43E5BF4D3DAF558C2DB9B
+:10CA00001D33BBABE2AD7FB299AF7F01F37E77B44C
+:10CA1000F4AF87B7E29F3AC325A8DFCB2492235D0A
+:10CA2000E99A117F5C98288550FFA21F4BF5728907
+:10CA3000F4FF612DFF601AD7971ADDC7C25952392A
+:10CA40009CB5EFE7A89C9ECD2A878F06670DBEB1E7
+:10CA5000F3D5DA83BCBA511F5F99DA34ECB7689F1B
+:10CA600054354B6E0CFD55296D66E4C3EAA6475557
+:10CA7000DC2FB8C3C3C7658A7FA87EBF76A0AAD0C3
+:10CA80007CF6178C25FBF1E25A6E1FFBEE39EF4264
+:10CA90003BE8B0C9FBFBB1C88F6FCA944F90088EBA
+:10CAA0001F2CDB32A34CD18F9B43F39CBEA458C5F3
+:10CAB00070D07796EC55BBEBE869A09A4AEFB5E7E2
+:10CAC0003D96780AF0397C8FE611FC8985611E4716
+:10CAD0007E436B4912BCFF4E4D0AA7C38A86BD66D2
+:10CAE000AAE7507BED7BDA7762F969467992A13E3D
+:10CAF000AFB4AD27C2A5DC127EC01B874E5B546D60
+:10CB00009FE4EFD4133EA0DBA1FF3FE889F3137C41
+:10CB100071E0F698DA453F748FA71F962EF7744799
+:10CB2000F82FDD95D71D9963E96BE333E2E9877749
+:10CB300096F1FDC0F7409E61D93E03F4C3F53AFD7E
+:10CB400030C346F411DBEF07EA35EA070D5FFFC398
+:10CB500072E61DD40F71F8BA5E35EA87DB9AE79268
+:10CB60007EB86D86CC3CBA78DC0F55B1CF95503F7E
+:10CB70001467DC4175D59B14876EDE117E09C215E2
+:10CB80004BFC0EEA893D42EEC7EA8B44F27C9A598F
+:10CB900012FBD55791E7FF97E0ACC9F3A5E0BFA022
+:10CBA0001DD8950E19C9EBA577803C97901EB93C0E
+:10CBB0005F7A97884BC6C8573FCAD7117AF9CAFB24
+:10CBC0005705B83EA86ECA797C16BCBFB35EF55A4D
+:10CBD000A1FD9D9DF2B6502F6FF708790B70EEED19
+:10CBE0008E83DF99B39298C728AFFAA29C3A31ECB2
+:10CBF00077F93B91EE0FCBB48FF867A1C70F0DFB10
+:10CC0000DD088C9F77332B443F7F16F2EBDCB2D0EC
+:10CC10008C32E0E3D27BB83D5CB94D263854357296
+:10CC20003BAFAAAF3DE481FA8482AF683F70F12E3A
+:10CC3000BE1F08802A2FD6E171F1E1B6BA6C7CBF25
+:10CC400041A2FDCCF9DEC514C767EB789CD80AFF7A
+:10CC5000F0BC0E1FC5912B05BC16366FA078F3C231
+:10CC600090310E5DD9F7E653E80F68F277F19698A8
+:10CC7000F7DE8769BFA212E3CD3A3F4416F6C3BD83
+:10CC800072387F27E676FE9EFB55B1F8D7DA75AC91
+:10CC9000BFE2BFB9FE23B0FE11FFFCF55FEBBA5552
+:10CCA000B3E0F7023602F9E3CF261FF17BF07558A7
+:10CCB0003F7CE79E47FB75D7E719A509BE3C6C0A88
+:10CCC000D46561BB2A89DA2D58BFFD4006D467358B
+:10CCD000B06118A65FB0CEA8173BF470A387F4EC40
+:10CCE000AC9AEDD2DDF9086F56837436AFC012C02E
+:10CCF000FDD423B608C92F8DEEC699393D8F15DFB7
+:10CD00003DD12352467E4493E426BE08DBB85F0142
+:10CD1000F0B7417DFF982F270878533CA6BA89E3E6
+:10CD2000A71AF0817C35A159D4B7703BEC3BA06FBA
+:10CD3000683FAC79AF8AFD2AA07D1AC99B41867DE8
+:10CD40002EDC9F2BCED0E16DD7314EB79B252F8B9C
+:10CD500083B701F04F5CBCFD93E85583C738B3B08F
+:10CD6000E705FE8ED85ACB87D33E94E4DD888D9BB1
+:10CD700053681FE593FA3CC2E32441BFB1748DF6BA
+:10CD8000BD47174FBA05270EF2954DB4519E1B7D36
+:10CD90003797DB3F7A7912EB3757B356B263264B9E
+:10CDA000818F145D5EDB6D22FF44DBA7D5B57B5C14
+:10CDB000BD423B96E936A19CBC5FCBB7C4FCE10CFD
+:10CDC000CA5BA2DFFE5E85EFCD82F55E5C237B71E0
+:10CDD000FFE77693E7DD22E4DF4754867479F1902C
+:10CDE000EAE3766712C9DDB9874FA8180A990B30B4
+:10CDF000417CCFFD0197AF27703078F647D05B3E7E
+:10CE0000DCAB670D23317F788677EF780FE0E5D6CE
+:10CE1000114756E33EDCF452F7BBEF227C1F961914
+:10CE2000C2F7F89A52F24FEEBF4F22BA3E0A70C4D0
+:10CE3000FEB7CEC879F75DF8EE5D6BD2695F6D968F
+:10CE4000EFC078A4B379539D0EDC5F9B344066013C
+:10CE50001D1CEF62ADAB515ECFAAB9EF569C6F05BA
+:10CE6000E8018CB356341F19DF1DEBEB25AF07C665
+:10CE7000AF0E06CCDD0185ADEBCE9B31DE311FDA86
+:10CE8000217AAAD7F376D59B24AF0DE9B1F9519257
+:10CE90003BF33749CC8DEDC1DEB3F271435618B781
+:10CEA000753DF487FA02EC8FE36E4AB90DF7D1AA0B
+:10CEB0000FC9BCFFE8E5AFA25C9A0FFDE0356BDD62
+:10CEC000741F8DB770BDC43261BC8AD1393F198DD2
+:10CED000E31D52BDF8FEBDBDBF32E3BC67C3F7B270
+:10CEE00060FC7972DB786CCFBE27B93753BC89E719
+:10CEF000C9B60B3E606F6771FE92445DD8819A3E61
+:10CF0000FC833997E8697EEDF23A5C575B303D0768
+:10CF10005DA0EAA6F366B4EB3E013807C06E3B2184
+:10CF2000F2D8F6074F98DB74722A62CEA3FEF7346C
+:10CF300015137FDFCBFCB4DF1D58CEF5F0B1D5B6AD
+:10CF40009084F687EA263DB97FF575BFC4F59F7BCF
+:10CF500056A5FDD173BDDA281E7B72BDCA8230C7CB
+:10CF600095EB65921B27B7F13890FC844AF5050FC5
+:10CF70009AA9BE7FFDF409280F4F02FC910E4B9F2A
+:10CF8000186FC6FA0290EB9638F263BE67119717D6
+:10CF900031F261C13A23FF7791170F4CE0F23D4621
+:10CFA0001E54F6ACA3385FAC9CA8660E4D3E1460D0
+:10CFB000BD359C45F45B75486568CF5529EED9EBC6
+:10CFC000906E66D970A718F8227C00E5DAC590E467
+:10CFD00009C2FBEFCC796924C2EF2F086FE48BB54F
+:10CFE00069B49F3A3F3497E0AAE5132E5867A467C7
+:10CFF0002D7FE98E80CC7C7A3D5091C47CBA76EF4F
+:10D00000FD00E812BE37A7490AD924AC1F7BF5C141
+:10D01000115477231D56D50A7DBAD64974FBDEBF5D
+:10D020009D5F8D7439FBFB12CD9F050375A857AA30
+:10D03000D6491E8C632EF83EEFBF00FA23BDBCF725
+:10D040002B4E3F40C71EA4F3AAF58FBE4AED3749C9
+:10D050001E1CFFBD0D7349FF56046546EF371D23A7
+:10D06000FB18F400E501ED0FCA1948E755AB2C6E2B
+:10D07000C4A3462F1AFD1D53C53901AB77E874E8E8
+:10D08000B7C1ECA175C7D29D3C3387E8AB7A9B4A08
+:10D09000F4511DE4F474EC5999E870FFEADB897EE1
+:10D0A000CE6D9612D05FA9390BE92FC4DF77D0DFA0
+:10D0B0003392A03F4ED7271FE0F4588AEF91FE9E8F
+:10D0C00017F629630EBDDDA1D19F464F57A3BB2E96
+:10D0D0007A2901BD816D7C1BCEEBFED5369A77692E
+:10D0E000DD4BB7D512DFA8B43F5F5AF76F19C8A759
+:10D0F000F3159E87A1C1B152E1793A5DE6F1F3E5FE
+:10D10000E6AC6B994FCC3CF676EAC502D48B9857C7
+:10D110001286EFFC6EDBD394BF7676EB31CA4B5CA4
+:10D12000FC0AE01DDA9FDBE66461B2A743245F16C8
+:10D1300035CA9417CA9470E174DDF9112DDF62F1DC
+:10D14000734E82EFA21D965039F45FF4C289A1B4E8
+:10D150001FBE22F22AF24F70ABC4E3F2C1B6A1D3D4
+:10D1600031AF52E1791FB17A778C85C76BCEBC9411
+:10D170003413ED1F69CB5EDA4F5AD470BB6AD1C548
+:10D1800027BD1695BE0BED689F260878C77D449C89
+:10D19000DF2D43F4F35BCEC77B86F3CDA22695EC5F
+:10D1A000A2455B36505CAF7ACB79CA7B2D7DEE59B8
+:10D1B00017C2A1BA4936E6436D91C316CAD7928FFA
+:10D1C00059B87C32E4255535F27319550D22EF27F5
+:10D1D000262F66F173BB5E08026816EFFC2F17F26C
+:10D1E000D1E9D6CD2E84278C47F944534727C83739
+:10D1F000BA5A9E51C3C371F38C4EE37F0081CCB603
+:10D2000018F333D9162EA700EB85FE38F14CCD5E0E
+:10D2100059FCECE74F62DEEB991D9F3D89F35EF20E
+:10D22000BF2E3E89791B6CB7CD8DF643F5D6772896
+:10D230007F50EB576B11FECF33FF457997E7DEB791
+:10D2400090FD776ED7C9DE681F9CDBFE5506E6535E
+:10D250003EB06B3CC51F1E78BEB43B8BE3DF6A2536
+:10D26000D265E81AF23E63F1B0BF510E3B609E6793
+:10D270008F5A88BF3BF2C51A2A79FE9D47E4896D13
+:10D280008B9F57ABE53755354E9F3A0EE55B23D75D
+:10D29000E31DF94E57CB0F7B1BF079FD35E06D9BFD
+:10D2A000C8FF8BC1DB59FC0FC0CF2F2CC6FCB0CF01
+:10D2B0001BEF7DEAD7F8AE31FE79328D8FAF062FA6
+:10D2C0002D6F779EC517B220DFECF80DE5E121BE8A
+:10D2D000CA3DA8E73FEF8D71CB4FD508C50323BBEF
+:10D2E0002C6ECCDB5AB4EB3DE28F73CF1FA1BC5840
+:10D2F00026F267CFB18E1FCF77143189EA4D4E9E4B
+:10D300005726E08E79671E173D17F9659C6EB5BCF0
+:10D31000B344F966EF5872C5B90B9E1757E96935E2
+:10D3200023FCF57968D268C4D33143FE9EB6EED8AB
+:10D33000F1DC088751FABCC944F97CC21EEFC01366
+:10D3400097C3E736883CCA8EFC48C67A1660BE0F83
+:10D35000D777D521E93D16871FB5BCC9D6587E0CB5
+:10D360005D5BBEE4D5E7FB8FC163BF85C79F34B863
+:10D370009CB91C5F1E7F26F81BFC92D316DDB99466
+:10D3800039C22FD1F2C8B4F9D63570BD7B660BB760
+:10D390000B63F9B94AC4DB63BFF395F84E55D3DE8E
+:10D3A000A12877CEEC7B49D01BA7E7AA6DC7CC415B
+:10D3B000219F437AF98CE3C59127B2958F077E6C44
+:10D3C000DCF1AAB79D8F3BDE69C5773BCEFF742B9E
+:10D3D000B7334E37C8134371C63F2BF44FC7BA9DBE
+:10D3E00066F2AB64979DE4CF03CED14793BB6169EE
+:10D3F000A6FC8595CB45BEC30FBC9908E795CE9B8F
+:10D4000019CE6735C247E767AAEE00433B47CDF424
+:10D410008F40FF499BAFF6DEDCCDC4427AFC2BC1C6
+:10D420009E18779D92FBA582FAA57599F15C47AB92
+:10D43000E23E9006E3B596495EB467BBD29971FCB3
+:10D440005B7CB2211E86B1675CD705AF89F0E934F9
+:10D4500085DDD084396DAD99E4C8799847C9A09429
+:10D460006EDADF7E64D9965E78CECAC5BC12BE770E
+:10D470007A3BCEB7D078C92C36CF9ABDDDB790892C
+:10D4800023C0F8DEBD17E312F6016C009EDF713396
+:10D49000BB17EF57784C9C7B5CEB0C90BE4DC837AC
+:10D4A0005E7EEE458B13258F560CE762527CC67A62
+:10D4B0005ACC39484D5ED3113A80FF0471EF43CA0C
+:10D4C00078BE7E8C57F5CBE89C6F4A3AF386F1FD27
+:10D4D0006407E5333B1C7C7EDA7C613E240F004C04
+:10D4E0007C3EF96D41B4C3615E317CCCE8DC13CC89
+:10D4F000EF78CCFC0C76DC1D56A11F14A6A01C7185
+:10D50000585B9980F305639E699061DE4172075C08
+:10D51000E13D8C93234DB560DE821BBDE03CFA5E9D
+:10D520004CBF9E6EFD79B1EB85DE28CA64F974AEFE
+:10D53000B0B91BC9ADDCDA127602EA523DA78FBE44
+:10D540006B19D17DDF88C8635965277B4CBB774059
+:10D550005258502DE8A43780C80A3C17AAAC019A4B
+:10D56000817ECD9112D3BD00D4067C05E3DF6BF53F
+:10D570003D68857675B704324DC37039C5AB5A8A9C
+:10D58000E814EF408C309996FB5A0EF62251C3D81E
+:10D590000DF8DED782B45AAFD54120E27D0BF5F607
+:10D5A0008EBACF0A72B23E97D757AEF1AD5A03E3A7
+:10D5B000C94EFF4A2BF2B1D53D88F62FC2D776EE81
+:10D5C0005D9BE7804DE1523B4CE2E6080014F0DF42
+:10D5D0000F7990ECE4563312C96687560F931DED10
+:10D5E0006F3C427E7965C3117A6FC23A947DD2C294
+:10D5F000A5D9B0CE8DD65BCA3207C2788D73334DB4
+:10D6000020A27F63BDA54549D7C3E156031C9415ED
+:10D61000D35B0E8ED3C3617A0BEAEB6B85C36FD6F7
+:10D620004C5FB5A6E7B5AF3BCBE6DF8A7899546C83
+:10D63000223935EAA883FC35F8D9283E25C6D99089
+:10D64000E0DCA3668F6BED343A4A442779CC3D8801
+:10D65000EB1723BDD4637E37C6EF02016FD9F04EBE
+:10D660003A65EEC0703C9F9E65BB3B6CD5C5F52608
+:10D67000152F9573613E943303CFD36B83B6FE4071
+:10D68000A7E93E13E52367D90207705DAE99913093
+:10D69000E6EA8C6281FBA5BC4E7AD7BE53B78BFB02
+:10D6A000A975734DA115240FDA245C7727DEDB62A0
+:10D6B000F01EE1786F3A4678AF6A3EC6F1DEB4BC40
+:10D6C000C42EF637D00FAC67916188CF0FD6549631
+:10D6D0002940D77D922275480F2A5B5C566E23B88D
+:10D6E000BF8FEBE90277313F0DFE89F0567F30F7AF
+:10D6F00047F9E8271D32D17E8606AF8E76369E77B3
+:10D70000B7C71EF80B7EA77A74DBAB28DE771C7CCC
+:10D710008BF6D55D87A6EDC5FEAE1980094FE7777C
+:10D72000EB0FAD2841FAAF8F50580DE44C248876AA
+:10D7300047627870BEE88047E331828F09EBF07C66
+:10D74000AB389752D424F950EFF64902BB04CAAF64
+:10D75000ACDC2F74DA645A8FD3C6F57BFAA17D3224
+:10D76000FA1945AB4CD43E1DCB7CFDFA57897E8A15
+:10D7700021CF4CC3A74647403849B7C09CC72407B0
+:10D78000CCB6917ABA494DCA85F7A35AEEBE1FF5B9
+:10D790009BD6EF27CB98F71EDDF972A09F13067A70
+:10D7A0001BA2DA106E5A7BA44B7F9C7B17A05F37BD
+:10D7B0005B3AFF0EC655B7B72C95E99CE235E2B54A
+:10D7C000D0C26A70FE8549AC6607F42F4C8612EB16
+:10D7D00069A2DE5DD4B345D9473C1FCCEB791F7AF3
+:10D7E0004D9203E3343C6E38D426F67315F720E4EB
+:10D7F000A3A1361E1F2FCAB493FCD7F8550170E2BF
+:10D800007EA322F61D7323B926C4A3C6BF4AC4143F
+:10D8100076821ECC553C26DC7F7E7D19C041492C8A
+:10D820005F6E1EC8CF8FC53E1F6B3319CE83FB3A88
+:10D83000CF778E453C555ADB7E320DDE560DBC4807
+:10D84000FB3F2B92AAC65EE91C78EC3C5EBFFCBB9A
+:10D8500024A4AFE6A825EE799107C4FA0F2E9B49C0
+:10D86000FD1ED6CE8308BBE55B249AA0ECCBE34734
+:10D870008596A0928AFA2F89C73B0A93B87E64DD09
+:10D8800073E89E8C42EC8BC2FABA4194B752981658
+:10D890002AA7FAE03CC6F33E75F98516D6615F11FA
+:10D8A000CA73119F819578AE86C93934FE8DCC68D4
+:10D8B0004F1566D7ECA7F7961CDA8762516EDF68C2
+:10D8C000F6D078B1BF52D8A7BE8CE699CCC72966EE
+:10D8D000C6F3C385D70515BCE782E5E5D0BC4AADE4
+:10D8E00031EF07F3FB45B4758CEF6247D57BF19EB2
+:10D8F000914903E67ACBC4F38BF06F1F0B9B734BFC
+:10D900007EA77CBFC97387B7CC607FD47B910FDFC4
+:10D91000F85A9E136F1FFCB0E0FB83CBFC5EDC6FFC
+:10D920007CCE06F800BFBBC423AD727AAE0EBF58E2
+:10D93000BCC5C2EF5BCDF3C97E8B855BF187DEB2E0
+:10D94000544F5738C5C2653CAB1F40F7D70838C79E
+:10D95000C2E5752BA787D7F32D21F42F5E5700CE94
+:10D9600080AFD73D12F91B85E27E0D20724E2F1A33
+:10D97000FD24E5707A4936C23D16BEB1F0D4E4C04C
+:10D98000AB082FCA2FF1958FCFE85C7F61F79A968D
+:10D99000141DBD68EB2FCC1674BAA73F9F8726379E
+:10D9A000AE137244C80FCD5E1E2FC6037B99ECE107
+:10D9B000D27427C5654B2BF938A5FD1C1B31BF81DF
+:10D9C000856FA47CD942267E516EDF823DCAE9B3C1
+:10D9D00079C229F4AFFB5802AB9C18879052685F5C
+:10D9E00009E07E3C06EEC78D7037DAC9B170780E5B
+:10D9F000FF634C577869F4D6621376750FD613ED32
+:10DA0000DEA12F8D4846F9CD9A53E3FAE9A38EFAA9
+:10DA10003BC611744B7429B140C77337D041D380D2
+:10DA2000D58FA13933D65A2F23FD8D65BE34BCCF97
+:10DA3000049364719EDABC864BFE77509E8D699B81
+:10DA400098A6BFDF44FBBE06E77102CEE358702FF5
+:10DA5000C651C631E5AFFA788336DE9F6C22DE9080
+:10DA6000CDB2713D45B83990DE399EB6BE3E792CB7
+:10DA70004CF7DF48563AA707FF0B9A533BBFA7E581
+:10DA80003F4F724EFBD44672B886F13C9F3021B1B5
+:10DA900048BC2F12F78CB18892E85E29F64D52E708
+:10DAA000FCBEB0490ADD9321E677768B3588F946CE
+:10DAB0000F49814BF89D33D2A1A1C4AF4AB83FDDD5
+:10DAC0003311F3FE62534B15BE8776F3A99D58D7E9
+:10DAD0006299C77923BB2C749F4F42FBD30AAA4B90
+:10DAE00027078AEC5C8E8CC7785F1EC90B05CBDDDF
+:10DAF000E779DE7871538182DF397081E759973099
+:10DB00009F827ED78D51A3BF76553A75C7C66FC425
+:10DB1000BD444AA437C255B3CBF2ED81EE76C0D7EF
+:10DB20002A21DF9ACF4FF020BE360E1879F37468A1
+:10DB3000923B70F834342B4CD65615F5DD5D82AE31
+:10DB400046235D4964F56874E5B1A31DBD2686AE24
+:10DB5000DCA9063F6E160BD381C7A21AF592C11F2E
+:10DB6000147648AC7DDE6997D7C7F5E7580B38A81F
+:10DB7000403FB3057C57A5988328B794FB78BECF68
+:10DB80005D8CF5C63CA0BB6A5483FF393B4521FC44
+:10DB9000CD5E6EA33C4FBC376A2ED403F09CCE35CD
+:10DBA0000CE0F74875E0B356D71FE9C09141743BCC
+:10DBB0005BEC87FF49E27EF8EC944FD2C9690FAA6B
+:10DBC00017F4F419FBFD84E3C6F45B25F178CE2A43
+:10DBD000D597E9D5D91B13EDDC7EBAE02E5B67BA89
+:10DBE000C2FD06016B8F7C45771F505B8A7566BC52
+:10DBF0007B24B4F1347BAF28C0FDF044E3F68D9470
+:10DC0000911D66FA795846FBBA6F84913D5C14F118
+:10DC100099E619EC72EE8F76B1CBF13E03A82F692D
+:10DC2000DCCBEDF286E564DF2F01FB1EE5F906DCB7
+:10DC3000F3ECC1F884F2C95EEFF02B31BFA5A84127
+:10DC4000EAF03B15C07B5E3D6FBFEA9171EAC30A03
+:10DC5000FA85814CD58BE18192D556F073EA7298A2
+:10DC60008D819FB3C25E327E2DFAA5A93E89A55053
+:10DC70007DB523EBDAFDD855F6E2D5E8C726F227C5
+:10DC8000ABED1E825F227F5276FA57D975710090F4
+:10DC90008B71ED8F49CE9235D84E93170F9BC27979
+:10DCA0003FED46F941945F7173EDDD64EF4FAEAD2A
+:10DCB000F0E2956EEDFB2EF7C7FC8A2281EF5FD86C
+:10DCC000B93D599DC4ED48490AFC02F9B375C0D36A
+:10DCD0006B0B803F6635F1BC0DDB75977BD37D40C8
+:10DCE000239FFE79018CFF5144A1F842B393C79B57
+:10DCF0003F6212D9AB45472CFE46C0C365905076B3
+:10DD00009DDF729995519DF5CC309C0FFE88EDCD2D
+:10DD1000FB297C2758C3F3942ED4E42423DE9B559F
+:10DD200063FC77AB9DE7B76D15F4370BEF8D1C8E59
+:10DD3000EDC2D9787FCB2C25AC527E46D4CCEF39BE
+:10DD40008479E07C9A6DC67176DAB9DFB5D3CEED11
+:10DD5000F859E2DEC9665BEC380A1F5FDC33170B4B
+:10DD6000F7347BE98BB89ECBCCD744780279857A9F
+:10DD7000A16844CB51B417AEAE7F7C12EA9FEACBC8
+:10DD800052B80FC6A71B55F2DFCF8873E2671BF7A7
+:10DD900067DC0D65E5F63FB8D0DF7B4DE0E9ACD23E
+:10DDA0004AF7BC2C795EA67B0AE0BB19DFA1FEF323
+:10DDB0000AF9392B7E4E48D3CB055FEFCFF6F3E05F
+:10DDC000209DFBD1ECCE71D66008E7D7BC5C26B9AC
+:10DDD000017ADB70EFCF8DE2DE9F587BF463BB16D8
+:10DDE00067CEA0BC9F07DCFC3B89F8BF289ACA42DB
+:10DDF0003AF950A484659C7F5134838500BE670F37
+:10DE0000E63E568EF4CA546F3F1C56612D640F8B4C
+:10DE1000FD1BF8B5E0FD74BB45654FE3C5E96389BB
+:10DE2000F9DCAB06439B6F8503DDC83EC610686115
+:10DE3000A7DD7763D418578DB5934B9A87AD42937E
+:10DE4000F20C3E40FA8BF07B91BAD8CF910971ED7C
+:10DE500066C61E2538143C9F3709EF7B2978CDE430
+:10DE6000C6EFEE41BEC6787EE345BA8FA48A856FC1
+:10DE7000C3F7558DB23BCCAE14CF5AF5C68D308F5B
+:10DE80003D11C583FCBF27D2621D4A7513C5318A77
+:10DE90000E170D46BE6D8E2814FF2F3ADF92342FD9
+:10DEA000BFD37E69BE6CA2E77B2EEFA3E7DAB8CDC5
+:10DEB00091D4C1A88FB79BB83FDDF2EAA52494A7FF
+:10DEC0007B2E5F48E3F70F2DD7EE058AB59B092E11
+:10DED000A54EB923CEACB7D3995CF436E62B8D4F63
+:10DEE00056994C78E0FE6617FBE343B6CAC9BADA26
+:10DEF000212568D7C871EC914E781BECE7FE49C22A
+:10DF00007EECC50AF03EB7A6CB698BE95C677392DD
+:10DF10007B05C59DB8FDD0DE72FA6793F0F92199B3
+:10DF20009FEBBF2C133FEDDBBDB84F9B430FEF3A88
+:10DF3000C2DF1759E7CFBD02EDBF3860A77839536C
+:10DF4000BC83E3C5453AE3C4E11E7C7F2BD883DF65
+:10DF50003FC3E300DFEA8C0314258DE4F737A15AB1
+:10DF6000EABFFE9819E3287BECFE6F2511DF34240D
+:10DF7000A19CA8B073B9146425D96024B1E70F9AA5
+:10DF80004A904E462CF710BEB7AA604A215F6CE655
+:10DF90007EFB563C070AE32C6CA837E7E8F0BB5041
+:10DFA000EC377DAA067BA7EA9EFF3E89FBA59F1E54
+:10DFB00058F414E523BC6F61FDE2D89FA1242E071D
+:10DFC000779A8393B661BBE3263AE7D1F2EACBAF07
+:10DFD000F600FC2E3CEA1986F27F599287E0D57450
+:10DFE000686B5D0F68D7F4216A4930B937CD954D1C
+:10DFF000F0DD579887C7F3DE36D17C3BE29F6007A0
+:10E00000E27A7F20E6F3CA419361FFEA153BD76BC2
+:10E0100095492ABD9F97C4E3693B0E96A461FEE92A
+:10E020001E7B603EC2B3FA93B63A97A733FEA7D9D8
+:10E030008163DEDE316908FCE798332637A2CFF32F
+:10E04000F64619D7EBF994B114A96B7C0AC6AB411B
+:10E050003C68E3BD72868F07F3D887FC1659CEDC87
+:10E060009497C9FC3FCA87FA2BAD4A2AE62D6D1555
+:10E07000FBAA1A1EB4F568F3F03430DF0607B18648
+:10E080006FC795E2CC223F72B8909B5FDB7DC124C5
+:10E090001E07247BFBD30376B2BB768A7835CB9CF4
+:10E0A000DB07E1A7E169BD2863E793E8FB8F2771F0
+:10E0B000BDA1955B554F90E8E179AE6FB73AC3D6F5
+:10E0C0003C947F2FE551DD130C260DC53CA8A67EA0
+:10E0D0005EDCEFC3FCCF24DD3EEB3841E79E868853
+:10E0E00039478787C4728DC3BD837E9406A2ABA6D1
+:10E0F000A38CF86DD196FB787C11E481B8CF89F6BA
+:10E100008F912FC43E7296C44B17F2C998E60D2B1F
+:10E11000B33D74BE80F66D353878902FA0DC2DF0BD
+:10E120008270C1F72F89756BEF5F14F01B2FE72703
+:10E13000EBF31163CB3DCB3229A6A8D55F12F35F79
+:10E14000C81E253B74E1E57AB24F3D35BC5CF80052
+:10E150002FFBAF9F6BC6F8EFC275F1EFAD1B95C4F7
+:10E16000ED97B3820F98C9DE03F3393AF46312D7FF
+:10E17000AFA71A1FDB9F4DFA24F02AD2C70D4D8F8F
+:10E18000FE12C1A4D1FFA94D2AF5D7E488D6FF0D10
+:10E1900031FEF36F73FE19B3492DC17B8CC6049910
+:10E1A0001BE3E4AF6CDA2CA35C7F05F92387CB0D6E
+:10E1B000D4C79F1E7824E921A483632686F1F89DA5
+:10E1C0006656B15D87DF960D2F1AE4C1A22DCB27CD
+:10E1D000E138A3DA522594FF9A1CD0F0BDD3ECBDF0
+:10E1E00089E4C994187952C6FB47053C1F13F2E431
+:10E1F000B189204FE051CAA61409C7D9698E7FAFF3
+:10E20000D5671ADF097A1CDB29773FE372B7CD9512
+:10E2100007E3544DBE40F1D78EEF08BA7BAC4CA358
+:10E22000BB1C09E108F6BCA92FAE1BE083F40FF676
+:10E23000FC9C69F9C4A50715DAF711FB48226F8227
+:10E24000384CC7BF9A9CFBDA1EF81BF2496159CDC6
+:10E250004AF433D2CA8344D7A7A4409F54D057A7C7
+:10E2600090AFE3C885E3623D5FA8813EEE38EF3BA7
+:10E27000F988F5403EA8600113AE83AD97DCFAF350
+:10E280000F9EF59CDE521C92217F5CAB6BF0BA9125
+:10E2900075DC3398E248273D65C6BCCAFE21AEA7AF
+:10E2A000985442F4C84C37F7407E3BA532A29F53A6
+:10E2B0002017116E0BED463F445B574F07E7AB2F1E
+:10E2C00052F83AFE28F88E7CDC91D48EDB59C526B4
+:10E2D000DA8745FA207A9B924A7E0A38460AF17913
+:10E2E000C73E435896B83C90711E6EF4DF280EB4BA
+:10E2F00081E7856DDB40749332D14DE7191E53BC25
+:10E30000B6145D1CB765F3E3E437223DE11C12D17E
+:10E310006305D2238B438721A043E8973AB186F067
+:10E3200008F81DE5807153CA0232D24D2C7EB5FD2E
+:10E33000430D1E3B63F61BBFE7E07C3951949E04FE
+:10E3400079279D7AC2286F015FDFE6F8EAA46FC4DF
+:10E350009BC66FC31D57A6F39083DF075EF7D13CC2
+:10E36000CAF7D0F699B47D63EDFB77087A49B44FCC
+:10E3700094650BCC7418F6A396D27E97C627DADF85
+:10E38000A558BA99E7BD6DC73708F7167B487F5E79
+:10E39000CFAD301FE2B3C29143DFD3F0EBA935B369
+:10E3A000BEE02F7C9133B7055F7DBB35583E04D668
+:10E3B000B1DD1C9C3199EC6EEF4D38FE4DE526F732
+:10E3C0002312E60BB8258C771089235F1CE2DF61EE
+:10E3D0001EAF61DE4B05DC353C697048A4AF12E12D
+:10E3E0002724E0932EDEC7F275B983F373BEE35A98
+:10E3F000F93A2823DDBB586005DE3FCD8AB81CEA18
+:10E40000E0EB2246FB886BC578DA73AD1E87AFD789
+:10E410003A46EAF87A749B91AFC1C215FA94F82B88
+:10E420007D93CAF368059F7D61E3F3FD9583DB630C
+:10E43000E9A83F007FE941BE9FBA54D0195010E5CA
+:10E44000E5D56FB230C483C6F7AE19AC44C57D596B
+:10E45000D437D86A46E0E838DC8FCD347B707FF85B
+:10E46000941A213C9D0207B59EF0E9A73C935307FF
+:10E470006EE0F2607287FEF1E17E4FF08F3DF97E33
+:10E480008EDC4C74BD743C23FDD1B27914D141456E
+:10E4900079AE8474B6684B8A84EF53CBDC26592757
+:10E4A0001747D59A58DFE144B7CF3974727154B029
+:10E4B0004646B8F4490B64AA29603738E64CD0C701
+:10E4C0007F5E81BA3EFE03F5BABF27FEB37BED5DEA
+:10E4D0007518FF694FF235233EB26CFEDDF8FDC2C0
+:10E4E000EC1A99E9E4C5D5ECA66A113FFA70F5EB90
+:10E4F0009BE7C2BA673D1C598D6FE7607C7500E6EB
+:10E5000005F0F86A75F3118ABB360B7E1E2EF90FE3
+:10E51000E377EFAAB9C918678D5CDB77BB09BE65E5
+:10E520001F32827F377F8D8CF1084D2E7C807F8F4C
+:10E5300081FB8D12EEAB69FC807205ED4F2DBF01A2
+:10E54000E35ECED44EB98CF5649D5E5D5B6E8A7BD6
+:10E550005FED6987C3A0B73439C89AFFF6C243DAC2
+:10E56000BD995C2E9E76E8F4FE63E5C7E93C311365
+:10E57000F7D0DD2F7CC8A756787F7F5DB7CE73ECD0
+:10E58000C32CE620E64F82DBEB71EBF261A5662936
+:10E59000ECC43CCB4BE8B900FE2E99A87CEADFFD29
+:10E5A0001373D08F6F3279C112C03C09A2636F1F01
+:10E5B00046E71E1AC43E6CF17E874F1D81F7E65B6D
+:10E5C00049FEB5EFB50791AFDB9D268A1FB7ECB2C8
+:10E5D000105C2FF6B50BBF3A64F0BFB5FD0D9BA5DF
+:10E5E000EDAD22E8BFD1C6C7DDF8707FBA4F23D1A9
+:10E5F0007E77516D2EC5F3B4F8626EC463E2496153
+:10E600007C7C25C2685DDAFEF73ACCBF189138FFF2
+:10E61000A297D3ACF94B194EA4C3996DAFE2DC625B
+:10E62000FDAF8C43C7F7E23819B53C2CB0EED052A1
+:10E6300009D7B76E567CFF4BA39F7522CEA5CB732F
+:10E64000C873EAF5CADCD4A45C9DDCD4FAFD52E4BC
+:10E65000398C6AB97B27DA77C0D7694E1D5F4F1AAC
+:10E66000B2DA166FBFDD5FFB10C53F13D1BDDFC44B
+:10E67000EF5B8A7D3EDE29EC1825D283ECC03D5F3E
+:10E68000D83D71F21FFCBB4CF47741B4784CD7EF06
+:10E69000FF3BCDFF4667C7BE5E8F6BD9D78B9D779B
+:10E6A000ABCA7AC5D327B17993DAF7E2F4BF4B7FCF
+:10E6B000EF81DFCC02DB1D5DFB69F6AE5FE2F74E5A
+:10E6C000B18F18E9558D4E00EE7720BE861E9E371D
+:10E6D0001C43A9CC5A23A31CB8D8D4928D71AA4448
+:10E6E0007EA1361FF8F58B1767F1E3BD4A71D67727
+:10E6F000BFC0835FE5F6A7547CE03B382FFF79B3BA
+:10E70000A43F8731C72919F8498B83369F7F773813
+:10E71000C947359C1D0F7EB1FB96733068C5F51C4B
+:10E720008783804B5D312BB174A33801DBE841FF57
+:10E730008FCB494F2D23FEBE5EF2D1BA5738B95D5B
+:10E74000B38EB5525EE3C5433C0F79E87D1EFAFBFC
+:10E750005CA00F8248B7A35860A74997D7A5D143BB
+:10E76000DDB3609F18E2559C7F34BFB59788FBF4FA
+:10E77000C47B4274EDBACF0452D5C9FBAC80952955
+:10E78000BAF85A7685DB50EF559369689F190C4BA0
+:10E79000C85799B51EC3F34E39C5D7DB2BC836A071
+:10E7A000DE5FC7DA687DBDC57CAE9702441F170FD8
+:10E7B0009D48C5386448E003D6FB24ADB736705198
+:10E7C0004F1FDA7AAFB6AE0F97C17C80EFFF847E21
+:10E7D0003994773D704CEA4E707753DAEF1CD1AF25
+:10E7E000D7F78F90FFD8ABA695ECF7D9B57B25D49A
+:10E7F0005B2037A8DFBA65562A7FBDCC4D3254C3A3
+:10E800006F4F68877947DA7DF089F4D22EE735EBD0
+:10E81000A55DCE387AC9648DBC86FBDB95CDB20789
+:10E82000E960E5F753297FE2A9067E2E717F33CF99
+:10E83000E77BAA8EE76D6BDF3DF77C32EDEF9C1333
+:10E84000FB7CCC7729631AED7B5FCAC0F3451F3B85
+:10E85000026FE8E5E053CD9FDB505F0CD6F26463B6
+:10E86000F40B0A5E3CAF42671F25B47B86AD917105
+:10E870001DB70586634A1BF0F73B9C3EB91EFACDD7
+:10E88000B61293FE9E8E8B4D7F9DBDCFD3B96FA4E4
+:10E89000ED2B69EFB57D27490A7CAC97EBB1FB4ABC
+:10E8A000B1FB21B2CB4A79D65ED9EE958D7A95E847
+:10E8B0006E653FAE3757EEB513DC56F673D0FE2DBE
+:10E8C000CCF70CCEB705F4169EC3BB78D441EDB49B
+:10E8D000F9C37C871ED2CDB7DA1499BD4F8A3BDFCE
+:10E8E000CFF570EC3A5F633EB2363FD9A9D0BCDBBE
+:10E8F00099DD8B786B30F3FBDB826FDA291EDAEE61
+:10E90000BB64C37B83DBD9251BC6694F3B02920BDB
+:10E91000BE23F78AB8D00FD9DF7C7120D27FA27DC9
+:10E92000BE41CE1215DBC33AAD588E72072E6E6310
+:10E930009CCF0257E837C959E2708DFCBBD69FEED9
+:10E94000BA22BE8CEBAFC6BF83A2B3A324216F63F0
+:10E95000E94D6ADEFB15C6F581BF285F34D89B857B
+:10E9600056029CEA8608BA9BC1C4DF4132D2C3C7B3
+:10E970000E7F3F5CAFC6975780CF409CF75B0EFF82
+:10E98000606C8FF3C0F33C207786B8B89EDA894775
+:10E990009635FBA94F1E97639114467926B1FBB3B8
+:10E9A000939CD34660BFDC011E13DEE3FE77D0FBF1
+:10E9B000B82BC32F4C792ADA79E24ADC27C4737C5E
+:10E9C0008DEA19E3DF4B32C2E1B4C3FF6D1C375847
+:10E9D000D249572B3D5784C72484C35B8EC0142C67
+:10E9E0009D2AD00B0265F45CFAFB555936DF2ADC10
+:10E9F000BFDCBA9CC3A1FD590E87ED2D26A2E30D05
+:10EA00006C10F1DF20D385D9383EC8979938CE886D
+:10EA1000D67A13E6F3F50B794C748F536B83C97474
+:10EA200065BA9D25E8768EC0C3FD8887C1DB785C1A
+:10EA3000E50A743B4FD0EDB5C27D89EB8A7CDB855E
+:10EA4000AE6AF47475ADF9439238071B3B1E636DD3
+:10EA500014BFDFFB9285E477D50E7EEEB76AF749E7
+:10EA60003A2F5AF5B28588B2EC651B3FBFD2C8DF9A
+:10EA70009F2B8EBFBFFC6F2EEE5F5536DCE7D5EBCC
+:10EA80006BCD0EF8A9EF82BBAFDCB94F9736999FDB
+:10EA9000075969D3F241F97E9D4BD0595A2FBF0FC8
+:10EAA000F54EDA781E177239E6D37E5DD7731F9C58
+:10EAB0006FD3453FB7DB43F640EC399074BC179CED
+:10EAC000EFBB12BDC826BB17F72DD326C6B4734CB7
+:10EAD000A4FCB9F498FDBC904BD8C166964972D499
+:10EAE00016FFBC9792ACD97376935E9EA09CA7FB51
+:10EAF0007A9C565AF7D27496568EF101A742E73D9A
+:10EB000063C7D1CA149FC9709E286DA2DD705F468D
+:10EB1000BA3FD550EF3EB387A17D5620D7F03EBB1C
+:10EB20006290E17DAF9A0243BD4FED0D86F639400C
+:10EB300070FA7ADE9A9B0DEDFBD54F33D4AF5B773D
+:10EB4000A7A1FDC0D0DD86F783B72C32BC1FD2B0A1
+:10EB5000D450BFBEE921437B39817DADC159D6EC8C
+:10EB60006BE788009D1F735A25BD1D72D8C5EDF057
+:10EB7000629795E0BF5AE8E3D5E2BCD96AA18F5B02
+:10EB8000D20BAFB8BFF28FFA63675DC6B8578988FA
+:10EB90007B9DDB673621DD57ED07BAA0BFCB15386B
+:10EBA000EBE2F6D794B9B47A7E8EB235413EC79780
+:10EBB0002ECDCF03BF248E7F674AF6C4F5AF40AE9B
+:10EBC0005D72E9FD205623A31CD0E452751223BBCD
+:10EBD000ADDD15ED8F7C04724A4A4E47F9F458CDED
+:10EBE0003E944FCD16924FAF0F38417EF5CDB5F321
+:10EBF000092E875D3C5E2B9BBD1E7ECED4A8770F71
+:10EC0000A9AD94A77D68A4CCF07E948BDE51749E50
+:10EC100039113CDF44BF1964D77E940D23AFEE77E2
+:10EC20001E5A5641F9CC89C63B34CC4671CFF29876
+:10EC30007B7007093A2A4B16F0B470FFF1EC0B4ECB
+:10EC4000CA2F3E5BF00EFDFDA2B38D7F181EA4BF40
+:10EC5000D7D57A3FEEBF07FFEAA0B84CF9B0778668
+:10EC60002F27BBD6C7FD37F177C1C6BD78D8857EC3
+:10EC700077F9F6FDDD823AFCC5FA6D65627D4C6977
+:10EC8000EB4F79A1AF9CA2BF1B53FED2816E3C2EED
+:10EC900064CC5B89F5D7CB6BAB086F5ABD326A3554
+:10ECA000E4AF542AFCDC6F65D441F92BAE64A33F7A
+:10ECB0009F105ED708CFD8E71A3C0F0D3BC5CFAFEA
+:10ECC000DBE2D36F4DB2313E1C7BAE2051FEFAED3C
+:10ECD000A2DF45EF183A075F6E0EF7BD96F8820681
+:10ECE000A7D72F2FA0F30A2F2438AFE04FE671F7F4
+:10ECF0001706DC4B79C763AC35A5A8BFC788F86594
+:10ED00009CBCE37B9247623EF33F27EFB852C38F30
+:10ED1000C8EB1D837C9CCEBAE41D5FED3CC824BCCF
+:10ED20008F3B0E7FDDD401BFF767E0BD4EF73FA1FB
+:10ED3000521ED002984310E3261B548A9F1EBE6CBD
+:10ED40006118CF3EB95E7D1AF3552A9ED8DFF331A4
+:10ED50008C5F0FB3501EDD820DFC3E1036CC16C208
+:10ED60003C8D8A0D0F66607EE467C0B74B605E0B1A
+:10ED70009E48A73C9EC32D8F64209E4E097EAEF810
+:10ED8000FA87B721FCB79BDD838741B9649B64C8D0
+:10ED9000035FB4C966A86B79401AFE98D4991FEE38
+:10EDA0000139FA78B2F17CCBF0CE7D85C793853CF2
+:10EDB0009D0EF3AD1A79D18C78DCFFAA9DE6BDC714
+:10EDC000C1EF570B0FFBF28DEBA15EFAB5A2DDABE5
+:10EDD00063C82B62B80981F79C88FCBFD297948ED8
+:10EDE000FC7CE13738C6EBF2A0C3CB6A886F4A7F60
+:10EDF000C5FDE2521BCFD74D986FC4BAE4330F4024
+:10EE000079DE25CFA8F33C84C12ED1E8A63159E4A0
+:10EE10001B09BEDEFF2ACF2B9A7F48D89357919BC0
+:10EE20006FE2BC15C4D7EBB370DFF1B080C6E1CBA5
+:10EE30002757D13D44A3258CB0B19397E3F38D5967
+:10EE4000939F98BF3FA0133F93BD0B3BEAC89653D7
+:10EE500047DF67385770EDF2E6CAF2A436999FBFD4
+:10EE60008B95EFB174FF7F4ABE970F3BD01BCFC984
+:10EE700043F99F745E7E3B978FB17C1E2BCF6F8AC8
+:10EE800091839D72DC6490E337097DDE29CFCD2428
+:10EE9000CFC13CE3F7B7142AA19512F93D5FA0BE9C
+:10EEA000CE7778D28AA1CB2A776E52E0CA7EE82547
+:10EEB000E493765BE06B2CFBFC6610FD5DCFC1DB61
+:10EEC000EA4DC8BFED09EC8FFF0D39A0FC7700803B
+:10EED000000000001F8B080000000000000BCD7D2B
+:10EEE000097C94D5B5F8FDE69B2DC94C3299EC2BE5
+:10EEF00013761570801010A27E4900A3101C5001DB
+:10EF000035E82490842D24205AFA6A5F262460C4B0
+:10EF10006843B58A8A7650F051450D8235B651273F
+:10EF20008014AC4BACB6A5AD621044362582FAA76E
+:10EF30007D2AEF9C73EFCDCC3799B0F4F97EBF7F7B
+:10EF4000FAB397FBDDFDECE7DC6566451B181BC3D8
+:10EF5000D8B32636BBD506A902E930C6CEE2DFD546
+:10EF60008CC5380A66452731B6DF0A29D463CCEA56
+:10EF7000383494B15C6660712A63258A37C601E52E
+:10EF8000D5D6AE07CAA074C96FBE354311DB10EDEC
+:10EF90004D352632E64B37BB37E504FB93699203C8
+:10EFA0002A41BBFE2B0AD9C104C62C56E68B1AC5D2
+:10EFB0009862643ED3281CC7B5D200ED8D4D8CAD50
+:10EFC00081F6B17646F36443530D2C99B13BAC8C7A
+:10EFD000FE7C850C27C37C3BA2FD0D0A63DF332D2D
+:10EFE00003E7F303D3321D50FF23A665615E8EDB7A
+:10EFF00028D6693430EF565BEF79CD74287C1CE657
+:10F0000019EC81312B0A9937141E322D7018A95E24
+:10F01000C1C337677741F9671DB76433E86FD7AF6E
+:10F02000C6C67545A82FD3B575B5EE89D0F4FE3A9E
+:10F030002FA5F18C69389F5FD4CDA7BC13F25BA1DB
+:10F040007D85D933383EA49F818E788297A3E04F87
+:10F050009E01009743CDAA437141CA0CC5D8FEA0BA
+:10F060003FAE78BB6897A86BC7E7A9328DB101B0F6
+:10F070006E9BF15F5D02766719AE9751BF7DAD73F0
+:10F08000A683D38799B9ADD8DEBCE33A2BE25755B6
+:10F090003407E6253D5C0123203DDC839FAE606C98
+:10F0A000B4E2F538A89D9620CBCFE6E0F8C594975A
+:10F0B000E3B34C58715ADFF0628A7613E2EF08D35B
+:10F0C00066627FAD66769903D6DB1ACDE6479A6F06
+:10F0D000A9C05FBA43D00BB3390E5F26C683F99D32
+:10F0E0008CD16EC77ED2A23C65D86F5E46AD6A8277
+:10F0F00026B3A21DA2BEA67886537925D663A99A07
+:10F100005202F0CEFB04E810B2DBF6142A2E183FB0
+:10F11000B173A2E282F11305FE7ACD5FC0ED25C680
+:10F120008A23CD7356349FE75201FFFD560FF1D766
+:10F13000EA1C6F6A2DF4E76A659A1FDAB5E2944219
+:10F14000E0F396C34CF5374477F954A4FB5B987B06
+:10F1500013D0414ABE4F31429A31B5A50030CE1A84
+:10F160001C4EEADF59EC4D55A05E7AAAD9AD2A179C
+:10F17000CE6FC35A35D50BE3E77A0D348F759DBE3C
+:10F18000A8C130AFE44E6F8119D2A2F864EA3F857E
+:10F19000D5D6233EA03D43BE1CEDE0FFCCF516AA1C
+:10F1A000AE10B8E4CDAB6D30C3F7EFA3BD6B43F940
+:10F1B0003163B18FC639AA78FB39819E8EBE193D65
+:10F1C000DB8FFD059C4447B2DE5388D724A487C259
+:10F1D00074960AFD6F34D1BC7237FEEA36E4FFDC68
+:10F1E0008DD718951039F38AC344F58FBEB9B01F77
+:10F1F000AEDFF7370B1B14410EBD28E8E5618187B0
+:10F200006DE6C874F59C1C5FD0FB04A648F9F79C1A
+:10F21000907FB103607D4BAA4F91FC6B76B8A8FE3E
+:10F22000E3C6D6DDE900D7C7E731B70F3E2DDCBC1A
+:10F2300041C1F56E33B75EBB05E7B5C4C0107FBBF7
+:10F2400076FF6E773AE4E7CF738DB4B842DABFFD4C
+:10F25000EC6AFCFEF87C3612E19AE65FAB18003EE1
+:10F26000DF46B5D0BABFDD6461F530B5C7373E9231
+:10F270006CC77A5E8303EBF5E22340B32115D3809C
+:10F28000C9308EE311E595C49F843BAE1FE5E2AE25
+:10F290004DAFD0BCE57C8050CC08F7A27817C16B8D
+:10F2A000E1E6ADD722F1A72F762A6A4E705EE7938A
+:10F2B000FB1F0ABEB8503A7C339EF331C8790DC7A4
+:10F2C000F3E51949CE7F62F3FE1DE13ECCE64A2804
+:10F2D0008029353AFAC77861FC7E03D8ED9E08FC98
+:10F2E00078A9BD703FD63F19E53D807CDDEFB94B75
+:10F2F00027B258C62EDBD262407C9C54B85EE8CD63
+:10F30000A7423F0ABD28F5A42C3F29E8E20EA12719
+:10F3100023E8C79391F4A38BB9EE1B06F8626F1B29
+:10F32000887FC3C75D2AE87282E62D427E9E1DE378
+:10F330003D83F3BE629C7FA70AF5C716FB7622BF0A
+:10F34000E72AB53BED0017762D9703095DAC0396D0
+:10F35000C5E2F77569B1909F8B7200C61F7F44EBC1
+:10F36000C0F1E23C4CC1F6CF229DC33A5A9CECF668
+:10F37000E911E8FD36B12EC343DD66D46789ED0A95
+:10F38000F15B6FF8707904F232261EE697D70FE42E
+:10F39000694E6F791A017FCE786877C996C00EAC36
+:10F3A000352A7E600C343B17FE92E3097F5A0A8EA1
+:10F3B00023F175E959F576CFB0DEF8CA8EE7F3BFD1
+:10F3C000D3AE6561BBCF843EE80B8FC3E339FE8AC1
+:10F3D000E2B99DF3AC5DD48BD2D72B8BE778A988AB
+:10F3E000D7CB83107C0F8F8F806F29C7B7ED7949FA
+:10F3F00045BCE54D6C69403C005E47E37AC6E7D703
+:10F4000036E0F784A95C1E86E355CAC370FC86E328
+:10F4100095B17A9A1FE0E3AAF808FA4BF613AEC743
+:10F4200042E404AD6B9DA04F1FD227E3FA68832D01
+:10F43000B80EC93FB709784CF07A8BCC9C4E4B7014
+:10F44000DC2B66FB779A904EE7FB769A43E97401D2
+:10F45000A3FEE43C32BA7CB49EB47DDE024CC71FEE
+:10F4600009740C837A29B5B01E165C4F56E7870ADB
+:10F47000CAABACDA4E85A1FCDCB383E69DD9B98B6F
+:10F48000A7A88787F5D6B78CAD1474C8FB79339ECF
+:10F49000CBD5D55FCC4D45BA595DC0F5ED2ABB56ED
+:10F4A0008EF3BEC3A1CD45FCADB36BF3303F2B9AB9
+:10F4B000EB85E1F15A257ECFEA43DF2F117000B8CA
+:10F4C0005763BBC4E5CCA7C03AC6EEB3F9415500BB
+:10F4D000E9C3BC614189B53EC50C704DD4981BE5AC
+:10F4E00074BF046FBD09EA755FC1DC4F413EAED405
+:10F4F0005180F072CE7777203C577FA1927DBB7A06
+:10F5000029F3AFA47E18FF3F6F7F3FCA57E4DF5057
+:10F510007EF18979F8E2391F80BDF3F378CE9F75CB
+:10F52000C49FC2DE917CD997FD12C2D7AB2F92AF98
+:10F53000EFBF48BE5E2BF8FA97949E87AF1F0DF27F
+:10F54000F53A9CD7F9F87AB3E0E737057FF7C5D7E6
+:10F550007F10707B27BE4F3F67338ED75B8E73BAA9
+:10F56000937CF1D29E5131E5D0EF4E31CF10F9DDD1
+:10F570008AEB3B9FFCFE37F8FCF7D8EFF9EC54D947
+:10F58000AFC4F7F9F864B8D343F092F668ACDD4144
+:10F59000EB917C0FFCB247F0CB5EC12F6F613A2B31
+:10F5A0009ADB07E1FCD5A3EF3AB93C014F2606E907
+:10F5B000478E7FA437BCFE12095E594CC0AB98CB76
+:10F5C000914CE65363B1DFA90ECA3B4E38EAD155E0
+:10F5D0008C3DD4ED43B87D1BCFFDCC5C857922D921
+:10F5E00075C7049F247616927C01781EC27125BDD2
+:10F5F0002732C714F473A29C5C6E8C1EA7ED44B92D
+:10F60000E4D03C2ADA1BB94ECE0F124ED0FE8B4806
+:10F61000F8D88EF818D6DB6F08C7C3A762BE514E64
+:10F620000E8FF0FEA5FCC1FE8753FF2E03F62FDBE5
+:10F63000FF109443DF237EC62EAF55715D894C8B3E
+:10F6400041F923E524CB84F6B9BDDB9BC4B8D0DEF9
+:10F65000E484746C2DB41F166C9FC5020AC2C339B2
+:10F660001FE41443FBDD4DF66C9BD5637312BD3074
+:10F670002EAF0A0C240FA6D934E2A748FADF7991FD
+:10F68000FADF29F4BFF342F4BF33A8FFB19D723E05
+:10F69000FD2FEA8F709E5B4EB87BF022E304BDF530
+:10F6A000BF3382FEDF6FD5A8DF087C3412D713E3A7
+:10F6B000D046610A7C34DA9914D43BD06E0C7E6F4C
+:10F6C00013ED9BA71A86927DCDA2DD91FC9942A7EE
+:10F6D0004D37AF2B859FC2DAFFFBB7FF91C7580D9F
+:10F6E00016F179163A43FC9607A77E9AEC253F8ED1
+:10F6F000E9E22BBF5EE97E6F088EF7AECA90BF7E4F
+:10F70000FD9F5D6684776B74EC0816171CB7E65F87
+:10F71000405860CF9FFC97815289C725EDCA680683
+:10F720000C59B0F33B8A939CECF817C5492EB5975A
+:10F73000CFC075ED7A8DC74B4EBF7DD0897424C77D
+:10F740005F26FCC849EAB0D600D0D3A9CD6637FA07
+:10F75000212A733D920FF3A9D963627E9283CC8AEA
+:10F76000F54D7CBACCB47975A71A8B79A34FC439FF
+:10F7700094B3A4EF5C714897A63D2AF9152C919794
+:10F78000D7326BFDD9FE2057C719982B242E12AF04
+:10F79000453357489C22A1D8A9CB338CA7C0B88B3E
+:10F7A000189F6792275DD73E65767F5DFD34EFA594
+:10F7B000BAF28CF9A374F9ACDAF1BAFAFDC03F0AD7
+:10F7C000CDE7F8AED3D51FD03443971FD4728BAE9C
+:10F7D000FEE7ACF6E17C5CB74FEB1C08F39C27E638
+:10F7E00039645DB9AEDDA586D63CE068362FB070D1
+:10F7F0002A1B01FCE85FA8EBE7F8B3C57B14F8CE41
+:10F800005A4C8738BC6A19C28BD60FF0AC6C53D8EF
+:10F8100063D0BE6A1D2F97EDE6B7AF5D9D01E9028B
+:10F82000BFFE3B637E33CAFD459BF5DF1F74DA13D1
+:10F83000294E93CED2CFAA91E8C046E39D5AAFFAA3
+:10F840002D803FD537248C0EF4F860FF4BBA700939
+:10F85000BAB0A4EAE922CAA5A78BAABDDBF202AC22
+:10F86000379C63863A23C251C2D9EED6D38B842FFC
+:10F87000E8C9FF13F8BE81F08D09C2372DCABB035A
+:10F88000F9EF74DB7295E1785EEF686CD797FC9DB9
+:10F89000622FDC8DF2E274DBD7B7ED80F5D5C47052
+:10F8A000FE3FB9E3BBC128DF64BDEB5694BB278E96
+:10F8B00006E02ADEF7B07FF9BD73E8D3CDA3603D43
+:10F8C000A56D2AF1F149A3AD49B99C96E97200DC16
+:10F8D000941EBC713C4ABC29ED3BFFA900DE2C30D4
+:10F8E0004313C61BC7B9AD384F8CF421BD286087C0
+:10F8F0009E8D217DF231CECF57A8318AF7FC89B990
+:10F900001BA056833DEFB2F3C4050E38495F7A1B46
+:10F9100051BE8EEDF49EDE82DD1B3B1D18FF9DE285
+:10F92000F5D27A2EC70982FDC41C00277BB03DB4F6
+:10F930003B8EE34E2970C6A0BDB575D732F2DF58B5
+:10F940007B22D9834832A1764EB89F25ED46B0D3AD
+:10F950004FF17978BE7686DAE9C26E93F6765FFD6E
+:10F96000807E1D8AF6415FA9B2431D6A04B8742BDC
+:10F97000D1EEA722E80D4B82DE9FBD3218DFB22404
+:10F9800084E88925779EDE8DFA03E01D9D00F3B49F
+:10F99000DB417F2B17A4BF63B1FE2331B144D7DD18
+:10F9A0007B55FF106870CAEA8A7302BCF2519F5CF3
+:10F9B0004E712096E10CB6ABB5A60F33823EC93F1F
+:10F9C00035348E9D23AE9E8FF54607F3ED514C677F
+:10F9D00017AC1EC5E7E512EB3C10C5EDACB1225FDC
+:10F9E00013168FAA69E2F1D70D6660B5907EC62620
+:10F9F000D879BCC75A3016D7B341C4A157E7286499
+:10FA000027AC5614B21B76DA0AA9FC90B3200FE19A
+:10FA100077B918672C8C81FAB9A5BF988FB0C764E5
+:10FA2000FFDDA27EB7B390D2B1090E8117C7A588BA
+:10FA3000FF0AAB46FD9A5535229CF313B8FD5313CC
+:10FA4000CDA49F46FC3449F0D76421478BEC204776
+:10FA5000B91F387512945F25F94FCDFFD00CA43B28
+:10FA600029CEC4305E7C959057EC8CF15394270ED0
+:10FA7000F81FCA276DA863178CC40A98E9D35039B8
+:10FA800053C83AD3913E8AACFAEF93B64F3E8AF20E
+:10FA90006F123306BFE77078C738837C7063428F7C
+:10FAA0001EC84439D516DDF5CB29E81FBFA3BA9F80
+:10FAB00062BDD75B91C0EDB066B4A36D042A0DE3BF
+:10FAC00097D9621FA5777D0E9F0D7DC4792BAC055C
+:10FAD0007311BEAADD538129B0C3A5C8EF6D666F4F
+:10FAE00003FA1DDD2F339AC7503FDB81F9E13E1742
+:10FAF0002E17F0EF8B1981743DD2407EBC6B5DCB2D
+:10FB0000CE282877AD579C0AE44D46E6B38F0ACA43
+:10FB100093C6841C9A6C7357F90E3B9427AD9FAE25
+:10FB2000F487F9B4B096A258B4B7D6B38871C13A85
+:10FB30004147530A76507C3DA91BE834021DD42569
+:10FB400018A41DFF9FB88EB1DDDED14AFFA03C2274
+:10FB5000518B7ED32E833F529C769AADA811DB0D3C
+:10FB6000F7B38871BF9A683E8F26AB670DD2E9F074
+:10FB7000ED01F287AAA45C9F676046A0AB1B841CC2
+:10FB8000BF617DC73FC98EF8EEEC5955DAA18CFAFA
+:10FB9000672897AA6EB4FB317E5FD59EE3A379797F
+:10FBA00014F720486ADADFF760BE2A37D78171661A
+:10FBB000EDEF4C393C944C58C6E59F911D967A96D2
+:10FBC000EC06748A189B21E8B906FDD124D21FCD1A
+:10FBD0003100FFAAF5F53BD2A0BF3F3F0D7D40D1DC
+:10FBE0003ED5BBEF67D0EF4DA0C4568CC2D4C84AF7
+:10FBF000290E9D4AFDDC28FAF1FD0BC6B506C7BDEE
+:10FC0000A97D2FAD679F89F9AC40BFA6423EB4E9FC
+:10FC10003FE2FC0D2808999FE86CA6B56512EAD76B
+:10FC200093E6EE116EB47F5FFB6B960FE0FFF1CFB2
+:10FC30004FDBD12EFEC4D86DC7EF47EEFEC0AE013C
+:10FC4000FC3EBE5B2D4678DF26F48D847787C07B33
+:10FC500042A2A70DF1727BDDF779DE10BCB3154926
+:10FC6000C43F0BFC30C310BB63D1E618B4847AF2F6
+:10FC7000D5AD09BABCD41FD516561B290EF48DE09C
+:10FC800097055B3698335C38BEF72D1CFF8891D3FF
+:10FC9000CF91ED76BF2F27389FF22D23CD68977C2B
+:10FCA000D26E6101D483C64E13B37139A3003D787F
+:10FCB00005DEC3E7B9FBF518EAAFE2575C2E95C144
+:10FCC000582B00AEDEF605247FC2D751F1B16B721E
+:10FCD0000AC0BBE25E85E1BE0AD6BF1BF0E65D71DD
+:10FCE000CF5768E785AFB3CCA79747739BF47929C3
+:10FCF00027AB04BEE7317713DACF152DFA7A55ED2D
+:10FD0000F751FF556172EC7882B0AFF2D8D8B3608A
+:10FD1000A734D8FAC779CFA1AF4ED4815C1FCCD815
+:10FD2000B13A2BA547EA18A56D092E82F7E2F6F73E
+:10FD3000EF42BA59D2B6D58CFD34FA2739C64315ED
+:10FD40004BFBCD0CBF5B705F159ACEC17D559827DC
+:10FD5000DA3A88FFD18AE77BE44793236C9F55AC5E
+:10FD6000AF54C09FD9B85D518AEB1981DF8D5F8791
+:10FD7000AEE7D49ED1561CD79C28E4F15858977A08
+:10FD8000E1EB92EB91EB93E5D52AD05984F692BE44
+:10FD9000DB04BDCDDB387D753A80A2E1B5CFB3BBC6
+:10FDA000B85F4AF6BC51E0C7685B43F6BC9181BDC1
+:10FDB000CED729EC79F621F2ADA4B3703AAA423835
+:10FDC000500087B7B30A3BBF877EDAEF2778483CFD
+:10FDD000037FA48A7DB354DC37033A3A144647BA0A
+:10FDE0007C458B3EFFA5A92B1BF91BE8E550287C21
+:10FDF000BF0C3B6721D3A4C4FE0487792E6DB203E8
+:10FE0000CA2B986735DF5F6D21B81C31B6ECFE193F
+:10FE1000F2DD464EF79F08BCFF32D1332111F59534
+:10FE2000511B81F2BD70659A9A08F5CA9A1507F2BE
+:10FE3000D3DCC69193910F47318DFA9B9310D94E25
+:10FE40009B93C8E15F5E6B6266B0EFCB610C946B15
+:10FE5000E5DB55E273A0235B09E061BEC043F5BD5D
+:10FE60005BCD6990CEAFADE276829FF30BC095EC8F
+:10FE70008485CD1D66A457F04722F29BD403D5ADEF
+:10FE8000FAF21AD64C78A8413E93740CE3CF4E1484
+:10FE90007CE6666EA447EF5D76AB1277FEF5B2DEC8
+:10FEA00071058A3B9CDA3388ECCA532E570AD6F385
+:10FEB00002CE3BD15E367AC7E2778013E9A3EEFA31
+:10FEC000183FDACD07CE803F88369CC33B16EDA4A1
+:10FED000AEBF67B1354A903EE57A6AACCD449F35F6
+:10FEE0004CEF6F96816383FB9B659B12FC3E85FA0A
+:10FEF0001FD18676C52613D90D3EB62C95019D7966
+:10FF00005699481E96B7C593BF5BDEC8F701CAB7BE
+:10FF1000C4FB55EED77F38302F8887038D45E634F4
+:10FF2000C2538E9BE2C36D261D7D4BFC84FB8B0B65
+:10FF30009B3A76A7BA7AFB8B11F073A80FFC1C0AC8
+:10FF4000C54F73187ED8DD095CCE2C7D739015E605
+:10FF500077AA36CAAD46B037A41E6299408079C1EF
+:10FF6000F853713AC70733BA93119FA79BC710BEC6
+:10FF7000C2F154FCC35CC207FBBB9DA13D3307FC2F
+:10FF80009019F0FD7685F3C79C866B8B515F6F4AA5
+:10FF9000E472E63D904F9A99B1F7413E69209F3E49
+:10FFA00000B985F93FD7A552FEAF752E4AFF5637E7
+:10FFB00094D24362BF54F20D108019EDC2E704BF22
+:10FFC0003C9728E381CB53D17428FEE1833106347A
+:10FFD000DD7D33AF9B94C5D8F59A5EDFCDBE51AFC2
+:10FFE000CFBA4C8EC9A9E8B7DEAB90DD57EE99A029
+:10FFF000ABCF8C2EF3740C6C0F1D1DFC4EF69CCBFE
+:020000021000EC
+:100000003C03F8FDE6A909BAFA339B3274F99D89DD
+:100010002E5AF7F4E201BAEFB7945EA6CB979D0192
+:10002000208C466A76121E965B9930169D3C2EE80F
+:10003000E075BFAE1D9BF21398EFD76F9BA83C1CD9
+:100040001F12AFF3D6199817A636771DAC0DFA3DDF
+:10005000D402788276C7F7D9C9BF58BD65F4BBE32F
+:10006000207F608B89E202071A131E40FBE8C096CE
+:10007000A45806A977B52AEC08879985C8ABA2C60B
+:10008000FADB502E95F92D6EB21776F99E947917FA
+:10009000FAA33849E4970F553FC6B7007F3C2EF0CE
+:1000A000AC85ECDD2360B7E1D6F8118535628A8A2C
+:1000B000250ECABFE94CF2233F17FFA06AA9484F9B
+:1000C000CF46517D8A5040F9B1F7073DB586E8CB60
+:1000D000D51A20BEB5903F30B78BAF8F29A3321011
+:1000E000FF47E299160F93A85EF6D7FD46C0D3826C
+:1000F000C19D2302D0AE342790340BDA9DD868A27C
+:10010000F320D8AF03F2D5CF59367039A2A54C1FD2
+:100110001E0A4FFF085CF71C83E7FF2502FE8E5581
+:10012000FA47903CBB3B89F82A1CEE87CC5E82AF35
+:100130000FF94009CAC7209FF17D1E106A69286720
+:10014000E69ADCC9A89F0E359BC8EE04FD113B9DC5
+:10015000E22B2F111D1F32BA26E3BA0F35E530947A
+:100160005772DCF26695FC02A43FAABF56F5828D59
+:10017000C0A49EF235295E96D29B6EEE583A3605A3
+:10018000D7136EDFCAF44BE0556F88BDB0F035D59C
+:1001900043E78172BB8C370E0F5D4723E7B754DE10
+:1001A000FF7221D717F7FFC37E9B01E5FA80388CD9
+:1001B000931FFD50253A3BDABF252F1548FF846178
+:1001C00047DE4F207FBCC477D808F9272DDE814950
+:1001D000B0A44586E66CF48F4EB61F7C6002B43B3B
+:1001E000F6BCC98DC32E7C76413F8AE708FBBAB7BF
+:1001F000DC0AA473FB404B53009E8B5CADA4B75D3F
+:100200005B14C6D7EFE7E705841E773CA4A02DC595
+:100210000E8EB1AFC178C75C608F50BBFBA089DB8D
+:100220000579495C9E48FDBE5CE4E71A385DB3D7AA
+:1002300015FF2661EF84EA0129972725F5A7FA3DE6
+:100240007A99B592BCAAC4731DB0BEC59B2D7E7FA2
+:100250000EB571209F2FE0E861F5492E7EBEC7FCE8
+:10026000FCC3C84355AC93E67DCCE4AFECCCC1F6FF
+:100270001B1A9DD4DEE4A6B8ABD027566020944765
+:100280005582EFAA5B147F80F886EBC50AD13F4305
+:100290003D1322BF7AEB15BD3EA9107AB48285C505
+:1002A0006D5BF4FACD1363A7752D8471515F06E77A
+:1002B00005F631C0ACD2EBDF3D8DE6ADB8FD11E601
+:1002C00051C5BA03789EAE7A8BE20EB0DEF30A5FB8
+:1002D000C785CEB3D23D7D627C6EC8B861F396F01F
+:1002E000A6C06F081E24DC2B7D1C9E95ED0AE1EB59
+:1002F000336197C11FC59B25DEAB98671A9E37A84F
+:100300007A08E4654E900E7AF4FE56BF19EDDEE3EE
+:10031000AC25D60674BF78DDD6995760BBF5EF9350
+:100320007F51EA0C0C32C4837FE7EB58539CD5DB3A
+:100330004E08B70F7E2CF8E0EC8D79A21DC0A362A9
+:10034000A3AA458DD0D5A3F6D23E98EFF399319E5E
+:10035000395FC409CF37CF1AAC37EA42E61BD99EC2
+:10036000F9DFCEFB8524E13FF5B2870645F4A37A99
+:10037000ECA0F3E8DF8F4C812CD4BFDD5946D23F8F
+:100380005F1BDD7F2D48447D3C88FC82BEE46BA56D
+:10039000D0C315A897213DBC6E5B2CFAED9F3DB4F0
+:1003A0008DF6FFCCCF57C4A25D7C78DDDC077CC026
+:1003B0005287B7CC253D5CF598D4C35E73A87E2FD9
+:1003C0005A57F6EB9F237D6E8E725BA0B8729757DB
+:1003D000D8DD20EF500EAEE3F28E3DC4E56115EAA4
+:1003E000AB61A4AF8660BDBB2ABD4390CE43BE9334
+:1003F0001EBB6BAE772CB5678E00FA5D203903A863
+:10040000AFA43E957AD668F07E9484FCA3BEFDE747
+:100410009FC2FABF784925F7AE5ADD90EDC0FD8244
+:100420003EE4F6BF0F6F430FBC732E00DEE5086F8E
+:10043000B27F38BC3F6DE2703ED8CCE1BE7ACB8053
+:1004400058F46F3F6D1A4076CFA75B0611BCE7AD3D
+:10045000017893DDEBD2DB3D4D006FB4F311DE305C
+:100460006EF92E9780B79BC3BB49E89D669ECEEB85
+:1004700005571F9D1BBDEB698B1BF5F991A8401219
+:10048000FA2347B6AA0CF7E57BEC2261BF48387F18
+:10049000C35A9E443BAA973DB3D6C21CD0DF829775
+:1004A000ED7E06F9634A410A22E044CB1F6271BC2B
+:1004B000E0F83D768C23794C881D7381F859C23C55
+:1004C000747E7D49FB1FF6A11DAF68DCAF5F62B58E
+:1004D00005906FC1DF39112ACF1517CA348C93B834
+:1004E000AD56A4834CE6D2EF1B7919EE1B7D3BE899
+:1004F000ABDB96113F770F0EDDD7A9890E9830BE82
+:10050000D4BD55217C572F2F882D60B82F554BF324
+:10051000189ECCF5B1A2691437B400DD44C378EE5F
+:100520006417FFEE72F038E27A18D71E9C6FF8F766
+:1005300069487AA8CF6D06D2E7E1EBBF2D99FB2B76
+:10054000D5AA81FC8EC566EE7FC8F30F578AF22BC1
+:100550009379BCB72899EF179C8C62A4374EAE8D67
+:10056000F1D7D3FA26523CB3277E22E1E6307ED97A
+:1005700023AF90AF44FC603FB68179CEB388782E2C
+:10058000A8586C7FAB687F6BCB3BB42F079ECB1317
+:10059000A877E7ACB0B8D17EF5BD6621BABB279A83
+:1005A000EFA3B0C43823F2D12D42CEDEDA729F071A
+:1005B000CF3DCC6989D13085717C4CC44F73711F9C
+:1005C00036DD4CF1D3526BD7F3E866DF9E7AF04EFE
+:1005D0002B2CADDEC0ED967A27A3F3239783D98E1B
+:1005E000F15828DA7E36E15CF4A38F0F2FC638ED80
+:1005F00078C6096B1CC155975F6CE6E5CB93474DF8
+:10060000792893B13F31D770C4F762840DD2435932
+:100610001CC501AEC778B1135323D1D90C23F319EC
+:1006200078DA84A135193F9E26D67DD33816888383
+:10063000F506F6EAE3D7B30286C010C0C3F5C6409C
+:1006400007D2B5C1EA32A13FE0295646A19FBC7846
+:10065000E585CDF79EE42B69BE8B0D063ECF9F2A24
+:10066000FEA7004EB70293237DDE6664BBD4511C07
+:100670007F487F354E978FEA2DE5F42DE3E6124F44
+:1006800023A1FB50F8DE2AE607FD34C5627B73E444
+:10069000F8D183C9D20FE6F6E622C1AF8B24BD6D37
+:1006A000D1F3E936E4173C9F83762DC0ED5691F6E1
+:1006B00045EFAD82DE5B05BD3F29F2173A5EB58599
+:1006C0000568DDAF59088F72DCEB45FA4232B79B03
+:1006D000E53C243D3311873280E4403A3AD4D2409D
+:1006E00076D3FCB038300B8D57A991F23DF2C7702C
+:1006F000165373F73C9C8F7255941BE9FA5673EBB3
+:10070000A05A5BEF7A721FB794759AF8BD1B11CF90
+:1007100012FA6A926AA37341A54AB41BEDDF9305EE
+:10072000769F210EE32D26426D29D003CAE78FA2C2
+:10073000F8BEFD9CB8BBA6A15D581A6B36627A3B29
+:10074000EBB4E7E404ED92D5052AEEC1C1C0D55360
+:1007500034C837A03CE1F9FBB44C8A0E89FCB23FA7
+:1007600062F98DDF01FE297FC7140DE4C5C9374545
+:10077000395B4EED4FAE1274EC5B3105F7394EFE2E
+:100780004A96FF9C97DF2BCBEB79F9FDB27F915F07
+:100790001B565E1F56FE28CF773D5C3FC587701203
+:1007A000FB31A5E31592272E4167A52B0304DF52E9
+:1007B000C30E9E16B28021F7FCF56C291E5732ED50
+:1007C0000B1EB2A3DE4E48D35CC950CF96E43D8EDB
+:1007D000DF174E577C6694931FFA070BB91EF15C26
+:1007E000AD4BD06D542AEF4FC21BFAF91AFBBBD8A0
+:1007F0007ED6E1BC9274FD7CFFEFF4332FB5573FFA
+:10080000E6947FA39FBD61EB92765159BA9683FD22
+:10081000B14389BAF3658BFED31D877615C3F365A3
+:1008200000FA452B5BB34743FF8B5E7835BB32C480
+:10083000EF5E72C6C034B09F6ACE304A8F77FCCD6F
+:10084000EC82F92CD9DE619E0CF56A202D0A99D72D
+:1008500062794E9275196784E8F5C12906219FD601
+:10086000D27C17BD70D488F85C64683DFC18C67BE8
+:10087000C62B11F75D6345BBFD7DDCE71A96C2E52B
+:100880009E2753BB2C05CF45A0CC407DDC10799F23
+:10089000FE4ED15F6934976F73F3EC5617C079CC75
+:1008A000877C9FB9727DCE288CE35E9E543806FB10
+:1008B000EB3B2EDACDE3A2ED3C2E5AEAEC5C0EC205
+:1008C0009BD5A66CB8CF7A2563531E917C062C0B62
+:1008D0006D8B2D32DF3665623EC5B9287FC3235B41
+:1008E000EF43BED913CDCF4DCC193B3C1AE542574F
+:1008F0004E8CC101F2625C62592DE26FCED82B277B
+:10090000E3F7028B7D70198FAB135D8C4BF44CC1F8
+:1009100072AC8F710DAF99C7B9BC6FA914E7F28E95
+:1009200088F146DA47BE56C0A136859F73DD03685D
+:1009300046BB43CE438E0F86CAF24EE8EFD0CAB410
+:10094000916B5CB8DF515043F424C6FF65A2B73405
+:10095000747C58EE08FC7EA1F3B83985D36F0DE2A4
+:100960000DF198AF322DC45F9C31314697BF716A4B
+:1009700002D342E3AD3766E8F2B34B07E8EADF3271
+:10098000EF325D7989A533B7F622ECDF1ABB3D1A49
+:10099000EDB08FDBBFF9CBAD68D76D54DD0AAC6726
+:1009A000C16B9BFE32016A9DC2E397FCFE14C5BD7C
+:1009B0008EE17936E43DA3660CDDAFF98275D2B9DC
+:1009C000C090FD00DDBECB22C72E3AAFFA63EDD753
+:1009D0003C9022FCDF516C14EABF53B57FA638DB94
+:1009E000121B5FCF17AF1E30E339063C177016E8B5
+:1009F000FB1A6CA8229FFB280E5DD476C08CFE915A
+:100A00003B85CBE525994B8D6091B11A48516F4CD0
+:100A100006F91407F4D1D9C1866FC7731339763A32
+:100A2000075E7D66060869A423DFB0A5506F5153A9
+:100A300031E5979C89A67EDF533B27D379E4571491
+:100A4000DA2F28C998B312ED51AC7F078C57F2E228
+:100A500035C5089F25DBF9BDA712F54FB9D8CFE200
+:100A600096626A5FA2B23D0AD807538AB89E2D41AA
+:100A7000DD0E7935CFBE06F5AB6A0E0C7E1CE5891E
+:100A8000D94EF224EECC2D347ECD192BB5FFAD908E
+:100A900017A62E3EAF49673CF45DE2BD3D85EF03EE
+:100AA000CABC2969A311EF1598BA18D5BFEECCA519
+:100AB00094CA75BE35F4E9449463A6A4AF276700D1
+:100AC0007DBC95A838C8DC0893B7A76BC7C6B1082A
+:100AD000F2A8679C33FCFCAEE50C3FCFDB9EA6FD85
+:100AE00009F96ADADD5D46DCBF6136AB03E1356DDD
+:100AF000DC485765081FA93B6E36235E4C0FBD6F5F
+:100B0000467D6C81B428A4BC5A9E3B0F93C7FB045E
+:100B1000DFC97B0752BF30DF6CB2476F13FEB7E40B
+:100B20009337457DD9BE13691CF1F8B285FCA73F08
+:100B3000A7798FA3BCEC2C60B35F22F9D8998DFB09
+:100B4000263FD6FC01CF5685ECFB2E3ACF3E6D9C5E
+:100B5000CB80FB01DD3DEBE0FC7ABE757C2CEABF6F
+:100B6000A7B215D8EF7B575FDDA9417F1D3F1B3D25
+:100B70001AE5BE1C5749E5F77098A3FB3BF4E76AFA
+:100B80005E8F71215F97A073941BB463E13BC3F840
+:100B90005FCDEB96A71428AF89057F16C62F7A2361
+:100BA0002A8074DCF1469411F5437DA657491D83D4
+:100BB000DF874C44FF4D6BB71819D9379A01BFF73F
+:100BC00035DFF3C9A7703A937CE96DE2FC5226E861
+:100BD000B45CF09F57F0D1E9DA14E2C3D377C3A431
+:100BE000719FF36E65F876B4075C76F72057902F07
+:100BF0004BD0EF81EF2597C593FF17C277C4878B42
+:100C0000CF38A8BFEA332EC1E74ECA4B7E2B17FC64
+:100C1000621176C43C41DF49E9DE91A930FF9206BA
+:100C2000E07718C7BB322D17F928482F6607D21571
+:100C3000D04B6A6508DF3474DCCCD0FEB0247A88EF
+:100C40005EE6411A6A7F54F4D81F8EC9C930EF6935
+:100C50008D39BA7B1679A91747F70352C5BEBC2D4B
+:100C60003008ED55536D941BEF839D4AE4FB33CB65
+:100C7000EEE5F05B66F214A1FDB0EC51C50D9821D4
+:100C8000BB02E551DEBE5A7368BCF1E63323980B14
+:100C9000E070C39981945E9EE49D88F82F3B3353A6
+:100CA000C06BC4BFB50F3846E3F12593DFE2DE80A9
+:100CB000FB6C515E15F17B248B391E0C892F613C36
+:100CC0000CE362727F50C69B2CB89F1AA227BF31DB
+:100CD000B664A3BFD32BEE54A0DF475BDCF1A73C87
+:100CE00003941FCBD128FE34C7E0BD0DF1BA708646
+:100CF000FF0513E417DDBF2D16E3DD129EADC6C060
+:100D000020D493AD00478C83B536ABC57E6ECFC47F
+:100D1000F0FD2F4ED7928EC3E97BE199FE444FA799
+:100D20006B2DA4774E03BDB210BD23F58D94EF5209
+:100D3000EF487AAE3672B9556D8BA37315417D338A
+:100D4000DD83715C36949F7F0BEA9BA71E188FF49E
+:100D50007F3291CE3587D3FF2B75A974CE46EA91A9
+:100D6000707D23E5B994EF525FDD95E65D8B702AC7
+:100D70007CEEBFB7FD1D3E5D67E47AEB3AA39DE8CC
+:100D8000E7C2E5E60121370FE8E4E6923EE4FEC360
+:100D90001749FF8DA23ED8AF6417A25C0FEDEFCFCD
+:100DA0006985BF41FA7D2195EBD51F6BDE7DC9FBBF
+:100DB0001752A51F7161F2FE7151FF7CF2BE43C84C
+:100DC000FB70F9CEA03F94EF275FBB84F6A7F73303
+:100DD000D007A8F7DA635C9B84FC27FD101DE73F72
+:100DE00097FCF764CEEDE843FEEFF8DFC87F498F4C
+:100DF000925F247F487E08E71FC90F53EE03FF0F61
+:100E0000F1F41EBF5F546DF46DA1FD4357CC48E46F
+:100E1000CB1EBB6DBB427CD64B2F08BE09F2895E50
+:100E20004F48BE907C22F9A35AF04345183FEC543A
+:100E30005B1F1C0FED6E4EF39E0EE58BC52F85EBF1
+:100E4000853EE90A2386AC22B196215D55431A4AB4
+:100E500057963EF8E14C0F3D5D183F1CBE407A8A24
+:100E6000493353BDFF437A8A494B8A484FB6B41F72
+:100E7000D19E385DFBD75C17CCE7742EC8D99C2077
+:100E8000BD4DF923E3F6C2006EF7EF89E6EBDC63B4
+:100E9000CEA278CE94B3FC5CABA44B8967690754AF
+:100EA00088784271BAC78DF395FEC285E2D992D88F
+:100EB00069463FA402D250FDDF97BD3B26EDE2F02C
+:100EC0003C20EDC2ECC4C902CF3FA29D383D125E6A
+:100ED00099C3A98B4380FEBB81ECB780918EC8F487
+:100EE000E957ACE37096F95501A3D4B709A86F810F
+:100EF0005E66E078FF2EBD941431110F7C79AA96BE
+:100F00000F78FF85C8B357A7227E668E93E5BF6D25
+:100F1000D606A2DC61328E4E7191F75491F7BDF284
+:100F2000F644A83FE541168CB343F9A4FCB89E38BB
+:100F30008AC282F5973EBAFDED66C2333FF7C2BC66
+:100F40005D46BECF24F2B990B787E4C785E5D7F3F5
+:100F5000FAB1C62EC6CF29FA39BFAAB8F5C6E9C775
+:100F600013628F002627E3798269DB1507C6416E7D
+:100F7000C93F49FBB1C1F5BF41EB5FD2AE88FCCEA2
+:100F8000B771BDB76CE7F9471EFD43B36FA0E82FFB
+:100F900099E264F4676A55343CFFB0789CE2EF9FB5
+:100FA000D31BCE8FA4E9FD1BFC33EADB333C7F77F8
+:100FB00031ED11CFD4BE3FB50F582E62FC59F991D7
+:100FC000EF3DFC97AC27E209D43FC0F286D6C8EFCC
+:100FD00097BC28F8B113F74D085E1F3523FC3ACDB6
+:100FE000129EFF68C67837DD9F81FCAB8FFE63AA37
+:100FF0006F189FBE16B6FE73CDFFF108EB77E9DBE5
+:1010000007CE05BF0DBDDA0BFA99AFA7A738A367C6
+:10101000D769E8270EFC7FB48B9778A29AD1FE0F90
+:10102000D2C761A28F4E19CFEF45FF9F4F9D682316
+:10103000FB47D43FDA8C7ACC63E8A9CFF941D217C9
+:101040005E05C2B3738CB7FFE0D123CD081FC00F7C
+:101050009553DE780E7E680DCBE787F18FA07FE297
+:101060005F94F3009F4111E4CC29019F2FC4B9EA9A
+:10107000CE426E2776F6E7A9339DDB85FF12F83660
+:10108000A4F3FA9DD1217008C133FC05D00F095992
+:1010900037C1E9E644B9EEA892A9B0AE4E272FB702
+:1010A000A59BEEF7E507F3E1FDC5A64795205C8219
+:1010B000FD5BDE41B974B3809B33DDFA8E8FCB4389
+:1010C00005F9B29A0804E862BBE253D14F40BA88EE
+:1010D000B0EEBFF7A62B5F587BCD748EF65DBDDBFF
+:1010E0006B61ED9929F762DA0BBC4D0DC36B71187A
+:1010F0005E2786E54B65DEAF937F522E96B7AD5DDA
+:10110000959C88714985EE8A06E939A504E97991AB
+:1011100043D26F2AC13548CF69EF20FDCE6895F2E2
+:1011200030FD7E0DF0361DE5E1F860FE0694179463
+:10113000CF28D1E242F5452695CF6A92F5B3EE2746
+:1011400079DA28FBCBA6BCC423F3F52B21BCE60A35
+:101150007DE173BD83E50BDB79FB498FE5BC734E05
+:101160007E680983CBFAB0BC2FACFE43E7D12F8D4C
+:1011700061EDEF0E2B6F0ECBAF0BCB37E9DB97CDCD
+:1011800053880FCB801E1011E7E3CB9BD27BECD4AE
+:101190001E7DAAD8C86ED3F1D594069EBFFDB111AD
+:1011A000254DB6907CBABB24942FE4BD604B22231E
+:1011B000BE30F5212F4BD2F5FE59CF7A8686EB5BF8
+:1011C0005EFE09FE338DF6777476C14E559FEF5063
+:1011D000E5BCAF7A67B92D641F945D5982F195BE65
+:1011E000F75B26944CCC0CB14B7CE34BB49075CAA6
+:1011F000FA93BF3FABE27877A68F2FD988FB39856A
+:10120000621FD2C953D06B2AEACD1A118F998CE78D
+:1012100063B15E7460D0B2503B84B50EC67576FC87
+:101220008CDF1BF035007E30BEC6DC668CA774C434
+:10123000C5AD7806EAEFFC99BA02F5E8FE15097427
+:101240002EE94FE9DCFFDC19D72FB902F21D31B7C7
+:101250009BF1BD928E7B2651BA43D5567703AF3DA5
+:10126000F8D8B525B64BB03C8EE0F38BF44925F5A4
+:1012700040D7BFC44B3BD0DEEB7424E3BD06B6C6FB
+:1012800044FB7A8CB99F24BAB9DF3212FDE7B2FA77
+:10129000CB68DFAAFC57D327D3BD855526DACF808C
+:1012A0003F3A7FE25D3389CE3DCD6B14A9EF1A4AF8
+:1012B000DFF8E1E906BC1FD9FD8442F725AEFCBA90
+:1012C000F58F23F0DC63D30037A2E675B0EBF13C79
+:1012D000D2A7EB86D03D898351B574EE13EA33ACC7
+:1012E0005FF59DEBDD69B9585F75E0D18AC3F01DEC
+:1012F000EDE1C3F7AA4FE1FDC3B2587B349E973EA0
+:10130000FCBDEB5DB46BA1DCB112BE1F5EB5201954
+:10131000EDACC38A2B16DF1279F1B15925A9697892
+:101320002FDF22F039CB5E067C5E66E8A117D21F64
+:1013300095F13CFF62FAAC924D30FFC38F0EA17362
+:101340005F8333B4D674C0D3E90C6D2BA607C57D7B
+:10135000E5377EE0FB85BF3F519E8CF4F47B41C7AF
+:10136000AF9F294F2E0FB1772ABF3012DEDF30BB7F
+:1013700096E33CDF88CE52E87C366B4DC078F73C74
+:10138000E17F00FDAED816C1EE79385D253C75DCF5
+:1013900097948F780DD27125C94BF21B20FFF6630D
+:1013A000E5A4D70E5956B08368378AF38B6C67145F
+:1013B000BFEFB825CA1F9583F14F6D32B663A9AD53
+:1013C0008367D843F84ED4FFD8C7CFE77E0CF5D15A
+:1013D0007FFBD8F70F7BE83E84AC5F156BF7A1313C
+:1013E000F1B9DD6E443CEC37D61DC6737D954F9840
+:1013F00048EE573E91747737CA1BA0178C8F85AF84
+:101400002B35C344F0EA930F7D77944CD4F90777DA
+:101410009C930F0F3FB6AC64A3AD6F3EAC127ECA77
+:10142000E4274C744EBD6A8CDD88FB8F854FBCB9B8
+:1014300089EEAD2E8D1A85F713AA9EB010BEBAECB8
+:10144000769F03F74763EDC67848BF167648125E6D
+:10145000AEC4B88CCA8CD65194D2BD04B9AF7774DF
+:10146000C5830FE331CA63CC3F732CC0EF14220C49
+:10147000E0724ADECB0ADBE7ABDEBBCD5CC0CEB1AF
+:10148000CF779EFD3D205F7A47E242F7F96232C492
+:10149000BD9F9E7D3E13BD0B5125F6F98AD6F3F311
+:1014A0005B552BF8FB1D45093CDE7BA8CE878FC41E
+:1014B000E27A7D0EBC9FFB10D72F554CF15BE19F6C
+:1014C000D7AC5F6AA4FB8FE91C3E65E21DA7835180
+:1014D000EE6CF4D32B9F8822B8563DB9E02F8F4293
+:1014E000BBAEFA92C450BF3847D003F4CFF09EAEE3
+:1014F000ECE7F3FA9F6723DD17FD1AFC5BBCEF17DF
+:10150000CF5EB83907F194968DFB91B25ED5CA9F34
+:101510000DE6F5C03F063FB8EC5E95BFBFF6B2855D
+:10152000F41DF0782A0BB9CF3CAF71AFD93C2C78C1
+:10153000FFEB53C8E395FB907B60668497BC978470
+:101540007FA979C2DE7691FCA077784B0D0ADD5F2A
+:1015500002C945F77EAECFE0F6EBC40C7EDEA92CC7
+:10156000DB4DF75FAA1FB0B857E6F07E7AEE55E381
+:101570003927436725ED3FFED64271919AC6282D43
+:101580002A969F8B7869189D8B369A71DFC4C5E5C2
+:10159000C4F582FE6A5CD3AF417A81F27D463C8716
+:1015A00065E7F2B03A1EE0CEF5B06680714EE2BF5C
+:1015B00006F07ED346848CAF88EFD08F2B36D8EFE1
+:1015C0001E036BC2B80BD6BF6404C23161E66C9CCB
+:1015D000DFF32AF1312CFE817168DF3DAF8E46BF0B
+:1015E000B6ECDE9D93D7617EEB48BCB1C0CA5EF815
+:1015F00080F4C52281FF2E711EAC1CF278DF7F7E45
+:101600000697935E95C77BE60B78493A90E5D5F748
+:10161000F2F350D5AB2C64BF54D7FF95FAADB67733
+:1016200026A3DCAD7ED944F79817897997D767E56B
+:10163000EF03BA2A37C5D17BCB8B7D2566CC2F6EC5
+:1016400051281F6C97948D747ABCF19558A49F8390
+:10165000518141A887BA9746B9F11C9E8CB71D6F7E
+:101660001CF414C665E6393AED781F69DEF2014EC6
+:1016700094DBFB1D013396EF6FCD31605E7338F262
+:1016800031AF192FA7FC7171EE84FE905E148EE7C6
+:10169000C55B769AFBC3782D822EBE78FE83C1A8E7
+:1016A000A7AAB33B07A33E013A189C81707E56213E
+:1016B0003DBC640B3FA72EE96009D201F0DD424139
+:1016C000074BB6BFF213E4872588FF51BDE908E850
+:1016D00074177D7F69C364C6DBEF423A91FA0BF25F
+:1016E0008D2627C6DF441EC6C1FC5A014F289FC85D
+:1016F000CB7DC3F839B72E3AB75723EE2BF6C8A7E0
+:101700003EF0FC82C06379BD85E4ED0B02CF5DF74E
+:10171000BE1C8B78FCE2F99DBB719FA4FA25C5C164
+:10172000F7ABC2F842C0A506E1104BEB20BBA20606
+:10173000D71D1B84430FFD0B7EAC617C9D72DD3594
+:10174000460107592EDABF88EB4C42F80AB86D1FE4
+:10175000C2F94FF01BF233BDCF23D6E775EADFDDC8
+:10176000FE3083EB83D744BA18E802EF6731BC9EA2
+:1017700028E504147DB17503C57D24BEE4BC0F07C4
+:10178000F58816EF0CE2B1CBC0EF2F86EBCB7704D8
+:10179000FC0EAC4AC96E03B81DDF4CCF5412BD1A03
+:1017A00043C6937423C72B7A6EFA75B85EE83F8000
+:1017B000FDCB71F7FB628CD8CF7EC6F903E913E548
+:1017C000A7E4CBA28639D78DC473BFBE2FEC0386A6
+:1017D000E17A39DD1ECEE0E77F34B413A0BDD6A692
+:1017E00050DCF980F0E70FAC7A25B63C044E874414
+:1017F0003B4967F887F12839DF3D4E1EC70D9FB77B
+:10180000944372DE45F7CCBA0EBFCBF94B7A95F410
+:1018100029E128E954DE7F0BA757A235A93F559D42
+:10182000BC27FD784DE65766AFADF7F7F0BCB48343
+:101830000E8AF3DBDD498CC7EB1B537785DEF7811E
+:101840003F5BA8DE09D127CDC6107D22F57F4DA2D2
+:101850007614F1559CC9CF951C63ADE602E877F18B
+:1018600091CEC9F84EA2B43BAFFC3AA0C6611C6A47
+:101870003B3F7F26E1BDF8C42EA2FB6A712FA9EC85
+:10188000DE0F4AC6227DFFC644FB3165AB26D1FD83
+:10189000E3059BE6E621FDE07D0694E747378E19D8
+:1018A000CD9FF37224CFC47B0D1B1F9C790B7C9FB3
+:1018B000D7A6BA49AE433FC8AF65778E66482F07B3
+:1018C000A3BA4AC6A3BDFE53D581F6FA844D63EE92
+:1018D000C6FA13ECFDE2713DDAC604CA6BC638D213
+:1018E0000BD2CE95E7F21A4C9C1E466572FEB9A447
+:1018F0002755C479BC86C1B87FDEBD218ADE412A66
+:10190000358B7B9CAFA5903F5163C62B85742F947C
+:10191000ECB0F966664DE3E79DAD69F07DAFA9F3E4
+:101920004ED41F7BEFB48FA473F5EA7779E5DC7EA4
+:10193000E6FB8509FA7787E43C468AF1C3FB93ED21
+:10194000F788F3C607C5FC8F36FE6626EABFA39B61
+:10195000073971DD9FBF1645E7F03F0F7BB7F06297
+:10196000EF6901DD86DD835AC9E545A6FE9C96A494
+:10197000F3F3DE53FA28316C3FE0DCE78B4ED431D1
+:10198000BA4F6D015F98EC9998EFB7E1B9BECA16EE
+:101990008B03EFB31C42BAA7F33C2ABF776BE57CFD
+:1019A0007068EB483FFA8D951FF1FB45BBD6DE43CF
+:1019B000E70A2AC0AEC4A3543D76F2436B67221BEC
+:1019C0009C727B57E33B2FA736F37310BDDE2DD8F7
+:1019D000BB6D77E8BB05176B1F5FA85D2CE30A356D
+:1019E00099FA7BF112AED23F7A03F03F6E54104E5B
+:1019F0005FD6CD27BBF8449D97D293CA8107262096
+:101A0000DDDAE3E8BCFEEFDB1E54F19D95EAED2341
+:101A1000BF43FF76BC2DCE81FCFA65DD0ADAEF3CD0
+:101A200051574B69F05D573FA5576EEFA0765FB6F3
+:101A30008D6EC77BAEAFDBE284BC0FDFD7E178EC05
+:101A4000EBFEAE5CD7B19F727CCA791FDB3C3716C8
+:101A5000D7D5F17842FB1588C7983807DA7755E271
+:101A60009CC7E175DC7E3E628D7B662A9E0F597FA6
+:101A70004332BE8353D171E34CFC5EF99AE240BB22
+:101A8000DFFDDAF4588CA37D66EC8AC57B4D9FADF3
+:101A900093F7A1FCF41EE9F86246FB4EE30346E629
+:101AA000CAE15BCC4827579C30D2BDD3E3B81F8531
+:101AB000718FEFA229EEC1C43E53C5AB3C5ED2E3A9
+:101AC000C70A3F6E8258F75B994EB97F40DF8BC6DD
+:101AD000F1EF9FAFDF360DFB3BBAD1E4C0797FB9A0
+:101AE00091BFCFB010FC2FBC9A726433F76F16B65B
+:101AF0002AE40F1FDD0CFA19D655BDD4A4F1FB9AC8
+:101B00007AFA2B82723CD728E96FA1E627BA0E7FBA
+:101B10003F239EB5D2BDAE1F8B1E03997A3FAD8782
+:101B20000EFBC2BF8013F22DD2A1C4F3C2757CDFBD
+:101B3000DCD93AB200E949E25DCA05795FA1C1CCBE
+:101B4000F87BA58668FA3D80E936974981F5DF90F4
+:101B5000D83511C5E7B02C6E7FA845060DEFA1B1B1
+:101B6000064BC4F7A8FE26E4E89C2C46E93799DC2E
+:101B70005E90F7B1640A0BC9423D3D3DC6F98D0B3D
+:101B8000AA1C5EBF749A11E63F7D82F3CE016EC03F
+:101B9000DBFA9F4C3302DD4E1FED7CB93FE4BB33D3
+:101BA000EFE2F9CB9D634C90AFAF5F316D22D4B7BC
+:101BB0006769873243C691FDC2F7CFF1BB3FC17B56
+:101BC0000CD31A33BF1F7552E91EB1222758FF7D6F
+:101BD00085EDFFBD12CC779918BD03F34DA69C7F10
+:101BE000E4744C96763A734CEFEFE58CADA2F3714A
+:101BF0003E7EBF05FE3CD664BC7FC4E9A95CDE77AF
+:101C000069D2DF77616E7EFF4ADE4392F78C2E0940
+:101C1000DE9F5A7F31F7A74E9A60BD71BDEFB329A1
+:101C2000ED7FA0F7B01A7CAC2B8AF0A0BFBF521D8D
+:101C3000C3DFF75BF6F217BB90AC16487B05956DDA
+:101C40005EF0FE3E4BE5FBFE770A3AFCBC8E0D1CB7
+:101C500008AC7C7D6767AC0B267B625A6030F2B7BC
+:101C6000CBE2CDC8423F7E7D43E6B244BCF769710A
+:101C70004F85FA47FCFC5EE562616FB28D4982CF09
+:101C8000D5C0D5506F4FCE25F47EC3A02CEE479C17
+:101C9000C80964E37B3ABE1CEEDF403D3ABF56BC48
+:101CA000F29A24AC7762EB3D032B006F167CBFCD1C
+:101CB0004929C3FB4FD742DFE39CF4AE1B53699F16
+:101CC000D64FFD61BD58D4EBAEB9A93C8ECEEFCD59
+:101CD000493C49F8F7C20B4C01ED5183959970FED0
+:101CE00097B0F50EE453891FF9FEE9B29779FC64C9
+:101CF00099D2D59880F9E7153AFFF6B995DFEBE967
+:101D0000ADE7369911D4F3D7CFD5BDCF23DF19FD79
+:101D1000B1E34053B3847C19C94686BEE35A25DA41
+:101D20004E524B5DF8DEDBB2242BBDDBB1EC8901FA
+:101D3000A44FD8DB77B0D07A6C7D02D1C7EA1C956E
+:101D4000E0BCA08DD1BB3B256DE9745E716A9B93AD
+:101D5000D2D833A9F4FDE8337FCCE5F287E3A1E4E0
+:101D6000BF520AE97CD07F0DA194F5F5AEB0CD4A03
+:101D7000F76897EDE57A69D94D2AC52799B81FEE1E
+:101D800011D3F1D89A289EE36191DF8FF5C8F763EC
+:101D900035D339DF8F95F0B508FC84BF277BD3DEC0
+:101DA000D1A9F41EAB784F76B6A8D729EE6D85BFC2
+:101DB0002B7B4FEC647A5776B65615F15D59A32FFD
+:101DC000CA8DF6AD29D3C6DF6BF086BF33DB65C4A1
+:101DD00075CFCCE7EFCCDE343BE45D04F8CF94FF65
+:101DE00015C969537EAFF7814C48DF168FBE7EB3AD
+:101DF000C4FF25EC9273BEE39B69A677DE8CF89E48
+:101E000033E4678A777CD18E43FBFC94C6DF95B3BD
+:101E10008877A63B596E2AF2FDC5BED3FCFFDBBB1B
+:101E2000CCE1EF2F87BFB77CD9E665BAFCF0D6FFCF
+:101E3000D0D5BFBC6DA5AE7C64608DAE7CF49E5FDA
+:101E4000EAF2633A1FD3D51FBBEF295DF9155DCFC9
+:101E5000EACA271C794997BFB2FB77BAFA579FD9CC
+:101E6000A1CB17B03FEAEA17593FD0E52739FEA1C9
+:101E7000AB7F4DEA415DF9B5AEE3BAF229434FEBD2
+:101E8000D763F4FE0DE57C89FBBF75EDA631D72F36
+:101E9000F0FDE75989067AAFE31F59C27F1174F745
+:101EA00057A9B707B26C945F93D4FC00D15D9BC275
+:101EB000DF1F0ED363C6E31E0DE371EC157EFF2B0F
+:101EC0000EEC3E63C878F19A151CC2603EA1D8A101
+:101ED000CB27795275F55366BB74E569DEA1BAF27A
+:101EE0008CF96E5D3EAB769CAE7EBF159A2E9FE35D
+:101EF0002BD6D51FD0E4D1E507B5CCD6D51FB2CEB1
+:101F0000AB2BBFC43F5F577ED9E65A5D7E78EB0AA4
+:101F10005DFDCBDB7CBAF29181265DF9E83D2DBAFF
+:101F2000FC98CE75BAFA63F7F975E557746DD695D6
+:101F30004F38D2AACB5FD9DDA6AB7FF599802E5F53
+:101F4000C0F6EAEA1759DFD7E52739FEA6AB7F4D81
+:101F5000EA015DF9B5AEA3BA7269B74C19FA95FEFC
+:101F6000BBB0634ADCFFD4B5F7158A77A55F52DCB6
+:101F70000D2E584F767FAEEF418046E1BB883E0F75
+:101F8000C57D9C78B00FE514DEBB76F27331A514E5
+:101F90003F4A243B8754910BCFE9801D108BDE55BF
+:101FA0004E0EDAC931417B2CF36CC839B9F3D963D1
+:101FB000D764339AC75DD9DEFCEC24F43FB64EA655
+:101FC00077C1996F35CE43BE73F76ED87BC832BDEB
+:101FD000D67A841943ECBFBD512D99A3CEE1BF5FE2
+:101FE0006B3DC1F09DE59E7E45BC4281F52D0BE920
+:101FF000FF01F0178C03196BA903BEC17DE13A07FD
+:10200000E51FAA4BA5FCC3752E4AD7D50DA5F4B183
+:102010003A3795AFAF1B47F927EB34CAFBEB8A2958
+:102020007DAACE43DF37D6CDA6FC33E01763BA19BD
+:10203000FC644C9F057F17CBB780FF8BF917EA7CB8
+:1020400094B6D635D1F797EA5A28BFBD6E1DE57F05
+:102050005BE7A7B4AD6E33A5BFAB6BA5F2F6BA369E
+:10206000CABF5E17A07CA06E0FE577D475527E576D
+:10207000DD3ECAEFAEEBA2744FDD114ADFAAEBA63C
+:10208000F2B7EBCE50FE9888B72ECF5674F7956412
+:102090005EBEC720EDBF6968BF23718C337DA9B3D5
+:1020A000DFC3ECE8707CC87182EF270C7EAA21C4E4
+:1020B0007FF26573FF4ABEC710FE8E0213F6A97C3D
+:1020C000F754BED75029E65525F8610CD2E750A247
+:1020D000CFB72FC65F90FEA02DC9DB42F49965F003
+:1020E000913F6CE3F7892F4FF23E983D06F70B2B9B
+:1020F00076D3780E37ED1B96580249B372E99D707E
+:102100008ACBF5355E8D38F7DD67F9EB4733D19E25
+:102110002EFE41A577B6DE35D967A3FFFF8CC0C37D
+:1021200033D9065DBA2DC9BB09E7F3ADBDF6360359
+:10213000CCFFDBAB963E73474ED04FBE1E5D4DF0DD
+:102140006FA6339789CE1532EDCD1CB49BC0B0C2BB
+:10215000FC2CE6A3745CA2F705ECE76630B831EF1F
+:102160001D6FC98EB4AEF079BD2AF0F56AB64197FD
+:102170001E48F2B621FCBEB56B34AF77AFB86630FF
+:10218000AE4BCEABBF7877641AEB7E12E7F7ED6B00
+:102190005F1D560604E12FFD71BAD78F726CA9221C
+:1021A000DEB5EBF58E009597DEA9907D3607FC191C
+:1021B000DC1F92EF069CAA35D13BF2F8CE00EE9FD1
+:1021C0009DAAFDCC86E40CF518EE6F34E0011D28C5
+:1021D0006FF829BF4F5F8AEF628CC2770BACBCDF10
+:1021E000BB15A2BBA4E41C7EFF19EC3DF29F12BB01
+:1021F000E99E1ED0C99F116E0BAF50E9DEF9BB06F8
+:10220000FF6085F6932BCC0ACCAF2A11E8A37FDFC1
+:1022100074B044DC1790DF81BE3E41B87DF9EAD846
+:10222000A1147F7FFD0A17C2ABC1C0EF0FF9DE52C8
+:10223000F9EF2E0911AD4E184E71466674BB315E32
+:102240005422EE9B74A86C45A4F7C4957E9C8EDE48
+:102250004DE5EFE73584EDB3FC53D0D53F05BD9593
+:10226000ECD84BEF082DD9C3DF3B64B95DC342DF27
+:102270009DE959CF8AB72E1918B28E9AB603FC7C05
+:1022800005EB1A167A9E3C5D8C2FE94835DBBD1BA9
+:102290006CA1F3EBA16BD60FE9271EE87A00D1F50C
+:1022A00061DC579C6671C5CD82B40B4084EFFB782E
+:1022B0007FEDA0F341F29CD03CE6A1B40AC800E94E
+:1022C000D8E35B4BEFB92EC45F62C5F778C6CDCDBE
+:1022D000C67C0DEB9E980A70BBA9A9FE4D7C0EEF43
+:1022E0008696B59330BE3AC35FF626A6D3372A87C3
+:1022F000D14F05BE88EF87F110A576151EC9BC65C4
+:102300004BC12ADC7A99A6727CB03F727C00DD68F2
+:10231000AAB3F73A810FD2F83A345A871A5BACE382
+:1023200083D2954C531283E7DD7BF862DCA24F70B9
+:102330004B8D19BB69DFBCE6758B13F1BC9071BD89
+:102340001D8C67487DCD88CE17B16837D63B26E80F
+:10235000FA581623BA3EA630BAA72EED4896ED4D90
+:102360001D3520A8778F19FC79B103482FBB71BDAB
+:10237000BB536F70611C6C51A295DE3F3D16EFCFD1
+:102380000E7BE783DE239271AC074C3CAE143E2FEC
+:1023900065DC6EFE7B1866E6C3FD09FCFDE33CE4EC
+:1023A000677C3747A177A0BB90EF4D851E57A4FEF1
+:1023B0001B45BF7BBEE7FEAE0FD683F71B7B8DE3CD
+:1023C00010E344F371A4FEE8F9BDE564A61B6F7A3F
+:1023D0003FCECFEFDA359A7FBD219EE44D9AD5EB03
+:1023E000417CC9B88EF403F7E47C3E90FCF5EF1A0B
+:1023F00032D13EA77708D0FEBE8ACBA5774D2E7A84
+:1024000077F7DD821C8ADF4B797BFD381EFFBA5ED1
+:10241000C6BBF2C3E25D61F116961F39FEC598DBBB
+:1024200084E35EC23E92F0A138CB8E7C23E15DFE58
+:10243000BED20EE17F9E2A4ECC453AFF5D3F5577D6
+:10244000AE40A66B447CB439ECBDEB35B9CB1C78FF
+:102450001EC0F23CDFEFBDBF307A7EE839F42707BB
+:10246000F1F329EEC1059B114EC36CFE4252CB9A8B
+:10247000D185F356C43A2E73009C0D686F7A449C44
+:10248000D36DE5F1A589A497257E2F542F3F6BF4DA
+:10249000AF8CC67526F2DF19B0AFB392DC545BB5D2
+:1024A000001E89FE72D08C5548B7CCE8198AE374B7
+:1024B000E445331BD4FFB6C34CF1A7D70DE5BFC627
+:1024C000F3EADD7FB3303CDFD06ACF30A271DBFAB4
+:1024D0003DFF5DAB56FB84C9FCDD491683EF638E7F
+:1024E00074B0A75F44E4887B61AD0ADBC31F69D584
+:1024F00062F07DB756033B7D35CCEB25DBA8072F7B
+:102500002712F3A8B8CE67077AD7E13CF2582DE539
+:10251000EF377BE66F8071EF775A892E0A077A1EB4
+:10252000E7F364ABA6C2FCAE2A52E8F7D65689DFC1
+:1025300077B0BBA375EFEC7ACE0C263DF14C3FAEE5
+:10254000571B53B54EBCD0D127DC1CC66EDDFB58E3
+:102550002C93E272128EA1F872E4E9F0E53585E27F
+:10256000ABE7776B24BEF8EFD65C28BEEAFA319A67
+:10257000AFA4475FA16BEDC45CAEBF1AA89623174A
+:10258000FBDF119D312CF47701243D4AFA8C4097F2
+:102590004B77A2DCCD323830FE79CFD468D263924B
+:1025A0004E257D7E9CD343A743FA631CDEE69984C7
+:1025B000B2229C4E31BE154A8FA57DD22D7384F276
+:1025C000E534B013E29C68D71CD9D81A428FA5B560
+:1025D0005F19B99C387B75745E301E372D5F619F23
+:1025E00086E215FEFB74A8581FD93546F2A724FCD5
+:1025F0002E14CEA61BEB87A29DB61AEF0D02BC9A35
+:1026000014B79602FD196B0FDC81DF57897BBBBEC7
+:1026100061666E3F09FE90FD7D39A8F038D2A37D3A
+:10262000EC89984AA8F76DB2C185C059E52A7F9117
+:10263000F86D5F0CBD37119BD039FF69E29F210C0B
+:10264000F7F3BE5DE0ED87FBEAF7029E3EA5FB399E
+:10265000FE14FEEE61570A7F5FD625DEA1F7A6F2D3
+:10266000EF4C94FB297F474E7FE15768A27E17D538
+:10267000BFD7DC628DC67172AC8EA742E8FC6A11CE
+:102680001FFF1FC180237D00800000001F8B0800FA
+:1026900000000000000BED7D0D7854D5B5E83E3309
+:1026A000677E330927C9240CF98133C92484640265
+:1026B000930410446512020D083AFCD520890C8A57
+:1026C000DEA82493426CA3D77733908001EC2DA22F
+:1026D000B568793AD042F1AF3728A5A18D74127E42
+:1026E0002E5A2A83D5165BB581FAACB60582785B83
+:1026F000BC9796BBD6DAE764E64C2680F6BEBEEF02
+:10270000DDF7E65EBBB3CFDE67FFACBDFED7DA8791
+:102710001C59C7580663EC52BB3C3F99B11C59A0E9
+:10272000FAE36D5B7D1FB818DBD016A2327D6E8890
+:10273000F94B19B31605E520F433AF65FE2E1B6384
+:1027400097F1373D5A3EE014199B04ED7D4F311946
+:10275000FAA5BB3C821FFAD9E7C278458C7E97E187
+:10276000BF5B180B8E28877E3B98974D646C9D6CE1
+:102770000D0585A1E3DD925175544C19FA7CB0FD2D
+:1027800006819D3647C7C5DF69751E3D8CFF57BD65
+:10279000BFCB8D35878E6532D6827D65C6AAF3E0C4
+:1027A0000F9CB7D5B8DD04F34E965369DF9FDAABC3
+:1027B0004630F7F0F33DD3060B2F642CD466A67297
+:1027C000479BC48246C6BEDBE6A0FAAE3699CADD98
+:1027D0006D45543EDFE6A1F617DBA650FDFB6D5EAE
+:1027E000AA77B5D550FDE5361FD5F7B6D5527D5F32
+:1027F0009B9FCAEEB6062A7FD4D64CED3D6DAD54F4
+:102800009F6E62CDB49FA2A063019C47E78346AF51
+:102810000CF06954CEF1A0372FDD6367CC52A4636E
+:1028200026E86639B685E17E2C0E9D3704E7B0DEDA
+:10283000B185DD05A5617272A73002F6FF92AD5336
+:102840009800EDE2E34C86E7CF08C106E6616C91A3
+:102850003CD6278E62CCE5F84A551AD46F974B3791
+:102860009B9D8C15CAF36BD7C4D4E5E4F2FBF64804
+:10287000D1FA18F776D10AEDCB421336DB05BE0E3E
+:1028800096C5D8BD72B96F0DE051388F0511EE03B2
+:102890004E636807B4AFC0F31271FD12ADFF66D688
+:1028A000EED0C1FAC7C8C6722650FF30B35F7BFFB7
+:1028B0004659A6E7F1EF5DA99F6EE235F563FA2B65
+:1028C0008C87EDC215C6310B0BCD1158FB2603FCCE
+:1028D0000F3C0F66D8423B015E9D06B6CC0770EFF9
+:1028E000B4F0F28893D3DFB3CEAAF14EA0A3F14E99
+:1028F0007EAE9D96A05485F397EA3C3B109D5B9D70
+:102900003FCF83F9BEFABAC836CA51FCEC403C80CE
+:10291000F70AC6247B711EF68FE65001CCF3A53171
+:102920002F75A441BDE03B1E8F1EFA6F621E2BE285
+:1029300049F0511DDB09F51726E6A7CD87EE259353
+:102940007E90E6077C398D7C00C609315683F8B647
+:1029500066DD3D63FAA1FCD309FF1809D6F9B83248
+:10296000CF7643A499CE73928DE1BE19DB9CA473FC
+:10297000407F071CD2758CE946F1D268906EC77E05
+:10298000C675461684F518FF729DD907E3B55F3406
+:10299000D5201F612C92A49B02CF2D7E29159E6FFE
+:1029A0000EEA882FB4CBB69000E36EB2951F95A1C6
+:1029B0001E94749E0284A35B4770ECB07D39A4879B
+:1029C000F144614D03CB87F54A2F9B9DF03CE4D643
+:1029D0004948E721EF821AAC07FDA2A74056180428
+:1029E000B6FBD3421B715C36F0D309D85EC73C08F6
+:1029F000877599FFDE9704F5F6C59247CF7BCBE24A
+:102A000064C646E15F3065BBA17F6D12AE6309EF1E
+:102A10000F7F79E6031DA698F8F97DA377B6945742
+:102A20008ACFC5603FE74BC2652044D1E0317BA02F
+:102A30007DBCADBCC60BA5985C6E96619F1D52B95E
+:102A40007939ED9FD918CC93CE387F6A97743521A8
+:102A5000A5FD2EA477911D724D2652A2F60EDB968F
+:102A60005E84877837634E19D707F3A97C0FE0613E
+:102A7000CEBFE1A80CFBE8BC278DF6210A1EAAB345
+:102A8000BB455A77966C0DB3F1708EC6794719F035
+:102A90008F2CF3FD73B13EAA41FCA03F864F8FF40B
+:102AA0006BEB19B5DA7A3A83BA393AEF6F14F91148
+:102AB0000FB778788C923A4EE0FA47F9457A18BF0A
+:102AC000FEA7A427522B19AED346EBCCB4DD59098F
+:102AD0001082A17D6B10FFFED6758E9716989D30E3
+:102AE000FF78BB0EC1C926B081B538EE2605DF3BA5
+:102AF0009DFC3CA374A557E97224D2E598561D0BA2
+:102B0000C6C81D67D0CA8231F3E577A669EA059B7E
+:102B1000B334FDC76ECDD3B48F0B156BDA4B7697FC
+:102B20006BEAA55DD76BFA4FE8AED2D4CBC2733453
+:102B3000FD2B8E2ED0D427456ED7F4BFEEE49D9AA0
+:102B4000F6A9FDF769DAA77DB44A53BF71E0214DBC
+:102B50007F20E386AE04723255E1571D0E6FC49B91
+:102B6000409EAB2593C481C1F300DE69720066C745
+:102B7000CC97ECB1021247EBA099481F2629759219
+:102B8000EBEDF25AC4E71423E1B388F21CEAAB1E62
+:102B900034864C88FF377964E42F2627E763FB0AE5
+:102BA000BDA39DB0AECA1433C905D1C6FB89B659C1
+:102BB000A4A78CDE0A7CA902EA121B6C4F42FEDC41
+:102BC00016F4B95CD1755BA4CD0CE9B732A586F5D6
+:102BD000DBA2EF8B9297F993713E99EB3F5290FAFB
+:102BE0005964783F665F07743A66433EDE0B7202B3
+:102BF000C6EF4ACE1691FEBAFE525C4D65F2B4594C
+:102C000088EF6512FBCEBF40FF2E811D65A02775A2
+:102C1000E9D885E9B0EF976DE58F83B806D6E8D39C
+:102C200023BF9BCC9AA91CAD63562CB70BFDAB19E7
+:102C3000F473379FA81A09FD9E77F9BDB8EFAF83EB
+:102C40000E81FBFAFA78AE67ADCB9C23A35ED6E982
+:102C5000EC3A9A87EBC900B9828420FA3CA857A8BD
+:102C6000FBBD4F394F31AFB31FE5DFAA54B38CFA28
+:102C70009268DEECFB00E0F58CA1FFB976A877083E
+:102C8000D2CA2EE48B0FDA3C3B19EA8F1C6E72B26B
+:102C9000AE622D8CDBB5C62BA6427BD706E6E9409B
+:102CA000FAB057AE4D85E70539CB7569480FAE359B
+:102CB0006BB1AC73E611FCC6B9B7EBD2A1BD6462CF
+:102CC000652D43D92BC17CE9C3E3933E652BC3FD3E
+:102CD0003097F821E2954E063E034BAF4C83F386C6
+:102CE000792D78DE02950407CB455BC8827517877E
+:102CF0008BC52B8492A06E777905AF1BDFDB4AE78B
+:102D00006B096BF5D82A97FF3EA47FFB5CEDB98A6F
+:102D1000E627687D9B749C2E3A53E563289F3B9D74
+:102D2000AEB47639BA4E95AF3CA0E86BEA7395AF76
+:102D3000FC0ECF2023AADF009E6FD5E5A37EB699B7
+:102D4000217FB23CBC99215E5BA4A0CC500FFFA7B1
+:102D500020E1B9AADFAE5668A63AAFD68CF2FA8265
+:102D6000BD9CF4594BEB2E3AAF78B859FA75CC7B31
+:102D700005B8A6143E4DF21D18B05C00F0E9CBB4C6
+:102D8000356C4FA0F78F50F4850D40C61192573E19
+:102D900033F26B831EF455926FB06190071724468F
+:102DA000F28B7539A9BE3A95D7D5715667948FBC09
+:102DB00092FE6DD96A66FE987D6C8079102EEB2E9E
+:102DC000CDAF41B8329188836DFA8B7BFB46A02F43
+:102DD000D5AE19A1E82B39383794A38D8CEC028F2E
+:102DE0007D6E0DD29DEF621E09DF83CE346AF7043B
+:102DF00099BE99D66D50E592EEF2045AAB6C54E54B
+:102E000030A9B65C6EC1FFF75E1690EFC7C8315EA1
+:102E1000905C57E576C1666DFBD8ADDAFAB8D09014
+:102E2000F7DF42B9BF98FF0D7241DBFEB422BF1736
+:102E3000A3FC86922D3290DC33C38A2E73B91B9586
+:102E400083C01772BBC295C846735A62E421A37D42
+:102E500068E463954B26FCF31D150D788EBE8B60E0
+:102E60007C540CE5CBA34D1CDE7DC6E4D05A78EF34
+:102E700051B08BFCD0753DD8437E20B5AF8B9E5FA3
+:102E8000D6A19D7554EF018C1D3CA7F873F5E4A9FC
+:102E90007AAFEF2DA403C6FA2B7CC97C3E7FCC7C95
+:102EA0007DD694F10CEC965D85FE5F61BF4F6AECB8
+:102EB00013913F98729801E913E767CAFCCC88FA2E
+:102EC000333FEF4D9E379B0FC23A1E396942759CC6
+:102ED000CDD41F3BDA06F555B922F133E9BA95CFC7
+:102EE0005A810F54FD1ADAE19D47647924E9E947D4
+:102EF0000D0CF5F42A058FAB14FBEB9902038DFB47
+:102F000089225FCE3A55BD276845FD172C022BEA72
+:102F1000B325BB81176BCF3389B77B49DF2DED8A92
+:102F20006FF732A4E362055FA06EAB847A9952EF2B
+:102F30006242BA04E738A1B6BF0F4D09F76B87ADFF
+:102F400088877B2C5C7F7B5EC1874C2678C2B0FE75
+:102F5000CCDD364F08FA25EBD99E08ECC373483C0C
+:102F60001D7BEEE37BB475378BA93B711DDAFAA3A9
+:102F700072B3807079B40E7474D8B2352FD9FE61F3
+:102F800009439817227ECDD4DBCAD09E5A55696377
+:102F90000857D3A9B1DF8A20FF38A1672817A424D6
+:102FA000F9B16A785FFA69BA678D1C3DFFE7DB907B
+:102FB0007533F6E4650FEB009EFCF52A6B03EABF60
+:102FC0002FC279A21CF93ED8D9D8DE05E78AF59739
+:102FD000C1CEC6722FD8D9F87C1FD8D958EF063B7E
+:102FE0001BCB1F819D8DCF7BC0CEC6BAA7B072749C
+:102FF0001E9C4FBDCD375340B87A455902BA12A234
+:1030000070661F1661BD5FB80C045227B17E13C0F5
+:10301000F5F81899CED7C47C0CE52BF37BCC8897B8
+:10302000571FC7AB8EE337241A670A8C4376825941
+:1030300042BF481EBC31029E9F79F057BB505ECC08
+:1030400013FC1E5C6FE3A4D346AE3F0F18B1FF36EE
+:103050000BE03FF0A11C850E8255004F94BBAFEBF7
+:103060003DEDD0EBA619A7566780FD5D95E79C2F37
+:103070004E85FAFDA72A4643BD73C7A6F968CFDF80
+:10308000F4BD53AF64030F3E9B378FB73F7EEA42D8
+:103090000EB48F605F9B5F0DED29E95C3E6D1358A8
+:1030A0006DAC7E776B1EC7F340EB169273C0DF19D1
+:1030B000C2A13DD347F2F19C7D206539F40F640C29
+:1030C00064DE7905FE1D687D92E4507BCAEF49FFFE
+:1030D000681F94171E9217EABCAABCF844C13D555C
+:1030E0005EACB2F0EA603F7F3E3D7F5CF1EBB050FA
+:1030F00001D5D32DBCFECF55F271B47B003E64E701
+:103100001E4C29FEC60D6857D6881E13D41FB795CE
+:103110005B50DEFCA3C27F60DC20DAF1C199E6D00F
+:103120004E3C54BB4CF498A68E6F77A1D2C5D29476
+:10313000751CBADE1A463BBFBDDABC03F5C92DB615
+:103140003C1AAF7D8A3188FE15B5BEF6FAEBCDA8E4
+:103150004FA4A6A439B1AEF2A78D80F758C24F8F05
+:10316000E35629DBAD32DBC27AE4E766C31F63F5C1
+:10317000641B8B10FE7874609000BD19F3395E55A6
+:10318000304F2D3E370ACD4144C66DB876DC47B28C
+:1031900091FC0C8C65F375ABFBF066F37DA9FB48E5
+:1031A0003606957D909EB4C5A60BA3BEB705F685E1
+:1031B000E305F264824FFCBEE0E7C371674C51D671
+:1031C0002DDDB017D73153E7EDC0F70E7F566707F7
+:1031D000F462B358B388CFF3C1A2FDD04CA2B3E3DD
+:1031E000F215F40E14E41FC6C8AD9B7E2BD07ED81A
+:1031F000FD463A97CD057CDF4F1B434E46066E6871
+:10320000D482E4E1F1F78521F8EB65484FED695E82
+:103210008EBFD240CA1AC4DFD481CCB5B4AF70C25D
+:10322000F388C7E3F8F3D907FF2972408FF0BDDABE
+:1032300079AAE7A8E241BCFC32E64BEAF93A689F7A
+:10324000DE224E07AA1EC5C0CE491E0ABFF5309E1B
+:103250005C18AD1B1D3ED28F0D764F11FA6FDBFF50
+:10326000AA6F48E4BFFD5081D39A142BE9CDED2914
+:103270005C6FEE4D99A3B177AAC1FE11003FF4E94E
+:10328000AC0BE9483FE276F27FE947A28684EB8AFD
+:10329000D34747CCE5FAA804FA688279D552447D31
+:1032A00034819E3AA88FA6CDE1FA688A91F4D16D57
+:1032B000C9C6DAED09F8CD813CAE5FF7E23E12D81F
+:1032C0007B60E7911F52B5F38C929FEC35759F0799
+:1032D000147C57FB9BA466867E31BDD123A3BEA977
+:1032E000B772FDD104DB2C8A91DFEAFCFBF30CF40E
+:1032F000FEB70BB91EAF3373FDE4A6E3427322B8E9
+:10330000FF5981FB7078F737E00DF185729BD18B07
+:10331000FA41B9CD5185FAC170EF81A919FC282D68
+:10332000CA573C7F9DAC27F9237A1C88675D86FECF
+:10333000578EA31D77D846F246D59BC14EF57AE04D
+:10334000E53DFF0114A81B6A9F82DD24E5C3787D5B
+:10335000AB3227F2F140BF2B1DAA4FC6FB0106E995
+:103360003C659793BF171A85EF09ABA68C447C8AFE
+:10337000A773B5CC75BC9EBB02D6953BEA2895EAEF
+:10338000F3FFC9F4E4578BEF3F365F853F97C7E300
+:1033900060B2117A92C36371DD675ADECCF4C05219
+:1033A0009AC4F3248F3F699E32E21199F3D9DD2844
+:1033B0005FBE22129FCDB9B737352DE67C9F6EEBED
+:1033C000CE155D182F88E456BBC80EF0265AEF4282
+:1033D00075FEF018E2CB06E5FC657B64F65880B715
+:1033E0006CD379D0150D425743FF95626AB504F34B
+:1033F000E7B6318F0DEA4E26911F2BF7B29EF02CC7
+:10340000F7E012C2DF31F60121E88E990759704CBE
+:103410003CE4D3E66AA2CBDC9183F61BC50D3EB536
+:1034200087E7235D7FFA045F51EE77B4ED205BC937
+:10343000CF7C4F8B358426E09887251DD6739F154A
+:10344000588E13D771D0F908FA697E98447E1AFD18
+:103450005617F9599E15FCD3F2812ECE84E4AFA203
+:103460007D4B3FE8D7F835EB8E8D24BF22B3497EE4
+:103470003DA0633B13F8916ECFE7F6DCD27C4E5F44
+:10348000B98E3772575460798CCEFB5AE9A813F97C
+:10349000358CF3C888CD14E70A56B122B4FB3A0D37
+:1034A000805709E8F45FF3957899CA8715F859D0E1
+:1034B0004A817DE80545BFDBFDFCF3CF67A2BC6612
+:1034C000A8DC0DD29B3A4E525117352679BC0CFD23
+:1034D0000D82E4E5FC550A3A8218D7F98B3E215E4D
+:1034E0003FA99CDF1AE77A07F6AF76791C4807BD3B
+:1034F000CEC98E3B017E369B919962F8AF8A2787B1
+:10350000922793FEA18EB32A39EF8A76B611F8B0CE
+:103510007C05F96C447F37EA317D53CD32AC77BD01
+:10352000AD3C827AD67A9BBD9CFCE636E017317EB4
+:10353000249BED08E1A1CDC3FD6B36E4BBE8475207
+:10354000F6DFEB3C42FB57FBAD52F88FCD13E67133
+:1035500047B062B09F45F405D1BEB0D819D99316D3
+:1035600033A7A724380E730C1F51E7BD3F9FDB69BB
+:10357000EB73CA2395B43E113D016CBDA3DC4172CF
+:1035800010E18C7AE8A8413D94FC25CF297056C7FC
+:1035900069EFE5FBF4B53ABCD5E9687FFA9E45BE14
+:1035A000B0DE76A73988F22079E215C77B255FD097
+:1035B000F87BA2E3B5CE50C67B0EC7D327974B3816
+:1035C0009E01F94402FC0B2BEBFAA2FE3080A844CA
+:1035D000F61AE37A1560BC2391FEA09666C5AF3556
+:1035E000F43DCE279D8ADD027CF218AEBF31E7F4B0
+:1035F000914AEAC5ED95B4D9629108E7F5099CA016
+:103600005E88DAEFF17A4CA57E80E4992A8754B976
+:10361000F434EA31C6283DA97E97EC061FC96BC178
+:10362000EE23BC01BD4646BAD163BC3701DC24178A
+:10363000879B903245467AA9BED49F4D723EF9A32E
+:103640006C16E33F53F9E1A1CF7659B0FDD386AABA
+:103650002BEA2B6A3C78B83870CA43BFFF4AACBE2D
+:10366000325C5CF86AF1E0BE1423F9DD9E11B47C93
+:10367000C9EAE2FCC8E052FD27FEBFE0393C23F86E
+:103680003CA42F2A7E947D857EE642BF57A79105F4
+:10369000E13C0F7C36D981F871ADF055FDE6598AD1
+:1036A0001E9565DB25209D66358404F47B673774A1
+:1036B00009DE2BF47B07E93923DADFA08C3F5D1CA0
+:1036C000D0A3BC9AAED071F6459115C5E87F6FE5E1
+:1036D000733DCAA0E8ED297DCF5970BC3E9DAFB3C4
+:1036E00010E5438A4EDE1943EF867BCBCD5531F092
+:1036F00069C7784E82F32B770DEA5B6417A9F2D67F
+:10370000A0CA09BBA8911381248EB7AABE13B89E84
+:10371000DB4182E02F41B89EBBFEF7B7E016CF0930
+:103720006183DD79F578C6A05EA30B2D57ED17A454
+:10373000972E83DCDD4FFA558A07FD00AA5E55F609
+:103740003D211FFB79042FD1C924E6A7F23AC6F523
+:1037500040D0AF6E7091BE075B89397786AE88CC5A
+:10376000ABEFAF00FDE018271023E44FFDFA2581F1
+:10377000F87B3CDCDA06E13618CFD3F845B315798F
+:1037800097ADB4CBE81775627C4AEBB7AC38AAADFD
+:103790004F8A68EBD79D8CF38306BD6FBB3279FCF3
+:1037A0001F07DD06F4867C628512B7CC09862A25C0
+:1037B000586F2EEBA2F86076439A06DE37E995BC87
+:1037C00009E61598BA4EF8658BF33EC6F75B5C8345
+:1037D000FE3BD2BFEE51DAFFA17AC5573BD096DE51
+:1037E0006C20FFA819264778FDC3EC0533F1BC8790
+:1037F000F8579BB57ED5ECD87680C33DDB0C9A7626
+:103800009FB78CEC82858ADF7670BFB88E0CBEDFE6
+:10381000ECF2A1F35F7D5EF82F6DE8FCEAB84F0390
+:103820001F42FECA2EC1B94E46B831F440B05C31D9
+:103830002C609C3AAB9979514FCE6E61DE44FEFE0E
+:103840005D0ABCE2E1CC82D3097E33946759363DF0
+:10385000D9ED592D3AD20FB3804F207FB86525900E
+:1038600011D4B357CAA45FDEDAA063281FD8A536E7
+:10387000CDFBB05CF27FAAE7FE348E87FA65230B9E
+:10388000E9703FCDC54467B4AEBC283E00BC4E7362
+:103890007899095EB74E3168FC9CB9E8D78C818B6A
+:1038A0008A07D971CFBFE492347401726E978BF09E
+:1038B00084CBBF02947FB0A433534FEEEA82F5DD90
+:1038C000B496D17E0752AD219E0F31183FD05F1EB6
+:1038D0000B7CCB3CA308FD2C9B24AB0EF3160EA453
+:1038E000F67F9BA532D60D6A71750E633FB10E94BB
+:1038F00008503FE46AD8D27923B45B065E40E7AF54
+:10390000CD16585013534F49695F5083873685C988
+:1039100022C0C78A33C03EADD29CDD7A98DFEAB6BA
+:103920009153D2CA06E994F6D371BDFC28E67D74A2
+:1039300014E8487F62B1EDB08FB20249A1036F1164
+:10394000F18F1A1EC78F1D5FB45F61FC3930FEC452
+:10395000CF31BE99AF3F131F81DCC9C4F5A3DF1A75
+:10396000C7C7F345E751ECFCCA78220B6EC7780B4A
+:10397000CC6713F87C12E69564326D1EC1E07C12B0
+:10398000CC57FA77D84FEDD0F3305CE93C6EFF7C32
+:10399000E7D1A1F3D27A83E36D64173168D64D463F
+:1039A000FB83CF6711D921B19CC3B5637214AEA05C
+:1039B00007D2B8D07DCD6505CE0684B36424380F18
+:1039C00007B73E89E7356D90ACA135CEFF03E7E53B
+:1039D000E0E7153B1FEA93D73CDFED309FFDDAE7C8
+:1039E00043F822FD0CC217CE646DE6B5C317561519
+:1039F000BC16F8F6C1B8BA18B846F3879E92D02E16
+:103A0000B0187C660FF0DF9B0A5249DEBAED0BCC92
+:103A1000944F90B1C08C797AEBDCB61ACCE75BE7B7
+:103A20005A6436C4C8E975EE3A6A87FE94F7E40E24
+:103A30005BD16DC14A5984FC021B6EA8762C47FCF1
+:103A400069E679546A5E912A0F9912AFA47DC18B01
+:103A5000236EDC3BD007FD37344FA4BCB111A9FF66
+:103A60004EF9529B1A3C1E6CFFB685C71D9F54E24F
+:103A70004E88A8E4571B7FFD7730FE5A5EB04AA0FF
+:103A800078E3CA2BC71BCBCF47AA30EF8A2DE77943
+:103A9000558E3A314E1E6AE97613C295E73F85048A
+:103AA0000E5FCD782D05193C1EEDDAC1D0EE7B05F9
+:103AB000C6D26BE94B877948F1F4281ABD5225EA42
+:103AC000EBAB74B48E6C0CED83882B2F9DEB580EF2
+:103AD000CF73EE163D023C1FE97E98F29140DB2742
+:103AE0007DC3ED3E5685F521FB5CA1DD47FCBEE2C2
+:103AF000D70D828BD6AD9E57F9794F12DA57E5056F
+:103B00000B285F8C7E2ABDEBE3F6938E76B1CE6BED
+:103B1000198F7641CCBE98A69F62BFFDD7D6EF44E1
+:103B20006442BD303E1EF64F3E5AA78979CC467A94
+:103B3000AF8EEC4835CE9685B483E73E9AF1384592
+:103B4000FCFB93F9FBCCC1E36E262B98A4407FC20B
+:103B50007D56F2679A4C5087F3118CCC3C0A9E3FFD
+:103B6000ADF803D7084CC47A74BE30C3F9DA05DF68
+:103B7000668F134B6E4719527D946F8861DB587BBB
+:103B8000B40FF338A07DD5BDCE91E8CF1B01041151
+:103B9000417B5A8953A9FE9394FCFEA528BF5F2C54
+:103BA000F8688119E5333A9CAE676CFFCED35B822F
+:103BB0003951BA345DCC62728C5D63129B299FC30C
+:103BC0007471B4C6CF1256EC31B5EEB58BD5385FF3
+:103BD00004ED05CC5F625207BE5709409163FDA614
+:103BE000171D9A71A2E3E768E60D835D1D1B171888
+:103BF0007EFC242617C58E9F37CCF88571E34B09D0
+:103C0000C78F8E9BAE19779DC8F945D06E0D25F2F2
+:103C1000F39D2DA87A1B4979B87CB33305DC0F08D6
+:103C2000FC58A4389482378F389A29FF4C6FE5F1FD
+:103C30005283123F3998DCC0F32472B4F967554CB3
+:103C400012B17D5DCAACA302B457D9B47AFAF44B71
+:103C5000A7F5C877A68B5A3DDDCB9A093F6F62DA8C
+:103C6000E7861C2D1FD8A8D0872E796284F2D43223
+:103C70006C9477309C5FE1DD3646F95386245F33E0
+:103C8000CA3863E1A5B4750EA88FE0F8652F4C5DC6
+:103C9000887EA277153C5E07748F70AC5B3572BB73
+:103CA0003E66DC3A63B800E5489D8EE7EBD30FE64D
+:103CB0007F37238BFCACF1F352C66F8CDFABBE5960
+:103CC000F0B962F6F1AE421783F3ADCEDE8E7AEC38
+:103CD000E07CA6F0249A6F30EF47992FF38BCDF755
+:103CE0009E42CFEA7CF55FD5EEAFDE18A1FDD5EBA5
+:103CF0009892E7CFE77B0FF7E7FC02F329F95B83A4
+:103D0000F37D4DBBBF7A5384F6573F684F2AF36566
+:103D10007EB1F94CC6668ACF3C26F0739DBB6BD44E
+:103D2000E3E8A7BF3077958CF8A6DA67B7E00B8099
+:103D300067B728F94DB7E618496F50C7DDDD3685FE
+:103D4000798DDC9F8365D10D02E5FB8F9B22783155
+:103D50003EB60DE8DE5B88FE2A89DA436D0E2A77CF
+:103D6000B4C9547E17EC412FF9AD3C54FF1F85DCDC
+:103D7000CE7F6C94B46405EA0B95569EEF7CC334F9
+:103D8000D044A3F61618607D16CC2BFC322BDB0832
+:103D9000B5C2AD1C1EF6EACC109E93B5EC50A40D36
+:103DA000EAA6A97A19F3B84D4EE64BE48F692DE4E3
+:103DB0007E9E47D4FCF81B051E7F077DA412F6BF2C
+:103DC0004C0135D3CF1550AFBAF56BA9A48FD42DC4
+:103DD000EA4F96601D7708656FBB001EBF51F491D6
+:103DE00065A3391DC7DB9376942C13317F4F1F0ACF
+:103DF000C19F0B9317923DBA70316369F0FEADF825
+:103E00001EC895E38A3EF346BF89A1BD16ACE67194
+:103E1000E73B1ED6DA918F59C212EA718F95D919F4
+:103E20009E475D8BB6FD11258EB030CEAEBC352ED3
+:103E3000AF06B44C9E1F827B9ECAD80385DABC9A1B
+:103E40008A4299F3B91C3B2555A7CD768DC078A43D
+:103E5000C998F81E8E3ADE33AA5CB67B090E6A1E3C
+:103E60001AD3BF5846EF2BF3A9EF3D2DBC38EA4AD1
+:103E7000FE4ED0DB3EEC2FE2F219F5EB8D71EBBC80
+:103E80003037EF1BD52C11DE0E88E85750D7FFBF17
+:103E90000B5FABD1A70178747CC6A713290EC37240
+:103EA00068DFB7A8F8A3E4572D1CAC8B4C8CC9AFC6
+:103EB000638E01379EF75B3726793612FE29FA4367
+:103EC000F81DDDE5A4CF3FDEE03A1CDE5CEE8FABF3
+:103ED00096283F48196F3838C7E73FA87E1BFAC5B8
+:103EE000E41FB66FE7F98F59F6AA8FF19E143E3F93
+:103EF000ADC12BED7DA8F6DEE704B42FBE8DF7BB78
+:103F0000C4E87CE8BF0D92FEAABDA715BF2EF5FE42
+:103F10008DBA9E76232B227B5407FC01E69B67EB30
+:103F2000170519FDF10322C5CBC7723F11E608F34F
+:103F30007B2F5CCFD367EB783EC71899EB7DAE81C2
+:103F4000D1B1F1A28F0AB95C9F97F4668B0CF2EFA6
+:103F5000FDC2C042CC579A37E2CD1627D44F153652
+:103F60002FC47CA679D96F7EEA049DEDB7855FE109
+:103F7000F592373FCD83FAFF2A5CC5EBD31801E5F4
+:103F80007785AB17225FFDA85052FC97911C9C6F60
+:103F90009EC0F1E58B967A932E613CFF7CA1EA4F9F
+:103FA00064069CC7D7F3AF27911FF954FFAB571B8B
+:103FB0008764D89489F786949F3D85F49939F837BA
+:103FC000C0F36631DC8BEFEBCC6182EB58CCA329DC
+:103FD000221478E2F215F225E2F14800746D457D75
+:103FE0005996581DE8C7EDADCC6FC98FC173E65522
+:103FF000F09CE7F5A8EB51E71FB22E3852312D7631
+:104000005DDB681C755DE7CA4C41BC5FA6C655D533
+:10401000759D13069E4167C49C929D8BF15CCF25D4
+:104020000F8C16A0FEFCD8B7E99CCF650C3C23781A
+:1040300062EA067E8E23C73E4A7A4F8BE01D391610
+:10404000F9A5D146F7D83A153D6F53863FC8B87EDB
+:104050004FF98FC15C7E3FA07AA2E08D8DFB3BC7FC
+:10406000F2B8494829679A36379F007C0CEC15D87E
+:104070001AE81FB874C188F6F8BC9E5346B4BB9BBF
+:10408000F69E32A25DDD847518A7699B91F8553CB8
+:10409000BC778ED56BE2EBAA3D7138B7709D1DD60B
+:1040A000D3B442F060CAECAAFDA933B1BE6A39EEBE
+:1040B00092B1DB6FD83313D1A5DED7BB0ECB65AC85
+:1040C000FF30DE9F5BE2D7EAF94B1BB47A797DB310
+:1040D000569F5EB6194E07E4D7B2D66CCD7B0C3531
+:1040E0006458CF12E53C97381E8DE8C7633DE65E05
+:1040F0008E40644DFE9DA57C07506AFD16F37A0440
+:10410000A2E3A65A33F95F0FE7F27CFAC04A3DE515
+:104110000905101DB0DE2C28FE2C2FF147557ECF4F
+:10412000EC3E7F241BDF5F692038B0A037827EFD24
+:104130005A059F96D5D67C8C78562BDFC7E5F89824
+:104140005D06F2AFF8B93E2E2BFEEFBAEEC7AAD34A
+:1041500050FF6C11C8BFB1B441ABAFD7E31FA8BFCC
+:10416000B50AA1B013E1A46D5FD6AAADDF355691B3
+:104170006325AC04E9A461AC2012DD28F53FE6FE1E
+:10418000E28D304CF490E0BB7F2C1CD04A63783C2D
+:10419000CAB587043FD5D57678DEC4E50E97F73AE1
+:1041A000A028E2BB06EE5708360A848F4B87C8FF6B
+:1041B00018FD403FB4FECC582EDFDA2DBE16B29764
+:1041C0005E1524D447AA45AF98E68EDAB3F1F8F825
+:1041D000AC82DF6FB07E37AEAB10810EF02F5C3853
+:1041E0002284FEB0C29F2CA77CC7C20AC1A3237A37
+:1041F000D6B1D6722C45E20FA86F5AA02CD477D531
+:1042000012BF9E6094783EA183C5F201EF734CC04B
+:10421000BC3E5C3ACE7B73CED1CFF01C6FD9FAE8AE
+:1042200079E477AE7C6FF963B0BE4D163EFFA6FD14
+:1042300002E9AF4DEE23C41747029AE0BC4D0E854C
+:104240003F76037F54F70FE73D12F9155E1099EBA7
+:10425000A67947A9F10135DF365CA5BB0CE73752DB
+:10426000997767A94CFBCEBCAF4BC07DE7B2E01A93
+:10427000F413FDF3584670544BD58FBF381AC776E8
+:10428000E279363AFA8DA47F2B71EC04FD4A12F6DE
+:10429000F3328D1F61A6FE520AC69B57BD9A7FC599
+:1042A0007C0BBD59A7A1578364D5D0F5CD455A3AAB
+:1042B0009FE7D1D2F7AD53F235EDF3BD259AF685E0
+:1042C00035159AFA62DF344DFFDB6A6768ED7DC70A
+:1042D0001C4D7F8BBC40534F2ABA5DD33FD973A787
+:1042E00096DFD8BB28AFC0680EF6FB010E9D80ABF1
+:1042F00053D2A2FCBA24C58C49C7CC5A61B161D94A
+:1043000059660AE3B97566F138ABE9B5071C6184F3
+:10431000FA8817CD9550BE2084AA305E6456ECBC56
+:10432000E28799869F8F2DE178AE96EF8FF57F5CBF
+:1043300004A57BB79CCDF3A723C5783E66742022E5
+:104340001EEF3393DE31214EFFFD5E69E56F51AE06
+:10435000B81FF6CE26BF543793F0FEEC0E23CF7372
+:104360000AEEE3F9B4EEEE7E9D3786DE02455CDEB2
+:104370007FD35745794B4D3D20CD10BFB79E36A218
+:10438000DFAEA9A73705E5C678DF6923EAD7D1E70D
+:104390008A3C1107AC18BFFC97AEC4F969638A8CDC
+:1043A00034FE1185DFD63FC0F92D20DC5CB48F547C
+:1043B000FE59BF87EFAF7EB191E85BE5A3C03F3503
+:1043C000F1B078BEBCF486D03AA45DE0A31AFB65D8
+:1043D000D9A2591FA33DC45898F418E0A3DAF69C5B
+:1043E000F544DFCBE2EC9BE422E0A7A8479430F74A
+:1043F00065A097933E5DC27DB94BF8F7024EFA6710
+:1044000010BCBF097043BBF19B43E0C4E17735F8B2
+:10441000BCA4F813D5738AEF5756C2F9E84BC3F022
+:10442000CB078A78FB0E21528ECC2CE0B3129E2E45
+:10443000359B1763FEC191DC3FADC77842FD0F0489
+:10444000B465D9AF7B5FCBC47C04E39EC399982746
+:1044500011E83A9CC9004E2B0DF21AD48B010F3C87
+:104460006BE05C9ABAC3B4FEC6AE8A5E7CDED82D21
+:1044700078901506F69E9F45FB64FDEB518FDF316A
+:10448000CCBAA615717D785691CCF398FD3027CA29
+:10449000D9BD26B263EBF7001FC275ED17E85EC603
+:1044A0008E0DE6DA44FAC9648437C0E9D00623C326
+:1044B00038CA4A781FF77124F788D18C78B347201F
+:1044C0009B30D0756231FAE3032D0686715B757DF2
+:1044D000677223EFE3FEDF596160788FB07D058F4F
+:1044E000C7BED3A2A771F4771BA8BEE45E9E377C3B
+:1044F00070C56FD767C3B8EFAC1428DF7EC6DDFF89
+:104500007604EB4BEEE57A503CFE0EE26B1C7E2E01
+:10451000F16BF16E089E367C313CBD338AA7E351C6
+:10452000CEC2B9CF1C89F8F320A37B8CB5970E1AA5
+:1045300046C27AF3D64B1E0CED96EA43EB32912F2E
+:104540001CE4ED652BB70B9CBFC874BF3DBBD3C843
+:10455000D06E7C4039AF0794F392D98080F96E4CCD
+:104560008CE4E1FA9C4A7ED7CB0656BB07FD482275
+:10457000E72FA53F746C8FF523B914BEA2F2BD12CC
+:10458000B0F7F7901FBA2B0BEF9DBF64E0FEB1D1DF
+:10459000CA7805F903B3E643F9CD22CE07DB94755B
+:1045A000A875AF82FFCCBE83E03BCFCCE13EA73500
+:1045B0005C87FBB847F4AF2B82F6B9A37FB1925169
+:1045C0007EE4EB6E3FF9B98A49AE0594F33838F5CD
+:1045D00077DB56631EDE382B9DE3FCBEA72278AE48
+:1045E0004D2E91F20F2D051347FAAFE047085C946A
+:1045F00035F7F89A7ACECFF226A0EB69CA7A4B95B6
+:10460000FB7AAC87FB0F801F8B53CAA3FDD4FDAB95
+:104610007E0F4BC177E99C567F8595F17BFC8FD14E
+:10462000FE97AE3C21E03D95DB0C5E830DE0FC8BFC
+:10463000116C31DAC1AFB731BAB7760CEFAF012BDD
+:1046400079A34DA27A44B9C7F6669B4CE56D46DF67
+:104650006E84CFE243CD0508AF83B94FFAF0BB0CAF
+:10466000E78E29FA2C93F8BD4605F72EF4E8991940
+:10467000DA2FEC1542E43451D67FC7C52CE6077E0D
+:10468000F22BE5BE5C63EBCF89CF791ACECF423BEC
+:10469000A36CE5A9F5580FB4FEDB2CD41BDE07395B
+:1046A00081F815E8169803C6A9BB9846EF37769FA0
+:1046B00030A23DFF926E6016C23F7840A07B5681CB
+:1046C000E6F3C43FB729FE958F8A781C31D053A6F4
+:1046D000A3F3F41673FB4439FFDEE27F4F41FE651E
+:1046E0006E958F4FC3733CAAA773DC583590222573
+:1046F000389793302EE68FFC4AC9D38B6FAF3506BF
+:10470000C92F5BABE06D7CFB070A3E02840D4A9E1D
+:104710001213603D750A7ED5E3F761D250CF17C200
+:1047200056A0DBFA9E19E4DFA86FBEF2F75E86C3DF
+:10473000B76B2D9B18F76FA875B4BF62F3B8D0FEA6
+:10474000D2DE4B0FD23E4CB9AE91FE2BE87781FE04
+:104750002C8A9F3475328A97345E2CA6F2ECFE4781
+:10476000E81E94D93AF024CA0556A823BDBE31A844
+:10477000D56F8E17733A385ECCE9F95211D8276697
+:1047800036689F801D7219F112EC90943EA6B14FCD
+:10479000E29F937D6256FC86A02EF95F4EB0EEB785
+:1047A0008AABC4711948579B09BF19E037E255FC21
+:1047B0003E478CE3EB52E97949DFC746D47703DD06
+:1047C00089E9F937C5952370DC0DC3E4E5BD5DCCFF
+:1047D000F95DE35646F00A6C4D23389D615B7D55CB
+:1047E000809767601D784FFD9CCF97940AEF9FF3E9
+:1047F000FB92303EA7D27FD3562BBDB7C1B5201D4B
+:10480000BFABE11AC7BFEB73B67B8619E17CC75615
+:104810004E77EA7CEF8797A423FD4C320C18D13FEA
+:1048200099D3732A05F5BA49FB17A623FD0DB74E98
+:10483000BB721E8DAD598BE91E10FCF440F7F72BAF
+:10484000722CB0366C44F8DFDFCA087F7BF7FDBA04
+:1048500009E9F76C4F928472F2CCAB4941E4F7E777
+:104860000E98423A186AA5F23DA43386FE5B487F53
+:10487000DCAFA77C85C0813F3C89F418D867A27B58
+:1048800035F7F73C721EE5DCCA9ED91F8B58BEF87F
+:10489000F7A587C6D6D18B63F38EFFD0B63B0BF955
+:1048A000E75991F389FBBB5F217DF6FE4B17C66389
+:1048B000FEE09957FF6332F2B3C04F2E4C463E16CE
+:1048C000F8F185C9D81EF861527322FD646609FFAC
+:1048D000CE862A1F9D6F891A3FCB39053F9C1D9BB1
+:1048E0006BF0BB05934E2CA23880DA3EA940E7C39B
+:1048F000FE93DEAE4EBF3BE6BD8E8848F912134FE5
+:104900005427AD88C1CB0F8A0DAA9FEEDAFC234A4B
+:104910001E82EA1FD91011F93DBB067D08F37B9773
+:104920004678FC3DDE6FC298EFE6523CEF7B333CAD
+:10493000F8BD1EBCA78E7191730F1684E89E7AD0C5
+:104940007CD815A3072D89E8C226F483F498C2A861
+:104950000F2D8988A74C317E91F7A597D7A11ABF53
+:10496000C4AFF563C4FB41E0972CC6C44FEA5BC2F9
+:1049700006554ECD83F97FB18E4918B719E21FA9AC
+:10498000FD12F961E2FD2472E40933BE27BBF8F79A
+:1049900075543D13CF6B6F027AB72974A2D2514779
+:1049A0004447E7D011A932BBA03428ED7B416C0607
+:1049B000312FA867E14EB4D33B2EDD9684F0EA7820
+:1049C0006B01C3EF479C93AACC05F8DEA52F99177E
+:1049D000BBA3F831847F8CE37265501F1846CE1D4F
+:1049E00051F8D6DF4BDEF58DFBEF21EFC0AE7E6DCB
+:1049F0001CB7AB9772BF07B7ABE3E584CA7FD5712D
+:104A00003F53E03D94FF7E4CFA0BD8BFC47F3F1B61
+:104A100027F3EF34F4CC4F27BBF8AD45E9B26DE88E
+:104A2000F8F9A24797E61E3ABEAAAF0582DEC36632
+:104A3000B463BC3CFF34B048A0EF48057C02E9D920
+:104A4000813A4308DBD5F54416F1B8E0628F40DFC8
+:104A50000551F53F553F1C6C9F08EDCEA8BEA8EA56
+:104A600085111FF78B2EF21AA8FD36A37F60DC2478
+:104A7000DC9F859E4F9ACAC7053E7018FD9FB77D83
+:104A800059A0EF76A9FAA28A9FF1FAE4273DF957D7
+:104A9000FC1EDD36052F55FA1A1D4717AA9C7229F0
+:104AA000F06942399D8E72FA3363BF6D78BD1BE4A5
+:104AB000B4584CEF31C2DB896F8BBE4476F7B7C672
+:104AC000717E6C2F56CE2D72A812D79BCB229417D5
+:104AD000359CFCFCB498D3C370EDAE715CCFB91AB1
+:104AE0001D4F2FFEFBD2F1B4E2FF1E743CA8FF194C
+:104AF00013EFF3ADE2CA6A3C7FABBE99EE4DB19FB6
+:104B00001AC86F1DDFEF3305FE20CF34787C38D70D
+:104B1000A843BB27D0C0EDFECE54F938D927AFF15A
+:104B20007BF8F72BF94AF75D94A8ECC40F8561FB7D
+:104B3000034EF2DBDCB7FB84C10BEF2F6D11CAD043
+:104B40001FB4B441BB9FCE0CEFEC583F78E7A82EC2
+:104B50008A2B0477E6CB387E3D6E16FD219D5921C8
+:104B60008C3D36A11F67023E8FB98701F3342ACFEF
+:104B7000A729FE1D16A707FCB8F71DF2F7605C0811
+:104B8000E9D7D823505E48E028F77734F570BEF0B7
+:104B9000518340FCE423253F23D06A21FFB6AA4776
+:104BA0007CACF4BBF74181F4BD217A85571B776952
+:104BB000FCEEDBC417E3F588B4BD7C1C8CB7A05FAA
+:104BC000E670EE6401EB8D60178E447D51966FCDDB
+:104BD000E6EB6321E22F5E8D1FE593A3BF253B72B9
+:104BE000E97E81A593DE11177FE99C13177F397247
+:104BF000381BC751F40C09FE0FFD87F17A4653F7B5
+:104C00000903DA05578BB36C2ED6FA05C788DCCFBB
+:104C10003AA64790D09F344681D3751BAC04A75960
+:104C2000EFAD48473A57CFE7EC7C7E5E67DFF9B4DB
+:104C300012DF9BFC9E2821BFFDF13B2D3FCFE67587
+:104C4000D92CE37B2D4968879C7D6F5512C2F1C733
+:104C500050E2F7927E78524CE83FFC6BF1A0DF788F
+:104C60006731CAB78715BFB108F22D39EA7F897F4E
+:104C70002FA784F3A94EFC8E11E2DF7E1EDFEE1C0F
+:104C8000E59F43F5A7F2781EB1C8F1F5959E54094A
+:104C9000F5BD12D82CC661BF6F651D185FE9CCF059
+:104CA000BF4EF4F1948EF017DEE7DFA1D82393BC5A
+:104CB000C3D014C63FC683AC31535EA39DE220EA45
+:104CC000776246811DAA7C576111C65D4B9438C836
+:104CD000782B1371FC4D06FFC6711877E9153D6BF3
+:104CE000F01DD1938EDF458A8FC7A8F161352EA3C1
+:104CF000C689878BCB0838CF788E67B1DF3D51E30B
+:104D00002FECCB3C7FB37D4A33DD8BDD8E3112E25D
+:104D10009F43E2297F463B353E9E22A2FCA1388D6F
+:104D2000369EB6B1E865C2B7CF1B479B5E3CDCFC44
+:104D300032B7E7E2E69F98FA4926D92F7FF9730A3E
+:104D4000C9B39E0B2477CE0D9894FB9DFDDC4FDDFF
+:104D500063207BFD1CD8411931F26CF9380E87BEF7
+:104D60009E19848F7B23D549D8BF53D17336BCB5E8
+:104D70006821EAD3C188C8F3B119B76BF646C449B4
+:104D80005C3F180227A93841DCC96C4D9C071456BA
+:104D9000FC056165DF33DEE1F64AA085C70F248597
+:104DA000DE023546E22747723305D58F3C32517C0F
+:104DB00061FF00F1D9FA7B797CF79AE30BDDBD0640
+:104DC0009697C06F5B338BF8CDB5FA6B195AC193C8
+:104DD000A3FC39AB44E127A58AFFB698E7F3A735D2
+:104DE0009755E2F7EFC2C39EB77F634982F34ED077
+:104DF0006FABFBDAE281BFBEC6B8616AD1B5F51B05
+:104E000093881E12F49B7E8DE37DF31AFBB55DE360
+:104E1000BC0BC725EAF7FF68FC333EBE191F0F8D98
+:104E20008F739A5EBB3B886D8F088F0E8411BA29F1
+:104E3000FB6A05205531F5BB66E46B73A7F278C0B9
+:104E4000866A7368BB108D8BAAF00A9672BD4B728E
+:104E50009F0FE27712477B23D5E940C7E7A632B21E
+:104E60001BCE5994EF2389D2A8F9747E127D1FA717
+:104E7000D39238BE3451196F383EF2BDD2CAF548CC
+:104E80002FD230DFAFC82DE17680D4CDC85FC344C8
+:104E900079D4029A571E45DFDF3BC49FA78419E5EA
+:104EA000F741BB7301E9CFB213D7B745897BA5CDD5
+:104EB0002974A29F2E0DE42DC6451EC3F808F9F5EE
+:104EC00025EAA7CE97ECE6F36D313001E358C171C6
+:104ED0003CAF82757C5F13D73866087FB05CA0B8A2
+:104EE000C6765CFFCF7461F70E273F1784AF7BAFA8
+:104EF00044F19637A67EAF88EECB2B718ED512EF9C
+:104F00007210ED0C58C7EA572B087F97F64DFD65D8
+:104F10001DEA832E91E03C440F57ECAB938A7DA8A9
+:104F2000DA57FD6827C6D81B3F50F4860474F58312
+:104F3000447C698BC0EDDFE0CFB8FD5B61F4E4C772
+:104F4000E653F52A7192E561EE8755EDDAF1DE90D0
+:104F50002E13E050F1A03E6C02395DB1BED488FC46
+:104F6000BA627DAE95FC4A2BF6E85478273AF79F53
+:104F70002AEBDC707480E212AFC4C52793DD466A69
+:104F80007F48C19F643C5B28571788ED287E47DC2B
+:104F900020E913F9C5EB41EFC7F52DEFE4EB55E33D
+:104FA00020F5617906CE73EAF0C07A2CCB1B9C33D6
+:104FB000C86FB8F2FC7A949B814B178E4C273F80C8
+:104FC000514E745F604B29F71FBE828A08C26BB6D0
+:104FD0004879BB15B3453AEFB47A0BD9E16906A617
+:104FE000C7EFB0A6CDE772ACBCC63E03EB6C512A4E
+:104FF000C9E1F2A372EADDEEA89D9F36BB2503E16D
+:1050000074B5F890EA2FB8CDE8FD6349C6E78F0F75
+:10501000351E7B8BF2CCEEE8D7C687D478CF70F103
+:1050200021353E1BA8F954134F0E8803B3D0AF525D
+:10503000F1EA298A0F07BA05C9E18CC68D027BCF38
+:105040001B09BE4ABC08FA1BF1BD0A38F65169F8C3
+:105050001D021E3FDA87F9B846FCBE9E4479B73F71
+:10506000C27CDC42FCBE1ECFC73D80F9B846BCFF07
+:10507000C1F371FB94FCDE40CF798A37A5B987E490
+:1050800053513CE221C197E19EA48957503D3E5EB9
+:10509000A1B7723B3470D440DF3F0F1C33139FAD78
+:1050A000EC593E06F531F5BBE44D182F88F12F9DE4
+:1050B000F57A2C78BFE7ACCF63C1384145EFC746DE
+:1050C00099F84E381B53989AC48811ED7D8403E5F6
+:1050D000F9F5545A10AE57F5EB77FF7FBFFEE7F1B5
+:1050E000EB7F2B4A97C43FCA7D3ABA575E7ED46B9A
+:1050F000B93B863F6CF071FFF006571ED1DF13BE3F
+:10510000BCD415B17EFC1A6EBFA5CD7659629FBF87
+:105110005BCAFDF86942E2FB0577B987E5B777B965
+:1051200013EA3B89E3011B6A381F51FDFD43E3038A
+:105130009ED75C317EFEB33F33D3BFAFD0BBDF44DD
+:10514000F2FC4FAF9A76A0DE5D5EB3624C32D4CBF8
+:105150004F9A9893CB234D5C61698DCE6B4949146E
+:1051600047F066D3F743E3E305353AE2EF83F18294
+:105170001AF114D515FDFC8EF3BF4BC64F94BE2219
+:10518000843AD1BE78A551F0F4B2A1F10318389B4E
+:105190004D815DD4703BC1536B26BBE06A7185BA0B
+:1051A000BD27D6A19FA08C6DEEC4EF5196B97412A5
+:1051B00088A20471059EDF59AEE811F1FE01C40F0B
+:1051C00094FBF17EC1AD6E6E9F6F55E47E5E0997D4
+:1051D00033EA38EA7BF1E77EC6AD8D3FC4B7BFA79F
+:1051E000B477D4946FC0730BCED531E4FF1D355521
+:1051F0006657CC782FB879DECC168C53D863E3147D
+:105200003C1E111F9F50F95345EF67B3F0DC9FE838
+:10521000E1FEA38083FB332B0E54D23D93E83A3951
+:105220007E3EE118BC6798CAF8BE9899FBB9C8AF32
+:10523000503EF7D33EFCF707982F95FE3D83C031D3
+:1052400057BB0DF9C85C719220937F7BD0DF8DFE38
+:10525000A885C71BE6603E70C5E2B213782E8BEBC3
+:105260000C9477B4F0782D7D675C9557158BB7AFAC
+:10527000B5627B91E0B1C8D85E5385ED37BF184663
+:10528000CF1E9B87BB077A891C83DE79E4DFFE296A
+:10529000DA4515F315BF771D97AB8B7BE61BF847F7
+:1052A000AFB472EE60EE9FC86EBED05341FEEC7498
+:1052B0008CB7BAA372A6E255903FC951F9F3B7CAA9
+:1052C0009D336E9EE73F01E40FAE276D3E8F0BC608
+:1052D0009FFF0B0A3E0D274F86E39F283F745338EC
+:1052E000BD088EA8DC95D19EBE2E2A7FA56EA88F04
+:1052F0001C1EFFF215BC4E1D46FF1A5D2A28DF1B3F
+:105300001B265FA3FBEFE3F7CE2A55F9E7FFE57E07
+:105310006FC5BE51FDDFAA3DD4A2C0592D1F50F468
+:10532000D9BF395F198562C27CE5B4C4F9CA777404
+:1053300009F41D16255FF9B09155EEB1639E9E727A
+:105340002F21E423FDE6F0D3BF5AFF9C1DEF250873
+:10535000128A9DC6AE13249F1B419F213DA8E70FD3
+:10536000DC2FD5C5F34B1BBBB5F71FD4725B29BF30
+:10537000AF500DFB213FB292C7376B2FA7EB80D701
+:1053800018929DE817FAAA18EB170AC8910C353F36
+:1053900030C4E552C23CBE263640F97E4D0D820730
+:1053A000E5C117F61379797EDFB5FA89EA4BB57E48
+:1053B000E6B525DC2F54EB1704D447CD3ADF4ACAB3
+:1053C000EF3D204889F244572BF87EB3E2A7DD6514
+:1053D000E478B0EB7A81F26AF15E0C9EEFAE033CAA
+:1053E0007F7E5739CF9F57FDB26A5EFCB8A85F96A3
+:1053F000EEC3A8F9F46A7EBC7A3F74FE566B18F5CA
+:105400008B4D862E07D2A19A57E42AE572CEAA7C4C
+:10541000773C7E9DCB4A2B5DA518A72BD50DE7E7E2
+:105420006A2B4DA0DFBCAEC8CF75A5C3EAE59DA52C
+:105430005ABD9CEAF17AF97F955F76CCF07EE15F08
+:10544000975C9BDFEA96C47ADC907E95A509C66BD3
+:10545000B724FE8EE8EF54FE1BF7EF8FB021F77BE9
+:10546000B87CEB14E45F4EA3389781E25C2A7FE9B5
+:105470004CE6E3EF53F88A5A9E50C61FEE7B93EF3B
+:105480002AFD5A04EF0F70DD25BBB57EB2D22EADDA
+:105490009F6C42779AA65E16CED2F4AF389AA7696F
+:1054A0009F1429D6B45F77B25C539FDA7FBDA6FF05
+:1054B000B48FAA34F51B07B47EB2E91717C4DD3BDD
+:1054C000E2F85D091811FBDE0CF35D9A7ED90DDA66
+:1054D0007DE5366BF735A655BB2F755C6750BBBFB6
+:1054E000FC4EEDFED2D07FEFFEE2FEFBDBDD32CDE7
+:1054F000D3D7934FDF03DC52E3A2EF5EABF7FFFE9F
+:105500001307AFFB52406F000000000000000000D6
+:105510001F8B080000000000000B53E16760F8518A
+:105520000FC15BF918182EF021F8F4C01CCC0C0C3C
+:105530009C40ACC8C8C02001C4FC40CC06C49E0C32
+:105540000C0CFF81F81B10BF05E22740EC0CC407D0
+:1055500058B09BE3C6CAC0E001C4DC40B378988968
+:10556000B7DF8917C17ECCC3C0700E889FF1D037DA
+:105570000C061B5E27403FBB7E43ED3A2932F0FE0E
+:1055800006612131609A1447F0A78AA3CA0B8B21C8
+:10559000D8C9D294D9950FD40F00F19321F080038C
+:1055A00000000000000000001F8B08000000000049
+:1055B000000BED7D0B7C94C5B5F87CBBDFBE92DDA6
+:1055C000CD26E44900370960501E4B80C84BDDF002
+:1055D0003252C40411828A2CAF10027914A9A5FF9B
+:1055E000DABB0B2804AADE5851A37F6A17041B2DCF
+:1055F000DA80D11B6DE02EA208D56A684551AB0D4B
+:10560000888808498C8F6AB57ACF3933DF66E7CB53
+:105610002E89B6FE6FFFBF7BC3AF1DE79B99336733
+:10562000CE3973E6CC9999B32696C20C9733F60D12
+:10563000FE416A3331C6C674A5ED4AC77035A7ABC3
+:10564000FC36BF9779CD8CD5F9AD946EF1A733EFC9
+:1056500060F8EE331406ED8CDDEB7751FE17FE4259
+:105660004A6BFD4554EF4E7F09E56FF7FB28DDECF3
+:105670002FA3EF35FE6ACA6FF0AFA17493BA280D5D
+:105680005082BFA2C2AC64C6AA9EC9C9DB0CB92DA8
+:10569000B3C627A8A321FF8A9119B300BE4FA5FE68
+:1056A00098EADE347074573D0DCF4DEAA47E08A70A
+:1056B0007609C78B59992D46BD2C1CE79D4B043CA0
+:1056C0007B6B4D4E72D47A8311DEED25006F28146A
+:1056D000B842D69CE8F02E46789B4B545E2F395842
+:1056E000931D1D9E07EBD5DC20E0A507AC31EA8DAC
+:1056F000C17A1B6E10F8F5F3D56445EF773CD6639D
+:105700002EF56FAD56467FDF64E3FFDB5DA72E16F7
+:1057100079236693181BD7D54E9F321660384E9565
+:10572000F90A890FEECCAFBFC967EC268409ED03F7
+:105730009358C808FD079258707D96547F26D56F00
+:10574000EDFBF537A952FD80214A7D136B50B0FC6B
+:10575000E72847C0F7FBFCB9946E14F273DF5003DF
+:1057600063D82EDD1C1C04EDEEF17B485EEEF68F57
+:10577000A5F2BB841CFEBB90B3A090B30751CE2012
+:10578000DD8A7266C6FE7CADA500A77D6F3CDBECB2
+:1057900026F95A4C78AA8CE06FD83B64FB66807F70
+:1057A000DF0DAB4E6F03FAB7350FF318A1DE3D43A3
+:1057B00035F9625E96DC55EF9ED9279C8B8612BD2B
+:1057C000CB10CEDD1EC13F15061651EFEE19E17A62
+:1057D0001558EF2E4F185E28B2DFBBA684EBAD2222
+:1057E0003E2BACA4C1DE9D2F3B9842F3110485E80B
+:1057F0006B42FAC2BC7C76C0754A2BB44F49CE4B83
+:1058000063D0EE7E9C8F669C776EA28BD61EE9ECF1
+:1058100083EF1916568DF081B2FB8D80AF69B63BD0
+:1058200011E972FBB5454C19C6585F519E1A2852B2
+:10583000B200AE7D4E9182DF4DB3A11CBEBB447958
+:10584000F21A5E7E3B963BBACA13B11CBE27554383
+:1058500039E4ED7379F91D7EE0C4E0AE7A9B80CF28
+:105860003EE2773AFF0E6C45FA9846F354C3FB09C3
+:105870001412A0DF414CC774E1BF69D0BD190BED14
+:105880005DF8DA06D7535EC36FD3E038CA6BF8D839
+:105890002EEC97B110D2BE4BFA326FAE980FAC3BE4
+:1058A0009D13BDD95279A6EA4950814E992F1959B5
+:1058B00000589009E289F0F4ED8A9881F0EC71FECD
+:1058C00025F76EFE9986CA74D0D2A3821E1A1D36A1
+:1058D000F697E9601920D361E300990E960BCE4F3D
+:1058E000871DCC4D748E450FADDFCD43E47EE32E96
+:1058F00092FBDD7C91DC6FDCC5FF9C7E6BB2E47EAD
+:10590000ADD972BF35D972BFD69C7FAC5FA67A6025
+:1059100032A0BED2FE2E94F4DBD5CC7716DBA39E4C
+:10592000C3F9A4E93953B28FF9EC5DFC84758AB1EF
+:10593000FC48388325BD0A703EC57A00C77B7E3897
+:105940002E1D9C417A385F0B7C58A49EEE06870D75
+:10595000D48FC3A4F076214344FF4CF5B1224764B1
+:105960003B8FAEFF1C7DFF4E458CC370DEFEDD3AE3
+:10597000BA66EBF14913F830C3F9E8C15C3A38591B
+:105980007A386E814F48392F1CB77E1C178AFE0368
+:105990008AB47E013D8675B56B07FC689DCAB30469
+:1059A00077827E08EDFBF214AE03E71AAF755BA0B9
+:1059B000FEFE9196D0E5507E2E5810B440F9E427B3
+:1059C0008F3AD18EA978D2A862B9619F8DD697B649
+:1059D0001D0A9557595AEE9C00E51D4F1AD976EAD3
+:1059E0002ED380E33B25740A0BF17CA98D672BB67F
+:1059F000EDBF11DB973559980DE0553CBD6CE604C1
+:105A0000C82F3B646258A562E75A735FC82F0F2AFC
+:105A10000D98077C699D0AE4D9823BA1FEBA7D5F9F
+:105A2000B621FEE71A4D83109F33B04EB8619D78C2
+:105A3000C9D1923A1BE8531EDC3D0DDB97EF523C77
+:105A4000A0E100FF9D073310FF47148F0558B8A24F
+:105A50003E9EB923E6CBA946238D77D53625C800CF
+:105A6000DE32563B0DE95981C4413C3C96A04DE9DC
+:105A70009A6F67FC75D49F96AF7804FA83F6958F7A
+:105A80002B1E1C72A581F9701EB73D6D2B79C88E37
+:105A9000E35D6B1EECC0716E3463BD65C1854FD98B
+:105AA000DC88E736F334C477EB3673E950A4235B24
+:105AB000503414F1FBBF327E75462F8E77D548CB1C
+:105AC0007623E0C1ECA181B31CDDF5EC1958AFDC05
+:105AD00011EB673903BD4FEB77D05C3CACEBFB9728
+:105AE0008644D21F2BEA8DCC6DEDEA47938FC0110F
+:105AF000211F7B1D446F8D9FAB5C7C0A68FC5C950D
+:105B000028F8AB76E4CF1AD61D9F3B912F644FBB8C
+:105B100028FD05AC9B986E81751EE9772FD84F6ED6
+:105B2000B2CB3DF4FD01B09330DD0A7612A60F82B0
+:105B30009DE4167612D6DB0E7612A63BC04EC2EF5F
+:105B40000F833D8E693DD8E3F8FD51B0C731DDE5E7
+:105B50000FD0F7C7FD359436F86B29DD837C83B40D
+:105B6000D11FA47A4FF9EB296DF237D0F767FC4DBE
+:105B700094DE2EE8E89CC80A701D757A990BC99EC0
+:105B800034C35B60827C5211CFA7DE102830433EC5
+:105B9000D50779A04BDF95A1020BE4FB56F3F20188
+:105BA000B7B04956C80F08F0F2ECDBBD936C90CF4C
+:105BB000AEE5E583B70626C5417E7090975FB42BAE
+:105BC00034291EF21735F0F2E1CD6CB21DF2C34359
+:105BD0003C9FF79277B203F2792D3C9FFFE7C064B8
+:105BE00027E4F35B79FBF16783467794F5778FC9F8
+:105BF000BD1855CE01E56DAF9A0179B3FB265489E6
+:105C0000479553946F3479A9FC7DA5DDABC23ADF8B
+:105C100068F652F917CAE7947FCAE4A3F278835270
+:105C20004079B38FCAFB1BE228DF640A50F90843AE
+:105C30001F9E3707A8BCC0D0AF00E13F630A52F9EE
+:105C40003586413C6F0E52F92FD4E10553A0FEE397
+:105C500006DF5ED477EB155F19DA874C6D48477D18
+:105C6000A5D9953B717068676698691EECF943FE8B
+:105C700043340FF02F19F3A50FA35D0A700E121C09
+:105C800013C031F60C27EFE5B1129CBC97CB34382A
+:105C9000AF101C5BEFE0EC7979BC8CCFCBE51A9CA4
+:105CA0006304C7D1BB71E5BD3251C6E795951A9C17
+:105CB000E30427B177F8341E95E9D378344C9F3349
+:105CC000B83EAC4FE91D3EA35F93E933FAB5307D92
+:105CD0003E267C327A07A7F135993E8DAF85E9F3F0
+:105CE00015C1E9DFBB718D7E5DA6CFE8D7C3F43166
+:105CF00019104E56EFE03CF5B64C9FA7DE0ED3C709
+:105D00006940FA0CEADDB8F2DF91E993FF4E983E64
+:105D10006984CF90DEC179EA1D993E4FBD13A68FED
+:105D20009BF019D6BB71E5FF45A64FFE5FC2F41983
+:105D3000427046F60E9FA6F764FA34BD17A64F1EB2
+:105D4000C119D33B7CC69E92E933F654983E1308A2
+:105D5000CEB8DEC1693A25D3A7E954983E5388CE20
+:105D600097F66E5C63DF97E933F6FD307DAE22383F
+:105D700005BE7AC287011C476C38CF9C93E9F3CCEF
+:105D8000B9307DE6109CA90027A76738E3DB64FAE9
+:105D90008C6F0BD36701C1B9B277709E6993E9F339
+:105DA0004C5B983E6544E7AB7A37AEF1ED327DC689
+:105DB000B773FA54593C931D68DF2532CF76687269
+:105DC000C9C986034EC89BECCC83605F52423B102E
+:105DD0003EAC956417AA1ECD4EF130B4436738DD52
+:105DE0001EF4FB18357B84B5D07EC1BE2B51F20763
+:105DF0007D6998740BE2EB00AB2DD22E49181B275E
+:105E0000D94389DE2429DFA7B0AF543FA5285B2AF8
+:105E10004F2BB9482ACFF0E549F9CCB2F152FDFE3B
+:105E2000D593A4FC056BA64BF5B302B3A47C4ECD71
+:105E30007552FD41B58BA4F20BEBCAA5F221C155F9
+:105E400052FEE2FAFF23D51FD6B04E2A1FD1B45915
+:105E50002A1F19FA85941F75E801A9FE9896ED523C
+:105E6000F925C71E95CAC7B5EE91F2134E3FA3B3ED
+:105E700003E5FDFFFA02C6EDC10C33D983218799F2
+:105E8000F2E67D36B2FFF7631EF869EE3B83F2E679
+:105E90006717BB93713F8D0060BD2FE85B7621FAD9
+:105EA0007B6E1EEFBBD005DF6F36FB46B8A2F82332
+:105EB0003CAA6F9F81FC452D0A4BC7D46DC034CEE0
+:105EC00028F6EB162E5F1BB3F21F0A44C8694D7FFC
+:105ED000987F903F6C3093FDAAC9F7C6FEA5E90BE9
+:105EE00023FAD9D0DF5CB27D28FFBED88EFD15BD68
+:105EF00088F3ACCADC3118F1D2F763C91E2BF56305
+:105F00001D5046FDBC86FD44F8BD2C03CA74FD58E7
+:105F10004BB68BEFA29F6338AE58FD6CCC1E2F8F13
+:105F2000674039F5F3AEAE9F8D03CA75FDC4F1F13C
+:105F3000C077D1CF7BE71D4FCE44793C17ACA47E10
+:105F40003A7474B35CB052D78F9DFAC1EF8BC99F7E
+:105F50000BBB8034E0B3A5A394E4E03F6D2C00724A
+:105F600061CE2CFF35E6D95B363608FB7143BF5056
+:105F70008FE572FFD1D386241ACF6771C0FF083B2B
+:105F8000B56B3F1BA07DF15281220B0246B0BFAD25
+:105F900014B2B96457F1809BDC90361D187837F63F
+:105FA000B3C5E11904F9B6A6C9E6C551E46969ADFE
+:105FB000E9546BA45F44DBDF4C62B9D5D0FF2E9B64
+:105FC0004BCA6BE94AC5C5843F82F22760DFC260D5
+:105FD0003FF067D8173020D5BB26BE4F7B07F6377A
+:105FE000986F85FD0D9633B696DA9D107EDA13B75D
+:105FF0002B41A4F7673FF9A189F47880BD9A9E8A66
+:106000007E37FEB7604D3CFAF8C3F82D0CF491F2E0
+:10601000A02E330DE9B42FA4FD6FC7D396E076A46C
+:106020006B4D26D054D4CB66EC75D8E4662451363B
+:10603000D33096B1D9D5C553D3681629FD57019EE3
+:10604000B31A479AA0056B33B5DEE8B177C1655E38
+:10605000D309A48F15FE219C6B0A211FD1FFB545E2
+:10606000727E2E53BBF2C0EFC1C66CC137D1AFDB1D
+:106070006B42BE16A5727CE6629A87C5DCDF51E2F0
+:10608000E26D357CAA169B5888F6A7811486FEE837
+:106090004032D5BB4EDB67EAF02B3159BD4540D7C6
+:1060A000928546A2AB1EDF37F7C57B0DC321ADB984
+:1060B000DB84AECD9EF09FE793CB5919EF4FA3AB96
+:1060C000262FA7047F4F20FF217D1FF90F789F14F3
+:1060D000FCEF9263CEFF2A8B6F26F2BFE37E232371
+:1060E0007E09BECF117C5F5A2BF37D0EFAC9A1FE4B
+:1060F0009CD559C1F558BFAE8FC45F18B84C87DA2C
+:10610000BBA6825AED86FFDB420EAEABD9FD3CB298
+:10611000F7FA32DDF8041F6E147C98AFA3C71CC1D8
+:10612000B7F9826FCB58E0B60CF21F054DE8179B0C
+:1061300057A630D417553FD5F8D62AF1CDA7F14D43
+:1061400087EF8D826F37FE84F34D8F77ABE05B6B0B
+:10615000DDC72696DD1D6F3D9E0BD6E8C615D0F334
+:10616000AD569C3BB8CC68EF147B0BFA9C8CA87F97
+:106170004DE1957D4E46E8856B8B8AA5FCDC9279D6
+:1061800052FD79BE8552F9F565CBA5F2F9D53F945C
+:10619000F20BD6FC44AABF30B0562A5F5CB3492A42
+:1061A0005F5A7B97945F5677BF547F79709B54BE3C
+:1061B000A2FE11A9BCA261B794AF6A7A5AAA6FD89D
+:1061C00037E46A94AF978E1A19FACB3EF5BC4FFEAE
+:1061D000BA4F3D260FD6A944991B87F2EC26793E8B
+:1061E000E5CFA5F4B4DF43F27EC63F96D2B6A60350
+:1061F00076F43F56C581DE4F043BDCF8E6DA9A7E42
+:10620000B8DE40FBF18C351B5BD706207F000FA367
+:1062100060DECCA833B3D02806D2DD372CCF1DC624
+:1062200088F2D61ECAEB5416EAD3BD7C466BF4EF57
+:10623000ED4AC7E00CF413BE61613B23FC75DDCF72
+:106240002B5826DA15B1CACF1A5859E479D6492302
+:106250003F27711A279D3442BAD2CCE7FFCA3D19B5
+:10626000939813F3A1C1D551FC2EE1FE1A00993485
+:10627000E4738E34EF97D55DDC35CF19F6934D720C
+:10628000BB3C384AFABEA27E82D42E57F1BD6B8445
+:106290007A67F71B69BD66A10303AE1986F8794FCB
+:1062A000E277D6944276578BDFDBE7E440C6FEE820
+:1062B0002FA4F4557F11A5AFF94B283DE6F751FA0D
+:1062C000A6BF8CD23FFBAB297DC7BF86D2567F804D
+:1062D000D213FE1A4A4FFA6B293DE5AFA3F4B43F3F
+:1062E00048E9197F3DA567FD0D94B6F99B28D5F4C3
+:1062F000674FF2775AACAF6750FEA2C899F956B60D
+:10630000AE6662979CC5A9967528671A7D67D459B1
+:10631000843CA44AF29088EB30C9590FE5752621D8
+:1063200087B1DA472F4779EBFB3DC81B63EB480E7B
+:10633000660AB9FBAEF2C6D01B9F82F294A99327DE
+:10634000590E3539D2F440AE52345C1DD325573343
+:106350008DDC4ED2E4EAE7682746B1B76E5015B13E
+:10636000FE71FB88F9320C68BFAD127E7FE64EA746
+:106370007CA7E87B3D806BC17A6A3017D791CEDC71
+:10638000BF0D46FF78E7310B433F7CACF1E9E525D3
+:1063900036DDBDB47F280DC2A236AA7BB92D8ED3BF
+:1063A000D56660852C0FCF67F38FF9809F71FF79D9
+:1063B000711EEE6BE1BBCAC8AE0A7A8AA3F8DB197C
+:1063C000CA785ACFF4D5EA9F7AE0CB7C3C379F2934
+:1063D000E679DC01233FD70E3DE4B926E27C06F6E0
+:1063E000DBE9E877EE18647691FD10EA2BD331D81B
+:1063F00057A2E381419F0DC6F38D4D208738BF3AE8
+:10640000070E4E60E7918F9EF47C4FF45C14ECDB3A
+:106410004B7A9A199E1B013DB7E3FD97DED2B32755
+:106420003DD9937E3CB199D3D929ECD358746E9F52
+:1064300004F32E8A1CDFA3AAB21CB381FCBC43A3C5
+:106440003FEE4B23E87FA9DD4DF59FDBF7D6805665
+:10645000E8A7B3F1C204C6CF73C8AEEB7852D8ED4B
+:10646000EE4C998FAD7D09AE06E7B9275F1F80FB23
+:10647000E4DB3003F3ECC9F8A25FA9295DF07A7B75
+:106480000E1F6B5CBBBFE5FC6C4FD5E667CB009481
+:10649000A7CF841E8839BE9EE414C70770AE52F899
+:1064A000F836188B7E877A263CBED129BD1A5F55F7
+:1064B00082992923003F87D9CC1218DBA1FA0EAAB2
+:1064C000B48FF3B406D04FB12FDEB31E5852E53C63
+:1064D000F372C88DED647FC68A7A9B4BB69F125DBE
+:1064E000B2FD94E18AB49F3A0F3DE4F4017EABD251
+:1064F0000DAE93A3709DF38A758EAFAB1A7E150D0A
+:10650000592EBB0447CE77D62A850D244FEE84D969
+:1065100051CECBB47455BAD97512D6AB33F539090F
+:10652000D8EF19BFD5C5D757978BF79BEE8A5C5F1D
+:1065300057AE89A3FA1A7EB1E0FEB3F163AC91BD08
+:106540006BC57511CA7262D78FC94FF513339D4B56
+:10655000379B3E43FBDD96ABD9EF2AE535B8550DA9
+:10656000C68065047EDF25F507EDDCDA1933B68BCE
+:106570002D372A3BA5F113F86FC58377DAB75A890F
+:10658000CF3E809800F0DA557B0DCAD50995CFE74C
+:106590002A21A715D656B3CF4DE46E41795E3496C5
+:1065A000691366EE5BA0A73F78D144F7B4D85700D3
+:1065B0003DBFEBAAC01256E444A7E7A2C61533704C
+:1065C000DDFEC0A0ED876BF371DCE798A110F5D27A
+:1065D00039F647E7A888F93AC4C4FD31AC86EF73B1
+:1065E00002F00FC7B7B456DEF72CAB93F3A56C5689
+:1065F0002AEADBD22D261604DC97E3BE491B37E8D6
+:10660000DF0C13F76B2C63D51B709F7EAF89FB7B70
+:1066100016B9989A097855FCC72FF3D1EFE3317179
+:10662000BB433B4F5E9EC4F12E9F1D347BA1FEBB3E
+:106630008DA3E680C685F6C10D64FF1433CF4ED618
+:106640009DEE8B6B64FC7AC25F8FAF6607753BD79C
+:10665000167824D72BDE60143D77994911FB3F3E15
+:106660003F669B647FCE3C93ECF7D1E4C024E4E02A
+:1066700084EABBDA3486F31DF9A8A81D665F443DA1
+:106680007357BDD9E7AB67C17A46AA37CF9482F575
+:106690003AA6D1FE98813C0DEDAA67EB827723875D
+:1066A00027D7ABF88FC79E0A80BC94FFF61E2783BE
+:1066B00075F303B536D503DF57EEBCCDE985F4B4E9
+:1066C0001A70223F3F081A0BA3D1634B981E5EBB82
+:1066D00082FE34219FAC26407E8ACF769A5CE4E726
+:1066E000AFB7842C20A7958DCB67B0E1943FCEF354
+:1066F0001B3F3262BE49E657F9AFEF4975F37B366F
+:10670000DC9FC44264E756EE786F1AAE1755AC832F
+:10671000E44CDF0EFBFF3C89E6F5427342F772C0A2
+:1067200093FC095562965535FEFC23A313F3B27C06
+:1067300094097B15E984FBFCDB4C8EE453F190BD9E
+:10674000845D82F35CA3070B72BB75FD23F70D3FDD
+:106750000EF89CDDF1A253191AA91FB89C75362CAE
+:10676000FE95D5105B8FB4811C46DA470098DAB9E4
+:106770009B84BDDDCCD395A69013EFB3ACDC66F261
+:106780008004B2958F1919DE03606F5882E8175D97
+:10679000F1D8F3AF8D07BAAFD86D4A9EC187635762
+:1067A00052BBF85205FF5B93D7C587F2279E37BBD4
+:1067B00087F1EFB72475F163C5EEFD6636AC3BFD9E
+:1067C0002637EC37B7DAA3F0A5E1F8345C67D73F9A
+:1067D000F25733FA133FD8A7B0B4ACEEEDCBB63DC9
+:1067E0004FEB1DD289F828F814E65B377E85663EAC
+:1067F000339AEAB9500FC6E2D732A177419E1F7F84
+:1068000006EFFFBC69F1E0F8CB1EBFC989E3785FF2
+:10681000ADE672FDCBDB52717E979902A92E4AF943
+:10682000F7B2077F44F2B6ECC88F52C95E60DE0C47
+:1068300003E9E240068E6FE9D66B697CA5CC47720E
+:1068400057F64B6311DE47FC546585BBA3CC8B38F0
+:10685000B342F8BCBF1D0C1918DFFBB8BF447DF66E
+:106860004723DD8B62EC87746FEC4762ACB0F2516A
+:10687000FE532BE7D371A12771224BF2BA63630B4E
+:10688000F2E74C7F6F1A9E73001D02825ECA3700CA
+:10689000D778646A1AE70F73ABF9A21DE8F7C9F855
+:1068A0001DEBB798BCB6E1523BA10F79FFAB45FF9A
+:1068B00080771CAE57EFA746B7F7C688F1C15F0BCC
+:1068C0008B90AF88F9CDE7FB8E4D7C7E6BF33D5806
+:1068D0005C88E59FBCCAE70FB6C3F501F00AA55175
+:1068E000F9FED90AE903D857479BD73B4C625ECBE8
+:1068F000E56029D27A0F78AB4A42A49C00FC24A21E
+:106900003FED834BB740BB08FBAB0AFBA37AE6AE77
+:10691000EF11EBC332A1074C6698FF1777CD7FB616
+:1069200095CFFB9EECC995A6E0C30FE07C7DC3E24A
+:1069300009B871BE9A8A70DC1FEE3AF0DA7520D77A
+:106940001F3668F354D69FFA795AB6670C8B364FC8
+:106950003FB4C3FE2ADA3C85EF51E7A9BD95E4F8C0
+:10696000FBD69F1ADD869A65BD897AF019776CFA95
+:10697000E9F5E0EF4D6EA2A35E0FC2DFAB2CBFBB0B
+:10698000DC69F2A6C959F96F2A2E407D1396474D4E
+:10699000DEC2F2A8C99B7E9C32DDF4E57F15FAE6E3
+:1069A0007A6BE13568175B3B18ED570A661B83B8B5
+:1069B0004FB67EC268BE4FBA219EF2738DAD4FA016
+:1069C000CDF756C5DC61B88E5FCF02267E6E5E6B5A
+:1069D000223BF5AB6FBE9908E3B94ED0F57A20F3B0
+:1069E00055C087125509C5019EF354164848427F89
+:1069F000B1C24E44E0717D999CC7BFCB52BBE0F45D
+:106A000054FFDBDAD5DF353DE2E767577FC294F606
+:106A100017603847C85171333FA7A81AAD04B3694E
+:106A2000FEB5AA4511FB84C7CCDCCE3832E59A31DD
+:106A300048BF82B9C31248BE6B87D03EB04AE8ADAA
+:106A4000CE803B01F57967730EEDFB3A0F2D76F89A
+:106A5000A2E8AF0342CE9E17E72CED76A5D608F24A
+:106A6000DECE3AC86E09D86D51FD6E756683B0777B
+:106A700004DFE0CF08FD9708399C074D13F222F898
+:106A800036FBAA0F5467773EE0DF89887DC33F4A13
+:106A90005F946BA4EF015BEBB4A228FE994785BE1F
+:106AA000BEECD92FCCB8CE4D692E50918E53EC460A
+:106AB000C9DFB15D9BAF43D950C4EBB26797DF31FB
+:106AC00006E4B8EA90D16383F155357F64F645D981
+:106AD000BFE9E989F0D17E6C3573FBF8A8A9682974
+:106AE000D2F5E8B5FC3CF74F664F45343C675B395F
+:106AF0009EF358D1A7A3957F3DFA16CC7584260145
+:106B00003D3AEDFC7E7277F9E3F3BED3A504D72AB4
+:106B10002887469E4FE6F77FA731DF1D13159AEFB2
+:106B20009747EAAF82A6E2C7F03E4B65B3E2324038
+:106B300079A5DA6A4639AE6ADAADA25DFE03377F1F
+:106B400067C1D4EA61B323FC5BAD66EE4F3AF0B7A0
+:106B5000EBE6237D3F9E6D61889777E8474E5CEFBB
+:106B60003F6E1E45F320D6B8FEE0F75C3305FDF11D
+:106B700066AECFF4F2302D395ECA5F3B99F5C37330
+:106B8000DECB2CAD3779A2F06F9D85CFD35EEB378E
+:106B9000EBFF30FD3611F41B976B53A47E9B6EE127
+:106BA000721FA1DFD2A2E9B7556BDD692817ABF6DA
+:106BB000E6A4215F571D5E9A124DBFBD20F6B58732
+:106BC000C53DE9F67EA0DF4644E8B77EA0DFA2F827
+:106BD000C1475B34BBB307FD66FDEF997F2FA07EF5
+:106BE0008B32DE2B84DC69FAADB0792DE9B7C27E39
+:106BF00046E93ED2651661C7C5D46F0BEFB996F270
+:106C0000264F7C14F941BAA27E3B2CF41CF6837A01
+:106C1000EE67966FA7E7E65939BE3DEAB9FF263A17
+:106C20006B7A6E557F85EC97EE72C8F5DCAA2CAEB8
+:106C3000E756EDE57A6ED520AEE7F4FA6D5237FDF2
+:106C4000C6DB57E6427BDA2766DD7703DEE72B31CA
+:106C500079AC507F865B7B5F503D2652DFFDCC12C6
+:106C600043DF7940DFD97BD677AFA0BE53498F0D84
+:106C7000C479A4978FE903E3A5FB6A47BF38F59B66
+:106C8000DFE27CF98391EE03BD6EE0FBA17D5F9CAA
+:106C90001A85F3EE65C407E6CB4E217F6DFEB1A4E5
+:106CA0004F270FE5F3BDE2501CAD13958D0A1FEF82
+:106CB0002D4AD08DEBC0DF3EA77DF2FCBD7C9F3C12
+:106CC000D7C2E9C17E6CE4EF2280040B23E4A1E487
+:106CD000F372F2F395A8CC8AF6EB8243D33F40BB24
+:106CE00075C1E73564EF2EC0EF78BF6277EB864C55
+:106CF000E877FE7285F61B4CDC87D0EE4B5CDFBC80
+:106D00009FEEAFE8EF4168FA7C7EB5FC7D81CEAEA8
+:106D10003F20C609F62CD185BD628CEA9F3BA0A717
+:106D200087878FBF6235B78FC3F400FAB895EEF44A
+:106D3000008ECE5898DA35FEF94FC2B892BBC6A580
+:106D4000D1433F3E6D7FB240CC8D58E3D5E8D76D3F
+:106D5000BC1A3D75E37EDE22ECA28BD9309C67AF76
+:106D60001B7C778C41B9F83D8C1FF099336F505ADA
+:106D7000A41E7E51E8F3AB7CC7A7A4BA915EFCFDCC
+:106D8000DD7565BB9F4F85715CEDCDCAC3AB08D780
+:106D9000FECDEC433FC2015B07E9354DAE2EB47228
+:106DA00039FFBB8073B4AF6B0AAD1F4D8A8BE64BC6
+:106DB00048A7B7C4BDB02AA027CEC7AA26B1DE8097
+:106DC000BCE17C9BA6AD3F487FF8CFAB9A39FDABC9
+:106DD000AA15A2FF4CD67110E95B99AC7842006A03
+:106DE0005AD3EEDBF01ED50B36F88EF3B64CF16CB1
+:106DF000E7E4B067A446954B359A5CB2EA21E457C4
+:106E0000D0D6C105582F09DF8BBC9E82F689DEDE05
+:106E1000B8CCD27214F1B8ECC726B68D75B73F3432
+:106E20007EE7C2BF6FA2DDE7E9417E0709FBF205FD
+:106E3000A4B71DE9DA6146B9AF0AF175432BAF5229
+:106E4000DD53883E1ABD9B605D18CDE98DEFBEF421
+:106E5000F4BC5ACBA33C63FD66C584EDAF043EF49D
+:106E600081A2C9862F0E6AF28BEFC4F474C1FD7F34
+:106E700046C47C47BD1479EE58D97484E8327D3518
+:106E800098551174477D753EFA749B0F4DFBA3DE38
+:106E900083FAB6F3E142AB3C1FF6D93A5E1C81FEA1
+:106EA000ADBD0AE903D69C28EDEFAFB0F27DD3016A
+:106EB0009B8FE4B6E3B089EE7BEBF5C658417FDCEF
+:106EC0004F44BE839B8C03C1F35D978DBDABE191B5
+:106ED000CDE527525FBF60F3119F62C19F26E0C7D7
+:106EE000B297C2F8627F789EE296FBD3AF179A9F63
+:106EF000A7A7715D23D6FBEF3AAEF0F9246B3133CF
+:106F0000EECFDF6D8E38679A23FCFC9A1F2CA2DE31
+:106F10004CCB98D8F5D0DF128271BFB0EB21F2EBE9
+:106F20009E7BF4F84C94DB15BF33322BF0B96D9790
+:106F30008385F83D0A33AEABE58DC6A8E7228CAD5C
+:106F400027FC56FCD6417AA57C8F253803DA973F7B
+:106F5000F5EE70F44FB5ADE3FA25F0A8908F40EB55
+:106F6000703C2F2F57F979B11EDE8F85BC9C7D3A7E
+:106F7000BE04F5A352CFDF759637CC355922F6E51E
+:106F80009578E0C6EBD13DE4C0230AF9C1BBE3B775
+:106F900096D77B84EBBDF2265310DF8796D76FA37D
+:106FA000FD6C55FD4766B4E326FFF631B223AA9A7D
+:106FB0008CB29FB0DE18B2901FD3781C53BDBFAE09
+:106FC000B2B182E6636583F087E9FC452B7EBBF7AF
+:106FD000A9009066C513BF76A29E39D3B2D3497E6D
+:106FE000B87AEE6753ED6A743F5C4FFEB7864D5139
+:106FF000FD6F67F03F60FE6DB5CAFE3756DFA757DD
+:10700000E7E02B1EFBF4413C173ABBE7C30711EF47
+:10701000955F7FFCE04FD13ED96773E17A57F5E881
+:1070200051F2AB6BED9E12F3AAED915F3FFC00CCE9
+:10703000BFB6372C74FFAA6DEFFB03DC30CEB6DD94
+:107040005FA4A2FF72F5DEA9B46F59FDE4E4B4F3C6
+:10705000DD2341B90CF6E23C44CF87038D4686EF31
+:1070600020CF1DB3909D11F6A3365470BFB45BF8CA
+:107070004F77453F77D2FC7E958DD75C7D29AE7BDF
+:107080008D268F9BBE0B3F604F7ED357819F237A07
+:10709000C1B75DC22FAEE3DB39FC0FE0CF9FACB2CE
+:1070A000BFF9D3C6A5BF7A00CB1AFBC4F49B867A7E
+:1070B000412FED5C6B9BD5FB8E15E7C39EDF907F68
+:1070C0001AF90536376B7BECD301E86F386DEAB8F7
+:1070D00091EE5FECB5D03DA1F2BDAFD3FC687BF281
+:1070E000089D173171AED4C6C27FFC1C40EC65AA66
+:1070F0007638B8BF55D01DFDB16E277D177E572E4F
+:10710000B79A3F36961FB68F4DDC0317E76C153BD9
+:10711000DE32339D5F5B198B7C3A2E9D0B6AE3D682
+:10712000C373211D2E893C4F88E5E7167A34CC279E
+:107130007E8ED0B64D9C2F84CF0D18EB9787F7DF4E
+:10714000F979775550799D45998FDA7982D3A69B45
+:107150008FC1DE9D23F48CEF77A38762E3FB568D0E
+:107160002E67BF8AAE8F87D814F1FEC0976B8B58FD
+:10717000771688F5A412E8C5DF93717CCF8AFDDD10
+:10718000D9478D41DC076F6838407A553FAF2B599E
+:10719000F4F821E36D5C9F5436ED1F8EFAE7ECB3F3
+:1071A0004F93DC55EE3A6E0E009C83F54F985B874B
+:1071B00076C939EAEB6084BE3EFBF8FEE1FC9C83B5
+:1071C000EF23F5F0AF10F0AB9A65F855BB3E92E0B7
+:1071D000AF0834985DF69EFB39A37AE7E278CFB426
+:1071E00098282ECA99066361B47825433190544A91
+:1071F000179D3638F8FB38639299ECC8D58EB1C725
+:1072000012923135BB711FBD7E2DBF0FB9FE679E37
+:1072100074E4CBFAC439740E54ABA3A32BD95580B4
+:10722000FB6BD794A2D128567A3D90E8354878AFC9
+:107230007614A6E17BEE5B853DC2540FBDDF333A89
+:10724000A715E2388C2E83CB16751DE5F04CF6227F
+:107250008A176172C9EFE9BEF7F80FEE7E72FC87FC
+:1072600040BF7F34FE03A33818FFEFE33F04B09F15
+:107270007F81F80F21F2DB68F11F92BFE7F80F6BF7
+:10728000991CFF41F0331CFF41F0F37FE33FFCFF0B
+:1072900015FFC118F7F729189F418BFF9012679EC1
+:1072A0001A19FFE1C2B884A991F11FC6C5A54F8D77
+:1072B0008CFFF083B8ACA991F11FE6C75D3435327D
+:1072C000FE4355DCA8A991F11FD6C64DA4BC16FFFC
+:1072D000E1EEB8A953E5F80F33A74E817C5B9CEF34
+:1072E000EFB85EC58AFFF01E4E96313DC77F00386D
+:1072F000E6B831B1E33FE8E1C48AFF007012084EFE
+:107300008CF80FDDF08911FF01E0A4139C18F11F28
+:10731000BAE11323FE03C0C9223831E23FE8E1C4D9
+:107320008AFF00702E8A4B891DFF410F2756FC07EC
+:1073300080338AF08911FFA11B3E31E23F009C8916
+:10734000042746FC876EF8C488FF0070A6D2B86296
+:10735000C47FD0C38915FF01E0CC247C62C47FD0F8
+:10736000C38915FF01E0CC257C62C47FE8864F8C81
+:10737000F80F00C747F8C488FFD00D9F18F11F0011
+:10738000CE72821323FE831E4EACF80F006715C128
+:107390008911FF410F2756FC0780F353821323FE08
+:1073A00043377C62C47F0038B7129C18F11FBAE1E2
+:1073B0001323FE03C0B983E0C488FFA087132BFE0C
+:1073C00003C0B997E0C488FFA087132BFE03C0F960
+:1073D00015C18911FFA11B3E31E23F009C7A92C387
+:1073E00018F11FBAE1F35DE33FD84203951C8AFF11
+:1073F000407122C3F11F92BF75FC8766C4F77FE31B
+:107400003FFCCF8CFF70B3DDF7751CF941BF5BFC0F
+:10741000075BFCB78BFF70B3BD283E1EF797DF32CA
+:10742000FE436AFCB78BFF00FDA4C78F89DD4FAC1C
+:10743000F80F39BA7E7A8AFF00FD0C3AEF7862C401
+:107440007FF0E8E8F67DC57FF822EEFCF11FFEE54F
+:10745000E22CC03605CF7F8A4914D9BF4CDC856B3E
+:10746000E3FFC97117C858F8578ABBA0BDDF6F305A
+:10747000E17AF5A6E0FB6B422EDE12F1178EC58C89
+:10748000BF10BC8AFCA2CBE5F80BD3051FE7F9645B
+:107490007998CEF879C3F429593C5E66992EFE425C
+:1074A000AE7C7E3DC377640A80635779E4711C111A
+:1074B000F230B3E4A3E7903D578F8D1E7F6196E0D5
+:1074C00047B18E2ED305DF8A457A3D3E4901799E2C
+:1074D00051764445BACE74B7AAE4D7FE81C63FB709
+:1074E000C4BFD902AE1EDF59827FB3AEE4FCD3E342
+:1074F000FD2AF2CF0969D928E29F1E6F3D9E7AFED0
+:10750000B3487E47C4CD286072DC85C95639EEC2C7
+:1075100054971C77E18A7439EEC2956E39EEC20F2A
+:1075200072E5B80B5779E4B80B578F95E32E147BAF
+:10753000D7EAE23E6CD2C57DB84B17F7E17E5DDC41
+:10754000876DBAB80F8FE8E23EECD6C57D785A1742
+:10755000F761BF945F5C7358AABFB4F688945F5616
+:10756000F786547F79F0B854BEA2FE03A9BCA2E10D
+:1075700023295FD5F48554BFB7711F5E15EF815F76
+:1075800013EF818F89F7C06FC688FBF0D79F7F719B
+:107590005BE47BFC2F7FFECD6DF81EDF20DEC1C6D5
+:1075A0008AFB102E8F11F7A1ABFDB78FFB9092FCD9
+:1075B000CF7F879F63E7E79B13E227E5D853BEFBA6
+:1075C0003BFC6B8BE4F7CC734BE4F7CC3976AECF56
+:1075D000E7F9E477CDD797C9EF9ACB6CBE6CC4437B
+:1075E0001FF76142BC37C78EFA52BCCF0FE1FB5484
+:1075F000581B9FC5F7A9903E87711F203D88711FBA
+:10760000203D84711F20FD3DC67D80F4258CFB004C
+:10761000E9CB18F741C5B811011137A246C48DA8AE
+:10762000157123EA44DC88A0881B512FE246348878
+:10763000B8114D226E4488E09CF01FA2F4A4BF85CF
+:10764000D253FE63949EF6B7527AC67F9AD2B3FEA7
+:107650000E4ADBFC9F53DADBB8119A5CFE19ED068B
+:1076600033F6CFE55893D319F6811B22E5B4C87ED3
+:10767000D10694D358F122E6224D5362C78B089766
+:10768000C78817D1D53E76BC88B4D1DF5FBC887F70
+:107690008BE7F2FA8FC68B985F2DC73358B0E6FCA4
+:1076A000F122CA6C45AB512E3579FCB7787E5ED598
+:1076B00053BC886D7645ACD74017B4BB802EB45E02
+:1076C000F7F0DEFE39C7C3B9B89FE8CCBDE8BC719E
+:1076D0000EF472119BDE3CAEC175DF739C889EE890
+:1076E000AAD57FB39CC72FF8B7F8F3C72FE81627A2
+:1076F000A2A7F802833E233DD9DB38113DAD0B3DF7
+:10770000D173D6F71C27A227BDDA933EFDE3744E52
+:10771000E709F1E78FC7118E0B676D39488D5D5E04
+:107720009ADAAA78075E30DB45FE93F65DE2DE98D2
+:1077300097B95DA9FC9D3ADA9BED7B1286337ABF3F
+:10774000EE625EE04FBCF8AEECDABF1FCFD36F75D0
+:10775000326F6212C583771B73701F36D28AFE9414
+:107760008AC68F5EFE1DC0B5351BE93E593BE0D091
+:1077700042769F3711F916CF6EA77D3A9E717DD361
+:1077800027F23DB3EEF71BB04AC4F9CD54A39DF6E2
+:107790004D9D5BF93D4F23BBE8BE89C9749F9A0597
+:1077A000DDC43FB25357083C3B31C5FA3E2BD98F5D
+:1077B000CB0E3F911F62FCBC32D26FD0A750F6D3E4
+:1077C000D4D99CC3F15D250B785BD0FE5E22E0A589
+:1077D00014C9FE9B0F17151EC273FA25BE52BA8735
+:1077E000905622FB739878378EDBB1F07D39C0A7B5
+:1077F000B449610F28DDDF919735DFB501F739CB4B
+:10780000837AFB9BE5A29C95B3380FEE7B57D4CBD4
+:10781000E50E87B8CF6167F65ED1AD75F07D134791
+:107820009F976E9E10D6DFE5A0FBB0CB0E2F3623C0
+:10783000B32CE932DD6C6E996EF1B9327DF4F473DC
+:107840007864FAE8E9973056F67F69F4D3EE1BAA1C
+:107850004CDC170DF27BA4DDDEE1376D233CF5F443
+:10786000D3D36B9443DC93E8A257913595543EE112
+:1078700099A18648BEF5F321D31E52F0BFFB27071E
+:10788000D7522B8F4345BD95CE413365096F178F76
+:10789000F301E3CA320FCD07DCD1A37F379EFD5938
+:1078A000C8FDBBEC1B486F2A7EEEF82228DD8AF269
+:1078B0003682FFFE02F9ABB4DF4D601E17EEA31A4D
+:1078C000FC56F71215CF05997BC9403C0F74517ACD
+:1078D000A778F7DB3E94D1BEBF21F4492A9EA3DDF1
+:1078E00099D73113FD0F554B5911AE5F3F72F277A7
+:1078F000179B443AC2C9FD339B8B0CCC3B1A7F8744
+:10790000C71854D0EFEAF21EBE1CEDD166939BDE81
+:1079100011BB3A5EBE9ECA47D1FBE80C43ED48C49A
+:1079200007EAD3FBDAF6E6779D8B23F4705BD3DDB1
+:1079300043F07EF1FD86E8EF7A4B1DDAFB367EBF21
+:107940006344579C8152C7188A47706736F453596D
+:10795000DC497CD4E47282A0FF73A5D309BF279BC6
+:107960001537FAEBA6196FF8C130C06FDC5195EBF3
+:107970002F71AF7BB4A8FF34F3A423BEE32E650AB6
+:10798000CE9F716F304F00495C5D4AF7E97EE79CFE
+:107990007608F935A519E409F5C859BB07AFCA8FB0
+:1079A0006991EFCB254EF11DC0FB85971C63A4CFD9
+:1079B0002E39A6EAEFC71871BF3FAE55FE3E41B75C
+:1079C000FF5CA7C99D93A5A2DC6DF9CA4878B5777D
+:1079D00030CF3A80DBBEA42F9DDBB67FC2C84E6C91
+:1079E000FFCA5818ED7EC9DD0EEEF7BADFCC487F2E
+:1079F000DF5F6AA7770ECF96965F80F6C5673FF187
+:107A00005D10CD4F1961A725F0F7E7DE043616E5C6
+:107A1000F05685D3BB36A328CABAA5C99D26879A36
+:107A2000FC6594C6F9A2DDD74C7672FB685269AE4C
+:107A30006246F9D9A730A46BDB3AC0EB3CEB768009
+:107A4000ADCB447CAA9A3EA67B58D66625EAEFF2D7
+:107A50003CE170F2FB80EB026BF1FEC5CD3089504A
+:107A60004F65986BB3A2C10FB02D64973EE070F3E1
+:107A7000770356114748ADCDC0FB086D4D93AFDC81
+:107A800000783E00F301F97BBFC94378072A18A3A9
+:107A9000FBA4C25FD76F26DBB639C2FEDDEB283808
+:107AA0008C727BD8C1EDC63E3E8F82787BFEFE573E
+:107AB00027C26FFFDC42FCEB2BEC4DADDD4907A785
+:107AC0004F89D37B00DBB3B264523E1E9FD3BDA46B
+:107AD0000FFACD81DE51EC2B6D5D4FF2313A9F48AC
+:107AE000B21B82A49CBC5EB74BBAEF1DA079A3CD9C
+:107AF00003165218BED7D7F49BD2AC841C20F7A330
+:107B0000ADF610DE3F4B2A837127633C0F2B87D7DE
+:107B1000A29E95FD5A208FF968DC337AEF8F8E5440
+:107B200084AFE93D4D5FDE9AC8F5D1AD77A9140F5A
+:107B300074ABDA6A437F6A96D73D0943D324A96EB2
+:107B4000BA97D2BF8CCFC3F89C5F2686ED0098E42D
+:107B500023BF362E88F69E2903E52905E9E5FBD0EB
+:107B600001E9F0431DCFA2B9E0B1B13EFCFE94D0D3
+:107B700013C2AE9926D6BB71EF19F83BCAD0E52CDB
+:107B8000F27D915E4F80DCFF097FBFE7FEF7548AEC
+:107B9000131AD60FA5D3687D62C6A10750CE26BCA6
+:107BA000C8F87194D00F2EF887F4B9E425DF7A4431
+:107BB000E3BBEA053DBF59C81ACEE34FB38D3A0483
+:107BC000F32D729D758AF55EE8919B8A07AEC7F921
+:107BD000A5C9D105B7788CBE083AEADB87FD948A3F
+:107BE00035FCDD9D837AE42523DE0F6B2F007E03B9
+:107BF0005D9EC4F902F44EFC247825F27D4BF3150A
+:107C00003694EF5B43935C33A04DA2B5889897C838
+:107C1000BCE4CFC903EA609C88F52414B05F578B9D
+:107C2000B29C29788FAB50F2F768BF8B070325BE53
+:107C300084F900721C798F55934FBD3C6AF2BB1ECC
+:107C40003758787E871E73488D4A0331C8C2B6BA4A
+:107C500050CF6AF6E5FAB03D9748FB8CD5C22E5A54
+:107C60006F9F662535B03F99D6F3D5B83EC1F8571A
+:107C7000A7309A07DA38F4F258F5B9810523F607E8
+:107C8000556A07DDE3ABFADCCC827D70DCBE493897
+:107C90006E8D2E23055DF474C8768AFDA6A0476C10
+:107CA0003CF35D787F36D1EA651B09CF4974CFB9C3
+:107CB000219467C5F5F6361D9EBDC06F4E34FC5449
+:107CC0007B0CFC44FCB609CCF7BB5690D7FC9BEA76
+:107CD00032F87AC15E4D8FE09F7EDE8C6DAA3E60E9
+:107CE0008E982F9A5F573F4F4634B36B90EEE34226
+:107CF0002AC3F3D79EE6CB2762BC55F19C5EED7399
+:107D00003A06A37CEE507DD54EB22F5A0D18F7B728
+:107D1000FD6946F3D9B3FFA493E21BB5F4EE7EBA36
+:107D2000664769F693BE9E663F697A57BB1FBEDD04
+:107D3000E9F363FF4A13C8278C7FBD8BEF8BF63ABC
+:107D40007CEBF07B3C8C018F92586E288BBF7F952B
+:107D5000E53F96BCC7EBE4B901E844BF9305FA7F61
+:107D600090D21D0FADFF29CE447EDE02B319F5502F
+:107D7000BF7CC63BAB64747FB2DF70E6C3F5A95F1E
+:107D80001EBFF71714EBF636A16FB574AFA3E87EEC
+:107D9000C4DFA4B28025EFBBE38DA8E27DECED4EFD
+:107DA000EF7D287FD6422F8D23D3C53C687F66AAFE
+:107DB0000D0ABE9B4C5AE956F83D6CD6F58E09E08B
+:107DC00065CE7017A09C64E23E1AEB37478FA3F58F
+:107DD00084D324D9991E168E53F504F60B76E6410A
+:107DE00033E0DD678616F74A3BB7F12848A736C768
+:107DF0001C42BAED5385DBE3899C5EFAFD00121E3E
+:107E0000F15345FE3633536D49ACEB77380D56B21E
+:107E1000E3E399A701F5D2CBCE6C712EEAA9C1FCA0
+:107E2000BFAB1DD6C4A15D727CE7C4591E15AA382C
+:107E30002FED1C8E7B2690E7C3886FDBC4CEC1B7C5
+:107E400012313A0670B9F11AA5B8381AFD9B4C12D6
+:107E5000FD6DB8CF8ED4830E33ED23DB94380FCE77
+:107E6000B3B6E50AC753B18AB841AABCFF17FA48AE
+:107E7000D3AF9DCE2CC23F9E05681FC0AC1E2BDD2C
+:107E80006317F8635C45F2EBEC8D0F6EC7F3285D6A
+:107E90001C457D9CC5C98BED74EF62CB5E1BED4B21
+:107EA0003B8BF8F97C67B385F46FAC799A86CAE0AE
+:107EB0003CF102816E1D48B734537522EABDB4F916
+:107EC0007CFEEBE9D18E03C5FDCE1F4CC168EFD51A
+:107ED000B5343DBD6F31DA65E919E9946ADFEBEC41
+:107EE0006AD47BD8C604458AD337047A14FB1C6352
+:107EF000027C3FE7FBE36B5ED675AFBD2E8ED3AF42
+:107F0000D3373EE161942B1038FA3D01ED5C53EC20
+:107F1000E7B5F8495A3F5BFCD6620CF959B768BA25
+:107F20000DD78114E6BD721E4ECA2D26B693DAE532
+:107F30004AF75DEFF58F2CC6F7C99909FC1EED27AE
+:107F40005BA6D27BE654B6CE3618E8505A64F0A051
+:107F50003FE0DCA2379D06909F45992DF928A7099F
+:107F6000265F66C218725DD17E6359893918027A1C
+:107F700025D78142203A06AE243A2E3444F50F67C5
+:107F800027F07DE75B623D494F1F50BC645464BEDF
+:107F90001FD1559323983F194B4677C5C3047E5E86
+:107FA0009410651EB49B5813BE97D0F451B2103391
+:107FB0004D1F6A729C8CF303EDB822D04FD2791F0B
+:107FC000544DEDFA3D43A5F9852FD08E755E3A8963
+:107FD000F40DCCDB1A92F35CAE3F6DA8CF22FC56B9
+:107FE000ED7B5FEF8FEF98DEFED9C70E7CD7F217DF
+:107FF000B5C381FAEBF42D7F72601CB0B76FE1FB63
+:10800000E41B75F6FF55423E8209455390AE0BFCCA
+:108010007FCF8FB4D7D81AEE7F5E1E94DFAFE2FD1C
+:10802000EF483F604583FE3E4080C72913BFCFA97C
+:10803000E7C33AC187E5BBB69933DDD8BF6F0EF60B
+:108040007F5AEC6F4E373AE83D8586CFA25D23CD4F
+:1080500068F3FFA5D922DEE9B598B85EF6CEC0F781
+:10806000393E41373D9E07F7C513BCA5F7F0F7AB86
+:108070000BA1AF35A0177DCD3C8E927E1C4BDF76D9
+:108080004F433FFAD24D0AEDE3B0FE2DB04EF8D685
+:108090006CA4773CFA712E0CC8FE1C7DBC466D3F6B
+:1080A000B04CF07F09FE1A6F4E94388ECDFC3DDD4A
+:1080B000329D7DD17928271EC7BF2641D8D9F9EC3A
+:1080C000128CDBB9E7507642B478185A7A569CF78E
+:1080D000E3BD7E4C4FFB19A55312DC3C5E57F39178
+:1080E0009B51AE2A9B76537CC47DC1F7FA8C872ABC
+:1080F00005CD5F1851A80A843D365FD8637B189779
+:108100001BB0A337A3FC5FFEB9CE8E16E3BC419330
+:10811000FB4349243737E0B886E377F59368E3BA41
+:108120003B417EFFD5DB7169E3D1C6A7955788F740
+:10813000E7FA769A9C4F1172B76447F186BE408A7F
+:10814000F57BDF1F20E2C8519C2D4D8EF472B24C9E
+:10815000F02D2C0FCD77D0B834BE81BCA78B7749DA
+:10816000E9E8CFE8492EF4FC6F33B50EC0F9AAE771
+:108170007F5B8C739FED09FC5C6389DB3B0DFD2B02
+:10818000601E6E7045D80FA7D5DA833FC579B483DA
+:10819000CB71E4BA48C6D28B265A675739DC698955
+:1081A00076C1B771F87ED112C07A5A3FA7FC35B3B9
+:1081B00006D27963EDAC8103E9DD06A55A79E9FDC4
+:1081C0001F3BD13E6DCF65E45F6873C8F81EC1C523
+:1081D000660CA69CFE2BD596AFDF421DB4A385E2AC
+:1081E000B79EFA4AF827BEB214461BE7D9046E07B9
+:1081F0006AF74F6E14F3E8C666FEDE6ED1D66233C0
+:10820000F901D6C8F7355E525CD332A1A9AF61A49B
+:1082100019F9ACE7C752CF15F40EBC1B5FD8EDC4FB
+:10822000D7A5FA776DE21ED302211F335D6E61A7D9
+:10823000F9E81DF1923A23D9F7CBDCD5B4BF59A1A7
+:10824000467F8F35C66538EF78F4E358D8A890DEBE
+:10825000D3E3BF6CC7DA0D7D198E9F8FAFFB384219
+:10826000FD48CF8871B2D6CBF9BB4CB16EFF174732
+:1082700094BC5700800000001F8B08000000000025
+:10828000000BB57C0D7854D5B5E83E73CEFC243395
+:108290004926FF21413C21111212E2908400017114
+:1082A000F24BC408030182607540518490207A5BD0
+:1082B000EFABB79990682DFA7AA358CB6DEDFD0618
+:1082C0002BAD0A4880A08126E9041403040D820A1C
+:1082D00096D68014B1053280B5587D8FB7D6DAFBBB
+:1082E00064664E92426F5F87D69D7DCE3EFBACBDED
+:1082F000FED7DA6B9F65ECD94B720E630FB7CB8C50
+:10830000E53356FBACEC65A98C2D63CAE9BE0C467F
+:10831000BF6BA9F85F67E59204C6EEC53F5568DB01
+:1083200057553278AE5CAE9985CFF56F90995982EA
+:10833000EB1EEF53C971D036498E4618C71E379EC3
+:10834000EEB33066817FD746D33C8C25E0FCFCD76A
+:1083500023B1A75260FEB38AFFBD0878EE2CC0E1BE
+:1083600081799678F873F47EF8FF32C78C2F2478E1
+:10837000DFFDEDF229730E5E5D6D32C0F8A52F4969
+:108380006C1D8CBFFF69DD78B12EFD3A1EDAF0A3BB
+:10839000B9E91981710F7B9F0BE9C3DA5456C0D834
+:1083A0007D023EF6EA7F05EE73F84DAE08C632ED6B
+:1083B000117167B3A05BC0265D4B63ACCE1A99C345
+:1083C000A2A03533C2233B64F46E02B8D644C08207
+:1083D00001CE355BA3BD1EC4E3EA68C646C0B8F64D
+:1083E0008D26B70DE6C4DFED8C9DAB6F9E9B9E0E78
+:1083F000EBAF7F7A6EBAC2D82CBB9DB189408FB6E5
+:10840000E7685CB7E29A6487FE2A4BDF8FEF5683FA
+:10841000F03899D363995C696286C07CFA7659B367
+:10842000F1CBBEA0751621FC56F86312C02FFF3D9C
+:10843000F8D5C4685B006EFDBC7FAADF1002F74A66
+:1084400085395B6C81F568E326DA0DB41EFDF37A9D
+:108450007A30E6A5717ABAAC443A04D117E15400F7
+:10846000AF3D1D56EF5A89F888E0F6748411DC1789
+:1084700093D6CD3D93C7D8617C00E0AE1DF132F5B7
+:108480005F515C6E7B3C5EF48F728DC76762199B97
+:10849000323CDE6046C6607C2ECE0FE3768539F333
+:1084A000988CD75DB1C807D31BFAAA2C40AA3AFB17
+:1084B000A40A05DE33FDB9BEAA30E83F629FCCFBBB
+:1084C0009BFA8E5A1C8C35B02915A5F0FC63700FF1
+:1084D000E7BB5E9B6F762D66C0573580534B0CB45F
+:1084E000C7C6BC8DF256D35B59214542CB984FCAC3
+:1084F000057E7046FAAC39D4678530AE33CAFD1FAD
+:10850000B8BE55579B2EC938EE98C2E5A53B8EF0F4
+:10851000A000EC61F05C53B853B503BE9A622C8E98
+:10852000C654BAEE098BC1BE535583AE6BF4C0E797
+:10853000108E2603734643DB75604C545FF6F0786B
+:10854000EBAA57AB14A0FFBEFA0C6AF5F78B4CF6FA
+:1085500074073C5F6460EE16DBE0FBAF22BF109D4A
+:10856000D414A4736DB789E41C7F12F0FD2AA1878F
+:108570006A81405100CFAA63CC171E89E3CABF505D
+:10858000B06D95D8E910BE6281BE3C3CDC37DAD6CE
+:10859000E27C4A309F703C152BA9554AD07B4B6D2D
+:1085A00099217D39D19081EB6172B86313E0574E08
+:1085B00031ACDE01EB976F8616F0A1D81DF2126880
+:1085C0009B4BA6CB4BA16D34B2852DD81AD8F26047
+:1085D0003C750879D2DA4B76D76F90EE17DEEF2D27
+:1085E000B0929E1A6927F916EB6D941C3ED4439EF7
+:1085F0002EE6D804D79A6417E37CDCC2908F7F2FD5
+:10860000E671980D3B55E0D7F7EC0F12FF3AA20C3C
+:108610008FA642FFA3E615150AF0AF23C5702515F6
+:1086200078F478F34ADECF325C190DFD4F9A6B78FF
+:108630007F2A4C99CCD8C9E655159E6C9C97EB3196
+:10864000B6C59985EF510C12C9A9B2D7E46D843F24
+:108650009B22393F3519812F6370BC4AE39F6A28FA
+:10866000DE6C05FE578A9DEA6A1BC735F2C3FFB46C
+:10867000D5F0285B0DAB118FD822BECF88756B74F7
+:1086800060ADCEAC39A8175A9C59732310AFEECF0A
+:1086900011AF793DBDD3510FB77EF049813B9BD3DC
+:1086A0000BE7C9EB612C12D673E1AD9B36CA528041
+:1086B0003E97EC45E7515F4BA0A61F877549AA9DE1
+:1086C000DD0372D7E864AA09D695C85EB2A3FD306F
+:1086D000207D4005B532AE5F3AA35C5FE2736CA4C7
+:1086E0008FEC4CB5DDF515BE5FD3CFAC3766483D9A
+:1086F000ACD757A69CC765067C1093D2767C29EA36
+:10870000F3DF9A1DB7A8088F933D0E706C33308548
+:10871000C5107B642870DFCAC21DEB50DE1D2CC95A
+:1087200003F2856823E0E01707F6D02864485B076A
+:108730003C5FCAA09D8470DD4AEB92919F263097E2
+:108740008C7AAB8079ADD8F677BC9584F87A3E8C7C
+:10875000DDE782D6F22A737A83F4467EB444F89F2A
+:108760001563A436DCD83217F934FC12B3A31FD03A
+:10877000FF0B9382F38360DC89D71DFB0D0CE1FCBA
+:10878000B5D16B8F82BE3F53515F6681F9FA059D6B
+:10879000B5799F37A999D1D0AF8A91082FBF2EE222
+:1087A000F6D8FF85C9FB722AE2C7B2DA1B2457E369
+:1087B000A3F9B8BAB8E2B1D1F07C4B4738C3F74F50
+:1087C000EA0C3720FE376FC90D433ED886B881F5D5
+:1087D000C798ED8FE07C315700DE54BAEE24BC2AF6
+:1087E000EA8428C06BE14C9BBA0EF0FEEBB0969980
+:1087F000C8F7FEAD06F632BC629BC93107FBDB2E23
+:10880000AB76D4B3BF4E6D09A7F56C35D07AB6857B
+:10881000FBC7AD01B8D7652815089F62650AEA5FF6
+:10882000C550AC3E02D7A74573FDA8E9E39A689509
+:10883000FACF4BF0FE5C1C5744725326DB48DEFA3D
+:10884000FDCC6B86F7C4CFEB95911EE173809590BC
+:10885000DF159FCC703E17121A5A9BD1AB929E75B2
+:10886000DA9600DDA70B3D3BFD644D258BC48EE3FE
+:10887000D854986F9FCDC8705DB7B13ED902FDDB6B
+:10888000AE32870FF9E7AA427E981DFE05FB7B6595
+:10889000629E5F494C898271455FAA0AF257110BAB
+:1088A000F5DBCA36947F81F6ADC4A2BB8EFE5C2494
+:1088B000B64AE03ACCB3285AF861A3D8A86BA4CF43
+:1088C00060D6046147555C7FF67FE1BAFA2B4C0E07
+:1088D0005CFF769BF3E3A9A8077B8D6C131B5E8E70
+:1088E0007E550F1A7D0C08C7D570E68D253EB42144
+:1088F000FDC76D68F684C17AC7A5F3F991DF506FA3
+:108900008CFD455C2CEAED8868AE4FB456E32FE44D
+:10891000237B14E723FBAD01F9FB5E742A8DD3E4BE
+:1089200009F90BE7D963F42E760D6117812FBF8704
+:108930007CB9DDC62A90CF9F19615988F2A4BD6722
+:10894000B7E07B7DFB54C39A2E23AEFB2FA0FF0123
+:10895000EED2E4ABA660FBDD15C7E12D93BF25BFCA
+:10896000FA62BB44FE7C423BD7D7C17C316268BE11
+:108970007801F17A3DBED0C7011A5FECB81E5F7472
+:10898000FF637CF18B68E1DF0ECB17DF46E2FA1F55
+:10899000EB2849647FC78F69137C30DCFD2956AE14
+:1089A000D7F4D7DB053E779B9AEFCC41B9BFCBE03C
+:1089B00040B906AAA7CC05FBB23B9C3FC794D5693A
+:1089C000D8DFAE703DB2BDDD4C7A64BBCDED267B09
+:1089D0009D6461E82730C5DDF77DD47FC916755DDC
+:1089E00010DF3E2EF4408BD137E573F47F0F70FA21
+:1089F0004EBE2B5736C1B8110F70B9CE3F67DA287B
+:108A0000C33CD53145BE6818DF17CDED62DD1918BE
+:108A1000057C597BC644FAEDADCE23E54E1BF937F4
+:108A20004EE4AF497B8E941767E378CE47DDA2D53D
+:108A3000FA53704D3164768E25017E5DC24E4C61D5
+:108A40005C0FB9903F72027DE634523CA6F141358D
+:108A500063596827E6F639CA908DAA2A42E95BED88
+:108A60009B4971DFFCE3CEB20858D77C97EEBEA0DD
+:108A70007FB58EFEE007FF01E564D5E6DE4E1BF212
+:108A8000ADCAED698B697516F77B56A7A1FFAFC913
+:108A900011FD004F2DBFCF78795D901D5763F83AD7
+:108AA0009F752874DFD367F2DE0297FE37E3CFB5F8
+:108AB000087BF3AD90E3DCC7DE588CFC9BB7DCB9D8
+:108AC0000FF1BF284EA6EBFFC97C9634A48F43213B
+:108AD000FFABC5A8967C2E05C631C5956183FB7B8F
+:108AE000E2C3F3F0FDD531EE6B4827A6F8BBF1B930
+:108AF0004985B9792857B6094DB1687F34B801AEB8
+:108B00008A4DB6001C1A5CE785FEA98E59720DF1DC
+:108B100080CFA15E693B75D682CF6B746FE9B8C414
+:108B2000E91D447FA47780FED27DD8D7F06011ADD7
+:108B3000D6FFE7E9EF1B89F41896FE18F747FE8F7A
+:108B4000E83F2A6608FA833F958ED7357FAAC50489
+:108B50007E7576A0AFD1BDDA5E44E31C265819FAC3
+:108B60004F9D1057A21CBAA3D1B9613BEDFC5DFD2E
+:108B7000BF3F3B0A5C4036292686CB93C93F06FDA2
+:108B80008D093E89FCBE0920F0F7909F3592F49D37
+:108B900043E0879D95A4B319DC05BF9682FE9F2F05
+:108BA00016E56082B9D287FCBEC33A3D05FDB75CCD
+:108BB000EBB434E4A737331E3B8426E7CDE4E53B32
+:108BC0005F51037E8EA6D7F68969B5F797C770FA0D
+:108BD000DF0E6A16FD3D740D83E1D0F4379205E196
+:108BE000907CD5866B56D2C7ED7D80AFDB110EC071
+:108BF0006B97C45A517F17199C7125E88FC5FB14D8
+:108C0000EED77D3D4A05BEA96C7FF738C25B69B1DE
+:108C1000F930DFC21CC6F37D41F912BD9FABF925C7
+:108C20009ADFAFF92D5A7C89FE0DDECFC7EB00BF6E
+:108C3000DD0C00A2FDF159BC0DF0FEE72FAB994E03
+:108C400021AF0AACA352AC6336EB25B8D8B7D7AE88
+:108C50004D03FACC12F8A8EC86B83007EF3376173C
+:108C6000E0E12E85C78B7739203E0CE2A3D99343F0
+:108C7000FBF89B9E1098E77AE3F5FA7FAAC817FCE9
+:108C8000B371A6D676831D3A0D0C70B09EC734859D
+:108C9000A3658F82F1803BD380FC5827EC1A84C9EE
+:108CA00043DB2321AF8586BE1C07E0B76BCF37645B
+:108CB000FFF6EEF9E623F4E7A67CA130333C5FF83B
+:108CC000457E14EA07E60A9DB7EE8FAD56C6AF1390
+:108CD000FFD48AB5EFAFC78C18C267A1F637E79FFC
+:108CE0005F8FF37D7946E1BC2DDE5F6E72A7DB6D91
+:108CF000D8F2787FBFC4FD1DEDFE7E23C00DD737AF
+:108D0000C568717FAF42F919F89983E87C17C6FBF3
+:108D1000B901BADE75AEE20B2567307DF0F7FF23AF
+:108D2000DED7E2FCB744FCC0F69D30A900D78CD654
+:108D30004714F4A36724C9CC19F4DE3B542B730603
+:108D4000C5FB6FC4E8FC907DAFAD9F0576A4AE4730
+:108D50007684A1BCB66F3F9483FD5ED9611D828F7E
+:108D6000F4F89DD1FE8882FC9F10CBE5E67AEF2FC8
+:108D70001C077C722BD29D911F77B1402239D2D330
+:108D800077EF9E9FC7F6650F8FEFE1E8AFA7C36F40
+:108D9000CE1747215EAE470F3DDF76C23A3DB03E6B
+:108DA0001FACD303FED6DE7A3BF5DFAE4FA2BEC6C4
+:108DB000AF751DBF8C457F4DE3D3B258CE37537688
+:108DC000AF8F65B600BD347C5D1474AB668EF9B3AD
+:108DD000E0CF5D922382F48487F5261504EC55F5E7
+:108DE000B172F233347B552D671B51FF6AF60AD3FB
+:108DF000C2A8CFF4F6697E7A9111D5AADE2EC102FF
+:108E00008DC8BFD50B43AF57F4342B11D433109D0D
+:108E10002449E043F8D51A3C1F3217C1ABA7A70677
+:108E20009F1E2ECD9FAE1674837596E1D2E7AA459C
+:108E3000B48E417655ACF746EDA9393634CEBA72C8
+:108E4000AEF4FD9C21F87538BED5DFD7F44039BEAD
+:108E500020975A0FFA1109B10944AFF2AB26E60484
+:108E60007BC14686B1CF82F3EFAF6492BD7B54D80D
+:108E7000DFE1F8A6F6AA81B96303FC636C7BCE8AB6
+:108E8000FCB35B69B662DEF136DB9CC628C053E9F1
+:108E90001F8BE7A15F57D76760989A2A6BBFB40F03
+:108EA000E3F6BAE3CC81FAB0B8BDAB04F9ED6DA539
+:108EB00057A638FA4BC69E0BF20FDBDA1BADE83F24
+:108EC000B5C5C914A7EF8FE6FCA8DD6F89E5FCD70F
+:108ED00076E6F22CE710F73F13F74B4FE51AD1482F
+:108EE000F6C74750BEA1FC6903ADBF54B25755A2A7
+:108EF000FF718791FC7A885BFEF07DCC37B599B71E
+:108F000063AABEACED878FD881102DFFE7B306337F
+:108F1000E60FE6488E97615CB9EAEFC27EF9BC5471
+:108F2000DA8799F47F65F25FFD774B94F72807762F
+:108F3000C17EF93DA95ECC3FEC9178DFD3C1F3FE51
+:108F4000CCEE899D05EFF9A03276C23AE229AD7FD9
+:108F50004BEE3A261838289E7A6C17DF3F7AAC4CD5
+:108F6000A2FDA3327B0AF304F155F9D340CF3CE0D4
+:108F7000C7F6C462E4DFAA0A997983F87ABECBCA3D
+:108F8000BC41E3F7877178FC92D98BF9124D5E678B
+:108F90000AFEAE5E181B327E0EE37EE242D66C44C1
+:108FA000F9AE13F0D415013CF0FC4C11A7DEED4EE8
+:108FB00009796F256641606856DC68B28FB3BFECF3
+:108FC00023B33A473E796C31BC876570F9D0E4AC85
+:108FD0004CAE69223E48921C181FCF97C0AB9451EB
+:108FE000DF85CAD1ECC9A1FD394EBD7E089577BD9C
+:108FF0001ED7E47C7E876CC4387A7E91E46043E8B7
+:1090000003BD3FADD703930C8E7730AE9E7BD54921
+:10901000FC35480F9CACF887F4C05B205B93415E45
+:109020007FA4E9839BD84DA80FCAE42DEB913FFAAA
+:10903000C1AE9987E00FCD2E68F17639C827F203CB
+:109040003BCFF725CAAE829CC606E2ED01FD007E4D
+:109050008363087FE657B16921FB4903FA22C86F91
+:109060003016FCF37E4319F88BA65C846F24F3E47E
+:10907000919EA2FC1EB43ECAB3255DA23C4A1DC40B
+:10908000F114CFB35F125CA8D7A49800DFEBFD0901
+:109090002D4F3B42E409F4FC3090B79B67F4229FCC
+:1090A00069FC506EE772513E4FA6FCB99E3FB4F783
+:1090B0005D8F2F7C12F085F477F842C8D38DF2C50E
+:1090C000218D1FD259FA8DF083C6071A5FE8EDC5CE
+:1090D000415DDE65387B71F23AF6E29D0C23E9656D
+:1090E000BD9DD0ECC28138AE7FC7C7F27D8A999909
+:1090F000F36DE8578C407D80FE9EB0370379A30D59
+:109100009C0FDEE95BAA486837500FA406E15DE4D6
+:109110004D35BEAB7D9A51FEB052E89F8B1D3C9FF2
+:1091200056572A7B2DF06749FB73EB79DF48F9B678
+:1091300022A54BB1C0BCB31D9203F3354E917F9B6A
+:1091400075D5E455293F3FF47E7A95E01B8C73700A
+:10915000FC6CA7E4851074901EAABACAEDBE5E1F0F
+:109160005589FDF22ADD7EB9294ED0F56676F3BF2A
+:10917000D2EEC7C72570B919868EDAF31A1D35FAF3
+:109180004DC0B1283FFBBE36A911DC3F46FACDB831
+:10919000AAD03CA3E242FD962FCFE7FE27C574621A
+:1091A0007C5DFB25937BFCF0F05FCF2FBD59F3C3B3
+:1091B000855FAEBD7726C8780A3A863AFBA1BDE73F
+:1091C000BAF6423CAFA7D3E4B8D07842A387A6470B
+:1091D00007E15BE8D9E1E8753D3DABE9B37FB59EBA
+:1091E000D5E6D7EC80F65EBDFE1D2E3ED3F4E953E6
+:1091F0001B0D9417B94DC4C1B7893CEB8342CE9780
+:109200000B7DDBFF178B01FDAC6D9DDC1F7198EDB5
+:1092100087D06F08E4F3385D9F8C601EDC2F674AAF
+:10922000AF85F62F8B81A4B87F99CCF72FB7283E56
+:1092300017E96987C21A405EFE2AF2164FEEF52C36
+:10924000463DFDE4E93106DA47577CBD18174FCAA1
+:1092500055683F28DAAC52BEF76287D98ECFF5EF5A
+:10926000FE5E9711E7F90B7360A8F6768779603F89
+:1092700006F54299DC23635EBEDF0FBE388C9FB6D5
+:10928000D05782F1CE6DACB711E3EA42A4E310F4FB
+:109290007B55675FF479FB920EEE279544F0BA9FF9
+:1092A000E980467CEFF43613F985D7CBDB177DC90F
+:1092B000C85F1A94AF6FE37A0606119FDC68DEBEC2
+:1092C000107D3DE0E39FE8F40E1B267FBFCDC4F781
+:1092D00073FC478C0CFD5E762E6EC8BCCBF5F2F8A5
+:1092E000BB3BC39D6A24EEBB71FF7C7767B253CD55
+:1092F000197E7C4E9FBF18F395DBB6CC55284E14D3
+:10930000F9CF41FB223AFCED90589315F369ED8EAD
+:10931000528C3F86DBE728F63B69DE1BC51B63CD1D
+:109320009CCEA27EE9762163DBCE863B91BFB79DC2
+:109330004D76223CBB057F6AFCBEFBCCE570DACFE4
+:10934000343955DC07F6475B1C2F13BF723E6F198B
+:1093500031C68BFBADDB853C6C0BF71FCC8A0BDE7B
+:10936000CFE0FB179DF59EAA33E9B4DF2D61BE5116
+:10937000DB27F680BC505D4E0C237E32B21686EFA2
+:109380006D74B29F633B7D9A1A85F8BE1CA7ED47AA
+:10939000AA519467F8F64A816BFC60BCEFA877513C
+:1093A0003D496BFDC22A05607CB3DE4D6D5BFD72ED
+:1093B0006AF7D4AFA6FB6B0F453E8E76BFCEB9A041
+:1093C0004A09D21B9FC5F3FC526ED6E912E473F62C
+:1093D0000D6318EF4C7FA24F463D71FB555847482F
+:1093E000DD887219F14CF9CBB4403F555A12867C96
+:1093F00079FB55E8078D97E2A3391D9A94A65B0A7D
+:10940000485A881FC2E29D17E3E0FA0FED2E7F5CF9
+:109410003CF241F5BE0B8CFA97F1FA0EE96EF902B7
+:109420008CCBF31551DE380FF3C6B934ED62C4DFCF
+:10943000C42E13ED7B6BF9DB5C31AFF3ABD03C7228
+:109440009EC8DBBEC9FA289F9C6F81C0CA8070711C
+:10945000FA39A5F94912E6FBE24D0EAC579898E6A9
+:10946000CAC37C6B573CA3FC695757C24815F0E050
+:1094700054785ED7A9E575D9DFCFEB767F1AE9215D
+:109480007D057E0AEAA7EEA3910E1FEDFF59C8FFE6
+:10949000DB810F627D4338AF1760F3E6511EFD7626
+:1094A0000B5F07D89FF878CAFBF9F61D86E77E7B2D
+:1094B00099F17DC4DE93B43F5D62C84CEC0338F78C
+:1094C0004963A3B07DF1D3C86C6A8F469E47FC7494
+:1094D0001AAC2ABEF7C37A56857567CEF76DB49F6E
+:1094E00031FD7D9B82EDE1FA3EAA477BBFFE1CB5B4
+:1094F00047EAFDD41EADBF4AED3B701DF9E7103CB5
+:109500008F6DEEE2087A6EC7A20813C2DB19C9B6E6
+:1095100068EFC17A335FB8AF1593F9EFC57FBECE60
+:109520007213D83BB37BBC3481B113F19FCF54A0ED
+:109530007F68C6A87FFF0BDCFFDD4F2EACB3005C5D
+:10954000F38EDA5A7BA0FFE94F2EAEB3A19E3D14F5
+:109550000ECA0EF546FF4190749687363D99710507
+:109560003B19FAB1A2EFE99F590A245F50D297C57F
+:1095700080B5A6FCC43FD302785C6075FF1BF64D36
+:109580009E976696DE847DE6C17A2EBF64A4F89E1F
+:109590008D94E2B07E6599DD7D2C3EC87E3BA53F73
+:1095A000D2FE51815362D1714457DACF62F653B182
+:1095B000C1F2B6CC5E760CE971473CDFBF9A384DFC
+:1095C0007206D749E8C74D3CA396229D0ACE95372F
+:1095D000613BBB229AFAAE85939A509E4B6DC33D78
+:1095E0005F42CF2F8837127F162B52487D887E5CD2
+:1095F0001E3013FAC7FE03E194179878CCDD887506
+:10960000A36549A9B9B2D0798CFAD11B711F6D62DB
+:10961000E587A5B1283F36C981E6A180F535C5C6E5
+:1096200061FD231644E1BA9E2BC1FA9D89AAE4404C
+:10963000B41539BB5AF1F9224784A308FDF1636AD6
+:10964000299A9CA3CA84C3F9306E46BAECB0C044D0
+:10965000477D774CBD00FDA28C28CAE31629ABAF2D
+:109660001CA67E84A341C5756CFC792DCD63267B39
+:10967000BE6356C97F20FF14BBA228E7576A3B355B
+:1096800037B82E0CD64D7017D9656F9884FCFD83C2
+:10969000523BF4778C9218CACF515FE69FE97E77F0
+:1096A000B81A0680EE30D94B71BE1D26C9BE96FA97
+:1096B000AE121CEF196354314F541EF745C8FC33EA
+:1096C0004AA5296710FEECA80978AD62E4A590FBD5
+:1096D0003D8BAC64272ADFCF267FA867510AD98B40
+:1096E000CAF7A71563DB63E07E7AE5FB951574DFA7
+:1096F000C0E3DFCAC5DF718A3EC5BB958B5751BF3A
+:109700004B4AFC777CDF95ECA85CCCA3CD4CFF7A70
+:10971000AE12ECFFADCE24F9CF1579BC2243E6FAA8
+:109720006900FFA307F83E4465B6145237372BFF94
+:1097300054483DA86BDA1721FDB9A59742EA43E7E3
+:10974000557E1DD25F304FAA0A1E5F7A209FEC6BB8
+:10975000BEA85FD2F24B458285DEA9CFA82A05B903
+:109760003C00ED03A01F8A7A45DE55E1717506FCC9
+:10977000433D586AD3E577994AFBD915DD7CDFBABA
+:109780003CCE783AD83E54C84F707F41B7FEDC03D8
+:1097900046B293B9D132E5AB34F82A46863EAFF9EA
+:1097A0005F1502CE1D0677530CE5C79CBDE87F68A8
+:1097B000F06BEFD7E0AE90EF29A5EDBFEBC0AF8720
+:1097C000170025FF4D0FC78178118780BF41FE59D3
+:1097D00037AF4B835FDC50765BF3CF2B414F4507B0
+:1097E000EB299B1487F576C3E9296DDEE1FC306D2A
+:1097F000DE6576173DEFDCFAD9D14239A89F7A2A87
+:109800003626B8FFDA67EB43EEC79FAA8A0EEE6FE3
+:10981000FAAC0AEF4F57D4461BF0E34126393CC857
+:109820009F3DAA82FBCF25C79C4DD8969D74639916
+:10983000299B71C6D384EDD4F3DE1E33ACEB8E0CC2
+:1098400059C5B85DF33FF4F09A13781C72F0AA6A18
+:10985000C5FDD31D1ED58AFEFB8E27542BFA1F3B58
+:109860009CAC02E331679A6135FAF3CE2C5E6778DF
+:1098700055E8E16FE2F9F35A7B5A717F837A11EB75
+:10988000C2D127A8FDDA4F75E007D1AFCA1EEC5749
+:109890001D54BC367CDFC127BCB6E07DC21BF5ABD6
+:1098A000FE8C363A1EF96C4E887C9658EEAE0A96BF
+:1098B000EF32FB9290FB9FC6A904FF8CA48743C69E
+:1098C000DDA13E12D2077F3103FD914613A33A5921
+:1098D0008F81D7C9EAF1F8A8C0A3C36647378619B4
+:1098E000E354AA6BD38F739470FCE9AFA727F0B849
+:1098F0006823C80CB6F72470F8F475B1FA3EC47C3E
+:109900000B713E983909F9DC61355C0157973913C1
+:1099100092EEA47AD93CC3A369D0AF4EC8E2FDA9A8
+:10992000869D581F7B774236EFDF6AC833821FF06F
+:109930002B36FE4EAC07AF0D13759D0F24D27E98CB
+:1099400016DF2886532F2EC638738F9161FEFE19BD
+:1099500013D8BDDCC0BEB9D5CCE352AB89D76D3FBF
+:10996000957AF429D41B6A987B7A02F951C52AE2C8
+:10997000EFBCDD42759D8FED2E4B44FADF93C0F3B3
+:109980005C593BA726A17EF917BC7F56C2C4E1DF14
+:109990008F75BE38CFF91D59E47F67DD0CE895025D
+:1099A000F887F098AE87419840E725983309F36C23
+:1099B0008DD1269AE79E04CE7F37DA0EAAFB8D3230
+:1099C000ACDE0EEDFD82FE0FE07B095FFE51737091
+:1099D00063CEEE1F35773CEF237D6539D78F7EACA4
+:1099E000FF3B11B4AFC246FA69FFE5E37BB21CE866
+:1099F0009F7E12CEF1B7D03BBAB14FC5FA0DEF4DF5
+:109A0000582F9191E8AE453C2C327B6F21FEB1ADD1
+:109A10008EC0F96FB41E78F07B218004FA544FE1B8
+:109A2000F4D1DE0B38B5A03DF8589C03D1E080F7A7
+:109A3000FF00F9408367000E5D5DB89667AEFBA33B
+:109A400081F20C7512E83DE8EF3CC91C1E98E7A2B4
+:109A5000E6AF8BBC266E45E17BA61C5E5A62833660
+:109A6000BF6D258F737B95903CD7A4E38A7EBF831F
+:109A7000ECD654ED795D9E71AA886BA7EAE2DA17FD
+:109A800013849D4966C9C1798035226EB8DC333AAA
+:109A90000AFD4CD45132E0D5A4CA6C724C40CE5B66
+:109AA00021EE674171BFC667E38FD9EF47B8C71F83
+:109AB00063F7915DD7E61DC82F70BC5C3ECEF132D6
+:109AC000A12FE3A7D3A06FEC3632AF1A584F21076E
+:109AD000955DC6FFE078BBC98B75CB05077E99E71E
+:109AE000834BE624035383F010A6863335482F5A60
+:109AF000336242FAB2866F61CFF3C4FC118EE490F8
+:109B000079F6C49477A37DCFB32D27FB1E357974E6
+:109B1000C83CAC4709B1F3B028DABF9C0840FD0C43
+:109B2000F05A704C09B1E793E23CB86236F9A4A24E
+:109B3000B3FFCD32CA41E199D0EB0786A3CB70F8D1
+:109B400063393F45FFEE1FC55FB433147FB115A1E4
+:109B5000F88B7785E22F7161289E46B843F192B267
+:109B60007C5CC8FD9B56E786F46F7EBC30647C2A23
+:109B700018A4E07EDAD33343C6DFD23C37A43F7665
+:109B8000C3A290F199DEA521F7B35E5D7143F41E87
+:109B9000DFB226649C9EDEB7B6FDAF9079357A7B46
+:109BA000E0DFBF82DEE6C4507AA70AFD1AEDE4F5D5
+:109BB00065FD46DBD312E8234C13A15E8B6E7FF765
+:109BC0006BCC43788A55AA9FF3CC64B40FFD82EC2A
+:109BD00092500FA5C0148634AA5FA7FABB1F1B0CB6
+:109BE00021FBE28989DCBE2726F27CCDCF4DFCDC4F
+:109BF000520AF88F64870C2C102F031E22315EA6A8
+:109C000078FAC7CF60BCDC14DD97A1427C6CC6FE3D
+:109C10004D017DB9C8AC36F6013E26C85C1F829E58
+:109C20004C4B84F93F919E30723FC263443F22C542
+:109C3000C23C91B9643F287F1CCDE224ACC78F0A97
+:109C4000E869F51A106BDF8A2C3A07F51E4282FE8E
+:109C5000AF2586ECE8DD9A7E5A9E49FAE9B22DD40A
+:109C60000FBBFC401A5D3F71AF99F6FB4F883A4439
+:109C70006DFDE784DEFA53BD85DAF3F5F6103DB6E7
+:109C80007CE3FA08F41F4F64707F51BB5E82789BBF
+:109C900088AD2CEC9AC58EF9AC7BC0384701BE5715
+:109CA00075F7452E62E43716E3BA6B375EB9F74DA8
+:109CB000E8D719FC09DC3E7878BDCCC78CFCCFEA2C
+:109CC0006F5888FF343791C7E973C5FC0BA0B10307
+:109CD0009E1600FEA3B17D775A39F2275CA7F3697F
+:109CE000B3BB19D59FCC71A7D23EE351E6F87017EC
+:109CF00080F89D4495E09CC75CB45FFFD1BDAB226A
+:109D000070DCC07CDA3CC028E86F7C1CED3126603A
+:109D1000DC7F1BAF6F80F759F0BAEB9E9427D10E12
+:109D200069EFFB88B92F7C88FBDDCC41F36AF33304
+:109D30001613A29F762C5FF9692CBC6FCD0103E549
+:109D400013D6749829EEEA5FF1D7AD2FC2FDFB520E
+:109D5000FA6E42BBFCC98A6FC6203FDCBD01F4101D
+:109D6000ACB130CAFD7062509C72E2812B11781F39
+:109D7000ECEBA617D1386E36537DEF272B368F09C3
+:109D8000F6471F4D2CAAC5E7D8E41B3B6F58F27A63
+:109D90006622D563097E7A58F0D39AD7C6921FB54A
+:109DA0002662809F787F13AFEFD0D6F1A1E0C71570
+:109DB000AF7F5D107CCE7407F0913A86EF6BA920DF
+:109DC000533B7B2EE7E0FD57147713C2D779F57428
+:109DD00024F677BEF737829FCDBB317851063D051B
+:109DE00081FD65EDDCE5C2F6D83CA43BC85933CE15
+:109DF000BFE837AF5DF81DE2A763F3A6EFE3981B5A
+:109E00003C7FC9847D71083C807DA1F8A09F85F3CB
+:109E1000731D428F2AB8839E86E7991C2AF1B3935B
+:109E20001DC27D97C62E03C3BA9548DCB409CAB3D8
+:109E300045CA06CD08392D49A09F855E7925F1E4F4
+:109E40009D4DE4E787FA3DF96FAF08F1775CF08F3D
+:109E5000FC9D97DC8D9807BAAEDFE3332C3145DDEE
+:109E6000B8FF0381B0532A105B38F06B4B14FB2210
+:109E7000420F77A21C61FD3FCE85F97A5F383F67BC
+:109E80000CA602F5F80F604DF8B02945B4D2C50C08
+:109E90000BE8C5BD897F78E669D0939674BE5EEC09
+:109EA00037E2DFDD9CDF06FCABB7C7919E62DFC205
+:109EB000DB100F225FA1A7533EC8078B0D9233F131
+:109EC000BC6FFFDF22314FBB35467D1FE9E03F20ED
+:109ED000D33E4D98D2678A1E222E7B13F59E89FBB6
+:109EE0004D546FDEC6F38116D5C9300E08B3DB279B
+:109EF000049FB36B17FA6ED5FE4F4699800E170C70
+:109F00003D91D9307FCDAE1D91E8C6DF6B747F8A5D
+:109F10007CB7F2C40705763ACFB671149D03F08D75
+:109F2000A6BA83F10AF328B983E1A8DB904BC6B83F
+:109F3000760325E3D9F8F6BC87501FD5F9F83A71B6
+:109F40006E2CFCCB6C63D4BFD8D61883F3D5FDB68A
+:109F50002319E567733C8F135FBF3A8E3FAF30051F
+:109F6000C77F99182DF8D96BC03863B3884F2E5E20
+:109F700035D038EDFDE3DB8A643BF043B6AF792F93
+:109F8000C543ED6615E91AF60AE378680F2339AF81
+:109F9000EB9CC1309FDF1FCD1C12DCDF1AEEFF03EC
+:109FA0009D33EB30AB981F0DB337B318987FABD808
+:109FB0000FCD048EC2F34ADA75ED7D61ED3FC558D1
+:109FC00002F981F2B4614A33BBCD168CE708C27343
+:109FD0003CF2533CBEC767C0FC88FF16C65E26B87D
+:109FE0000270327AAF066726F9735B4DFEB3787E56
+:109FF00005E0B223FD33198793B58F5531BE0FB3FA
+:10A000003B691D6176D5E19106C35597C3BC68BF16
+:10A010007FBC960DC82BCA6F5D78A06F0119D83A26
+:10A020009A09F9B63F5B3A2DB80F8A6472E0F9716C
+:10A030001B629E6D1A49718347C63816DA88185C10
+:10A04000A7CACF3B636A2897E301F7C5AD167E7FA9
+:10A05000603CF0B70DFB363ECE1165B7CE94484E4E
+:10A0600028AF572BE4FD31C977F67690D3BFF8F6C9
+:10A07000E6A8004BCDBB7B884F571ADA5F1C0FF761
+:10A08000375ADCF94980CFB74E1AE81CE99F5E0BBE
+:10A09000F35662FCB87B63827308F9D0CFFFC3E349
+:10A0A0006B9F4F41FAEF9654CC9BF61BFDA310DE3D
+:10A0B000DAF6CF4D548FD0768AEA938E24B99DF884
+:10A0C0009EC96D0DB46F3C8535D3BE7196387FDD6A
+:10A0D00092C4F5C7E563635E6E08C2FF8349DC0F77
+:10A0E000637EF7CD2837ED423E3BD12F817697F046
+:10A0F0008F7675DD9DA606E5FD1AD8DE14C4F75AE5
+:10A10000F636B5DAF57E2F3FCF98F591E53E67102C
+:10A11000FFB993B89FE716EFF327B91724A1DC76B0
+:10A120009D3645AA785EA56514DA9116F09FEC433A
+:10A13000E065406E757254A7F84D38BEEE1C3F774F
+:10A140000A746EC2FAFFCD1FB58D5B02D77701AEE0
+:10A15000B1DED373C24C758FBB8CAE141CDFF0E143
+:10A160005739A8B72A1069F0BFAF3A56DE8C78038A
+:10A17000BE2F0E47F9DACE488F69F2998DF209CFDA
+:10A180006723DFE7633F93F4F056532F3FF7B98B14
+:10A190009FFB04BE273900BEB7A39F906D0739A06F
+:10A1A000E7C7927C6FED35D0F9540FE8F15BA85FFB
+:10A1B0005C85FDADBDA576926FCCC3E7A29CFAF697
+:10A1C000D23C2D108320E924E60AF61FDB132389F5
+:10A1D0008F35FD783091EBFF960C350AEBFFADB271
+:10A1E0001C2217417690F7859DECDD50FCEC0BD3DB
+:10A1F000D0DE09BB20FC27769CEBF94785AD5AF3EE
+:10A200004EE1EC2DB0CE3587E5817A6EF4577D8234
+:10A210004FF60AFF15ED849AC7EB67F0FAC40DBC40
+:10A22000CEB5C0B9BA04CB38265734EFC3B6D0D5B3
+:10A230005282678EA72DECDDC7CF1EF3F3E3AD7B13
+:10A24000EFC8C27DEAFE136686FB24AD7FF3FFE113
+:10A2500075C0C3773B01FF43D825580EF11F58EA5C
+:10A26000149634F87EBFA4E98FF995286F175BE543
+:10A27000401FEC612D3038F67F9D54F5AC07004B44
+:10A280001BE17C1D59A230D94D6DFF91BF25A02D3A
+:10A29000D8758CFB4DAD266716F24FEBE8D0F3FA7C
+:10A2A0005AFB62123FE79C6F6643E6250F09BB37F6
+:10A2B000C6C39E413EAA6D95ED5EA0FB8556D96949
+:10A2C00002FFE6ACD39D806765CE31CF82A968E7F7
+:10A2D00045DCA87D4F6519FA2760A71E7C61501EDA
+:10A2E000DF807CF450BBC47E066B5EFED2D0FB0ADE
+:10A2F00035629E87DB36EE4F013AAE7825745C8D71
+:10A30000A813ABD1F92F8792447C98C6D2D02F01E5
+:10A31000FE21BD605458B719F8F5C1647707C61B14
+:10A320009BC5770C407F921C7608BEDC2AEA04FCB1
+:10A330005B25DAD7CB7CD52B1BE0F942C52BA39D3F
+:10A3400062D0E23EC164A7BB1CF10BEB3E86FB353D
+:10A35000CB851E5CAEF9655EBE9F01E696FCB22918
+:10A36000CCDB1889EB7E5572F854FC8EC8A03A5CA1
+:10A370005A779D5877CD8623FB318C5BD5123AAE48
+:10A380004EACBB4EB76E6D5FFBCF49BA73C837B8E2
+:10A390006FF16723F7133E10F368F7CD23B83EAC97
+:10A3A00005F0906E355ED9EBE57E9D0DBFC373BFA2
+:10A3B00080F77E41EF3AE633A5C0B8552FF075B26D
+:10A3C0006743EB3F1F6C7DC484F1959E2F966F31E0
+:10A3D000923F0A8833A1BFA8E78B1562DD2B74EB8F
+:10A3E000AE754B3AB8B89F3C18AE960548D7555B4A
+:10A3F0008C0CEB11F5702D6B59528E7C36985F39B1
+:10A400005D5688F90270AEA6737C370AE7A8118200
+:10A410002FC7B17144978AD81BA28BDE8FDDBE7F18
+:10A420009C15E5FB72F7688ADF35BAEB9F2F177E24
+:10A43000F08C0D8CDA0B6D25D6F118A7F4181C9250
+:10A440004AF156E478C0475E87CC2AA1DFDF9EB68A
+:10A45000DE0378CF3D9C5F85F17CDE61039D77DB79
+:10A46000D99D4FFBC07907D263D3281FEDA0EFCD54
+:10A47000C03C643FFB7B72D7E3B980FE9ED27C9CDC
+:10A4800057827168E773851D68E8C9B5069FEF2E8E
+:10A4900018C1E3F5A7923EFB31FAE133B61BE97C24
+:10A4A000C30CA3FF3DAC9FDAD9ADD0BE75CDE1A5FD
+:10A4B0006BC390AEAF49B46FBDBF774DDC62E4AB08
+:10A4C00076A31DF7A1FBDBFF6D2FDEF76C91E87B18
+:10A4D00012751D65595BA19FBB31CF117CDE2B37F7
+:10A4E0005A25F8D8082BC5C3336E32925D3C9F6C59
+:10A4F000FD25FA372B9C1B498ECFEFD969A2FAB9FB
+:10A50000AD1243D3BF3F69DF1B888FF36F1E31A1AC
+:10A51000935DD27AC4D4F777ECFD052F04FE1407BF
+:10A52000379B304E59B551EBF799904E2EE1FFD441
+:10A53000BE728AFA2BDA24D2332B5E92E93CFBBE40
+:10A540008EB74CC8C7B55B2496981A747F8314F2F3
+:10A550001D84A58CF3C152A1675632EF53C9306EEA
+:10A560006533AF23604F87D6E5AEDC3287BEDBB400
+:10A57000AC79687DF3B0E0EB87301EBC15BF831467
+:10A580003AEE61EDBB5C3A7E7E5CE3E74C9689FC7B
+:10A59000FC55911A950DD7BF3AB2E2E6A1CEB1F7BC
+:10A5A000083BACD9C1CB3E03D911FDB88B6D570820
+:10A5B000DEBA9ECB26B483E5ED9708EF95ED5D54AA
+:10A5C000C7711773D7209EEE6AB7DA518E2BFBB88E
+:10A5D0005E9AD96EF67A25BCDFD284F4ECEFE4758E
+:10A5E0008B9E3D12F92F9ABE7A48E0EF2181BF87FA
+:10A5F0004041A7E4A21FCBE3DE873336EE8F81FB19
+:10A60000B5E27ACD817D91E8EFCD6497EE457AC0D1
+:10A610007B18BE87BD148AE73B1987E3CE2DBCDECD
+:10A62000596FAFFA4764CDA6FC23C49D084FCD9661
+:10A63000503CD7EAE2ED7523B87DDEA4C373A59F35
+:10A6400059B3110E5576786974AF82EFEDCE91282B
+:10A65000BFDAADA6450DB5FFA8B5EF09BF59EBCFE1
+:10A6600016E7AB5BECCDB6E038D894CCEDFF8A2989
+:10A67000B207E934103FA4EFCB510D81F801E28617
+:10A68000DF8C88E771041674BC3B5266717181F8E7
+:10A69000E18749EB2B73A15FB785CBF9C5C9301FA3
+:10A6A0007EDF4B61E45FD66D31D339C03AA03BC544
+:10A6B00009EDFC1C83AB5D2A437A83FFFDEE88899C
+:10A6C00078AE8619E360DD73DA389FCF29BD447C0C
+:10A6D00072209DAFF7B2A2260EE58F6B7E389EC327
+:10A6E0005283CF3F805CE2F8DA765E0FD4BAF7EBA4
+:10A6F00051A9A8D73AFE3A6A09B45746F0F56B7EDD
+:10A700009E1FFCBCD1DCCF3986FEE7839ADCD8F9EA
+:10A710003EDA83C2CE30A989F8BBD6D8F2760CFADD
+:10A720004D5BF9BE3DDB6DC46F9CB1860F5E6F8AD9
+:10A7300081755F7C5DA27A347CFE09E0B38B4B5B54
+:10A740004EA31FFDD5560BF98F0F828F383D77B082
+:10A750003C6A72AB7D77AA81AD257F722D6BA276A4
+:10A7600095E0E38B6D8D26CA9B79839E1F3DD8EFC4
+:10A7700058A5E33B537228BF357C104EFE5FFF01A6
+:10A78000D98EFB2780A7FF4E0EC687F02F5AF7867B
+:10A79000113DFB8FD8C85EFC49F0D97991376E988E
+:10A7A0002CD3FA0D53789BD5F9D668A41FE21BEB86
+:10A7B000DE3777BE358E9FA7F612DE57BE8A49F187
+:10A7C00020385BAC94DBD3FA0D1F2CA2EFF0D4ED54
+:10A7D00019806B8C292E00D770FC2F493C1E344801
+:10A7E000A1F160DD6ED9155CEF05EBB90FF54F9265
+:10A7F0009003A6F813D02F1999AC92FD6A68E7F47C
+:10A800003474F016DEBF80E73B8CF4FE41F78B3DDD
+:10A810003578FFAB542BDF4FBEEAA9C4FE7747CB98
+:10A82000544FF9DD0F568C0DD69B0CE1047AD619E6
+:10A83000FD0914371E31107C75472E27A4DB501FED
+:10A840006D2CB567A3DEE1FA6EFF68EB72E4630F6F
+:10A85000BE373130CF6BC2DE325C6F127A152FF00B
+:10A8600079C57AD7B2B9223EE67C942DFC3D882B7F
+:10A8700026264F1C1C57DCA83F09F6E0E86209EBCE
+:10A8800089140FC6B53B8F737DD0D0F1D0A7C8E730
+:10A89000759F98A9BEEABB9D0F8DA53A5BB7FB5685
+:10A8A000F42BBEEA7CF856CAF3496B092E0FC29707
+:10A8B00084FECB8709580FBAAAE3C304B2AFBB2604
+:10A8C000AEF744A09F927B275E07BF81F80FFC176D
+:10A8D000E2BF9D3DF99ABF62C579571D505C889FC4
+:10A8E0005507F20F55A21F71B8381FD5B874389F9D
+:10A8F000FC953CF4576C01FF455B4F6532AF77E93F
+:10A90000EF0AA33C81C44673FE61E921FC53D3FAEC
+:10A910000ED9F59A3639A46E507BCE9DACF07D7E73
+:10A920008D7F5A2427F1C776DED6B4EDA4F5AD3479
+:10A93000B610BD1BB618F9FDADBCD5EAAA3D2CC6B4
+:10A9400083F8388497800E334D5EFA6EC5C154EE9D
+:10A95000BFEBE9F15932CF631C3CE1BE19F9E56068
+:10A96000917BAC7D08FBE061C53C3E9504BE5BF984
+:10A970007925FDB853C93C8E8F8C0D3D3F3A605F01
+:10A980009239FFCC340DFD3DBD9F69F2C4D833062A
+:10A99000E08BA39546FB3AE1B78F08FA5E42D55D9E
+:10A9A00046F20F8E32FB3B5867384BD3AF93B95DFD
+:10A9B000D5F2DDAE0D2ADFD7197CAE91F4E47C6DC3
+:10A9C0003EFD7969E1D7CCD7F935EB35FD37868D7A
+:10A9D00041FDD722CEB9ADC90CF306E7A3F4ED7E55
+:10A9E000B18F81E775B06DC8FC98F23607BB4EBCDD
+:10A9F00041756627C2D8689E97A3FCF5AA61F2D775
+:10AA00000D03F2382F84BF347A5C10DF55D1D3E3C5
+:10AA10000D81776D9F2D5CECB39D56DC6F24535DEB
+:10AA2000D67913FF8E9A9FE2AB864CEE1F5D28937A
+:10AA3000685F1CE01C650ED2EB1746F0B8EABB0B52
+:10AA400024CA9B76E1788C9F5A24AAAB5EE5EB354D
+:10AA5000211F8D695DF224C9AB871D6341DFA99871
+:10AA60006DE17671806EDABA07EC568C87EBE138CF
+:10AA70006A713CDAC159C2EEE9CF218D65BDE51896
+:10AA800057563B2507EEDBEBE93D77E18477E2FFA4
+:10AA9000013A9F4B761F21FDD67B7901E63F0F6679
+:10AAA0007E3E0AED65ED307CFB3BC1B7DAF7591C01
+:10AAB00063D546FC3EC98F12DD9F207EFB0DDF462D
+:10AAC0008E63F87CDF7FAF91902E8CE8319C9C9C4C
+:10AAD00012F39D4A16DF258CE3FB24CBB18FF26A7B
+:10AAE000F48EA4FC42F68DED4B35EC7E3707F5D69F
+:10AAF000C5AE0339A6203A9E5F03F28EF6A3635FCC
+:10AB0000826A0BE63303F1972469FCA608BB18CAD6
+:10AB100077E791EFB2B1FD30321DF5EEF6A391B7B4
+:10AB2000E07CBB783BC09FED328D837867CCFC889E
+:10AB300060F89E24F82EB4F07918EB1B53353EF8DC
+:10AB40007EE3707C6B4CE1F584217CABADB705BF37
+:10AB50008783FE7DA799BE8783F9E6E820B9484D33
+:10AB6000E1F230497CFF660AF3D0F7002789EFE075
+:10AB70004C51984F89C17D2E9FCCF765F97986029B
+:10AB8000C1BF93145F17D6394C11FB3285AC97C601
+:10AB90004D677E6A9DCC4EE7148A9983DAC916DF29
+:10ABA0009D9876C96E69A1FA3F5F82127DD622CE4A
+:10ABB000430C41B7C0FA15FAEE0DF1A58CE761869A
+:10ABC000FE6E4A650A9773FA3807D2F702A3FC149F
+:10ABD0007EDF0C5F325561155877749BC22CE10003
+:10ABE000EFF6B70D24BF9D7DAA17EB401DB1E2B96A
+:10ABF0002F18D5BB4E7272F944D3827512DA7AF5EA
+:10AC0000782884F9303F364981C892F0E8A3F7DD0F
+:10AC1000CEF8398D22A6D207566EC78F27935EF7DE
+:10AC2000539C54027112EA7583C543F828C3E4CAE1
+:10AC300044BEBF1109F314364BEC38EE57A4F1F5BE
+:10AC40006AF3170223E0B9BD32B15E4C811E8FE179
+:10AC5000FB1E9154385C6AE7DF094AA0EF04DD2847
+:10AC60005EFB13F8772123EFF75FFC7E7E60FFC762
+:10AC700081DF0D8A0C7C8FD281E74C307FE753CE89
+:10AC800007FBCD77A72CAD4E9918A897636EA6A2A7
+:10AC90005FA1AF9743F49D0B3ADFACD57BBCEA9D37
+:10ACA000ABE2B9B98571163A4F9B6B199587762B34
+:10ACB00023D15D9D42751F5B6EA14914EF4457443B
+:10ACC00080CFADCC3919F11CA8D7E3DF4F1A38CFAC
+:10ACD00094C0E8FC9FD5CCEB199F01B9C0EF178158
+:10ACE00054A958D7C29E28A1FAC7A7A22D0E3C8707
+:10ACF000604678AD01781B2DA2EE475777D96833AF
+:10AD0000D0F7381B59389DE79E15E6FE1EAEFFB101
+:10AD100088623A2F9DB56D5A12F983B0DE69DA7AEE
+:10AD20000D83EB10B1FE0F9FD3D7FF69EBC2E3EBAE
+:10AD3000F85EBBC097B64EBB76DEC7A9849CF7D140
+:10AD4000D6FF4C385FA71177E2D3E85915F5837E1B
+:10AD50007D1A3FFC3FDDFB356D605C0000000000AC
+:10AD600000000000000000001F8B08000000000031
+:10AD7000000BBB26CBC0F0A31E815964181826F126
+:10AD8000A18AD112CFE066607804C42C3C0C0C85FB
+:10AD9000407B23807424101F01E2A340ACC2CBC0CF
+:10ADA000100BC471403C07C89F0BC4A5409C05759F
+:10ADB000632B0B03433B107702713710EB303330BA
+:10ADC000E832136F7FB10803C31309045F5112689F
+:10ADD000A734FDFC3FD8F00C7DFADAC76DC0C0B0D7
+:10ADE000D402C11703B29759A0AA596E81DF8C15FE
+:10ADF00068F22BD1F8ABF0E8DFA787CAD7D340734E
+:10AE00009F160383155298E86BE0770B3ACE04EA5D
+:10AE1000CD0262009F3090CD68030000000000006A
+:10AE200000000000000000001F8B08000000000070
+:10AE3000000BE57D0B7854D5B5F03E731EF3C8CCFE
+:10AE40006412420810C2092FA30D382121058AED92
+:10AE50001020A2458D8F2A54D4098F24E435011F78
+:10AE6000176BDB0C04232068B058A2463B4150F01E
+:10AE7000061D6890200107B01A7A7D04AFF5D1F65F
+:10AE80007A8352400824E20BBD6DFDF75A7B9FCCBC
+:10AE900039273340FFF6FF6FFFFBC7AF3DEC73F67A
+:10AEA00063EDF5DA6BADBDF61E990C24D20F08F9EF
+:10AEB00016FEE873A644087DD5F774BE4254924846
+:10AEC000487D0E2DA710923E8A84884048410D2D62
+:10AED000E711F2D06D2464CD2464FFEB16FCBECAEA
+:10AEE000CFCAB45DD87239FD3E9ABD7F2C8BB6A314
+:10AEF000EF1F3B2762BBE02C12DA4CCB4984F636BD
+:10AF000092D021FCF82CF036D8C7D2FA4DB7598828
+:10AF10005525E4513A0C9944888BF8EC84365D351C
+:10AF20008AF5F7C82CCB33A2001F2369F36979F5A2
+:10AF3000F492FCD5B4B446667035CE29792648FB28
+:10AF4000F75846E23C68BDC79CB4DEC3EF9792D584
+:10AF5000B4DD86B916A1249BD66B566687B2A3F3DF
+:10AF6000D79E7389C4DB05AD9689F0F4F1674481FF
+:10AF7000E72FA658709CB5350C1FB49E624923A4D8
+:10AF8000B5F380CD4FFB5B5BD97AB8907E7F709430
+:10AF9000C54B31481EEC3C60BF848E1FCCB3784754
+:10AFA000D3DAE95244F038A3E34D2214F009B49EF9
+:10AFB00077874D75F6AF4FFB9D0AF35E43F12E6622
+:10AFC00046DB8D073869BBB59464613AEE2F65EFB7
+:10AFD0002118F797D7240B4112AD77150009F5E634
+:10AFE0005A4884D62352AF8DD071564F79DB369AAA
+:10AFF000D65F5D64814990B55EEDBBD74EA0BF19A9
+:10B00000630E8D02BA5E45BFC33CB21F990DF37E3D
+:10B0100078BA4200FFBF14683D8AE2C662E5870045
+:10B020009FAB8678E03D7DFA62E1B54DB0211C64AE
+:10B03000CD0642F20980807FAB7DA1952380BFF2CF
+:10B040008817CAE95EDADED9BF7D976045BA34CA8F
+:10B05000C1C180BF78F41BC5F1B93A6B891DE841C5
+:10B0600048435AD15842D6039E6050C9AF5EEF8A1A
+:10B07000D65F2930FCAC93894FA0F34BC85342CB29
+:10B08000289E2DD99E39305FA75F2157D2F22A2101
+:10B09000385804BA8C55C86615F9C23E9A96D75EE0
+:10B0A0009AEC05FEAB17C269127CBF867EA75D1EB7
+:10B0B000281A3F07F8B3C9AB203F53FE3904F85EA6
+:10B0C000EB4F26AB55FCDE89ED9DA33C56C40485B1
+:10B0D00087E26500E525C06BCE75F5578D04FA4C07
+:10B0E000B0788042AB85A9EA7C909F249B07C697E5
+:10B0F00027DC80F49307260B4447EF9F03BD299E6E
+:10B100006AD5A29FC3BC9EC8FB286934ADBF26E7A1
+:10B11000C546A0D393F7D8907E4F4EE85C0C72F5ED
+:10B12000D8B9DCF7FD28978A7733EDE7A99C6399B6
+:10B13000840EF8C8CC8F92007FC34635DC49DCF41E
+:10B1400039ABB7968CA3F09186A20599C827C28D1A
+:10B1500014AFC3962A44B5315A7E4BE03BF185B318
+:10B1600059D949E7338CD3B9B5F36D5B31F43797CF
+:10B1700044C6B8F1BD2D3539AA6786E591482AED58
+:10B18000FFB185AFA29C3F7959AA97C9791AF24BB2
+:10B1900006EF271DEA53FD926623C104FA1CD6D19F
+:10B1A0007B03C0352CEBD85C8073FF1BAF0A40B724
+:10B1B000A7C6A5AAA08F92FC9DA48BD27D58F6BBF2
+:10B1C000F7413D97339456948DF5FF82ED4CF03F57
+:10B1D000A9FA3601DEB6093587803EC11C8B97D1AE
+:10B1E0009BE9C13577A586408F0C73FCF17A710419
+:10B1F000F20121A9143E0F4139A91722B691D0EED0
+:10B200005ED66E38090980E76159C1C5A21BEAFB09
+:10B21000852257FF715B4123827C504E077EDDAE55
+:10B2200090F2A21872F03297E77A81CC467E26D24D
+:10B230005F816F862731BED1CA4F013C74DCEDAF10
+:10B2400024FF309BC2F3ABA52372440ACF43D02E18
+:10B2500086DCACE572E0E8204181E275FF6F7F6B30
+:10B2600007BC6DB79032A83F352B6CEBE274057AC2
+:10B270002C24ACFFA6EC8D36D4174216F2DDC28921
+:10B280008ACF3E0EE46FB9E0A7EDD33C4C2FBBBC98
+:10B290004A08F4B22B2D2858283C6A36F16CCC644D
+:10B2A000DD0529FEE6C13F80D125567FCDDAA4D049
+:10B2B0006AFA7D5E361534C01BC595858EBB80B09D
+:10B2C00079CEF3D62F06FA115264017CAEF630FA2D
+:10B2D00034C138742A4DE9AC9FB57793D072E0231E
+:10B2E0000F6B3F0A9A50BA8DCA7BF15F04DA6F3A4E
+:10B2F0006F07720FED12D242360B6DA7D65808C2F7
+:10B3000027450E0940F7B1A92AC0D394E6FDF759A5
+:10B3100000FF6CC9BB917E1E0570D07E9A6A2C3EE0
+:10B32000D417794A33E8E9D53EA6E7357C65F27152
+:10B33000D3BD1181CE9D64523D8978F245EC1E2823
+:10B3400067337832F3D8BCFAE01FAB8496D3C6E9F2
+:10B35000B608817A1A1E4A787F257C1ECEB4D04A60
+:10B3600009E0CE6370D37519E149CF569A410ED2E8
+:10B37000D3587F2AC58F867780CBA1C19547EB83B1
+:10B380001EF62ACDC00A0E0E5F49368367FFEB6FAB
+:10B390007708AC3F942B0787D7C1E74F00DE54AE48
+:10B3A000D7697F2D72441069FDD004A26E64A3A9F1
+:10B3B000527EF4FB2335140FB4E0E4E390F5569489
+:10B3C00007FA2AF82DE583F90DB49C15958FD12B3A
+:10B3D000AD067971F27993062647946D22D02E93AB
+:10B3E000B0B205CA741E25594639235E5D99C2E183
+:10B3F000027EA7FA67D92485F1CFA5CC8E214457C8
+:10B400000FF87C82FAF41AFCAEE0BA9EF153C50044
+:10B41000DFB09AD40211F449C7E3375880AFEE2267
+:10B42000163111F959E8D35F74BC1D4B227698A4EC
+:10B43000A3A32819F09651935CA0001E3BFC5876FC
+:10B4400074D4F8F0094BD378428610DD3899A05FA8
+:10B450003D152D14AFA4460983BE9EA087937ECFD1
+:10B4600078A5E17AA0D7038B5F1D0CF29B6A6A3F37
+:10B47000CE3202E574D82BB4168E7FEC67507F1560
+:10B48000D7270E80783C3E5F81E73027D5B3544FF5
+:10B490006750042BE3A3FA62F5A5EFE6F89D9C7FC5
+:10B4A00092F11981A759AFE8EA5FCAEB0785F3D695
+:10B4B0003B86F53478CCDFCF0816D4532EB0332931
+:10B4C0007E1F269E39B82E7B2DB82E26F0F761EF11
+:10B4D0008102A4679878854CD0B77FB5EAF9E02758
+:10B4E000F012F4AD14463951321C681F52394E80A7
+:10B4F00075AF49AA2983F7E1740701BD7060C6AB37
+:10B5000002E033BDCD3F1CE450B3730BBCE1347893
+:10B51000FFE021FF25289F71EC46CD4E34CF67E830
+:10B5200015CB511F0CF7F776C07AEFAC94BC5702DD
+:10B530007FF9295C4ED4932AF92E85DF1B5C067AAD
+:10B5400056F5D3F220FAACE4CF32F67D556D59EEC4
+:10B550005129DAEFAA51D41EA57A717DE77ADB353D
+:10B560006067D45854E0DBB5DEB76D3E27940B0618
+:10B57000009E5B8B34BB2F22C078E9EFF8D0CE9BC6
+:10B58000E0513CA0B4C65A23833DBAF5A269C6BBBC
+:10B59000E3010E721325E2E0F874A4F3453E8BB785
+:10B5A0009E002C16DD3AB23F6B07AE2F6F904B9189
+:10B5B0002EDABAA2AD23D823D52FF3B91C3DA88625
+:10B5C0006D02EA2B2ABB943EF3B91E7172BD49F598
+:10B5D00030D3737C3D59BB3815D7134D7F826D0D29
+:10B5E0004A623ED7B76B739E49BA86C2E4043D0BEC
+:10B5F0007A298D14C0FA3B1AF40CE8272928C07860
+:10B600004D133C6435AE63467D3ABA86E9C107D333
+:10B6100008F2135D879A61BD6B4A0FA7413F4D3514
+:10B620000704BF6EFDD4D63B574D27013D382F8F01
+:10B63000AD73F3B2D978BF07044D60F0825E35AFC9
+:10B640007BBF98B203956502B7B7CCF8172CCC0E28
+:10B650007C78D6DB88C7B50B1EC12769D880FDA5CD
+:10B66000D9180D56651DC0F76BFC96996077AF979A
+:10B670003A578EA2F0AF9F394F09D2EF6BBCCCEF97
+:10B680005A3D65DE33B0AE592D0A83ABA60CEDD51D
+:10B69000040ED706E81BFD4405FDA2BB6FDBB872A4
+:10B6A00004ED278DFA31820A9542362BFDEE049A7D
+:10B6B00082FEF64718FC5E524062C0FF1F8283F98B
+:10B6C000A1FECE8ED1484F8B07E04DF0F6DAC04F89
+:10B6D00054A91FA6AA00AF6A1F8BF05A3CCBD468AE
+:10B6E000FBDF717FE17658F8C1BE9FF3EE4C90AF5F
+:10B6F00075B731BFCC0CFFDD53431D161C87A05B13
+:10B70000E78A83D7B9A0C140FF784308972B8BC144
+:10B71000755460F47AB8B3E02AF4938AE87BDAD1FE
+:10B72000239D23EC20DFFDECCC840F73D0DE31AD04
+:10B7300033172A0F33E9FBB1D6F0D5C86FDB2CA83D
+:10B74000A708617A4E2016F5DB91B08830B890F5E5
+:10B75000A8FE5E2147E62CA0F557EC7412C097C6F0
+:10B760000FE9BCCFD535940F62CCBB4310E3D19D1C
+:10B77000D9199CEE9D30DEC00BD39F4AB31DECB6A9
+:10B7800070A87E4839F81F35CCDF0D470EA0FE4962
+:10B790009F7E33FA295B9A53E72C00BECAF27901E7
+:10B7A0001D1A3C609FC4F213AFB6D8CEEBBFC7D30F
+:10B7B000C38D952BD0EF6DEC8C3DFF2916E66F877E
+:10B7C000A99EF466C71F3FDFC2ECE8240BE7BB1954
+:10B7D000AFA6E9D7336D5DD5D6D96112098ABAF51E
+:10B7E000F0268E3FF3BA49A406DB18C6E7E83F36D9
+:10B7F0002E6071880D532C185FD1F89CD64B03BC7A
+:10B80000D279A03D47F93004F6DCC3A401E526480F
+:10B81000DB6F26FDE1BE8D582E6A7E93F9FCFAC6D9
+:10B82000E3FEF5ED5C5FADCBB9C70E5DD1F1D28023
+:10B830003F026EA627AB5CCC8E9DB6538EFC80C2B9
+:10B8400051D52CA09D65D9674738CF6CA265DA75B4
+:10B85000C4A560FDD31E1B9603D6CE87BE47CBBDC5
+:10B860003B4582766496C302FC7A8CF32BC9A365B0
+:10B87000B087EDAC58D5BCFF76E8AFACCD4AECB4A0
+:10B88000FFAADDA5D77E8F964B3B640255AA362FC3
+:10B890005386D0F2A2901086724F015DA8002FC986
+:10B8A0004A08FCF61E7767EA8FE8BC4FD6DA884A6A
+:10B8B00041A97375A6DE44F1511EDA5E08EDCA5B3C
+:10B8C00004D088741E9B5F1D0CF3DA2A78C1BFAFC9
+:10B8D000D89260B0078FD1A9FC807E5F42E70972E1
+:10B8E000594A1A0A619DABDABC4E5175F18793B57E
+:10B8F0001E1C472B576DA5E3D076D5CF0B5E986203
+:10B90000B585F8410F9DD96D9FFDB413E6B74C196D
+:10B91000E382793DA040BDD250F18B7615E06B56A5
+:10B920000AE9F7F2A66605E25B012BB903FCDC8AA3
+:10B930002D038C70358A28AF4B926C1B419F13A747
+:10B940002FED86B1FDE97CB296EAD831D17239E8A3
+:10B9500043E4C39072BDAEFE703109F9B5628B68E5
+:10B96000B4B3F9FA1F3CCCE81FDCEBC2B89F46BF6A
+:10B9700025DC5FD6E8B72489D353EACD8F05CF43C2
+:10B98000400F0A4F03E08B3ED770F8DC53C8548851
+:10B99000BBB87DC423C4E06BF3B34126C5C0BAFF76
+:10B9A000BAFCFAA9D260741F1643E4C9B362CED4BC
+:10B9B000E9B4FC3B4BD1660BEA0FAF0A72A4F9D98C
+:10B9C0004F59985CD60F56107F0D33F29F66F109E0
+:10B9D00082EB5EC38C9267C02EA0EDB759500E6902
+:10B9E000FBB1F1DB7B0A271ADA7B0ACBB4F63BB159
+:10B9F000BDEDFCED1B0A271BC72F2CD7DAEF45F84E
+:10BA00009DE787DF73E514E3F8575662FB8095D115
+:10BA1000AB37C98676CD0ABBD727313B2A02EFA5C3
+:10BA2000E4311BA19EA8F103E9F481FDED6C491AF4
+:10BA3000BF9AE8F9A2E00D80C345A545CF17891349
+:10BA40001D067E4CF2251BCAB427CFB1EFF0320C95
+:10BA5000E2B6213CCA1005F5C5D4213684F79E7D97
+:10BA6000762CDF3399C17BCF1027CA19AE2D948E67
+:10BA7000F728FECBF5762BAC4C104A7A53F47F04B2
+:10BA8000F88DBE572DF0DE21921AD4CF5682FAE8F7
+:10BA900081CCFCA7833AFCAC1C46E94BCBA7C1FE8A
+:10BAA0001918C5EB03C34AD28A75E3D40F53666FE6
+:10BAB000CC66EFE73B61BCA21EC04340E91D0376A4
+:10BAC000A5791CEB888986716C196538CE37A6710B
+:10BAD000AC1965A6716CB337F2F77C9C3FC3BCE22E
+:10BAE0008DF3C088C9C6F96494E33856D1349F8C6D
+:10BAF00072D3380E361FFA9E8F6317CF379F91533C
+:10BB00008CF3195E89E3A4888A216E651D5E691A2B
+:10BB1000C789E3C07B1887A433FF46B1F69620FDA2
+:10BB20005FB613B0A715ABFF59E897FCC14E509F05
+:10BB3000A874DC41A0579271BFE03F2CC9389F2FF9
+:10BB40001D94FE4E3D9D839A5D80F6CE420E2209E5
+:10BB5000D5A37F5ECD797441CBF519CBE0D9362DD5
+:10BB6000AD18FCECF52E2FC44FCFB44D53E6C7B043
+:10BB70000B1636C8C7BA0CFCCBF55E01C9AA013F4B
+:10BB80008BDB015AF918D55F84EAAD8FA8FE82E7F6
+:10BB90007199EA69FAFE28D56F44D1C3BB0CDB1D4D
+:10BBA00093181E8F35B175E4CB7587658CF305C985
+:10BBB0003B59741E37F3692C6C4860BE028723C062
+:10BBC000E9D1BBDB1ADA88F4F00D05BB87340EA08F
+:10BBD000B8E2F54600BEA8B824637128D8473F5E96
+:10BBE000B9FD3750ED5DA178D8123ADFD9ADEBE45D
+:10BBF000A1B47C46EEBADDEBD4F5335BFE08E66D0E
+:10BC0000A3FF413F73FCB4AC1BFFD63263F936226D
+:10BC100045CB946E33C4119C1E7C5C352403BD6EF1
+:10BC20004E65F0DC06CFF1F0D983F4BADDC3DA6AF1
+:10BC3000F004EE934904D7A3AE81CCB81D88F5FC7F
+:10BC4000DABA6282EF76D9E62BA2F4BCFD5E11F17E
+:10BC50006886B76B5F82CF42FDAAAEC6CF64F02F75
+:10BC60002F04FF1D4B8DDF49908DA7E155E3835BCA
+:10BC7000664F1D7054576F8EFFAA014775FC726B9B
+:10BC8000D9F586F26D35730CF5EF585A6CF85E1CD9
+:10BC90005C64F83E7FE562437961C3BD86FAA58D99
+:10BCA000CB0CDF17855619BE576C59672857851F6F
+:10BCB00033D40FB4351BBE5BF65D7A1DC863DDEF70
+:10BCC0004402F6D917CE630F817DF5855342BFAA92
+:10BCD0001A788DCAE189DA34E4EF93B52A3ECFB4FD
+:10BCE000E5E2FE58C041E599AEF51BEA0E2D5B3941
+:10BCF00005F408AD4F75F813756F2D0B52DF7D23DA
+:10BD000004A929DF8B8D0A890C003F26B98FAF7BF0
+:10BD100045DDF7AE0B7C6FA40B566EFFEF6257EC60
+:10BD2000F73D42EF18B0EF821F5871FF269EFD408D
+:10BD3000FF869218FE83F6EC86F8864EEFBC2C3216
+:10BD4000BBFA72B1E065913E2B1526EF953B0617C5
+:10BD500040BCA052898CA9896167F78D17A6C00CD9
+:10BD6000827E98BC2C0A0D8DCA2FD26FA441EEAFF3
+:10BD7000B1F8F7817EEEDE2FB2FD81C8C10CD8A7E5
+:10BD8000B95CF4BD0CEF49DB405C1FDFADF50D384D
+:10BD90003A8A90F76B67E2F3F7B54503207EF4C764
+:10BDA000DAD958FEB0D68FCFAEDA327C7E545B83C0
+:10BDB000DF8FD62EC5F2B1DA203E4FD4AEC4E7C92C
+:10BDC000DA06FCDE5DDB88E533B5217C6A72A0D93A
+:10BDD000A32485DB7FDC5EA72B0796CFF23988F49E
+:10BDE000DF9D28D7DE3490EBB3CE2FC7809D7BF646
+:10BDF0007D2B06D1E3E1C9CC6FF1E9E7C3F5BE24A1
+:10BE000044E99FDBFFBBDDC1E863B79099E09FADDC
+:10BE10001AAD1088AB3B5EFE0EDACBF4BD44505F2A
+:10BE200086BCFA7DC4BEFE61CE832E4C27ADFEB12A
+:10BE3000C7FF2B7F5E36D087D1D77150AC61747B42
+:10BE4000DA0B74D3E18FD9653BB93E37E151E27229
+:10BE500067C6E7E9811A3E3B3320DE522516592496
+:10BE6000FAEE6CAB15E775B63D81ED637B522E2A79
+:10BE70009E57B1C5EED1EB87AA7092C7A82F067B5B
+:10BE8000F4FAE26CC7D36E90FB256916CFD15CE063
+:10BE90000F1FE70FC6775AFF55E14C8FD3D08FB1F4
+:10BEA0007CB64198C9F615D5C49B62F807DA734988
+:10BEB0009AE2394AF5C2C92D2313615CEAC7796059
+:10BEC0009CEE5A8F878D9BE6D1F365E55207D6D756
+:10BED000E08BD7EF3F1A3ED8F1FBD8C6624D10A7D2
+:10BEE00089573F2E3DA4CF15F00F48BBFC25AC3B36
+:10BEF0008E2C6DDD91B0ACF51B088B41EBE5F0BEEF
+:10BF0000C5301E6DA76A3E34B48B4F77891CD3E8C9
+:10BF100049F5E4953C3F843233D2D94F7B4CA4FDA4
+:10BF2000F548CE9510E7CD9454D477011888F25394
+:10BF300095AD4BF1AB88EE4E8C7B4ED4E45EBDE507
+:10BF40000F94E53EF93719E319E4CFB477FA5DE6CB
+:10BF50005F179022373819F35A2B66819EFCC4A2D2
+:10BF6000D9030DF930EFD3C482FBF9A7C9DBEE5C2E
+:10BF70009D5D5626F1F8E44AB63E07E97F303F6AF8
+:10BF8000A719D6EBD24663B984DC900AF250B25EB0
+:10BF9000861D5BB208D67BDDBEC96CC983F32E2536
+:10BFA00035F560A7AC96D93EEA3C0F918652B8AA07
+:10BFB000763D990FF66C4062FA5EF39F172533B811
+:10BFC000CB53428A8F7EFFB835F7E6EF11681FAA80
+:10BFD00007BD1674116FAC78CCFC9546F82E04BFE3
+:10BFE000195E42961BE0D0FAD5E010B70831F33461
+:10BFF0007E26093CAEC3E463AD64B45F1FE178D034
+:10C00000CA1B4CE526537D8D4F64CE279992FF11B4
+:10C01000D03F55B6DE42B4D308E58FEC683D255AD3
+:10C020006FC3F9EA59A19E88F59AA409F1EBD9A347
+:10C03000FD35C7EAAF6AD7B61783949FCA5F78D435
+:10C040000D41DF4FA48654887F556EBEDF0D783AD0
+:10C050002105DD40EF4F4262CCB8E07B7DF8F2393C
+:10C0600005F02390B529DE9F7BF05AD0D75F6E96FE
+:10C07000312F26B0C51AB1523EAE6E5D340BE2F7D9
+:10C08000B47C84951FF814F60D036D467A963FFB39
+:10C09000682AC489282699BD4D226877546FFA53BF
+:10C0A00021E8F100E9453E34B783F1CF25A3DC1741
+:10C0B0002B89FDBF6BF90A012E6781D6073F85BC2E
+:10C0C0008480897FCAFAD6932E05E2081D922B053B
+:10C0D000FDF2EF92EF821ED0F04142CC9EA8DBBA77
+:10C0E00061DC110A4FF7A67F730B06BF9BF1E1D904
+:10C0F000F0FC5FBDA4C6D73367B83F146D17C27696
+:10C100006A1BB37F483B7B56CA1137D89B95CDB28B
+:10C11000977228A9DCF6F4338F839FF68115FDB45E
+:10C120008A6DBF7977322D576C975366B1E93885A0
+:10C13000D4285D02F47F4BC747E950FEEBDF28EAC5
+:10C1400058F6FEA7C9517A546CDFAF90B1FDF137B4
+:10C150002DBC5FE972C6A04BF84821D82B755BBF98
+:10C1600052C0EFFA649F400665F66F5FD6FC1B5C19
+:10C170000F014F48474EA73EBAF5A357E4DA97F2AE
+:10C18000B09E07F4643C7A3DC7F572D52E174982FC
+:10C19000F8E7EFADA15940C7E7EF74C33C8E4B35CC
+:10C1A0008CAF9FBC3F15F6FFCAE460AA079FEC7DE9
+:10C1B000D9537723BF950A35A96C1FD33798C7CBBE
+:10C1C00007C3FC1636FD08E75742FCC877654F8A5F
+:10C1D00045101FFE422233B7C7908B6B64B6FF74C5
+:10C1E0007CA31592FCC871B0F3C1BE7E5BC4382B32
+:10C1F000218B711FEC6E2D8E4B9660F90BBE2F3587
+:10C200004AB668FEA1CDC0AF9B1EE804FA9C1CE6AE
+:10C210001B0470523C0439BE04D8EF170FCF18C46A
+:10C22000E8C3F20DB01DD5FFD3E03DD4EF94719F6C
+:10C2300050D78EEB4B36FE5D7C7C0AB703D6B3E35A
+:10C24000A96CBFD23CBFA57C7EF4AF93E8F84B2726
+:10C25000DF4CDE37AD62F2ADC97BE8FA99F0FDF351
+:10C260007798FC403B583F285C9141F87DFF4D0298
+:10C27000EA032B89C492EB4D32976BE3F700955399
+:10C28000880B50B825C86788F209ED3F19F18F7EF9
+:10C2900049C97ADA4E679F05603CACA744DFEBD60C
+:10C2A0008F52AE0766CA46F9274D032FCA5EAC947B
+:10C2B00049104CCBCA0FACE877576E938B60DEA762
+:10C2C0005A0EBEFB63CAD7A7C29A9C1AF5A7594E4D
+:10C2D000CB766C16803FCD727AAA8CAED6B1E49440
+:10C2E000BE8F29A7655DFF57F4A786B780096F54F5
+:10C2F0000F0E4FB2C4C79F590FBA6435A61EA47F54
+:10C30000EF90FCFE7CA7F19BC667D4421B0EFABBE4
+:10C310008F1F357EEBE3478DDFCCF334E2CDFC7D20
+:10C3200032186A14AEA2DD32FA2595ED6CFF86B69E
+:10C330007B75681EE2C787CB17697875688ABE1C53
+:10C340003295C3A6FA3E53B9C854DF6F2AD718EA0C
+:10C3500057B61D54589251C450CFBAF471F2710CB3
+:10C36000FB5E5B6702AD9F2A41E087F45E05F49CAB
+:10C37000BC9C9A66103FDB2BA2BFD5A3F6BA93E90B
+:10C38000FBFBEDCC8FEDF1F072122BF70E54EA416E
+:10C39000CF69EF7BED2CCED953D4EB4ED2F9F747D2
+:10C3A000DA4537EC077785583E6A7F78EA506EBAEF
+:10C3B00048BCEF2C2E384374662C05FFAD41F48247
+:10C3C0006BB860D92D6ED877EB691F79DD6CFA7E7A
+:10C3D000E12111CC67D2E3708F03B848D0270DCE8E
+:10C3E000E7F913F4EF0409FE720AE44DB433FB7A63
+:10C3F000C11A933DECBC4BC1FCB2F5BAB8968EFFA6
+:10C40000CB793F654DC6EFE5640DF25FB9491EFC7F
+:10C41000DC1F38ACC9430EC961FBDB84F9B15CEFAA
+:10C42000CE10B3AF9B4DF1DED32162DEECD9769115
+:10C43000D4C33C5B04DCE724C1812857D5A417F59D
+:10C440009D86976E901B25BE3EEADEF91FF9F70127
+:10C450007FBCF887714FD067F78B1F8CD903E55DE0
+:10C46000EF65FC81F4AF3F6DDFD7B88FD8B3CF8ACB
+:10C4700071AE9E7DAF65DC07E597AC18E7EA596EB3
+:10C48000C57D94E03E5768347C1FC6FC81BABD5F11
+:10C490008D6379922B904E7F96993F72B6FDBF3E89
+:10C4A00084FC91B3ED74566017EC4B40B909BC6441
+:10C4B00047FFBB67EF57F97EE73F6E3ED50AF12392
+:10C4C000FFB9C8EC1DC0AF492C1E1CD833E969C8A0
+:10C4D0006FAE6ADDAF409C7DDACB7F19077AB26719
+:10C4E00007B377CEC85D4FC17E9855F974B94CF14A
+:10C4F0007C06846708214F2BE3A705B363E185E140
+:10C50000A187E201E645F15206FA3D1E3E32947FD4
+:10C51000567C7C7A3BD363DFC53CFB285E041F7BE3
+:10C52000EF0AD9049C3F7BBFEFAB71A0674E8597A4
+:10C53000A13D72A1795FA1B07D96FF39F316221754
+:10C5400033EFB9FFB4F466FCFF11ACAF03FBCB4192
+:10C550007F3EDF750F969F777911DE8B94FF9FFEEC
+:10C560004FA3FB0E4A77F785E9FEC43FEDBC2F448D
+:10C57000F7439CEE2E0FEC2FF7ECFD0BC64DB5F9F3
+:10C580005F68DE2FFD3F3A6FCD5E7FCDA2BE934345
+:10C59000EB1F220DEF8C11207FF1E0613802562055
+:10C5A00090A258F6C84985C53F0A049627489204C8
+:10C5B000EEDF31BF6828B71386DE558276C6D0F429
+:10C5C000B5681F10495D0FFB71AF65CCF7B27CB049
+:10C5D000F1780EE535CF15BC6CF40F9F10880FF283
+:10C5E000868766FCB003ECD5F47411ED59FA443B30
+:10C5F000F615F74CF6BE5231F84557115D99CEABA2
+:10C6000030C5E8FF4CE7FDCD2023DEC9A1F0CFB057
+:10C61000C99E1045D15553FD12CCE7AAC10269D07D
+:10C62000ED074D37F949AF825FAB8B97FDADF84B06
+:10C63000B7323FB24018B1BE08F0374CC478E005BD
+:10C64000F14758FED76B9E1C96D72A7919FE92ABFC
+:10C65000BC184FE57E338405C05E919CF59D20B7E4
+:10C6600012A17E2F831FFD65CDEF8D8767C2FD6808
+:10C67000890FA9E15D4A17315F55D71FE243A3C770
+:10C68000DF4A078D7E7F2F3DCE98E891FEB94702A5
+:10C69000F99CC6EDFFE99F778A584EF74AB81FC547
+:10C6A000EDFFA9CE2409ECFF2BA4C322C865A9ADD8
+:10C6B000ED6A88D3DBBC02F2F525DD16F46F6C79E8
+:10C6C00002E23DAB51C2F2618B670218DAD77E6F8E
+:10C6D000D7A97B09C4877D0A1ADEA488C5E7FFFCB9
+:10C6E000EDB753B4F31AF89D906BA8FFB5A0894439
+:10C6F0001C144F0B25124C4C86F8AE403E32C477CA
+:10C700008D65F8FB7E6AB49F0BD58FA747FED1CF0E
+:10C710005D546F7D449963373C715F85B284CE3F31
+:10C72000FE6E3BC357E075121A8171059F58A4DB5A
+:10C73000377BD0CAF4C7AE3FEEC885B8D8D49EECDC
+:10C7400044A64F47A15F10E07EC159A22642FEC118
+:10C75000D9F69189B82FD821BAFC31E2325BB9FF02
+:10C76000FCAF904F419F3D9B48039CC3E821BD18FF
+:10C770008F0D6EB2C5DCDFBDC7AAC59B38DDE89F53
+:10C78000A89D3752315F2498A8A75BF7AC4FA471DE
+:10C79000FDE9007F1FE9F64BFE5EFC82BF0EF8DD6F
+:10C7A0006AEF2A8C751E6C25C7DFB507BEC638E652
+:10C7B00065EDCD16E0DFCB36590CFB8D412BF7BB79
+:10C7C000C693F100D7B507ECAE3CA04B87E885FCDB
+:10C7D000C140FBA78A3FC6BE95199FD03FC4C5F78D
+:10C7E00059599C7F8F1C9E0F78DD73DA86F939BB0F
+:10C7F00095868A58705E62677A6E2109DF392EF35A
+:10C800009F0FBF537B9C9102F03337111EC730F34B
+:10C810001F413E3EBB85E0F950F04B412F9C6D61BE
+:10C82000E780294AD6823F4DE5FD07FAB8CC256D51
+:10C83000DBFF15EC80EA76C103A9B3D5529702F16C
+:10C84000D6405B9208EB6E8EAAE5557AC6DEA493BD
+:10C850008B7D56966F7C70F29E5B61DCCFBA1502C1
+:10C86000F688EF955E37ACDB9FB5E726C6CA9BD747
+:10C870009EBFAE25574F97A01F827837F343768B24
+:10C88000C350FE9EE81F02F275ADB5EB2E6F0CFA99
+:10C89000F96D8CCF2E5ABF85FE3FD36FEF68FACD6E
+:10C8A0002F16E9E428CBD64FBF0D8AA5DF9608EAFC
+:10C8B00020C0FB92BD2307015D971C9207C6D26F73
+:10C8C000DB6AD97EDE0B3C1FB6A795EAB7CB75FABB
+:10C8D000ADD5867971E676C9360B5F172FA0DF429A
+:10C8E000FF3DF2B70DF45B8CF98EB631BDA1E9B70F
+:10C8F00071ED4750BF8D6BB518F246D36D17D26FEF
+:10C90000C2C09BC01EEE90BD0931F8671BB7BF5F68
+:10C91000E07978300EE8B95B6D6C7FF362F55CB658
+:10C920009DD1FB827AEEBF09CF9A9E5BB2533BE763
+:10C9300068E643A6E796ECA67A4E007E647A6EC956
+:10C940005E768F8359BF65F5D36F04EB574758FB6D
+:10C95000405BE686B9B4BFF13ED96BA3F5C747F596
+:10C96000DD04BDBEBBD5C6EE5DE8A7EF3A2E4EDFB7
+:10C97000EDE4FA8EEAB111A05FCDFCE16D37E61D62
+:10C98000EF9974BCE5D7202F6F88B86F78989F4BCC
+:10C990007B73D2F13CE0AF161BD3BF759CFFCED4A6
+:10C9A00006B1FF69AFB0F95539593E72752BB30F17
+:10C9B000AB5B84904AFF5938F96B05E05FB45720B0
+:10C9C0008368F97A2BAB4F9ED5F6BDC8AC1C1D3FD2
+:10C9D0002C98588171FB0512B1415CBEC259F8090F
+:10C9E000D8BF1513591CBF82BF5F74A8AB1EE2D914
+:10C9F0008B1E1370DF93F07C002DBFB1B47D19C680
+:10CA00006BCD79019A3E5F1432BEAF30E53336F319
+:10CA1000795E2F76215EC85B62CCBC8466333E3A79
+:10CA2000383E3689B86EF6E183E247CDEC8F0F4A87
+:10CA3000D15939A9D1F92F7A83CE2B2F3A2F0D1F37
+:10CA4000E6F96971E70ADE2EDE7C35FCF59BAF86E0
+:10CA50004FD3BC9F06BD010A2187E4425E0CE5036B
+:10CA6000D41BC1DF8A787EBF68EAE8417A3DBC9575
+:10CA7000EBF3DC86A9D30613C017A901BE29695CB4
+:10CA8000FCEA603AEF09EFABE36179FCDE64AB1FCF
+:10CA9000F647B7DA7B51AF697CF50DE7AB77391E06
+:10CAA000F70CA9C173AA8136C1037645206247FC01
+:10CAB0000528FEE0FC4A809F5F0C50FE02793AF8A0
+:10CAC000D8970C5F7B0515E2E385DAFA03F8A7F542
+:10CAD00073DB19FE032101F19F477A717FA4BA51DC
+:10CAE000F04668FDEAB6C598F7A0E95BFAE7D4D34B
+:10CAF00043C78F522C7EC44ABAF5AF82D7BBD6DA71
+:10CB0000F02EF0E7B5CFCAA459C79F59F4BF6F63A1
+:10CB1000D049C3E785F8F21CC7D336C0A313F0D5BC
+:10CB2000CBECA7C8D7788E46FB1E9082063C4E7B86
+:10CB3000FCDC79F13441C313F029E8A9F66211CA8B
+:10CB4000256D021990D97F9EB03FA997DB457B8F59
+:10CB5000B0FE9F14F0DE1233DF6AF3EEC7B771F850
+:10CB600015CEA5815F74B17CFB8D896FDFB4F7BEF4
+:10CB70009E0B7CBB5760F183F624C3FEE2103B5B47
+:10CB8000FFB7DA297FC3BED621D9BB51ED2FDF090C
+:10CB90007CFD02BB5F7F2EE9529808E43D6EB161D7
+:10CBA0001E19C23182D9957ABDBACD4E06DE9417D0
+:10CBB000BFFFC1BCFF78768D561E0BE341BE571BED
+:10CBC0001D2F2B3A9E59AF6B7EFE85E635E6EF9C16
+:10CBD000575F1E26E9C47DA74CC9FFB0559707775C
+:10CBE00033CF33A210A07DA5AB976D3B4F3D92E6AE
+:10CBF000C1F34F777A343E63F9EE453C8F7D86383A
+:10CC0000E53D583F3FF3B17DBE3C0BF9DD14D0CF7D
+:10CC100005329EE3FBEC7519E3B59F4D67799CD710
+:10CC2000BD71508238CD75A09C283EAE9B20A0BF20
+:10CC300002C7B060DF6C17B56F7C63703EB9708E51
+:10CC40002B6753C334387F3C7E4BA80E9EDE69BDF4
+:10CC5000296F021EA78A04F0D8E91B300DEE4FBAE7
+:10CC6000F34F04EF0FA1EB2CB61FDF410642BDC905
+:10CC7000BE81E80E4C6A5D3F0DE2A3D71F743AE116
+:10CC80007E96AC260BF519A2F89B4C4275B0DF3EA0
+:10CC9000E9A8EF4680B78CDA0B10772E6B6FAE7376
+:10CCA00043B949F0AAB4FF40D05FE8A6F3D8D6F85C
+:10CCB00069E177401E693DE826D0C4EA0536C1C562
+:10CCC00043F07E1DE6D9946C12F0E0D7B690406C2C
+:10CCD000ACDF908DF6BBAD89B6CF837582B6877E0B
+:10CCE000377DFACE8D20EFAF8BAC7D0BDBA72EA16D
+:10CCF000ED54E0DB4D8BB1BF454D0249A3FD95B529
+:10CD0000B075A0EC75D90BDF5BF73F86EBD82C3AFA
+:10CD1000DEE04CD0FB91E95026B98207CFA1548EBA
+:10CD200041BAF5703927534633FD21F032F71B34F1
+:10CD3000BBE95D3BCBF72DF12E5306D07EDE9C3850
+:10CD40003013D202026D9FE2FEF3518A673FEDF28B
+:10CD500030CFDB3838F163A54BB70E7D6667F75BE4
+:10CD60002D689B8AF90C0B4911E6335C3B89D96B22
+:10CD70006F5D610FC115076FC9BDE9F0FEE0155683
+:10CD8000B47FCF6C93918FCE0CEBC2F8F4F12619DF
+:10CD9000CF0DD735B1FBB98EB7B0755C7C92EDEB9A
+:10CDA00097BA142C1F6CBAB110D6B7E39BD879C7C9
+:10CDB000694FCE50A05CDA2C78D9FD454C3F6AFE15
+:10CDC0005B8987E52368FAAF8ACFBB5FDEA249DFC4
+:10CDD0005569EB8D49DF55C1BEB21B9EC6F701E216
+:10CDE000647A10EC7EA07BE46BE4DFEAD765027620
+:10CDF000BFF0717721E663ED15309E3FA95DF0C16C
+:10CE0000BE7ED9FBD610DAABA1E23B7E027AFC03F0
+:10CE10002B1154C86BA778A7FA61A2B5F78FBFA0F2
+:10CE2000EF3F396C834C18CA27C588672DFF336FD5
+:10CE300033CB63C93BBC3E15CE5B92E90350DF9612
+:10CE4000368AC4AFD31B9F08BE1B7FCCF432DE4FA3
+:10CE5000A1D12F4F692881756CA483E92575B30C86
+:10CE60003922E4108F93507B1ACFDF2EDABD2E5576
+:10CE7000A1F5EA79FEC7A2BDEB5245FABE0ED62F48
+:10CE80005A7F91C2FA5FB44FF034EBFAD7DA6BFDF8
+:10CE900069FD28BB8DFD8CDCCBCB17D98F0687367F
+:10CEA0007E3C7B7CE2BF9F5B0FF7C54C7C4BC4A4F0
+:10CEB000E3891FCF1AA9DFEFD09E5AFC35FF1D0B67
+:10CEC000F1E9F036F18F0EE2D3F145EB042ADF945D
+:10CED0006ED7B4092100A575C211A52A0FCB1E90EB
+:10CEE000E76A1EA7AD9ECEF6AD5A730EAF00F99E4F
+:10CEF0009527201F90A05F19908276900AF1F1D2B9
+:10CF00003CD6BE94B607B96B7D8CC921D5072AE8FB
+:10CF10008BEAA67585587F93A042FFADCDC5B8DEDC
+:10CF2000974D14097EDF7404ED8FB2B6232920AF2C
+:10CF3000543ED7C3FA5B3DC58AF7796972A7C9F138
+:10CF40005B32BFAFC9E6190B79FDF7015031E457E9
+:10CF50007C9D303FB54546390B4C6472F9D636118D
+:10CF6000E5F9E015B7A01C9ED92CC491E3690A9C91
+:10CF70004B3E1E62DFFBE478ABC0E598E987E34EE9
+:10CF800026D7D3E03BC8F14E81FB83CC1E34CBB116
+:10CF900026971792DF8A2D26798E23B79D52D74D7B
+:10CFA00030EE9D57D811EE69DFDFFDEE9DA87F645E
+:10CFB000CCFB98F6FD7B5341DF95482C5F49C3635A
+:10CFC00095C4F2D9FAC1B17E9932F8A2E031C2F12A
+:10CFD00084DD15D51F22F039BB872BB849463E3773
+:10CFE000CBE1DF2B3FFF28793EC4F9478347DCCBF9
+:10CFF000DA43FE5884E2E9B596A7314FF5F473475A
+:10D00000AE053C57ECA17C4BE77BA6C5C5EF7B0981
+:10D01000E13A53DE2A621E389122F937BAF472C916
+:10D02000F2902A5E70217F94EF60F9A4E52F7E3C98
+:10D030000EF34496F7627E55F0396E6F06BBC6015B
+:10D040005F974B2C1FCA2CE7373998FDD9BD3B6140
+:10D0500036CC43D8C2CEE997876F91810FB57A3F1E
+:10D0600074C85A3DDCBF0C52BE85FD75804F7FEE03
+:10D070005CCB83EADECAE4BEBC4D467FA97C4B3361
+:10D08000C6B1035B3EC53CF7692F6CC3F841A04DA8
+:10D0900034E63D6E112356CCCB148F58D93A65C86F
+:10D0A0003FAC6EADC2FDB6EA30CFEF33E5BF55BC45
+:10D0B000B0F7C520454DC5AF9F75831E38D9B9D986
+:10D0C0000DF8A4FD61DEE0F73F970C7951F1F37B99
+:10D0D0007DC67CC2F0AA98F98427E11F94C1EF7540
+:10D0E000707ED5F230B70CE079DA91FCA218F1FB32
+:10D0F000BE733BDBBE780AF2DCBB779C7A0AE0AEFB
+:10D10000FCEB674F413E13D967C77529F0DCEF3060
+:10D110004F586BF70B07F7F3B73E8BF9D5673EB067
+:10D12000A29F7366EFF10CC85F3BB3FDEB5488C759
+:10D13000DDB57706C62BEFDA396D1089A1DFB5278B
+:10D14000F065E822F2BBCD7438D87A10F3AE4EBF4A
+:10D150006F457DD697171AAE6279B62ACF076D89CB
+:10D160009D47AFE53156B7DE78DD15A09F5B993D51
+:10D17000D797D778A13CD077283D2FBF08BAB5F014
+:10D180003C5F13DD4EC33F287DC226BA7DD1BAF085
+:10D19000578FC3B7D60171F3402317812F2D4FFF4F
+:10D1A000E70EDF1E079CFBDB91104C63F40ACD12E7
+:10D1B000C0DEFB2203CE359C907B31DFA377AFD559
+:10D1C00003F98CE57BDF43F938B3F330C65509CF5B
+:10D1D000933F43FAFE585EB3C0E7B7C9C5F247397B
+:10D1E000DE21BF5475E37B9E47CAF856CB2F8D973F
+:10D1F00057DAEB18C1E2D0FCDC4015F593F8BD59C5
+:10D200007DF9A6C244A0D311439EAE366F737F1E34
+:10D21000AE37A3F9D1B1F376B57CC1289DD83AA237
+:10D22000E53F9F69E679D3F47DFA78C88363EB75AF
+:10D230002024BC4762C8A3961F7DCA61CA8B0E5DBD
+:10D240005C5EF485E0FDDFC5C7870E16AFD6F0D271
+:10D25000FDE7D8FA5849607627F54FE504DC1760FA
+:10D26000FEE91DDC3FD5F0A5C15B1F667643F716CE
+:10D27000E61F98E5B93ACE7D49297C9CEAB6FDE3E4
+:10D2800040EF741FD8CDF98DF17375CB1196774BA4
+:10D29000F57348AF9FF9FD12E6FE32787F81F6D82C
+:10D2A000FD055A3E8DD9DF49C9770BC07FB293D9AE
+:10D2B0004927C3E2CC58F7DBD8126443FE40BD8B4C
+:10D2C000DD9721BA1D681FDDE59AF87E620A3C15DC
+:10D2D000CCEBA95BC6F3807EE6C57B45EB5C5713C0
+:10D2E00080E77EC08F2ECE207BFC04EC3439AD2845
+:10D2F0004F54A3F0F6D123C542427AFA4B9174D031
+:10D30000E71FE61C97A1BFFF34C547FE5322F583F4
+:10D31000285CFF1914BCCBD4F876B556F6FF54340C
+:10D32000C433AAADBD1F827D4E5EB6E37EB8B8CFD2
+:10D330001EC4F8D853EC5E8D833BBF7A06EFE5F947
+:10D34000959570BB50007D50CAE314C7777EF5D425
+:10D350007F811D098DE9F8A54FD1FA603FB724A060
+:10D36000BDDFB323711CC4014A5FBEEF5AD017A5BD
+:10D37000A0FBC0CE7C6150A88EF6776C202B1FDB03
+:10D38000360CCF0554EC70613EE1C19DBBAA41DF74
+:10D390009F79218180BE3F2D77FD15CA813D89A4EB
+:10D3A0005945BB4FD5AFAB8B88A4EAEDB90A281B12
+:10D3B000F25B08E6B760FC8DF273455B229EFFD0FE
+:10D3C000D5E3F21C1CC2EF891A027247ED46D598CC
+:10D3D000F7CCBE2F4860FA2B60EDBD87DD87C0EA31
+:10D3E0000794DE12566E18C2E4B613EB2FD6F895EA
+:10D3F0007FEFDF2FAB1F4860F180683FAC7DB595B4
+:10D40000DDAF61A6EF4F13047E1EF72F97C4BA7FDE
+:10D410002206FCEC5E2E8104E1FE55B2DD8EF7F1B2
+:10D42000542A913190AFFEA2C2F63F2ADD9131908D
+:10D43000AFBE87EBBF4A072DD3F743381C501FCA36
+:10D44000C4D6F53CDEEBB4CB8EF7E155BDECF2A1D2
+:10D450009FF0E257C79EC8837CB504CC93AE7AF99F
+:10D460005F90FE55D6C8EDC0FFBDDBAD783F69F7D4
+:10D47000F64319603774CB918CE4F3ECEB5485AD33
+:10D48000867D6A6D1E276B974E8673BCDA39C3F2B0
+:10D4900038FAE28D0496D7D19CE0FB15D373C6FB16
+:10D4A000654ED6CE36DC9B586E8BADC75A402FE802
+:10D4B000E27862F45C610BF47B9A74D50FA124A925
+:10D4C000127A717FBC7C4B663AF8BB07EC97E0BEE2
+:10D4D000D50159457F109E7A7D7CA2D69B2BE179A0
+:10D4E000FAAC5C89C2D1D3FC69C91002F981F6D9C2
+:10D4F000B1F4D3DE8404E4A7729B35E6F9CDDF7284
+:10D500007EDB06F236818DE7CD8E8E7B400E2900C4
+:10D51000C714A78AF329A77E00BB276A4EAEFEDC9C
+:10D52000F622A901EB51F9427C2C22EB953C677F56
+:10D53000BDB268695EAE948B0AEB9B3E7E13A3740A
+:10D5400022C114B493244E43B27EB021DF5F928B8C
+:10D550006C802F851479241148DD8072EA20617C6B
+:10D560003AA919C2D6A11A02F1F1137C7FD62AA9D1
+:10D570000FE37D331D22EAF30BE1EDBD0437C26DED
+:10D58000956A8817ED8D591EB0C784A09F7C4BF912
+:10D59000A1AE76662E3B174E7C90EFE6260C3EB78A
+:10D5A000E7D5AFC13EA07CC6EEB1FA3E09D5D1F1B8
+:10D5B000E09831C6FF0AD87DF6E6F1FECCE940825C
+:10D5C000FB0DF79DC35FAF767F1EF8EB897F9D084B
+:10D5D000FB314E0F8980BD94E024918471704F9E81
+:10D5E00074522FBF6EC2CA23283B835EF34C317E38
+:10D5F00037F335F14A9FF7E94511DB7F6E6AFFF992
+:10D60000F9DA6BF808D8367A8FE646F1E2E073086B
+:10D610001678CF75013EC6B9BD754047A5F7C3FB67
+:10D62000001FE39CCC1F4C69247A7F2DD7C9F4D509
+:10D630000A7EFF34FD2B72EAFA231E1BC647577180
+:10D64000BCF7D5D7E226FDEADB25C06BBFFAF6783A
+:10D65000F51DB1EBBBE2C193101B9EA438FD07631F
+:10D66000D7AF7EF9BD37232ABC647A0382F3FCDC92
+:10D6700072AE13FCABC40F538B1957B0FD0013DD12
+:10D680001CC07F941F1CA374EFE1FFB275F41B1143
+:10D6900083FE24827C57CCE1A165E7600ADF8F39E5
+:10D6A000B8D337B1FDCAB977B138D18F6DA5E8EFDE
+:10D6B0001EE1F701CD6D647EF5DCA56C1F9194B180
+:10D6C000733E1EFA1F8C771B7442E97D5B83108AC0
+:10D6D00064C2BD3526FBB5EF7E9C450AD42F36C506
+:10D6E0005D347ED2CE23CDE7F67526E7CF85A4D76D
+:10D6F00005726F3EF7FE0AD76B9ADE0FAE235970A4
+:10D700006E5FB438BCB03F2AF273A6C4CDEEF323EB
+:10D71000BE61EC7E392D8F2B4B4D84F58D84F97BCA
+:10D72000BECFB2E42A7590FE9C9674CE81F783D466
+:10D73000C9DE34D083F2396AD751574D393782A8C0
+:10D74000BA7364D49E43E1963DECBE44C953444A47
+:10D75000C10EE4F7039094ABFBECAEB7281E96AC79
+:10D7600053F1DCEA4227B3337FE12ABAD33901EC23
+:10D77000CB895E76CFAD918EC19D6C7E7530BFCC6E
+:10D78000FE70D7295E2FDA9D57538B01E3385EFC7C
+:10D790007D07D1AABEA7823CFE9BCC7EAFA01F1EF8
+:10D7A00018FDCEA624E3BDEC0BDCAB3F043E5DC30D
+:10D7B000EF235C599B85CFD5B5696877D6D77AF1C9
+:10D7C000A9E1C5E66DC07BDF6CA3587F368F9FD97A
+:10D7D00015D496817C0AC9531381B22DBD8680BDB4
+:10D7E0006BEFC34F03E247E92BFBB16CF5B0DF8D64
+:10D7F000901B67219E697B524ABF2F71F91F073921
+:10D80000B1AB9719EE91B3A68D37DD3768C29BC6D1
+:10D810001FDB18FED60A8C3FCCF85B2B77AAB0AF83
+:10D82000BCF6AABE7B67107FD4BC67F8FB2DDB6714
+:10D830008B8B3F4F32DAAF0BF2EB6FAFA3AF1EE42F
+:10D84000FB8B0FD44E447CADE2F748DE5FEBC3A701
+:10D8500008F8A3F3B3660709DC8FCE7E1B823E9DDA
+:10D86000453EB87F167817F0273A193EAD6935B8AE
+:10D87000BF6673327C89CE20E24576327C894EC603
+:10D880006F0A2F4B80BF5C6C8FEF29FE0E007FD993
+:10D89000D2271BF0A5A4145C1CFE1EA3F8A370A441
+:10D8A00070F932E3214561F7536A7215CF8E7B948C
+:10D8B000CE1FD6ED0DB5049F03E3F88B235C6CDD22
+:10D8C0004CB1D4EC97011FC984AF2741929E4F58A9
+:10D8D000EA21FCA505890A6581C1411A8619EE95E0
+:10D8E000143D92E95E367503F0C1FA43B205EEA32A
+:10D8F00013975E6D380F2ACEF625A9884F3FDED3E9
+:10D90000FC60AD8AF45B0774847B40B9FF753FA768
+:10D91000E703FC1ECA555C3ED672797998CB491D47
+:10D92000BF3779CD4C9667959263E1F79545883E70
+:10D930008F29C91B260A850B6D6A159F78CF22791E
+:10D94000DF1A1A4DDB2564131FF049D2FBF786D886
+:10D950007D8D4583C10E4AD2EE5F9CA226CDC18348
+:10D96000B01189F91D5415A21FD36989754F559DB2
+:10D97000F7800DE2A1F1E049F0FA32EFA7E3253498
+:10D98000BAD07E1FE02F9AB390969D8D0918FF4B59
+:10D99000E0BFCFE2A47097EAE81DEF1EEA8DAEABC0
+:10D9A000125D949E1E80913E1F691C89BFCBF2A818
+:10D9B0005C84BFE3F2285F4FB57BCEB576DF70FDA8
+:10D9C000E8CEBBCCE0B7AE977DD8CE33C528FFEB11
+:10D9D000B9BE4D9E6EE4734DDF1EEDD3B7FE110050
+:10D9E0004FEAB9E9A8C7526E88AD77EB6405EF2D11
+:10D9F000AF1BCBE43C58ACB0FB4BFBEB018C539F13
+:10DA0000F58FD9087A54E3ABE584E99D20717871EC
+:10DA10001DE2F7DB6876F04AB80790EB57788AA3E7
+:10DA2000D8EF0FA4CE65F7F9AEE1F7583D44F98A77
+:10DA3000E0BDA75E7C5EED62FB13CB6DE3F13EB50E
+:10DA40003AA705F584F48135042687B47F9207E26E
+:10DA50000592ECEDF441BCCF2585E1DEDC3A671E92
+:10DA6000DEFB2E24E57980FE5FBA160C3F5F3E1D7B
+:10DA70009D28DE97E94929221F65E36E009E47969F
+:10DA80003D3710881B6E48A9B103DE26B9585CBF2C
+:10DA9000B1381FF148F17B9D6B60B49F41B3AFEE8D
+:10DAA000BB070BBADD10E75CF3AD2E662F91F420B7
+:10DAB00019A593F346ED774ED420C9D2C9FBF2D114
+:10DAC0008504F687FACB791C3DB699E9B115426C0D
+:10DAD0003DA6D9999A1E934DFA417BD60F9F69387E
+:10DAE000A7A5A4788177E119B478C1BE7BB1FED631
+:10DAF00024C4430DE081A45DDDE7BFFE6004D88F40
+:10DB0000F931F9CDACBF16F4ADE7BE54A0D3095935
+:10DB10001D3407F8E950ECF57CEA23973E0C7CB005
+:10DB2000E0B7A2A0DF4F293DB712D7D3927313F10C
+:10DB300059D63813F99E40145CE7871D6FBADB0D88
+:10DB4000701D6FE479004D7208F2338E37DE8DF769
+:10DB500095409EB7A8DBDF27792ADA97DA3D63C7BD
+:10DB60004377BAF5FBBB25BFB0FBC06E8DC75F2501
+:10DB70004DB1FD7A5843217E4A01CC027B98DA37B9
+:10DB8000BD11B07F365ABD41122D071FB1C7CC4F12
+:10DB90005CE29AF128E07D89CBF724C83971B27B29
+:10DBA00041E3F3391BF7186C02C37ED3E33C4F53B8
+:10DBB000F2BBF5F7BBF5DDC7C9E324C416E7BB43E9
+:10DBC000FB7D8338DFDD2C9F8378627FD7FC8484E4
+:10DBD000A89FD006F3A86A3C55FF01E289FB091C07
+:10DBE000EE133283FBC43356F63B3726BE38C1F3FF
+:10DBF0004716090CAF1A7F9FE8B377FC780F8D9911
+:10DC0000FF848D976E9844FBFDAC43C6385C25E5D8
+:10DC10001FE01B61E324CC5F171E99F430E4257DDF
+:10DC2000FEBA88DFCBCFD9F07BF7CFBC1BE6429C96
+:10DC3000E70D19EFEBFEBC6346228BF318E3D00B24
+:10DC4000DD6C9D3FC9E5BEE4DC6AE4CF3EFE68586A
+:10DC5000A8805C959C7B08ED99922D02DE13498289
+:10DC6000BDAF4E95381F4E86F6A70B9703BEA7345F
+:10DC7000E0FE46E966AB77B5D09FCE275DAAE15EB0
+:10DC8000F5D2AE35D82FA1F6548A6EBFFB04CF0370
+:10DC90002E3DC7EE07249E204903BEE77A27CABF60
+:10DCA000C67B5FBBEDB1E3ECDF707BA6E4DC648395
+:10DCB000DF109DDFF7997CF2F5BCB46B2283AB6F6C
+:10DCC0003E1B26C59A4F741E53B07D7752ECF1333C
+:10DCD000399E8FD596C1C90D52A6B07A250D772BE6
+:10DCE000A04F4A9A929205DDBC4A1B2B0C7918A5CD
+:10DCF0004DC5CA3C5DBF513A385E9B3A2A4A87CC33
+:10DD000087E42B973B61BD2F72B961BC8D8BF27F8D
+:10DD1000A2427F4CFF7C223764D4A07EB9D31DEB96
+:10DD20005C43A65B35C4954A1B397DA89D9CA7A37F
+:10DD30008F461773FB63CDA5F93F8178F263EC56EC
+:10DD400090F87AC744B7CCD8789BDC87B72CCC073F
+:10DD5000BA30DEBE63C8FBE987374E5F0D2FDA7B32
+:10DD60006A1FE502BE2643C06920F4C3E87F217C18
+:10DD700045C7E5F49F1A7B1EFEBE792C25416A3FFC
+:10DD80002CB8E03CEE2341DB79E6A1D19F5C66A094
+:10DD9000BFFFA1D157821C6AF45E70E031E4DF0559
+:10DDA000541E615FFE78C3DD86F5210A5F1CBA8FC1
+:10DDB0000A92ECFCFF7374FF440E6640DE57701D40
+:10DDC0005B474E6C7C30438FE725AEA90B812E64F8
+:10DDD000D3C08B5A3F8205DE0E15D72519E361BBF0
+:10DDE0005DFE809BBE2FE37EF58AA4C231B1D67D55
+:10DDF000EA174E81F8735DEDCC29106F93B9DD08F9
+:10DE0000BFAC05F6265C811EEB7EAD064ED7FB6BE4
+:10DE10006B307E4D6C41E2D19FF725CC2EFA86B057
+:10DE2000788BD64E91FD1E887F2AFC3CB22CF95788
+:10DE300066E6411C232527A8C3DF436E66D7AD499C
+:10DE40003BE0817C522BED1FE231B674E9AC719F4F
+:10DE5000929573844932CC474E09138C6766D3F789
+:10DE60003A7C2B2914CEF3F89B92CD8DFB451261A1
+:10DE7000769A367FFA06D7B307F8BAB41CE2B82907
+:10DE8000608759D01F5ACFE394BFAC2DE2789070D1
+:10DE90001DB326B1FA4A2283DB0E716B11D6D50869
+:10DEA000965D70C38E885793E1EF8F2611157FA77B
+:10DEB0006F0089D4E33D2653BBEE81F7BE04FF1605
+:10DEC000E0832F07777E28401CBAC87F09ACBF8D3E
+:10DED000623047A5F57F25F6E6403DF87DAFF79324
+:10DEE000D97338E42DFB75FB52EC5E4E551FD733CA
+:10DEF00097872F954CFB357FBE44FFBD39C1B70BCB
+:10DF0000E048F958C07D983A3BBBD7A7CE7573223D
+:10DF1000ACDF8739BD90FEC03F1DCC8E392BA9895F
+:10DF2000C918DFCCCA7DC530BED75096B8FFB689B8
+:10DF3000F2A3A4BB977594E4B300BF8C6EA0EFF579
+:10DF4000F48B11574B76E2F5B731F76134F8E8B846
+:10DF500004F0279E2B64EBAB890FF6080CFEA08B18
+:10DF6000FB5B2428023DE768F7054B2B5859FBBDA6
+:10DF700008A02285E3036D7F81AC6065BE4F1998D0
+:10DF8000C7F621CDF0CC697FA013E2FA73DA07CF90
+:10DF900087FDA939CE317F82E71EB9F74002D881CB
+:10DFA000770B78FEE3C7BF7B454EA0CF9DEF6CC4D7
+:10DFB000F3C6A7B9DCDD4E7AF11E763FF1F07DF2B3
+:10DFC00010BE9F073F3087E5B00C7EFADC48E8477B
+:10DFD000D7D0D26DAF84AE01B3EDF68EDEDF801AFE
+:10DFE000F0873D85B807A0B56BF3BECACAAC5D1417
+:10DFF0000F366E8FDA705ED179DB100F1FF4E58D6E
+:10E0000007911E7D78E2F72A6978E99B77E2CD5780
+:10E01000439C379E3E9BE3CCFA13DBFC607099F186
+:10E02000F4397CA276E4E76E9F3D91EAB78FDD3E3E
+:10E03000073C2B6DBD19D20894173794AB45FFF000
+:10E04000548A87D3C3FC970C047C740EB8283DFA1D
+:10E05000A19DE901929781F3D1EE7D3F78EF711791
+:10E06000D89DF53BDFCB806795D8B5F6168C6F8AC7
+:10E07000E80F9D6DBDE4BCE7C33E84B8135DFF4669
+:10E08000276A7CC8E677073F5F73476B029EAFB98C
+:10E0900063A968B8B7F98EA52CEF8E489DE36E3260
+:10E0A000D8EB2BE2F6037100733FF39716908F07BE
+:10E0B000C03EAB672AC6059E62FC357FBA4F847CA2
+:10E0C000E4C92B058CB74C3AAAB675D1F2FC5012B4
+:10E0D000FEDED1FC7B97E4C23D04D59D2CBE3748C3
+:10E0E0005C9CF333889F1C60EB389417837C3B7DEA
+:10E0F000AA5317EFEF966B72E0DEBDE06D4E1FF096
+:10E100004FF14DBE0FF0F712791C425B5777351671
+:10E11000631E6BF15C7522D0BD386CC7DF1F2CB657
+:10E1200011C941F558B1446CF01CA410C90E4F0739
+:10E13000B1C1337F39BB27BBA4F17AB40FDC138B99
+:10E1400014B8FFB6B8FDD92FA07DA914D9CFCEB58C
+:10E1500030FC14B71FFA1AF867A1AF08F30EBFB36B
+:10E160004531F87F63C3C6F2E56DC6724EC458CE22
+:10E17000ED3096B7C21D673A3BE2C05E2BAE131579
+:10E18000A7D839BD9704589B201E6C45799A56D163
+:10E190009E0FFBD1A79E7759E0FB9EBF30BFB7779C
+:10E1A000AB1DEF7BDBFF7B0771405EE10BF68DF073
+:10E1B000FD94239C0F71385A9FFDCE5651780CF870
+:10E1C0006F2F5EA6F9E9A17130AF17FFCAF2647A2A
+:10E1D000B75AF1F7534EED7EF679D8173BB575284F
+:10E1E000DA592F09410BF41B5CC5E86FE6D38A2D81
+:10E1F00046BFF89E44A66F7A0486EF4B1A8DF3BE95
+:10E2000034642CFF3C91F953F388EE7D26ECDFABB0
+:10E21000F569B0AE3E1DFBBEE1FBB95C3CF79CA2CC
+:10E22000F1ADC8EF6723AAEEFCD29EE8FEDD5D43A8
+:10E2300021AF02703122FABEC234AED67F5122DB4A
+:10E24000874FE1FB33BD6F88889F93A6DF2DECB32A
+:10E25000EB6A6B064FD7AD43258DFB538BC13F6AED
+:10E26000DA9F3A4FB7BE546E3D987A2BE62549F8AF
+:10E27000BB4C95739E7968720ABC17C3002F7C87CC
+:10E28000B85777F8376EA847EDDDF1A20EEFA58DF0
+:10E29000770F9EAE93D3BF952F3579AAE4F6C9AE1A
+:10E2A000899D8590275ED1C87EBFA922FCA31BE172
+:10E2B000F71749133B679A2F912291CA4FE5F61F32
+:10E2C000FD107E8F2BF0E4042FC043BBB809DE574E
+:10E2D000B47C8AE709569B7E47407BEEE3F4A5F5C4
+:10E2E00023165A7FF5CDCE32D04FB4DF57A07C2015
+:10E2F0006B23DE6FE23EC1E2B4F4FDFBF09328270E
+:10E300000A826FDE4A9B9E22E177AFC984791BF9AE
+:10E310008CF2AD007657EF66017FD7965A5AF937DF
+:10E320008049ED5B8679B7F4FB1DB1CE3B2F0A190E
+:10E33000FB31D3FFF79C7FE95F969E8FCCF506CC2F
+:10E340000AE2B9C4CAA554DFE9ECFCCAA30D789F60
+:10E35000A3791C0CC2E9F20D60BD5451BEEDDC6E18
+:10E3600020822D9FE7CD8E6465BCB710F895324AA8
+:10E37000C56564BA0AF8BE81CC84E74B42E42151FA
+:10E38000647A02E340DB12504F747BBA9E7902F844
+:10E39000AB652CC69F86F0F39EDD6A04EF79ECE155
+:10E3A000F1C96E0F2B97B7DB310FE6D46905F5E89D
+:10E3B000B2F04137D0A3FB79BB057E97F4D4F601C8
+:10E3C000059027D91D66F7FF9E0C0FC0DF7F8DB724
+:10E3D0006E99F581B64E1E817FC27A9AE8FB06D609
+:10E3E0005BB282E5910E1A509313EBF724B47629B1
+:10E3F0004A4D0EF829FF0BC935400200800000008D
+:10E400001F8B080000000000000BDD7D0D7854D547
+:10E4100099F0B973EFFC65669299C9249984FC4C14
+:10E42000420801024E42884851272160C054078AA1
+:10E430001A7F8AC37F80FC89B61B956E26266242AE
+:10E4400051C31A1110704051BA6A1B5CD46883CF53
+:10E450008068B1D57EB176BBFEECB223B088562081
+:10E46000A2A5B4DB96EF7DDF73EECCDC49A2747716
+:10E47000BFEEF37CE943AFE79E73CFCFFBBEE7FD72
+:10E480003F6786BE6BF5EECE67F017CC575C8C9D70
+:10E490000BB8BD1BA0BC58825757306671FA8DF679
+:10E4A00034C66CE58CF9E09FF388BC5B86FAE3B276
+:10E4B000F7FBF6B18C2D637E03C36779C0C00AE019
+:10E4C0009B4E689CC9D852858515273C17FA3E900B
+:10E4D000A6509931F87EE97629D401DF2FDB6864F4
+:10E4E000CCC4E8EF22FC5BD10BE5E25879150B199F
+:10E4F000980CFFB13DAE1DF4BF4A091F9492195B01
+:10E500006D62610BF4BBFA29ED776B5898E6D3F096
+:10E51000DC45637CFFB03EC6606ABF63EABA7C1E1E
+:10E52000FB34C65C0628C3BA87DED187100EFF21F4
+:10E53000FB695D6B5880FAB9A5B58A1D4F65ACF9CA
+:10E54000EED6CC65F03CDB7A4FE6B2A9508FF38073
+:10E55000F1AD8C7FCF605D7B00666BAA593807E612
+:10E56000B71CD69B5406E501293C19CB26164C2E28
+:10E57000E3EF53CAF87A7D71F3AB673D345EFD7605
+:10E58000ED7BF6EB548267031BA47AF6545C3DC026
+:10E59000A341C0A1E139781F078719CF4941DB6545
+:10E5A000580A75A4C3FC9A4E31B6014A4DFB2F1A86
+:10E5B00035FDB31EC6000E19498C99015F8F4AAC18
+:10E5C000AEAF84BE9B307F32B4C1BFABB1DC4EED89
+:10E5D0008E0AF83D7AC38ACC00B47BD801E52C01C1
+:10E5E000E0E930860E07A772D804E3244D8D96A982
+:10E5F000BEE23E5E9E6F2FAED992CDD8667D20D30F
+:10E600000E405C2AFBDFD401FC9E71066E40BC2CE0
+:10E61000D5F972155C2FF315F9611EAC95C3E1B104
+:10E62000B296092D25B179C5E6C7F1BB59EA0BEBC6
+:10E6300080CE82AF48DE3D1EA4DB217DC01A6BD7A1
+:10E640006C97681D2987226F8E41BCBF28B1DDD031
+:10E650006EABF4F19B63E0BBAD733DAC03CA6EC01F
+:10E66000935C86EF59A7047029DF3FFF8E3710CFE8
+:10E67000E549DE71F068DC5F29375A69FDB7FB6157
+:10E680003E1996965D3AA8CFB8BDB80CE91BD67D69
+:10E69000FB02787F97DD43E3655A39DEDDF705F34A
+:10E6A000D796E0F8FE3BDE80F18626277971FC0CD8
+:10E6B0008095CD49CF2E33B663ED12B67B3499F7F2
+:10E6C0009FA6936F9F8FE5325E76AE937CBB89F8F1
+:10E6D00036D1BA338CAC06E789EF4325B4657CFBB1
+:10E6E000A83EC4F13BABA514FBCB18CB9F2E4338FF
+:10E6F0001BFB795BC5F740A68EA5E37CE1BF613EBD
+:10E7000077EDABCC70C2F76F7F6E527429F0743323
+:10E710003688ED94B095E1B3B098B73789F6A5B3D4
+:10E72000327033B872B5EDCEEA7D2953012EC17730
+:10E730006586F8F8CAEA4B7140BB6F19F83A12F1D6
+:10E74000B813F103EB69BE00334F8DC35BDD790372
+:10E75000F6D77C4161A1A9B1F79FB79958A828566F
+:10E760006EA83F3407DB35B2C1F548578D7D1616CC
+:10E770008AA3F76F258D3CAE4ADFCD17742C984ADB
+:10E78000E49BEDB7217C86D62FC7F91F90D81E8653
+:10E79000F506168C1BBFF982535B8ECE339DFA892A
+:10E7A000B563DA76FDBFA7766C7A2419C739638F13
+:10E7B000243BC5FAF0BB2C99B5205ECE8674413D52
+:10E7C000ECE3331E5E7F96B19A3E6BACBDDADF9907
+:10E7D0003A030B13DC87A85F844B1078DBB6812FDC
+:10E7E0000C1E28370C1C24B8A8F4100F9F601CDFE7
+:10E7F00048EF180CEB604FFFDABEAAABC40CA83888
+:10E80000A4EEDF355DBE99502FEB34FBD9521EDDEF
+:10E81000DFC4561ED5C9821F347455CF8C2FF3F632
+:10E82000B1EF1B6BAA61FF9797F0EF8FDA9B8EDC3D
+:10E83000A7C4F811AC2317E1122D9B12CA56284F1A
+:10E840008E2BDB13EA5D09F5EE8472366FFFB92D6E
+:10E850009C2B7B19FBD4BEB64601FEF279667891FB
+:10E8600004E58D1D77D554039F6B2C1FF4C9C83F59
+:10E870000724AFC462F06BF2325F08E067F5460C24
+:10E880004B4B100E836FE2FE6FE897EC12D0B9B5D8
+:10E890006F5F98CAF89D27EEBB3E89BE6BE8FB9878
+:10E8A000BE1BB5FF621DEDE30DC5C7A81D00C07EF0
+:10E8B00002F0741393580A80345F09FC11F9646301
+:10E8C000DF275CEEB221035F1FE78367327DAF1362
+:10E8D0001F3C20D971DF45E90EFBB5C6E85D6DFF31
+:10E8E000D1E4817FC66E2C777DD1AE40FB7F6BFC7F
+:10E8F000641A03547D844DAE40BE1A9A80F2781B90
+:10E900000B4C4039F4DDC6710775D0EEA83EB283DA
+:10E9100001BC8A1D1B6A146877D416C99180874C84
+:10E92000DCD4CBCB69911D08CFE0A64709BE477365
+:10E9300022393A284F718479795C6407966FDCF448
+:10E940002C2F4F8EE4C8F07D41F0B99A6A28EFB1C0
+:10E950008FBC5FF31C9C8FABF33B31D697E54843EC
+:10E96000B2E37262871E2006FC70D1EACF9EDF03FD
+:10E970007058748F85F8D49ECFBF33CF4FEB0FFA0A
+:10E98000950AE0879CF4B91C237EAC901E9089B256
+:10E99000CB19C3872D77D0437C7E62CB3E94F71989
+:10E9A0008B4A88CF5F48F1B53BA6C59EBF4BE7CFEA
+:10E9B00076879DF36559E7A3F6F7DA48EF79D8CC67
+:10E9C000D703FB86F06B15F82817EB2977E8E89951
+:10E9D0006B9F4DFD7C28F9B69A647CB2A019F1B901
+:10E9E0002A89F48C5B77015F00BEDC2BE6DDBB6916
+:10E9F000422808FDDF2A313FF28D5E872F13F9C3CD
+:10EA00004B7F916FC7F5F69642199E3F15FCBE7776
+:10EA1000BE2FD31127177B77F17A95EFF4E6F3EF4A
+:10EA2000557993D1C1C7C97878C26E5C8745613E7C
+:10EA30002C2FAF2BDADD4E727B01CD97F97C99122A
+:10EA4000ACF7C4AA021DEA912A7E9442DF75587F72
+:10EA50000BF66F8DE1491DBF1DD79D867A00C87DDD
+:10EA6000586F9B33D08EF8043D600AE981420F68ED
+:10EA7000C7F5C6C197299169F8FEFF2338DD89EBF8
+:10EA8000FEEFC269047E11C4711B5B815FE8E2F88E
+:10EA90008580DF6629ACCFE0FCC28B720EDF2F00D1
+:10EAA000FE788B3DF000F6AF8EBFE8DE46D2FBD499
+:10EAB0007959FEEEE59A9BD8F07D96A8971DFDD07A
+:10EAC000B491811C3B6AE823BE78741EF3B623FF21
+:10EAD000D0B17A84A3AA5756DCB3E66D06FAEC9758
+:10EAE0000E99F0DC2DF932715DDD805713CAE1F922
+:10EAF00086D09EFC985CEC7584B6AE40BCDE50E2DD
+:10EB00000D7A483ED27E0BB65AA85DAF23C214AC34
+:10EB1000BFC2638799209E091F43371B42BB25C490
+:10EB200037A797DE5513434189F01EA4EF6FE6F433
+:10EB3000D33B9F917EDF7BB39BE8C6CC42669CCFE4
+:10EB4000687490DEC1888E98E29B32DF1683C32FF3
+:10EB5000C5BEB694475EFC17D423379A498F4499B3
+:10EB6000897617EBC9A0F9023E5F22FA50EDA5475E
+:10EB700032431BC83EF356203E1EB0F916D3FC7F2D
+:10EB800060F1E0FCB79B5997A90CCD0FD649FC4E1C
+:10EB9000CC87F53CC6503FBB5DE867FF5E7FCE8605
+:10EBA0007AC01B0EAE5F21A19880FF2D61BC7EC98B
+:10EBB0003ACBC768CF2C5927878D60AFB0AED9BE8E
+:10EBC000489C9D411405FD0504BF645B866C483775
+:10EBD00001FC2E19FBFFA3CD63C5327C3F05D10E8E
+:10EBE000DF17C7BE7F5FECDB45329F3F6BB378100A
+:10EBF000BE897CFD7D757E3D8FF9E2C753C749EC28
+:10EC000017ECB80F903E01EEE114D4E77F20135EBD
+:10EC100013E7EB320C3D6886FA456DB2E33E806740
+:10EC2000A0D546EB55E77B7BC6D095645F25F47F86
+:10EC3000D2D254A1E0FA85FDC1D669ED2FC60CB140
+:10EC400032D0C572364476CCB0F7C26E4DB4FB18E4
+:10EC5000FB8B31BE9DBA5F98474A98BFA02B8FA40B
+:10EC600020DE0212C79BC130B408F94EE2BC5578D1
+:10EC70001A9D3A01774E1789F0363AB9DC4984B7C4
+:10EC8000CB10C9C17E03AD46825362FFAA5C7CCC27
+:10EC90000CFB07E86E8B2411BD6EB9DB42728E99B6
+:10ECA000389E9B572779907EB719869EA67DF5AA38
+:10ECB0009121DECF9A875E227E55C8FD0A677F29A3
+:10ECC000EFC27667D238DD9F79454FFB8D4F06F452
+:10ECD000A15FCABBA95EE2FD9E69B77870BF36230B
+:10ECE000A461FCE6E07FB63180EF711DB7939BFB1A
+:10ECF000B5F6F019F8575F16E31B67191F27D8CF31
+:10ED0000F904AC74158D736B12DB00FD36E9241F1A
+:10ED1000EA4F4DAB27863A383D99703F3588293503
+:10ED2000E9C02E2C8BEDFF26DDB122B4AB1A4C1BB3
+:10ED300007E564AA3F8CF618437B0ABE5B8D1FE58E
+:10ED40000F877FD3C6DFFE19E7DDB45F4B170D31A8
+:10ED5000FA912E4AF87D1C3DE5C7E884F46FE41F64
+:10ED6000D52C344EE27E1A2C5B6A0643E8A769165E
+:10ED7000FE8BB4439139483FB6F23EB6049ECDA710
+:10ED8000B8FE316360D7EB68073B6A06737099CDB4
+:10ED9000AD6BA79E981AC3AF3ACF2B0636C968DF72
+:10EDA000A97A4B9C7D3961C1E4F8E77DF41DDAABAB
+:10EDB000385E045FE1BE51B8BCDB2CE41DC845E2FF
+:10EDC000CBCB7BC6935C44B985FC4DB57791DF21F5
+:10EDD0007F79C659759B13D6E94DADBAC9398D8F68
+:10EDE000437A3E1A49570C8767A2DC51DBA1DDDB71
+:10EDF000621DBD5DD40FB43585F30F45A2F28A5F65
+:10EE0000E8776DA0F929442F6B77E4133F56FD3561
+:10EE10000DC24FB542F8775608FFCECA2D46E68997
+:10EE2000F76785B4E506C10F1A5984FBB9F6427D30
+:10EE3000BC5FA79A856D588FFE1D7CF669BF6F6613
+:10EE4000A1590AE2B7FFA231FE3DEBE5EBBD5DE063
+:10EE50007DAB99FB7566ACDB257367155F6F4A99CF
+:10EE60002FFF7E94236FE9C9FFF01F024F2A5C2C0D
+:10EE7000CEAAC508EF24B4D7B0DDFD4682CB0990F9
+:10EE8000D7FB84DF6301DAA16D81CCC242048F3DE0
+:10EE900077816D387C37BC6AAE477AE97172BD45BF
+:10EEA0007D3FC7A9A732F98310EEED16D2BB01CC86
+:10EEB00053908E2A0A5439CAA6A01FEA633DE8631C
+:10EEC000506EBAD11AC0FE22A837407987E05F3B66
+:10EED0009C06EA4F2D47ED3C412F300EF5877E19F9
+:10EEE0007F1C1D3C156DBF49E8939C2F6C5E9544BB
+:10EEF000FC2846B73A46745BE237A03FE955C14764
+:10EF00005E0580929DD567E67C44E1FCE9D553130C
+:10EF100089EF1DF96C35F195737549CC28517B9FAC
+:10EF200084F52F1A43F7417999F0B3BE2A713D3128
+:10EF300078C046FD3418025BD1EFD0F0C2382F60A4
+:10EF40008CBD6408FDE869AC7FCD4C7EAD86643E27
+:10EF5000CF8657C7109FFCA93EF4EC8FC94F6124A0
+:10EF6000FDAD21C99342F53F4F6558DF65098471B6
+:10EF70001F6519B95ED960081739008EC7425C3F1A
+:10EF80003E868C06FB1FB091DE03D3CCC4F18F7795
+:10EF900067783778627039FEE024A2FFCD7A8EB7A9
+:10EFA000E02BDCEF794CEF9F9309E5632F967AC154
+:10EFB000B26467FD86B001E6D8FC30D7E796EA3C3C
+:10EFC0003B5B9137BD66F16AECD18756D6627DF323
+:10EFD000EA75D7211F1C6D3F233F8FF7E79E6143E2
+:10EFE000B9648FD617F48561DC330313BC243E99D2
+:10EFF0001B900D7462E76D4FE801DE485F07F44433
+:10F00000BF97DA3FAE17ED43942F384E33F0DFA8A9
+:10F010009F99F86F5C591EA9CCF1D9FC6A86D0DFA4
+:10F02000B4F5B7A604CEE1FE6AFA87DF1F6D25F8B6
+:10F030000E11FF633DDC7F7E42EF5B8474EAA80E15
+:10F040001B96C4C9EDA4542ECF971A859EC7C286BD
+:10F05000F87DA7D6575469E95C7D9A5339BDDB0624
+:10F06000391F1F5EAF13FBE13B46945BDCB503F633
+:10F07000F629EEEF484AF550FD8C5361C35228E75C
+:10F08000AD0B1B568827EE0B8077D804EB3EB1D52D
+:10F09000C6F7338001FB59319D91BEB242063DB5A2
+:10F0A0000CDF7BFA238097932F3A387DFD09A0026D
+:10F0B000F05ECC443B23E8B5C0B75EEE94C2A8F73F
+:10F0C0002FDE62DC6DCEC77DEC936D88CF1D12F113
+:10F0D000ADC59D95455BA1BC7AFF64C27FF2744EBD
+:10F0E00097AB430E927F33041F5C6A0C1948CF7EA6
+:10F0F00096FBF1A07FD2971BE0A3CCB2E17040FE5B
+:10F10000ADA18790360E31A34FF0D3BD71F1878248
+:10F1100038BEDE97F03DE8795AFA08AA7287F339CB
+:10F12000E6C9403EA7F2618BD33F2D95F050988100
+:10F13000F8057C723EB94F22B836B2162E3704BF9E
+:10F140008F8E2BE4C54939C8E59271133DE7A5E6DA
+:10F1500013DE56A3BC21BF3AB7FF46A38379A93A71
+:10F1600061278C4C07D70A3A6838C5C257C2780D58
+:10F17000EB58B8710A7FDAA6901CE4F2D024E21DA5
+:10F18000261E0FF926B998280787C9BD047997610B
+:10F1900010F24DE039DEDF8DF27EC6BA908C7ECF64
+:10F1A0005CBBAF32635A4C7F697EDF64F25C86657C
+:10F1B0003F2BB0A2FFA6F25937FA7FC15EC77D652B
+:10F1C00001B8EC42F9A2EAB76EBE5EB781D3AF5E7A
+:10F1D000F1B3522BE26590ECD9A13466477A54E141
+:10F1E000B9C306DF95E1777CBF45BF37B1CEA4B880
+:10F1F000EFAB5E35135F3DFF8A2D6424BD2390E79E
+:10F2000080FED23F32921E7AE6551BC9CF3342FEB2
+:10F21000B954BF005B4FF85927F01A645563D0BF4B
+:10F22000CAA479639005AA7A58A363347FB7A8CF9C
+:10F230001FBC91D39591ECC9F38EC8F7B10CF36163
+:10F24000A85FDF25F0DCBC7F56E9BDF0BED96FF5C5
+:10F2500072E8074A915E8DF25D37A2DF658EBC6E63
+:10F26000E86E5847638ED56E844FAAF3FEF53737A4
+:10F2700043F9D3FD7A66443CEF9955C70A46E7BF88
+:10F28000AB42FA6391B8FDB266AFB6DCD8A72D37B2
+:10F2900033E558248E1F3F9E6A739D9C44BCC37BFC
+:10F2A00011E8DB686C39B50BE66BFCA991E4514BB6
+:10F2B0006A20949A867AF9D09B086763DEE753D078
+:10F2C0008F5195F7278AFB9CFF01F3E2BCCF9B2B64
+:10F2D000497E9FDF6AF604E3F857B3A0FFDEDC5AED
+:10F2E000AAEFDD66F448BCBE765A05EA833436FEE2
+:10F2F000997400FFE62D733F25BB09B57628F7A268
+:10F300007E89DFBD2085DA517FDCC2E5DE69D01F52
+:10F310004D309F9308678C7BC803734CF09FBDCE24
+:10F320009A09C85F943F2B7EC4FF03D8559CBE7BCF
+:10F3300020CAA7B99FE75AF4F38C253FCF01E41BFD
+:10F340008DA688A112FAB9FACF5F115F5ED9BA848F
+:10F35000F4FA989E6B243EB2F2EE00BD7F7DEB3551
+:10F36000B4AE93B06E84CFC91DDC9E5B996D0DE188
+:10F37000FCAE7670FD77257C2749C3E19208874F64
+:10F38000B65FE3467C7FC2F878C13EAE277C621F41
+:10F390004C26FEE36949463DAF79CB359F22DF5AC3
+:10F3A000B943F6A21C67076CE41759B963F684E504
+:10F3B00056ECE7CBD44A84DBCED97699DECBFE106F
+:10F3C000F7AF0C5E0DEF959D977B709F1CDE61E49F
+:10F3D000F373989EC6F95FFD6799E85ED1B100EAC4
+:10F3E000ABBD06DF04DC6F9EED7BE6205C3F999FA2
+:10F3F000A5A3F6CF4BCC8E7070B4A6E3FB9592E23A
+:10F40000C7FD55BF65556DBC3ED2952A137E2AF3C4
+:10F41000D6A547AC44EF37A29C6BDCA127BDEEF02C
+:10F42000820F7F73B32B46EF2BE59E1B67C4E91B4E
+:10F43000CDDBBF2DE8012436C069A58093316F5D17
+:10F44000118EFB4DF4BFF2BE96221EAFF9FA7D106D
+:10F45000DDDFDBF97EF833C8FB8BE8EFCB766AF4AF
+:10F46000FBD1EC20D51F6DF232DF1E2BC5157D6858
+:10F47000E716B814AA2F400202FA52FEB076EF3B0C
+:10F4800030FFFDA9018B0BCA79CC578A78F50CD9CE
+:10F49000AB409DC42591FEC3B61BB93EA970BFDC2D
+:10F4A000E634F6F486B879E68AFE607FBAB09F3318
+:10F4B0001FFCE94D845F53EEE75378BCED2B8A5F68
+:10F4C0005907785CD3EAF533A48BE681F96C594986
+:10F4D0008C1F367B39BF1EC6575C7ACEBF5C43D4C7
+:10F4E0004F4D1AE767AA3F785B6B12F9FDB6B94238
+:10F4F000666EDF0619F2F3EBCA651E8F117A895F1B
+:10F50000F8D14CBED719C66B9857F68E83F2A0EF90
+:10F5100078672A94DF299FED95A16CF53DD9558038
+:10F52000EBF6EA45FD58F227BE3DB392F493EB7C2F
+:10F53000328DCBEA93C95E1FF4BDE75A06E35ECF76
+:10F540007CA927608C1A10D688C7411C1BF0655413
+:10F5500002D35D7176D3B7BD73534FC4CB4B1F97A6
+:10F56000FF688FF789B8C24870F0A6565E85F0BD77
+:10F57000FA2A8E87CF9EE7F6C76766EEE756DB7DF1
+:10F5800066E372C6EF52FD847DB9C8E7A3E5DB8A66
+:10F5900035716297A12F17F7D96F256D3FABBB74FB
+:10F5A00014BF5DD5C5285EFBD98F5ECE457EFBE9D5
+:10F5B0009E977397C4CD2FF13BF5798B3A9EF04B14
+:10F5C000A97E4A97885B2FF11AB93F70143FA5DADC
+:10F5D0009E6DE1F6D859E0EE4877EA7767EB937CC9
+:10F5E000A8579E6526E2674B0684DFD3E72B74A1FC
+:10F5F000FDA07E9FD0FF23827EA47E89EC734BC941
+:10F6000010F1D75526FF9B633C98B7E223FCCC450D
+:10F610003C4A48AF3E03AE5B11769E51F1DF8178E4
+:10F6200058DEA3C5638E4BC433EC2EC2BBA1C9AA5E
+:10F63000A07C48EF10FCFA7B3AB25F0C596E2BF2BB
+:10F64000A5AB8B923A312EEF4A4A9E827EF59CAC56
+:10F65000626A1FACE2741D4C67E4B7CA642D12F1F4
+:10F660005B3BF783674F6776CC03F9A98BEB0D6E95
+:10F67000E6DD22933ED827513C40AC5FE5EB482FB6
+:10F68000C8E73E934C442FD28044FA9DACEB5B8498
+:10F69000FD8E463F5B5CAA5DCDE9275AFE1BD1CFAC
+:10F6A0006E75BC61F413A038DE12B76964FA117E7E
+:10F6B000D74B6E3F5A1CF17B26D50F2DE17A6B4557
+:10F6C0007FB5266B589E42FCE1F3787FEA76D03313
+:10F6D000D11E51E38E633A167BB89E3E1841BBDCC7
+:10F6E00072B989E4DC0F7583F9A8CF27C62101B36D
+:10F6F0000EE4F7C863C8AFD85AE53F911A27EF0F59
+:10F7000070BBA1E96E1FBD9F35C0E57B73A181F47D
+:10F71000CEE67E2988786EF21B42A67C8ABB2C2618
+:10F72000B9FDA0D9C3E3289E768AA3FCC0C3E32C0D
+:10F73000513F6A64E7BD486FF556F23B24C6635EED
+:10F74000FA8BCCC71FC768FCDE521EFFE99DEB2178
+:10F75000BF46629C8D7569F7AF1A67396B03C0C0ED
+:10F76000784B369A090F593287334B3171F9329CF5
+:10F770000F90BF367DBA408C888744F73590249629
+:10F78000B344BD1ABFB195F8F351C35D94BAFFAD50
+:10F79000A4697F4DBEC33D3FC47C8651F31D82C624
+:10F7A0005AAC37A1F62CEA71DA206FD5B2CFECC192
+:10F7B000F84EAC5E01BDD1D42F89F15EBE7636889D
+:10F7C000E0B3923A7EE7069F95E2C99AF1E2E7A795
+:10F7D00024F4AF87FEAD1ED13EF8E3B9B30B296E1A
+:10F7E00029EAA50D3E98DFC37A6D7F0452F13D16DC
+:10F7F000D4F10E67D4FC70E3CC98DC073DC09A3698
+:10F800002D26FF1FF8B0B6E73218CB62FFD2807208
+:10F810005595E3CD2E9EFF90B85FD3D338BF07FD3B
+:10F82000353D8DE40ED76B6B45FC12F4D939B8B574
+:10F830009AD7F919C62F415FC84A237DE1F3930790
+:10F84000117F0B3E237DBEF982C2FD2EA077A07EE4
+:10F850006E1274CEFAF5246F553A582DF84FAF0357
+:10F86000E43DD2EB01695A90E8A225F706C0C1DF5A
+:10F87000A7F90A711EAADD9538DF2BD3B87DDC5CB1
+:10F880005CB5B508FB7F4A6228EF37141F4B47BDB4
+:10F89000A479E0E3F4E571DFADEA7F94E0B06AAF0C
+:10F8A0007EC4F55F99C6E39D4DAFBC48FEC1CF4213
+:10F8B00012EDE57A25D43D03CAF5F53AD4D058794E
+:10F8C00068F1CDE4EFAF33B071B0BEB1288F701ED8
+:10F8D0007BBF139C81F619FC93E0D536FF0A927B1F
+:10F8E000DBEA4C568C3B34172FB983E0604FF22192
+:10F8F0001C36145765E2384DF3E7D8294E00FA1547
+:10F90000D637DD7D0BF94DD4796DE8D7D7A0DE551C
+:10F91000017AD63FC1BC739CF36ABCB0FFC6C8FB7A
+:10F920004AEFB462DC7864FEFB5E3AC767A7E40F77
+:10F930005E5F4E7E4216EFF7CBEBE7FADC0D690611
+:10F940008D5FF8863485E0303338380B69EF352524
+:10F950006241BDB799F9BE40FB92F9AD9E3D842747
+:10F96000CE475C6D1EF21F995C911F5E86F53315C4
+:10F97000B21F98127904C73DD3EDF26E60827EB15A
+:10F980007C774908F9E8EB69812588DF0AA13F9E69
+:10F9900079E59A52F4B3A9FA51F72E7308E384DD9E
+:10F9A00036CF3FD4201FFC83C2E3E2A6A1C1598811
+:10F9B0008F3F3AA9DF6E73A81BF11FDCA4A7FA578B
+:10F9C0006C8146A4CB53F36B8A282FC71A2CC238FC
+:10F9D000B0DED5C3504F007381FC0926979F61BCF0
+:10F9E000745670B122219F4FD03B6689FC52629EB3
+:10F9F000F0BE4AB0B1714005274DB4053A2FA6C6F6
+:10FA0000F490237F5AA8E04B553FD199783CABBA8C
+:10FA10002E89C948F7EB87DED4A1FFDA3548FA6BA7
+:10FA2000639F44E33416BF40F9626B445E52343F37
+:10FA3000488950BED4FA348BD0033BB91ECD06C9D9
+:10FA40005E66CF717C3216A13CAA981DD14EEDD4D2
+:10FA5000FE0CC2EFDE28FC2E20C1A87E539AAA5FBE
+:10FA6000DEA7F5D78B71374B833E19E15A2A69FC23
+:10FA7000C5EA73AFF83EE5D0D01CDCBF43AFA87930
+:10FA80009C3C4F73EBB4895E549D86E571F67F31E3
+:10FA900007E906146DDAAF4DFD9796C7F9BCD86734
+:10FAA000FFE3799C5EC9B71B9E2FA739B4799C5E92
+:10FAB0000E3F35CE9698BF792633ACF07CACC8CEDD
+:10FAC0003D489FFD46CAF3AAEDFFD9FB281F6B4DA9
+:10FAD000AC0FE390897A469BFD3B61A4FBB3A74F33
+:10FAE000EEBC9F611EEF4B5ECAE748D01F12ED844B
+:10FAF000DDD82473747DEF37517C727D2F5AFE1F41
+:10FB0000D7F7B83E1FDCC3F307547EDE2CECB3B34B
+:10FB1000F5E79251CE1C4B53F5CF843C87A7449E0A
+:10FB2000C3C0C8790E8AC817027D3D4874B28FC71A
+:10FB3000758E3C6D21FE71CEAEEC467DE9B46DE86C
+:10FB4000FB082C45E8499D078C1EE417C0EF887F11
+:10FB500007F7E9799C06E33618C7796D8288E38850
+:10FB600078D1AB16D25B1A923D29F8BD1AA7F9A934
+:10FB700090370D493C3ED36509FC3E6D84B8CD2ECF
+:10FB8000A17FED82AEECD8DFFB4611C7060681F6F9
+:10FB9000CE83393CEE20E2366745DCE678B12E6C48
+:10FBA000E07E08F25379BA149609F59EF7CD210F3D
+:10FBB000F767997420F797AA719BD7B89F6AA988AD
+:10FBC000CF1C5F3087F28796637EBC8C7E0CEE671D
+:10FBD0008EE6EB33BB0ED7B306D8C5366431418011
+:10FBE000FAE5F05AD249A84F783AA14CCAB2AFA769
+:10FBF00006C65DD2A9237B646997D65F7E7EC31D4E
+:10FC00003528BF1FE8E4F1C7609744F27B29F3B9B8
+:10FC100051DF50E9615C7A2AD159B053E7C371AE24
+:10FC20004CE7FE04007D88D6279E9D7AE16717F396
+:10FC30006867BA303E75127F3E60576A4694CBA221
+:10FC4000BF4E7D8BA912F5D81C1DF979CF1B7C7591
+:10FC5000E427751611DE3A6D2D5D35BC9EF6CA7926
+:10FC6000F3909FEAAF54B8A2C73C4EE49363D245E9
+:10FC7000FC2661BDCB7BB4E5C4F8C3AA90B6BC94A6
+:10FC800005C667E23985BDDAF763D239FF3FBF2188
+:10FC90005FF8F9BDE4E7EFD47B7E958F7CAA5B210A
+:10FCA0003ED99ECDE1A5CBE1CF0247751DE9070EF8
+:10FCB000D02B68BE7CFE0557BA2494979D0E4E97B4
+:10FCC000FFDD7927CE77767A11D71350B9C37DD46B
+:10FCD0002D8538BCF8BC2FD55FB1225D6B6F46CB4C
+:10FCE000FFF3F626A7C76E59EC373BF19F2522DEBE
+:10FCF000785CF23E1DC6F756D00B60DE4BBBE5329A
+:10FD0000D44F667DC74AEB687ACD1C32427DE3BA98
+:10FD1000482EEEA3A6AA4851CB0870C5D92A2ADFDF
+:10FD200082764B5C601FE0BEEDD2C6A186C7157D12
+:10FD3000F7A6A7A11D727CDFCF10DFFBCC2497E0D4
+:10FD4000BF0E1AD1DFF14A3EE94B5352021DE9289A
+:10FD5000CF93C23B9FC947FD84EB478D03C65DA887
+:10FD6000FF2DE9D49EAB611BB5712ED6E5247F062D
+:10FD7000EBD5BEC7F32B9AEF86C5BDB89CDF6C08E8
+:10FD80004C40BDEEEAAB787CFDF42A1D43FC2E9579
+:10FD9000BD2B908F9C366BF5EED3368EAFDDE9AA86
+:10FDA0009CF116219EA3E56178F616219E97EA58EC
+:10FDB00020BE9F46C4F354CC4EE7783EFDE2E545B5
+:10FDC00088E7CFF75D5E8478DEACEFF1E1BE79C6FF
+:10FDD00019781AE17362B69FF42635AFF252E9B191
+:10FDE0003F811EFBFFDFD1635D7CBE5FA21C3C1C1C
+:10FDF0008597560EBA0C9E6CE4874B4CC6AF958720
+:10FE0000F837A23FCD64247FC46B7FFAF221946F50
+:10FE1000C10199F40FB5BFD794C058F417BCF6BE12
+:10FE2000DB1B9446EFBF45E8556E130BA2DF43D5AD
+:10FE3000F755BD31911FBF2FE0782ADD578B7AB679
+:10FE4000EA9FAD177D9A425F72FDF42989FCAF26C7
+:10FE50004F1FCFAF3FB0D88EFED95321EE8F6D7AB2
+:10FE6000B194FCB5AB42AF8731FF890D4876B41B26
+:10FE7000563DF57132C6B3C10EFD243D2EBE325B38
+:10FE8000D8A1A742C79331EE0DE3D7A05CB6B886E0
+:10FE90000C48BF4D609F4113D6A40CD1B9A22617C0
+:10FEA00023795FDEAFB5D7D4F8E436BF81F8DDB68D
+:10FEB000012984F659BA21909F8DF28965DB4F5A4A
+:10FEC00062FBE577E93E17C62D637161DFEF715E76
+:10FED000AA5F27B23585E830A2673ED203B6DA04BE
+:10FEE0005FE2F19ADF6D778478FE126FFFBB503EC0
+:10FEF000955579BD429CD35B21CEE921FF0E27F0B9
+:10FF0000EFF87234DEAC9E47037E1E1E29FE1D975D
+:10FF1000B714FF7D131B12F979178D9A7EA3F93A56
+:10FF20002DA51E98F79ADBAC740EB119E8BAB52C62
+:10FF300046870D62292A1D3609BF6E73FD31B20353
+:10FF40009AF1FC05EA555E4E870D601F617E67E2FF
+:10FF5000BE657DDA7CC6D1F6716986761F47CB7F98
+:10FF6000233FE6CC0CEDFE55D7AFFAC1A3EB1C90B6
+:10FF7000F8FE4A5857A25D99E8BF56EDC24BE56BB3
+:10FF8000DF89CE87C3235AFE1BF3B5DB3346E36B11
+:10FF9000DAF8C05FCDD712E30485DCFF8D71028CE7
+:10FFA000DBFE77E3049F7A7AD2753C4F5F133FED17
+:10FFB000925AAE338DC5B8228F2F37DA8C14874D05
+:10FFC0008CAB367BE68838E2E06FAE40B9B95FCFE4
+:10FFD000509ED75B5752BCB2597ECE80470E87C524
+:10FFE000139583A4B7FFB571F5F5193617F1230FF3
+:10FFF000CBC7B87A625ED1EBD62F530371F8AD2A26
+:020000022000DC
+:1000000001857F043A362941167F5EAD3783EBC107
+:10001000AF8BFC17B781E7B13F6C033B0BD6E7D63C
+:10002000F1FC9CBF4FF36FCE48433ECEE1F7C42BAB
+:1000300037313C77F484BE8FF844B0D1EA457EA7CF
+:10004000FA55A2E309FBF352E9FAC709FBFCC77FA3
+:10005000E37DDEAFD2F35F1BEFDA026BD5D03FA3B7
+:10006000B8D6DB18AFC91F4EA7A3F5331ABDFE22C1
+:10007000C3FF6606ED33DF14CABBBD447E62291F91
+:100080003A8EFE1BB6DFE8417BC224CE65B08D9967
+:10009000224FD25B319FF285F9B906F5FCC7687A29
+:1000A000DFC7D1FDCEF5BE8F47E53BFF35BDAFCDF8
+:1000B000E93F8E72F644A5AF08E5E20336983FDAD1
+:1000C000733F328E78CE423D0F00F4C4CF9B3CCFBD
+:1000D000E3DC8974F587047EF987FF257EA977FF25
+:1000E0008DF865FD1F93D1AF397A3F419EF75B359F
+:1000F000E8137129867121751DCD833CBF2C5DE409
+:100100004DA9EFBF127AECED6E5F861B9E9F7F605C
+:1001100032B114507190C650DFF25BC9DFDFD4C733
+:10012000F3409AD6318AEBAAE7289BFAE733D4EB5F
+:10013000F6A706F2F1FB073EB406E514F4832F6040
+:10014000A8CF9DF980975B5203E3B0BE795D44135D
+:1001500057A8B8F8E57AF457C07CC9FE7719B5E717
+:1001600029E6BB393F539FD7097847D7E5E2F364C7
+:100170007D7208F5408B6790FC444DFBB9725621A7
+:10018000FBC81FCFD638E97C44D3FECA523A6FDE93
+:10019000672E453DB6E2A35A3BFA1F3EBFD24579D2
+:1001A00004B9726415EA51AFA70566E27C6DE5A15A
+:1001B000B9A887E6811E8A7AEDE7FBE69606E2FC9F
+:1001C000D99BD19F0DFD6EB669FDD5CCC4F3C0EBB4
+:1001D00077F33CDF576C8139D8DF66339F6F7093BC
+:1001E000C86B167EECC4FDAFEEFBE839C75B4D145F
+:1001F0007756F9C2663D0BA05C53F94989C8830361
+:1002000078F03CBC81F93C9F4394AD2E6D3EE2A951
+:10021000F4D925389F12378F0B2C370D49E8575FDB
+:100220002EE2ECD7887C09353FCAA8F8BF8BEDD900
+:10023000BA9A587CBD00BFB78B73BF3C0FC67281A2
+:10024000EBC7057603D18D0DF617F93F806E103F91
+:1002500033870667E179A2C2DEF04C84E76B17743E
+:10026000040F65FEDB141F4941B4413F633746BAB2
+:10027000C7A39FC4FEEB2B112F9E1E7B15826E7FA2
+:10028000AABFD14DFEEC9662B41BABFE59CFF3FC76
+:100290000E58C8FEEFCD6DA03CBF331F1A473C1768
+:1002A000A23E83EC3ECAEB2BE87F8FFCF4B6FDD276
+:1002B00088F99A5D6E2B8F1F0507297F8CCD74F10D
+:1002C000F384073EA2B8AED2AD9087A253EFD3E13C
+:1002D00039A8603B23FFE4B85EBB0EF19227F247DA
+:1002E000CEBEF69F53026487A87EF910CFF7D147A0
+:1002F000D6A35DA5B447AE821DCC1AF73B744D253D
+:10030000D8DF5013CF5BB730A493BCFEB1F77D0BA1
+:10031000CA795D762621FF79754D1EF943619DE30B
+:100320004658E71D6E9E9FA31CB0E8506E299B188F
+:10033000E5172A8EF42A9AF7A350867ED608BA517A
+:10034000E38D305D37CAA3DBDD811D88EFE8399886
+:10035000D6247E0E469CBBB4B57EF83C9E2FD96950
+:10036000E0E70C0FBD366901F9E5BA1509F170DE59
+:10037000B138CF0EEFF78A7D6B530699DD1A0FFF68
+:1003800043944F597080E79D297A4E274AB76B17DF
+:10039000FAFD2EA404286FF4CACEB04CF12AFB89D2
+:1003A000476A3C7176CB162E479AF6727B39D14E4E
+:1003B000F926F971D0ADD54BA2E5BF915EF27682F8
+:1003C000DCF8ABED0FA6B5DB12F593443B6D985E00
+:1003D0009DD0DF687A8A9AB751151B87E8E1759B33
+:1003E000AA070535792D555671AECDA4ED7FAF8B9B
+:1003F000F30935CF25BDC3D38E79E3433F60E4478E
+:1004000053F36D8255DC2E08EA4C74DECDCD7A288C
+:10041000CF660C0B4B12E9F7113AD79981F936F0F8
+:10042000DD07EE027E3E8579BB64E2871E09E76D3B
+:10043000C63C0DCACB0C6D5D81E3DC60A571CC9828
+:10044000A7311543EDBEADC83F67D5F3384316C895
+:100450005BA4DBAC424E87E63A9EAFA1E663A8F907
+:10046000132A1CAA047CB3C6AFC847FDBF5B0AFCB5
+:10047000483D4F1B7F4E3A7A3E7A55019D27899E13
+:100480008F2B64A2FED2CE4927C253CDDFA8B2077C
+:10049000EC9969C3CFCBAAF41187379AD7B6035C1E
+:1004A0005FAFAA37D0FCCFAE9A477EC2B3AB740C15
+:1004B000F74DD58091D35BC278DBA2F76084CC7412
+:1004C000DF85C0FB37E9AB80CF62F4C31E6AAB990E
+:1004D0007A02607BB8CD4FCFB366A94FBE8CCE2BCE
+:1004E0002E42CEF465E6B65ABCA7E0AC6D2817EFF5
+:1004F00039F832EBFE6F53396DE8289693B39EFFBF
+:1005000036DE7B7076DCD04EBCF7A0705B25AF4743
+:100510001ACC62ECB2CC8A6F0769DDDCAF342B7683
+:100520003EBB1CE1D3C822EB07C97FC3F3F3319F65
+:100530000FF1E0B61A489F718B3C4A562DF22A31D2
+:10054000C202E58ECC528A475B9967FF20D667F3DB
+:100550007340504FF4DB318EFB7D4D02AF2C5BF5C9
+:10056000134582C89F3AF21DF47D948FEE3786B80A
+:10057000BF8A8FFFEE8B93297EA4E6873266CF5920
+:100580003899F2493465F57E03A6D873505FE8D0F8
+:100590000BBD5494535302F333E3F4A27767FF5D2A
+:1005A00009EE83D32FDD5B887CE91A03E8ED23F0A5
+:1005B000A17FCDE27CE8ACDEDA25819EF65E72E0BA
+:1005C00016ECE77DCBA2390E58575D6AA5C181F3C1
+:1005D0000DFE4846BE9826F0ED58C8E7E7A8F64B52
+:1005E000CBA1DF0E33EC5FF83E2DA0F8288F3EB094
+:1005F00050BA01E6DD21717E0B1FA5905D52EC49DA
+:10060000C1FCE406711E5216FBFE8ABE4D32EAD3CF
+:10061000BF6AEB9FA114C6E53B88F8F17BF9ECF6C5
+:10062000F923F82D5B3339DF5E207B26231DAD9740
+:10063000FADFAECDC4F79C1E6727B796635EF1352F
+:10064000969672943FC3DEA7C0FB92B8B291B76B87
+:10065000300DE5E2F9649F25B02E13E33E8B3FA6F3
+:10066000B8E4F7B3DE3D8A7905EFEA7B6625A37C23
+:10067000C917E7FA855FF0CDF1AA5FD0C4CB93B874
+:100680005F309AAF3599E78BD52EE4E7106B453E86
+:10069000C21C3B3FB733A73CDFDB0153BC8E0D29A7
+:1006A000C8F7E6BCEF4F46BB9D2D0C94FB278FAEE1
+:1006B000CF30B7DE13BF5FE77AE2CAF0EFDA626DE0
+:1006C000F9DB5E6DF9FAE97F1E1F5FDE65F16DC52E
+:1006D00075FF54E2F98DC12B989DD6E99282A877D7
+:1006E0004C7A394B9CDFE47978FF28ECA297A7334A
+:1006F000AA4FDF6BDA8DF9EDAA1F5916F593DCCC02
+:1007000094E7E4F705A0BC1A92443E9F8B6225EC67
+:10071000A53BEC1C7ED0D600FDBCB4D843FB23DD4A
+:10072000AA6357E11E2A37911E5231C6948474730E
+:1007300048D09D7A1E57A5C30A85F9313F01865ED0
+:1007400088CF77F5F683E83F0E7ECA18C757A542D3
+:10075000F985622CC6DAA9FC98A0EF43624EC11F4E
+:1007600028B49FDFB019089FF2CFE55D282730F647
+:10077000827EE1731B27D2FCD4FD03BBBAD0954E19
+:100780002E6BD1AFA2C349140B7D42A56FD480B0AC
+:10079000DD18FCCF7CA273E23743D3F8FD09EFE507
+:1007A000737E32B4C929CE7BF178588E29DAAF0F27
+:1007B000FBCD8C8EC3CF13A58B32548575B0EE4F15
+:1007C00032F369D34A033FFB03C965AB3780E318B3
+:1007D000924D740E46DD37F6CEDFBE5D7B05AEB3BF
+:1007E000E87BB4CE79363BAEB318C8BACE494F5F7A
+:1007F0002AF5C7F78F9CE4F5E03EF94ECD2B3394F4
+:1008000038BA81EF1BF9F716EDF76EF8DE19F77DB0
+:10081000327C5F32FCFBA76CA6B06E0AF653E1890E
+:10082000103F0FD362E68975C9E9FCBB7922DFB3BB
+:100830003019DAA3BC29D6E663B0E95E13BFAF4333
+:100840009B7F718DB42E13F7D55C53E34004FAFB04
+:1008500099C0DB35BAC057783FDDCF16151DC6FDF0
+:1008600056630A29680F5DCBC2EB1199672B034FC2
+:1008700038C6123FF80BEE8B263930DE09E5D3FA85
+:100880009EC23BF269BF5CCC9C367CBE2A5DA8F35D
+:1008900045FA403A8BD247C2BCA378BAAE8F12D584
+:1008A0007680DE834F550F024B9AE7137B7262EB23
+:1008B00002229A636A29443DE467ED41E21BD7387E
+:1008C0001EA1BCA5336302AE2CC07FDD655FD0BD29
+:1008D00026CCBD783CEAF730DFB4ACB4FFBDF9AA52
+:1008E000FADEB07CDA4F0D9A7CDAD1F6953A6E33A7
+:1008F000E3F7D3CC1AD845F9B1CD0BAD5E3CE7D0C8
+:100900008CF99DE5143F223D0ECF01D33D2792493E
+:10091000E85D979A77CBF7616FA387F4B7281F1725
+:1009200079E3BDA57CDEBD7778D47B4EB87EB798E1
+:10093000F17B52D47B4E96DBA95ECD2FEFDDC5FD5A
+:1009400078BD2F8EA7F350A0BF91BEC052747C7E9D
+:10095000F9DAFB55F04F4A8FE5436FD6737D739BF1
+:10096000CE5B8170DE86719EAF89EFDE94A5F59B2C
+:10097000A8E544BFDE33CEC02D59E80F28F1E54A83
+:10098000403F4B0DDC6F07F4B51DCF4ED4B096A79A
+:10099000F0FEC0B9ACE5D7BAB1445F01A2AF495F80
+:1009A000F07B0563F4B598D3579098924A5F51BA9B
+:1009B0002A4ECC9F0AACC6F6BD8EBE8F9A504F1DF4
+:1009C00030125ED43CB8C47D1C379F137A3E1F970B
+:1009D0002CD37CD68E349F4BA1F378FACA609C9EB0
+:1009E00047A3F70C85056D65317ADF6509B4E3B877
+:1009F00051BA5FCFED9161F396AD441F37DE2CF312
+:100A0000FC700B9757188FC884F1E78BF16FECE6F9
+:100A10007474A3CD4074377FA091F28558358F2B25
+:100A200078E17FDC0EF4117CEBC4770B5DA57A24B2
+:100A3000D985B5DAF8439D558D6FF8F5B81F6F5C11
+:100A4000A83F162FEFEBD8C62F30AFAD0EE314EA58
+:100A50007730EEE359D1F37FE3314E7158D8E9672F
+:100A600081BE91FEDF485BB9FD0EA0DBF18F97944C
+:100A7000A13F6776FAAAA73641F9996D13A9FC46FA
+:100A8000FAAD77BD8BF53B8BA85C8D97B8A0BDD137
+:100A9000C8BF2FAEB8795E3E8C7BD82CFAC57D8559
+:100AA000765F52A0773EB4734F2928C37CC36AC1D6
+:100AB0001FCEDEC1F3DDAFBDCCC65338577AC86F49
+:100AC000549D24EABFCBFB7DBBF45FCA30EFB4BAC0
+:100AD00080DFE3F276D94F2762F9B0F4C5A291E244
+:100AE000DF938AA5F004804FB593B7AF2DFB511665
+:100AF000DAF1D555BC3CC95BD93D16EB75E7168DCF
+:100B000074EEF317623F45CF35897DFAB2EF633A51
+:100B1000C7E437495E5CA27FFAC7FC5E22AB64473C
+:100B2000FFA3DF97AFA09F74968FE7255699DA331E
+:100B3000D1FEBD2E6028C7FC52BBA9F430EA1929AA
+:100B4000D32BA7217E6799981EE512D0F9FF213A91
+:100B5000BFFC8BDC64242EAB96CE553A9AAFD2778D
+:100B6000B5968E617FFE7356DA37F3D7D1E818C693
+:100B7000FF77E41375DFD2CA95687F09FB2DB1FFBB
+:100B8000D1F800FEC5F3B9D83CFA685F6563D6D7E3
+:100B900058DC773DEABE1BC27518748374AE234FD0
+:100BA000F24EA4038DA3C87F757E39C0DB58D9F0FF
+:100BB00079E19FA2EA65FCCF85766EB6A887EF7CC7
+:100BC000CC199B178CCFC6A0DC5FCFE7B3436AE19B
+:100BD0007C43E8C5AA7DDCA4AEB75FBBDE8A247E79
+:100BE0009ED98DFE0BFCCE553AF1EBE6DD2CE4E60A
+:100BF0004293FF4123ACE106C752A2879B58F045C0
+:100C0000D44F8C2901E79834B4BB820722F9E4CF92
+:100C1000A5BC00C077EA9838FD449D57223C9A460F
+:100C2000E18789F34E84430C3F83A45FA9E7A3A225
+:100C3000EB4A588F2AFF5D06AD1FC829FC364EE1EE
+:100C4000A7410A413958CB92286F61965722395EE5
+:100C5000CB4CC43F6B6BB8DC745AB99C57E5EB685E
+:100C6000747DF5559CCFD4363071EE8ACF3F91AE6E
+:100C70003258E47BF8AC3579B62EC3FD8AFA80276A
+:100C8000B6DF6BADDCAF3B778CF01BB2C834B46F12
+:100C9000A3E5617EC4C834E41B89F745D55EE07ED8
+:100CA00044A7B897B5D6FBF134B4D79D359169C840
+:100CB0007F1E74F8E621DED4FBDC12F9CE8D63745E
+:100CC000AA1FF192E82D110F6ADC2835C55F87E372
+:100CD0009C96062BB0F29134E1D767817CA44787BC
+:100CE0003DBF12FD01C0DF2E5E44A30AAB005ED300
+:100CF0009D8100D2DB4DCC3F1BCFE2396B027AEEF7
+:100D0000E766B4FEB562FDB385DC3BB75D263F7D8B
+:100D1000B5AFF83174A5371FD1B310ED3B1FC9B182
+:100D20003562FEE718C7D3392B977F2BDFFAA70A66
+:100D3000A05C367E8B2E768F01FC9B104AD2DC6342
+:100D40003069AF53539EDC97A5697F597F81A6BE5A
+:100D5000343C51533FF54899A63C6D7086A6FDE59D
+:100D6000EF5769CA5744E669DA7FEBD4024DF9CAF6
+:100D7000A15B34ED8F0BFB94057D83C5E978CFB77C
+:100D8000A0CB0B4B34DFFD3679CE11A4CB651B799C
+:100D90009E70254046739F430F97EF2DF03F8E576F
+:100DA000BF82F05A017A2FE607AFDCA295FFF50368
+:100DB0009BD6234F4BCC5F58CD5AAAF06AB8C4FCDF
+:100DC000856AFB621DD2E1E363449EC2E5EC727169
+:100DD000FFCAD7E2B58815FE97F06A746BF16AF620
+:100DE00068F16A29D6E2D5E6D5E23565BA16AF0EC6
+:100DF0009F16AFA9355ABCA6F9B578CDA8D3E23570
+:100E000033A0C5EB987A2D5E735AB478CD6BD5E2DA
+:100E10002F3FB85A8BAF047CABFC6F6CD75A4DBBDD
+:100E200028DEFDF5947732AEE71E4DBF2ADE83F053
+:100E30003F8EF716CA0BFF6BF10EDC86FCA089789B
+:100E4000FF2001DF20373E44BE00F2FEDFF05937BD
+:100E50005EE8D5FE91E5BDCA7FE2E56BBCFD381AC0
+:100E60005F1A264F843D39AA3C49B0273FC0EC1891
+:100E7000D2533692BFE566419F5FE2AB2BD09FF91C
+:100E80006392931FC044A6C3BC3EC079C3381F24DD
+:100E90004D227BFF5616D6D3FDBB98F1079DDE8E03
+:100EA00009C032DE9BE3A1E7522147970B7F80CF39
+:100EB00012B83886FB01F2D271DCEC417E0FF2DB16
+:100EC000A997741FC031F4872B8C9D407F383CCF8D
+:100ED00098393D9C54F9838F795C71705B324B2A51
+:100EE00026BD514EA2BC9C253749244796FC9E3F07
+:100EF000D3B3B9FE99F8EC6855E1C6ED9299D91EC5
+:100F0000E2EBD9AC4FC83B16B08EA57EB8FFFA49CC
+:100F10007E0FE8F31253A63BE93812E131C3C4E770
+:100F2000F5BC9E99107ECFB28007E1F243055813BD
+:100F3000CF879F88F4B0E4F7EF16A03F49EEB05F8B
+:100F400087F73C4FC0F1601EB36F6B91D0BF9AE141
+:100F50006E91D07F33ECFDFE7B243CC7172D33DE32
+:100F60000EFF100EAA9FAC58C7E3C54377703DFF34
+:100F7000A9EF32F2FF74B4062B83182792C120C365
+:100F80007C123D3FF73B339BFBBF32D920DD2FCA9C
+:100F9000DE14FA99B897BD44E4979F11F19615BBFA
+:100FA0004C0CF3154AF61D74627C6505E07210E581
+:100FB0009912A07B2C4AB6BEE1E4F77DEB1D785E6A
+:100FC0004C95A3A3E35B6127E3F2B4018F23DE1703
+:100FD000795B0E97E31D6D3533313EA2CEE7FE36C9
+:100FE000DF4CA40F59F1529E17DE6FE388FBDEE061
+:100FF00082FAB8FDAB586B3465BDD54F9746AC6FE0
+:101000006B213AD38B7B781EC85E6B8FBFBFFFD638
+:101010006CA1479882CC9ECE840A8B4FE524F28740
+:101020003F326E0F1ADDD04F3C5FBB2B97C5FB776D
+:10103000BBDAFC34DFF55220809D180B59D89C8C0C
+:10104000F90378C611DE6FBDE608E6B3186C6BBD18
+:1010500061CFE87033BA95F3F17CA9215BCB97FEA1
+:10106000A1ED14C1A9A3AD8EC63B83BA1CFA773299
+:10107000B97FA7A36D31BDD7D578889E5EDF3AFED4
+:10108000A007EA8FC23FBC8FC6E8E2F362E5B9244D
+:101090009F16093A40DF510ED0CFD1563DD1D99D90
+:1010A00039D6106EC23BDF197710EFD334008CE4D1
+:1010B000BF62DED171049C0C822F013DF971BF1912
+:1010C000B214F2C33AED0B084FFFD5FE54F81ACC18
+:1010D0008CEE7B31E458C97F72A9F3DC922DEC7C55
+:1010E00055CE97E7121FBD53C0E5F5AD3CFFE7E8CD
+:1010F0005D8CF4EE3BEFE67EB03BC18EC77DC95AF6
+:10110000E1AF2246372ABF4EC31B37E0654F1B3085
+:101110009A22C61E6A33E1092766417FD5D8181E78
+:101120007B7C8A03DDE29BAA5DF3F1F9D0F4133DE9
+:10113000C8561E9EF9D5203ED1D78CE3DB5B5808FC
+:10114000F54C8A89C2F88E7A28C3F8C9A23E39C004
+:10115000CB29A23EA58E97737C2F48D538B18478D1
+:10116000448ED539B710F9DE32C6CFB78AF3ED3BDE
+:1011700004DF1D6375CEAFC6FADB18E5BDABF58F96
+:101180008BFA4CEBB1AEB1C897176ABFDF2AE0907B
+:10119000613DD6338BE216DA7A35CE90663D7784A0
+:1011A000BE2FD1D63F2ABEB759CF0DCEC2FA42EDDF
+:1011B000F80F8A7A8B95F343E6E7F794AAF53F1484
+:1011C000F5662B3FE7053C5953DF2DC6EF9042846F
+:1011D0001FBA8B15F74F1AF75BEE6C6357E2FEE907
+:1011E000691BA27DF450DB05C2D339CCF39916DB21
+:1011F00057F65636E2B9EB73829F247B223EDF0816
+:10120000FC4EAD77DAF9B972D96D203A325A05BF82
+:1012100010FB30CA2FA4162F272EEE4FFE267A86FB
+:101220000D761EF58B5CF8437ACEBE4BC702717CFF
+:101230002BAB218905E2DABB973935E5F4DBB23413
+:10124000ED5D0B0B34F5D6F2899A7AE6CBA1FDB2AF
+:1012500056D055524999A65E3DEFCE7A7234FAB314
+:10126000BE7086A6DDB9620FFD8EC7C9B9EAEF7DF3
+:10127000784DC817D6DA0A3250EE3CDB361D956C35
+:10128000F63CEC273CA2F49C83E7F93E87F151A899
+:10129000FFC7361FBDDF03F5A0B9B02761BF79A036
+:1012A000FDAE363B959F6873D373479B879E8FB780
+:1012B0001553FDD6362F951F83FEF1F928F483EFE1
+:1012C0001F69ABA1F2A6363F951F6EABA3F2836DEB
+:1012D000017AFEB0AD9EDE77B7B550F981B6567A89
+:1012E000DEDF16A467475B17D5170BF9F69C382F7E
+:1012F000F85C253FFF9B88C7C939C28F26E2F8B644
+:10130000581C7F720EC6F1FB229A7BD671DDD49FEA
+:1013100099AF3FB1BF2AD1DF4436D86EE1FB98E2E6
+:101320007FE3FABDF75980DEC7B4703CE4F70F5194
+:101330007D663DC74595982F73055976053FEE8923
+:10134000EDCE488355161E0F257F0073C33A2BC47C
+:101350003D344476211DCE4B99CEE5A68AD7E8BA16
+:101360001D7C9EB8FE91E6FB6D315FB9BC8FDF330B
+:1013700051D31346B24FF2B5D03D13A63A7F187F32
+:1013800047C2E50FD0B9F78917E68071037CE6C242
+:1013900055CC03CFEC06ADDD93B5AC4C635FC817FD
+:1013A0001E629EA9D06F89D63E492A5CABF9CE94C5
+:1013B0007D8FA6DEE0BA4F53BF644DFE7A37C2730D
+:1013C0000CA3388971633BC3D0DEF2DE4D34AF7BB2
+:1013D000C53ACE481E3A371BDCA7C6C9B97EFE8C7B
+:1013E000902BCCB491F6C378072F16A50475281757
+:1013F0003EFFA714E2474F3FA10BA11F74020BE968
+:1014000070FF4F02750FEB27E34DB5325D5D226330
+:10141000B99479642C4F6543649F807E7E27D20BFC
+:10142000E8E74F98314E97137886E70F85496E1697
+:10143000097C16A9F6C81625D13F7A770EF93FB474
+:10144000E7863A859EDEEEA8C8C0F8E49951F2BB63
+:101450006CEE1933F0F7AC6C99D3E9A9BE7FD0A339
+:101460001BF13CECC61CD58FC4E97E0210B9A0FB71
+:101470008D388FD3E5BF4A4773AFA97088E8FF8CDA
+:10148000E4732F46B8BE25733A1CC8A4752902AE72
+:10149000CABE4AF762809FF2CE586F90C5C679BA2D
+:1014A000CD37435162E522919FB8B76DFE8CEAB803
+:1014B000F7FD027FC56CB006E5537189CE1BA29E75
+:1014C000DD1AFE652EECF1E1796EA58C7991BD4DAA
+:1014D000603DF7A1AC56FE2253BE8972E80AE601D0
+:1014E000BBC06A0D33CCCFE98FEE6FA6F99DA3AFD9
+:1014F000ECD529742F5F5694EFA14CC4DF351A4404
+:10150000FAF9AA57CFD775485B5F6CE579342B8A17
+:101510000D218F84E1ED1EBA7F4ED9293154FD95FE
+:10152000BFCC2238B0972C447F962D53E8EAEAEBE3
+:10153000944008E9E374D8F3926EACA04568D738BC
+:10154000C9B01BF5B1F108175C506131C175B958CC
+:10155000EFDEB6C504A77704BE3A7312E6C3BC3EFD
+:10156000BC9F7145AFEAFFD0AEF3C1F2AAEBF13EEA
+:10157000BB8E4159E84A5A786ED00F4EC1DF883B86
+:101580001D8179C934CF7710FFF2960AFA9D231096
+:1015900020B4BEC627C0DECF277E5443727B9A8E0E
+:1015A000F24413E9EAD7828F2DCEE1FE3C9BFBAAE1
+:1015B00019F87B6BB1F24CA2CF6775DCCF1AD471EE
+:1015C000FB52CDA300C5C183765D41AEEA67EC64F2
+:1015D000F3505E3B74947F27EF4AA27380B243A11D
+:1015E0007CDF4E6BB57D35F6635728BE31479E399B
+:1015F000887AB3D1A19B8A7AF7E1DDF70C629E87E6
+:101600009CA330F41775DA15AE7764EB282F4A7176
+:10161000549B301E52643D5189F03CB8EBFBE4DF33
+:1016200090BF277235843F492F50D6C95AA8FF6012
+:10163000B622EECDF0D596A60B57BE07ED9F9A4F7A
+:10164000D18F72D87ECE8CFA8AC7BA82FC6969B90A
+:10165000DC2ED463DC0BCA4FAC3BE740BEF5D6AE04
+:10166000F5CE7CD49F430AE920C57FEEC8A2F3DD06
+:10167000BB0C74FE5C856B5E50D1C4CF725AB565ED
+:1016800063421C4D9F70FE2709C7A7FD5EC7C2714C
+:10169000EBD1BBB9BDC65C56B277D27225EEE7116D
+:1016A000656B2EBF7770AF3E98E505F81CDAB52262
+:1016B0000FD775FE9500E5DB8EA6EF7F94E311F85A
+:1016C0000B9A75748F69D88CF9B74FB5B134D4EFD4
+:1016D0004C2185F29FF7087E5668E5F4FFFB5C4ECF
+:1016E000E789CFC21EBEEF94E7924216C49BBDAFFE
+:1016F0002C087432E9F5B9CC03F2AFD0EE23FF61C8
+:1017000061AB210DE3F8737E62253A39674D223FC4
+:10171000A1D29AE4C5F71DBB2B8AE3CF3585DAEC5D
+:1017200069981FB3BBCD94867C2A340A7F1DEBD009
+:1017300051DEB047C7F3DABE25E6F5AD5C0BBF4717
+:101740003997F3992795E0029CE793804FCC573E59
+:10175000B891EBC36BDB4D348FB56F8D25BD6A340B
+:10176000B83DDDE64EC37BD8776FD465A1FFA8B244
+:10177000BB7003DE47B0D6C6EF6395532692BF9386
+:10178000FD42CF507FEF489EE15D1AC7DFE5949997
+:10179000C54857B21CCC42BF887F67D5F598B708BB
+:1017A000F8DB86E5BADC89D7635EE35E5B300BF37A
+:1017B0001C03B95378392DB80DF31CEB73CB783972
+:1017C000279885BFE7D4925BC1BF1F17DC86E5D69B
+:1017D000DC19BC1E7D4FC03B83B9575D1F84F13AB5
+:1017E0000CDE7A64C83F86F997C0FCFBC4F33E0167
+:1017F00017B5FE057C0F70DE2F9E89F52F89EFFA55
+:1018000047A97F55D40F8CD2FF6BE2BBF028DF1FB6
+:1018100012DF1D1EE5FB37C5774746A9FFB9A87F34
+:101820007B94FE7F29BE1B1CE5FB5F89EF7E3DCAD2
+:10183000F7BF11DFBD3F4AFD87A2FE5F13FA3F2AC3
+:10184000DA47C4FB02DBC60FC3407705C047902FC1
+:1018500015DB363A719FEFEE2A27FAEFA8E0F11D6B
+:1018600095DE0BF07794A0FECB5C7E3FE89782FF7D
+:101870006E17FD031D3E8C74B7F61D99F25D3A7428
+:10188000DE5321E4A31B74A40FAC7D8BDBE76BBBA1
+:101890009550FC3988ED09F35F2FE6D729E6DB9BED
+:1018A000CBF3A98D6E775A6DBC1FC9AE2D637A1428
+:1018B000F25DE0DF943F5BDC5DD5550CE5314E1DFC
+:1018C00069204AA3298CF72228362117ECE53DC56B
+:1018D000383FAB42E7C1158712DE8BDFBBCB49BF78
+:1018E00053E7D76955E85E2CD9C6E5C09C9FCCB4B8
+:1018F000A39ED5C902833EFCDEAD90FE7EB0ABCC8C
+:101900008E7CCF605B66C7FDBBD6C3F77F75537116
+:1019100012F26BF9411DF1EFC376BEDF77BA75E4C1
+:10192000B700B942E74A805F7B51468C67E1763A5F
+:10193000A7F0D04B8BB95F8FD94A2BE8DC861A0F02
+:10194000969438FDFF04C207CF4B0839A2A07C81D2
+:10195000E793E5E2BC4190FB9FF214E61E13776E1D
+:10196000F244AECCCF63280823E84BAEA5FB8172CE
+:10197000D7291AFF7BF65DDAB221416E280972651C
+:101980006C17F0C938B9931FB46BCAEFE50ABF9959
+:101990009779517F9DF3938DC40FCFA17C9346E738
+:1019A0007B51FE2BF8F193E2BE9B2783FCBCEEC17A
+:1019B0008D653F477CAFEDD6D1FDCE97CA47B7E7DF
+:1019C0003282C3B800C81DD467149685F6D237C1D9
+:1019D000619CDEEFA4FB0BBE011EE31E2D7722BF30
+:1019E0001D175048EE0C931BDF00AFE725EFFB01FE
+:1019F000C4A32389EBD576BEEECE7417BFF7479C00
+:101A0000039485BE76BFF0832B29733CF8531C9D4D
+:101A10008E162AAF97BC19D742FB07A4801DCB476F
+:101A20009C495CEEE424111DEE455D86EE2FCCF45E
+:101A3000A37FA42F6450EF030CE3FFEDC33C19F523
+:101A4000BE4137E967A2FCE0F5D5D85EB14F4295BB
+:101A5000B328AFE761FD95D0DEC0A2EDF15CD3B352
+:101A60008775A2BFCD0FA3BEBA2F8969EE5BDC8755
+:101A70007E742A6F7D18EF4F84F1AE95C1069BFEF0
+:101A8000C4130F5BAF88CD676AE8A987DB295F9530
+:101A9000DB250EC6EFC33EED8924E37601FBC4933C
+:101AA0008776F9AE13E99ADF3F13ED5344FBA68125
+:101AB000A1A6E73CD4BE88DAF70F2597D0FE1AAA74
+:101AC000886F9F2CECFDB8F6255FD7BE589DCF736D
+:101AD000BFBAB184B72FC3F6673C9174CA3D499829
+:101AE0004FEAF0FEA77F5DFF1345FBD3E15F51FB9B
+:101AF000332C923E399FBEBB3A0FE8F8ECDBBFAA0D
+:101B000010EB4E473D19B8A20FDF277B98B877AD91
+:101B100085F4E73E538F1DF535B3BEC78F7CB710F4
+:101B2000EF4F9A1E7BCECA2BE47A55C2FB3E134B75
+:101B3000AD457A6CD591FDD2671A2C2B417DFA65A3
+:101B40002B6B87317479EBBCC807FB236BBD25D0A9
+:101B50006E67F64CB22BF6195AFAE89CED622B9D93
+:101B600003DD69EFB1E3FE313B7AEC184790EFE615
+:101B7000FA93B2C41A780AE929BCB67879DCFE9DDA
+:101B8000EAE1BF23D3FD867523DA01DD7A6FCF78D2
+:101B9000D4B36D0AE5812B4B06E6D1B9BD1FEB1816
+:101BA000F177585715943B1B75742F7C9B67C9328E
+:101BB000842B53FCFE2AF82E374D91F01CC4FD8A6D
+:101BC000DF84F10BA3D0DB767AF9EFAEAAE36EC81F
+:101BD000E3F269431EBF1FAA7BF173C56FC2773B57
+:101BE0005BD7F6E178E6092686F95E3BB34F76E3EC
+:101BF000B9CDC7DD60F1021CAC0D3AFA5D94C76B3C
+:101C0000A14D0AFA330C1A7FC5F3521FB50F36EAFD
+:101C1000C84EB0961834FE8DD4069D0FFD8E3B3C09
+:101C2000817B71DE53DF51AEC5F1DCE3143BCAA703
+:101C300007DDBF36E9609EC9E5DA7EED33B5FD38D4
+:101C4000ABB5F5AE5A6D7DFA426DBDFB364382BF32
+:101C5000465BBE888208E1083CC00A72288957B1F9
+:101C600024EB79FA5DAEEEC0F69EF1B01EA32558C6
+:101C7000FA26CC37696212D9FB0FBC91849B0FF80E
+:101C80000F23BEF3C06446F9A78772BEEF46799A68
+:101C9000089F9DD9065AAFB510E0998FF6FA29FA38
+:101CA000FD2C2B8B6B978FF0F16DCF9BC6CBEE0A83
+:101CB000F4CF31E283CFABFEE31BF8B9A69DADDCD8
+:101CC0002FFD601DCFCFA31554E0FEE6ED93F1F795
+:101CD000BCA6A0DFBEEB0ECC3B4C846B06E6E3C893
+:101CE00031FA58AF9E23C1538C159C2DE3BE3BEEB9
+:101CF000E174F2933C2EFFF7897B0FA2ED711FA6D2
+:101D0000336ECA427FAFE6A9FE079E97BF598DC7C3
+:101D100088325E1788E57D879DD7E27EDABCD05990
+:101D200086FBE901A197A5641B7C1360BE8F1C3163
+:101D300004A5CBA0ACB0C37A90E7FB9C7C5CC35BF2
+:101D400049413CD7F488BB9CCE497D24E6F542A5A9
+:101D5000F7BD5ADA8F0AE5393DE2F29ACBB8BE8177
+:101D6000774A33FA4954502D0ED696919DFA88CF72
+:101D70006BC6FDFA48B6D78C79C2E64CC58EFBD847
+:101D8000E956E8BEAA474C013BEA2D4E1080F83BCD
+:101D90006D869C9EB9743E0860A8ABE0210126F2D6
+:101DA000E9309F2D55C06BA77B991DCF91BB0AF7DA
+:101DB000FF1DFAD553B1BF64FE1DC2C921E0743CBA
+:101DC000CFC3F38345FFA9CB5EA0F6F8D75911D74F
+:101DD0009F97D397612E0BD1EF8D89F1D57EA2FD10
+:101DE000331FF9EDD7FF9CC3AD3D87DFD36358C3E5
+:101DF000C80E7BA132B0F720C2273389ECEC2C77D8
+:101E00005615D247D6916D0BF03CC0FA9F73F96915
+:101E100058CEE34D590A335D85EB4E0BD8118E89B0
+:101E2000FB30F370CF7C2436152F89FB3253615D74
+:101E3000B273F8FECC74BBAA8AA68CB04F13F641DD
+:101E4000E691A1EF61FF89FB7587E56829C2E5FF8F
+:101E5000029F8BFAF4008000000000001F8B080036
+:101E600000000000000BD57D0B7C94C5D5F73C7BB2
+:101E7000CB26D9249B04424248D8CD8D402E6CC23B
+:101E8000C588A84B48102DE2227235E2131220407B
+:101E90000201F46B6CA9590C372DD6F0360A5AD4CE
+:101EA0008D058A8A362820566C978B8AD56A5AF512
+:101EB0002D554B13A18A728BA17D3FDAFAB6DFFC58
+:101EC000CFCC24FB2C89D27E6F7FBFEF4B7F7598E0
+:101ED000E79967E6CC3967CE9CDBCC3266632E3B54
+:101EE000A3BF7F98F1DFAFAFAFD53AEE1F369A317F
+:101EF0007F8AC5B3C3C5585AE87B37FEFBF708D4C1
+:101F0000356672FD2393B151AE78C606E279BDCB3A
+:101F100057C0D81E9B73A26300635D2B98E729FE10
+:101F20007DE94B9BE6BEC5EBFF95E67046F056A9F2
+:101F3000C79ADBF3F97376401F86F6DB2CFA93D150
+:101F4000FCFDB6E383985F632C229AD5B7393854E9
+:101F500026A6A3FC07FEAEC738561A6794CBC4D892
+:101F600018C678170153F2BF5EB60D1992E7F4F068
+:101F7000FE0229ED76DE6F9BC59967E1F59CA1CD48
+:101F80000F59AFC53C388CE368DA5E56C2D8B34708
+:101F9000F9B883517DE4A1320B7F1FD5F3DE8FF7B3
+:101FA0007B4C26597FF4A1B2218C0D39DAB6C6E1FB
+:101FB000E4F31FDAFA909DE32DF257E2FD045EF799
+:101FC00067012FB5433BF8FC0EA72FA1F937FD2E73
+:101FD0008245F0760566CF56D4D947916C07AFEFAE
+:101FE000DA377EB68BB76B8A19EBD2F3192B73698C
+:101FF00034FF525986CFCB6CF3E81EC7E5CFC74BF1
+:10200000BC31E639DECAE95BF0631B7B80BFCC05DF
+:10201000DCA0576B64E029D0B7790B63498C553B42
+:1020200005CDABF73F907E88972FC74CBBCDC5F150
+:10203000541D53960478522F31A62772BA35DA9977
+:10204000CE71953AE0058D71F8860C383A8139C029
+:1020500037ED6B9C28EBA398AEF807F4BF6461FAE8
+:1020600028F4E7A5FEF0674F02178ABFB5093A5B6F
+:10207000C3E1F1735CEF00773AA33AB542FE8FE417
+:10208000326F47AEEC27037CCA66B7F1F12A8107AD
+:10209000DE8F8DD3C45ACC4B872518D147FB8512D0
+:1020A0005F66BB23681EC94BE7EBC7A95F87E56C7A
+:1020B00087BDB79D3D60217CB05A16C8D6084FFE3B
+:1020C00008D4E312A8CEBC5ED78024F03F23E4A658
+:1020D0005AD8D1083E2E712F5F3F292C48E5E31CCA
+:1020E0003D8E4C344A8BFF349AE111031F3FC5D813
+:1020F000E450BE56E5C57413CD23ABC134F014C70C
+:102100004FDE914882C3B2910522F96059A007A71A
+:102110005BD62616B0B8D1CE36F05422BE73D17736
+:102120002EE634311AAF6D04D6D5D6D71D9B581C78
+:10213000D1F74E1F1F6F6B14AB01BED4788CAD214D
+:102140007C6C768971B7353A898EEAFD90DAC36185
+:10215000744C30D051B54BBD3498E8D9DB6F80FA60
+:102160004D6DD84BFC907A295DF289EB1BFACFE8D4
+:10217000A7FF64FABEFFFE87D0F88F07DF8F9FCAE4
+:1021800051F1A3AEBDF13E5E465A9B7D9E3EF09C52
+:102190007A57883CE3FF1F7980D7737BEB0A2F9136
+:1021A00056EF80691CFF91779B3CADBCBFAB8E1B8B
+:1021B000DB4D767F108FF5D8DB3E38603ADAD78971
+:1021C000F6D79C36B6F74DD817D65EC077FD256397
+:1021D000BB70FA84C3CBE11A382304AE89F608C376
+:1021E000F7B32B2F836BE0AC10B86E4836B6D7D759
+:1021F000F40DD7B77223BE162ED5EE96922B6B1721
+:102200003E8FE99323FAC1BB683F6BF695F57B7B64
+:10221000CDD7B7BBB3217C1CBFDCAFF8DAE2EB381B
+:1022200011FFE04B20B1C1E48D8C65CCC9BA18D642
+:10223000D1C9A12E6A97C09CB49EF9C2D7B0AEDEB8
+:10224000C33F53F856E0F69D738D01FEBD150FF3A5
+:10225000A66572BF6253788F57A3735FC1AD0597B0
+:10226000F31F63F7115CAF68BACE689FB57B76F059
+:10227000F59D97CAEC2909FC757220E3D618C6BEF5
+:10228000EA91D75CD470384748DC3D37B86D653C7F
+:10229000ADF34002E0F967C7B5BBBD66F798DEF65F
+:1022A000E1ED7ADB0B3CD96C6D2B0067579DC38346
+:1022B000FDE17DBCE2DFFD786644D0CCF175C1EA7A
+:1022C000D8A87139733C7ADEEB03391EDE8BD5E377
+:1022D000D1FFEC5937AE475D3B9CE85AC9E1BB5092
+:1022E000D9311678F546EB03DDBCDF5ABB3E3489A5
+:1022F0004FF15C9A3E2C0EF8F525125EF93F0A7CF0
+:102300007DC22FE029D304FE13E3F474F453666A0C
+:102310007FC2876796F6B1F88E3907127CE76C5C4E
+:10232000DEF5B1FE151E4A653F87AC9EAFBAF8FCDC
+:102330000E6D8EF3347178AB1367CD5BCE5F2D30AD
+:10234000F992826603DCF904B7A372680AE0B64A20
+:10235000B8ED0325DEBD595F077713C6C3BEF63D52
+:102360002DB0C32D6889FA4BFEF8C003BC1E61BABC
+:10237000F83EE4475781C9C3F708B68DEB1776BE20
+:10238000AFBC2BF1FD38577FEC09F47C239E274727
+:1023900089EF931F31059AF8F7BED297894E3F5EB9
+:1023A000E6F098F95895CC6503DF5631AF0DF0FF94
+:1023B00071C2DF5EEDE0F3BBC9AD97833E77269A2D
+:1023C000D2DF2738F4BC699CDFD87881FF6FE20741
+:1023D000C63699D858C66E95FAC10289C7E9CC6B42
+:1023E000C53833986EC5B8BF396FF332CE1FBFE121
+:1023F000B8621CDE59CC4FCFE7B00095B7B320B51B
+:10240000BF837550FDD7D185690D1CBE695B86659C
+:10241000633D86E0FD76C92F770E10FCF2D920E0EF
+:10242000BD65E015F1EF344DE06FB05BAF76D37A68
+:10243000750DF00026E7C421BE9890F5533650F094
+:102440009FC599FD75EBA7BD3BB6908D2479E048FB
+:10245000E178B84192F206EFD229982F2408D6EB02
+:102460002D72BD969B1D6C00A74BBBCB1C88E0B0AA
+:102470004C9EB02219F37D630DFBD5284EBF372645
+:10248000985913B5F4D27753657F53874CFA1CFAE9
+:10249000C9DB2C386034FFAEFC927E348EE367AA31
+:1024A00079F75AAE71B3C943AC9F7484C8B51B07A2
+:1024B000ECB130AEBFDC94657C3E259FD743E4EEA3
+:1024C0005466E97DCFE97F08F881DC61CD66F0EFE5
+:1024D0004677CC804FF37875041B21EC034E8D902A
+:1024E000F974DBFF6EBBC0BF7BC5AD3F04BAAC8CDB
+:1024F0003F3F8FF40E8B98CFB277CCA4577ED2C8D3
+:10250000C079EC14D70FBD398C7DCAF50BD44F3789
+:102510002653F905D707509E6DCCA5F7E71B3D5410
+:10252000FFC4EDDB8A7EE76FFCD2827D6943A4C2E3
+:10253000B7806395E4BB0D6963B7FC95E375C3DBB6
+:102540007C6170786ADA9A2771358BAD4AFBE43E7C
+:10255000E8CFAB9ED63C68B7F4A0D7E6E0F02C38C5
+:10256000AAAF079917BDDD311562A20EFA2BD71B52
+:10257000EEB7FA7662BC311F9C4AD27903EFC1CE26
+:10258000D71379FBCF1A4B08AECF1BBD04D799C622
+:10259000C954FECDEDDB8DF65EF6A50DED6FDEDDEB
+:1025A0006949E5EDCBBD9A17EBF13A2F0B04383CA6
+:1025B0005BAD42BE6FE5F21DEB7342C1AD8FDF052F
+:1025C00071E1D6F7830F6724549527F2E7534B2A1E
+:1025D0002D6837EB2B2ED3DCBD7CF8CDEB50E0A380
+:1025E0004ED2E5DCCF35C2D3B9FD79B75CC3FBFB76
+:1025F000F931333373B8BA2F9908AEEEE35101289D
+:10260000ADAADDCA7D66D22757A6D902C0DFCA7D32
+:102610007983A04F9DE1746339BDE39D79EEDB2E94
+:102620003D448E9E4968FBAF0F21A77E2FE414D74F
+:10263000373F7D0C726CC8600FE87EDECAF57220F1
+:102640009AD547631F5B6693EB8BCB19D4CF44318C
+:10265000D247C73E9F5A8AF582F15CB65E3994F341
+:10266000FC968CEFBA7AC7DBD5B6E0C3C778FD5CC1
+:10267000C0E4B7F27DE61C6B3BFF33C8D1ED0E0F13
+:10268000EC830D1A8707FBE88EC154CFD52C510D72
+:10269000C4CF015AAFB99ACBD2C0E54FED0B8F0E24
+:1026A000063FBDC27150C2DFBFB2399AE4D32B5688
+:1026B000CF8906F4F7B8E8EF273FB8E79303281F60
+:1026C000AC2BBE879717DD09D44FF57F2C1E81EF09
+:1026D000F93ECD52787FCFBEA40523F9FA2C683994
+:1026E000745F0A876FE4B64ED3605E166DD79A505A
+:1026F000E6A5DD74CCCCDFFFC5ED1276EB6EB73905
+:1027000015CB6A70E0C3EB69FF36EEEBF92D5F96EF
+:10271000C2BC54FBFB08ADED8B56D8C3E9C78B7523
+:10272000C25F33C1B1EFE0F4F76E679807D71C00C2
+:1027300077A5CD43FB49C0DF0A3A9FD3733D0F60B5
+:102740004DFBFC8F82BEE7F4240FF697FD267FEC4D
+:1027500038B43F61A179BEB4FDD7B1565E8FDB6B53
+:102760006591FC7D5D51D724B4AF4B73911D9EF6EE
+:10277000C40D93819F657BF7B5523FB5768F867503
+:10278000B6EFE2EBA9B0876E649E6CF0DD5E51FFA0
+:102790007E99D7037EAB69FDB3A8B7FBA8EE33FBE8
+:1027A000DD16B4AF127ACE16B98FB18E429277C4CD
+:1027B000CAAE5E7A7D9FBFC6FBAD6E7F4ABDA37772
+:1027C000FFE3FBD6900CFE3EC526BF774E4FF7FDCC
+:1027D00013FB964DEE43AABF2D36E68FE4FDA4F120
+:1027E000E71AF6559BD86F7770F9027E51FB2D1FC3
+:1027F000371FE3F2EFBD9093A97C732DE2F349DD1F
+:102800001211A03DFD0AC7577AD2F22821CF94FEBB
+:10281000313BB1E9D50E8ED73FC5EA2519BCDD02A3
+:10282000B95F338B2719F33B19EBBD3A83F6BFAE83
+:1028300074CC81EF87D7A2BECCCCF5A7CC10FDC954
+:102840007E65FB61449C7722BEBFD2F6E3A3FA9675
+:10285000BFE3BB4B48FEBE2AE5EFAA3F9B5811AF32
+:10286000AF7A3882E409ED697DE0E555BEDE752E6C
+:102870005F7E01BF012FAFFD538799EC8FA3A6DACE
+:10288000D7F97E4A4367E03F5D4D71A3A9EE0599F4
+:10289000AFFB93A94FFB50959C4E95A093F72BA3AC
+:1028A000BFE1FAAF9C36EADF917045F335F7335F4D
+:1028B00073AC98EF41CC97D36ED597C5242F0F5E9C
+:1028C000E13CD322BC2B015FF83C38DC0DA047383B
+:1028D000DC3DFCDD756570DFAD31BF09EBEC4B5BBA
+:1028E00000EBEC200713EBF6E0E2FC00D6F37E9B56
+:1028F000A8FB636DA47F1E8C617EC88F83D3920278
+:102900007EECE7680FF9309089F791F2FB3949F4D2
+:10291000FDE008CEFFBCCE6E8F92FDD7BF5580F78D
+:102920006B523D1C02AEDF063666907E6B26BFE121
+:102930007129AF5BE283B79BF9F3962F7318C63901
+:10294000CE82A9CBD1AE268AE4504BBC372581E399
+:1029500071FFDFCDB42FB414F1BA83E434F9775AA0
+:10296000A67953E2797DAEA44B4B6B60C723E86F29
+:102970005AAEC7CFC7196C66F5D4CE2DFAF9D02A56
+:10298000BEFB9DA40B5FC7B4CE8F66CCDF03FCEB10
+:1029900053A32DF08B708CA7681CFEC7AAB319C96E
+:1029A0004BE9F79A2D6930B7970FBCF6B1D06BC5DC
+:1029B000DF9C053B22218F67D444925FEA78CD7D6E
+:1029C000312E3EDE0CDD1C8C80FE775BB9C1EF74CE
+:1029D00034C34BE372C342DA09C12AE0F1E75D7602
+:1029E00006B9DC1F3DEBDA26249E0AE1871A9B908C
+:1029F0001FA7A53EF4728CFE0BF0CDF20337269E86
+:102A00000AD1F7AA1794E7407F56E37D13DF34819C
+:102A10004E2369BDFA4DE08FB648A2FFE45BED445A
+:102A2000EF6E87E929F825EF94F2AA0986307FDE58
+:102A3000B42F22701F7FB63C223813F28AD3FFE9ED
+:102A40009DA0EBAB9144FF5A9BE0A7DA9FE5117F75
+:102A5000EDB779DDEBD0FFCF2388EEB5B1AE387A94
+:102A6000FFCB4426F98FF486DAA8604E3CC7E7C650
+:102A700068FD43E08DF31DF9836B6DE2F909C957D9
+:102A800027781F80C35F1F43FCC8645DFF6E22D997
+:102A9000535C1F25FED51FCAA3BA6EF3A62CC0FA3D
+:102AA00058194DF09D90FEB413B5F1C4DF150F2DEC
+:102AB0007D9B717A9EF0EDBC3F87B73B71D0EAC138
+:102AC000BEF471833968E3743DBFFAE4D8ADBCDE6F
+:102AD00071DF47E97A881FADE2BEBA29F8AE62C954
+:102AE000EAA9D82FFBC377456D0497B9BD74B266C8
+:102AF0007AFF04FAB933F5FF8D792ECFEF5808B974
+:102B000077DED6FE04EC830FE3F4BFE2FD85973F4A
+:102B1000DB49F2D0D29503FD7C9985F301F852EEA2
+:102B20009FCB255F063275963986F047FA78747E1A
+:102B3000BB907BABAF4CCE7F7170C77E8D8FB334B3
+:102B4000EAE0322ACD8142F473460BC66A99C01F6F
+:102B5000D7E3787F679DC158D0419776D3D25DC6C1
+:102B600079E10F7E95A5F807FF6E699B99FC2A1CF9
+:102B7000421BE05F0A4FAF219E20E40AEFE7295A8B
+:102B8000878E8FE77D97E37FC9D3C38BA14F2E8DAF
+:102B90003FF0836BA81DFF4EF1B9F9F2BA9ACFE569
+:102BA000F088F99D957C7E96493938DBD66387435A
+:102BB0000F3AFFDC2003DF9C7F7A38D5BFD0BAB450
+:102BC000280ED779298F98A76DEC341810DEB6B18E
+:102BD000D0671F91CF9726B68D85FC51F288D9DB3F
+:102BE0000AC9AECE6D2B843DA9E419F3B5E5D0F347
+:102BF000405B0EBEDF6F127E0AFAC3BC9F4D6D258F
+:102C00003CD8C57A5CF26C1EE1458D134EBFF0F9DD
+:102C10005E9F29FCDC1CDE3B7DBCFDB0AD36C3FBFA
+:102C2000E10163FD06D97E68185D069BBB0E454039
+:102C3000DEFF98D17A0D1F77AAFCEE99677AE860DB
+:102C400096F6227329FABB84BE6D05BE7FD783EF4B
+:102C5000BB52B93C5D8A3966F4CE7F7F919E0AB93A
+:102C60007FDE24FCD4FBE3793D1F7A8EC0A7AA2B1C
+:102C70003C86F3D17DBF5B988A78CA3D9926A954DA
+:102C80007A0681DF9A202FB9BC68B20A7C7CD158C1
+:102C900033EA9405F6687D4AB5A5773E0BB716D999
+:102CA000B15E166D2BB2CF0FB1779A768D3AE6E210
+:102CB0007439BBCB426E83264BE007D0A39B769939
+:102CC000DBFC8CDEDBBDBCFD59C7E177D06EE1B625
+:102CD000F862E8BDEAFB455BEF4EA90EC177DE2E38
+:102CE00023FE0BDA8C75F8A343EB4DD005C7FCF33C
+:102CF000DF15058DF551C78CF5CFDEBF6B26D8F8F3
+:102D0000A512C1EFA7033101C4A96A3E9A740CFB56
+:102D1000DAE9FD2FC5823E4B7F5FFD3AEC96455BBD
+:102D20008D7CC6E9A641AFF7EFD4883F1607C2D71E
+:102D30009D5CEF97ADC735CAAF991BCA27E1F43C3C
+:102D4000C3DA667A393FD536AC1C857848CD14CEC7
+:102D5000B81C9EABDB36DB1037081FAFBF75CF1C2E
+:102D60005E17FC559525E2DDB8865276124EDF4D92
+:102D7000BF9E84F556F97D8DF6FFCA17871D85FC29
+:102D8000EEDC33E7262A674E263C28FFD9A2835A79
+:102D90003086D79D25AE031DFCBB05018DF687F956
+:102DA0006B237AE510FF7FF5A630385A42DE73F8C0
+:102DB000171D38F4178DF75FB3CDF8DD628E2FC87D
+:102DC000FD25DBFF1111FA5CD97DE30EB69A31EFD8
+:102DD000050A7EFF750CF31221482E3AA4BE720A32
+:102DE000152EEFA3137C8732F9FCC7B588EFB8C066
+:102DF000AAC47CEB1C3617E65B6767C1680EC7B1D7
+:102E0000189BD7C99F5FDC1A43FEA985115C2F2C44
+:102E1000A6924516E33B0FEDD39FBE6B267DA50E14
+:102E200063A39F2735B27FEAE06C44FDC7A2BE983A
+:102E300005691EE0176FE8FC02C63A6B167653ADC3
+:102E4000257808F858C23A84DDC3E9E80D89C7D56A
+:102E5000F2791E4F803E64FC7E396BA3F6CB0FFCEB
+:102E60002322F479889F94EC3965579A6DCC0BFD39
+:102E7000D87C6F14EDF75C1047813FD769DE47EDD2
+:102E80006694625EFECD42FF99DB2AF60BAE9FE6AA
+:102E9000003F2D9B877BA0A7CCE57A7624F488C5DC
+:102EA00051D4AE259E917FA5654E8ED0B3FFFE62B4
+:102EB00010E3743DAC917FA4A548F4DBF2E0707A96
+:102EC0000F79A8D13811A4B7B44C53EFD3484FFAB7
+:102ED00010A0A540CF95CF07BAE8F960B33707FA3D
+:102EE0003AFB6124D9FB4AAFFD4982FE0FECFB6A35
+:102EF000BE4A0F663557A6FFED90FB5DD76611FF02
+:102F00003DA5F95E3785E8A5CE2C21E7C7967A77EF
+:102F1000CA761407A8364D7BE07A0E4FF523265764
+:102F200093BB17EFCCEBCDC1FC4F6D8E2C069F8D64
+:102F30002D15FE9E1345426E478F66DE002F5364AB
+:102F4000BF29592643991CC5F98FF773AA5CF887E6
+:102F50006346FBC8CFC6753692DFE1F3C896FD54D1
+:102F6000DB7CBFBCB60F787AF8A04CE819A756688E
+:102F70004F09B8385D797DEC7F44927FEE94DC5741
+:102F800014FE39DF8CA17D5AC549259F6C06FDB121
+:102F90009F2D1676502F9F18F960AE26F0CA1E148A
+:102FA000FA694BBCA82B3EE0F60EFB2BF8A49C1153
+:102FB000DEFBB37BD43C5B5AC57B4EEF6BB3C65C88
+:102FC0006EF7287A334B600CECC6FEE83DBF247EDA
+:102FD000AC66A2B8B51F716BEC758497FB2D81FBB5
+:102FE000381C432C02FF6916C15F5C2AFBA38AA927
+:102FF000BDD7C6EB953F5CC4BCBC7D652A237F1062
+:103000006FCFE2D09E7763867F8497F8AE324EF41E
+:103010005B3988919D407F5C5E65A1CCA07EBDA69A
+:1030200004F17D6C317DEF3789EFBD165E0ECD1456
+:10303000FA7CD7BA88C05390CF1BD272C007534ACC
+:103040008D7CD026F94695A9D92E95E7908CF53D33
+:103050007FED70DA2F9A227D75FB40B7E784FE5F23
+:10306000B9FE8E9BC700BEE7133D00EF8BA97B28FE
+:10307000DE307FED9CBB3F80DDB02B929E9764EBF2
+:103080004BB3A01F6BAE79FBF883F9338ED892F95E
+:10309000F77ADBB4733FE3E554FF9E77A00F4CBD96
+:1030A000CD4CEDA732E11F656BC53837FBBFB424AB
+:1030B000F3FE6E1EAF51CE4067A4337D05F2162499
+:1030C000FDBE0DFE851D16C966BFE0005C6939199D
+:1030D000FCF9CDD030FB885FED93FCDE3441DB069C
+:1030E000BD66E844B1BE547BF4837E5FC9127AD0DA
+:1030F0007DB254758E576A5FBD31A2333316A53544
+:10310000380CFB5D4EE97AF0D5940C36692BF07ED5
+:103110008F19B90A1CDEAE4A5AF731392EF0A9CE02
+:103120005890F22302C389AF3B2774756EE0F5CE49
+:10313000D6611EF2F9483B7A01EC2B17DE0B39A65B
+:10314000E4CB0967470CF1ABB4ABAB246BFCB161CA
+:10315000E22357F1F6550E5B27F683050F4F8F4597
+:103160009E49558B59E4736C32DAD5DCFE0D00DED6
+:10317000703B39DC1E06CF808FAA3769C487439B1A
+:103180003CB61492639A13F3AB7604B320DFAB3DE5
+:10319000911EBC3FDBE84D3C958578C4642AD95725
+:1031A0001CEF63E18F6594C4F162B6FE1CF8A1B216
+:1031B000B992ECC5E87C9DE4D3D92CC17753E04F9C
+:1031C00084BCB174A4601DCE53CF139C390EE2E7CA
+:1031D00048063C745A9D3980AB735DA409FBE694A4
+:1031E000FB045FF37566B7F0EFEFB7B028ACF7EF0D
+:1031F000E27B3E5EC51A8BAF95D787D8992526010D
+:103200007C55447C9D394CBF0FF09CFE1E2BC1FEAB
+:103210005FB56933C1A3F88259DACB12A1DFED7033
+:10322000173FC07AF9287358E951E0AF871F6ED372
+:10323000880F78792893F8E1D637891F4A83592B6C
+:10324000F311C7AA655EC411929907FE806ED64538
+:10325000FA4437D72720CF943C517283F3811779F2
+:103260003D8ABE4A7EEC6CE42071BCEE6AB453F930
+:103270004CA39359B80CD8DD984CF5E71B5D54B6B8
+:1032800035E6D2F3171A3D54DFDB5842F5FD8D5E6B
+:10329000AA1F689C4CE5CF1A7DF49CE385E49092CC
+:1032A0002B4A1E297E5272299C8FE671F45E574C80
+:1032B000DF93DC53F20EF33015F7CA2345DF0CCD54
+:1032C000E74F76438E75CC81BC28379F7DEE25F87D
+:1032D000496A1C9E0817F022E45EB7C34E723EDDB9
+:1032E000C60EC05E6F5AE1EDDC10B2AFDE5EA331F8
+:1032F0004B089FDE511FC92C217C7C6743BCA15E1B
+:10330000D1F0DE6B8378FF5ABCFEDFA0CB897B3F18
+:103310007DFCB7FCF993F77E910D7A7338766CC11A
+:10332000B8ABA37AE048407DAD95F487A151C20EB9
+:10333000C21FE8329F89F5F9E4BD7FA5F5DDD910FC
+:10334000E132F376F31B22085F1F824E1CAF1F4B46
+:103350003A55AE3BF9DC4B58E7AB6D24E7E6AF9549
+:10336000EB7223C76788BEF6490A23BD4CF3328649
+:1033700038CC27DFB305F99ECF3ED1EC010DBA0F53
+:1033800037922AF8737DE31B947FA5351C237D5863
+:10339000475E16FC047EAB211F4B6B90795A1D4390
+:1033A0000C7954D1A3BD36C807F034E8363FF73066
+:1033B000C3BA66CD9A135B40B57C5EBD51237DA335
+:1033C000475FC836131D2BB32C54FE026B9CECC513
+:1033D00066DA9F14BF7279E10D605D3417D91686E5
+:1033E000C8E1F9F27955AE894AF5BC32CB46FDFC0D
+:1033F000028B91F7FB406E866D01C939970D7240C3
+:10340000B59F9F5BBC3E6334FA99308085ACC7A200
+:103410006C0B7D5F89442FEC5F76E1FFAFED671F9A
+:10342000507AC969FCF36A829FECAD25CF3FFB3C23
+:10343000E2634B3E8A203A2D1929FD11F981B1D35F
+:10344000499FF13A343ECF6592FE65CFFE3EB6838A
+:10345000BF5FBE57F82F79D98972D9EA1AF26B2D5E
+:10346000F3F0F59100B96A8C231F7DFEA3D80EB24C
+:103470002BFCA9C82FE4DB422A4B46BCE8E424F825
+:10348000C597B3AEF5C8EB0AFF6EB9F655ACF0EFD1
+:103490008B38B98A5F96BFFAE7248263DFC524C8F8
+:1034A000B5E5AFAE4BD2FB98F7F2B0F8B58A9B2BDF
+:1034B0003FD872B6E94BC4DDC2DB5565C70C00FFCF
+:1034C000B0ABD855E4A7B030CA6358691778E80E96
+:1034D00064C7B13EC6EB19772B17ECDC0EEDB6B81E
+:1034E000E23C1CCE0BFDE4F1EDCA16FBF93919479D
+:1034F000BDB0DB4C7AE185DD31C4FFCB76FFF0F562
+:103500006B787DD9760DC3B23AD64E785AB6D7CC01
+:10351000ECA1F60DFC3689FDC3B9F4D9987AF0D345
+:10352000E236CDBB231F717957DCC01078D6497EB7
+:103530005A1AD13696E820E1FFAED48F54BBC507A6
+:103540007F6803BD78BBF3A4B7FC341ABA36FFEB2F
+:103550007A07709ED9368AE2BA8BDBF62CA37D7F80
+:1035600077B41353FCC26AF4476D96E36DCE167AB6
+:10357000C619E9FF3DF3BC99E40FE0C43AFC4213DD
+:103580007E5EF5DD16F9DD1689B7EB10541CD3DB32
+:103590007E715B676C166FFFD981F7A86C95ED178C
+:1035A0003BDA0BB15F7EB6377A7280CA1F4D7A85DF
+:1035B0008F77AE6DC2002D645D3D9F6DA5FECE6D13
+:1035C000334F06BE5840E519B5D17CCEEC4ED5C878
+:1035D000AE05BE397ECEEC7D31D644EBD66FA0A3CE
+:1035E000C92EFCA96E8B4BEA977627F48CB95CAB9D
+:1035F0008BE3F2AE6EAFC807087FAEDAD37A4B0129
+:10360000BF77D904FFCBF8BD8C2F214F84E2F13175
+:10361000B600F6D779235DB36E873C7BCB2AE831C1
+:10362000C4B50576D5BC7713C95FB1D2EA1A84FA5E
+:103630009FDEB692FF7CDE28B9CE933BC6C03FD951
+:10364000E916FB7AED46BE42F8940773FAFBF9FCE3
+:103650006A0326CAA77C3F3B83E6F7588DC96BA354
+:10366000384730077ECA1336E637434F7E2192F43F
+:10367000BBDA0CE1777F0CFCCECBDA84604E22F40F
+:103680001D49C7DA5BF9FB107AD63E15CC81DE7294
+:10369000D626FC7878EF44592CDA3549BE413FE80C
+:1036A000B7D3ED3C4FFAE5BE18063DDFF4528CF07F
+:1036B00027FC2492E20EAADF53D942BF6F92712EEB
+:1036C000FF0E011FE082DEBCD8D69C03BD528DBB2D
+:1036D00038B699C63B2BC75B1CD52CE207322F0CA2
+:1036E000ED697C2BF3C21EEF7A3A82F4D32F52DAC3
+:1036F000F763FC2F9E1E4E71F04E7760E1017ACF8A
+:10370000F5364E8725CF440401EFE74FC7509CF3B1
+:1037100073ABD0833E8F49223DE858CC23F3D05F72
+:10372000F7F6080DFE94CF35664BC6FB1D03295EE8
+:10373000B5A4B181E2044BF872473C9A97931157B4
+:10374000FE7CC770F2B37CFEA699E28BFCF9463C86
+:10375000D759F3BCEF60DDED8A263FDB17CFFC6D58
+:103760007868FC41954BB61BFD498AFEEABD35479A
+:10377000D80DD61C81C7C81CB1CFD445B73D9241E6
+:10378000F314EB95D381EC2DBE3E92E09F3ED1F633
+:103790007292E6009E83393F02DE7709BBE68BDD3D
+:1037A000568A8B2C7929C64BFE9B0D5799B05F2CFE
+:1037B000310BFD77096737510AFFD092D81CF20F01
+:1037C000717C93FDD8B5C32CC711E37EBE334DF891
+:1037D000DF83B2BEBF20003E9F92C0EEBC95F49B3B
+:1037E0006D85C0EBC5EDD126F0051FC78BB8FD92E6
+:1037F000EF7C57E0336E21E9E30C79D063112F178A
+:10380000F2B26EC33571C88761EF9A1944DF458BF8
+:103810006710E46138BE66E74879B9FF711BE2675B
+:10382000B57CBD203F68A98C9B2E7D46237D6EE92B
+:10383000FA6BB6901C7CC7CAB2391C67DB7E181BBA
+:103840004A8FD21CA157F47EEFA1F64B797BF1FD94
+:103850005BB104CF4EAB07F084D3F18ABF7FC67C47
+:1038600045DFF7F0471BDFD70B2F9FF745D6FEBF8D
+:103870003E821CD91DE9F1D3D3368A3B9FB1B62DC8
+:10388000C4BCCF3C1749F2E54CBC58EF9F7179E8B6
+:10389000B7018E6F3D44FE8DDF4C6710DD8B02C695
+:1038A0007ED5B837E488731B75899E38C433EA38EF
+:1038B0001DD01FA7CB2DF4FDBB56FA3E7C1E393917
+:1038C000426EF7ACCFE7A2895FCE0C16F438F3FC5A
+:1038D00030DA573AE3059F7378D361A79C8917259F
+:1038E0008332C2F96089B443CF4C6823BBFB8CB6EA
+:1038F00087CA4EABF86E49838CDB72BE4B06DF8005
+:103900002711B7B26F6A871E01FFF4D8622A8311AC
+:103910000997FB99C19FD8879E94EB0B6A0DE43AF7
+:10392000C537483F69B3411EEB528FABDD7D79BC93
+:103930008CE2A0BB358AFBDCABFAE1500F50FE7184
+:10394000CE8F4BFD9A17F9464BD7AE580C7E5F5A77
+:10395000BFF976F0BB9AC7520B9B0CFBAA533313EB
+:103960003C9D917CDD000FA1E365F4E2F7FE1CAD08
+:10397000270FDA99447A2629D70FE688FD0AF566DB
+:10398000DE5FED5A6D138DE356F6A4989FC2134780
+:103990008B0D7E326EE78BF7FDCC5FC1193E7F0544
+:1039A0004F6B8ED01B3ADDAE87C683DEBF3293FFEE
+:1039B000F4E257A3E212BE462F83C5D6E32FE6F00A
+:1039C0003FCFF76AC0BF42CAB7A5F047733873B696
+:1039D00019E31FB9DB8DF511BB8DF5FCBDC67AE18E
+:1039E0004163DD73D4587F04E30EECC513EC5CE453
+:1039F000B5C1CE45093BD79523EC5CD461E7A284E1
+:103A00009D8BE7B07351879D8B3AEC5CD461E7A244
+:103A1000849D8BE77F9078AA957E47D081F2AB5E3C
+:103A20008E5471705A2F17E62491FC54F1CC0B8BF5
+:103A3000F3A9DEE3CF9966277F8ECAD3B93D4E7FC7
+:103A40003387E286EDEB5340374B07F97197FF4C14
+:103A5000F8716B8B231DF02F74ACFB6C3DD4A7C2A7
+:103A600038FD1DB4BF60EDDA29F2958224373AD6CD
+:103A7000B8DEBD5ED08FFC1C2AEFA612FB5D42FFB4
+:103A8000740C8FA3B04DC6B849781C253C7E12CE6D
+:103A9000072A6EF2A4B52B05F2FEE4D3F64D80FFA3
+:103AA000A4F48FB1D94ED2BF945EDDA37F3DA83D73
+:103AB000857DFB428EC8FBEB3EC6F5ED3EF65B55C1
+:103AC000565D2A26BDB1A7BE493351DE48722CEDA2
+:103AD00043AB244CE95A57E706C8BB1813EDE3176C
+:103AE0001D26B20B2EBE6F263D6218F4F390F90C22
+:103AF0000F4419F82B6F574258FC6FB0A1FDC80353
+:103B00001961F1BF11C6B8D46D6B0EC1BE9EBE69FE
+:103B100094A15DB5EF9A303C4AB8A55EDAB47A6BF1
+:103B20003AE4CFAA986E827FD5BE48CAABADE6F024
+:103B30007A11974385A3A0C6EE9D0AFCD5B459E33C
+:103B4000B1CF57C9FD873518F7E31A0BF33B137A4A
+:103B5000F9AEC6C9BCF1FCFB7345CD3B4D9C6EE78D
+:103B60004CDB1E19EF425CA935DDC9F9EA2EAD2DFB
+:103B7000E96ADEDFDF2C7ADA304E8F746BF00715DE
+:103B800090977B32D91ADEEEE4A6176349EF967C54
+:103B9000966E754681DEADCD66B20BE0973227F4A6
+:103BA000F2436B73625496A3779EBDF4FF8AE6C717
+:103BB000E9E2C139C56EC7E121ABA0C7B589F9D625
+:103BC0004CD0FCA427CBF9AC94FB0ACB12FDDC252E
+:103BD000EBA7A4BDA0E67776F8A14217E2988D077F
+:103BE000D2CD90E3A6DD3B717EE0DE28BD64D840F7
+:103BF000E44B66FF763C1F77C907225FF78F2D13D2
+:103C000063AF86FEF99CD53385D73734FFD806BB22
+:103C10007889256083DD59F374ABCDCBCB1B76B5AA
+:103C2000D2F385BB2AC9DE5EC4EAC98E3CADF26F11
+:103C3000253E6A4AB56D4E0EF793C384DCA88912FF
+:103C4000791BE5E6F1AF212FFDE22EAD08F3BDCDE6
+:103C5000B7C756C99FDF3A4C9E3B095B1FDD6F4FCC
+:103C60002F1F087F529B887BF6B71E660473693D41
+:103C70004CBFE4A2F2B64B23C88EFD80F90A484E31
+:103C8000E487D9B36F8B3CE4EE83621DD4D8820302
+:103C9000A6639DFCDC4AEBA48ECBAF9262D8C98CA4
+:103CA0008DE3A56FBCD9C0AFCBCBA20DFC3C9B254F
+:103CB00018E2C833716833A47EDB944C43FB59B7D8
+:103CC000E585F17F71EF7B9223E30C792675ABFDDF
+:103CD0002E8DF2594A8DCF79B99AF8EC26C3F77533
+:103CE000ECD6DE76B083B7FF9AF0CC58BB0DF65613
+:103CF0008D49E4D5CCD63BE5F30E7ACE27625887C2
+:103D000043333DBF15FBA295FCF2CA2F3D1BFFCEEE
+:103D1000EC6B5FE48496E3223F14FE05437E2107AB
+:103D200080EC4F26E85027FD3D75B9C2DF53E76FA1
+:103D3000B721FF96E3DF92CA51B2AC59237F1E6FC1
+:103D40006F4F4D10F5D578BED778DE00FD5DC2FB14
+:103D500063E64AAC97F0F7CBF8BCA1672C839F06CB
+:103D60007E26D5BFEC57F1E7A2AD46BFD132F8733E
+:103D700042E8F8C93017F1F3925D7B5E1FCCF13257
+:103D8000DD175F84F553DB36CD5A997F399F29F9CA
+:103D90007EB1C64471EEEEB78F109F75D758889FDD
+:103DA000BF091FCBBCC29F19CE7F0BF97C10975D5A
+:103DB000B857F30434D10E78190CBE0CC34B6A1FEC
+:103DC000F85278EAC15BD8FB45F8C768E40D688112
+:103DD000A0BB2FBC483CAAFEC3F0C44A8C7858A8AC
+:103DE000BBDE85BC5978CCCC025730EF45981FC656
+:103DF000E7F3C3F8B75E127E1215379879C942F51A
+:103E00001E3EF189FCE9DBA618D7650FDFF8C43A3E
+:103E100099712989BEFB9FE69F6FE21B0577787E2B
+:103E2000B23ADF737A983CFF32868DA1F57F8579AF
+:103E3000C36ABF57781E7A6F09E513753B32487F16
+:103E4000E8D96F9CC6F72B6332288F5897FE392527
+:103E50007775D94E8D53C9DFBB46818F8724C1EF5B
+:103E6000BA7E6D667A47885EA2AFB392DF347D4D2D
+:103E700022959591CE24EC17956BCC3EEC839FDC7C
+:103E80003F28A9047EF875D6015378D79FDC333AD2
+:103E90009D15A05E4EE5C9CD11B343FDD9AA8CCFC7
+:103EA00015FB46DDBDC769FF3A677A3B7636D6D942
+:103EB000BA7DB148A959BAEEBDB14EAE7AB45A74C2
+:103EC000672EC5495B773A8137676B21FCD174F661
+:103ED0007260AF9EB0645DF920F8BF6AFF7EE409AE
+:103EE000ECEFFA1A6B12F4CCCFDFE7FB9F46FB171F
+:103EF000E907A7917F3C0071AB683ADF765A635EB1
+:103F0000C46F169B0F153A0DFBE9C19980E3E528B4
+:103F1000DD953B06E3077626637C8F9FF225F5351A
+:103F2000D9717DF94B54B97CABD0DF762A7FADF4E3
+:103F3000EB426F471D7A3B8242D0DB5187DE8E1207
+:103F40007A3B9E97C25F8FB86A535711EC4E7F2918
+:103F5000CBADA7FDD5910BBD7C9516E581BC59A5D0
+:103F60007906C10FC6B6A7887D358CBEAABCB68BB4
+:103F7000EB5621FC7EFD253B0BCD1F9BC0E20DF5D2
+:103F800089F61443FB72A7DBF0FE86E4E186F7377F
+:103F9000BA8A0CF56FE55E6D687FB36782A17E4BD0
+:103FA000C98D86F6D3BCD30CF5E993E718DACFF0C8
+:103FB000551ADECF9ABDD8F07E8EBEC250BFBDE688
+:103FC0001E43FB3BEAD718DE7B99D382FDED20EC44
+:103FD000298EF79FC39EE2E5AA5F653B42E93A7EE0
+:103FE000A2A9BE2F7FFCA25CA1CFDC3FDC3B1FFC63
+:103FF0009126CF81A4C9F31C77E7BA44DE00CEED49
+:10400000933DDB9E02BE096F17FE7E7CF4E18B2E92
+:104010004EC3F6DC5B6EB370F930FEAAC3A33279EF
+:10402000DDFC74D36D162E57C65F73F8C50C5E8F1A
+:104030007EFA55511F79F822DEAF7E7A83A84F674A
+:10404000A45A243E3DEE363F9FC7F8EB33367984C1
+:104050003FA4CF7C4B55020FC85B041E5006397F2E
+:10406000A23CCCF913E551CE9FD5598CBDCEF913A6
+:10407000E5316E57E2F92FB95D89F26D6E57A27C7A
+:1040800087DB9528DBB95D89F2378DB3A97CBF51F9
+:10409000A7EFFEB3B186CAE38DF5F4FCC3C6062ACA
+:1040A0003F6EF4D3F3CDB9CA4F11243F8B8A272D2D
+:1040B000431C0F7EB803D6B3A17156150F54F1BF40
+:1040C000A67AD6118D75DA6189FFD4DE1BD7EB5F36
+:1040D000CE5AD8A721FA566BB4775B2EF92F8638C3
+:1040E00029AE239F976AD3D38A79F9854B7F0AEF4C
+:1040F000671457AD8B73E31C48BD15FCF281A9EF23
+:1041000073C1774B3EA91AEEFD09BE53716C15477A
+:10411000EEC94F0989739B42F262E82F24BF45C55F
+:104120009B553ECD7576919FA7E2C92A6F46F557FC
+:104130007E8991BCBB76A385F493180B0BA27F9567
+:104140001F73ADBDAD08F902D7D63A280F6D107FA9
+:104150006E2BA6765E332FB7FF99B72FEC8D5F0FCE
+:1041600092F0F3F7047FF9259DFCAED7CAF83DBE67
+:10417000B78BF77E7C8FDC29E819BC24BFDAE3C853
+:10418000732AEE8DA7A37DB4681F447F59FFC5C76E
+:104190008BED5D3F69096D45C8A74A5BE6A07CAA27
+:1041A0006D1382747E4B77EBEF019FBE08E7EFA3A0
+:1041B00069FD64A6C14F304DEABD5F4387E358AF48
+:1041C0000A3F0ACF8A2E0ABF21794784D7FEE81416
+:1041D0004E9F70BA287A945FEAC533F074391D7A1D
+:1041E000E9047FECFF2B74186D69A3F37F11B5769A
+:1041F0000FE0FA26BADCD9C526E13C7172867E371B
+:10420000E85379C9F53AEA556CC2246C4DEABDFB16
+:104210001BDE4FFE86F70BFB79FF56A4CA47F03A28
+:104220008A385D264AF9B1AA5CE077B2DB4CF89D8A
+:1042300098BF88F451E6107A9D8BFF0FF264D25735
+:10424000BEB5E86FD200A37EA8E2C137C9FE2687BB
+:10425000C5816F927AE34D617AE1B0E1323EEC665E
+:104260006E61F78973EE65729F4E9574CEE4C6FC5D
+:1042700078D091E91608ADA338E75E8873E07EAA8E
+:10428000DFC802547E8B0569DFBA990B38D46F61A1
+:104290008CF2198F444FAD58CEFB9B386A62169E44
+:1042A000879CEB2B193E86CEF5FDC11972AEEF70DF
+:1042B000998BF486C3F64CD263B00EAC217EB43732
+:1042C000B9DC472AC311BE2FA07C8DEF0B599CC9C6
+:1042D000DFE0FB02EA37E5AE61F86E92CB986FA2A1
+:1042E000BEFF96B3945946F52F77BF55F8F210F8F4
+:1042F00057DE8A1F5606BFF35BF1579561BE6FC547
+:104300000F328932C24665C14B597DE9598A0F7B0C
+:10431000C79BC42C8997E357E1331C8F0ABFFF0268
+:104320003EE7F785CFBBA53EDA6D7F2F363903F127
+:104330002FB1FEEB5E2A1804F83F0768C84BB60B96
+:10434000BC84FB773E6B6443805FB63D8E9EDF2D61
+:1043500079E8DA8671D4FEBA86129ADF3551FAAA64
+:10436000E13877521CCCE19A03FB6C5B139DBF3D97
+:10437000F7BCD903FDBBD6ECDAE4C15A7F4B9C975E
+:10438000635F1D4947BC8D6DEF3B6FB7D6AEF0E65E
+:1043900027F88B32BC778BFD4F9C2356FBEF9008A0
+:1043A00091EFAACEB3F6B71F8F8D12726548849035
+:1043B000838A4EFC3BAAA7F27EC672B991FA5014CA
+:1043C000E9DF2509DE07804F56C60CFAABB2ABBB5E
+:1043D0000798296EBD12F1CB01B06BECE4CFB98E1A
+:1043E000E5DC023DB80CF626C743F99B55744F81B6
+:1043F0003A9711916C32DE6FE38A32DCD7129D9BC3
+:1044000060A8C778061BDAC7956418DEC77B471813
+:10441000DE274E2E36D407FAC619DA0F9A5D6AA83F
+:10442000A7E83719DAA7D6DC6AA82BF9922A1EB1B9
+:10443000B4FAB986EF8736CC37B477FB9718EF9F7D
+:10444000F17BDB73932097C45FE6C69586F73F8ABE
+:1044500015E70E263B16D27D12D9CDDF318E6FFEC9
+:10446000CA0CFCA6C669E2BE0097907F7EFE3FD0D4
+:10447000B53CD9280F273A8DF630D7D734ECBFA9F1
+:10448000F516C3F337864BBBB7901592FCFB27E9B3
+:104490001C8E97EE32E609A23DF4155EBF4E1FF169
+:1044A00010FC0E6503AC9E0013FEEED079C1DF1D3B
+:1044B0008A07F8BB43EBF0771BEF6D32D21DFEEE9F
+:1044C000D0F7A38E19E93EA6DD48F7AB8E1BE9AE07
+:1044D000F8319C3E577718F9219C3ED79C0EE30F8C
+:1044E000498FD9FC7FFF10E798895E931C1A7BCC1B
+:1044F000FDAFD3E76F61F4E9A187C34EFAE275C15E
+:10450000BC38D4CBB1CEA037C8F9DC9057EFC88007
+:104510009CB4E9D611037BF9A72945F04FF7B117F1
+:104520002321F7224618FB3F9FAA47A1FDECC48B2D
+:10453000E936F04397B8AF6FBE949F2A9F90DBBBDC
+:10454000E23CDD77CC14DF3F616AA6FB920E3BF5BF
+:10455000047C7F677EBD86F84132F3ED59C8C79B66
+:10456000F78B088A27CC1B2ACE75B2FC0ECAB3572C
+:10457000726E5EAAC863193C42C6273D229F256D14
+:1045800084D00B633C4ECA7BADCC17E708B859907A
+:104590003EAF00F8783B12F71676B708FF7D8755D7
+:1045A0009C2FF5733E455C0C7A22F4B834A947354C
+:1045B000FDCE6E07FCC3B632C3BE383C6037E45D47
+:1045C000E6ED721AEA056DC986F6230FB80CEF8B7B
+:1045D00082B986F7A38E790CF531ED2586F6571D45
+:1045E000F71AEA57774C36B4BFE6B4CF504F655D43
+:1045F0008F02BF4335618FCE1821F278F81AA57863
+:10460000D2BC0DF1E2FCA0B453951EACF27175C999
+:10461000D7E1FAF4509B4EF9BD4D29CC43E700ECAD
+:10462000D23E61463D5B97F9B44A1F657E633EAD5D
+:10463000CAA3EDD1C7A5FEADF4E1903C5A6F681E48
+:10464000ED3C79CE377CDFAB1C21CFF385C13FD465
+:1046500026E6DB748F8DCE2D28B8C2E1392BF33BD3
+:1046600077D8FB3E3FB27C84B0637F96E95B3482AF
+:10467000974F403C65F6359EA7C3CFF9ABE97B3633
+:10468000CF7DAE6F1E6FDE48319F0A93E9CE69F988
+:1046900094B734FB8590F11B257F57E76B7DCE6F78
+:1046A0005E9CC82B62713617F8B7FFF1043E936D1C
+:1046B0006C2D9D739179E7776C6A7B102EF20A5B03
+:1046C000B355DC5F16B0821FA69472FDA988DBC9C2
+:1046D000DBFFEB870EAEE73CD160213FC4FA67CA2F
+:1046E0006770CDABE71CC1506E5F803FA0ABC02EA2
+:1046F000F94B9EC89BFDC9084665B9F9AB9EFC6F96
+:10470000F2A73326F70761B7F4C16FC4876A1EFFAB
+:10471000EE3CF0703C29BB90C9BCBB2C0997C25F32
+:104720008F1D2FF1A7F2F15D2BACBEA71C94D73FD4
+:1047300019F94C8A7E31F9822F7F27F181769047D3
+:10474000FDB52B37E7C7C15FDBCD5C71CEAFF1475D
+:10475000FEBBF0A2F0DFDFF99EFEE4C36572A19F0D
+:10476000F33EFDF127FDFD13E77E42E483C82F9160
+:10477000F4086499289EBB21C6B88EED79625F78F3
+:104780004EED177E6E4F1AE504837FB9699D59CAB5
+:1047900009B16F63FFC4F305EBACA4CFB006918FF2
+:1047A0005C23653163BEA471A3118FB5D27D56D74A
+:1047B0007919E93BF31DB6402B6F5FE90FDFB7BDF9
+:1047C000F43DC56B5CB8B7C4B31EFEF7AA8DC676C0
+:1047D0008B1CE25EAF056176E92269972E0AB34B26
+:1047E000FF3A42DAA51EE621BD4CC69F159C3D7CD2
+:1047F00015C8A4BC60D8A966E12FA17C2585271720
+:10480000E20B21F768727C46E562DF5E6BE9338F6D
+:10481000AC079FFDC4C9CF224EEEC2FAEFA6F33F0C
+:10482000DD7B23451C4DC52F64FBB3FE8BF41EEDD1
+:10483000D1DBB9A2F642C4917AE21D6171936E8711
+:1048400029B604FDED16F72FA83C80257F0D143AFC
+:1048500043E29C7A87C99077115EEA6BF6515E401D
+:10486000AB45CFCC433EB2C563C77D91F73B0E2726
+:10487000E1BCF614E9AF0987B747AF1AAF8938A191
+:104880005FE8B9DD9335D273B95C6458472A9E3D21
+:104890008D0507A054F1037D6309E159C50F2A83F3
+:1048A0002504E78CA645565CD9D7F1E8EAF22857EB
+:1048B0006F5CA1234DE4A3F4175F987EC943FDDD2F
+:1048C00076691CF5539AE716E7F5D73EB8027C34B3
+:1048D0006217B3629E1D61F9D8AA7C214FC89F77E9
+:1048E000F394DC96792E6B34A1C76B4CE5BD90DC5C
+:1048F00056F58BCDB25E2EEAABD6897A87BCC768F7
+:10490000A7F437609E28311FD8C5BBA53F02F340EE
+:104910008979E039E414EA9053A8434EA10E398511
+:1049200012720ACFE7335F7A9159C441CA42D60D59
+:10493000E22065217A10E220A175C44142DB230EFA
+:1049400012FA1E7190D0F7888384D61107096D8FF3
+:104950003848689D95DCD85B875CF34E33D4A773E9
+:104960007DBF2C64DD220E12DA3FE22086FEF415B4
+:1049700086EF6F670D86EF1107096D7F6783668885
+:1049800093DC29CFA5576D4D20FEB8C9ED6BCCE364
+:10499000F4FD43F4DFEFB6C20E341F5C4CF6595DF4
+:1049A0009447D0B979B2A0BB89093A77CD213AAF03
+:1049B000B6897AB9C88BED2BDE509625E20D281109
+:1049C0006F408978034AC41B701F36E20D28116FAF
+:1049D000C073C41B5022DE8012F106948837A044B5
+:1049E000BC0125E20DF80EF106948837E039E20D9E
+:1049F00028116FC0F313887B64F5C205BD3DCB6001
+:104A00003F723E34D88F4E431D7A7B687BE8EDA120
+:104A1000EFA1B787BE87DE1E5A87DE1EDA1E7A7BBD
+:104A200068FDD00817AD33E8EFA1DF417F0FAD1768
+:104A300034FB5F838FE9E66DE78FA2EC88D19ED0CF
+:104A4000B82808E67D3C0371A48E482D3D9E2F7941
+:104A5000EB9ACE1965BCAECBFCB242D645F73BEB28
+:104A6000F2DE1A3DC8281FB6E02FC9422EC83824EE
+:104A7000FD71BA17ED65640794CAF383EA7B0F737F
+:104A80009A51AAF6BDF5BEDB858FAFDA91BC0C81D9
+:104A9000831B8845C883285AED28461EF74E932667
+:104AA000F220EF1379A8E17CF527B96FEF34ED39E7
+:104AB0001C85BC964A8DEE8BCFB1B063B8C7BBA046
+:104AC000B9BE18FAC2C7793DF7CB8F435E8C825BC3
+:104AD000F901B99CA07355E3BB98AD3A1FF7893132
+:104AE000DB02C8779BD013F01DECC73CBFE67D2AE4
+:104AF00084BF3FCD137ABFEE5F31AE9A3FCFDB5D0F
+:104B00003F0EE7B5A64489EF7EF2642CE171EA5AC4
+:104B1000ED299C8B1BBF9B7971FEF282843B6FB7A2
+:104B2000D3564DE33AE99C578FBDB22D9DCEA55586
+:104B3000B28EB264F2E56B748FB9C21B9FDF51CCA9
+:104B40008F8BF86356D247C5799128795E449D13BF
+:104B5000715B7C7B608FA8F322D78E8E2F47BE16A9
+:104B60003B28EEDDBB7974E5BA81BC7F3D20EEDDEC
+:104B7000BBF64FF5AF517DBBB8778FD8602C8D4316
+:104B8000FBDA30BF46F73D4CF5B79A06B8707E7435
+:104B90008D3509ED77330FD49F614C9C8354F0E53C
+:104BA000B37613EE1DE75BCC91C4103EE29C7A1BFA
+:104BB000E85EE4B1D27D10D32C4E2BE446F83E7E65
+:104BC000793E5D989E10960FD1B4FA78BA3903FEFB
+:104BD00024932708B9B52F9AF405A5EF54CA3CA829
+:104BE0008B6B5FA3FBAC2BF708FD40E77200F24F25
+:104BF000E547D46506D24DD01706B7162698C5FEF0
+:104C00009FCFF178C6FFE2CC1217CE31BE46F9FA3B
+:104C100095EBC6C489F33A22FE502DF1542DF35F73
+:104C200058BE33097AA7BAC7B4DC3C3E8ECEBB353A
+:104C30000B7D4EF9772A7F35EA75D0B9F271791F6D
+:104C4000C8C64A3A07149E87A2F44375DFC9E2B585
+:104C500056CA6F591CA6072E957AE0D2303DF09ABD
+:104C60007CE99F517AA0BA9F4EB6A9FCD59119A4B0
+:104C7000A7D48BFBF82AD608BD85ED11F7D857AC21
+:104C80009968C2BD1515FBBC1EAD0FFE7857EA2F03
+:104C900053306822F27C065339F3523295B32EE535
+:104CA000921CC0590CD0BFE36546FAF47B525F9961
+:104CB000813C3F9C8FF347C87C3E46FA5211739665
+:104CC000436E8CF06A47E0BE9E62D5D7218F704A52
+:104CD0002BA3F3303743AFE12F6643CF19053E775F
+:104CE00097D3B980C91A9DAFB879F40AC9D79CCFB8
+:104CF00019F8DC2FF9D647F59EFD40F2B7EEEFB478
+:104D0000D0BDAC7ECD867BD97469CF2AFE0DE7F38A
+:104D100079F2F7269843F8997AFC50001697ABF889
+:104D2000C7CE84BE380FBEC1C1929076D875E2FD61
+:104D3000DDBBC7CE5C8B1CEBFF4BFF4485FA1D0629
+:104D4000AE67419EDE7157916D7E885C292D2C6D7A
+:104D50002918D84BF7F93DE7C6F20741FF5F797F85
+:104D6000F6A0AF3BBF58C5F18CF5312FAEE36EDC3A
+:104D70008CFB703EF39625E33E66A62E9109225FDA
+:104D80006DAEAC1FDE7DE77F6E74107EA8BE39BFAE
+:104D90007CA69FD68B9057B7435E9921A7F487F2E4
+:104DA000911F64EF98047A44E777C9F3F0F21C6B23
+:104DB000983FE270BEA043B85FA22A5FC8716671D7
+:104DC000A5DF4EE7545DE4D753F07F62359E1B5458
+:104DD000E5CFA47DFDEFCAB7FF7392FE2CE6F788FE
+:104DE000499CDF1E6C6E66D23F247E2743AE1F2691
+:104DF000EF33E8A53F971AA0FFFD9A3394FEFA46D9
+:104E00004D9C9BEEC78FC372BB1EDD013F5EA3F8B6
+:104E10007D8E2773041F3DF91D1BE9DF15B6F6D7FC
+:104E2000704F93C2E3470DFF61A5FBFE58301BF79F
+:104E30004FCDAD8FA4FB5E4B0B7D8720F7A2F33DDA
+:104E4000448F9602C1671D4EDF513CAFDB74E80909
+:104E50009C1F5F7ED04DE71A2B0F14ADC7BD16A562
+:104E600085FA9B986FA5C369C3FEBD6C6D3CED6769
+:104E7000F306C9F385AC8BE2540AFF9DF9621FDD8E
+:104E800052C8E43DA732BF9E0BCA69867632AF385E
+:104E90006C9D28FF60B89F21FC3E81FED68FF227D3
+:104EA000C07F600BF12F2AFF8435F79339D83F2B51
+:104EB0006CC6F370AA4C289076AEB40317F4EC5F7E
+:104EC000F99306415FDEACD1EFD6543B5CB3AEE65E
+:104ED000F5EA6356640AB229092E718FC4FDE21EF9
+:104EE00089F97CBD42DE54C8BCA1EAAD25B4DEAA76
+:104EF00003BC4CEC7F5DDEBEF948DACBE09FA097A7
+:104F0000CE89573BBDB68490755FD5AC19CE99ABB1
+:104F1000BAA9C02CD611AE302F86BC70DB70974B6F
+:104F200005572B9087965020F8437DC7DB511EC351
+:104F3000940CF6BAB8C787C3ED16E31587F43FBFE4
+:104F4000D9785E9EB7277DC8511023CEA73BF9BC08
+:104F5000E1FF703A094E8E07C253D783BC3F178DCD
+:104F600043F4A80A06ACB0B72B903FC1EB739D0188
+:104F70002BC699BF56DC5BA16F12E3E81BE36D05FE
+:104F8000D0972C4E5B1AF027EFB5E7F0911CACE6FA
+:104F900078C1F91F750E301C3F9512DEEAE678A342
+:104FA0001ED6BCD90A7ACCE9E7FCFC7505826FE70E
+:104FB000AF9D40E79FAB2D5ECAAFD7257EFFB822DD
+:104FC000F201C407E6B46CB1BA79BDB040C899EB40
+:104FD0000A047F4DC90866D3FD342B223D80738EB1
+:104FE000B399E6D783DF87393E34DC83E223FC7252
+:104FF000BEF0238FACBAC548CF5E7862C43D462D63
+:1050000095B4DE165A749B33148EAD87B271AE67B9
+:105010000E5FDFB8778739753A6FF3E9C3B3D269AA
+:105020009E1C4EE035C6E39A84FB66389F101F2B0A
+:105030007E51E783D578330BC479C799057DFBD7BB
+:105040007BD7A597F49B264E5FF8BDFB5B97361C7C
+:1050500034E2E3DAAAC53D60E1EB54AD4FB52ED59D
+:105060003A55EBF709AB2F98ACF5CA19BEDFD6BF9E
+:10507000D0079E5A0A841C992BE9CAF17A34F45C51
+:10508000D1F7E47AAEC830AE77F447F7064ABA579C
+:105090009406B3710E50B557E3562488EFC0F7E07D
+:1050A000B7A5723CB45F49ED4D067951D5232F76F3
+:1050B000AF4B82BCD8A391BEBBF2C12369DF861E71
+:1050C000FB9CD063CFD4EE589602BF8125901E7A08
+:1050D0003F537550C887055CFF81BC5828F7E9929B
+:1050E0006CFD3B0521EBB7FA87CFE5E842BE042112
+:1050F0005F3E7EEE950FC6B97AF74F05FFFC8DBF78
+:10510000B6563A42F1A5C9FB28BAE9DC5795C3E681
+:10511000429E6DD5DA4A92B72C99DB135A489E54B9
+:10512000181F54AED5E8DEACAA86B101F3FFA05C2F
+:10513000AEDA348DEEE6517452F76FA8FD54C1FF1C
+:10514000B8847FAEE4E380946B736BDCB685B4EE19
+:10515000DDB62AF0BF7C3FA7DAF8BC874E3D71EC84
+:10516000FCF5C9F21C0BD9259BACC2BFB73B86F43A
+:10517000D5332B5F7A67266FF7C523ADE9D04F147F
+:105180001C8BA41F6F81F4C72D947A2BA7D34F0BD0
+:1051900042F25B163D29E854F5FCAF7E8FFBA12A55
+:1051A00032A43C7B509C2F9FDFB687E83667E366CE
+:1051B000AB9BB7FB4581DB20A7ABEA8B9CF04FCFC5
+:1051C000DDD86A851CF8859437E1FC5E21F3521521
+:1051D0005EB1EF6821F10BD51EF26F0F1FE7AE1520
+:1051E00091B1C87351E39C967C5C551F9F80F1AAD6
+:1051F000EA2B7F00BB47C9FBF075773252AC87F9C9
+:10520000BC3FACCB93133C74CEB642FEBE5478FB8D
+:105210003F48BAFDC82AEE114C8D6E7B9AF2169665
+:105220004779201FB2B23A021817FC0CB86D2671EC
+:10523000EF60566DC7978083ABC5949F8212F71DB0
+:10524000414D4EE2F5A74CE23C50865994D642C1FE
+:105250000F704DE13D1BD041F79F85E4671AF8D5EB
+:10526000C6B66FC4FD2BB6018C7EEF45F1A7EA47A9
+:10527000F1A7E2DFFEE6F7DF5738BF936EE987C894
+:10528000F5A4E31CC5BC8786D1FDFCDF344F9BBC75
+:1052900007AF67BE11E2770B2E9B6F968C8FF73BA3
+:1052A000DF96F2A43EE61B3E4FB54E54EE754F5CC2
+:1052B000A159C4154E6A7CFFE2DF9D5C1149795FFC
+:1052C0006A5ECAEF7DA5F9F2EEC2049937DC1103DC
+:1052D0003DB242FE1E040B8A3A9E4F0B79AEF67D1C
+:1052E000756F9892CFA7EAE5BEC83A1EC47A660DDC
+:1052F00099744FC689E69331B8BFE3E404019FFA7D
+:10530000EE2EAB38F7CA626C2EDC9FC8ED2BFADDAF
+:1053100087056B07911D79474326C9853BFCF1C280
+:10532000EF20F5FB85520E46DF55B9FE2AB4DFEAC1
+:10533000766A7C9C050ECFA75BE9FB3C0FF4C1E8C5
+:105340009669B60CD27B851DA0E2407769CC47E711
+:10535000992027B1BE4C87B2B0EF2CDA2AEC802915
+:1053600026B611F1C2A14DBE492990138F8A7B2325
+:10537000D936E3BD4A2F66FBC617026F61F791DD90
+:10538000656DF30E821CE7FA06FC4C0B1C3ED2DB6B
+:105390005F9172F2444B27DD4FAEF07AD939159BFD
+:1053A0003897DA156322FFDB959E57A996F124C53D
+:1053B000372A1EF518FE7335F064A27DADDC5C4122
+:1053C000F7FAAC6F994865F5E6F247FC05380FEB44
+:1053D0004B1A47705BC93F565D37519C1F7D2A228F
+:1053E0001EF64DBAD59F1EAA9756B76EA0732AA770
+:1053F0005B23E99C4A99735A59FC00BA6F97CE7D9A
+:10540000A976B585623F5F5237D170CE6401EF1344
+:1054100079B07F6E8BA6BC52757EE4DE287D51E1AB
+:1054200040718EE46A97383F9242ED5D7DFAC35534
+:10543000F969A3388F10722E66EA1CFE7D6DDD8B34
+:10544000B1E867E9C3EF8DE59881FF6915FAEF3997
+:1054500017B3559C8BB90BF612F4C804DFCC39C0D6
+:10546000FF9B66C27F7FE3D5E0474942EC883B0261
+:1054700071A4B7EA4166433C597732D28B4F9B59AE
+:1054800003F400A5BFA8E71B245E4EC735A7833FE2
+:1054900016EFDC928EFDE5F31851AFD839EB9790FB
+:1054A00057FAF608A19F5B18E9C3557EA15FB39A2E
+:1054B00004752F66E43CCE479B0BA3C53D3DF2FC33
+:1054C0008C824BDDB7FAB945DC17837331E0F78F77
+:1054D0002CC105A0EF475C7F851D5B2BE5D847CD30
+:1054E00066FADD113F5F28D0433E6A7E3106E773DE
+:1054F00095BE566EFED88BFB6856EE13E75471AF1F
+:1055000039DD5929FD20CBA41F64E5CBD649F8DD50
+:1055100011AE7FD1935A4BD0D617FD9648FDAAA75E
+:10552000BE770FD96DB5BB85FE50DBD649FA83D265
+:1055300047D4B9B8A5BB3B499F50DF2DDB2BF052B8
+:10554000B7573CAF44DEBAFCBD502D0BF6B446F560
+:105550007776CF9DB5C6509F43F577F2A5BFDED2D3
+:1055600045FAE003B9BF213BBC6EADEC97D7AD2146
+:10557000E3ED07138D11CF331DF8DE65D01BEAF67E
+:10558000C6D3F7C1BAA88DD8E7BDCB1C16944D750C
+:105590000EDAF7B7D59B722DA3015C94077ADC4134
+:1055A00099BF3570E97F46C27F90C2BA8EE0DED7E0
+:1055B000C34EFD4DC819F57B96EADCCB85573F1BE2
+:1055C00085FEAF1BDA7111773C58B585B3109FF893
+:1055D00075A19C477EC728F0F5C0C3423E3F6E656B
+:1055E0001BE9FE608B8FC16F1F947145FF5F4CE21A
+:1055F000F725B4E08F43F52BEB48B19FFA22447CAA
+:10560000B1C8AD7F08386ED1AC0545B0A95DE66C78
+:10561000F4AF7E4745E9A9A5523EA749FBCA3638F3
+:10562000D9013ED6BC5E3A87785FFEE12AECCBDF3B
+:10563000EFB2D3EFABAA3CBFD2AE28D25BD3064FBA
+:10564000A6FD4C7359584531FC2AA620F255BFCF10
+:10565000EC222FC01EA6D79A22291F593BF8C65FFD
+:1056600020CF53CD5F1EC1EF94A47E5BA3FB2FE739
+:10567000757FFA387E63A682058AE81EBC78FD2213
+:105680004877A27B72A7CE49F67D679BDD23F6099A
+:10569000160AFFC17BFE129B60EA85EB42D7A77416
+:1056A000AFE0852E3BF96B4B0FCAFBF6C2E0B99019
+:1056B000ECA2BC68DE8EF4CC0B0E13DD33567AF010
+:1056C00008DD9B57AAEED5B31BEFD563AEB478F8CF
+:1056D00093C987CA9582A42641B7EBE28C7662D241
+:1056E00048A127268DD4E43DA5027FDDF6F36FE9BE
+:1056F0005AEF3A5CAEE2F7EAF7A66A22E8F7A6BAF2
+:105700000F667EEDFD09EF417FE07AC1F732BCE91B
+:1057100023C7F4EE9F33245ED43E6C96FDCF90F801
+:1057200099E130097C84FDDE86E20F457F05AF3AC2
+:1057300077A4E8C6BED3FE1ACE05717A153CC4889C
+:105740004EB918FFC45FDE5E8763FE83CDDE4EDD9B
+:10575000FD6FA15310F7E05C319DDAC3E9148C1C96
+:10576000063DE161F1FB5BE1798D2C97D13A9F67B2
+:105770008E223FA02EEF05E7EBFB35AC6FB5AE8771
+:105780004EEE28C0FE78829BDE80ABC3D446CF1796
+:105790008DCCA0753884B5A7C8FC9B31D0CB9AE4DA
+:1057A000FDC73DBF63B8D841F78D5C08A8FB8F03E8
+:1057B0008F2EE4E3B6CCC827BFFE0526D77B4DCF9E
+:1057C0003DD9E2FEE39E7BB2CD7EF293CC89223FAF
+:1057D0004FCF3DD9D9E2BEEB573496837B68FDD3DA
+:1057E000EC941F1F7E4F36DF679E463CE3B19A283C
+:1057F0008A43A9FB914B9D7AE5C88197DF8FFC888E
+:10580000E69BB300FD1538A8BF8E3951CFEF146861
+:105810000EC28F73A22186EE85567CA9FCD743FD6C
+:105820009D8F024FEA5CE71F247F29BCAB736D0A92
+:10583000FF8ACFD47DECDA6AC16F3D79B2CB18F91B
+:1058400047867010A229EFD1E3029E1F8CD71B0060
+:1058500077D30A2E37C82F2EF2374F988CBFDBAB89
+:10586000CA26B92E99CCFF9F27F7A9792ADFBFC195
+:1058700098EF1F7E7F66629C6F1DC63BA7BD3716E3
+:105880000FDFFE6F739FF9233F90727974B4FE208F
+:10589000DAAB730F4A2F7CBBE8B334FA9D91AF8E1D
+:1058A000D0EF29CE75FA9AB18E22B3441CE00F29AD
+:1058B0001D744EE30F73FE9A467EE4D5E2DECF2BD5
+:1058C00085F3F273B4820F562D107986A9AC9EF839
+:1058D00036B9F77C6624E0F8FFED1C6DEF39D7C9C7
+:1058E000A34E51BE858F7EA7229C1EE3230EBFE8E8
+:1058F000E216CA1B233F9945E74EE30EAF72F3FA57
+:105900003B3FFD54D4530F5F74E35CEA4F3F9B452C
+:10591000E74CF30E5FC439D4DFFCF4B4787F0DA3F9
+:1059200038D6FB3FFD7C16CE9DDADDFA07A0EBCC26
+:105930004BF5AF615BFD60CDAD0BDC748E725A5AD6
+:10594000AE3847F916E8392369FEBA38ADF71C6559
+:10595000F748DF07787EE14BC1E76EC4C006FEEB77
+:10596000A53A47AAE46C7FF250ADB77FD73958B556
+:105970007ED94ECF462B98D0FF2F9F4FED12FB992B
+:10598000F17CEA6BAFFED685BCC3F1A3EDC4CFE3D7
+:105990001DED2EF80550875CDCFEA538CF87769686
+:1059A000D07603C439BEF1384F01FF41B73867F8EC
+:1059B000DAAB6FA440DE8FAFB7519ECF16F9BB00B4
+:1059C00031A643668CF37F00B1492F16008000009A
+:1059D000000000001F8B080000000000000BB53C19
+:1059E0000B5894D795F79F7F9E30C08008288A3F38
+:1059F000820413A433BC345BDB8E0A14A54D31DD65
+:105A0000A41A098E9120AF01D4B671B7C9C7188CFA
+:105A1000519B74756312638C1950D434B83B463073
+:105A2000A0D84C4CA4C63C96B05BE2B7DBF86162F0
+:105A30008CAF0C48926EFCD6D63DE7DCFB330F20D2
+:105A400026ED2E7EEDCDB9EF7BDEE7DCFB4FC430DB
+:105A5000634D1263530C8C19B3188BD733668A616C
+:105A6000EC591DC050EE1D665E4D246353631A56FB
+:105A7000B31C28CBCCD6A664067F6EC672194B9C8D
+:105A8000E09D6484FAC4B57AAA8FD0F4290D66C665
+:105A90007C8DDE45E75319CB0F8BCC64DF8152CF71
+:105AA000D2B5D08F69C2ACADB05E817CA32711E0C6
+:105AB000355D920D9666F986925D2C85B13A2D0082
+:105AC000B1F83F93BB15D7D1F656ED877E7D71892E
+:105AD000D62D004E4938C252B3617C7D51069BCE13
+:105AE000D8098B638A7522B4B3AD128E0FCFE0E371
+:105AF0007F5A14DE22C3F8C1E3B7E53AA0EE6E8305
+:105B0000D2C1AC8CA578A29768EF04384AC9952C0D
+:105B1000005B63976827011CAF7448D06E74452FF3
+:105B2000C99F84E7335ACEA733F63326B12899B1FB
+:105B300064AD231DD771167DA6671A6C1FD297CC52
+:105B4000622CC36A213C4C3C0178827D0E2D8C7006
+:105B5000B7C0F95886928BED49BAA1480BE063F0C3
+:105B600086B6C86DA671917F0FF537F1EF078CED02
+:105B7000EE96A95E85D5D267854960BDFA54F313C8
+:105B800088BFBA04A391CAEE6B850CE7D196A4DE58
+:105B90000DF3D8F56C7949C6E8F103560DED2B7974
+:105BA00023107432AECBEC4C81FF0B632AEC627392
+:105BB000186BFE2554FC1D6F879330FD0C8D806D96
+:105BC0003BF25383FADBB1BFBF9DD98DCC3FFE7E44
+:105BD000EB8C1D1BB4623DA4730573CF802324B2EC
+:105BE000068901FE129897E8B3DB1643FBA23FA09B
+:105BF000D30BB1A6E62DD02F55662E531695CC02A9
+:105C0000656238AC07ED89AF99DCC8577B4DD00E83
+:105C1000435335BCDCABE1FDF561CC857C3A1560C6
+:105C200006E5319BA3CE3691E6F1D23CF2211BF280
+:105C3000E324E6A1F5E3998BF6A3F69BC27A4D081F
+:105C400033ED501AD26BAEAC19139F3ADBBCF5485A
+:105C50007F5FA39D7DA20DA05378E4BA40FAD5E101
+:105C60007873E0B8F9344E1DEF5CA7619F4CC0C358
+:105C70007B897F9CA91ABB3B03C7B137A52CACEF2E
+:105C8000D59744F8C7F5371AD9274087FF68645479
+:105C90009E69B4D0FAFFD99840E51F1B15AA3FDBD7
+:105CA000984EE540A395EA3F6A9C43E5BDCB22723E
+:105CB00090FFEB3BE7B14F8C1CED37E17F4E8FCE71
+:105CC000311000F7CF1B9B8FF60B3EEA4F1EBBDD5A
+:105CD0008BEDB8CFEF737A0E3EC8DC2DC9C4971B8D
+:105CE0002C31A3E90FE733E1F90623D8120FE0E9DD
+:105CF000588E44F30F4EE270B35547F3D9356C0715
+:105D00008E3F96A3E7F34FD75462BB3D86CFDB9F10
+:105D10000630ECA768CEBC17114FF638A8CFF2C3F7
+:105D2000FDB7F376FB645EAFEE576DAFB359685EB7
+:105D300095EE833A583F83F89DE657FB7F96C7E57B
+:105D400030B4BF3B5553E41E031F1A1BEF4F7201C3
+:105D5000F870A11C2407C8459D4272A1F2A1CA7F18
+:105D6000BB6D1C8FA906C1E7E12007312407342E43
+:105D7000311EE44022BCD8199C67AF24E425541E90
+:105D8000A0443DAECA832A072ABF27829C4931FE20
+:105D9000737C2F845FD5F29495D3A5372EE21744F8
+:105DA000D76E9D055421F40742C6207C4F8E1DC638
+:105DB000153C6E6E184B7FDDB4FE8D7850F5C13802
+:105DC0007818757E3D2FBFEDF949BFA1DE46BE1D97
+:105DD000435F7D6655F515E75B9DCDFEA915F95529
+:105DE0003269A528284D9C6F42CF7F2C87CB8DCA66
+:105DF0003FBB6D8CDB4B3C67CA687DA79E67E49C0C
+:105E0000AB18E9BDD4305E1F4A5FF55C017AEFCF75
+:105E1000B82F159F8C796C1698674AADD9BA25D9D9
+:105E2000CFBFBE89D72BD07E6DB62AB49FE735325F
+:105E3000D15FB52723F592BC7C7146909D6116A079
+:105E4000E3D07103C9B757C32A5F8171ADB8D49D40
+:105E5000FE73CF16F41B5E3243B30EF6E5FB93D907
+:105E60008576CB3779E8AC04E37D3B74CC45FE8383
+:105E7000FD47521C630F824D41BB7415F41C4B63EC
+:105E80004C7EEECBB312ECBBE239991900753E5053
+:105E9000DB328CAB7F3AC26DE4E3188371B5625C90
+:105EA000D38ECFEF45FEBA00FC6980F64F4C75D318
+:105EB0005926630B9ED3111E2B22F46EAC7F63C751
+:105EC00053A796017CA15D52D0DF2894CDD45EFD0E
+:105ED00092ECC6756ACD859724F0737CEDCDCF84A6
+:105EE00041BDF3808E99605C61BB64F5C2FCAB3C44
+:105EF00011881956B15DF7D140BA5F6FFE50D8B125
+:105F0000CABD921B388655EE0A6EAFDE1B0CD73227
+:105F1000AD1F86F9B36C11B117EE006026B3DD44F6
+:105F2000BA6D8F416335A2B743F90ACD36E9C7355B
+:105F30005C1F33F645DCDDC097F2F12F933E3273E0
+:105F400078B180CF01FCD9971CFF2ADEEA84CEFF0E
+:105F50006C12CBF1C039EB8E9B2C2E38585D974CD0
+:105F6000E7F079A208CFF5610377919C1E952DE8A3
+:105F7000876DEE945DD8EEEC36EDD1C039EB3A2466
+:105F8000A645B8D3E0E678BA5681EDAB3A4D160592
+:105F9000DB8F1A980CE37D403713D271EA00D11FD2
+:105FA000E9EA92680B3F92F2FCF497915EB17E7A37
+:105FB00035EDE0FBB97080D3A7507E584BF46A965C
+:105FC000587C009D7FAF7979845ED86FC1737FE87C
+:105FD000413A57C0FE0C0AD25D263A5F00FAE0BC97
+:105FE000FAE39F240D98FDF49681DEBF52C743FF6C
+:105FF00055B7A07725736D447FEEDBD2395CC83F7F
+:10600000F8BD179E47BF37426F453E8C15FEF1C461
+:106010009AFE93B1B06059CC15E76AA89F91F00A37
+:106020004B053F418A763C6483716717BEFB18922B
+:10603000A36FD1CB36E48B26DD40EBB350E18A0E63
+:10604000B7A20C0E262FDEF52AAC931F733DE91084
+:10605000CACBEF0C1664A726218FF86704FA3B1908
+:10606000C737D0F11C9EDFD96DF01A008FACBDC0D0
+:106070003EE20F4C477BECD1A39E2AD00F95AD4654
+:106080007F1CE6C37524602394EB9AEEDF9F91603A
+:106090009CA4C4B252848D66AF8CF3B4E9AE8E9CDE
+:1060A0001BE6912CEF52BF5DB6E9B48F94F8EF294F
+:1060B000A87F9A96324758CAD7E979467AFE059D55
+:1060C000D0EFE3F97FE3E87BD5EF63AE29D117602A
+:1060D0004EC405971FAE7756CD61E24FC885802B21
+:1060E000D7BB228DD079D51DD6043CFFA7C86791B8
+:1060F000C87FEF6827C0BE6A5B25A25B1DF20F9CBC
+:10610000EB24DA37A81FF4083DF2526FFE84582CB6
+:10611000252B482AABEA96AD5E68AFEAE4FC348AE8
+:106120006F84FEA86EE3FA63141FB5011CE0A7D5C7
+:10613000215FA930D0FBA85F7FCCBA09FB7D713607
+:1061400013F4E67AA240CE881A007E19664A942596
+:1061500023C06E49DCDF52F5CA6D3B40D507AC3B2E
+:10616000D36D64DA8075EF3860098267791282FA3C
+:106170007FA753096AB779D383DAB34F5983E0DC39
+:10618000DE3941FD679FB107C1770E1405F5FFEEBB
+:10619000C59220783803CE3396DF21CA1F264841A6
+:1061A000FD172AA6A0F98BD3A383E061B3C08FF0BB
+:1061B0000355FFF4A28DFB41A1A58ADF1F5B83D7A6
+:1061C00051E3E29FCC095E6FB13D78BD6F4A977D88
+:1061D000E0F76BC1AF3F00F611CBDF82FFAF05BF29
+:1061E000BE0DFC7F84FF05FC7F2C3DE0FF63FD2B93
+:1061F000E0FF23DC0EFE3FC247205E41B8B3B1880A
+:10620000CAA38D25547F2BFCF588754F89754F8B5C
+:1062100075FF5A3CA9A5B36886E62B90D3793197D0
+:10622000F4A887ED6B060A310F30F496CC5A504033
+:106230001CEE538DB1688F2630F45B58C9D0DB1A41
+:10624000843B522C5B14B443FFFE1EB6FBDA65059B
+:10625000F5F989CE8F23719EAB5F811C66E3B88F01
+:1062600023313EAEBDCE08DE02ED0AC00B0F8162C7
+:10627000207F06F41AF64F5561B79E4159D27648F1
+:106280008FF4A8397088DADFF2E882DB0F3407B5C3
+:106290005BB03F94355A37C5F7973BD5F9BCD4BFAF
+:1062A0003655B2A35F7CF9C0BFC75560BFB6F7E3F0
+:1062B000567E0DBE3F3BF27206EA7527D861AFD914
+:1062C0003F8FB34B2760BEEFDAD44385316808DADD
+:1062D0002436038AAB6C2B5B07FAAEA6B3B516F572
+:1062E000504DFA321D4B267D24F20DA06DD15FC2B8
+:1062F000E01EF077D5F379E44A98F735CFC9BBECC7
+:1063000048BFEE372271DDC17639289E5994C5FD0C
+:10631000D645597AA2E3D5F637221568DFEC7983A2
+:10632000E35BEBA5739F10F0209484E74E99CE5D5C
+:10633000F59586F0AFCE774F964CF32DEC9C1181FE
+:10634000E7EAF3F0F596672934FFC2D415E5B8FF04
+:10635000D3094B7365F2F34031A35EBDBDB815F3AD
+:1063600003351ED93E56BCB55ACCDBA3E37CF856A8
+:10637000EAE19EC9C01FA78B26D848E78B7E5559F6
+:10638000DC1F2FD43B52D12EF4999508E4E3478BC0
+:10639000522290AE27B0C4FAA23D7A0794D5ED7C84
+:1063A000BD3E4B6F24F25B5F7BB68C7E8B3ADF4A3F
+:1063B000B1EE085F8FD0CD4574AA74379B711E3F34
+:1063C000FD78FDF22C9E2F3AED7EFF5EF453FAD25B
+:1063D000C3AD48971E3DA3F8B606E88AF6A0AF3BCA
+:1063E000B119F1A0AEB73C4BC4C9E91AA2ABAF5387
+:1063F00027FA2D6B6541FD78FC7C756FF07E2CEEE5
+:1064000073BF598676E905F0ABA1BA56D71087E776
+:10641000FF7457F0FE2A059E6B75DEB8B8007EAD9E
+:10642000ED1A911733F177972A1F0AD153A5635FAD
+:106430003AF7DBFA120C6E8C176B0FB5125F8FCE2A
+:10644000EFF426A39F9FF89091F286B78A67553F95
+:106450002020EE6118C7E98A527235D3FDF67ED04E
+:10646000667F3E6B22C6432514EFF5B1A10A34FEC8
+:106470004EF483A350EFFEF1195C77B81DFC3D5834
+:10648000D769EC5C741EFCAC612B080AEC7B789736
+:10649000CE2DE21333FAA715C23FFD5471E4C96053
+:1064A0005F9DEB3574BEDA8C30EED70A3DF9D9A189
+:1064B000E49F20BFD69E922D46F443216E21B88DD5
+:1064C000FB05759EE47F9A8BFE769B8EFC00D5EFD4
+:1064D000700ABFE382F0672FAC1FD293BF7A5C6271
+:1064E0004FC13E2A3BB7F52442BB336311F9AB4E93
+:1064F000B98DF28FAB7604FB0555EE60B8E64030FF
+:10650000EC0CF11BD4B8ED44D688FF3013E38F02B6
+:10651000796E3CCAC107829E6A3CB27696351EE50A
+:106520007DB35659A4E603104FF5C70F57E17EDD42
+:10653000B561568A0BD61D257C0E7EC1E38EC10443
+:10654000C6FD23C6F13AD8C9F9BB5E27F13803D896
+:1065500095E6334AEEF5D034E81A8E24BDC45811BE
+:10656000CAC39AA53C8EB463CE15CA17845E0AB519
+:1065700097DFD70EC8D101FAE17C16F737F3F5CCD7
+:1065800081766A6D8495ECD63423F7B70B1EF6D866
+:10659000900FA6417C6C08C8674F330F49D86FEF46
+:1065A0002310E266FAE3FBC55A8B2E3AC0EE31B6F1
+:1065B0009EFAABF38326E1E36F35BF05E637FBE7D1
+:1065C000077C4721BE3FCFB1923D4E5ACC582FC9D0
+:1065D0006303C9A37A9EABC067988FC59C09D2ADEF
+:1065E00076D7EB940776B25E8A470A23F93E0A71A2
+:1065F0003F0887F19265737CD9B3B9FE589B1D6C37
+:1066000097BBB2ED5236943BB21DBA6CD26716E21C
+:10661000CBB58257C04F891F1843EFAE7997C75546
+:106620009F831CA09CDFDF2029A9417E10E7EF7A21
+:106630005EC5AE304FFF5CC483CBDE9B1E877114FA
+:1066400097ABE5EB4C4A6A009FD6239F035E2A2D49
+:10665000553F42BFDBB12E4EC17C7F3DF2FD7444FD
+:1066600023E7EB58F887F1C5283EF704C3F0B70BD2
+:10667000F9AB8E19AC6847EA3B43DBAD5ACCEBA4CF
+:1066800064831C84FBE52049F065B34372A3DE6F8D
+:10669000BEA1E579AC5289F256F74025F225FD619D
+:1066A000BFCA796E9CFF1E00311E62DB63496EA873
+:1066B00011F4C8DF8BF3DEA3F5BE8E727C52E7497E
+:1066C000C67CCA49A7D18AF32F65E070807E296510
+:1066D000BD54F687D775786972D7548C9B3F701874
+:1066E000288FD3BCA12502F56926DB60B9908EC640
+:1066F0009D1DB8993DBE5F018CC42EA874A1BCD06D
+:1067000056118772BAEEC8B6CFCBCE1D7F7CCD1F97
+:106710003AEEC290A2E617ADFA78CE36BDE9797EA0
+:10672000FAD5334F3AEE57A5D708FD60CF53000F87
+:106730004BD8501EC6352ADD8CF06F2CBAA9F84C08
+:10674000D20DFD1451067689F44B283D55FCD6B187
+:10675000061DCF7335BCB714FADFB741A3A07F384D
+:106760008ABEB7A083D7C49BBC1112C59BE3D14599
+:10677000A5874A9F33D17CDC99FB65CAD3FD5FD3E3
+:10678000A52BDBF1D0D7C963A8FC8D276FCBD785AC
+:10679000C86588FCA9F472AC8B243953E958AB3036
+:1067A0008A5B6BBB23AC6EE6A79F19FE21FDF09EB2
+:1067B00082F231ED12DB297D13391CA07B8D50FA5A
+:1067C000006FD851AF3F951D6C8754BA8DA77F5489
+:1067D000FDF521F39EB448743FC0E5F3970637DE1C
+:1067E0002FAAF703EA3DC061A1F742CB0FC1EFC06A
+:1067F0007B972DE97D13D15FEBD7ABF3F0FBC70F90
+:10680000D7F74E5D0DE33F9CC7CB7EF4D302607B90
+:1068100018CFC37D38C9E042BC7D28CD9C8F76FC63
+:1068200043E9A1BB381CAF57105E1A3FDF0270BFAF
+:106830004ECDDB3D2AF4B09BEF63E9EC7CEA27B157
+:1068400037111F8AC44A681D498A2982FD7CF88B4A
+:1068500019594DCC7FFE966CEECFBA55FDAEE6B120
+:10686000FF41A23CF672300116CCB7CF7FB6683A32
+:10687000D49FFDC7141BDDFFAD095E1FED6832E537
+:1068800007B7D13CDFFF6A48B722C3BFAF11FB9700
+:106890007F8DD797CFA078A252D0D01E3393C7B1A7
+:1068A000EE9428B447AA7D1A3E75D81C98BFBC0444
+:1068B000F68BE903E0994F2605DAB7D7F7FD3A0DD5
+:1068C000E7A9D4BB32AD184F363F9F847E40E5BE6A
+:1068D000C7D3C82FDDB7390DE38BCA965FA7D90997
+:1068E0000E77507CA3E5E7BE72F0CE3D5B02FCE084
+:1068F000EA5C99F65F6A7CBD00FDD345777CF618AB
+:10690000E6C367FCA34479B1FB59EF636837CBD288
+:10691000B91CB1ED46D2EB301FDD3BB6CEFCF15ECB
+:10692000D4E7A7D33FD69543BFEBD95AC24F1973CB
+:106930003F118FF9B04D12E5C3FCFDA7D23DE68AA9
+:106940000D923E2116ED61B44D56705C34EDE3813D
+:106950004DB61EAC2F7B98D72F32B8DBFB709E67ED
+:10696000F5D65605272A995E12702F7C3D9BC75D90
+:10697000CB9F90C81F57D799F14C5C73E039AF0B90
+:10698000FAB31BFF46FAED27822E3F7AF8FD371344
+:1069900014BC4F72DC443DF2DED31752517FE5C781
+:1069A0005CCA403E9FA177ECACC273B718287F98B1
+:1069B000939928C743FFAC9FCF7B0ACBE50FAFD895
+:1069C000598579D01D468AA3D4FDAD91140DC69B7F
+:1069D0006F34FFEC01C4DBC5A78DE447AF69BE2D62
+:1069E0009E8D21A76AB91FE8AFA431F652A391CAC0
+:1069F000971B2D4C81231E6C4C20F85F1B152AD948
+:106A000012CE5F6B44BC3ADE7CD910EF2BA0AF7284
+:106A100036C17CE06FDA4CF6C93980AF19B73B5B01
+:106A2000368B73CD80F13657F202C443CEE6D53DA6
+:106A3000E88AEA73787CF476DFA624F2A31F3EB7D7
+:106A4000BB0ADA17E794A4E078E3AE6B14E7BFD192
+:106A5000F57819E5F55B0CFC7CE2DC179F4E8BDFCB
+:106A60008979D7B774147FD7EF3AB77B33942B9FCC
+:106A700058AD0FE4F76F7ADE64B19F5BC9D57878C3
+:106A8000F8F672F5EB24929F1690AB8CBF5EAEEADF
+:106A90001F5E4FF87B28A764510EECFFA2CE9584B1
+:106AA000F27471E6F788CF5DC725C2BFAAC7D5F1DA
+:106AB00045E2BC351ACF13E40F0A3DFE25447E881B
+:106AC000DFD7BB3E4D437FF8CBCEA55F7BEE238D5A
+:106AD00078838E792D2395A1ED797A478A15CE9703
+:106AE000A7E17EF028FF55DCCFA9F7EDF88779E123
+:106AF0005A613F9DB0B1A818B47F92372C13EF397B
+:106B00007E78498BF117C4751F05FB97ECA3003BFA
+:106B10003EDE7E6F55D6E13C5ABFDE9D7D46C3BC4E
+:106B20000176FBCE8130E60D587724EE30224F43BC
+:106B30001CDA3589F402D20DEF657C5D335B10BE43
+:106B4000A4E774F41D81F88AE755989CE73FE7A510
+:106B5000AE2B99A86743CF5B77F40AF1476DE7E363
+:106B6000D7243AFFC24BDACC5B9FFFF57D573291B9
+:106B70007E977403791847F9F403994887BA635CE0
+:106B80009F7F5B3CA8F5559BF43CBF2759281E2CE2
+:106B900090AF521CEF3BC5E3F8BAAE3DA44F87BBA4
+:106BA000793EA55ED35B188FF98786733DA8CF86A3
+:106BB00013787C05F3DB116F7353841DD40E252DE0
+:106BC00006BDF6CA083FF0B8EE22CAAF1EE7F1D400
+:106BD000D27BA4CC70867EC5659467A82F5B97BCDA
+:106BE00011F9FCA27B226682D8DB99FF5347F9B7E3
+:106BF000D7C22D32F9AD501B40BF9173B865FE70FE
+:106C000086A9717A38B307F4ABD72B3FA1F8F834D3
+:106C1000BF27ABBF9DCB133BCAE5C9B9E1757D4228
+:106C2000C07CBB519E68DFDC7F5CF4DAFF905C7651
+:106C3000DBECDD2897E1A80B71BE8428B724897EA0
+:106C400079FE7B4073B788C78B646AAFEF94D92411
+:106C50001C931041F7F5456CAB16FDDD45CC339721
+:106C6000BF9319F8CD77A1BDF835391BDF6381FFDC
+:106C70004CF7C785618ED435E81F692481574FCE04
+:106C8000E2407B26DE79CC9525B2634393C2C94F9F
+:106C900059B8C4598AFB1DD10F5ADE0FE6213F8B2C
+:106CA000B98732F13E93798732F19E53ED77EF6BDE
+:106CB000E10D64179927E7DE8075C272B9DDFC1C0F
+:106CC000EF9F419FD48BFBCF02F9C6331847AD39F4
+:106CD000CEEF09FB35C91FE07B2D17E019E97A05D6
+:106CE000E86A47FBE360763BCACFAC896E949FFAB3
+:106CF0008312C3776B755D8616CCEBD4E906E29000
+:106D00009F3777FE418FFC5CDFF1BE5E9985E379AA
+:106D10001E08FC750DE2B75ED82F67E76D1F60DEB9
+:106D2000CD798A5B51A7F67D8AEB6BDA0F51FC5E59
+:106D3000CBBC14BFD7B605F3CB7002CFB387CA471D
+:106D400058AE42FA528517EEE07271AFCC1A28DEC7
+:106D50001779D38509F1E48FF8C7093F51BEF218BE
+:106D6000FA2F83D325AB04530D86B936A05FE44ACE
+:106D7000E3FECCE0EF5ECEA920BDE2CEF929BE8BCA
+:106D800011FEEEC24DDBB472C07E1676F33CE160BC
+:106D900018AB3C42F4764C413A446695987373497B
+:106DA000AE32E99D8F86E73543CFF1A4C8679EC612
+:106DB0003C4F867FDFC589895C8F3137F14F8F86E5
+:106DC000AFAFBE7B51C7AFC89582E2A53512CF4F9A
+:106DD0008DA757F01EA55CDCA3948B7B9472718FFA
+:106DE000522EEE51CAC53D4AB9B8472917F728E5D2
+:106DF000E21EA55CDCA3948B7B14AC3F8D5BA5F7F6
+:106E000070CFEF44FBD9833236D90FF7C784C093D4
+:106E100083FBF7C748C1F06489FAE7E43EBFD39526
+:106E200081794C8B906F2502FDAF8B269E5FEA8A9D
+:106E300070FC1DE2B97C61D33EFE1ED14EEF59F2CB
+:106E4000639696A27C0DC71A18EAA1865CC7BC5C43
+:106E5000A0FBA9530B52B7917E3459F19EBBFFBEE4
+:106E60003BA2282FF796CC6458725E7AF6861C8077
+:106E7000E79925E25BD013DF2951E3499867413751
+:106E8000BFCF28906BCB71FE35934CD9A87787B2D2
+:106E90001CC5B901FC583879552AFA413D3AE50339
+:106EA000CCA7BADED5318CA3D4FC9BDAAF276BDE3E
+:106EB000521CB7303D654316EA1B102ED46F763D49
+:106EC0006BC37DD935E15213E92B458BF2BF54F0EA
+:106ED000EF7C85FBC35EBDA28DC1B83D6C5EAC4B43
+:106EE000E1F755E5E2BEAA5CDC57217DDEC1BC19A5
+:106EF00094EF413D96BD508F65E87BAE67724A5670
+:106F0000E652BC3D9414F81E6C11CA15D73349C81B
+:106F1000CF3B05DF26083DD3935D524DFCCE3C347C
+:106F20004F8DC8BF5DD105DFE3A9E3FCE319957779
+:106F30007F87EB6716A5E7EF5DA73017BEA7BDFB00
+:106F4000D549944FF2B9352E5D14C020E3A8BFD8BF
+:106F5000AB3CBE65095C5EEE3E1C4FFD9A441ED400
+:106F600019D39B16837657C8950A1FF90B7FE7E361
+:106F7000CC0218CA63123F9FF3EEDEB468807D92A4
+:106F80004983F971670B6FEF1372E79C2EE613E7E5
+:106F900061464F12D263F0F8AB490F00BCC5ECADAF
+:106FA000E0FADE9B467A9A79D3F0BDD015C9731604
+:106FB000DFDBAE3A92B50CDFD75ED17976235C7316
+:106FC0002487C3D2A1B396C0F6899E247C8FBBEAE6
+:106FD00048F6327C9F7B65E2A1DDD1D60058F7CA26
+:106FE000596CD73F9AB32C1FE06283FB5423F2CD38
+:106FF000BF72FE321DECB880F8A9E9E2FEFAFC830C
+:107000001D575F417BDC1141F7F507729389DE4D17
+:107010005DFB9F407EF31DD2911C6C69FBC3EE5F4C
+:10702000513F03A5518A0D9E1C4CB934E4FDC77D28
+:10703000B86E71B8E70B84D7E7FD80F6513C81CB81
+:10704000F3C6BCF9CB503E7D1D077F89F2571C0566
+:107050008E2CEEE76513D1A7FAF0CC7CCC03F82296
+:107060007ACB70FEBADF1AACC8A7D587E3E7635EB8
+:10707000A02397E7A7AB6EDF9A84F65573F4A57D3E
+:10708000BFC23CE56F4D743F531FC3FDBB6AB939A6
+:107090006F35D16FCF3E7C37E27BC944F7A45530C2
+:1070A00007AE57B56F06E5D58FFDF9E332A44381EE
+:1070B000BC6B1FD67FB1D7A4413CF4E9ED51DF434F
+:1070C00039ECD3519C5925E0AAFE097C3FE10385A8
+:1070D00044BFD8AD49685FAB27FCC35DB8EF6279A8
+:1070E000EB6E8C73D87E03DD155C7A09F006E32E17
+:1070F000B5EAE895AAEFA5082DF2CB15696BD94E34
+:107100009CBF95F7BB62DA4AF874B5DEC6703DE8FD
+:10711000C7505F5D91B605D55F6ADD9F8971E8E56F
+:10712000DF16533CAAF2F9489CB1D710640F4913FB
+:10713000C489F71264665DCC0C76B64A80978F3CA2
+:10714000E7DBC9FCE32FB7E9BC7AC05195816DC07C
+:10715000F7C1AA3C5427FEB008CF57AD694E437F14
+:10716000A52A7BA00CE5E292891913A0DFDBC25EA1
+:1071700055B7AF5F8C7EEF78FBF98BB03F5F0A3974
+:10718000FCB2D3E40EBC1F0C2DFFD8C8947702DEEE
+:107190000DDFDF6020DF5D9DEF6DBDA716E3B3BAA5
+:1071A00018AE3FCE42FF36D0633784DE5BBE2EB8CA
+:1071B000FFB5DC18FE2E553F9086764F9DDF97ABCE
+:1071C000EAB58134D457A1E38A65A16F5E9648DFA2
+:1071D00054B74BE764C053B5D1E5C6F73BD5184C5F
+:1071E000F2736A6F4A7C5C429EC03B8C7D3C2F9957
+:1071F000CE5DDD66B29B605C4DD84024FA43B5118C
+:107200000391E8E7F88ECAAC45902B364ED067BAAA
+:10721000205940DEB1CAA3B39B32C7A033FA4DF860
+:107220003E07FF1BD6DF95379DD6ABEC0CA7F59834
+:1072300065200FF9B47257F0383C972540FE7C9DCD
+:107240007BE202E3F164B1EF41E91CC9C9E09F3F71
+:107250004A42BA576BD806BC47BC2CF1EF1E00A6B9
+:10726000EF1E2E8BFBC8EA3F99C3905F2E7F594BD0
+:1072700072EB930648AFBD7BA484F4814F37407A0C
+:10728000ED44DEBDA4C77CD10365A8A7DE3D52C195
+:10729000DB270D9429D0DE8630B64F6564EFFF2BD7
+:1072A000CF49FAA358E6EF1BD81E9D85E78136F536
+:1072B00037525CA15302E3EE3FE6A9F7367AFFB9F5
+:1072C00065BFDCF89872B01DE5B0D24CF91CF09F98
+:1072D000DA5E413F6F699C15F3E295388EF3813E8B
+:1072E000F0FE2F36E67A05D2675994A3202F17EFC8
+:1072F0001907287E00AE263FBDEE77068A23077564
+:1073000043FB504F65463916E6017FD5EA7B37A22D
+:107310004B7F5537D083F77E8B64AE8FD87ECE57A8
+:10732000BE8C3DFC3B09717FB854E01FEC166B46E8
+:10733000BE90387DDFE83CFC0EEA155F6F0AE9E39A
+:1073400050B9B9D4F95424EA873360C75D0171FE9E
+:107350009915FBE99E7E09BECB80F2810DC1FC3000
+:107360007CE3A714EFB12702EA910FB707C3A17C12
+:1073700084FCE80DD23B2E92A76773B91F5633BF2A
+:10738000B70EF13002DF0DB01C009F088143FAB345
+:1073900012EE273C8BFF8D789CEAEDA7F8FC207F4E
+:1073A00017DB04F68BE08E70BA37D61C04FB14CBC7
+:1073B000ED13DA859AC85ECA4BF93A0C743FF2684D
+:1073C000D7A7F49E11F890F22F355DAFC661DC7E31
+:1073D00000E3845CB28371F44EA5A32B0EE30DB5DC
+:1073E000BE56E34913EFF1C94F57EB9DB2370DF786
+:1073F0005F23F56662FB01B1EF5A0DC032C262DF56
+:10740000129777D625933E0FA5DB0EC1AFA017329A
+:10741000E99DC5519E1750F54095D02727B03E8372
+:10742000CBBD45BD5792F0BD5CF898FA213E4FE8C0
+:1074300037D640799BED797CDFEA789A97E795A873
+:10744000BDEED895CCE919384E19790739A2875283
+:10745000FC7A05E53F81E4FF515D1C9CAB7AB76483
+:107460006D423D55BABE10BAB355DAD585942F1387
+:10747000EF3F43F715CA4756D80BE9494D74416CA5
+:10748000C07C97215C4FC8223D43EFE81F8C7DB242
+:1074900010F3133F2BDD46FC3C626F02E51CCFB3BB
+:1074A0008BEB71149B9B9AD17CBCAAA17963FC18CD
+:1074B000FB08DD6795A3B9304E195DAFEEF7B24911
+:1074C000DDDF7CDDC4403C2C595F3811CA55C6BF96
+:1074D000160FFCBC97BB0C5EB4AB55A5AB37468D05
+:1074E000C137A3ECC1AE00FB351DE9EBA67B8DF1E6
+:1074F000F61F5AD64ADE7ECC133190AB56922F90AF
+:107500009700BB30272F24DF50B9621AC69DCCB13B
+:10751000621ADA1990AB32EB1871257E59A2A1B725
+:107520001B2E2A43F7733E8FE749E7E47179E9B6EA
+:10753000D97DA837C7FBDEE2BFC53EC6FBDE2251C0
+:1075400033FC1ECA5B625C8482F740050BC279BFC4
+:10755000E3260BE66D068F5FA7BCEEE063E625FC35
+:10756000BEC0CC26417B4FC2AC96403BB275365F65
+:10757000273C87FB2DF5E9BAAFCF0B65448CE4853A
+:10758000C86FC808A77B125FE7E764B706BB732D17
+:10759000789FE1EB85E810E4A9FECFFF1D87F6D5C3
+:1075A000D7FD09BD07F3DDF894DE896D16EFF44EC3
+:1075B000748A7756BD4A047D1757F47121F6DB2291
+:1075C0004A7F7E80E789D5528DFF03E2DFC9B3C7CA
+:1075D0008E7F631CE6C0BC80123F561E25302F9064
+:1075E000AAE579012C312F909ACAF30208635E0054
+:1075F0004BCC0B603DE60510C6BC00C29817401886
+:10760000F30258625E00EBBF10DF3F0C8262E2F9CA
+:107610004A33E9F5B5F8BE1DF0B7F638BF775ADB47
+:107620002AD3FD2D7EFF80F66DD4BB9976F16EC610
+:10763000B38DEEF1EA3B642B92A85E377412F338F7
+:10764000F58724EB7AD42B8D4B68FDCDDDB91F94E3
+:10765000627DABCEAA51888F381D9B257AA75FDD4E
+:10766000DD4A79A7FCF8E37AAA6F9318E649EF356B
+:10767000F038D729436D16DD83921FEC34F452FCA9
+:1076800051734052CA03DF69CCB9467A40BD4FAE50
+:10769000E04DCCE93129E563BC031979772EDE4D45
+:1076A00057E03D33BE17976FD0BB7E2704A41390DD
+:1076B0000F77F0F7CF16F847F21EF2AEA9BAFBD05B
+:1076C000467C0F157ADF3CF23D5DC8BD73D96C7105
+:1076D000AF6CE3DF57143D5D7EB003D61BDE6A203E
+:1076E0007FA321D7F120F2D1499D9DF223278F9BC3
+:1076F000282E3ABFEDB6A0FCC85096A37A36E59B7B
+:10770000A650BE628D4E227BBCA028251EF1B8E09B
+:10771000948EEC4E4F56492DF65B334BA17C548131
+:1077200081FD82E611EFA5547A1434496E0DC02B09
+:107730009895DED92F073461BE725067DE84EF9AC8
+:107740009633FECE41E59B35DB24E21B4C10203EF8
+:10775000CB043E9777FFFE3ABE635869E07E6BA28A
+:1077600086DF5F276EE1EF191E640E3DDAD955C83A
+:107770005D32D9C7DF0D40BD237C4A12F7CB957827
+:107780009C7FC5691DBDB72D88FF719A83EC743E3F
+:10779000BD6390BCCBE49B778C2F3FA1EF184EEAE2
+:1077A000B85E013C523CD4837C4979190795A71BEC
+:1077B0002BA9AC13DF438C7EFF3F7416E3C4C4F8DF
+:1077C000082BEAB971BF770BFBFAEFBD768AF76B2E
+:1077D000899ABE6C05F1F127B315F1A1BE13ECB681
+:1077E0009534239DEC91CC65A1EFC14003025E0B63
+:1077F000F12012E6B53D76FCEE68E8B864A177C9E1
+:10780000A3F4E3B6C7F09D487DAA649114CC7F6FC2
+:107810002D88837D174E4FA67DD777F2FC286128EF
+:107820000EF3E79C5E91598EC3B373FDF5C5426EAE
+:107830007CD09FF3C977DDC86FDF206FBA17FBBB21
+:107840009889BEA7A63FD84FF11D53297FAAF2CD34
+:10785000705B7C0BF2CDEF67F338B2B4F47D1DDAC8
+:10786000FF9E6CC709DC4759F9B5C7E2E87C63E7BE
+:10787000AFD477EAA1F9AB40FDF9FFF13EFD9DC61B
+:10788000062ADF6B5C47656FA38BDA03F4FF7F8EFC
+:10789000A3FF43F39FE7B05F68FE93199528B29F5B
+:1078A00020DF3CDF1C92EF2C9AF0C026C0DF82ED77
+:1078B0007A2B56A9F94F7C3FBCD64CFAE0F2EC315A
+:1078C000F39E2ADECC94271D66A62CC4FFFCF4147C
+:1078D000AD06DABF107450F38E281F783E940F2C3B
+:1078E000513EB45ABF7CBCA00711CEE176DE45768E
+:1078F000DE4474DDB81EF407C02B9925487F5C0D6B
+:10790000D11F1070DC47DF55751B18E609D5779439
+:10791000F3A1F82A6B0C7DE2E1FA646A98E725FA94
+:10792000DEBF2E8CDEE79E14EFE14E6EE6EFE1CA7D
+:107930005909AD3B865E89447AAC9C3074F679E88F
+:10794000BFF2D766F257364EAAC8FB5BF4CAE06CAA
+:107950008E8F67F17705B45FF7BB024F48781FBA87
+:10796000E67E66433AABBF2B102FEEB3BFC5EF0ADE
+:10797000DC3667E237FF5D81CC39F1A581BF2B9002
+:10798000D93989C3EAEF0AB0F8D2717E57207B4E0D
+:10799000EEE8DF15983D87C739E3FDAE00F8937335
+:1079A000707F3A9BFD4E2C13C53E43BFA73D2DEE85
+:1079B000EF7A348E522C0B235D5AAAD7B873B07C61
+:1079C0005BE3F939D6033FE7E33E0A9FB2DD9E0E43
+:1079D00070A2C1437AB227CB5E80F583367B21AE9D
+:1079E000139A3747DA627C0FFB5984EDA1EFAE544E
+:1079F0007AAE98C3F9FE0151CE6D1AFB7BF207E611
+:107A0000F0EFD56EB56FD8EF7DB82F75FF6CEB8AB0
+:107A10001C92A72CFB32B1DF522C993926E8FBD4FB
+:107A2000D17CE612FBE2FC05FAACF83CF707A94C66
+:107A3000D3BAA3D17F9CFC883B1AF73BB979C884A1
+:107A4000DF41BCE81A32A17D7FF1E12113D6BF6886
+:107A5000E7EF9543E77F710EFF4E206DEE108D9F8F
+:107A600006FFDD4BFEF95034FA4F6995E737D27DBA
+:107A7000CB8199645FA609FB32ED91E99D03C06F4C
+:107A8000D39E8BA2FB6C961F4BEDD5462EA7D58FB0
+:107A9000941FE950E8BBADE2F301FECE4C37EC3B5E
+:107AA000C8FFD20EF3779700239E0EE808469E4546
+:107AB000FFCAC9F8BBCBC9426FA09F560A7AC15909
+:107AC000F9E675BAF7C7F1381FDED122FF75EA86ED
+:107AD000C5F769168C43572D59DF4371E18E917AB2
+:107AE00011671EDA887133F86F41F5D5E5AFF7A05D
+:107AF000BDA939105CEF6CB846F12BF86F41F5F772
+:107B0000FFFC9C9EFF7E41703DD07707F29B4ADFD1
+:107B1000933ACF4C8CF34E3AC3ACFCFDBE877EAF9C
+:107B2000A4457CFFBCE79FE7E7F0F7A29CDE30DED0
+:107B3000FDCDF8A389FABBE6B37494875B95AA5E82
+:107B40001AF9FD133D73517E6F5104E99D7A115767
+:107B5000D5955BC8CE27D619497F15C8615684478D
+:107B60007EFFA448167ACA43F2DF775734E5F1E87E
+:107B70000008C7CCA27B9FB8260E0F4D34907E28FC
+:107B8000D094D4EE87F24D4DF077EC2FA07E90513B
+:107B90007E793EB55EEFE1DF896B955C8C739B244B
+:107BA000FB73F8DD639324F2885566BA2F18C4FC82
+:107BB000229C677BB4FBB90A5867FB3D19E41F0F91
+:107BC00032AE4F5D4BF8BDD5F6E892D2D5D8BEF4B3
+:107BD000766A3FF297942773D07FAA0AB3A2FFB4C4
+:107BE000DDC6FDEBED8BD3A9FD98A4ACC773BB1E1E
+:107BF00061B4CEF6C5FCDCDB9F9C2ABEBF709B50F7
+:107C00009EB737DB27E17DD47C8BE30CD26BB2B817
+:107C10008FDB9E0CF5503E23952C7D10E799C5F720
+:107C20005B6753885E2797DEFEE43E85CC8817EFBE
+:107C300085EA1745501CFCBF93011353F046000022
+:107C4000000000000000000005001500000000001A
+:00000001FF
diff --git a/firmware/bnx2x-e1h-4.8.53.0.fw.ihex b/firmware/bnx2x-e1h-4.8.53.0.fw.ihex
deleted file mode 100644
index 48d7612907e..00000000000
--- a/firmware/bnx2x-e1h-4.8.53.0.fw.ihex
+++ /dev/null
@@ -1,12028 +0,0 @@
-:10000000000039D8000000600000063000003A40CF
-:100010000000191C000040780000009C0000599866
-:10002000000082E400005A38000000D40000DD2007
-:100030000000C7CC0000DDF8000000780001A5C872
-:10004000000056980001A648000000C00001FCE82E
-:100050000000F1D40001FDB0000000040002EF88B0
-:10006000020400480000000F020400540000004594
-:1000700002040058000000840204005C0000000636
-:100080000204007000000004020400780000000078
-:100090000204007C121700000204008022170000F6
-:1000A00002040084321700000604008800000005E6
-:1000B0000204009C12150000020400A0221500009A
-:1000C000020400A432150000060400A80000000489
-:1000D000020400B802100000020400BC001000007E
-:1000E000020400C010100000020400C42010000030
-:1000F000020400C830100000020400CC40100000D0
-:10010000060400D000000003020400DC0010000020
-:10011000020400E012140000020400E422140000B3
-:10012000020400E832140000020400EC4214000053
-:10013000060400F000000003010401240000000098
-:1001400001040128000000000104012C000000004F
-:100150000104013000000000020401D00000890603
-:1001600002040004000000FF02040008000000FF79
-:100170000204000C000000FF02040010000000FF59
-:1001800002040014000000FF02040018000000FF39
-:100190000204001C000000FF02040020000000FF19
-:1001A000020400240000003E0204002800000000B9
-:1001B0000204002C0000003F020400300000003F59
-:1001C000020400340000003F020400380000003F39
-:1001D0000204003C0000003F020400400000003F19
-:1001E000020400440000003F020404CC00000001AF
-:1001F00002042008000002110204200C000002008A
-:10020000020420100000020402042014000002195D
-:100210000204201C0000FFFF020420200000FFFF5A
-:10022000020420240000FFFF020420280000FFFF3A
-:1002300002042038000000200204203C00000000DE
-:100240000204204000000034020420440000003575
-:10025000060420480000001C020420B80000000131
-:10026000060420BC0000005F0204223807FFFFFFE5
-:100270000204223C0000003F0204224007FFFFFF6F
-:10028000020422440000000F010422480000000084
-:100290000104224C00000000010422500000000074
-:1002A0000104225400000000010422580000000054
-:1002B0000104225C00000000010422600000000034
-:1002C0000104226400000000010422680000000014
-:1002D0000104226C000000000104227000000000F4
-:1002E00001042274000000000104227800000000D4
-:1002F0000104227C000000000C042000000003E840
-:100300000A042000000000010B0420000000000A85
-:1003100002050044000000200205004800000032F1
-:10032000020500900215002002050094021500202D
-:1003300002050098000000300205009C0810000033
-:10034000020500A000000033020500A400000030F8
-:10035000020500A800000031020500AC0000000208
-:10036000020500B000000005020500B40000000610
-:10037000020500B800000002020500BC00000002F7
-:10038000020500C000000000020500C400000005D6
-:10039000020500C800000002020500CC00000002B7
-:1003A000020500D000000002020500D40000000198
-:1003B00002050114000000010205011C00000001FB
-:1003C00002050120000000020205020400000001F5
-:1003D0000205020C0000004002050210000000406F
-:1003E0000205021C0000002002050220000000138C
-:1003F0000205022400000020060502400000000A59
-:1004000004050280002000000205005000000007E3
-:100410000205005400000007020500580000000813
-:100420000205005C000000080205006000000001F9
-:100430000605006400000003020500D80000000665
-:100440000205000400000001020500080000000190
-:100450000205000C00000001020500100000000170
-:100460000205001400000001020500180000000150
-:100470000205001C00000001020500200000000130
-:100480000205002400000001020500280000000110
-:100490000205002C000000010205003000000001F0
-:1004A00002050034000000010205003800000001D0
-:1004B0000205003C000000010205004000000001B0
-:1004C000020500E00000000D020500E80000000742
-:1004D000020500F000000007020500F80000000718
-:1004E000020500E40000002D020500EC00000027DA
-:1004F000020500F400000027020500FC00000027B0
-:10050000020500E00000001D020500E800000017E1
-:10051000020500F000000017020500F800000017B7
-:10052000020500E40000003D020500EC0000003779
-:10053000020500F400000037020500FC000000374F
-:10054000020500E00000004D020500E80000004741
-:10055000020500F000000047020500F80000004717
-:10056000020500E40000006D020500EC00000067D9
-:10057000020500F400000067020500FC00000067AF
-:10058000020500E00000005D020500E800000057E1
-:10059000020500F000000057020500F800000057B7
-:1005A000020500E40000007D020500EC0000007779
-:1005B000020500F400000077020500FC000000774F
-:1005C0000406100002000020020600DC000000010A
-:1005D000010600D80000000004060200000302200B
-:1005E000020600DC00000000010600B80000000068
-:1005F000010600C800000000010600BC0000000069
-:10060000010600CC0000000007180400009B000059
-:1006100008180798000D0223071C0000325E000036
-:10062000071C800035960C98071D00001AEA19FE79
-:10063000081D43D057860225011800000000000065
-:10064000011800040000000001180008000000006C
-:100650000118000C0000000001180010000000004C
-:100660000118001400000000021800200000000122
-:1006700002180024000000020218002800000003F5
-:100680000218002C000000000218003000000004D6
-:1006900002180034000000010218003800000000B9
-:1006A0000218003C00000001021800400000000495
-:1006B0000218004400000000021800480000000179
-:1006C0000218004C00000003021800500000000057
-:1006D0000218005400000001021800580000000435
-:1006E0000218005C00000000021800600000000119
-:1006F00002180064000000030218006800000000F7
-:100700000218006C000000010218007000000004D4
-:1007100002180074000000000218007800000004B5
-:100720000218007C00000003061800800000000290
-:10073000021800A400003FFF021800A8000003FFF9
-:100740000218022400000000021802340000000019
-:100750000218024C00000000021802E4000000FF32
-:100760000618100000000400021B8BC000000001EE
-:10077000021B800000000034021B804000000018B3
-:10078000021B80800000000C021B80C000000020C3
-:100790000C1B83000007A1200A1B83000000013806
-:1007A0000B1B830000001388021B83C0000001F4B0
-:1007B000021B1480000000010A1B148000000000CE
-:1007C000061A1000000002B3041A1ACC0001022716
-:1007D000061AA020000000C8061AA00000000002AF
-:1007E000021A1AD000000000061A1AD800000004ED
-:1007F000061A367800000006061A3670000000025D
-:10080000061A500000000002061A500800000004FA
-:10081000061A501800000004061A502800000004B0
-:10082000061A503800000004061A50480000000460
-:10083000061A505800000004061A50680000000410
-:10084000061A507800000002061A4000000000025C
-:10085000061A400800000002041A62C000200228A4
-:10086000061A20000000016C061AB00000000028E3
-:10087000061AB1400000000C061A32C00000001237
-:10088000061A335000000064061A810800000002B6
-:10089000061A25B00000016C061AB0A0000000285E
-:1008A000061AB1700000000C061A3308000000128E
-:1008B000061A34E000000064061A811000000002ED
-:1008C000021A2B6000000000061A3000000000022F
-:1008D000041A300800050248061A301C0000000700
-:1008E000061A31C000000008061A5000000000027D
-:1008F000061A508000000012061A40000000000294
-:10090000021A2B6400000000061A303800000002B2
-:10091000041A30400005024D061A3054000000074A
-:10092000061A31E000000008061A5010000000020C
-:10093000061A50C800000012061A40080000000203
-:10094000021A2B6800000000061A30700000000236
-:10095000041A307800050252061A308C0000000795
-:10096000061A320000000008061A5020000000029B
-:10097000061A511000000012041A4010000202571B
-:10098000021A2B6C00000000061A30A800000002BA
-:10099000041A30B000050259061A30C400000007DE
-:1009A000061A322000000008061A5030000000022B
-:1009B000061A515800000012041A40180002025E84
-:1009C000021A2B7000000000061A30E0000000023E
-:1009D000041A30E800050260061A30FC0000000727
-:1009E000061A324000000008061A504000000002BB
-:1009F000061A51A000000012041A402000020265ED
-:100A0000021A2B7400000000061A311800000002C0
-:100A1000041A312000050267061A3134000000076D
-:100A2000061A326000000008061A5050000000024A
-:100A3000061A51E800000012041A40280002026C55
-:100A4000021A2B7800000000061A31500000000244
-:100A5000041A31580005026E061A316C00000007B6
-:100A6000061A328000000008061A506000000002DA
-:100A7000061A523000000012041A403000020273BD
-:100A8000021A2B7C00000000061A318800000002C8
-:100A9000041A319000050275061A31A400000007FF
-:100AA000061A32A000000008061A5070000000026A
-:100AB000061A527800000012041A40380002027A26
-:100AC0000200A294071D29110200A2980000000054
-:100AD0000200A29C009C04240200A2A000000000CE
-:100AE0000200A2A4000002090200A270000000009F
-:100AF0000200A274000000000200A27000000000CA
-:100B00000200A274000000000200A27000000000B9
-:100B10000200A274000000000200A27000000000A9
-:100B20000200A27400000000020100B400000001F5
-:100B3000020100B800000001020100DC0000000119
-:100B40000201010000000001020101040000000197
-:100B50000201007C00300000020100840000002837
-:100B60000201008C000000000201013000000004BE
-:100B70000201025C000000010201032800000000E5
-:100B800002016080000000010201055400000030F5
-:100B9000020100C400000001020100CC00000001BD
-:100BA000020100F800000001020100F00000000155
-:100BB00002010080003000000201008800000028CF
-:100BC0000201009000000000020101340000000456
-:100BD000020102DC000000010201032C0000000001
-:100BE0000201608400000001020105640000003081
-:100BF000020100C800000001020100D00000000155
-:100C0000020100FC00000001020100F400000001EC
-:100C1000020C100000000020020C2008000002114D
-:100C2000020C200C00000200020C20100000020444
-:100C3000020C201C0000FFFF020C20200000FFFF20
-:100C4000020C20240000FFFF020C20280000FFFF00
-:100C5000020C2038000000C6020C203C00000000FE
-:100C6000020C204000000034020C2044000000353B
-:100C7000060C20480000001C020C20B800000001F7
-:100C8000060C20BC0000005F020C223807FFFFFFAB
-:100C9000020C223C0000003F020C224007FFFFFF35
-:100CA000020C22440000000F010C2248000000004A
-:100CB000010C224C00000000010C2250000000003A
-:100CC000010C225400000000010C2258000000001A
-:100CD000010C225C00000000010C226000000000FA
-:100CE000010C226400000000010C226800000000DA
-:100CF000010C226C00000000010C227000000000BA
-:100D0000010C227400000000010C22780000000099
-:100D1000010C227C000000000C0C2000000003E805
-:100D20000A0C2000000000010B0C20000000000A4B
-:100D3000020C400800000411020C400C00000400EA
-:100D4000020C401000000404020C401400000421B6
-:100D5000020C401C0000FFFF020C40200000FFFFBF
-:100D6000020C40240000FFFF020C40280000FFFF9F
-:100D7000020C403800000046020C403C0000000518
-:100D8000020C404000000034020C404400000035DA
-:100D9000020C404800000007060C404C0000005BBD
-:100DA000020C41B800000001060C41BC0000000329
-:100DB000020C41C800000001060C41CC0000001BE1
-:100DC000020C423807FFFFFF020C423C0000003FCC
-:100DD000020C424007FFFFFF020C42440000000FDC
-:100DE000010C424800000000010C424C00000000D1
-:100DF000010C425000000000010C425400000000B1
-:100E0000010C425800000000010C425C0000000090
-:100E1000010C426000000000010C42640000000070
-:100E2000010C426800000000010C426C0000000050
-:100E3000010C427000000000010C42740000000030
-:100E4000010C427800000000010C427C0000000010
-:100E5000010C4280000000000C0C4000000003E880
-:100E60000A0C4000000000010B0C40000000000ACA
-:100E7000020D004400000032020D008C021500201B
-:100E8000020D009002150020020D009408100000D1
-:100E9000020D009800000033020D009C00000002CB
-:100EA000020D00A000000000020D00A400000005DB
-:100EB000020D00A800000005060D00AC00000002B5
-:100EC000020D00B400000002020D00B80000000393
-:100ED000020D00BC00000002020D00C00000000175
-:100EE000020D00C800000002020D00CC000000024C
-:100EF000020D010800000001020D015C000000016C
-:100F0000020D016400000001020D016800000002F2
-:100F1000020D020400000001020D020C000000207E
-:100F2000020D021000000040020D021400000040FB
-:100F3000020D022000000003020D02240000001830
-:100F4000060D028000000012040D03000024027C44
-:100F5000020D004C00000001020D005000000002D4
-:100F6000020D005400000008020D005800000008A7
-:100F7000060D005C00000004020D00C40000000427
-:100F8000020D000400000001020D00080000000135
-:100F9000020D000C00000001020D00100000000115
-:100FA000020D001400000001020D001800000001F5
-:100FB000020D001C00000001020D002000000001D5
-:100FC000020D002400000001020D002800000001B5
-:100FD000020D002C00000001020D00300000000195
-:100FE000020D003400000001020D00380000000175
-:100FF000020D003C00000001020D01140000000978
-:10100000020D011C0000000A020D0124000000076F
-:10101000020D012C00000007020D01340000000C3D
-:10102000020D013C0000000B020D0144000000070E
-:10103000020D011800000029020D01200000002A05
-:10104000020D012800000027020D013000000027DA
-:10105000020D01380000002C020D01400000002BA1
-:10106000020D014800000027020D011400000019C4
-:10107000020D011C0000001A020D012400000017DF
-:10108000020D012C00000017020D01340000001CAD
-:10109000020D013C0000001B020D0144000000177E
-:1010A000020D011800000039020D01200000003A75
-:1010B000020D012800000037020D0130000000374A
-:1010C000020D01380000003C020D01400000003B11
-:1010D000020D014800000037020D01140000004914
-:1010E000020D011C0000004A020D0124000000470F
-:1010F000020D012C00000047020D01340000004CDD
-:10110000020D013C0000004B020D014400000047AD
-:10111000020D011800000069020D01200000006AA4
-:10112000020D012800000067020D01300000006779
-:10113000020D01380000006C020D01400000006B40
-:10114000020D014800000067020D01140000005963
-:10115000020D011C0000005A020D0124000000577E
-:10116000020D012C00000057020D01340000005C4C
-:10117000020D013C0000005B020D0144000000571D
-:10118000020D011800000079020D01200000007A14
-:10119000020D012800000077020D013000000077E9
-:1011A000020D01380000007C020D01400000007BB0
-:1011B000020D014800000077020E004C00000032D2
-:1011C000020E009402150020020E00980215002065
-:1011D000020E009C00000030020E00A0081000006B
-:1011E000020E00A400000033020E00A80000003030
-:1011F000020E00AC00000031020E00B00000000240
-:10120000020E00B400000004020E00B8000000004E
-:10121000020E00BC00000002020E00C0000000022E
-:10122000020E00C400000000020E00C80000000210
-:10123000020E00CC00000007020E00D000000002E9
-:10124000020E00D400000002020E00D800000001CF
-:10125000020E00E400000001020E01440000000143
-:10126000020E014C00000001020E015000000002BD
-:10127000020E020400000001020E020C00000040F9
-:10128000020E021000000040020E021C00000004CA
-:10129000020E022000000020020E02240000000EB8
-:1012A000020E02280000001B060E030000000012C0
-:1012B000040E0280001B02A0020E00540000001069
-:1012C000020E005800000007020E005C0000000F34
-:1012D000020E006000000010020E00640000000B0F
-:1012E000060E006800000003020E00DC0000000390
-:1012F000020E000400000001020E000800000001C0
-:10130000020E000C00000001020E0010000000019F
-:10131000020E001400000001020E0018000000017F
-:10132000020E001C00000001020E0020000000015F
-:10133000020E002400000001020E0028000000013F
-:10134000020E002C00000001020E0030000000011F
-:10135000020E003400000001020E003800000001FF
-:10136000020E003C00000001020E004000000001DF
-:10137000020E004400000001020E01100000000FE8
-:10138000020E01180000000E020E012000000000F5
-:10139000020E012800000000020E01140000002FC0
-:1013A000020E011C0000002E020E012400000000AD
-:1013B000020E012C00000000020E01100000001FB0
-:1013C000020E01180000001E020E012000000000A5
-:1013D000020E012800000000020E01140000003F70
-:1013E000020E011C0000003E020E0124000000005D
-:1013F000020E012C00000000020E01100000004F40
-:10140000020E01180000004E020E01200000000034
-:10141000020E012800000000020E01140000006FFF
-:10142000020E011C0000006E020E012400000000EC
-:10143000020E012C00000000020E01100000005FEF
-:10144000020E01180000005E020E012000000000E4
-:10145000020E012800000000020E01140000007FAF
-:10146000020E011C0000007E020E0124000000009C
-:10147000020E012C000000000730040000D2000022
-:10148000083007A8000B02BB0734000031B600008B
-:101490000734800036500C6E0735000037591A03A8
-:1014A00007358000286127DA0835FF40401802BD63
-:1014B00001300000000000000130000400000000C6
-:1014C00001300008000000000130000C00000000A6
-:1014D0000130001000000000013000140000000086
-:1014E0000230002000000001023000240000000251
-:1014F00002300028000000030230002C0000000031
-:10150000023000300000000402300034000000010E
-:1015100002300038000000000230003C00000001F2
-:1015200002300040000000040230004400000000CF
-:1015300002300048000000010230004C00000003AF
-:101540000230005000000000023000540000000192
-:1015500002300058000000040230005C000000006F
-:10156000023000600000000102300064000000034F
-:1015700002300068000000000230006C0000000132
-:10158000023000700000000402300074000000000F
-:1015900002300078000000040230007C00000003EC
-:1015A0000630008000000002023000A400003FFF6F
-:1015B000023000A8000003FF0230022400000000F7
-:1015C00002300234000000000230024C0000000033
-:1015D000023002E40000FFFF063020000000080097
-:1015E00002338BC000000001023380000000001AAB
-:1015F000023380400000004E023380800000001063
-:10160000023380C0000000200C3383000007A120BB
-:101610000A338300000001380B3383000000138875
-:10162000023383C0000001F40C3383801DCD6500BC
-:101630000A3383800004C4B40B338380004C4B40D6
-:101640000A331480000000000233148000000001FF
-:10165000063220000000010206328980000000C826
-:1016600006328960000000020632322800000004C1
-:10167000063232000000000904323224000102BFA9
-:1016800006323180000000200632500000000400C5
-:10169000063240000000000204324008000102C08F
-:1016A0000632400C0000000306326B6800000002A6
-:1016B00004326B70000202C106326B10000000029F
-:1016C000043274C0000202C30233080001000000AB
-:1016D00004330C00001002C50233080000000000B3
-:1016E00004330C40001002D506329000000000A028
-:1016F0000632950000000040063297000000003CD2
-:1017000006322450000000B406322AD00000000245
-:101710000632308000000020063280000000012CDC
-:101720000232323800000000063250000000002073
-:101730000632510000000020063252000000002056
-:101740000632530000000020063254000000002042
-:10175000063255000000002006325600000000202E
-:10176000063257000000002006325800000000201A
-:10177000063259000000002006325A000000002006
-:1017800006325B000000002006325C0000000020F2
-:1017900006325D000000002006325E0000000020DE
-:1017A00006325F000000002006326B780000005215
-:1017B00006326E080000000C06329280000000A085
-:1017C0000632960000000040063297F00000003C10
-:1017D00006322720000000B406322AD8000000029A
-:1017E0000632310000000020063284B00000012CD7
-:1017F0000232323C0000000006325080000000201F
-:101800000632518000000020063252800000002085
-:101810000632538000000020063254800000002071
-:10182000063255800000002006325680000000205D
-:101830000632578000000020063258800000002049
-:10184000063259800000002006325A800000002035
-:1018500006325B800000002006325C800000002021
-:1018600006325D800000002006325E80000000200D
-:1018700006325F800000002006326CC0000000527B
-:1018800006326E380000000C02322A3000000000E0
-:10189000063230000000000406324018000000024A
-:1018A00002322A340000000006323010000000042A
-:1018B000063240280000000202322A3800000000F0
-:1018C00006323020000000040632403800000002DA
-:1018D00002322A3C000000000632303000000004D2
-:1018E000063240480000000202322A400000000098
-:1018F000063230400000000406324058000000026A
-:1019000002322A4400000000063230500000000479
-:10191000063240680000000202322A48000000003F
-:1019200006323060000000040632407800000002F9
-:1019300002322A4C00000000063230700000000421
-:1019400006324088000000020720040000740000F6
-:1019500008200780001002E507240000322600005E
-:1019600007248000246E0C8A0824CBB064F002E7C0
-:101970000120000000000000012000040000000021
-:1019800001200008000000000120000C0000000001
-:1019900001200010000000000120001400000000E1
-:1019A00002200020000000010220002400000002AC
-:1019B00002200028000000030220002C000000008C
-:1019C000022000300000000402200034000000016A
-:1019D00002200038000000000220003C000000014E
-:1019E000022000400000000402200044000000002B
-:1019F00002200048000000010220004C000000030B
-:101A000002200050000000000220005400000001ED
-:101A100002200058000000040220005C00000000CA
-:101A200002200060000000010220006400000003AA
-:101A300002200068000000000220006C000000018D
-:101A4000022000700000000402200074000000006A
-:101A500002200078000000040220007C0000000347
-:101A60000620008000000002022000A400003FFFCA
-:101A7000022000A8000003FF022002240000000052
-:101A800002200234000000000220024C000000008E
-:101A9000022002E40000FFFF0620200000000800F2
-:101AA00002238BC000000001022380000000001010
-:101AB00002238040000000120223808000000030DA
-:101AC000022380C00000000E022383C0000001F446
-:101AD00002231480000000010A231480000000008B
-:101AE000062210000000004206227020000000C8FC
-:101AF0000622700000000002022211E8000000002F
-:101B000006223000000000C0062240700000008065
-:101B10000622528000000004062267000000010037
-:101B2000062290000000040004226B08002002E955
-:101B300002230800013FFFFF04230C0000100309EB
-:101B4000022308000000000004230C4000100319C9
-:101B500006228000000000A0062285000000004050
-:101B6000062287000000003C0622404000000006DC
-:101B700006228280000000A00622860000000040AD
-:101B8000062287F00000003C0622405800000006B4
-:101B9000022211480000000006223300000000026B
-:101BA00006226040000000300222114C00000000BC
-:101BB0000622330800000002062261000000003007
-:101BC0000222115000000000062233100000000223
-:101BD000062261C000000030022211540000000003
-:101BE0000622331800000002062262800000003046
-:101BF00002221158000000000622332000000002DB
-:101C000006226340000000300222115C0000000048
-:101C10000622332800000002062264000000003083
-:101C20000222116000000000062233300000000292
-:101C3000062264C00000003002221164000000008F
-:101C400006223338000000020622658000000030C2
-:101C50000216100000000020021700080000000219
-:101C60000217002C000000030217003C00000004D3
-:101C7000021700440000000802170048000000029C
-:101C80000217004C00000090021700500000009066
-:101C9000021700540080009002170058081400003A
-:101CA000021700600000008A021700640000008034
-:101CB00002170068000000900217006C000000800E
-:101CC000021700700000000602170078000007D01D
-:101CD0000217007C0000076C02170038007C10041B
-:101CE000021700040000000F061640240000000246
-:101CF000021640700000001C02164208000000019D
-:101D000002164210000000010216422000000001ED
-:101D100002164228000000010216423000000001B5
-:101D20000216423800000001021642600000000264
-:101D30000C16401C0003D0900A16401C0000009CAA
-:101D40000B16401C000009C40216403000000008B9
-:101D5000021640340000000C02164038000000104B
-:101D6000021640440000002002164000000000015E
-:101D7000021640D8000000010216400800000001D1
-:101D80000216400C00000001021640100000000185
-:101D90000216424000000000021642480000000007
-:101DA00006164270000000020216425000000000B9
-:101DB0000216425800000000061642800000000291
-:101DC00002166008000004240216600C00000410D3
-:101DD00002166010000004140216601C0000FFFFD1
-:101DE000021660200000FFFF021660240000FFFFC3
-:101DF000021660280000FFFF021660380000002075
-:101E00000216603C00000020021660400000003412
-:101E100002166044000000350216604800000023EE
-:101E20000216604C000000240216605000000025DD
-:101E300002166054000000260216605800000027B9
-:101E40000216605C00000029021660600000002A93
-:101E5000021660640000002B021660680000002C6F
-:101E60000216606C0000002D061660700000005223
-:101E7000021661B800000001061661BC0000001FD8
-:101E80000216623807FFFFFF0216623C0000003FA7
-:101E90000216624007FFFFFF021662440000000FB7
-:101EA00001166248000000000116624C00000000AC
-:101EB000011662500000000001166254000000008C
-:101EC00001166258000000000116625C000000006C
-:101ED000011662600000000001166264000000004C
-:101EE00001166268000000000116626C000000002C
-:101EF000011662700000000001166274000000000C
-:101F000001166278000000000116627C00000000EB
-:101F10000C166000000003E80A16600000000001D3
-:101F20000B1660000000000A021680400000000648
-:101F30000216804400000005021680480000000AD6
-:101F40000216804C000000050216805400000002BA
-:101F5000021680CC00000004021680D000000004AD
-:101F6000021680D400000004021680D8000000048D
-:101F7000021680DC00000004021680E0000000046D
-:101F8000021680E400000004021680E8000000044D
-:101F90000216880400000004021680300000007C55
-:101FA000021680340000003D021680380000003F19
-:101FB0000216803C0000009C021680F00000000722
-:101FC000061680F4000000050216880C01010101CC
-:101FD00002168108000000000216810C00000004B7
-:101FE0000216811000000004021681140000000295
-:101FF000021688100801200402168118000000054E
-:102000000216811C00000005021681200000000558
-:1020100002168124000000050216882C20081001F9
-:1020200002168128000000080216812C000000061C
-:102030000216813000000007021681340000000003
-:1020400002168830010101200616813800000004C4
-:1020500002168834010101010216814800000000C7
-:102060000216814C0000000402168150000000049A
-:10207000021681540000000202168838080120046C
-:1020800002168158000000050216815C0000000560
-:102090000216816000000005021681640000000540
-:1020A0000216883C20081001021681680000000812
-:1020B0000216816C00000006021681700000000705
-:1020C00002168174000000010216884001010120FF
-:1020D00002168178000000010216817C00000001D8
-:1020E00002168180000000010216818400000001B8
-:1020F00002168844010101010216818800000001D6
-:102100000216818C00000004021681900000000479
-:10211000021681940000000202168848080120047B
-:1021200002168198000000050216819C000000053F
-:10213000021681A000000005021681A4000000051F
-:102140000216881420081001021681A80000000859
-:10215000021681AC00000006021681B000000007E4
-:10216000021681B400000001021688180101012046
-:10217000021681B800000001021681BC00000001B7
-:10218000021681C000000001021681C40000000197
-:102190000216881C01010101021681C8000000011D
-:1021A000021681CC00000004021681D00000000459
-:1021B000021681D4000000020216882008012004C3
-:1021C000021681D800000005021681DC000000051F
-:1021D000021681E000000005021681E400000005FF
-:1021E0000216882420081001021681E80000000869
-:1021F000021681EC00000006021681F000000007C4
-:102200000216E40C000000000216882801010120DB
-:102210000616E410000000040216E00001010101AE
-:102220000216E420000000000216E424000000046E
-:102230000216E428000000040216E42C000000024C
-:102240000216E004080120040216E4300000000534
-:102250000216E434000000050216E4380000000510
-:102260000216E43C000000050216E00820081001F8
-:102270000216E440000000080216E44400000006D4
-:102280000216E448000000070216E44C00000000BB
-:102290000216E00C010101200616E45000000004C3
-:1022A0000216E010010101010216E46000000000C6
-:1022B0000216E464000000040216E4680000000452
-:1022C0000216E46C000000020216E014080120046B
-:1022D0000216E470000000050216E4740000000518
-:1022E0000216E478000000050216E47C00000005F8
-:1022F0000216E018200810010216E4800000000811
-:102300000216E484000000060216E48800000007BC
-:102310000216E48C000000010216E01C01010120FD
-:102320000216E490000000010216E494000000018F
-:102330000216E498000000010216E49C000000016F
-:102340000216E020010101010216E4A000000001D4
-:102350000216E4A4000000040216E4A80000000431
-:102360000216E4AC000000020216E024080120047A
-:102370000216E4B0000000050216E4B400000005F7
-:102380000216E4B8000000050216E4BC00000005D7
-:102390000216E028200810010216E4C00000000820
-:1023A0000216E4C4000000060216E4C8000000079C
-:1023B0000216E4CC000000010216E02C010101200D
-:1023C0000216E4D0000000010216E4D4000000016F
-:1023D0000216E4D8000000010216E4DC000000014F
-:1023E0000216E030010101010216E4E000000001E4
-:1023F0000216E4E4000000040216E4E80000000411
-:102400000216E4EC000000020216E0340801200489
-:102410000216E4F0000000050216E4F400000005D6
-:102420000216E4F8000000050216E4FC00000005B6
-:102430000216E038200810010216E500000000082E
-:102440000216E504000000060216E5080000000779
-:102450000216E03C0101012002168240003F003FCD
-:1024600002168244000000000216E524003F003FEF
-:102470000216E52800000000021682480000000055
-:102480000216824C003F003F0216E52C00000000BF
-:102490000216E530003F003F0216825001000100A5
-:1024A00002168254010001000216E5340100010009
-:1024B0000216E538010001000616825800000002ED
-:1024C0000216E53C000000000216E5400000000096
-:1024D0000216826000C000C00216826400C000C004
-:1024E0000216E54400C000C00216E54800C000C066
-:1024F000021682681E001E000216826C1E001E005C
-:102500000216E54C1E001E000216E5501E001E00BD
-:1025100002168270400040000216827440004000A3
-:102520000216E554400040000216E5584000400005
-:1025300002168278800080000216827C8000800073
-:102540000216E55C800080000216E56080008000D5
-:1025500002168280200020000216828420002000C3
-:102560000216E564200020000216E5682000200025
-:1025700006168288000000020216E56C00000000CA
-:102580000216E570000000000216829000000000B4
-:1025900002168294000000000216E574000000009C
-:1025A0000216E57800000000021682980000000084
-:1025B0000216829C000000000216E57C000000006C
-:1025C0000216E58000000000021682A00000000054
-:1025D000021682A400000001061682A80000000A6C
-:1025E000021681F400000C08021681F80000004079
-:1025F000021681FC0000010002168200000000208B
-:1026000002168204000000170216820800000080F3
-:102610000216820C00000200021682100000000068
-:102620000216821801FF01FF0216821401FF01FF4A
-:102630000216E51001FF01FF0216E50C01FF01FF84
-:102640000216823C00000013021680900000013F39
-:102650000216806000000140021680640000014004
-:10266000061680680000000202168070000000C09C
-:1026700006168074000000070216809C00000048C7
-:10268000021680A000000048061680A40000000288
-:10269000021680AC00000048061680B0000000075B
-:1026A000021682380000800002168234000025E401
-:1026B0000216809400007FFF0216822000070007A8
-:1026C0000216821C000700070216E5180007000723
-:1026D0000216E51400070007021682280000000019
-:1026E00002168224FFFFFFFF0216E5200000000013
-:1026F0000216E51CFFFFFFFF0216E6BC000000000B
-:102700000216E6C0000000020216E6C40000000146
-:102710000216E6C8000000030216E6CC0000000422
-:102720000216E6D0000000060216E6D400000005FE
-:102730000216E6D800000007021680EC000000FF39
-:1027400002140000000000010214000C000000014F
-:1027500002140040000000010214004400007FFF4A
-:102760000214000C00000000021400000000000031
-:102770000214006C000000000214000400000001BC
-:1027800002140030000000010214000400000000E8
-:102790000214005C000000000214000800000001A8
-:1027A00002140034000000010214000800000000C0
-:1027B0000214006000000000020200580000003215
-:1027C000020200A003150020020200A4031500204D
-:1027D000020200A801000030020200AC0810000054
-:1027E000020200B000000033020200B4000000301A
-:1027F000020200B800000031020200BC0000000329
-:10280000020200C000000006020200C40000000333
-:10281000020200C800000003020200CC0000000217
-:10282000020200D000000000020200D400000002FA
-:10283000020200DC00000000020200E000000006CE
-:10284000020200E400000004020200E800000002AE
-:10285000020200EC00000002020200F00000000191
-:10286000020200FC0000000602020120000000003D
-:102870000202013400000002020201B00000000167
-:102880000202020C0000000102020214000000011A
-:10289000020202180000000202020404000000010B
-:1028A0000202040C0000004002020410000000407C
-:1028B0000202041C000000040202042000000020A8
-:1028C000020204240000000202020428000000208A
-:1028D000060205000000001204020480001F032904
-:1028E000020200600000000F020200640000000706
-:1028F000020200680000000B0202006C0000000EE3
-:10290000020200700000000E0602007400000003C6
-:10291000020200F4000000040202000400000001B2
-:1029200002020008000000010202000C0000000189
-:102930000202001000000001020200140000000169
-:1029400002020018000000010202001C0000000149
-:102950000202002000000001020200240000000129
-:1029600002020028000000010202002C0000000109
-:1029700002020030000000010202003400000001E9
-:1029800002020038000000010202003C00000001C9
-:1029900002020040000000010202004400000001A9
-:1029A00002020048000000010202004C0000000189
-:1029B000020200500000000102020108000000C8ED
-:1029C0000202011800000002020201C4000000001F
-:1029D000020201CC00000000020201D4000000024B
-:1029E000020201DC00000002020201E4000000FF1C
-:1029F000020201EC000000FF0202010000000000E2
-:102A00000202010C000000C80202011C00000002CA
-:102A1000020201C800000000020201D00000000014
-:102A2000020201D800000002020201E000000002E0
-:102A3000020201E8000000FF020201F0000000FFB6
-:102A4000020201040000000002020108000000C8A8
-:102A50000202011800000002020201C4000000008E
-:102A6000020201CC00000000020201D400000002BA
-:102A7000020201DC00000002020201E4000000FF8B
-:102A8000020201EC000000FF020201000000000051
-:102A90000202010C000000C80202011C000000023A
-:102AA000020201C800000000020201D00000000084
-:102AB000020201D800000002020201E00000000250
-:102AC000020201E8000000FF020201F0000000FF26
-:102AD000020201040000000002020108000000C818
-:102AE0000202011800000002020201C400000000FE
-:102AF000020201CC00000000020201D4000000022A
-:102B0000020201DC00000002020201E4000000FFFA
-:102B1000020201EC000000FF0202010000000000C0
-:102B20000202010C000000C80202011C00000002A9
-:102B3000020201C800000000020201D000000000F3
-:102B4000020201D800000002020201E000000002BF
-:102B5000020201E8000000FF020201F0000000FF95
-:102B6000020201040000000002020108000000C887
-:102B70000202011800000002020201C4000000006D
-:102B8000020201CC00000000020201D40000000299
-:102B9000020201DC00000002020201E4000000FF6A
-:102BA000020201EC000000FF020201000000000030
-:102BB0000202010C000000C80202011C0000000219
-:102BC000020201C800000000020201D00000000063
-:102BD000020201D800000002020201E0000000022F
-:102BE000020201E8000000FF020201F0000000FF05
-:102BF00002020104000000000728040000BD0000DC
-:102C0000082807A8000B0348072C00003406000022
-:102C1000072C800037960D02072D00003BC31AE8F1
-:102C2000072D8000382629D9072E0000124537E3EA
-:102C3000082E22203BBC034A0128000000000000AF
-:102C40000128000400000000012800080000000026
-:102C50000128000C00000000012800100000000006
-:102C600001280014000000000228002000000001DC
-:102C700002280024000000020228002800000003AF
-:102C80000228002C00000000022800300000000490
-:102C90000228003400000001022800380000000073
-:102CA0000228003C0000000102280040000000044F
-:102CB0000228004400000000022800480000000133
-:102CC0000228004C00000003022800500000000011
-:102CD00002280054000000010228005800000004EF
-:102CE0000228005C000000000228006000000001D3
-:102CF00002280064000000030228006800000000B1
-:102D00000228006C0000000102280070000000048E
-:102D1000022800740000000002280078000000046F
-:102D20000228007C0000000306280080000000024A
-:102D3000022800A400003FFF022800A8000003FFB3
-:102D400002280224000000000228023400000000D3
-:102D50000228024C00000000022802E40000FFFFED
-:102D60000628200000000800022B8BC00000000194
-:102D7000022B800000000000022B804000000018A1
-:102D8000022B80800000000C022B80C00000006637
-:102D90000C2B83000007A1200A2B830000000138C0
-:102DA0000B2B830000001388022B83C0000001F46A
-:102DB0000C2B8340000001F40A2B8340000000002C
-:102DC0000B2B8340000000050A2B83800004C4B451
-:102DD0000C2B83801DCD65000A2B148000000000A1
-:102DE0000B2B8380004C4B40022B14800000000111
-:102DF000062A29C800000004042A29D80002034C2E
-:102E0000062A208000000048062A9020000000C802
-:102E1000062A900000000002062A21A80000008671
-:102E2000062A200000000020022A23C8000000001B
-:102E3000042A23D00002034E042A249800040350DD
-:102E4000022A2C2000000000022A2C1000000000A2
-:102E5000042A2C0800020354022A3010000000014A
-:102E6000062A404000000010042A400000100356CB
-:102E7000062A6AC000000002062A6B000000000457
-:102E8000042A840800020366022B080000000000E8
-:102E9000042B0C0000100368022B08000100000046
-:102EA000042B0C4000080378022B080002000000ED
-:102EB000042B0C6000080380062AC000000000FC00
-:102EC000062A24A800000014062A25480000002431
-:102ED000062A266800000024062A2788000000240D
-:102EE000062A28A800000024062AA00000000028C6
-:102EF000062AA1400000000C042A29E000020388F1
-:102F0000022A300000000001062A502000000002C2
-:102F1000062A503000000002062A5000000000027D
-:102F2000062A501000000002022A52080000000188
-:102F3000042A6AC80002038A062A6B1000000042B5
-:102F4000062A6D2000000004062AC3F0000000FCE1
-:102F5000062A24F800000014062A25D800000024C0
-:102F6000062A26F800000024062A2818000000245B
-:102F7000062A293800000024062AA0A00000002804
-:102F8000062AA1700000000C042A29E80002038C24
-:102F9000022A300400000001062A50280000000226
-:102FA000062A503800000002062A500800000002DD
-:102FB000062A501800000002022A520C00000001EC
-:102FC000042A6AD00002038E062A6C180000004210
-:102FD000062A6D3000000004022AC7E0000000004D
-:102FE000042A29F000100390062A50480000000E21
-:102FF000022AC7E400000000042A2A30001003A0BF
-:10300000062A50800000000E022AC7E800000000D7
-:10301000042A2A70001003B0062A50B80000000EDF
-:10302000022AC7EC00000000042A2AB0001003C0E6
-:10303000062A50F00000000E022AC7F0000000002F
-:10304000042A2AF0001003D0062A51280000000E9E
-:10305000022AC7F400000000042A2B30001003E00D
-:10306000062A51600000000E022AC7F80000000086
-:10307000042A2B70001003F0062A51980000000E5D
-:10308000022AC7FC00000000042A2BB00010040034
-:10309000062A51D00000000E0210100800000001A6
-:1030A0000210105000000001021010000003D000B8
-:1030B000021010040000003D091018000200041066
-:1030C0000910110000280610061011A000000018B9
-:1030D00006102400000000E00210201C0000000088
-:1030E0000210202000000001021020C00000000299
-:1030F000021020040000000102102008000000015E
-:1031000009103C0000050638091038000005063D8E
-:10311000091038200005064206104C00000001008E
-:1031200002104028000000100210404400003FFF41
-:103130000210405800280000021040840084924A87
-:1031400002104058000000000210800000001080B3
-:10315000021080AC00000000021080380000001057
-:103160000210810000000000061081200000000213
-:1031700002108008000002B502108010000000005C
-:10318000061082000000004A021081080001FFFFC3
-:1031900006108140000000020210800000001A802A
-:1031A0000610900000000024061091200000004A44
-:1031B000061093700000004A061095C00000004AF7
-:1031C0000210800400001080021080B00000000196
-:1031D0000210803C0000001002108104000000007A
-:1031E00006108128000000020210800C000002B5C9
-:1031F0000210801400000000061084000000004A45
-:103200000210810C0001FFFF06108148000000023F
-:103210000210800400001A80061090900000002424
-:10322000061092480000004A061094980000004AD8
-:10323000061096E80000004A02108000000010808E
-:10324000021080AC00000002021080380000001064
-:103250000210810000000000061081200000000222
-:1032600002108008000002B502108010000000006B
-:10327000061082000000004A021081080001FFFFD2
-:1032800006108140000000020210800000001A8039
-:103290000610900000000024061091200000004A53
-:1032A000061093700000004A061095C00000004A06
-:1032B0000210800400001080021080B000000003A3
-:1032C0000210803C00000010021081040000000089
-:1032D00006108128000000020210800C000002B5D8
-:1032E0000210801400000000061084000000004A54
-:1032F0000210810C0001FFFF06108148000000024F
-:103300000210800400001A80061090900000002433
-:10331000061092480000004A061094980000004AE7
-:10332000061096E80000004A02108000000010809D
-:10333000021080AC00000004021080380000001071
-:103340000210810000000000061081200000000231
-:1033500002108008000002B502108010000000007A
-:10336000061082000000004A021081080001FFFFE1
-:1033700006108140000000020210800000001A8048
-:103380000610900000000024061091200000004A62
-:10339000061093700000004A061095C00000004A15
-:1033A0000210800400001080021080B000000005B0
-:1033B0000210803C00000010021081040000000098
-:1033C00006108128000000020210800C000002B5E7
-:1033D0000210801400000000061084000000004A63
-:1033E0000210810C0001FFFF06108148000000025E
-:1033F0000210800400001A80061090900000002443
-:10340000061092480000004A061094980000004AF6
-:10341000061096E80000004A0210800000001080AC
-:10342000021080AC0000000602108038000000107E
-:103430000210810000000000061081200000000240
-:1034400002108008000002B5021080100000000089
-:10345000061082000000004A021081080001FFFFF0
-:1034600006108140000000020210800000001A8057
-:103470000610900000000024061091200000004A71
-:10348000061093700000004A061095C00000004A24
-:103490000210800400001080021080B000000007BD
-:1034A0000210803C000000100210810400000000A7
-:1034B00006108128000000020210800C000002B5F6
-:1034C0000210801400000000061084000000004A72
-:1034D0000210810C0001FFFF06108148000000026D
-:1034E0000210800400001A80061090900000002452
-:1034F000061092480000004A061094980000004A06
-:10350000061096E80000004A021205B00000000113
-:103510000212049000E383400212051400003C10E4
-:103520000212066C0000000102120670000000008A
-:1035300002120494FFFFFFFF02120498FFFFFFFF37
-:103540000212049CFFFFFFFF021204A0FFFFFFFF17
-:10355000021204A4FFFFFFFF021204A8FFFFFFFFF7
-:10356000021204ACFFFFFFFF021204B0FFFFFFFFD7
-:10357000021204BCFFFFFFFF021204C0FFFFFFFFA7
-:10358000021204C4FFFFFFFF021204C8FFFFFFFF87
-:10359000021204CCFFFFFFFF021204D0FFFFFFFF67
-:1035A000021204D8FFFFFFFF021204DCFFFFFFFF3F
-:1035B000021204E0FFFFFFFF021204E4FFFFFFFF1F
-:1035C000021204E8FFFFFFFF021204ECFFFFFFFFFF
-:1035D000021204F0FFFFFFFF021204F4FFFFFFFFDF
-:1035E000021204F8FFFFFFFF021204FCFFFFFFFFBF
-:1035F00002120500FFFFFFFF02120504FFFFFFFF9D
-:1036000002120508FFFFFFFF0212050CFFFFFFFF7C
-:1036100002120510FFFFFFFF021204D4FF802000FA
-:10362000021204B4F0005000021204B8F00080004E
-:1036300002120390000000080212039C0000000820
-:10364000021203A000000008021203A400000002FE
-:10365000021203BC00000004021203C000000005B7
-:10366000021203C400000004021203D00000000094
-:103670000212036C00000001021203680000003F08
-:10368000021201BC00000040021201C00000180834
-:10369000021201C400000803021201C8000008035E
-:1036A000021201CC00000040021201D00000000311
-:1036B000021201D400000803021201D8000008031E
-:1036C000021201DC00000803021201E00001000305
-:1036D000021201E400000803021201E800000803DE
-:1036E000021201EC00000003021201F000000003CE
-:1036F000021201F400000003021201F800000003AE
-:10370000021201FC0000000302120200000000038C
-:10371000021202040000000302120208000000036B
-:103720000212020C0000000302120210000000034B
-:10373000021202140000000302120218000000032B
-:103740000212021C0000000302120220000000030B
-:1037500002120224000000030212022800002403C7
-:103760000212022C0000002F021202300000000999
-:103770000212023400000019021202380000018413
-:103780000212023C00000183021202400000030604
-:103790000212024400000019021202480000000652
-:1037A0000212024C0000030602120250000003063F
-:1037B00002120254000003060212025800000C8696
-:1037C0000212025C000003060212026000000306FF
-:1037D00002120264000000060212026800000006E5
-:1037E0000212026C000000060212027000000006C5
-:1037F00002120274000000060212027800000006A5
-:103800000212027C00000006021202800000000684
-:103810000212028400000006021202880000000664
-:103820000212028C00000006021202900000000644
-:103830000212029400000006021202980000000624
-:103840000212029C00000006021202A00000030601
-:10385000021202A400000013021202A800000006D7
-:10386000021202B000001004021202B400001004A0
-:103870000212032400106440021203280010644066
-:10388000021205B400000001021201B000000001A4
-:103890000600A000000000160200A0EC5554000035
-:1038A0000200A0F0555555550200A0F400005555F2
-:1038B0000200A0F8F00000000200A0FC5554000037
-:1038C0000200A100555555550200A10400005555B0
-:1038D0000200A108F00000000200A18C5554000075
-:1038E0000200A190555555550200A1940000555570
-:1038F0000200A198F00000000200A19C000000005E
-:103900000200A1A0000100000200A1A400005014C8
-:103910000200A1A8000000000200A45C00000C004E
-:103920000200A61C000000030200A06CFF5C000067
-:103930000200A070FFF55FFF0200A0740000FFFF0F
-:103940000200A078F00003E00200A07C000000006C
-:103950000200A0800000A0000600A0840000000576
-:103960000200A0980FE000000600A09C00000007E5
-:103970000200A0B8000004000600A0BC0000000384
-:103980000200A0C8000010000600A0CC0000000348
-:103990000200A0D8000040000600A0DC00000003E8
-:1039A0000200A0E8000100000600A22C00000004B4
-:1039B0000200A10CFF5C00000200A110FFF55FFFF8
-:1039C0000200A1140000FFFF0200A118F00003E0B4
-:1039D0000200A11C000000000200A1200000A000C5
-:1039E0000600A124000000050200A1380FE000003D
-:1039F0000600A13C000000070200A15800000800DA
-:103A00000600A15C000000030200A1680000200085
-:103A10000600A16C000000030200A17800008000F5
-:103A20000600A17C000000030200A1880002000043
-:103A30000600A23C0000000400000000000000009E
-:103A40000000003100000000000000000000000045
-:103A50000000000000000000000000000000000066
-:103A600000000000000000000000000000310032F3
-:103A70000000000000000000000000000000000046
-:103A80000000000000000000000000000000000036
-:103A9000000000000000000000320056000000009E
-:103AA0000000000000000000000000000000000016
-:103AB0000000000000000000000000000000000006
-:103AC000000000000056008C000000000000000014
-:103AD000008C009000900094009400980098009C46
-:103AE000009C00A000A000A400A400A800A800ACB6
-:103AF00000AC00B100B100B300B300B5000000009D
-:103B000000000000000000000000000000000000B5
-:103B100000000000000000000000000000B50100EF
-:103B2000010001060106010C010C01140114011C25
-:103B3000011C01240124012C012C01340134013C1D
-:103B4000013C01440144014C000000000000000061
-:103B50000000000000000000000000000000000065
-:103B60000000000000000000000000000000000055
-:103B70000000000000000000000000000000000045
-:103B80000000000000000000000000000000000035
-:103B90000000000000000000000000000000000025
-:103BA0000000000000000000000000000000000015
-:103BB0000000000000000000000000000000000005
-:103BC00000000000000000000000000000000000F5
-:103BD00000000000000000000000000000000000E5
-:103BE00000000000000000000000000000000000D5
-:103BF0000000000000000000014C01510000000026
-:103C000000000000015101520152015301530154BF
-:103C100001540155015501560156015701570158EC
-:103C200001580159000000000000000000000000E1
-:103C30000000000000000000000000000000000084
-:103C40000000000000000000000000000000000074
-:103C50000159015E015E016A016A017600000000FF
-:103C60000000000000000000000000000000000054
-:103C70000000000000000000000000000000000044
-:103C80000000000000000000000000000000000034
-:103C90000000000000000000000000000000000024
-:103CA0000000000000000000017601770000000025
-:103CB0000000000000000000000000000000000004
-:103CC00000000000000000000000000000000000F4
-:103CD000000000000177019A0000000000000000D1
-:103CE00000000000000000000000000000000000D4
-:103CF00000000000000000000000000000000000C4
-:103D0000019A01C200000000000000000000000055
-:103D100000000000000000000000000000000000A3
-:103D200000000000000000000000000001C201F3DC
-:103D3000000000000000000001F301FA01FA020196
-:103D4000020102080208020F020F02160216021DEB
-:103D5000021D02240224022B022B02630000000039
-:103D600000000000026302670267026B026B026FD1
-:103D7000026F0273027302770277027B027B027F7B
-:103D8000027F0283028302D102D102EB02EB030520
-:103D9000030503080308030B030B030E030E0311B3
-:103DA00003110314031403170317031A031A031D43
-:103DB000031D035E035E0362036203660366036919
-:103DC0000369036C036C036F036F03720372037563
-:103DD000037503780378037B037B037E037E037FF5
-:103DE00000000000000000000000000000000000D3
-:103DF00000000000000000000000000000000000C3
-:103E00000000000000000000037F0391000000009C
-:103E100000000000000000000000000000000000A2
-:103E20000000000000000000000000000000000092
-:103E300000000000039103A603A603A903A903AC95
-:103E40000000000000000000000000000000000072
-:103E50000000000000000000000000000000000062
-:103E600003AC03D9000000000000000000000000C7
-:103E70000000000000000000000000000000000042
-:103E800000000000000000000000000003D904DC76
-:103E90000000000000000000000000000000000022
-:103EA0000000000000000000000000000000000012
-:103EB000000000000000000004DC04E304E304E769
-:103EC00004E704EB00000000000000000000000018
-:103ED00000000000000000000000000000000000E2
-:103EE0000000000004EB052B0000000000000000B3
-:103EF000052B05340534053D053D05460546054FB2
-:103F0000054F0558055805610561056A056A057381
-:103F1000057305CB05CB05DD05DD05EF05EF05F2E6
-:103F200005F205F505F505F805F805FB05FB05FEA9
-:103F300005FE060106010604060406070607060E2E
-:103F40000000000000000000000000000000000071
-:103F50000000000000000000000000000000000061
-:103F60000000000000000000060E06140000000023
-:103F70000000000000000000000000000000000041
-:103F80000000000000000000000000000000000031
-:103F900000000000061406170000000000000000EA
-:103FA0000000000000000000000000000000000011
-:103FB0000000000000000000000000000000000001
-:103FC0000617061D000000000000000000000000B1
-:103FD00000000000000000000000000000000000E1
-:103FE00000000000000000000000000000000000D1
-:103FF0000000000000000000061D062C062C063BF9
-:10400000063B064A064A06590659066806680677B8
-:1040100006770686068606950695070600000000C8
-:104020000000000000000000000000000000000090
-:104030000000000000000000000000000000000080
-:1040400000000000070607190719072A072A073B7F
-:104050000000000000000000000000000000000060
-:104060000000000000000000000000000000000050
-:10407000000000000000000000010000000204C079
-:104080000003098000040E4000051300000617C05D
-:1040900000071C800008214000092600000A2AC0F1
-:1040A000000B2F80000C3440000D3900000E3DC085
-:1040B000000F42800010474000114C00001250C019
-:1040C0000013558000145A4000155F00001663C0AD
-:1040D0000017688000186D4000197200001A76C041
-:1040E000001B7B80001C8040001D8500001E89C0D5
-:1040F000001F8E8000209340000020000000400040
-:1041000000006000000080000000A0000000C0006F
-:104110000000E0000001000000012000000140005C
-:1041200000016000000180000001A0000001C0004B
-:104130000001E00000020000000220000002400038
-:1041400000026000000280000002A0000002C00027
-:104150000002E00000030000000320000003400014
-:1041600000036000000380000003A0000003C00003
-:104170000003E000000400000004200000044000F0
-:1041800000046000000480000004A0000004C000DF
-:104190000004E000000500000005200000054000CC
-:1041A00000056000000580000005A0000005C000BB
-:1041B0000005E000000600000006200000064000A8
-:1041C00000066000000680000006A0000006C00097
-:1041D0000006E00000070000000720000007400084
-:1041E00000076000000780000007A0000007C00073
-:1041F0000007E00000080000000820000008400060
-:1042000000086000000880000008A0000008C0004E
-:104210000008E0000009000000092000000940003B
-:1042200000096000000980000009A0000009C0002A
-:104230000009E000000A0000000A2000000A400017
-:10424000000A6000000A8000000AA000000AC00006
-:10425000000AE000000B0000000B2000000B4000F3
-:10426000000B6000000B8000000BA000000BC000E2
-:10427000000BE000000C0000000C2000000C4000CF
-:10428000000C6000000C8000000CA000000CC000BE
-:10429000000CE000000D0000000D2000000D4000AB
-:1042A000000D6000000D8000000DA000000DC0009A
-:1042B000000DE000000E0000000E2000000E400087
-:1042C000000E6000000E8000000EA000000EC00076
-:1042D000000EE000000F0000000F2000000F400063
-:1042E000000F6000000F8000000FA000000FC00052
-:1042F000000FE0000010000000102000001040003F
-:1043000000106000001080000010A0000010C0002D
-:104310000010E0000011000000112000001140001A
-:1043200000116000001180000011A0000011C00009
-:104330000011E000001200000012200000124000F6
-:1043400000126000001280000012A0000012C000E5
-:104350000012E000001300000013200000134000D2
-:1043600000136000001380000013A0000013C000C1
-:104370000013E000001400000014200000144000AE
-:1043800000146000001480000014A0000014C0009D
-:104390000014E0000015000000152000001540008A
-:1043A00000156000001580000015A0000015C00079
-:1043B0000015E00000160000001620000016400066
-:1043C00000166000001680000016A0000016C00055
-:1043D0000016E00000170000001720000017400042
-:1043E00000176000001780000017A0000017C00031
-:1043F0000017E0000018000000182000001840001E
-:1044000000186000001880000018A0000018C0000C
-:104410000018E000001900000019200000194000F9
-:1044200000196000001980000019A0000019C000E8
-:104430000019E000001A0000001A2000001A4000D5
-:10444000001A6000001A8000001AA000001AC000C4
-:10445000001AE000001B0000001B2000001B4000B1
-:10446000001B6000001B8000001BA000001BC000A0
-:10447000001BE000001C0000001C2000001C40008D
-:10448000001C6000001C8000001CA000001CC0007C
-:10449000001CE000001D0000001D2000001D400069
-:1044A000001D6000001D8000001DA000001DC00058
-:1044B000001DE000001E0000001E2000001E400045
-:1044C000001E6000001E8000001EA000001EC00034
-:1044D000001EE000001F0000001F2000001F400021
-:1044E000001F6000001F8000001FA000001FC00010
-:1044F000001FE000002000000020200000204000FD
-:1045000000206000002080000020A0000020C000EB
-:104510000020E000002100000021200000214000D8
-:1045200000216000002180000021A0000021C000C7
-:104530000021E000002200000022200000224000B4
-:1045400000226000002280000022A0000022C000A3
-:104550000022E00000230000002320000023400090
-:1045600000236000002380000023A0000023C0007F
-:104570000023E0000024000000242000002440006C
-:1045800000246000002480000024A0000024C0005B
-:104590000024E00000250000002520000025400048
-:1045A00000256000002580000025A0000025C00037
-:1045B0000025E00000260000002620000026400024
-:1045C00000266000002680000026A0000026C00013
-:1045D0000026E00000270000002720000027400000
-:1045E00000276000002780000027A0000027C000EF
-:1045F0000027E000002800000028200000284000DC
-:1046000000286000002880000028A0000028C000CA
-:104610000028E000002900000029200000294000B7
-:1046200000296000002980000029A0000029C000A6
-:104630000029E000002A0000002A2000002A400093
-:10464000002A6000002A8000002AA000002AC00082
-:10465000002AE000002B0000002B2000002B40006F
-:10466000002B6000002B8000002BA000002BC0005E
-:10467000002BE000002C0000002C2000002C40004B
-:10468000002C6000002C8000002CA000002CC0003A
-:10469000002CE000002D0000002D2000002D400027
-:1046A000002D6000002D8000002DA000002DC00016
-:1046B000002DE000002E0000002E2000002E400003
-:1046C000002E6000002E8000002EA000002EC000F2
-:1046D000002EE000002F0000002F2000002F4000DF
-:1046E000002F6000002F8000002FA000002FC000CE
-:1046F000002FE000003000000030200000304000BB
-:1047000000306000003080000030A0000030C000A9
-:104710000030E00000310000003120000031400096
-:1047200000316000003180000031A0000031C00085
-:104730000031E00000320000003220000032400072
-:1047400000326000003280000032A0000032C00061
-:104750000032E0000033000000332000003340004E
-:1047600000336000003380000033A0000033C0003D
-:104770000033E0000034000000342000003440002A
-:1047800000346000003480000034A0000034C00019
-:104790000034E00000350000003520000035400006
-:1047A00000356000003580000035A0000035C000F5
-:1047B0000035E000003600000036200000364000E2
-:1047C00000366000003680000036A0000036C000D1
-:1047D0000036E000003700000037200000374000BE
-:1047E00000376000003780000037A0000037C000AD
-:1047F0000037E0000038000000382000003840009A
-:1048000000386000003880000038A0000038C00088
-:104810000038E00000390000003920000039400075
-:1048200000396000003980000039A0000039C00064
-:104830000039E000003A0000003A2000003A400051
-:10484000003A6000003A8000003AA000003AC00040
-:10485000003AE000003B0000003B2000003B40002D
-:10486000003B6000003B8000003BA000003BC0001C
-:10487000003BE000003C0000003C2000003C400009
-:10488000003C6000003C8000003CA000003CC000F8
-:10489000003CE000003D0000003D2000003D4000E5
-:1048A000003D6000003D8000003DA000003DC000D4
-:1048B000003DE000003E0000003E2000003E4000C1
-:1048C000003E6000003E8000003EA000003EC000B0
-:1048D000003EE000003F0000003F2000003F40009D
-:1048E000003F6000003F8000003FA000003FC0008C
-:1048F000003FE000003FE00100000000000001FF79
-:104900000000020000007FF800007FF800000704AC
-:104910000000350000000001FFFFFFFFFFFFFFFF69
-:10492000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF97
-:10493000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF87
-:10494000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF77
-:10495000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF67
-:10496000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF57
-:10497000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF47
-:10498000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF37
-:10499000FFFFFFFFFFFFFFFFFFFFFFFF0000000023
-:1049A000FFFFFFFF00000000FFFFFFFFFFFFFFFF13
-:1049B00000000000FFFFFFFF00000000FFFFFFFFFF
-:1049C000FFFFFFFF00000000FFFFFFFF00000000EF
-:1049D000FFFFFFFF0000000300BEBC20FFFFFFFF42
-:1049E00000000000FFFFFFFF00000000FFFFFFFFCF
-:1049F0000000000300BEBC20FFFFFFFF000000001E
-:104A0000FFFFFFFF00000000FFFFFFFF00000003AB
-:104A100000BEBC20FFFFFFFF00000000FFFFFFFF04
-:104A200000000000FFFFFFFF0000000300BEBC20ED
-:104A3000FFFFFFFF00000000FFFFFFFF000000007E
-:104A4000FFFFFFFF0000000300BEBC20FFFFFFFFD1
-:104A500000000000FFFFFFFF00000000FFFFFFFF5E
-:104A60000000000300BEBC2000002000000040C089
-:104A700000006180000082400000A3000000C3C06D
-:104A80000000E4800001054000012600000146C04E
-:104A900000016780000188400001A9000001C9C031
-:104AA0000001EA8000020B4000022C0000024CC012
-:104AB00000026D8000028E400002AF000002CFC0F5
-:104AC0000002F0800003114000033200000352C0D6
-:104AD00000037380000394400003B5000003D5C0B9
-:104AE0000003F6800004174000043800000458C09A
-:104AF0000004798000049A400000800000010380D7
-:104B00000001870000020A8000028E00000311806D
-:104B1000000395000004188000049C0000051F801D
-:104B20000005A300000626800006AA0000072D80CD
-:104B30000007B100000834800008B80000093B807D
-:104B40000009BF00000A4280000AC600000B49802D
-:104B5000000BCD00000C5080000CD400000D5780DD
-:104B6000000DDB0000007FF800007FF800000487E4
-:104B700000001500000019000000002800100000CF
-:104B80000000000000000000FFFFFFFF40000000E9
-:104B90004000000040000000400000004000000015
-:104BA0004000000040000000400000004000000005
-:104BB00040000000400000004000000040000000F5
-:104BC00040000000400000004000000040000000E5
-:104BD00040000000400000004000000040000000D5
-:104BE00040000000400000004000000040000000C5
-:104BF00040000000400000004000000040000000B5
-:104C000040000000400000004000000000007FF86D
-:104C100000007FF8000003E000001500FFFFFFFF29
-:104C2000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF94
-:104C3000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF84
-:104C4000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF74
-:104C5000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF64
-:104C6000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF54
-:104C7000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF44
-:104C8000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF34
-:104C9000FFFFFFFFFFFFFFFFFFFFFFFF40000000E0
-:104CA0004000000040000000400000004000000004
-:104CB00040000000400000004000000040000000F4
-:104CC00040000000400000004000000040000000E4
-:104CD00040000000400000004000000040000000D4
-:104CE00040000000400000004000000040000000C4
-:104CF00040000000400000004000000040000000B4
-:104D000040000000400000004000000040000000A3
-:104D100040000000400000004000000000001000C3
-:104D2000000020800000310000004180000052009F
-:104D30000000628000007300000083800000940087
-:104D40000000A4800000B5000000C5800000D6006F
-:104D50000000E6800000F700000107800001180055
-:104D600000012880000139000001498000015A003B
-:104D700000016A8000017B0000018B8000019C0023
-:104D80000001AC800001BD000001CD800001DE000B
-:104D90000001EE800001FF0000007FF800007FF8B6
-:104DA0000000023E0000350010000000000028ADA9
-:104DB000000000000001000100350804CCCCCCC587
-:104DC000FFFFFFFFFFFFFFFF7058103C00000000D7
-:104DD000CCCC0201CCCCCCCCCCCC0201CCCCCCCC3D
-:104DE000CCCC0201CCCCCCCCCCCC0201CCCCCCCC2D
-:104DF000CCCC0201CCCCCCCCCCCC0201CCCCCCCC1D
-:104E0000CCCC0201CCCCCCCCCCCC0201CCCCCCCC0C
-:104E100000000000FFFFFFFF400000004000000016
-:104E20004000000040000000400000004000000082
-:104E30004000000040000000400000004000000072
-:104E40004000000040000000400000004000000062
-:104E50004000000040000000400000004000000052
-:104E60004000000040000000400000004000000042
-:104E70004000000040000000400000004000000032
-:104E80004000000040000000400000004000000022
-:104E90004000000040000000000E0232011600D663
-:104EA000001000000000000000720236012300F331
-:104EB00000100000000000000000FFFF00000000E4
-:104EC0000000FFFF000000000000FFFF00000000E6
-:104ED0000000FFFF000000000000FFFF00000000D6
-:104EE0000000FFFF000000000000FFFF00000000C6
-:104EF0000000FFFF000000000000FFFF00000000B6
-:104F00000000FFFF000000000000FFFF00000000A5
-:104F10000000FFFF000000000000FFFF0000000095
-:104F20000000FFFF000000000000FFFF0000000085
-:104F30000000FFFF000000000000FFFF0000000075
-:104F40000000FFFF000000000000FFFF0000000065
-:104F50000000FFFF000000000000FFFF0000000055
-:104F60000000FFFF000000000000FFFF0000000045
-:104F70000000FFFF000000000000FFFF0000000035
-:104F80000000FFFF000000000000FFFF0000000025
-:104F90000000FFFF000000000000FFFF0000000015
-:104FA0000000FFFF000000000000FFFF0000000005
-:104FB0000000FFFF000000000000FFFF00000000F5
-:104FC0000000FFFF000000000000FFFF00000000E5
-:104FD0000000FFFF000000000000FFFF00000000D5
-:104FE0000000FFFF000000000000FFFF00000000C5
-:104FF0000000FFFF000000000000FFFF00000000B5
-:105000000000FFFF000000000000FFFF00000000A4
-:105010000000FFFF000000000000FFFF0000000094
-:105020000000FFFF000000000000FFFF0000000084
-:105030000000FFFF000000000000FFFF0000000074
-:105040000000FFFF000000000000FFFF0000000064
-:105050000000FFFF000000000000FFFF0000000054
-:105060000000FFFF000000000000FFFF0000000044
-:105070000000FFFF000000000000FFFF0000000034
-:105080000000FFFF000000000000FFFF0000000024
-:105090000000FFFF000000000000FFFF0000000014
-:1050A0000000FFFF000000000000FFFF0000000004
-:1050B0000000FFFF00000000FFFFFFF3320FFFFFC3
-:1050C0000C30C30CC30C30C3CF3CF300F3CF3CF324
-:1050D0000000CF3CCDCDCDCDFFFFFFF130EFFFFF86
-:1050E0000C30C30CC30C30C3CF3CF300F3CF3CF304
-:1050F0000001CF3CCDCDCDCDFFFFFFF6305FFFFFF0
-:105100000C30C30CC30C30C3CF3CF300F3CF3CF3E3
-:105110000002CF3CCDCDCDCDFFFFF4061CBFFFFF7D
-:105120000C30C305C30C30C3CF300014F3CF3CF3B5
-:105130000004CF3CCDCDCDCDFFFFFFF2304FFFFFC0
-:105140000C30C30CC30C30C3CF3CF300F3CF3CF3A3
-:105150000008CF3CCDCDCDCDFFFFFFFA302FFFFFB4
-:105160000C30C30CC30C30C3CF3CF300F3CF3CF383
-:105170000010CF3CCDCDCDCDFFFFFFF731EFFFFFCE
-:105180000C30C30CC30C30C3CF3CF300F3CF3CF363
-:105190000020CF3CCDCDCDCDFFFFFFF5302FFFFF61
-:1051A0000C30C30CC30C30C3CF3CF300F3CF3CF343
-:1051B0000040CF3CCDCDCDCDFFFFFFF3310FFFFF42
-:1051C0000C30C30CC30C30C3CF3CF300F3CF3CF323
-:1051D0000000CF3CCDCDCDCDFFFFFFF1310FFFFF64
-:1051E0000C30C30CC30C30C3CF3CF300F3CF3CF303
-:1051F0000001CF3CCDCDCDCDFFFFFFF6305FFFFFEF
-:105200000C30C30CC30C30C3CF3CF300F3CF3CF3E2
-:105210000002CF3CCDCDCDCDFFFFF4061CBFFFFF7C
-:105220000C30C305C30C30C3CF300014F3CF3CF3B4
-:105230000004CF3CCDCDCDCDFFFFFFF2304FFFFFBF
-:105240000C30C30CC30C30C3CF3CF300F3CF3CF3A2
-:105250000008CF3CCDCDCDCDFFFFFFFA302FFFFFB3
-:105260000C30C30CC30C30C3CF3CF300F3CF3CF382
-:105270000010CF3CCDCDCDCDFFFFFFF730EFFFFFCE
-:105280000C30C30CC30C30C3CF3CF300F3CF3CF362
-:105290000020CF3CCDCDCDCDFFFFFFF5304FFFFF40
-:1052A0000C30C30CC30C30C3CF3CF300F3CF3CF342
-:1052B0000040CF3CCDCDCDCDFFFFFFF331EFFFFF61
-:1052C0000C30C30CC30C30C3CF3CF300F3CF3CF322
-:1052D0000000CF3CCDCDCDCDFFFFFFF1310FFFFF63
-:1052E0000C30C30CC30C30C3CF3CF300F3CF3CF302
-:1052F0000001CF3CCDCDCDCDFFFFFFF6305FFFFFEE
-:105300000C30C30CC30C30C3CF3CF300F3CF3CF3E1
-:105310000002CF3CCDCDCDCDFFFFF4061CBFFFFF7B
-:105320000C30C305C30C30C3CF300014F3CF3CF3B3
-:105330000004CF3CCDCDCDCDFFFFFFF2304FFFFFBE
-:105340000C30C30CC30C30C3CF3CF300F3CF3CF3A1
-:105350000008CF3CCDCDCDCDFFFFFFFA302FFFFFB2
-:105360000C30C30CC30C30C3CF3CF300F3CF3CF381
-:105370000010CF3CCDCDCDCDFFFFFF97056FFFFFD8
-:105380000C30C30CC30C30C3CF3CC000F3CF3CF394
-:105390000020CF3CCDCDCDCDFFFFFFF5310FFFFF7E
-:1053A0000C30C30CC30C30C3CF3CF300F3CF3CF341
-:1053B0000040CF3CCDCDCDCDFFFFFFF3320FFFFF3F
-:1053C0000C30C30CC30C30C3CF3CF300F3CF3CF321
-:1053D0000000CF3CCDCDCDCDFFFFFFF1310FFFFF62
-:1053E0000C30C30CC30C30C3CF3CF300F3CF3CF301
-:1053F0000001CF3CCDCDCDCDFFFFFFF6305FFFFFED
-:105400000C30C30CC30C30C3CF3CF300F3CF3CF3E0
-:105410000002CF3CCDCDCDCDFFFFF4061CBFFFFF7A
-:105420000C30C305C30C30C3CF300014F3CF3CF3B2
-:105430000004CF3CCDCDCDCDFFFFFFF2304FFFFFBD
-:105440000C30C30CC30C30C3CF3CF300F3CF3CF3A0
-:105450000008CF3CCDCDCDCDFFFFFF8A042FFFFF4D
-:105460000C30C30CC30C30C3CF3CC000F3CF3CF3B3
-:105470000010CF3CCDCDCDCDFFFFFF9705CFFFFF77
-:105480000C30C30CC30C30C3CF3CC000F3CF3CF393
-:105490000020CF3CCDCDCDCDFFFFFFF5310FFFFF7D
-:1054A0000C30C30CC30C30C3CF3CF300F3CF3CF340
-:1054B0000040CF3CCDCDCDCDFFFFFFF3316FFFFFDF
-:1054C0000C30C30CC30C30C3CF3CF300F3CF3CF320
-:1054D0000000CF3CCDCDCDCDFFFFFFF1302FFFFF42
-:1054E0000C30C30CC30C30C3CF3CF300F3CF3CF300
-:1054F0000001CF3CCDCDCDCDFFFFFFF6305FFFFFEC
-:105500000C30C30CC30C30C3CF3CF300F3CF3CF3DF
-:105510000002CF3CCDCDCDCDFFFFFFF630BFFFFF6A
-:105520000C30C30CC30C30C3CF3CF314F3CF3CF3AB
-:105530000004CF3CCDCDCDCDFFFFFFF2304FFFFFBC
-:105540000C30C30CC30C30C3CF3CF300F3CF3CF39F
-:105550000008CF3CCDCDCDCDFFFFFFFA302FFFFFB0
-:105560000C30C30CC30C30C3CF3CF300F3CF3CF37F
-:105570000010CF3CCDCDCDCDFFFFFFF731CFFFFFEA
-:105580000C30C30CC30C30C3CF3CF300F3CF3CF35F
-:105590000020CF3CCDCDCDCDFFFFFFF0307FFFFF12
-:1055A0000C30C30CC30C30C3CF3CF300F3CF3CF33F
-:1055B0000040CF3CCDCDCDCDFFFFFFFF30CFFFFF73
-:1055C0000C30C30CC30C30C3CF3CF3CCF3CF3CF353
-:1055D0000000CF3CCDCDCDCDFFFFFFFF30CFFFFF93
-:1055E0000C30C30CC30C30C3CF3CF3CCF3CF3CF333
-:1055F0000001CF3CCDCDCDCDFFFFFFFF30CFFFFF72
-:105600000C30C30CC30C30C3CF3CF3CCF3CF3CF312
-:105610000002CF3CCDCDCDCDFFFFFFFF30CFFFFF50
-:105620000C30C30CC30C30C3CF3CF3CCF3CF3CF3F2
-:105630000004CF3CCDCDCDCDFFFFFFFF30CFFFFF2E
-:105640000C30C30CC30C30C3CF3CF3CCF3CF3CF3D2
-:105650000008CF3CCDCDCDCDFFFFFFFF30CFFFFF0A
-:105660000C30C30CC30C30C3CF3CF3CCF3CF3CF3B2
-:105670000010CF3CCDCDCDCDFFFFFFFF30CFFFFFE2
-:105680000C30C30CC30C30C3CF3CF3CCF3CF3CF392
-:105690000020CF3CCDCDCDCDFFFFFFFF30CFFFFFB2
-:1056A0000C30C30CC30C30C3CF3CF3CCF3CF3CF372
-:1056B0000040CF3CCDCDCDCDFFFFFFFF30CFFFFF72
-:1056C0000C30C30CC30C30C3CF3CF3CCF3CF3CF352
-:1056D0000000CF3CCDCDCDCDFFFFFFFF30CFFFFF92
-:1056E0000C30C30CC30C30C3CF3CF3CCF3CF3CF332
-:1056F0000001CF3CCDCDCDCDFFFFFFFF30CFFFFF71
-:105700000C30C30CC30C30C3CF3CF3CCF3CF3CF311
-:105710000002CF3CCDCDCDCDFFFFFFFF30CFFFFF4F
-:105720000C30C30CC30C30C3CF3CF3CCF3CF3CF3F1
-:105730000004CF3CCDCDCDCDFFFFFFFF30CFFFFF2D
-:105740000C30C30CC30C30C3CF3CF3CCF3CF3CF3D1
-:105750000008CF3CCDCDCDCDFFFFFFFF30CFFFFF09
-:105760000C30C30CC30C30C3CF3CF3CCF3CF3CF3B1
-:105770000010CF3CCDCDCDCDFFFFFFFF30CFFFFFE1
-:105780000C30C30CC30C30C3CF3CF3CCF3CF3CF391
-:105790000020CF3CCDCDCDCDFFFFFFFF30CFFFFFB1
-:1057A0000C30C30CC30C30C3CF3CF3CCF3CF3CF371
-:1057B0000040CF3CCDCDCDCDFFFFFFFF30CFFFFF71
-:1057C0000C30C30CC30C30C3CF3CF3CCF3CF3CF351
-:1057D0000000CF3CCDCDCDCDFFFFFFFF30CFFFFF91
-:1057E0000C30C30CC30C30C3CF3CF3CCF3CF3CF331
-:1057F0000001CF3CCDCDCDCDFFFFFFFF30CFFFFF70
-:105800000C30C30CC30C30C3CF3CF3CCF3CF3CF310
-:105810000002CF3CCDCDCDCDFFFFFFFF30CFFFFF4E
-:105820000C30C30CC30C30C3CF3CF3CCF3CF3CF3F0
-:105830000004CF3CCDCDCDCDFFFFFFFF30CFFFFF2C
-:105840000C30C30CC30C30C3CF3CF3CCF3CF3CF3D0
-:105850000008CF3CCDCDCDCDFFFFFFFF30CFFFFF08
-:105860000C30C30CC30C30C3CF3CF3CCF3CF3CF3B0
-:105870000010CF3CCDCDCDCDFFFFFFFF30CFFFFFE0
-:105880000C30C30CC30C30C3CF3CF3CCF3CF3CF390
-:105890000020CF3CCDCDCDCDFFFFFFFF30CFFFFFB0
-:1058A0000C30C30CC30C30C3CF3CF3CCF3CF3CF370
-:1058B0000040CF3CCDCDCDCD001000000007010051
-:1058C00000028170000B81980002025000010270FA
-:1058D000000F028000010370000800000008008033
-:1058E00000028100000B8128000201E0000102009B
-:1058F0000007021000020280000F0000000800F004
-:1059000000028170000B81980002025000010270B9
-:10591000000B82800008033800100000000801001E
-:1059200000028180000B81A80002026000018280D9
-:10593000000E829800080380000B0000000100B0F8
-:10594000000280C0000580E8000201400001016003
-:10595000000E017000038250CCCCCCCCCCCCCCCC93
-:10596000CCCCCCCCCCCCCCCC00002000CCCCCCCC87
-:10597000CCCCCCCCCCCCCCCCCCCCCCCC0000200077
-:10598000CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC57
-:1059900004002000000000001F8B08000000000031
-:1059A00000FFFB51CFC0F0038A277033309CE345E2
-:1059B000F0E981831829D35FC6CEC05001C4554099
-:1059C000BC0B883FB132307C66255EFF352904DB95
-:1059D000488281211E88D7883130A84922C41DA45D
-:1059E00019182603F9A150B147403A5F8A32770F60
-:1059F000169CA68029E62A8760A7639147C6196886
-:105A0000F24BE550F99904F40F34BEA28ECAFFA2FE
-:105A10000AA113A0E257D1E4BF42E53BA0FEBAA61B
-:105A20008EDDDC4E32FD5DC302A101FC99B04798CA
-:105A300003000000000000001F8B080000000000B1
-:105A400000FFED7D0B7854D5B5F03E731E3393798E
-:105A5000E424E43181104E1E2068080384888AB74C
-:105A6000271030F6D27678D5582D0EAF10F2866B0F
-:105A70002DBDB67F06084978A8C11F11ADD5E12913
-:105A8000F6821D3122B6880328D2ABBD37587C552B
-:105A9000EB1FD10B8A90442A6AEFB5E5EEB5F63ECE
-:105AA000C99C9309047BDBAFFFFFFD7C9FEEECC735
-:105AB000D97BEDF5DA6BADFD18C93181A40D23E476
-:105AC00022FCFB0621929D1032A1379DE32021D7B5
-:105AD000184292662FFDDD921442DCBAE2BF49A360
-:105AE000A9BBFEE41A9A5F5FECF0AFA44D5B1F4DBB
-:105AF000786A092DBFEFA12FC34FD07CFAEC79ADA6
-:105B0000C5B47ECE24C90F5D1D1AAB1002EDE7D8D7
-:105B1000C276015281E5979030A17F92AFE8F845B7
-:105B200084B8E89F2497FE37891CB2A5603EE4D173
-:105B3000A09E029946483631FE55607E36FC09F536
-:105B4000447767D0EF759E77E513EC7F8E5F0ADBB5
-:105B5000E94773F20372C84DD3C6086D49C71DFBF0
-:105B60005D3908F9C00C99E46387B6D8FE6FCA0F97
-:105B70004C7514D2FE670B08FFF9D94936DA82CC8E
-:105B8000A6EDE13B224E1F1ACC679FD9E8B8DFE0B3
-:105B9000DFDDDF40FFA7C05F4B09A1E5CB1C0C9EFA
-:105BA000E4D9D9C530CE8919D71643BF73A61332AD
-:105BB00088564D9D3DF69044F3EB1A89DF4EDBCDC0
-:105BC000290D1CCF81D9F8CBA79302E8978EEE6000
-:105BD0007D5FC4FFEB38EF643EDE3FCC1E2B10FA36
-:105BE00041F6978AA95D72A0F953D14B486A052DF9
-:105BF0001F1953EE9F769AD0F2E4E9E6F64013724D
-:105C00001D2125C49372EA1AFA7716C9BA2842AD43
-:105C10006A0B8CEEE50F6B4AFFFDF922D001FA12F8
-:105C2000FBD61F6A9CE9E9A0F85A377B9687D0F427
-:105C3000F5C02C0FE0EFF5D9B3108FD6F673666779
-:105C400027025EFB1BEFFE063AD008FA3DC7B3B54C
-:105C50007E9048EA23F4FB393AD1C331FDDF01934A
-:105C60004D256409301B4DB325D5A6D2FA6C8DE8BD
-:105C70009138E39502B1693B92499928E352F30FB9
-:105C800061BB3726D94AC371E67307EFC7551AB807
-:105C9000670EA56FD674127551BA1229AAC6E2759D
-:105CA0005D8A541A8E03C7DD1C5E42687BCFC0E15B
-:105CB0007165D802D09F32470CC4C2F50380674299
-:105CC0006F4AA24CEEE6F818FD72BFFB6C508F33A2
-:105CD0008FBB008E0990AAEC3B0E8F0C7C9301B217
-:105CE0009682FC43C26324E0FBCC1EB9240107E585
-:105CF0008FA1F01715AE2DA47BD41214B256EC4729
-:105D0000F4A42403BD5711DE0F29514F517E1542D3
-:105D1000AB848BD75C6A9E123965F035F0A93B19CC
-:105D2000C7BF1C5E48A018E55231D48878C007E38D
-:105D30002BF94DED02A5CBBAD1E57E946F8A219067
-:105D400033437EE1DF57F43B37FFCCBD9CD291CA91
-:105D5000916B39D38F8ADF2C67EB928EB50820C800
-:105D600064B9490F1012244077036FEBBEA278BCD0
-:105D700004BF5BFBDD6FC8E7603298C927933F051E
-:105D8000FA07BD79D37E07F0F53ADF5E07CC6B5D8D
-:105D9000FE5E827A8AD3C7E8D795AF5D52CED681B0
-:105DA0007C8D80EEC348A79EF2D1A7C6027E76A660
-:105DB0002AF78B747E3B9308EAD9756B48782BD011
-:105DC000B594E5B56F69E1B5748E3B9DBCBE98D6C0
-:105DD000D3BC06EDA9BEDB3A490B87687E6B8B8D81
-:105DE000B51FAB85459A1F319184148A4F6DC5C28A
-:105DF000954E5ABE75A3EA17B55EFD34A225672DF0
-:105E0000B4DFB2DEA60AF0BD8FAD233BF3493844C0
-:105E1000C7DFB139F99B23693E14B2F987D34FF23A
-:105E2000F8FA45D9A5442802B4313A9C21795CAEF0
-:105E30000402E5A9BC7CCB7EFFBF8EA4F03D365D9D
-:105E4000F2AFA0453BD6CF4CD0289E766881043F68
-:105E50004D7FF0C07CCCEFCC0C2600DD766E9C9F95
-:105E6000004CF1C0E6991B46417B61D2611DE96C93
-:105E7000D6FF471F283AEC00384B999E4F6A0D7E9B
-:105E800053A2F9BC4912B9894E21CFAD21DCDB1FE9
-:105E9000B211584FFBE86D8BBE4ED4CD7957EBB4A1
-:105EA0008F817F5D0F160920DA3B3586E7413792F7
-:105EB000F08AECBEE3EF5CC8EA13295D800E2EBFCA
-:105EC000625967965AF856477970713CB95A751CF1
-:105ED0008F487A8990D68B57FA9F4662F0E97AF01C
-:105EE0002881F5E98AE76381275DA07C0F83AB9C5D
-:105EF000EFB91E1CF7CA5763E3F1B121EF1EA07F73
-:105F000022C577612404EB507A61240AFCE2C95768
-:105F100034B00B9A0931C9C5A1D1FB7C1D203713C0
-:105F2000223E58AFD78D7E83C98F5681F830E66FF9
-:105F3000B4F7E4B79358FBC1A88772F8CE537869D9
-:105F400039BB87CB594F7F84AD4724731CC2754F33
-:105F5000E161755E1C7D4CC80A94CB9749E07A815B
-:105F6000A6DECDED51A7066CAEDF0079B7400291F9
-:105F700038DF4D13D87AD242745DA0E9A3442F16BE
-:105F8000709D4B66FAD7B22EF5D19FBC5D16E9160F
-:105F900040DF68D43E803487F831CD23014C4792EE
-:105FA000564CAF26114CF3493BA605A41B5343AFF7
-:105FB000F8892A427EC4C4FAC920E7A4DA638BE5D3
-:105FC000BBD06432B23ECE3C9A2D787390F8EBF899
-:105FD0001D025FE748A68AFC43F87AF16EB018E824
-:105FE000C55428FCBBDBCCEFE224BE0E38EA3D6989
-:105FF000805733DD8D5454CD7C5A6DF0A944241C58
-:10600000C7321FC463CCB8D6FE5673FBC6989F9C9C
-:10601000A2231F496E66CF5038F4BD71F0D1280815
-:106020007C9E41ABDC3AB229BF4B49B6C85A9A6B49
-:10603000744F76E8382F3F894767EB7CACF02ABE77
-:1060400081C1B3A9079E0ACB3AFA97C2F34FA6FEC5
-:10605000A44CB21DD60BA28670DE56BCF6F9DE4209
-:106060008FFEE4D29169D6574A8AD70287859F0668
-:10607000687F7CE34BEA7FE4C3FA1B21412AECA949
-:10608000F90101E67FAD401A13295EC868A2EDA0B0
-:1060900070CDF56ACC8E8B693719F491660BC97493
-:1060A000BECF92EE23D03EE427911DF4B367F36D8B
-:1060B000A55B697DAA9FB663FD05401EAE1D6D0BF5
-:1060C00040B9D19F4E9E32F547FD2E11F0E136E8E2
-:1060D00063F1C3E4B136B41F957CA26F89235FC717
-:1060E000B97C151D71EAB09EB8CA94B0331BFA8F03
-:1060F00014433EB59AF8615D9FD4CDE651C6E130B8
-:10610000E69DFA5940007E6AF7313BC05548D03FC2
-:106110005432DA74F01FDDB40EF5427E541753503A
-:106120003FA23FD81F9E3D5F3DED0BD07E7DD4B991
-:106130006A07BE92FCE9A09F578F56C860FABDF867
-:106140003B3BF6FFB9A762188999CF470DD1B10B38
-:10615000A9C170A6E118A6671BDA31ED6C780BD3E4
-:10616000FEE94A598EDACEEB7EE2D7C01E100F3F11
-:1061700047340FC01DD5755C171CA212B32E808248
-:1061800006FF6FD3D8BCF0DA6CC46B08E64DD56758
-:10619000787836E05B0A009E873822C2D27C867708
-:1061A000C03FD001CA8B8E3CB702F15C4DC6029E47
-:1061B00037C9A40CF43CE013D6897D82ED0E800330
-:1061C000F2F369FEFA8FFAC1FB5986F78C97299E84
-:1061D000004E494B64C6AD8EF2953B910B12D7270A
-:1061E000BD7A92F9D9BDF6BDF6EF00CF964689ACDF
-:1061F00085BCA6684A11B7F7414A8215D3C1DFDCD6
-:10620000563EFD28D80BB9E25787645A3EB45E3A31
-:10621000D911234F596574FDA476C2B0E5E6F2ECBE
-:1062200090394F07407F34B7C55C3EC4C6F5AE8792
-:1062300078401EADF35AB6E85771FDD3550D24EAE8
-:106240009663F202C3A79117BC133B42747ECB4600
-:10625000118C034CB7B1F5B315BEA37C712F4FD78A
-:106260005BFA315269A2DB46C6303D196F7DBADD5B
-:10627000563CCE46FB6BB04D1E67A372E4922204DF
-:10628000EC77975BD1E3F993D36D128E9F20B5EB3A
-:106290002285ABFB3AE2DF4AF1BE4CEE8E827C2CCB
-:1062A0002BD6FC215047FE30CA6312D56162F61529
-:1062B000C153027050784A6C384E04FBE9A6380787
-:1062C000FB7D99CCFA5D364A236837F603E75536ED
-:1062D00019E10CD80409FD344E97551539F74DA333
-:1062E000D94E559F05FD67260567C17846B96F7E73
-:1062F00029FA6319C3CCF42B77D467017F540622A3
-:10630000D3807F4E7B5F6C92E9BCB73610BF44F1FF
-:10631000FF9E2B701BF457737BFD08B07FDF065E7A
-:1063200098002A3B807AACA564A55FA2E572891427
-:1063300095293FCA130FBF2517401A2A86388B9319
-:10634000D4337D47F54B2235BD1C23F58F217EA22A
-:10635000803CD072556F25600F38A8DB703286EF15
-:10636000944C731E6CFAD87C7F7AE3722998E727E5
-:106370008703FE09DAE9DD49CC7F9226FA0B00DEBD
-:106380007BAFFFA606F0FCC46633F967567F4D5A13
-:10639000FE6F69791068E2FEB6B4FCD5B4BCF1803A
-:1063A00097569C9763CA32940B05F02432F907BFC5
-:1063B000BE671DE478F85BCFDB582F5737BC35F844
-:1063C000C3E120A71D833FA4C4592D0591FF423E80
-:1063D000F0B5281C92998F09784F1362526E1718E6
-:1063E000F69B9C5A887494DCD2A98E98F5DDC08FF8
-:1063F000B2FCDDC11F8E87F46D4CAD7855A4200131
-:106400003FD068D713B718E0FAEF34E2A979C41F78
-:10641000A53873A4B0786A7A5E280AF37252FD092F
-:10642000EBD33D235F6BC5F081C50F3B94AD203F9F
-:10643000B48CB6615CB36578E49002F90C6A40D123
-:106440007A67CA5D21886D4CCD637CE3F4B3F5D4E3
-:10645000353C8C7E98A1BFBD1C1F5EAD1CF5B3679B
-:10646000A2D9DE31D601272BA2F436DB51CE94A679
-:106470004FC582BE7E9A539B761AE569A4B93F2325
-:10648000DED16EE3F18B6BC9B5683759E212FDE1DD
-:10649000CD6BF87113D9BCDCD34918FCE6F48951F3
-:1064A000C49BD7CFF066D89B1E3EBF9B4A2304FCFB
-:1064B000BE9EF8F3CD0C6FEBAF8BA27FB77EEC29BD
-:1064C000B467BD851D263FCEF81ECAA1FEFCC4766A
-:1064D000A8A1F618CB1B71238AA7E91969BDEB6146
-:1064E0002BB7DBAD7453279262D0634747A7158360
-:1064F000DEBEB784C24EAB3C7A589762F0ADF27EF6
-:10650000D47C86DF7BCBD87C697BF4D3EF9D9893DA
-:1065100004E366F2F8B0117FEEF1CBEBCD784F28B3
-:10652000B4C4852D7EB7EA67F4524BCCE5AB395F36
-:106530002B22A7572A19CEE835303E4F32F8BC84BB
-:10654000F17932DF37482FD10E011D924A99FF4D64
-:106550002C7EF34D291D8C5E378FC8003FFCFEA9B1
-:10656000DD3E669730BA26717EBCEFC61102C87157
-:10657000728926407D723EC35332C513AC77C9A5DC
-:10658000CCEFF64ED4B05D5209A35B0B7C4CE15FBF
-:1065900003748A891F3B4B5B75A07F6BF14E1D74A2
-:1065A0005932C5E1200ACFD4520A1BD89DB45F806E
-:1065B000D75318C5B85A524970D8A5FC7A42A2825E
-:1065C000CD87F8106C684BE93C25587E6862B22094
-:1065D000D07EEFA77CC0F180713C178FA3DF5F787E
-:1065E00012F5DCFDF04D36C8A9F6EB1C9A27A5364E
-:1065F0003FF807F797E608F1E2E7C6BCFB83CB2A32
-:10660000C712F83531FC7295C8E3DE16FE5D4722ED
-:106610006A2EC857486FF7A5F5EA0F83FF7AE4653D
-:1066200012E3CBFEF489A187DD2418B265F7D51FEC
-:1066300092CEF8DE9E174079EB03EF24C6AF528A64
-:10664000B9FC3691DB7F865ED19207142727A10023
-:10665000AE7722D74F4FDA020BC554F0BBC3B84E0A
-:10666000B8C874AE37199FCA9CFFA6E633BDE24A8C
-:1066700089B076978DA73A90DFD634A8A81F5AC65E
-:10668000DED59E43F1B06678931FBE738C6B19B94B
-:106690008DF6DB3C7C79702B0CC0FD30D4BF22AC76
-:1066A000838C5F8D7D30030E9219D2619FCC097E61
-:1066B00011E06724DB5F902412B58FEB1DDF954757
-:1066C000E1CD6769289FC10DFEC9EBB6E02A9C6F3A
-:1066D0007E6B94A29BCE9BC9CB6A21425C22CCEB01
-:1066E000727C1EB231BE8E9FF6F75D02ECD3C4E120
-:1066F000DFDD22DBA7592D478850087E1BED89F28C
-:10670000C9EA6C6A97C781A391F36BD52E67F8C36A
-:10671000187EAB892499F275FB33C21FC6FA117734
-:106720000AB84F51CDD158433AB200CFEF291AF6EB
-:10673000576BEB48837C17E94E5B027810038F8B15
-:1067400074FD7752BEC4B8907B60EBD6E5F0A781AC
-:106750000CD18540CBE4A90F79988E17DC07E3694B
-:106760002A2BBFD271E3F0F50BB17C4DC457596AA7
-:10677000E56B7F14F9DA9D12C57AB79FF1B5C18F29
-:10678000899C1FAD7C688CBF9EC7AFD6723E5F33BD
-:10679000A1498570DFDA519B309EE62CDA5C017CE2
-:1067A000DE32AA250C7CDE64F035DF17A1FE2EDB7D
-:1067B0001FD35AA3B04E2672BE56D4EE06907BEB82
-:1067C0007C5D9338BC3405BE06B8395FBF07F893CB
-:1067D000FDDD08AEC1D76B07CCD7BA456F9BD3FEA2
-:1067E000FC27D9C2D71E89F1E767C0D7004F0AB38B
-:1067F00063DC3E96CA7EEADFC7E9E70689F9996B52
-:10680000B91CACE572B0B61F39F83F22F303FE9A0B
-:1068100072308BC98143A2E58993AE8C1F25B0D31A
-:10682000E3C87B9E24FCB5E1DE3443BC723CFE270A
-:1068300030CD84BEF434D2CF44E7C0E43B8FC9737B
-:106840007F72BE76687C38FE5364F4A7F82E9226D9
-:106850005C39BEFF5A7015727E36F04382C528B788
-:10686000317A663AC02BA9869E7904D3A979AD28DE
-:10687000A786BE81580AFA2B6A2BC63B9C99AD6845
-:106880009F39F398BE31FC24EB7C8DB87813D73355
-:1068900049792102EB9F3D85703FAA9EF95199CC21
-:1068A0001F30E2D586FDA8187ED4D0BB709FA77993
-:1068B000783DDA97CD37D63BE2EDC336FBEE77F085
-:1068C0004D5FD33EEB1A5A0EFDAEC9BB9FC4B3C396
-:1068D0008C7918FB464E3E6E731EB5A8605CDF32A5
-:1068E000FCDE6AC73467B2FE7ABEE77A57EED1BBE8
-:1068F0002C8F76546E8C9F6FE9C7E00385E843A325
-:10690000103718E41E09E74C9A84043FD8C74D920B
-:10691000209D72901E7BA95A891640FF2766BC9C59
-:1069200085F6B23DB806E4BCE9AB8003E2A9AB53FF
-:106930005EF3C6969F9DF1E6B7C16CA5DFD5E27EFA
-:106940008E8348B1FB6327DCDBD17E4BC837C7E9B8
-:106950009C14AE0902C413CCE50A8FBF2899E672D5
-:1069600099C75FA4144B39E70FB934BE5E7993EB36
-:1069700015DF02764EE7C41C16D73B712B4F6730EC
-:10698000FE3EC7DB75F334C2F5EE5F531F25E5F617
-:10699000C2EF9BE2C7F822996547BB3E2B859D2B32
-:1069A00020B1E726E05F6BA24462FCCCA18197FF97
-:1069B00008F1D4610BBECA063C6B15EA615846DB90
-:1069C000A56C9CC76342F72818CFE63A8BFBF5020B
-:1069D00045E3726A120BF4DBDB2185EFBDC0523A4E
-:1069E0008F7B0591BFECC03722D0298CA98B44B195
-:1069F000DE433A309F081BE6B9E08751BF4BC433F2
-:106A00004C611BC68D7ECCF643D688786E83A80376
-:106A1000B4BFC9ED2AF89742887EE71AF877BE40DE
-:106A20006B31C8C4E0B208C693ADED7C53D839A031
-:106A30003E7AFBAF4FDF375273818F542C37E81CFF
-:106A400014F54E6942DFF25F8981F312C6AB58DC60
-:106A5000CD5A5F2AE91740DEACE5C20B7F3A057ECE
-:106A6000F4AA6764F4A3A73C2347BF41F3355B0452
-:106A7000F4536D079DE80F773EC2F2518FA243FB9E
-:106A800073DB058C07D5D9DBEFBD01E28ACF880423
-:106A9000FD8D7019EE8B9DE27326FB59BE9C07801D
-:106AA0006AB61C9A0BDF57ECB713D877A8796EF14A
-:106AB000B76FA0F9C5C764F4516A76AC50607F65C2
-:106AC00049588840BE6B32C1F143FBC4F00EDABEB8
-:106AD000CBDB9E36C70DFB2B0EA25D45E1F6B4A7BE
-:106AE000CDA6F4A90C3F350DBEABDC2DF8C1FF9847
-:106AF000F2CC8EA319F4BB9A27043CA750B5CB4522
-:106B0000B418BA9C6A13A3DF80F8339D27F8C58BAD
-:106B100049EB34C07BCD8E0D8A1613B73CD330922F
-:106B200068F6DE7CCD13741CFA5DED93821FA658C7
-:106B30006B2341E08FCEE79C65DBDC30BF15CA08D4
-:106B40000FCCAB5981768BC3F3F6C17E7A65788B17
-:106B5000328DD6573EB245298FE1A7AA5DD7102DB9
-:106B6000863F4E6DCE4DBFD47A7B86AE5BB1F0547E
-:106B700012A6B788145666C4EC7B76C8499C3F457C
-:106B800053FF06DF875E2718C70A3DEF41BC1A7422
-:106B90005BA632BD60D0EDBCCAE9287517CD88B3BD
-:106BA000AF7A2FD0C10EF12A15D3FB1B7C986E6CE7
-:106BB000D0903E9B007F57E1BE06967B279162886E
-:106BC0008B7875A2C2529F3C5D2F96214E1260F9C0
-:106BD000B4DB83827689F91BE92639380F825CB7EA
-:106BE000C94F4C96E8BABE49092E257E3ABEB47705
-:106BF00072C97560A705E7C8A9B09F1DAC60F1E830
-:106C0000880FE4A289EFCB7C4B66F2D694A1607C1E
-:106C100064D3F78BB6A1ED41185E367DBF7C27ECBF
-:106C2000ABD17EE6CA54AE1A65DA4FEEE5FB499B5E
-:106C30003BD1D44FDADC0AA39FC5D88F7360FD6CBB
-:106C40009A7BBD199EB995463FF5D88F6760F34A88
-:106C5000BB6392199E3BAAB19FF4DBFD681F8806B7
-:106C6000FF9076DC1775EF4E1AB796C4F2D1E41F89
-:106C7000C3781E2A55B17C943831C1244F497AB269
-:106C8000293FA874B0A97D6A20C7549F5E76B58558
-:106C90002FDDA8BF314F818A26B138AB325841BDB4
-:106CA000533CD881F9BB06BB51EFDC757DF02AB0AF
-:106CB000F70056D0F37729C1316A1CBEA1F3120840
-:106CC000C6CF341BA47DEC32BEEF3979C85723DE22
-:106CD000A7DFD7D9BA4724D1FC434AF12330EFAD1F
-:106CE00032B3E38D3843829DA0FE6BCE2EDA168A36
-:106CF000C16BCB50CA2F426FBF2D72D007FCB87347
-:106D0000F56F574A14BEA6A10A1E6E7A5CFEEDE12D
-:106D100010B5999B8796FB00FF7685EA8FD8F11511
-:106D20003A7E3E8EBF1BC6DF2B333BD93ABE3D6752
-:106D3000A2697C475685697C8742C7A7F2B16FF587
-:106D40003B7C7C8ABFEB0979567E07C7B76755E065
-:106D5000F8CD0AA9308D9FD033FE01909FC3FDCDA1
-:106D60003FE77AF3FCB32ACDF357D8FC8FAEFE8011
-:106D70008F9F80F37F59FE80CD3FAB92CDDFCEFA5F
-:106D8000ED19DFDB83FF5761FEAFF537FFDC49E626
-:106D9000F90FAB36CFDFCEC67F63F5277C7C378E0D
-:106DA000FFA6FC099BFFB06A1C5FB107FDC047CA84
-:106DB00090847AF09FA961A461405DA3E3403A9278
-:106DC000C5A937C83908C75D098CEF3E4FA0FCE65E
-:106DD000EED5A7244C2590EACB5ACED355BB8B15C4
-:106DE000E62F84D05F58C4415DB85FC4F58C6CB4A5
-:106DF000878753783BF78B21C82FDC78239E5BACC9
-:106E0000B313DC77A75630FA1FFFF1C0E8ADB1F33A
-:106E1000B2A68B5A65CBFE1383C738EF5424ABA6BA
-:106E2000FC2988A7503D7C12FC1F9A9E96E978B4F5
-:106E3000FC43F083AE8A951B762E8C7677229FCE0C
-:106E4000EBBB1CFE5312C3F7A93B05DC47F87CC320
-:106E50005205F4D9A25697C96FA8E374EA7ECE8E84
-:106E6000FB8DC679BE5B501409F9FDC16F1D05BBD2
-:106E700071F1E641A6EF6E27E1D5701473C1FA797E
-:106E800043553AFFDBCAECE3448C6BEB43581C9C44
-:106E90000C81B84959DB067908CDDC52269BECF908
-:106EA0005B83E6FC6D15E67CA71C966D60CF2C110C
-:106EB000C816DAEFF7EB65CBB900368E5749E676A0
-:106EC000251BEFBB948619B4E8FB908E836215E90D
-:106ED0003A5765DF1AF0D4DD2D9328AEC71DA9B847
-:106EE0000F144A45BF2DA8B2795BE19D2B3BF400FE
-:106EF0008567EE8F44C4A715FE8E832EDD46EDF325
-:106F00008ECD7F90217E6C9D8F15FE3B965BE7A317
-:106F10002AB03ECC0B59CB199F58F9A96E7FF13698
-:106F2000B33D7BF3B658FBB56AD70C537E49F85690
-:106F300053FBC59BE799EA17B52E31D52F68596ADF
-:106F4000CACF0BFDC8D4FE8EE52B4CF5DFAF5F63D7
-:106F5000AABFAD6283297F6BF02153FB5BCAB69851
-:106F6000EA6D07477D07E468D5EB229EFDBDE03E54
-:106F7000752FD89B17DC12EE737E44ED159083338A
-:106F8000D45E81B473FF78F4A7A91E2C874DA2F9B3
-:106F9000CA98552D99A09709EACF7265C2AAD02444
-:106FA0008A17B0D7A97C889B15121D04CE4C720F8E
-:106FB0001F778B31F51D97A9DF4C057D7CDF7AB1FA
-:106FC000237E79DDD679C3D4387E6AAFDC9221B0D6
-:106FD000CE7559CE9F1869B5E53CA7B1BF7D81EB51
-:106FE000D96A85E983EABD1993617386FAE523E2DC
-:106FF0009D9BECF93E22B00D48B0FE53811F869850
-:10700000F66BAA76E59AE4FBEC2111E1AA059D4016
-:10701000F5EA1752608D0272163D92356B34C0A1AD
-:10702000AF5540EFEC4FC575FD6C43E936D8AF3F27
-:10703000D310C0F4A386324C4F350431FDB0A10209
-:10704000D3930DF59876342CC7F4BD8610A6EF3691
-:10705000B460FABB86564CDF6AD88CE91B0D614CD4
-:107060003B1B744C0D79E8D1BF016E0F1B1BD784FD
-:10707000DBC37C2E8DA93DE7C270FFF7BCFBF3118B
-:1070800060EF9F7FCB8EFB6CFDE1CBCA6FFDD351D0
-:10709000477BA53C3C089D636BBD3381D1C9692307
-:1070A000A5641CECFFECF4CFCFC7BCC42EF584FD67
-:1070B000333C71FA85785DFAE5E944F4EE829994FF
-:1070C0001EA71EFEAF22E8F702AC7F60071C1171FD
-:1070D0001D26D16D7EA0D795E24D78E1F759102F8E
-:1070E0003BD783BFF62C888B5DABA8D8FFF9363B26
-:1070F00081F8D2F9032EBCCF75FED8362FC8E33203
-:107100009F188E3D47614D6B22D961B7C9EF36E7B5
-:10711000CFB70AA5781E9A6889B347035FA961387B
-:107120000FD2D9E0C3D4E867994FC171CEECCA65DC
-:1071300071337E5E83EC4E427EA57E27B6FF9F862E
-:10714000A7BF7E0C780869231F38085E71BB98DBE7
-:107150007FFB7EF949FA4C81F82A39207F0EF682AE
-:107160009DFE77111C652261DEE8B72E2286EC6356
-:10717000A07CB7693CFA9D66F8F417732EC5B7E694
-:10718000FB34220468BF469CA40AFE80F330F5025B
-:10719000C6AB8C784997E46E11C6F4C64BEA78BC4E
-:1071A000B8C6D1A10469D1B9B6DC4BEE9F9E69384F
-:1071B000A6C239AF0A47AB02CE4F45645409E8B9BD
-:1071C000736DABD2C01EAC12CFDF152F7E9B6767ED
-:1071D00071BD2561B9DBBC8E72FE20B45FA39C1D1E
-:1071E00072749F8AC99FB5313BDBDAEF04FBC0F6AE
-:1071F0002D6A771F9F7683D6174FB5FB3F55303EDC
-:107200002E11535CC9C0DF7B4A60829DE2A972D710
-:10721000FB688F7E248746DC7D09FDD4777E6E9FD8
-:10722000E97C7288B4C338F327F2818876CB3B744B
-:107230003DFDF815999DDBE4E7807BF695F9BEFEF0
-:10724000029E9BDF5685E7843EDEF78F68FF2D2484
-:10725000012FD281B416811D798ED84A014FE7C81B
-:107260006BDEF13174B8953A4A40EF052D663B86E6
-:10727000DABFA6FCE2CDE67C39999906FAA47CA394
-:107280004CC202CECF547FB35DC57E1793FA265809
-:107290005725EE8FCC57893484EAD59A677F5634C8
-:1072A0008FC211B4333FC888BF2C49667660654AE7
-:1072B00058817DC20FDAC67FF70620833DDC04715A
-:1072C000289248FC3B485FFC5E29FC56788DF5BA55
-:1072D0004F1C88C321EE12E2EE03D6DA056ECF868C
-:1072E000303DC0E76DF805C72CF915767EDE5224D7
-:1072F00022D0FD9CEA08D912B1DE1F8578DC5EBB86
-:107300007F950671FCC06A7B6A6FDCDF6897640F4B
-:1073100062F959E1D5723CF720450BF0DE218FEF81
-:107320002B9C1FC4046F019C23F540DC1ECE753AD4
-:10733000BD5B21DFE4A9C0F31F7520EFB4BF7BBCA8
-:10734000D38E419CDA415AA33AE55FBBCFB21FA06E
-:1073500099F32E904BD0675080E7A209C6B95C2301
-:10736000CDED3C7E73FE312E8F7481433EEE39DFCE
-:10737000E67047E13C0999289DEDF1B772C0DF63E3
-:10738000F0C3FD56687FA7CADAD7F27DDD3BDF9EEA
-:107390009C9E7C097D54F7A540C231EB489DD4AD3D
-:1073A000001FD67D2961F9D7D69B1A5D5563F4E697
-:1073B0002B4AF059FB04A627013E818E13BBDF64E4
-:1073C000BD877002F861422F3F7C6D385288497F3B
-:1073D000BFA7048FC583E36BF7EFEBD3FF09E0BBD7
-:1073E000FFB1FEF3FAF4DF110FFE9A67F7EC0BD151
-:1073F000F5B5F2170F78E110D3C7526B1A9CEFACBA
-:10740000DEB1DA0B72F99114F2025D3F0E8B71EF6F
-:10741000E7A63B0CBED3DD708FB096F3DD999FAF2E
-:10742000FB36F82F9FEF90558C0FECB247ED942967
-:107430006BDB9630F9D8657F9FE59BF1BC53DD7E11
-:10744000B3BEA87CFC81340D0F5585B8FF1C45FFE9
-:10745000A076FB7F4C03BBAB8E74A3DEB37E07E349
-:107460007F998CF6C03C25B16FBD710EAB8EE3A544
-:10747000AE6D1DDE13AF6BBBF934139A0EF43BAD4A
-:10748000DF5570BBDFE1309FDF34F042C2CCEE5FEE
-:10749000F5C48305EF53B8CE6E7FC52BE4C7F22940
-:1074A000D37FE7230B1EFBA5D6BF5C7552FD186B7F
-:1074B0005F1BEBB4B69FFB2B07585A2D47BDE00F5F
-:1074C000566F91F1BC7BF59E6D3B1F86F8CCDB7649
-:1074D000FF70DA7FD59E97DEB89EE6AB9E9253A6EC
-:1074E000B369B8E19EA2419F3AFADFF271BDF4A8F8
-:1074F0007CFA25451BCDCA7F9CDC4B97AAA70E2999
-:1075000064745F7C4C891C52D87EB6853E91F7A787
-:10751000815FB1EA892F14D05F1F1F14487A761C4F
-:107520007C6E7909ED63C013D293D3AB877E96F658
-:1075300075942EA8172DF4B2B6FB98AF07D02FC4C0
-:10754000E3297F3FF94BD8B7F99DDD0F78A878F292
-:107550009FBC309FD3523DE3F39FAD4E83FB20157C
-:1075600072284DC59495573CFA03E4BFC5C77F9078
-:10757000C6CEC5EA19FC5C5706CC73D12373709E46
-:10758000E524887C58F13376CFFC82444A9F8A23D5
-:1075900027F739D83A767AAB1D37114FC34202FB31
-:1075A00018AF89E11D180F64E70D7F60EC3F91650E
-:1075B00098BFE060F45AE430EEF1D1A524967FB78D
-:1075C00037B7039DCE0CD5D3218E5C47A410C78757
-:1075D0007091F62B1E9F9ACECF1D685211FF8EEA36
-:1075E000FF29500EEDDB65DD5960FA8E5CCCEE1D97
-:1075F000FF4E3E3E853B01ECD7D369D41E8C33BF92
-:10760000030E639DA676560C9FC5C83B93FFED6B9A
-:1076100098BC1BF21F9E510AF59F9D607204DF818A
-:10762000FD42E18AA663FDA1D902EA073B89C69320
-:10763000F3ED32977373BD955F28FC12ACC73D7CA8
-:1076400003E324231DD0BE2DDF48BF8FD5AB30AE62
-:10765000B76FBF861C2FE6FA60AD451F90475207F3
-:10766000B47F5B2D87773E0CF24BE535A481FCCAD5
-:10767000F85EC127BB8FBCF13D2AB79F440CB935DA
-:10768000EB55ABDC56EC9D40E2C9ED276E3F892BF4
-:10769000B7B43CAEDCBA3B909FFFD67AD5C0E3D3FB
-:1076A000163C1A7AB23F7C5AF5E4B71D5A5C3D4944
-:1076B000FF9D20457DF9D1E04383FF2AFFA506CF3A
-:1076C0000BF5F0A9C1873D7C6AF0619F78A4098F12
-:1076D000D6FABBE16F3A85C07332C6CFAB0FB0FDAF
-:1076E00067FADDD12185882F1D9739D27A74484AEF
-:1076F0006C3E6CC9472CED754B3E60691FB4E4EBE2
-:107700004DEDABF71F51D8B99EA8A99DB8FCA7E4D1
-:107710008338F101631DAA6BFB5409017FB8BBF1EB
-:107720007B79250979205EFEBC88F1F22E8AE3265A
-:107730003A4ED7EE6C7C8F60B593C557BAD46E2F96
-:10774000D893AB9358BE3B5569023D6894773B593B
-:10775000DCAF2BD0ED4D8AB1EFDE3F20A21EEF084B
-:1077600093D2787E28DE40A1F8ED20FDD5B3FD80D0
-:107770002EB0D761BC84AC30F0E354D19DB51CE28F
-:1077800035AD22DE6B5BB8E2162F9C23E93A90FB05
-:107790009D325ABEE8D722DBA60CE952468C1FF870
-:1077A00011096D9A24C0FEF57AE49F0507985FB829
-:1077B000707D7C79A8E4DF95BBEF5440EF527FEEFB
-:1077C00064ECBE87D14FC52396F203FFC8E5A6152A
-:1077D000E31F95DBCDF5411E3F18ECE4E7BEC792F1
-:1077E000B1DC7FB7C5DE0F9E2AE67FA78CD2A7EB60
-:1077F0009848E03CC1F90322D2E7FC6E767E00E3B4
-:10780000FCD701BF772BB1E7A9CE827C5DD5BF1E27
-:107810003BFBCCEF8BEE063EDAF74EC14F697A7632
-:10782000DFDB237E05F967DFCC7A87F46D3FE5A0C7
-:1078300013F755BA0E7A90FFBB9EFF4DD6DD907FB1
-:10784000CE8EF1ECAE835F14003F75ADB457801E51
-:10785000ECE2E7EF563DFF454107AEBF8D48C7A9B3
-:107860004EE64F9F3FF05FEFC1FD81F307E8ACC0EC
-:10787000BE38E842F9AAFBA513E36F5DCF7F511430
-:10788000EB27FCA5F3A9E5FB9D5D1E52B617E04B67
-:1078900062FB4475BFBA6E1BBC2F51D3764859406A
-:1078A000EBA7BCF0A702D0AF5D7B99DDD429773C74
-:1078B0000AFB7981350F34CA945E9D20648369FF89
-:1078C0006BDE280139EA8B973F615C71A0F858FCA8
-:1078D0007F0D3E049DE93F4F184C852907FFF8DED8
-:1078E0003BA0270EDA912F8DF97E125981F6CCE557
-:1078F000E6DDF4FFDCBC85E840E6BD03E63DE1EFF4
-:1079000077DED7C0A1A1D4BE72D097CF9FBF0BF3B3
-:107910007B3C7E847780FCFED2DFF9FCAF98EE7B67
-:1079200029DDBD979FF7877FE7F3EE9FEEBF9ECBE4
-:10793000E9AEC27998BA17FE84F05DA99E9312FE53
-:10794000BEE5BDBFF91BF6FE5A9BBF35271BCF9383
-:107950003AC0B0707B66B6407871EDC8992AD89D60
-:10796000623FEFD54C48607E9528B0F721C850168D
-:107970000F24DCCF82630DF80E889BDD3B93DC4D3A
-:10798000687713C9DFAE53BCACBD7ABE1FCF1A9166
-:10799000716F05219F39C98FF16E8BBFD928105D9A
-:1079A000A0F6AE74F5378F81DF238FB445ED0598CF
-:1079B000BE0F69338F63CAAA62F287DCF9E6BC5353
-:1079C00033E7EDBC3F0761F03B7C240CF16C71D4D4
-:1079D0006115CED3896325024FA538496B08FC0E8B
-:1079E000BBCFFC7D5202E17EEF5F86C78A0416A7FB
-:1079F000128571ED3AE071940DE3DC78481BF1E2F9
-:107A0000C7F7BA08F7AF7BF1DAD40EF894C03F6637
-:107A1000F617FAD584FBD312EF421A69D39DE676A6
-:107A2000DC8FBE2C9D185DB2AA399D9699E862D074
-:107A3000210E7D4C7431F07CA5F4B1D2C58AFFEBE8
-:107A400013185FF7472F832E996E1DEFD7C9DC7F80
-:107A500028013F13F2990182FBABDC7F905274BC8A
-:107A6000A724AA7EBC97007E5C941AE02FEFDE86E6
-:107A7000F1A4733F7FFFDB004FD5AF44E2A0F8EBEA
-:107A8000DCED2151F85E0A2BE09F56B689B84F40D5
-:107A9000A468D1AC987D62C30FA8FA8507E753B9F3
-:107AA000D71E9E4EBFAFDCF74101DA612BBBD1CFB1
-:107AB00009FD5C60740F7514C03E70A5C4FC112BE9
-:107AC000BFAC4960F196B3CFB9CA20AE23EC62E7F0
-:107AD0007F2B23B7C8F698734DA10499C59B9E735D
-:107AE000A15E083D21E0F928802FF6DCA9E1879C02
-:107AF0007D4260F0ED97F19D98CA5D4F75427CAA7A
-:107B0000F22DBB1FCCF8BA5D9FE27EC8945FECF10A
-:107B100076A01F2E9AE2127DE201BB44E48FDAB612
-:107B20001AF443681EF9A236C2FDEF2BF457AB7E60
-:107B3000F1FC3EB87056F5F4E35E887F9D69DFE1A5
-:107B4000C5B8C0AE4BC7E7FAF8FF9135DCFFFFD6EA
-:107B500069764F3BBEFF7F06FEA076F1D30996FB08
-:107B6000ABBB06B1F71449B4E852EF7155EDB9F06B
-:107B700028C4AFCFEEFDE45180BBFACF7F7814FC70
-:107B80000A72D0A9C27D82BA9FBF8EF13EE3BBDFED
-:107B9000703DD0F9C4E3182FED7C9BFA1FF45FE72A
-:107BA000F3A7B3C0CFEC7CEA8F69104FB9F3F9A902
-:107BB000F86ECE9DCF4C492771F4899102FF86075C
-:107BC00010AFB5D2ED48DB11F47FCE51BA83FFD9A7
-:107BD00013D789D4B07899C6E339BBE3C7C7FBC4D0
-:107BE0006FDA667DE7C6424865BF460610C7394171
-:107BF000E939660074DCCDE375916F5D328E730EEA
-:107C0000FEA0F43A6BA1E385B6458F3D0C756D83FC
-:107C1000FA8DE34407803F23FEBE3F41FF2201E48B
-:107C200068EFBF60FC0CE8379D4EB873CF852CD849
-:107C3000BFF848EE9E8BEF853C6F57211E51F9FC33
-:107C40009B284F9DCF1CC7F836E171F04ED2F38FC1
-:107C5000C52BF999CCBAED1E16FFE17480F890E6B9
-:107C6000C5721E07627C6DC487FA8B0B8D71B17370
-:107C700027C6BE40CDF67778BCA5976EC244A0D784
-:107C8000FB97DCCF30F0A0021EAE8D8D7BC68FC37C
-:107C9000F5C43D2D74037A42BCB327AE49D8137B9B
-:107CA0007561E1CD7871F4CE2D2C5EDA29C73F8F56
-:107CB00065C441AF7659E29FE181C53F2F378F2BD5
-:107CC000C5D3609786FD5AF175F6ABF8FAFD5BAE49
-:107CD000819D5FE8777FADDA7C1FE63D2538DD05C5
-:107CE000FB6B6DEF2B04CFA774B3732B7CBE67F9CE
-:107CF000F9D3B33F17312ED6143982FADDAA3F8C5F
-:107D0000FD572BBC7770786BF7B3F5E3EC5E4FD87B
-:107D10004DFB397BF839E4EBDADDEF635CEEE8AE7E
-:107D2000A7958E98F516D68F70CC7CCE3E79A8801C
-:107D3000C579E3DF1BAB71317BB3EE40FC71EA76B2
-:107D40007F6A1AA72A1451981D70E9F1CE48FA2DBE
-:107D5000D0DF997619DF4D3A1311E3BE171C70C9B5
-:107D60007C1FA195C90F5D47F19EC071767FA7F07A
-:107D7000B5043C577FE7F1D277E0FDB73BA95883C4
-:107D8000DDDFB682F169DB4FF42140EFB6E3DF13AC
-:107D900061FDDA07F88DB1FF8B4ED44FF150FD50E5
-:107DA000F46EA010D8D5AA77AE7DCB66829F8E9355
-:107DB0000EEB4223ED07EE83C0B939BC57EE9D565A
-:107DC0000AF088AA4D750A7DE721BBF97D55DEAF23
-:107DD000AC9AEF2190AFC66BD08F6F268B4B66CCE1
-:107DE0003252169F0C19F787CA13C2ABE87C7FAFDB
-:107DF0000637BB285E7C9E8DD92F1178276AA20694
-:107E0000F6D3632E7EDEC14BBCECBC833B64A37A0D
-:107E1000FD61FFF60D93089E67D8067CD9739E819D
-:107E2000440B802F8D767DEA2DE71D32E1132A5A0F
-:107E300022873317EE2550FDB26A86772BE41FF1B7
-:107E4000B0F7CDB248F72138DFB08DDBA3D960158C
-:107E5000E7F67DE7ECEBBE6F9632A578E9303F851B
-:107E6000D3F55F53E15C7CCA2DC54F0D5169852D5B
-:107E7000631ADCA34979BC786C06CDCF5FFFF4347C
-:107E8000ACFFF7E2B15934FF937B0EB2FA2A01CF6F
-:107E9000C1BEB0AE761AF0EFD796FBD9143366B9EF
-:107EA0007F05F0772EF0EE77176970AEA25BE1EFF9
-:107EB0006504A0DDD0890C7F99EE779F027F6598DD
-:107EC000AD6305F0EB63CF7F9184F716F9FBA12A30
-:107ED0006954E1DC152D9A78F112E7F3FABCFBCC7A
-:107EE000F5CB8D49C177813F9AE78DBC6F1A1DEFA5
-:107EF000E18A710E760ED0F24EA39A82745DC8E9C3
-:107F00004AF83DCB457C3E8BC590C202DFAD5C7F1D
-:107F100019EF51578B57F41E3587ABDBD5EFFB6755
-:107F20007F00783393827F00FC59DF3F7BC515B813
-:107F300000F519E55FE27D5CE33D33EBBB6844EAA5
-:107F40008EFB3EFB56FE2E5A7FF0FE9B3B28BA6905
-:107F5000FF392F687B8F51391BB350F1C3D1CF311B
-:107F6000CB0BFDD220C226047610A71F3CCF88F78A
-:107F70001FEE22B85FDB651774F0AFBBFE49457D8D
-:107F80009EB9703AFA5F5DAEEC089C33EABA5BC307
-:107F90007D3D8A0101E469E881C428F887541E3ECA
-:107FA000B7C8C3E766FE378FDB7551DBDF81FDA9FC
-:107FB000BC3F6AA0C5DC8BED12999EEE6AD0108E94
-:107FC000A1247408D6FD818E97E3E6EB37A7CF4650
-:107FD0009B9EEB9E80F81FEE8EC1FF2877BF74CC6E
-:107FE00077333AE6BBE3D0D1FA6EDD7BAEE058687A
-:107FF00077BAFC28BE5F677DAFCE4ADF3AA9F5218C
-:10800000783B2BEDC0A7B8FE18F41BB37C2CD2290B
-:10801000869E93008E31073EB501BC061D1FECE71E
-:108020003C79A99BAD73D6F1D2CA3A0607E3B49F57
-:10803000E5D64CF70E0A1C457E89CA69BA8DC587FC
-:10804000FAB6EFB7FF9C4B9DF32C5059BF14FF734A
-:10805000004F06FE6F75F3FBEA7DF17F3BB4A3F89A
-:10806000BF1DE63F00FCCFBB14FE0DFBBF8AEB87B4
-:108070002AD89FA27CF41FDACCB41C3AEE34D18DFE
-:1080800072B06487C8F731D9FB5F863E59725DFDD7
-:1080900021B817B9E46702F2EB42FEFEE527FCFDCA
-:1080A0004BEBB9C1F2B210EACBCB9F1F0CA33EAA97
-:1080B000DA652EFF6777CFBB975978DE172435AD89
-:1080C000F7BD4E2BFECFBBB9DE58E8B4C57B2FD72A
-:1080D0004887D6DB4CE7CC33A6F4F483FEA0CFA6CA
-:1080E000BD89F1B87F9509C4137429A510DE192044
-:1080F000854209F45BCCE5D7E86FD872F3FA9F1D8F
-:1081000032DF43CC6D31DF431CDE6ABE8778D56633
-:10811000F33DC45161F33DC46B768D33E54747AE03
-:1081200037B51FB37FB2293F36FA4D53FBF1C7660F
-:108130009AF213DABF676A7FED5BF34DF5D775549A
-:108140009AEA6FF86899297F63F73F9BDA471731FE
-:10815000FD78B8617911DC5B30F07278A96253A1C7
-:108160007CE9089B5A105B9EA66B059016E9E07FA0
-:10817000F5272F531C3F2A8A5DA78B896CD26F533A
-:108180001CE67CD46DFE7D8F972C7235A47E52CB7D
-:10819000089A1DBC240FCF6353F93AC6F5DBB10131
-:1081A000EAB7DFA07CD5469B206F952FE3BD019AEF
-:1081B00086D88FADB0779F1F729AF9D4D78F5EF9AA
-:1081C0009DDB3807D4CAFA53CBC64B263931CA3F98
-:1081D0002A8C2D17164FC77340FDF5ABF8165CB30C
-:1081E0007D10BC3B3C0F53A3BCA9CC16F7DCDF676A
-:1081F000EEBFD07FDADCC78EFA0CF07CCEF7DA2641
-:1082000038BF567B7B37FA511976335E7AF3EC5DD3
-:1082100063039E471A483EACF7C6FDB64534E1EB12
-:1082200036CE77D1DB33D3E09C41663FFE55A18744
-:10823000E9EB471B42D72C04C21187E95E7956B49B
-:108240006E1AF839C3F879EB4DB6F8E7A0923C0CFA
-:108250002FE9A048C15E50DD682F9C2B7FD70B4FC4
-:10826000C7DC680F2679E838F3C7B417B1FBD4BA76
-:108270007FE6E85EB80D7D94E50E6C02FD92E59315
-:108280008896DD179EF4DB832DF08E7863B2CDEFF8
-:10829000C67CB700E3D97F4CC8203A5EE39F458493
-:1082A000AFF1F075783EC8EEAEC7B8AB314FC2CF74
-:1082B000091871E60BBED98980CFC6AB7BEE07E10A
-:1082C0007B9017DCC176E8F7C24619C76D9C2C98E5
-:1082D000EA8D794B9BBF8DF7BEB2DC6CDEE574DEB8
-:1082E00000B73D93C1D5F8A8403211AEFFBDF428C8
-:1082F000F835FB5CF8DE07C5C710C0C7393DFB7316
-:108300009B31793AAF9A41EEAD6BD19E89EFA74E82
-:1083100037E6A18F34D13BE32A33FCE24619FDC690
-:1083200045496E3CEF106E8872FA9AE7DFE49BF9DC
-:108330009D5B295CAB4E88F8DEB6D6D1BAF428FD39
-:10834000AEBCCDE50F6B7DF17F4E63F052F8A77B9D
-:1083500040DE364FC3F9E3796A80FF31813C9C0DE2
-:10836000FC172C453E186C23B06FD3C74EF0307904
-:108370009EED51D97B35BE722687BE85D76CA7FD91
-:108380009579FA5DF76FF3B075FF364F9C75FF7204
-:10839000EF075797B51F8554D445B43708A91F1167
-:1083A0006B47533D560EFD1B7931F1C705D06FFF6A
-:1083B000769ABF6544F6E5ED34B0CF800F0DFBEC47
-:1083C0004E8FD9AE8CD1BB3FF430BDFB43CFC0F450
-:1083D000EE8FA1FDE9EF45E3DA35A94A7CBDF7B49C
-:1083E00087DD1FAC531582E703FBD90FD8C9E5DA47
-:1083F0003AEFFED6A5CBF91F392E834FCDFAFEFCFE
-:10840000312D11F454CA0742DC77B7862CBF6D3C7E
-:10841000D06B9BAD7833CCF76716FE78684D9FF52F
-:108420002BCCF1188E8BC76A8A479B098F3B3C97F0
-:10843000B00FBFB6BEAF30DFF3E9E4F8A67ABF09EC
-:10844000C63B37EBBD22886BD4CEF91CF5FED71E98
-:10845000A7CCBCAE187E391D6705E0A173D69F7905
-:108460007CAE03E34AAB9EB92A11E25835930D7AEC
-:1084700044F07DAAF3F939489773FBEC3AC0792EA2
-:10848000999D133DB7EFDAA310F7F8A4E158722CC9
-:108490007DCF3D79BC48A6FD9DDB7BBC48C2037700
-:1084A00061D33BD435177F5B1470F7DE4BE8E137BF
-:1084B000075B8F363A597CE54138173786DABF6A51
-:1084C00012F2657A9AED5E28171DBF1DFC215C39FA
-:1084D0003FE62FA659B24AD03316C17ED33C37EEC1
-:1084E00067F972C9C86CFA9D12AD87E3CCC4F96A0A
-:1084F00098C0EF04B84E44F1F7023CEF7660F83EC6
-:10850000F143B2029EC2FFBD1A3C09784F3AAB0953
-:10851000891AC4778A6E1E4753690AD3BFDDB73AFA
-:10852000F0F78C8405AFAA53A8FEDA3C93FD8EDDEC
-:10853000F9630B92C01F695599DEF20DEBE163B44C
-:108540008B07E76B371723E6757C574055191D924B
-:10855000336C6B8A358CC7F9F398FE25521AFF3DB0
-:1085600029CAB71ECDA6431CD8F8CEC5BF2B52FCD6
-:10857000BFCE037846DBFCF04E8FFBAB6F38CA9260
-:1085800069FBCC28BE5F5E94C0E19DC3DE07EFFBB4
-:108590004EE345D37D18B5D4FC4EB727D0B414E2D2
-:1085A000FCD0EF6DC9F8CE8BB99EA2389196BB0B6B
-:1085B000CDE5AE0A9A8FE147EB77D6F6865F92AEAD
-:1085C0003238F63738100FBF6C50FD79948F0E3467
-:1085D000F8307FB041C334DA3012CB0F37F8312F87
-:1085E000DAF46C984FFAAF7F9014BBEEC2EF549D53
-:1085F0008CE1C37572E4ADF9808FDF8888AF15AF69
-:108600008E47FEDE349A8E3A86BD677332C6FEFE12
-:10861000E9F257D24A285F0DF9D1AFD34AC6C3EF6A
-:1086200096B0F31770413AF61EEE7A25A0F993E062
-:108630007734C6343B86C2FBA4C15BC9589423FD82
-:10864000C589F0BB0B7B336CB47E9A94D7ECF807EA
-:1086500080ABDE64E7AFE7E7331F9F6CD6AFE3BCC8
-:108660004CFF660AC5E3BC71F8097E5300FDAC39C6
-:10867000C6B907331E8954BFE1768AEBE6EFB3DF54
-:108680005F4854C7FBE1BDF7CD5EC3CEA9F7C5BEB9
-:10869000E7BE99FF0E44E2E1256817293EF63B103C
-:1086A000290A7B0F8904934DEFEDCDE5FDCC06063D
-:1086B0009AD0571FCFE6FD151D790EFB83DF9788F3
-:1086C000F5EF87F0DFC3D8CCF5D3743550EC4DED22
-:1086D0006D67D45BBFEB59776D21D10BF6430189F0
-:1086E00080BD04ED8A69BBD40F0302DCEF33CED723
-:1086F0003E0BF8CDEFFDDD937D02C3EB933C7D8A0D
-:10870000FF4E49D4139807E3FB163C12DA0376CAEE
-:108710003EBB06625274E48FF87E94F83BC501E7D5
-:10872000FC530FBCCFEEE5D93A1438BFB8D25B7C0E
-:1087300013C45145A53E03F3F74E6F81FC839EFAA7
-:1087400087D8A3DDC537011FA4F3F706080400018D
-:108750000E08AAE18F63FD43B34E65649FCCF22BF4
-:10876000BD37368732215F3F0FF808F28DB4BF7DE9
-:1087700049C121C0476EE186E6633742DE687F0368
-:10878000B6FF895765FE8F3B980DF64A4F5EA57977
-:108790004F4C5E6279E260A931BF9A237FC473D0E7
-:1087A000B507D83B5DA907660830CFD4FD3310FF6D
-:1087B000E7D5B7BC2B348C878F60EB048B971BF409
-:1087C00030EEE1A6D983F77963F8619DD76CC7C411
-:1087D000DC27BC0FF0DDD31F8FAFCB36F69E4AF7F8
-:1087E0008FD8EFC60D037B5484B8B986692EDCA3FD
-:1087F000A7FEC170125C3998D65FE3CD413A5EB5F1
-:108800003BFBCDA95A2F5FA7642977803E4EB5F870
-:1088100035D95C3F8F508B7F93482B370AC1B5F019
-:108820009E6C688FACE27D935D19284767B98E22F4
-:10883000F583315FCDEFBFCB2B836B47811E59C4CE
-:10884000F46E5576A058A6DF573D978DBF0B67F0A5
-:108850005D5552246D9CBBF75CB791377E47E42190
-:10886000B5D509EFF218FB5AB5FB3764C13EFDC719
-:1088700087DE463B71496236C259D3765C81DF6937
-:10888000A96DA37C47BFFBD8D963C7A35FF287C894
-:10889000A06F02BEFED068C3CBDDFDD9552F52FDBF
-:1088A000A6D385EA688303D39D7AFDD5E00A9CF0C0
-:1088B0002EB8C949F9E9F11C5D05FEEABCB71EF501
-:1088C000D8E38A3A0AF8AFD3FBC366E0E7AA24915B
-:1088D000F3EB0F5FD6F3F87E3DCDEFB9B7EDA6BF52
-:1088E00068DF60A1D9FEA97BC48DFC41ED92DF0257
-:1088F0001FD56EB68560FDB339DAF1BE7327E81B6C
-:10890000D45FE6FB991B05A60F4373581CFA72F758
-:10891000342BBE7491708CFDBD2491E9AB0A29847F
-:10892000FB76155F7AB1FE2F1FC769BA0FDA771C85
-:1089300037D61BE354F78E837C52FDF661F4CF5F8C
-:10894000BCDAB0AF75D4FF773EC5CF6138F574E8B7
-:10895000E741D9D027D4CFA47886E71E793E24F901
-:108960000879A947FFAC6D2EC904FAF6D613B37E79
-:10897000D2254AB79712783E747F73C9A438ED1395
-:108980002CED738CFC4FB17F2B3C0F3A7BF30EDA4E
-:108990005EFA93BD270FF06DB059FA4B36C6DF86ED
-:1089A000FD19FCB7C7BBFB6578EFE9A5A440F11042
-:1089B00066DF6820875B24157F87D1C0F31EBE3E2B
-:1089C000557C798D09FFBD782F30959F6ED04CFB7B
-:1089D000A18B172EC37B3F7BF83A564142EC3EDB1E
-:1089E00023B9A67DD0FF0FC7D785A3B81F384AFE8D
-:1089F000C6708C32E9815E38F24DE55F170E316941
-:108A0000766936EC53ADB1A19F90660B3972C06E9A
-:108A1000FB5FECF71A203407E799A8616CDA57CEB0
-:108A200039609F07C6798E448E49E3409E746D0578
-:108A3000AC533F91D0AFA1E50E3919866ED5E1FD5B
-:108A40002B2A95D85F4E75B08619F5E6776287AB0D
-:108A5000A458A2E5E3D579B8EEE594DD5507F6FD17
-:108A60003677E1CF571393BCA27DB25A588AF6C726
-:108A70009AC4179B61DF383D81D9330279B1F95827
-:108A800046BC7A26AF2DF7BD7813C431B6AED4AE4E
-:108A9000067F6EAB331C390CEBF93D6EFC3DAADC56
-:108AA00075E116F8BD0A71830DD74B3129BC6B2BCC
-:108AB0009C177860841FEC8BAD60D740FB356E5CF3
-:108AC000FF5B1A42682FAFE2EBC0F6F5935438E72C
-:108AD000DCE8969261BD6B91EB6F05B85EBAEF640E
-:108AE000B3E33AD063FE96413CEFCB80754DCB713A
-:108AF0008CE5F514195B576883C18534F2C3FF44D4
-:108B0000AD12D43327D10E6B742FAB043B8ED6BF7E
-:108B1000ECA0787A3C99E385D7E7F4E8A593CDA05B
-:108B200007C515BDF9123AEF1D3F637AEA09DA3F2E
-:108B3000BC2B45E713827718BB4749E8872524C13A
-:108B40006FC7D074740EFB9D5BAA17BDE8C7493888
-:108B50005F631F4919C57E0F1DDAC37A9390918315
-:108B6000FB98CA0CF65E83E271E3FD66E37756DD9F
-:108B7000C4F8A7B37829DF677159DE4370AE5F8907
-:108B80009BE94E783721864F15CB7B0B1209CC071A
-:108B90007B4B54CDE5BF49E4FB4A83D8EFAD0EB71C
-:108BA00085D02EA35284E935248AF6D968D281F97A
-:108BB00031E06DE6C2352C0D2F8E8D27BAC8E2BB91
-:108BC0000111ECC7B45B8D784CF0F544BADEBF966A
-:108BD000C8E336FC778C536614E27E7D6612AB5F89
-:108BE00015C8BB0FECBC8D33A6619CC6B0EF8CF5ED
-:108BF000D2B0DF16729857AB425C7BC1B0EB163A2D
-:108C0000593E75B6FEE068886BB6530B341BEE2FE9
-:108C1000B3F86AF9E6E234B0CB161EBA15EDE44CAF
-:108C200095D9658B36CE5082A3E1DEDA3CF4078A13
-:108C3000374C48847D84D54E7FE27585E867E2FB3A
-:108C4000B903B5C7B6A65D3519E471AB8D1290CAEC
-:108C5000FB4BB2EE1E0B7CB1210FEDCCAD09C1C6B2
-:108C600024DAEFD67FD6FCAB68FEA74EBDF0388C79
-:108C7000B33A81D5C3BB51C09B3DE712B6E1BBC936
-:108C8000FD8D6F3D97F052127B7FCAA8FF6F537E18
-:108C90007C7D0080000000001F8B080000000000A9
-:108CA00000FFBD7D0B7C94D595F8FD66BE796566A9
-:108CB00092C963F2220913C24B5E4E9E80224C126F
-:108CC000C243B44C102A20E8F03490A7485DDCBAC7
-:108CD000FF0C043050B60657112BEA8462C5AABBBC
-:108CE00041A31B35EA8080B8D66D44DAD216FD8FD9
-:108CF0004A1510488AB5D2FEDD65CF39F7DECC7C47
-:108D00009319F0B5FFB4FE3EEEF7DDE779DF73CEE1
-:108D1000BD73E912FC4D612C94A43056CAD8C151E0
-:108D20008CF58C618CA9DE2406CF4D066FD2E2341F
-:108D3000C6FA7EA367BBE1F517666F92C3C6D82556
-:108D4000D12EFA79AA99B1A089B1B3CD6E161CC102
-:108D5000D8996633956B961F98C6A09F9A0E85B9D1
-:108D6000F2195BC5DA36633FAF3B9269DC55013DD2
-:108D70000B8E64F47709FE5BBDFC28D55FDDC9EB83
-:108D8000D7B20EAABF92314F073C6BF75A59D01C8D
-:108D9000AE5FDF51AC691F4AD251BFD725FB063BFE
-:108DA0009C8CDD5B3DFCBE2A789F565D62F6E1FA45
-:108DB000588EE313ABA8AF87F73AE6EB88B1AE77EE
-:108DC000045CDE49828A4EACEDD0B132C6D63AE0C0
-:108DD0009F2EC61E50D87C6CB7F6F715192963C2B2
-:108DE000EDD62A9E0CC798F8706ABCA86781D48813
-:108DF000B2DA67C4F5355E34D2FBF30EB35F0763B6
-:108E00001EC9F43F702DAC7F26EB5319CC539F90B5
-:108E1000388E5DCD588B2571373E67BA0C7DA10821
-:108E200038303353717E33F82BF6EBC469479471B5
-:108E3000D83E40ED67D98EA90C4073C45E7303839E
-:108E4000F737B090CA0A06CE0FFAFD28B2DF5923D1
-:108E5000B5E51BDDDAF2EC09DA32637E82D74F9A90
-:108E60009BCA4E1AC2FDFE04A6D611032EB70258A5
-:108E7000B17EED5E4BE064041EEB3B9235E5C6AE81
-:108E8000ACC0C988716AF11F59F05F135F779D58B4
-:108E9000F70746DFAD0EC05B3D0B1971DD40C146E3
-:108EA000EF58C6AC16E6457C1DD86FF1B012E8CF7E
-:108EB000666EB7007C1BBBAB9525F0DE6A87EF3092
-:108EC0003F2796E16935F0FA8C05880EE08FDA3994
-:108ED000BD99ED5B15E413B7ABDAFECDE7DD00FF1E
-:108EE000DD93024F953DAC2446ACA30ED6911E5E99
-:108EF000C739EB0765882F58CF6FECA5481746A6F2
-:108F00002485D7F3ADE1B55C0BAFC65D36A237184B
-:108F1000E7BD4418A761A7CE6F84B2CEDC63447E60
-:108F2000B917E93C06DE721C4A4C3C6F433CC7E073
-:108F3000A7EDACFC3EE4C71CE41F18C7B6EE2765DE
-:108F4000278B818FAA3717FAA0BE4D05FE86715474
-:108F5000F8BFA908C8D93B6D5532D0E9293BE7C312
-:108F60000D892E7AEE50BC0AE2355DE7C947FAD585
-:108F700027B843CCC1F1A366421960CBAEC162F9F8
-:108F8000BD1EE8EF21981BCB168409F078C8C2CB30
-:108F90002F39CAEFDD08E36E4AE6E50D3FBDB9D5CE
-:108FA0003F09CA16599E43E5870C6D413DE0DDFF40
-:108FB00082C9F5443EB5F728585E3032F0044C4D76
-:108FC0003F8465235EA62642E720B7F42F9A769B5E
-:108FD000A05ED0EEFB2784A75CFF39FBF13C362670
-:108FE000667F7E4D7F79DFAC3F18BF537775F8FB06
-:108FF000D4C49D413D6FE7C2762CA7E7033FF49FA1
-:10900000FEA2896D85E22306769B17DAD55D2C6377
-:10901000C10839D423F079B6D941725BBEAF43F9A8
-:109020003D06F9A987E4707D47AA46FE4AB95C7FF0
-:10903000F15A4D7F398E7CC257BDDA43F2ADFEE264
-:1090400064FA1E12F2F46C7326E989F8E30CD2C8B4
-:10905000F5F0381359B0F872E34CA2EF721CE6CB6E
-:1090600022B9BD06E70C24A43782BC87712E0C758B
-:1090700025255F469FD976029145AC679B1A3463DC
-:10908000FFDBDC071CBE18FC20E544B8BD51DB1E2D
-:10909000F4231B81F4ED6348B7FFAC7ACC91FAD48A
-:1090A00066F038506FA8F68A232E37344D7E6486DA
-:1090B0000A286951393D7FD9B681E8D16E701F41C8
-:1090C000FCDAED3A971FBEAFB7E93C48272D0E7387
-:1090D00000F1BD51B9C1817243F66B07318FF3B80E
-:1090E000601B427A3DDE7AD58B89540F669219A9AE
-:1090F0001FFFF7C683C5170F1C8FBD31F1880BFA10
-:10910000574B746E0BE00B91FA71041D44F763DF4B
-:10911000A9C69C77743D09FFB8F836841211FEE7A2
-:109120006DBA198118F32E4D56BE9B9E5A1425DF39
-:10913000937F3B3C88ED95D00F0AF249FE9626A31B
-:10914000FC2DBC9058E922399FEEB573B185E3B68A
-:10915000D88E9A7DA48F98ED13D9BF3E3EFD49B8B5
-:1091600018DEAA64881F6004867AE34A70B02B4137
-:109170002FE29715AA0CE5D3403A6FA7F9F4D777F9
-:1091800043E711EB6F51DD0EA46BFD751E33CA99D9
-:10919000F58E39E6109437AAAED9F92087FADE02A7
-:1091A0007B12D6B729ADC81C8B8F5AC16EC4F92D5E
-:1091B0004DD669D6239F661DE7DFE8F75B92B99E1F
-:1091C00068DD3FB1C753129F7E40D279518F9BCB50
-:1091D00054C756589FDEC0E76B896307CA7EE3C158
-:1091E0006BCB7E0BC96975A83980F644F4789B5423
-:1091F000778F07BE6F82F9F8B19CC3C7DF54A23ADC
-:109200007643D71657023347D437384B08FE176CCE
-:10921000694C0FDF37213DC6989784D3BCE4EF68D3
-:109220003FF9A2E832F7B7C3D9100D5DB6C6A2CB9D
-:1092300079A8374BF9FC993972FE4393BE8E7C8C2A
-:10924000A69BB249CC837C9701CF76586FA7CA669C
-:10925000EC437D80B6D64498DFCD36E600993E39A2
-:10926000B57C6732ACB7ACE78091213F743A691D99
-:1092700075A27DF4B8A6148E3F538A839E49C73DDC
-:109280004F4F01F876F624B814F8D49902FA300654
-:109290007C8F08BC33D6C69F6A681CF28FAC5FB661
-:1092A000887976C3F350026B3583BDB24FC807C6C9
-:1092B000EEE74F151817C699FDCAE8DD642F8AF549
-:1092C0001F02B580F5D3D343E314FD77C0DB5E58AE
-:1092D0007D04DEEACD21C2DBDB46DF6B089FC6E3FF
-:1092E000A1742C771E3D9387F870B670FBB5EF25FF
-:1092F0006B00E96E207ED6D3FCEA2E0E62FEE28180
-:1093000078AB5383A45FEB2EE6D17758B7DF9C127E
-:10931000FE3E1B6C8609B02E66E67042F8C4C2475A
-:10932000BBE06B890F50EBA3ED021F08A78FC43E73
-:10933000A71FEF4EE36606783F6BE6EF996724DFE1
-:1093400087097DFE51425E00F7331F0D07CE467A36
-:10935000505DE9917AA7CEE2B96F3EAC9BBDAB6799
-:109360004FC06359A5AD15EDAB65264F12DA5DCB45
-:10937000DED32BEBF30984C4072B043CCF32F75D1B
-:10938000883FFF368BE309C29F76FF97BFA3BCF8E7
-:109390001D68BFA24BEF46937169A5CD8FFD96F571
-:1093A000543C6D87F72B5BAD2E06FD2E9BE2FE0431
-:1093B000EDBD65F7595C1BF271BF38A43C0BFA5D3B
-:1093C000FB60BE03E581759D37D3EC0693E07EEB31
-:1093D0004C2BE06D93B264895208AC7D7FCA1615A0
-:1093E000F0ACFE57E56716285F757FC116F3758CE4
-:1093F000BD82B21CED59FFD09968DFFE12A746F678
-:109400002EB76F7F794427CAC55BA6820A18E5ECA0
-:10941000D4D960CE2B538AB79861FCF4144FA10EB7
-:10942000C65B93326126F6B7F4BEB17FDD09DF7704
-:10943000A4CC9AA9E613DE447BEFCCCAA1D06E92ED
-:109440002CCFB354427F695616B6A72700BF0F0929
-:109450008F8FF67767BFFDBD60E6D41CC04B4553C8
-:10946000A50AFDBF9E72DB9631573136FE817287A9
-:1094700007C63F98B264A615F0DF6994F5976DF1C1
-:10948000C0589DCCF78601BEFFF1FEBA9966A89F31
-:1094900096EA2D74C0FA53CDF76F9991FB1DF865CC
-:1094A000A412BD4F2C487112DF1C4690E6ADEB3381
-:1094B00072FD2AF83D87D3717F792494ED11E54C34
-:1094C0005EEEDC105B7E9C4EE572B93321F6778F41
-:1094D000904B00EFA00EE9B3CB1A18961F9627C049
-:1094E0004FE609C45FDBB93C01BE9A63273E8ED9C3
-:1094F000DF37E55F803BF5D3A97AACE8BF90720D0A
-:109500006666C571BE4C7669E47559CF5292B7BF95
-:109510004A157CEBE2F071566AE50A33F70C47B85E
-:10952000C8768BC53AF3474BFF52D088FCB9D6E2D8
-:10953000C9C0F9ACDD579EC12E6387D75D2CD7F823
-:109540004BC2EB984AEF07F40BFDB944FFEE315FD5
-:10955000075EC95780571A7DBFD23AC3FD69FD3BEC
-:1095600003FBE37E9E017AC5187B9E1B53B85E41C8
-:10957000F8EB22E4DA4A215F416A913D7EFEC5ABF9
-:10958000766FCD8F1C7703F50FF87D7A0AEE2F41A9
-:10959000BEA21C2B533DB3B07E594F8A03ED79A078
-:1095A000B78D82DE54A43789E7CE94A6725AEF763F
-:1095B000C5B13B861DF81339AF36C583F649C622BF
-:1095C0009F7E49C4FCA4FC87FE3B45FF259C9E1F53
-:1095D000EDA7E7C5C83FC22FC4DC40DF6307CE5FFD
-:1095E000C136CE08FDF5822580F39170FBB6F42FCD
-:1095F000ED87BAB87A2A91DA651C0F26BAA09E21A7
-:10960000C5C5F9B9E3E3C46B515F75E999E2E2EBD3
-:1096100046B95126E5A4BFE748854A764C582EBB8B
-:10962000C89E917233683687EBDFBFBD67C646942C
-:10963000AB26BE2F4FD383142F0ACFE3E514AE2FF2
-:1096400027F89827961D7824D92EE508ADE3E17513
-:1096500095EC63589F5DE8D709213FF9B39E4C66AE
-:10966000C23EE1F090FA7BB629F4AFDC4FA6A547E5
-:1096700059063BA5415710EE1FBFCF89A0FB63825F
-:109680000EA2F1F35DE513C0C18F70484DE172C8C1
-:10969000096505ED0B15F417C0FF5CB5CDBD353F71
-:1096A00062DE362E8F9D7A1D976357E08BB454FE91
-:1096B000BDEF253BF173181EDC8EF92F01F7761DE7
-:1096C000ABC17DC1211DF009D2A28DAFF3FC8B5936
-:1096D000D4EFE7293AB9FEEF452EB71B613CCED750
-:1096E000643FD6BF3CA85D3B7FDEDFDC544E8F6518
-:1096F000C73D8568C70CF3DADCB85F28EB9973C007
-:1097000000E5E1DD8A036B4B3A1FDEC1F914A84B7B
-:10971000C0E5AD6722FBB5A5723AFABED631FC387A
-:10972000A757C4CBE2083ECD4DB57178C1FA4C08BD
-:109730004F552B47E5F3FB9B87F78001D65B07F07E
-:1097400040B12DE1D6D9B1648305F9F83873231FF0
-:109750009FEF58A21B8B78DDC9C8BEEB970F0FF0A7
-:1097600075487B14E8B203E9F2EAD45C1A6FD87149
-:109770008F750C7C1F867613FA953BEC01DC574CF9
-:109780004EF5CD4D4578CEEDAB64204A1AAC4DEB8D
-:109790002D11EFFBEB77417DA2639F7E2CCEF3363C
-:1097A000C6B6BAC2EB81A9FAD11F5A6F043E2DA0EA
-:1097B0007210E1D669E4F5FB16338ACF34E8FB8CEE
-:1097C000F81DF4F72CA2CFA3BA14C42FEE9BD06ED1
-:1097D000AED37B7314DCD76798DCA807601F42F414
-:1097E0007EC8C2540BF4FF263C514E57E9EFD88F88
-:1097F000F0AA2A50DC2D24AEDA85DC6041DC37CDBE
-:109800009E62257A645FDD39B41AF5BF95E309FAE3
-:10981000318B7ECCE6A230FFFD3AEF2ADAFF48FD1D
-:10982000764851A89F43D78DDEDD12B12FC2FE507E
-:10983000FE1F52AA73EE40FA17FB3AB20FD3C27A58
-:1098400017ED95225B24DEFD627EA13CA4A3487B3C
-:1098500014EDD37E7BD6DFB1653AC8D9F1333A82B5
-:109860003A0752D1F333FF01D65105F6AC05E0704B
-:109870005B2A973387F2FDFA449CDF30583FBC3AAD
-:109880009CE01BD3640B8F932EFC0FE946EE2F4810
-:109890004FE0CFBFA7723BE727695C1EFE218D9783
-:1098A000D31363FB2BBE10F55413971F5BCBB9FC8E
-:1098B0008FAEB741F4FBADEDDE318A667F0F76EFF8
-:1098C00086546EF71AB95F88C713960AFA063B8763
-:1098D000F014B6AB783C50DAA15FF4CCA3F272F38B
-:1098E0007BD9E8BFBFED9FE6DD87F4B6F2377AF2A9
-:1098F000579C14F18295C9BEF464DCBF27C4F6AB53
-:109900003C27D675BA99911FF8538C1B82EC3D8980
-:10991000714328AFDAF9E034E4BFD52C40FEE0E52E
-:109920003B37515C707940612E05F7695EEE271672
-:10993000F858BD47AFF14BDFAE361993C784E977CE
-:10994000459B366E58B3AB5853FEF6F669250B446B
-:10995000C8A1B0FC9946EFA3FB95F41E6DA77ED479
-:10996000ECD2F8C397EE1C46EB97F5973137AD77FD
-:10997000596B8166DEAC95F349BCF949BA45BBD455
-:109980001F739E46CDFB8F00FEFE08FFFFD25343A0
-:10999000691E2DA9BEFF40BA09CFC3CAFC1ABFDA9F
-:1099A00024C727B05666E17E49A023FFE5EC81502D
-:1099B0002AA7FF6F0FF7D171F605E3FEBFEE0BCAC2
-:1099C000267139CCDA14360C1EE3A76AEDB4BFA0B9
-:1099D000BE2BC5A795EB6B61472D5FA4AD7751D426
-:1099E000BB28EA5DC9BF12699F290528D7787F0D7A
-:1099F000828FF3CF1C35BAA0DEF8346EC716393D1E
-:109A00009750EF6CB3248E437FCA364B5E00F552FD
-:109A1000FFFABA381D6D33483F8A3B03E1D6FE5F3B
-:109A200077B6A888C77DB00F007958FEE841168A3E
-:109A3000905337AE533CCB01DE7621EFEADC7C7DE0
-:109A400075EEA07128F4935DC7E795D3B15F5123FC
-:109A5000DAE5D4087F5F9A41B3CFCCC1324E258D71
-:109A6000CBE39C9AA03214EA65EFDAA3A8D85F870B
-:109A7000427A33BB0900134157D925DCBEB9B1A4E2
-:109A80005D5936260C87565DF51807E0A735DDEAE7
-:109A9000467D738FD337240DE7792218C4EDFCF887
-:109AA000133D2ADAEF3F757A0AD29C6138B8F48EFA
-:109AB0006CD4A7D6137C9E6DFDFB63AE6728A24DC8
-:109AC000FEABDDDC9ED1B3238CDB87A4AFD2378C19
-:109AD00024BD27E7979E22F4453AF33D67A3FAADEC
-:109AE0008CF0C9683DE91B86EFE6F62CC7775581F7
-:109AF000770FBEAFCAB8AAA805DE176C0BAA4BA198
-:109B0000DDCBBB62FB83CB853E81754CC2F5C9754D
-:109B10005C492EC87A86387E0AC90FD619B1F71F5C
-:109B200030227D2F7F346D21CEB76EA39199943072
-:109B3000FC7FEAF4CEC6F96477B42B081BE9DF9307
-:109B4000E34AFF1D7E47FEFCC828F996D35F5CFE02
-:109B50005FA7F72C8F94671B8D8427693F87E7C722
-:109B6000EDFDD5695CCFBEEAF42EC1F934746D27E2
-:109B70007FCFAA3D1F1A63F9ABA3F9E24A70546A7A
-:109B8000F8BEA06EBE3980EB2F7F54253AA8DD6861
-:109B9000A43859DD33FBB89FE71EE6463951D7B1EB
-:109BA0004F590EE3D63EB34F591101D74175010508
-:109BB000E733C22EF990CBAF68BA473F32DA2D8730
-:109BC0002D5C4E9C2DB7F91580EB5983AF0EEB9DA4
-:109BD000CDB2BAFDF9613CBCB96FFA11CC37B03FD8
-:109BE000670AE2B355B73BD30CF55A4719DD485F16
-:109BF0003F75FA36235C52546F27B64F4EB3BBD72E
-:109C0000435B978915A1BCFBBA70181F4527E3EF8A
-:109C1000E1FCD3857288DB9145C83F8134BBB4A792
-:109C200048AE1D36F0753CC7F87CFF9EEA7990E897
-:109C3000F8480A8D9B5D1754D09F9D7FE639926B43
-:109C4000B2FF309D791E89E4DF2BCFB3C388F45671
-:109C50002BE450F9A37B948F23E6FD4B30F4916EF7
-:109C6000B29F01BAB4D1F7FD33D3A83E33B9F0BDEA
-:109C700042ED6AE1FB8A087923D71143EEECC3F584
-:109C8000D84EF41CE47227C8FD8D62BED1F87C1555
-:109C9000E51F7C9A06EA99DE1BFD23312E7A78486F
-:109CA00002F527E54034DFBE2AE81CE5A5CE46FED6
-:109CB0005AB22BE5FC64BD2267C5FE3482430FC156
-:109CC000A17E974AEBA9327A87DE11C10FBF16FD3C
-:109CD0001DB8F90323CAFD07FEFD5DA2C7FA36854C
-:109CE000E2F1ACED5DE33CD447FEA7F46867CEE259
-:109CF0002601DBF1C2BB84A7599D5C2ED777EE53BA
-:109D000097D9C2749A7FE6C0AD4867F51D2686FBD9
-:109D100022A0BFDF207CA2E954C247CADD78F8B494
-:109D2000CEE07294F98DE44785FD543EFA29A4DC17
-:109D3000FE7BAA4EF809F8FB0B69BC1CA61FDFA727
-:109D4000088FB0DCB5105FE49F293A60C67DB85B30
-:109D5000213F7F5A258767E4BCAAC7C6979BCE548C
-:109D6000A137D450DE1C7B58BEF7CB7FD1FE0B81D0
-:109D70006F781FE4EFD910D4F372FED1F8CB77726D
-:109D80007D1B83CEFE1BD711ADDFA43D20E9E6C9C4
-:109D90005DAA468FD89D46EACF0E1B739CC78E7274
-:109DA0001ECFD861E0FA6CC77A7300E5C99B0B78C7
-:109DB0005E997DA13188CF43BAA575F8FD50361F55
-:109DC000BF55A75B83E5D60D36D64278F5243A4BCE
-:109DD000917E1219978F5C1E3EF03C9767757E5BF3
-:109DE00080C13FEB7C739753DC39CDE2C6B833F3C7
-:109DF0001D34CEB30FA42BD773FB8D2E783FAB83CE
-:109E0000F39FC403C853A22FC90F12AE617872B872
-:109E10004B7E92F8F8BBF46703BD7CA7BCAA3DDA81
-:109E200078DCDB46DFD54EBECF3A6C70A19F86C78B
-:109E300017E2D16FEDBAB7B34F821DB53AF32D7A61
-:109E40004ABE85FDAC86BF2709BC1738B9BEAF74C2
-:109E500072BAA92DE920BEAC3DD944FC6C9BC1E58A
-:109E60009AED84561E33F6CF62BDDBA85D95B563CF
-:109E70001AE677543DAE3870BF1F4F6EDEAEF0FC71
-:109E8000B84F77BD9188F972EC2BB0F2319E62E148
-:109E9000EB9DEBE472E2EC5E0038D17B93F172F65D
-:109EA000FB95FA63C1630AC2B356C0FAEC3395134B
-:109EB000FF847EECBD49EE61B0E4CF9EB9E9EE3F90
-:109EC000C1BCCFEE99E246F7655A8B97E8A7CF69F8
-:109ED00071E37E03C4F70CF417AEEF7823F15A68F0
-:109EE00077FAE9AB8B506ED78A799E795EBF0EE127
-:109EF000B2E1C97F9B8CDF6B034AAA09C7D9FBF883
-:109F00007F6763BEEA9E46F217B53CFDBA11F317B0
-:109F1000748176FE7E6F9203EB9DFEF9F6C908EF21
-:109F2000968E16FA7EE6E7ED543EF0E4BFBDF67776
-:109F3000F4E37813DD58EFCCF3FB092F753E95F26F
-:109F4000DBE2D1F58E7DFBB9BC443D8F7C309FCBED
-:109F50003149D7927E4F3F79DBC448BD21DFB70A34
-:109F60007F4E6B02D7239F09FEADADE0F1CECF9EB1
-:109F7000B5CCA7FD8131341CF7C57563385DDC2D88
-:109F8000E051D77187A1C146EDA99FDF02DFE373DE
-:109F90002CD0E72723298564CF25CAD7F957AA0FE4
-:109FA000F526A0BFE7E6451F2A381FEB9826432D6C
-:109FB000CDF369FE1D561DF9BD6C6D6C3FFBBF38BE
-:109FC0006DC22EE07C90DD599DE3223960720F8BCB
-:109FD000B087B36B7C2D1827BE7EADCFAD073CBEDE
-:109FE0007CEAE8B441507E72A4524CF8D72B5CCF87
-:109FF000F96D344E3DFAC1818F760B3E497730F5CD
-:10A000001A9203DC1F50A532D5467EAA3E9213F564
-:10A01000AD420FEE117E6E735FDE4D766A67BB2632
-:10A02000621F06ED6C362AF7E5FD10F34A67F8E784
-:10A0300093DE711969BE67A43C607EF27B4A7E8B19
-:10A04000F61BA1BCC1FCD1579DE55D281FE5333D42
-:10A050008EBFE4EFE2FBB8744F17CA15B63755A3AD
-:10A060000FE2C99503379FE77AFB950F890E1B9086
-:10A070000E717CDF498DDE5E4EC215E8F0A50F89BA
-:10A080000E977771F9DAD0556EC4FDD40EE1D76919
-:10A0900010F4847484FBE8BF3A93699C86C9A1E1FB
-:10A0A00028A7CE0BBA3BFF12A7B7433A1DF9010E02
-:10A0B000ED1EDDDEA20CD48F4A8D97F0DD00F8E6B0
-:10A0C00076F3DAA36867D5D73037F26B43A7E0079A
-:10A0D000B07B11BE0D5DD5CBB1BF416933C9DF0D7A
-:10A0E00076C9B441506EA863A5C86FD9BB2A5E4239
-:10A0F000BA605D7C3F9E5D03F62CD24D5ABD5B9FDE
-:10A100008F7A8FDBBDD78F2CA3F63B725D14E7F2FD
-:10A1100057318AF3EF40FB19F55DD6686E3FFB3689
-:10A1200092DDC55C09E437653E750DD66FF02F6290
-:10A1300094D711CDC72F29B40F680858291F685626
-:10A1400017B77F1ABA381F9F93F0914F43CFADE4F2
-:10A150008F7FC1C4FC11FED0375F9ACEF5EC8B2601
-:10A16000D2B39F357BD8C7B0A0B785BC9770AC6D14
-:10A17000CBD721DD32769309E7B14CCCA3CDC0F526
-:10A1800046B2D00305DBF83CD474E1774CD789A7FD
-:10A19000519BE7E2F0937FE19C188FC8225DE8397C
-:10A1A00018BA7E7990F8A4EE19DE5F9AC9537867E1
-:10A1B00004BD4AFB289A1E0BC4B8D9BB0E2A284CF2
-:10A1C000B277CDD1F0F9F5352CD808EBBC7E972EBF
-:10A1D00038651CD94D0B499EAF37B258F92A23D2A6
-:10A1E000B9FD5695EA2D44BF76D5CD3677A43FB953
-:10A1F0002AC1A3B3A01D5724FDD8DE128C1B9D4A93
-:10A20000B7BB116FE3D25DD20ED3D85B03F7DFDCAF
-:10A210000EBCA1CD3F0EF71F81F509F329AE09DA77
-:10A220008DFCDC0E688FFBF7DDD7FE9CEFDF5BB8A3
-:10A23000FF020407C999546F09FA8F9D05DEB55CCA
-:10A240003FD9DDB1D6F3AA93AFE7C0CDB716E23E52
-:10A25000B161AE8DF8E1815794A59CDE4011E2BE5C
-:10A26000DAC7F983017F3CE1227A243BAAA1C91B0A
-:10A27000884D8F9C5F1AC0AE423B1BE8710DB793AF
-:10A280006D8CF313A74BB9BF47B91569CF4A3E8D03
-:10A29000E67B49BFFD7CFF35F9FDBC81F3E37980A6
-:10A2A00003D27B3F9DBFCCE97CEB7AE047F8BE153B
-:10A2B000F8B12542FE47EF7F709EB81F90F2F61E60
-:10A2C000A777513ACAA1DD6F6DC650AB948F0D2FA1
-:10A2D0006F197E39BBCB8C95A15F33F06B24FD6089
-:10A2E0008CD65E444F3FEA09EBBAD8FE8FBBD26DE5
-:10A2F000DFCD3F3F302FE5AEF4D2817929E9A87355
-:10A30000106FBBAD01B48FA51F297A3E4B049F4946
-:10A310007CCAFD03C621B0FEFD82EF37897A8F88A3
-:10A3200067C4BE84F8C1A5F37D4879F671F4916CD9
-:10A33000F77DF9B5E438522F46D38D8CA3E07AAA85
-:10A34000C7C4AFD7B65FECCFA2E8F829C15F0B80D6
-:10A350003770DE6D86E017C48F77D819E513F8994A
-:10A360002715E371AF8DE07C34B26F38B6B766FA6B
-:10A37000BE44BA927E5D7C8F71AA5A11BFACDD6B70
-:10A3800008449E7FB93783D138BD76B35F0FFC9107
-:10A390009BE9DB87EDFD15CC1D443DF38F168A2B21
-:10A3A00081815B8AF2A691851211CEEF25FB5E209A
-:10A3B000FAD5F70C47BFE33925340EDF9F10FEDADC
-:10A3C00013C25FFB7ED77BCFBE02AD17BF726EF1AB
-:10A3D0008F91CE5EB4E4217D9CB0F4E7BF25A1DD72
-:10A3E0007D81B9922E770E699159EF5523FC67272D
-:10A3F000ECB1FD7F6F0B3C378A782B5319EDC3B757
-:10A400006770F9193EBFC4E3ADEFEBB4FE37F91C3A
-:10A4100093C1E1DF19E71C506106DFD7740EE1FC40
-:10A42000D8D7AE50BCAF66DDFA3FEB412ED4ACB509
-:10A4300007E9099FD18EAB71F8833A289F3070B934
-:10A44000047F73CD6561FD07F5D449C8337E07C528
-:10A45000BF960AFDB5ACE9CDBFA15FA14665E6494F
-:10A460004518C7F21E1E049F3EB52D4F44F1BFF2A2
-:10A470004777A6A37ECA58D426F2C1A63AD0FE5585
-:10A480003C37E82F592F676FA96427131D00DE1E84
-:10A49000CCF0F6221F2F4AE27EC145775A03FE0810
-:10A4A00079B857F06134FD7C10E7BCCD97191501E0
-:10A4B000EC6F61AAF76FD4EF9DE73472EDBC12FA2E
-:10A4C000C523485F77D8DD4FF0EEF222F363D20563
-:10A4D000FC6B310E04A2B1B7B067F8BA7CA4E3BE3E
-:10A4E000BCDFA15FABDBE4F0BBF0BB91BECB76F190
-:10A4F000E241F1E3402E23D247C34585E86169F785
-:10A500009BC751AE37A821A293A5661BE1B1E1A27A
-:10A51000CAE9A9D5703624DB03EED7A47AD232601B
-:10A520009EFE7B2725533C09F889C3172A459CE3E7
-:10A53000F832C3372803E0F79035F136DC7F5D3021
-:10A54000BB92308FADD108F4703575E73547D843ED
-:10A550002CC7AEA583EEB7FE86F35A6EF61951AF3F
-:10A56000AFF034D179B14549C152C79848BC4FD2F8
-:10A570005F1AFDF5F17E49C897F78D3C6F64209D09
-:10A58000733C6CCF10F5B239BFBC9FC76A9EC3E75E
-:10A59000287842BBF787887291280F17F5D279790E
-:10A5A0009AE097F7C7F17AD1E32C15E37C99E1990A
-:10A5B0008C7082764123D2C76B163A67C44A40FE3C
-:10A5C000A1BC5B934B762CC8B96908771827984CC7
-:10A5D000F54CA4675813C841C0676FA98BE0B3B5A9
-:10A5E0001CE805E341AF9A281E24F12BF11A8DCF08
-:10A5F0008519CA77CB4F1F18BF5E98513A307ECD70
-:10A60000D850C217D14B8CF31FF1F0F56B3BC70349
-:10A61000F0EBF20CD283C1B1917CB349C051CAB501
-:10A62000F713B478FD3C9DE3A15ED4BB84761FDABA
-:10A63000D1EE3EE2BFF75378FDB402AE97A45DFEC3
-:10A640004F022E5FA66B9F52CF44FBD1BF14F2E2A4
-:10A65000CB74EE4707BCDE8DF395FA09E44C301954
-:10A66000F878D1EB2692336C631FE5D540BDFF83AC
-:10A67000F05A64EABB3515F4CA0FC1DE311651BB7E
-:10A680004B284706ECEFC748BAB033D4DBAD190E00
-:10A690006E1F94F4F1B8D748BEAEA50CE48772657E
-:10A6A000FC630C210BE4F06B22BF42C1BCAE146210
-:10A6B0006717F60770FF978CD230DCA3C73B21E801
-:10A6C000E0D10C4525BC15B242C4DBADEF7E6E5F18
-:10A6D0000C5D9E13E765934DBE76ECE7ECDD6F9164
-:10A6E0009D7EC2181CDE668BF1DD187CEC2125FCFA
-:10A6F000FDB6A7F47EE3D5987F7EF6C19B61DD4B66
-:10A700007BF46E1C72E93D5FBC331EEDEC1E03C58D
-:10A710006B40DF6F5371DE4DDCAE3CA1D3D2C1671D
-:10A720007769F73DAF0B7A90E772A5DC91FA7C155B
-:10A730007373799390B81BCB1FDD713B9DCB5DCEBE
-:10A74000BC873D00F7D36B66925D7C3BF3515ECFD7
-:10A75000B256ED39DB156DDAF2ED3B079CC32539B6
-:10A76000BC2A10FD5EF8A52B63EBFBF3822E3F3372
-:10A770008AF8FD7A53CCF8FDEF85FC09C7D9FBB404
-:10A78000F1FB572F1FBF6F8C8ADF87ED88E8F83DFC
-:10A79000EFF713616F60BF9171FCCF2A62AFE3A343
-:10A7A0000C69B75835F9199F0CB05B12E97BE3458A
-:10A7B0004B9CF9D8E8FD672B638FD3D73F8E365F6C
-:10A7C00020DC9EE709C8FDB5A493C68B59A4676534
-:10A7D00059DAC7E17639F43DFABCBAF46F4BBEF8EA
-:10A7E0005861E62CF2476D1776BC9BF2333F46BBAF
-:10A7F00008F972BAEBB5104C71D98F270E578784C0
-:10A80000F9267A1D405F674211F2D898694F23FDFF
-:10A81000EB666E3A9727E8FED6BBABE87CCFFFBD70
-:10A82000A73223326E2AF7530D46698FD934FA9630
-:10A8300045E9E3655D6F911D06F6D770143E7F7A9A
-:10A84000F56ED2C32B99371DE9BDF7D511746EE5AE
-:10A85000DBEA61399F9BFC4B0C3CBF358DEC8739A3
-:10A86000623E3775733B5067F618681C0F7339D218
-:10A87000698BCDE70B425485F275FDF347E71D6305
-:10A8800093C4FC156C0FF0BD4E3CD9525F26CEDB55
-:10A8900084E3EA310D269089CF96896E173EA7286A
-:10A8A0005E95CF83E3791A6BCAC1FA3A7348CFD762
-:10A8B000093348C7F6FDF0A2B25D9437CEBD70EB08
-:10A8C0000A7C6FB3933C318A794CCF04B988FC6D14
-:10A8D00066665CB7C9163C4DF133F1F457B8888F02
-:10A8E000FD4318F9411258079D3FB5D9CEF971B112
-:10A8F0000EE650B06C715C08E27EE29CC3E6C7F3E2
-:10A90000C4202F6765A23F5FF9D54AC40BC867EE24
-:10A91000178AF75D0DF2F31142DEA588F9B50879C3
-:10A9200097C5DC8AB8C780E4DDFDF69537E07E2662
-:10A930008D79F7A3BC7B387106C5FD32988FE693FD
-:10A940003A43D5C82DA7575BCE98AF46CB3B05E71A
-:10A9500097E5D3BE37B3139497A404BD9997526972
-:10A960001F3612FD310621378E59783EC26631CF2F
-:10A970003B3353886E8E59785EC2B7B65BDCDA7DA6
-:10A980007D430A3FBF7F3EDD6CC6F1C08EB913E147
-:10A990000776CC077E16CEDF2C9CD24179029B6FC6
-:10A9A00054DC1BE0FD66BB6BBD0AA4EB9FA9707F66
-:10A9B0008FEA28C77C9CF63C871BF3441B45BEF7F7
-:10A9C000668BA3F619F2639A783DD6B719E396ED34
-:10A9D0005B1D0EAC9756D937CD88FBAA15CCB19B21
-:10A9E000C5A0F7AF808F60BE3FC732E04911F46366
-:10A9F0003DE2BA85D620BEEFC17F17F0F29432DC7B
-:10AA0000BFF2BF82EE423A77C93C7AD2978DDD859C
-:10AA10006FD860BC82B985E4AFF756F2B82F1372D5
-:10AA200060BC1C57F0D9B561BAA7EF85A23CB45BF6
-:10AA3000F87FD34C3CAEEB8021CAC49143AC9FC697
-:10AA4000F9C1CDE41FE7D36B58F80FFBAB0CF74F00
-:10AA500072696AF87398EF60A822B3BBA50EEA8DFD
-:10AA60005783FB91AFAF15CF42F13C547E23E9E50C
-:10AA70001E9DCD65D4713E3717A0ABC3AB47B894CC
-:10AA800039B6B4603FD729417AE6CDD8DE82D39F6C
-:10AA900023FC4CC999C6009E376B99007826BFC825
-:10AAA0009F0FA3FF5AFF2FAC18F174CC20F59E27FF
-:10AAB00089E7FFB9683DD50E3E5997CE337B2EC24C
-:10AAC000F9283FCFC6D0748BF8FE97A9554997D780
-:10AAD000BB3C0F30254BCFE5E30C1E876D9C6FA66A
-:10AAE000BCE546710F03537DF93F8CF0AFC8B8C584
-:10AAF000BB06367F5F8CFD464A16B707E6DCC0FD15
-:10AB0000C28D221F477E4FCCE27EB2BF644E7B37A0
-:10AB100093EC3D1E6FFD9D945F23D948945F11F225
-:10AB2000E58F245FCADF8E277FB4DF85FC99E72994
-:10AB300036D0BE40C82129EFBD22EF6801F31810BE
-:10AB40004F3DE21E95A3E5AB480EDDCC7CF4FEF74D
-:10AB5000153CFF0008D380FDDD34436B3FCDF36A25
-:10AB6000CB37CF8FB6AF383EE4B80B7CDAEF73A4A7
-:10AB70009D3C436B272FFA87AF9249CF67FCA2FE1B
-:10AB8000D2E0703E5163543E5183C8276AEC2A3CA0
-:10AB90009416914FD4D8CDF3891ABAAE944FC4ED20
-:10ABA00029AF29B01FE324DE5AD294EC0D917F72B5
-:10ABB00010F34F8AC2746EAFB0F33C0CE6A1BCA296
-:10ABC0001C8795CE5DB4EA8AC88FDB9A68D7F8DD1A
-:10ABD000B7AE7755613DE9BF95F9434837B1F6C344
-:10ABE000D9597C5FB343E17E74FF0233ED3B9D0591
-:10ABF0005E4D5CC1A967C7D1AFF86EA64BD6273FA3
-:10AC0000C90E832FAB189E0185D17989FEF67AB6DD
-:10AC100091FC905172CA99EAA6388033692CF9F5F3
-:10AC2000E77517923F92D92CEE614AB8FF7973DB32
-:10AC300055CCEB69EC6E5797DBC27437364BEC435F
-:10AC4000ACCC8AF4DAEFD77BCE447EBD6493B730C8
-:10AC50000BDAD71983E4BF8BA0577A1F4F5FDE2E24
-:10AC6000E8C550E15DB002E6D7FB8ED18DFB6B0AE3
-:10AC7000CC41FFCFBF944C7E49750E233DB5B19CAE
-:10AC8000CB935EF493C13A3E4DE6F7FA6CAC66A402
-:10AC90005FCFA74C233A5EC502873DE847DB0574CA
-:10ACA0001879CFD21E6DB98E7590FEA97B66003DD6
-:10ACB000937C94F2B89EB9F4068C1B746ADBB3A142
-:10ACC0005A395C28F447F1BCA92D98FF50ACE3F247
-:10ACD000912D770F9A43FBF5458E4F2C28727FA15B
-:10ACE0005CCEAEEBB59FD273FEE77AA154F41FADF4
-:10ACF000BF4A853D3719E417EE6FA57D06F5A97C9F
-:10AD000050D7ADCFD485E75922DA49BB50EA0B8939
-:10AD1000AFF2098CE179B5BBB2847C1AC28620BE41
-:10AD2000A17FE21305375829D4BF1FF785D78AF1D1
-:10AD3000801EFCA8BFFD3A7300E96BB3D244FAD27F
-:10AD40008CF63F3CB72A3ED20BFF5EE3D7237D4C07
-:10AD5000644D37DD00F526997BAC28B7804EFE3177
-:10AD6000927E5A58306F9FA2A123FA7E36F9ED9851
-:10AD70007424F55AF0F7DC9E99C5BC74CF93E70FA5
-:10AD8000DCEE3AA8F07D26D89F07D1EE7A5B3793A8
-:10AD9000E864262C03EB5539B4F89F9EA92D47DFB4
-:10ADA0000FC5D05A284374487806549C4FF4BD51BF
-:10ADB0001E29F79856EEE5B3AF78DEF896C33F420A
-:10ADC000FF83751D1B89F60E58AAC48FD1F4B027D6
-:10ADD000EB7B8FB7ECC98A116FE9157EE56B58687C
-:10ADE000E533CA407A3B7F689D3E33822E257FBC87
-:10ADF0006CE07913CAEB3CAE35C1CCC604112E25EC
-:10AE0000DCFF28F9E31AA4D39430FD9589F787A4D1
-:10AE10007C19CC0623BD5DD76509EA013F85A2BF39
-:10AE20006B90FE8AC2F689DC77B44C184067F998BB
-:10AE3000170EF64C01D295B44F8A958E163CE7FD5D
-:10AE4000FC4BF7B6E07C23E8EA2D84C35905E88A79
-:10AE5000FC6A03F4ADF67B14DD49FC4B7BBA9C35F0
-:10AE6000D17E676E02D7B3C1EADB49CF82B824BA7C
-:10AE70007B730EA7BB2AE621BA2B675A7AA9346BDB
-:10AE8000CBD1740923EAB474E723BA8BA6D77874BC
-:10AE90003718E94EEADBD42BD3DDE74877DFC58FDF
-:10AEA0003990EE3ECF72C6A7BB687A93F26C9FC50D
-:10AEB00051897675638D42FAA1F89DA12D581E51D6
-:10AEC0009F4F76F6BE6437D9DD8D4DFC7B498F47A9
-:10AED0008F7933056BC5F77C6F25961BD7C177E853
-:10AEE000BAF418CFAB197A0FFF5EB8A1E90DBCBF59
-:10AEF000A0D1CFDBBF7C7A339D870A6C16EDCBDB0C
-:10AF00002AB1DCD8CADB7F8A71AEAB31BF2DD082CB
-:10AF1000EFAFDA96EFE6DB6F6ED74F11EBDDA73CB4
-:10AF2000F706B56BE3ED6E3F6C4E60E427E0F6FA92
-:10AF300064B1CE29BBF83AD33EBE7E860BE86345AA
-:10AF40009F9FECB94F74756524EFE2ECB3CB95B6D7
-:10AF50001C7C4E4739A647BCBB5BF543781C743755
-:10AF60000C717536F7D3C8F821E6295447D817571E
-:10AF700067733B44D64B4F61747E8DFDCC4EFE72A1
-:10AF800019DF0C3EC414D407B8466197C48C774EC1
-:10AF90002F6822BB62FA6019E70CA94B61DCC24B37
-:10AFA0009F4F8BE5472ACBE6F6F329917721DFD730
-:10AFB00004F2754817FB9048E8FCF09077D09EDBD0
-:10AFC00097CC34E7DCF6E5F3F2D4ECBC7F6ECD0130
-:10AFD000F8EA9A54BCF78BE52994B7F2831E164C15
-:10AFE0004A1C38FFE92A0B1A290F8ACF7F658B513B
-:10AFF000DC57C2E5DA3C813F366918D1EF5C81A7A6
-:10B00000EA6CA1178B5931CAA979026F3F343719FD
-:10B01000B8BE6E3344C98F79D9283F1E8E6BCF6B73
-:10B02000BF47C9971A31EE4A61C7AF627DE43FFD61
-:10B0300044D8F1A71EE676FC6AD641FED3DE9F71A6
-:10B040003BBE1E9687F412ED07ADDDAB2DD77768BA
-:10B05000CB0DA0DEB1FFC6AE28B93386FBA57B1FA2
-:10B06000AE2F433F64CDCE77C8FF5D23E54C402B28
-:10B0700067C040E772E6A151E4BFFAD6F2E319D8FF
-:10B08000D59569F24BEFC97646F8775EE4792E0DD7
-:10B090008CFB117AED236FC17D2C8BD24FD172A521
-:10B0A00050C815E9FF90F25BCA9B42C6F514EC77D5
-:10B0B000DFF1609B283BEFE16CA1AFC4FE4DFA4D80
-:10B0C000A47D5488F611D2D7A82622BAB07E72BFCA
-:10B0D0006DD247E8A5052566C47B9119F81BE1A64A
-:10B0E000B78DF5D934F4F168F6E5F783DAEF51F46A
-:10B0F00023F7630B05FDDC84911818FF0F721FB84E
-:10B100008AD3CF5CE63D84F4F3FBD59C7EE4BEF0AD
-:10B110009BEF033DFAC87DA0DC4F7EDDFD603FDD87
-:10B1200058C03E86E7B15CE917E0F1FD4685D3459E
-:10B13000FD9CDF3D56C5C2F2E2683373AB8670B941
-:10B1400065A6C98C7E971603DF2FCD99F57ED9D2DF
-:10B1500008F913B4971F40B8B16E27F977EBADDA51
-:10B1600071362B3D77FD11F7558F5AC9AF74E10841
-:10B170002393E5C2AE11940FFE9981C75BE57C6E07
-:10B180003FBCF7B510D45BB9EE9662CC2FA8550240
-:10B190002FD6C1B70FACBE7791BF6B7541712F67CA
-:10B1A0000FC527E4B8F1FDBA7E92C7C6035C3FF72E
-:10B1B000290994DF0BEF8747C6E9FE3888CBEFDC1F
-:10B1C0004CDF07B81EA9475BFAF327F813B4301B0E
-:10B1D0009412CEA708E74D707FCB5F98E78A79136A
-:10B1E0001B23E204D03E66BEDB7921CF47617201AA
-:10B1F000CC6765BAA717D77F4AC4854F8938E2A9BB
-:10B20000441E57FC7B7F7DFEB40DE27AE894883BB8
-:10B210009E4AD1C69B64BD44F13CD96CF66E346045
-:10B22000BC9E793782FE703D646AA27C95451C5FA6
-:10B23000BD2F256BEE11C81A543E6A10B4FB99D38A
-:10B24000AB1F04E32C6FD39E83EA15F7DBF60ABA33
-:10B25000E9B5F0A71C376B50F5286CD7BB80DFB37E
-:10B26000DA5F9E28CB5EEABFF7BA10C9A3FEF28F61
-:10B2700042E29C3AF793C8F840BCF86174BC30FADB
-:10B280009C6974BC7FB1E43711EF5F24E4D4E26EB3
-:10B290001E6FB8D5CC360F82EFB7756750FCB82655
-:10B2A000D13F5C13EFF75BBF519E87A4CFDEDC9EDE
-:10B2B000FEF8F8CF22E2E3F5223E5A2FD7D7A95D58
-:10B2C000DF6401CFEF313E3E799073607C3C3A9F62
-:10B2D000E245B4330C613CAC7170B855E9EB2AD14E
-:10B2E0004F7C6139A33CF7356F2D6B413FF29A2DAE
-:10B2F000E296556177D70B38C75B97D3AB632E8D3A
-:10B30000BF3E81B922D693E54BD194C9928FC83301
-:10B310001D5493AD699FDB3444537FF0BA519AEFCB
-:10B32000F9FE224DB9A0F51A4DFD616D159AF2880E
-:10B330009DD76BEA17B22149E46F3BA2475F12BB6E
-:10B340002A3047F37DF4DE859AF69FB2A61D93A0BE
-:10B350005EA7457B2F33F37B7AC69485F3A9C77626
-:10B360002CD5F4C3824A50290BDF33F699B8A7795C
-:10B37000790F8F875CDDB55A334EADBE8EF0181D48
-:10B38000EF2D627DE4376E0828EE201B18FF5DD597
-:10B39000D54EEDAE64F7C878C8C64122DE97CDB26F
-:10B3A000395D47D3858DECC30BBBF4E47F2C64C3BC
-:10B3B0001F9A44F032B0806B20FE2E30EE17BBF0A7
-:10B3C0008CDD8D7945B7BFB58CE663CAD4D205DE76
-:10B3D0001F18B95EEB482D5DD8DD5A3A489AA0A5F2
-:10B3E000836878277BB474C142F0BFCBC03B7586BD
-:10B3F000966EFEB7E0DC81F0B586E15B7CD0D3626F
-:10B4000023B8F1BC35699F99843D141DD790764EC1
-:10B410007090B0BB453F322EB159F1935DD51F7787
-:10B420009C10CC0BE6A33DD5C4B85FC97B10E56F7B
-:10B430000CBF24BD8FE79794709D9BC0F5672DF3DB
-:10B4400092FC3E66E1FEA493D5ABC89FB4923591C1
-:10B45000DDFDD99CE9C2EFE8A77A57CA5318909F3F
-:10B4600000F6298BF0D7AE068B1AEF1F8A86A7D27B
-:10B47000AD04ED786E98754B7DE0A3FC150FDEED05
-:10B48000A989FF68ED5FE65122E597B487E5781258
-:10B490009E52AEC9714CAC499F897C1125E7D8C832
-:10B4A000E8F893D69F23FD41328E23E34CD1FE9BD7
-:10B4B00008BBB8558F71D2C1F92D78CEB7D8E1212C
-:10B4C0003F6129EBB905DF4F3077B4A82EE1BFB853
-:10B4D0008AF5FB2FE2EAAB2BC4B56FF22BA147F242
-:10B4E00007C6B3657C1C96FFF11FA1F124C5958B9F
-:10B4F000F398F3F20827D2D340BFA6FBF82BD08FE6
-:10B500005ED7978AF5AA30313D22DEFDA612A2F55C
-:10B51000FC907936459EDB6F601DD36E217F32E84B
-:10B5200049BC27A793FBBB5857B43DAC92BF590702
-:10B530002B41BAAF651171DEFCF0772AEB079665F7
-:10B540001ED295EC89A7F18272CAA3E0F9534CC8C8
-:10B5500041B9FF8CB7CF93F918F27E4F9977549485
-:10B5600023F8751C1B87FD03BF95E594A27F01F8A6
-:10B570005389E4C7FE3C25FA3E801FA3D62FF33142
-:10B58000F4F612F21B2D8B5CEFD78087B45B7E9CA8
-:10B59000C3E8E9C871D1B33EE1C46F3DF8B9A4472F
-:10B5A000933FDA68840D0DFA135E1479811D5ABB3E
-:10B5B000FD961C9D801BDFF75C095EF1F121F2F81E
-:10B5C000043EBEAE1D26F3F8241C970C84FB0A0D26
-:10B5D0005CFBF78FFD705F110BEE122EE74A7B7E4E
-:10B5E00081F8D2DB8FA523BC17A67A5763FDDCE375
-:10B5F000A14F145D785E55FAB394877BA14B4FE75A
-:10B60000FF1AAEE372B0E1253D8986F3DD268AB3E9
-:10B61000D674BD4176E1D96610B406FCBD0C187233
-:10B62000D865FC0851F08EB74F92EBD99023F6E520
-:10B6300062FD32EF07D6B93927665E473F1CB4DF9B
-:10B64000051CAAF46392F01C597FBE92DA97177911
-:10B650005F5FF43A2A7278FEDB29B3F73EECEFC362
-:10B660009E9C1DD85F95BEFB7036C267AD42E7BB9E
-:10B67000A698F879DC2C715E6F42A8C98DE79933E2
-:10B6800073F87D66237EA4F7621CF9FDB577A6E00A
-:10B690003934D9FF084547E747197BEE837F2CC132
-:10B6A000F8E62237DE6FBFD824EE2FBACB1A2C0073
-:10B6B00039F2BA91DF476518D244E766FA92F5E4A9
-:10B6C000D74CD3B3A9487772DEF2BCAD7C8FF701BB
-:10B6D000605EB17C3FA5A5AF780DFA7B043DC875CF
-:10B6E0004FA9EC2B6EB285E12FF33CA3E15325F873
-:10B6F00043EE431BF05E5BD0BFE7CDBC1C7DAF6D5E
-:10B70000FFFE7458FF3D36F6C8B87E83C593341EDD
-:10B71000F951DC6BFB17872789DF77A4BDA7F6BC3F
-:10B72000C8B797BF5312EFDE9BFFCC51BE977B8209
-:10B73000E2E585CBBCFF7870694856997A359D73F0
-:10B74000F75EAEDE2BFFAD8FB9DFBE28BEF7DFD3CD
-:10B75000F96AECBCC55EB1CE707E6188CE29F7E790
-:10B760002DBE547ED97B471AF03ED20838C8BCF6AD
-:10B7700006BC8FB43846BFD09FCB76E57B87AAC482
-:10B78000BC1A308F3035F23DA7B7F03869222F3020
-:10B7900094887CFBCB2E3D9DE3FFE511DD8CDD31F4
-:10B7A000E69D9BCBE132CAA9121F8D0EF2FBB5E3D9
-:10B7B000D593E779E4B9D8E8F97556846EC5F9638D
-:10B7C0009E72ACF11CB97C3F2BE7DD99C2F1D1F040
-:10B7D0009A89DF9BAAF27CF2CE94D04AE2138716B4
-:10B7E000CFC3041E3BAF0FE5D1B9B299DCEF108F88
-:10B7F0001E26A7FACA51BEC87BEECAD426C511C1FF
-:10B800008F57A28730DCF51ABC0E84BB91BECB7E6D
-:10B810004F1F157CCB3C36DCCF2D11FA6EC99E5ADA
-:10B82000B287E57EE9F44E3DE56F9C663CAE72BAA8
-:10B830004DA1FDD0521F63EB402EAD7CA27833AA00
-:10B84000AE2599B09614FE1E7F1F66E9C6A8F8BA09
-:10B85000D85F49BD2AC75FBE4D6B17D7B06D7F4615
-:10B86000FBE9F4512E3F56B026D23F2B1FD0F6579E
-:10B87000B367D6A738CFE8BC8011C28F372D57ECFD
-:10B8800057CA5819EA8F354F7C6EC49F6089C71715
-:10B89000F8FB4F4387F1DF7DC227FE8E083E6FC95C
-:10B8A000F5FC2017FD3EEFF2F9AECEF5CDC9457F90
-:10B8B000C9BB7C7E17EA2E703DB32B8DF45B8BFDEC
-:10B8C0002E92FFFAC15CFEDF8BF735009C4C26718F
-:10B8D0006FBAAE499F48F64D80E8EC43E71D737E92
-:10B8E00040657726F243DAD3D36760BFCEA7AD1E9B
-:10B8F0005CDFD6724F21FA2FB656F3F3A166138F91
-:10B90000DF077E39F100865386766CAF40179DA322
-:10B910007B7F10FD42ADBA3F1FC6BC98D6C93C5FC5
-:10B92000325D17DA3F28623CA7359089F17DE768E0
-:10B930007E6F4E9ABEBC90CB7F6E2736085C5CE86B
-:10B940002A207F62AF41FA173B2C742EAB8EFF2E5C
-:10B95000C628C6F12FF3EA700E9176F1D966A6F9E2
-:10B960009D86511D4AD09048F7A8503CA86E4330A0
-:10B97000FD16D4674FA9144F93F34B7B3DAB02E305
-:10B9800066528FDDA238B8BF4DD8FD0B98FCE3712D
-:10B99000B7F9829E16087BFF162B87F752E6CEC3B7
-:10B9A000760BCD2C5107AC764B654729ADB3D690BD
-:10B9B0008C76858C1FC5B74762FBC91A7E61E7E7A5
-:10B9C0009E95BEE1D8C919F4415D863FDB853C698F
-:10B9D00018CECFFFB1A1CC83F1CA86D746D0EF30C5
-:10B9E0009912783C1CE49619EF113A84FA1ED6BDE0
-:10B9F000EA158BC85B0A8873CDFCDED8C639394599
-:10BA0000741EF1781FDDFF71DE10CA23FE067984F3
-:10BA100037A6BE92FBBB1FE0BDEB0DD960D741F945
-:10BA200074EE9F7879486825DE1B9992778997474D
-:10BA3000853EC1724E5EC26C2A178556EAA13C3E15
-:10BA40002F939771030A0436356FF06C3FDA2DC9D6
-:10BA5000C22E7087E8BC77C3CB237491FE58771E43
-:10BA6000976767843FF94C3EBB6D0EC27B64ECFA6E
-:10BA70006979D2DE6EA3F5C9F5CAF62C3376BBFF21
-:10BA800010727E9538A73DC5CA5A2D3CFEE74F047B
-:10BA90003C1CEC1E41F1CB7FCD4DE1FD3B42744F90
-:10BAA0008FEC27FA771CE4B8AB15FE7B59E7A3F2BD
-:10BAB000BC7E97CBE52B8CB391C619EAE1E79BE7F7
-:10BAC000E41422FE006FAAC09BCAF7C9ED7C7ED0A9
-:10BAD0002FFEFE13E88762F4FB1FFC0AEAE787E704
-:10BAE0001D4D2727C538AB5A78DCB62FB980E869D9
-:10BAF0008A55DCF752A25DC7F83C6E9FBAF392C537
-:10BB0000791D09AF0C85C6691170CC090D9F33F6FC
-:10BB10009BAFFBAFFF4BEB8EC09707EF6D39D8C5DE
-:10BB2000EF371E9FC7F185F49C4276E0764D7F6724
-:10BB3000D647B59FC0285FAE21A580DADF2BEE6F18
-:10BB400095F7D961BBFC71DCBE45BB57DEA7C1FCD4
-:10BB50009359641CB2FFDE8C0E71BF70FF3A6F28E0
-:10BB600011EB7488753A22EF33ECE7CF637D79737C
-:10BB7000ED03E9B81FFEFDFD8D2912FD69F83C5665
-:10BB80007FC8D7F1F072551E9727DF1B5EE43CA3F8
-:10BB9000E0D90FE7A8F94978227F53BB315ABA940C
-:10BBA000F3CC11F43980BFF3BFE578E27ED9FABB5C
-:10BBB00079BE387369E9BABE335F87F909B2DD0728
-:10BBC00078C0A034EC27BC214FEC2773584E9CBCA6
-:10BBD000476F9E33A67F91DE47EF277B93E5EFD932
-:10BBE00069FD1ABD4EFE7B39FE73FC7E836BA3FCA0
-:10BBF0003C188F7ACE166E17D62FDAF263027E03C8
-:10BC0000FD547D7938BF1253C5F3F83B5BABF34A63
-:10BC100067AB6077942455DC990FE5A6C7C693FC03
-:10BC20002E1954F1793EC8F3358F4DE0DF47577C2C
-:10BC30003E04CB791379798AE77994F760B4CC9E86
-:10BC40009A15B62BEECC73D1B8FA4A1DDD6B67425C
-:10BC50002306D6637ADD44F98012AEF19E25265D77
-:10BC600053ACF3BFF7F4D3038FBF4CC07FBAD01FE0
-:10BC700028FC052155E32FE84DE4E7CF7B5FFD92DB
-:10BC8000CED7DC9BE75B9F07ED1BAD676FCD87F2DF
-:10BC900006EB0714EF533C6087A01FC6E5608B607E
-:10BCA000BECAD9AD5EB49FD86AB75925B80AFF1885
-:10BCB000DEA907F07BE5B5A77E3C880FE3C5794C8C
-:10BCC0001472A0F1B5BFFD15E3C48D676C6E341B13
-:10BCD00027763F7C27DA5F13BBDFFE1BD7C3FC3C14
-:10BCE000909CF744F47FC2FB095D269AFFC4EEAB3B
-:10BCF0005660FD6BDFEB2E403AB9EE44B005C5420D
-:10BD0000EFABFF3E48730E887D7AD97CD1B8F1390C
-:10BD1000098F3F01A093081E3FE7F0F88AF2D9CEC1
-:10BD20003B8F6E0E9193547BDE0AEC788A3B5F600A
-:10BD3000096E8C7BC873FDD17ED5E3D5B03E787F8C
-:10BD40005D1FCC20C29E9E72D10C82245C2E67C9DE
-:10BD50009A72A5394B53BFCA91AFF93E3DF32ACD34
-:10BD6000F799AE424D79D6C8899AFA37BACB35E5FC
-:10BD7000D913666AEA577BAA35E5C26087A67EF1C9
-:10BD8000912EEDF7634C8F78283AEE7E039FA5271E
-:10BD90003DE49E2D3BD5F4063E27FE858323DAAF96
-:10BDA0007CCDC58E37F0BDF42B479F9F927EE69BDE
-:10BDB000F5B68031B63F39532D08DF83A0D7F1F3B4
-:10BDC00053EF25FBFE807893E7A7A6A05F1990505C
-:10BDD00075DBB99FE2EF325C58C4FD6EC711319438
-:10BDE0004F6E277FE57143D3B37FE47903B928F71A
-:10BDF000AEEB9BAF59F7948B3ECDBACBD9AA283C7A
-:10BE0000DDA1295739EED6D49F9EB95EF37DA66B8E
-:10BE10004B149EB66BCA37BA1F8EC2537B149E9EBC
-:10BE2000D27C97F4DD2DFC5FAFA1DF0A9E93423DEB
-:10BE3000958887C9A7FA081F137ADA2A114FD71CE9
-:10BE4000EF207C9504BD95282ECB8E34BD81CF206C
-:10BE5000ECCBB0DD81E64C7A1E6C7691FFEB70F393
-:10BE6000487A1E6976D3FBFF689E40CF5F357BE83A
-:10BE7000F99FCD33E8D9D3ECA567477307D57FAEDB
-:10BE8000B98BFBCF52FBEFDDC845BFC1795DA8017F
-:10BE900023C68EC15B499E9E4F089DC7F2067FEB6D
-:10BEA000ECA92034F0671D902F7F209E452E4FFB7C
-:10BEB00060780E1ECCF8FD19227FA343E729443B8E
-:10BEC0007CF4E30FDEA7E632B669BD37137F3A187C
-:10BED000CB662813B2E9F7901EBCCF93C3D8B3A8A2
-:10BEE0004AE8BEF7076763B957FC9EE7E0C71F241F
-:10BEF0003BFC5BC7D93D03E2ECA307C788B33F7B9C
-:10BF0000CA65477FCFD1AF46D8111E4785DFCBC367
-:10BF10000A0DF83B1CE56AA101F5ECF138E7215464
-:10BF20005379C9E0525CB77B1EE5915F6FA0DFE1FA
-:10BF30009BA3F0FDAFAC97ECE2FAA0F74613EDA798
-:10BF40008EE93C2B903F7A95BEC710CE373DFE144C
-:10BF5000E9A95E7B5F1EC2AFFAF1BDBCECEC7B4C85
-:10BF60007147940D1C3E958F3F39DB6FFB5EE133CB
-:10BF70001BD7110D9FB9831D7C5F11F4E4A21D2016
-:10BF8000CBC7AA3DF514572CF70CC3751CF59A388E
-:10BF9000FF7AED8161E437F294CE8BF0FFF40C363A
-:10BFA000D0FAE7A2DE443FE8427D20D6EF159E1F7F
-:10BFB000CCED3DA213DC672EB0D2BEE0988EDFA39D
-:10BFC000105DDFEEE2FBA3CFE2DC879C28BE57DCEE
-:10BFD00054FFEC0BD05FEF5A0B75DDEB1D41F658AB
-:10BFE0006F13401768BAF754D339FEDDE41620A169
-:10BFF00038EF2DF82FF8FE6CF79D5FFC06EA7FB056
-:10C00000D6EA261DE21845F05B282A2F4E3593FD0F
-:10C01000B4784E6E05EAC55B44BCF056BB9A4E61DF
-:10C020004335D9E8807E96DB0A370304D9CAB46A5F
-:10C0300023FE64534DCE1D9BF1B97AE87623F25866
-:10C04000DD987D9BD18CAD07162E25F9177AA7199F
-:10C05000E675DB3ABD8BEFE7E4F9DADA6F94F722A5
-:10C06000E9F798C84F0220D07E35C9A568F649493E
-:10C07000824E1F182CE23163D9D84BDA78D74EE4C0
-:10C08000A3B38BDF191E271EA1FD2EECC7DF8A7B11
-:10C090009EA3EF4F91E33A5C7CFF75CC089489F640
-:10C0A000E442AE07C6CDFF7C4329AC7F5CB7434773
-:10C0B000790DB7D5BF8078B8D025F068605DC84FDE
-:10C0C00037F9977CF01B424C9AE6DCF095F4A5BB5F
-:10C0D000C75119A92F4B42DECA487D39A1AFAD1215
-:10C0E000F5A2D48FC1E61A218F9B488E1E6C5E4745
-:10C0F000E5C3CD7E7A1E696E15F2B88DBEFFAA79B2
-:10C10000A790C701218FF7D2FBEEE6F9F47CADD9F9
-:10C1100047CF85A9BED7116E328E3BD7ECA3BCDCCE
-:10C12000430F9B18C6F12E749B288F0338E2B1474A
-:10C13000D2304FC944E744A3F395A2E57C3F3D7458
-:10C140000EB8B7E56DE4F7FE3C23B41707C7A7A701
-:10C15000A3CC6547B9F4F1E0F324878EBA5C76B4DA
-:10C16000A74F3E2ECA1E97DD00E53F0DEE25FD715F
-:10C17000D4E7B29BA0FCC9E3BDFCBBDF65B740F9C7
-:10C18000D3C17DFC7B8051D0FFECE02F488E9533EE
-:10C19000E520F247A5397F2AA80BD0D7E507912FD4
-:10C1A000A6672E998A7CB160B08BE872A66BFD41C0
-:10C1B0002CCF1AD9AEE215151E5BE1466C5791568D
-:10C1C000AD62BBA939776CC476D3866E5723DBCDBD
-:10C1D00018B36F23966F70B7AB689F2E4039561A0D
-:10C1E000EE4796E57729A7653EDDD5DD5ED207E30C
-:10C1F000BABCA40F245C2AE6566F42FF676397E23D
-:10C20000C0DFA5A998ABF4273360EE6203DE930A82
-:10C21000F2FAFF3DAE77AC87753662F91A2AB7ADF0
-:10C22000FF06FAED7F00F6E231E800800000000032
-:10C230001F8B08000000000000FFD53C097854E582
-:10C24000B5E7CE9D2D64924C360842E2649924965F
-:10C250002C43B6261064480CEE3001F944651910E1
-:10C26000C2164804EB17AB7E191A17E0698D6BD123
-:10C27000AA6FC4B5AFB6E461D458091DAA52D287DB
-:10C280003A5510B47974A488F0999011DC78D2C72B
-:10C290003BE7FCF766E6CE248014FDBE078693FFDD
-:10C2A000FEFBD9CFF9FF5F008053F8B3027F603403
-:10C2B000FE38253D8C046804F167BFD16DB295034B
-:10C2C000AC34078CA0A32F41A3AB1060AF0E9676C1
-:10C2D0001400A424C3FC7A0B968DB0740B96E75D12
-:10C2E0006803480568DABA206E8185DABBE36660C8
-:10C2F000FB4517E2AF38CE52056E54E0930AD49B4B
-:10C300009C89344F9A4DD21FCAC76F8550784A0610
-:10C31000E8B79A3DBA048044937BAC0DC7ED9BFB14
-:10C320004E835887AF88D6316CBD1EEBE300326C6C
-:10C33000561E1FCA8219545E09ED46C846B8F5CF8D
-:10C34000FBA422DA97C52723844E435F205FECF9D4
-:10C350005416FE63063D54E07AE9036E6999D7707E
-:10C36000206056EAF1673974EC706622DE5ED47E96
-:10C370006F04BF18BF43FB7D15E28DBE377569BFE3
-:10C3800003545B0F8D433002CBB8DFD912FE5E85BC
-:10C39000FF0D8F874967C0C3A4A1F010B51FF01A25
-:10C3A000418EDED70ACB6EA673E4BEC09DCAFCD117
-:10C3B000088121F7A7F245F4FEDA05FEF502FF2514
-:10C3C00036E7745A5FDDFC389053008E6D35794D39
-:10C3D00099DCFFA93D2944179375832D9A3E5B5B39
-:10C3E0006783DE00B0ADD5CDD0D7BA14F476803FE8
-:10C3F000B53673F9ADD6162EEF68F530DCD9BA8EA6
-:10C40000E15F5ADBB97E57EB462EBFDBEA65E86F8A
-:10C410007D91BF5F3B7F6586DB124DFFD5C9CE4561
-:10C42000C48F9E7BAA13993EB8F753C8AB9E1AC817
-:10C430006FB644C30183659D94C0658F11F7E1D940
-:10C4400016E36DC37DFD738CBB89C619A8097EAD4B
-:10C45000437C434A80F1D030D2BD9ABE4B461C3A51
-:10C460008966F5E412FE0EEB3CBF0764D9569BD3F8
-:10C47000A5473E381A8F551700DC82650FCEF3783A
-:10C48000AAAB85FA417EC048E39CA23F93717C0928
-:10C490006677F03A10A21C0EC408E8B1492C8FD17F
-:10C4A00050C8DD40BA9FF960E0E91319B68233CB7A
-:10C4B000C570F8A893AB039E32A46765ACC384D55E
-:10C4C0007D12F8A412845346D6008ED3976ED413EF
-:10C4D0009C14445650C7C39FC9DF226386F1CB1416
-:10C4E00048D4946BCDA335EDEBAC999AFABEF45CCD
-:10C4F0001EFFD2B48B34EDFA46579AC5BC532F2396
-:10C50000D865746F5C80740956991C9BB0FEBD9809
-:10C51000F822280698161BBF89E07B31195E6A371E
-:10C52000EDC0C914C07D4E937D238B105597DBC69B
-:10C530006BC7ED995363C37657E65769D721C12579
-:10C54000B4DFAB1D5334DFA7575EAEE9EF32FB9388
-:10C5500008ADF5CE7ACDF7C696AF419F0C30B1E568
-:10C5600024E84B01C6FB3A34E394EEECD2B41FBF8F
-:10C570001B6412EB927D8E3709961F74CAC42A156C
-:10C58000879BDF2458F5A53F83F6014EB059519F94
-:10C590004B8ADC8347023D962729E5CAA0B72D8147
-:10C5A000E87012F2F548BF8930C2216363A9F2BF77
-:10C5B0004E101F4C5220003207F6AB164B80793AD2
-:10C5C0008BD798456A05E51BF5C106C991A6473882
-:10C5D000470E5450F928048A08CA3A979EF86B2AE5
-:10C5E000348FA5B209DC69043F4874BF4F7CDC2F4F
-:10C5F00005DAC4E282C9C4CF753FFF68DE6DAC17AF
-:10C60000621C265CDFEFBAFE914A6BFDBB3FF591E1
-:10C61000376C217E6FB27ECD7852CB8D2DC7197FBE
-:10C620006AB96F2DCC77E192DB0D689F1036FEAFB3
-:10C63000CC760AEDDA3AA25323FCC9B8BA20D41E4C
-:10C640003ABE18C47731EABF7A5AD304C2D7DF5D45
-:10C650004E6C576F1072089E45F54E1CA73E46293A
-:10C66000834FD4A72AEDA1B29ECBE96A7D95686F6E
-:10C6700057C77B58B41FAD9695F12E52CBCDA29CD7
-:10C68000A9CEF7A02817AAE5FF7071394EB43F6113
-:10C690009B55EF2908E9FF53AADD180FE3C96EA0E7
-:10C6A0003D9033C91E48BB1A981FA2ED85B65EB1F6
-:10C6B00017F37F237B8CC5448FCB63DF21B9EE90CA
-:10C6C00080E4BAF17683D38BF37F9ED451B4C61243
-:10C6D000C2DFE7B7087CBB6AE39C32B65FF96ADE6B
-:10C6E00026E223396EF7C885F8DD3A56C77AA74E99
-:10C6F000B63881E87BAFD0FB6AFF48D8D0F2868697
-:10C700009E51F5B2C4F3C16CFCC1F9FAEF1BF5F40C
-:10C7100006C2598E3F9770939929F4DC48D4AD95A1
-:10C72000F8F336EA5933D23D251B9C3A6C9FF21A36
-:10C73000EA67A2F141BFD0C7AFC5F824149C958F1A
-:10C74000BDC9F66FA18C528EF87B2DCF9D97897C49
-:10C750007A34CE9F4B7CDBD0B28DD7758DDDCAE3AA
-:10C76000833558108ECFE2CC28FC979E01FFA53F61
-:10C7700026FE718203A4CF752874B4BEE596B778FF
-:10C78000BFCB95EFAC5F3243EDB82C47978FC639DE
-:10C7900032081F0E854E0774B60A055F5713BEFA9E
-:10C7A00017FB7313B1ECF0F947BAD93EEC2A97881E
-:10C7B000EECD7140743F2AF98BF60E41FF8ED60EF6
-:10C7C000B6CB5B5ABB18BE8473D0BA557CDD108DD6
-:10C7D000DFF967C0EFFC1F13BFA3F401A303FBAD98
-:10C7E000DA073C4E85FF8011C2F44C2BF125E2277D
-:10C7F000A14BE2FA3AB92021A0A98F13FE528E7301
-:10C800003CF1E9CA19BBAA37482179981C0B1D31A4
-:10C8100049CCD70E85AF1DC4D72AFF223F96EA1117
-:10C82000CF6F9DC47E43E037C4BFC0F3A878BA3B46
-:10C830001AAF1B888EA7C1ABB6FE07C66B27FAC717
-:10C84000A43782AFC478376546E3F9770A5E557C32
-:10C850006F53E47F383C6F233CA79E7F3C6FCBB483
-:10C86000F1B891F81ECE3E45D2475DF710725A7E60
-:10C870002E723A2DDBAAF8DFE8771646D3FD6DA2BB
-:10C88000BB5943F79E33C853CF8F294F91788B8480
-:10C890008D12B83A2CD1DF3FCB1C56DF9D173C4E92
-:10C8A0000ACED6F86793BF756BFCB329186169FD92
-:10C8B000D89B34E53AEBAD9AF697A6ADD5D45F6E2A
-:10C8C0005BAFA9BF32FF014DF96AC763117EE6D3A2
-:10C8D0009AFA7AE76F34F5739BB76BEAE7B7F468B7
-:10C8E000EA1778FEAA29AB78DCDA0A1C2F6D6B35C3
-:10C8F0002BF1D3650CAB03FE5A12838B0F07D9DFE4
-:10C90000ACF4B7D7B24BB2AF83FDD1329FAB96C276
-:10C91000AA8A9DCD6F12F4B55A95782D8DE15BAD45
-:10C9200036D6EF3B5AF319EE6C7528F15A25C35DE4
-:10C93000AD4E254E73318CB40BAF66BBA764213D61
-:10C94000A6BDBC4407B880E97FF867C15E5ABC77D2
-:10C95000BC8EE2DC35CA5E8E577FB3FF36E4AFE3B0
-:10C96000CD2607957BB71F31D80AA3F965EEB732FC
-:10C9700038C3F86C6ECB5F0DE467CD450FBA630822
-:10C98000399D9AA5637E20F703502FCC368321056D
-:10C99000F5C1ECD992A30DF8BB079218FADC583F09
-:10C9A0004D0F3E1396EB2D7A9F299E97E632A33FBB
-:10C9B0003D4B2C134C7AF0503DA424739C7E0D7D8E
-:10C9C000B4A13C3865B818BFCF223F1CFB5D6FE9AE
-:10C9D0003090DDBD6EE72FFA6FC37AB8D353CEF136
-:10C9E0003D5C6225FD2D793ED69D1A37BCBC2035B5
-:10C9F000E150185F4F25194EA5F8D1E17752DC7A46
-:10CA000093C1F19C2DBADF05CA7EA7C912FB6FC185
-:10CA1000D74DDE4D52483E717F3B4DB8CF26E201E7
-:10CA2000DA67B3C19757447EF676F6B39B2AD716DA
-:10CA3000119D9A2E913E311585E29DA6962FD98F94
-:10CA40008FD4CF91F04CF190C36F65FEDBDFBA93CA
-:10CA5000F9458D8B7A5B7D5C2E0BB86AC3E3A339F5
-:10CA600093FF4DA6B8A7EA4B11FF4C3CE9DCFB5302
-:10CA7000DC77A0D5FF2FE517D4BC829A6788CC5B02
-:10CA8000A87A64DEAD75096EDCEF9A2C5106F3943A
-:10CA900074A6A35E4055DFDE9A156597EFC83ABDD0
-:10CAA0007ED6D6FFC0FAF96CF9BF314DD8D548BE55
-:10CAB000DF37E30503AD53E5EF48FE9F437D70FE8E
-:10CAC000394D92D7837A7AF69276C344E9DCF97DC0
-:10CAD000B9E5A0888B23EDC2F7B60736A69B5C2B81
-:10CAE000737C61926F72501E44A5434734DD3ACF88
-:10CAF00040B7CE1F936ED176F1E0BC73B38BA0F13B
-:10CB0000CFDFCB8AF2273EC83ABD1FA9ADFF81F720
-:10CB10006D1D6B63B87244EF3C5927EA457C620196
-:10CB20001DF2EF8057E6B87469667B3CC533501937
-:10CB30008C277DB7AC5B06F20F41EFD48F46FE5CCD
-:10CB4000A2F0671FF83E247E5C05F77E4109982518
-:10CB5000D54BAE223DB7F40943084FFCAF93F32702
-:10CB6000AB947ECB2D9D46DAEFF267B5EDD4711A0A
-:10CB70005F8AC81F575FFA19B0DDF073DE6F55A7E3
-:10CB8000B6DF77597129876259164B08EF67D2A72C
-:10CB900047C9AE1BC2CA275B39BF203FF3E0039EE3
-:10CBA000B121FAC46447F1715CF6E9F9585BFF23DF
-:10CBB000F3B11CF7AC91E8F97DF978BFDD9945EB4D
-:10CBC00056F5F3A0DE79C3C47A67A0DC26F2A43759
-:10CBD000FDAE2D9EF8E40438881D162AF9D2856A28
-:10CBE000BE749D365F3AB9CFC779B94907BD6D713B
-:10CBF00048F789BD1ECEDB55ED76B759B0FCD35D45
-:10CC00004E99FCA3F16FB9645AB7EADFA8FE4E480B
-:10CC10008FE5B0BEE3BC6BF6D9EB3BD52EAAF63060
-:10CC2000D20E5606DB6BC9FE4DF8B6E34D82E72BFC
-:10CC3000AF1E69F7DE8B137AE2A8C157BE97FC8C52
-:10CC4000D7631CCF41F4FAAFCB167EC64CCF02039C
-:10CC5000CB1F091FCADB0C456EAE4F765F974DF5B3
-:10CC60008ABDD0999D06B2A37572DF23D7125FF9F2
-:10CC700065CE1BDE7CC707BFFFB5EDCCF98526EB83
-:10CC800071F63F868B339A74E0A6F8A2A4D6564A72
-:10CC90007E0CC56D944754F38A91ED9FB0D7ACC814
-:10CCA000E63C57B5DF49EBD928D6331CBD9A5ABEAE
-:10CCB000D0E431879BBFA9BBDCBA304C3E5ECA16BC
-:10CCC000F12ED2DB7AC81CA2F7D9F2C5FFB7F865FE
-:10CCD0009A0C1E09ED6CA1E415FE2F083F780EF8A2
-:10CCE00019CE8320433758F97C6A2138182E021751
-:10CCF000C37CBBDB4B7C3360088E24BEEA7FF5BB74
-:10CD000002E29BFE8B27B657C1F93B5F8AF4FF0610
-:10CD1000C6DB78FE8157BEDB43FC397087E1ACF49B
-:10CD2000C6EA646727F151E479CBBB53643ED7016F
-:10CD3000FD7A968B7AABE80397A4721BEBD84CE68E
-:10CD40008B90DE1CF5B4AA371760BFC24F74ACD706
-:10CD50006099E4B563D3AE808E45AC7071A657A6DA
-:10CD600072A7A82F5C99E895B05C581523EA6F4A22
-:10CD7000F44226C5430196CBF900AC0F1780D08B47
-:10CD8000378293F78991419684FD176F3597703EEE
-:10CD9000160239A4FF8B288E1A224EB7E608792F87
-:10CDA000CE12FABEB8469B17F9305BC91BDB6B4A43
-:10CDB000721056E738F7121D8B93FC1B1E2AA37CBA
-:10CDC000900E36A17C7D56752B9F77AAFD1AED3506
-:10CDD000BD84BFCD1270BCE2E936799F13E78C2386
-:10CDE000C3CFCDF2EDB507A8DD115A7BF9F078C5B8
-:10CDF0007E1CF747CB9587D7574CB11BE7FBF14318
-:10CE000025CFCBE5FF79E6EBFA3B0BF84CC1437E2F
-:10CE100072A3DD7D9CD76F04B0D0FA9F14711440CB
-:10CE20007306E547973C65D2919FF1119A63C80359
-:10CE3000F81BC6DD04FF1BE367827FC7F899E02774
-:10CE4000183F13FC07C6CF04177F3B1E8322808D3B
-:10CE5000394E4B4E79E81C3072BD861C81CFC1F92A
-:10CE6000BB8D3C7F9DDDCDF81DA4F7EBE0A573994C
-:10CE7000CD89C10B924EC36F03DDDFF0F9E9707805
-:10CE800051CF2523EBBF53E85AD4A967FB5FD415D4
-:10CE9000886F086B77418E91EB0B5F39184FE31F5A
-:10CEA000B50EE2D729E196A7E944F982672D330848
-:10CEB000BF75766709ED1BE53C83F651D4F5C18358
-:10CEC00013CB787CAB64A375041FE5B821621F9176
-:10CED0007850F7B539D1BF81FA6F7E258B76827A8B
-:10CEE0000784DC101F4943ED772DF3CF7453B0CC8A
-:10CEF0008AEB9D7E4A6E1E0AFF75F6298CE77754F1
-:10CF00007E53CFC715FE52E976AEF21D391E906BE7
-:10CF1000847EE76AD2A536B24B27E3C92FAC57EE21
-:10CF2000197475E6BC47FBF4EC94C16E633ED6C839
-:10CF3000DF62855F5458D86D7411BD36771FCA59AA
-:10CF40006461FAE42CC6F6B372EC9ABC6761D589C9
-:10CF5000C71F4AE1F6569AEA3A78BACE8AE3DF600A
-:10CF6000DEFE366D69AEF593BA442CCF4F93761042
-:10CF70005C60CB9C9A64A3E57A79FD37E64FD94192
-:10CF8000227595A39EFDB929A464C2EC43AD3996E0
-:10CF90000E1F07CB75D6644DF9D2B4319AF697DBE4
-:10CFA000B235F557E68FD3D4ABF35EE528D5B42B75
-:10CFB0004E0A66515C87FB60B980E764AF5DA27D75
-:10CFC000EFBE621C96A73D3FCB416ECA66A57EDAD6
-:10CFD000965A2FD16300F1694487EA70E5FA471F3A
-:10CFE000A2C122E286C6EE6776386DE710370C13D1
-:10CFF0002FAC00718E3F5CDC10192FA0FE7C90F4EA
-:10D0000067F1ABD758DB70DCCD55272EB0E13EEF92
-:10D01000CCC13882EC8D12470CC73F837222D904F1
-:10D02000FFF4C8F0DC10FC03F00B851F059CF63EF6
-:10D03000FA3305DF5FBF7D4AFA8DF3071EC5EF5750
-:10D040006044BEAFD8E8786F0DE5A7DE9181CEF9D8
-:10D05000E124AE03EB1BE87739C4F7B0E8E9BB463F
-:10D06000A7F0770FB9A6AB94FCDF1F7314BFAA71AA
-:10D07000FB5DA3CB42F570F3279AF670BB74B7A69D
-:10D080007C67A6B67CEF94BBC3FB0FE797356C5C5F
-:10D090006074A39C363C2C39BD43E88BC1F5A428B1
-:10D0A000FAA17B09EBDB43DB97196D71D1ED57E1F9
-:10D0B0007894B76C18C6DEAA7AEA3A199A87AA7FDA
-:10D0C000479DCF717EE7FB08714FF6CDF39AB0C351
-:10D0D0001F25B88DE17CB22F479C7BF43FF6C01D25
-:10D0E0005FD379EEEB22BEEA4F14F6A3A8F3339D8B
-:10D0F0000E61F108C15F45D6808EECD2C0D2580FC8
-:10D10000A09C352D8BF3E88AC98F087E681E4F5E80
-:10D11000C72D0F9A91CE1FEB741ABB3C40C11696D7
-:10D12000FB9EFDD98C3BE9F702712FE97CEDB32F13
-:10D1300007847DAD117A631EF19F62B7005556D307
-:10D140005D3068C748CF105EA89C6BBFF5FD87C9EE
-:10D15000CFEF117A83F20A37B05FE0B468F30D1DA8
-:10D160002CE7F8BB2DFC3ED759EB8FB7DA8D96F341
-:10D17000A84746D8B5798721F4C5FB57223D9B5E69
-:10D1800097F95ED0B1ADF60408D31F91786CDA2818
-:10D19000B39CABE5A35BE5CBBC6C0F8319F585D1E4
-:10D1A000F806A783E57FB555CCB77AD23733C84E9A
-:10D1B000AFEED68B4B2FC3CDB34E065BD83C9BB79F
-:10D1C0009996925D53D73F6055F449F75749530AF2
-:10D1D000045C3B847D45BFC090427E41BDC4F1EC00
-:10D1E0009EEE513584A73D12F86C253CC435665C33
-:10D1F000DF4C311C7DB7505E14D2F2F99EA51AD7D0
-:10D20000AAF1ECACEE5976F2633FEC5CB807290763
-:10D2100093ECD9CC4FD78287FDEE3D89AE74CA938B
-:10D220004C53EE3FEC490CF691BFBD6752AC44F74E
-:10D230001970FC3B697C755F7B0CAEF466DE9792DF
-:10D240002F75FE443E157BF671A2AA67EBE4DBA7BF
-:10D250005C49E7F773C04AF1EC7459F8D5F04721FF
-:10D26000CFAA5E6D92FC496CAAED33A6DB114FA3E9
-:10D270005A7EA9E47DDB35F700CFD6AF1E8CA35FC5
-:10D2800094987F563944BCB1AAFAF347AEC5F95712
-:10D2900061BC4FFEDDC2AEEDFB087F91F1FD607C0D
-:10D2A000F52FE67BA3E333D732DADFCD771CDF73CC
-:10D2B0002D44C769837181EA5F3E17CBE7D6A85832
-:10D2C000857C28FC7A645BEEDE35587FE42F0666A9
-:10D2D000D73727FDEAE8AD58BEF9B958C6F391240F
-:10D2E000F0901D39B229CFEBC1064B74C15EB26F0D
-:10D2F000B0258ECF693E7B32EFB72F517EF2B776E5
-:10D30000F643487E6CE8C27C46F78FE8FBCBA3B9B6
-:10D310001FB8C5BC0D8A5CCA2F14DE5F4DF52F24E3
-:10D32000737E42A5DFE127639C14AC7D05BE222BF2
-:10D33000B2DEE792E710DD5B5CA17B69BF847CF91C
-:10D34000D508F706DAF7F2C7FFF3C389B89FDA17F3
-:10D35000AEFE5515AE6FD907A940E384E83AB4DFB5
-:10D36000706C6BB6907F053F2B5E8CF11E0CD32743
-:10D370002B3B1235E5A6AED1DE83617A68F09E7252
-:10D38000A3C4E7048D8A5CED37BADBED94D7A5FB27
-:10D39000A94C3F711FB584CEAB08FFF79918FF91D8
-:10D3A0007CF6A25D396756F33CC9604E23B9750B14
-:10D3B000FC0DDC97B789E2319F3D49F13B82B933DF
-:10D3C0000AC3F9B377D51B9CE731897B8F31439F23
-:10D3D000EB77DA13B97D83F94B4D9E6955CB094D37
-:10D3E000FE675501B01F50D2662BBD89CE8714BA97
-:10D3F000DC9FEE7A8DF1DEF1C0ABBB189F4FDCF203
-:10D4000031CDBBD3C2F4835D4A3C16116F3598BF52
-:10D4100050E4EF698D7F7EE8B1BD4594FF38F4CAD2
-:10D42000B822CAD32E94FD877E9DC9F79CF6DF866D
-:10D4300070CBCEF7392F1EB9DEA87B0C92D0438D6E
-:10D44000B48F64BAFFE37AC7CE722EF4C3810D8520
-:10D450008C3F351F3D7064E878505DA73ABEBA3EF8
-:10D46000757CB5DDDFEC225FD06FF41791FD5F4175
-:10D47000E73061FBEA8FF717255AE8BB55F81349E7
-:10D48000580EE3B77FF5BC2AF27C6AF05C56C947B8
-:10D49000EDD3ADFD9911F9AFAFE321833B5CEF7E96
-:10D4A000CF732A75BDEAFDDA7EAB85FD9B937625A9
-:10D4B0001F9F0EE9D40EEB1D3EF2BFB7981CE4C7C8
-:10D4C000279A5C908BF86934FAF8FE9ADA2FD1E447
-:10D4D000E6EF9179F9814423D0BDE58154E5FCF76D
-:10D4E0002B60BD4271E8169CB7AC56D7BCC512D2B2
-:10D4F00087AAFE2C1B87DF0BE81EA93EE42720DF4E
-:10D5000094156BDB87F6A32DFF7BAEA06359B26E3B
-:10D51000C838B92457C8651B74C8429E851D9DA88C
-:10D52000E01D0DBF1CEED7AC52F4FC40BCD9430744
-:10D53000BB13B78A7BAB13F5BEED04510B404B1206
-:10D540005D99F489F1BAB4FA9C6CC81CB6CBE3D8E7
-:10D550002E4F50C87DB7D4CCF75B43F75CFD32C18A
-:10D560008B21C8D009563D412403C34BC0C5702A46
-:10D570003433BC0CDA195E011D0CAF023F43F8894D
-:10D58000AF0DD81EDC6E65FFE9F2253AB2CB65D748
-:10D590000EED97CF52F0353C3E50CB579C3B3EA60C
-:10D5A0002AF77287C5CBD87CE67B152F26E24FEC95
-:10D5B0001703DE34829320C0E34C2646CEA678DDE6
-:10D5C000C6F77E6BC1C9E5BAB3C44765C0AD77176E
-:10D5D0000C8197DAA1F9649EC22703B9C0F851E91A
-:10D5E000F548AE8DCB2ADD30504C237B104D4FC813
-:10D5F000A07596C5D61CA7A722B73F5F36538F7A72
-:10D60000B4ACB4660DA9905FE64E15E589352FD30D
-:10D61000517DFBF3978A72714DA9C1815EE8DACB27
-:10D62000665E82FAD9ADDC2737A311A07B6372B6A0
-:10D630003817762BF7CA4D72E65ABA2F66BA0D58CC
-:10D64000DFB86300FCECD722B791BCB8451C7BB3B4
-:10D6500055D0AF3AD67D4B2ED933B32FDE8674B872
-:10D66000796DDD28B29BF718C5F89FA4DAC6BD8195
-:10D67000F83299C4BD5675BF58EF89C17240B2AD3A
-:10D6800069C90CAD4B5DC759CC7BD7E9E6CD4F7767
-:10D690006F203D023607C7156314FBBE65CBC4344B
-:10D6A000F430701D565E47202E774D0B56DD91EEFF
-:10D6B0007A84C61B88137CF808D1297578E8CB7565
-:10D6C0003E943BC4F781B5DFBCEA23BDF4292E04A8
-:10D6D000C7F94DAEFB715A47932E90518AF4FB4522
-:10D6E0002C7A000521BE96909873100F6D4EF01A9B
-:10D6F000595E947736CAF9992A17038B713CC44F47
-:10D7000099CB558BEE2254CC6E7E9360A5BBBD1693
-:10D710006B689E17683D4D72B081F8E468E207C6F9
-:10D720004F596EC70AFE54F459F7B69EDBC688A25D
-:10D730000BC2E4B269DB89AFFF86746F3A66715041
-:10D74000F3903C3EB6469CE75A34FA4695D3095DC1
-:10D75000263E389CB8F5A2C5D46ED207BDD9A4B771
-:10D7600027F706DAC87D1EE8DE3B46C889EAD77F80
-:10D77000239D8B7DF9CC8CFC914010F9235E9C831A
-:10D7800073FCF48A38075FADE43DA9ECE17D8B784A
-:10D79000548D3B57F6BC2DDE8579F06F05BD2B12FD
-:10D7A0007F963E71E355C46F91EF8BD478B449698D
-:10D7B000B7A2D77B37ED27F2BD5113C5A345C3BF31
-:10D7C000376A7AA296E3D1C8F746BDB94AFE4AB194
-:10D7D0008FA0F8A14B9436B43F0BC78746AF09F72B
-:10D7E000B6FAC9350E2B95D32D0ED6C7573D0EE18F
-:10D7F000EDE18964E619559E97AD93D8BF56F15A6D
-:10D80000FCBCC949EB287E7E14FBCDE8EF8B7BE99D
-:10D810004A3E91DE12D07B83CD89C12CBA67BAB95A
-:10D820003BDF41FEF81F5A9DF00F43687D6A3C5074
-:10D8300027BF544BEF878E2DC2380B3FADEE79A634
-:10D84000CD8CE5D5EBE95510A584F313C8AF2ADFDD
-:10D85000298397C601EF43D5083B153937A5E9C0A1
-:10D8600016868F18DB08B00D910F3029F48BCD4F41
-:10D87000D2D4C7392ED0F44FA8CCD2D4B7C588F7AC
-:10D8800032E071FA0B2A42EF48129D3FD1F4830037
-:10D89000FEAD08BD17B9277EEA4E7E4FE26FE03C31
-:10D8A00045F265259AF62679AB4CFC5DFDA55E43F5
-:10D8B000CF9F52A61BF156B91BFD1C9C67429FB619
-:10D8C0003E26E001EA17B35BAFC94B986CDAF285EC
-:10D8D000794A9E622C8CD5E42906F12EF8FED86197
-:10D8E0001DF34505E4FCAABA8CF06C00AF2D1A6F4D
-:10D8F000C740F85DC7C65A1CF4966A42CFCB32C9FE
-:10D9000041AA4B8BFF51B3B5F81FEDD6E27BCC5249
-:10D910002DBED39BB5F8BEB0458BD74C8F166FD9B3
-:10D92000EB2668DADBDB6B34E5BC8D5768DA5FE445
-:10D930009DA1298F7BF17A4DFBC28E859AFAE2AECA
-:10D94000E59A7A95CF86E383F1BED511FCA603DD77
-:10D9500069F8A074E7CF35F3FD50F49F9FA7E80561
-:10D9600085FED72B76E5DDF8C3F792B84E8B157A96
-:10D970007030DF506DE078EE3D5B726D1CE905C5DF
-:10D98000DEB9147B07394F89B255941D7E71BFA251
-:10D99000649FAB36DE46F72CC4FD8A8AC3EDB50919
-:10D9A000D43EE21DD6F44A4973DE1DF92E6BA667FC
-:10D9B000AD9C20D1BD44713F31F21E84FA3EABDEF6
-:10D9C00019A339271FEEBD969A5FC278018C142FD8
-:10D9D000E8CCFC3E31DA1F726C94D95F73B3FFF66A
-:10D9E00067C9CD79A76BCCFE0CE2EFECB1EEF5790F
-:10D9F00088B7A33A878DFD3DE5FDD6006D8CDF2FFE
-:10DA0000F5CCA43CE90086BB94D7D4DFB36326BD34
-:10DA10005BC4E55B031522ACA63F8FE6B91FA4717A
-:10DA20000E48D6BB4BB1EFBB133ECF207B66A27333
-:10DA3000FE123EFF7E382FFCFC7B14EE0FF56D408E
-:10DA400067F3F079EECF258E533EA7C1AAC2E477E3
-:10DA50009D41794F2AE2B6B90ABED4B86D8E32FF25
-:10DA6000011C6229EAF3B95D7F66BCAC48EB53E266
-:10DA7000BD668715C7BF71ACA584EF7B394B1D22EE
-:10DA8000DE57E3B831F2F7B1B367BA87B522ED8854
-:10DA9000269E86979287CC5746E6C542FB16E31F23
-:10DAA000581FCB76E8C0FA74CE3F86C63FCAF985C8
-:10DAB000B9CDDAFBDDF35B3ED2F0DF02CF279AFA75
-:10DAC000404AD03006F71F7875F4D41B107FFDAFA5
-:10DAD000982A289E45BAF5E49587C60FDC97778982
-:10DAE000F01BCEB4CFCF791DBDCAFD5A759FFB5B2D
-:10DAF000F77139D01A88B8EFE4D1C4BF2A34FE09CF
-:10DB0000F2C98F0E4A231C43E57366E78B38A95789
-:10DB10007977DAABBC3BED55DE89F62AEF427B958F
-:10DB200077A1EABBDD5E099C74BF648EE47A6A81EA
-:10DB3000C4EF760FD13E9B96078BE85D635371600F
-:10DB40009E24F3BBDD23F47D8877BB459295F46971
-:10DB5000EA35F46EF7F008CF51B2D8D9F989D75029
-:10DB6000BC70D828E4A3F4C56F66D27BBDC753DD73
-:10DB7000C789BF3F95641FF3F3EB129F2B8333607C
-:10DB80009C7116EF7ABFCB13E73427F3C4B9890A27
-:10DB900047E60BBD564AB09CE8726F2EBFBBDA68F1
-:10DBA000E27757389F5317761F22F27D5CC91F4DCD
-:10DBB0003ED21F6ADE27215F9C37D3BB395A67CA22
-:10DBC000FD26F16E2EE0CFA07776740FCA45F2BD28
-:10DBD0001B9CE21D5EDEA6F0F73009F9CA3DBD458B
-:10DBE000A079A7B7B2E7C07ED227AFE5B993F353C8
-:10DBF00043EFC756C66F677FAF20DFC6F3E27A797F
-:10DC0000FFA817EE24FA9CC77C61567E79F4FFD7F3
-:10DC10006038BCF52FF63F5A90197AF716F6DEAD4C
-:10DC2000203F2CAFA7AE3F34CEE9E542CD7BA9E53E
-:10DC3000438FDD934B72867411F948599A3F63887C
-:10DC4000FED3F305FDEF4F774DA0F997378BBC60FE
-:10DC5000886FDA6FF998E8DC6319F23EBFDA3F7239
-:10DC60009F2BB7F5303E709FF3687F61FBBC8CF053
-:10DC7000A5EEB3BF7BEFA305B673DFDFF77D776E4D
-:10DC80001A81716DD2507976B43E617E9949ED3F2B
-:10DC900056AFED8F0E39E5B1BB48DED16FE954E2E6
-:10DCA0001EB2CBC417AA5DEE54E22029B083ED0268
-:10DCB000CD4B7271B7E461FBA8E63BDA24B47F94E4
-:10DCC0005770AF617B215F6871105F7722EFF94970
-:10DCD0001EF4CE58CE7347C4D73F8B75DF4478BC53
-:10DCE000F9AF35A328FEDEF2972B94384ED8AB72ED
-:10DCF000853FCB697EDA474102F36D99B2BE0A7364
-:10DD000033FBC955E091455E43C993ACDFC1F1DFF8
-:10DD1000FF011A14AFAAD043000000000000000069
-:10DD20001F8B08000000000000FFFB51CFC0F00374
-:10DD30008A739418187A351818366B32306868313F
-:10DD400030883120E46885AF7153A69F9B9581810F
-:10DD50001788F981581088D73331306C60225EFF04
-:10DD6000115104FB9E2003C351207F1990EE1466CD
-:10DD7000605805641F03E22F40BE801003830C101F
-:10DD8000FF1561603005D2C1406C03C4C745F19BEB
-:10DD90007F82807CBC082ABF1B8D9F278C5FFF255C
-:10DDA00011FCF20F08C863C33216E4C74722057A94
-:10DDB00007023729A2F28FCA33303C546060D05139
-:10DDC00082F09B91E4ED8062C7E421EC2992C0B817
-:10DDD00007CAB5286237772A50FE0450CE4B8934E3
-:10DDE000F7DCD341E5AF3484D000BC3E14E4A80393
-:10DDF00000000000000000001F8B08000000000071
-:10DE000000FFE57D0B7C54C5B9F89C3DE7EC6E92B4
-:10DE1000DDCD262121BCC22601440DB8400CA04115
-:10DE2000370F5294A8E1A1A2226C782421EF22F6A8
-:10DE3000621FBFDDF088C4521B1FC5D48B7651B062
-:10DE4000D18B3640D058175C9E458B6DE845A0D5E8
-:10DE50007A13405E06B240A5B645FDCFF7CD9CDDF6
-:10DE6000734E36266AEFFFF6FEFFDB9F1DE6CCCC35
-:10DE70003733DF7CF3BDE69B8964BE91D88713F20C
-:10DE800025FC6E25E451891092184E9B3C93C69F49
-:10DE90009409B1ED7E24EA3B99840C9E6B7046D1C7
-:10DEA000A25F08644E4B0621C9658D7546FA3D791F
-:10DEB000917DBCE808C319987CE4BABD09840C7252
-:10DEC000D3F66682BF2FE97F3FB737C69174C87912
-:10DED00085A231E1FA4A9ABC48FA7B87AABE9B1414
-:10DEE00075A6DD48FBFB51FD20B785901FC3784622
-:10DEF00042A9CB40B2E8B8785D6F2EFD3F3A0EAF35
-:10DF0000CDE85B2910221A1CB1442424262348A002
-:10DF10009DBE9F673CEDD74908A736AAC84AE74986
-:10DF2000C8B49608F57289807888CD76257BE97823
-:10DF3000577D2EE2BC570D22A49DD62792D34E6862
-:10DF40003A95C461BDC72D2306427ED5AE3F120768
-:10DF5000851B9B19245E15DC060F210E13C5AFC768
-:10DF60008CE92A8F9DA7C9C4710D21AB3D0E4C577A
-:10DF7000794663FAD8D027DB7306D0F90C32D8E99A
-:10DF800048488363A6DD91118627C72D30E73809FD
-:10DF9000C92629AEC4545A2FD140C84D84DC42F35F
-:10DFA0007523081949EC8450FC3D93BC2CCA9D0193
-:10DFB0007907E6450371C37C6332032E91E22DC6D7
-:10DFC00069CF951CE1EFF81B80DF5F782C15D6C177
-:10DFD0007D1BCCEF19E2ECF0029EDD46E7265A7F6E
-:10DFE000A5EC4C5E4AE18A46DA2E83ADBB94101E46
-:10DFF000DF4CC01FED8FCCC9D5ACD730184722B449
-:10E0000073DC05EB6471B2755A097415611DE6F293
-:10E0100075586577D919FD384924FA11ED5AFAB1C6
-:10E020006468E98F7EB19FBA9EE769BF4D42ED3BC0
-:10E0300053E93CBD4B0CCE4DF4DB60A15100F80A16
-:10E04000BC25C480FD2AF9416552A063B41A9E170D
-:10E05000CBE9F7F60E73CFEF2D06E252E872532AA2
-:10E060007C77C4CEA0E3266647EC4C6BCFF187E902
-:10E0700024D925C940EF0E4C1B0447AC00E37C4774
-:10E08000249B049C7F72A4F6FFD3ED08F1E17A375C
-:10E09000F07554DA513C203D791F8B463C88503452
-:10E0A000390CE7171CCF17AD454F434A48E3685872
-:10E0B0005F9A5F87F463A6792BE69BB0DC1ECA3FAC
-:10E0C0008BE5C9AC3E5D5EBA18BDE3555917DA6EF3
-:10E0D00003C29142705E44389650BF9B303F2094FB
-:10E0E000FF25D61FCAEAF7B71F25EDCE0D9EC2F950
-:10E0F000BF2E3B009FC2DBD6C0AD942E0E6E107CAF
-:10E10000269A0FEC8C41FE757EFD0C9F89E267D745
-:10E1100038930BEA9FDF9883F9BCEDEFDB245A5E5E
-:10E12000B55D94206FD879D6D641F15B636A7FFCE8
-:10E1300066FA3DB85D242F6077D3719F9DE2B448A5
-:10E140003E63F9922896ADDAB06B1EC02D6B339109
-:10E15000280AA7EACDD23B6FA6F9D20332812A550D
-:10E160009BEA8C83697E894F6881FC8A9D1F603F92
-:10E17000DDB9A40CF6F739E05B942F75DBDA93EE8A
-:10E18000A6DFCB7D5B0AA07EF966C1094B5CBE7E33
-:10E19000D78700BFBC551E2152F815CD31C4A1DA76
-:10E1A0002F79DB17DF09E3AD7A472694ED91B2AB07
-:10E1B0000F199118A44623E0B56AD31346E09BE7F4
-:10E1C0003C07B01F059F552FD37E68BBEAD70427B5
-:10E1D0004CADDAC0F8CD8537A3E6BC688179D51996
-:10E1E0004741FB371F3542BD525FF1EB510E18DF3F
-:10E1F0000663018C73FD0663898A6F5634FF5633BC
-:10E20000AE534DE903DD19BDAFE739CEB7957C3983
-:10E21000154048DF92CF3843C5879E33C421FD5750
-:10E22000348BC411811F78DFE7FB608795F103BE53
-:10E230005E4BEDC01AC2EB75C9CED74F0A66CD88CA
-:10E24000C0E71EE7F2A391CB8F27417ED0F4692E61
-:10E250003FD671F9D1E471E2F7673D93305DEF711C
-:10E2600061FABC671AA63E4F11D67BC13307D38D26
-:10E270001E377E7FC9538669B3A716BFBFE2598E8A
-:10E28000E9668F17BFBFE65983698BA711D3AD9E8F
-:10E29000264C5B3D3EACF7BAA719D3364F0B7EFF39
-:10E2A000B5A70D53BF2780E94E585F9A063CED98FD
-:10E2B000EEF61CC374AFA703DBEDF79CC1742DC74A
-:10E2C000BB2D9BE448146F36174139185FE8CA919B
-:10E2D000693EBE88E593E67A738C349FE4A6798A1A
-:10E2E000C7C195811C13CD0FAE65E5293F24B966E2
-:10E2F0009A4FF1B2F2B4B5AEDC289A4F6B64E5A345
-:10E30000D67B73A3697E948F955FB739901B43F3D7
-:10E31000D7B5B0F2B17E9267A1F9B101961F7FD057
-:10E320009567A5F9F1ED2C9FF5A137CF46F3591D5F
-:10E33000ACFD4D5D81BC589ABF29C8CA6FB94AF27D
-:10E34000ED03402E0B98CFB5E4E4C7D17CAE9DE53C
-:10E350000B86164B8E08F4B753EE5808227C86B015
-:10E36000D125517EB3D3D8F110157D64A1F0AA4B0D
-:10E37000A2FC3320934550FEB0F03A96078C641906
-:10E38000943F2ABC8DE5BB650796FF5C38C0F2461A
-:10E390000796FF877008F37B651796EF10FEC4F2AF
-:10E3A000461796FF5E3881F9FDB21BCB3B852E9652
-:10E3B00037BAB1FC49E953573EED2FDFE09E2EDC22
-:10E3C0000872DB5D8672596A49067E59CFF9FF04EF
-:10E3D00040062DAF1F644439B8F3F3AC174581D321
-:10E3E000F600C897BC04FA0585335B48047D82C2F9
-:10E3F00011FB8673CB179334706EF9A24C81F32016
-:10E40000C289EA1F9C9D5FDCA41DCF17E50A9C1200
-:10E410009C97B57FF3BAE5CB6CED78BEAC54E0D4F5
-:10E42000209CB8FE8D27204FD4C009C8A50A9CE5C2
-:10E430000827B17FE37119276BE0B88C4B1438754E
-:10E44000086750FFE0048C376BC763AC50E03C8634
-:10E45000781ED6BF79B94C53B4E3315529709EC2AA
-:10E46000F1A4F60FCE6EAB163FBBAD21FCAC473826
-:10E4700023FB37AF5C9B163FB9B6107E36219C6BF1
-:10E48000FB0767B74D8B9FDDB6107E5E43FC8CE9C2
-:10E49000DFBC7263B5F8C98D0DE1E70D1CCFB8FE86
-:10E4A0008D676FA2163F7B1343F809209C1BFB3737
-:10E4B0009EFC242D7EF29342F87907E14CEE1F9CDE
-:10E4C000BD495AFCEC4D0AE1E70F08674AFFE695A3
-:10E4D0003F508B9FFC8121FC7C807072DCCD4CA96D
-:10E4E000A470ACBDC3D93F4C8B9FFDC342F83989A2
-:10E4F00070A65238E97DC32948D1E2A72025849F20
-:10E50000F308E7B6FEC1D99FA2C5CFFE94107EAE38
-:10E51000209C3BFA37AF82E15AFC140C67F8B955DE
-:10E520001A877286CA4E27D8E7DF199AE31232C1DA
-:10E530004E6279D1EE24A0F7888A3E43DA5D22AD9F
-:10E540006FD91C37FE31A2D66B728D064ACF56AA00
-:10E55000E5A9F59AD849D11A3D2ACE15AFC9274C5D
-:10E560001BACA99F5894A6291F38E73A4DF920F70C
-:10E57000784D7E48D94D9AFAC36A7335F9E1CB6F6D
-:10E58000D7D44FF5CED4E4D3D7DCAFA93FB2718155
-:10E59000A6FC9AA6724DF9B5BEA59AFCF5CDDFD7BB
-:10E5A000D41FD3B242537E43DB639AF27181273585
-:10E5B000F909079ED5D4BFB1FD054DF9C463AF6815
-:10E5C000CA27776CD5E46F3EF36B4DFD29C1DD9A08
-:10E5D000FCAD9FBDABA99F43FE53AB6F9B3FD0D417
-:10E5E0009F6A3FA129FF4EF2273A3D556B1FAFCCE2
-:10E5F00021CCAF3288D9AF01AB11F3C6C11666A7E3
-:10E60000584B1C2729FD18772F740CA0F4033403F2
-:10E610007651CEE0B26B3AE8F7EFDDE4BEC64EBF0E
-:10E620007FCFE8BEC11E41BFA1F4269064481D06FD
-:10E6300048F5E58FCA8CDE73875C1DD549DBD7189A
-:10E6400082A3E268FE2331E73EA0C7F90603EE830A
-:10E650006891D442BD681341BBE9D1D4AC17BDAABF
-:10E66000FDB06618D5338430DC35B23B19F528C3CC
-:10E67000F83AD09BEA87D1790D2664D18A71BBBC68
-:10E680002368FB6125C9E08F3019993F24D4BF91DD
-:10E69000F69F81FD2F81FE6B7AE9DF943649D3BF67
-:10E6A00039A54CD3BFD948FBB713F290E126DEBFA2
-:10E6B00019FD36CB564CC6FE4D2965D8FFA3466AD8
-:10E6C00077A9FB8F0EF5FF8881F6EB3130BBB9C718
-:10E6D000FCD36ED2CE3FA55C3B7F239BFF4A432EEB
-:10E6E000EF3F1AE7BF6A450E9B7F4A399BBF89C13E
-:10E6F0000DF56F0BE1BF01FAFF692FFD9BD2B3B59A
-:10E70000F31F5EA99DBF89F5FF94E176DEBF05FB8F
-:10E710007F7AC56D6CFEC32BB17FA3C9ED04FA31BE
-:10E720000E89AEF5D1FEC9506A250D0472A1FD40D7
-:10E730003A3A1EFD08771AD2701CDF8B66F47625F4
-:10E740009AD21BF2332FB3C37D947352BBAA9AD3D0
-:10E750007AC5E61C23F03D2C4F2264311FEAA23615
-:10E7600011E99B3C6DF28DA4E3BDD0267A21BFE870
-:10E77000E9293EE0AF352632BF08DA492400DF3F01
-:10E78000FED99817D4F3D2A78B1BE55391FC45DE35
-:10E790005C32BA968EEF0210812A7F9CDA71601883
-:10E7A0007F48ED1E42ED9F1332EBEF236AEF41BE2F
-:10E7B00083DA7B6838933AE657F3BADE1F41C75FC6
-:10E7C00044949F0BE7792F6E290A4F62FBF7F85AA2
-:10E7D000C107EB317F790C457E783CC5DE044DBE28
-:10E7E000C6C4EA076F137C2F0808C30DF899C1E16E
-:10E7F00011182FCDCFB1B3364777DEB15FB0D17DE1
-:10E80000B466085D8B309C59C4250FA4EDEF5E56AD
-:10E810002C836BA75D1086819FB066A14C02683780
-:10E820007B134906270E3ADEFBED0CFE0C977C525B
-:10E83000ED479B239B5D45743C738A451CFFAC6987
-:10E84000DAF23FED8C7119C6D274CD53D8CFDD45C5
-:10E85000DAF27BE768F3F7B9B5792A576590AB0F21
-:10E8600094E9BF53B42481DF31F41B00E37C90E3CF
-:10E87000E1C15AD9AB59576A761B95727084B809B1
-:10E88000CE0BDB8B3DEBCF5FAECD177BB5F9856B48
-:10E8900074F039DD9CE2EB7F1CE883A6A7813E285B
-:10E8A0003E4F72FA08F3552D7DDC139A06A30F65CF
-:10E8B0001EA724B604A7D633FA58DC1813991E8A6B
-:10E8C00043F4E052D397420FF3383DFC99D34369A8
-:10E8D0009396AEEE23BED5C9B4FD036B77E13A1D26
-:10E8E000118A193DFC40A1870E0D3DB8393DE8D78E
-:10E8F0006F1EA787798F307AD0AF6707A7878EA65C
-:10E90000CB3249EBB9AE741D3479BA0EBA75B7A3E0
-:10E910001F8AAE47447A58109A379D38CD2FE46548
-:10E920003DD68BD30396A701DA09E209DBA7F7AC42
-:10E930004FF984265FDA1479FD6BDA36AC3DA9FA1B
-:10E940005ED5F2F25AB57FBBA2798B26BFC4F7A67B
-:10E95000A67E69D32E4D7E71E33B9AFA0BD71CD26B
-:10E96000E48BBD7FD4D49FBFBC5353FE60ED594DA3
-:10E97000F903651735F9FBDC7FD3D4BF778EF0132D
-:10E9800075FEEEA2A89FA8EBCF9A16A7C9CF700D6F
-:10E99000D2D437ECBCF62EA0C783EF8B04F48F4F94
-:10E9A0009DA7D1FFF9A95376429D931E07EE83538D
-:10E9B0009ED1989EF138719F9CF34CC2F442DB1EAD
-:10E9C0000BC8152A474BE0C8A674E596BA35D9207E
-:10E9D000D709CADF8A956FD4798712B21494638AF3
-:10E9E000EFC22623094C204400E1C4C7151455E5A5
-:10E9F0001D7D9437514191D0B3BCB023F2F79A27D3
-:10EA00008B87DB239C7F84F73519027A52772FE7B7
-:10EA100024950229527F276405F281AD5C4FA93409
-:10EA2000327E51B975502EB1413E30AAF6ABFA6B29
-:10EA3000A19B6C20D049BA663F97365DAFE1F704E1
-:10EA4000BCCF89406F1334DF2B9A6FD6B4EBDA2535
-:10EA5000E2B8AB819750B9FD2A297A52043E15D805
-:10EA600093326B0C8CD3F514E6DB12518FECF2343D
-:10EA7000AF85F3C7739E164CCF78DA303DE509AC0D
-:10EA80008573C0939E03981EF7B463DAE13986E973
-:10EA9000479E0E4C3FF49CC1F44F9E20A6C73C9F5E
-:10EAA000617AC4437E02700E7BCC98FEC163C7B40A
-:10EAB000DD938CE9058F0FFB51F65D5F747786CB94
-:10EAC000ED73407F11E86CBB78AC6ECDD0309DBD4E
-:10EAD000B9F223A43305CF854D264E0F491A7A0883
-:10EAE00080ED7723D04B1FE54D32A7C3DEDA472EEA
-:10EAF000AF79E1BF87DEAE7C4B7A0BD3D3101D3DDF
-:10EB0000A5F7454F1FAAE9E98AC1CEE420A7A71FB0
-:10EB1000F3736B7DBF51123BA70CE977AEDB0C8022
-:10EB2000AAA5FCDC84906998BFC4FB5E49C1B5A36B
-:10EB30001EE81B0D72EBD2E8BF8F8273874BC7E8CC
-:10EB4000E2A7F63E3F3D9DF48E7717DA43253EBAA5
-:10EB5000E80911C61BCDF01A6520D3C878421A46C1
-:10EB6000BEE45C90817989C4437B9F734684F33A09
-:10EB700042756BC06F5F785D69BD3216E09D7AF6B5
-:10EB80001F59905EE1FA75F41E11F57C1278D109D7
-:10EB9000F80DC925933319FCF3C191463BEA09648A
-:10EBA000BA167FDEDB35F86B4855CECF1B93117F4D
-:10EBB00023AE8C1AD40FFCF5C5DFFBC2E70298F731
-:10EBC0007F033EFBE28F7DF145E272BCD646E7DF74
-:10EBD000BD73CCF8C71CC007BF1ADFCA799C7E3C46
-:10EBE000F992F4B5E8B83B49A1E3F614885BD82460
-:10EBF000DA11FEA5D66B62615D4270FA584FE1ED05
-:10EC00003FA780BD7F3E550B2F4B07EFD281176D7D
-:10EC100060772D4D5ED87032C23A2869554B5D83BE
-:10EC200045AD87B669F3971A85692D382E47ECEC08
-:10EC30003120276A1B18DF5E8EA90267697209F608
-:10EC400073AE393D96D97B3EC60F36C721BF38E734
-:10EC500029C3FAFFECF1F40647190F21ADE484193A
-:10EC6000F8312D4BEFBD7EAFF42CFDC588E7DD7E7E
-:10EC7000F90AE88966FADF9760771009F30ADC9AE7
-:10EC800016D16BBA01BE6FD6F447DB399433E22F4D
-:10EC9000D3BE6ADF48E49442B7545ED483BD80E7B4
-:10ECA0009B4B1AD47A5955CB7735F99AB6471AD473
-:10ECB0007A5C05FC83F25F522B484037959C8CBAF6
-:10ECC00025CB1A818EAF18824F808F08AC5E95B924
-:10ECD000C3E8A69FCEB7B275EB6D7CE73CE65488DF
-:10ECE0003B283337E2397259CBB5F92067CEB7AE3E
-:10ECF0004C02F95B215EFA5E5184F6BF94042E5FEC
-:10ED0000E4A056CFE7F441285CD5BCE9CF12C21786
-:10ED1000CD7719985F460FB78DCB91BEF053BDF9F3
-:10ED200050C1CD8E9E78AA6EBB6874235FA4FFCBC2
-:10ED30000AE349C15FB154D426D171973777A2FF56
-:10ED4000E28CEC1DF583AFE0973DE767493E15A3E4
-:10ED50009A9797B4433F0B26F18E88E3DE0F281F66
-:10ED60003FFB5B99001F225769AD2C74CD70BBC768
-:10ED7000400C5961BB67416B4521E0FBECEBD3D103
-:10ED8000EE5B448A6CB80EA4310BEC9CF3C480712A
-:10ED900055E7C91F6C1354EBF0B164E478A65C30FE
-:10EDA00089BB3410BE7B10D85FA639F5EDE258F868
-:10EDB0002E297690F025CA15B780F11773D8772FD2
-:10EDC00031D701FD527B4A63AF517B4A93A7F6943A
-:10EDD000265F426626413C45C9D332F10988274D5A
-:10EDE000F941C98EE32B25B5F5A01FFD9CFBE1166B
-:10EDF000D8893484CA87AA379ECB2AA6F3E9929889
-:10EE0000FF4B890F584265C5205A5E5EE633BA2C27
-:10EE10003DE777A275C23D94F3033C160770BFD15E
-:10EE2000C7E26B8843CAE2AA4F5AEFF31FD82ABA47
-:10EE3000A26C508F7E57C69BFAF5E7AF9F2F214FEC
-:10EE4000E23CCA9B67601C568F78073E1FB9597019
-:10EE5000F922EC27511634F12E0932C39FE2D71A5A
-:10EE6000AECB5F0F7995DF6BA2AEFC1BF39701442D
-:10EE7000C35F8A25F7703991F113C0BF2005717FF8
-:10EE80007D63F8C93DE05F2FDFF84F843F54BBEF4F
-:10EE900029FC89FFD4F18FE831FEBC48F0ABDE7865
-:10EEA000F57588772CFFD5CF6C84EEB7B35263929B
-:10EEB00093AE7BE5A6D53617F01DC96B837D71D661
-:10EEC000274E8B440FDF9779DC1F715904F0BBC2CA
-:10EED0003F29FC73AFFCF84EB0A3AE6C92EDE84F47
-:10EEE0006D36054C949EAB5B971492B198EF64F924
-:10EEF000472F02FDD7B4C9C7D5745AFECB9F254111
-:10EF00007C10A5942186644803689F546FFCB80068
-:10EF1000F48D1A12C4FDAA6F07FD7F168FF2B0D8C8
-:10EF200018DBB31C1D3449D09EFD6A5A7F7C51B456
-:10EF3000417ADB69E06FD4B244BF90BE5D19B73B44
-:10EF40002A64EB00E4AB13C944E0AB0A5E888FD9B6
-:10EF50001D2B5F7E666C271D57D7C6DFDA0415BEF2
-:10EF6000147BE952CBC25FFCDAD13B1FBF40F7A351
-:10EF70005ABF55E494A38DDB4B7E9656CA011BC441
-:10EF800073556E909D5EFAB9F2D5175F7A16FCD96B
-:10EF90007F34394752F815AFEE3B7213CD576C9161
-:10EFA0000714B2695884A4F0FAD4D0FF968F0FAF3B
-:10EFB00047F9B67D46C718F6FD87F1E175A9D8B2C5
-:10EFC000CB48C6F4C4475ECB2E638725C2FAB4741F
-:10EFD0001680FEB7F2E5BF1A81EF9DDD299081A969
-:10EFE00011F0B9611FEA8780275C4FBE5EA1F5D39F
-:10EFF000D5AFA1EB027246BF5EFA7A859CBF005C7A
-:10F0000088B3A1F4FDDAAF210EEE4F2627E0A1EC84
-:10F01000B5876C309FD3522DA3F3E7562701BF2B42
-:10F0200093BD49764CD9F7B2E71F46FA2B3DF470F1
-:10F0300012F357BA061950767A07C13C17AFBF1BB7
-:10F04000E75942DC488765CF89453E9A7E2A916917
-:10F050005B22EC934B7C9F9C7E812E2E9DE7694525
-:10F060002EFC41E472E1BBE80F7D98CF856A909851
-:10F07000FFD4CCD6EB806CD0C8D110FD6E7C14E5EB
-:10F08000C7B961AE8170EE561396172847C4435333
-:10F0900007B275627207DB51B99307DFA17EBBEC43
-:10F0A0008A1AAB69877246E97F19EF9F8E3B1AF483
-:10F0B000B7D34991ED91E146850F503D434567AA8D
-:10F0C000FDCEF6FFC606B6DF95FDEF9B310DCAFFFC
-:10F0D0007298ED23680772978E2B3010CB77CD1680
-:10F0E000903F984820D23EDF28F37DAE2DD7D30B3A
-:10F0F0001DBF24C4AAE806FA89C77540795FF234B7
-:10F100006DAFE2A335D0AFAD275C651F97727E70FF
-:10F110001EF8C1F5617E40D627F62B5EB452F6BDCF
-:10F12000F42CEC5FBA5FBD0ED8BF7211CCFF93CD4B
-:10F130007B8EDC4FF7ED272DCABED5F255FDBE2DD7
-:10F14000DBFA30C69FEBF7ED27436B49C47D4BBF1D
-:10F1500047DCB7433BFE47F8AA82C724A396AF2AF1
-:10F160007CB2377CEAF9E416D98178D5F349FA3BC9
-:10F170004CB27AD2A342870AFD95FF47D570E0478B
-:10F18000213A55E83044A70A1DEAE7ADC5A3BEFC05
-:10F1900023F02D527A297A53C6F3954A3F8B03A662
-:10F1A000EDF60FC9447CB950CC91C6FD4306A8F3D7
-:10F1B0003E5DBE4557DFA5CB17E9EABB75F95A4D51
-:10F1C000FDCAB63D46827410D0D41397FF3B393147
-:10F1D0002112DDFA98BFA1F5A211EE39D45882D8D8
-:10F1E0005E5E41BC101F19DC21E2B95137C5713D8B
-:10F1F000F83736A7FABC948FAC8E627E856E7BD0D2
-:10F20000164FD3D5712C1F4C34D6031F54BE07A301
-:10F2100098DFB1BB28688B53D95B9D7E11F9788745
-:10F220002FF2BD0D2A6970DD3B7AB9D7A19C8F758D
-:10F2300047DBC6627FD1293EA0C7A9A2256539F860
-:10F24000A11A4527E8EC8BEAEEB5C17955B73FFD29
-:10F25000AE39F4FBE27744168EE37549835476D0D9
-:10F2600019E25D972D405CF05AA49F857E66172DAC
-:10F270005A1B793F94F37625966546E0BBD40E3948
-:10F28000AE3EEF51E094ADD77DF74FE7FBA611ED11
-:10F29000FFF28DDA7237B79F7F64E4FC671C19C7F1
-:10F2A000ED57E6BFE17C7BAA9871D71CBA3EDD071B
-:10F2B0004462A2F94B7E11D7E7D266C107FE37E25E
-:10F2C0004DC4FD574D8246F57D882ED85FD7F4CECC
-:10F2D000C7BAB6FF39EB074047AF7F30F6DF69DAD0
-:10F2E000F5FA1F47BD05F9378EA67C407AD6CFDBED
-:10F2F0001985F102DD3BAD48FFDD3BDE4BF901E452
-:10F30000DF3439619CDD3BFF3A16E8A97B85A90C07
-:10F31000F860F730E6BF5DB9E3AF633B50FEAEC2C5
-:10F32000756C361A999FC9FF8F8FE0DEC2253F9D0D
-:10F3300015E8173CAEBEE6D7513E82F0FF9AA5BE57
-:10F340000FF46DE753CDE343BAAD64CE56185F1C9E
-:10F350008B7FA8796BF28B75B4FFAAD65DC685B496
-:10F360003CEFEDCFC7621CFD56A6375D903B9E87F4
-:10F37000F8876DC6EFAC94299E2FC026A346F65D94
-:10F38000A63579B08F7AE2E573F4A7F5171FEF1A67
-:10F39000997DFDAF8F0FC1C5F89FD5671660DE7FE1
-:10F3A000FBE803F4839A902E95F97ED25287FA4CAB
-:10F3B0005FF33EFBBF860EFA3B6F21D09F799B4DDA
-:10F3C000FFDAEBFDB8D181EBA2DF073DE97CC7F79F
-:10F3D00030FFAAD589E3ED27BD8F36FD3FB6EE5B42
-:10F3E000E9BADBFA9EF777FEC5E7DDFBBABF338FDC
-:10F3F000AFBB1DCE536BDEFE1CC7F775F95CE9FF92
-:10F4000052BA57F4FD7643AD3D938E6F0E69B482C8
-:10F4100062715FE2254BA603A2702F0FC0F83B3844
-:10F420005F8D6057359998BFCD241858BCDADD82BE
-:10F43000E247443BEB4EAE5FDC39B40CF5903B5DEC
-:10F440003F417D8248B5ED39B47E7BEE4227C66AE6
-:10F4500092F1C7DC909F3D85E7B5F6E6EF04E21236
-:10F46000A87E7F67EEF403A0E7DEE512510FA62920
-:10F47000EABFEFA714B0EF93B4F6D07D6E6DFEDE59
-:10F4800039DAFCDD1CDE3D848DFF9E22C1077E58EB
-:10F4900053CE5389E097352D9689900A7146B5ABC6
-:10F4A000C1EEB8BB48DB7E1928672A7FE337C5E386
-:10F4B0006F43785C8A78213922DE03ED138F7CDC80
-:10F4C000EDB3C7F920CE9A484E86C77BAA9CE83791
-:10F4D000E7F6B8CCDBCB9635EDB09F659D1DAED879
-:10F4E000D3BDE19B70FB1CE1A485F12FBB44B4CFDD
-:10F4F000659D7DAEACCBD75D0F651DBFEDBA3C07FA
-:10F50000EB7263785D865A5C04F6ABCCED877C8B3E
-:10F5100093E587161176AEE8C3FAD20017F1668438
-:10F52000E3D197988B2BE09CCC3C5A407FC85D6B15
-:10F5300045940FE60C01C7553449C6F8E38F0D45D5
-:10F5400059B0DE851326567F9F0DC309F85CC2F1C2
-:10F550005E426A517F2557BFFC323B0BCE2508EA3D
-:10F56000BF4B5C84DC41EDB8926C21100DF16A1246
-:10F57000F1C68E073FB9408E6BFCE4DA3CFC6E4965
-:10F580000AC3E9AB7E6FFCE59F9DFE17E567C729BF
-:10F590009174423A12BB97D476F77C3FC3634DA572
-:10F5A000E04B43BA0BC8EAFBD30566B60FFEEB8708
-:10F5B00013904FE6FC744C2CF30764E27DC41A6E82
-:10F5C000375CF23A62C10F76C99FCECF73F36C6A93
-:10F5D000BEAAA487B81DFE9F109748D3EE7CA15108
-:10F5E000043B8B04D1FFEBCD8FC27BC5FA76A3CC55
-:10F5F00006BEAF6BD12F003F11EEAFF27994D2A6C9
-:10F60000B1F1AA755B7BC759696CCF7580DF71D585
-:10F61000F9DDB7C52FD8FD80D743511D054511E64B
-:10F620003B89E3AF70F7DFF0FEEA4C7FAA0C7899D4
-:10F63000992F6ACEF99D66EECF984026C0B80A771A
-:10F64000DF669B0CEB724074C27DD51AFF45A33B6D
-:10F65000C2F9B11E9F001FFCF027646709E0F3C4E4
-:10F660004FA208D8D5EFF173C90CB8CF9181AE1E67
-:10F6700017F81D73CCCC4FB8CE6CC77456618E9CF6
-:10F6800048FBCD68B58F8350B5C1BCFE3AB303CB00
-:10F6900087F0764ABDC195AC5EA7D15E1D69FEBFFD
-:10F6A0008B12F87999F37B93847FBD75CBF9A935DB
-:10F6B000900BFA41BEE267D1D335C1FD71699AE082
-:10F6C00003F90DF630E60B05D41FDE53EEAFCF6421
-:10F6D0007256A17B3D9EABCDDAF7021EE7787F889C
-:10F6E000D387826705BFFAF12AF529BFBA55ED9F86
-:10F6F000BAAB6DDC6BA0DF54FB05BB8182AA963AE6
-:10F700008CB00F6BDA9E90E17CE63E07834BA4A29F
-:10F71000B1EAF8837566160FB267FCCDF3804E2E02
-:10F72000AF35812C24AE45176DC087DF33387F0F8E
-:10F73000716CDEDF8964D357F0AB0F3CF6F27C5975
-:10F740000D3715E733AB32470677DA0395BBE48113
-:10F750002A7A5A678EC772E5FBE04A07BE0F42FB62
-:10F76000C371781F3711B84F92D1D28EF76C1FA892
-:10F770008D637458D6B2CB88F954CD7B224A3FFAB8
-:10F78000FD34BB501BAFBC30AF6328E0A5D014588C
-:10F79000E68C40A793A39473CAAF29275C946EC7E5
-:10F7A000FE7F2427962972A203E3E395F602DFE7A2
-:10F7B0002A393130929C585AE71808EBB07447FA4E
-:10F7C00040D8244BDF999A14494EBCEF61E7CC47EF
-:10F7D000F97DF6EED9544EDCA09213B3A3904EF40B
-:10F7E000ED3E51F6495F724259B7FFCBFCE67D9082
-:10F7F0001311F6F7173A39718FBF18E5C43DB345B9
-:10F80000CDBDAC4FFB94133949F7615E76C644A079
-:10F810009FF7B97D7394DF0B807E405E6446D911FB
-:10F820006F7AB9D11B5FFF537FF9FAFF109E15BEA7
-:10F83000BE94DA3FA6D4487448909E97DE47F9BA42
-:10F8400000F4C8F8FAD207B99F53C7678B80CF6618
-:10F85000AAF92C6B5FED6672A1A62DF599B9B4FCDF
-:10F86000FE46D909A2F2FE30DFCD52F3DDCCA85E10
-:10F87000F86E19E3BB97FD13507FEA6D7E7FE6FCBF
-:10F8800096F2B311CE08F431676E8CE6DEDE897134
-:10F89000BFC9D806FBE53D11CF793FE67AC0C171FB
-:10F8A000BFC9047DFA493E9E797C3D2F7848793E58
-:10F8B000C55FDE22A64F576D16117FD5AD6CFF5781
-:10F8C000370B3E07CD178CFF1B9ED756EC60E7B574
-:10F8D00074068539AAF5AF78AFA31ECE092A36087B
-:10F8E00078DE0CF71E009FA51C9F25CE0A3C5729E9
-:10F8F0006DD2FAC11BA26D2F901B101EFAC3AB78FC
-:10F90000FD425310CF1D0A7F293837209FD4B6AB54
-:10F910001A71FB59B04F2A9A75DF9D0D78AE0437E6
-:10F92000D441AFAD6AD1967BF8BC178B818C6D1436
-:10F930003EF93DB3F3F478F7E8F153F62DF173880F
-:10F94000E227F39F879F25FE5D785EF075F1A2C7E1
-:10F95000475D143F1F184F32613F7E6C70217FF16D
-:10F96000BE2BE2BB4E8B9E18A9790FE5A71C2FEF8B
-:10F9700019DCF583A05EB580F54AD76FD99744F3BB
-:10F98000735BC8383866286DD2CAE390FC6F75A0E7
-:10F990007C9F5BBB4580B8DAC5FCBE6099EF097CF3
-:10F9A0003FE6C1E554DED3FA0BC79BDC705E7E28D0
-:10F9B0002A88FC53A1DF9D40BF946FFAF9384E0CA2
-:10F9C0000EE6A39C6A13ECB82F03514C6ED17582DE
-:10F9D000776DF64CFE6B015F17E65F6A63EB584389
-:10F9E000D70DF675819FE75B983EF880FF223BE7D5
-:10F9F000F4EF92D9FB380249407EE744FB5C918FDB
-:10FA000070EE9A93A45ADF1D9D8CFE37094EFCE0E0
-:10FA1000A3FFFB36EBDBCBBA2AFA4C7FD757C1D317
-:10FA20004EDD3A1F8A6A2F9C80E7728213DF0BF249
-:10FA3000C7E179D1C946F6FECD41AE1FE9F705D839
-:10FA40001FEAF77866C0C0212E7A5A14C69562BFA5
-:10FA5000694C3F53F329FD3B485F376EA986B4A339
-:10FA60005E168E7F74DF6E06B93F4DD0C449D11942
-:10FA7000E1BEFF27C097A3BE023E4936A37C79C8EA
-:10FA8000CEBEEE196624F01EDAE53532D2D1BD06BF
-:10FA9000C7916CE02F8FC904F6C7E583371E9D3BE5
-:10FAA00000CA45A48FE2F72654836BA598C5AA9196
-:10FAB000E247985C3AC1FBFF1395D7AE6B7897A0ED
-:10FAC000077BE27C70BF74B673D75407F85B320FC4
-:10FAD000AD8673CF5979F62347601D1BD8BB4FC73E
-:10FAE000D7E4A19DF6D07705DC67C7E87A019CBB17
-:10FAF00067A71E3942C7F7E09A443CB79CEB4ABC63
-:10FB000007CE31E71E149D0E5A6FE15D560B9C7FA8
-:10FB10004E1F2D12B70A2F0F9276F4EFCCADFDEEEB
-:10FB2000DDB04FCAA83C84F79CCAFC87A60E84FCB3
-:10FB30007A01DBD778DD46B8E7D9DE74D19849FB86
-:10FB40002FA1F500DD35EB59BD9A8D02BE1758E2A5
-:10FB50007F02F964C946011FC469A7FAAF99C1F5CC
-:10FB60008129D1BE9EB6A7F952680F7037C6DD0352
-:10FB7000E79335749CD87E521D9E5397D076B498E7
-:10FB8000B46FFC2EC25BB25E2070AFB06C52EAE381
-:10FB90009300DE41D909E54777FDDC08E39E47FB8A
-:10FBA0001B44E12F143BA6427DF203C18EEF2E15BC
-:10FBB0005E8BFBBA9BEF3B621FCDE21404A2DCEF2D
-:10FBC00093D4F12A25D169B89F4A96D7D5C3BC3AB8
-:10FBD000BC89A906A4A78B4690E32729BEDD547FE4
-:10FBE0003D616471307BBC278C1D2AFEB9323A1D01
-:10FBF000DB2F6ACB413EB39814613C85BB8EE92371
-:10FC00009DABA37CE057EB94ED29F07DCF6A137E8A
-:10FC1000BFF02A933B178675A07FFBF47A99C0BD8D
-:10FC2000C795EBD3D7C13A9EDE2C3BE1DC407C8EFE
-:10FC3000C51194BECAFC647BD633B8A79B197FCB91
-:10FC40007BEEEE02E0DBA5944F99707E5A3E56E2C1
-:10FC500028473EF55C14E34B7A7EA5E753658D1B80
-:10FC600022CBA1650591E5D0D07AEE378D2C9F6B24
-:10FC70008885E9BBE3C978F06316570D9BD704F478
-:10FC8000FC20BB70D01E78F3D39F81DCADB4E23B87
-:10FC900065D5927D9DC0E88300FF9FEBDFF229ECE4
-:10FCA00087B2B951F80ED929580FD8476B13F01CF9
-:10FCB000BBC4578C7857E2794B9BB4F4AEF821EF74
-:10FCC000738BC4A5965F6531C4A5AA77F447946E7B
-:10FCD000693FF3DB041FB0CAA33FEADCFF7026E6EE
-:10FCE000ED38AEE55C3F586B45BA3EFAC8C5D54025
-:10FCF000B7F37E2810D0DB89D75D0FF2B0BA497018
-:10FD0000809FB8F487AC7D296D0FE33EFA73465FA0
-:10FD100094CE1DB00FAAD73FB11FEB6F141C00FF8C
-:10FD2000E88662D427CABC22C1F28D9D684750790B
-:10FD300085F1687BBC6212EC83EA55263BB86215FC
-:10FD40007A52E8B393BFA740CCCEB1B3683B67B457
-:10FD500003F9B29E2EC53942489E02FDD47819BDE2
-:10FD600075BE2A3B618BF44D9FEC1EBD427F22D0B5
-:10FD70005F6698FEF6ACCF33023D9EF60918679198
-:10FD800007F40BF4F9B2E29F2116B51ED5177DEAF0
-:10FD9000E9B007FDC1CB58E961FA54E8514F87C774
-:10FDA00025720F8CFBA1D551388FBCFA37EF59CE95
-:10FDB000F6199ECFE5D53F9204FBBA446271400A22
-:10FDC0005EAB241637D6635C4FD71907F5677CBA4C
-:10FDD00071CC8A0EC9EDF120B7A93E4A02B49FDF6B
-:10FDE0006C7E11E32BCFBFD27927EA376F513A00EF
-:10FDF000FC6FB69200DA213EE447E5AD22C66913F6
-:10FE00002990354B65BF2B713115BFB222BECBB7E0
-:10FE10009A7C85B47DF9EB27C6625CC20AA67F7B1B
-:10FE20005F11D83988B7632CDC3B2A97587C8E5EEB
-:10FE30002FF85D34B3C3BBDE8C99037A9BD0CCDE44
-:10FE4000172C6FB95736A9FCBBFBA265A51E9E9364
-:10FE500079E93AC3FB0A303EF5FB764A5C4ED7CBD4
-:10FE60008CFECADB64D4E7CA9BB75C8078CDF263B2
-:10FE700026B4776B9A2F1AC19ECDFBD5ABEC1DC46F
-:10FE8000365113A7D7233EAE590C9820AEABB50A16
-:10FE9000CF7168BE13F32D3C1EED6BC66F55FC6A27
-:10FEA000C7EB5E8AC28A6DBFB4E17B85ED9B6C783F
-:10FEB0005FAAF9ABE3557BC4C3B534F078B83B4EC9
-:10FEC00013E48F91E3E1CEC13F28217D16AD8D87EC
-:10FED00023CD8CBFD17166457A0F35A477BDFAE981
-:10FEE000F310CFDDB5F593E761DC955F5C7E1EE234
-:10FEF0006CA88268073DA5E695F731FE5569171F86
-:10FF0000C3EDA0977F89F1C317FE687202B40B3B63
-:10FF10004EA780FE7161CBDF92202E78D98EA9E8A2
-:10FF2000DF59B63D0FDFBDEDCD9E05FAF5F5237E19
-:10FF300059BF6E7B5AF7603CD079BAEEC027427148
-:10FF40008E2D552C7ED4C1E31B37478E17EF11CF72
-:10FF5000D83AEBAE29C01F5B999ED0675CE361BACB
-:10FF60009E37F4631D37F3F8D5963BBE32AEF13CB5
-:10FF7000FC83AED7B8186D7CE8A7AD8B7FF12C94CD
-:10FF8000B526F41AD718E807FE9478F4CFA35DD904
-:10FF90003189B0DEFF81F1A4B07E850EE0D79FA647
-:10FFA00080BFF88C1C44BF44708709EF6B96EF3814
-:10FFB0008AFBE9C2F64318EF4D785CF80512FAB1F6
-:10FFC000F85DEE03AAD96865F1907C1D205ED261D0
-:10FFD000C3EF3C2E92D1B5122FD95B9CE4B298347A
-:10FFE000FE3E0B8BE7ACDAF8018F3F0CAF9B30097C
-:10FFF000D6ABF32BE350153CD8010F13D571C0914C
-:020000021000EC
-:10000000E3524371C0BA7583F5043E1E8AF3A5F925
-:10001000A110EFE9138E468A2BBFB081C50F5F9008
-:1000200023DF8F56E2826B6274FBD6D7BF78E0BEC7
-:10003000E6F175F1343FC6A1A11B055F5D5723F3BF
-:10004000F72763846F64B785EE9B540AFAFB2C4F45
-:10005000C4C07D99D64E23BE93A2D8557CBE5DDC2C
-:10006000DFD6F58A8871A2F52D7B90BFEBF9473575
-:100070003F47D18F77231F6F751B931F5D5BAD3E8D
-:100080000B85D3B5FB4DA4EBEACD9D18A7BABF797C
-:100090009BB14375FE0CF2C3A71A7FD76BBBC62278
-:1000A0003FE7EFA2E9FBD9CAF9638D3F723F359B69
-:1000B0002F6AFAA9F0B618ED96BEFB3B27B9EE05FC
-:1000C00078E7DA991E75AE459CE68BD0FFCF626467
-:1000D0006E5737323F3895A3F83E9C95BD0727DA17
-:1000E000A2512F5B669D740CDE215D6635625CCC8F
-:1000F000CA3A1E47F3236732ACF74AEBED04C6BB9E
-:100100001AF0ABB2EF65BB9B803E27271765AACFDD
-:100110006194F11B0718884FBD8FADD306827D4ACD
-:1001200024EF5018C79D697F95402EB67B987F9F1E
-:100130005C3D3102BEB74BF67D09146E7BBEE00418
-:10014000D76C4FBA67F0437E0697F61D5DBC5347E8
-:10015000E777C969403DD16A08D86915628D6A4F51
-:100160004603D7411C52125EA5C07889C73CE611F0
-:10017000703FD446A8DA0AF59C92E65D95D849927C
-:10018000EE9D15727804A5570BA757C55F6765FFED
-:10019000A6703BF0FD96B80C5207E4BBD6EA467D4C
-:1001A000E2299B0BEF3FD2DF6888938827D14EF579
-:1001B000BB50B45FCD7D3BDAAF261FE7D2E613A676
-:1001C000492723C99B043E8E02D18278889B6AE02E
-:1001D000FAB2AB70645278DC7189C41980F23B2C9E
-:1001E000788F806E2FAF7A1E168B76DC747C1A3E69
-:1001F000119BD1E135B0716ABEDB8903DF47A7E30C
-:100200003DAE1BAF266FB5707E271109F89DC5DC8A
-:100210004E38FE2F69F0BD4A2A8A4F224C64C238FC
-:10022000E93021DE2596CF83F6AFA96F07EF01EB0A
-:100230005F0B870CB5ABEFB5DEC0E5E0114B518A23
-:1002400085EE93ACE1B518B89D9D2CB84E4EA065D7
-:10025000FE01C89FD296E7615C8AD0C8E86AC45A9A
-:1002600082FB664490C755AD8A463DD56426DEA81C
-:10027000F1703F8E78E5F1D08B8F9F3F395618286B
-:1002800028690DA535DACE1FCC352CA68BD00245BA
-:1002900014FE108B6B0CF45F3FC39D6C1807D31BCF
-:1002A00056BF7728EEDA6BC16368A81BBAFFC0148B
-:1002B0006421F82E08F10EDD0F72B851C953C60E35
-:1002C000EF06344687F22E33E5F78D692C7FF3DA9B
-:1002D000A1F5F07E4DA7BDE8660B8CC76CBF0ECFB5
-:1002E000C302F19AF7D57B932FCA38476F0CE4C14C
-:1002F000FBC7B707D9FBC523ADA17BFC288F3759B6
-:10030000947C00ED8BA2D643C8D7AA5A0E61B901DE
-:10031000F2341D9E10C81B42E779BF654C41F2B50F
-:10032000145E6B71323CC1B1D03266BFA4C1C3B898
-:10033000FABDD9613C482B6ED0E1E186AF85878557
-:100340006B6FA887F755FA3B6F4A170B005FD373A3
-:100350000CF88EDBC46316F4BFD05F14CA230E679B
-:10036000432FF7BC153B85C22957D397D24EA1AB7B
-:10037000DEE8269DD8AF63EF836AE9E7DF2DAE871D
-:1003800000DE328B2BDD9688F3C77705A6BB8B8BFF
-:10039000F213C2744D2CEE09F0AEFE11CB821F5A3F
-:1003A00054FEDAE9394BC5343ADE1F0123B8313C3B
-:1003B0009FC4E5DEA851749E892E03C6D51FB1B82F
-:1003C00057403BDB9C600062CB2612F704410CF7E0
-:1003D000A3EC8FFA1DCC8EAF2F36F856B0F360FC2D
-:1003E000BB1D61FAE8D0D14790D1475B27D247B512
-:1003F000BF93D1475B5D6E343F57033BBA9104C74F
-:10040000C1BA37590A0BA461946E6282F54037B2C3
-:10041000F7B682C228C4EB3A185F8FF5E1E352E6E3
-:10042000D5DBFA361E48FB7106D899070D781EA653
-:10043000E04DA9B7C3C2E246FFCDE67E11FAA99905
-:10044000D4B11F966FEB813F605C87EDE0CC5DD04F
-:10045000DE369BAE9023DC6FE3C115F84E78237F28
-:10046000D73B9604BD20D77BC707DB3F217C80DECE
-:100470009301F8E8C4FDF20ABF6796DD26B840CEC6
-:100480000F8F61EF90BC6E6176F5BB1691A74CAFF4
-:10049000493CB85B04FB2B7B9501EB27429AA19E5C
-:1004A000FF2A5E5FD2F8DD957555E88972D218781B
-:1004B000CFE4F978F71E2DFDC4C7A4A9E029ED1EED
-:1004C000F790A245945026EE5DF010C8554A3F3E85
-:1004D0004DBB317214E02D443F943E23AD0F6D7738
-:1004E00088AD6B7C0CE80B5BF62E15F15D8E7EAE55
-:1004F0006B16BC4749EB67C590DAADB47D562C4D01
-:10050000219FC0F303797E084BD33F741A04FA7D10
-:1005100003F7CB9EE5782592FDBA996320CFF4B816
-:10052000ECE418940BCABE856754E05C5BE2E7DB41
-:1005300069C13403AC9BB28FA5A02160A5422B4DAD
-:10054000721820CEE15D8FBB08CE0B7BE33BB75F1B
-:10055000CBEE81EABF7FCEC7F38DF5EBBFF4B82FAA
-:10056000FE39E0B7CADCF1F84C9AAFBEF632FA6950
-:1005700057C454DFFC55EF68E8C7FFEED5DFC40071
-:100580001DFA3F3345BC3F35CECAE8F180670EB651
-:10059000CBE2EF0492814A1CB22ACE15CAB85E861D
-:1005A0004B9986DF51CFBA055920ACA7578A87F6F9
-:1005B00031A978AE78AB2EAE55392FBB25C0FC8063
-:1005C00059B1BE42ECEFFA74F6F7493E63FA9299DC
-:1005D000FE0FCEA1A6F27333D731FB5E1087590907
-:1005E0008DF9083F3615FD5A3944FBFE41D640AF20
-:1005F0006480F2F454849767D695A713F45B916BEB
-:10060000AEC3F94D252AFD0CE546A313F8F1F4D14C
-:1006100094FEF9F7CBF4BFE126327F86CACEB8CD7F
-:10062000715F51BE466F69C477857EFBB9383F5212
-:10063000FCC563213C1715413C801E8FB90E6195A6
-:10064000D5D113DF7AFCE9F1ADE0518FB79C0F9D56
-:10065000F9F18E9EF8D1E3237C7EE95B0BEB3075DC
-:10066000B488F24BC17B4FFCB0F5FAEDB5B49E00F7
-:10067000F442F10DF84C1730BE272B86D34F6C3A5D
-:10068000E2370B14C001480F98D7E3558FC7AC046D
-:10069000DE3E81D5DF0FF81A89FC00ED2165DDB261
-:1006A000D26BF7C641DEC4E84CD1ABA772BC50BDDB
-:1006B0001AF5E6BC442BFA9B40AF9E9A14C65B5ECB
-:1006C000151B57DE48CB0B609FFE0AFCD1B1080614
-:1006D000DFC5BC95F05FE0563C5FCAE25905DFB765
-:1006E0007EA6D593A7FA0BCE82FE3DDCE45E6505BF
-:1006F0007F8C1087E77914FFC775F8D7B6B36BF313
-:100700007A7CFC0AFE31B927DE147AABB372FD7C29
-:1007100030190AFAF2D8373363817F137F7C44BFE4
-:10072000C4C4634521389C6E919E05E20E7DB7A737
-:100730007F0B3E76904A49151FBB5372AFB3DED88C
-:10074000938F29EB3585AFC714E2DD057EA62944DA
-:10075000FA4BC81E480DCFFF792BF7B30D2143602C
-:100760009E5F581C8CFFF37986E64DD54BE83F9B86
-:10077000F79F6DB6E0FD1B1294BA42784EC3F79313
-:10078000BCC6F8F0386465BD536A09D3E7E6E2FBFE
-:10079000D9142FE4CB98F038B6590509DF0FE2E3FE
-:1007A00038DF6CF6429CDBD392FB0D2BF83D848343
-:1007B00063717E526014C83F7DF9E5B6BDD5504ED9
-:1007C000EB95603D3EFE0A91F91F823B4CBE1752ED
-:1007D0007BD753E9F64639A1D07136DC7BBD01E801
-:1007E0003E28C2B8FDFC5C65E74576CFC145ECAB61
-:1007F000AEA7F0F65D62F702F228DB817A7AFAEDB5
-:100800008B4EF349701EB4D3D3AB22CF1BF8FD5BE4
-:10081000453FBB6875BF0FEBDEC0EFE3FA2F8EBA22
-:100820000ED6E71BD3D5612D5D29F444E9EB38F4EE
-:10083000D39DF9F13A50CBDFCBBC9C04F251D1E30C
-:10084000C3FA8AEB63A8D79B3E3FDCE6EEB27E8517
-:100850003EAFE8357DD92364AF4446D371CEE3EB98
-:1008600033D7DC2EB38BC6418CD36F8856DECB7367
-:1008700044833E39AF21ED95663857AC637EF90766
-:100880006B658D3DEC86DBBED89EBD673B7FB9B600
-:10089000FC238AEF41F1F8CEADD68E86FD91147E11
-:1008A000CFB767BF062FC8C97923A3317E4EDFAF0C
-:1008B0007E7EFA7EF5FD3570FBAAC1D838DAA9D262
-:1008C0004FEC3616477D69CD93CDF0145E6FF8730B
-:1008D0009B87B8D47F6FAEA3217A4EA4F7681478B3
-:1008E0000ABEE7C2CB98E00FA895FF1EE99DDD6C1C
-:1008F00037F313F4D6EF88603EEA8386A70322E835
-:10090000F5238204F5F0ECA0CBB050630F307BB937
-:10091000873D00EFA4D07C65EB2E660FB4D4A15DBB
-:100920005149ED0A903B1BE01D90C17C401968279E
-:1009300084EC5E88AFCA867732B95D0C4FA7A537C5
-:10094000B2FA331F4F37358C00BBD59D0C2F93CE99
-:10095000B45DFBA899DA57F5A9248A50FBAAC8769A
-:10096000ED77D64EA2DC3BDE25C0BBA434FFA865E4
-:1009700072FFEDEC99B6D18F82BF81DA67B7D95497
-:10098000766F6FFBE3669B03F1D9DBFEE8B417CD0E
-:1009900004388ADF82F221E407FE28BEFFA342F476
-:1009A000170B7853E8E5F6E50BD1CE88BAE66A0A6C
-:1009B000C49365733A70DBB85F3686C1A9896170EC
-:1009C000264A6E37F4D3BDFBEA28F03BBF3BFA045E
-:1009D000DA797E2BF3DB1FF49415A9E3DB6B6D0250
-:1009E000A797C010D87F77DCB82701EC956C59C069
-:1009F000F74EFDB2EFE9F199C09F66DB57D2296649
-:100A00004F36E2FD327F5460C8C32A3DCECFDF4D62
-:100A1000F55FDC3F441DFFDC6ECDABB531F822C085
-:100A2000CFCEDC7B0CF480DEE44E58AEB804902BC5
-:100A3000E4EAA1243C5F6ADD67039F68177FE7E073
-:100A40007CEB9EA40534ADDAF29F36B0E3EA383E83
-:100A5000CE4BEDF85E53E57611DF13A1FD263D0088
-:100A60007EEBD68559ECDE1FBBAFA6C8D5F19FEF54
-:100A70001952C49C8978FF4CD137A798BD3E189F66
-:100A8000BF8EFD1DCC29BAF7C96EE5EF93E9F5CF0E
-:100A9000676CB2E22FC3F8A96576D64F6FFB2BFBCC
-:100AA000B304E253EDBF6C2920C2F8B33F4BC2EF51
-:100AB000E70FA43D5508F63D919D2301AC44F6A2F5
-:100AC0007ECBCFA7E86F2FBC7BBE9367DE6EBD3CAD
-:100AD000EB66246E2AD704D0C7DC0398D391C907EC
-:100AE00045FFBBF533ADDF55AF072B7232D73F6EF5
-:100AF000D510027877CCC2FB1307248CF7D2EBC950
-:100B0000538305BDE8C34F207D6D6D4D8F017BFE86
-:100B1000DF609F00DDB65EC6F783AA49E01E78C796
-:100B2000A9BA55B40760FC24F37AD8678A3EA1E0DD
-:100B3000A5EDEA1EF358DA7FF645837D0505F176CB
-:100B4000F02F68574FF8FDC1049067FEA084E707B7
-:100B5000D917F7C62C54F145FF55037E7FFBEA6E8B
-:100B6000EDF760FCF5D06E8B81D9CB7BF7FF3D06AE
-:100B7000F8D4DB572F21BC903ED1536F46FD3BCFBD
-:100B80002A86FCD16ABD9988D98721DE6B6A2C152B
-:100B90006B42EFFA70CE87649595F4D42B42782798
-:100BA0002E09F0D0431F56F0ACD3333EB2713D77DF
-:100BB00018190FEF5EB65D4DA8C07BC7FE18FB0A83
-:100BC00094CF4C8FEADE7BEEC9E9F0FDA0C8DE9D34
-:100BD000B82AE27EDABDB36278876ADF524E8AEBCA
-:100BE0007665D0C50B6FD1FA57F64533FFBAE4BC32
-:100BF0005E7D4F225CDFC7F11518CCCEE9BC83E1E6
-:100C0000BDA86FACCF74F5B0F7FF61433D39580014
-:100C1000E262D4FA4E23ACFFBFD98A3E67FCA52519
-:100C200006F88B97E40E21B4DFB268920B7415AC12
-:100C30002376B033B61F3018605D3237A5625CCFC3
-:100C40002BFC1C73494BA3315545174BF839D81968
-:100C5000D99B12AFFABE3296F19733FBCA7F8171EE
-:100C60001D7F34919111F4D085B14CFE6E337AA77B
-:100C70006F867AC70D78DF68EFFE5FEF877793970F
-:100C80001C738C03BFE09458B60FDA0EBE520F717E
-:100C9000C16D1F82D4A2726663B168A0FDBE451CFF
-:100CA000CCAF7798FDBDD6903F94B812609E37C503
-:100CB00032BEFDD60183E6DCEC2DFEBEEFF5B18C35
-:100CC0000FA5C632BFDAD603B9090B70FFB947C406
-:100CD000821FF064473D6C45C50FA8E86F930F6F06
-:100CE0009D3E86FE737297C10ECBED38FC8208F3F1
-:100CF000759C21244E203DF4390A6FAC1ADE5B5DF1
-:100D00000C1E1DC76ED8AF0AFEA904FE7106CDBF2A
-:100D1000D52EC5433C98827F651E4AFF8E16E2DAC7
-:100D200060C1ADE4DAFA15FE68E5EF314CB013E5C9
-:100D3000EF33205D6EB7B96E89C5726F0AE4CFECF0
-:100D4000637AD2362E4F4972F170C09FB24EF3795A
-:100D5000AA8CA7B7FEEFE7E354D2AF4BD7AFC80ECC
-:100D60002FD2CD76164FEEF006CCE91077D6968EC0
-:100D70007F9F4A15977B3F8EFF8CF6FDC2B60E8390
-:100D800001EE8F55EF10E250DDEDA7BE1DA233A995
-:100D900005E9AFED18C17D5CDEFC5DE68FA4729FB6
-:100DA000BFEB86E7EBB07FF839FB2081A693FD1BF4
-:100DB000560E41FC066CB0AFC278A2FB06D2DA46F2
-:100DC00023D0EB92652C2DE5E7D54B9ADCB83F4B51
-:100DD000D6B378C465B1A94C3E737A2586E8C1F8CC
-:100DE000DEBA4D7B8FF01F5C7E9E6D7D6A0FF44BEB
-:100DF000E9EBFB808F9BDA9E5807C355E8F5EC467C
-:100E000019E194456BCFF33DB1CCCFB8FD30A3F7DA
-:100E1000C91BE55C784F6CB297D8C1BFFDD6C64DF3
-:100E200022F0EFB7809E53D93E07797B66DF6331AE
-:100E3000DF07F9D66920E047DF6624655B54FB6273
-:100E4000EF863734FBB7BCB96E3AFAEB3BE205E00C
-:100E5000F3CABE55F0BECDE8BC0DF7FF9DBAFD9FAD
-:100E6000CFDAB7C2BAD07A4FF1FDFFD434BAFFE976
-:100E7000A7B88D7102C0D9668CFCCEDC4BDF90FE2A
-:100E8000427CB5A3075F7D2996F91F6CE9B4FFEAA0
-:100E90003B2EA1FF21343E4E374FE52B74932A00A1
-:100EA000FE1BE90A8E007C51BC023D533D7AFECC0C
-:100EB0000CDC9507243CFFE1E74B3C2E0477946A59
-:100EC000BF86F999B26FDD6FC038B2F26B57829E60
-:100ED0009F50E845FA3C2BB887C753797616F671D0
-:100EE000047EB08EE3E38AECEEEB7DFFC140CF657C
-:100EF000D46284F990F5821DD6452977AC67EFBDA1
-:100F00001EE6F094EF87BF2DBE833DDE213DCCF081
-:100F10001D34425CEB281F936344C8C5FD400CB7E9
-:100F20000F867DB684CAAFFB55F2EBACDC8874AAA1
-:100F3000E0E123CEB7AEC4B1793FCEC7E9071F5D6C
-:100F4000A20AFF8224096C3F8B02DBE722C03FBB71
-:100F5000EFA6DB90DEEF884CEF76B0B7E2E1EF472B
-:100F60006D40FA8C9B66C77B2F4F49CEA8388D7E8B
-:100F7000E4C374EFA667D0CE03FA85FDDE1BFD97B0
-:100F800001FD930874EFA374AF5A3F850E285DFCF2
-:100F90001DF0A57CD7D385720EA9E0659BEE1C736E
-:100FA000AA9DE1E9FF00528D6EB5008000000000AF
-:100FB0001F8B08000000000000FFBD7D097C54D598
-:100FC000D5F87DF366C93233994C76B230490CA01E
-:100FD0002C0E4980B0D84E08204A88C352D7A0931F
-:100FE00000094B36109556948120068B18152DB6A6
-:100FF000208385EF431B6D10A858832610112D62A6
-:10100000DCB17FA54190454122A81FED87F53BE764
-:10101000DC7B33336F26026AFFE1C7EFE6DE77DF62
-:101020005DCE7ECF39F7C56ED3313684310763AEDE
-:10103000E6018C7D8F3FBFF4978C2DA1E77337CFEE
-:101040005E712482D1CFF7F0BFBA795E50BD76C70A
-:10105000AF571CE9E7AFCFC55F52E0FF71A66789C4
-:101060008C55F147AC4CEF89B525C0FB119DD66C72
-:1010700098B466E2196384039F781983F66F631C42
-:10108000543EAA6FDED32B1FCA31CCE985A6399B0B
-:1010900033158F99B105361BAD67F927D393DDB0B2
-:1010A000DE46C6C6E3BA9BC57C72DDD93685C699D5
-:1010B000E029738F898367664F9E7BA0FFF90766DF
-:1010C0004F966D88BF3EA170BEEA18404B8CC47E1F
-:1010D0006355980CE69FBFC9E4336532B6059FC4DB
-:1010E000C32ADBA37C9B32FDEFD9F4CCA5B73396A2
-:1010F0006BCBA475C1EA5AB1EE58686497C1BCDFE6
-:101100006696B59BE1D1D51DDEE281B08F2D46EF0D
-:10111000D489993898F31A1CFF9A629DED01586A98
-:10112000ACCBA63807D092695EB68FCF9397EDEC23
-:10113000CFB2A1EE70E6B92D8C8D12F862AD30C938
-:10114000703F1C42F1C6E1D9135E17207C86501710
-:101150007A7EE2D5A81B7D66FFF34401BF2F63783A
-:10116000F9ADC1D3DB660E1D27603E554966CCCA7A
-:101170003C4B555CFF2866DBE4F03F778C622E1C0D
-:101180007F9A1857B6CBFA8FA6AFAE10FA9A867828
-:10119000AD8EE822BAEA53D06974C0BC4C19DD8B1D
-:1011A000C1FA98EEDA5EAC80BAEA71BD0048552902
-:1011B000E0EBC7F6848D33D7239ED90113CBC90C3E
-:1011C000DD67B5CDC0E1B6D130FA66E897E065B825
-:1011D00003C08B83E38535DE8AF86BDC686288D7D1
-:1011E0006F6339DCAC53D96803F4B7427F24F7C688
-:1011F000A99E035741BD31D9E850609E13862EC287
-:10120000FB89ABA08DE8C3AD20BE4FBC3AE29ADFAC
-:1012100040BB77A28EE5C08B5B8DB005A4C3BFA792
-:10122000F9362948A72DC427F3C7B2C12678DEBEF8
-:101230006918D1D5ACE22C05E976CEE658059FDBDE
-:10124000C7D8742AF3EF63D84295E813F8A0DE16E6
-:10125000808F61DE3A15E1D53BCE936C8865EC1149
-:10126000DB35E323D281CE3259241BCCD843505FE7
-:1012700009706BB4BB14164BF506730AF121632396
-:1012800008AEAD0CF0D418D55D774560FF2C5E7FBD
-:10129000A4F1EA868634C69E897135229E3E30BB13
-:1012A0001FC1F98726D5A944E782AE7F80CE7E1282
-:1012B000BDD42E2C6287F3E0F70E660EA41B904778
-:1012C000B76E06F895E83D9B705D35BD8E3E8EC3CA
-:1012D000D5B67C65F484A17BB98E782117D8C78CEC
-:1012E000F011EFAE53CBCD7EB9B3C566174CED52BE
-:1012F000265BFCFC8672EB7933973B59509A229817
-:10130000D762C77E3EA223ACC7E4FAE5D1CA62DD4C
-:10131000785F183E7E0D89EB6794CFACE57FFFF2D6
-:101320009BA1D01F7F57899F5EE3FCC4E5F5A3C551
-:101330009F26223C9093F0BDDBC51CEB973ADFEA79
-:101340008B74B95F659BA03ED864F42A31B86DE612
-:10135000B0258AF1900D5B9456CB20A8FF4B612EEF
-:10136000C0C3E97FA954AEBFD73D3E13DEAFD9A1BC
-:10137000732E857E352D0AF183B337F345001D3773
-:101380004759073118AF70B7D96580F6D34A04C9F9
-:10139000659C00D76190EB2FE8CA6882E7F52DC005
-:1013A0007F503D5D08A8C6F5EA9D316C801FBE8365
-:1013B000DE7CB41FEC00DA1B9DC8674F45F2F19F3D
-:1013C0008ACCF081108352BEE788014A6159826E4F
-:1013D000F47AC662004F5078B11CB530DBA5073CEB
-:1013E0002B7AE63500BE4675B5AA089FAC2E878ECF
-:1013F00099FDF3E9BB18ED3B4BEFD03903F4D5D69B
-:10140000BDCFAB7A80EBD0318DF52A9489319E6FB8
-:1014100010DE2346D5D5637B5CB157F540FF7CA534
-:101420006EB705E9EC1AE644B92AF924AE93B5C1C2
-:101430007259EC814E9715DA471C77B50D80FDC7C0
-:10144000B89982E349FD0D7CC662910EE35DCA4402
-:101450001867E83F18C1478EB375EF6805F93EBEBF
-:10146000638CE218104AE76B98E3B738AE779FCEEB
-:1014700089F8753433D70694137FBA620CC24BF6E1
-:10148000EF1DCBF5CA488FA7084415EE2706E71DC8
-:101490007EA36FB701D6336C9677B7D111B09FD9C1
-:1014A0008CC64BEDF4D23E520E780AB1CCB6C6D201
-:1014B00038238EB7B60D807E4975B01F684FEF7820
-:1014C0004F41B8A6D7752888CFAD7B77D17AD33A6C
-:1014D000DA7929F8EB79611774DB03561DED23DB0C
-:1014E000CAF5CDF2535C6F66C77AB2AD09FE7D2CAA
-:1014F0002FF424D7C1F86BF66675EF17E5EE952843
-:10150000E403E4526EAC91C6B9CBEAE98FFBABBD04
-:10151000B1730FD2E0F37BDFB1127FB4C4137E133B
-:10152000F77D4AF8485C48BA98ADD9375F4179B140
-:10153000A61470A684C259CA8D35B87EA21F5BF46A
-:1015400024A0CF27ED9E82D8407BA5CC1E9D1520E0
-:1015500097E47B8F2F66EE19B09061EDE55B59162D
-:10156000C9F77EB101F27DC2C0FB22919E9A2C2E5A
-:1015700017B69F56D88D38CF335842FB33065E9747
-:10158000F07A40E0333B7652B6750887930DE8F861
-:101590009948DE4F2B8FEE8DD509BB83D30BEBE043
-:1015A000F482FB08B4BF66C6723C8C74798AF49CE2
-:1015B0004EA6E2FE8617F87623DD0E1BEFDD8DF4D6
-:1015C0009FCE049D8CE774A2A5F7DB63B97C1D71E7
-:1015D000BC8B21DCF315E60E67EF54C672BB29BE47
-:1015E0006334D10FF04319CE3734B54E35A0DC66E5
-:1015F000B609A87F7E13EBA07E7905AEDD486F3675
-:10160000979BF879BED9C6E92693D307BC3F271C20
-:101610003F6D433E1AE0E7A378A44773283DDE26DA
-:10162000E0F41B01DFD0F13D77E1F8F11D3A9702BC
-:10163000830C3B60F631E83A6C01E849E45306F468
-:101640000F0BB4CFB215229FA5563915C4EB02B3C8
-:10165000FB1EDCD772948DF948CF3A5F3DBC976C86
-:101660007311FE7EB49E6867116C68909DF5402CE6
-:10167000B7E35795A1BC7EFA5B23CA5387E4BFBD8D
-:10168000B9D1E501F4F1C7507C3F120EDF5A39A7FA
-:10169000C5B75F2E04CB3980D75A8E0F6EE7C77758
-:1016A0002C50B97C08966B3DE123443E083CFCC1BC
-:1016B000ECDA84EBCCC64540E91DCDFA617B4FFAEC
-:1016C000F8C558F34FB3672FAC8F5F8C4D08D5C763
-:1016D000BA88AED7158047758BEA50610BF58BEC55
-:1016E0002EC4FFFA66C58976E1EE1695E861FDF233
-:1016F00028D29B72BD5F6E8F19C4AE8452F03F6BCF
-:101700008F257D5A1B2BE65F06BFC0FCA76DBCBAB8
-:10171000DDE6793D500EAD6FF92612E1DC3F5971DF
-:101720001D41BB4AAB8F81851478DF84BF2908D760
-:10173000C10D2A32D6F59EAD2695F0F62E8E378C49
-:1017400075BE330AD6F5A7A6D1BA407BEBEC8EAFB7
-:101750006FDD05EBAF8DE6FAB9369AEBE7D3BBCE7A
-:10176000F7417ABB76E174927BC3F49E8F03E5DC8C
-:101770001BFD0E7339CC4A6D47FBE3D42EE5FB68A5
-:1017800000A135A29F1EED0A35CAA906DB15441C2F
-:10179000F539001F845F5B14C1AF3E07F82E93D666
-:1017A0007902D7D96E31B214683F0BFC88FDE4BAD8
-:1017B0007FC47ACF845F6F9AED68B4A00BD5BFBEAB
-:1017C0006EBC201E607CD5A2A77D9C66514EC4676E
-:1017D000B3D1C510FFDE83C23E1078AB113477BAA7
-:1017E00065C8010FEC6FFD813427BE7F7AC7D948E9
-:1017F0009D19ED478F6A877DA9E95D56D487BB5B4C
-:10180000CE5EDE3980E49BC10EEB3BBBEFB0DD3337
-:10181000E047EDCF6ABF88FDD5EACD0D817622AADB
-:101820005952941A3A525ADAFEA90C22FE63280F32
-:10183000BD19CC570FFB5E3E50D0D354E640BED707
-:10184000E27BBBCD9D610FE0DBCD36B703D785F3DF
-:10185000A4E6D23EB3B03EE8CDE979061DEE6F0CAA
-:1018600043BD29ED3DB94FB4C72373FDFB93F65E2D
-:10187000F7FE73CE0FDAC768DF83EC740E742CC5E5
-:10188000735A2D2885073203F7DF4A78A916FBAC77
-:101890008E30B7AAB02FB6CD70B253CA83ACD07D0C
-:1018A000009E86F37D380F7810CF7F373BEB114ECB
-:1018B000FA0E1BDAAFB0AF91B80F5650968C70F895
-:1018C000C0EC9A8CF2FE99258CE8FAF4B3CCF714AC
-:1018D0006C7A4BBB8EE86603BB82E8FF0ADD995B3E
-:1018E000DD66E2EBB1F87E7E47A30EE56F8ECFA1F9
-:1018F00043B97A7947B34E47F4E0192FE074560F95
-:10190000EBEBDF54A7FE48BA98149E2E42F0F6ABDC
-:1019100040BC49B88D12F4300AE18632B94B7FB22F
-:1019200033C20F37C00B4BB5878EC7586706C2A9A5
-:10193000EDC5637D3A61BC9A978FDD8A70A9F9ABDA
-:10194000898861CC5F2F8F41BAFFB230BC5D737262
-:10195000719D5B0FC478AB3D8BE47B15EB30A2BD72
-:101960000072DDAD0F90EBD28EDB67E828C6F1F791
-:101970000D51D91280F359E7B02416465FC8723F63
-:10198000DA6D39007FF455E1F9E4C5FC186E47DAE9
-:1019900083FC5AB2DCB778967B8CA1E7F1F60D8E0A
-:1019A000247F4EB1C61E7AC8CEED8DA7ED5CCF81E7
-:1019B0006076E13A4FFDC5E2F342D3A9DCF7AD0C06
-:1019C000E0746ADBBB795EA0A353ACE3F69790DFCB
-:1019D000BE36D3B9AE78F0FB794B2C7EFEBC8AFBC9
-:1019E00052D8552FBC697540FFE22DBBE3BD01F015
-:1019F000BB8AE9BFEEA6EB4C9C97EF8FE93BFB203F
-:101A00003ED84B27121D5016BFF86A3CA703383743
-:101A10000D45FF14E78F3F635380DD5DBCB0C63DCD
-:101A2000262FC01F732E92F902EBFA0E231E89ABEC
-:101A3000CF99A9FD76BB259EE44D2FD60BE54D8FA2
-:101A4000F0BA48786ADB253CF70D3E9181F6C597E0
-:101A50003DD8C507ECC17EAF37167BDC6372FCF561
-:101A6000BF7DA7DEE60EF35E8B18FFAC737812DA4B
-:101A70007DC5C6D6CBC2F9E1E439530BA737CE57A3
-:101A800046E3B87F39671A1F6E5DDBEDBA9FE63F0C
-:101A9000D807AB0AB00B4BF49E37EDDC5FB06A326F
-:101AA000D46B2E3F3B8ECED9925E84DCBB8A79DB31
-:101AB000907FB5F421F1FDBEC45B2A4B45BC3D6966
-:101AC0007770BA11FC20F9430B476D39C1C83CE16E
-:101AD000CE03CF75C3359279411EDEBEC1407AFE7A
-:101AE000CDF31F4ECD037A3FB6D6605B0A53CE5A74
-:101AF000B73BED51F4A70D36D914A81F73B45E8619
-:101B00007C5FB94E75233D1C5B7B7BE27428BF0074
-:101B1000FEAD8275546E3050FBAC0D7750FB09C1A1
-:101B2000D795EB12FAA3BC7CB3FD8144C4E3ACEFC0
-:101B3000EEBF1EF1B2C568EB3F18CAAA26C53D2606
-:101B400000DE73364606D5B7E8D82CDC87C42B53A5
-:101B50003CDDCF1DB01E63DC4FC4636B881FD518FE
-:101B6000C7EDCC9229B0EF9A2167C9BEDFBD278AA5
-:101B7000F4C92B6695ECC8D6C1FFF3B72BA15EF470
-:101B80009DDE49369EC0F358816786CE40A08F8A7D
-:101B9000085E2F7A514F766891452578B7825C1D93
-:101BA000434ADE651E0BFD7E21DF5347AD1E0EFD51
-:101BB000C6C61818EAA15FB4CE2966A0277F794E61
-:101BC000FF6967C07E4633971EEDE24266086A5F92
-:101BD00011657D0AED5A184C8FFAB02822F8F9D811
-:101BE000CBAE3D81F6C4585B70BBA4BF9C38A0BF90
-:101BF000FE7EB9B17BCFE78F4C807D56EC53C99EFA
-:101C0000BE905CDE8FFBCA417CBF51DA04EFBD2978
-:101C1000A0F3E6F963CB5290BE0A14867EAE63E76A
-:101C2000C3F3E55C419F8C019EFBF9F13CD139BBCC
-:101C3000BB8E6C7F5DC1BCEE3AAEFFE2E5D90FCB47
-:101C4000AB4E3BF76F68F587967FFE53FAA378F0AB
-:101C5000AB195E0B95FF85E5C92D5CFE6AE58556DF
-:101C60005FC87569D75B7D4E0DD213CF0979E2D776
-:101C700017467AFE339E8F6BE286849E8FC19E212B
-:101C8000787987EAE95C0E76D7EDD86F80D911575D
-:101C9000084B5A66CB8A46B9D664F1DC1917E0972F
-:101CA000EADFD4A843F9D1EDAF3104FB6DE4F9F5D7
-:101CB0009E38BEFFF2385E87F32B9DFB3744799246
-:101CC000F5386F2FA333307E25CBFB85FC9076AFA4
-:101CD000B477A59D2BED597D03B767B363DD417ED6
-:101CE00033D6AF5F903F18ED74E473EFAE28DAE7B8
-:101CF000678A7B10F26915733D1417A007EB0D7C02
-:101D0000FDDAF5BC1627EC13E6263B41B6CF1C1DC9
-:101D10005E9E6F8DD353FFC2C76FCA403BEEB3B612
-:101D20009B3350CE7EA6F1FFF6C40F0F0B7E7D5085
-:101D3000E89358E1277808F908EAC0EDAE2DF0FEE7
-:101D40008AC56EE2ABDF2EBE91CA47172FA4E78F7C
-:101D5000C565D2FCB6C277DCD900A7232B55D217B4
-:101D6000338DEE3EB1F0DE91081DF91B0ED799C7F9
-:101D70006F33633BA3F3E5CCC7276CF206F8011F72
-:101D8000C37D0CE9799FAF09BC5E2A9D56B34E2BEB
-:101D9000EAAD6E7A3D10A2B7DB112FA7596722F684
-:101DA000AB553AFA3429A1F33FC85CAF61BF662353
-:101DB000EB8F7CD31CC5F592B6DF9B027FABD09E28
-:101DC00085F233D45F61E4CC3B825E7B5B5DEFC424
-:101DD00091BC3393DD4EEB56294EF43ECE07E7B46B
-:101DE0000FF139C689D05F976DB575C755F879C7BA
-:101DF000FD715C187F5C4FFE1FED3AEE89E770D5F0
-:101E0000FA856429FD42C7C47E16C5D982FC44E820
-:101E10000F0FE70FBA3ADE48FBDB10D5E9C5B8A8CB
-:101E2000F7667E3E4F1AE555D0DF955ADC5888FE9E
-:101E3000B07FC6713FA67DBC2719CFF1BD928D4EF4
-:101E4000F4E35C2C3F0E6876F138814747EB58D3BA
-:101E5000E18DEC03EB4AECF0141AA134C426D2F85D
-:101E600049AC6E09E20DFA1130F2DBA37C8A3C74B6
-:101E700043973C214761A591C877DBAD1E533CBC1D
-:101E80003774465D3DFAED53AB783CE284E2E96D90
-:101E9000CF0E8D1BCB32395EF0AF88BBE66F34D0EE
-:101EA000BAF2373E46F1D1FC8D57EB950039941FBD
-:101EB0006FA0FE275E9DD39BFC181F858FBF0E88E9
-:101EC000E7F462461FE1108A8786A5BF7EF13F31A5
-:101ED000AEDC09F650B03CEF173F24206FA1FA0C9E
-:101EE000C9737D3CD7237FC07C0558D31F66C87C4F
-:101EF000850DE48FDD6A6CBE06E351DE1A1D43BC1E
-:101F0000B7EFF92BC56B67CD7050BCB6FBFD7DCF2D
-:101F10002CC7F63FCC628311FE29BE8715F4CF7C17
-:101F20001BC9E3C9DF6E32B125B0A5D96F37533C69
-:101F3000784D958EA17CD1EE1B6632E8785CDBA0F3
-:101F40002BE0F8473928F10E0464447C48BC21FC9E
-:101F5000B698316EFC02AD5FAECB807EF004DCC77C
-:101F6000966B904E7A55D915F417C8755D489F4CFD
-:101F70008AFF69FAE467D4C3B7C55F9C1E9E81746B
-:101F8000AED5C35AFDDB64715562BF0BE9E1134264
-:101F9000FE4D89D7C443307E16066FC7841C0CF0F3
-:101FA0008FDF19FF23FCE31FA11C09E31F7FC6C8B5
-:101FB000E56FA39DDD36290CBFBC27E6D7ADEE3219
-:101FC000A2FE8C6F51C2CAB36CAB51C61357E0FA74
-:101FD00064FC442B8FC3C0B711FB5FDED4BA0B7B0C
-:101FE000E5C65E168DE6DB15DFC3B937CC3C6B0466
-:101FF0009F3B16308AA33AEA18C92BA8FBB893B0C6
-:1020000095F223001F4FE0B8178A639DB615921D05
-:1020100024E35686D8E0F3F89E78D9CFF547C46F0D
-:102020007A0F7AE24F625DB0FF67B05FFC02161470
-:102030009F917199F83AAF62CC4775C4C8DFDA3B1B
-:10204000CEB304F33FBA8633E753508F29B515A2B8
-:102050003CB5CF72B661FC66F929EE9F5F3E8FF901
-:10206000962A0179059E2CCA0342BC05FA07760A16
-:10207000F9B653AC1BF4E45FE3F9BA5AE203F4A4F3
-:10208000C4876E75AB4A78ED0AAFA702F0DAFE435B
-:1020900078FD19F9F29D8BE4CB0F2F856EFE7191BF
-:1020A00074F34B8C6F0C093BDF678857ED7C4067FE
-:1020B0004783F8BE073ADB7889F1D2F9E69FA8A7F3
-:1020C00042E1FA5D7C42285C5716EBFA91BC6651FE
-:1020D000CE707AD59660FE4FE791D812865C7A1E54
-:1020E000C9FA7B3B8D8867190791EBD5E68FC8F657
-:1020F0009A16250FCF9F85BBCFD339E074DBBFE89D
-:102100001C109A07C2E79D0FE48DFC39561DD0DCE8
-:102110000AFC77A6C948277595397E370AFDF77BF3
-:102120000DCCE7A0FE11D8FF0AC6FB5FD1B4BC03FB
-:10213000FD575730BD579C4795EFB91D15837C7CE3
-:10214000C55E95F2BFD866FEBC8E452C41FF744C2F
-:10215000818E3902E019EB8A628E0078C68DB7074E
-:10216000D5E53979AE9837C1DD2BE8FDA41BB382E4
-:10217000FAA778AE087A9E3A2B37A89E5E3722A837
-:102180007FEF85A383EA99DE6B83FA67374C0EAA4B
-:10219000E734DE1CD4FF18AB7B7C14ECB33FFA5B56
-:1021A000003FCCEBEAB80CD63B43ACB7EF9AF2A0B9
-:1021B000F781FD5A311E385390C917CF8DDFAB0020
-:1021C0001C6708FFCEE5BE3941E3CF55AB887E677B
-:1021D000361A8E04FA69F4AC6B4F2AC0B9C6A73818
-:1021E0005BA15EB926F8F9EC1D1BE8BDD9BEE0F68F
-:1021F000B99B83EB83DE9CD29FE701B929BF72466E
-:1022000042B0DF8785D08999E4F499B5DCFFA57ADF
-:10221000FB6AE824185FEC27D28D43D08D293998CA
-:102220006E221DC17453F9FAD6A108072DFCA3FB39
-:1022300069E8C90BFF7E00FE1667307D69E14EFB41
-:10224000837556EC50D8EF9550B8CF6A7978792AD3
-:102250000B853B633E23D71FC1ED8F68E0FD81D91D
-:10226000F318CA89B33B16A8188763E3793CFFECDF
-:102270008EAF07ED7384892FE584C497D62504F8C3
-:102280007F647CE934C619AF64171167DCFD4F84A5
-:1022900007C8008F01F3110B9C11DD71C5487F3C0D
-:1022A000492B3F6509FAE3B904D22BFE786C3DBC9B
-:1022B0003D34E60337AE53C6E564BE8ECC2B0A939D
-:1022C0009FFC978404CC0FB447E3F9754BFB7C3A31
-:1022D00077C9BC2226F202C3D8FFA44F9AF1D714C3
-:1022E000B20B762670BDFE0A8ED76D1788BC2FA95B
-:1022F000D77B1A47C6DF7A2A955D2AC513BB942877
-:10230000E75361F4CA47093F51BF85E68F7F14A8A0
-:10231000476AEE38BB07F50BC0FD636CB758406FDA
-:102320002B7EBDFDBB682BD16BD7EBAAAF2F349CA6
-:102330008970C4D8018E2D22DFAF45E4FBC9F5D6E4
-:1023400045A4BAF479D81E9CFF27E38ADAFD8DC232
-:10235000FE71FE3ABC1764972CCFE576DB690187E6
-:102360000D166E271813B99D50AB391FD53670FB6B
-:102370000CA4D7AC9680718C8916EADFDF5C684CC0
-:10238000C47184DF6579A64276C57245217BE47706
-:10239000B6D1F4FCCF09858644E8FF6F31AF1160F8
-:1023A000886563165F8F439317FE92E8FF52C268F9
-:1023B0002A8D8936E17FB65D81F4916A7619A95D2F
-:1023C0000D1FA78A4EE4FB1A29F264B47180714292
-:1023D0006EA2DFDFC4EDD2E2B18941FEFEF78CF1DF
-:1023E000C2DFAFD0EB2E9453BF1478EFC9FFEFEAF2
-:1023F000676B47F1ADF5FFAF8CE4FE7F191F08F165
-:10240000FF3BC785F5FF231EA2ED7EFEE993D82D85
-:102410009FD2503EED307AEAF1FCD5B51DEC7868DC
-:10242000EEE7EBA4B8C0C07DD94E3C672DCF64BBAE
-:102430002C486F4B18433B7F47A76E69243C5FE9EC
-:1024400065367C3E7C2D3FBF55AE7138719B520E78
-:102450005C9DC8FD8706381F5B72F1BDC96D1827EA
-:10246000583995D9510D35B2C6222BDA456B59D85A
-:10247000F3E368414F130A7751FE764217CFB70F47
-:10248000EDA793767E21E2735897E72C8FCF717971
-:10249000422211CFA9ED3A5FB8737DB2ADE86AA4CC
-:1024A000AF81BEF0E78891C24FE632BB27E2F80366
-:1024B000B7F17CD84A297F67E8981EF03E45E07561
-:1024C000CA5A9ED7C1CE7FFFBD2AED4546E333945D
-:1024D0002B95532D3EF41355B6647A695D6EC599FC
-:1024E00083F2A2E56D37D62BF3F36DE89770FD9D6F
-:1024F0002947FB91A9C9B8FCD2B3A3529E901E8F65
-:10250000A738D464416F23F1B09C40727E6534C01B
-:10251000BB72ED925D98D7F3FE1F19C59B0EA85DA7
-:102520004371B05F017016E662A967A5E4B748A6DB
-:1025300071A68A71BCFF827923FCF3FEAAE575DAE5
-:10254000CF0103F346001D9DDE798303EDEEE5091F
-:1025500011E4CF9371DA83AAE73E5242FAAE1A5CD5
-:10256000DA4D2DD136F4839CDEF9613AC64D3EB981
-:10257000E7AC05EDD87FE8BB2C982F7C7CD1BB164F
-:1025800017C0F193452AE59DDD2AF48684FB7D89F9
-:102590001CEE1F27BA1721DC6F5BFCDDD0C03C2A84
-:1025A000B63081E879B64FA5905CB79CDD1C8D16DE
-:1025B0004A77BDBA392EA82EF540B589D5853BBFDF
-:1025C000BC24E86976D30663AA03E7F7AC42FA387D
-:1025D000AEE774747C9BC5E7CDF4AFA7BC69B011BE
-:1025E000ED837FB498582BEA337D8781E749BB8A16
-:1025F00015A00B8FC0BF769D7B5E8EA6F1663EC692
-:10260000E54719CCB510E0EB69994D7241BB8F9944
-:102610009F38C625015C67AE5018FAE3B0FF22C0B0
-:102620009F67E1FD5FA1FDA5DD679937580E48F969
-:102630005529F03CBD21F87965CB6F699C19CC43D5
-:1026400079206027699E5F730CF50AD84741ED67D2
-:10265000F6669B518F6F4914F1EDA16CD8F7F0FE2F
-:10266000AE88EC184F187E92E5C9C53622D6CF1732
-:102670004750797C31A3725122A7E3AA96B7EF4461
-:102680007BA966C716238E73C9F1819613D69B99D1
-:102690005FEF96E83DAF211ED92C25284E50B3E1BF
-:1026A000AC91EC32019F52D15E8AF0003CDCC21C3E
-:1026B000ABF13C505A65F0C7E9E0FF5B72BFC36005
-:1026C000BF80DAD1913917B55FB94FB96FF9BC5AEC
-:1026D000057A0CF3BEE48345421FCDD83869792FC3
-:1026E0000051FDCE63199DFCBC49F67891C06B5139
-:1026F000C4FD648F1785D8E3EC3DDCB7A4C74AE678
-:10270000243DA2A53B4907CC6CA0F72384BDDE4D38
-:102710006F2D0F125C243DCC5C5D68E4E69BC7C85E
-:10272000ED4A6FB2F0D726A3BF16E830C83E06BA0E
-:102730000BAA6BEDF12F0D9D19281FB476B8CCE7CD
-:10274000D4C2E76022CF5F9AE1708DB30DC0738071
-:102750007B39F985F146CA10E4DBC63D7723DF6E8D
-:10276000E47CF30F410FB3923C1149F0DCB3F49ACF
-:102770001AC47FE7125306F2B367698A1A0FFD3D48
-:10278000AB1492C3A397A61811CED3970D1E877CC6
-:102790009DCB5C34FEB43816D66E189CC4E54779E0
-:1027A0009D811963082946F40B9F6A50C82F8C9AA3
-:1027B0006422E06B96C057F58AB7ADA4AF1CF06FEA
-:1027C000285E1FE03FB3EA2A091F70EE08CBC7520C
-:1027D000AF54B166630A8C3B67651BD1319C47825D
-:1027E000FAD7B29584AFEA664D7BDDD5843FD8B980
-:1027F00011CF89B53B829FF74F127682933991BEF4
-:102800003D775A2230AF71B4804FD94AC586726B7A
-:10281000FAB2B6841BA03E7DAFEA84ED74C387850F
-:10282000FA23281FEDCCDE1CF2579C713892B09F22
-:10283000C7CAED5245EF1986EDD3E23CC3D0CFD8DD
-:10284000F59185617EDFA1732A73E411950FA2FCD7
-:102850002A1B1B3429C0BE2F33D812311EE965F361
-:1028600093C53DB88840F8D446AC247EA8457E8800
-:10287000F0F3C3348C7BA1DDF3A24279846C473042
-:10288000BD9F703426C29190B9EF33909C2E6F8A11
-:10289000A5F371F9B22223EAD5F26DB1641FC1F933
-:1028A000F4BDCB86FAF1796859DE9E6418B7BC395D
-:1028B000D3A906E331F4DC19B0CE390D8724FE8E9E
-:1028C000F480BF23E1F007780B6A2F4F127249E0C2
-:1028D0008D2D8A23BD5A3AEFD59C0858D799BA480E
-:1028E000CA93ECE97CC4668CA0FC03E9BF1ADFAB99
-:1028F000DBCF44793E67570E21FC69F136FEDFD30A
-:1029000087A1BDCBFE6E6168674DCB66B74D86F67D
-:10291000DB14CE6FD3EAAF198F76C4DD495C9EBD60
-:102920000572D0D597B1B7410EBA400EBE0BF21169
-:10293000EBEF2F4EA6FA878B1D547EB4B81F954738
-:1029400084BF5FF21D1002D1ED92242E179724C987
-:10295000F8FA82643469C6FFFBDD213A1BDE676C3E
-:102960009B30369DB1EB5CC1FAF7C6A9C1FAB5D36D
-:10297000601B978CE7DB150AD9A3E5EE9141FDE1D9
-:10298000DC64C47B2BAC5F9EBF9DF486C33819E822
-:10299000F1A6E2B8A0FED737A406D59F4872D0FAB8
-:1029A000268DCF0E6ABFB9B47F50BDEC9C9131A487
-:1029B000774701F1CF0291670407778E171BEFFB72
-:1029C00075DDB0A4BB60BD5FEF33D0732D3E245ED8
-:1029D00067AC519907C69BBE06E41F2CF148E3740F
-:1029E000E2AF2F0E58E85CB2BC296F7F01D40F35DF
-:1029F00019280FE8D0B2B85568AF1D6A4AB032281E
-:102A00003DCB5561D7D88C2C40DE152D5B42F9A605
-:102A1000653E9393EC9776EF93B2EEC0F32A2E12B5
-:102A2000F9E43DD5D7AA10FE5C04DF6722E95EE138
-:102A300071B027F12AE1F44EBEAEE30A5B86F513CE
-:102A4000911FF7B90BD6716A6263850EFD15EABE58
-:102A500004929FCFAB0CE9B6749E81F20C66BFAFB7
-:102A60006EC03A53725339BE55CAA366CF98687C7C
-:102A7000D6051402FD163C6D7AEA01AEFF787DFBA7
-:102A800040DF03823E918E8EC732572C2D56A1F522
-:102A90007EFE76C2067CEE87A76F10EE7BBDC1FD81
-:102AA0006612E0EFF30ADF20926F8B1288AFB470EA
-:102AB0003F62E4F2CB8B7CA0F8E5A69FCF96927E96
-:102AC000986E70263A496EE5A7A0DC3AB2D24076FD
-:102AD00030D3BBAC93488F3E4F742CE739A2778C30
-:102AE000C3F51D69C864985F51BE52A5F30AD21F91
-:102AF000EFEFE3E7D487550FD824CCDBA07858520A
-:102B000028DDDC3E6F18E55D6AED6D597E09BCEA93
-:102B100009B04BE6ECE479812CBF533F7560E03E91
-:102B200096F1F93C0541F94A5559AF1D34EBC82ED1
-:102B30008CC173C289F754A2B313598D4393019F7B
-:102B40002775BB86DE05F52F267A8FEAA13E22DAAD
-:102B5000F32F84EB5CDDCA0C250BF3FA0FAF1A09D7
-:102B6000EF7DFEACC1496C2EECFC39CFCCEEFD43C1
-:102B7000F615D81BBDB8DDE14AC1FBCF731DCD1AD8
-:102B80007B80C3C78149200017DB6A056D377678E3
-:102B900088E5013C574FD7314FE079E0B0C8E3B149
-:102BA00024F373A8B41BA6247339335DC7E99BBD16
-:102BB000AC707A03FB2A500F48B93D17F3AA55BFF2
-:102BC0001E9072BB8A3552FE8A2399DB2FB3151FE4
-:102BD000D9DD35988902FD2B6C3C6856B5D9E4F3F4
-:102BE00065D298B640FB607A329727738CCF3E8EC1
-:102BF000E45BC93AF83E35FD3E37F82A3A3243F5F0
-:102C00004F856DC3323B8D6F70A29FB752F06B75CD
-:102C1000A3E26B253B85EB51E9579D29F4A8563F6C
-:102C200085E8258D3E9AA9D1BBAC3158CFC27AE94F
-:102C3000DEB25CAF769DEE680BC1610EAC0BF56F3A
-:102C400085C7B7A784D6AD3801A321EBA964EE31BF
-:102C5000B1B80F78DEEA085D9F765F21EB15FBD4F3
-:102C6000AEBBC2F9552BE6BB543529042FED3E24EB
-:102C70003EB4769CC44B8597C3B7A245217C7ED6D3
-:102C80006D1F32F26F4BBA61CDF02FE07D4947B036
-:102C9000AF12946F95AB411E6786D2D31CD66C459C
-:102CA000BAA961ADCB5390DF5A9BAF1F8E7E86B51C
-:102CB0006FD3F9A9D4DE9AA38B05507A73578EBFD0
-:102CC000CA4FE7178A27FC5CF0C3DDE9A59F1EE029
-:102CD0003573A3EA8A1C14D44FE43F7A098EB3BC3F
-:102CE0005E23FA6367093FE585D659ABE7F75F2EA8
-:102CF000B85E01CF9F7BDD0F27F76477853F17769E
-:102D0000DB5B1A3DFFB181FB5BA57CFE5AEF22FF26
-:102D10002EB40B3BACCEC6E37D1AB99E9E4F72BD5E
-:102D200042E87939CFD1355B295E3013ED8080F6EA
-:102D3000CF566FA578A5F1D99956B4CB8FAE99BE71
-:102D40000AF3528F364D27BD5FF97BA9F73DC64088
-:102D50007BA2684DD9FA7B908E3747525CB1A2DDD9
-:102D600023CE452067A19F630D97AB6C3597B39534
-:102D7000A81F07907EEC8BFDEEACF0F4457E086852
-:102D800027BD79E774CF9F77C2B877FE29DAE925A6
-:102D900050D85A7564CFDB5A513F56CFFFF020DE32
-:102DA000D3017BE0FD5F4B7B00AA45064F5B32EA17
-:102DB00021610754AB1B326C683708BDF11F807F5F
-:102DC0004478F8E712FCCB11FE01F1DB4F1B389C75
-:102DD000A76BE07F7825C7CBF2A66C2B9E2F3F6DAB
-:102DE000C826BBEBD3A61C82FF8C0700FEDC5F1F4E
-:102DF0006C773500FCF17C81F087F596B73B04FCDD
-:102E00009D1CFE0D1CEE6C252F6784C0D94BF95715
-:102E100077FED1E4443BE278642BD957C7B7A8AC1E
-:102E20003EC02E9376D137ACF149B4DF24FC67F76E
-:102E3000E91884F2A7F4E1D7AC8887D95B785031E0
-:102E400004FECC9544F1C7EEF9BBEDA86F115FDD30
-:102E500076D445E2A986B919E9C796D70EE039427A
-:102E60007171BF458DBC6FB623F8BE19E69295DA35
-:102E7000D1C5E28C88C0F5A469EFD37918C6BDBE70
-:102E8000CDF9EAD6F9C4E75D4179B925ACD580FE24
-:102E900036D6ACD03DEDEA0585D6428671B53A5AB4
-:102EA00087334509CACBAE5675644F5619457C44E5
-:102EB000E45524897E4929DC2F909C62A3F2742476
-:102EC000237D70DA62F4E17D2A385F25E3FCDE9D24
-:102ED00026C2DB415C13C05F350A3F33A842A4B76A
-:102EE0005B18A7D35BCC7B29AE07279775A81FA7D4
-:102EF0002D3439C9CE8D8FA1F8D2CD42DEDD625E90
-:102F0000EE463D31CD6C746109E37A31F9D7301A60
-:102F1000A687F90DBD8C74EFB034A2F3593C12DFD3
-:102F2000967CF88E0858EA95608EA31F187EDDF611
-:102F30007D5C285EFCF809F64BD74685F78B0C17AD
-:102F400070505C2EF23F9B60EC2858C7A814076FA6
-:102F500077D8B83F7A2DE0C9E2C7AFB69D7979FC42
-:102F6000B20AF3B1F9F758BC241F545D50BDCAC86A
-:102F70009F4F796243F1EA34C6DE618E8188B72AB9
-:102F8000942178EE2F8BF1617CEF3AF487DBB1D49A
-:102F900013BD4CD633AF8E970D663B0EC7FDE325B0
-:102FA000029EBF2A60AD3100F7D6D783FDF337B458
-:102FB000EA5AFB027CAFD3B7B6217DEA221C061B7E
-:102FC000CCE31EAFE4E239A56AE9C5ADB7E289A654
-:102FD000E2D5A3A0AEE3F9AC5DBFE6FE895B805904
-:102FE000116EB7EA59BB9ACBE900E1526B7778A929
-:102FF000DF3C85E237322E20F13F18860FC4E32DE7
-:10300000627D304E8315DF3786C7D77C812FCC8C0D
-:1030100046B8CF157C3757F25B5330BF3D827804FA
-:103020003E55D02E06B8DD22CA9EF8E2A1146E47A6
-:103030003F94C2CFEFF75CE27CCCDC95417979829A
-:103040005FAA4D7C7C39FF75A27C30C54EE3CBF581
-:1030500000BD7E8AE3E8400220BD1E69AC27FB6804
-:10306000160B88C365FAFB49BA0EAD77CB11DDF7B5
-:10307000581ABB6620E8955F443A518EDE626CCEEA
-:10308000A93387F69371E652D661A0EF03493F99C1
-:10309000D03F635533E535952AFC1EF4E9428B5742
-:1030A0000776E2C722BE7B06EC469CA73456A1FCFD
-:1030B000AF69317796205F975A8D7A2C3F16F1DFF2
-:1030C0005B59178DFF892D2BE60686DF4D5031E6C3
-:1030D000070BF8A4D805FBAD47F9C3EB2B5D69E4FA
-:1030E0008D12F54FF7615C66EA79A003AA1F2E7670
-:1030F000C1BCA75F15CFD991627C7EFA3E41CFDE7D
-:10310000E334DEE9C7E4F353FCF90AF9FC2B5E7FF4
-:10311000508E2FEA0F6B9E2FD13C7F82D75B9FF89A
-:10312000AAD88BF6EB684EDAA523149257462137BE
-:103130004A97B6129C4B75BB78399AB5EAF22FDCE8
-:10314000EF648ADB989280F7CE8F58500FFF33D50B
-:10315000654C817E9F2679FE86E59C498AD78872D8
-:10316000F73D1FE985921EF2278D42AE9FEAE5A644
-:10317000F7A51E8371DEC3F12F759CBB43C7F9E42D
-:10318000C78C734D6AC838477FCCBEFE9CCAE12409
-:10319000C791765171BA4BE985FC3A666490BF706D
-:1031A000EEBDCE18F44B31CC7703D0CF5DDA9C91D5
-:1031B00007E3CF7DEEC58C0AB49B84BEAF39A7323E
-:1031C00017C8A3DA730A955FB47D64C47BB335DB9B
-:1031D000DA8CE3A05F2D944501EBAA12EB047DA7E6
-:1031E0009F1CA0A78DBD74426E3CCCF3329E3BA1C8
-:1031F000477CCED5351FFD3DEAEF114AD8F8F2974E
-:10320000627F077BB81F61EEC5E551616F5734EEF1
-:10321000F314063960FCA2FAF0F902BF12EB28158C
-:10322000FA6FFA504B8403E03CE43D1E5FAF589BBD
-:10323000998BFE6263F2E804825B8F7ED62EEE6786
-:103240006DE17ED6527BC702FC4E99BB57EC83F8EA
-:10325000DDB209BF937C062C0BEF8E37C97ABF898C
-:103260006346713F18D6F37E9FF920F2CDDE286EBB
-:10327000CF4E1B36300AE5436766B4CE06FCAC4F32
-:103280002A73F74AC0F6ABC6617BA1C9D2A78CE00E
-:10329000CB882EF449EEFEB84EEC8FFE118FB1357F
-:1032A000E106D887E70D95EE037806457BC2C5CBCE
-:1032B0002FEFC5E5B9BB978DE0B15707EBCCF5AF64
-:1032C00043CE0F76FD820E18EFC8D294C10F38306E
-:1032D0001E53785DAF04FFFCB3923CA302E73FA20C
-:1032E000637DF06871B1EB182EF0711DC2064AF7CC
-:1032F00028A0B780F3DEE431D141F5A9C571CC1522
-:10330000E8BF9D9A1A54BFB1343BA8FFCD33FA07EA
-:103310003D9F68EAC8AF0BB0677BB697BC049F5A65
-:103320008B250AEDBA4F5ABEF9E016B40337AA4E00
-:10333000B45967EFDCF4C148E87506F01B477E49D5
-:1033400007F9D13E9779747A973E307E748A75502A
-:10335000BEA23CD75E6CDC68AEAD9DF2097FAE7854
-:10336000D1BC5EE2FC9BCB72513F9EA97B9FFC7956
-:103370003566BECF532F1EE2DF2D44BD02747F356C
-:10338000BE88F6E23910FCC0FF453B0E519CCD864D
-:10339000C14DB4F7D3E6E9F1FE642D94A85FC68170
-:1033A000DC8A01BAE9686303B761DE48A685DBE51C
-:1033B000E7A690BF7C6F14F7FBEC4D8CA5EF48CCD3
-:1033C0006DB886DA6BCE45D3F86FA91DE3282FFAC6
-:1033D0000585E2131353A72DC5FDEC8DF20EB81D24
-:1033E000E69DF8E7ABC723DC6AB6F17B0213D5771D
-:1033F000F2E74159D5780DBD3F51657B15B01F628D
-:10340000CEDD42E34E441B00EAEA50CB03A89755B9
-:10341000636B9F3FA0BC315A48DED49E8BA4F72635
-:103420001471FDFD7B214F0C9D7C5D63CF4DA2E7A8
-:10343000922E7CBDB282F2F70D091BF5F8BD214337
-:10344000A742FDAF3DD79F4AB9DF37FAFD91BE2FA6
-:103450006048F87A1CE68DBE11AFD8C82CD1C8E3FD
-:10346000B375C362581879D53DCF399E6F6C3AC792
-:10347000F38FFF3BCDF517E4C392459D7A8C17314E
-:1034800073840DE1555230D85111C067EAAE9B8C60
-:10349000881FC3EAB78DA8AF4D5016053CAF16F98B
-:1034A000585A79DD22E483FC8E9BD43F2C7906D1D7
-:1034B000E7AD3641A0828F9E167C2CDFEFA0330E45
-:1034C000E0713BF7F3B7A679DE4239D151C86E7C83
-:1034D0009EE4674706C6697EAEF5039E2314B21BC1
-:1034E0003B29AFBEA4C0A1C3F8C07BDD7A87F3F34C
-:1034F00085F6D126F6FD96CA16E2B86FFDF2971D45
-:103500002E18AFEDEEBC3CD40B72DECF7AF17B0B04
-:10351000CCD6751ECF87B52F473B90EF27E2E10C45
-:10352000E3A23B4D746E81768A77D4BE6C7A0AEF43
-:10353000BBD55AE1FC0AF317BD12D98A74DCF64AEE
-:10354000A41EF5C71DBD3D9F217C8A5EE93B06CFC9
-:103550008BAE16939E91FDE33A4AF2B687F55E482C
-:103560007E69E94CF2A7A781F34B99A0D372C17F82
-:103570001EC14767EB92880FCF2E8245633C759141
-:1035800032701BDA0B0E0B7D974EF2E5443C1F4167
-:10359000FBC4FEB1748FA1EA5C6C101F569FCB1464
-:1035A000FC1D47ED92DFCA059F98847D3143D0B55D
-:1035B000B45B243FB2744F622AEC63623DF0BD9568
-:1035C000E2FEF9C84F7EBA31DA90BE806E922B02CD
-:1035D000F8A7BEED2686768A29DE4D743303CA40ED
-:1035E0003B6566B79D621B9708EB2F5996A9C37B75
-:1035F0009BF2796AEAA5D17F44AAC82730B7E6A032
-:103600005D6BA88B74E27D9A33F13C1E347F058795
-:10361000E37C83BB08ED8CF94F28E43F43FB03E5D3
-:10362000D2D00375C640BFCA4DE706513C7DCAB92A
-:10363000CBA834267B2E4738949DBB5EE06BD08FA1
-:103640008A3F0E7171BF92C167726EC844BF9247C4
-:10365000453C1F4F67B64703E37D6B54F28FC9B8F3
-:10366000A4F43399F0DE4F803EFD46DF9841DFA39E
-:10367000D1FA9D0AB9FE3FB9D140FABFAAED9DA18A
-:103680003A78FE79A62B09F5C97A83A708F733673C
-:10369000B2EF3903D4E73EB8D53ADCE18767B3BE71
-:1036A0003507F56933C011FD5FCD2BD5F13E6EF7BF
-:1036B00044F3381AA76F49CF5A3A9F732E9BE07391
-:1036C000B6CE447AE82CD02D0BD04352EF48392F98
-:1036D000F58FA4EB6A3D975FD5E618CA23F3EB9DFF
-:1036E00049EE42A4BB7E3C1FD0AF779E5A3502F90B
-:1036F000E0743CE55D4BBD21F9E085C5C9944724E4
-:10370000F592E40329CFA57C97742FF5D6E83FFD09
-:10371000EFD6BFC3AF93D23C77A5027D5DABE7FA8E
-:10372000EB5ABD85E8676CFC243DD2CDC5CBD143B7
-:10373000428E1E0A92A3353DE88145A9527E5E1C49
-:103740001FCC117C33DEC4ED4894F381E3B5A68D24
-:103750007E08F7B13A95EBD99F6BDD3DC9FFD5A93E
-:103760009726FF97A45E9CFCFFEF54FE9D0AADBC1C
-:10377000C70F71A3BC3FBDF3721FEA83830CF40330
-:10378000EAC19668C726A10F485F44C5F87E481F66
-:1037900014F69EFEDFA9E1F5C1666CFFB1FA40D2D6
-:1037A00097E41BC927922FB47C24F962C26FE1BC55
-:1037B00088787A8BDF8FAAD67B9B280EE9881E8CAF
-:1037C000FCD96DC76D5388DF42F484E01F3FBF040E
-:1037D000EB0DC91F925F24FF540BFE9829F843F2AA
-:1037E000C56EB5F9D111980A90E6F908E588E49319
-:1037F000AAE7B5FAA147BA424F239B195FC790AE1B
-:10380000AAA10CA42B530FFC70F012F5C2BE8BA41E
-:10381000A7AFFEF3F4F4550FF474E6A7D053A81D38
-:10382000FB61BE03D673361FE46DA69FDE26FC8DBA
-:1038300071FB219B9F07F646F17DEE35A693FF674E
-:10384000C2F73CCF57DA033385BF41D2691ED80196
-:103850006943FCF8C7F3C0BC8B937B8467537C87B8
-:1038600011CF2733A10CB4037AB27F53D32E4DEE80
-:10387000458AFE17C2F380B49FDD6E1C90161EAF02
-:1038800003D37E025E2762A22AF92BB24B5CA3000F
-:103890003F0F89BAB74F09C2F1FA02F9FCB2552EAF
-:1038A0003DCA07D6FDDD75F477BCA5CA7ACEFE31D8
-:1038B000B09E098F32BF1F1D9E8F1D15D3ED1F5166
-:1038C00098BF7F715AD6FE95A4E71B45DE4AA79E96
-:1038D000C783443D1FEA96807A81A6BE96F7B7EA71
-:1038E0003B59603E09D28D92CBF1EC0EB01F60FACD
-:1038F000F6B3A82F6C0A43FF466DFC8657CFA25C37
-:10390000DBA1506CAA1B0EDE810407FA3E38D507F6
-:10391000EF775DC6D8CDDB78FDF6B54356792F132A
-:10392000E306DC1B32342B2ECA4728507C5999A160
-:10393000F0BE3D4DCA13B91E46F71402DE6798AFBC
-:103940007729EF77E74D67D1FBADA64B98FF8651FE
-:10395000E1EF6FAC10FDC6E4C7847DFE709ACAE14A
-:103960002FFC06343F344D690E7F9FFF09C12F1D88
-:10397000183F21784E5A85FEED0EA384B77B15C201
-:103980007B2C63417E34989FEA1BD7BA4B1AF47C98
-:10399000BB2E0DBC7E68BF77A505DB03F49B065FDD
-:1039A000A61F80F7DD61DE7704BFDFFA43F85A1205
-:1039B000F2BEA0DB59928E5D41F41EA377137DC643
-:1039C000C42B36B4A36BDC912BF1BCE0E7CFD21251
-:1039D000829B8C1384F0DFB4923103C84E12CF6FF8
-:1039E0005B85FCEBD675F7E7FC28E91AAF36015C7E
-:1039F000C9F507EFBF9C76EB2AF44F025DD073AA9E
-:103A0000EB03D6ADE5C7664D7D94867F05FF91FC3F
-:103A1000407D0070CA41F9167FC8E808A0934F04A2
-:103A20009C4E897CF28ED1DC9EECC8E2E577693C45
-:103A30002EF599A0CB53929EA202E09016443FF43B
-:103A4000F72102F64D70BA295EF2F3BD25C5C0BF5D
-:103A50001D76FEFC7FD6FE669537CD5FD78EF7CFFD
-:103A6000B5F796205CBAC7F72EDA8F76C44D026E92
-:103A7000DFADBD67BF7780C073A2FFBBAB401FF453
-:103A80003D9E6AA40F25943E5E0DA52FAFE67DFAFC
-:103A90003B043DBDFFB75079E0D2BCCFF07B10179F
-:103AA000FFBEC05BB106AFE335781DA3A997CABAC4
-:103AB0002F48FE4AB95CBEE3E1FB12E3D1AFA9D0C7
-:103AC00075243F3D3F48F43CD726E97715C1D54FD3
-:103AD000CF0FED47FA9DDC2CE9B591F4CF2494C3C8
-:103AE00023FCF5292887A8FE7009C6C5FCFAEA91CF
-:103AF0005528B76F6890FD1FA5FE372F93E3ADA63D
-:103B0000E7128F8C3D46FAEEA67CA9AF1E27B93F7F
-:103B1000A785BFEF4CFFDDFE1FE487460D5CD66A2C
-:103B2000EA5E4DFFD517D06FCB34EF2FD23C5FA9A3
-:103B3000A9AFD1D41B82DF2F9BA1101F9615F0389F
-:103B4000A5962FB5F4E14AEFB673BAF5B96226FB34
-:103B50002E88AF26D4F3FAB5E91B4B1ACC01F575C4
-:103B60009B4A385FC06C01F79F41E67A55A0074336
-:103B70000F72B320BD07B9D94FABEFF9F37FE0AFB8
-:103B80002914370AB24B76ABC1F53655ACDBBB75A1
-:103B9000FF820181F1D5E74BF05CDD631CC7DB5C84
-:103BA0003226D02E62CD25AE807DCAFEE3BEFB5EFE
-:103BB000C5F93CEBFE5CB2D18C714F11DFB4F3124E
-:103BC000F4A58AFABA56F86FC6611E2FC693A25A98
-:103BD00073E60F08D8276BEE83FB6CBB5BE5DFB7A2
-:103BE000AB07FC009CCA9883F250A73317E5A5B633
-:103BF000C5C42CFC2F786FF7DDEA42D4D30717C673
-:103C0000515ED32BE9FC7CB13BA677E24CA8B745CB
-:103C1000DF46F2B6EDFEB154EE525DCBBB6C8C2D9F
-:103C20005EF74A89F9727C1E4370BA3BFDA5922566
-:103C300040EFF7A63BE87D8FDD96B803EDED070C6E
-:103C40001437040E7892E8E741D3603C6F972DE972
-:103C50004F71B1F2C7268DC37BA4E5F719285ED258
-:103C6000A9B3919FC8F3C058CA939AB14C94DEABE4
-:103C7000A97CE5DF7FACC77BA65DEB14FA4ECD5582
-:103C80005F37FF6D10D42B1BB2E97EC6CBE774946F
-:103C900017FEE99ABE3ECC533E1C5947F9A5D09F6A
-:103CA000EEBB569E77EC2FC9C7FEAA0D53388E4245
-:103CB0003BDACF4757A84FE13DCE32AB250AF3BBE5
-:103CC0008F7EC7C8AF73F43E137DEFE653B3E7D6DC
-:103CD00035F1748F092D7D765471581580C3DAF44F
-:103CE000FD25C929D86E12F8DC6F2D033E2FD37540
-:103CF000D30FE9938A585E5FBBEECD924DB08FA390
-:103D00004FF4A57CB1840CD7BA7480D7E10CD7935B
-:103D1000548AFBD9AFFC9BC7255F3A599E88F4B5FE
-:103D200059D0F5CBE7CA1303FF6E41C5293DD1C178
-:103D30002B46C702FAEE6954BA82E76CA08338F4C6
-:103D40009BCF10E716A0E7855BC3D8574BD3B93D8F
-:103D5000D6F6DB84518E20BAFE98E4299D37A0FE6A
-:103D600062FA47A4E78E9816622E75773E24DB1D13
-:103D70004970323445FA2233D17FEA1AE7A2F34F71
-:103D8000739FC996003E14FD3FF1F2FCDF4FA03F48
-:103D90009EFB3EF1FE3F4B603C43F6AFB45ABC681D
-:103DA0005C1CB358F4888F83FAC547313FAD629DE0
-:103DB00081F440C5BA84455D287F806ED0BFA6DD02
-:103DC0009729C3C0FD183DC6573F2F199316785E3B
-:103DD0003941F2BB27BE7C37FD44C9C6013DF365BE
-:103DE000A58DCBA771EBF8F7752B8758F474BF7BC3
-:103DF000DDAB9BE81EF0BCC85CBC5751B9CE44F8A3
-:103E0000EAB458BCB62BF1BE81451F0BE5A174AED8
-:103E10004FF5190EC24791CAF411B954D23D0A198F
-:103E20003F3CB1F0D1C7311DF373E6BB7E18C0EF44
-:103E30008C8BD3E9996D2AF91FB5F1C4EAD7B71A6B
-:103E40000BD98F8827F61047AC629DE2BBE2E1E315
-:103E500089DA38E2BFD2C5BDB3EE38A281BE875140
-:103E600029E288456B155A7FE542FEBD92A238EEE5
-:103E70003F3EB218E8A02FEDDF6BCBC53C69AE7FAB
-:103E80002A99E28B805FAF5E3B8FFC9975E91C5EDF
-:103E900065E23BB087239D1978DEAF58174970AEB5
-:103EA0007C72F6074FE4E37DC089F181E76B9BA04C
-:103EB0000F189FE13D6839CEB125F7D077678BD6D3
-:103EC000C33919F3B463D973376522DE523230DE59
-:103ED00029FB552EBDBB0FEF07E76CD877D90A95A4
-:103EE0007F0F6BBB89F421F07C320BB82F3E63D976
-:103EF000EB4623D7672C79A8B0B31DFEFB6C9FC29D
-:103F000073FC0441ADB8B726E127EF5B95E9F8F7FC
-:103F1000364B750ADDC3028946F7977E91C1FDA332
-:103F20007919DCCE2DCB70D23D9EEA5526E7D24CD6
-:103F30003E4EF7BD7538E755EB3A2A28AEF9171310
-:103F4000F9576A9745BA22AD3C1FE3F9019477AD62
-:103F500037023CAA1C5C6EFC42D063AD63D2D594A0
-:103F60009FAE6707F0EF07565BB89CAC8E05B89B19
-:103F70003901E986E2F73919E553E2B8298302E607
-:103F800057443B8CE3B0FAC7DDAB630DE8A7C1FE35
-:103F9000970F4238C65D7F23AEEF5995F81A80B46B
-:103FA000AA00EDBF67D53C3C7797ADD83D0EE5F054
-:103FB000DC2D83F146052B7BEE5DD2237305FE3BA2
-:103FC000453E5A39D4F1BB81376470B9E951B9DF44
-:103FD000E806012F4907F279F50A03F7E383BC47A6
-:103FE0000153BDE4431AB7DAD2918872B87ABB8123
-:103FF000EE87DF8CEB0638972F491F7500E8AADCA7
-:104000001043DF51ADF24E3462BDAA51A1BAFFBDDB
-:10401000840CA4D32F96BD6045FA391CD99A83FA33
-:10402000A96B5EA493EE29DAB8DFEE8B653974AF25
-:104030006986ADC382DF6599B120DB8E72FCA0ADCD
-:10404000D588CF0F3667EAB0EEB2D94661DDA5BF9D
-:1040500092EA5F887C17FA41BA52389EAB9A761B77
-:10406000F1EF2FDD2BE8E2D4B3EFF6413F50754678
-:10407000471FD42F40077D5211CECF28A49F6B9AA3
-:10408000781EBCA4831AA403E0BB39820E6AB6BDB5
-:104090007017F2430DE23F37948E809EDBA9FDF945
-:1040A0000DE3187FBF1DE944EA33A82F33A03FCEAC
-:1040B000C8EB8B05FEA17D0C6FF70EE0F975DDF9FD
-:1040C00008417CD0137ED766E8043E4C2477D78A1B
-:1040D000FD76AED86E45FC9D7A76F71E8CB7543FC0
-:1040E0000FDADA11861F043C6A71FF565A3FD9195C
-:1040F000B5B85FAB7FFFDD742FF8B096F1FDC9FD59
-:10410000D6EAC5FEE573F1FE3AB1CF2A26E0B5AD99
-:104110002FE73BC167C8C7F4DD21B13F8F3DF8BB36
-:10412000BABBC5FE9A44C96CCD56840FE217E50FA1
-:10413000D08FCB28E5097439B56503E5F74B7CC909
-:10414000F5BFEFD72B2EFC9354128F9D3D7CF7B615
-:1041500045F0C9A1FB92327600FCBED84C9F0D24DD
-:104160007AD507CC27E946CE57F4A749D7E2BE61F6
-:10417000FC561C5FCE7BD01BADC7710E32CE1F72BA
-:10418000FD922F8BEAA75D3BD88AFD4E59B2D15ED6
-:1041900011787C3FC346EFBBD06E80F75D3B14F2D5
-:1041A0005F1F12E7FD43F7BD602D1FE0A7F777C53E
-:1041B000BA259DE10FFAC9E47AF7DAB93F58BB6E28
-:1041C0002987E4BA8BEEBFE15A6C97EBC7F8512010
-:1041D0009D4A384A7A95F7FAB4744B3427F5AADA2F
-:1041E000337DD7A61DA2FC9D9076ED78C23E3A2C79
-:1041F000F2CDBB9E56F97DE765C9ED41F78E1833C8
-:1042000007EA9F25F3AEB615623CB749A17B1E5263
-:10421000AFC0CF4A7D803E92F6C1F0DE3C7FA5362E
-:10422000DE7502F15975BC631C7E9244DAA5577D98
-:10423000DDAAC6A0FF6A1BCF8393745375B29DF8A5
-:10424000A15ADC932A5BF1EEC46148F74F1B28CEDC
-:104250005376DF5823DAFBB3374D1F8AE0C07B1259
-:1042600028DF4F6C1C9247E061B6C4EBF1BEC4C6B8
-:1042700047AFC7BF5F3A63874ADFA1C171908FCB59
-:10428000EEC8237FEBE1C8CE8923D0AEFFB56A43E9
-:10429000BB7EE4A6218BB0FF484BEF58FA78D0C61E
-:1042A00038AABBF431A427A41D2CF303EBC5BD90A1
-:1042B000ECDE9CAF7A75978AC80BACEF83F1F9AE50
-:1042C0000D91F4DDA852A3A3B915E7DB9944E78E5D
-:1042D0005A382625DBE99E2BD969B38C2C222597E9
-:1042E000DA233045F97543C71DA84F5EBFC33218A6
-:1042F000BF8BCBD4F343CBB97DCDE39071C1DF61EC
-:1043000092EBC8EACDE9573B9E7C7F2F9E2BEC7445
-:104310009F91DE3FB1ECE9EB511F9ED89C63C77DB6
-:104320001FDB1949F70B8E1982BFE778A9F7C2B4D2
-:10433000F7A9E43DD7FCDEC1F69CA4FB0BDECBB9AC
-:10434000ECD2F2984E2E66744FFC5C06E3FEE4E875
-:10435000EFB6627E6145A3C986F7648E20FD637C5B
-:104360006BBB4ADF01A2BBDF80AF23DBF3E83E700B
-:10437000C5C7BC5ED1ACF8F0FE72FBC3F753FEC2FA
-:104380004CB037F16A79B73DBDFAE1EB910DCE380B
-:104390003DCBF13B006736F37C8B90EF3ABCBE75AA
-:1043A0004F8AE3FFBFFD2CFD13D37B07DF4793F05C
-:1043B00096E7AA57802E0A72FDF0FB72F12CB29F8D
-:1043C0004F2EF650795A39B46A24D2B32586EE15A9
-:1043D000BCB4E35115BF7353BD6DF0793C1F8F30F2
-:1043E000C7D0F79FBE5CBC90829A2717D7893F8AB7
-:1043F000B654F8157C545EB5AD8DDEFB72475E0B8E
-:10440000DEEB7DD91CC3C59AAB20E83B9912BF3DBA
-:10441000DD5796FBFAFCD71CCF72DD9F6F9E6EC5F1
-:104420007DB5FD21AE6538E2373AC6867660A5C80F
-:104430002F39BA86DBD9C72362FEAB18F07C7CED3E
-:104440009444FC0ED1CCB6A9D7637BC54EC586E794
-:1044500003E7CE49563CCF7DA6EFB4E23DAACFD6C6
-:10446000C8FB573EFABB7B23C6B329D87F44AB9E1B
-:10447000393229844CF432FCA49EEECB7E01EDE46B
-:104480003F391F45FE13F889C37C92992F72BF4BA9
-:10449000F7F9579CFF468A7DB7F7B6CBF806B517F4
-:1044A00015F0F6636BB796D0DF4FDE68B0E1BABFA8
-:1044B000DC68A0F1E7C0B94D07EB3DBE999F83B022
-:1044C0008EE7E8139BF979674E333FEF54CF33B84B
-:1044D000F8FDD260BA2C0AE847DF2DEBE1BB23736D
-:1044E0005C7C7F73407FE27E2F44BFB1AC99EE9F2E
-:1044F0005D6A3EA9967EFFAA9117DD74DB13BD08A5
-:10450000B822FF23DD4ABA98B386C7F5EDCD830BF9
-:1045100091FE249D68BF03586F64FC3BB2BA28FA31
-:10452000EEF724B3C380FA624A7CE718044F5F07B2
-:1045300097AF6A91CE85F7E458BD29EC77C4DE15B4
-:10454000F2781ABC4BF7BB7ADBF8F7CFC47D315950
-:1045500082BE4A477D3E29DAFE8D03BA74AEFFF271
-:104560003A3DD0F5A491F63BB29D80D7F55FF37A42
-:104570009E7D7B16D43FEF7DF63A3DEC6FD295F6EB
-:104580002106A82F59F2CD7563E0B9C9E13AD83BAD
-:10459000609E139B92D2717FD07E08DBA7277A8E14
-:1045A00060592BEE8F9D56BA062DCCF4F77F7BA772
-:1045B000E5E04B0E7FBDD3C0E8BB3BA77BCBF587C7
-:1045C0002F9D0ED7A9DE09A1EDE58CDD47F97C5EB4
-:1045D0007E6F077EDC118978AF8AD35DB9BCC7D303
-:1045E000A0B9C7E3E4F7D5E4FD2A797FEA72FFFDBD
-:1045F000B3B59772FFECFF0069F3B24F0080000083
-:10460000000000001F8B08000000000000FFE57D97
-:104610000B74545596E8B955B73E492A4925845438
-:1046200025A984AA7C2B90C0257C0C3148E5030485
-:104630008858286AD4A005A2808214011D74F455FC
-:1046400061307C9AE98E9F1722462D10957178DD96
-:10465000D1B16D868F532032FC9A0EB463EB8CD3AC
-:104660001DD0D168631B3138F40C366FEF7DCE4D11
-:10467000EA562A80BEE77B6FAD975EF6619F73EEC8
-:10468000F9ECB3FF67DF5B5F192CEBA564C6240F61
-:1046900063AB53A1745A596319947BFFE9CFD26875
-:1046A000C69A83AC3B2E8FC15FA3F5D35150CF7C0C
-:1046B000BA4B502E4B481ACDC660991362D06F99F1
-:1046C00089B1AE12E8263B6DCCC2D81209FE9D011D
-:1046D000FFF9CA194B676C9515FEED44B84287F097
-:1046E0008366467F9F05983FDFC0D81F4F742539EA
-:1046F000F58C9D9D1D2E0CBB18FB65BCCFE69C0068
-:10470000ED1DCD8EA634C6BE7CC3A4D443FF9ED07F
-:10471000DF27F960FCA57AE6EF84926D1FCED824DE
-:10472000282FEAC353A0DF6157F1B68DF0BCCBA9A7
-:10473000630C9E3FEB0AE7FCF578C6822E93F232BB
-:10474000A37E773280EB1E9F3E1CFB9D7D7D5DFE30
-:104750003DB06E93CC5812EC7B068C590E7830002D
-:10476000AC2FC30742340EB40793A0BEC5F5740E38
-:10477000237C302F9BC8D80D8CEFEB0639BC1FF182
-:10478000C5946419F7379B6F0FDB83328CA33333E7
-:1047900003AEBB9875583F4D0098B18E4BC3607FF8
-:1047A00066C063329680C724C6A6EAA113ACAFE9FF
-:1047B00097FA9009D6D784781470D085237A2CD7AD
-:1047C000C3F88BC5BCCB8EBC6BC4C15810FE07EBC5
-:1047D0005922E65DDC71773D9ECB9290E14CB7C0EB
-:1047E000F525FA7F0F9DC772D1EFFEF2AD469CE230
-:1047F000FE1DDA7ECBD9A6AFF5F0FC52D66DC4FD16
-:104800002EEB8C6AEFA8F90CD7BB7C97B6BEDE996D
-:10481000988674C2C6B2B197F4544DE7BD48F49976
-:10482000AA6F74CAB89FE166C50413373D9F47F469
-:10483000C2DE0CB0C87EAC6318D14F8B4B4FE7B1D2
-:104840006497C49CE318BB7E5716734253FDAE6158
-:1048500054265DC8A0FACF5F3936DE5732705ED776
-:10486000BF6AABC6F55DFF6A1195EA3A9A041D4E20
-:10487000D5977486611DE72CB00E809B8EC0628137
-:104880007E9A6ED68718E19999B1BF572CC76B599C
-:10489000DFA54F42580E8AFD4A97243A84643C1F94
-:1048A000EF613D437A621E03B53B9979CDA55CA0CB
-:1048B0001BBB8E3963E0DF24CE2FCE19CF9CEE8157
-:1048C000763958FCB34A588761AE4109417B735C25
-:1048D000D236E43316F474E5C3730DE2B9AE384E44
-:1048E0003709EE54CDF32A1DDC2AFAAD4B9A76181F
-:1048F000E9B2C1B388E82151C9D4ACC7A45F6A400A
-:10490000FAB9D567F8A43B621CA25F58C70D5E29AF
-:1049100084FC787383B6DD50F975AD4425D4478E99
-:10492000E7D5F6FB29D203D03B107E71243D0C9CC9
-:1049300083C5A3C373F02412BDCBCCB9B912E05B1D
-:104940000E1B18EEDF14CFF7790E319786FD800F1E
-:1049500060E2758817A84F2ED7E237C5A3C5E7B028
-:104960003A2D7E867BB5FBB735E46ADA337C233596
-:10497000ED598BCB3470B6BF42D37FC4EA6A0DECDD
-:104980000ACED4F4CF5B7FA3062E68BD5DD3BFA84B
-:104990007D81A6BD38749FA67DD48E260D5CDAF984
-:1049A00088A6FF985D8F6BDAC786376ADAC71D7EE7
-:1049B0004A034FE8DAA2E97FCD07DB34ED93BA5F13
-:1049C000D3B45FDBF386069EDCBB5BD37FCA850373
-:1049D0001AB88A1DD3F4AF31FF56034FB5FEABA60C
-:1049E000FF74FBC79AF619CE3F6ADA67B9BFD1D216
-:1049F0006B3C9793D72BFFA579EE5993EFDF505F70
-:104A0000344B95DD4186F4EB243EBA354DA7840145
-:104A1000FE832A97041D9E1C612539C1F2598EB769
-:104A200014E9B0328C7C7C6E9744F2E0AB28BD2850
-:104A3000FFD1EB91A09DFD4A525E7622DD415DC41F
-:104A4000FC291E339323D639ACCEAA81877BED9AFD
-:104A5000FEB606A7A63DC3E7D6B4672D563470B69A
-:104A6000BF5CD37FC46A8F067605EB34FDF3D67B3B
-:104A70003570416B83A67F51BB4FD35E1C5AAC6926
-:104A80001FB5C3AF814B3B576BFA8FD915D4B48F89
-:104A90000DAFD7B48F3BDCAA812774B56BFA5FF3F7
-:104AA0004148D33EA97B87A6FDDA9E4E0D3CB977DF
-:104AB00097A6FF940B610D5CC58E68FAD7984F6A74
-:104AC000E0A9D60F35FDA7DB4F6BDA67383FD7B4C7
-:104AD000AB76D02CF7D7DA7A61175DAFFC59F37C4F
-:104AE000B0DAC3903E826F484AB313D6EB02E13F7F
-:104AF0009CE47C779C1EED282F18148C0129AD4175
-:104B0000FD920C420CE90A488C35A6E22840AC2004
-:104B1000B74955C1F3C9684F0090AA73B9FCA01FEB
-:104B200013D85AEBA766B21B1C9740DF5DC2BF29A2
-:104B3000834B94A09FAAEB85F966A14E023A6F724F
-:104B4000F93C2E58CF7D9DAF4FCB626827045B7038
-:104B50001DA00793BB416F9E886377794B068F3703
-:104B6000C30C788998EF485CABA3CC32F4FC33CC0F
-:104B700067A97FFFB8063EAE04FB6B8A18FFA7A0AB
-:104B8000EE65B0FB5A03C037058C3D15B012FC4CE6
-:104B9000C04E705BC049657BC04DE5968042ED1DFF
-:104BA0008172825F0878080E05EAA8DC16F052FDD3
-:104BB000F64003C1AF047C54EE082CA6F2B5809FEA
-:104BC000DA77065613FCF34090CACEC07AAA7F2348
-:104BD000D04AF09B817682DF0A84A8DC15D841E5B3
-:104BE000EE4027B5EF0DEC22F8ED4098E070E03094
-:104BF000C107025D041F0C7C40F0A140379587037C
-:104C00003D541E0DF452FBF1C0058207CE4B6B578D
-:104C10003361572E1274C0D2B83D792F3F52F685BA
-:104C20008E2D46BB7791A04343359887407786CC3D
-:104C3000C26DCD2E3C6AA01337D1C971B42FAF9687
-:104C40004ED070407A0D563337D29B5AB654E9C9CC
-:104C5000FE0CAE90422F73BB88EB6F3353F537B524
-:104C6000373E2885D09E9B0776B211F8E623619FD8
-:104C70007C14C7E5F539BFC18D765FA314AFC0665C
-:104C800001FE77B23BE02F8CA47FD75ED356B49F52
-:104C9000D4F535C2383A18E7BFEC2E5A57233B6C8F
-:104CA000C0F540BD470FFC72C6E6DBE202BABE2F7C
-:104CB0005B17342213594285DE44C68C76DFF348F5
-:104CC000E7E7FCF71CC2C1175995429CE77A537875
-:104CD000F8AD307FEF11BDB2CD39345E96B7CE005E
-:104CE000E17D99F6B73F77A01D5FF717BD0FCFE1C4
-:104CF0008421B1210474DDE99288CF3A5D3A4DD91F
-:104D000066F7FD02D7F96DA2FF4E1DA0F2DBEB5650
-:104D1000BCB212B6D4B8A22019ED55F00F0C685FE2
-:104D2000CF614E03CA879B98E75D1CEA66E623F8CD
-:104D30005616A452B6F976E1BE6E6321827D15A6A1
-:104D40009C58FB8A5ED73B38D8702C759AF290DD60
-:104D50007700C7FB36D143EB3A31697A21EE4B5DE0
-:104D60009739C349FD66B3DE17707DDFEEFBFA535A
-:104D7000296F309DFC88F4618169B03F33C2793777
-:104D800003EFE038CD0F4B21A473953E1AC14CA719
-:104D9000F11F857A29925E804ED07F4BEBCD99939F
-:104DA00048F4D24DF26F923E68047BFA842E542868
-:104DB000E9894E8C12AC73511AD049EED0F4F0C090
-:104DC0007A2823E420D0D91738DE9FFEE11A37E293
-:104DD0006DF9DB939C88B7661D9C07D073F0A89E85
-:104DE000EC042644BBFEDAD210F907B2A2CC29C5E6
-:104DF00073E37271BF9EAD7E3D86DC4DC8E5F474F1
-:104E0000C26EA80BD1B89CEFD5767D2E3F477D2E84
-:104E10003FDFA6159F2DD5C3FA4F1CF8DCE82C8D7B
-:104E2000B18FD53F79283F82AE97EF3A3DCD837E53
-:104E300017EB2EB93171A0BE50CCABD291DE98E801
-:104E4000DB6A895C573F5DC7E7225DA7005DE7111C
-:104E50005D7F8A76F96C9333F95628BB013561285A
-:104E60007D2F5AC97F5CC0142A17322F958B800C76
-:104E7000908EBDC1278D88F7FB5827D53F507E7790
-:104E80003AD2F5BD3A1FF9D94B5917D52F67BDB5A1
-:104E900078B437AF5FF3AE1D567D53EB9353914417
-:104EA0006F0CCD7F17CB39DBA54F834EE293EC5CC3
-:104EB000C047B7E47F2213E6BF7D67D51359503F43
-:104EC0005BCFCF851DE3E7A2CA91E87D035F14E0C5
-:104ED000F3DFA678685FFAA43A0D5F343ECE3C1249
-:104EE0008CD3BBCF14DAE68AE093F2FBFF9085F215
-:104EF0004CEEBD13CF7BF9DBA6543CEFFB18D7FB80
-:104F000092478DAFA8FA9E11BDDFCFE215ECF78571
-:104F1000A0EF2FB219D1F71712388A65037628CB84
-:104F2000F1D9CBF206F4F672DDCED18827D0EB951D
-:104F3000780EF77DDCD932D685FA2094837688E125
-:104F40003593D2ECD2E817762901858D9F213E7FDB
-:104F50008AE38E19BC2EA9FCD09FD1EE301959D00E
-:104F60005C467CCE26227F671A89BF9A11B57938B4
-:104F70008FD7E9B70C1EFF8458EFE1EFB83F1D84CF
-:104F8000FDBC2CC59A87EB2F53FCC03C2447D2199B
-:104F9000CD73472EE763753E66E976A09D7E34C1EA
-:104FA000773B9E8F1A4752FDC8C3AECFF2F17C66A5
-:104FB000576C50E5338DC7AEE372E984C11944F8EC
-:104FC00044954B0109D62F6F6F28FFA70F701D372F
-:104FD000982D618C77B04AC3D97EFF3577401FDFAB
-:104FE000A0EAE3CAA8F88E1AF7618A01D757CC3E27
-:104FF00052F141F11D554E0ED2BFB0B12EC49F8863
-:1050000097F5C779FEB93FCEA3C3798D428E32E6BC
-:10501000777B23F8D4D600AE8BC67F30B37C8DFF70
-:1050200060D5C0D97EBBA6FF88D54E4DBB2BE8D638
-:10503000B4E7AD573470416BB9A67F51BB47031736
-:1050400087EA34FD47EDF06AE0D2CE064DFF31BB72
-:105050007C9AF6B1E1C59AF67187FD1A7842D76A53
-:105060004DFF6B3E086ADA2775AFD7B45FDBD3AA72
-:105070008127F7B66BFA4FB910D2B457B1BFD5B488
-:10508000D7985FD7C02FC6F178E754EB3F689E9B57
-:105090006EDFAF815F88E7F19A19CE23DAE7C5F9B1
-:1050A000066F8B277E98E53EA969DFFFC8C8CD8DC6
-:1050B000C02FA14774E47FB6D5713DC51AAA391D2A
-:1050C000C4F1BED72B1F6AE6CBD1F7BA908E9D7A7A
-:1050D0006B26F2757EF99C034076ACD0B3A21AC55C
-:1050E0009DBBEEC903588EF4BE5E8D6C53D270F238
-:1050F0000096A37D5F570319336571CA3B5896F933
-:10510000C7D6D87089ABE7BC83E5C4E08A1A94B3EC
-:1051100060267EB108D67D3E38926D84752565AADD
-:10512000715E0FD1EDAA0C1DF1F9AADB2C14374BDF
-:10513000BFD622A33EDF1CE81A7910ECDCF4A7D31B
-:10514000D762DC693DD8F9A122B017C0EEC7F25989
-:10515000B0EB43E01C6D04BB1FCB4D60F763FD73E8
-:1051600060F7239CFE74D97A7C6ED5C97BEA7261A4
-:10517000FC110FCA563453D739752B0EC07AEC0F79
-:105180001AAD284B8CAE67E29CB08EEC65B08E0AEF
-:10519000428B0751FDEC52301C32391C07FDEC2BC1
-:1051A000741AB81DFF45B02E588BCF973EE9DEAE7E
-:1051B00030F6F9B6B337198A619F795DB76D4D0145
-:1051C000389779E602BED3F12C60FC93798FCD0934
-:1051D000960C8697147AFF487249EE2C463EB51617
-:1051E0007D9481EBDA50FD85A2B3E23C8FCC390887
-:1051F000EB7E7E78BC58E72373AAF2AF665CCF796A
-:1052000094EF50EFEF8C2147FE53E8FF93795C2F2A
-:10521000C39F15E5938D9308B3819D940CF276F3AB
-:10522000A4D5A7D1A790AD4109E523BB08CF4F1462
-:1052300028C823784AFC441EB247795354E433E724
-:10524000C178361FD84E91F1B1C55A78339CE71911
-:10525000C3C07A0C77E98232ECC1F0925751609E5C
-:105260008E79B05F80371BB5FE65918E917D719F01
-:10527000BAEE8B372968A7DD97C7F5F09680BBECAF
-:105280001303FA7F4AD9274047998BFD920FE4AB6D
-:10529000ADD1AB04A19FE1D2DFEF372261DFC53A88
-:1052A000519F63FD9A08BB27478C6BB8A427BC1994
-:1052B0009ABD4A6AC4FC06BDE4EF8C617795E6C9E5
-:1052C000FCB96646ED86771E969C305F666348BAE9
-:1052D00087C6F14B0AD4DBC2BC3EABB1535A08F0CF
-:1052E0001D794E3A07759CACC5B0FE083CD9E5A0C7
-:1052F0006485E7ED8F0625C483DDEA555822E2DA9E
-:105300004BFCBD52F0B47DF5C4B24F86E1BABD8A04
-:1053100017E79BA5F29BDFCA703D1F2BBFA942BDBB
-:10532000F61B3DC3FB8C6F9C4A725A8C7DA8A5A9C5
-:105330005BCF3C97F16792721EF1939EBCDDE22C2D
-:1053400000FE7DF1364BC3D6187476471EA7B375A1
-:1053500099AADEE2EB49D7733CA9FAEA1B2BA71FF7
-:10536000556EAD4CE1B03ACECAECF12437865A8F77
-:10537000AD3D8EF922D6BB19E6B1E2FDCC772BAC60
-:105380008837F021BC349FCCE5E9D6E7DDE4374629
-:10539000D3CF203E00D19B5C8674D91D6A06BA31FA
-:1053A000CD332A682FDAFE5B8B84722493B54A28AA
-:1053B000476DD9B58765D4E7B2AFD81BC38EBE128F
-:1053C0003FA8E7A9DA2583CFCFF9BB2AB2430D0C5A
-:1053D000E9B6C9E5B4E1F9A974DA746478AA2FE2F0
-:1053E0003CD70B3A2E67AD7AE4D30AD6496525EB54
-:1053F000A2F23AD64BA58759652CAB9942652DF39D
-:1054000052398DF9A9AC63AD54CE649D54D6B32EF8
-:105410002AC1BFA3D2CBACE487DE08760C96739981
-:1054200097CA5B989FCA2D48DF13F0FEA195E0DB79
-:10543000592795BB80FF9D45181F3153B917E43993
-:10544000966F833CC7320CF2DC69C2F8889BCA8332
-:105450000185CA4381722A0F073CD4EF68A08ECA27
-:10546000E3012F9527020D5476057CD4EF5460316B
-:1054700095EF05FC54BE1F584DE507812095FF129E
-:10548000584F659111E40AE2DBDD3D16FD9A9C8FD1
-:105490008D1E27E8A34FF384FFEBD1FDF7E2F178EF
-:1054A0008E3ABA83B1D5AE94901E6D6E9D2704E5F9
-:1054B000467793743794EB4E703BD6644B243BD9BC
-:1054C000D6BE4A72C2B8BBA46E7D029CEDDEBC0F94
-:1054D000E798414F54ED656B1314847FFFA419E8DE
-:1054E00070ABC1DFBB15DA7FF5D2BFCE3183CEAE54
-:1054F000483CF5C7D7384CED930EB2662BC007F287
-:105500004E3F9926F175A0103EFED2C773D6E4E354
-:105510003AB91C79D5058E36FA190F5BC8CF18DB5E
-:105520007E66AC0EE049AB2D65E81F47F4A3B8F5E5
-:1055300050FDA2DBD5E73A56A437231ED67D0AEEEE
-:105540008913E565F7588CCF458EABBBBAF999FE48
-:1055500032F347F6932E335E5191E754DEFF037426
-:105560001E4DDF864B1FBFAEA3F8983515F5FAF632
-:10557000142E777AB3E343DB60DDDB5305BC219F58
-:10558000F6B50E61D8D7BA8DB964C76F8FF3361DE3
-:10559000C1F6BFD129DBA0697BBC6F6331C1F914AF
-:1055A000AF5997EA77A35ECA49E0FAB1CDF1489CBA
-:1055B0003382FFFF22E4EEE6CABEAEADE84FADD7C0
-:1055C000B102786EDBFA051BDC30CE4B9BC02E029D
-:1055D0003879F2C20D05D09EBB4137512F641EAE03
-:1055E000E3A54D0B5FD928E1B823530B61DC3C21C7
-:1055F0003F7386758F5D0974DE66D4C615FAF56350
-:105600003EE7978530CC19D0BF39225EB1D5C01A9C
-:1056100022F566413E97B73545BC344CE1F13CD3A9
-:1056200088F8D0E3B0FFAA113CFE93BED64CF19FA0
-:1056300074C77F9E9C0EEDE91D3A054D5AD9B6748C
-:105640008D01FD9EDB5827F2E356893F1FCCE6769D
-:1056500032182CB97322FC1EB037CAF223E2A7F627
-:1056600086A084718CAA114B258C37A73BEE933012
-:10567000FE91DEE0937C89E827F9A9FDAE229F2BFD
-:105680001FD6676F84E735F7B1BE0C3C5798B781DA
-:10569000F20964561639DFEC228E872764203DB468
-:1056A000DFD71A695DD1F89AE5AE1E993F7CE01C00
-:1056B000A3DBBFCCE7E7B8FD719802F960128F1F3A
-:1056C0009C783993ECE5D96DF11EF4234F3C39B247
-:1056D00096E0A72A3C68FF9E78B9621A96B39F9A13
-:1056E00049FD4E48EC30C605663F75BB8CF53979EF
-:1056F000B02E1CEFB491E871F653F789E71FA9C5E6
-:10570000F6725DF0EFD09F2E6F7E2D01E3051589B7
-:105710006F64617942D7BD6A3FCC7F8395FD1AD50E
-:10572000B57743DADFD4C13FE63C996BC0788C375C
-:105730003F97CEF326E631F07C072FF9B7953BBAB9
-:10574000DE018B8E5DD7D95B83D7BA9E5DD6835839
-:1057500056871534A359ED61EF412CA775F96BD12C
-:10576000BCA9FBA0F52096DD237D5EC4FFABFFED59
-:1057700096375E0578C463ABAC6887E63FDE3D6371
-:105780001BC52F0D0CF9A16092BF558F046CF6A6B6
-:10579000A27C78F6195987FADDE46A8D43D8744FF4
-:1057A000AE0EE34CDB535A17D3BE0BE219E2F128DD
-:1057B000E821A48B82146F2AF213F0259DC39D82E9
-:1057C0003E4D297E6B0AD68B7B8EFE7EF11C5ED809
-:1057D000DFAF354EA27952A5A0C4CD08B423EC4268
-:1057E0009FB7337F06E2C396E8DF8AF1AD822ACE07
-:1057F000FF2C91D305766F99488F50103EBDD53F51
-:105800000BCFC1E6EBCF1BE074076AB0DF3EC925C2
-:1058100098EE7F364B1C063943EBC23F8CE7A45B06
-:10582000D2C9CE51D76F6B80F122EC0EDCC78D96BA
-:1058300081E754BADB20F6F584280BE6F3F1D4F5C2
-:105840006ECCE77A1DD6EDD4E17AF4623DB00F5DFF
-:10585000C47A22FAD1FEFAD7CD143BD205637E89F1
-:1058600097CC2947EE7FA1CE13371AD7FFD65F61B9
-:105870005C2909E508ACF367FB2799914FA3F7F181
-:1058800042BE88FB80BD8CFEC34C1FE7DFE646BFEF
-:1058900084FE940D61DCBF43F6605CD46669920CB3
-:1058A00011FBB539B89E9ED9E8DF8F7265667982A3
-:1058B00082F43D8B75AEB572FE3E980FEB2B62FD08
-:1058C0007F163671C04E7CFE99F74EE2913A5867CA
-:1058D0005531EACFC7EEA5BC89CD8FCC3C8CEBCF40
-:1058E000743FB93F1506F47E2DCE7D3E8F6F6577F0
-:1058F000C89ABC872CBFACC98BC858AC6D077AD08E
-:10590000C02A5DD9A5D529A86F7409253367A09D44
-:1059100092A423F90E724A9A1BD31E8DA22B817F6B
-:10592000F57CDECDCFA773B359F839B05EC57C7373
-:10593000A2D8AC7A4E306F33B07932D07D73AD3EA1
-:1059400024A11F8FFDF132B2970DF7260E3EA7ADB1
-:1059500006E7CC1928A71FD45929AF2A0AAFA06798
-:10596000FE99FC9407D3A81DEA6533C53D23D6AB49
-:105970008F056BCFE34AFD3B5878CE0CD7E0FA4C4D
-:10598000C7DC99A8673397323AFFE8F6A247B5E734
-:105990004A7EEF788CA3B150F8079CE74CC7F65AC3
-:1059A000B4EFA3CF55A5BB9C61B1F5C223055C2F15
-:1059B000E42428A7EAC8AE90C94EF066CBC323FD05
-:1059C000A4EFF2B91F30E55716D243EC6373081FFA
-:1059D00055C25D3F298673A8EED3A1FBC2DE3D7E92
-:1059E000E0E999504EFDF57B4DC7A0DFD4EF2CE3E5
-:1059F000B07E37EB9E8181A0E06103F98D6BBE7CA8
-:105A0000A5150344CD8D4C41BDABCEE328E0FA6E25
-:105A10008F21E425F95A2CB36D2407D9C54B11F415
-:105A200002909EE887B7316F632BF991B6FC12861E
-:105A3000793CCDACF30ED297678D0CE3AF37363897
-:105A40000D55B0FF1B1B9D86F9789F21B33AB423F7
-:105A50006E6A50A8FEA64685D79B79FDDC060FD559
-:105A6000CF6DF4F07A0BD45B300F29D41580716FB1
-:105A7000B6A43A75781FD0E8E5ED174CD47E1CFC2F
-:105A800001CC278C8F0B91BC6FEDD1F17B237F7CF8
-:105A90004882B59A12CB0E3B117FF7E8145017CC11
-:105AA000942D332BC0CF3678437A687F8E853210A1
-:105AB00091BB1736790BA17EB743B6E2FE76837BA6
-:105AC0008BF947C1A532E19DFE00DEBDD841F73A12
-:105AD0005B45FC3EB8C44CF166B07528DECC9664DC
-:105AE0000A3B86B7772CB086D01E033948E7D87BAF
-:105AF0008F4C7600C8C3A36EB48B76E62B189FCA72
-:105B00005CAAE5B7F4850BAA68BC4666453FBDBEF6
-:105B1000918FD7BC5317D2A15D65B97126D241F3DD
-:105B20000EA6A03FFBECC253B5C310EE50142E3F9F
-:105B3000B472A179E153479CB81FBFCE5A40FD799A
-:105B40001CAFD95FBD5D2F0DF0339DB773407E0C48
-:105B50009637CA611C27635EB582F1C174D827C627
-:105B6000F33B8CBC3E78A74CF72DE90BE5B075F400
-:105B7000007F670B14A6231F26917CD1F0D7C89D08
-:105B80005AF879C1A7C0EF32EE2BB89D513E67D1CC
-:105B9000766D3F90933A9457D9EDDAFA5B8BFAE33E
-:105BA000021A3C44E3D9E6E7722F7A9F03FB0AC747
-:105BB00015D1BE747C5F28D7A0BED87280EA8B1B3B
-:105BC00065C5E94479D7790AF75FB453666180EB1C
-:105BD0001796CD447AAADFA4A3F0C8F5AC8BE4C233
-:105BE00095F6ADC63BA2F719BDBFEFF2F55C8EA8E6
-:105BF000F6E01366B207DB1EB6E8F09E15ECAD7852
-:105C00008C2BDC55541D2C407B40C81DC3253D9773
-:105C100027CD16A25383ED517764FCA16554F5138B
-:105C200005D46FD88D753C6E41FB8E96633F17E3AC
-:105C30004DEAD6E6E35DDB131F953FA6CDC79B7209
-:105C400021332A7F2C2F2A7F6C94A67DAA755C5461
-:105C5000FED8B551F963351A78967B96A6FFF5CA3A
-:105C60004D1AF886F23B34FDE778EED6B4DF547770
-:105C7000BFA6FD66EF4A0D7C6BC35F6BFADFE66B78
-:105C8000D6B4DFB1F8279AF668FF492D771570F979
-:105C9000BED9EE3F49016CD0F791F73D6A99DE28F5
-:105CA000F7469E7B5202B7A7A2FBFDB980D3FB8BC0
-:105CB000129F8F05ED9A781CF3D835F1BA7045859F
-:105CC000B91BC6711A95DF21DD62E20EBFBFB66B4C
-:105CD000EED9F63F0EFD60BCA6C45C1BEA3B8CFF10
-:105CE000FA40B9378774745F615BBF4A223DB86977
-:105CF000158FAB5C30523CAF7F1DAC8EC6FB46DCD3
-:105D00006BA9EBEC1071A42D18474285E49941FD75
-:105D100056C6F17E3F4D57E38E3E1A37A3DC18A4DA
-:105D2000FCBC857E09E3C0CD3E66C57B9374CB0287
-:105D30009AFF9B0625995D262EDA16B0330FCC67A5
-:105D40005F155C6384BD7D52D0F7D4B3F0BCDDCF6A
-:105D5000281ED35BF0ED53188FE943E108749D21B1
-:105D6000733C3FF7C0EECF5F81F9DAE6A597A15CFF
-:105D70008D6ECF5ABEF7EB4397697F6ED95B1FDEFE
-:105D80007BB9E71FD875BA25A27DC838694326F3C9
-:105D900044D001E02CE6FD805CC8F5F9F20A23C589
-:105DA000B1AE01FC1502BEBFAAF8CF893BE0B93FF6
-:105DB00039FBEE443B1DEA65AC877E84D73FE59F07
-:105DC000A3FC929C5160DFA3FD1D179B6EC715724B
-:105DD000BA956D8DBD18076A4A343AD1CFCF32BB20
-:105DE000CA3E1907746DE07E75B4FFFE5CBFBFDD6F
-:105DF00049FE779118274B947A2B7F9E99834C4EBE
-:105E000017F71431F0A14F6A97505E652E943F8DBD
-:105E1000E48BFD89468A23A45B44DCC1B258131786
-:105E200050E306FB13EF9590EED3C34B289E8FF102
-:105E3000021C6F5CA193D6111D2FC832E7D3BA861E
-:105E40001E9FF5D7274831E6895A871A9F889E27D3
-:105E500084F604EA9965F1644F44EF7B4961557912
-:105E6000E170E4D7DE93D3517E9F32903E1C8A5E70
-:105E700030CF3C1431FEB442EEDF63FE78643DE681
-:105E8000878722E3D9CC41EF2B100C2A6684B17BA3
-:105E90004311CE7794CF77C2A0D8C91E04B587FE30
-:105EA0005F7D21D703D330976D38F219F7CBDB81B3
-:105EB000AFB1DC12B0927DD601FC87F00B012795C3
-:105EC000A1809BCA6D0185DAB707CA097E25E0214A
-:105ED0007847A08ECAD7025EAADF196820F8E701CA
-:105EE0001F959D81C554FF46C04FF09B81D504BFCF
-:105EF00085F66001C6A9D753B93BD04AED7B03EDC7
-:105F000004BF1D0851190EECA0FA03814E820F0642
-:105F100076117C281026F870E0309547035D547F99
-:105F20003CF001C137E33EC9AE58DF15C078854F5C
-:105F300076A27DF7AC6FA115ED6BFB7C9D15C57945
-:105F4000BB4FB704E31C1D8DFC1E13EF23310E0461
-:105F5000766808ED39FBFC678E4CA5F6B9D4BE19FE
-:105F60008704A7C4B682DBAF6C9991FAD930210AB5
-:105F70009EEB58DA18D203DC5A184FEDB61532F9F9
-:105F80006DCFE9FC2985DCEE22F96D3370FB41A56C
-:105F90008335855CDEAE29E4F75C1F16F1734ACACF
-:105FA0008BAD479E2D54EDA6F587717FF679B03FF6
-:105FB0005CEFBC5566BC97B5DDA3B3727B93DFCBBA
-:105FC0003A60BFB87E580FC585D97C6E2FDBE6AD31
-:105FD000A57539E6DF48EDD6A24753D04F6FF7AF2E
-:105FE0009A43EB6D9429AED9EE3B9082F76CCF8942
-:105FF0007C27DBF0786FA864F07A9E8D5A7F07E3E8
-:106000007E8303ECA5D763EC03D36E49CF3011C771
-:106010007BD41C338ED729E8D72171FE630FCAC405
-:106020007F2F30B0FBE0B92D60DF05510E54BFB6B5
-:1060300002E355BD85BE9D28379F778E3F20039C88
-:106040005AC7C7CF5D25BF8276349CF7E72D50BF76
-:10605000E1BE4D5E5CEAB04DCE35C86EEDF3DFCAF1
-:10606000C0F89743D29E8F5ABE2DF6F982878FB71C
-:1060700065954CF164DB8A375D07F9BCBB91FF3352
-:106080008B3E8AC3304CDE5CA70E4586639EFC3592
-:10609000CE1777FFA63A42CD268F3ADF589CEF6A9B
-:1060A000F134E2B15A9B2FC6BA869227579223BF8A
-:1060B0002914EF8164B12C9423CF19B8DC0A9EE433
-:1060C000F62425054D1A3C8F9A2FA0E60F44E70BC6
-:1060D000FC5EE029CBC462DEE77ED64FBF413AD7F3
-:1060E000173C1BBD9467E3923149873519D8127A62
-:1060F000EFA72ADEBA26063DA8E55328C700C11F30
-:106100001632712E9BEAF8383A3ECE64B682E02A07
-:106110008B3518435EABE533629C7F2BE4749B7533
-:10612000DFCE0D87F07C8F1A28376A8B2EB401FDE5
-:1061300084E0093DC9D74C7DE7D65722D6F51741F3
-:106140009F5B8CA162BC876E87F14A50AE22BF94E0
-:1061500050FC82D547E05D7DEE3F841DF0FCC575A7
-:106160002974FF3C6F6D1CDA47EDCC4CF46033F8BA
-:1061700053C646D0830DE932067D388B8C340EFC35
-:1061800059AA26E2BD0CD7CB35289760DDFB162631
-:10619000913EAC99FFDEAC310057F6C994CFB265A1
-:1061A00029CFD39CF4EF3ACA1379FB31EEF75DF7B0
-:1061B000502DBD9F9421CA67D1CF83B2723D53C287
-:1061C000702E950B2D14BF997C413E13E9A75148C1
-:1061D0007A3CFA173C5E736DAFAC790F6D528FB697
-:1061E0003F60548F764646B7B6DE3EEFCDD353615F
-:1061F0009EF6A5FCE1F68BBF3B827070958EE22483
-:10620000EAFB64509341F14D399881F99B1BCC8C8A
-:10621000E4B96DBED98AF2607F7A3CC9BFF6DB2C47
-:106220006487AECB6F8A433BD9346F550A96238C73
-:10623000C1AD183BBDE6D52D37D92791BC55F355D7
-:1062400082AC1CEC81BB8DDCC8093EF7F45419E527
-:1062500025CF6799F4EA96A783F9D8AD95D6E1D40E
-:10626000B14CBEF97EF876BAB796B8BE701AA11DC9
-:10627000E079A37CD715417B465A703F366DB69CBA
-:1062800069A47C6B4C3282F90D0BFDCC88F58D65D1
-:10629000E6483E57F9E4FBF27F3CC687875F590E1C
-:1062A0005C69DC2BF17B413EE79BA1FC69D310F2DA
-:1062B00054F58F1F29E0FC8B6C4B7AF58C31A67D51
-:1062C000F5AB22CE67E5469EA732BB615A1DDDC302
-:1062D00004BB65CCE77B51DC0BB5A727D23D717BB6
-:1062E0002E0BE3BD4170818EC77BD2F87FED8DB957
-:1062F000141F6A93FC29C13CCC97F0B9F0FCDA0179
-:106300004789307F5B0E97EB2CE4B7E27D358CB389
-:106310003872FDE0EF05B574CCC81EA6F8859E78EE
-:10632000CF698C88B7635C1CE317D1CF4DEED5C223
-:10633000532E68E12A66D0C035662D3CD5AA853734
-:1063400015713B7DBA5D5B3FC3A9851DD907E37419
-:106350003CCFDFC222E249F0F75E7E441C68DD6874
-:10636000FE3E5F76F7528ACBB6E5F0788F639536BE
-:10637000CE91C54212E22F7369543CD6BD663F866A
-:1063800097ED0BA3E341FC5E02F0A1A947318A7CA3
-:10639000F0EA689E87DE3DD2B7BD08CEB3600C5FE1
-:1063A000C7AB1D4D743FC5DAD388AF5C225F69B0BF
-:1063B000BE7C8AE8401D0FF92218B17FE48748F8B7
-:1063C000A151BE37701EE48B60A4FE2CE936D0FBD1
-:1063D000AB62BEA1F843E5CF72718FA2E6DDF4890E
-:1063E000B1D4BC9B55225F705754BE4E9FA3361943
-:1063F000FDE7BEAE95F1B1F810F92E68E27C88E5B4
-:1064000006917F837C182CE27C88F5A6EF56786392
-:10641000D98B0B055DDCBF63C9864F22F6B7AC7321
-:1064200085065EBEEBE10D91F951F7E33F3008BF01
-:106430009E517EED52B19D2F4FFFCB2BCD0CCD4801
-:10644000DF0728CF96159C31F27BA75E239EEB4297
-:1064500061FF99CCB3F2D12FDB11E2F26C9D88374A
-:10646000345B1533C681993B5513C750E3114D4B2F
-:106470005CB654D847727F7CC16BA57CDCE1F91413
-:10648000DF48AAF1DCCEC632D653649C6B0662DDCF
-:106490008EC156C0E9F957D93341C7C0BE4D17F870
-:1064A0007BC9FDB0EC67248F2EE468EADB449CA333
-:1064B0009FBF2D0BAA703E8BDB49FBB031FF1A1E2C
-:1064C00017D4C6D14CE23DE7C1E33B34F56D227EE3
-:1064D00072E5F1B57139D385BC21C62F8C1ADF1A4C
-:1064E00073FC8171B5F1BDABB8374F714F183A2EBF
-:1064F00036D2CDE9699DDDDF85713183E07F6606A7
-:106500003A9988F280FFE9E3797EAEC1A18D8F19B7
-:1065100030AF0BFA3F97B898E48AFA3EB5FD99057B
-:1065200012CACB27F0FDE8A4C1F2245A8ED844DE6B
-:106530007CB41C81F93470D3C35CCF364B8A0FE531
-:1065400073F47EFE7FF1877589E3BBC8AECE8E778C
-:106550009A2E630FB7058263F1B975F1FEC578070E
-:106560007EF78E91694F94E37BEB8CF86CC58E2996
-:1065700073310FB64DF0EB13693AA2A7F4DBD3B732
-:10658000EA23E829DDE873A13D9CAE13F95FF887A3
-:1065900071B427D2B76D8C31BF6AD7A9B0AD01D61F
-:1065A00011718E6DC29EEE9FEF8ECCADFA8871D2C6
-:1065B0004DBEB1345F7FFEA398AFE587CDB759C418
-:1065C000C3D4F96C776AF76733FA697F36A187D449
-:1065D000F936E3FE62F0D515E713FE75FF7C7769A7
-:1065E000F76733F9697F36F53B1BEA7C2D3F6C3E3C
-:1065F000BBE0CF76F1DE973D9E7F3764A8F7239A04
-:10660000FBF3CCBD66942FED6ABC50E8BB7351FA26
-:10661000AE49E83BF5F97369B914FF3D77F8267385
-:106620002C3D87FA8D093B93093B93093B13E1D934
-:1066300035A7570D077AFCBB1D37CF9541AFCFBEAD
-:10664000FFF4F81C80DFD9F18BB932E8A9D9AF9EED
-:106650007E330B1E29FEDBFB38FCF4E93E07B45BFE
-:1066600082CFCCAD05386918D7CFEABAD57977B9DA
-:10667000B95DB97C751E8F6F829C453DD69CE367E2
-:10668000187FFCCAD19B341FFA2FCFEE4D5F100349
-:106690002F6AB97C75217F1EADC08998CFC648AFDF
-:1066A000DDA8BEC752A77D8F25296923D987712C04
-:1066B0006445399660F6D0FB97D71673BD70335397
-:1066C0001AB85FE12C10791CF4DECB4DE5625C6BEF
-:1066D000E52FB1FD669DE709F477FF79D2BCE1684B
-:1066E0003EAB7973A306DE3BDDFE7DDE4F9EFDB142
-:1066F000C46DE5641E8F9936CAC9DF7B8B882BA2D7
-:106700005D3C143E3F7573FF7E009F1E8ECF540F7D
-:10671000C7A7B537690D9CFFF294DEF4C7894FC354
-:1067200031F13508AF51F8FB939BA97EA01EED888F
-:106730002BE15BC5AB9A5FD82C390BC85E67199A01
-:10674000FC60C61467AC7B1EA4CF483D6BB47B19BC
-:10675000DAA38634C58DF9EFCD7FD1C7CCDB7315B5
-:106760008BF85E523CE57D362719C91FDF9F3493B5
-:1067700061FC59B64C23BCD426D5513EA67E18EBFD
-:10678000447F353A0F5D9F7C3BE509E96DE8614048
-:10679000D99FC7EC31235FE93F56925D4800579976
-:1067A000872E5F290F3D7526CF434F323A315ED891
-:1067B0009E688C9987FEAD9BFB5DFB717F69B81F5E
-:1067C00023FF6E88D8976CE5F7EE589F00F546AB2F
-:1067D0008F51FC5DECFF5B6107A9FD4D563F43F90E
-:1067E000A0372A4EB45FF4A95C7FE0775BDC31E22E
-:1067F000285FBB0DF4FCFDA3AC5CCF99B9DD3EFB7B
-:1068000037B1DF27282B9644BC2436DD0D453737BA
-:10681000EA78DE9DCA97732D46CA079C6BB1D3F701
-:106820006CE60221F6A446F4BFEE56FE3EB5ACD8A7
-:10683000919E7E7BED945FFE96E1B50097DBA766A7
-:1068400018E8BDC25312F328A983F35DBDDE94A9F5
-:10685000B8CC1BEA4FAF45762C18C3C84E7A75C129
-:1068600043AD954EF28FEA8A919E7D73A6A20F7773
-:1068700063C3D877B1FFF2042ECFD5FBA5E509FCA1
-:106880007DDE6B64DF6CECFF55C51749D5485F7240
-:106890006F0EAE2BA23FDD3345F49F5B3C81FACFF8
-:1068A000E6AFDDF5D27739CEA59DF9C8C7E87CEC17
-:1068B000B1EC29F4B758E4BD86901FE87745D6A31C
-:1068C000BFC522CE535A506EEB8E214FD432C33EF9
-:1068D0006EE442A0D78C8CB154AAF5CF7AF475A19E
-:1068E00018E7FC9038E71FECF7B4C36A270EF83DB1
-:1068F000E0EF3C84F8F872E1A9F4F1B0A5076ABFB3
-:1069000026BFC76EECFFCE16F97103B0F6BEB32DED
-:10691000D05B8CDF196088878911F98B62BFF625FF
-:106920006B52D0EF81B3F420DD7604BC236B0D03F2
-:10693000CFBF2CE4080B16D2F306B12E475AEB0C4E
-:106940008CBB382C3ACA7360CCAA9167736A53A681
-:10695000A6A10BBB9C291627FAF75DE41764E0FBA0
-:106960000D189F7CE73686F75F59699D12DA75FD31
-:10697000F388F7C657897BE13E5F2DED27C3D6EF3D
-:106980009731F25FD38273506EF53DC35794F19205
-:10699000B6DD91C6F31FEE5D181F7202BD672DEDC7
-:1069A000C24F4FB00C70F830A69F71A9D9D5827232
-:1069B000E657091477D6B7E7B320C8FBB0ECFB1B4A
-:1069C000C277C8F9902E4F6C169E5BB6289EECB924
-:1069D00076A97506F931F7E858AC78D1CE62EEA702
-:1069E000FC8F622BBFCFB54FE4F4631F3F72E1B859
-:1069F000ABE7FF77849EF949B293DE7F52EDA34D5A
-:106A000043F8478E913A215F845E11F833339F1922
-:106A1000F9452F7979B074C76BAFBD96CEE8535B5B
-:106A200048471B84FDA38E139F1FA2C678C543F25F
-:106A300052B27AB8BEB0FAED4138AF75DFE963CE35
-:106A4000FF85A0FB35D90FD9B17FADD3E7C632FAA8
-:106A50003D98969C7BDD783E2D33FBE995ECBA960C
-:106A600033CEDF613E56F028CF37D89F5D68C3EF45
-:106A700041590E1B64D365E2F146D027CECBD8191D
-:106A80004691AFDE7280E799B658CABA30AFA1C559
-:106A90009256466AD8C2F356D5FE16CB21D20716B7
-:106AA00085DFDF5A507F48B84CC04709AEEB10E194
-:106AB00043ED7750C85D8B1266F85E5A9CD24AFD52
-:106AC000CCB2D78379CAE63446F744662BF017E296
-:106AD000355FC7CC31F4C9BE62AE4F5A4ACABAAAB2
-:106AE000697D327EB98EB5D8CBECA4E711EFF07C8E
-:106AF000738696CFBF137857C76916F9B477AE4E31
-:106B000009D68EC33893F71BA4E716CB027310F592
-:106B10005AE2F8CB8E671A39D478FBD78AF1BE4394
-:106B200079AE4F2CB3E27806C6F7158DF7E1629C7B
-:106B3000FFD5FB7BC02CBD474D301D58D81EEB7DCB
-:106B4000ACFEF313F7F2D1CFFD6079BC561B870280
-:106B500079EC1E09FB5A5672E65035D5F0F8D30B86
-:106B6000C29F51FD927431F60B127FBF3F28C52B97
-:106B7000F45D0CE1A7A4C769F130F03E2D3F876FAB
-:106B80001A781EDE37694C7C874ECBD7DF1CFF3866
-:106B900045939F057CEC31713FC623DEA7F588380D
-:106BA0001DC2186FA0179D04FFF7C7891B9C3FC328
-:106BB000EFAC99408EEB605CC9E127FA3639BA5DDB
-:106BC000C8EF39E2FB0FD178FEC9482EAFA5477A4E
-:106BD0005C78AF519BD69B118BDF5F7CF84206EE51
-:106BE000E7C519FD793B74DFF4E269E7E602C4CB3F
-:106BF00011EDFB6FEAF84D47CEA7F822FDA5C0E5E1
-:106C0000DF2F4B3AB37125D98D0BB8DDF87FFA7DB4
-:106C1000B317E6733B7597A495CF4F08B91C14FCC6
-:106C200060BB20D3F743EE2AF2AD403A6A93AC0B37
-:106C3000502EE73CCCF3F29A1E5BD5B328067FB406
-:106C40008CF2FDD5C808BFBA7CBD91E45EB3253790
-:106C5000F972F728439FBB9FE4947ADE558F9879A9
-:106C6000BE8A8FDBD1E9BE7B290F263A3F65A87E1D
-:106C7000D5239D440F6A7F138E8FF2C57223C515ED
-:106C8000CEA18F81713B2BB733A2D75989C898C049
-:106C9000F163067D997460491C8E6B10FEDC0B6AF3
-:106CA0005CA4A1CCEC8978DE705B99B93A824E9AEB
-:106CB00019CF0F8E1EFF372355FB22ACB1630CA8F2
-:106CC0007F31C694269FED973B6478F2FCB4950320
-:106CD0007CCCE30E43E7A3C571BE2D237BAC0DF343
-:106CE000D2C00E5ED3B06004E2B74DF6BD68033C7F
-:106CF000F47E68A23CEADF0B3EED167C3AD4F9053F
-:106D0000D90130D2187B9C1DC497E2804EC6272340
-:106D10005F34E7EBEA4231F6795CECF332F67878EF
-:106D2000E4F7B3C70F89FE1A7B1CED6D4FD4FD4607
-:106D3000248C76B627863D7E4212F105912774C2D7
-:106D4000E0DCD50D7839313999BE975690C0EF5DAA
-:106D50004EA07F52067EC8ABA7F3D17E992DF57F5A
-:106D60001749F8438C60F047FE05F9620EF3BFB691
-:106D700048223EE2F735781B9F7EE573DE3692D1DE
-:106D8000BA36C0F9E1FD46DBC5F93362DD67A48E92
-:106D900052FD37506511EF13333C9D88FBAC41F732
-:106DA0007451F772786DD39F77AC1FDCFF8672ED5C
-:106DB000BDD9868B3C2E625AC2428F4B9897AA6DE2
-:106DC000BFA9CE107D2FA8B94FBBD96B885E0F7DB0
-:106DD00017D421D69BDD711FDDBF4FCDE6F944A648
-:106DE000658CE204D1F76DA6B15D1E3DDACF0D8C46
-:106DF000ECFDE83839E6A952FCB081B12D12E579F5
-:106E00006BDF7379A6FE73FE7D94D63A9CC70E762F
-:106E100010DAD3D1EF49A8F75AEAF751553CABDF66
-:106E20008F4ABF4D47EB63C129D4AEC6FDF17BB895
-:106E300055E911F9E42B587F7F7A7F2B187BDF9B74
-:106E4000DBEA29CF2073BC7F6C189AB2144678C84D
-:106E50005AC8C86F003C68F2094CD9DB699FE71635
-:106E600033364C223C68DA3340D3D3FDC0426D7ECA
-:106E700001EC530347FBAB57F2534DD9F99795F308
-:106E8000578A639AC4BDE49451E2FB97A5AC14ED14
-:106E9000A2F4DB9EA1F33807E781715F749C62DD89
-:106EA0003B6E82F1D18FFC77C12FCDE26E5BFDAEE0
-:106EB0000FF3C8F41E9B54CED72C0DF3F27BE912CE
-:106EC000467C6E8A6766CC8F972A4C1EC4BBC90469
-:106ED000306C5932327306D4EB453C7B8DC46484EC
-:106EE000995531F3F8A3FA5DA1107D5768A879D4BC
-:106EF000EF2BB2207F4E9D67D077F52EF33CF97BC8
-:106F0000D6E8E76B299EA9CE3F14FE87FA8EDEBF36
-:106F1000D5BC3781C7531D44AF8D03F44AF07C4183
-:106F20008FF83CCA85BBD5667B5729FA0F671E4C84
-:106F300050364A11FB08CED2F3EF037EBFF1FAD7E9
-:106F4000617792BCEFDF9718EFFBEE8BFE22E4DA5D
-:106F50003A7C5909F35E1A19E531A4FBAA3F972937
-:106F6000FF00F6A0911311DF4980F1D63DCEEF1F4F
-:106F700036E3773EF0FEE7C040FEED13166CF7D126
-:106F80007736D4BC5CCCA35D5B32F03E72F47D837B
-:106F9000BD11C689986FB2990513409FA4F43105BD
-:106FA000BFF3ECB96854A6037E6C7DA05001BF937B
-:106FB0009989EEA52AAD7E33FF0EE10A166967EFC7
-:106FC000976EA5EFBD86BF6494BF143ECF88EEC315
-:106FD0009FC3C4702EFFF8DDFB7AE4CBA97D5D7AF8
-:106FE000D4F393FBFCA47FF6D94F3DEDE2E7629921
-:106FF00011911F751D5B54CFE98A9F972CEA275F7B
-:10700000306AF8FDDA5EA3461EC8175BBE46FD6512
-:10701000EA89AA67D33FE3E3F928DE2DDBB5ED5318
-:10702000443ED0DB2ADF5FC3AEA173BC981633CFDA
-:107030006EE0DCD5736EE27174C6C7796E94F79F0B
-:10704000464D40FFC04771E864C42FD8172995DD2D
-:10705000CC8E7958E54C998E72BDB2F31DA487E4AD
-:10706000B33C0F3C7AFCFD5FBE95857EC39EC99DF7
-:1070700059682FEDF9F2153D8E57D5D3CBB03E1997
-:107080004A1EA4584C78AA10B43350CFE34491F56B
-:10709000B49E4AE765E5E4CF504E1A876EDF33D9D8
-:1070A000C2C2E4877526A03DC77C7CFE64B3CA5784
-:1070B000EC2F97705E84819FF654EA526A619F7B41
-:1070C0009E91156CDCD3F34602CEBFE7EC39CD7A46
-:1070D00098FE22F345ACFB5A71EE532B7BC9FE7E22
-:1070E0004AAC2BF96C2FC5A15395DE30EADBD4C333
-:1070F0007AFAFE37B3F0BCC8614CA1389ABA5EFC8C
-:107100006E2A3ED78272DE88FBB3325628EC7E2888
-:10711000332A8355988F9ACC764A486B532B7D41FE
-:10712000A4E7E4A59C9E93ADFEC318BF4F5EAFA33A
-:107130003845F259DF06F4CB92CB6505C9E44AF82D
-:10714000EC10F3B78AF9D4F9D5F58CA8F44BE87EA6
-:1071500024B3E362FEAE2A138EBF5ACCEF14EB5970
-:10716000C5E83B2CC967AD55E82F27839D41DF3328
-:10717000B8E2799A35F345B7274FD99945E7E0B199
-:107180001ED90AE3A5645B365441B9CEA123FF3270
-:10719000A987513C3DA9279DE47D524FA128278A0C
-:1071A000FA69420F703993D4F3502DAF6FA1D2A476
-:1071B000CA17873F8CFB98DACBB87C717849BE98A8
-:1071C000D2B87C51E9B856952BCC5A321FEAF70F4A
-:1071D000FFACB5069E7BF773FEFEE5BBD95CBEBC7B
-:1071E000FB25F7FB4D69BFD3A35CAA42C305FA4D4B
-:1071F000BBC0ED33951FABBA25361148639A83E7C0
-:10720000871FBAC89F3B84D9D500AF6312C929959F
-:107210006E6B05DDAEB3EA8349D8FE8189DE773433
-:1072200039CEE598C11EFE83AEF7417CEFF8F73307
-:107230007AEF5D41F5827E434B492E9A846C39E4A6
-:107240005860413E847948AE1E7218E9BC0E083A77
-:107250003E67AFE908C33F5BCCDFFC693ED4FFC1AA
-:107260009EEB40934C3D971E412F5F88F33B2BE8EC
-:10727000A629DD7B53C904FCFE621ECD7BCEFE0D2C
-:10728000BD7FB2DCF61F9FC6FA2EA73A8EFA7C4F5E
-:1072900068A519CFF5D09B1F9F40B4ABE35F237B5C
-:1072A000EFE4E37E339AF8D0123BCF7890FCF3AD55
-:1072B00088967F8B4A860FC8BF7A6691791E12E73F
-:1072C000EB59421E4D55B8DD5E6FE5E7555FB25F85
-:1072D000A6FE8A8BF655AFD28DF2E45AE47F9BF27C
-:1072E00024D14B7D3EA797BD829E0F0A7CCEEC63D6
-:1072F0009DE897ED2F986E190BF83EE2D213FF1C14
-:1073000019BBC65206CF1D2995F04B026C7AC9D61F
-:10731000B5A900CF5224A2A7FA92AD1D4DD07F96F9
-:107320003541A903F8E8F9B31634AF0E05BC8497CC
-:10733000E972F8E354179E1BC7D3CCCAB08CFE4F3A
-:10734000BD63BF8CFAF66DC4AB11E32E1EC1677529
-:10735000041F576A2CB88F23A526212F3DE3515EC9
-:10736000CECA37D58FA1757C7D6C4C1ABE776F5015
-:10737000F8953CA7FFC9827EEACC276B53A0DFCCEF
-:10738000926619D77BD42C91FC3CDAD744F993C789
-:107390003B39ACD22D3D077479BC6F5B7312B66F6D
-:1073A00097483ED52B2F1DE2EA8FD3A73A7E0F0BCD
-:1073B000B6E17730CF29AFB7603EF5B1BE05CFCC8F
-:1073C000013C1C7F533FC4B84D1FADC071DF4C243E
-:1073D0003A9E6D3569F4B18C4E69845EAD1E6FD3F3
-:1073E000C0F54A0DC5D3CF2992E50678DEF35DAD31
-:1073F0007B3991D152DA77BDE87B4CE17C79CCA125
-:1074000023BE3CD6F7B89C8AF05946FB919976DEAC
-:10741000FA921AB2AFCE295BF54467820FD5F154C8
-:107420003A3E8A4F231EED9CFF8FF66DB320BD1DA3
-:1074300075BF23E3395D67891A57D0A1AADFF05DD4
-:1074400071A49FDA51FBF37E86EB5138FE6B94D723
-:107450008F237DD53B64A2A7A3CAFE9A1486BF27BB
-:1074600062D2ECFFFE1DC99AF19775DA3470B45DF3
-:10747000B5CFFDDBA7CBC40E66A447D847F9C23E03
-:10748000D21F77E0FAAE681729EBE8F74906D9452D
-:10749000F9DC2E8AB68754BE6ED689B8AC8EC76525
-:1074A000A3F9DF58FAC3EEF1D82A498EBCBF5BC6F8
-:1074B000BA7390BEE6A31286F11ED075A723FC1501
-:1074C000EB6D8B07397CADCC7669BFBFCABF373F48
-:1074D000BED4771EE59574364CDF6165AB18E507C1
-:1074E000E86B789E115E66AD88D48B25FDF12D8DFD
-:1074F0005DA44BD89B8578AC386BE4F18F9EE8385F
-:1075000097EA1F8525F22BAE522EEA93F9B87BE657
-:10751000F078677F79338F931509FCE5941A695DDC
-:107520008A80F7DC16FB9EB5A454FA41F9A2DF0766
-:10753000DF2980EFAF90E6619E3D55B1D79152CAE9
-:10754000E3B5779778F24AA12C2AF11596225E3D91
-:10755000605FD377C53D649FA9E3BC33CAE316FDE2
-:107560004661C9BCDC0E8FEE07ED63689C86D8E3EC
-:1075700040FB387A7E6EECF643B839FC7D23FB3055
-:10758000D243060C64A6F2522AE3E516FAAE468808
-:10759000FBE70D1ED2F34691AF88371091FCC7F47C
-:1075A000F534BE1C9E41F7582DD82583FBF9917602
-:1075B00094AC846A22E3AD6AB9A894DF73CE28152F
-:1075C000EFF34C6013C8AFA8BCFC3CEAF343CDC357
-:1075D000EC6557C87B5EF363D349FAC3E4275FA524
-:1075E0007D600E4A91DF391F6ABF894A941C8AC2A6
-:1075F000D350F35CED79DC22E8F66AD75D657ACC8E
-:107600004EF9D12ECE076B057DF5DBD53F1E3FBE73
-:107610003F1F86FECAD9FBFE93F87E4A4268A53713
-:10762000C67E5E14FBF931E5C1D370CE1B8CA1FB85
-:10763000D1DE9907A76302D27BC7F2F1F005B09EB5
-:1076400037C5FC2D9695EB6F85475B1CBA98F91EE4
-:107650006FFE787AA20D3FD9FF95E3DCFB6D20A782
-:107660005B1E7DD0ACB08175306BD915CEF947E388
-:1076700013755D6D5B305E624DBDAAF7145A5CAF49
-:1076800024E07D69EDE74D76FC0E46B43DA0C6438F
-:1076900054BDA5C64D54BBA4C2C1E31F33EDFC7B52
-:1076A0003D15F669A4DF0FB2AE1AF2AF303B6D2282
-:1076B000B10AFD19DD5AFBE43ABF57463B2ADA9E70
-:1076C000A84D3345D907BD7A94DF1517B5FD54FE93
-:1076D000F8AC54C45154791765479ACF9F4940BBC1
-:1076E000EBED0B67282E148D9FEB2E5CDE9FBDAE5D
-:1076F0005D4FF783D171ADB72FE4D2FDA011AF1B61
-:10770000C1D4CACC3FC48C80974C7B6B9511EC18CC
-:10771000A38329F8DD36FC5833C60D8D17789C7C81
-:10772000849DFBD7898BC12F85513395A07DC1786E
-:107730007CCE48EFD3995DEF91BDBD09EA86219ECD
-:10774000C79E19A68B110753CF638AC0EF6EE6B7A9
-:10775000E3EF814DB18BF7F72E46DB59FC3C2DA2B0
-:107760007FE2622D3E2DE23C27835B43DF79ECD341
-:107770003E6F11E76B591AFB1CECA3639F43A27A7F
-:107780000E13B6C5E1396C59BC4D8A750E998B2F15
-:107790007F0E5B845FA9D2EFB4AC04B2AFF7A6E86A
-:1077A000E8FB417B13C359CB31FEFDB299DECFAC70
-:1077B000107136B4A4109F6BB797BF8471DB71A3AF
-:1077C000F5748E7B25D1FFBC8EFFFE60CF78EA1F5B
-:1077D00027B383F8BB8007FBAAE9BB1BD1FCBBD353
-:1077E0007A00DD33B6CEB93D6B019C8325FB8099D1
-:1077F000FB9B83CF07EF3F4A05BE4B7BF8B954A6EE
-:107800009DD4A3BD5EF266ECF351E38F7BA49D3A59
-:10781000202B36AAAF8BFC98913BA3ECE9B32D64E7
-:10782000675BC647D5F7C039D1BD8E9FEC16D9A18D
-:107830003DAFEB8738A74A1187307F7D8AE265FB31
-:10784000FA4E717EE9D1C62527F75DFE9C5E13E7EF
-:10785000B453C4A17E2EE2009DC27F7E23E0A4F239
-:10786000CD809BEADF0A2804EF0A940B61C1CF7731
-:10787000563ECB4717AFAA84FBED47CF73BF7D7F42
-:1078800062A883BEEF74DE42DF17A4BD4D14BFDBD8
-:10789000077C722CCE49BF1F7834DB4CF1B3A3A513
-:1078A000BFFB7B8ABB7C6BD1F1B80BC7B37A4EEBC5
-:1078B000704E186F5D858BEEA536E04714A1FFEE84
-:1078C0003289BEFF341B0E04EF45543A37F569F197
-:1078D000590FFF6595F1DF1DC8427F618C8BE8A4CD
-:1078E00042EF73223E37BA4F915F1E57D8EE1B8787
-:1078F0007180F17A26BEFB143445AC3B0E6F42E03A
-:1079000079538944DF731A0ABFD1E58654AE2FA399
-:10791000EBFF7534D7831BDDDBE83C773BBAB25015
-:10792000AFEF13F910B3642948BF5F2877DDB11CAE
-:10793000F65B91651FBB11C02DA35368FDFB4A4F39
-:10794000531CF8D88557C621FD1DB3765A30CE7921
-:10795000CCC9DF53871395F97BB79DF22D31F2A483
-:10796000D5F258E922FAFD957FFC7CEFDAD17CDF75
-:107970004C52F50A8C5B81FB4D42F9DEB202F9C331
-:1079800098B983FCCCE873AA705FB388DEF364FC1B
-:107990007B4FBFB6862C783F1CED67027D6C42FFA3
-:1079A00078F7043D7DAFAD5EE6E782E788E7A41F88
-:1079B000A3137E99767C66653E63FAC079601DDE0E
-:1079C000D7D03AF13EAAEFADBF9262F8B583D6C9DF
-:1079D000FC9E58F9B0D1CFCD76B2209A86B3151659
-:1079E00076A19F70309FC6996DE5E3CC12717C9BA8
-:1079F000A0FF59177594DF81F4D680CF95CC2779F5
-:107A000072CCF550571DACB71ECEC641FE469356FC
-:107A10000E09395B5F5245F7BDC7DC07C6A3BEBF81
-:107A2000BE74E5E13227C29FD45441B729A52FD5B2
-:107A3000205D5A942E8A2F4C76CB745D787DB936B2
-:107A40004ED1AF17A3F44BB4BEA88F923B11F7549D
-:107A50004E43C4F9CF729F4B88A483ABC7CB1C2F76
-:107A60007EAF7BD6051EA71D8C97F7E973A503781B
-:107A7000893EEFD878893EA7013CADEAAACB1D8CA0
-:107A80005F156FBF2E79C91A99E71B8DB71F8AAF93
-:107A9000E6D15641AF5C9E5708BE7D3B3B4471B773
-:107AA000B74BF9EF4B1D73FF96E2BFB358A8630DB8
-:107AB000CA45E0CB3942F9E823E44C341E06F8F419
-:107AC0003F282EBFFBF3B7282EAACA2113F225EABE
-:107AD00013C11FEAB999901F916F2FF0EF875E2DA8
-:107AE0007FA87C45EB213F38A48FCC1FFCDFC55F0E
-:107AF0007B71CD18177616523CB8CAD1A5C77BAC9E
-:107B0000C950D23D92887FD23A9C91F53C6E1C5967
-:107B10004F712FA1F7D4B8A6DABE3EBB2B41185542
-:107B2000A4474DC2DE51FDC47D8E53647FAAFA5432
-:107B300016F7FE57AB4FF7087D3A54FBDE73BB795F
-:107B4000DCE7CB433D0F801C9F9C6FA4EFB84C0E2D
-:107B50003FCCDFA3708449FE6F7437911F0CFB6923
-:107B600046A304E67544E6F3A9E5BEF36D0AD6EF35
-:107B700095BBF40AF507FF16E0038656FA9D860DBD
-:107B80008F737D1357F451D6E5DE83BAB34F99E670
-:107B90004AC2EF616F5F83DF010B2A8CBEEB98B5A1
-:107BA000B48B45EEF7A531DCAF9D9CFFD61D076871
-:107BB000DD1FEA69DD6857039D4F969D0E05E7CFEF
-:107BC000F6DB23FDEC7DD9F7DA9D00B77C696C0804
-:107BD000D17AC3A37E01F3EC33578D074B8DED7340
-:107BE0001F18F50BC0C74673D504CCA3ACB6DFDBBA
-:107BF0003E1FE5DAD95B2660FC1BECBC56D4B7838C
-:107C0000F6DFB7CD8CBF3B5DED789FD631A2AFAB31
-:107C100006BFBF5AEDE0F748BED1BE87C64C407BD9
-:107C200039ECC1734F349F0C22DD4C16EB65172FD6
-:107C300051FC41BD97D9739ED347FFF8400FB88FD1
-:107C40006BBF5C45F722B97DBAF926A0D5757D3C9E
-:107C50007F0CDBF17BE058BF28861D00F35CE74B0F
-:107C6000C6F3EBCABA3786DECDEDFB36E083E7F626
-:107C70006470BC44B76F1EC3ED82B8AFDECF7292A2
-:107C80003DC0F57FB0C012F33B55B7A9FAD21A3BFD
-:107C90000F452D5579A5DA23805FB32102BF9BC61E
-:107CA00070FFFD7CA9A703F1F77DE77F0A710BE563
-:107CB000F152CFF631C391AE045FAD9763C601EECA
-:107CC0001CF3A3C52B6E4113EFABBE73E96FE986BE
-:107CD000A6DB41746550E9F821A2E3FF8BF47BE257
-:107CE000FBD0EF207974FE14DDC347D3B14ABF0344
-:107CF00074C8E69B9206E87928BAC17E8B9206E8A2
-:107D00007AA87EFBCEBF1F93DE07C6E9BD2CDDAB94
-:107D1000F4B759D0917A0F5429CE79FDD78CECFE67
-:107D2000A33D46F577C6357E11E83FCAA3AEB072D3
-:107D3000B97FB43797FB193D66BA9F9AE95E29BEB1
-:107D4000BB0D5D23C6AD11F27EA6DB755939AFEAD6
-:107D50000B55DFFD4F7C774398008000000000004A
-:107D60001F8B08000000000000FFED7D0B7454C75E
-:107D70009560BDEED73FA9919E3E881692A085C022
-:107D8000164640EBFF053D7D10321FA7C1180B9032
-:107D90004C8BE0041B49DD60E2903D9EA131321224
-:107DA0009FCD621FCC7866BD390D038C9DB177C025
-:107DB000561C610BDCE237384BECC671189C4C3C0E
-:107DC000C243086C6CD318C743B24ABCF7DE7A0FC3
-:107DD000F56B750BDB43EBCC6457E740A95EBDAA9E
-:107DE000BA75EBFE6FD5D37A3363CCCED817F85380
-:107DF0003DBCAC081A19CB65F4F305FCDBE2F2EBF1
-:107E0000252B63DFB9EECBB443F9932CDF0A671E51
-:107E100063AF5F35CAAC88B1AEA9E3F6EAB387FABF
-:107E20008F75088C15437B12748676EF54C17700EA
-:107E30001E31D1272E9D1E7DDE9F4CFDAECD958738
-:107E4000B3FA329D63687AAF3E8DB159F89B0ECA82
-:107E500020932D33A0CCED5AC712A0CC2CF9369626
-:107E60004C622EB1843193F29EE9CA6BDF15F03972
-:107E7000931983FEEB95F556307F5D0DC031CFCC65
-:107E8000BCF189387AD3C9C9D05ECD970AE369D7E6
-:107E90001DDE9FFEA529F3E430362E57A0F5CDFB5D
-:107EA0008CF94CF06B756EEB023603E78771CCD121
-:107EB000C7A9601E99E9011DE55EDB2AE83F6BAAB0
-:107EC000C9E1E5AF4BF8DE6CC6DF1B3ECE7AC64A91
-:107ED00086C6D9E209C8FA54C68E494CE92F5B6FB1
-:107EE000C167E7F8C37A85B23E536ECD55C4CBEB7C
-:107EF00092C7E10778670F868D6F1DCB583A63559F
-:107F00009F699F8B0E6D7D385C30FB58FAE54F5FA3
-:107F1000C07C4633C78F395D47F8795D32FA903EB1
-:107F20002AAED4EE6293184B96EC87FCF0DC2A99CB
-:107F30001D3E053633F6537EAFB8020404ED9FC2F2
-:107F4000BF1480739B6EEF5A27D0DD166C4C1FA2B6
-:107F500097250B4C1A38962E49D4D49B9AC769EAB8
-:107F6000CB574FD4EC6F73DBDD9AFA431B666AEA9A
-:107F7000AE274A35F5559DD59AF156EF9CAB69FF72
-:107F8000D6EE6F68EA6B9E7F50537F74FFCA11E98B
-:107F9000221A5F88B691E98979053BD2BF884D3AAC
-:107FA000FCCFC59CD3A3F7F7217FC27EBD6EAFB7D0
-:107FB000AD82FED5573F8DE7FDB4F4C5BC7200F924
-:107FC000A356D91798C72B407B8D52AD95BE45F46B
-:107FD0005E633645E41B95EEB60A5611C7AF66DA06
-:107FE000FDAAB06DBDAE477E2E1AD0EB61BE5937EB
-:107FF000B5FC572135FC06C767CCAFC7F584CBA5C8
-:10800000FFEE18937A399E60B57F01FCC4ACC98C31
-:108010009547C7A34AA7B75D37635F6FDDCAFCEA20
-:108020007A2B58A00EE93EDABA673BFC7A926B5184
-:10803000D61DBE5E15FEEF6F865F81EF5FFF23F3F7
-:10804000ED1310DBB288FCE6DF5DEBCFB52B400211
-:10805000BC27157AA8918227128B900E980365830E
-:108060007190F9510ED433C16F8452961C04AF380D
-:1080700068EF34302AEB717E711086A6D245EB355D
-:108080000ECA8D286F452CA9EE9CC7EB8E065E8725
-:10809000F7A82ED5F2BAE73E5E8792EA5E27AF4395
-:1080A0003FAAEF5A8CF5CEB8C0894401EBBE2558E3
-:1080B000370E1E5ACA4BFF05814A99E49638E85D8F
-:1080C000A7A77EEC22AF073771FAD0F283315EF6B4
-:1080D000F9B3195F3D3C3F81BF4DC2FD5CD76F00D6
-:1080E0003CD48A82C30EEFD50C32873F15F7D5E416
-:1080F00090D997E033A033316D88CF8C2C98B14A5A
-:10810000203E790FF1ADCAEDE1E368E9AB1EF55A07
-:1081100001EC3BFCBE3119E530A7A7FAB2E0122C06
-:10812000F1F913D03E7B32FC4B1E4E1F2A5CA2326B
-:108130005FA5B55F8FAAB6321826B75917D15985F2
-:10814000799D2CD987CB6D7150E52F2E2FC2E1562A
-:10815000E5AD391FF86C1AFB3A7C96B90A6AB3AEE2
-:10816000BEABF0D9BA303E93ADF79684F019103219
-:10817000D3F0D9B7899E6E275F4E09837526184FB5
-:10818000F60CE823CA9954C04342243E9BFB1BB221
-:108190001FA2C89737F01758676E7E989C51F45C01
-:1081A000B5AAE7FEA8B3A2DDE2677A11CB707CC85E
-:1081B0002C3B31D273B53CBE0906BA6BA80EF890C1
-:1081C0000F81BE631F15DC06CF9BC9CE62B85A80F3
-:1081D000C7AAE2318C6EAD712F9D90ECBC05F5EC19
-:1081E00018856E4E66A711DFC376BDC742E49DB504
-:1081F000E8CBF101CD3709C7736622BFD540DBC696
-:1082000082E1FD33B10FF09935C87C3E78CFEA08A2
-:108210000858AF46FD9E8DF4CFEA51FE575F09E83E
-:1082200025EAA5E5975B7400BF3F01A4578B7C51FD
-:10823000309C2E64E6D3E37E7CD5FDAFB61F349030
-:10824000BC0EDBFF9A41B0CF004E39D5E420FA1ABC
-:108250006464CFC84EC1C748BEAC21BCA8F6E3AD2C
-:10826000F6266817E8912E627BB340F6D0A76CB370
-:1082700081F305F3FA557A86E7CBAF303911ED3447
-:10828000CBF3D47E6C1323FAA8B6973C556747B856
-:108290000676CC44B824BD0A973F15C7BD60E2708E
-:1082A000F9DA087FD50AFEE4411D3343BBBF4F69AD
-:1082B0000FA35FFF20B7D3FC4FC42B70DDC8F04382
-:1082C000BF07D04E069368E5DD03FF4384F7DC6902
-:1082D000773FDF015DAE28F0FC6F856E3FDA2451F9
-:1082E000B93ECDF5FD7CA0C77F916E7CE266C80FDC
-:1082F0003944F7D5F6CF27901E52F1D93786F410BE
-:10830000C24DF8E8B34483DBAA107538BC0ABFE558
-:108310008CC8572A9C2A7C577C7AAB0BC67BB3E768
-:108320005F131CF621F84B45E77E84FBCDC14F67F8
-:10833000B888EF9235766634F96652FC88A44C967C
-:108340002BA6A23E8873CC85758CCB74D1BA4C36E3
-:10835000A31DFD024B2793F360487382CF8CF0F787
-:10836000A737ECD243FBD6A92233C1FB5BB3BC36A3
-:108370005AA7FE0986EB9993E96103D6E8F377657E
-:108380003E29119C835047BFC7C6F1A29F68F4F8ED
-:10839000E0B95FC7D61C0AC1CBC102EE8F9DCDE705
-:1083A000E5DA171ED97629843FDA0FADD3D4DDBDC7
-:1083B000DFDB762954DE6E1044DC9736858EDBD900
-:1083C000C004F45F5A453BE1A143379086F56B2C1E
-:1083D000787E0AAE0FE78F00FF3FE75B623DFFD27A
-:1083E000A950F68FE1FE69FF241FF90DEAFC1F2B4F
-:1083F000EBFF385F177338A6011EBAB3BFC5709F75
-:108400006A6C7C3F4D50727AE67243F577869E73B4
-:108410007951A53E0F3ADE73121DE91CA8764C99DE
-:10842000F611E97D27D2BB71A8BEB548D7E88BF01D
-:10843000FE730522C17BC016B93D5BA1979D135CFD
-:10844000DDD9E8DF3FAB736C8625CECBDC3A1EE589
-:10845000FD56DB7AA253E6E2EB58C038BFCECBF430
-:108460007819E8D179FEB782422AD68DCCC286F837
-:1084700057F50BE7893ED101FDBBF2D79971DD5D60
-:10848000B6F5661CCF84D6826E383CEABA0FECE6AD
-:10849000F3CECBF489E0E9B2B9B97BC501A83FA31B
-:1084A000AC7B5EEE3A6AAF6AF49F14097FE06743E3
-:1084B000DDE868F5E23C2687BD46C23A736CC6B279
-:1084C0004F7889EC1355BF0DE94FAD9D72FABA9103
-:1084D000E463D7159DCF44F2535E3007DE9FAFBCF7
-:1084E0006D0D727BBE6BBFA35FC4F71C02F9E3F393
-:1084F00073BF4D769D35772EB7E7B3567991549873
-:108500004FF0A13F314FC55B9E565F191D17B7A0B5
-:10851000FA30DED4EAD1592CC090BE2AC2FCF370E6
-:108520007D3BBB40B1D7725931DA2B2D26DF63C8B2
-:108530000F960D423AC2A1E27545818EE820867CF5
-:10854000B06726945DD965B4AFFACCD31704985FB1
-:1085500017DF6643BED0DB8C7EC41BB38A1F0DA819
-:10856000F34DC2FF3325B2B7B08E842F7D3979FC2D
-:108570006E96C786EBEC32B0A648F2A7B680F3FD44
-:1085800007597E920FD1DA8D1B04D27BAA7C376605
-:1085900032D937C278DB8C5CCE805FD22B40BF3EB5
-:1085A000A417A0FF175AB3F7E905A27B19E5F1ADAF
-:1085B00052B1EF120BB91FFE668189CA93CA7E546D
-:1085C0007F7136C33582FCAFAAF23084DF94CAC70C
-:1085D0003365F2F14C222F7395713F2EE27CDC5C07
-:1085E000147BB95F9A337AFB1C4B7A8D87522890A3
-:1085F000E879DD9887492EC5126F39A38837A35DC6
-:10860000A13F07A713B5FD7345DEFFAA20E674B2AC
-:10861000B47214E5412CE9A4E2CF83DECF97FF7951
-:10862000EC47DA68AEE3A399F2D442E093BF9C2E04
-:10863000DF83E596D723DBBBF3632F77D31E8072EE
-:10864000F104DF3723E9B37985B197FB4BD1BE48FD
-:10865000E1F645F8FCCB153D144B79D20465B31116
-:10866000D61F01FF8F8EC2FCCB7350EF727B81E56A
-:108670009EB9A40FB1DFE167B22EC43E067B141C85
-:1086800041B443053992DDED8DFD7E2D7D483F647B
-:10869000AFCC615C1FA8F32F2CE1F87A7A14E0B01C
-:1086A00000DEEA256EAF9BC2E050CBBF2D8CBD7DB6
-:1086B0002AE943E04805BB1FCB0542447BAFA7D066
-:1086C00018737E1A0B78D9E2608D91E4C9C9D8EF8E
-:1086D0004B9A0DCAAAE9CED328D7964B87E7605CA0
-:1086E000F9FBF81FE61BD279BE61A5C1E545FFAED7
-:1086F0004BB23BBC768C47ACA2FACA7CBB43AF52B0
-:108700003EB6DF947CDB056CD7517DE5EF241FDAA4
-:10871000C3DF17D69DC9C6F136EB1DFB18C69D9564
-:108720007C838DE71BAC369E9F106D3CEF60B529B6
-:1087300079071BCF3B586D4ADEC1C6F30E569B929C
-:1087400077B0F1BC83D5A6E41D6C3CEF60B5297908
-:10875000071BCF3B586D6ADEC1D33815E391369EB7
-:1087600077B0DA78DEC16AE379079897E71D6C3C49
-:10877000EF0070F1BC832D72DEC13A947720FFF1D7
-:108780001896A467B85F7F54A9CF067BDD34637861
-:108790005EB56AE7FE2D1817AB0972FC5539785E95
-:1087A000D914B4770A307E4566B0DF04FE65451102
-:1087B000C3F0D5B0F9C3F313DDD9E7BD02FAA3B016
-:1087C0009729BC03E529EA187F3F7CFE6171573B7E
-:1087D0008FE7D6657E8BF03BBB2C4878C3E71887C4
-:1087E000AD53F213B556ADFF2A7FE6B2F9715F992A
-:1087F000D49908F890456DBB88F92F8CBB5EF1D7F2
-:1088000061DCB76A501B7715331BD4B83CCF4B845F
-:10881000C139DFE11C5F046B6A017F2A01E6CFC129
-:10882000A415AE53127C5EA4B7DD1B88BEBC3B45CD
-:10883000C71468AA0464609EA512206A86D254C632
-:10884000ACD24CF29B389DFED7D4BDF1D9280F0392
-:108850007A46046C233CA8F9850458BF3483FC2B6A
-:10886000F2EF2A33FDBF473A50EB82CCF338825DFA
-:1088700062CD802FF96E265C3693ABCE906FEB45C0
-:10888000E635C37341E9379B05294E2D3389F276CE
-:10889000B5CC4165D174576911F0A3CEEC75E17A7E
-:1088A000AAEC6609F9853DEE3CDB48F1E47AE93251
-:1088B000E04900F6F862DA48768AC82EABF81C4523
-:1088C000BB481F2F7822C9AD8AD8EB61B2832A0A30
-:1088D00019C9C72D2CB2FC7CAC84CBCF374B5DDFE4
-:1088E000443CD7FB16D58F872E8FBED04A799B6D1F
-:1088F00061F1C25BFD8A626F4724E7903DB901E9EF
-:108900007AF1048F0DE18816C7782AF6F0EC491B3E
-:10891000C1AE7B7614EC5AD443B7EC2AFB9993FA98
-:10892000503BCAB10E4FBAD0EFBA929038AADDC30D
-:108930003C14678D1CAF796914E22099A8BF13FE1F
-:108940000B9D63EA3A02FB87E5FBBC54E1F88E42DB
-:1089500087E34B63CF17D3A0D4273E610B8D1B77E2
-:1089600059040E9741D0C0F5B962FFFDA024F678F6
-:108970002A81727DA9FC2EF261D574F96758AA7C10
-:108980003BDFE1BA40FC292DAA4F02F9BC667F7695
-:1089900001EA8906DB5EE32A80F7D552F9FD223A27
-:1089A0006FF41F5B1E6EB11E8F47BCF7B922CBA3BD
-:1089B000BB1109C5E44FDE28E2FEE467848728FE88
-:1089C000E4AF8B63BE2F7BEA7386FCC970FE1F5B2E
-:1089D000CCE39D6347018E06285746F1EBA68CC277
-:1089E000FC8D5ABF6EBF3E44CE104185E6696CDCFB
-:1089F000AF6311FC3D9735BABF377B14D6B110F386
-:108A000071B591F5DA7DC531F7AF967E03CA0733AC
-:108A10005BFDA9D0C4BC306FDA50BEB2C9D5AF0F70
-:108A20008D733F38E1E037E508707EB338E672F2C7
-:108A30007C9C1EF975BD19E1E96A067E8DB05F2543
-:108A400025DCFF9B3BE111968876633A43F711E4FE
-:108A500009CF3736297E6383A27F762A72D4532CBE
-:108A600052E92CE5F5B951E8FAD7CAFB8D4A9CB614
-:108A70005162F22B91F47FECE9E6FC3828E7C671ED
-:108A800038EF0DF3CFDF53F4C49ED8D3CF9E0CA0A4
-:108A900093B9B591F17530F674B17402CCBFD4F6C8
-:108AA000F41C90F8B02F9B0D945F9C2EBF580CEFD8
-:108AB0006D8BC2579F2B7869863E3AB0FB5BA03422
-:108AC00042F91090815440FAED55EC6F018E30144C
-:108AD0002004DEF1E8E7F43AE41E7CCE5C6DE47F2E
-:108AE00084C81BCA9F569939DF74A783FF88FE0E7E
-:108AF00033D33993AE20CF9F7665F2FC68383C6A59
-:108B0000FEF46F458F19CF71776516C485F2DDEBE2
-:108B10009B98266FDC7585E785C14F8AD3FA49C9D2
-:108B2000E427858F9F90B9745EA87F24C8DC1F025C
-:108B30007F26505C3CE417A9FECF987CF95CF17F5E
-:108B400002FD1DCD9F1147490F8B30073EFFDD749D
-:108B5000F9DF108F23D0D31FA3D0D39FB0DF7F3492
-:108B60007A62CC11B768CCF071BBB21EB7B58E700B
-:108B70003F2021D31991CE54FA027A9B503276E8E5
-:108B80007D21F3B44A6F134B8ABF3EBD5DC0BEF07A
-:108B9000EFACE1AFECD649D1FB9DB57ACC280FFA0A
-:108BA00032D79BF19EC4D4992E07CE6B11996C00DD
-:108BB00038BB5C3E339E7B003B2FBF6484BCC1CD81
-:108BC000222E3F7EADECFFDC099CFF2A960BBE7D7A
-:108BD000C07F4D6C9701F74D7DFF5849ECFD887BB8
-:108BE0007248EE35968C20F75E56F8E273055F2BDF
-:108BF000DAD629E7995844FB6755ECFD8C342B9461
-:108C00007352D745A4E35B7487E78522AC6714E20F
-:108C1000E0E7C7E4E03C4CCD2B6D40FC3E56C4F190
-:108C200017CDFE7D6A14FCB38900D74AF69901FD81
-:108C30006959FFC7AC48E7118E15D9399C069003D6
-:108C400080DF9559BAB731FCD995A4B587D4F767B9
-:108C50002BFEAE6714E467520ECEC3F11A7E0E4CA3
-:108C60002DCFC53E1EB0B488FBB9FF80FC0EFC734F
-:108C7000A8A458E3E7FEA864643FF7B57F8FDC1A29
-:108C800050E8A8CB11D99E7D21F6FB40E7E060DDDE
-:108C9000EF7C15B9116E6FAAE59ED8DB7B69597A16
-:108CA0009C87C3D1C8B4E7246EF1DF28E02D5D8F27
-:108CB000F368E97725E3FA5F85C3581AF3738CE705
-:108CC00067E831FFC3F9797DA92BBE94EC368F1983
-:108CD000F537D80714675FB939251FCD2AD8676BD8
-:108CE000A996BE934A47A6EFE4D23B40DFAA9CFC7C
-:108CF00017614C53A8BC99A8C89B69A5B1DFAF29DF
-:108D000018AF488E2CAF2B631FE7DB73774E747957
-:108D1000AC9E37FB47411B4F6EBD258F634E4769A5
-:108D2000A9FA2179ACEA87703C8D865E480CD10B9C
-:108D30000D51E4CC68C03136041FB59D02E5AF98F3
-:108D40008DF9A6C0AF9DD839E4DEC7965188134F80
-:108D50000F8D7FC860AF47A0E3DDA5B1CF7FA3BC77
-:108D6000E9377CDB36D2F947A3D5C5283F6273319A
-:108D70003BEC9FB1B395F2F6C605AD9487669D02B4
-:108D8000E5FD98F42EF979AB6CDEA7307D365C9E5C
-:108D90006C8D395E8B72D897F637C5287ECDEBF88F
-:108DA0004A3AF937AFA33C1524EE47B30DCC4EF742
-:108DB000A4AF7CB9FB582F2012302F9AC4E83E761E
-:108DC000A7E1C77ACC471B053EFE5CE6E7F94F9763
-:108DD00077FCA3F09EE5A0317F3B547F519A4DFB79
-:108DE000DE69E5CFBBF69BF39F84A59EB6159EC1B9
-:108DF000F3E153A727531CECC5038F6BECEC5ABC73
-:108E0000C7807EDF0B1E867EA229D33571243B9C52
-:108E1000317F92AE8C509AA8947A5EFA059D6DF8D7
-:108E2000FB3BF7F748E867BD78C04C727FEA819E4C
-:108E3000F85521E32796713EB6063DFE1900AF3581
-:108E4000D3733209EF1D2BF9739179CED4C22B6302
-:108E5000A4009D0FDF91576B0EA5BB2EA9D64C79B0
-:108E6000E45C9D638A1DEBFC1C43FCF4DAFD82404C
-:108E70007EDD2E1150EF9AE1BA867AEC0D89EBC3B4
-:108E8000A9536B49AB752AE71E76E42D3980EFC7ED
-:108E90004FAFA7F13B59647BCC58C6E5F08B0699E0
-:108EA000E67DF18048E7C855BCDE697CD6CB300F43
-:108EB000E0A3DEA6A77BD8A78D4E11E5D0E93481CB
-:108EC000ED822DDFE97885EE99EC8802EF2F4AB923
-:108ED0009FCA6CA9447FA7F7772E8F747E5FA5BFCA
-:108EE000C93364A90CEDC0499E2694FFCCB6E43684
-:108EF0007CF124DFBF4387E6CF03FCCF7DC17F2217
-:108F00000EF7216BCF785CF707A5766ABF450F1F78
-:108F1000BD42F4B0C5C8EFE37875718E03B08E859D
-:108F2000D60111CF4F18528394E76D2AE3F2748B68
-:108F3000CA0F63811FE03D7D06BF07C526DAA9CEB3
-:108F400026072784DEA39E55A6AC970532F1F9C209
-:108F5000F87737D81D8C15F6A6378BB0FE8589EFCC
-:108F60006EC8867A49EF785ECF78F7B36C89B1B274
-:108F7000DE0C5E9FF6EE6793A05ED19BC9EB953049
-:108F8000D478B09B7AB39ABD7938BEA419BF150FB7
-:108F900072147FFD526FD2458C5F3528EB871F031B
-:108FA000CEE3ECFB473AEFE2345BFD782E83C986D3
-:108FB000B0F8193485DC7760A90924FFD4FB0BF3E2
-:108FC000457F3FF6D799FD84DFBB5927D97380AD24
-:108FD000DD5F147E797B2E5CEE6DD9C85C784E8C9B
-:108FE000B16609EF33084CD67DC1E3784E9C5F85AE
-:108FF000479D7F185CB0B5C89F43703D4FE3A87094
-:109000005DCB377951DE7A6B59AE27044FD784E0B8
-:109010000F186C45DAAC1D0FE13E5D1B139C204020
-:109020003DB97C1BEDDBB5B1C11F088E90BA81EF55
-:10903000635B6F09ED639728B7219D9B8CD66E21EA
-:1090400091B1EEB884190CE6D931D6E5C57B6E40F6
-:109050007774EFD89B65741C0038EB8BB4F9A1C70B
-:10906000153AFB83220FE6987679CE015DBA7B0430
-:1090700086F770DC83378CA8FF16F65D3462BEA4D9
-:10908000A3E7A211E9BE03EB304EC7F3C688F96F20
-:1090900063B95EBD2F4AE791D64B1C4FA7B2EE7A5B
-:1090A0002A15E0E9582DD0BDBCF54792E6607D7DDC
-:1090B0002BAE92B1E55587E720B9B438FB9FC27259
-:1090C000251B38950A24B4CCA567F6103DB9624D2E
-:1090D0003CB387E8C9164F8AA6BE7217ECCE0C289F
-:1090E000376668FA31E5FEEA3236F483E7989A94F7
-:1090F0007D5C66DB19C0B8EE3297C13B1032DEC230
-:10910000BECD6232C2ED111C748DD2CBCF3FADE02B
-:109110002B84521C7A1FCFF7F40AC4EF1D6D7ABA64
-:10912000C7D3DCCBEDAEE63582CF2E201EF8BD0DC9
-:1091300077AF40EDEEDEA7EB9311EF1B000F00477A
-:10914000DAF8847D2C114793E9DCD54A055677DFA0
-:1091500039038EB3E23B02DD6755BF9BA0C2BFB2AD
-:10916000A991CE91017C5EA44F759D4DF647E95CB7
-:10917000D5CA89970DA887617D970634F8D4D65B48
-:109180003CDAFACA8DDAFAD132E59EF234360DF9BC
-:10919000E9789920E23924B5FE51D6F9B7F15EE7B6
-:1091A0006ED1790AE9B3CDE89F81FA7EB7E8A2BA19
-:1091B000DA0ECF3B18F19DF8E100F1B140FCB9C5E2
-:1091C000204B35F83D977681E87605B6ABF3670F0F
-:1091D000BD4F75FDF0FA4D55EE5A9C1BE8BB30476C
-:1091E0000509ED907A511693F3882F229E77F9BDE9
-:1091F000C2076FA3F603B8EE4222857DBAEBFE44A8
-:109200009F17E6BDEBCD563AE7765721D0811DF981
-:109210005E47E7D6E6E3792F28EF03796881F22EDF
-:10922000FDA12692EF338D12C977E59C972A2FE492
-:1092300017B5E7B6E6679E213BEBBEE776D279B578
-:10924000C93972C1D3A80F2D7CFE1D4704DF6618F3
-:10925000A723EF34C9CF71323F2FD76153E4682F72
-:10926000C85175FDB0BFE350AE612269411ECD9B70
-:109270006E56A95D263928F86B75E8FF8E53E6DD3A
-:109280005F6DA775A73D7A48C0756731EF6601E647
-:10929000BB823A7CEC50F955EDD7B5F80BE85D563A
-:1092A000AFB5635B45D7E365305FBB6DC0C8CF2DFD
-:1092B000068DA81FEEE0F8DE48E3C3F27574EE50A9
-:1092C000E2FB30473F988076CEFAA339E3D808F620
-:1092D0008DDEACD3C8118314A79137F373B5F26751
-:1092E000A1432B77BE5196A3695F244FD3B4DFDF30
-:1092F00058A8A93FE0ACD4BCFF60539DA66EB2CD88
-:10930000D3BC6FB12FD6D4E373976BDE1FE358A5A0
-:109310006937BDF5A32601ED71B377C00578E8067E
-:10932000DE284B1ED223D312E06528E30A2D562CEB
-:10933000BBF34D744EB67B3CE89744ECFF1D3A7787
-:10934000694E7CC95C03E5DF0BBE5AFC7E0EA0C9EA
-:1093500085F6DB3D4F68E3F0C7AB385FA96543B9DD
-:10936000EBC10A28F35EB067F07BE9817B707FCCAC
-:10937000718CDB45AF99C92E9A89765388BF71B03D
-:10938000BA667E39F67B42BE17F982F532690ABCAD
-:10939000B7CF083B8B7AEE3523F5CBEB1DD085E6B6
-:1093A000F77F59CEE5C1B3CEDA7B71FC8E3ED0B2E9
-:1093B000C84FCF7D6844BFAEA3AF3F01F5D90CE7DE
-:1093C0008746B4CF879E2B7A4E0CC6619CE31F0E56
-:1093D000E923DE63DD5E6EA4F14F2B72BDE53B7ABF
-:1093E0003A4F8BF7376B4A86E473CBE1A01FEF63EC
-:1093F000B7B4F37B9B788E36929C06F9FC61A8BCCF
-:109400007D361DF4C14C1A4FA30F9697F9E9DE3E45
-:10941000C86FCDFB2B97345CC57C25C871EDF34C30
-:109420007E1E96B10103FA7320D735ED1BCB95FB59
-:109430009CD358DE1720072E3823DFDB7DBB8A9FA5
-:1094400033B8E0AAA37D7816F089E7479F1D863FD1
-:109450008ED7DBE1ED65A48190FD1B66FF5771FFA0
-:10946000EAE52872FBA2B2BFFB8440010A55B7337C
-:109470008EE87785B975EDA542DC97CFB7A2BFDE40
-:10948000F22381EEC1FFB2FFAD343BACDF78F8547C
-:109490001ADE97761F3A9586F789DB0CF6CD68CFF2
-:1094A000037DD03DE48E5E3FC1DF7EA8B01F9FB735
-:1094B000F70A0E14C9EE9EEB0DB44E36B015FDA39F
-:1094C0007D51E03A58CEEDABC3E5762ADD2E9813F8
-:1094D000F57E8FC9E713901E403E215C47C00F8286
-:1094E000FABE6DE6A648F6D46505DF27B71919DE82
-:1094F000FB6D83FEB88ED359A78DF8BD8596C3B09A
-:109500002E01D771EE81781C7F8381A19DA1C2F7C6
-:109510007156E0035CFFFBAB0D0CCF2D6F59AD27EF
-:109520007CBFBF81DB27FA877FBD3503EACB802E66
-:10953000F13B0F2756DF389D01E3BEBF86DB69751F
-:109540000F1B882F97AD136EDD4B0EA56B956EFF2D
-:1095500046A1D370FA0DA7DB61F4BAE6EBD1EBDBE1
-:10956000E5B7EC9019A8F761FFE78C433AFA1E7350
-:109570001C407E1A3C611807704FDA2A39C0C36359
-:10958000D3F5BEA7D2506E9CE0EDF96D7B052E7F22
-:10959000ECCB717D19DD4686F7082E2AFB7651D972
-:1095A000373B0B0AF1C8CF626012CAA96C25CEF90D
-:1095B0008A81351D46FF52E4F267FA8F6D7BB787CB
-:1095C000D0EF7F2BE774ABCAC56946E63A6CC5F7A6
-:1095D0000F8D5F04E3BC6CE0E7352728E34DC90934
-:1095E000362C825257C1E5E46F1538D4FA9F143EE9
-:1095F00060277F43F85C68E6F89FB7D1DF8CEBF813
-:1096000099C975BD1CDE5F30E17C1BEABDEE493FA8
-:10961000C9E3DFB973901DEE56F07FA2FC37CF632C
-:10962000EECF32358EF6D772F46909E9D932A568E2
-:10963000DC48F130F7CD6CE64A01BABA9943A55A35
-:109640005F74FCAA7180FC82EB0DC42F37D3E9B99B
-:10965000DAEF5305EEE9468E07D6974A7A1BE4B651
-:109660005816926750F1A0FAE39629FB69BF1E5B7A
-:10967000C728EECFD8D3848F156DE7845618E741FD
-:10968000836CB002BECF2736ADBD3485B19F6C620E
-:10969000CC050B3ABBC9CC5C77037D6C92A81ED875
-:1096A00064A3FABB9BEC545EB638C7A2FE79E0A473
-:1096B000670AE2ED44D61E672DCC73EDAC81F04114
-:1096C0003B06F4FD98426B37FAF4CC0CED377A94F4
-:1096D000EFAD28F03F743383B940BEFC02E7838EC0
-:1096E000ED1B7F4672CFB1E67A03FA49F96D17B7E1
-:1096F00062DDBDF1770D685F7C00FA04E90CEC7E59
-:109700006613509E9C33DA810E9A6FA6D0382FEBE9
-:10971000820DC877DE630243FAFCA0F7BA711CD74A
-:1097200057742DE1F94D74E69F2DAD4822FCB8FB2E
-:10973000F2757C7F8B74A1F729FAEFF94302EE876B
-:1097400079A3FD9D4AEC7F46CF90AFB7D70613A40F
-:109750000872F8028C8B97A3701D5886B73719BD15
-:1097600053F03C419342C7E1ED8B15FA044C1B9436
-:10977000EF2932218D9F23C19F1658526232F94141
-:10978000FE38E0E796BEBAAB22961E817DA8F5CFE3
-:10979000D88721767C343AFCB2257E43E6C3294340
-:1097A00075F42343EF7FA01F19E9FB82A6ACC9E340
-:1097B000468A77B907C0BE83FDEA00C3C99E82F41A
-:1097C0003E8DCA4F8E74D9917FCC71C13DA82FD8E0
-:1097D0005D3AF23BDABD5A7BA841E18706C51E7AA5
-:1097E000B442EB3F819FD45EC1FDA484E34CE33FD0
-:1097F000853F27FFC98C7C05F34E83FD7925D2FE7A
-:1098000054D5AEC77E13D82EA27306748EF415BE3F
-:10981000CEBFA8E07A54E5EB65C8D748BFBD9CAF82
-:10982000C3C76DA9AAF90B1C775B947B10F757F19E
-:10983000F1DA9F13085FEEE752084F1FB3E79CB5BC
-:1098400040971F031CFB802EAF399DF149D0FF9A32
-:10985000CB199F6C1D92031DCFC553BF6D9317A7E6
-:10986000B442FD19A47B18EF93DE3A8A6F3EF41CD4
-:10987000E73F75BE0FFCCB52909F8A0D41A303DAE0
-:1098800033FB2E26A01D587CE4FE14E4C368706EE2
-:10989000AD54E0DCF8D8DA4B299C1EF01CEE5A459A
-:1098A000BFB99FF41B11FF6B3732A2DFFED77ED901
-:1098B000817CFC495FBC84FAF0E3A3F15E94FFD79E
-:1098C0008E997C3A81FC106F22C8B58F0D03F791F9
-:1098D000BD79442FA1FFE83EF6DB3DC88FEED74CA3
-:1098E00068F9B1B57D5DD751EFB5F5DD7B55C4F2B3
-:1098F000A5D1E587F68D8FD37AD5FA6F3799ED2804
-:10990000473F11B99C58DBFB2AD9BF6B076FCCC00E
-:1099100038EAC747FF4F09CA35F79B374A509EB907
-:10992000DFB85182EDEE1FC77B22D92D71B3F484CD
-:1099300057555F66BF276AE2451B14FAC8EEDCD5AF
-:109940003809F0577C6E8903F3B66A7BF1149D13D6
-:10995000DF2FFE797DCAC321FD3A0322E58D8ACE31
-:10996000D5C7AF0EA1CB47AA0C9AEF947DD5380F7F
-:10997000B6E2F72D6FC575023AFA0EECB680C8BF95
-:109980002FBB46F0A1BF01F64B783FB2A7AE3D9288
-:1099900042F71099E89C3FBD08EB531CDBED2856BD
-:1099A000CCA72687D84BCB023ABF09E8A8A9CFE4B9
-:1099B000277B3F205EA4BA62473D74FD3763B285C2
-:1099C00008719ADC77E7A01C0F8FD7C0CF18845B93
-:1099D000B5AFCEA7F3F851A647D22D04B89A3B995C
-:1099E00084781D16D7699A4BF1A2F0F88E3DB0DB52
-:1099F0008CFDEC937512C2ABDAA5B88F3D11E4C0B3
-:109A00005F567279A6F2576780E7F53A03B5E6C963
-:109A1000507E5769EF9174CC0B78E9ECBBFF00C620
-:109A2000173A071F8C9F0EF374BEB798619EE79A92
-:109A3000546B9E82FD06E79A1FC81BA29BF0F91A81
-:109A40002AB95D34642F44D67FA50A5F8F961E2CF9
-:109A5000ACFCF3D083E09F575472FF7C058F9F705E
-:109A6000FF3C5C7FA872591D77AD82EFE172F92A45
-:109A7000D939E047935C5E5B69A7F732FB16A59086
-:109A80007FFDDE9214BB75F8F839A243979C377CB2
-:109A90007CD59E737BE55366F47B643DF1A77B899F
-:109AA000E0C3FC976AFFB99D02D9E5EE66830FDF3C
-:109AB00053E10A2CE1F1D8076483CF220CD989AA9B
-:109AC0001D79ABDD2150BB6A57AAF663C0C9E3BB61
-:109AD0004B8A78FB658B6B55E5585CA7859E17977D
-:109AE000F3E78C394FA15FF5E05281911C50EC4AAD
-:109AF000954EC3EDCE4FFB7212478A433DAFD0A7C0
-:109B0000CA6713C2F843D563CF54707EEB403D5E05
-:109B1000887AFCF71AFB3C7C5CD0E38F57523F46B7
-:109B2000FD8B7E2E3A23F9EB6665FCADEAFE054E11
-:109B3000D620BC592CB019FDCC68FAF57B8A9D1350
-:109B4000ADFD19C57EBC1D3F1F56E4C868F1F3CBBF
-:109B500095B7F270FFA9F9F9967D688C62BF57D569
-:109B6000BC86FB1FA7F7046A90FFFE9781E2EEE137
-:109B7000EF3DA5FA9F22D3ECCFA92CA30EFD23F72E
-:109B80001A1E3FE84EB2BF437ECC5B7A86E3AC053B
-:109B90007F10EDB8476F2651D986F632942B5E3888
-:109BA00047F988156BB4F077634C17FBAFCBA6F37E
-:109BB000032DAC9EE24C2D7D49D216500ADD630F79
-:109BC0009D46BEF21ED0DB0F84BEFF88FABE99C749
-:109BD000E136A6FB28F71A660FB478C2ED7EAD7D9C
-:109BE00050A9C48DA2D9096FF45BB85C39A3273E94
-:109BF000EFC078D34CC68C7D5C2EB837F23849471D
-:109C0000DFE604FC086ABBD27E450C501C8AF26B6E
-:109C1000F0EAD5BEA7D3E83E97ACCD27B5EFFF3924
-:109C2000C9CBF0BC52720F974BEE36BD92472AA1BA
-:109C3000EF97B7833F390EED4BBBFD1B8877808BC9
-:109C4000F948DEC89AB8CB3E25AFF4E9997F253FA5
-:109C500074C5912879A4EE793C8FA47C2777781E6F
-:109C6000E9F4A90CFBEDF3481DBDE7E81ECBEDF2CE
-:109C700049A6AA5B711C8A3B4E14797C77629F20AF
-:109C800061BC6A621F5F77E9B638B2AF1B7EB53A36
-:109C900005E581BA4F9F2CE2F8FDE4FDCF6AB05F85
-:109CA000C9AF44C902EB7AE3FD0D3FCBE075BBD9E8
-:109CB0008EFD36C4A33FF3C9AFD6C7237EDF801223
-:109CC000F7E7C717C4C8F1C9A178756615C59D9592
-:109CD00078B508FA70CC505C27BCDF8B555C6E748D
-:109CE00083BB4271CD233CEFDF9DEE9A47F5BF9ECB
-:109CF000C4F8DF2990291EFD2AD035C68DA6C16281
-:109D0000312FFD3FE35827E691BAC7BA7E427CF473
-:109D1000D73A3BF211F4A7FC93F7B09DF423866A7F
-:109D200031CF33033F5B40F7315229DF738FB28F5E
-:109D3000E9E0CFA25F09D02CC13CF43425DF332306
-:109D40008E8938FE0E836BFB54CC2FF58B8ECDC4E1
-:109D5000048E143C6F199E7712649E2F57F34F6A3E
-:109D6000DE3C5AFE49C07994EF56F0F396B280F982
-:109D70007435CFC4963A29F9B5A5CC43F7427C8017
-:109D8000B3AF73DE6B84FCCFC31511F23FEB2B989E
-:109D9000629F69F38DDB735F213AFDAA79C6C378B0
-:109DA000AEE28EE6C5ECDC0F0D83BB28E9D334F2BE
-:109DB000BBFEF86F09A467FB6E903EBC1634B10081
-:109DC000C51F0778DCBDCF4071866BE0BF8D0DD11C
-:109DD000B3EF54F0718FF7D511FDF704EAE3F1FD0D
-:109DE000DF2BCFB7BDB7E47EB4F7BD01FE1D0BC6B8
-:109DF000B83FD613108BD16EB983FBF2646584F53E
-:109E000099E3B87E0AE7A35285FF4AAB389EEBDEA2
-:109E1000E77E987B03CFAF488A5C707B785EFD74E9
-:109E2000569AA0C6D3C745CABF1C0992DE687944BA
-:109E3000A0EFC97CD9FCCB33E991F3F12B7A2F4603
-:109E4000CEBF343690FC8C16CF0E8F63FF9D2AFF59
-:109E5000A6F338767A9544EB4EF6E4D78C6343EB61
-:109E6000BF83FBB07456847DB883E36F9C1DDBF128
-:109E7000EBCA633BFE13311E7F7B8CC7FF61796C9D
-:109E8000F3EBBA8AD8C2FFDB18C3DF1F09FEFF5706
-:109E9000CF0784E7FFC3CF0B849F0330BDF5B01716
-:109EA000DBBA849D413FC3EF8DBFD624801C149341
-:109EB000F6D37DCE05E53C1FB6ADDEECDB2B0C9D6D
-:109EC0001B50F1F56835F723A5BCEB5EFC5ED404AE
-:109ED00039509F82F1B272FE7743AE59785E8C8919
-:109EE000523AE6C9E0CDF4C56097745B22E7595356
-:109EF00095F1A2E99183D5358B6715E31F3D8A7CE7
-:109F00000EFF874A1C52EAE5F7E999684F5F4CF368
-:109F1000DAD3D11E4A3CC99F27F899BC97E0B267B3
-:109F20002FE67FDC201BE17B46C9FF26CFBB2B1B26
-:109F3000E3D2C96017625EF069CC0F923F2BD17BF0
-:109F4000EA7C9766713FEA190313309FEB9DCACFF5
-:109F500039B19EDF91FDA6E6F5CE1AFC975A05CAE7
-:109F6000EBB523FC3FD5F9F3F6652B440CF8CDEBAC
-:109F70009128DFF876F9DFE5BA681E9EE77B4CE2B0
-:109F8000AF9C40BF19E078EC6821D1EF8AE3E5FF90
-:109F9000D48CFEC76491F03CCCAF54E205179478A2
-:109FA000871A2F50F35BFFACC4493EC0F80B9403F3
-:109FB000180F8172FB2CDD9DD64FDB6745E0FF67F4
-:109FC000041E1FF2FE94C7870A8D8E9CD0F3947FE7
-:109FD000358BEF63AB9FE72FD478CF0F95F5147EC9
-:109FE0004FEFC7EFA1156E9D6E443D5FB8352B0E48
-:109FF000CB19B24F9706F85EB6FAB04EDDBF487483
-:10A00000B45759E7B63341CAEFBD1A96F7BF348B40
-:10A010009F6768A9E6FB7B09FFA018D41F9B226EEF
-:10A0200041F331B14AD247CA2BB5805F8C70B67606
-:10A0300073B8557CB7F8ED7538CFC553C1AD581618
-:10A04000ACC9AEA3B87BDBF5AD68BFB9076F9CAEFA
-:10A05000A67899D18EFEC44303DAB8DB13D53CFE53
-:10A06000FE2A1AE088B77B45F28F0BEF15897E92A6
-:10A070005B2CE4BF261B98DE8AF545DC2E2A684C53
-:10A08000ADC33A5B9244F660C1197BD2C379437188
-:10A09000B0E47B378C453CDD2ECFAAC6D32E5BE4E3
-:10A0A000E3B89F5F35CFDA7EF63D3A6FAAAE4BC577
-:10A0B0008B9A2F8D966755CF3DB81B3FD39CD3709D
-:10A0C0008BC1068C3F161EBD6854CE5F4AB6ECA10C
-:10A0D0003C6CE191EB947F55F3AD6ECF75B2ABA1C3
-:10A0E0009F11FBF76CE2F9D7D7000E2C7B61DDB234
-:10A0F00009EFA1DBA8EC8375E3F3639B72A9F46F0E
-:10A100007250797C531995F899C9F464CCDB5EA739
-:10A11000BCEDD559C3CE4D525E6FB7E8FC08F115C2
-:10A1200092F7A37A78DE4F1FC7E335EE3306FABE07
-:10A13000A1FBAC99E4774D5FEB44F40F3E3FE79A07
-:10A1400088707760DE2D842E3E911D9624F4839DC9
-:10A150000E0BE6DB0AFBAF1AF13C4C871830623C71
-:10A160000C20CFC0238BEE9EEBFCDC6F5F8D05F1E6
-:10A170007BDBFC58EFFFCF8F7D95FC5877353F2771
-:10A18000ADCA9102A74EDE8BE519D9F270889CD832
-:10A19000E6E4F9946D9327111FEE764E4A5A1D326C
-:10A1A0005E67238F5F24DF3BD912FAFC97D53C1FF3
-:10A1B000962C306724795633FBEBDDC71B416ED7F5
-:10A1C00044B2FB3FF929D0E54CA08B23DF9E3890A9
-:10A1D000C7193F341EB7AD71F5C431289F2E98D8EA
-:10A1E000141EAFD3C4E358585E2E5A5C6E45A34E7E
-:10A1F000B6D079A1E004D4DBE1F13326062770BDA7
-:10A200002E67E0BD1498318395B161F9B95F30DFF5
-:10A21000CF27C3FBCB1A75A42FD43C5D41A3C8360E
-:10A22000017D166C34F8283FD7285EA476C56FEC04
-:10A23000940A3290CE3F386B9430AE161E1F7334A2
-:10A24000EEEF9E04FD1D6D02DD0BBA5D1E4F3D0756
-:10A25000DED2DB3F07E36DF96C57773DF4CF9FAC5F
-:10A2600093F0FCF4F07C1E3FFF5DA0D839E171361D
-:10A27000A433B44BC2E3F01B153AD8389BEBADD7EF
-:10A28000147F531D47ED174E3F3F9DCDF56DB4B87C
-:10A29000FE5165BCCEC6826D93717F17E818EA93B4
-:10A2A000CEC65AF3E490F176CCE6E7DB9EC1FC60C3
-:10A2B0006A687E90E701C3F382AA9C2BECFF7D03C2
-:10A2C000E27B37C86BD4636E1BCF1F141EAB398380
-:10A2D0007263084EAEB777C39E07C8BE732431BE03
-:10A2E0002EFA7B45DEA302C5E70A167C763C1EEA01
-:10A2F000CC9944F7B0DC67276FB1A23C5A2016E333
-:10A30000BD1EB753B89567C27CD2FDEFACA1EFBCC0
-:10A31000163E907F0EF7E58166039D0F54F5DEFD36
-:10A32000EF3435F0F6BD4FC6617BAEE0B0D8F179C1
-:10A33000237D3F76FE4B7EFABB580B113A90E781A6
-:10A34000B39744E49BCB16D7DF231F152E52F24C54
-:10A35000CD5C4F3FD0B7C8C0C8CED3EACD13599F0C
-:10A36000533CE8465F21E58F52F0FC43DE90BE2966
-:10A370003C0A7A6CCC9DD3633F9D2D113E67821EB3
-:10A3800043789217F13C7DF8FEEF50F63F9A5E8AD3
-:10A39000268751FFF0FB63DE0CC1365C8FDB31EEAC
-:10A3A000538AF63A94E3A2D3DF1F6671BA4E8A62EB
-:10A3B000CFFD49A1DFA8E7A77A4727CFF487D97F48
-:10A3C0001E7963D5FF52F34DAABFF6A0620FAB65AD
-:10A3D0009352FEBBEF37A0728D78BF2139F2FD8614
-:10A3E000870E0968A7A8F71B4E1959CDE1543C4FB9
-:10A3F000ABDC77F22D223BE9D4DFFC62EB8BA97852
-:10A40000DF4990501DB51F3A477ABE1DEC23B2A715
-:10A41000FA7ECBE3AD87F8F9F0F6DEC8DFDDDBAD21
-:10A42000D8DFF53223B9D1AE9CB76DE851F244B70D
-:10A43000E2968F8BA1714BB73D30563DC7EB237F22
-:10A440004F1BC78C16B7EC60413AB7DBB14670A022
-:10A450007EB8DD39DC5DCA79DDA8714C79E473B969
-:10A46000E1714CB95A9BC7B96F96C4F7DB250868F0
-:10A47000EF9A75CE363AB77F4C90229DF35E5ACD57
-:10A48000E5F47C250F72D0C8E9E3608540F76FF0F2
-:10A490001E1EEEFBC163FC1ECEC1027E0F47CD7BAC
-:10A4A000A8F76BA60EE53DE8FE9D7A2F47BD67C372
-:10A4B000988FE05AF45C1C7DC76B87E1908DDBBD03
-:10A4C0005E7E3F1A6510E6434DCC13895F6BAB6B24
-:10A4D000C46A7AEF8EDB4F8F5447F07B7D8A1FE989
-:10A4E000AE8EEA2FACAFD6FA0B540FF717EE54DE50
-:10A4F000E38BD9EC4EFBFB87631C8F9E323BB6F19E
-:10A50000C4EC48FBB6C5A2FD1EAF5A5E56E4DFB0F0
-:10A51000EFC50DBB2FC9F57AB760FFA74ACAA71BC5
-:10A52000289FAECAD5EE317CFC1F29E3A9654029DE
-:10A53000BBA37CD7F9974ABCAC4B947B10EE692F38
-:10A5400068E397D30F69E397337B9335F57CFF7806
-:10A55000CDFB85672669DA8B03F768DA4B2F146821
-:10A56000EAE503159AF72BAFD46AEAB382DAF86505
-:10A57000F5CDC561F7387DB4BE1AA0DCD07E75E696
-:10A580006F6ADECB58A35D579647BBAE891BB5EB10
-:10A5900052C7CDF66AD797D3AD5D5F32E6E3F2BE20
-:10A5A0007E3E2E7FB65DC9C7E558B0DF338D932D53
-:10A5B00068B7A9F7A9D5F7FE2F376658DF407F00A7
-:10A5C00000000000000000001F8B080000000000D9
-:10A5D00000FFB3E46660F8510FC17BB918186E72C2
-:10A5E00021F84301CF6786D06A2C0C0C1A40CCC6E8
-:10A5F000C4C0C0CE44BC7E714E047B1D0703C34C57
-:10A6000020DEC831F0FE1A487C9D877E76A9F34291
-:10A610006859C181F73708570A3130B40A3330C45A
-:10A620008840F80CA2A8F2554208B6A924657639EC
-:10A6300002F5030024CC7134800300000000000008
-:10A6400000000000000000001F8B08000000000058
-:10A6500000FFE57D0B7854D5B5F03E731E3393793A
-:10A6600064F2200F02F18400A242180284870827B6
-:10A6700021C4A8018380BC54263C43483211A8BFA2
-:10A680006DBD77260411ADB551691BBCE81D1014D2
-:10A690001575A0D1061CE84014B1DADBA8F8A8D5DE
-:10A6A0007650444048C2CB8B2DD57FAFB5CF49E61D
-:10A6B0009C4C48D4F6BFFFFFFDF1F3DBECB3CFD9E0
-:10A6C0007BEDF5DA6BADBDF61EC1329A244E22E465
-:10A6D0005BF8A365842784F4E92CDB0ADA8F9164A4
-:10A6E00042FC2F8BF2368E10EE778EF0A45184BC94
-:10A6F000B5990B98693DBCCF4608AD9FDE343D60EF
-:10A70000CE2264FF08B302EF9FDE9A8FF5C92FBDFA
-:10A71000E714687BD54BBC0075D3BE13CE889D1063
-:10A72000AFB9E5A16BE9F3F69778B2850E45FC93D6
-:10A730004D2485906316C2FE2EB2FA522BAB566D95
-:10A74000DE7F07F45BDE642656DA4FD5EE65D3AEC6
-:10A75000A5F565874402AF546DAB95FAD2FAF200C5
-:10A760001784FA9A7D7FC671DA0A48797028212702
-:10A770007D16225F49EBCE969459F47945606711B6
-:10A78000BC5FB183739BE8FB159BF67F0CFD5734D0
-:10A790008A0379DAFF8AED36220F61637F4B601EF0
-:10A7A0004BA601BC556F88C44CEBE5975649047025
-:10A7B00024D44BA50E18FF614976C03887701C0D54
-:10A7C0009F55CFD071E877D52F706E985AB589789C
-:10A7D000009ED6DDD6394FDA615EB5D260F87EF7DD
-:10A7E0007D12BCB72C50F6B25506F8364B4500E743
-:10A7F000A6CDD2D2A19DFDADD8FEA60EAE630DD9D9
-:10A80000A99EA8766379D247886CEEAC5710A20453
-:10A81000ED0077409A3EACF3F9792E8190D1D03F8C
-:10A820004F644B67FF9430C807FEF7E83F810FF68F
-:10A830003A02DBB23AE9B5D245FF2D77D2EBAC4B09
-:10A84000A59FD09E17DDBF563E0474A0F0D4FB5CDC
-:10A85000583EE24BC372834F46BCFDCA3704CB0659
-:10A860009F1B9F3FE61B8BE5269F82E513BE622C54
-:10A8700003BE527C6F8B6F0E965B7D1E7CFE94AF89
-:10A880001CCBEDBE1A7CFEACEF6E2C77F8FCF8FC0E
-:10A8900005DF7A2C83BE7A2C77F91AB06CF405F0B8
-:10A8A000BD977DDBB16CF205F1F91E5F1396215F58
-:10A8B00018CB7D405F5A867D2D581EF07D88E5AB14
-:10A8C000BE087E77D0771CCB0755BC3B27907C8198
-:10A8D000E2CDA9101715179258A2E48BB49E58CA5E
-:10A8E000EA29B7F9F3255A4FF1D03AC563DFCA70A8
-:10A8F000BE99D6FBD6B0F6CC7B488185D633FDAC6D
-:10A900007DC0834A8195D607D4B3F6C19BFC0571FF
-:10A91000B43E38C0DAAFDE112EB0D1FAD541D69EA2
-:10A92000132293EDB49E1366F5DCB794C90E5ACF8B
-:10A930006D61F5BC8FFD939DB49E1761DF8F3F1550
-:10A940009E1C4FEBE3DB59FBC44BA4D045EB130932
-:10A9500087F5027B7E6102AD17B858BDA85F9920CC
-:10A96000C7E0BF7D626411A1BCB0DD7FB322A4D378
-:10A97000BA145945DC149FFE39580F8B6431B4BFAB
-:10A98000E52F538471B42E91D5D0FE177F05B61FE5
-:10A9900010656C6FF7AFC2F603928CEDA6DA7BB050
-:10A9A000FEAAA8607B72EDBDF8FEAB9282ED836BD0
-:10A9B0001FC2FA41D183ED636B7F8DEF1F943CD8AA
-:10A9C000FEC8DA805248EBFFC179B6005FD7719EAE
-:10A9D00072920DFC1A4C2BA5FCBA8E2373403E1EBE
-:10A9E00000A6A6F2B02E5D5240BFEDFB47DE933CC1
-:10A9F000A7F27632D4973EF54016F6F31CF623D232
-:10AA00007EF89EFB99F8CD585D3F13BF29D7FA69B0
-:10AA100084F7EAACBDEB67DF37E3F5F07C53A1F5D3
-:10AA2000B317FB71F46E5E13BF9DA087E7DB4AADE1
-:10AA30009F83D84F42EFE0098B6374FD84C5655A4C
-:10AA40003F7FC47EFAF40E1E451AA7EB4791966B22
-:10AA5000FD7C88FDA4F7AE9FB074AD1E1E6985D63F
-:10AA6000CF11ECA77FEFE6A598AFD3C363AED2FAC0
-:10AA7000398974CFEA5D3F071C7AFC1C7074E0E7EB
-:10AA80001CC233A877F32A70EAF153E0ECC0CF255B
-:10AA9000ECE7AADEF573C0A9C7CF0167077E440EB5
-:10AAA000E635AC77F32A88D7E3A720BE033F4E0EE6
-:10AAB000E019D13B785EEDA3C7CFAB7D3AF0938A26
-:10AAC000F08CEE1D3C85297AFC14A674E04746788C
-:10AAD000C6F5AE9F5753F4F87935A5033F57613F4C
-:10AAE000D7F56E5E85A97AFC14A676E02717FBC918
-:10AAF000F76C477808EDC7D17D3F07FBEBF173B0EA
-:10AB00007F077EAEC57EA6D07EB27BEEA728538F90
-:10AB10009FA2CC0EFC14229E6FE85D3F0733F5F830
-:10AB20003998D9819FA9D8CFD4DECDABE80A3D7E34
-:10AB30008AAE60F899248CC07586AE9D6E9E7E723A
-:10AB40007DBF7C85A3EFF32E56E75D6E02760FAFD7
-:10AB5000D933A445E1E9FBF61D09B90F9068BBA6FE
-:10AB6000E076C08F835A79D1764DFCD8389D1D95FB
-:10AB7000A024EAEA49C57D75EFF7291DA06B4F9D1A
-:10AB800073B5AE3DDD93ABAB67948FD7BDDFBFA68A
-:10AB90004057BFE2EE1B75EF67F96FD1D5B3D7CF42
-:10ABA000D3BD3FA87EA1AEFDCA860A5DFB55819547
-:10ABB000BAFA35DB7FA27B7F58708DAE7D78D303E8
-:10ABC000BAF611E14774F591871ED3BD3FBA658B84
-:10ABD000AE7DCC87CFEADAC74576E9EAD71EDFA398
-:10ABE0007BFFBAF603BAFAA48BBFD7BD9F4FDED561
-:10ABF000DBDB963FEBDE9FE2FA4CD77E7DDA9706F1
-:10AC00003BD5EE3A768D5AE741AE08FA25FE740937
-:10AC1000EDD5B043C2BAD4D7CEFC14C752F928E55B
-:10AC20001FE9C0223919F992FE51BB21BF6FF99576
-:10AC300011FAFCAEF19E2B5DF4F95D9267B82B869C
-:10AC40007D43F98D236950CA26288DEDF7898CDF65
-:10AC50000B322E0D3E42BFF79ADA0727D0FA703E2C
-:10AC60003F08F2F1326742BB3A8E2735F05E9C997D
-:10AC7000A0DF745F56DE93FE287958DF9FDA195CF7
-:10AC800067BFEB454F1ADA51B59FF8C1CE59D79F30
-:10AC9000CEAB2F21AF709F84FD03E9F7FD97A67916
-:10ACA000687F6689FA19D1E34B74FCA1387E18E4F9
-:10ACB000E1208C3FBAEBF8E6016375E35B32CB75BC
-:10ACC000E35B243ABE8B90DFD77EAE8E4F89309EF9
-:10ACD0009037B9CF717C7366398E7F9F44FDAEE8A3
-:10ACE000F1E33AC66F81F9BFDFDDFC078CD7CF3FB8
-:10ACF000B3423F7F89CDFFA3DAD3EAF87138FF3F33
-:10AD000073A7D9FC332BD8FCCDACDF8EF19D1DF899
-:10AD10008FC0F8C7BA19DF9C3D413FFF2B2AF5F3DE
-:10AD200037B3F14FD65E50C7B7E3F85F7217D8FC60
-:10AD3000AFA8C4F125B3C70DFC2365C4D504E8F85A
-:10AD4000A41F557CA9C02E741C28872452A12164FD
-:10AD50001B3700E1B82B8EF1DB577194DF509FF960
-:10AD6000F1390950CD9947FD4695D757ECC8974022
-:10AD7000EF613BF5B796A8A02E6EE291BFC90673AE
-:10AD8000601085B7B589F7437DF186EB02A05FBD02
-:10AD900066B2A014BE1348189E7FFECB615BA2E78B
-:10ADA000652C97D48BC72251F2D6E1071690213536
-:10ADB00014BE29C004A33BEB9F523F0E1CE38FA996
-:10ADC000DF43A8FFF399C8C6FB0BF5F7A01EA1FE51
-:10ADD0001E3ACEA416BFA3DD1D4EA3F097AAF07FA6
-:10ADE0002A3079FDF4362EE0A7F2F9D58F47A07FFF
-:10ADF000BDE06E1B457A271C65FE245D9DCECB0F02
-:10AE0000746ADF6D0E6CE110BF32E06B3A8A262166
-:10AE10008BD667505C77BEFFC1BEA907392721B723
-:10AE200012454CA5EFDFBE9AEBEFA2E3CE52CCB9B0
-:10AE30006C1D52324C28D724C33496905B1A478835
-:10AE4000B407325D113F8D448D3BA3585F9F55AAD7
-:10AE5000AFB78A8A68A270B54EE7C866DAEFEC39F8
-:10AE6000FA766D9C81A644466775BC528A9374FA43
-:10AE7000683694B9F0D885749EE362DF6AF078177B
-:10AE800089248C7EBCBF0F01BAFA93F1BD792E36AE
-:10AE90006F23BC73448B524AE739A78C0F007F1B8A
-:10AEA000E1FF689F4D31E5D072FDA32231759D8F82
-:10AEB00011FEB91EE37C8222ACF3F3CB8DCF19DFF8
-:10AEC0001C53E9FF29F0072DBF00FEA0F01F55F924
-:10AED000A353AF32FEF09A3DD3801FDA37F204E974
-:10AEE000AAF2CBAD2ABF2CA9D7F305211E11E8B8D1
-:10AEF0006C0E97FB40141FCC56F96059839E6F6E01
-:10AF0000277E313D065DE66ED87C6F9ADC757E9FAC
-:10AF1000A87C33FFC1FD889FAEF36474BA43A5D308
-:10AF2000ED35FAF65B55BADEAED2754EC3C3AF51FE
-:10AF3000F541E6C90111E4DDFB538D9E111D3D3D38
-:10AF40002A3D8D70DEA1D2F38E1F337A1AE18DA8CF
-:10AF5000F48C349C13C980AEF01AE15B707797F9DA
-:10AF6000605CABCC1F9B9EDEA6FC5547A39E57059D
-:10AF70006F5875344ACE566C9FAEAB2F0FCCD5BDF3
-:10AF8000BFACA14CD7BEA47EB9AE7DD1FA3B75F55E
-:10AF900032FF8F75EF2FB8BB56D77E7BCDFDBAF64B
-:10AFA000F9E50FEBEA733D1B75EFCF9EB359D73E22
-:10AFB000ABF4195DFB8CE29DBAFA7465B7EE7DD3F4
-:10AFC000BEAB6E06FE7CEB3D9E803D71C1FD05C6AD
-:10AFD000332FB84537BC73D427235F1FF30DC1F25D
-:10AFE000B8CF8D7C7FD23716CBD6A6663BAC137418
-:10AFF0005D5C4A12086932CDAB5DDF0FD66982EB2A
-:10B0000069C8E4A9F5D37AB34946792869904878A4
-:10B0100024211C2C362A1CED7C547BA487F606AA1E
-:10B02000F893BAB69744623FF73E527605F06577DB
-:10B03000EB03FDCB00BBA74DB5EB8DED951C298D2A
-:10B040007E4EC81A84C36A627647A5C4E4BF7257AD
-:10B050007A0171423D3CB8E672E3052993A7029F4D
-:10B0600064EBE47859C3353AFD4E209ADC07F86D5D
-:10B07000A4EEF98AEDD7EABE3BB59F47B8AB41577E
-:10B080008C8365B1F43313E8E17073E68C6100A73B
-:10B090007214EB4D7DD02E3CE52B5E757410D0AF55
-:10B0A00014CBE3BE39581EF379B03CEA2BC7F253F8
-:10B0B0005F0D9611DFDD58FEC5E7C7F263DF7A2C1E
-:10B0C0003FF2D563F9A1AF01CBF77D012C0FFBB6A1
-:10B0D00063F98E2F88658BAF09CB569F82A52677A3
-:10B0E0003DF1DD71751D3E09FC1783CFA43A7FED5C
-:10B0F000FA099D7C16C7DF877CA6E1B9A4C1ACF232
-:10B10000438A8E1F12C097433EEBA1BD4154F9B054
-:10B11000BBEF63B77BB7FC6BF86DEA0FE4B74E7E0D
-:10B12000CA30F053764FFC348C8FE2A7A92617B3B0
-:10B130007B547EFA19CC23865F310F8C903E51F6FA
-:10B140009A926F82756CA5BA0F421F60FDAC3A7679
-:10B150001D7DB705EDBAC0105837CE0EF9DB60D8AB
-:10B160004738FB21257E56F7F333F249F77857D05D
-:10B17000BF591AA0444FEADA6E8D6378B59A483108
-:10B18000A1EBDAFD839E722F1C8A758124C2F70120
-:10B19000F774478C7EA9AD0CF8ED09AF758EAF72D0
-:10B1A000A0BF638FFD3D0FCAA926662FC735F36880
-:10B1B000B793F0936EC06FC7BA6476A741BCBD7DEC
-:10B1C00090E442BB814CD6E3CF5FA0C3DFFD1447C0
-:10B1D0002DB8EED6A721FE067E3538BD17F8EB490F
-:10B1E000BFF784CF8530EF7F013E7BD28F3DE945AD
-:10B1F000A2C82F34D1F9B7ED1B96FB800CE35E1E7D
-:10B20000DFDAFE9A119E5F7E473E6E4BD1F8B8257D
-:10B2100093801FA4CACBD9C62BE3812E1DFDF44019
-:10B220004FEE779F6482FF7E3A4BDFDF7DC6FEE202
-:10B2300025C20DA7E33A2489C453BF92F76CE3D12A
-:10B240009F7147FC1037D86773D7C9E0379EFCAFB2
-:10B25000B00C3DEBE30B670F3DE9043F6C651A5FF3
-:10B260007334061DB5B22A9855638FF6579AF4F5D4
-:10B27000B3F55C7110E725C7CF1C06EB8CABE6A8D5
-:10B28000087A3F0D4BAD9F9569128E73727B763CA9
-:10B29000F3FF024C9FEC48407D73D267C1F7FFD9A2
-:10B2A000F074D78F060F218DE4330BE873DA96DD47
-:10B2B000FDFBDDCA83705E82F82909895F81BF6961
-:10B2C000A5FF7F3B00FA15B0AEF5EB0DF27EF370F3
-:10B2D00078BE43371EFD4ED6F68CE1BBEEE54E2020
-:10B2E000C734BEA7F4FBABBABFBD62BBB5466FC7E0
-:10B2F00026E8EADEA6F41A9D5D0BFF00C3BD8613A7
-:10B300006009AB54D9B04DB0AF077EDA03C149F044
-:10B310005F38F65E9525227964149716E0D385632D
-:10B3200035FE9767FF99EAA9136F8A04E48C5CA243
-:10B3300050E5A9AE20F29B8998687D91FAF6C2C6C5
-:10B340001525B06E9D78F926F44316935227F8C759
-:10B35000E5A43E0FE2B5A789A918E4F33479C7390B
-:10B36000324A1EAD82849D2E5AAFB7E3A97FAFABA0
-:10B370002F6BD0D797925B5260DF7EE9069104383D
-:10B38000D01BFAF6AF7917F6BB8CD4AC8375FB579C
-:10B390006ABC6BA18B0819546F55FDF6F1BC320ADB
-:10B3A000874B6071166D1F7A7922F37F2A66062417
-:10B3B00085BEFF59E3C85BA906A2DF07D6C17EBCE4
-:10B3C0007F3A716F235DE9F75DE137C2ABD9035D69
-:10B3D000F6C3553892B7734A20861ECB14382667B9
-:10B3E000AABE2B105CBAB8C73443FD7BF35332D1ED
-:10B3F000F1D31EDE93278C66FC03FCC009ED92E7B7
-:10B4000087F49FD6A5FF827F6AFFFD68FF79BAFEA9
-:10B41000A7FD53FB1FD805FE79B1FAAFFAEDF32F64
-:10B42000FBA93EA978F1974E42D7C913427D8A9B6A
-:10B43000D2B572DBBD4E8596C705BF13F8F54480C3
-:10B440002F8E45EF87054E1542C5CE41DC0DFE49D6
-:10B45000FB3FF9ECCF301EF1D536D185F1B4EDE6E6
-:10B46000B099CA6175E3F2129283F523AC7EDF19BD
-:10B470001EEA4D7AFEAB78FA9729901F4239458D26
-:10B480002F85D19EADDEFA7911AC4F5ED28E7264FB
-:10B49000FC0EC6BF9888FAAF4C8AEFDA4EE1C4388A
-:10B4A0008157C58BB7F16767782794377C01FA829B
-:10B4B0007A22E8C71BBF2B57EDD4358223F9988D2C
-:10B4C000FE7B0C19037A51C30B09303BB5EE995F33
-:10B4D000E71CA1709DDAFAA6938BC297264F67836B
-:10B4E0008BFE738FDCBDDE6DA5F2166D0F69EB96DA
-:10B4F000DCA4DAD72156568A6127E4F3546E16DDB0
-:10B500007EFAB8F2F9279F7A0CE2997F32BB07D115
-:10B51000FE573CFFDAFBE3697DC54E31B9844DC36C
-:10B52000CEA574D2C74BFFBF3BB7931E15BF794D55
-:10B530009287B1E7F72476D265C5CEFD1219D615EC
-:10B540001F9383FBA5883D067D82478AC05EA87B4A
-:10B55000E6BF2588339ED8C791D4AC18F8DCFC1A16
-:10B56000DA038027A4A74AAF0EFA19DEF752BA8091
-:10B57000DE36D2CBF8DE2255BF40BF906741F9FBE3
-:10B58000853D9007F591D90D78287F619513E6F3F5
-:10B590008550C3F8FCF17B53409F958BFE141796A2
-:10B5A000EC79F9133F42FE5BF6F68F5230BE4494BD
-:10B5B0007413AE45FE7498E7924DB3709E4B8907A5
-:10B5C000F9B0FC71BE3440CB0B0229DE19434EACFE
-:10B5D0002293932FB650E2D2797E01FE24E8EF77D2
-:10B5E000F8C036B4BBEF24A00F7EA4CE855A0C5809
-:10B5F000BF6061F4FAABBA2E10B03EA3F977EB7DD1
-:10B600002D40A793FD9554D877F112C1AFE283FB8B
-:10B6100096F6CBBF3D2595D189C8429EFA1D5DF7B0
-:10B6200027C37378BF4554AC39BAEFC8B7599DE307
-:10B63000AF56C7A770C7C17AFD454A6CFB354FD4DA
-:10B64000F4005DB7A3F82C4ADE99FC6FBD9FC9BB1F
-:10B6500026FF81E9C5D07EFE309323F80ED6430A3B
-:10B66000573815DBF7CFE4503F503F3A969C6F15A3
-:10B670005539D7B71BF985C22F70F1517C03E324EC
-:10B68000221D70DF65E906FA7D941EF5C2B8CEAEC4
-:10B69000FD6A72BC4CF35B45BD3E209B981EE8DE04
-:10B6A000AEF2239E2AC5C0538F81FC5279F5CB2080
-:10B6B000BF6229CCFFCB1DCDEFCFA372FB655093AA
-:10B6C0005BBD5E35CA6DF9AED12496DC7E69779399
-:10B6D00098724B9FC7945B7B04F9F9FFB45ED5F079
-:10B6E000380CF0784D271E353DD91D3E8D7AF290ED
-:10B6F00020235E8D7A92FE1D26795DF951E3438DFC
-:10B70000FF2A9EABBA02F451079F6A7CD8C1A71AE0
-:10B710001F7689EFEAF0686CBF00FB3414AEF9962F
-:10B720008DD38E5257D2D24E70DF267F268FFBAA42
-:10B7300096F384E5811011F3433F30D58C063B75B9
-:10B74000E2DF6F3D7D1785773EF18B2C2FA05E44A5
-:10B75000BBFFD2B7DF4EA0F399A7E2793E45FB5479
-:10B760004A973902178EA370CE15883F3E11E2B773
-:10B770001CF9340A8EF9E5FA3AFC4D4CE9ECA7A71E
-:10B78000F7BFAB9FF27DCBB7295D3F1D44C8BB50CF
-:10B790008A38BC10CD57D381AE147FDE515C600077
-:10B7A000EAA988501AE577BD2032FBF3EDC219A350
-:10B7B000C1BEC99F3D2C9EF1FB60F47BBDAA3E3B00
-:10B7C000EB97E341CF9F0D65A37F7BF6D02247AC7B
-:10B7D000BCD06695CF5E53F75DDAEC5C3D4FF9BFA8
-:10B7E0008DB4A37DE3B75BC9B618FB821B454D5FE3
-:10B7F000AB74A37F3C1D7F8ECA8773E9A7F1B95153
-:10B80000749B39F584E0EC4A07F8FB34CA0FFBA1BE
-:10B81000F805BE06FC365B2345A531E279CFA9F8D1
-:10B820009B78E06BCCCF2D0CE50B80C7423BAF8BF8
-:10B83000833CA9C9EB503214E09A7860F9CF4753A2
-:10B840003EF61EE2DD908FEB0D9D913C31FC6123B5
-:10B850003EA17FB0338F882EC4D77B62E912C0EB44
-:10B860007BB3AC04F635DF95DC55B1E02C33B3F592
-:10B87000662E29BD308AFBBF0FBFF9B31DE1028AD6
-:10B880008FB37696F7DD95FF98DC9F7571815A0E20
-:10B89000F89067F5642E0071B422E2F9F9040EE520
-:10B8A0007D52B4FECA6F9AFE3CE4F55487389789FE
-:10B8B000B6570B1109F8D8DBB45300FBFD269928C5
-:10B8C000188F106A86CD8C8A7B1D1105C457F3DF53
-:10B8D000E6DD0EF83D37D34C002E65E81927D80178
-:10B8E000E74223510EBA9BD71F7C645AA108FD1072
-:10B8F000E40F233F1425DB74F55993493F37A5DB4B
-:10B90000447364953B06FDEA24C667BDD66F96FF77
-:10B91000CFF4DB04AADF185F8BD1FAED2689F17D25
-:10B92000947E4B8DA5DF56D6CAA9C0172BF766A704
-:10B93000025D57BEB1A44F2CFDF6BA8FF9F76FA880
-:10B9400079E66DFDA87E1B1EA5DFFA51FD1623AE1C
-:10B950003B5AEAA57EB3FCCFC8DFEBA0DF62CCB7D1
-:10B9600058C59FA6DF8A43B5A8DF8AFBF1BA7CA938
-:10B9700049524FFAADEC97B3B02EBA6D31F807F0DB
-:10B980000AFAED0D55CFC138A0E7FE5D727D273D67
-:10B9900057D55B3DF73F84674DCFADECCFA13DD38D
-:10B9A000950F999E5B99C5F4DCCABD4CCFAD1CC404
-:10B9B000F49C51BF1574D16FECFBEA21F47BF423A6
-:10B9C000B37E7D1B6D2F9923BA2DF4FD12593B9F39
-:10B9D00051333A5ADFFDBBD48DBE739FC1732E3DE8
-:10B9E000E9BB3F82BE1B847A6C20C891913F6E1CDC
-:10B9F00068D3E5D3BDF7F5B1E75E0479F9038FFEAF
-:10BA0000F70726E627EDFBFAD84890BBF7001EAAF9
-:10BA1000EF9E51F9AFD5E7477D3A792893F7AA7B96
-:10BA200018FEAA1B3936DFD57C408675E06F17D12A
-:10BA30008FBE7D2FF3A3679B5BFAD8C0CFFF5F2239
-:10BA4000CA25FD2B298BE28739172B30EEB92BCE77
-:10BA5000B905FCCC3902B1801DBBE0D08D27C07E7A
-:10BA60005D70713DDABD0BE07922E9C8FB98DBA17E
-:10BA700027F5F6EBBCA69DAF6590AEF91013CD8C03
-:10BA80002E13577181CD595DF323A85D86F92DC61C
-:10BA90003C89DFABF39FCD47105FE48F7CCCF8E5AA
-:10BAA000EF8D787233BC54ADE6F578AAE162E28995
-:10BAB00052BAA42CA5132FB7BF14599701EDCB3957
-:10BAC000F4B78CF3D6F0669CBF8647CDBF59A0BEB5
-:10BAD0003F3F7424669E8886E72EF9221ADE0DF811
-:10BAE000784BD333D7906120971F983C3F1F0D7C34
-:10BAF000F47B8A170AE7AD7307E9CE2BBDA3E26595
-:10BB0000AAE748618A0C782435C067F3CA77BE96E5
-:10BB100042E777B392950B21F5597F933C108F68DC
-:10BB2000B6B6A31ED4F8709499C98559D52BEFF5F4
-:10BB30007515E27AD3C4B950BEC2063DA7E699791D
-:10BB4000EF61F2D7CCFDF7BA8C518867582E489137
-:10BB5000B65E015DE83FA786185DBC4017FACF6965
-:10BB6000A4FD20E0BD3A997387E1FDA69DF7023F51
-:10BB7000BD6EA5CF41CECB39F716860E7B7ACA654E
-:10BB8000F95888C5C718CCC8EB5C3F17C07B895DE6
-:10BB9000ED9389E696F7008E89546E36C3C300FD97
-:10BBA0002F8AFE46FBC5C8073DE50375C7EFB92AD6
-:10BBB0009E5F073AD801DFED12D843DE305B7FB4D9
-:10BBC00076AF201722DE343A34D1F56514A38329E9
-:10BBD000069E6FD6EA2A9EBD214E84EF6FA0FE6FAF
-:10BBE0001207BB7E5F1FD4F8DD2C77C513C415D2B6
-:10BBF000A3F406E8B7E87DCDEAA6B7115F37AEA695
-:10BC0000E699DC155F1A7D400F5E0E6FDDCA4FD3DB
-:10BC100091987961DF557E4699F5F2B3CFDAFEE669
-:10BC20007088ABEDE550AF9050822E7E30D3CCECD7
-:10BC30009666AB07F9BCFD0DD1BD45EEAA7FA6A85F
-:10BC400074017F25FA7CE2649808E84D97957CA6FC
-:10BC5000CD7B00E3B7E8F5E075AB07E9D75DFF33CF
-:10BC6000CCCCFEEDCE1ED3EAD7C37890D728EBC755
-:10BC700033AE475A5CA9A77979D471BFEFBCB471D0
-:10BC8000BEEBBE8497B4603C4EDB9FD8C37B768905
-:10BC9000603F1673BA7D100A39EE6FFE13FABF5972
-:10BCA0001ADD7DFF103F0A533CBFBEE3498C639F02
-:10BCB0007EF6C834909F15AFF0C442E5AF75878318
-:10BCC00084599E8804764245238FFB5D4408E7CD66
-:10BCD00088B233A827C3F0F1A203F55EC52E73A086
-:10BCE000847E5FF1F26739107F6B5DC3F49FFF596B
-:10BCF000951FFD911CC807A810D8FEBC913E8FA8C7
-:10BD0000FC796AB76D0EE86F6E3B3BC75B119C2DEB
-:10BD10009AA3E20CF79B4516E7DE6DC33C6CFF333C
-:10BD20001CE631037CD1E748B5FCD053CF30BD5C75
-:10BD3000D12406E03C70C5F69DAD1017AFF8D08C4D
-:10BD4000F6AB77FB1909ECD3C92F3ECFCE1B37F1E9
-:10BD5000BA78689738E4763E6C86F8596315EA013C
-:10BD60005A3F82F5A01AF7FB8E71B2152FEE7DD9DE
-:10BD70004F51B8E2374F3BF15C70CB3627C623B743
-:10BD80005F7E5FA04BDC3178BF1A779CFA05C1F566
-:10BD90002176DCF1A4CA2721B33EEE48B627613CE8
-:10BDA00092C299571A237ED1C1FFCF5F7802F6CD98
-:10BDB0004EEDFAF20980BBF29B734FFC94E2932A9A
-:10BDC0002017ACDBDE67DFC37D06EDBBF7557DD208
-:10BDD000FACCD3B84FD3FA27B31B7A6BDDFB4526D9
-:10BDE000EC53B4EEFC3A05E2B8ABF74E417F6DF58B
-:10BDF0004B9353490C7F402B817F03BDD82732D210
-:10BE0000ADB9B13913E03C4DE90EEB77473C3958F9
-:10BE1000C5E2F4B21A47DE117B5FAE4BDCB871C6E7
-:10BE2000CDD7C13ADE28BA65D28BF8F1614ACFE1AD
-:10BE3000BDA0E30E759F2038F5B2F1E3D3F00F4AB1
-:10BE4000AF0B667D1CFE42E392FF7C0CDA1A93BABC
-:10BE50008D1F877B813F6DDF6FBF59211690A35DDA
-:10BE6000CF61DC1EE8477D0FD2FAFC854C88BB1CF5
-:10BE700017DBEFC0FCEBBD66CCA3AAD8FB01CA530D
-:10BE8000EB4B6FE3BE1A51F7DF5A49C71FDB27514F
-:10BE90007D3AEF56078B3BAB7480B8B4ECC4E76ACD
-:10BEA000FC99F1B51697EE2E1E3DD63280EDBFAB54
-:10BEB000FB91555BFF2C1143BC9F1B0BF43A72D9CD
-:10BEC0007D540D0F2EC0C398E8FD96D8F1FF8EFD6E
-:10BED0001603DD809E608F75ECA7D07A3F88AB0794
-:10BEE000B80F62EDDFB56E66FB34AD62ECBC456D3C
-:10BEF000FF65A4C5B0EF12E8DDBE4B4FF3F8AE7896
-:10BF0000CA0627B44F577C9DBA145BBFDF6AE1D4E1
-:10BF10007B03BEE7BE7E2567CC1B98057C59D57890
-:10BF200044027B4A5BDFB4F99E52FDE753CFF278BF
-:10BF30004E645DB019F5BB517F5413163734C25BA4
-:10BF40006E617AABBA89AD1FA776390276DACFA9CE
-:10BF500003BB91AFAB771C91FCB4BF83DB7F234560
-:10BF6000A2F2AC60FD0844C17FEA85FD396C7F898F
-:10BF7000F9EBC671EE52C7F186628FE3DD71463789
-:10BF8000CE0A7F5062E77E2E3FDE4941990DFD9D2E
-:10BF90006C1109E4FD9F0CF2C58118E3CFB5885AF6
-:10BFA0003C8BC90F5D47F11CA6839DBBE41325B4F0
-:10BFB000BB573BC67E08E7FD573B2419E21775B512
-:10BFC0002C2FB5EEDFDC6940EFBA845B713FAEDE4B
-:10BFD000805F57B22B1FE21AAEC2D251C0AE46BD2F
-:10BFE00093A09874F0AF7614A7CA14CEB5AA9D4654
-:10BFF00004379E0BE59D45C5301FDE65725963EC25
-:10C000003B88F652E289C28BE8D29FE3249746CA66
-:10C01000D08F967F53696939888D2E05538C85B1F1
-:10C02000ECDDFC992E9C77DB0ED57F5088EC4A61C5
-:10C030007964B08EB4ED8ACF21C3F143A2507EB4AF
-:10C04000A9CFB91DFBF7835E5AEB244A0295338AC8
-:10C050005599CF86F3AC232C5C36F0E999FF7A85AD
-:10C06000F66B0DF1E857B4D9B57C522501E4CC4606
-:10C070001EC4BC4160E56F933AE134E613127825A3
-:10C08000EA3E8D29BC1DFDA1B39B587C802757FF3C
-:10C090007A028BCF9100C0AFAE2F2B5438CF12E273
-:10C0A0000EC3FB3B1C180F58F6C622941FA0433446
-:10C0B000BE928AF5E75E1BACCE1CF067365A55BFC0
-:10C0C000C6AFB4C0399BC56ABF7D4AF5E762A918FF
-:10C0D000FA415E97A8F2FAE5D2A243988FE6598A10
-:10C0E0007A3E758EFEDCAC314F4B20AA9F1C60FE61
-:10C0F0007397BCADA6CD08B7317F6BC5767D5DC3A8
-:10C10000E327A037AF027412FBE5E2803DE237324D
-:10C11000F8D713467D77FC9AD3F4F8B5CA7AFCDADF
-:10C120008618F1A7C7AFC3ADC797E6977687DFF844
-:10C13000B1FA73C8FF2AFC8A56D58E54F14AFF4AD9
-:10C140002D294C6503DCE94218E5C2284719F63071
-:10C1500007FFEE9F1CA8C5AFDC0ED4EF69EA7CB8E0
-:10C16000C5EC3B1BC8110FF0BA518EE02420E879D2
-:10C170001BF9D875CC0AC4FA8C7C7B4DF7F45C357E
-:10C18000FDD5230BE9579B807F87233FB0F3BE8902
-:10C190002450970572EA76C1FA1DF459DC8B45B834
-:10C1A000F785B8170F82FB5E5C583EA4E6ABB40D72
-:10C1B00025786E30183E9F02FAE9A1DCF669A0F7F7
-:10C1C000BC4B4829E8C11FC5B1F3030FA865BF38B0
-:10C1D00049D5AB856F4C82EF43A20CE7D5DB42DB40
-:10C1E0002C83A0DEC4E33D2ADE84FAAB60FCD6904B
-:10C1F000C8E05A6C090C8238C85E11C76D5D3C01FD
-:10C20000CF6576D86F21962FD216FACCB9284A9FDF
-:10C21000B7363D7A15C4B9369A62E7A94CB19A7E11
-:10C22000D8FA1BEC92B737C5CAF2EA1E1A40E7519A
-:10C230003DFDACBA0E3379B856A5F3AB4B6FC4F9DC
-:10C24000BF14E26458478AF8DB6E1A46E739EE3DC0
-:10C25000418DCFB078E528F5FD3AD02FA85FEBDF10
-:10C26000E5E9C3DD470502E7F446D52C457FEB152C
-:10C2700027E573CA17794A7024F06D612801EFCD64
-:10C28000F17E4CD0AE1FDD22E8F8334F5D57F3222C
-:10C29000545EC044F950DF3E2E2218ECA0000FFC83
-:10C2A00075ED71FDF38556D5EE729214E0F30D979E
-:10C2B000780EF25EDBDA897B0D85BB6D715F84A33E
-:10C2C000ED3C9CFAA5E525BE38D67ABFCACAF8620D
-:10C2D000A344709DD9B8D48EF1C5034B2BAE80F525
-:10C2E000FDAB1F7BAE88758E3C4A3FC5B37C2C25C9
-:10C2F0009E8C05FE5ECB31BCD7A797C6C8F7D7F892
-:10C3000059E36F8DAFD397C67962E5357E63657665
-:10C310005AC1D2219C04FEDA3E0E8FE3B6AEF15C28
-:10C32000F6DC8D9FACC90078BC4DE7D0EEB6843802
-:10C330002596BDB1C1EAC4FE5BD7F86B218FEF2E05
-:10C340002A9CA027BBEF7703FA5B3F81A02C7C6778
-:10C35000A92FC373BC4B2C640BC4BB85FAF45B1CC4
-:10C36000C0FF936F5847E17DACD484EBEB46D18D91
-:10C37000F0FBAB08C1F8831ACFED378D6C8E3ECF42
-:10C38000FC8435FF592BA5C7B35617D225C9E3E660
-:10C39000007EF73FFEDB09F2DD76D18C74ECABFA60
-:10C3A00043DA77AF5999DD36334ED90ADF93F26419
-:10C3B0009413B7C7E95E3C12EE4DA0788F92A34E5E
-:10C3C000FAF9F1BB440FD571149E44BB09F99228C8
-:10C3D0008AECD2C529FD28479A5C903047208F4DC2
-:10C3E000D3AB5C880B3BA81C8CB2D8C3E0772496F7
-:10C3F000D3795310ACC4C2FA6B114E759CCBC63CBA
-:10C4000079CA977970388A6048141271A17F4DDF1C
-:10C410006A7A7A6D02417959FBB010A8A3FD6C12BB
-:10C42000225688AF64297201A41A250A329E17EF9A
-:10C430005F4E30FFD296FD784287DD42857EC4375D
-:10C44000FC8258FB797C9C862FCF1F406FE41C6ACE
-:10C450003F00E68DDBCAC673BF66413BBD437FA884
-:10C46000F65891BAFE8EFBDCC4F209C29348F43E42
-:10C470009B517F68F6C9B8EB226B60BF68DC9F18E0
-:10C480009CB45B05BE1BADCEB7439FA8EBE69810EE
-:10C49000D527F4FBDCD0C866B8072BF76326C75D49
-:10C4A000F4C9213F0FF8FBBE7AC4C81723C2542E2B
-:10C4B000D5F6A132DCA7E1EAA843FB1983DE499E49
-:10C4C0003E2A15ED5C95DF8C78D6E4DB28F7B9774A
-:10C4D000BB9BCD0C2EE6471AC6215C271C7236E8A2
-:10C4E000A5B778B0F7DBF2291E285CBF02F9A3F4E8
-:10C4F0004B381FB801E6BF2174BD15E4E47BAF27BC
-:10C5000021FA75549EF6D3BC273EAE0FAE274EC01F
-:10C5100043F5FEF3EA7A12467A77C8019593E878F4
-:10C5200089C6FF467ED7E4A30E2EDEC8C673760406
-:10C53000D6599E0BE2653066B2C90578D5ECED3A66
-:10C54000D5BE25FE74B4FF56BB88BA1E6506804F63
-:10C55000EA44CD5E775BA2E353AB1D05A997DB4FA1
-:10C56000F55EA4FE59D4391BAFD08EFE9BF7A28492
-:10C57000CFBF37FE9A2814793AFC8D891BDD157FD1
-:10C58000F17184B0FBC2FE9F9FDF0C237FDC277715
-:10C59000CEEF5AE2792542F547DEAAF57536193F06
-:10C5A000399C96D7552F68FB9FDDE901A3BC8FA965
-:10C5B000AC6FC6704B0FF2EEB5A9F8256406E8B370
-:10C5C000F1616AB7647595FFF3EAFCBC3686F7B68D
-:10C5D0005BDB07833CADE73D3571682F464C26B0E9
-:10C5E0002B7613B47BDCFB8F3A51DE5B9274EB4FFE
-:10C5F00057BBC08FF2A9D9A79A5D6A7CAFC32E55ED
-:10C60000D71B2D3ECA355179A1F03C19E7F1031C27
-:10C61000752EE6BFC20157D0634F583D75C05F36D7
-:10C620003A9738D82F1912CE62F196B04E3EBB938E
-:10C63000479B41DE82143FB0FEF9E9FA3788EB1ED2
-:10C640009EB171090C5EAA85C0BEE99747D860D536
-:10C6500004F3C7FBE5B0FB6BFAE5B2FB3237C73139
-:10C66000FB658BA17CC25AFA18CC4B1488DF9CFB6B
-:10C67000FDE10650210EF9649CD200F8B0142B386D
-:10C680008F0C17717394DE19429083BC89C44A9948
-:10C6900063F147D2B9FF48FBCB2891F3813F3206C3
-:10C6A000123C379A118A7D9EE89538F187D9EB8D37
-:10C6B0005DCEC1BCA2CACF4189CE37A9849D83E992
-:10C6C00088FB50F001BFAD8E5B71B2AD17D83EABA9
-:10C6D0003F81E1D9E8BF01C1605E825ABF57228223
-:10C6E0003511FD2B3FF0AFDF6441FFCA46DC41D07E
-:10C6F000B71FC4B1F8EC3ACEBD1EEABF10DA2D70F8
-:10C70000CF8F26379A3C3C34E116B7405F755E7791
-:10C7100036077C5F2A17EF009E5B279C1DBC1667BF
-:10C72000D29EC9F84EE175F9F61AFD9A441DFDAC8A
-:10C73000105789D6F30E6908D8EDAD5C9C1BFCAA96
-:10C74000D6E51C8397B3A8E71104DD3CD36CCC1F5E
-:10C750006953F5E7DFE3B2901FB5F584CE6F3DC6B0
-:10C760007F0DF3E838876A38776A3C979A96DD112F
-:10C77000074AC77CDC5209EE3223674336B4E3BC78
-:10C78000CEF64C12E3BC646AC41AF35CB05652BCD9
-:10C790007D0D784B156B12401FA7DECEF488111F5C
-:10C7A0006D9C7FC441D847FB8318331F452BD3D2E0
-:10C7B0006E4A584CDF4F4BBF014BED79835D8819B2
-:10C7C000574CB2713FECDC6403B118FCCD241BED77
-:10C7D000EFB4E79DF71514FF768CBB37C431BC3737
-:10C7E000C431BC37481A3EE57890BFCEBA5B97F7A4
-:10C7F000B4C1674910200FD19F8EF2B9C4C5E8DDDE
-:10C80000F9BE82F64D1FA2DC301794C406916C432A
-:10C81000BE67F121ED7CC8AF7CCF2440BE94DB968F
-:10C82000A5FAFB1646DF0406F7F90D5370DC14B2C7
-:10C83000C63A98E27969A9C90D71A3D30B3F72C2B8
-:10C8400091E985192D79200FA7798F1BE6974A98D2
-:10C850005FB86C8E1408D32E931BA8C26274BA0101
-:10C86000F73BCB4C31F3AEC7D8D8FEE9D138179699
-:10C870006969D3904E9DF59204F04B8C7C4AE53566
-:10C880007DF1A8CE73CC946F145B0C796B134913B4
-:10C8900087EB5B18F195ACB1B3AAB7357949063986
-:10C8A000847DAB52AA47353A0F505F4DC1B828FE80
-:10C8B00071A1D7BF067FC3795D01EA454D8EC810CF
-:10C8C000A6E7ADA077A3E2A16D7B3FE80FFB8E9FAB
-:10C8D000FCDB3907EC3BFD556877809E3D7ECFBB86
-:10C8E0000E38C7F4C93D2C2E7287C14F5B6463FAC2
-:10C8F0007F8FAD741EE07781EF1F799E287E2577AC
-:10C90000B3FD93E501DE70DE5D7F6F505530C97079
-:10C910008F901FF15AA5DE1F66A4C7461B8BB72C4C
-:10C92000DFB159CA90617C4F258C7F5CF5438F370E
-:10C930003AD0DFD1E059B8638404BED95F4366754D
-:10C94000FFBD4564EB875202FB671E156F46380F2B
-:10C95000AAF76A2FF925CB8F29A363DD4DF5B02700
-:10C96000C4CE7B18E7B1E413B92895126FC9FD1C3A
-:10C97000FADDF0FE3D743DF3DC7D1FEEB319E7D91F
-:10C98000F55E1F05FDB3652ABD8DE76D9785D83E21
-:10C99000F862E241F9EC72FE36C4CEC518E38D6749
-:10C9A0000F65DB000FBFB0A9F1C43C3206CE6DEFBE
-:10C9B0003A3420FE72F7569F52EF8B827BBBA13C2C
-:10C9C000EE2358CE032390E2BF32F4F65DC05FD56C
-:10C9D0004D3BF13EB4EFAA8FAA42279C904BADE9A4
-:10C9E000256A876E03F9208B399D7D5ABDF99CC459
-:10C9F000FC6A869FDBD4E7B7013E7220DF5BFED97D
-:10CA0000044AEFDB2AC5F3D1F7A53D6FD3EFC3F797
-:10CA100076BEDA3CB5796BED556A5E9CF13B4D0E06
-:10CA2000E6A97CB978EBF4757D298AEAF67E91A9AE
-:10CA30009E93C3F3421A9F2D23A545E931F849A3DC
-:10CA40006F07DF847E8EF3D3E8BAB8BE4CC5833F50
-:10CA50004DDD4F4C837895918F7A3AA7DD2A463287
-:10CA600041BE8D7CD2DACD7D28211BB32F16CB4A57
-:10CA700011C4CFA8F9BBCE1565DF1C17EA0FFE1451
-:10CA8000E46E2BE3FB0E3D084E31E8F737455CFFC3
-:10CA9000573AE454B8FF0FE9370EF213CC7E784FC3
-:10CAA0001BE7984F51068A80FF622C4FFA4A958106
-:10CAB000833ADB976E3CE704FBBB6D08C1B851AB12
-:10CAC000430FEF691B8F7AE3B44A8F4AA1E59B3F7E
-:10CAD00083CEDADA827917C72EA971A74BE6E2581E
-:10CAE000F3B4D839DDBD7877A872A8F9350B54FABC
-:10CAF000DD1162FBE90B374D477A74C9BF54FDA1C4
-:10CB0000B2460EF58E913E4BDCD7633EDAA2403E34
-:10CB10007EDF855EE441A4BB916E77DA5DEC1E3763
-:10CB2000A146827BED8E6DE270FF7185107BFF73F5
-:10CB3000B6DDF49DE6639C4777F02FDB5ABBAE2F42
-:10CB400081F98F9080CF8DF06BF35F4214A6A7D44C
-:10CB5000F976372F1299C4F234D4757F399C5B81F2
-:10CB6000FD93077996CFADC6A134F835788DF328BB
-:10CB7000E22BF17C415B038F79D977F8D97D067779
-:10CB8000ACE570FDED8E4E9A5ED1F67BAA9BCA3065
-:10CB90006FCB43FB013BB6ED63C2F629D67378CF6A
-:10CBA0005BB7F40CB17CA5EEE84908A3DB624A3719
-:10CBB000F03FBBDE9F90AF0C8CDE270ADCA00C8C14
-:10CBC000DEB72241CC5759B17DBAEEF98D76358E5C
-:10CBD000A5EAF59EE48FD424C48C6F69F2A6C99FA0
-:10CBE000268F77DA65666F0A81831959809F87D10E
-:10CBF000BFA1FA7A9E9DF93D0FCDA5AF546F3CA71A
-:10CC0000DBA7583296D16B095F82CFBBD3BB140F21
-:10CC10003ABDBDD8AECFC3F8A1F3D1E6A1C98936DC
-:10CC20003FA39C18BF37D2438BEF19E962A407C01A
-:10CC3000097EC65B7B6D813514CEB73806B77FAFF2
-:10CC400015E16E4D9BACC0B9CDEAF4F958FE013E3A
-:10CC50004C07FBB0B4CE8E76AEEA878DEA5D5C22DF
-:10CC600057B5CB5EB22A23D9B9A7D224E09389B5B0
-:10CC700091191617218F3E585C04F7A44E7C383268
-:10CC80000342F1BF7EF04656DF1679D7E286FBFC01
-:10CC90004B8A0A69FD71D02FA02FFA95DBE0FB6E5D
-:10CCA000EBC473F9BACCDE1F652E9DCFEEB166EDF5
-:10CCB00095D43EB3D0F5AEF2F0E057417E2B5B4AFF
-:10CCC0008A212E54091178BADE5529CEB02D87ADB0
-:10CCD000FBE3E97B1FD93C4FD921EE76712DAE8B5A
-:10CCE000958705942F7288C567053A572BFD6E6DA1
-:10CCF0001CB593297ED7265ADCE017D3E77EF09740
-:10CD0000D7262AB21CF55CA31F7C0770AC35B17C1A
-:10CD100082FD6F0C8E8F5CC62ED8EF2325E0CF34BA
-:10CD2000FB2C581ADBF325179EE7C837B17889B179
-:10CD3000FD6DBB76AE49CE00BEA83E24A1FCC31F4C
-:10CD4000D89F5584C9493561E7D0AA0E133C775363
-:10CD50007DA808CFDDC0B9844F757AE05F73EEA679
-:10CD600093AF189E0A04AE44881AB7D06ED5D5F991
-:10CD700054D310980FE1E3DC706E84CF30D5ECA271
-:10CD8000F3E7AFA025C587E072F370FF4CFDE4899F
-:10CD90003CDC9F5527AA792D26763EBE63DD57E5FC
-:10CDA0004F2BFB394A8F02DD4FFFB125CFC6F6531B
-:10CDB000D0AFD6E65BC72984037FED3582E71972D1
-:10CDC000934933E0CF4694B1C06F1647A2CA976C1F
-:10CDD0003F9BFE6540E9369B7E23537EFFFAC19F51
-:10CDE00022FFBBE34DABB2689D73F8593DC3742E6F
-:10CDF0008BB230EFA865F56B4CE706D0BAE858C3A4
-:10CE0000EAB0F14A173EB3A3AEC83F14C67131BAB7
-:10CE1000EE50AE01FE164C2CAE231C90707F47CB1B
-:10CE200057594B7906F8D1E2607A745D6DC173365B
-:10CE3000889B172832E44FEC51EF41FABEA5865784
-:10CE4000DE66427F094AC07FBC83E153A30B69546D
-:10CE5000AE813C5E1254AE817DBD7E0E4FA2837EBC
-:10CE60003FF2AD9689A0CF1BDFF9280FEF73BF8289
-:10CE7000F533F22DEA43D2F99CFE6DFFCDD1FBE4F0
-:10CE8000FD1CF9A9F01D2503DAAF9CEC22B751393E
-:10CE9000AC53882C65839FADF72F1B09D34F1FD947
-:10CEA0004AAF70A03E09E33AF613BB6700D48D7E0B
-:10CEB000336949EC55DE9D947337EE172566347D52
-:10CEC000B810D685DFB17B4A3845C1FCD3173BEE9D
-:10CED0006B231897B2913837C48D899BA4F953D42A
-:10CEE000F89A89F155725E94FFACCE877E5F08791F
-:10CEF000F2636C2CBF81CE8F07FD3A82C8588E84B6
-:10CF0000385936A0D883F53D24F8E14F69FF8F5892
-:10CF1000597CCAB29DE8E28F650E16B779C0C9E2A6
-:10CF20008F7162F016B02BE2CE1017D8156D8F4BB3
-:10CF300002EECF0BAE9B70DFEEA009E3DC4F8B015E
-:10CF400017EC17B55F25C85B48677F6D2ADDB57E96
-:10CF50001F91E4AB20EEF70B27AB3F9D4F308FBB0B
-:10CF6000FD841480FDDCC40C4B4D743C699E83D958
-:10CF7000BBBF7315CC043A04F7C611187FCCBE387A
-:10CF800013D0E3B91DB956E08B170147140F89661A
-:10CF9000D79DD05FE2390A6F163E67F9FD823C22C9
-:10CFA0009EE277FC8D7619EED17ADA1ABC11F3562F
-:10CFB0009F37E1BDC12F4AEEE9507FF1ACEC023D55
-:10CFC000FC7456300EE7F3BC09E7F3625CFBD52B2B
-:10CFD00029DC0F0C61F12EC14604D0CF82A940BEDE
-:10CFE000933E5FAEF2B1A6AF37811CD1FA231CC1CC
-:10CFF000730C82291FE548CB276A6B27984FD467AB
-:10D00000660B0FFC1C375D8B3B857988174D2825F7
-:10D0100068CF4DB08B78CE05F299E1BCDB44550F5B
-:10D020004FFCB8B284E507BB0FC3BD9ECD76F57E3D
-:10D0300030759F7392CA27D791086FA1EDD75D24F1
-:10D040006E88274DBAA8DF8F78CA605F4E51FB57B4
-:10D05000DA5D85F0389FE8EDBF290D4527603D2C4E
-:10D06000208A00FC34D96268073BD209F7F0EB9FB5
-:10D070003FE050FDDC4C92199DC7A6ED434DE18782
-:10D080006E44FBB55872035E76DA950F203FC0DF21
-:10D090002292CBC5259FF2B17CC321176D04AE2C23
-:10D0A000A4FC6987F95CDD50EFB7D2795F3D90F55C
-:10D0B0000F7C08FAE5CAC7939340DF8F57E9A5951F
-:10D0C0001ADF017FB9E2197FB98677CAE7D38E2CC0
-:10D0D0007C4F9337E03BE8678F18981F6BBF9BF23C
-:10D0E000EBD3C0AF3BED04FDB89FA55BE6809C6928
-:10D0F000E3B4AA7C6D2CD7D5AEDC0FBFFBE4BFC078
-:10D10000D68DC2BE17A5E875BF4F0283D72BD7CFE8
-:10D11000980679687611F3CC52D47351D1FC921EE3
-:10D12000C52F1ADFB5DA599C48E39FC9BBDFE5E19B
-:10D13000F9E40B84B8B24887BFA2F1CF447F18F757
-:10D14000812712E69F18F9675737FC937F5E1640D8
-:10D150006F75E19F438C7FBAE31BDA0FDE6B61E4EE
-:10D160009F771CAABDDD2DFF5CC2F3FCABF74EBE62
-:10D17000EC7E65934F9F9F6A2CC7D962E72FBB5403
-:10D18000BCEF96EA6FCA01BD31D5C4CEEF0924E3E6
-:10D19000160AEFEE38EDDEFC9A6CA8EF14981EDA52
-:10D1A0001932A31EDA69F778307E9B6661E757056E
-:10D1B0004F04CE23B8FB5AE4E8DF21D9EE6076585D
-:10D1C000500C8FFB02ECF137181F8C9D9ACB432A31
-:10D1D0005AFA62A617461D9736C3EFCF3DEACCBF79
-:10D1E000007C9606B8A3DF798F4A78CF52F55109B3
-:10D1F000F5E36FF7BD5D04F1512DCF79CC9EB78B70
-:10D200000A86C2FB8CDFFEA1EA65AD8E4740405F17
-:10D210001AEEDD1FD7711E4B7F6F7E29F0514E67CE
-:10D22000BBF13EF9601CDB3F994D6411869871B4E7
-:10D23000F45EB8DECC78AFFCEC303BFF36F3B027C1
-:10D24000F6BDF22A7F18EF37A7F6778A13ECEFE7DF
-:10D250005AF6416884C86CDD0E4A35D7303FA326A4
-:10D260001BF8499343FCA3F80B7E3244F7BB06B787
-:10D27000A9F37FD02DB0FBA92212EE4BFE9CB0EF9C
-:10D2800082EA3A36CAC9F440EEEA17E6039C23CB99
-:10D290009566A0CBB32E16D7F905095BB2816E6EE9
-:10D2A00001F75382A23CF90BAEF33D22940EB1D3A9
-:10D2B000F63D7DE246C2F88F3A3D639C609F09EDE2
-:10D2C00087E0BB31E37347821EB78F589B04EB9A0C
-:10D2D000063785AB789BBD130E0DAE814EC6978F7A
-:10D2E0003ACBC6001EE03BD04B4D478E59E07B8DBC
-:10D2F0001F827BCF303E88E20BE0834EBEE01640BB
-:10D300005DC383A2AECFB7FD8BF8428B6BF4C81719
-:10D3100010B7707E2FBE980B7835F205B5E73CCE7E
-:10D3200018F65C50627993C6E73FB1E7E3FB6E897C
-:10D3300060DE13D96765BF6BE849C07D90DFB8D860
-:10D34000986D9F1CCBA4A62859E56476BDF63B2AB0
-:10D3500023C21CDA9F23A8A2B80DEDBC7EA827DD4E
-:10D360002AFEC8318E83FB4631373E03ECD0701263
-:10D37000D86B23CC256190875DB68919603FE6DACA
-:10D380002664C3FC5F1EB2FA4D58D25EEE5BFE9B74
-:10D39000AD72A77DA5E9C366B55B6DFC352A7F4CF0
-:10D3A00052D87927D0EBD17068EB039009E0E0C246
-:10D3B000B34DDFDA508F8722146F93000E8A87FDFA
-:10D3C0001C6904FB21DFA4244F063BB04F580038F2
-:10D3D000DBF67E9D09F1CE92D0EB1F02BC25DA3E32
-:10D3E000AC5BBF0F6BB4B7357B48F33F347B49F37D
-:10D3F0007BC1AE82F632D51F7199D9BED884B005F3
-:10D40000EF5378E4AC7C95A2CAB340E751A2CEE3D7
-:10D4100066D2827069F7A94C53F1517288FAAB3920
-:10D42000D04EC8548A87A9EA7D2A53DDFAFB226EC2
-:10D430001E1BFB3E15AD9F9EDE37AE1BD71AF6A313
-:10D440007E6879C8C7EE4FF9BD8FF9C3E307F07E58
-:10D4500001D6DFB159ECFE0917C3C32129F63A768C
-:10D460005195EBF1A6480E9CC7DEBFE7EFB86E1EE4
-:10D47000D8F3F7F7C18E1C77422090973BFEC4A8E3
-:10D4800078CC0F182B235F69FD7A3F6FB411F69C9F
-:10D4900044FFDECC410A8F7225C067C1F295538FDD
-:10D4A0003C0AFD9D3F2A90E8731F45926720C4E522
-:10D4B0008BD4DF1D3AC8317B4A6B3FA8FEDEC71113
-:10D4C000956F212143BB67C51C45E7A9EAFD1F1ADB
-:10D4D0005DA71E2F3E21E474A50FFCFD33E2105A18
-:10D4E000FCE19CAA0F49F39FF07CCEF58D770A6092
-:10D4F000BF5F9FC613256ADC1B64EAE947C5214E5E
-:10D500003A0DF66FF3338F4E83BCE5B7784C81F458
-:10D510008676BE9903F5163EE6BD2A46FC5E1FBA26
-:10D5200013EF55991BCFE4A3A7F1C75F4DF96438FA
-:10D53000D09D303B308FDD4B62A4EF813DFF9114D5
-:10D5400019DA3DBEBBA3BF910EAF9C2AC07DAC9E35
-:10D55000E861E4DB7D749EFE2BE177532DC48FBF21
-:10D560009BEAC2FAABBE34AC6BFCEADDFB6412D8BA
-:10D57000791A9F4E49627C336EF7A349C4DE492F66
-:10D5800023DE86C533FE7FC9AAD925EE59D3E8A389
-:10D5900077E93A848CEA272D903756AAC23AFB7075
-:10D5A00011DA25443DCF625CDF66F3B74D0175DAD1
-:10D5B000D3EFFECC94CB7AF57B39C56FD50BB00E8B
-:10D5C0001609AB991E53ED780D1E239DDF23A50888
-:10D5D0007F77F019F9C008E74B1DF9F60AAE07DAB4
-:10D5E000EFE0CC18982526C69887868F9984AEC719
-:10D5F000D9BD5F8F6F8CD7DBEFE78E17FE11D0DAC6
-:10D600009DBC19E9666CD7F447110C908BA51FECF3
-:10D6100093B9F12948DFA28B1251E83A43FAE9CFD6
-:10D62000F593922B91DF56B9D8B3EEF8ADFA224FAD
-:10D630003C233BF94E6C7AD8067CB75BA8B7411CFB
-:10D64000F53AFBF43A10BDC2CF0B66E2FD1511139B
-:10D6500081D0DA94D099668833783F2478BEA120AF
-:10D66000B47F32F0E9AB420BFA596DE7097938CA59
-:10D67000EE6C0AD5D9C02E6B4A66E7F30E26105D14
-:10D68000FEF4C578A66F9A8E9E9DA6C4681FEE62B2
-:10D69000FC3C8328C939F49F45EB297F801FDCC7F8
-:10D6A00081719242CEFD5A32D82D7339F423DAF6C5
-:10D6B0008E792D99C2DB7A7B02EA99294DF7DDE953
-:10D6C000A28408FE63243E6F2FE3F0FE8422D98DEE
-:10D6D000F5A2C559E8F78DF926694609B4DF20A2FD
-:10D6E000DF3385AF14205E753A8DC3AB3CF6709185
-:10D6F0005AF83D62FF74360E71F993C03F7DA7243E
-:10D700006904FE669EACD507E1EF2E1283FFB6FAE0
-:10D71000A573FBCDB47DF52C0EF38DA7B832883FF1
-:10D720008A7F8AD64B38AF5B42A905C0D7338AF5CA
-:10D73000E71EC3AA3D39ABD44602D1FBF99C0BE5E9
-:10D74000FAA0B5FD56FC1DF1BD2281F969727EA3D8
-:10D75000CAEFB3E724E9BE9B4E98DDA9C9D54DAA0F
-:10D76000FCDDA8FACD733D19BAF14B09B387FE4031
-:10D77000DA0B8164F7B8D87EF4B4F696C3F3E125EA
-:10D78000BEDF68D087370D31F8BD7CE55AE48B34B5
-:10D79000CE8DF7C8B8F5ED378FD5D78DF26BD40F96
-:10D7A000B3208B8FEFAA27347D306B2F2F423C683C
-:10D7B000563EC533DAC57ABBBD277D3126AE1B7D0B
-:10D7C0007149BE17CC902EFAE2E3E2EFA52F7E4B13
-:10D7D000DD96B154AEDF8E57D7CDFEA43FE88D293C
-:10D7E000FC8E47818FDAE8BA698EC147DABAA3C5E1
-:10D7F000018AA81CA31E38C5F663A65C4C27FE91BF
-:10D800009D71800E3D42ED12770C7BA9353E1BE5E4
-:10D81000AB43EF687A25CA2E11F37EB85D3285DA04
-:10D82000A3522EC0D70FE12B52EF252982842B88DB
-:10D830001FA69DC1389057A0FE2CAECF4F227F81EE
-:10D84000FEE3123BE5C368AF6871E80A97664FE9EB
-:10D85000F9A5231E3993DDC3AAF14911E013E47F32
-:10D86000268FFB04FF1BD47F03B300800000000061
-:10D870001F8B08000000000000FFC57C097854558C
-:10D8800096F079F55E2D495592AA6C148BF012B67C
-:10D890008424588480EC165958A314A080CB688146
-:10D8A0000B6B129A719CEE69FFA642024343B78349
-:10D8B000D2DACEE8F457D83A831AB40801039DD0DF
-:10D8C00015504C5834082EF8D91A6D1AD10E4984C7
-:10D8D000D646BBBFCFFF9C73EF4BAA2A854DFFFFF7
-:10D8E0003FDF9FB47DB9EFDE77EFB9673FE79E97E3
-:10D8F000DB9B55B3AD08E0F6998A071400D0F177A9
-:10D9000022C042E07FC3ACAD16F08EC7BED7FC6923
-:10D91000870DF8E73BFC2F9C90FC2CA450CF0B907C
-:10D9200009B054CE5FFC577D333D5E3C277AFE52F2
-:10D9300098FDB9920C701BF8CD301CF7F3C58EFF23
-:10D94000EC4B15C7972E8B7E9EE94C4ABF9087FF04
-:10D95000180123BE5301CAD4BA9DB722BCDD275596
-:10D960008F554C33D1FE0F39C5FE0F35970C807C97
-:10D9700080DF7416A7F8B13DB611211C0DD0BAD1C5
-:10D98000C6ED71EC07F1C5EFE8E7663C9F05FC21A9
-:10D9900007B6B45221B701480518EDC4452760FF0A
-:10D9A0002A9E3F0DC78624C0EF73245CD900AFE7E1
-:10D9B00098E704F1BDC3B85E00D70DE3FA015CF748
-:10D9C000C84627F75FDBE8E6FE0D2E446A06C0FA7C
-:10D9D0001427AF372FF776871FDF5BE3CCE6E750DE
-:10D9E0003EDA44F836E02F7B6A080410DFAF77ACEC
-:10D9F000D09474802AB7E2B166F5D1014FE3588E16
-:10DA0000F3CB25BE2BB72A10C4E7E51FAE2B07C406
-:10DA10005F5733EE87F8A92A558336FC6749D363ED
-:10DA20003B45DF0CD608FADE228E0233B516CD86D2
-:10DA3000FB2CF0281E15F7F13689F76FF52A411DEA
-:10DA4000FF798B279A1E8763E8BE58AEB380FE0F1E
-:10DA5000DF5B30470986719D0593A2DF5B7C75D63D
-:10DA6000E7CAD8FE7CB498E83EB63FBFDC4E74B738
-:10DA7000E33F86C130A2FB958BA56F8D853EBAC56D
-:10DA8000B6B1748E1DBF169DEF273A675C9BCEC65C
-:10DA9000FB7F8BCE0F114E90BE70F41B8B9E04301B
-:10DAA000BBE9071AD179F6558DD7AD32CE3314863E
-:10DAB000D279FED459F86FB742DFFCAAA62F2DFE0B
-:10DAC000826B9FE76FEDBF2245E7FD695F6F7EDFE9
-:10DAD000BEF33480C178CEF939D1F88DA56B2CBD59
-:10DAE00016CAF762E9B535E61C065DA013996860B1
-:10DAF0001CBC5F55198E6BD1AD972E16FF084F7E5B
-:10DB0000FF71805FF3B9FAD693748276CD5720E027
-:10DB10003247C803F2752005E95BDE0AE14404ECF4
-:10DB2000968B733ED7A8F528F069C439E8E753838C
-:10DB3000CE6ADFFA655707B2FC19FB966910B0147C
-:10DB4000D2732197B1F055D23A23697E80F968CB20
-:10DB50002ED3B2109E63BA05EEF5519B28DA034E20
-:10DB6000A1071A9D265EB7FB2B9B096E0478E5F092
-:10DB7000806240F83C56E709D28B2133F0FB45C95F
-:10DB80003ACFDF9C048104DC1FB4769B0FF9442B51
-:10DB900006C84139D306598235B8649D16F691DC22
-:10DBA000757B34A846B9BBD178EF48E02E40926C23
-:10DBB000FE7494A9268BDE0FB74FC57937156AFA24
-:10DBC000369CE2B2EA3FA0F1AE66AB93DEEB3EF8E4
-:10DBD000CF2D665AE72BF02084F05A3332158E4F42
-:10DBE000739883A437CAD493AA09FBDD3D00A48FA0
-:10DBF000A62D0B9700D26D3AB4D738B19D42748CE4
-:10DC000043BFBFD0793384DE1A88749A21E9344344
-:10DC1000EAAB926695F54649921A84AC3EFD74B320
-:10DC2000A4D18C407B490AEE3B43533C35D8BFF925
-:10DC3000AA16C58F2F933EBAB14F1F95C9F5BD3DAA
-:10DC4000BA869601664234FF96350A3D54628B7956
-:10DC50002EED0FBEC97C55E68C1E9F42BA13F9FB10
-:10DC6000628C5E8218FB53A6FE35B903F1F08AC5BB
-:10DC7000FBDE5484BBE7B4199EC5E770113B93FBF0
-:10DC8000E3A731C61EC5B6070F277A7584EB15E2E8
-:10DC90002307F50779F5B1D79E3FB6A3A7988EF174
-:10DCA0004ADD220DB2992DCFBA33FBF0DE0FBF92C1
-:10DCB0000EB178AD977ADEDBE87C8D8EDB0F8FAD11
-:10DCC000B3D89E97FC49D748F5FDBDF834E4E595F7
-:10DCD0000B895EE2FF572E0CF2B2FD4AD2593E0C80
-:10DCE000793878FE7222E951C4A7AE219FF4B86C4E
-:10DCF0009E67999F851C84068E0A6EC3FE8524C18B
-:10DD0000F7AF24F61CCF23BCDF62F23C4BDB68EBA1
-:10DD1000872F2A20FDB975D1793380E205E5872860
-:10DD20004F8AEE84BBB10DA03C11FF055221487211
-:10DD3000628610D0BE355E789ADA19D3F414C2FB2D
-:10DD4000655CB3DD41EBE929C4F7F0D72B137D0502
-:10DD5000FDF15FBF117C1AEED3B0D1E6D3502F1C7A
-:10DD6000D8E8E47EE34637B78736EADC6E3A91FCC2
-:10DD700043F21FAABC169F16A157E6A50AFD300361
-:10DD8000F50EC13503946000796FC623C0F2887226
-:10DD900010DCA410BDF03C397DF844FA5CEE88E854
-:10DDA00043AD563B2193A582E95E9867E2F7D1091E
-:10DDB000083E9FD57F3ED23FAABF8CFC1684C3EF9E
-:10DDC000F296B9B00D397CB35D88DF7A65E9D14B45
-:10DDD000C0FDB9F4BC5EB943BD84EB8F0FCF841F87
-:10DDE000A2BD188F8421BCE2CF5D04FF84160B1006
-:10DDF0007DD0B0B27C161AF2F9B5A25CC0FD4884A1
-:10DE0000BE1B8CEF59CBC3C44F07A0238DF05E64BB
-:10DE1000F3D9497E97B9043F7895DBDD0AAE3739EF
-:10DE2000C3E25109B4E1BEF1EB117F2D19B821CE47
-:10DE30006F69C91CA2E713B7BDF13EC9B7D7E608A1
-:10DE4000AB6C98CC9D1D11F67C003CE3247F927452
-:10DE5000DC7768475A3F4E0EB09EBB6A09925E6BF4
-:10DE60003D93EC09E33ED3AFDAD8BFACA717516EB0
-:10DE70000F27268F653D13420D43F26313E7986D1C
-:10DE8000F6AF233CA0653E7A0ADFFBED6500D2AF1A
-:10DE9000D3DB3F54C90F2D31E50EE840388F2AA35C
-:10DEA00053A87DF2E3E47C6ECF2477127E0E9BECC8
-:10DEB0003AEDFBCE46BD7404F2CBA98D503A02F97F
-:10DEC000E3AD8D366E4F6F74727B66A39BDBA33818
-:10DED0004EFCF33A8E137FBD81E3D46FC3716A4F5A
-:10DEE000E03AD47ADF7298487E67BCE5D0A82DBCB2
-:10DEF0002B89DBFA3B932C748EC3C95067EC4FFC23
-:10DF0000144E0C378007E52ED5FD53DB0D683FAD71
-:10DF1000FE02651CC0D454F75C6D3AAE3B7BE88FC3
-:10DF2000BEC2F119A9C37E6A43786F3BE3683889A2
-:10DF3000FDD2C7F59F3A883F4F24A292243C64B794
-:10DF4000795136C793D218C468F7C224ECA719FDDB
-:10DF5000ECB9A5C80A4B4A3AF2C005B0F3B1E17377
-:10DF60006D88DF2576FF3F51DF12689B533A9DFA9B
-:10DF7000107092BC2BE620CBFB10257D11DABFADD3
-:10DF80000EFFC4D4087FC0ABFC218DF4C344AF02A4
-:10DF9000AE74A67770A4D2F7DC98B7D55136311598
-:10DFA000F9F7D72E95F969C234C51B74F4975F63EE
-:10DFB000DE84F37A29D16FE2C559B5D42E98E3E215
-:10DFC000BE6FD94DB524FFA58E6BBD5FC2EF875CD8
-:10DFD00066D647C51ACE8B63178D79E391C9C8FF02
-:10DFE000EE694B0C3E4B7C7DD65F9384FD327756B9
-:10DFF000A12A753470DFB56B1B8D97BFDEC072E54B
-:10E0000049F2E859C48AEDA569383ED3A178C22403
-:10E010002AD33EA94DA371A7E221B4CDF48E3B557E
-:10E0200044E32354CF4CEA9FD54B9DD89ED1664EF6
-:10E03000BD84F366E7A4786CF8DE99F08FAE10FF2C
-:10E04000CECC49F224E81417049FAEA4BEC7EAA9B7
-:10E05000D6E91C8F9524D33ABAE23161BFFED6923D
-:10E06000FF457014FB52405168DCA5911FFBE4C7CB
-:10E070003F2975E2BCFAA10A90FC9C09E7FE91E0F9
-:10E080009FD99AA8272040F5166729BD576F519C44
-:10E090009BB8EF2BA1F9815166FD795CF7E49D7681
-:10E0A000B607E56FE5B35F74F2CEC16C17CADF9AAD
-:10E0B000564CED4993F0DBCBDF2A9FC3E326089350
-:10E0C0005229BFEB1FF8BD1D253F294DC7F54F0C49
-:10E0D00073B16E413A956A117A0DE78342EFDF55CD
-:10E0E000C1F35B94013F3A8FF3AFE4A7145A71FF79
-:10E0F00059E90951F3E70C7145F5E78D1858AA4520
-:10E10000D8B1F2FCACA8FEAD454AE98888F9BE69F1
-:10E110000951FD45A5AED21111F36F2B1F18D55F24
-:10E12000725B56547FA669B2D01F1BA1BC54C87D38
-:10E130007929FB9BD9AC870A9D62EE1B387E3F8E06
-:10E1400017B6097FAAD085FE14D2A5B4AD88FD808C
-:10E15000367C8FC68BEC528F05A0DD3D91EC80FCA8
-:10E1600009E22FF68B6577663BFA056389AE68B7DF
-:10E1700023E02F7544DBF1FA44E127CC017FAD0B9E
-:10E18000E939A7751EFB5765E9D54561207C46BF77
-:10E190001F0B372AD19D77131FB66AAC37E70C895E
-:10E1A000D9AFADD4C17E8CF4EFE6C8B78C7D21E049
-:10E1B0006D27FFC63887B1FFB5CE33479DC67EE1D8
-:10E1C000DF3AD7AC9C85A5A971E15FCFFE4C2C9CB2
-:10E1D00079A9324F81FE15FB85ADA9EC2FE24F7A6C
-:10E1E0003C3FC1F07FCA51CFB922F59C43495F58EB
-:10E1F000706D3D67AC7B2DFFCF58D7781FEA54DE9A
-:10E20000DF78BFF7B9AEC47FBE1BE727C5799EAEE6
-:10E21000C47FFE5CF4FC199A5EE340793E0E8A27C7
-:10E2200040783FA96BE49A959CF5D6525BF6A15FC6
-:10E2300023B770F6F9402DB5533B8327AD78FEB96F
-:10E2400039AA4EF907C32FEA1767A50A7FE4F855E4
-:10E25000DDAEE3787D40B753DC51FF886EA7F8AAA6
-:10E26000DE0B73288EF40E37ADA738C49B872DF6CE
-:10E27000EF4D15FA7E857CDF680FA9FE15047F85BA
-:10E28000ADE351F2492ABFE9B1105F1C277F2FBFD0
-:10E29000BFBF775C0B3A68BFE38F041DBE087D7E6D
-:10E2A000BDFEDE2262A60CE253C517A94F4A6C09D7
-:10E2B000BE48FD51E67445F5C793FF83EFCD760F59
-:10E2C0008C7A6FAE9E15350FFDD81CF2876A2C90A4
-:10E2D000A3913E35257AC8CF8BC5E3EFE5F93D0E16
-:10E2E00027B951604ED7557F1CFBE42911F88B7D6F
-:10E2F000BE3D55C47383C89EE33A2752756E6B5575
-:10E300009F70E6D07F267E88ED63ACBA8CD6C3952D
-:10E31000DDC4771EBBE90ABAE0F0D2E3F3E76A682E
-:10E32000FF3DE34DFF381CFBC71E5F21FA534DFB39
-:10E33000B2B1DFFAF87DA27FA369BCD983EC19B82A
-:10E340007F6E29F90BE9BE7F27FA759B1D5B15D4FB
-:10E35000039509A8D7B0D54C0A14A6F7C5C7DB2D7D
-:10E36000685F91C0C86C5E17D2C06E15F17465C24B
-:10E37000D020D913ADD8AB13DE2A130C7A77649270
-:10E380009D87DA0951719DDD82EFE1FB6536FF0B58
-:10E39000826FC2C93AEAA5870E960D20FE3891EA2F
-:10E3A000643CE4ED9BEA267D85F0ED21FBFEFF0158
-:10E3B000BEE678F0D59AC53E9DF57925648FF38643
-:10E3C0002179943EFA156A3A3F4F0821EFB0BFEE2B
-:10E3D0007553FEB1C665F190FF7E42F2EFF5B6359A
-:10E3E000328FA1DA051FA929A6F57BB17D5BF2CF9B
-:10E3F00019B92F6ABEA10B913FC0D933745181E87E
-:10E40000137FA86A610FF9E13DFF90E4A1F8F98359
-:10E4100044813F18D2F3D18FF1F97B77E779B6F1D8
-:10E420007381A765C1EC9A0EEC8FB3066FA0FCE375
-:10E43000A134FF4784873BADC191CC878EF549B4A9
-:10E440008FE2058E538CF80FE33CDD32BC7F5C70AD
-:10E45000EDFDC1467665E9648177637FC4B18DE8DF
-:10E46000F1DE24F1DC8007E1E8263E30E0EA8507B2
-:10E470008638398F0022FFD425E38B2E5A8FECA7E4
-:10E48000EA1079DC3F9838FF5245C28AFD7DE74D9E
-:10E490001C0F1A79E02210FB4D3EB54965E003F8E8
-:10E4A0003B51A2965E695CCBF1FD84762D26FEF68B
-:10E4B000B23D9D2ADFBFA9D55FE2A0F6FDE8795302
-:10E4C000651C3F09822AC559933B62C61BE77F46FC
-:10E4D000EB4FBD18FD3C294DDAC3413028324FB215
-:10E4E00041C64D974F66A7101F6B182BA8480F8B7E
-:10E4F000AEC2A4D43E3DD3B011E759499FDAB82D3E
-:10E5000038EBBC8FF669DC880C3F9AF4AA9B5B431E
-:10E51000EE0ACEC2BD3036621F2917061E2FBF2F4E
-:10E52000F038AE23E797D3B06F6E354350EFC3C3D7
-:10E5300014892F0CDF38FEBB7CD1C1F66B62DB6225
-:10E5400095E4D9EA36811E71BE043D11F4087D6C54
-:10E55000CF498DEAAB929EB509D17ECA78B94F9268
-:10E560006750D47A86BF62D0F350EAAC56F263C6E5
-:10E570003B56B1DF9232293B6AFDA293D1F82E04BB
-:10E580009F97E263CF87C071C0C4B35A947F32298A
-:10E59000BC83F963D287D1CFA79C8FEE97A6C9FC25
-:10E5A000562CDDAE854F18FBCB69E97F3F3E5DDE23
-:10E5B000687CA6CD89C667862F1A9F039645E36BB4
-:10E5C000A03F1A1F83578D891ABF617D61547FD880
-:10E5D0000FA744CDCF428319D91FBE755ED4FC91DD
-:10E5E0003B1645F5473F7567D4FCDCE08AA8F1BCD3
-:10E5F000DD6BFE2EFA17843644CD27349BBE87FE92
-:10E600003736FE4BD47EFF53F4AF8DA1FF56D2E7D1
-:10E6100013885EA8370BFBEC19B925A43F5D4D6F3D
-:10E620007C43799B40B1CEF9AAC03CF0D4E0D82F0E
-:10E63000549F427A6E30A2DA847AA3D604ABC81E05
-:10E640003C6A32711ED390F317D3843FF2629AC8AA
-:10E650007B19787B1AED22D94155EA4373FA8E244F
-:10E66000F253549309DAC9FE691ED61FE71C10BE87
-:10E6700019F7550701E7C54A92272D9888FCA8BECF
-:10E68000A972FCA90EF2838EF6A4E6E4CE53849F11
-:10E690002B0E9B4E7CABA6FA0364DFF09CA1E7A196
-:10E6A000BF9FF3DE465849F196D15FE65EBF99E61B
-:10E6B0002FBB7BE6488A7F7B9FDFADAC2C8DA043D0
-:10E6C000E43917C5F1AB0EA409FB67D813C37EDC90
-:10E6D00069D56B3AD03E8C53857D40BB71200DF1DE
-:10E6E000F181F28859F86901339D1FED2ADF27B8BF
-:10E6F000D021DF806D4A9FDDD2BF43E6FA203BDAAE
-:10E700006F7D9300A33844F7F03DE31D86FE5D95D1
-:10E71000CBF8BBEC889E7FF9FEE102AFF720F690C4
-:10E720000EE72CE23C06FC17A55EFE42EAE54ED25F
-:10E73000C711F9EB55BB7626917F7E2E47F8E3C6CD
-:10E74000F3DF493AFF2E4DE5F3AFDD9DB0FE7C04CB
-:10E75000DE2A42AEA87E55E3C0F591F9CDB5C639A3
-:10E76000FC8A46E75827E5A8A2B523F94E607FFE4C
-:10E77000C3345CB772D7957B0ED0FBA69E4C616705
-:10E7800003BCDFD2F780E382A57F8128BFB633CDFB
-:10E79000CC7075A689386109364EE4BB25E803B80C
-:10E7A000A87D63DA2CE23F7C1E56B0BFA015CCA436
-:10E7B000BF16FAB3CC84F433E079673F1EEDCF691E
-:10E7C0003AEF731BF8F87EFBDD7B2A92D80F34D624
-:10E7D00033D64181203FEF3D57C09C49799FE90ADC
-:10E7E000FB17B89F8D9EFBEE1EBC99ECB0B1DFBB52
-:10E7F000E0BFF40EF2C522F0F0BAC6FA40D73411E9
-:10E800007AF9034B2F1DED44BF0D6DA630E585361B
-:10E810009CB3F2BD4A7775CFCB0F239C1FAFF9662F
-:10E82000BF82707FB4BCE7BF0EE0F33B9E5241470E
-:10E83000BEF1D9FD5A7A44BC79EEFE2B2C6FE8AFBD
-:10E840003CFF2429A597AC1E92930FD6BC342A32E4
-:10E850005E484E9F99904EF73B93D2E2DE6FC4C65E
-:10E86000A56B883F597E75F64B0DBE5C2DF972C3C2
-:10E870000BA3F9F986A4DEF388FEF32AE7C1363448
-:10E880005B39AFF18EE487352F7E333132CF578F2E
-:10E890007CA95BA975724BF7A63AFA09FB4E5E1E7E
-:10E8A000CB71ABEACFA2731EBEFA6932F5F7BDF9A0
-:10E8B0002D9F076EBB3EF8BB11799178AE4AEA797D
-:10E8C00097F44AC501AB4EF9AC9203B927EEC27E6C
-:10E8D000652BEA1F3CCF2557C7B1A7291E3BA800CF
-:10E8E000E5B72AC309ACE42B1B9420E5C3D634EE6C
-:10E8F000DD3218FB6BEA161611BB56250B7D5659F7
-:10E90000AF0437B11F3E87E95C2865A3E450EEBF32
-:10E91000E5E378D771B1FE858DB0F63CC69D5DF517
-:10E920005F5E2038D6355A39CF7621296C198CFB99
-:10E930005EDAAB84027A9FDC76B9441CB62AF4987E
-:10E9400085F65DF5DCC211E436761D386D213DB9E2
-:10E95000AAE1B159F2799130FF41968BB5BB9595FB
-:10E960009179ACD5E80E42A4FD42F80213FBEA40CF
-:10E970004E49FA2C6B1A5E43E842BDB6FF6985F535
-:10E98000DA42E2970F0EEFF9DD6F68DF83FF3D9209
-:10E99000F15F747DF8075F80FD8B4AB90F5C3C63C3
-:10E9A000A1F8B2B2C17C21DEFD5263BAEF1EDACF0C
-:10E9B000888F63FDEE2D1610F73FD9107C9EEC82F8
-:10E9C000A3C7B21CE1F9579A80F068CE1ECB0AECBF
-:10E9D000DB48CEC85EB81DC17871F5BE748DF18478
-:10E9E000B1C4FA78F7A021395EA27758289F57E979
-:10E9F000EEB4105F57863F17F7FF8D9FCCF2C689A4
-:10EA0000B75F4E57A4333F274ADE37648C61B93075
-:10EA1000F7DAC3908DE5BE60450FD9A90D07913B8C
-:10EA200014A2B7BF87E00EEC4FD0E97C25073E9FCC
-:10EA3000D811B1CF1FA57CF4E6595EF964AC99F00A
-:10EA4000B9EF93B15A52DFF3AE4CC7AA78799997D0
-:10EA5000D385DDDE9CECBB182D07099E30EE5BD91B
-:10EA600064E77B1494832D2D45917270C7AA5DC411
-:10EA7000E74DAA0725022A1B17FAAB797E9287C8B1
-:10EA8000A336CE0C101FAA4E1FF327FC15F79B28A8
-:10EA9000EF8F50FFCD4DF73F4D72AC396065641E6E
-:10EAA000A4D2D4F1AB1685E8BAC36BA2FD0A81F5F6
-:10EAB00096EAF075703C5594A953DC7B74C22C2007
-:10EAC0003CFDBC59E1BCAF39D5BF358BE87B5CE57B
-:10EAD000F996A32F04E8BEBB6B1C14117CC6797F8A
-:10EAE0003E2E0C2AAEB3B9003CB4EDE6834BDDC438
-:10EAF000BF3FCF38C67E86DD1302D22B35E83F50AC
-:10EB0000DEC79E1F0AD33A0939BE2215F75993EE84
-:10EB100064BEB458FD1ECA273D20FB36CDB78AE03F
-:10EB2000B3A5278AF87BC8F5E5F9BA48FECD746F1E
-:10EB3000E9E77C4B9759F069D70DC07122D7FC4C9F
-:10EB4000A6212FE3CD063BB8AD6A54D646DAD744AA
-:10EB5000F0DBE879D7C1A51E82DF9C2DF93D33910A
-:10EB6000E52276FF8F889FA9CEC0B4626B16E1992B
-:10EB7000F0A6F79FF7A1E47B031FA0F973485E118D
-:10EB8000546FBCFC923FBDF82CD17573AA2FC7956A
-:10EB9000CFD7BCC2297627C6953B9CFF01C9B731A8
-:10EBA000BF95F089EF6FD1FC36C2EF51895FB3C5D5
-:10EBB000A73B59FE7D3AEDDF7BBE41F1CFF78D3C9F
-:10EBC000DF966CFFF79EEFCFF27CE654E4375A2FC6
-:10EBD00019789E39391820FEAB4D82A24DF8F8A85D
-:10EBE0006B969BE46ECB916F8692BCD72679DC4006
-:10EBF00079B1E69B9691DC6F197427F3FF172FE428
-:10EC000016AA11FB24A7177F45E73B2FCFB1C5E21A
-:10EC1000CFA1737C2CCF699C6B49BAEF2FE911F916
-:10EC20002618927E5DFCB3D7B8D794719E47DA61FF
-:10EC30008CF3388FD80D895C7FB657FAE11AF898B3
-:10EC40007FECE0D1D9BFF2C209AA2BA96931C13644
-:10EC50003A3E25B522EEFD925593110C7A6D18B20D
-:10EC6000D335348D3B9FD839AF16E13E080155F8B6
-:10EC700069D1F90CF02A5E25328FF1DA9AEBCB6379
-:10EC80003CE3AF21798DCD634C0E9B965B52AE2356
-:10EC90009FF1DABCB8F98CD119D171514186CEC03F
-:10ECA0008572047F86C28941913783F194BFEA2639
-:10ECB0005B85E39FE39959DE95AE1C9B0BEDE0135A
-:10ECC0004F6CDB3A0DE57084C003F56B88C9F5F134
-:10ECD000EC07F5E6475E1BC37E38EA3D95F3024E2E
-:10ECE000094B0C1D8BD07F1341A5272ABF123EF67E
-:10ECF0006D32F1DB9E54FD2DA24F4F9BCA75280942
-:10ED00005A87C51547EE0E907F8076E09F33843E8C
-:10ED1000B7358A7B4B9BEE653D99E0748E5323E4B7
-:10ED2000242F43D8A58A631F0CB5A02C5D329D4CBF
-:10ED3000CEC7F5D7EDAF4FA634DEDA736F4FA4D24E
-:10ED40009F3B35FF820C3CFF17CAAE5136F25BB7D2
-:10ED500006C7127E42E16CAECF2CD020A015F687FC
-:10ED6000A7EA293C14BA04954FA5715BD0347E25DF
-:10ED7000F15F55589C97F630A38ACC6D54B8DFD517
-:10ED800058934AEB55FDB67910E9AF9732849FF35B
-:10ED9000E2D53CF1BE061ACDBF3FC325992A68A231
-:10EDA0007CE34B324FD97555E579C6FE058D335559
-:10EDB00027F2417E78C711CE8B365975A26FC27388
-:10EDC00020F0D194C07E68D5E1D94076AFDB051E36
-:10EDD00005C7F724F67C44FCD0D36CD5E93E37C197
-:10EDE000B9035271FD3DB21E2C1719B6DED1F7DC06
-:10EDF000D82FA1E997944324BEE07BE5046D074C2E
-:10EE00007744E23B49D859C9577B12C326BA67E910
-:10EE100041DFEF5986AB0F4EE07D0D3873D90EEC14
-:10EE2000B1F45CF8713AC3E5243EC8050127348D7E
-:10EE3000D649AF2638BD7C8E04A7EE0928FDE1AA8D
-:10EE40001A8B8E20CACFA3A4CCA6F4C97755625FD3
-:10EE5000DF86B2B0271BA4FCB76E2B9D16D9478561
-:10EE600033A9EFFDFF78E2F8B6DA219CFF0BA84842
-:10EE70007F3BB649A9744E21572812DE8C42810788
-:10EE8000AA0BB4DBC478EF7CE473472ADB7F9EE7F0
-:10EE9000B13AEDF3B2585EF87ED1F00F1F52C217AF
-:10EEA0006E46D2763EE64BC9C773759A8E3C5C8738
-:10EEB000F3FEB83C342A8CFD16ABFF79E2CF573F06
-:10EEC0005CB1BD80F4EF1EB3A79CF44F47E071F630
-:10EED000CB5F34EBDB22E40E86F46472DD61CC3E62
-:10EEE00055E7363D4EFE76F74145A7FBF46E73CFEE
-:10EEF0005082BBB2E9330BD563561DFC84FDEBB2E7
-:10EF00004CFF5EDA6F526335D7CF4D861D5C3F876D
-:10EF10007A91EB20436EA14F2E9F1DF56C75041D59
-:10EF2000DE93F2063DFE6164BF9AA4BC1EA6381CA7
-:10EF3000DBFD2D770CA7F5F7CBFC80F15E351C19B6
-:10EF40004C78DF04AF716B3CEF0E6A5CBF9CF7AE90
-:10EF5000ED5E6FC4FCD352FE4FCBFD5667FADF2047
-:10EF600078D7B67C6AA1D2C2AAF3A1A114F78634DD
-:10EF70003DC519478FF4CA6F8C3C55693D169A5FA1
-:10EF8000751158AF20BD6B53907E2FBDDB386639AD
-:10EF90003EDF8F3449213B8BF12AD9E3FD66DF60E8
-:10EFA0009A5FFDCED763498F1D2420F07F5F37AF76
-:10EFB0001D467843FE2F4E2439DB0BACD70C39CDE0
-:10EFC0002739C5F7F389FF8BA89FCB7A798FA57D69
-:10EFD0001ECBE57E13905C22FFB33C20FF3BC9DFD4
-:10EFE000CB77A23CF0FBA359CEF7B49BBCEC37A384
-:10EFF0005E1FC9FDE2C5D4DFD35EEA6439A73A8457
-:10F000004292D7F0115E270440D7F2450AF822FD5C
-:10F01000FFBC8C64712F24F1393943D883508E9E04
-:10F02000E2C173D855354A3E22ECA5E84B7B5A9A8B
-:10F03000F9976DBF98465226ED8453DA49FF78D68A
-:10F04000FBFF286DD586D7A72CA8C3736E38A5F211
-:10F05000F86119F785259F1C91F91AB21B7A9AA8B5
-:10F060001FA6E713B04FF5E513BDEB4BC81C4D9A37
-:10F07000B3E328B5537CA11272DBA62D6B3F6A1651
-:10F08000629E47FCD770646E1ED5E3759FB3420243
-:10F0900082D8F06DCF472F221E1E3E8CF88F63A7BB
-:10F0A000F038CC7FE87F0D0677FFF16E45EA91409E
-:10F0B000D27CE2C7AE06B5AF8F8054226353DFFD2A
-:10F0C000A47D7B006DE77F677A0767223ECF0CF057
-:10F0D00073DB7DFADB4C12CBFD67455CDF60F1E64C
-:10F0E00011FF346463A81B874FAD9922EF536485E9
-:10F0F000B8F79C37670A39181580ED0AC7EBAA33B1
-:10F100008874BFD4A07A2DE82F5D84C092A9A46F23
-:10F11000645EF701903F5EFC45FA3C28BB0F90DF30
-:10F120008276EBC15FC4D61178D96F31F25800EB0B
-:10F130004DC45F2B9B14F80FC4C5AA67A2E7AF9319
-:10F1400075F2AB1B771D1B8C745DF35CCC38F92D0D
-:10F150007CFF11E278785D5D743DC3CD99D27F1953
-:10F160000EC3C97F41BE623D61D6A0D58A7CAC602A
-:10F17000144322F69249E00BF52BCB67BE616F8AF0
-:10F18000855EEAB9045CA794BB3B7494EA81A6D47B
-:10F190006579688F299A189FD29825EEA7B4A04A5E
-:10F1A000750C93BCFE59EC7707BC67A9DE6495D457
-:10F1B00097E0C45FCAFBC8D3AF92FEDDEA606C9DE6
-:10F1C000A8C053959C37198235B4EFCADDA2DE6919
-:10F1D000EDEEE8F955124FEB9E3A7D8CD28515A1E4
-:10F1E000987189A7AAC6983A16B138DC9F29EFAD65
-:10F1F000647DFBF5D65BFCD12CFC8DB7E53AC6F8F7
-:10F20000E64C91EFADC463107DD705D520F1D12A2E
-:10F2100025902CFC5E702CC7F3DD67B081ACCFBDB0
-:10F220005FE2E93EC93F7C7E7CBFE219F17DC5FD0E
-:10F230003F8B867F0DF82C83F1F9830D3FB050DEB4
-:10F240003196DF56D599D9FF5D23F113CB5F6B7AE9
-:10F25000F9678785EC5B2C7F55FA956BC02FFCF620
-:10F26000FF5BF80D3AAF91CBAC3587393FB5F60966
-:10F27000C543F9AB6B9DABF73CF27C7FEFB99E3594
-:10F28000E83D06C630BDE7A45D17BD63FDEDBD9644
-:10F29000DEBC26E7052FB766733EDDE0ABD87566AA
-:10F2A00049BF7DF653C27FBDD4586227FFA3FBA49C
-:10F2B000C9A3E89CAF4C2EC0F38F6F5681FC91EE32
-:10F2C000A6E13B03087FE1A9A2C5945F1F7F0AED79
-:10F2D00013DD07B716FD5702DF077BD248EE67B68E
-:10F2E0008D48FBBD83D761FBDE7DB2706739E9E9EC
-:10F2F00093A545B4AE82E3549F5E28ED54F5C94210
-:10F300007B4784BDFA4DA6C8CF6F71FFFE518A1BA3
-:10F3100066EF357B283F32DBECDF9480F015BEA032
-:10F3200078AA71B763ED479EA47551BE28CD8AF3C4
-:10F33000FEE9088D57ED5118FEEEA6B2BC3D643FC4
-:10F3400083AA87EC6277D37DF90F921FD4FC40FE2D
-:10F350007D11FB1D4B15FA66F60D66B6D79D83EC45
-:10F36000BF2EA7BCA87717EB8DCE43FB2CFC7DC32B
-:10F370001E05DC78CE63EEA32F131E3A0F9CB65009
-:10F380001050D270DAD211477F1BED250CF3C29CCE
-:10F39000AFDD61E1FACDFD7FB0D0792B9FFB84F327
-:10F3A0006F6B287E203FEF1995BF773ADAFCAA856C
-:10F3B000F8B4B24E81015991E3661E27FD4AFDCF94
-:10F3C000EA849E36F87F85E47783FF0D795821F52E
-:10F3D000DA7D5BE3F3BBA1FF1E04EF9641B8DE03C9
-:10F3E00075CBB90EE9811DD1F35752FC7A23CD17A5
-:10F3F000FCBEF2A9E8F1D5BD7C1E60FD1FAB47BF86
-:10F4000033F47F2EE4129F5F0EAF18A6A13C7D7DE2
-:10F410007ACD308893AF3C29FD06C36E5F0E9BD832
-:10F42000EEC5CEEB6ABC62217B5BD5FA27F673672B
-:10F43000357DC9F4286F6AE17AD95BC0BF8EF07957
-:10F440004B93DD49FE767987D003F39AACC1A04295
-:10F45000E3A15AA273F761F1BD49E090C2FE1648DC
-:10F46000BDB852E275A5C4E34A8CE306537D8C8C8B
-:10F47000E32B65BCBE3A67D7312A29A994E3EBDABE
-:10F480008E26131EE781D05BF342426F19F431ECF4
-:10F4900050ACBE400B770FD1776D9395EBD6E74B11
-:10F4A000BD35BF0EF596D25F7F740FB48BFCF17E35
-:10F4B0000177ACDDAD6C889EEF1A20FCD8CBD27FF3
-:10F4C0002E1C104D97F21EB0537E7F9EAE7A82FCAA
-:10F4D00056BB46FBB78E457EC3F55BF5E129F1EAE5
-:10F4E000B58CF64D191718FD059467C3F921E70E81
-:10F4F0004764DCFF9F03847FB366B21A20BA46C418
-:10F50000490B0AB3E2C6497309F43786DCF7B371D5
-:10F5100091719277D728E2B77F75EF2CA7BAA6AA88
-:10F520003AA12FBA26E1BA29E4F703FBD15575D6E3
-:10F5300020C53355C82FFC7D1AF109C96393524683
-:10F540007C8271C6EDB4FE42BAEAC4F32F6C44FB70
-:10F550008ECB2F2CFD92F9AB6D843837E26D40BC19
-:10F56000B8C388372AAF0ABFD6785EA97570DC5158
-:10F57000D924EAB51B8E7C33340BE1ED6EFEF3D05B
-:10F58000E5544F3E40D8E786E2D0A75457F4F51E25
-:10F590005B5CFFB557FF2BB52C0F95E68E4CF66BD9
-:10F5A0000EA21F7913EAD1B7BFE038A5E148C2BD6A
-:10F5B00094CFEB5AE11FE6FC1E3A55C326F683377B
-:10F5C000412DB7E41F45FA8D2B9DA24EE941693FBD
-:10F5D000A9FF08F2F583387746617FF937F449854A
-:10F5E000E4EBD510D83255E9AF072AA4DCACCDDF67
-:10F5F000B585AEF663FDA70A294F1831B0BD8CF56D
-:10F600009FFE33865FABDF4E64FFB8BB4D7552AED5
-:10F6100019F1FBAB41E427625C901D275FFB85E499
-:10F62000CF4E797F5C3D4965FC99268BD6F0B710AB
-:10F630008FCC37DDA71D41B26F79875FCD263E584D
-:10F64000BB3BFADE89E8E8E7BAB1A0C84785EC7CA5
-:10F6500017658CBF74F8D531C46FD56F7F3B4AD026
-:10F66000E79B5196F46BC367B48A22E2669322E269
-:10F67000E6FD5A4732C56B5507555F643DBF41EF04
-:10F6800097A53C8126F203F50374E6ABEA26C11F79
-:10F69000A666D1E2FE4B447EC8CCFBF71B2F46BECC
-:10F6A000F91E7B060417F24095B987F9AFEAB489D1
-:10F6B000E1A93A7D397344C47B015A7700E9BFEA76
-:10F6C00075C0FAC40EA46FE7D3F791D89FFF7E02EE
-:10F6D000FB61C7B2B7978BFB2F15487F3DFCF69AAD
-:10F6E000D191F660E200712F0E840737793FBF1089
-:10F6F000FB4B3C6C824532BF20F879AF8C9B302E9F
-:10F700007B73409CB8EC7AFDE9EA662B50FEB9EABF
-:10F71000032BD7197DDDBC92E37EB8EA1F4DFA06B4
-:10F72000FCFE1BA97DF8F0CAD1F4FCEBC3AB6FE47F
-:10F730007CA9B2292ACF1120F8DCE45F7DF5EE5DCB
-:10F74000E47FB669EC9F14B69D7D97EE69F7359816
-:10F75000F9DBD18AFD13760692C8AF2A9C4FDF11E0
-:10F76000ED6BD598FFD0DF32FC2B3BFB57A78AD837
-:10F77000BFC2757C416E8B4E94D3BAA78A8B689AB0
-:10F7800082E3A4D7C6937FE5E8F3B70C783E93F8FD
-:10F79000EC6E49E0BC8B02D982CF604414DCEB1ADA
-:10F7A0005E67FF645DA31AF5FD88F1DE5F06887B66
-:10F7B00087EF0C3E0B295EE6A3BDA25DD7B82F9361
-:10F7C000CEB1D61C623EA9AE338BF13DA205BA077D
-:10F7D0009AC01F4107083F27E811D2659E2538844B
-:10F7E000FCFABDBDF78AB22E2428EAF56A5A87F3DF
-:10F7F000774C975BF7A5C7B34327E99E071DBEE388
-:10F8000059221E8A1DFFAD5BE4418E9F13FAF1F869
-:10F810004CFFE8787A3200C5225FA048FA3588EFBD
-:10F82000ED63E735D37A78FEDD4302C7898F3BF776
-:10F8300026F0FD63A74BE4754BEADB34FA1E666DD8
-:10F84000833281ECD2DA9CF7F87B19EC17919E5C3D
-:10F850001B3EC8F7AF15757B6779E3C0B1DD2DECB2
-:10F86000C33CF99D72ECF87C397E063C19329EDB74
-:10F870004EF73E67CACD4EF1DD9BF8EEF556A9D79F
-:10F8800017DF62663FEA0CE866717F22EE391648A0
-:10F89000BD7DABD4F7B1DF631BFAFD76B9CEC2678D
-:10F8A0006033DD73C47E9F7DBBF40F178197D7EF64
-:10F8B000F75DBDF41363FFFE42895BEAF551308AC0
-:10F8C000F47A08ED0DD75BE426B0DD9E5F3032AEF2
-:10F8D000DF41DFA9EBF23B756A0DFA57E7BEC7F6C9
-:10F8E000F078CBB997F9FB867309901DE79EADCFF1
-:10F8F0001E1A7AE436417779EF51E114301AF4BFD9
-:10F9000084115A647ECDA0FF83920EFFC7754539DE
-:10F91000A045E6630EA9FE07DD195447DDC9FE3890
-:10F920009E80ED219E6BA83CD7506B849DBB3470AC
-:10F93000795C3EEE3B5F6A40D893746E5B72ADECCF
-:10F9400037568414FEEEB0220CA27F9BC2F9CA5136
-:10F950000D2D5CBFB1A454F178855A3C4BF0197C55
-:10F96000B4C026FC03835F7AF125F988C6C95FB865
-:10F9700055FA0BB1FC341ADA67D1FA4BBD8A87EA23
-:10F9800036AFC947CBC6BD4EE1EEB5F808F9D24C4B
-:10F990007A31969F5E73FB1F25FC75B75F5E5280C0
-:10F9A000EB1FCFFD6C28F14FE535E4E84549BFDD9D
-:10F9B0008EC071AE63A9977504F5B98D1D849756F5
-:10F9C00060BFB2D3D5BE6583F0B7B98EA0229CC00C
-:10F9D000F5A5154D76FE6EADA2A13A710CE9E326B0
-:10F9E000D563C77E79C3E952CA239417893A972A07
-:10F9F000BBA8BBABB28BBABBB9E9FEE7DC13F8EF2F
-:10FA00000344D711583A7EB5E17BF83E56DF359373
-:10FA10000F37E17F4E0F354BFC6C68BB923986C4C3
-:10FA200034DD7F88E0EE7EFD450B7D8A5135E6D5DD
-:10FA3000595482D6ECD679DE2D752DB5945636E024
-:10FA4000B7BB9D42EF9A8343D86FCDBFBE7A9BEA86
-:10FA5000836F8C25FBD5D5D236D612C1EF9D1B50B6
-:10FA60006FC7A1633598A41C6BDC2ACA22E9470939
-:10FA7000B9AE6A3E9A49F98B4E92E77C6ADF491E1D
-:10FA8000816DC5DE33C923C99FD92F5A63BD4B4D44
-:10FA90002ACF03AD63D4ED4991F06D66F82E85C48D
-:10FAA0003A001DA31617448ED7FCBFD60717853E14
-:10FAB000E888D207069E4216E0EF880387AD5CA770
-:10FAC00040F73FAE083A6A0305FD6EC2608AE476ED
-:10FAD00032DD7B0F27974F83BBA9AF41584BA5FB66
-:10FAE000E9B02AEAFB86B0BE9F28F7BF490BB750A2
-:10FAF0003DF064795F3A05DA79DE0CE8E1D60B4E29
-:10FB0000FE0EBA183CDC4EB285E7535A2B3F14E286
-:10FB1000EF7BC2999AEB824D7E6F1D87DE7D78D395
-:10FB2000E082810F95EED5443D53EC796E1828FCA8
-:10FB3000BC9BBC420F914B41F5C09320C4F7F9D355
-:10FB4000A143DEEBC73FC7548C0BE91E6F3ABA31B5
-:10FB5000898C8F20CF9F46E751E39DA7633E931981
-:10FB60004A9D049F12CE347D67BFFE7374533528BF
-:10FB7000E5BDEFEBE9FA7151DF3DA8A7E98DF7A9E3
-:10FB80007E59F17AB9BED943DF8D53FC13D63A7B47
-:10FB9000F55936C098812B72064EE8FB6E04FCC006
-:10FBA0007524B1DF8D447C27021723FE2E9251E786
-:10FBB000BB3BB848A73A9165E936FE7B3B85B6A1C9
-:10FBC000E329AF7928CD9F333083EA7DEB46F2629B
-:10FBD0005A7002FBB992BFECE09D447850BCC6F766
-:10FBE0002BC07CD3FBF70B3281BF27B25BC5773EBE
-:10FBF000DB911F6DA92C053AD55FC323253AF9D3B4
-:10FC00005B5C360F7D476C25B8ED7D70D7D8441D01
-:10FC1000488D4DD47918F572B178ADB119794E8F00
-:10FC20008DFDF198EF907E62F3DF42787A28A998F3
-:10FC3000FF0E53DE2BD3DC5C0F25BF7FAA4930F0CB
-:10FC4000506CE3E77DF594EC67D6523D37C259938B
-:10FC5000015CFF783469540AD565D5B4897AEE9A87
-:10FC60008C00EB77B35F617D5FD35AD24AF6E2B284
-:10FC7000C3C275DD352E51071FC880D0F37A343DDD
-:10FC8000A619F4A0FB4B598F64D0655C3A94D07BE5
-:10FC9000E3C2DE91849342DBCB37D0FDC2B87074EF
-:10FCA0007D19D26935D1A9F73B1ECDC9F51E067D58
-:10FCB000907198D99D92EE06BD9CC6DF23F06A51E3
-:10FCC0007F8FC0A0E3F644412F3355E00CE77775F2
-:10FCD0005A37964EFF1BE114C1BAB04B000000002A
-:10FCE00000000000000000001F8B08000000000062
-:10FCF00000FFCB936560F8518FC0F9D20C0CDEBCCD
-:10FD0000A862B4C40C5C0C0C41405C0EC41A407B6D
-:10FD10006F01E9DB401CCECDC01001C4FB81F81F90
-:10FD200010FF07620D20D604E25F407945A81B5BF7
-:10FD3000981818DA80B80388BB805887918141975A
-:10FD40009178FB93841918DE8923F87A120C0CCD74
-:10FD500052F4F3FF60C33156F4B5EF29D03E4E178D
-:10FD6000043FC71998245C50D570BBE03783074D1A
-:10FD70009E178DCF87477F9E212ABF5C0B953F4DF5
-:10FD80008781E123929A0A2DFC6E41C78A460C0CAA
-:10FD90004A46C4ABDF608CCA0F3081D000F9ADB1E8
-:10FDA00009A803000000000000000000000000009F
-:10FDB0001F8B08000000000000FFE57D097C54D582
-:10FDC000F5F07DF3969949662693900D0871028AA5
-:10FDD000A88013086940B4C322A2228E5BC50D26F9
-:10FDE00002D93710FDF0AFFD3210362DD6D0824645
-:10FDF0008B74C0A0C182040D1824E0002EF82FD50A
-:10FE0000D8BF7B5B0C4AC31692801B7EB5E57FCEC4
-:10FE1000B9F725EF4D26806DBF5FFBFDBF69F1E6A9
-:10FE2000BC7BDF5DCE76CF3DF7DCFB14DB2896F89C
-:10FE300063C6CEE00FD2AB2C8CB151DDE96CDBA0F8
-:10FE4000A187FA74E7FF5965D3EA87421EABD06EEB
-:10FE50001ED6FD9CB185547E408C6B38BB1CD3F400
-:10FE6000101B0E8F6DC91696CCD87D6E46BF01094A
-:10FE7000BE742991B1CE1556F7BA0C78AE7A5C08EB
-:10FE8000DFF7C8207750C2F73CC95216E43FA2BA48
-:10FE9000D701CCBE3F23B36CC666DAE06F0FFCC35C
-:10FEA0007AA0BE7CAC6C1063EA699905A07FEA7702
-:10FEB00012A5033436C3EF0078F92D6CDCD0EEFECA
-:10FEC000B913FDEC7380B7E8F9897E5BC0907F09B8
-:10FED00093A8FFECFB4AAA5F6F6FF1F25B6C3E07E1
-:10FEE0003616948DCF3B967FE9C2E78B9B6EA17A45
-:10FEF00018532CD8CF72B7C84FFC5C6396EEFABB90
-:10FF0000F114A27674D8D304EDFE8831E9B5BFB6FA
-:10FF100032C043D556D56305BC4CD8AA867F0C7039
-:10FF2000E95A2984B065979D31C04BFB6A0E879DC5
-:10FF30009A0FCB9FA80518AA28B736FFFC0AC4DB86
-:10FF40005699ADA366FC84F7561BC73B6BE4709EC5
-:10FF50009D83A56B774FC7F70B1AADCC0EF5956E49
-:10FF6000CF9F7A05C0F9FB5486454AD72FD0FA01B6
-:10FF70005C1892EA11EE18CFA8FDE03639B41ECA1B
-:10FF800077B89A936F83F11FABB431CFC5D06F6749
-:10FF900073F2AD8087A2D09649F85ED146C98B2C0A
-:10FFA0003461EBFA37FBC27BA51B24AF15F0525C22
-:10FFB00017CB3C43781FCEC0BFD60639FC63C89F21
-:10FFC0000BE3641948D7EA494CC6F657681E6737F1
-:10FFD0009E8E550E611E6B375CBA01DA81F7CA5EE0
-:10FFE00094BC38C4320B0B205FB66FB74F7BD68101
-:10FFF000E35BA00D76E2B8966A582E3F94BBCDEE37
-:020000022000DC
-:10000000C1FEADD526417ED1EAB55A9E81FEC575A9
-:1000100097318FCDD0AF9A412946FE884C8F019BF6
-:1000200018FB53C498AF1EF94409693719E4A29F1D
-:10003000144FF42EAE934DF50326194B82FF7E002C
-:100040007F02BE823B9D84579D6E73051FE9743B02
-:1000500025E487299DD9C6FAF5F4E74807E84F75E6
-:10006000A59BD25F54A652BAB2D243F47902F107EB
-:10007000E972D16FD758364E81765D3EE646314BF8
-:1000800098E21BA7029CE0E770F2DD01C97396F1CC
-:10009000EBE9136A20176572159BE453FA02AC056D
-:1000A000E6302FB4AFDCE89B389AB1D759E0711C29
-:1000B000FF222950807465AC3ED50F745922811EF1
-:1000C000017C2DC541021E96F4057E063A3D714F16
-:1000D000F6B3B224C69A8870DE738F66503D3554ED
-:1000E0008F0AF50C3A773DC9D3734CF5244F2FD0C6
-:1000F000EB594BF5D8CFAF9E27A68F31F7677A9192
-:100100005ECF0B586E91F3FCC6953C63ACB93F33A0
-:100110004AA89E94BBBD2C00E5659D7F58B34F86D1
-:100120007CC7C6F8118F32231F8DDF86F53941AAAF
-:100130008C7C1497136392A7785F8209EE33B99F82
-:10014000A97C927FA0293F65DAA5117CE970B75E92
-:100150002660E854385EA3FE6AFD34D23BE3FAD948
-:10016000087EA09F83F4CE03630217BBA1DFD8579C
-:1001700006F47F400B5CEE8EC237302E89A562EA12
-:10018000B1601A99BF54E5781BDFFFFBC107E1FDA1
-:10019000724BE7E07880FF4B1AF7218EFB8FA84C5B
-:1001A000816E3132ABC072315646FA6F6946F6B392
-:1001B00041035E970D007E91BAEB5DA60652911F3A
-:1001C0005B821541E4CF253041B07E8C1D6415E182
-:1001D000E085F0FE80BC54C4BF5503FD616C5F83B5
-:1001E000F68752FBADD87E5B2FED5B07E698DAB75A
-:1001F000A51798DAB769D03EC8476770BE681FF088
-:100200003786B1936C3EB56F4D2FA0F6976AACC0A0
-:10021000D47E4C57FBDF60BBDF63FB4951C63F70A8
-:100220008C79FCE945E6F16B7CFC6C4150B41F43D2
-:10023000E397A4201F7F7A111FBF95D7DBD5BEABF4
-:100240000BFF9A04ED3AA45EC63F68AC79FC1794A4
-:1002500098C76FE5EDBB172C13ED3BA8FD78691926
-:100260001FFF0525D4BE660D78918FB4FE31152190
-:100270009C4FD34080524807FA281D92C018E8933B
-:10028000DFB2818487076238DF7D1303FCE6E8D69E
-:10029000A72C041208F37099E0E9E28DE3343E3FA5
-:1002A00007695E9F2DBA3AAB51A6F98CADB4862E84
-:1002B00082FEB637CA418467ADBC3224D37C0A764D
-:1002C00002BEA7B0303EFFF3AA61EB8CE38A4C6715
-:1002D00057ABAD2D06B9EAD2EFE3D9900AE85F0536
-:1002E00032C1A86EB815F434033DFC39E8634C0FF5
-:1002F000ABDC2E39047A9C5D6C949B05DC2E09B234
-:10030000F78740FF7F22FADFAA707CB7CE9342883E
-:10031000FF6F56CCD1509FCDAE8E05A477F7A35C6E
-:10032000D0A973BB3544F6144C07889FDB491419D8
-:10033000FBD3AE1BDE945C303FD6F431BD77370B78
-:100340002D4E85F23397E70E70C3F8EF9A661D21A4
-:10035000E3FCC47CFD2D24C7ACBF2587B1690D2B00
-:10036000D4FE00DC3E4DFDBCC5F0FE1D01337C57C4
-:1003700081196E5743AA05ED994289AD857AEFA997
-:1003800030E7EBED4C9612385D457B3F011CF48560
-:1003900047F7603A021FBB89AED3DDFC5DBD3FE588
-:1003A0000FA92C4CF3714B1223FA2751B9809B8F64
-:1003B0003BB2BFD3559BCF0FFD99FEA04CF88CEC00
-:1003C0007FCBAE589F05ECD9969A2F5564C1C8F1E2
-:1003D00044F67FC6FCC8F1B8359C1F728391CF39B3
-:1003E0009F44F25379E3B85F1E32F05369FDB5BF05
-:1003F0003C6478AFB8EE26135C18BAC3543EBF26EF
-:10040000D7943FBBBAD0943F73D91C139C1B7CD0AC
-:10041000547EC6FC05A6FC7B2A1E31E5DF55B0C222
-:1004200004DF1178CA54FEF6696B4DF9965D97DCCE
-:10043000887254F581CC70DEF8DAD1FA73B437BF24
-:1004400076285EA4C711B057500E8E81BD82697B9D
-:10045000E348B2AB410FE63130A1564BFB83CBC62C
-:10046000A25E66A43F43D2EF83C134C69E973C840C
-:100470003FB94663616061892574F171A76CC86FEB
-:1004800039477E0D08FAC89EF9724BF4E7E5EB7226
-:100490002F40BDD39B3E805F7F9CE73A843D1099FF
-:1004A0005F2231BFF1B9BE7EBA5CE27ABE44AC5382
-:1004B0004A5EEA3B9EB9100E0FAE385B7BF5805466
-:1004C000D49368FD27213F801418E8515C37C82475
-:1004D000DF6DBB65EA5719EA04D0AB99CCBF574230
-:1004E0003D13DE9B7ECB30EC87EF75D4FBAC3189BE
-:1004F000E6F5B6CAC9BF3CA4227DFC941EA99C4661
-:10050000696B6580D2439505947E5E5941694BE5E0
-:100510007C4A0F540629FD63E5324A3FADACA6F490
-:10052000E3CA1A4A3FAC0C51DA5EE9A35497872E0E
-:10053000FDEB17F6B058B7C0036E0F8BB12C82B22B
-:10054000CD24E7DE5494F3538E6F06A3BD7FEA6398
-:1005500060A28CDEF115C96FBDD3D147F64A5E08A3
-:1005600098A74FCF7C7B0CA793DDC22633D0478F53
-:100570005CF49CF7DEA1042BC832C0A9DE9B9C5121
-:10058000EA85B90FE9752E3A315FE7705C67B73ECF
-:10059000FD976CACF77269209F87F7CA340FB3F0F0
-:1005A000B35EA4D70FC59BF4DA9FD25BA0DC892E83
-:1005B000FC35A73348E7486EAAFF5483952988C7BE
-:1005C000A6D8102E8D4FED7BD685F2383755AE3E2E
-:1005D00034B2777C95D667543B0CE3296F34C3A7BC
-:1005E000AAA5C9DC7FE089BB7518F295BBFAD04596
-:1005F00048FF544AF57AE6A66AD4CEB1BA41717C76
-:10060000FE0EF17970633CF12BAC3BA9FC3FBB3F84
-:10061000BDD5A3F787B106F6850DF501E40D3AF7D0
-:10062000FAA807DD95AF343FD2AB49FD06ED85183A
-:10063000F8776620D6AB10ACD75B5E2F07AD97E39B
-:10064000F38DA6F6E03D8FBEA6C7F77AE75B85B5CA
-:10065000EAE3047D75A5F0E714D7D9ABCDF34ABC26
-:10066000092E6FEC5B6D9A67F00F907F562129C8B9
-:100670003F25829B3A14C73209FA976AF150BDE5CB
-:10068000122F576A6BD1021E62C766B433EECDD10A
-:10069000F9CF73FB1F40DF1FFDADCA1EC57CE1D73C
-:1006A00051F56CB06F2DE8E711D0BD0DC55350EF7B
-:1006B0001DDD763DD927B398DF858BA402569D8D2D
-:1006C00076CE0966998CFC7F82FDDE35D2B0DEC81D
-:1006D000B768D49F99CBCCF32CD8672638BFC60C0B
-:1006E000E7B19B9391DFF356AA30B7A05C9AF36F02
-:1006F000B7B849BEF259C5125AEF083FD8BD6EA629
-:10070000F407B92F7DE599ECDCA1E887E0FA5BF707
-:100710000F1426703BA52831A4F920FF8B86913F4A
-:10072000B982E1FBA125A8A7824EE65DCF7AD2EF80
-:1007300087F63FB2BFFA7CD2C34F21FA21D749BE18
-:10074000509475DAC31649D85B414A978B71EB76A2
-:100750006B4D045C1B01D747C07F37BF253213BFE9
-:10076000A55A02359624CE5F682F484AA716F84747
-:10077000EA4FED517FED3FB5FE34A83FDB547FFDDE
-:100780003FB5FE0B7BF4BF295AFDA5AF6CDA16040A
-:100790007D53B479958BC13C7454A94EF602DD4B60
-:1007A000D62F76211F1C51822EE4E7A321797234C3
-:1007B0007EF8D222FCA2CCE790705D857F42FDC717
-:1007C0005EF8D954B4E7BE59AFBA69BD54670D5B42
-:1007D000414ECB1A0AA7A0DF17E0831C5E7A52466F
-:1007E000B8D1CC9F45CFAF4A46FF1E708A584F8480
-:1007F000C95E2AABFDF3249C87CA5927C959E47BFB
-:10080000D8FEE904D28FB95A5CCF7CE827D9F9E544
-:10081000022FE50D3F3B29BB30BDF630EA13B04C4B
-:10082000C80E8F7CAF40D841872CCEC4565842B1F9
-:100830001FB11FA1DED4F1C242DC0EAADAF0E4F04F
-:1008400083D0AFB6DADFBA2403BE74793B553FF3E9
-:10085000D7AF7A7AD7CBED62BDD7FD5E88DEF334B1
-:100860000AFBAD89A7256AD885F671C95AD51B84BC
-:10087000C7259B9E7DEE695CAF7E62F55E04F51731
-:100880006F7AE3C33100176F5113A7F06138A4E406
-:100890006EFA94C3BFF923BAE951F4F21B9A6718B0
-:1008A0007FFE7042375D8AB7ECD6D8B09EF898507C
-:1008B000BF5B6B7144A14FFDC1496867556DF85628
-:1008C000C375E5D15D124BC98882CFB56F90BD80ED
-:1008D00078227A0A7A75D12FA27C39D005F57A244C
-:1008E000BD22CBBD81FA6514AF17FD93C0DF2FBECB
-:1008F0008A7EEC4FAD5EC443C18BF7B9703C8795DF
-:100900000ACEE7CF2C4E463F7D811A4C7653CA9FC4
-:1009100017ACB99FF82FFFBDFB93F9FAD0D7D74298
-:100920007355B02F8E73F6EADB689C792C407C58A7
-:10093000F08CEC0F41FAB5C2266F892227C5329799
-:1009400093C3EB80B830CEC3B84E41BFEEEFE5D0D5
-:100950007AF28FCC61A80FEED7FDF16C2EC15F8BC0
-:10096000FD8471B2455FE7DA4CFC5BBBB419E974F6
-:100970006C802F05FD6AE54C090A7C4867A05EF98A
-:10098000BDAB53389D9847C916EF815D30019F6319
-:10099000F966D5671F6E7A8F9DC9E86E7F9E681FC6
-:1009A000FA1D83F3F9E16456501F657C35B2AE073A
-:1009B000605E37F09941DEB9FCD73EC2E55D97FF36
-:1009C000D04D9331FFABF7B91CE17B385F42BFC21A
-:1009D0002994BFFB5689F4839585A3C979AD2AE490
-:1009E000DC9C1FC92FD07F458A33F00DB69340742D
-:1009F00020BF5ADE4A78DFA857B15D57CF7A7539E4
-:100A0000CE17FA204F067D7059B73E60ABB91EE88D
-:100A1000DDEE0AF2F59B1A7AEE69945F90D7A00793
-:100A2000E557F5E3F88F6FDCFBE19D20B7C7EB7569
-:100A3000B935EBD548B92D7869BD847C1A29B7C77B
-:100A40000BC04A8926B7F03CAADC16B4FC4BF4AACA
-:100A50008EC7C765B35ED5F5646FF88CD49397CA1B
-:100A60009EA87A127EEFB3EC9EFCA8F3A1CE7F4540
-:100A7000BF29BD80FC093A9FEA7CD8C5A73A1FF67A
-:100A8000F0CF98F018997F3BF2040CC1BF5D257F31
-:100A9000624913DF8F83F7DEEC9F45F8F2D134C74C
-:100AA000AADFEC9F68844311707D44795F04EC8F6A
-:100AB000281F88802B4CE54B1AF76A8CF8206C2A8B
-:100AC000679DFF2BF6459475AC3E0F95379CD482FD
-:100AD000C81F699D1AEA3F752198A8E83FDC299351
-:100AE000FFB00370BC04DAE9D898110A821E596C71
-:100AF000E7EBCD0E77A72B01D2C5F11CEE4CD296B9
-:100B0000A01ED49F77DAB91FA4C3DFE98A37F83172
-:100B10000E36C9A4C75B426C72343F09CC3484DF03
-:100B200016D65B3EF78F76E0BE33B687FBCE40CF5E
-:100B3000AB6547FA7C5CBF56CB5E6023366BC1ED7C
-:100B40002E74A177340DBA711A3C9FFDB6CCB76DE7
-:100B5000823EA5AF61DD7184059F182BE17EDE72B8
-:100B6000E29F994D7C1D326B7974792812EFE5393B
-:100B7000E669A87761FDF0B9D10FACD753B03AE27E
-:100B800079D3F5426EAA693D58546BCE0F88F5D4DF
-:100B900037BAFEC96499A47F70A184EB7AA1B7AF7C
-:100BA0009687DE380DE8D3B14F66B8BF7AAA4926DA
-:100BB000FA9CDAC8F753593089E4AF8C7592BED4E9
-:100BC000F1D686F27571EF7AAC6DEB9FB21F423EA3
-:100BD000DAF687E1BF82B46DDB27837720FCCA4752
-:100BE000E97F603DCB4FD865273F73C72E27F17F44
-:100BF000C7CEDFA53F84F0762BF9F73A767D3B1C14
-:100C0000F9B163A1B500F560C700BE7EAADAF9EDBF
-:100C1000F0169A7F17111D33148DE87DAAE92F076E
-:100C2000302EE054138C0AED8B5DB1245FE5AFDA12
-:100C3000C91FD1B1F3DBEC80E39F379E32B1FFD304
-:100C4000E164D35EC2FEC573BF79F98ED1CF2EC0E9
-:100C5000FDF186DDDA4CC89FF0DA5F87A37EED7880
-:100C600089DB4DED6ACB1ADCDF18BA485EA802BDFD
-:100C7000DA51C8FA31B66FD1C4F128473DF1F257C5
-:100C8000F2B39C2F3E26287C3DFBEF8F0FC9C7F5A2
-:100C90009F33649370DCDF1DF803EA895D56E24BF5
-:100CA0007DBCC7EB17903D73AE71DFFB3F6EDC522E
-:100CB000F87CC6BDE0DF9CFFAD8A87FA1729073DA7
-:100CC000F97CE703046F727AA9BFE7C9EF6BFFA74E
-:100CD000D1FD25A0BBEBDCE30EFF3F4BF7B7A70B25
-:100CE000BABB313EA0FCB5BF52FF7EA89E6BF93760
-:100CF000A77B6FE3D7EDFDB72C9EF733A1FC6456BD
-:100D0000ED40C3E2DAD23D6F6742EE5B697BE3B14F
-:100D1000BFE323F67BF4345EE5FEB6F1B8EF03EDF6
-:100D2000B27849AC17F93AABBFB02FFACFCB233B1F
-:100D3000A47FDA63644F30C5B312F72BDF4A9FE913
-:100D4000A5D80B36E2E300C2EE2B056C5E6FFE4ABF
-:100D5000623EDC4AED9F7EFD3EB473D3D264B28323
-:100D60002125FBF775D764FEBC4433AD87AEF598FB
-:100D7000D7479312CDEBA889A2BEAB19EFFFD50ED2
-:100D80002914023C8C1FF0CB44F4A78EBF48651297
-:100D9000C093586011AE3B263ACCF59DC07D6C8364
-:100DA000BFF1EFC5E3C42E3C0E5CE9473C0E90C991
-:100DB000AF7A4E3C62BF096F99218CC7618A97E375
-:100DC00031A1D44B7E6AB11EC76EA21DA3389634E2
-:100DD000A33C2BB89EE678A075B8BE9EEE0DDF4C06
-:100DE000ACCF15D1A48E7F254DF6D9CDF5D1FA5CC7
-:100DF000A7CB0FA5874EC77F942EC9AA992E698EBF
-:100E0000390ACAEB645C3F8CC4F2991C4E0B2AB4BD
-:100E1000DF24D60FD778E628418027A4652A48AF7B
-:100E20007CDBF6228C1FB57925EAC7C56D169A1FA3
-:100E30006C5912E17D488D42F07B16F728A4F7D457
-:100E40002B5E39FE20433FBB4FE306BA9FEF977CF2
-:100E50007FE6CCD86CF4C7F01FC67FDE00EBB75935
-:100E6000AB593806F0345B61C1B804F4934BEC73B2
-:100E7000939FDC0CE3EFAAE4EE7ACE55BE37BDF2C9
-:100E8000CF4E5F013DF6F9458C6DC7946F8A28C639
-:100E9000F5F68F9A38BECAF7B3D0401E8721FB0DF6
-:100EA000FB8A2FABDC3FF3CA1F5F1A89EBDC711D95
-:100EB00043E3B87ECDE271A962BD708A79E2BC0ECF
-:100EC000D4AF83E268BF749FEC8C16E7B841ACBF27
-:100ED0007F83F1289076D4B26A19D757AC93FCBEC1
-:100EE000C15A1B5B1F251E668D6A117E224137F891
-:100EF000C9D9B87FC3DB9F0DAFC619E9D636E5A8BF
-:100F000032BC271DF0F7B961FFEA1FC52FAEF711FC
-:100F1000BF1BEC2D93FC51F447BDC0DFD43DDF91E6
-:100F20009FF4D2A6B516E4DF4B6B2DA6FDD83A553B
-:100F3000F83146B011D8AFA97BECCE2CA4CB3ED96A
-:100F40008BF1A5E54D27B540947DC4487C62FDE852
-:100F50007F6F55DDD4EE0EB57E26E275C7091BC343
-:100F600075F576ADBA385A3FEFB4F27ECE66F5F736
-:100F70000DCFF8F7C3EFB80E47783CAE3F6B99F052
-:100F80008344F21F233E3E55C74238BFE27A15F52F
-:100F9000C2A98D8CE67740C963B8FE0679FFB1D14E
-:100FA000AF7371E396DFA05D50D624B9714BA24CAC
-:100FB00069D1D08F5BDE182FE33C9CE9D1E36FDD74
-:100FC000C36E35C845ABAA10BEF68ED97117B6FBF5
-:100FD000659BC6D04EF1BDDEE9C279FCCBA691245B
-:100FE00007BD8DEBE54A563411E31C843E8CE48743
-:100FF000A11B634CF01572A01FCAD7546BCB3C6F7A
-:1010000014FA2DD324B18F789EFA2DF4FF997E7BAC
-:101010005FD76F01D96F9023BFC09B41BFA544D359
-:101020006F73254F0AE27DEECE412948D7B96FABE9
-:1010300049D1F4DBA64ABE2FBA59C44D7734807E1D
-:10104000BBDCA0DF1A40BF45891F19A3E97EFA73F4
-:10105000E8B7D0BF46FE36A17E8B32DE1B04FE749D
-:10106000FD36BCE920E9B7E10D16533CF0444DF8DC
-:101070009B7AD56F52D2AD681FEF53BDB151F8675F
-:1010800093B0C7378B38466C07F55C95F6C3F45CB4
-:10109000DEF9EAB97F119E753D37772BA3B8E89E3C
-:1010A0007CC8F5DCDCEDA0E724E447AEE7E6EE64BF
-:1010B000DC2F17A1DF86F4D06F8CCA9785F9FBE58A
-:1010C0008D194FDE0DF58DF0A95E1B941FD1ADEF8C
-:1010D0004619F55D95D68BBEDB777EFA6EABD07781
-:1010E000A0C706A27E8DE40F6F9339DE7CC7E8C3EC
-:1010F0001B5F4679F99D4CFB92EF59F8FED13BA35B
-:101100000F67217F7D2AFAF3A2C6E9D95E19A4FAF6
-:1011100027BCCEC757BA91FBCBCB1AB87D58562BFC
-:10112000873CF0E7A431DF69D8FFC29D124B01F87C
-:10113000266BF5130EB4EB9F5799581F4DC934F029
-:10114000C3AC9C62F2FB57D95DEBF0FCD12C85D986
-:10115000D0BF5FEC987414EDE0E21CBE1F502C9ED3
-:10116000EB71B0B3BBF464443C48E39C37FBB39EE3
-:10117000711653AD9CAE539F954218B7DA33EE22E9
-:10118000447AA1B8CEFCFC5D217F37C92D842FF6AF
-:10119000AE1C35EE432FD785A77D024F8017139ED7
-:1011A0004252543C01A5A7642677E3A5F0772D4B66
-:1011B000705FA0F02989F69123C7ADE32D72FC3A48
-:1011C0001E753F77B1A82FBF692D9D6B8AC48B8E8A
-:1011D000E7487C74E13D021FEF695D7EED9118D711
-:1011E000047C437A26F89F801768C73FEE22D3F924
-:1011F0009B8F045E46568F9B80E10F37611C3AE45B
-:10120000E7D5CC79B32FE063D4C79E11389D5E310A
-:10121000C61AC07DDA0DF64ED2833A1F0EB3723E67
-:10122000D4845ED9D1AF623CADF31B2537DA21E51A
-:10123000613BE1B51CF8D10E45F63EF5CD24815752
-:10124000379DAF6A14F313D0C182EB267DBE0AF13D
-:10125000F358239B385DCAEB385DB25827EDC7942D
-:10126000D548DE308CA7AC710EC5A1EBFA197E0E05
-:10127000239DA2F0AF128D7F193A9BB3BBE7CD62DD
-:10128000516EAAB5FA43DCE7990AF2B196D810FE7E
-:101290007716FE3E57FC5024BD2E1378DB847875FC
-:1012A00020FE3AB9FD15FE8ECE69E9F9E54AD084F3
-:1012B000D7094F9FE6FCB753F2A05FAC0B6FC8CFC6
-:1012C000903F4AC71BF233D2A1295746380FF0DDB1
-:1012D00027A3E77871BFD428F7853B0FF2FA9F91D7
-:1012E000BC2CCAB87F307FFF40BEEE4DDE8759C5AB
-:1012F0003A41F0F73BF6CEFD2391BF774ADC2FD180
-:10130000146FDAF7BCC1CAD74D1BEC2007B8DFF663
-:10131000B6EA5DE7E9A91FAEB27239C0F584C7E04D
-:10132000F7BA040782F1A675368A17A47E0CE4F694
-:10133000AA515F6FB2B3A45BB37AAF7F8AA8BF37FD
-:101340007B498787617BA8471BA1BD21DDED45CE89
-:1013500017BAFFE05CE3BA43F0CFDF3B2EBD9D1F21
-:101360001A4F55CE9A695F4C8FAB4AB5045E51D186
-:10137000BE9B2C99E2B7A0E782CEFF70FDB76AA3AF
-:101380007AAF9FA5DAC88ED0CFCB5E2D3B5810F038
-:10139000F6A54F2579012BE383B1387F8C8779102F
-:1013A000922FF78FFAE86ECA97699FEDC6DFF5298D
-:1013B000C57DC81B790C1DBB315322FBE13DAC6CD4
-:1013C00034DAE136E6B38A26213FE747F1213CD7FC
-:1013D00092595B3DC103723DA22E5485A9774267A5
-:1013E000E23B48AF7132437A35FBFA4CC0F9F7BEA5
-:1013F0003FB34CDC8A073B81EA19B18F2561B931D3
-:10140000BE245ACE8C6EF8EAFD5BA07FA3F7CB5EBC
-:101410000F94BB69AFC381723664B585050C78192A
-:10142000C34255E8771A7DC8770BEA8302B07BF098
-:101430007C4941D3DA2A17C2AB257ABF3C1898E41D
-:1014400082FE6DAA3939E932D40B500EAB295FCD3B
-:10145000CB95D74A5E0C71CE6B5A41F14879B512E3
-:101460001D60DC1492988DD71BB241BD9B56C3FB07
-:1014700059387FC1FB586FEDC9F76F41BD03FDA41B
-:10148000F737F2FDFA3C78CF8372523B87EA2B5C48
-:101490002D313C0753B091CF4F05FB552FE637EC6C
-:1014A0007E8AE6DD29D05EDF0C9C8FC213E93CD139
-:1014B00048C94DE7381FBE80F456070E185FF0A5E7
-:1014C000F3F80949C062FDA3DB7FFD6DFC5C539E10
-:1014D0007781D607EA79272729C342FC7492F6E17F
-:1014E0000F01BE03569C37793CCBDE9C2FB416C34C
-:1014F000FC98631B44EFCF6A1C47711EB3999FE2AF
-:101500003CA68EE676E7BB57DA43E8EF7B57ED4C17
-:10151000C3E77BAFB4D2F3F64D5C0FB70F6821BFC2
-:10152000FBE1D52AC3F32F55AB65D2138737AA74D5
-:101530006E577E86C737E46FE276C8DED5BCDEC361
-:1015400075DC7E9BF0CC6D93701ECE5FCFCFF9EA39
-:101550007A5A5F87E6B90B4DF35BA49ED5F570A967
-:10156000C04741F55ADA4F8FD4BBA5FA7C18A16F5A
-:101570004B719F9DF6D3C32447A5F591F1658E6EFF
-:10158000BF0DF243F83BE2EFB2FD2AC3758DF4457F
-:10159000DB248A67C3F91EF24737493E8C7B28F863
-:1015A000D81A227B3C943BE33F709EF9C4CAF0C832
-:1015B000482BD203F4548EB5F38FBF84E747DFB3D3
-:1015C00061E410F04F2EE15F8F13CE5ACFE37EB26D
-:1015D000DE5B998CE78DD9C43EA407F26B641630AC
-:1015E000E88DA392EF963BF9FCE046FB47A76B968C
-:1015F000569D87F36C918DEB47CF7A95CE8BC70BB9
-:1016000018D60B3EB4770AB7AF48D60CFC50B87367
-:101610004532A80EB644C4CB548973E6851A6FA729
-:101620007097E45E6B6847AF47AF57DBCEDF1BB404
-:1016300093A7BDD55F88FDA3717EADA1DE88ACA761
-:1016400047FBBDD493F35FA757E2B9FF9C77650AC8
-:1016500076CFF962CA20E33E8F9EEA7EE6ECF72D54
-:10166000CC67C05FCE1F6398CF40EF865120FF400C
-:10167000BF1B1AB93DD730EAA0569A45B01BE5BD4D
-:101680004CF8A3CB26F2FDBB86CCF716A1FC4FC9C4
-:1016900092881F5830A0F54924FBCD83FB00F959EF
-:1016A000FCFD7C781FE5B2E1292EA7A02F3CA84FB6
-:1016B000CA56AF9844E56B250FD6DFB03697EC924B
-:1016C000821C99517EED41B2930A1A0F26A23C83E7
-:1016D000FCAE447BA06CACD58DEA58974B5DCEDF59
-:1016E00015E76199CD3D0CCF77E0765834F996F740
-:1016F0003361B772B92CCFE172FBEE261547783E05
-:10170000724E72ADCBB18C729CD52DC77B574FD02A
-:1017100050AE0F87248AA399807A00E57C831EE768
-:10172000C4EDD8F395F373D999A520BF385FEA7259
-:10173000AECB75A43C372B2DB7623FEEBBD24EE348
-:101740009870D5F60FEFE3FA8AF65F275CF5603202
-:10175000EAC73C85C779E9782D55785C608F7EAD06
-:101760005CA0F53D9FFE45F4E333ABD95F126F8B70
-:10177000E7F1EFB52AF1FDB9E4B3879C9DA77C9E04
-:10178000AF5C9D4B3EF5F6E59DE67AE2916947F543
-:10179000ACAF1DF018063CBEB5F1598A0F3EF1C240
-:1017A000C1A94887E21DC0E7C85F1B9D2C8C7A4EFB
-:1017B00009D1BC55D420D33903A684B36F711AE57F
-:1017C00098C775156F76123F15BD640D4D81F78B67
-:1017D000B67D319CE26A167652DC5AF005612F071D
-:1017E0005B86A31C14293CBE2C522FFCDAC6EDE705
-:1017F000B6EDB1D3707C521DBFDFA2A8FE76D56ACC
-:10180000D8A778C2A652BB508EF67983C0C778FE9F
-:1018100017FB67BC57418F2B6BDBC0F54451A31AF4
-:10182000C27B328AEAB6B463BC71D1C756F27F95E7
-:10183000D79DA4F31413366F22FF4A79A36CDA8F75
-:10184000EB11DF592787AD1897D8504AFB90001F3E
-:1018500024B85EC453FEC0F8C3E2CD3BB705018592
-:10186000C52F3FEF42FD72AC79BD0BF10EF59E35F1
-:10187000DEBA473C67FD23229EF386C3746F4B2F6D
-:10188000F19CC7F00F1094B76DE6784E56D787ECF1
-:101890004BE867B63FCAFE47977DBEE9EB35781E39
-:1018A000A1EDA5E36BB0DF257FFB720DC689B15DAD
-:1018B000769AF7CA5FF880E2B7F5F7BEB0097FC83D
-:1018C00086E729FEBDFD13AB176B6BDF79381DE38F
-:1018D00006DBB77C978CFECC793BAF267FEFBCADA7
-:1018E0001352589479434F917F43E7117F1F49B7B3
-:1018F000BD0D7B299EED04D01DF560579C6E7D29A2
-:101900008F7FF688F8DC8DD1CF3BF488C76DB8E5C2
-:10191000C62B51FF37707BF29C71B9EF033D2F3F0F
-:101920000F3A6E14F1D7F5379C352EF704FE01F40B
-:10193000B2D8CD74FCBA61F6AF9FC6BC863EBDC6B8
-:10194000E586CF037FFA798A776C3EA71DE5E8A587
-:10195000DF503C34D26F8A07E7A3AFD3F13CCA1102
-:10196000B5733ACE3F9D3BAD74DF4FD1CE8F489ECD
-:10197000DAB7BE477E6A26CE35B4B3AE1F8F3F9727
-:10198000C4786B9D3C9E57D001E37D3D2E7A2EE2BC
-:101990007A395FEBF1BEBDC5F95E6D1F28EE0FE031
-:1019A000F1C8A5B57F10F1B3DD749372905E07CFD7
-:1019B0001A47ADE3C12DF472771C7BF4B8EAAE3858
-:1019C000F608BA213D719EEA8A5307386D04F94939
-:1019D0003E8A762EA27D2D8F7F6F57A39F37D6E349
-:1019E000DA7D11F4D6C7DB9BBCE8727BAE71FC508C
-:1019F0003CD16642524F7CB57D1F5DBFCFB44B7F5B
-:101A0000D7FABEEBBC548914791EEB5EE4CBD286C8
-:101A100083E4CFEC5A7F8BF1B609FF7BDB0B32C539
-:101A2000392FA9DF4BFA3D527F94E1BD2D51FA7B4E
-:101A3000BF5DD8E78D7CFE687BC91972403D6D7B28
-:101A4000B6135F976D3C4871D66FD6BDACB518E242
-:101A50002770FE0819C6D3F6E2EEE1A4CFC5FD302B
-:101A600091ED548976CA9BA2B753BEF1A4A99DE219
-:101A700060BDE6769CBBBD638AEF76ACEF5833B7AA
-:101A8000138FD5CB9343D1F669ECAAD8EFAFE629F3
-:101A9000CCA3740F8E93DF7B23BB62C8EE9CE7CC94
-:101AA000F9382E11538DE2BAAA168838B09F7A53AE
-:101AB00091DE55CEEB18F67731E2D7E0FF51DD012C
-:101AC00086F6AA9AEACF42BF43A4DED1122D2C6437
-:101AD000A0F73CE7E4140FED8B84D3909E07320F00
-:101AE000AB58EF6711FEABCF14B62405FAF7595087
-:101AF000F22E807AD9F75F0CF03B7BD6AFC381879B
-:101B00006593BFA9CCDA7900D72BEC353BED47C8FC
-:101B1000BBEC747F48F91A3B8D77EFD66F9F23BBE0
-:101B2000FBD756C6F787605583F796B9791D87B7F7
-:101B30007EBBE62F6857E3CBD07EFE1A288FEB8959
-:101B40008DB1B4FEE978298EEE51CB7FEDA1A9A825
-:101B5000D7F263393FE66F4E0955417DAD491C6EA2
-:101B6000DD3480EEAB287EC949F1A57BB7BE528635
-:101B7000F354FBE6580C3360EDAF09FBFF37E27E10
-:101B8000AD1AD5638C332F648AC7782EA818615399
-:101B90005C13233F06C911FAB11AE3E83C11D8C51A
-:101BA000A67A4EA89D0F78898F83FDF839AA703FD9
-:101BB000D40791E5F4FCFD767E8EBDDC0AEF39BAE0
-:101BC000CB976B9D791CAEEEC7F5493395FF44E783
-:101BD0007391DFB35E5EFE23BDDEAE7AF8FB65E295
-:101BE0007E9B48FE3DD4A557FE7A71B4FB5BA2F400
-:101BF0009F9EDF2FB1A005ED962D76BAB70BEF674C
-:101C0000C0730EDB34BEFF55E20AD3FD393B843E80
-:101C10002E8909D37D3EFD443FB03CC2CCD6F22292
-:101C2000D2BDF4153BC3F8B3D2D79C3EA477E9B636
-:101C30006F5B7F9585F18BB1E4D72B7DED7F111F15
-:101C4000945AC3D3E9FEBC2D5686F7E7B56D793BB0
-:101C50001DE5B54D0DA7279C655FAFB4DE6ABE5785
-:101C6000408CE35865E842BC77413FAF5BD48B9E24
-:101C7000B93286DBD7F6189F3586E4DD7C4FD4B1C8
-:101C8000CAC641C6F3FB459EE87AB17F8CFA8F9DA8
-:101C90004377F438F7DA3F2609ED99E66474409605
-:101CA000813D8EFABCA8EEE430F41F7C16A3DF6FF2
-:101CB000E089C3F9E833AD7318EABFCFD23B871987
-:101CC000E7992395368FA2925F87D28EB527F3FAD4
-:101CD000318C37B54F8BA6F786C5C412FE8A1E8E8F
-:101CE0008D7A8E7A4C0CE7AB34681F536C17E54342
-:101CF0006FF7332D447AB831C6C3EB490B69F8BC92
-:101D0000B86EFB20231E0A956A2A07724AF82C64D3
-:101D10002BB52C83FED6DB2B9CEFF028743F81F291
-:101D20007FBAF855EEA6333991318E51E014665CD6
-:101D3000F233EBE74814D56F43FC69CCEF5664648B
-:101D4000956A92F718564FA903CC2E7E5F5A054329
-:101D50003D7944ECEFA31F0CD36E7C3D487A3F38AD
-:101D600080B18B32F0BE094F9CDB80BF6B70B33EFD
-:101D700009E3692B18D71753DC688F48C1003B0370
-:101D8000FC5455593788DF03C27C182F49262CF4A0
-:101D9000CFE57EF33BB483804FF93D8457B15015B6
-:101DA000A018C386C9EF3A9EF1FBF3967DCC8CEB6D
-:101DB0008F12410716DC4D7ACCC1BA7F9D00A35A21
-:101DC000457D5B15F7B71CDC9F73B85918EDC358F8
-:101DD000070BC742EA18AA1C33CABF2B0B60035F6C
-:101DE000BAC79AF323E502F45A44BBF5843FA8F737
-:101DF000AB887ABF8AA8F7ABB3D5ABE3A9DC3628AA
-:101E000003EFA5585C592FF0C6DBB309BC017E86F1
-:101E1000E03D7FCC12E315FBE684D718D11B2B964F
-:101E200007BA6E8EC9207EFA59DCAE4E8C97668951
-:101E3000350CD7C38B24FDBE4FE67718DE636E1BCF
-:101E4000C9E123A29DCD02CF8B74BF558FF276B22C
-:101E5000BF7A94B7F7563E267A79676FFD898DDE93
-:101E60009FF85EEAAF8E8D5AFF0FD54B65AF7DF4BC
-:101E70000EEEEF76E92737A0DE6C676E46FD541A4A
-:101E8000DFFAB7167AC2ED4C5B9A99DE31C8DFC033
-:101E90006F31179A9F47F24914FE72F48571DF295A
-:101EA000DABBF3617E5E4DE7835C31BE89B57C9F12
-:101EB000FCEE79DC8F07CB461FE6DF25F2EFAEE1C3
-:101EC000F6E3DD0FCBB40F1B79BFD5C1FFCDEFE13A
-:101ED000B8071F80BCDD335F0A8533A2DDDBC5DEBA
-:101EE0008F877A6788FE44DE8315609E49CBE4685D
-:101EF000F76071BED4CFE145DE7F318BF9C5FD6659
-:101F0000E6E759316EE2DB2225A4550FED9EC7822C
-:101F10002B80EFD1FE04BEC7FD2F599CC7662E8DC6
-:101F2000C7D7DF9A60D27FA78678E270BE66AF8B94
-:101F3000E76EFE7CEEB59E14E37945E574ACE91ED0
-:101F4000A02AD59B8AFA4D3D7D3DF3801C6AA707E8
-:101F5000318F211FEC56127E0CF3243D95AA84503C
-:101F60002F2A6E3FCB47BB379EF3B35E5E4BBCAEB2
-:101F7000CBCE7C17FE1D46E681FFCF5DE1A1F3DFEE
-:101F80005739FCA771FE955D39DE80A3273F04B762
-:101F9000F27157E1B8337A8EA74AF37AC9DEBE0EE2
-:101FA000E645F2CB796DD83FD9EAF9C883FDFBADA0
-:101FB000CAD00FD3133FDE2321C83F15EA4F712447
-:101FC00072DC94C1D8FE72BC6F14F4FF3271BFE8AA
-:101FD000A24A26521E57B708EF1FA53447A43E91C8
-:101FE0004EA6728F8A7B4A97547A29D5F16BF356A5
-:101FF000D33D98B60B79FB36B7A05FA245E02F40E2
-:10200000F6972DB582F61DEDEE8A30DE27C7D26039
-:10201000DEC161B9AB09BF9A9B91BF13CA136C456E
-:102020001852B5660AD1497157B07CC84F7504067D
-:10203000C7A27DE331DF87694D1D71D6FB31BBF847
-:102040006D13C7FB6312E7B748BC3FA6367B306E03
-:10205000E2B16BBBEEAB22BCC37288E3FD3FF97EFD
-:102060006E4FBC374F9B69C0BB337B32E1FD6702CB
-:10207000CF4B055EAB041DAA043EABC4BDAF55E219
-:10208000DEDC2A81DF2AC43BA48F887B7B17233DBB
-:10209000209511EFC0BFD6A14126437B7C0F0F5284
-:1020A00087E05BB785FCA4B2C3EF43BC5B1339DEAA
-:1020B0006D0EA003F135E0DD83F941C2A7EAE078B7
-:1020C00086F29C0E025610EF23F139A707E0FDB609
-:1020D000D824D487634C78D612C79F1FDE9FE2F3C3
-:1020E0005BA290F348FC256AFC5E605DBE7BB38F0B
-:1020F000AB445C7695B89711F18876CD2AC00FBBBA
-:1021000098E3933F1F22602FA54962FD5F0574C0CD
-:10211000FC27853D8478C674672C5FB7245A2A76DD
-:10212000AB88A7047EDF0F4B0CB2B46CC64380F1C2
-:10213000971A641E84F5FDE15A33FFC86E25E27ECE
-:1021400049CF93C86F2BDF562DB87F2FCFBFDE74DA
-:10215000AE5B9EE68BF710FE0312DA353F1372B8C2
-:1021600002F985FAC7D7C38B051F2C15F7063F2246
-:10217000F8E73121CF8FEB7CE3E5E748964FE6F1B6
-:102180008E89991671BF629819E309E3BDF54C83F6
-:102190007ED1DAC64329DD9FC93EB692DCC60E6504
-:1021A0003EE4AFF88F1F0CF1FB70FD7DD11E8AD786
-:1021B000EFBF1DEB89BF830EB4871571CFA4CCD7B9
-:1021C00093CD51EF8DADF2EEB1A15FA6B7FEECBE9F
-:1021D000691BF173DEE5441ED627E0BF6336C08E6F
-:1021E0001A5857C12FD61BC85E8C7AA5C649FCEB7E
-:1021F00080FEE71BF824B617FFCE54C7B51B505F0F
-:10220000BC80062430C12F6A06D911CF80730FFA23
-:10221000B156A9FEBE382FAC8A8FEE8FFB652CDF3E
-:102220008770655D6AF22BAC547DF49E7BAC59EFF0
-:10223000AC14F344C244B39CE8F3C24F457D573914
-:10224000023BB15FC9A727923C27DE1C7D9EA852A6
-:10225000B520DEF751358CCB773057E3F6730FFDA1
-:10226000C3689FE45460F03AF483E97CB690717DD2
-:102270001764DCAED4C7F504F2BD15E70337F13FB0
-:10228000CE0708CB176AFCDEE3BB2DE4875822E4B7
-:10229000ED512167CB857CFD1CE5CB8AF7587B2966
-:1022A000FD8590AB952887901E8FCDE0F6BCB83F9A
-:1022B0004C5FCF2CB48DA0FB22AB1C169A17944F09
-:1022C000AC2107AE0F768F76A3FF477666B9034E33
-:1022D000CCCFA2FBDCA5F82C37F2CD37CE59179C1A
-:1022E0002D1E16C84FF7162B2AF74BEAF7C8578949
-:1022F000FB0854F7CD0CFDD54F2656D829DE359670
-:10230000C787D7E46613DE811E9DB186755ACAB4AD
-:10231000EBBAEEFBC3EA9FECE55E83EF85DE606916
-:102320004176A1414FD488FB249927C88618F4C56B
-:10233000C28B2631F4EFF5D413BDE8CDF55C6F2EDA
-:1023400092A2EB4DDD8ED7F566A47ED1D3C5174C96
-:10235000369DBF541D5E467A6748743F42B2C3CA79
-:10236000F72F99D79B9BD1331FF095EC30E00BED05
-:1023700021DD6FF1E328E389D49347AED3E7D7009B
-:10238000DD3B344BF33C39FAACF3AB795EC83FFD2F
-:1023900008CD4F79A747535A50732DD9230C77692D
-:1023A0000CF72E1C5E7DBF0BE97BB846EC9FAF5649
-:1023B0004318BF74B8667119C1D5760FD266DC2F89
-:1023C0001E74E13D4DB3D6C8B49F7E2426984EF1CD
-:1023D0009FDF9F39231BE26316AC5D9A8EFC386B3E
-:1023E000DD523A377B24C137D86F80599687EC7914
-:1023F000FDFEC6BC67AD3EB4C77BE3DBBCD5D1FDFB
-:102400003D55F827AE53987708AE4376BBC6748621
-:10241000810F8EFCC24EEB822A2DD88E70D5BA5811
-:102420007C83552544BF0F28D571B50FE994EAF098
-:102430005D8B297324D07E4FEF72C4DB6F455F3B09
-:10244000EEBB3E2DEE45023ADD64F2BBF27DD7567F
-:10245000E14763B65EF26344BEA7977C178F936231
-:10246000EEE8F97FB7FF69688FF55D318EBFB4E69E
-:10247000F8924FE889791FA150C48BCF5A171B5A85
-:102480001845CE6689F3C7B3C47E99CE8F85D7EB46
-:10249000F639E7E3483E975EB884F8FACB7D2ACD5B
-:1024A0006B65C0AFA8EFA51746D37D500B9EBBE26E
-:1024B000718C0BFC6ABF4CF925A7EDC4C7ED3FF545
-:1024C000D23982CEDFA9F49D88AFF65D4DE701DAFF
-:1024D000C5FDD33A9ED29C7C3DBCC6C1F550DEE919
-:1024E0009F913C74F15768A686729E77FAE75C5E0E
-:1024F000F0FED93138ECEBDE1C77A1E06B80D72CF5
-:102500009F346921D49BDFC2E58A8D0D96911F7B94
-:102510006DACF7D128F2BFC6E131F9B5F25B96F3A5
-:10252000F7C0AE4C34C499CC12DF7BC83FCDEF6509
-:1025300065EE204B457912FAB05B0ECCF772B7DB33
-:10254000CDE3D4D317BBC6798569FDD63DCEABE8C4
-:10255000799EB053F25B4613DC3D9E5F8D8E369EB6
-:10256000EE718CA5F2EDF1D1DBFF50B4DF5A59C00A
-:102570007CA04F8BC4FDBF79A1FB34D41F79ABE3A2
-:102580001324C3B8F26B8A4DF14F7935B974DF5F0C
-:10259000FEEA5CED5E83BC76D185CD36D1E543475E
-:1025A00080E832D5E1DFE340B97CA1F0814F3D58AE
-:1025B0002FA7D3112D38BC82F4DB7DAE68E7A73E90
-:1025C0008CA4538DA013AC1FB20C74D2E913F97E06
-:1025D000EBFAD2073EC5FD8BA7F8ED45BDEBB10880
-:1025E000FA6544C75FA783F36B2BD80F81F3C2DF73
-:1025F00065A6F8BB5EF127E8ADE3477F0EF6DF5135
-:1026000094FB4E94CD51581FE78773E1ADBB7DC15C
-:102610000FE3A28F27C5A9F3C37C1604013EAA715C
-:10262000FBA3F7F13CC482B6F3184F979C2E36F10A
-:10263000438A7301975341FFA37B1E21BE6E0DC5D4
-:102640007AED19BD8F27C5D90B1F5C186443B3FF02
-:10265000EFF1C111CD37F8299C4760DEC279BDF09A
-:10266000F9C7861BFB97EA1897E6C479A9FAFCF626
-:10267000B783E3BDFB701D1E5C277BAB6048258ED6
-:10268000C0607CBFC8F5F437E8DF5B14FFC4F068B6
-:1026900076F4E2CA7D97A0DFB5AAB2995255D8C5A3
-:1026A0000CEDE20CFE5D8F68F7055E2BF4EBE2CAE1
-:1026B00066EEB7B50599DB70CF003B3292FCD88A45
-:1026C000C36CCF696AC08D7E734DDC83A02A81659F
-:1026D0001959E8674ACC0C1AF0778D93EFD72C4F35
-:1026E000DDE3C6FD102BD48FFE335B9A72CAE4770C
-:1026F0007B5D99E5043AE9D744C7B07A9F24911FDE
-:10270000F254841FF294A91F89CDA67D8A48BC2863
-:1027100036FE1D288509FFB3C087FE9DA4A56E3E29
-:10272000CE95C28FFD04FAAF2F023B36D645F6C1D7
-:10273000920B2C7C7D6853E8BE2B6B3C2FAFC5F110
-:1027400071D871FF43C6F559986027DE1026D3D59E
-:102750008B12C2F1CC2321DC878597E07AA3635CDE
-:10276000CB03F8FC797B20D70978FFA66FF301092A
-:10277000F733FC818B11CF357230D303E57F2D7792
-:102780006662B974C8FA3881A717E0398780619FFB
-:1027900094DFD7DC0DCB3DE10BE62B11FB86DF5F31
-:1027A0006CCCB7C7F82AB01F91DFCB4AFC42A2FD20
-:1027B00041FC4C079FFFFD343F2F77F27505F10771
-:1027C000F2D73E6E3F9D523C71B8EF87D879DDB4A9
-:1027D000EF63F3BC6E684F11EBD85AE057C5B04FAA
-:1027E00077A1E2B3203F5D540DCF8DFD8D62272789
-:1027F00038E8DAF2A876BDDE3F3CAF83F8944F4F5D
-:10280000227B24922F7674ED27F0EF69DDA1339EB1
-:10281000B288C3F14CFFD1FAEE93AEFDAA451C7607
-:1028200073A8FC5EBE3FFE696E1CC599EAFDB8A3A5
-:10283000696933DAC57734F59D89F8BCA3E0E23FD6
-:1028400063BA43EDDC138BFAE27E89CE97DDF9C1E2
-:10285000EB6A2CA45BDF5F47F71F3C2FE4713AEB78
-:102860005491FE01E6D6F87E5788DF47C5BC02AE1C
-:1028700057D15F71773874DB0D00DDF37AE80634E9
-:10288000F7A6EFEB7C03D543A0DE3D89F694F4F781
-:102890001ABD6F7298BFD7357EC546E3E91EAF8D6E
-:1028A000C6AF8F0F7A4AF8EFC28FB8F74DC7C7F897
-:1028B000997CDC77C4DE751D3BCB3AE00EDBB03F84
-:1028C000F3783EDE9F48FC7C8559A01F5F74FAF6C2
-:1028D000203F3EE3F4ED45BD5762EB4C570692BCFA
-:1028E000BC85CFCBE4C005C930FE130302172721F6
-:1028F0001E9AFB9C97BD7FC0CEF9FB809DF3F781AC
-:102900000C9DAF5B9CC8D7EC74228D53FF7EC792A1
-:10291000AD871FBB1DF8FBC4DBFC3EBB52D973E384
-:1029200043E4979699312E3E323D20FC0C2D5D7C80
-:10293000C8C73B43E1F232A32196CEC1CC982F9B6E
-:10294000EEDB9F319FC7C332A579F8ADA675C222D1
-:1029500011D7D2B31EF48344D63373FE04BA17657D
-:102960009BE61E477E91359CCF664EF4C9788E60FB
-:10297000CC3289F6F1471FF234B6003C3314EF45F0
-:10298000319DF9E07F0DC2FB51CA9AB97F34459E53
-:1029900093F9534857EDE1F33DC273104F0E9FC7B3
-:1029A00061D8CF69532B32DDC8CFF7387CA80772C6
-:1029B0006FF57D8274D5FD22FABCFB0AD801181789
-:1029C0009A7BB72707F924B7DEEEA3D4C69418D0B4
-:1029D0006BB90AB3619AA231C58E690CB3619ABD15
-:1029E00050D84F353791FDE0CAF16B78BF796ED37F
-:1029F000F35FE3FBF94A78B764E0ABDCA6B7BFA3AB
-:102A000073763E3FC5FD5E56A799D69FC3EACDF0CB
-:102A1000E58D6638336C8647EE33C36538366867B4
-:102A20008CF81EE19E9D5686DF2B2BDE6CA538F4BC
-:102A30005771AEA0785E3BE9C509C54DD91827711D
-:102A4000FC45A705FD953BFEFA32C559746E8A65B3
-:102A50001867B8FBD318168371BC9BEDEB30BF1819
-:102A60006887FED9E2CDF6B5184FB3ED529D4F43BE
-:102A7000140FB5ED6FFCBC4BE7066B08E32E8E6FB1
-:102A80007FFE45E4CBE31BFA931DF6AA14B4607DE8
-:102A9000C14738DDC708BD3E46E8F5E23AF37AFCA7
-:102AA0000A976EAFBA87E2FC372681E3BBB5B22F37
-:102AB00087C5772574FB6D8CB067DD40CFCF8776F7
-:102AC000D37988D0CF79A17B351FD16B410CEAB384
-:102AD0008EA3DA0CF44B5D5C63C6A3CEDF9784CC87
-:102AE000CF27BA24A1E70CCF33305EC5B32415E756
-:102AF000EF67A3DF537FBD8BDB192FBCA0E9F2206A
-:102B00008B7B2A99C770AEB25BEFB379FD319E081B
-:102B1000E935B0FB797144BB7AFDB12E2ECF5FDA77
-:102B2000F879824481876395FBC86EE8B2232B7DD8
-:102B3000BE890638AF6677722EE16F77F2BD86F9EF
-:102B4000AA64C3DEE4BB304EAE4E418F362BB9E3F0
-:102B5000B99F8F49C4E7723DF613F3118F6DF56F7E
-:102B6000B8B01CD8D9238C7167F93557FB261AE405
-:102B7000FE87F2B94EB71237C7CB2B39CD93F09CF5
-:102B800048710DFF8E6171FD6DB7DC80F85ECDCFB1
-:102B9000D3672BCC2F833C966CB9EDFA61F0BCFC6B
-:102BA00099515EEC0F54712B3E2FDE7892CE153D7D
-:102BB0006AE1FE8E48FA04059F3DFA134701EA399F
-:102BC000A8EF75CB087A7F9F05EC9B23E383EFDCAE
-:102BD00005458EB3FA0F6FA0F830339F02DF4B68C4
-:102BE000BF75AE97BCEBE8E9C2EC9BD154F72DA0C2
-:102BF0007879C88FBA7E290C99EB89A4EF6AC16FE6
-:102C0000F01B62E493C8727DA604E9DC74C97CD031
-:102C10009306FF43C9A16A8ACF8D6C07235898C1D8
-:102C20000EDA81E17528979B789C16FC245BB688A8
-:102C3000631FC461BAC715F91118A2F85236D183BF
-:102C400078BD994DC654D7376D39F5C3B1FCAB5239
-:102C5000CB73BFA2FA9C24E76DEE30DD6FDB4F9C97
-:102C6000476FF37058FFEE8F9E5FD464A7B8AEE352
-:102C70002734D2BF0B309E14CBBF68B758C0683D15
-:102C8000BEA5CF788C536EABE7F7A51FABEF335ED5
-:102C90003BCBBC1EA94FF4F9F620FE391AFD7ABED3
-:102CA0002617CE838B781C774A9F8ACC8A2874D2C9
-:102CB000DF4BD42A3271FDD3798FC3BB8EF014CC95
-:102CC00050C8EF9F4A7E9A5CE19F3AE8F6BFED025A
-:102CD000BA39A1AC0FFE25EC93D7A1DFF30BD9FBDA
-:102CE000807B50F73EFDACAC009DDFA30FF440FBB2
-:102CF0003315165680DF66E23C359C609A4F67AE0E
-:102D000096289E71D672F378F0BE6EE3FC5AC0AA84
-:102D1000A9DE22564F69C16A737E21CE472E3C2719
-:102D2000C7E3768A6ACDF9FAB9C0928D67ACD1F063
-:102D3000F635D3C7E7FB02C727DD6CA3FEDDB72A54
-:102D40008EEF7769CC87F36DE72A27E9FF6216A03B
-:102D50007EDC29E6FDF207737DB320ED983FD33783
-:102D6000AB0F9ECBE7F3232D19499EF9BD7EC5130A
-:102D7000597800BFCF87E1BC5BDC248587216C03D9
-:102D8000511DC19FE3BD26387EE379367DFC386E48
-:102D9000E373F63EA76F119E9B92F9B88DF9250259
-:102DA0001F251BAD267FD1988D52D079399EAF6AF1
-:102DB000A1F7CA1ACE584DF58A791DEC016607BAFB
-:102DC0008D29582BE3605675E9F1D025D1CECB1C67
-:102DD00010785C755B5E5F94DBC7D1BEED27109DFC
-:102DE000437A4AF8A358D806EDC58CEC82293F7B7C
-:102DF000218793E21EBDA6268DBE2F4AFB61336557
-:102E0000FF9B780EB3323ED0370EDA9969F1A52BCD
-:102E100024BFBEC1E46F9DCFF1F0E4888A4B2AA2A3
-:102E2000ACB7753A3F21D5539C40703B9FA79D5945
-:102E30009D6AC0201723E3B8BE8CDBD342E78F3AEC
-:102E4000B74A74FEF929E9209D0F7EEA5A0F43FF25
-:102E5000402AD009F5EF53125B84F7FC6535DC346A
-:102E6000E70DA473568C17E30F4A1BC6C9A50E1AAB
-:102E70003FB7E3622BD6E2BE54CA8C212390DF61B8
-:102E8000DC336E86E7A3E33CD45E5F07A77BEAC230
-:102E900060C6DCA1D8BE7FCE1B288FC362E8BC7C95
-:102EA0000AE0CA9940E932B4CF5259E66EB43353BE
-:102EB000A77846A04F7F958BB793649167DC84F623
-:102EC000E3080E273C2CF9D61113AEA07652ACFCC9
-:102ED000937AF81CED4D1BFA271C067A4FA8C8C43C
-:102EE000F65306F134510BA7613DFBBBE81EA075FC
-:102EF000C83C37237D3DEFBB7129B82EDCDF060BC4
-:102F000075D063FBD3F4FD97B083ECFB0B87F0F235
-:102F1000C24E9997C9CFE724A6EBF6152FD7A1FA91
-:102F2000E246A25E7D8FDBF95F397CE407BF42EBAE
-:102F3000E53C80A053F9E9581632CC0BE5D3BE210D
-:102F4000FBB3FCB4CBF41CEF0935C6959714ECA188
-:102F5000EF3B94B2663A9F505A6F8E83BF22267A17
-:102F6000BB3A9F979F9659306ABB9AF9F9E93E2C74
-:102F7000D8275AB964F3F3D392196EFC569453E8E8
-:102F800039CB6971E1FA710ACE47A8674296A07AF7
-:102F900079375DDADD2DA679A8DDC3E10EB1BFA8D2
-:102FA000E7EBF5B74FD3C4393D7ECF7B5B252820B7
-:102FB000C0CFD34D27C9DF5DD2B49BF0A3F3453713
-:102FC0009E6259D080A7E4AAE6B00564FCE9B8FD8A
-:102FD0004B875E0224D9A3CBF33B4B7D63211FBFFC
-:102FE0006B6190EFD8AC2E792775B3CA220BFDF038
-:102FF000EED289638D302FDFFD7EF3351381B7B2BA
-:1030000086F2F76BE3DE7B6B21C606759D3BE84CD1
-:10301000F73B0DB02D0276003CCC00BB23F213230E
-:10302000F25323E0345EBECD194E97BD8C6D8EFBFE
-:10303000E01A05F45C5BDFF074BC796479D547D79E
-:10304000E0F78E4BB3F8F77BCB9A24AF64D0A3653F
-:103050005E1E87E4F0B6683387221E9ADF447D50F7
-:10306000D228B971FDE0A8DF122618DFF318DEAB15
-:10307000E7EBD392FA83F45EAFF50FB1903C3F3AA1
-:10308000E4732A77AEFD2D36C5FC3DAFDEF6BB52AC
-:103090002D81B750DFEAF7C7B76DF9A8FB7BAA20EF
-:1030A0007FED7D7D7B499F469C5B2FC7FE38BAE54F
-:1030B00045C7E3A3434ED17DBA7F18D6F4019A07E2
-:1030C000B1F34E2EC0AB75FF547A7814DA5F7827CF
-:1030D0002FCE1F4F48A14B705E7A9A052EC176EF16
-:1030E00029BD68377E6AEC80DAF20C5E09F34DDCAC
-:1030F00049C2FF0167CB00FC64DDE9C7FFC2E1A460
-:1031000016BA09E6B6EAEFAFC1EFCD1E18D032C04D
-:1031100002F0F78F5F3A99E08B5A9E41F8C2EA04B9
-:103120000E0F6B1920C3FB03837D2623FDD6BBA3A3
-:10313000CBFD09A16FF4FEC50EF61D8943FBAA84E1
-:10314000CF3B782CDA067A757AD1B14DEB011FD3DB
-:10315000FF2396F4DDFAB65BAEF3131E827E8C6F0E
-:103160004C11F8A67991F4BB42F6445F9C0B13BA5C
-:10317000E9E94C6FF6D0BC7169C516B41F52A60FB1
-:10318000A579E35597EF27EE51DDE9E9249EFEC4CA
-:10319000EDE6FA5BB650BC46CA434EB2AB1E17DF33
-:1031A0006700B923FE7008BA58DC7C3CFF0D197328
-:1031B000D11B0080000000001F8B080000000000F1
-:1031C00000FFDD7D0D7894C5B5F0BCBBEFFEEF26AA
-:1031D000BB9B4DB209F979F343081071139318A9F9
-:1031E000D64D881831B50B22626B7149F84930C948
-:1031F00046AD162DBD5948548208D146040AB8E19F
-:1032000002622BFD82458C1AE88288F62BBDDF72A4
-:10321000EBAD3FBDD71B7E8A884256B45CEA6DEBAE
-:103220009D736626D977935CA87A7B9FE78B8FBEC8
-:10323000CE3BF3CE9C3973FEE69C33B31ABB86902B
-:1032400064428E25DC30C74E9FDF31E6159D4C224F
-:10325000A4BB33F49C494BC87B1221C44548F009F8
-:1032600053687B0E21DFEDD1047589B4DEE14D7327
-:1032700016D1B2447CBD45C3E5BD7FD5DEE5B3D2F2
-:1032800072312DD3E7AB12998BF533BD690E5AFE1F
-:1032900002FEAEA7E51E569FAE25AD589FC3BE7F6A
-:1032A000AA84DCE5A3CFD4763A6E297DAE9DB8B56D
-:1032B0009D8E6B918917CA0BE7166C5D4E616A7320
-:1032C000CC427889D79B2651F84E36E66A56D1769D
-:1032D000BFA7AFC835845C51E0CDB097D1F940FFAE
-:1032E000741CD2442795363CFE1C9837ADAFD77A74
-:1032F000B3643ACFDB1DFE39D0BE5EE39D42B4D04D
-:1033000089B7C07705B423889F39763BB627F2404A
-:1033100019BCFFFF084F95B8EE5F114F77EF34757A
-:103320009D2C24F8F705FDB7B9D7A12A07FAD2BA20
-:103330004E1A87CB77C3FFD07148AD2493143A2C33
-:10334000AB226E8DFF36E8BF79E9077AA28137514B
-:103350003DF42FF0BE4E0AEB52E9FC82FB24CF76FF
-:10336000C2DECFB2119295E8BF13E621E09EF7C30B
-:10337000E6347FD1F07C2C3F78A9E6765A9CB7E4FE
-:10338000CCAEEDF4FB790F59085186DBD31E719D4D
-:10339000DF7FCFB89A5C499FFADEB086E2EBFD1979
-:1033A000C4B39CB67B5F431A00FFEF73BC953F74B8
-:1033B000F7113285905FD9B5F89D49D083E4DBBD24
-:1033C00088E2B753224123D0C34C3DD2C36088D298
-:1033D000C395B0FE747DE8FBEE07278782747D06F7
-:1033E000C90091613E15C4BE5D89A9BFA300EB2948
-:1033F0009D044DB43EDA680E6D95805E28A0A55000
-:103400003F09EB5F95D8FA07EF30E238DD33191D3D
-:1034100076373A43C11C00B68B00DEC6A2A3947671
-:1034200082744864EF9499B6617C6CE372C1523A3D
-:10343000F0E2DBB43FB2DAE4194F1FB0843294BB40
-:1034400052713C4A0FAB91BE640647FD8FD342AB2D
-:10345000705C4F39ACCBA336EF7C781FFD914501F2
-:10346000F83799C84A63097D4AA4C3E8A4EBC0E1D0
-:10347000215D4F13A083BB60008A877F6F386F5335
-:10348000E8FB9FD825840308CD584E481D61F5758B
-:10349000CB2CC7A429F0D4860D09F4DDCA1BBC03CC
-:1034A00082BE72D9D348FBF373BA22EBA336C08332
-:1034B0001FBE4B80FE3FB7295628D3EFA7C0F2D3DB
-:1034C000EF0B87BFFF39F07D19C0C7E0276D166588
-:1034D000BB348C1FF1FCB980AFEB696FEC78629C58
-:1034E000F87E8FD9BDFF07F045F11E4E74015EB422
-:1034F000B8AEF1F0BAF4D1C74DB47E5E9BD6B182BE
-:10350000E2D3BFD486F315F0DE951ABD8EE48DECC0
-:10351000FF94A5A55C86F92F65744F961928E26281
-:10352000F1A21F2E53D25D48A28735D228EFE5F0D5
-:1035300001807F5177CCF7F8DFBF1A62DB09BE212B
-:103540008A14073FA72B459261DDFC125B37BD3E15
-:103550003A0FE4563CDC029FFFC6E58DA08B787CD9
-:10356000FF1BE0BB6C24BE5DFA814CE8D7BFD48062
-:10357000788AEF9F90107EF7B489044D94EED64B75
-:1035800012D2EBFA072D21909B83A6E80EC067604C
-:10359000FF8DB8DEE71ACD0AA14D36EA19BF05F74F
-:1035A000DB181F170C1480DC3B47E7ECA5EB73EE30
-:1035B00037DA9EA0248020A4E537DAAD40FFE75E2D
-:1035C000BE89F5B3DCA2105A0E0086E9B881E07F0F
-:1035D000B6118A57699611C73FB1570A19A0BE8F15
-:1035E000E239465E9EA3FF36940CCB8D41A800388D
-:1035F000FA2C08079D69238EF75D335945C76FD1B3
-:10360000485E0DAD6F593229D4CEE031C6CAD51609
-:103610000DE9904A86F9BF4573BCE0DE225627A724
-:103620007079AC60BB431285B3C9B83AA205FA05FC
-:103630003EA0F54BA03E67781D5A567FF417984779
-:10364000CB1E357D343DAF9EC79258BACA19A61716
-:103650004B29C317A926A1F1145E1B2F5B6A2221F7
-:103660002DE063E93472E22ADAF4E0C074A0235B4F
-:10367000692FA9A3CFC069E20D51B8A7F6F7BC36F0
-:103680008EB677D4443261BA81A5BFCD3B79D5F0EF
-:103690003A0B38AFE97F424BAC381E7E4741F1EE22
-:1036A000B662BB89B3AE887DAEC0EF92354C2F0FAA
-:1036B000C02BE01F99E9CD755C6F52FD8AF27A61EB
-:1036C000D704D4AFA0FF40CE3D95C0F431C83D90A3
-:1036D000336D8EAAAB1C749E6667D51447191BC741
-:1036E0006783E927A1FE88A7EB783D24DAA5E6B534
-:1036F00016B75AC76E47F90CF116DD90C8E4882C4E
-:103700006179D1AF753DAB103E19E9E6DECD3928C0
-:10371000971B48971EE8BC8984F440C78B8C24987B
-:1037200040E962116D96489F8BD71B8812B37E8D3E
-:103730002175B989CB85BB4904BFBF7B675C7D35EB
-:1037400009DB687DB391842DF0EC55D7B7507D8EA1
-:103750007CD6F78521F63DE966F3BD8BAFBBA33A76
-:10376000A4F5D3796F3051DDEA84065DB83E5397F6
-:10377000F5E07A269678731E06BDF22B9D672BA581
-:10378000DB3FF0F512F83966AFAA00BC9BB51A9C76
-:103790007FF46103E2E724D5E3B0FE6B1DE4AE598C
-:1037A000F479AE8D78F37580267BD62CDB483CAF60
-:1037B0007AC5D40074D3E0D0A8E82AD3A1C372F9A3
-:1037C0000A8EFFE596D0D61C44F714A0A7F25CA1A0
-:1037D00057C99499B47C4C47ED3B5A6E9963F543B5
-:1037E0007F03604FD0F2FD0E26CFEE77E8713D45A6
-:1037F00059CC57D00D1D07FB335FC59E028E654324
-:10380000ED9F6074C3F5F0BA46730FEAE121FAD573
-:1038100010A4DF229F1EF0FA0A972BF3C16EA1F8C5
-:103820007E851214C88F602FB35F293EE62DA5E573
-:10383000574E1779562940674CDEBCF21D3359416B
-:10384000877CF3CC4F1FFB275A7FFEB45E31D0FA42
-:1038500005406B74FD5E918817C60BBE680881BE7B
-:103860006CD2337BB469FF15CC9ED1FB372C8471AD
-:103870005ED079C0DE694A083DB703EBD33C94A221
-:10388000C9AB3A86CFE0CB16F6BD39F4B39FBBA0E7
-:103890003ED513A4EDA326FF4658D7748392887AA9
-:1038A000F9D75AC2C6091738285E8F8798DD7D9CE4
-:1038B0005649304EBF0DFBA17C9AB690F673A233E9
-:1038C00015E743E52FDA5927D618B682FC5D373461
-:1038D000AE84ED8FEB7CD3D368F9F88BC59EE5B44D
-:1038E0006AD0A70FEB293D07D632BBAF5EA36C01B0
-:1038F000FC90FD169C87588FC09AC5B5501F58B2D2
-:10390000EC16908F63F139C87B122337CF9168167C
-:10391000F0D3C686DCDE30E895FE891E54AFC44D78
-:10392000179FD28D9DB53DA963F88DEED3213D5FE4
-:103930006EFF40177239D343304E80CA6522F80FAC
-:10394000E5724C593B5A99AD63E095546EDFA9EB93
-:103950005312FC47605D5A9EFC8FF7972A305E1425
-:10396000E522E94A46BE3CA9F3CE03BA755487F571
-:1039700075317AFDA483D999F5066E0792B03E960B
-:103980000F457D79959AEEC5F304A77F5B84C9F74F
-:1039900091F51ACE1FB71A408F4D6520936CD02336
-:1039A00056E85FC1FEA79E0EEBEB69397B5958BF05
-:1039B000883F814F28BEC3463AEF931B6C8CBF29CA
-:1039C0001AA09F451504F5E5222DB5634BE0BDD245
-:1039D0003740D7E5D48B0EA42FF2678A158AEFF90A
-:1039E00084B73350BB97CAB1973AA430EC0BE6AF1B
-:1039F000376C35E5005F7BB53658CFCD12CAB1F9CB
-:103A00001D95051B6879C99E2B70FD132A185D2E24
-:103A10000939502F4EE5F2B1DE10D2A31DFE3389D5
-:103A2000C03E88F68FF67413FD28AD64241E40AEA8
-:103A3000ABE8211453A6F6D1D45E26570995E724A6
-:103A4000C66E12F21EE43889B303D5F41114FA8855
-:103A5000C93DA2A482DC1372F998DD97E8443B3E8D
-:103A60003F15D697AE27939BBB25C46B3369457D25
-:103A700022F4C0D0B85C8F9CD20699BE323C81CF74
-:103A80007C670EAEEB12D28BFA44E895B1E820DFEA
-:103A9000A9E1FB88D1E960BC53C1FE9A4E93F07551
-:103AA00074BCA66524DC3C853D6D53503F323D69B6
-:103AB000647A129EE6CBD097F1FA315E1FC6EBC155
-:103AC000543DD377629D853D933A8DD901539785B7
-:103AD000B4A408FC35DEEA94E461BB26F08ED1A8DC
-:103AE0005C09651FC905F99E50F9622AAD0FC8C46B
-:103AF0000B7C65A178E9A1EF3773FBB72795CDD78C
-:103B0000AD67F4AB937DA4D80AEB12C17D6F3499F5
-:103B1000D8811E053E37DBE87725F01DE3B7A1EF1E
-:103B20008DA4C31CF37DD52B26D43F175EB6850C20
-:103B3000688FF8B31DB4BF94DF1BD04E3DF78A0DDC
-:103B4000F5E939AE0F5DC2EF401E617E16BEAE4193
-:103B500052358E00ED4B33C6810814F659B383D924
-:103B60005923ED215E9F1399C3E8CA80FBCD0B8ECC
-:103B70008107A04CE121A07F6E71327E0FEC995637
-:103B8000FC43FA3EE0B37A18F6FDC540AF06EDF708
-:103B9000E718297D4DD72E8B3E48E7D19C69B58328
-:103BA0007EABCEFED7DFDD41CB1FEED11103ACF3F0
-:103BB000F6697349EED8F2B731A43B3E10C32F77B4
-:103BC000EF54979B7BD5E5409FBA7CBFD3E63A651F
-:103BD00041D9E1F982D2B5C1D07ABA87C26B78D522
-:103BE00080FA6886D3FF9013E4AD267A18F06CC88B
-:103BF000FE780AF83B02FD9F48F03450368A1431B3
-:103C0000FC035F5F30CDCFB68F82B761FC11A30696
-:103C1000F14CAD75F6443917E07CE2D27B3F3C4075
-:103C2000E7BF6896D9BE02DF786BCBCAC19E441845
-:103C30004960FD4D1FC2BE8BB66B84F53F3593B610
-:103C4000A37035AC67FAB0894412806F5BA8DD6958
-:103C5000A44BFC1BCE6F777744CBC3F47FBB9D3561
-:103C600013014EF92FB20FE8E351E837C64EDEEAF2
-:103C70006472FC4BFB993246F899B602FE9A8D03AA
-:103C8000FA4A3AFEF57FF90CE5FDE2A5AFE13E8286
-:103C9000CE633EB3AB4D0AC8A7C50F1EC0F762DFA7
-:103CA000762AD38AFBB6D7361858D9A1C7F2A9CD40
-:103CB0006C5FB9B8570AC13CA55917932A412F6CBC
-:103CC000D6D90D64245EE3F1F8C1A6B713C0EFF5B1
-:103CD00001221DF67B12B3C7ECAD09B87F505A1311
-:103CE000C0BE0CACBFF143908F8B376B3D602F9003
-:103CF0007D36F4CF2CDE7CC3C48556E8E7D3A44AD6
-:103D0000F0136DB9013C54D0CE17627E9EC8F5F415
-:103D1000BDBCE56A05F8F1D06606FF62877107D081
-:103D2000D1F57FD1227FC91AE2073BB95BEF9D082D
-:103D30007CAD6CDA3E1DD6E78399E91A6CBF4B2245
-:103D400076C08B63690ABC5F2CC93EE0E386F58DC3
-:103D5000B5B1764F9D93F9C72AB397A50C5891AF8B
-:103D6000E6803E6DDE4CF908C69FF5DEEFEE700D85
-:103D7000F395346BFD2D53A1FF67751EE0BB217BCE
-:103D800066D3B790BEE02F4CF1B598E3EBABF29958
-:103D9000C122F8A4B500E4EAE215AD05F651EC8CB9
-:103DA000213ED944F9723221A79D12F902FC9319E0
-:103DB0004ED5BE63AC7D9AB550837AC6E821DEED60
-:103DC000F4994AB7C9B01FB725C9586F4BD2237DA4
-:103DD000CB7FBA77E76FE8BC9E74FA2F80BECC2603
-:103DE000DE62D06B4AD45E45CD5A4035DA61641349
-:103DF000B3AF89CCFC85EB92C98E5531FB7353125E
-:103E0000DB4F5039F105F473EEDD3F1F06FCB6645D
-:103E10007D3C05EC85C0C5CFF4E05FB3F64B28DFF1
-:103E2000AD1E1F01BA09F4CF240B8A86E572C0C308
-:103E3000F446FCBCE624E9981C7545B19F4A97827C
-:103E4000E56E07417ADAB8D48CF6FE4657C80440CE
-:103E5000FFAD7C2BECA746EE0F346EFB85570B7441
-:103E60001E92ECE3A1AC30FE186C9817D2D2713ED2
-:103E7000DC9617C4F29E4A8F96D659B7FDE3CA5C0A
-:103E8000C0539FCE03EDAD9E810498DF87DB4E24A7
-:103E9000C0FC1AB66971DE0DA14F5216160DCB0982
-:103EA0009DC65F900476825DB2C2F8425E7CB8ED3A
-:103EB000D3940556E63F407D5A3A3A5ECCCECAC905
-:103EC000F0FDF5DF64EB726697210472F08C89F9DE
-:103ED000F745BB3336A6FFAE4B12FECDDE2CD03FEE
-:103EE000436579A206E4C4F7ED6CFE2E7D6F16F0F3
-:103EF000E54792BA9F252BB52444E552E34A8984CD
-:103F0000A8CC3FF3DC4B5920FF3FDCFE52565D0C42
-:103F10007CF1DF89E78D496A7F9AF0AFBAF4E10C52
-:103F200018AFCE63607ECC31FCABA23D59CFFCA470
-:103F300083946B810EC577830D662FD8BB83C4181D
-:103F400002975B5D3FF7D77ABDF92ED8D788EFE3AC
-:103F5000FA5F0DF444E192FA24F427588AA2289FCC
-:103F6000BFB4FC77D1F58C91FF749D8DB04ECDC65A
-:103F7000E8E17104E9430F78D3B75865D05729EDCC
-:103F80008CBEA2F76B709FE532274C81B8803EDD76
-:103F90006D05F9767D81B9439308EFB342D03E3386
-:103FA000BD10BF0B5631FA0FA610F4C3A5915609E8
-:103FB000FDB476E6E7CFA820F655B4F8B32466E75B
-:103FC000B88967BD360FD75FC23807C78BD00F409F
-:103FD00047202FCF4846A423A95F427B54ABE99DDD
-:103FE00007FD8E45572BC5BA72BA1A2AFF9DE8EA1B
-:103FF0004941C723E8CAAF205DB98DA3D315F72384
-:104000005F767B12F4C1BE3695E36B2D973FD1FBF3
-:104010008DC2AF2EC17C6B797FB5466B580B7AC4CD
-:10402000A3FB38D63FBC89DAC5B07F4A03BB9E3EAE
-:10403000C7B5CF5770DD486400FC0896AB8DA82F3C
-:104040001FD34472C08E499DD4BA1BE823755E51BC
-:10405000493BEE0B331CA01740D7A27F74E9341FF5
-:10406000B323581C283A538FFB9C96072B7DCC8E8C
-:10407000A8417E09AC3629A007A7F5E72C07FA0866
-:104080002C231E03D271CF8645E0CF9D6DF580AC09
-:1040900013F125B252CD779D128B53056F22180F65
-:1040A0001B8E330D6CF921E8FFC622F49B0CF98FAF
-:1040B000F309EA8DCB8D43D6AD3621DE45FC68D0C1
-:1040C00046117425FA91B13F9268647A68A47C40E5
-:1040D000FF734A05117FEBA19C2ECA3CDE23F85FDB
-:1040E000C4A36C45BE1CB0C82B9C39BF32439C0492
-:1040F000FC776CB31684FD00FA8D5919DDCA4F693F
-:104100002820E950FB9FABAA3362CABCFDD0F7C19F
-:104110005537575F8BFA77A81EC0A67A5994BD26EB
-:1041200005E255C3F532B5838D7D12FFBEE2E61B75
-:10413000A8AA1E94C4F87FEEF4821FD14454E3C5AC
-:10414000C227C7F5AFA3FD5B15DE3E38EE26E8EFCC
-:10415000A912517EA0D34BE15BAB53F78728E5DF73
-:1041600043418CF77F530EAF5A9D316C1F507BE15A
-:10417000CF4965C376C2A3EFD5765D49C7B2D83FB4
-:10418000D583FE15FA3EE092D00E89E7D70497F466
-:10419000D5EC6B65847D9DE062F6F5746049BA2FBD
-:1041A00041F91D58E62360DF52BBC4E942BBE4E39A
-:1041B000530768FDB9599F1F1EA740BB7BE6C1BED0
-:1041C0002A705146F91BD8A90D49946F8CFDCCAECD
-:1041D000A6FA1CE305827E96D839FD388204FC9746
-:1041E000DDFBA432A077425AB36EA36BF903973775
-:1041F00013C7E1FBCDF87997BB985F205058B5A164
-:1042000000FADF2611B01756151E4F5980FBA9631F
-:10421000290B63BE6BEC7B0AF1D9B853372A1ECB4E
-:10422000A9E104786C79F9452FC88D3321096542DD
-:10423000831CEA04BBB6A141031621290DCDBF039F
-:10424000E31F73F5643C9D5F06D777819DB706A792
-:10425000C2BCE9BF127DB5D1B708E5C4C6B9462BCB
-:10426000C6910AEBEE413CD8CD5EC0C3AAC2AA34C7
-:1042700018A765E6743BC64DA83D07F52D0F7E07D0
-:10428000FD4502AE557DBA1AB077CAA95DF70B0A93
-:1042900077A673468D87F2F538EDEEE2FBAC10574A
-:1042A0001F5D8EFFBF6446171D922FF8ED52F48FED
-:1042B00092587F67761FB31F6F71E955FEF15B5C03
-:1042C000CCAEBD36189906E4B25F1EB0805D1D20ED
-:1042D000DE4F605F4D7C56653BAE13935FAE360597
-:1042E000FD6646D7C0635742FDB532EE67883CF0A5
-:1042F0006318F75CA7CBB38A703E80F283452190A8
-:10430000C7FB5CFEEFC2FA96737BF5DCCB371683F6
-:104310007F51D85F9DCF99506F76DA94276B404ECE
-:10432000FE49667903C668641AED67C9E74E1CB793
-:10433000D314EA84F50FF668B1BEC9EA5F04F4DB72
-:1043400078EBFA299887600D15801ED5B9BA08D088
-:1043500031DDBEA01FC5E8F21188234F0BCE972593
-:10436000D0177176CD34F063E1BEC5857EDC2ACEF0
-:104370001FE329159C32222B747C91346CE7BCF925
-:10438000E7D932BC14F68FC6C8FCEED573CD04EC69
-:104390005CF248F4B006FCF8AE08017BB8B957C22D
-:1043A000719A0B5FD0C3FEE5EE5EC6DF01BEDFA0F3
-:1043B000F8CBC27894CBC2ED810E46672472781C8C
-:1043C000E0F979B69E84D076317E5742963379C033
-:1043D000FBD3F3F84333F737514D88F5AB5CC2CECE
-:1043E00058A18E5BF071D74911AF16F05A2CA9FC79
-:1043F000E4E2D9C3BF4F3C189D0EFC1BA5F4057E1B
-:10440000A70DD2CC7B5EA7F3DB5036C903A6989BE1
-:104410009293B604DE5352A4782FEDFB643AD00D8C
-:10442000A921C8AF2D7D95DA662B8BEB605E8CA53C
-:10443000B507EA53EF2A44FD0C719359F4FDB31C00
-:10444000AF6956E6C773AF08E6401C34F1A0EF9E93
-:10445000D761FC2BCCE8874DA56B6373E27325F81D
-:10446000BDDCA4F800E86777AD5202F088781FC47D
-:104470000B67160DE7E3383D92772B7DEE76399882
-:10448000DFCE406A005E781FB20EC71FC19F07E3F0
-:10449000427C0F9EE7D2C232FAFFC9C096EDB8EF58
-:1044A00037603E486DDF1BEF80FEAD35925E8CC7F6
-:1044B000C6D92DD589B7BE02F43F78F6D4968701C8
-:1044C000AEDBF67A30EF25CE1EB9FE9BCC3E3FB375
-:1044D000DDA2003F6CE5729BDA8FC827C15D6C3F9F
-:1044E000196F471E75A9F72743E5AFDD8E64F00508
-:1044F000B7B33C0B21DF037CFF37D8703E01F4D704
-:10450000BF0DC113970FB28DE783F48F9E0FF2E6B4
-:104510000E4B10E8E17CAF09FD92328F7B9DB545D3
-:104520001F002475380ECF01791B5872E6E71ACAAE
-:104530007F720F8B23C9128F33FD4A4B585CCC6BB3
-:1045400007FF8B805B764C777B8B403EB27937716F
-:10455000BF5193B34061F12E9637D494102E007B57
-:10456000EA55AE879ACC2C5E35E8D087615DA326EC
-:10457000FF1F5D18D762DF935F1A94D8B8564F8833
-:10458000D975270A35613D9D670FD807B06EAB59C5
-:104590007C6B289F60BFA1C7C0E290581EECCC4145
-:1045A00039592FE256FB993FAE9EC7A74ECC5AF41D
-:1045B0000CA45C7448AD35B03FBBB0AA12FDE80F47
-:1045C0003C39139FF52BD57EFF45E0A7CF1B8E23EB
-:1045D0000BFF7B1DF1E899BD3CEC47D450FB4559DE
-:1045E000295781BECC21F61520FF95205DADABE9A2
-:1045F000B3833EC168973412D83972A7CB0CEBFB5A
-:10460000688706F554B043E3857602CF39C9CC8F6D
-:10461000744D32F36BD0A50AC138E2D9A1E371071A
-:10462000DEDF72A209C35323B1E7A376B966347DF6
-:104630002DFAEBD0B51AC14F17CDD4A0DFFB82DE27
-:104640003B17FDC6CE020279541DB6D69535AC1E79
-:1046500079E78229EAC3FAEB64664812C509F233A6
-:104660003599E7CBC5E16D6197BA1C1F8F690CA91D
-:10467000CBF5C43F212D8FC50F62DFA72633F97517
-:1046800061550EC7B707F3E3C4FC976730BC6932C6
-:10469000D93337B36A2ED0412EC49773E0C9FCAB2F
-:1046A0007426087FEE752E09E9230EDE0E30DA80BF
-:1046B000BE3A593CF46F853F1EEECAE414AE1FBCEF
-:1046C0006E885FD6DBF5188FBE5C3F495DB25A0E2F
-:1046D0000D95BFFEFD2CDB27756A799E8D1DE5507B
-:1046E0009D9DCDE584E4D91186F7566A2FC03C3AEA
-:1046F000B525603F4CBBD58AF368D96F423F70F354
-:10470000B2812CD0E32D55030510B789C72F402B5C
-:104710000BF945DBD5B9E8FE03EC84D8763C5F4B5A
-:104720001D67F5FE20B90CF6392776BF01FA6AB786
-:1047300009F515FDBF0306F0B3BC9C83F6CC8736A4
-:104740007F1BB40B98C35B9ECD01BB85D94DCDFDBE
-:10475000861EB00BEB3A62E27CF09FD5EAB81F5997
-:10476000E944FF3BE956BF6FD814F7DD883860177E
-:10477000AEF33ABD7F22F03BD53B987F70B65183B4
-:104780007903F55ACF2290B7674D6A7BFCAC8DADAB
-:10479000D796A175F6A0BDB565CC75F614C03AD70D
-:1047A0006B883FB69F665867BABE4D7C9DCFBE787A
-:1047B0007501ACF3C7BBAF2E80755EA7EBF202DFCD
-:1047C000B439FC5B9369BF276FF0A13D25F2582FE8
-:1047D000971EF724ABFD2B43E5FF21FFCA58FA30A3
-:1047E0003C04875A1FBAF44A06C8833AA3E1BFD5EE
-:1047F0008BF037AA1FCF68407FC7FE3F7FBA66079E
-:10480000C8817E2DDA23A2BFFDB23F0FECA1FDEFE0
-:10481000B83D4169ECFE1BB95FD86D2441F0AB880F
-:104820007D80B027E3E5F15B7C3E1F257B6F00BBFD
-:10483000E6CBFA8D1BF83B63E85366E76E933CCCFE
-:104840006FDC8B7EE4967DF3EDE0273E1D627EE318
-:1048500096178BD16FDC187A2D0C7965A45FB2C3E3
-:10486000FEA371DBB104C80710FB5CBAAF3D938CAB
-:10487000F4A8DEEF9E0E9D4880FC010A7725E871C2
-:104880008B2BAA07BA6FA1FB3DC8236C91A387A10C
-:10489000DF1617C13C97D23EF5FE4FC47937FAF4C4
-:1048A000287737F64B2190D7297A7F4E06E8359244
-:1048B00061C77820E7B38BC9DED494B2D8F8BAF7D1
-:1048C000F3E4E4E17CB0810D8948BF033AE2B583AB
-:1048D0003CDB60E3F24C46F9F6C74D8E10CB0F631C
-:1048E000EDFF18627642A3C80B934958A6EBB56852
-:1048F000B6F75D586F90F7E138791F5B1671FBBB17
-:104900004918F552331918CA0F8B6D171FD78778BE
-:10491000B8AA1FD25AAC801FEC4EAB07E081F8B8A2
-:10492000BA3EC8F6EB941F96960CD3AF580741BF1A
-:104930002DDC0F1D6838FE08D06FA04FB2837DD7E5
-:10494000E461F4DB44F75B90471BCFEFA4579D373E
-:104950003A16FF97A6A8F5D150F9EFE45FBD3E45A2
-:10496000CDF762FEC26F3F34CF7E89F165DCBCE2D9
-:10497000F7A9F1FE76B1CFBC5C793827452D0F87BA
-:10498000CA7F67795837B42EF1F2501DCFF89BE5F6
-:10499000E1FF705CE3997D4F27C0BE03EC78D8A798
-:1049A000ACDCAE63F91314FDB1F1E2E95AAB97C583
-:1049B0004FB5A25E1D8757A6F3383CE3EBD75ED414
-:1049C000E2BA35F33871F33E9B079A365817639C69
-:1049D000363E7EBA84EC9E0E4B151F476D027ECE8E
-:1049E000BB743C75750A8B8F525872206F213E6FD5
-:1049F000EB35EBA749FE9875AF2AA21B8251E8DB85
-:104A000028078933E6FDC6146657BFC6F38BDC7AE8
-:104A1000768E60ADCDE285FD8C5BC3F29F7EE0F2C9
-:104A20006D82BC18A3C2F1FAF2ED4443F1F28CAEF0
-:104A300017E54AB0D9EA013928FC37A2FF8B3C5E62
-:104A400071D9FA3F8EDEF7FC0FD37B3C7EF68BF1FB
-:104A5000FED6B8DD7A8A1B155F10A4E323105FCA67
-:104A60001949BF63F533161D1F4DF11D496176FECF
-:104A700014CC57B84C3963298D9E003F11D963502F
-:104A8000C0AF097E12D48FABD3783EAAA77C26E6AE
-:104A900069B37325E21CCE5876E40743EBC3ECC838
-:104AA0000FC65C9F2F6747DEEEF07D087476B2D2AA
-:104AB0008BE7011EB551F8617FF89C61D4732EE23B
-:104AC0003CC6A5FC2D5FC4D1D517FF4B72D4923ADA
-:104AD000965DF975CBD1CF13C07F3A763F419EFFEB
-:104AE0001941BC45F749646B8C5F3B1061F97B1938
-:104AF0001C5EF1FE3FF8BEA121D59B994ADF7FFCE9
-:104B0000AED14812A99E2E6572B1C567C5B8424B99
-:104B10002FCB7F695946508EB780DFB408FC8933AC
-:104B200009D87D4F3AFD13208FEED1F7AC416D22AD
-:104B3000F8DB6711B0F3CEBDCBCA339CFEC99867D2
-:104B4000B76C00E318DDB3CE601E56F9179F3E52D6
-:104B5000538AF0A23FC165509F67B93D95C933F1B3
-:104B60009C3D846F2FFAF33F6E60F9DA0197D70E00
-:104B70007E09E10FB728118C2BB4EC61C65BB996A6
-:104B8000CD87FC3003E9A9654F6531F84D49AFA9E0
-:104B900018ECDDF2DF5B71DFF7F183E99827B1CF25
-:104BA000E5AF027CD84A4337817D9A4DC701BBF7F8
-:104BB000E3DD371503DC42FEAD03BF391D7F9D4D9C
-:104BC000ED1727469677BF644726EE339BACFE5A17
-:104BD00098FF3A138323B89D9F4FE1FEF278FE17AA
-:104BE0007C9FAAD5E038A9DF35629C5CC885753A00
-:104BF000E237E60DCB93129E671870F13CC7FE9921
-:104C00002C4F8597AD2E75BEE747C93794003C25DC
-:104C1000A9F2578B675947E40B94A4B27896EA5CE3
-:104C2000A2E522B3A773ED7AA427DB4AC2E254942B
-:104C30009EC0AEBF361A9906E7BCF2BBC3D7029E30
-:104C4000F75FD4209EE49947303E9328B1F1F256A5
-:104C50000F744E007F8CFDADEB6049952E7B15A047
-:104C6000F449A7EF8154E4FFD64218AFEA5F742CF1
-:104C7000BF729F05FD0CDD594D985F79EE3D83EACB
-:104C80007C4EFC334856603E656EDF6F314E60DB14
-:104C9000238D9A27FB44AA15F9A62518998E393633
-:104CA000D7BA50CECAFB7E1F04BB43EE944102919B
-:104CB0000E9D5703E7D382CB09FAF5C777DB35B0F2
-:104CC0005ED93C3F6670FF7F4EF1E3BE45C40542AE
-:104CD0002CBF4937F008ECC7E4E503DF0CC27AECDF
-:104CE00071685AC07FAA8BB6A0DF659F05FDACD95D
-:104CF0007D792BBE41CBD92BED18071B7CE5EE6CE3
-:104D0000CCE7A7F31C3FCA3C1F4A65F948F23E8B2B
-:104D100006F499FC04F1C0A8B223A50AE17E8A96A4
-:104D2000693FDF077A4A1E8E9B823F0AF45443AAEA
-:104D30007F07D0CDD0B9A4A566762E899FA7B52DC3
-:104D40007D6F179CF7D9C2FDB907F74F9E85FEBF4F
-:104D50004E598275B8E060F9952FA4B278E248FC0C
-:104D60001FC43CD6DC7DBF657A8DE202FA97758C54
-:104D70005EE44E570FF8195F49F063DEEE751D6172
-:104D80002DC6CDEC277F5CA3C4EC77D6333DD3B2E0
-:104D900093EDCFE3F73797D22FBF1E92334CBF0C62
-:104DA00095FF4E76CBEFE2F4CADFBC6F21EAFD5EE1
-:104DB000BCFD12BFBF1B618FC7F537961D23F25094
-:104DC000AA86C761F6B44DD84941559E4E95959F28
-:104DD0003B34AAFB5F9F64477A10793B29EDCA7286
-:104DE000C8DB8FFE88A0DF4EE415893CA26015CB9E
-:104DF000F7096A8C782ED14DBA307F681C094B12A6
-:104E0000FAD706F0FC6D2AE411D1EF4FA4E662FF59
-:104E10009B8967A516E5A62201FC26C83F4902B872
-:104E2000431B16C178B759713C13E49F24E13E033C
-:104E3000F939DDC7F256A735B0B8433AD5CF504E51
-:104E4000CF6774699AABC73C56915722F24F045E04
-:104E5000AA38BED3272CCA01B928F254D6993DE509
-:104E60006017C1396838BF1C6C34F3BC13D66F7738
-:104E7000632E9E4FFEB27929F17816F929FA447F04
-:104E8000A6BB6CE43967413731EB89706DDCC7EC48
-:104E9000FCAA063DCE63B07106FA2B071B3504EC65
-:104EA00081AA7E03A3C3B8F136CED59330F42B8705
-:104EB0004C204F053D5CCACEA5EB5B08FEE0836D40
-:104EC0003BF34E52DE3FD4D68BCF4193D4ABBD12D1
-:104ED000CFA1CE03C9F58DB4FC5AF91AC8B78966BB
-:104EE0004994846AD3AFFA964CF5C46072F47D2875
-:104EF000DFBEE17BAC3C3EBA45A2ED9BD33E62ED0A
-:104F00008136D3A9D85EFFEFB541EB57D07F7F261E
-:104F1000F1F91C35EE64F4EB3C12413F12D77FA54A
-:104F20004C3EBAAD7AB49FDC3C1F9554F3FC5488D8
-:104F3000F8D0727B5A31C6EFAD44D91381FA0C0315
-:104F4000B32708E387F6F1CC6F6DE4F4403284BFF9
-:104F50006A2008F2AE3DC781DF0FC9E73D8610F336
-:104F60009BB1F18FBE78059E4B1279B684D833671A
-:104F70005F81F936AAF25A133FA729DB33E1BC7BE4
-:104F8000BB8EDBC1BC7CC4E65F88F304BEA4F6DD47
-:104F9000D11B7E5004FC7476EF0FF341CEDDA8A741
-:104FA000FB8451E45A593A936B833AEB4A897EB7B2
-:104FB000C6E66F013A7CC7326F3A1C319A9B54A9FE
-:104FC0007700BCC1E7B480D7644E278ED90C3E472A
-:104FD000B54F823CD476131B37D92F7BF15C847F8D
-:104FE000B6741B85BB5D62F29B7E94887655A19258
-:104FF0000871C8267EEE55CBE58896CB917F6E1B57
-:10500000C897A9C1784DEF135AB0E77FCBE3E2BF51
-:10501000CD519F9FE87133B8C5739656B902E8CF5A
-:10502000A5AB3A524BE940ABF78470FD326D1837AF
-:105030003E602B770FD0EFA5EC1F95423E777BE6C5
-:105040008F4A21BEA7757ADCBE98728F9BD17F35BF
-:10505000B403BC595A4BC1EFFBB5F59748FB2BFA8B
-:10506000F2FD0DF56360703519A359706EFE59930A
-:105070007F3BACFF85F9C7302EFC40FAD1F721AF5A
-:10508000E3A88ED15D3093E7E393EE690994EE0EC9
-:10509000E739785E0A8BBF1E9EC0FCA8547EB1FC27
-:1050A000D18912E621D6CE66E7626F26918E01FA8B
-:1050B0003D3A5968FDF48A1CB47F6B799EC8F47739
-:1050C0007C09B07ED36F8FCA20F7C7B2E76E74EB4E
-:1050D0009481183EBE4951976F2E5497BFE5519762
-:1050E000BF5DF19709B16593D97B10E8F55589DF6C
-:1050F00047710DB1237FBAA420D85D935F4AE7E7DB
-:1051000089593EE54FF97EF1A50A82F5293B8D5B71
-:105110008D50CFFDEF5A5E3FD94D8CD94EC407EA72
-:10512000E9A8C4F3325D1893227BEFB1333F346DAD
-:10513000ABA7FDEC9DAF201FA75835E49BC0EBA5A6
-:1051400046B4C3045FB49B287D533C968F339A8149
-:10515000DEDB759EF5D097D66C50402F572618B1E0
-:105160006FED3FC8A8D7969B0CC44ECB071F376383
-:10517000B95C263EC823A120CE86E7519D27D40ADC
-:10518000F3A5ED60BEED0E1657D796EB51CFD37E4B
-:10519000715D0F3EA109119C7FA58CF9A61C66C10B
-:1051A0007774247CFF34E76BAD8684518EA5B37B86
-:1051B000390ED1FEA1DF83BFD2F6A0DFAE50B91306
-:1051C000EACF1B27E0B9A8C0D0792F5903C015DA60
-:1051D000B97CE867E7F2043F0BF942A55EBE2B8578
-:1051E000309014F80F053B05EC0482FB0011B7CC9E
-:1051F000348A7AD90BFDA60DB567E7E05278995647
-:1052000085352560A7BCF127A0C3B1E445611A9399
-:1052100013E229E4C516C3C3476AAF196D3D0AEF0F
-:10522000C7F20C9B9DADC7840CE04BAD794206E8FC
-:10523000CD768747F1C5940BE9766AAE13F045DB6E
-:10524000D1F2AD35C7F2E518FD5498C6E4006DE71C
-:105250004DA2F01E342919C0BFA38CDBCCC6B57C8F
-:10526000BDE3BAE9B8B4DD411B1D97B6DB663284F5
-:105270003509A38D5FA1C078971A97A21D913F832E
-:10528000AF03A59320F8C10EDA3448AF3378BEF2ED
-:10529000C164361E2954E7FFE49BE9F8985FA6CE67
-:1052A000F7B951DAD4017AFA6953C256A0CF373828
-:1052B000DD1CB6FC433ED8696FCC2B388472267156
-:1052C000790710D10CD28BF246C8C10B69C7CAA1AD
-:1052D0004CE5E18D6974DE0FE41E9D079D1F723C55
-:1052E0009D8FF6A5D95B935636127E419F026EA024
-:1052F00053E08B213A8D835FD01BB9A51713253757
-:10530000533B179EC2EE25A495E5C52B99C3F3A385
-:10531000443EDDD8CAE6D11844B86F74FC18F3E6F1
-:10532000EE18E7FF1EC035F7CA4FF0BE22E29E3FDF
-:1053300001F67714DE7969C9FF7BF0C6DBF997CAFD
-:105340000F1F8BCFC5F8D2AC9D981F1E986DC57CE2
-:10535000F1693C3F36D0A0C1B800DD0FE23EA28526
-:1053600018432097A772BB5C9C5B784562FED6E031
-:105370008B06457D3F517CDEB88279E9C1652CBF43
-:105380007CC87E6F56D07E1FD273FC9C44773193CD
-:10539000EDDDF728EAFB89E613F5FD440BED2171FD
-:1053A0006F8A94329CBFDFDD4390FEBB6DB9589F7E
-:1053B000AE65FA887C83E9A3EE1CA2BA1F699D3909
-:1053C0003411F394785EC146C83FF86FF20B7E9AB1
-:1053D00026A9FCC243E5AFC92FDCE6F0EF023A5B39
-:1053E00058E4CD92283DD6EB997F98D2EBA6088160
-:1053F00074C5D67CD8A7DD445ADFD2E421BDFE02B5
-:10540000E97532A5D73C15BDEE61FC1544212DE8A8
-:1054100075884E0BE3F300FDFB60DC6E47EFEF5B3E
-:10542000605FD36FF0B03C6896D7192F1F62E059C8
-:105430002033785C5A2DC2F33AF4130FCFE5F04DC8
-:105440002C9DA612C61F63F14FAA4C82B69261FE34
-:105450003199FD6FC1B8437CF408DBCF8E805B6B64
-:10546000457A9A73078B7F052CCC2E8038581A1DED
-:105470007F261F7F4EA7AFDA01ED664A0C0F61FA57
-:105480000F857F16AF9FD9DF8C7970B3AA75C7637C
-:10549000ED20212F45DC6D2E6F7FAB7DA60EF2D265
-:1054A00067D7AAE35D73EF64F1B639B3D5FDCC25B8
-:1054B000AB3FC17C4DD2AA03FCCDBD535DFF49DAA1
-:1054C000509C6C02C4C90E713FD020E513E0A3D7F5
-:1054D00093176FBA87D2F9849F149580DFF0869472
-:1054E000C66D4FD0F2B31B2761F9F594EF7EFF280C
-:1054F000D46F29C072355CE204FB56E043CA67856D
-:10550000E577CCC849007DC2FBBD87E07BB7D9DF1A
-:105510003D93B6734FC9C53CD66AEED7185CC8EA4E
-:105520006FBED2C65295EF52D05F5C6D66F7351DE7
-:10553000297EBB04F2AAAB7379B9E4D549503E2465
-:105540007D82F73A9C6BB6CAB00E2DE9CCCF3EB93E
-:10555000500A4FA478A976F2FE9BD9BC6A4B9E4BA9
-:10556000073EA9AE62FD4CF65476E6413BCD792C60
-:105570009F4B372600FE05BFE5F07D95B02B7D5C87
-:105580004EBCE43DD69144FBF519250F4CD1577123
-:105590008CDD4B6665E7037DDE1C19FCF4D3BC2C67
-:1055A000EFB6CAB83C0DE4E12D7E7D29CCCB6E2C44
-:1055B0003E0479118915956598A76D24B8BE94FEAF
-:1055C000C7A7033F5EFD495602109D554DFF82BEA1
-:1055D000660ABAAF56D337E5DBC9E9659796DF2A85
-:1055E000FA360DD3F758F63E85AB02E1FA865AAF8C
-:1055F0000D8D13C79FF1E38E2537E02F56FE0EC3A6
-:10560000D78B7C9801D98D79C0A75D824F6F023806
-:10561000F49A089E8FCA963C93F0807185C7887A69
-:105620002F8E5F057C99E0332F190917FCC9C26ED4
-:10563000657F2EF0A364F07AFA9D973887E1A2E3A4
-:10564000DF910E7AFC1106CF66A995C919BE2F11FC
-:10565000FE971631DF3EF57CCBCDEC1E0337F8CB41
-:105660003076523C6908EECB5807319F00D7E7B33C
-:105670008D3E9B9ECEED36473DD2CFED54A33A28CA
-:105680005EC274FF0F701ED404F7C17E6F21F162F9
-:10569000FC9CD247203DC66E12F0C6E3A9650CB94A
-:1056A0001A3F9F78FC0CAF5B240D9EE2FCE1D07C9E
-:1056B0002F739EF1F68A4BAFF65B3AB97FD139EC86
-:1056C0004F2C84FA5A62F6A03FD123E17EAF96DADE
-:1056D0001F20A76B6B08FA719C560DFA13851D32BB
-:1056E000169F5CFF4D26B76A9B083FF7C8E6174F29
-:1056F0008FA964E07E78D61A950D0B80FF1BACAAAB
-:105700007306B556168F784EC8113250067A7FA8A8
-:105710003C42EF0F94811C8ABF7FAEF622F37B3BA5
-:105720002F4AF8ACF51C2B03BDEFAC1928037956B2
-:1057300067F7FE14D655DC13198FCFBDE91A919780
-:105740007259741ACF47220E7AC4E67F393DC63F9C
-:1057500075568AA09F75B5CBCEE7E7CF017A76D88C
-:10576000732AC1EF34DBD8AA03BB38D1E13F90CE16
-:10577000E4E8175FC0E6179A523CDE56ED7F5866A4
-:10578000C3221EEEE578B881EBD9F39BB4B80FA91C
-:10579000F6163E0DA1A0C09B3A1242BEF5A27E14A1
-:1057A000F7C69DA7065518DA3F6F437DBBF857F53E
-:1057B00018279BB05E4394187D39316456DD7F32E3
-:1057C00079A75355BEA2375DD5FECABE5C557D7123
-:1057D0007892AAFEAA374B54E5B2C85455FBABDF0A
-:1057E000A95295AF1998A16ABF03F43DC5E3374E9E
-:1057F000CF52BDFF68E3F437213E7D5DF43BAAEF55
-:105800004F703F04097A238574FE0B04BD5EAC53D0
-:105810007D4FCD9AB0540E7CCFFE16AC6679F795CD
-:105820001463B1FD2DEC52DB13379028E62BB684C0
-:10583000244F9840DE9DBABEB1AF07F17AA97B0F25
-:1058400026B8E66BC05497C6513B632220825C0D9C
-:10585000798363F1FBA5D6BF80E47FA9F537B8D57E
-:10586000EB6F52D4EB6F2954AFBFCDA35EFFC40AD8
-:10587000F5FA3BBCEAF54FAA51AF7FB24FBDFEA986
-:1058800073D5EB9FE657AFFFB806F5BA67B6AAD750
-:105890003B7BA97A5D73824B54F5F17420E849C8CB
-:1058A000CFBC95F7AADB53A46862E842D0D9025F67
-:1058B00003E6638DEF7A48355E3C7D4C203C8FF4E7
-:1058C0002BD247E5386E7F72BAA07AA96A5C32DAC9
-:1058D0001937C073EE046EFFFB46B73384FC8AD5DC
-:1058E000EBB1FBE6B1E4DA087DC5F7D163EA2BD86A
-:1058F000479B86F7D163D1EFBB84EA591C7C35FA0C
-:10590000CFEEB033380E9A993DFF29545D43DBD179
-:10591000361514DE77613E74FC77CD93D10FF21DFE
-:10592000D2AB8371EF24117CCE23517CFA895D7553
-:10593000BE6501F1E9B95F6409E0A9C938500E7A82
-:10594000FFC2FCA3EF637CEE48D265DD07721CE268
-:105950003FE30939C5E5C9498803D1F23913F7276F
-:105960007A89E28AC1E729EEF7AC9B26A19E255AE7
-:1059700033E6B1D5DD2EA19EAAFB0FF66C1FC7F44E
-:10598000DA88E75281D72E6E1F303BA10F0EDD6201
-:10599000FC90F8AD688F7AECB0DEB43F1687F9471B
-:1059A000767FB1DBC8E0DC2511B9C289C70671DD9D
-:1059B00061FDE17C9BDBC8E0DBA52346C0EF64E230
-:1059C00047FBF031998A3CD6EF24D6EFD15CF01733
-:1059D0009ACD6F7EAB1AF2A9E5E072F4DF7F8FA853
-:1059E000FDF777B64AE8BFFF1E859B3EDD768F1B2D
-:1059F000F4B228EF02B8211E00EDE8FB5477AB04A7
-:105A0000FEB1AFADBF3D0FB1765FB2BFA17E0883DF
-:105A10000BFE603D857F3683D2B781D2CBB6EF11C6
-:105A2000F41FC6FB6BC769A90681FC311DBB97C07B
-:105A30002DAF67FBE2C31EBBCACF44740E38477A52
-:105A4000297B0EF2BE4FC59CD3A07434EAFDBA1F69
-:105A500065B07CA4F6B6C844884B9EE371D787DB5B
-:105A6000DEC4B256F6605E26DCF7E588F95EEFA28A
-:105A7000F531724EB6D2EF63E48DCEEAC3CB6B1E26
-:105A8000698B60BC53C7EF257B34E35EBB3FC6BF69
-:105A9000F2CE386E271983C49E42B8694FFF4E4F2D
-:105AA00023403F5ABB7C2A761F6D70D3FE62F5EE11
-:105AB000C564121B7F58D9F60EC2FD88E4F7436710
-:105AC000867C1236517C1B6438034DDF6FB811E5BC
-:105AD000AFDE76AF07EEA11A0B7F06B77C21567EAC
-:105AE0007E388EDFCFC5E5E7936DD1C9304E7BDBC5
-:105AF000800A6F5D6D17F1FD9A3652C4EA3FC47A91
-:105B00004D8D82F4738AD24204E27AF2800DFCC198
-:105B1000D43E26107FD6B98D186F30B818BCE4A2D9
-:105B20000BE9639E9DC1003EBF4C4A1FEF2FD5E19C
-:105B3000FEFABE4C2BB6BFEF37E30F7829DFEA2918
-:105B40001AB47FC37C86C761F8D373F94964BF0F69
-:105B5000E4803E5DC63885D33E0BD7F1CBF627F007
-:105B6000AE3711CC47D6675AD15EB85C38DD196ABA
-:105B7000BCC7E38FE209E5FF7D1C4FF73DC8FC93EE
-:105B8000F7DD4FF03C05594AFFCA87E96A1C978741
-:105B9000A9C487CFAE362A080DB05E46E29F40ED1D
-:105BA00011D28B8D4DE0A7827AAFEC80D48827AAE2
-:105BB0005D33E1B9A6E26417B0E3DA6B3F8BC01343
-:105BC0006211802F7B0309C155BC98AB40C777F8A1
-:105BD000593981D727CC65E5445E9FE863E54CEFF2
-:105BE0000B523500161747CBB43A6FCA0779BC8001
-:105BF000B073F1FC7E8DCD84CB0BAB736635D4DFF7
-:105C000049F09C8BA8FF09AF4FB31E5F99077A63D9
-:105C1000B6FAFB0D1C0FA9D6E35DD330DEA6AE1796
-:105C2000F1AC64EBF937F1FB2275FD53FC7B9BF57E
-:105C30007C641AD4E7ABC77F9CD75BAC2CEF8DCAD2
-:105C40007E767F03AF7F8CD79BA01EC62F64F55A4C
-:105C500071DF096FD7C9E118E2331E430C2633BF49
-:105C6000F2963623F2573CBFDD07F773950DF39B91
-:105C70007D2919F5DE86FB3298DC495006BCDE51E1
-:105C8000E4A2A877DA65CC37D0BAF5484F062B974F
-:105C9000279C1F87E489D4EA6144C6E4F4A5E89A06
-:105CA00012F005906B59F40FE83AE3FB1AE28F917A
-:105CB00073E94D66E28FE583054E5539E5CE74559F
-:105CC0007BD7EC5C55BDB57492AA9ECC76229FDC46
-:105CD000CBE9CB5C54A2AA17F765906DBC9D9DB52E
-:105CE000D3E54F55B53B5FA824028D9FBA49DCA38D
-:105CF000E631827CB8D7969B0AFCF8B3B60A444ECC
-:105D00003BE527F6B4F3A71B8C59FA5478B910CBAE
-:105D1000CF3B587E7F7B9B879573089EAF6F6FABA1
-:105D2000C1F22ECA9FF0FC699B179FDB6959A1CF76
-:105D30007FA4FD2BB49F1EDA3F949FA1FDC3733354
-:105D4000ED1F9E3FA1FD43FD06DA2F949FA670C173
-:105D5000F329DA0FBCFF31ED1FCA4FB4F9B0BCB65E
-:105D60006D2E961F6FF3E3F3B1B6067CDFD9D68AAA
-:105D7000E547DB96E2F3E1B6203EDBDB56627D2FA2
-:105D8000A793E7F979DCE72BD9BD03F1EBDF9F217E
-:105D900061BB2F9D9F534A157AB92A3FA73F03FC49
-:105DA00002BDEAFC54C01FC26162788C87E36806BA
-:105DB000B30F2791C8720B931F18071FDFE75961B4
-:105DC000A1FC35AE95AD7B4E5F14EBD31AD8784766
-:105DD000B99D405C419251CE8E9B43BB7352A4CA85
-:105DE000C2F207D00F43DC143FE5EC5A7246E621BD
-:105DF0000DC02557503D1E33AF217C39189C80B70C
-:105E0000D1E0FD578E376D692FBB5FA7A62B0C6CB9
-:105E100066F6B6E2FD3AC6B9BEB04C9F2E9F1FEFA4
-:105E2000E99874713ADD2452F976F19B44A1CF8C44
-:105E300026F5FE317D41896A7FA6BDB8862857D1F7
-:105E40007E8BD4FB3C73FEBDAAEF8C190FA9EAF53B
-:105E5000AE15AAFABABB731E71033EC7B1B89961F9
-:105E6000F5720221E485DD4F205CE64C368F73929B
-:105E7000C27E5F6037FF3D13BE7F79D6CEF1655C91
-:105E80008DFBF2090E562C480C6A400F7DFC8B44AA
-:105E9000947F3B9ED1A09F7E22096940DE4CA6E6FE
-:105EA00024D45F01378C6BF1AA262D948B89A285AF
-:105EB000F255248AFB3ABA7FD164D2F56BD1FA9FAE
-:105EC00031D1F2D94CFFB32CBF308CFABA80AF6716
-:105ED00081D8C7AD97E3FDDCC64CF437A9CF257652
-:105EE000F0FD4B8789F90D973BCA53C10E3E3746EB
-:105EF0003EA8CD7DE28D0514DFB6B463F814EF1F24
-:105F00005734A39ED7CFCB94BE5A5EF77AAA4FD40C
-:105F10007C9307F3385BFACF29E0766BC98F22FFB9
-:105F200074E8843C5312419E0D973D8924661E3BC4
-:105F3000DADEC9935121FA116F325F37315FF94FC1
-:105F40009576C84B2CE079D13BDBD2F2ABC70F7F03
-:105F5000EFE37450482235A05F0B8B349E1074E041
-:105F6000B5ABFC31A6FC2E2F9C0B934B8807C4F2DB
-:105F700044D285F729C87FD5623E9A7CF01AA25098
-:105F8000FBD86A0D9360D170BF84FB75BECFE5FC72
-:105F900067F66A9C8F9C25EC260FE874F299D51B56
-:105FA000013AFCAC5BC7D8F4B8BABED04A50EF2D6A
-:105FB0002AD4871409EECBEBC27B40E52D12C9C869
-:105FC0000138A6B9E7837EDF6B413AB6AC2FC79F95
-:105FD00030B859E3AF40FC0E287B35C2E8A2ED9AF9
-:105FE00027EBB7823D3901F06205BCDC915F0D43C0
-:105FF000E717221E17F2792FE4F3E8C81CC23F838B
-:106000008778BC701FEFA26EE18F52CFF3F1D2AA56
-:106010006FC3BDA2ED112DFF9922353E57E92253E2
-:10602000E64BC37051381766825C01B8AF820FD857
-:10603000FC9A9F91C8C61C946B35686F9469303F79
-:106040003D9E2E9B3299DC8F66D8D97DE4EE534875
-:10605000CFC3E5936F2C48C2FD33B35B6C32CB8F5B
-:10606000F47A9558BFF72AE15FE4E772CC1CDEA111
-:106070007B0527B1BC602B89AC87BCB4B1F6F52B8E
-:10608000327370DCE17D3DB55D203FA5CC88795C45
-:10609000AB443EA172549969634F385765E474FA72
-:1060A000A84D9DF7B39DCF6F3B5F8F41A3C87BF297
-:1060B000D616C79CF3A9EBAF473F9688D30E72FF65
-:1060C000E1A0591D576DE4A43078A8ABCA0CF1C10A
-:1060D0002E16A76DECBF99DD6BBBEFC7782F30EDA7
-:1060E00053017AA8E7EDEB57AAFD580B77FA915FB9
-:1060F000E3FD64F17E318A393DEC1FE3FD625B33E1
-:10610000F97EC2438A210E7B6275DE6133EC7772C1
-:10611000089E0F1FA77D01EFDDA6BB812EB84F970C
-:1061200014B1FBA3E2D7FF54961EF1B253ACEF7843
-:106130002BDAA53BCB981CD879E0FC2DE3693F2BEB
-:106140007324D5F98095393A5CA7B7297DC3B397F5
-:10615000909AD1EE293B94A9F96A72EF5AF5EFC1F2
-:1061600034F70D1CB62828FF5E03BA1F3CFC7942A9
-:1061700011F251147FBFC408C23099C10DE7B37644
-:106180006B3E99174B0F6F67CA58FF36A78B2F0DC1
-:1061900057B51AAEB3456FA5CC6070FD0EE4C6B915
-:1061A000F0F194587B46C0B57B8CDF03F8F0ABE28E
-:1061B000A942AD1F62F074FABFC3D36EFDE8F0FCD4
-:1061C00095C3F3B343EC5E9B91F55F519F75ABE1D3
-:1061D0003DFB7C640E88490AEF5F117FEE9329181E
-:1061E00013E6F8EB2DE5F459CAE58F07CF5091C0BF
-:1061F0007B57631E66AF4C926AA15CBE007FF72C92
-:1062000093EFC3021A3F9EBF21EF1946957FD764D3
-:1062100031BADE9D2E8D8A87D22C36CF0347EAB263
-:10622000C1BFF1D83B0602726133CFBF7ECCDE6BBB
-:10623000847BA6051EA15C429F017D741128BCC70A
-:106240004A3F332AD651C6D3B0F1D6C6F18D184F86
-:106250003CA76415327B553AA48573386BAF7D0B30
-:10626000EF7F5B5B2AA3ECFDD2F85F1D87FFF05B3D
-:1062700029B7307A999245E16B91FE90F06D5A0EF4
-:1062800048D17F2A827C15BD1FE71FA078EC91467C
-:10629000E2292D8BD18B989F98BF80DB76DD025C45
-:1062A00007DBBB06541AA5BCBDD017895CFFC1BC77
-:1062B000505F5C2BB3734C6532AEFBDA8AA978EE83
-:1062C0006C37CF17895EA31FF577441670BC3D76F7
-:1062D000F1B711B84739D8AFC3FB3F883CE0BE15D2
-:1062E000EE1FFF8D8CF789537AAA81FBCC0E1C39E7
-:1062F0009F00FBEBF9593A847B3E97878317B535AE
-:10630000781EECC867766D0CFDD76569B97D12897A
-:10631000C039AF3525EC3C8B95DB03D623271B001A
-:106320007E6BC543062986DE66651910AE35FA68B0
-:106330008A87F617D8A72561E6FFC17B1987CEB3F8
-:10634000DA191E5A4A0FA1BD60ED67F735D66529E7
-:106350004CCE52B8F7D2F7E6899FD9EBA1BE948E06
-:10636000973BFCBDCDCED6D35CC6EE4B5A7BED3F02
-:10637000DBE13EC844F81D47D8EFF2790AB89272C3
-:1063800035BCDF482417F8CB2E63BE5A6FF85E2366
-:10639000D8FB822FDECAD562BB47F93989472B0A61
-:1063A0004370AE4CD0B135DBFF4016CC8FF2C50B3D
-:1063B00068EF447CD3103FF662C833DF2545E632F0
-:1063C0003B446F073E2CD46854FC16E1EB269E54E8
-:1063D000FDA3DD733FA75DA1F73B424602E74DFEFB
-:1063E00078716622D8A71D19C2DEF31A015F9B25BA
-:1063F0005F620E8CF32F5ADC0F1E3872BC01C6EDA3
-:10640000A0F302BE7DF875EB6AB0533AEC5EE4533C
-:1064100031BEECD0F0F560FDECD67BDF047F64D4B8
-:10642000C1EECD3A38758611E89FB6D3403F7FA0C4
-:10643000FBF7F004E8A71AFD060BEDB3A6C3778BB4
-:1064400088FF11B06F17756B55F7833CCCE5C5C25B
-:106450008B16128ED92F2CACF80E9E6B5C78310106
-:10646000DF3FCCCFED3FCCCFBDEDE2F878993F5F79
-:10647000CFFA8AFB6F4F9CDE4AFEDD8E3AC6F7BB31
-:1064800060FD9AA5013DA8FA35533FC7F3647F68C4
-:10649000B393B02106DE11F34C22E1987187DA5DE7
-:1064A00034917052ECFA32FA1D9EAF15EBFFD0E634
-:1064B000463C8EDDFF38151E87FBCF53E17164FF2C
-:1064C0000558FF87B6C24BF43F798CFE7354F00F2A
-:1064D000F79B8FEFCF1DAC7BD642F9EE6078C5C637
-:1064E000574BE1F7F70CF87B1BA4AFB70ACFB9EE17
-:1064F00022780EFA81FD7F7A1FF2521FD8AAF7C0C8
-:106500001883BAE83CCF287A269FD88370EF9C780E
-:10651000BE9D9587EB1CFFDE2887EC90676A2C9464
-:10652000EDA0E78C24125A01FB975223CA3911DFE0
-:1065300012FDFE3453AB92B3E27EA1469E7FD86833
-:1065400061F1AF26ABFF2CACFF124D57CBCF681FCC
-:10655000A70B3BF07C3B210EDCD788F88E0CFBC5EB
-:106560003C707DF9089C0B9B97E3FF0CBEFB091563
-:106570002B10EFD15EB1CD0FF9798FF37DE4E3A657
-:1065800088DB13233F75D9F257B31BBAE2E8B7ECA7
-:10659000773BC28C7E75D940BFDAC8CFEB72E07C06
-:1065A000E300BF674E41FBB9AEF430DE475927FC2C
-:1065B000022BE3F356321D604F8B785402E41782AE
-:1065C000DDB086DD53586F61E5FA5F27E1B917BA90
-:1065D0001FB214819CD9AD65FE221E073BCF611E00
-:1065E00034AEC902FC0EF27C97F3FDAFE1BDA7E724
-:1065F000578E473AA8FFE50FF11EC3DDE94C9F0D0A
-:10660000EEB3A13EAB3778CAE15ECDDDE9CC6EEDED
-:1066100095C309253176ECA3195528A73F5E395E4D
-:10662000131B27199FCDE4C21AE1FF94A3E570CE96
-:10663000EAE3D2F03FA13EDD63C2DF1BD3ECFD53A2
-:1066400039DEBFBAC680BF6351B577E2BAB9B05F71
-:106650004C90311F5BB3D784F09C5DC5EE83836F94
-:1066600041EE35EF1D87BFCB566F8962DE64B3D92B
-:106670005300F1C1FABDDFC0DF9F38F1F8C42C90A0
-:1066800083C793952CBC6FFB718A743AEFE3FB26AA
-:10669000B0F79D57E3B96ADB1A8B7F34FF88D04B84
-:1066A000F1F7CDED4E2F3ED707F89968F4801C5EC8
-:1066B00038E45F67F707D6BF199DA524A0FF06F34E
-:1066C00017EAEDA7F0F71DEBBB8FDD49303EE9423D
-:1066D000FA15FBBCF871EBB9FEDAAD8FCE83DFD5CE
-:1066E000AB6FE7F8E7BFF759AF29C6DF9B14F85F38
-:1066F00013771FF3F738DEC5F3C41119EFB9A47689
-:106700004516F88F4EEC3720BD9D583319EF5710C2
-:10671000E3D55358ED944F8F3B9529B0BE0BB2157E
-:1067200036FF76B67F15EFE9F811F8BDCEE83E2DBD
-:10673000E6AF0DDAA30910C714ED4479683EFD5A9F
-:10674000FCBDB7DDE90770DD295D11A02BCD2F6DF4
-:10675000A8B703BF64BF1BF7712909829F34F88E65
-:1067600001F77B07F719D09E1E7C979DCF1F71EF15
-:106770009F359A05F7DC067E390EE5DA6066740B04
-:10678000B3BF4D78CFE4E051FFD53C5E9CC6EFD15E
-:106790004C03BBEFC23E5318EC3EFAC4B843906CB6
-:1067A00073E3FBFD16BC2F883ED9F924698F1B7F4C
-:1067B000378974F1EF23F8FD0359FE0920A71FC89C
-:1067C000A3FD5BE1FB93D8EE42AEFF4A8C591192D8
-:1067D000CEC74BC77E33FDD9F85EFACCCD7E0FA86D
-:1067E0008BD747B03E60F05F8DF3F8BD8DF48C32EF
-:1067F000CFAF7A5FE47DD949B88E026E8A67B42341
-:10680000E3F1D293CDF69F021FF17439B49E9780C5
-:106810000FFC3278BFC03EB68EAB26EA993CE99CAD
-:106820008CF632DE30149327B87CDF074897833A22
-:10683000EFD3A097A2477584DDC3482D03F05754CA
-:10684000B076F516E6F710709CE1E7071A3B591E83
-:10685000E199E73EC89A6F85F3F31FA8CECF0BFFEF
-:1068600021ED2401FC33568F925057C4EC762DC293
-:10687000C57E8F6E8D4EC1DF0B0C3E3E11FD122783
-:10688000F4CA5EBC0776D5151AA0276D3197BF4FA5
-:10689000B07989FBDDC43D6DF17819C866FAB2990B
-:1068A000F8EF823BFE8F132585074BF1BE4A74FF3C
-:1068B0006B20CD52F69A587E3BEA8591F742EA2F3B
-:1068C000F17B82FFBBE553B05665809F6002E8D53F
-:1068D000D376B67FC45B2240BF6BD93C3BE003B8A4
-:1068E000FF82F84E835EC45B25281E4E4BAC3E9E55
-:1068F000CE84BC1B810FA01BE817BEA37D7F9E9D8D
-:10690000C3F63F76273F9417D4435EAAD057014978
-:10691000D6C07D0F271D4A02D0E5C9CE3CE772C81C
-:10692000F7712829B1F676E010C17B0E1438FF7399
-:1069300035FC2E92770AF805773BD5FE8878785E8D
-:10694000A81C40FDF35F98C6C553008000000000FE
-:106950001F8B08000000000000FFB57D0B7854D5A8
-:10696000B5FF3E73662633794E1E8484409824E436
-:10697000018430090F4141074810156878092885BE
-:10698000930710421E88B6175BDB0C24205AB441D3
-:1069900051D18B76404154B4414141037700A55811
-:1069A0005163D5566DCB0D88BC1F31A897FFADAD97
-:1069B000FFF55BFB9C64CE90A8B5B7F93ED8D967CC
-:1069C000BFD75A7BEDF5DA3BDF7C433FD7096175D2
-:1069D0002B42F41022CE6D11629810A3DC82F34298
-:1069E000D885C811FCF38DCA89DB3A5C8885F88D9F
-:1069F000AAAAF9DAB59EC82BEB2D5C1FE375467782
-:106A0000F1BDF1B5FF50F228B3214C0887FE3D5D82
-:106A1000880F311E8D7BEA90DDA70C461A2EAC093B
-:106A20004254AC75FA451AA56F4ECCBA53E685426E
-:106A300075C76C5C99D84AE3966F2ACA1291B21F47
-:106A400041F3AAD0E7559EEACD52870AD1F6A8EACB
-:106A5000DA84F6EB559E8F6AF3B81EA5EF27D6DBD6
-:106A60005CCBA99F0A7D3E277A6BD1C5B994B70A42
-:106A7000ABBD80F2562DDA45FD2E78542DF677B158
-:106A80003EAAF781B5A00BF8604D893A7C32A81E6A
-:106A9000D66994E3BFF7687257D1FCC2E977CC633B
-:106AA000A3E2F7D1FC4EF4D1E6217FFC9330B18212
-:106AB000F2EADA45D1EEDC2BE17DC2A1457B720121
-:106AC0005FB91E039EA1E318F0BC0878C620BDBACA
-:106AD000C54BF0AB7D48F5A0CEBEE64BD180DF982C
-:106AE0003D4547AEC1F7B561228CDAEC3B9CFECE4A
-:106AF000AD348F8BAB55413D8AD23D198982C6DBBF
-:106B00006EF97C2EE073BF4DCC7A91D2D2B7A747F5
-:106B10005B28FD46A71FF5210927356A7AF47CAE6C
-:106B2000DF3EB998F2C7DC9EC482A07A3FD6E92C3A
-:106B3000145F656BFF168D712AD6D8785D065E2EC0
-:106B4000621D34BF8B8D11FEE504978BBDDBB85FF2
-:106B5000034F46BF15C083414F546FA5DBA58FE39C
-:106B6000B31747115CD3B4E19E2EE864C183342E81
-:106B7000FA5B1FE575E67DFF710D7874E09B962545
-:106B80000CFC038F4FA46DBC97BE59DEB30AD193A2
-:106B9000E0D0787DAA42DFCBF6840985FA2B53DA60
-:106BA0008E28099C77FB14AC7FF13C8C57F67198CA
-:106BB00005E5C7F75E9FC7F30AC12BC129B52B7A3C
-:106BC000BF98D696EA0982DFC53E6D7379BE067D11
-:106BD00074CE9BE751BB374C605F5C4C237C4676A0
-:106BE000C2B101F819C6F55D76A66F6F1EE0D7B188
-:106BF0005E57C87A5D21EBFD40307D0B8FC6EB29D7
-:106C0000FF24CC82EFE50FDC94E5A6718EDF3B8E8E
-:106C1000D7753CCE9B87FD753C95FACFBD729DE53F
-:106C20000FD03A73BF659D8D4EC657B7EB8C6B7B0B
-:106C3000427CCB3A37EA7468ACF333AB3BDA8AFA7E
-:106C4000BB55B19C8A6AFB14DF7F8DCCBB56D0D07C
-:106C5000B536490FB56B23FCC0D78566DB047F6E64
-:106C6000271FA0F1BE273D58981E8E8F753F3C020E
-:106C7000F4759FEAF2B9019721EFFC9CF2C7EF5738
-:106C80005D02F9B1127EC40F2CE00FC7538B27733E
-:106C90007EAFCDB582FAF9B4F16F7F04FD5CDC63A1
-:106CA000730B5E5FF1FDB390A7F982AF115C6EC606
-:106CB000B854CEEB57EF19D68872F1E86057A6BBEF
-:106CC0000BBE1402E78A35AA691FD201C1E3D53E83
-:106CD00090E2C63A0C381387CD9A3AA8131EC84FD3
-:106CE0001FD409975ABBD09AF8FB12FB944141FC80
-:106CF0000CF04997E744FF3CC9C7D2A283F673C89A
-:106D0000FC42F98F51CF48FFD2C157CCFC7851706B
-:106D10009EE05019925F1CC237AA42CAAB43CAB761
-:106D2000F7FA9CF940E8F813D3E4BE31E058AAC35F
-:106D300071BB45917CE43EC5BF897E2DB5BAED4B54
-:106D400069FE2F8E11F3D04F995538AEE57DD9CE1F
-:106D5000EB2BB58A86B0027CF7703D63DDD45F43D0
-:106D6000581CE5C3251FA27A13EC417983DF1AF37F
-:106D7000094F93F030D2C55B9D8DC783E059DD1478
-:106D80006BCAD7EE4A6E3CEEE8CC2FC62FC9F46F23
-:106D900022AD7E38E0227FAA77B51E8C20FA49B258
-:106DA00068E169D4EFC583FF1B9DEB66BC0F2F26FE
-:106DB000FC16A8E92F1DA6F5B6ED563D9BD0EF9B1E
-:106DC000F2FC115F5F7A781B7DAFD99B21EE75775E
-:106DD000AE3F148E17775D8A4EA7EF170ED9C30505
-:106DE000C901A5CDF163EDD1BCBFBA84BB5B87BB44
-:106DF000D1DF056B6BF494A07A17446BF4D4207A3E
-:106E000029DD75A94EE431FC7C6A101FFF744F8F99
-:106E1000B12A7D2FFB7DAFB1164AC7E9FDDE6F7346
-:106E20003FB986E6EDDB1DE6D94CF3BEF0E62C0B50
-:106E3000DA5F78B3424F7FEAE5F4B34F53317EB463
-:106E400045D2BB31DE8834294F95598E3E311AFC2C
-:106E5000FFD59E69F5699DE56596822CE0799BAD2D
-:106E60006D2EE67D4111AB95B8CE7EC6A5B9B9FDB4
-:106E700085DD279F007FF8F4FE3E05602B177667BF
-:106E8000E769547EE1E321592EEAF7C27DC91EF07D
-:106E9000856D36F74F99DEEE89F260DF1BFD619C50
-:106EA00025E87FF755C335A41FCBF9523E4F93E336
-:106EB000FA9482CE7EA32DEE5F8F02BFF8BDCDB3D4
-:106EC0009992A57FCFE8198BF5613F778187B2D57D
-:106ED00061C26DE2272B78DEA5C263871C84721124
-:106EE000445FE5A298BFCF6F347F5F407C02DF171D
-:106EF000AE377FAF108DAB5A697D8BFCE6EF82F623
-:106F00008F2F11FBDAF869E2F37EF1D66FC24CF5F0
-:106F1000844FE70F0EE6C7A5B41FC1C79E57FCFEFE
-:106F200015C0EF3D2AAF33745DCBD3D2781D8F44AB
-:106F3000FC636E6B105E8F59843589E07ACC2E1C11
-:106F40004905E847089CABBE3D61FECDD4E4DEFEBA
-:106F50005FA59632DF4BB2E03CB8C305CE47FDEDEE
-:106F600039998A7ECA5617795B83E677D1E67DE444
-:106F7000E79057DF237E4DF58E8DF5378EA5791D71
-:106F8000BB57F5D47731AF33249FF9E3091EF728B7
-:106F9000C23F84F2CF9C4C2D21BC9CDE7C32B534A8
-:106FA00098FE15312B981E8D9466C2EB82AC89F445
-:106FB00018AD05EB09ADD7895FF37C0D783A55B173
-:106FC000A42B7A7814744FE5397F5705E4CE9A3DA7
-:106FD000363FE83362E3170FDF0AFA6CB6B940DADE
-:106FE000B57B542FE474B15BF567E21C6BFE34BAD9
-:106FF00012E7CCEE212E3568DD740E17E37CB9B0B4
-:10700000EB5262592EF73319F244ED9E873CA0DF14
-:10701000EEE6F15C9AFAAFF13FAF99FF9DCFFD200C
-:10702000F146F0818D27B2C0DF890F3E9786FD992A
-:10703000F5B51D79215A8783FE687E2CBF5FF47FEA
-:10704000C5F2A5A359F5FABBC0C39E343BC3FF07E5
-:10705000CF6F02CD2FB1737E349F3DE0CBC63C6B2A
-:10706000DC6D769CB3171DD179E0A7B4A089F989AE
-:10707000FAF9E4067F2D9B2888BF16EE9EBFC20951
-:1070800079A151F1400F286F56F9DC2ADFA0FADD13
-:107090008497C2ECBBF63B219F3E44E5D474BC3AD6
-:1070A000EA8FB3A8FEC2FB54CEEFDBF8D33FDA8001
-:1070B000D70D3611063C86476FD2C7637968913E7B
-:1070C000BF45CD379D56A0B7EC513D01B4DF1CE55F
-:1070D000C1F7B2D5B663C1F4351FBF507FF3D72BCC
-:1070E000FE401AF884B9FCC2309FCE2742BE6F5CC6
-:1070F00035757F02522BEB898BFCE672FCBC4EF39C
-:10710000A9D57FDF9AB9A617F073C129440BF6AB56
-:10711000B595F51D11684D051E2FECFE2C1578ACAC
-:107120007DF57FB24417F8EBD84FCD510927228463
-:10713000384BE7C63716D0FDA5C9C55DD47FB18FE2
-:10714000DC175B6DBE5E9063F76FFC8AF9C1C5DD2D
-:107150005A5F5717F4DBB95F7D4E4B12D280532034
-:107160001DDAE4BA11FB84E4C17B411F9B564DDD5F
-:107170004479E76B364842A2363392F70BF6C7FCE8
-:10718000A07E8D7DB2157C01E930C91F5EEC23E540
-:1071900084D5BABCB0755FFBE4CC2EE6B33ACD26FD
-:1071A000CFDB3E926FCC4D2B0E4F879C61F1450398
-:1071B0001FC2EB7527107C159DBEEA972D51F03D3F
-:1071C000493472DA5B3471FAB8105A24EA0B8F0B27
-:1071D0007016A24F2CE0C77B9ED7AB31DFFC898EA7
-:1071E0003BF06AD0832F56F837D3EFEA46875063D7
-:1071F00020EDB546A351D4A0A9BFEE4BE5B60F5480
-:10720000D69FD43E063E3D2EE0F7CBC8E931C1F80B
-:10721000DB77B87402FAABDE497A2EF5777E874DBC
-:1072200004A0575969BF503DDBE12FEC69E04BCD1D
-:107230008A80BC5C4B797CAF1D65F5FA83E0929740
-:107240002EE1919A9EC570BB60F51E9A08FA73955F
-:10725000DA21D7DB0E974FC079634B2AB5635EFB0B
-:107260000E8F75A4016FB156DE37AB9A8D715B5CE2
-:10727000E83F2AF6039E6F43AE454453BB868FC258
-:10728000FC0C4C87E443613A5C1B02850E7717F8CF
-:10729000F189C2143182CA77A81330CFF3AE5217E6
-:1072A000F0688B957687309B7702F49AB0D8B878DF
-:1072B000CC6F447A06CFFFABD8253CCFAF48BC801B
-:1072C000BE41F27A31F20DBDCB55867DE323BC8FF2
-:1072D0006B1D72FCA83D2A9FA362A443E7DBEFBBB2
-:1072E000CA689CC8BEDA24D083319FA861AF0BF076
-:1072F000E71C8B85E5B3863722D7802F18E51BD294
-:1073000025BD19F858996075817F3CAED3E74A577F
-:10731000B1A320689DB61E161D5EC50EC069BBBD1B
-:10732000F810CE9736FA8E73737FD25407F414AAEE
-:1073300067413F27EA68C764A3DFE90EC07741428F
-:10734000E978B45B2896ACC27E5BB85E1581203EBE
-:10735000DB6093E32EB81C2102433AC75D40F8E39B
-:10736000F697A3F97B8353D66B8892FBE7CE7429FB
-:107370002FAED4D3B57AFA83F9BAC7CCD7CFC7FE2C
-:10738000714BA9E4EF77A653BFD54AEB788826ABBB
-:1073900092DAED80EF893A97088405CDF78A75C6B1
-:1073A0008B40D0381DF52E3B45203E181F6EC6473A
-:1073B000E77A23B9FC445D12C3B1FBFE534C70EC79
-:1073C000EC3FC304C72BFBCFE2F2137539DFD1FFCB
-:1073D000C06EFA4F33CDBFB3DF7EFC5DECD2FA82D4
-:1073E000BFDCED227EC074D3CA7626BBA2FD067632
-:1073F0002FF1719880DCF79553CB7605F1876DE915
-:10740000765D9F0BA480DFFAC43A4E6B775D1A8FCE
-:10741000F66EE20B6CE7D0CB6B451BCF13FC02FA88
-:10742000BD48B6BAB97C97960DBDC89847873CF35E
-:10743000BB489F85F641D89EBF47631F5FB4B64DDA
-:10744000867DAAA9598D08DED707F4FD31B6CF177E
-:1074500079B0D7D5A01DF1BD9FEE5D9C0DF8D48409
-:10746000B5E561DEFBF7FE2D0FE7C8577B16F7C5C4
-:10747000F7AD549FE50F7B5B8D27A8BF7EC2E5B3B8
-:107480008CE84C9BF5FD1FFA7DEB9EFA5E98C736A3
-:10749000D83D482EAC59F656C6F178B021EF83E0BE
-:1074A0005F82F816EB43BBA6A96320DF7D48320F4D
-:1074B000E587EE9672C3D03EC26F4983DCF7E12CBC
-:1074C000F0899A61761754E1F0FC1696B7C38739B4
-:1074D0005C389F9FED93C1EBB3434EC840FBA2784D
-:1074E000A6E754F1AFC96D1B42F64FE00F35DB68DC
-:1074F000BC6AB575F23885F7D131F0A99AB7BF7873
-:1075000047D75F13819F5A8C4BF0785FEF27214359
-:107510003B897A9AA3F5BEABA8DE8C9B9353A11F3F
-:1075200095E8FA9998484019C9FC6810EC20579ED4
-:10753000DB520F7A4DD134C0C197ECF0E0FC1A98C1
-:10754000221CC971D8D0FEF4A934EE57E916C32E17
-:10755000AA60DE03F4353DDFAB69692C9F93FE38EA
-:10756000D0D13F3BAE25C3FB77F00BA3FE8737DFBF
-:107570003A48EBE2DC30E479BBBDE936CCB3AD3A56
-:1075800092F54798F3D0EEC99BC3022AEC8AB6C89D
-:10759000D5D0E73F8A987BB007C1E3FE282D228330
-:1075A000DACD9A79C32AE495FDF1EEA5A0E792D64B
-:1075B000E1C0E7D34E2D2683C6AF72687D1369897B
-:1075C000E7FB68D93138E48BE3259E44F1A0E22E35
-:1075D000E72FE753A2C8F10F476949E8A7C4D2F2E1
-:1075E000C455F8666D617B8368E8C1FD9CB78B8AE2
-:1075F000AEE47F030E47F475ECB3896B2FD3FAF634
-:10760000AD8DF1D4D37CCBEF9E39B796D2F996E20B
-:10761000C4806A9A7716D655E52BE99B4CF2F3792C
-:107620009B3EEF65FABCADAEACE0FD1C3AEF7A4391
-:107630005EF985C2FA20FF50FE155FACFF5ECA8777
-:10764000592E7D300DE7D6200BDB493684D3DE2260
-:107650003DF25D7D9E8FD3BE73C4F1F7D5F89E14C5
-:107660002EDB273D6CF1C37E503C7637E3E9C99AA7
-:10767000488F4A639508B71D725099F0B25CFCD9E7
-:1076800098BFED69A575156668D7016EF3E22DA95F
-:107690001FF03CB48153206F8D92EBF8167993D78D
-:1076A0003155B86C2C94893516C81F535D7229F377
-:1076B00015B93FA609AF0DE3CD101AD7FBC305BB23
-:1076C00017FAC41FA00BD1BC670A1F7F9F2DFC9C1B
-:1076D000DE2A025CFFC7A295F306BC893EE6254878
-:1076E000FA38D95365F8DF8C79BF1791D76719AD90
-:1076F00063CA23D999AC5FADEBC1F0F9AE794FD134
-:10770000E986F6EF3CF483FD3B9DFA997A63C8FE67
-:107710002DEC61E033F3DBF6514B7B87FE14994C83
-:1077200070B85E47E9F5DEC5AC3F15A991C247F8D0
-:107730006919A5FA21771CF22E4F48A075DCFDB916
-:10774000D4837EB75CBC3D84CA7F374615F5DCD256
-:10775000CBF2D464BD9FC9BDC79F869DF5B00824F8
-:107760000CA5B9175DD65E8FA1F94E56B735C45238
-:10777000F984DEA4C704F1BD1B12B65BA1D7DDD826
-:10778000CFFC7D62AE59DF99241A55C079F250734F
-:10779000BD7D800FD1D78A0CA9B788016280EEDF4A
-:1077A00063B9FB477A1FED132FD9E10B793543BB42
-:1077B00007705C3AE9B3B9185758E57A6ADE51D9CF
-:1077C0009E778CE42C2F9DDFC7EBE8840893F208AA
-:1077D000F2A7486E407AA6CECDE9393AE7517EA1AC
-:1077E000CE23EB67143F807D56BAFA732BF072B745
-:1077F00053C2F96E67AA1F76B58AA6C6F1985EE5F0
-:10780000AEA68348CB03C5E371CC2E38B4E420D2B6
-:10781000BB3BF4B6250EDD5FC0F3BF5DA7D3DBA392
-:10782000A6DE3488F6C9EDBBA5DFEBF63E53A74DC7
-:107830004A40DEC6F9EEE8A8FAB22234DA22CFA82E
-:10784000DECD58B7B7F9E8C1785AE7C9BA113CFF9D
-:10785000D3755E9EFFD9BA099CFE3DA3F839AE27C9
-:107860003E67796CD2B6A3D614AA5FE455BCD8B7EC
-:10787000D77A85DF4F74B1DE26CF81F5740E601F95
-:107880008F1934F5F13B30E90C6D27DACFB871511F
-:1078900011C6993CA2C48A7A33BF16223EAD934EDC
-:1078A000BF8BEE8DF557EBF83BBF5761789EDF1B22
-:1078B000CBF06CDF911103F960E9CE8C9E48896FA3
-:1078C0001A7A6F04E0D77ED9C2F36DFF289CF58E3B
-:1078D000D0F64B770EEC897A6709DF2248DE3CFB55
-:1078E000FC7FB883CF95B3714D5F7D02FEF657C91B
-:1078F000DF48B239F118F85FEF5E1ED0CB055DCEE0
-:10790000263D2302E75F8D6E57047F42FE6CB8B4BC
-:10791000E70E7F21652CF617C673139CC31C19B99B
-:10792000C787707F477E46FDBDFC589207FAEFB9C6
-:10793000ED8FA463FCAD4DF33F798CFA3FEFB7F8C0
-:107940006C744E9D174D175E051F7E2A92ED7B7756
-:107950002B342F9CC39B7B713E47B1862FC3392CA0
-:10796000FCBCCF7314B77519F1ADAA171FED057ADA
-:107970007C8D603082CA5F5B1BC17CED359BE7C8A4
-:1079800032F4F7B8ECEFE9FBEF3CB60BE97DD50537
-:107990007752FA65461CE3A1FC814503D09ECE795F
-:1079A000914CFD3DF78A1280BF6AD0BA7D2B926957
-:1079B0007E83371CB5F4A234FF29A51EE9C03E37EB
-:1079C0001E82FDF96F196E6E3F645B9A9A826DD9C3
-:1079D000CBFFC9757CFE9BE582DC759F8FED253A58
-:1079E000E583014AD3998D34D7B0D48F0A348663A6
-:1079F00023AF6767F3B4F76F155807491E98778967
-:107A0000DDC3E791DFB711783EAFE57858BF2BF6BD
-:107A10003D0A7A3BAF257A703EBD4CFAFCD5A87F73
-:107A2000C4CAEB7CE5A9F7A261DF89213DD909BF72
-:107A3000487EDB78D4AFEEE316F087F579E2FA09F9
-:107A4000804FCD8E9D1BB99F2A8707FA6EC5CE4BFE
-:107A50000753202FDE203C99A0C71D32FFAB42AF59
-:107A600047A5A5566CFC52E65B8A395F4CDA27FCC9
-:107A7000FEA24CCA498FE8E7A068CD637EC924EE18
-:107A8000EEC4D7AFA818E5EBD37CC9B06F1BE727CE
-:107A90009D7BA9FDB065ECB27DCBD85B53192EDF81
-:107AA000F3DCB3EBE797D1DF2376E173523F30DFAE
-:107AB000C09EBEC12ECFEBCDC467402FC6794DE32B
-:107AC000E6F593EDBDE0AF29AA326807C123E59141
-:107AD000309637BEEFF8B36256F1F96DC85BB5E189
-:107AE000922FF2D941ED5F88D2AEEE370C76327923
-:107AF000DE0BAB3B17F2C8E351DE6BFAB1BCD59697
-:107B00008A35D0397A1DE653A392FC9511247F451E
-:107B1000C67DAF733410E52D42FBEF5B7F6C04CD67
-:107B2000330629F1EF68A486DE455A4897FC397D73
-:107B30005B13F8F34361923F470D61BE64AC33744D
-:107B40009C03C40734E23B6FD039A3113F181739A7
-:107B5000C6CA787DDD527590CEE522390208DA1A60
-:107B60003B94F3DE28826361A42AB42EF4472325D4
-:107B7000BCCDC73AC7274498EA1525C4DAB18FBFF0
-:107B8000EFFA551D4F6AB83CBFD47083BFBA137467
-:107B9000BF7DC8FAE57A6F770E63BE3A56F97EEB81
-:107BA0002EB215DF093C8F8BCCE773735CE4942312
-:107BB0009AE075D4E17BE87A43D7251CDF4F8EFA33
-:107BC00089227C16ECC7CFED6C776BB6B53EF75BC0
-:107BD000826BF3A25C0FEC472FD3BE70809F4EB533
-:107BE000B39CDB0CD992EA37F770715CCB6BBADFD0
-:107BF000DC375B6FEF147CBE34CFEEC57EF45E6184
-:107C00003410EC48F5D26FD26C5BF216CEEBE6E5A1
-:107C1000291E9A8150C1EF69CB7CE497FCBC5E09B8
-:107C2000DC0A7F81EF73BB40FD75B1FED5E9945F3F
-:107C3000F78B0C9ECF47A48FD762BC8A70E65BEBB4
-:107C400062BDC971049F97FFA1F279B22E9FF29194
-:107C5000CCD7D96EB36E8A37197EAD041D6FEB3663
-:107C6000CAF25EB093A23C4DB6FFC426EBDFA2D7AA
-:107C70004BD0F1FBB14EA7B4FF993F689323ACA062
-:107C8000FF77FB95BEC6FB467893E1177AAC3C9331
-:107C90006D98B754DE90C6F4A4DBD366E9FCDCE84B
-:107CA000170D1CC3214FCB9FD9F3373B41DF332A3C
-:107CB0009C47211F7E54B1220A7AFD0C4D0D842170
-:107CC000BE6A7A91B743AE4BC7B85E396EB9A11F91
-:107CD00006CA00DFBD6D0E712FCBFF8121C1FA9660
-:107CE00081E745FABEAD6E1AF360B07E5D6927FE8E
-:107CF0003318E5723F57456ABF077DD5EEBAE1C13B
-:107D000060BDFB54F94379BCEFF471CFD5791F3CCA
-:107D10009E09396F02A7C6B81DFA11F049FDF6D5C4
-:107D2000CF73DAEF3E0BF0DAE494FA92B5EDE38527
-:107D300094AF9F3580CFF709531D5ED8F5DA77846D
-:107D4000F961AFAD9F15EEC5BAEAF744F9615798EE
-:107D5000A7EF1BD2BBF8BB6FBB8DE9ADCAEE7F6648
-:107D60000BB5ABDADB9FE989E895ED96BE57236446
-:107D700079B4376DE55094F764FA79CDE68EE1F287
-:107D80003755C1E5E181AC5882779B533B8575132C
-:107D9000BDB2FDBCCA2EBF1FD1E912FA25FBFF966A
-:107DA0004471BF42CF6B3F8F677D4F58BDC9F39180
-:107DB000BF7D20AF47B3CB7D216AA47E78C425E781
-:107DC00075A4399EF785418F478AB7DC939580EF7C
-:107DD00024AFD2FCFEB24C0DC01F6ED09F32F5F224
-:107DE000DB5751BB4F5F55D96F33E7D78B0FE3FBA1
-:107DF0009C15D51339ADBC6B329FCBF51FA7EEA2F6
-:107E0000F284A9A7D8BF6BE07F4E95D99F9A98E9D5
-:107E1000553381DF5CFFF68354FFE1D9271600AFAD
-:107E2000C333354726ECDBF6D697FF4CF36D5DFE8A
-:107E300027D6A336446B11F87E71F7D35CBF66C5B5
-:107E4000FF2C807E50639574639CDBB53A3DBF91F7
-:107E5000A9C5A2FFAA15BF633D2222B745F2D7BB31
-:107E6000BE1F3F3AD3BCF96585DA2D0E6FAEE154E3
-:107E7000F5E7E1FC3BAB04A2950C862BEB75E75CC8
-:107E80008168E047B348B972F1D610BF315092A86B
-:107E9000DB8BA8DDE226558F57F4DB41A7A1F51750
-:107EA000D377AEF73DBF578A26F93D76D7FDD73059
-:107EB000FE4500FEAE33CF646E023D9CDFF9745682
-:107EC000B09F3634BD72BE72FDE7F47D738EBED8AE
-:107ED000406FDBC24CF6850BCF24EBF426E9E9C2F8
-:107EE00033D9ECE74ED4F7D905C5670947BB5F081E
-:107EF0008E67109EA6E11C97E36D1A0EB9FB619D7B
-:107F00002F2E8E6F1A0EBE67F041E168CA63BB4127
-:107F10004E531EF464837F8AE2A62CFEEE6FCA42A3
-:107F2000FB972DD20E63CCA7F2B9148E7BA2B5F0CD
-:107F3000FEAE7C6EE026E48D71EA9D92EFD43B2587
-:107F40007F095DB79629EDE8A44FE61EA7B3A43ECE
-:107F500096F4825CE49365DE29F30B3794D8E16FE5
-:107F6000AFB7C9BC6B7D89FD18E6F73569B5C44F5D
-:107F70007374BFC5027FA9DD0BFBFEFAE5E11C3F70
-:107F800031DB3ECF4B69F67ABB695C030FFDFDE642
-:107F9000EF8BF4F9F40D890BEAA5B6ED0BC339F6B6
-:107FA000A4E8328E6049A6B4E33EFB6C477C91AAFC
-:107FB000EBDBC26DD0A15BEA1B8CD78FED065EEFC9
-:107FC00048A1F92FD6E3A55EB648B8FA9E957CE3A2
-:107FD000E57C2D05E7D505C01DE75C2CE57321EF99
-:107FE00049BC1979035FA1F05DF1F18214D8959F26
-:107FF000C894F6C7507C2C8F1ADE13E5065CCFD4EC
-:108000001DCA00DC8D759DA8F37AE968EBB4BFAF9B
-:10801000CF77688C8F7C47307DD76F1D7288242086
-:10802000716EABD58325D45BFDF743BFA8DFAA36BD
-:10803000F904973B80977391FBDF41BD051B620BF1
-:10804000A00F18ED17AE2FF29607CD7BE056335EEA
-:10805000063599F3837799F35B71060DFBE7DBE552
-:1080600007CCF92187CCF9931FDC7133B64F85EA31
-:10807000BB5F85BEF3E7F187704E9F7AF99568E0A4
-:108080006BF15FCB0F428F0B8D67213C2AD0737C45
-:108090005B14A6972BE25ABAE14346DC06766230BF
-:1080A000DD540ADF416BDA95F5CF8AA69BBD4467A4
-:1080B00055CBDECF907AB3EC7764D35A3BE4CED085
-:1080C00071BBE33B22D2EBC63E2A1921CBAE5E3612
-:1080D0004E7C8AFED6BC371EF458F22B85E59B9267
-:1080E00097B25F07DD1CDD3EFB464E6F9EC0F03051
-:1080F000EC920B9B954014E55D2344877F1FF18B29
-:10810000A50D21F19F6B42E282D699CB17EEDAF7EB
-:10811000FF104750E17882E32EAE8C67F41F805E3B
-:1081200059794AB07DAAF2A96FC2CCE5725DF3F528
-:108130007518E7ADF05DCBF17B57CBAAE238FEA313
-:1081400073E9A84B3B8573CB3877AF5EB75195F297
-:10815000BCB784FDC891768E8BAC76884004CDEB9D
-:108160005094DDEBA2EF97D647B1BCB280E45CE857
-:108170008B940A27C74D7A62D0EEC4BB2ACB65D553
-:10818000F1121ED5BF51FCB01D57C3A88BFC933212
-:10819000BF4804D8BE0B3AF206AD03F80BCE8B46AF
-:1081A000A95F565903FB009F8E7368ABB95E15AD8E
-:1081B000F3A338C87BE6EF35A28DEBD7EEFA262C79
-:1081C000F87B903D9AF55E43FF5675F94AFD653898
-:1081D000CB4F74208483BE6CBADCBEEE1E92236843
-:1081E0007D2B0D7BF85A29DFDDB2519E63249F67FA
-:1081F000014EEBD6927C86EFA46F20CE442C0AF77A
-:108200004BF95EEA0BEB6667B15CF4F23F5E0A4045
-:108210001F697B4861BBD2BA7CD9EFBAFBFA7339CC
-:10822000F8A7C2E384B11CB66E8A51DE87F5914F80
-:1082300030C564C8F9FAF71E6EFEDE4BF566C13E26
-:10824000221E74B27DC490FB0DB9BE2E56CBC91A46
-:10825000D6B9FE75B16D51F0BB898AF8EF25B76CC0
-:10826000D6CFE3365A3FFC2AC795E283F08F19F543
-:108270004666C97365F858EF16BD1EFB5FCA2D53DD
-:10828000EEBD8EE655FEB0C50D7BA18107E1F5661A
-:10829000010EC7D73A0B4077C3C74A7BD9917CC937
-:1082A000E723860A8E371AABF73B36CB624A93C276
-:1082B000891EA99FE345D21E1F35B498ED9624135D
-:1082C000CCEB2A6E65B2DE4FB9BDF8F7A3BB984F71
-:1082D000075D144AF9FBF86DCA26392F2FC7270E00
-:1082E0007FC0C9F6CEE3FA3964E081E86818CB0FA5
-:1082F0003A5F8B0DA19BB5A0079C87A00725986EC0
-:10830000CC74718B22E12BEE93F2F7BA589937E8CF
-:1083100082F43FF1BFA09B22C1F0EF4E0F34D6DBB9
-:108320009D1E4874B00874D0512F840E84D53FEC44
-:10833000DBFC42A52362872B848214ABF021CE178D
-:108340006724C3EB1EAB1FB178BDAD122F7DAC927D
-:10835000EEE8B4F18517707D2FE27D4B1E5C28BCE2
-:1083600054BF2445B07DAD1FC9553171DC4E204549
-:10837000588E0ABB13A5685F1223FB2FE92938FE2C
-:108380008EFAF35AE274E6361CFE5EC17205DA47D5
-:1083900017707B9F45B6F75A29ED9B21F598B69546
-:1083A000611CBF5C72779F2CD0C9C4B1663A39A2F8
-:1083B000D39591DE94EDD68D759E24F083D286FE02
-:1083C0007CDED43B8BAB77029FCF47B0FC59B2EA3F
-:1083D000C79386617E2FC47B80C23393B7B33FA817
-:1083E000B461F64F3E84BEB4D5C9DF2BB2B5F559A2
-:1083F00090FF15F7DC9DF4A174C6017B12B5D79AE6
-:10840000A69C7F95D2C9BEEDEF409E983C5DE5FAF3
-:108410009385B43F8B0639CE24DFE7D624EA6FD2AA
-:108420002885C3698E3A5DA9B7C10FA4E3F7A92CCB
-:1084300045977FE43D8192557DB2D273E13F21C9DA
-:10844000B80B39FD53A3FE186503E4A5BEE3E4FEB3
-:1084500033EAA31FF47B3A4BCA55BFD5E162E40966
-:10846000AE5CBF7C75D8D18C68A4B64036A5E9FD5A
-:10847000C7BE84754E4C17E3D703EE77AA6213CFBD
-:10848000B7AD84F94254961BF4AB9142CDFAE3D6D2
-:10849000FECC278F8E693B7A37E58F6E1E24ED8CDC
-:1084A000BA7D61BE4BB07C70748CE4776D9B239871
-:1084B000FE8FB85AA3E2A43D8EED0D653A497CB615
-:1084C000ACFE7EF8B9CB22ED47717ECC7F681AC72F
-:1084D0002794AD530361B807B0C66C6FA88AD4DE89
-:1084E000C67E08B51B84DA074033A0A3F2350AD351
-:1084F00061DF7A8F3D99F99CE2C2FACA2303FD70CD
-:108500000E947B9C1CC77C85FDE06B82FB70D8B908
-:10851000050789B5676B9F004E258D25ACEF46E4B6
-:108520006ACCBFFAAA0417EC179DFE26C25E0BBEEA
-:10853000646D4DC6BEFC55969BF13031CE9515C984
-:1085400074EDE4FB11476DAE2CCCEFE84AA705E7CC
-:10855000EDC41592BE69DF39708FE11EAB08073F8D
-:10856000D89A25FB9DB3DC5ABC91F2BD1DC21A15E9
-:1085700007FACA67FA5ED85FFB2DE675EA17620450
-:10858000E489B2356BE5BC74FA10D696C2781AE766
-:10859000D4E6B402D8013AE4DBFE63DB01C70EBACD
-:1085A00098AE303DD07A0EC18E9CDEBFF432CAE95F
-:1085B000FB3ED0CBC4B1817E881B2F52AB38BEB6F8
-:1085C0003D4978E0776C176D2C8FB4933C02BE6701
-:1085D000F019839F105D781D899DF8DE5247532264
-:1085E0001EBEB5CEC1E9B3752E6125786FAB4BE2E7
-:1085F000FC0B756E4E9BEA72F8FB8B751ECEEFA8D6
-:108600001BC1F997EBBC9CDF553781D357EB8AF937
-:10861000BBC1AF083ECC970CBE63F02783BE0C3EB7
-:10862000154A577309CCB81741ED991F1A7C10EB06
-:10863000B01474F22703CFE94AB12F09FC50B4CE2D
-:1086400006FF2852CF3DFF0AC1B9BD2292ED22EDAF
-:1086500042F2C1F648079F07A976B10BF689FADB0B
-:10866000BC47EF0E3A876FAD508435888E7FBCC40F
-:1086700029AC41743C6F59AC293F67D9FB6FF4A416
-:10868000FEDF8DD172B3691E477E79E2F13FD1F7EB
-:10869000DFFCF24C26F04EF3D8FC08C6BD2B5C9FE5
-:1086A00047AB9CD75D769697FA864B7DAB6FB8D477
-:1086B000B7F0E3088ACF3DA2E3A3242DF69DA7B12E
-:1086C0006FECAE9B47C04EB452DE4BFA04F8A3F2F7
-:1086D000BFE8F82B5D16C6702D6DD0F76B70DC36D9
-:1086E000C1F558B260F94EF10A01BFD7B15FD803A6
-:1086F000242B88638AC3AF407622E56B0EEC98ABDF
-:108700007FF711E47665D92196B3354724C77F08F2
-:108710009FED5C707FCAB2835C4FB4F636C56F467E
-:108720000CF5DAC13740E3C05F69CE7E81FD2E1AB9
-:1087300015BE7F54AE7F2F5FAD98E2A26764ABF2A7
-:10874000DE459695D3F359423F471AF9BC32E89675
-:10875000F808C7619637E6DB1704F1E752FD7B594D
-:108760008EC514A7797F969DFB398FCD49FDDE9B81
-:10877000936E9FCFFCCFCDF7058CFAA53905AB6082
-:108780004F2E5D83A8A6CEF625D9567D5E2EA97FF5
-:1087900039E85C8BE2F8A22ECF07439E39855F470C
-:1087A000F2FC59EFAA7CE1B917E08FACFC73189F7B
-:1087B00053958375FB4AAE7FF8349683BC91CA709B
-:1087C000C8E112FF85CFFD351A715DB53BA4BD9799
-:1087D000D2A3486BEEAA60FB5E8D87F6491CF8AD0C
-:1087E000D9EFFFFA0B7FE6FB9D84B0143D6E98E352
-:1087F000D46A767CCAF16BB0C7F986727F1C5F1DA4
-:10880000DABE56F99AF557422CC3A768CF97893C30
-:108810008F9D9712C1E76AF7AC4CEC2A8E28B41FE3
-:1088200023CEC1B0FFD58A359FC3CF597BD7849360
-:1088300092DE65FFA1ED1ECA8E4A38315020C6EE89
-:108840002AB6935805C79F2CD5ED38EDFE4CF6633C
-:10885000772777D7AEA7462492B55BDD3188B3BEC4
-:1088600028C484AEF0F449B6946BCFD33E823FFB6C
-:10887000E23695E5CA8BDBA2783FD46C7BF020E230
-:10888000046B9E52D8ED582D5A38CEAF66872A1CFD
-:10889000C1E71DEC47F1DDCF73F173514B405F8BA6
-:1088A0009A14EF669A4FBBC31DD323683EAF80BEB8
-:1088B00088341787350D47FFC6FC9F077F0B92371B
-:1088C00017353FC8F18D54EF02CB37BF8DE0383CF0
-:1088D0003AC9DEC13CCF6E18C2FEF5454DDB6B5880
-:1088E0003ED816E182E9E98CCD7C0FE4803EDE8142
-:1088F0006C298F9CD5EDD1675F50591FC23CB12FB9
-:10890000CFE871B846BB37F5766F664BF9A7265BA3
-:10891000EE4FA3FEA2A6A3D1FDA8FEC95DEF73FA98
-:10892000BEBE6F1645B6F03DCF933B22F89EE0C920
-:108930001DFF39FE351AEF7CD3980425689F9DC82A
-:10894000B6C97DBA41C62FF32517D6139A783D676D
-:10895000B7A528AC2F03DEA4B79FDDF112DF4336A5
-:10896000E4EB1F1C2F384BB186DCA3183D08728D39
-:10897000A355BFD7D1A6DB63FE6FFAAFD1BF27598E
-:108980008AF571E43D0D61C46FB864BD2235B72727
-:10899000F6DDDCC1EE99B8972DDE927197A2B7FB98
-:1089A00011E87F73DF8D67BBCB529BBB27F25F1C47
-:1089B000268595E0337788CE57925A87C1BE7B349F
-:1089C0004DCA15863FAD6AB522BC04BF5E44673E02
-:1089D000E4FDAAD06007C949677C3D5661F1DA71B0
-:1089E0003E46D9992EEAB73B37C1BE75C42E7CEC02
-:1089F0007F7BD129FD27E9D20FF218F617A5557113
-:108A000081AC78D8F174BAA99A4AE541F453B529F2
-:108A1000900539EA9C5DDA2B510EFDA9AA40D6AB30
-:108A2000D7E914FDA0DFA369AE0B2CF7EE8C12D0B2
-:108A30003F2CAF4449BBC8D3CE4D6141E776BF1C44
-:108A40008B1177C7FE4ADF66393FCC0BF2FC227BE5
-:108A50006316E45D63DC45D18D3CDE397DBC45E1C8
-:108A60008DD29FA3C711A23E8F6F13EC776A7B262E
-:108A70008CE5E633C92D2F63FC33CFF4E7B887A329
-:108A800069FE05BBB8DCC9F1E795CF860530DFD3B9
-:108A9000CF44B15DEBB44DCA63A7A312591E3B147A
-:108AA000F5F05CF6633D15A6C02E745A11F62494B9
-:108AB0006FEEC1F24065DD32F6D754127B811C4B5C
-:108AC000E904C87FA737F7677BD1E93755BE5C411A
-:108AD000DF57E3BB261AE7FE8CF58008B6239E79A4
-:108AE000F66FFD83FD3B465AF994D93E66D083511B
-:108AF0005E9423F960518ED4536EC871715A1DD1A2
-:108B0000F4703AAF53F207C203EB81B41F1361EF65
-:108B10003FD2B43B5189049C0359FF09B86F95FAC1
-:108B2000D6996D36F65355BE12E5653BD4DD57F147
-:108B30007DC94A55CAE3951679DF50F9E556B6FF67
-:108B4000D43FE32C003C08DEACDFB66D56F571E493
-:108B5000B8A7B7F4917E8D809E7F7910FB3526C62D
-:108B600089795359CEDA9007B85E7A2A82E3FE6992
-:108B70001C2FE2342A7FF67309CF9805AC27D0C1A9
-:108B8000CDFCB94AE7CFD5775F1383FB10E25D9543
-:108B9000EF795CB27A7A82FF86C2EBD11C9D3FBF2F
-:108BA000FC38F3832ADA37880F5BACFB13173FAB33
-:108BB000B05CB978D5358F30DF7DC726702FE25C89
-:108BC000D383D1C1F8A8CF91FCB0B3BD87EB2FA65A
-:108BD000FAB2FD5BD13C9F2D360FE6138AC7EFDD5D
-:108BE000FE59F507B5AF6C22F922EFCAF55F122DD9
-:108BF0003FFD33F8CB3627FB5109FF7C3FEAACAD94
-:108C00006901D67FF67927F39DB3B172DF9FA4F394
-:108C1000D4978DF9DCF46BB6CBFC619AC039B4D033
-:108C20006FEED798D7EA1C9BA4B7784F0CFC44D5BD
-:108C3000840FF447F8F911B77FD7C6ED43D7B34097
-:108C40006FD7B14F9F8F60BA39DB4BE2E5EC0BD9A0
-:108C50007C9E1D8D95F44EF34D85DE743656A6B878
-:108C600099047AA874497A383BA689ED026795ED94
-:108C70009C1EB5C97695CB747F3BD15F12E807B4D3
-:108C800009BBAA634D0BE419F0F9E1059C06704F8E
-:108C90003BD48E0E3AC5F9D7AAEF33E31D05F6EBA8
-:108CA000B09FA789EFC76BBA3C59B5ED4A7F25F055
-:108CB00054B54D617FDA7F19FDD0AC130C3F00D164
-:108CC000E5629FC2EF222C6EB86D11FBD396ACBD4E
-:108CD00015746FAC63B17E6FFCA8A2F27C8E3A690A
-:108CE000FFE45E399E01DFDFE7281DEF75B88CF3E6
-:108CF0008BF6F03B396E4947946DA4FEAA1A943561
-:108D00003C4E9AA1E7CAF5197022B0D861E73BAA98
-:108D1000DFD3EE6EFDC63CBB9BCF319DCF1F4D9385
-:108D2000F793DBDE96F7CC2F7D3D2426EE5BE44106
-:108D3000BE6160F487B863D020F5F322F81CF635E5
-:108D4000ECEB34CFAC0D66FF4ECE53E6FC806DE607
-:108D50007CEE0E733EAFD99CF7BC6ECEFF09E30EDE
-:108D6000EB8413F46FC43542FF460AFDDB1D26F584
-:108D70006FE4A17F2385FE8DEFD0BF9187FE8D3CF0
-:108D8000F46FE4A17F2385FE8DEFEEFE124E55BAFF
-:108D9000BD1478E0B8BADD4E233E81F7CBC5D98942
-:108DA000CC478555EAA51717E5B2FCD8616F9AE262
-:108DB000607B93118F9518AD85F7471C80D2B22A3E
-:108DC000398DDBB11DBAF6556987AE2A7046C2EE01
-:108DD000D1BAF2E42A883DA7A3B418D4BF686BDBEC
-:108DE00002F8562F3BC07EFFD6E5EE77AF93F863CF
-:108DF000FB8B115F5582730F7C9BF4251977EE7105
-:108E000004DB5343FD44624D501EF2D33A733ED40B
-:108E10002F04BEE635EDAB46C6C76F6C6DC9E0FBEF
-:108E20009F3EE3E0FB699FEAF63B31CBC1F298211C
-:108E3000CF23CE1B70597A9FB209E795A77F1CC339
-:108E4000B9FD50A6E97E61685A767908CBF31DF921
-:108E5000358A05E3944F5FBE8FF56ACDCBE7D2ED3F
-:108E6000FADCB2D75B4CF3EEEF0F37D1D1C0AD7166
-:108E7000217ECC5EA6FA8377A587F8310798CAA72A
-:108E8000AD1962BE8F5F7C8DA9BCAFBD236ECFA133
-:108E9000FBB9E4FC5CB2CEA5C8025E6F68BD54C5E8
-:108EA000F327F86FC5DB524E2DA773C61BAFBF2B40
-:108EB00052007F9D7732E057D1648B859DAD4C3F4A
-:108EC00087C432F3B95C61153E575C27DD55B88421
-:108ED0003796DA7F696D4C653AFAE547A92A8168C9
-:108EE000D180963CE8AF8BDE7C7238E8AA5ADD98D8
-:108EF000EAA2F23B14FF165C203F13B73D712495A4
-:108F000027A95A497FC273AA2D70FF1CF0D1ED1911
-:108F100002EFA47CBAE6A5688E1FD4E92FD5E60A35
-:108F2000071D6C6C54594F81FD4C8DEBA4938D8DB6
-:108F3000F1E1D06B2AC6283EC8C7065C0CFA08854A
-:108F400007C9EFEFBA69BD970EC9F7948C752E75F6
-:108F5000C9FAA241B637DE0730D67B5CD7472B373C
-:108F6000BE91753B7D3FD77F5F9E1B7EDCBA5DBCAB
-:108F7000EEC5966D5B92297DC7A1DD85752D7D7B44
-:108F80005CF4481AE7CB6D32AEFDB3754F3EE1237A
-:108F90007E7A77E39376E80F9556BF9DDFCD7966AD
-:108FA000A31DF10ED76FDDC8DF176C2D617B8071BB
-:108FB000CFEE941197ADC3A362ACB2C145EB3CDEDA
-:108FC0005FCA8515E1329EA6481DF54602D6B55505
-:108FD000C9C7BAA6176FB7E3FD8187F57AA1FBA6CB
-:108FE000FDF0B4A21EB07B35291CC7D4DD3E99111B
-:108FF000E8CFFB64DAE5344EA75F1EC87ADE8782CD
-:10900000B42F9C23B921FAF56155DAF59A55F94E3A
-:10901000983D90300DF2C25EF96E45359D43230AAE
-:10902000A0B70B7135A5C5A354139DD7164698F666
-:10903000C12C11B4AFA8BF9B452F537EFAC40C536B
-:10904000FD99D30786F89D0B3ACB997F5D6D7A8F9A
-:10905000A6FA2E9F5B61BBC758F3774AEF623ABB13
-:10906000D1D4BE5A4C35BD47B3E8A9F718CE4465F4
-:1090700076C4E154E8F758666947F5EFADFC9D16F4
-:1090800062DAAF7D333C7F92E7A58DFD09863D7D99
-:10909000167ECFE8EABC0CEF881745BC30EC1D9A71
-:1090A000591E69613D55483C54EBF6A8EA1C698F8E
-:1090B000AAF6B5D8118F4DF0B7A610486A1A15B6A2
-:1090C00037527D474A9CCCDF85EF3BCCF752D0DF4F
-:1090D00065941F524BB0BF42CB6B68DD38176A6096
-:1090E00047623BD884936C0733C6D1FB37E834F42E
-:1090F0007D80D0FE060C7033FFAEDCBAFD602F829F
-:10910000CFB4E2D87CC49D54354DB195E45E496F2F
-:1091100006FFBF546161BF7EFBE1034C6FED155646
-:109120008F8C4BFF76B8D478A5DD35940E17D0BA66
-:10913000E07F5EB043F1F815590FF0E905FA0C81B4
-:109140004F4A177033E0D501BF90727E3F6E28E220
-:1091500026E47B0A57C025149EFA380B34C17227C7
-:10916000CDCBCFF30AE9578C08DD8FB7DBD9FFB041
-:1091700041112EE5BBE131F5B2B4E3F4CD90EB6FD4
-:10918000DBA97820BFDF7CD9CADF3BE8A758C6D966
-:109190004F9F68DEAF1DF4542CF7CF8CCB89DCEEEB
-:1091A000DF4557DF454F86FF26347EDDB847E61999
-:1091B000A0DFB71A26867DF34FC4E11BF24177E7A3
-:1091C0004CC739E4D2F11099DEE5F9BC342A9DE3AD
-:1091D000CC35DDBE68F0694D6F678C5B42E5EE789B
-:1091E000D07B6F7E67715543466AF0FB37DA4A1BC6
-:1091F000DB815397C7735AE27425E27C29592EDF2D
-:109200006939764FCF44F8298EADB4254CA4AE8F82
-:10921000DD3934550C42BE88D34FD786CD0AB6CF40
-:109220001BE92D03E4F9619CEFE72D87A367613FFC
-:10923000AEDC198D90A1C52BDF1FEEA273BED9A2A3
-:109240002D1AC0FEE08D7CCE0BD7C63CD8E70C397A
-:10925000A37265514FC80355FF38F004E4016DB99E
-:109260002D1172EAE90F5481D01A3AE758BE38E559
-:1092700094F47D6A7304DFAB3CA5082FFC518BD4BA
-:109280007D792ED379DB7C33C68F70D2B8C330AEF4
-:109290007F4B12C6F5F8B230AEB63C33A62BBB8B73
-:1092A00091D6AE97F2DF16C3CEACDBA321F7230F26
-:1092B000B95F644BB91F79C8FD4821F7E37B0DFC0A
-:1092C0000EF01BD7B7E5436FF58D15394BF81C8EA3
-:1092D000CC815C7FBB12EE013FBA5DF1F4E478848F
-:1092E0000F62E5F91B8257231DDD46B25910DD5E82
-:1092F00077D92182E3EBC68858537E9C23D954BF8B
-:10930000C895662ABF3EA9BFA9FC0677BE297F5330
-:10931000CE4853FD499E31A6FC8F46DC60AA3FC56E
-:109320003BC5949F3661B6A9FE8CE21253F9CC5925
-:109330008B4CE5B3B5DB4CF95B2BEE34D5FFF192EA
-:10934000E5A672AF7059710E36431F23B8EF853E04
-:1093500046E9ED6F674606E375D4384B97EF0C3559
-:109360000D90FA5674AEF739D025EE09810EFBE860
-:10937000F780F6E29C1906BF654091FA704B32E81F
-:1093800026B45E68F9A888FD97F09465FFE76E9FA4
-:1093900061253E31EAAAFD4332287FFBC0E619561B
-:1093A000E22FA3AED9FF523AE57FF1DC37B27CF071
-:1093B000FE4B285772F7CBFC34C122C8AF06CE9BB8
-:1093C000E1A3758CBA2E7D8D47DA53BA8C53355292
-:1093D000C001719D8003D200D127D2FD449F485F18
-:1093E00027FA2CB7097190E813E921D24BF1FDF768
-:1093F000A497223D4C7A29D277482F45DA427A2920
-:10940000D23FD4CDE2F4833A8DDBFDB1AE82D38F6F
-:10941000EA96F0F74FEA9671FA973A1F7FFF648059
-:10942000617F08B09DC6F08BD5C01F097BDE2EDBA7
-:10943000B960BFB1E295E7ABE1C7AC5F225A23B098
-:109440004F5BADB1271C9DFEC9EEF9AD559C08924E
-:10945000CB9CE1DECF06F0F8BD5DCCB7F5EF47C49D
-:10946000B43E0584A74FD3B5B3E007330ACA56C646
-:1094700010FFB8EEEB2536D0CB8796AEEFA3EFD535
-:10948000F9DBA703BD6DE8F75AFD5DA66B1D32AE93
-:10949000F05A6B6B3DDBDBBF146EC403ED33ECEFB6
-:1094A000F758F95EB1F285E0FCE804C1F9FA2F5BE8
-:1094B000380EF15A972789CF1D3D6FC40575F8FD09
-:1094C000F11314EF63F8E18D789FC22F5AC7413E24
-:1094D000181D69778785C40DC0DFBE2FEA8FC6BC13
-:1094E000F87D27C3BFFFD4972280F7F20C3FFEB56B
-:1094F0008E9634D81546DFE1F004C73319FE7AE5BD
-:109500008B1615E78911AF648C63CC3BCA4AFD15F5
-:1095100074C6235DEB6ACA475C467D7524F7D79312
-:10952000BEE3DD49AAE755B95D533EECC7A3AB22C4
-:109530003D42E98C13E8A9AF9BEAF13A0BBFD03862
-:109540004E62B41E27817E1CB29CDF011C9D104818
-:10955000C6FB9FA397D83DB0833E8EB8B382CEB8EA
-:1095600005D48F08DAC79827FAEDF715CD17F2BCA6
-:10957000D7CBF09DE692F429DC7A5E3FAF85632C71
-:10958000DBBB543D5F1CE6FA6B04D1CFAD19DA901A
-:1095900081D4DF1F948CCC7CD617327A60DF4F09E0
-:1095A0007947B00BFA1931F0FF847EBC12EFBD058C
-:1095B000DBE142E9C8C08F414F06DEBBA32B830E1F
-:1095C00082E2D018EF1D71657A7FA1F4D61D9D1936
-:1095D000F475AD43D201F08CF82083AE942F9AF845
-:1095E0001EEBE82A079F7F065D85D2C5957425E9A5
-:1095F000B4FE270EEEEF4ABAEAA407C0E587D355BA
-:109600008B8AF3F89FA5A7796D623CEEFF975C7695
-:109610001F44DAAB9FB6177CA64C8C190F12132E81
-:109620007510EC62A1F532BAA9174A7FA1ED6EBCA4
-:10963000A25D466E70BB71FA5919DAAE12ED7A046A
-:10964000B71BC271116FE9F708DE721A712D9E996E
-:1096500090530EB96DF22D2FE18DCC27BA19A7F3D7
-:10966000F34362099FBF24EEFA404F853A698DCBE0
-:109670005DC8FA426164D7710537EAEDC77F5DDCEA
-:1096800080F98C4F30CBE337EAF2FCF5A291FB0F67
-:109690007D47E1C6DCEB59CE0F7D4761F3403DFECF
-:1096A000204DA481DF170A8F9C9FFE0E46A1BECFDE
-:1096B0005374BAC970AB62541CEE9B6A561C32AF2D
-:1096C000E31D8C3C8CEBE3FC0DC2CFE94D22C0FDC9
-:1096D0004CA20309F91F096193EF5FC8FBBA35AAD1
-:1096E000F6DF90578D7BBA4F3BB557B0CF0F444C48
-:1096F0009E83774AC60D19D70FEDF617BA59CEDB00
-:10970000EFC860B913FBD216D7C927DEA473BA5FBE
-:10971000A6BC378A14F746FBD179FA3B3AC791BF0A
-:109720003167B940BBF16E73BC93D1FE26D7386167
-:109730008DEFFE9CBC296F776FD8CDDE8ACD2E04CD
-:109740007EDF8ABDAA10EB7D2BB6A745A661764EBB
-:1097500007BDD2AF2BB9D8A0FBCEF1C6F378DDC1DF
-:10976000D9806B283C0D38FF00B81EEB0AAE7B0792
-:10977000089637AA23245FAD8E907CD580737558E8
-:10978000C77DDE9EC1F127550E09AFF9CBAE11564C
-:1097900012F5172C1BC9F99375C207B89FC69260C2
-:1097A000100FB1F709EB58CE1BEFDC9D7DF8BDE83B
-:1097B000249AE72A87F63F98DFB98240164984E267
-:1097C000E4867ABE8F7FFE05D5037DAA4A75AFF188
-:1097D000C0CEFA962AEF717D7D2015FE58F154D740
-:1097E000F1E8550E095F439F1CD2AF98F7ADB15F0A
-:1097F00085FEBE80215FF50E93F1DCC63DF7EEE4F9
-:10980000ADE1E192AFF50E93FCD8C0EB06BB7EEE66
-:10981000533FC3898FA6FC3A9CF5AB98586F4C2EEA
-:10982000EC8385C2A49F187695F604F97ECAB5220A
-:10983000EB9151942F3C64137E2A6F074340799239
-:10984000F4B3B61FBAA482EF174529FC3E86716FA8
-:10985000292CC922DC417CC2E90E37BD4B1B911378
-:1098600067CA47797A99EAC78C483795C77A0798C3
-:10987000CAE3271498F23D8AAF36D5EF396BAC298D
-:109880009FACDD68AA9F5231D59437F8588AFC24E2
-:10989000FA2CB9C5D4BEEFB25253FD345FA5A95C12
-:1098A000C53B9B3140ABB7252711CF81CA9F8CD5D3
-:1098B0004B43DEE3B508CBF0CE776BFE335ADECBFD
-:1098C0009910B980DFAFC96CFC99799EEA446B2C82
-:1098D000A5D7BBCD7CB128C99C1F17B94F81DF71BB
-:1098E0009CCBCC9F5396584DF91FE5EAFC344FE4CE
-:1098F000B1DDE3BBF0AF0D30E13F144E440FFC7E11
-:10990000683B9DEF3ECCEBCD327E0F077E93E0753A
-:10991000C06F120C07F84D82F3F09B04D787DF2449
-:10992000B81C7E93E0F22187CCF81FD662C6FF55A3
-:109930001F99F16FD06577781AD96AA60FA1299A75
-:10994000F22D78BAE694997E42F1731D895BB109D4
-:10995000C087E209B87F38BE5686E08BF0C3F73780
-:10996000DB7B47317E1ED7D7756D6020DF972E3A9F
-:10997000A40ABC6F63ACF371FDDC3F6DD51A73892B
-:10998000CFFCCE5D90043E769D907EDBF155164F68
-:1099900080BA7F20649CD929DA43A83F2BFE52AAC3
-:1099A0001D74D226DFCF7B0E7C79D895F1B23E12A2
-:1099B0004FF8BEF6CF54BE2775C4D2A8808FAF8EA5
-:1099C000D19E009F9997BB84D79B248AB72F405C78
-:1099D000D47F85A5223FB7AFBCC72D725BF9FE8946
-:1099E000C127E7A6C8B8A92DB9BA7FDD23E3A79E92
-:1099F000C995727794C7C571DE25B9F27E0DA98B22
-:109A0000A97307013E879DD980CF3A0BBFEBD98A56
-:109A10007BE4099DF7C8210F43FEECA3CB7FF51F24
-:109A20003B1C5847F67A613A7FFBFB1DA6F8E281A2
-:109A30005B5DA6FCA0A62453FDC1BBDCA6F2FC40E6
-:109A40008EA97CC8218F293FAC6584A9FE551F795A
-:109A50004DF991AD134CF5AF39556CCAA788B6478F
-:109A600001DFBE8AB4531CCD4D97FAB95B70DCE4BC
-:109A7000DCBB63E57D5FDD7E61C8FB46DCB9A6D358
-:109A800075A81ED1D72EE5E8FA6421F54687AE1FEA
-:109A90000AB33EA1E971E31DF7587CE6B871235E75
-:109AA000BC43EFD0F58A8E7B349DF1E2DEE078F1A5
-:109AB000B9615DBF1F7D5EC77BE8FCFBDAE57AEB31
-:109AC000EFB4F3BD1D635EA1F349C99674BBD9D150
-:109AD000F5BDAABFE54AFB466B66F125D0FD1336FE
-:109AE0004F2BFF6D842BC6F3B4225EB7FE1776CFE3
-:109AF0000AF7778F3777B05CCF1C8B65DE945C8E6E
-:109B00008B33FDDD84884192BEAD8375FB4AC878F6
-:109B1000736364DC9A88B1BB41BFDD8F27E1996430
-:109B2000170D7CFF4BBF67F1E3354DF7A1688EBD84
-:109B3000517F3FCE6F033D4C1C4BF2593EC9135B26
-:109B40007A3D144972CA13CBAC6C9F8A7BFE57379F
-:109B5000FBFA75DE9FE94BFA10E803B20EF4A80792
-:109B6000F25429B70C92EB2B52BFEEB8E7C07E1827
-:109B700021F4F34370BC4F17F4C67468ACE3DF758F
-:109B8000EFC1A0DB503819FAAFD0E33BFB19F3D299
-:109B9000E167EC07037EC6FD13F76DB6E24D917CDD
-:109BA0008F6502E2E50CFC6DC993F6C6053A3C50A0
-:109BB0000FFCA8BB7A456A6E0CECF7EDC21DE3EA18
-:109BC000820E3BEAFF9BE062C0BFBBFB6DDDF1870D
-:109BD00050BEF05DF7DDBAA3D37FF6DE5B109F9039
-:109BE000F14B3A5EFCFD2C1C17707794793F3F32A5
-:109BF00048F2899183F4FDE423FDD6CC2F04FC0FB9
-:109C0000F52B559D5FC8F3BC24AD98DFAFC6F98A2C
-:109C1000FB5BF3374AF94788E2C4AB87C28F6FE337
-:109C2000FBCBD77A05DB6D4A1B153FDEF92AF175B0
-:109C3000AD0FB39FCFCD7207BF3BC8264D6A5746C5
-:109C4000EDF6A55DF9CEFAC248F9EE60E8FBEA0B45
-:109C500075BD192F6A60DF86FABDEE19A4FBB13C11
-:109C6000C2C3F29C1ED750A1D7E9A037BF7C6F0EAC
-:109C70007A32F631A51C1F67C0CD0D3FD490CE3C83
-:109C8000C1373C07E77983B5CBF8C50EF81A7EAB30
-:109C90000EBFEC61BE27111A8F71CE7720BA2B3F11
-:109CA00098E11FEB6E1F74F8C7BEC3EFD61E69891B
-:109CB000C6DFF169DF26DF67E9F45BFD65B8CB221B
-:109CC000FD5331F03FB5EAFD898D795DDD0FD59605
-:109CD000EFE43894668BB67310ADEF2CF58F777B7D
-:109CE000EF89DC9F88771126EA76A92BD7ADCBCDFB
-:109CF000A314E98FF6A98CEFF609F25E3DF15181CC
-:109D00007D67C44F4C118104A4861F4A5B3D92E1DC
-:109D10006FF8A14A0223799E33EA17DAF0E468EB80
-:109D2000A3771585BB3BFD53AD7D645C54777EAA5C
-:109D30006997F3B9BFE997AFE17E3E189426E5B67F
-:109D400086FB6E039D0DD82A6C5867ABADEBBF4BFD
-:109D500051A8F3AB12E89A3D82E2AD962BBC2F9648
-:109D60002AC288BF623E6FE42F35EAF92299BF7D8F
-:109D7000A5CCB7EAEFA76DD1ED20582752AC077AF2
-:109D8000F936DD4E827520C53AF01D7C0D79F0352F
-:109D9000E4C1D790075F430ABE86EFA5A2381576C7
-:109DA0005BF8D30A83F607FC6985417213FC69C12D
-:109DB00079F8D382EBC39F165C0E7F5A7039FC6929
-:109DC000C179F8D382EBC39F169C873F2DB83EFC28
-:109DD00069C179F8D382EBC39F165C0E7F5A703944
-:109DE000FC69C179F8D382EBC39F165C3E6F996220
-:109DF000F2B7CDD3DF7F285B1FCFF45198511C9B66
-:109E000047F8FDEF887FFCC4960E3C372F02DD2E0D
-:109E1000AD0EF7483C374E9078B70889E7B6D98C35
-:109E2000E7BBEC325F24E3B443E9077EAB429BF42B
-:109E30005B2185DF0A29FC5648E1B72ACC947E2BAA
-:109E4000A4F05BE13BFC5648E1B7420ABF1552F86B
-:109E5000AD90C26F85147E2BB483DF0A29FC56F8BF
-:109E60000EBF1552F8ADF0FD08CD03FE2B635E90DA
-:109E7000F3FB99F452A243935EEA32E521E707D758
-:109E8000879C1F5C0E393FB81C727E701E727E70FC
-:109E90007DC8F9C1F94983DCBCBF20EF07B783BC9B
-:109EA0001F9C1FD4E87B03B6AB491B2EBC8EB43578
-:109EB0004A7942710931352F7326FC8BAD4E253519
-:109EC000D623846DF980998594D7F438C73CD16640
-:109ED00001BE39AE80F0A60504C7650FFA7FC95CE4
-:109EE0006EF8B3F987F09EBF43B0DE50A3DFAF3505
-:109EF000DA7B844B456AD4EFCC775D2F747CA31E4C
-:109F0000F3CBA0799062998F7893FCBB220B70AF52
-:109F1000608B4591F1B82B643C74285DADCA93E722
-:109F2000FB16CBF6FDE1885329513CB8EF9165153E
-:109F3000876C0580D392027EF72A2F565FD792ABAB
-:109F4000118765CCDBB04B129FE07B86A3DA84BD22
-:109F50009CC619FD85B0E3EF734CB44B7902EDA0BC
-:109F60006F0EF429DE4D41F4BD2C4F9E7B9AEFB667
-:109F7000ABCBE9FBC06D4BAEC6FDC589E1B2DDD30D
-:109F8000BF8966384E6E50F89ECEA86DC28BFBC955
-:109F9000CB757E3A709BCB5ECEE3BAF8DEA3D16F71
-:109FA000C98654BEA759225A0B710F450C55F83D6E
-:109FB0007C036EB4BED7B1BE2CDA2AB02FFFE0FB13
-:109FC0004F242E7E9FFB4FA387C61621AE5034CB65
-:109FD000F742270D2D59D983E6A5F9E57BA1A3BF4B
-:109FE00058F206E79F92EF8532F90CE7F9F179987C
-:109FF000ED53F8FD95C9BE8D960437EE652FB72554
-:10A00000A2FE36E1815805F508F78A8D75E58A16B6
-:10A010008B5301BD8803F141F4479C633AE825DF87
-:10A0200063E3F759A6585D36F01B43CE2971C9B1D9
-:10A030008BD451317CCF32444EB8D4D083E3627E8E
-:10A04000789C4E3BDFE75FBAD3C97285B65E61BECE
-:10A05000793E5FC6BB56DDF6E1704B7A679CCE99C0
-:10A0600034FF16BC037B267D7BF40885E588BD792B
-:10A0700004D7A30D2FF13DCD92956FF03D944B0D7C
-:10A080000F45CBFB6CD2FF52AEC3CDB03BCDD7F169
-:10A0900053AEC7691DAB93EF3AD339CCEFAE5C6AD0
-:10A0A000B0B19C112A2F1AF2A7F11E9110AE3FC237
-:10A0B000CE53D160E33BC00BD794AC4A1257CA9140
-:10A0C0008B75397351838DE3B22AF4F7D442FF6E56
-:10A0D000CF623D1E6BF156F3F74FF242E450E37D41
-:10A0E0004DBD4EC9DB0766B03CB4C4C6FECD39CB0E
-:10A0F000A57C24B60B3FEE93CC593ECE82F766E6A4
-:10A10000ECF47A942EE8E95D5D4E9AD8EA64F84F53
-:10A11000B91CC1FC65EAE514CEDF7C3999D3999767
-:10A1200065DC2AEE22816E5A8BE43B07EFEBF2D11D
-:10A130000CC4B1C6433EEBC9F4DD4EF48D21F2747C
-:10A14000BE35C0AB1C807838D1A6AD449CECC48D24
-:10A1500082EF834D821C45FDCF825C158FFD9156A9
-:10A16000C4F76126287CBF68D2D0DBF4FD40FB43F6
-:10A17000303FE1F757B4C2297EC439CDD2B65B80F7
-:10A180007F635F68BEA3FC5EEA249F62C73B929A2E
-:10A19000AE6F1B741FBA3FE646E876B2486907EB1C
-:10A1A000B09361B27824C9B76A26E4D3B9B06DF62A
-:10A1B000D20981601F952BCB7BFC76D5CC069241D2
-:10A1C000FF55FBC91C8B45DE3F233990EF0B88966A
-:10A1D000A29E942F59A314403F32E6F5B967EC389C
-:10A1E000CFB04E3A28EDD8A7F21EE5D27B324D7E95
-:10A1F0009BD0B48CE08DFD3437A6F5270A6168F456
-:10A2000060E12D1C81F7EB85F1285400F198B7E847
-:10A21000F9EAC13BFFB43A97E1C4F991BF7D68A662
-:10A220002FF25FE09373146BF0DF1B4BB268570D96
-:10A23000EEC1F750C703BF11B96DFC9E444AB64B3F
-:10A24000F2A9107B4BF56089C750BB4B59AE3C77E8
-:10A2500084D59D7A2BFB7BDC6CB734D67DCC66BE77
-:10A26000E76BA4F307EBE75EDDBFE79ECAC316F911
-:10A27000FEC26316FFF657885E2FF7D06660BD8F6B
-:10A2800021DE9EE7AFF1FA8CF74C3AF895FE6E8925
-:10A29000414F47965DE2FB2AA59176B71A444FE5F8
-:10A2A000AB15BE0F5ABA4CDEE7D6562BF25D846E64
-:10A2B000EC58BF99FDBFFC9ED56F7E112E0B75F833
-:10A2C000CEB1B7BCE148EB84EF9F973D60937C34FF
-:10A2D0009089FB0EB72C71F2BBD99F7B8AAB060F1E
-:10A2E000039E3C8CA771D8E5547F4B8CB604DF4BA2
-:10A2F00045CB41D81DE7FEFC6D7E8FBAB6398DDFA8
-:10A30000BF2CD995BF0AEFD97CEED17E82F5974458
-:10A31000BAEC90476A1A62F97C9EDB53BFCF2BDA06
-:10A32000D8CF67E0E7BEC1D28E777DBE1CE7A2AE74
-:10A330005711C06C534CF5BAB6631AF6D1503B4B6B
-:10A34000E8BB21DF655781DDC41E645F35EC32B6A2
-:10A350009C63B371AECFB177FDF73EF7EAF337F404
-:10A36000DAF91D7A6DEEF89E90FFD72A2ED8D3CB5E
-:10A3700023DD3371BFA1FC900D91B462629C5BBE82
-:10A380001F738F7C3FA6F48E7CE66773809302DC9C
-:10A390003B19C9FBB8DC4FE990EEF7FBAD6B0FF44E
-:10A3A000D90D7A0A78F91D827297D71E17241F9546
-:10A3B000352AA677248CFC0B8355C99748DD00FC11
-:10A3C0007E7C479A1D6F39CD213109F1997B412758
-:10A3D000C33ADB513D8E3F99982E0ECAF7BD14FE4D
-:10A3E000BBE4182FF8EF5B95369ADFC3A0FA2CDF99
-:10A3F000ED1A1CC5FD95B868DD69485D3C4F8203C8
-:10A40000C3A9ED3EEACFCDE3303ECA027E1BEC0786
-:10A410007310F742F95B5C7E1BC6296D90EFD46820
-:10A420006BE438DAEA58FB20C8075697BD4FB05C9A
-:10A43000D820DFBD9EA3FFDD119A2FCBCDE50427E9
-:10A44000DCB333EEDD86C2AB449F7F7963AC59CE7B
-:10A450006C5C6B037E6677F35EC639DD0E5DDA30C9
-:10A4600086DF3728B77AF9BE8AA6C3FBB3DB9CF731
-:10A47000C25F327BDD23B634CAFF65B0946BCFE98F
-:10A48000FB71627A2093DFA9BACDC9F1E3B35D8D88
-:10A49000BCDE0E783F44F081DCE22A6678139DF83A
-:10A4A000106F59BECE8CDFCEF944C977FCD795F03A
-:10A4B000FE5B60D5ECAEE079ACDF9789F8A1D9B44A
-:10A4C000EFF10E9770697C1FF6C44333F9EF056214
-:10A4D0009E1CCFE6718FC7BB5344374CD706FD187F
-:10A4E000F7F38DF1AC1EABB4C77BBE6B9F7A0F4206
-:10A4F0004EAF277CC30FD0DD3EB5E302268D6B2F18
-:10A5000097EF075EC1EFF4FDFAFF016A916CD3008B
-:10A51000800000001F8B08000000000000FFED7DA0
-:10A520007B5C5565BAF0BBD6DA57D8C0668BB051A4
-:10A53000C00D0262116D10101575A1805B736A6306
-:10A540003729C48DB7500191ACA89FF3B10D6FA905
-:10A5500095262A9675B6A68D957570B2461B9BD921
-:10A560006A9A5D0F3A8DD33953B6CD32BB09D234D6
-:10A570009F7DD399BEE779DEB560AF0DA475A6F9CE
-:10A58000CEEFFC3EFCE3F57DD77B7DEECFF35E7630
-:10A5900022634CB23136789883B1818C1918934577
-:10A5A000C83FA177FBED02639571ACBE2D13D22895
-:10A5B00056FF6B0B63DFE3DFF89E74A253642C8FAE
-:10A5C000B1DBA05D1B7CAF10D9ABCCD6F33DD3295A
-:10A5D000D0F78A1436D31DD41EFBC37EE3D5EF1308
-:10A5E000FC698B337BEAABE356D878BBA9D07E9A63
-:10A5F00005EB8BDDF51BA83ECFB3E92691C53236BE
-:10A60000DB04FF87A594487B56C4E632D6B057706A
-:10A610001AA1A8E14189B118489F8BF0B164C6BE68
-:10A6200068F8CD3BB740BDCF376FAF64437BE635AD
-:10A63000C73F8A39463036F75236730C606CDEA558
-:10A640003194560FF364380706D5DBF85CBA07C6B9
-:10A65000BFAD2DFBDC7F305AB79FE530F6FE73BFF0
-:10A66000FDE368E897319FDE7D4DCF3A66AD3EA1B0
-:10A67000AFB204C38DAF734D4657158379CEB6186C
-:10A680001C1214CD5E5EC5649827B333671AE413B9
-:10A6900075CC2B42BF6CFD16D904EBF330FE57B5D9
-:10A6A0005C90A95D63BE4F82F50C867AC61C5EDFA6
-:10A6B0000CF0F7580C678448A8E82D910319BCCD1D
-:10A6C000F7293DF81D0CA921A707EF890A1DCC5ECB
-:10A6D00057066D7BF0050333960FEB651CAEEAFC65
-:10A6E000A72AF3BF6DBD20FBA0DE0D4E07CF572775
-:10A6F0001BE6C17AE7AC4F36CC86B45CF95E3E47C8
-:10A700005BDE8D2FAB8AAFCC9576584F571BC75762
-:10A71000D73A3DE1AB6B4F2F7C2531A9671E7700FF
-:10A72000BED8008E2F3682E30B53C057A5332FA817
-:10A73000DEBF707CCD7EFEED0F5E76D0FAA8FFCE38
-:10A74000078DBE1DD0FFACB6BD84B7F2D51BF4C9D2
-:10A7500050AFCE994C7051DBCFAECFB63280E76DA3
-:10A76000ABB7EB1D16FCEEE893EE219559103F4177
-:10A770009E099067BA40BC3BA2A77E39A47B619C2E
-:10A78000258BCD91ECDA9E71B628F43CBB3EDA867F
-:10A79000E3CDAEAF7A886571FA7767F6E6BFB36648
-:10A7A000CE17B3A03FE4CFB345CE24E48B0A51D4F7
-:10A7B000F09B9A3E847883793D06E03523FEC3DB27
-:10A7C0009E46380C5E14E66C864FA9A9011F8E8B3D
-:10A7D000F48CF33688CC6B827AA935818B388F5410
-:10A7E000A0286C8769848D52160BF91D30ED024844
-:10A7F00053249EEE73F2F5C3773F7E6731813C5C54
-:10A80000BF4ACFA1F46A603B57A700FE0D31CCD9F7
-:10A81000ECE8A14FB51F953E55FAED6F7D7BAE700C
-:10A820007D6793393C598633C904E3563E3CCCB925
-:10A8300046B8FC3A0D61000F5BD07A81580B6C7DF5
-:10A84000AC3735905776CD0FADB7A524B68FF586CA
-:10A85000AE53E5933926CEC3C02751019877D7FA76
-:10A86000A1510CF12D302FCA9DB38BCD22CE5B5D53
-:10A87000D7534D5019E6B6BBC944E9334DC068C340
-:10A88000003E4D76CA3FDFE4A0B4AD2983CADB9D0C
-:10A89000369A3F6381886980A78A3085FFFD3C8FA7
-:10A8A000E56541E5536D9CEE4E5B0311B62039FD25
-:10A8B00071BD790D8B42FA0E3C88FCCC1A87B25DD3
-:10A8C00030D4E9F56723C44CA44F3E3FB5DD127D7B
-:10A8D00027C93F166170EC02969BB124FB7423E0FC
-:10A8E0006BEEF2382790129BD13894E4C20C6FB40F
-:10A8F0009300B07E0B4378CC53E460F892AA952382
-:10A90000B17E6BB2558071E65A9CE75AA9FDD5CE4F
-:10A91000FBF17B4B99212593AACA26906377287275
-:10A920006C89C0DCC88777A09C44FE120FA5A2FEEC
-:10A93000B9A355F01B29CF560B00D721CDEED27805
-:10A9400094135B05E70E6CBB0DE4A9A9479E760D39
-:10A95000737F817A817D07F407FD5F252002715D99
-:10A960006D721CCAF14D827517C379B90D089F0528
-:10A970000A9D9C6E3913E1C8EC81EBA3F85F10656A
-:10A98000CC238B286F1B143D86644079454E0E31D5
-:10A9900070F841CADA113F3AA709E9A0CB9212C573
-:10A9A000FA286F884889C3F239AD12C945959EAA25
-:10A9B000D535287C3317BEA3DE2B912A6291BE5673
-:10A9C000B64CA474CE8692CD5EA0E324C11D3B9A02
-:10A9D000D6A367B89E39B513AF47BC55EF30469B39
-:10A9E000006F497A6F524E103FCED9BE2A8941BBC3
-:10A9F000F3DBCDD351FE175BCB8AA3A1FDBC6DD198
-:10AA0000D952901E49CAE67A6441EDC43806F0ACCA
-:10AA1000F9FB9127ACA08FE7429F56E8FF9BB670E9
-:10AA20009F17AAD434ED4F9280E7DE3179E2B3A1CB
-:10AA3000FE42F1E02DA3501F08BEA7E2A9BE23CE1F
-:10AA4000DA873C50D373C00F0EA0F7DAFFF51EF57E
-:10AA5000F395F8D6F5E5D0BEA6F68548EC67E1A6F5
-:10AA60003FE45BA1FCA0E849C3FE3F17B63F654544
-:10AA7000026CDD9E857A7CEEA6B4284F1FF217F992
-:10AA800000F151BD5F20F8AAE5337C510684BBC7B5
-:10AA9000CF0C564CADCC80F47E5E628D680FA8F66C
-:10AAA0008C5A3E329BCBADF351EB93904EE63FB5C3
-:10AAB0002509F5CC67113C5FF1D4AD6FA0DCF2EC59
-:10AAC000341A10AF1E1D3338519F7941BF221D55D6
-:10AAD00003FFC693DD61AE047A2ACA0E27B8CE6F93
-:10AAE0001D41FA519D177CA7F2CF74CC85F318D283
-:10AAF000DC998D74FF679D7F2EE2F3CFF566A71773
-:10AB0000F199CDF5DB9FD74BA558EE0586417BE447
-:10AB1000CFEB5F8848B5F4D86F25D2FBB28476D6E8
-:10AB20008B4236EAEDF0CC76C32CB21B18D1599D7E
-:10AB300095D359C3017DE9E018B2C7A8A446E73709
-:10AB4000F485AF058ABDD59DDFB7D7807C52B3872A
-:10AB5000DB11356D67C88E50ED925A859F17EE391F
-:10AB6000437685DAAE6E1F874BED3E5E5E9501C87B
-:10AB70001DCDE5800042BA0AF105F9FBFEF5D7D3F9
-:10AB80009769F27B297FDFB5562E0F759D49A8B7CF
-:10AB9000D6649C3420FE6B972BFD425E1F34DEBCD6
-:10ABA000EC81042F2C1F6AC1F60E8DFD50BB2F9A2D
-:10ABB000DAFB6BC356A3BE97EB2C3A4C9B6B2DA4D0
-:10ABC000FFB7D58B19BA5C9C5C9813EDB983619182
-:10ABD000592847072E3C650648026A3B8F8850BEBD
-:10ABE0003ACA732FD2671C03AE90506FF805B45F5A
-:10ABF0003B5EF97404F63F6E48E06B0653D70BBF1B
-:10AC00009B5E0CF26419982D641F670646201D0F89
-:10AC10003CCCE5F4E37AB61AF51BD3B9D93428F75E
-:10AC2000A3DC423C7F1BE6DB05FFFF1DF30FC6FEE6
-:10AC300099C93F14DBBDA4D0A7DB68592DC0BCAEB9
-:10AC40001EEA59834BBE41D05F932D220EA434AC33
-:10AC5000D7A1E7DF557B758222A713C18E40BBC801
-:10AC600030C86E413A6E36F3F509B2CC1A611EF760
-:10AC7000671E9E8D7A7A6DA78919619D133AC3C8A4
-:10AC80007E4D1CE422BDD66C4E22BD2D3874AC0224
-:10AC9000EA1FCE14FD3AACCF4C3EACCF4C2176AE81
-:10ACA0006896B19D70F0B56F51BE0F962E1E8982C9
-:10ACB000F50DBE477036439DCAAE738FFF1BA415BA
-:10ACC0009776ECFD5748FF2DCAB313E17ABACB75DE
-:10ACD000C603A85B6B6D3339B9DE60C1EB3878EF22
-:10ACE000B79136B1677E1D9DE79EFB4D2EA62627A8
-:10ACF000EA9F090725D21FA1F3E9B0C3C487523DDB
-:10AD0000B23B3B2CA24F10B0FE91F7707E134C1655
-:10AD1000BF84F6BA49FF65B07E618EC4E87357936D
-:10AD20004A61DF8391108B93477D74D14276EB3873
-:10AD3000850F553A7B2B9BDB8F6F297255853373BB
-:10AD4000C82C58AFA8F06CD6ABFA2210CE327BF8E4
-:10AD5000769152AFEB9228931D5E6DF431E8B2EB21
-:10AD6000E050D233FDC9D93FA0DD01F6C4F254F959
-:10AD70005D842753F4EECD0AFC54FD2D29FDDFAC94
-:10AD8000C0F1668BC8E1765308DC147A0AA5971ED9
-:10AD90007A8841DBA31BCFECBEF6A351C984DF6BDD
-:10ADA0001EE678FD90F0FAED5B2B80CDD8A0BF4D6C
-:10ADB00021FCFE0C78F58BB93F02AFEDA178F59B35
-:10ADC00087215E37896467A01D8876A307E5C0B533
-:10ADD00094E7F66006233951298539D724E3778033
-:10ADE0004316C987A3281F54B930C415B806F5E91E
-:10ADF0006970E5717E01B18D97E7A4105D24B0F60E
-:10AE0000782C07BCE7A17D279986667E0C72B7E592
-:10AE100001DFDEDF403FCD826FEB3C988FF7668B22
-:10AE200013EDB70E9FE8D5C33C5AA259D67E18BF82
-:10AE300065FE554E2F9633456E4C37F8D07E83EF26
-:10AE4000498DF8BD9C7F7FE9EF671F44FBAC338DD4
-:10AE5000D1BA5AB2593ADA672D6519F4FDB7AADCAE
-:10AE6000793082B72FE3F4DD32DFE6433DF4E8A327
-:10AE7000BEE1A8275AB6CBF136480D519EF81C9872
-:10AE8000FF2089D37D4B329443BA597097CFC57E4A
-:10AE9000AEE1F30D94873DFF1474654E05D106E5D0
-:10AEA000A71B2376A05C55E974F0302EDF8778CF9E
-:10AEB0006C45387927B08C7AE8FF4385DE54F80B6F
-:10AEC000C0368D00F798103CA87417A3C05F58CA0D
-:10AED000E9CF3B41594F1DF3A1BF910053090738FA
-:10AEE000571AC1F0837496D5938DF36F5E0CF89169
-:10AEF000701D1C0FA74556DDD6075F15E628F10D1E
-:10AF00001802F9A69271BEA944BA427A6C04BA0A30
-:10AF1000A2471648883E17AED015CA8308F7B81C5A
-:10AF200058E757C21FF2B1F0ADFF94A6F735CEA493
-:10AF30001C2E2F1E337B4A7348EF4DD0D89D6F6572
-:10AF40007F9A88FAE5F4BDAF25609A14E59E8CEBF4
-:10AF5000D85CFED75214FF1FC607F4B88E0FCBFF84
-:10AF60004F22DA2D954B5F23FABFD2799699983705
-:10AF70001CE01E5D2C38FD00BF792D46E724F81635
-:10AF8000575C750CE159D66A74189156D8628D1CBD
-:10AF90003B2B8F40378A1DDA6A24BA39F74B89F484
-:10AFA000C1B9928BAF0E800FE756084EAC57D63220
-:10AFB0006C2590372B2916A85E9957A07A65A91C95
-:10AFC0005F271A05A23740AF253B28DE31A7F58E53
-:10AFD000A988DF13C55F0FA4F8C17A1847E5632E6F
-:10AFE000DE489E9529F5AB561B9147BBBF97B5AC84
-:10AFF000BA88FC3FD31B52DE3AE953ECB7AC515B45
-:10B00000EEC635821D77574E440CCA07E664CEEF74
-:10B010001148F240F20FFA93BB407144CF300FC297
-:10B02000C389BC617AA4EB990857A0DBE8A57CDD55
-:10B0300033A70ABE49B0CE9916CE671F9609BEFB4C
-:10B04000053EFF0940EF65501E0B745D16C3E438E2
-:10B0500048DD26E60FC7792E1DF609CADBD338D4A2
-:10B0600028AAEF8FB4A15CF7E81189B7322FA5E5C4
-:10B07000CC47E9EDCC4FF398C13A937490AF93FC71
-:10B080002B318EF32BB36703D2D75F8B4E9C16E028
-:10B09000FBDD3942DE2894438D0368DD975B1F702A
-:10B0A000A5807606AA41AC5F96E37E14FBB3CA4C3A
-:10B0B0008F71AB74958E5A993715D617BBDEE29B0C
-:10B0C00004EB8B6BF51CC2F5A64F373810EF8313DA
-:10B0D000F83A1374DC9F3F546E60A3810E363F181C
-:10B0E000E6433ADBBC3520DAA1FEE6038001CC97CB
-:10B0F000AF14BCF0DDEA614E8CD359751E11EDFE24
-:10B10000A2568F1808E2A7E1B241443991BED32379
-:10B11000A29EB45AD7533D355FACD44F3779065908
-:10B12000C94E9E4EF4335CA11FB59FD456835F0475
-:10B13000B817C94A7D99B757FB618A9E56DB6139BA
-:10B14000D2677AABA34F3F454D5B503F838FF808E2
-:10B15000C605D27BCA1F71FDDA84F01B78F3AB36CB
-:10B160004C370321F8711C9DC74CE379F83CD3158B
-:10B17000DA87BFBF7F8FE3631EF0BBB9F5FE22E421
-:10B18000A3CD001FC4F3E69DB3CCD4CFF4599A7974
-:10B1900031A986F22508074BEF753CA2CC2F3DD58F
-:10B1A000235A69BDCE4368E7A5CB8CE2016A3F769E
-:10B1B0001D7405F46A777A857ACCCB905A94B84797
-:10B1C0003A8EB34E40FF315DC157496BFD6133F696
-:10B1D000E366145F4CCF85FEA1FE268483A137FC75
-:10B1E00042E7995ECCE77342A9DF8EF194746CE775
-:10B1F00058114374C5E7D7D5EA14621C97B18FA0E4
-:10B20000FDC9907E9EC2B80CA4CF4E7E6D4A2EB46E
-:10B210007FFED19776B4D0520E3EB30FE556ABF514
-:10B22000E69B709C83229FFF4D72E25D98DF6D204C
-:10B230003D9ABE534EDB44799313FDEBAE56DF557A
-:10B240002F42BD2C18C664EB3D8F130A9CDA153AC9
-:10B25000383979CB205CEF5345772C5802ED875F66
-:10B26000F7388D3B7CCAFC9416C80F9BF8CBAB30EB
-:10B270007F5F8EC73C02E4FEB0D25FDEB60FE56AA8
-:10B28000E9FC1C8297C57645F2A939DAE3F502BFDD
-:10B290003747DC528EFCB8D26670482477EB19FA37
-:10B2A00059CD1177DBB1BFE5D1F9264C0DD6BF36AC
-:10B2B000A19C3C6EC931211E9A2D131896EBAC0A45
-:10B2C0009EBE1B4FFA40528872778473BA4C74E565
-:10B2D0006428270C0906ADBCD671792FD91D3EB460
-:10B2E0009FBAACF54881CC600954A07C935479692D
-:10B2F000717A713CC9E2B4A3BFB44291372C86AFD6
-:10B30000D36039F79F38AF5EFD632E96504B7F8632
-:10B31000B0CC2841F93FDA9BC6103E575383C5BBDA
-:10B3200018F544687F5D2070508EA34F4776337EBA
-:10B3300048EEDD5EB21B347AA45B5E7AA2F521F2A0
-:10B34000521E817AA2582079E961EB0CB8FE120CEA
-:10B35000B2005C3CDBB85E54F97B26CE05F0E549D3
-:10B3600065915C5EE9E473260EC6EFD1AE5C2A45BA
-:10B37000221E025EC9E0E9C39FF778937F501E9DAD
-:10B3800041FA87A90790FE21FD44E10F8F8A076FDC
-:10B39000D9F5A3505FCB12D90395CB8536B4CFE254
-:10B3A000BCD14769BEC5DC2E6897BFA6F51C2A89AB
-:10B3B0004B44797962D999C7EF41BDBE299CF4FF0E
-:10B3C000A4A56756603C6EA657701A21EF591A7DE6
-:10B3D000F77B986F343A5D903FABF081FB974591D6
-:10B3E000684F08B8CE8C9E75561632839BE239F1B1
-:10B3F0003396403B4FA3E0343B7AE0A1C77A52EF4B
-:10B40000F505BC3746FED0FA3FBCD7A8C859773EF1
-:10B41000CAD9A2C6E4870A705DEBF57C9E8DD1D7B0
-:10B4200053DE27393976B91C9EA9D83F9EA5B3575C
-:10B43000C6C3F7C06A41F9CEF156A9C8E540E38812
-:10B4400063183F0D2C17483E79BC52A21FDACD5C21
-:10B450009E4D78EF280A905DD8E53DB4925A2B7244
-:10B46000DEA37436178C58946FA7DFE3FE9F47FE68
-:10B470006325B69BD3A2B5832602FD0C40B8BC67FA
-:10B4800026FDE9F196D1BAEFF04569EA55AD8ED3C4
-:10B49000E43DAB8BAEC7B0E7AC7B27523CAF9239F3
-:10B4A0002291DE2A656E37C19F251BE633579D4FDB
-:10B4B00031B7C72A8BC17EA2EF5A7BB0C7FE893352
-:10B4C00020DFA87854F1133AEF5E7619E376D0AC1A
-:10B4D00075DA7ADD761030168ABACAE5DA76BF32C6
-:10B4E000BB9F45B9E8DE38E01BF2ABAE501E828050
-:10B4F000217F6E26E3711FA6E843D5CE2F597A51DE
-:10B500008F726866E3453DC273E6D21FE6A75F38D7
-:10B51000B5F3BEA1204ABB3E394E93BFD13544534B
-:10B52000FF66F730CDF75BA75FABF95EEE19A9C9EF
-:10B53000DF5E3D5E537F46FD24AD1C7A379AD6A36D
-:10B54000E2A7BF79BFA5E8A37742EC12359D3AE2A6
-:10B550003F1391BF3F2C67E4BF7C7833D3F8311D94
-:10B56000232482E7805C3DF931F7E5C8EF8F20BFE7
-:10B57000C94FF4A1C2F34373A1C928A27F62E47E3C
-:10B5800079A85F729039505ECED4B1FD42548FFFDE
-:10B59000670EF39CC7FEBAE30D4B0FF17843881F8B
-:10B5A00073A578FF7006CCBF0F79794D2EF7C316BF
-:10B5B000EE36AFFF38088EB56DD19AFCA2FDF1EBE7
-:10B5C0003F0ED63B4B041DAEB346E1935A16A07D09
-:10B5D00052BBE8A0FEEAC4402CE63B58676CB4F4CA
-:10B5E0008F838B0A0F808F253728DEA9FAC33F1976
-:10B5F0003E450A9ECBB4701A93CBE3905F8F10291F
-:10B60000DD9C23C7E7FE03F11CB49EF4DCBC7FDCA9
-:10B610007A2247C859089F9F1BAFDFE31E0F94177C
-:10B620008E900B7F26B84CFE47C2A547CF472FD838
-:10B630000DFAA3729D81FBFDDE335CBF3772FDFE08
-:10B640007CB48FF6879BF344E70E07ED97D23EE973
-:10B65000A17B8D611918DF59A1237D797A99908199
-:10B66000FEC226218CFC360FAB4816C8BEB978C87E
-:10B6700048FD31AA07EDFD3A90F351053E6B09E410
-:10B68000DFCCE571B1356E714A8A03F5F61FAC1E49
-:10B690008A8B7AE2111E9EFD30E16B69DF45EE2B4D
-:10B6A0007E12D06BE5D112858F5FCCD5D13A1F2E9B
-:10B6B00014B99D942ABA701F6315D8A968570696C5
-:10B6C000EB285F91C7E9596DF71F0A9DC794DD14F8
-:10B6D00086F388DA24BA7D7D8CFB512E8F0F3D795D
-:10B6E0005718EDB3012A7468EFDBBDD6692E58AF49
-:10B6F000BDD0968DB6DFDADC68EA6F4D469715CF80
-:10B70000A1FC8C7478CA8EFEA0C0FA8C33CD55E6AD
-:10B71000ABEE0F5894FE36E941BFA29D2298281E39
-:10B7200061F11AF9F91567B126DECA1C020B6EA782
-:10B73000D6F328F46AC7421BE197F6EFD578B15DDE
-:10B74000A117A41BC4BB4ACFA1FD8389EC8DCCE912
-:10B7500089F3D915528E1AE5D98D748FFDEA901FA1
-:10B76000BC5CFE076EBEC4E32CDED7DEC37988E185
-:10B770005F529C0CEC4ACE5F4B43E2BE3F914F02BE
-:10B78000660ECF4084561EDEABD0C9DA7F82DE481B
-:10B79000BA02BC3E9CCBE58FABC0FD36CA3BC7B2FC
-:10B7A000D430A2FB1F0B2796604538515EBA723821
-:10B7B00079F33D1F109E74CC6FB4717F0BF9E17269
-:10B7C0007CA4C23149649EBEF4F2883CE5FB1BCAEE
-:10B7D0007EAEB76AC80FD9612877C502C6D22CCC15
-:10B7E00061BCB6FF7A0E9C8F85E86A39D2E5AE96C9
-:10B7F0009430E4CF6465BCCA9BD2A70C77A05F20CD
-:10B8000018D00E04BFC3C0E33FDC4E57E57A4FB9F2
-:10B81000D67EC4724F668F1FA6DAF7EA773C97820E
-:10B82000E3AAF359A5D861FDCD7755124B72A2DC7E
-:10B830005A768F80F0DCB15AD4F87D715E612503B1
-:10B840003F3ECE7FAF13FD8E38B0AFCD28CF75F51C
-:10B850008233085E817B810A381387F82BE04FE240
-:10B860003ABD67895E42C757D7B1AB858F1BE75D8D
-:10B870002CC8909F54512FA0DFB756997F5C05A329
-:10B88000EF69993E01E3219E16568AE3555633032C
-:10B89000C6F52A33995386F2CAC64374DEEDB9025F
-:10B8A00039256F20C94F3A4FE32AF0A4E7011D4D17
-:10B8B0004D28437667B84B86F1897F161DA7B54C96
-:10B8C000F0A2EF59D4E23C84FE01D011C57D3C2D9D
-:10B8D000011A5FE7E571725D8BC1E98075488D657E
-:10B8E000B4FF21551B9C32D43BB629DF8FF1952D37
-:10B8F0008DDCDF0DF59374D6FAD7C3D15FAB109909
-:10B9000044010A792AFA5956852E5630773BEEF7CC
-:10B910003319FE41BB48A5DC5A3D6F2A6622E5D0AB
-:10B920007883DC139F409E6BDC40B2D394AA8D6772
-:10B93000482D2BC9AF33627DA8AC0F897748D5A5B8
-:10B94000141797ACDAF25BF32262088E593C1E9E04
-:10B9500073EF888DB7C27C727F79E31F303D8741DA
-:10B9600033805BFEB23B074C87FF16ACD87823A62A
-:10B970004FBCCEE89CC18FE057668CFAF1FCFAE828
-:10B9800095F2ABB2260FD0B9C2AF7DD2BF1A4F0924
-:10B99000E54F95FE43F94E4DD75E867FD7260512BB
-:10B9A000910F4FDF3B3203DB5736DE73C8C7885F2A
-:10B9B0000507D077A577711123BA605697D05B5EE3
-:10B9C00084370B49ECBF371F3F867C3BFEEFE71304
-:10B9D0007F08DF95098CCE6381FD49F69C9AAADF2A
-:10B9E00023F2B93EBD906724BC4E46C10AAC3B056C
-:10B9F000DAE0BEC778604E2BA47F2EF03C8BE34D7F
-:10BA0000813C9EEF7BFD406B0CAE374BC7F58EA79C
-:10BA1000DB8EE67648B7FFA8D80F59063605EDDC71
-:10BA2000C02611776E59E0C0E73BD6E2BE6BB9C9BC
-:10BA30009906EBCABADF48F484048AF6519668A7DF
-:10BA4000B8E5AEB68FCB699FB1D1C0D2286EE00EFB
-:10BA5000C3736400CFB0AA4CB257C3AC68AF7A8549
-:10BA6000A4AA881E7B08F5220AB42CEFAD53AC3093
-:10BA7000FEAE42B047337BEC1CD5FE599C9F4CEB8D
-:10BA800057ED2068C7B0DD8FE5A74A0B4B22BB19E5
-:10BA9000E683FBF7B64C2690ED1352FFF43223D920
-:10BAA000AF76AF7BCA70B45B97A7E6A0DD0AE39AD6
-:10BAB000246E7FFD3BCA67BB4EF95E28E6E0B949BC
-:10BAC000751F800574D1188753EDAAFEE7A563E7BB
-:10BAD00054B905957F9B2F9FC17EFF5972DD635539
-:10BAE000E84D4D63F879E0E90ABD8DCF37539A9E52
-:10BAF000FFB3DB73A7AE93FE79EBFE39D7E1FA9F74
-:10BB0000B18ED8FF21F8D83CF97FC63A6E99F24F32
-:10BB10005C87375F6EC8CF4379D646E788EC2E7EC8
-:10BB20002E1CE4DE3DBC9CCB398B930964C7FF74AB
-:10BB300079D784FD9D411F1CCFA17877083A1867FB
-:10BB400088A5A188ECCDA58CF681862CE5FB404329
-:10BB5000963A4D22DA03166E270E52ECCE414BB9BF
-:10BB6000DD19A79C2B888B117D32D43FF6CB5BCAA5
-:10BB7000E7C6E0BE9091ECD5E636DDF516D4535E0F
-:10BB800089CE8F86DA89D2D2954A9C5F6B9FAAF6BE
-:10BB9000681AE379FDB2B3B44FA7DAA34394F2B4C1
-:10BBA000A57C3F60488BD61E8DABD6DA8FFA82100B
-:10BBB0003B73A9BA7FD049EBD32DD7E9F1FC7FA81D
-:10BBC000DD897BB0A81407AB7A06B4FE4DD730F6FA
-:10BBD000747EF7F98C1CDC1F9AB95AD0E83955CF1E
-:10BBE0000224287EA4E2E343D473883FF734B55F90
-:10BBF000D26F3EAF48704C2E4FD79C5362EC7E1EE6
-:10BC00002F71733AFAF5EA116BD1AEDDB7EEC63794
-:10BC1000317D69FD9DE1E504AFF5546F7FCBC6EB47
-:10BC200030FF5076BB3D12E6F5D0A853EF09D0EFB8
-:10BC30006A3CE385EBB378298FB6149E8BD0B37A38
-:10BC4000DADFDBA40F4C9F0DE52B12451C91BE23C0
-:10BC50001D9832189D9F3059787EF5358CEEE33073
-:10BC6000E55C9F1A87093DD7B7CAC3C75905F0C419
-:10BC7000733596187E1FA939E1FEE908EF668781C2
-:10BC8000E139398B72EE4F62D5AE2AA877DC7EBFE0
-:10BC90007D16EE0B6718887EA498CE26C493D99E95
-:10BCA00063AFC27142E235CD29E9372059BCB5FBFB
-:10BCB000F09E67207D7BCFC92F319D2AB5EFC3F35E
-:10BCC000255246889FD26BBF9811DC9B87335F4A11
-:10BCD00032963B6E10914E75EB6F9A86FE54C150B2
-:10BCE000E71A584F5802F31B601E61BDF689797B35
-:10BCF000A9209CCED54896F5150DD8DFA808BA7FA7
-:10BD0000C0BE03AECBA7F34DF457F680A8473A0E5A
-:10BD100053F68FC3327BED1FD3FCC2304DE1593B4C
-:10BD2000E4C3157A5F637BCA87FB776B13526E108F
-:10BD30001D3DF5695F19D6BBF2BB1BAB685FFD26E5
-:10BD40009315CF9F8529FBCAA1E374A53A5B67438E
-:10BD50006AB418647316F1550F5F72E0D85383E626
-:10BD600001F5FA9CA73A6E731EC783DA9FD1C264AD
-:10BD7000B42343F7AD43FB817970BE56EAA9FD3188
-:10BD8000D646E70174888B517DB5ABA7B90DDFE9C5
-:10BD900024BB1FFF82E382CC1A43FC35AC55DBCEBB
-:10BDA0009CCACF0DA8F4182A2FA5D0FDF7D47A6F1E
-:10BDB00038E1819F2708AD1F0AD7D0F6F0B7335876
-:10BDC000DEDD60E1FB885DA99DB922AC7BA53D4726
-:10BDD000337F5ABFD0D37FEFFD3C6DBE4C36F6B9F2
-:10BDE0003E94077DCD77824EBB6F596CD1B62F8DB7
-:10BDF000D17E772568F39245E9DF916DA2F31A8E23
-:10BE00007C139EF753F9D818E2EFF78ADF2AFA2E4F
-:10BE100091C9741E7593DE790EE5C4E33340D201F7
-:10BE20007D3C2CF8CC582E55B45B510FC6ADD39346
-:10BE30009C7AFCAE5BCEE0BDA016A06B84E571F7EA
-:10BE4000479B6EC57CB148F10D9BFB7039D251CB3D
-:10BE5000775FBF371BCF9F3A0D74CE5B3DB7B1758F
-:10BE6000AC612B1E0B8ACB94CD69F0FDA12AE68430
-:10BE700099B02363632371FC2DD1A215F5DDF3D1B5
-:10BE8000F5FF8E7194E6198CF61942E15737D246C8
-:10BE900072366E75B680F75B1E1E9B5F8972310627
-:10BEA000FC6594AF90CA7DC517C715F0F8C0B6C53C
-:10BEB0002FC523BE37580FDB699E15A213A7D85292
-:10BEC000C1E57F8B85D13E7BF3A852371E4DEC72C6
-:10BED000C90E3C8BD8E2DE41F35E592D72D9AC9C81
-:10BEE000970158C851399CBE0C364AFD986E34B340
-:10BEF000F839289792C2E87C507FF681B484CB57FA
-:10BF00006C6FCCE9BFDE43118DF1C85CCB67E49F59
-:10BF10009F0BFD6D9DB199F2AA3C8D53E8BBBBDF31
-:10BF2000103DBA1BF04B72361AE42C9EC7638E8705
-:10BF300089B775F5C2B4203AD555807CCDE2E72E9D
-:10BF4000307EBBBEA834E387FC4C9D9BCBE51855E7
-:10BF50001EBBEB9761DC05DAFB515F633F78CE0FC8
-:10BF60005219D7B751A83F447EF30C8303EF39E849
-:10BF70002A400E437B5D82564F1C18C9F135FBC128
-:10BF8000BBCC9EA0384D8C721E66A3BEDE9C06EB19
-:10BF9000D93843746E07786CA96810FA8AC7C455FB
-:10BFA000707E990DF5D16FDE5291131BBC9E668C8D
-:10BFB00073C0D036D70F9FDBD385C8BF5D2379BC54
-:10BFC000BD67DD1CBE71403FA8879A4797AEE66A01
-:10BFD000DA41725567E56D6DAE7A3A07D955C1CF32
-:10BFE0005DAD13F87E82A4C4CB9B8BF249BFF44BAA
-:10BFF0002F152B499F84E2579D3FFDE507E91199D5
-:10C00000F1F119879BB4CE4CFAE107DA3B74F94A97
-:10C010007DD40B1E6D7FBA625136E3F8A85F10AF76
-:10C020003AE6C57B93A1FD952AFC163A1FC969E043
-:10C03000EDB19D8DF88BF4DB6901E0C8E982CEA1FA
-:10C04000B3F7383CB7243A7C6BF8012ED28774AE34
-:10C050002BA5F7788F098E65B8EFE87D5DA2F3E731
-:10C06000A17A4FCDAB7030B136E79C3EEC4D9C0FC2
-:10C07000EA3569A7D789FA01D0978AED362A4B09A4
-:10C08000BBB3D45CE0E8ADD7BA5C6DABAF82729362
-:10C090008399F6033C4C53997F30C079ED33CF1C24
-:10C0A000BF8AF53D0EAE03F899E0BCE6F94733E6EA
-:10C0B000407BF3EDAD26B4B943CFA1F56EEFA47686
-:10C0C000714BAB4CD319C5236554B986080BD9AF56
-:10C0D000CC7486E4B334C9C6EDA7103DB90EF85050
-:10C0E0008FF04A6404AFD03871E8F84905C9FCDE26
-:10C0F000E4E2521A774345A71EE3905DAE7AC54E3F
-:10C10000F2F4A9EF42FBB17B3AA723FF77151AC8D7
-:10C110001E7EF8C1499311CFDE6512C5D17AD17B5D
-:10C12000C8BA3D23F59CAE1C8BCD287FB7CCB9DBBC
-:10C13000ECE8C3FED852318BCE2F5A96703B63A5E4
-:10C14000BD81E488A542B9E7A2D8CB71AABF13A2EA
-:10C1500027B7543798F1DE9B7ADE9085D8DB97EDD0
-:10C16000BF1FBDBB61F98BF1A84FEE2A6988C77963
-:10C170006F89F04F7713DFD5939F02F2381EE5F1F8
-:10C18000A2910E922FDDF27FC6393B0E1E18695523
-:10C19000F88ADB435FE27F41BF668D92A714601C83
-:10C1A0002DB5448E7660BC74DFBBD300AE93BD7AF0
-:10C1B000F2638DFB81F4C12F322638495F9E1E68E1
-:10C1C000B0229DAC6AFC468FF76BCEE2E955E87F62
-:10C1D0005502B78756C51898DF42F3A1454F752E13
-:10C1E00066A8A7F509DC3701BFC58F79162310FDB6
-:10C1F0004C8EF1BAAD00872931BEBB30AD4AACD709
-:10C20000D9609C1247B480F09DA263C5061EAF9D05
-:10C2100085F35C11F311C55927A7C5D17D54A3C57A
-:10C22000ADC3FBC97A67D5F6B58CCE8B51BC15B0C2
-:10C230004AF7E18C18C7BDB6278EABEE13A9F1DC27
-:10C24000750529042F21C1FF2DE223CB1A10F11E01
-:10C250007E983E40F6F8AA4613F941CD093BDA91A3
-:10C260003D3223F83EA47A3E17E063B1027C560CBF
-:10C27000BC9BD6959414BB17E7A5FA91F120AF505B
-:10C28000DE6525CC9B8AEB4B7AC3ED4A867AC60CD9
-:10C290005D366016E0EAB9A278AC1EC6213C58D8DB
-:10C2A000384CFBABBF22D140F1D8D0F2270B785CE1
-:10C2B000320B0521AEEB5E13DDCF5D75E0BEF7AA54
-:10C2C000507E1E3039C967678114BCFFDE1D77665A
-:10C2D0007CFFDDAE9CBFB5DB0D743FA63BBECCF84A
-:10C2E000BEBC1AE7881AE5D98C78F231C721F4C7A9
-:10C2F000FEAB718F1B46CA4F607FAC6DC015C56326
-:10C30000C2C6EA689F2729857982F7055629EB5F1F
-:10C31000D50D877A3BEAF575289407F60F878D3798
-:10C32000E7BB2622DD46EC8847FDDA47BC431317FE
-:10C33000C17B2879B10462FA93AA799C2466EA3C0D
-:10C340008A774853F93ED90A1660FCDCA0C0847C89
-:10C35000BAEA4BFD0D7087E8D7CC7A929391AE90F4
-:10C36000B8482F7F45E6766588DCDBA2F0F9F1025C
-:10C3700025EE91CFF2BFE79325BB2852D9F7891854
-:10C38000954272E811570AD943C41C41F0BE9C9DE6
-:10C390007350B1877EA79C8FF72BE7830F2BE78322
-:10C3A0005FC5770BC0903F86EF16407ABCC949E560
-:10C3B0006F341528CA99E36F45EE9248B21F94F97D
-:10C3C000E994F9ADB04E7325037E566DD3D37958F9
-:10C3D00063C284E968CF32AFDC9E11DB73EF8775EF
-:10C3E000C2BFFC9E73A75D091E3A4F3AC7CAF73F0A
-:10C3F000557C2D54EAAF12B619905FC7766AE136C4
-:10C40000FE52A4C6AE2C62DAF397134D4334F54BBB
-:10C41000ACDAF39793ECD76ABE4F7668CF5F5E973E
-:10C42000313E641F564B570B13806E804EAA337DEE
-:10C4300034FF85D6528A7BCD0DB9C77447AB363FE2
-:10C44000DFA7CD2FDCADCDABE7C9C34629F43092D1
-:10C450008DFC31F14EE4F70C85EF0701BF6FB33A65
-:10C460009911DACF1678BFF81EC6001BED4BC976BE
-:10C470008C23ACE3F79FB05CC7CBBDC395F67ABE07
-:10C480006FC58EDBE8BE1D4BCCE1ED06F0EF7EFC08
-:10C490008EA4F1720EAF87FE12D61BA2F453C3E531
-:10C4A000939C45FE829BEC33236BB3626A01FEC210
-:10C4B000349A39E99E750CAB27BF7590727F325163
-:10C4C000E8A4BC43B086613E4570A6F0F8858FE4D1
-:10C4D000C35049FE752AF1895B7447F4E6970DB99C
-:10C4E000BA07F0AAF8860291E4E2235646EFF9D89B
-:10C4F0005CF713BF6EC316B06E336B8F49157AF8B5
-:10C50000E7EDBC61C45F135C0EDA2FB515240B7820
-:10C510002EA588859CCB364569E8A3C41A17425FCF
-:10C520004342E84B4B7F7F9DECD5453990CE42E8A6
-:10C53000F02FBEE5512C18AF4C8FFA058FD58976B8
-:10C540004A059ECA02964F75469B31EE678BD173A2
-:10C5500079A5D83FA54A9FABE459EBB2E1FB6B56F6
-:10C56000D149E6F6BA2D3DF12518DF9600F635EAF9
-:10C570006399915C7DB0D31F7635D47F04FCFF6551
-:10C580000CFD1BEB64BCEF65B5E4105F3F624979BD
-:10C5900000F35ED0E8587F4331F7AFE5E86C82EFF7
-:10C5A00051A1BE05EFA53DC2F24CA9C1F52DBCFEBF
-:10C5B0007A596451909F183182EABF9D6766F8CE20
-:10C5C0008177A0D98771EC63F2AC77DD41EB7F7B9B
-:10C5D00014D707AF191CF1A80F1E997C77A687D234
-:10C5E000748D5F684B10E4BECE17858F3672BD9296
-:10C5F0005BE2C7787C74C234579903FD1DB70BE921
-:10C6000042E712F1E85B37FD442B7EA8E406C10F38
-:10C610004B9B745D0E43FFE3110B77351E299ED5AE
-:10C620005286F90291EE03D95CE2EBD9B8AE027EF4
-:10C63000FEF04AE571A81E18329ADBBF9386443C8F
-:10C640003014FADF50245AB1FF0D7A2BDDE7F14E9A
-:10C6500066E45717BBEA97E0BC6D09110CCF6FDA9F
-:10C660000A1A78BED8C0CC004F936BBD17F1694A47
-:10C67000F58CC0F647077E7A1CED195B82483A704C
-:10C68000A2CBF9AE1BEB1728F19DE279EB703C9B36
-:10C6900045B49A590F1C54B9BE9EC9CBC9FFB20A02
-:10C6A000F4DECC0A6B430DCEE7918470B2F36DAE2D
-:10C6B000060BE279C3403DD14149227F576A55C2FA
-:10C6C000B40ACCFF62A09171BEF32F1F8AFE815382
-:10C6D000A075355B1A685EC72E8939C1EF96A8A987
-:10C6E000D9A185CFEF46F1F89009E3F1809FB7F526
-:10C6F000CC9C9A8BF4A3A778537F7C6B735DCE7E22
-:10C70000FB61FE2A94030B11BE8597C2984F40FA35
-:10C710003D2961FE777F015B80D6D960C1FE416E05
-:10C72000BBFAA2BF88D19C7E9B0B0E4BF84E82D7E2
-:10C7300021101F345B4E4E443E7828B58CE8E8A1AA
-:10C74000828F9A892F86F3FCDB79F7EE413C7A13CE
-:10C75000C3697FE7A1825931C1F4BE609448F432C5
-:10C76000EE6F614E3FE2639481F8FB9108C7568CEF
-:10C770004F79F3CC64BF4B8275D96C98E7C46228BB
-:10C7800087FEA25D623EF17E75058F0B2B307ED554
-:10C79000653B84F8904A66317EAE4939F71491EFD3
-:10C7A0005C4335B4FA6F952597DECFD892D07042AE
-:10C7B000D9B620BB6A9022570694884528DF0659CF
-:10C7C000B85D65EB940594BBA1FB47AABED729EDE4
-:10C7D0008C325BA6A3541B37D215707D1B6A7FE990
-:10C7E0002CDC5EC33FBC8FAECF353F89E738743158
-:10C7F000DA7A7F19A59C730AB1AF543ADF60E57A03
-:10C800006243AED18774BDA198DB592A1FABF247B2
-:10C8100085BF2A87D47B7EEF28F695514E5E3687FA
-:10C82000E4EA99E5786F07D49E7317C37B8956FABB
-:10C83000FEAE721FF194626FBDA7D85BFFA1D85BFB
-:10C84000EFA3BD05F986518308BF37142E76DD08A6
-:10C85000F31A902011DF143A4E4CC4EDAF71192732
-:10C860002C7DD96111D1A20EE3058F34F27B4936BC
-:10C8700097ED9815F159CF95F92C6B766934BBBCBF
-:10C880007CF2E37AD2D13EE4EB7B55B94F794C99F7
-:10C89000FF7165FE6F28F357ED8F4943BE32A1BC8F
-:10C8A000DF10AFEF477E29FC29A7D0B9A85079B592
-:10C8B00001C408E9EB2291FC9F2078E76AE4BD25DA
-:10C8C00020F7F54E59C9681EBFDB6076572C467CB1
-:10C8D0004E6614A79DE8AA27B96503B94572B3F857
-:10C8E0005CEB6CCA473883E59E518163B1CB5A8EAD
-:10C8F00072BE38464F1F5724A4D0BD5BD5FE0E1D17
-:10C90000F772F00C9567A682F55EE2F3FF47726C52
-:10C910002CE3E38EBD243AFD5CDE1C4F2679239187
-:10C920007C0AED5F95376F63CC6420BE4F64A1FB3A
-:10C9300000770A614E84E79D287C303F97D17DFFC8
-:10C94000C18A3D6757DED1014EA1B8CED84EB0F5B1
-:10C9500083F87AFC2553F71B6CDC8E8FD6E4279A7C
-:10C96000E235F54BACC99AEF93ECC335DF273BB208
-:10C9700035F9EB324669EAFFC259A4C9DF50305994
-:10C9800053BF4C2ED3E46566A577480E36ED1EFAEC
-:10C99000B11EFDA7B6A11FA7F5864FA1F1F00B0EA2
-:10C9A00060E1B5A38B67E80046855187EF4C86FCB4
-:10C9B000C6D19367E880EF0A071FFE3A195868D37B
-:10C9C000E8293C7FF5E1AF5320BF65F4753C3F8615
-:10C9D00091F0DC3A7AEA0C2FE0591CEA797434D0F1
-:10C9E000F12D97EA8FA23DF8C765D3E6264BF84EA6
-:10C9F00040596206CCE76C8AE761FC7E73ECAC15AB
-:10CA0000781176FC77F5748FED37A379BB8E8BFCAC
-:10CA10005D8D8E8BFC1D0DBBC8F1F65353F5BECB5F
-:10CA2000040E9A7EDF5F11647EAF05FDCD3969DCAF
-:10CA3000DFC414FD4D4CD1DFC414FDCD397AEE6F47
-:10CA4000628AFE2696A3BF89E95B4D32A5EF34B911
-:10CA5000286D6F7253DA7DBFE029E76A3D0A38EF2F
-:10CA60004F8B5B98C3E417114EA1E74A3AF49D4FF0
-:10CA7000D07ECA45E6C0FB1287224E3970BFAC3962
-:10CA8000CF44742E74B63B4CF0BD3097E79B2FB665
-:10CA90003B507E611EED9E8EE8B66C94BFCDB51600
-:10CAA00027EEBB355FF4C7239F14D61BE8DE4C711D
-:10CAB0006727C5E90A2DFCBD844311C78E28E39181
-:10CAC0005CDA7991F9457C27C7DCEEB02AE3603F58
-:10CAD000306E32EAB7C225302EF55BBF98FAA9B0A6
-:10CAE000748F2B848C6BFAE171270A41E3A67631AF
-:10CAF0007A1701C77568C6F54B743FFCA25FC27810
-:10CB00006147B4D38E714D355F8CDF21BF45CFDFD8
-:10CB10005F2C74F825D493B8BD89EF5BC681D833F8
-:10CB2000D3790D1FC965A84771B99D5D7C9D179A82
-:10CB3000FC0B909F8A957760C08CA57B9B4C0C73F7
-:10CB4000A2BE2891BE3B363817DF39E3EFA0151B94
-:10CB5000DDDB901FEB745CDEB01833DF57D0B5CF50
-:10CB6000FF15D43B193B98EC9504FB4B2C7504B492
-:10CB70005FE4CA44BBE3245B4F72687594E77F8F20
-:10CB8000067ABE31B35E50F427F5637785EFC0FDBA
-:10CB9000888E5786E5211F4D333A5E64C0BF7F1FE4
-:10CBA000DD44FC3C2DCA91872FACFD7DF40A9E8F9D
-:10CBB00073BC883783ADAC694671FC8F3F2F45F15C
-:10CBC0000D749AA70A3AB47FD4735376D1133606FC
-:10CBD000E054EBFACAC0E7D769C07870D41807C12F
-:10CBE0006FE06146E7983A2747F876E07EDF80FA03
-:10CBF0006C8C87B24C471ED64BD277D27DF28EEF2B
-:10CC0000F8FD27A819795350FCFE898392ABAFF841
-:10CC1000E3C931DC4E5D946A598778A8B39B4C9484
-:10CC20001EBC48E78299CE9D8AF16BD9D0F77BA9CB
-:10CC3000AF8EE1FA2179A54131024174C294E53009
-:10CC4000A6E6BD0CF4D0F6BBC3BADF8B037032434B
-:10CC50009AC8F3DE1D8F17EB34F565ACDFFD1DE3DD
-:10CC6000F4ACA7BDFCDBCD8F2F4F55C6437A99C7D7
-:10CC7000C87F0CD53B6B0B6DEA3B3F84E7C763CCA9
-:10CC8000DBE93D5249798714EA5A314E11CEE83D2D
-:10CC9000AEC1BF37FB9A819E769A393DA78A3CDDAB
-:10CCA00029F2FAEA3BA5EABB6BCF147A6E2BCCA330
-:10CCB0007EFCD48FB4371BDFCB88676D34BEFA6E31
-:10CCC000945A2F01F420092B5D673AE2AB5012FB16
-:10CCD00084E7E7638AE6201D5C68F2B24F82F4CDF8
-:10CCE00085F0C8C660FCD549DAF75A3F1F3381DAB0
-:10CCF000A9ED6B1B27B24F2878E9273AAA4D156991
-:10CD00001FBD4E62AFE23B9C20590DA897D576A778
-:10CD100040DEE278EF82FCC5F43D90BB9FE8D13E57
-:10CD20009D4EE9FB4D1E2A3FDD544D69A0A99ECAC8
-:10CD30003F6A6AA4F496DB2372917F16ED5FC63ECC
-:10CD400009A2F7DA36BD2710943F55D4371DAD51EF
-:10CD5000E8E85472DFDF9F1CC3EDBB53E3383E3B72
-:10CD6000C0DEC0F7DA802E975B6DFDDB1D1DCAFDAE
-:10CD7000AEA3E3F9FE65473CCF2F1FC3FD6E596498
-:10CD8000ADD8FEE87803EF3F45ACC6EFB28DF77B38
-:10CD90002A5DA477A47E35B1E8FE31583F16CA73E8
-:10CDA0007AF2A7AEE2DFE541BC5C9DAFFAFDB64288
-:10CDB000ABFAEE613A7FCF8FDFF7027AA7FED5FAA2
-:10CDC0006326703E0CADEF4BE5E7C943E1F1A9C224
-:10CDD000B7C4176867231F2407F1459D83F842A550
-:10CDE0004395FED6167238A71A153A0FE7E7EE07F5
-:10CDF000A32E847683E3CCB48F20E3BBCBB09E9D7F
-:10CE000082C22FA1FCA0BC63ACF283CA072ABD0F6B
-:10CE1000063EE3EF34F3758C95FA795F5859477BFA
-:10CE20006CC45D84D7837A2BEAADB1127F2F79B0C1
-:10CE3000D8F5CEEDC89FB1110E8C9196ACB2D4F757
-:10CE400025C73EFEAFC243950BFDC0A3171C0CCAFD
-:10CE5000BBC33F120E24E7508E23FDF621B74E8C44
-:10CE6000B1297617A7DFCFC7C86F221D7508661DC9
-:10CE7000DE7BE830F77D5FF0E878BE0E958ED61643
-:10CE8000324A07E33A87F6967BEA7ABAD7790723DC
-:10CE9000F9971AC6CB43F1ACAE2B48FE9DC179A9D8
-:10CEA000F0640CEC1FE827A1C642EFE8DD56E8E08D
-:10CEB000FC36F0D3CA0DAC67FD358A3E7B4C94F846
-:10CEC0007BC88A7EE92E17A49965991ABD4347CF7E
-:10CED0003A5FE1EF8AFB45568DEF72A36F1D1C1779
-:10CEE0001F52C8E543D7F43C11F7132FFCD542F786
-:10CEF0008B2F0CEA3C8DF6CE85563D53DE239B2AC4
-:10CF000080DE9D8B3E130CF9A5F29EF3E7E8F70E49
-:10CF1000837A6D174FA3BDB568ABC44C789E60EBA8
-:10CF200037B7203DCD7B454FE7999A5B371E477A4F
-:10CF30003CB74FC0E76FD9857D02C5316B5B227C62
-:10CF400066A85F0A79AC7FC76EC9C7E38B32C53963
-:10CF50006A94F13E31D7A5A05D3E71EB5D3A84FB4A
-:10CF6000BCED028B837E8FB4DE790CDF1D39B78D6B
-:10CF7000DF2F6B3647EEC0F9974AEB0C83A07CC1DC
-:10CF8000765E5E6329FD0CF743173CCD28FEB36047
-:10CF90006F04F98FF35AF41F0582EC8EEA6DDAFC08
-:10CFA0007CD666403A58B0535B5EB307F241F279E3
-:10CFB00050A1122F19CEB2295ED2C2E307AA7CEF8C
-:10CFC0006D5F7BB91C6D50DEFF667F89A5F70F5F33
-:10CFD000F926E9230BCF9729F93390FFEA1B8E1727
-:10CFE000152E75CAD85FC5B3DC365867DD2B662BA6
-:10CFF000FAED7507CE46E279B04561017A1799BD21
-:10D000002C59D1DE7B60BFE445F8D61E343F89FB46
-:10D0100098752F9E30603CA174DF62B2572631EFC5
-:10D020004AF49BFDA2C8DA898EDAE97D5F2677CEC5
-:10D03000C37E2E1C305BD10EA87BF94FC76EC7FC98
-:10D040008B02DDA7BC9018203A99B755A27B430C00
-:10D050002DB4FC1E3A9110AF88E7B6287A8FE50E02
-:10D06000C43BE219F0EE48463AE171D0794F4BF4F7
-:10D07000BDB9B5D980F5CFF9387E55BC974A4B0973
-:10D08000CF0B1EE7F89CB875D7E630A483A7F564EC
-:10D090008F1F817683783B0D1D185EE1FD5FD8C53B
-:10D0A000CF9177D3C10163371DE03C2F4707C0A75D
-:10D0B000A4F72F47079DE89792BFFFDDB9C7D00EB1
-:10D0C0008FE0E787D5771BD5771A072E3C7514DFDD
-:10D0D000E74AB3BF407677A5ED8BDAC58CDE099DB4
-:10D0E0005388E74B26BFBD02D17772CAB3D9142F3C
-:10D0F000D507766DC178437438C5C73A92CBB6E18F
-:10D10000FB98C5B66F93F6C23A16FDCE48E711EB11
-:10D11000157EC63F3C07A2BE4B0C78A7F319B50796
-:10D120008DFC5CC63EEDFBE11DF19CCE4B0C9D954C
-:10D130008BD14F80FE701C41E6FEE9C283FC1D4589
-:10D14000D59F5CA8BEA7B847FB6E83607D9BEA3D78
-:10D1500050984270181A37D68176797339F3840D56
-:10D16000FD217DC1DFA97C5CF18BFAB527FBD11BCA
-:10D17000AA1DC9BC21F7DA15B97547019FE3D1BBD8
-:10D18000DFD0E17B8C1D3BF9EF3BCC3F08F22A0658
-:10D19000F719F51AB953A7D4FF14E90FE076DE5B4F
-:10D1A000FF922805CB97F78BB19F9AA7793F7548D7
-:10D1B000571457F56F0E83FEBE6CD333E497054CBE
-:10D1C0009137FB23286ED44BBEECDCBE12CDF7505A
-:10D1D000BA5A0876262E2294BEEAF669EB3D5DA87F
-:10D1E000EC7B0E67D7E0F9FFAF31E090D7235FBA51
-:10D1F000DFE9678E28E4EF6E7D2868EFEF0F6B059F
-:10D20000960FEA77B8CFC463A44AFEEADD564DFE16
-:10D210009A36BBA6FEB5FB1D9AEFD9FE0CCDF711D1
-:10D22000C79D9A7C5E7B81A6FEC8F7644D7E54C084
-:10D23000A5A93FE6BC5B93EFCA84F5F461CFA8E9EA
-:10D2400024BBA0A93FD961D6F47F5D46B426DF6533
-:10D2500051E0A3D899AAFDFBA7426EFF86A62A7CBF
-:10D260007FE1D48EA3FAED371468C72B93B5E35D45
-:10D27000295EF01D419D9EFF7E02A6F8FB09BA348F
-:10D28000FEFB0998C7DF4FC0147F3F01CB7FDDE471
-:10D29000A4FCBEA602CABF047E09E6F7839F82E90A
-:10D2A000CBE09F60F9E5E0774C19F7B832EE1BCA86
-:10D2B000B83F154E6F29FDBDA3F487EF0DEAF43D8D
-:10D2C000DF6B5D79E225E0E322DB67745F596E086E
-:10D2D00094621CA3F37589E1F967E6F11D6F8A4139
-:10D2E000FD3680A19DC4DC9D6FE23E6EDD8B43ADBB
-:10D2F00078AEEF81FD7F7807BF5FD82751BCE6F09D
-:10D30000FEB391D8CF9797C2E9300AE945C8D77CD8
-:10D310002B507E0D7CC7736793F74ACABB676DA419
-:10D32000EFBE4C55F33EBA2FEDDEB3D780785AB836
-:10D330007B2F7D7F1DF85AF37DF776CD772BD6872F
-:10D3400074A1CE477185CFF7ABFDF9A97E4D2A7F39
-:10D350003FFEF3DD47568E417DBCB76A00C6B51768
-:10D36000EE39113BFB07F0F1D54BCF66A21EA83D6D
-:10D370002029E7D1787FB507F44A9ECFBF26756F85
-:10D38000299E37637B04BAB3F4255B4FE7C416EEDE
-:10D39000DF5583727661C6ED7A8A7FB5494ABC83D0
-:10D3A000BFD3506365DCAE6BFB3A12DFA9FF7DDBB8
-:10D3B000D1EBF11E74C7C123F45E4CC73E49E34F65
-:10D3C0008D1DCBF13B762CF7FFBEDC772412CF0905
-:10D3D0003ED07684C35DE7A7F51F56F21D9012BCC0
-:10D3E000F74BB4FEF99724CDEF01B8C071A1FBCD86
-:10D3F000FBD322705D27DBF878D3407D50796AD566
-:10D400001C9CFF1BF6F23CE57D32FADDA18EABAE33
-:10D41000DB857276619BD4E779F739D82FCCEF980A
-:10D420009ED3E9EBA92F1C1B04707FC335209B748E
-:10D430008452AF622CD79BA5064F2AEA91931647D8
-:10D4400004D2F9FDAEA11188DFC39862B9EB49BAE5
-:10D4500007BE601F1FEFA4B53D12E9EEE4BE1152F6
-:10D46000F0FECB2DCA7ABAE9BB1B6F5EC253B56F13
-:10D47000BB05FBE9C11F2F9F36D64AF5DFF09DB8EB
-:10D4800005EDAC9319FCDDC0630646FEF5C23DDC3C
-:10D490004E3E7970F0F6E0FB59D3147C7464F07D55
-:10D4A000F50BFBF54ABDDB77314D3D3DC7D74EED62
-:10D4B0007CACBE330FA17D5EF3B844671D6AF4F502
-:10D4C000B1B8FE4FB769E757ADC0B946EF8F8D0DC4
-:10D4D000A2D79A03DD7C63213A3FA0F28983F0A9A9
-:10D4E000E2F16486C4E765E7EFF8D5ECDD4574DD6D
-:10D4F0003BBEC4E3B783EF313929BE74197F5AB5F7
-:10D500001B82FC2DFABD23BD6B689E98D2631F9CC5
-:10D510002E941F1A9B877E989BFCCC930CEC5B1877
-:10D52000B316EDEB28FA1D89CD386ED73E3DBDFF11
-:10D530005F6B3AB000DF23EF7202A3C0BCBBB6E959
-:10D54000BBDF67463B779E62E77EEAF0E44BA07F55
-:10D550006B9789B4BE9A3D920FCF175C50E4DE57AB
-:10D560007B936F407AAD392E59D13F9AD896FC7093
-:10D57000612EE977B257EBDAB89D5CB75B20BB58F8
-:10D58000B5436A153BE49C62079F5BD6C9EDE35740
-:10D5900004B611EAAD0D037B04E65D9B3985ECDA38
-:10D5A0005A69DDCAC10E3C47A5B51BE61F3C44E7DE
-:10D5B000AEC0CED1942FDCADCDD7B669F3AABFF8FB
-:10D5C000D2D86E3B6338FA372552611CF2C39B0AEE
-:10D5D0005E557FE7CE6B9CF4FB270FE81C53D4B855
-:10D5E00004C26BD12B2FCCC779FB6AC29CE47F3479
-:10D5F000FE96E0DAF117EED774E0DE1BF233E3F0CB
-:10D60000EDD8CFE97C915EF0E1EFBA2C425D81FD6F
-:10D610009904DF328C3B7BBB22493E29E7081ACABA
-:10D62000B9FF2A630C18A6B27E2CF7E743F5EA3857
-:10D630005D408A0E921381B12954AFD8C0CF57DE16
-:10D6400019E124FD36C4C4EDF521266EAF0FD17566
-:10D650002EA3DF851824F07D8EAC9769FF606D9D49
-:10D6600085F617047B950EE1B17650950EE97D881D
-:10D67000B52D03FD3A355F8CDF337BEC83528B474E
-:10D6800087E3EC8C17947D04AE4FCB74567D749079
-:10D690007E656C99667EEA3DCC9F7D7E56989FA5FF
-:10D6A000677E80EF286CFF75AE93EC86A432F5F7A9
-:10D6B0001AEA492EA8F0FC12E8BD187045776C8173
-:10D6C0006E6AB61D22FFB296B5AFC476A5917C1DD9
-:10D6D000A506FEBE5169184F75E3B8FC2A51D2A5C4
-:10D6E000E3B4F6C39171B27E1CA43BC6B94DE3F21C
-:10D6F000683F9579617D0D6FF377D643E53E9413CE
-:10D700003D7D0D7C88F26F46BD604DD5D8699CBFCC
-:10D7100016F1A26E3E5AF8F693C427EA39CC6AC6CF
-:10D72000F97B66A3D99A1AC4178B90DFD0DE77C332
-:10D73000BF7C8C13F0BF6AEB7C3A97E9698CB5A289
-:10D740005FB748FA92F6257E2CDF2DDAAFCDFBCD00
-:10D750009CFEFD1102F94919E3BAE30DC48F490A91
-:10D760007F6CF708740E60FB773A1ECFAB10287EF3
-:10D7700077331436DA944962BDEA22BA4F7233E342
-:10D780004763594B8CF2BB3D31B46F7993B2EE9B3A
-:10D7900075FE4328578EEADB92319E74B4D6E4C4FA
-:10D7A000FECB591BBD6F5AC1DA293D155EF7A29F0A
-:10D7B0003AF72622DDFDC963A478D6F6E53B225070
-:10D7C000BE67B1E556DC4F0450ECC6B701FBB3733E
-:10D7D00042F71DD5FBC4602FC7217D02FE27211D06
-:10D7E0009C07DCD8737AB75FF8C71723117F5F2CCB
-:10D7F00079E1965B19FA5F9DE4472DA85F46F75DD6
-:10D80000819CDA33F27BF0AAE25DC55B375E1DF0E6
-:10D810002F18AFB0A6048493F46519C9A57F91E8C9
-:10D820009CD6E5F0AAC27DBC829F3B0E70F9158A9A
-:10D830006F150FB7E2BBF54349EF6E233C3123C9A7
-:10D84000CB507AB81CBE8030E93CD9C41823F9A16A
-:10D8500083452E4F07CF13285E793BF3BC1280F42B
-:10D8600096F0F7F5FCDE0AC75B8582B73F31DF2F04
-:10D870003292FF71783B32CEDD346E606FBE0DE5C3
-:10D88000D3FEF8B2C6E1FC37555FFA18F263083FE1
-:10D8900087F06B371E9DF02F088F9EC648E2CB6E37
-:10D8A0007C4B7BAE4C2FE27F308EB55FF0F993AFAF
-:10D8B000805F0546BFBFF8F838ADDE54F1A6C2A5BB
-:10D8C000BFB8E007CC7FD42AD0BE0AE7E3BB8D7493
-:10D8D000FF43DD5751F74F5E19C7F55C68FA01D871
-:10D8E0004BB85FB526E3E440B4334F19D47EF8FE5D
-:10D8F000EF07CBDA13F1F7B63E28E2E92903FFDDA3
-:10D900000F352F87F1B8E407F1462FC2E90361F81C
-:10D9100004D4331F08F75CCFF3710607E6CBE32688
-:10D92000E03D90537A358E79BF127FF0F179948F74
-:10D930002CA67A02FF5D4A07FEDE1DF62B0836177D
-:10D94000CCE783BBD2E87D9DEE7D8D71DC0E7F46FA
-:10D95000594777DCFF5E81E2FE335135E1FEC48436
-:10D960002D2E7C87F3F47D43B369DFB4413B3EEA5F
-:10D97000FD648A976EE0E7FE2E75EAAB82F45BB732
-:10D98000BE2DBEC8CBE7E4D1EF8CA8BF4727DB860E
-:10D9900073FFDCC77FDF50D5675DC75FB004C77317
-:10D9A0003F53E2DFDDF9E10F2605EBC3434FAD4DF9
-:10D9B000C77EAA0DDE2CA7057F87EEB124B45BAA33
-:10D9C0009F5A954EF6F4530FA4A35F54BD636DBAEE
-:10D9D0004CF9700FF9653ABEEE2F9E1B45E7F3D464
-:10D9E000FEF6CADCAFA8301D2A41BD3DE5EAAF56C0
-:10D9F000E0FE41DA7D02C5FF66B0F615A8672B335D
-:10DA0000385FB11613C97FE88FF66B770DFFC54EEF
-:10DA100094076F649CD5CF817A123E203510DFD5F4
-:10DA2000F2ADA3DF095CCD7F27B0A77E22EDFF56C4
-:10DA30002D17E89DAB19F5FC77F3A4F1D104C75974
-:10DA4000ABB38FD1FB574B79F914A36FDF49EC6768
-:10DA50008B81DF3F64EE94E0FB7092B25F38739D80
-:10DA6000F27B71CA38699B63B707AF5352F61D59F1
-:10DA7000EA7724DF6E50F03275E98957EDD0EF5424
-:10DA8000BDC73C1EBEBFB3E95CAA9F611CF4333A1C
-:10DA90005F9866F03C3A1FD7BDC34871D2DCACC179
-:10DAA000521CD4CF5952B411D3994BAB1E9D8F72D7
-:10DAB000B8D594CD8F35F2F935084E11E5F491EDD6
-:10DAC000B7CE42B89DDFC47FFFAB61FB30FADDC249
-:10DAD000FEE4DEAF9AF8EFF93DDD64A2F4D9262B1F
-:10DAE000C3A3EBCF35D929FFAF4D0E4AD9F43CCDB6
-:10DAF000EFD8F4D7DF884BE1F4BB73B9ABCDF43B7F
-:10DB0000880D4639753CC02BEDAADA1D0F28EBC2F3
-:10DB1000F7B8B2BDC913110EB90F2C3E86A6B37566
-:10DB20003CDF977DF3E4EA2414D6772C3DF3C47CE4
-:10DB3000F87EFB78F7350827D3B68B14A7387260C8
-:10DB40005525C2BB7A8791AF4F59F7F94DE9718FCF
-:10DB5000627CF9753DC50D166D3BF3C4030C7F87E0
-:10DB600077B12198DEAF74BD578FE77EE6E5F8AA5E
-:10DB70003F38FC78BE5A9B44FCB303F82AF3A7F362
-:10DB8000D5A2A5CB087ECBC6BB6F42B89DD77B93F1
-:10DB9000909FCE0F1F4B74EE7D4520F8AB72BCDB1F
-:10DBA000AF56E0BF506C5B5798DC23C7BF61B90428
-:10DBB000DF43073E4D47FBF99BFDE53FB8EE97601D
-:10DBC000DDFE6118AF33511AFA3DDFE019EA84F542
-:10DBD000E5F7F33EE8D2F16AFC9F9F53C03F213640
-:10DBE000F89D21E68D82F9D41C14FC6159A8CF263A
-:10DBF0007DA643BF11FCCF8F34E78C19FB28489FCB
-:10DC0000F737DFCBA575D84F5A8FDC1DF99EC8FCBE
-:10DC1000417A7B54208CF983C6EDF673A0CC40FB8F
-:10DC20004EF12417106F782EECC281E13B30FF9942
-:10DC300081E3F1C24B604FF1781093F27BD6F9D9B2
-:10DC4000812FB250CE86AEB7EEE52F883E6AF6AF92
-:10DC5000BA28D0FA277FA6CBBAFCFA0F3DF54516B5
-:10DC6000E2EF337D201FFDB60B864016E2A1EEB732
-:10DC70005C9EFF5838A8E5F3571BE8F73AEB04130E
-:10DC8000D14989F425C51F2E1CE7F187BA034F92AD
-:10DC90003CED3AC8E3408BC4F6D2388C9BD49F3914
-:10DCA00086F2ACCBCEFD31E89FDE712B1CAAE84199
-:10DCB0005D6712DEF73BD84D0FDC8F3C8FFC3B0CD1
-:10DCC000FB69A3F3BD2C2B9CA15DF139F2F3307CF1
-:10DCD000BF307925D2F979DFC01C948F6F66FDAD16
-:10DCE0008EE286BF0FA77BB2B56D92E69C79F73ABC
-:10DCF0007C123F70C454FB299CC9C1E7B90C8E1B30
-:10DD0000C86E7E83EF132EBA8AF3137B99F353ED1B
-:10DD1000F243067B507FBB157E52EDC829BFFF1B27
-:10DD2000F1E5B38532FD04D54FA5C7FF9FFEF74C43
-:10DD3000FF2F4133EC630080000000001F8B0800C0
-:10DD40000000000000FFA55A0D705455963EEFBD2F
-:10DD5000FE4927DD4913421208840642881A6203ED
-:10DD60008172D6C4E9FC6E2033BB016B2DC4088DD3
-:10DD700022249D7482E8EC6AB96E1A02AC6475368E
-:10DD80008C59471D479B9F8028EC769440C0A00D7E
-:10DD90000ACBA26B45AA263A555B54ABAC0EE0A663
-:10DDA00023823BD6E2B8E73BEFB5DD1DE24FEDA69F
-:10DDB0008ABA7DEECFB9E79E7BCE77CE3D8FB45247
-:10DDC00022CA226ACFCD082A0AFFA66EA245446D58
-:10DDD00029247FF641451FAFD364BC7D40A3C958B9
-:10DDE00093EB08CE9E415447DD269A45B4844265A4
-:10DDF000A471BF29F2CB5B79BCFE0D6D4117936115
-:10DE00001BAD6AB013D5A67A0B3614130DABCAAA94
-:10DE10008662CC0B952E9D4BF40DFE7E4A749B873B
-:10DE2000994F222AD3140FF61B9D9C16DCC95D8BDB
-:10DE300097FB1B494D98A7EAF3984F53087C82A3A0
-:10DE4000254B1DD868B46499233EEF8E37D2D60790
-:10DE5000314EA1D23B12F6F94B8F856821D117CBF9
-:10DE600017AA0F65F279AEDA037433518D76ED2976
-:10DE700085F7DD70CC4C5605FC67BCAFF239026704
-:10DE800034EA65FA52470A79ACCCCE4B1E0FCF1B51
-:10DE9000993B29D8C5E76F3FA09089E7B51DB1EE42
-:10DEA0004CE1796DE648B69BF7DD36F03B8B87DBBE
-:10DEB000F6FEF72CAEB958CF4736439E1415FA6DCF
-:10DEC00077F24F17917F60CEFB77313FFF694DF4BA
-:10DED000ED37BD6721D6D7059E8FFD5A0EF6D58248
-:10DEE0006EA5F05627DAFD3CAF48BF9B6FF8DFE523
-:10DEF0005C5786B3387EBEF8395DA2A718BDF869B5
-:10DF00003EF702D68B46EB437659EE21967B716E37
-:10DF1000CE8E2E25719DAE5F8F76694B0ECB159DF3
-:10DF2000A9B81566154D0D6C76421F858AB39717F3
-:10DF3000475F7FB9742DF49B122CBD9DCF17B59010
-:10DF4000DCC7E2C7B69BB40479160F6A1EDC433403
-:10DF5000959A0EC9BD7BA7E23EA8BC61A96712D6FF
-:10DF60008DBE7B2B6F195579BDFDFA7304CA757987
-:10DF7000CEB0A9C97D1B72D7E7E5ED80FED900C4FC
-:10DF80008E4EA9FAFE1E95C7E7C7D7BF689CA74665
-:10DF90002BCE89F0F806C59DE31C679F58BB87F51B
-:10DFA000BE86EFE945BE6FB42F753869CD6CA2FD12
-:10DFB0001DB942FF73874BDA504791F4BFD2E11687
-:10DFC000FA60C72D421FEAF0083DD05127EDD18EEF
-:10DFD00006E93F0351FF8C70A020ECE2147C6D4AEF
-:10DFE0009C1ECE1C434F499E3F9CA924D353149999
-:10DFF000FF70B83C1860FAA532A79C938DCAD1C0B7
-:10E00000FA684E4B2FA10CB4F9414A67BBB17B03B0
-:10E010001EB6FB3FD4EDDA4333C5CF4B30AF3AF3F6
-:10E02000CE46F8DBE52C2B69ACCFC31EEFDF63DEF9
-:10E03000E9D35505DBD13F68735BF9FE8757DC9464
-:10E0400001BD47FF4D238DB7AE285AB0B994E90AF8
-:10E05000BB2276CCFC6E6EC866BBC64FE65335B8A5
-:10E06000BAD4A4E38473B602FDB7AEC13E1B26DB6F
-:10E07000165879FC4AB9F757D827A6F7DA29EB0AD8
-:10E08000BCD08BD9F5BECAF302FF6EA65E9EF780A8
-:10E09000C39D64DF47CB2B82B09BC545B336CF070A
-:10E0A0007F76BAD9BC3FBBF57EC8E751D3944EC149
-:10E0B000319709B810C4FDF33E952E45EC306C71D4
-:10E0C0009932997F38B5222BC0EB4E19F77DDAB81B
-:10E0D000EF33C67DBFC3FDD5DCBECBFD6887B81F5F
-:10E0E000ED8A989E4DA385D05FF0A70D2F7944EF60
-:10E0F000A3F9A0A3665A0E3B5C023FD3F127BF8170
-:10E10000E578A25C97E36E037F866E6BE8D3D785D4
-:10E11000844F8B85BCB0FF4B589F609FB175F1F564
-:10E1200024EDB29B2990C2E7A0C3B620F4445389E2
-:10E13000805FCB0EE7082E6929B38ACF4F647A013E
-:10E14000099ED2AB567D5EAE6B21FC857524FB8C9F
-:10E1500004D58099EDC49F395498C9F28E187E1663
-:10E16000A30FFD4913FCF6CF679ADBD714FD7CFEA5
-:10E1700065438513B05EB1A9B033FF4E7DFCACE1C1
-:10E1800087FE99063FE33C9412CAC77D448F1DCE9B
-:10E19000BF87E92E7B78AD1E07C28582DF142E5C17
-:10E1A000069C5442E7C84DD477FC7DAFE927D047A1
-:10E1B000E879D0FDC77FAFD34ADF3967E2F8A450D2
-:10E1C000BEE204FD8141F73D3FC19D409B5F398721
-:10E1D00071CBA6DF7BAB27336E5883A73B6037FF3D
-:10E1E000A2DB97ED40FF27D05BCB112BC12E2B0F6D
-:10E1F000F47FF60A8FB7F43BDC80FBA86786E8BBA8
-:10E20000F3C8DEC7616F237D66F187AEFDBF7BFE7D
-:10E2100011996725985BBD35544ABCCFD1E37FE3A4
-:10E2200035619FB4D015D06F579C1739EA27EAFEA5
-:10E230003D54F1A93700BDF51FF86BC4B5FA0C0ABF
-:10E24000C06EE965BE4766E47BF5866A2AE171C760
-:10E25000D04AF06F7BC9EA869DFA5ECDA9841F5F24
-:10E26000F3CC14FB6BBEB13B1F71573DBA6FCF238C
-:10E2700059986723C8DB9EC976C47AF5693B16DDD9
-:10E280002FF7B76BCF6F20F73E1BED643ECDCC036D
-:10E29000FB35EF991D0CF0D15EFBFAE395B8871AB8
-:10E2A000EDB93DE8BFB2DBA6420F672D9E8C72F838
-:10E2B000E159B3BB17EB0CBA7978A22E4F5AA4568A
-:10E2C000EE2FAB3B1F71D737F1E1BF80DCF55AF77A
-:10E2D000F3CFE23C7BAD843871611FEB8DD75DE8F5
-:10E2E00035CFC72D8FEC7398602F9794EE95CF8222
-:10E2F0007FAF3EEF92AD5BF419E89D43D88FE711F5
-:10E30000E2F225657B52FF85DEBD255ED6DFC5972F
-:10E31000EA8BBD09F61BF317DF6E6B527C14246089
-:10E320005CF219BFC919203BC7DF6683BC78E89946
-:10E33000916729BEFEE27E73D8C23A6AB6D2E694ED
-:10E34000CCB83FF8F2FEBC0EE7F3A93B0A91C73404
-:10E350002F88AC845F5CB0514A2ECF7BDB885FBED8
-:10E36000831B972A25DF2D4F4D85EEC75773F53850
-:10E370007675C0160C28DF1D8FFEA3839CEFCC8E14
-:10E38000D377AF677E29717E6F5B42AD6EDEB72DAE
-:10E3900053C78F733C7F3FE35895B1CFAA8792E76D
-:10E3A000DF529129F6D3668914220EC6F82FAC8865
-:10E3B000E15AA4107835765D3DD213E0C8CB8AE0EF
-:10E3C00088EFA0F2A1966EA8343BAE4F5F4A20A81A
-:10E3D000958C7F0FB98B8C7B605EEF55E87EE5DB1B
-:10E3E0006FF3D8984F4B6A241D7953AB23928E7CE0
-:10E3F00068E4A8463B8DEBCB8AF19F19DFAF494615
-:10E40000B83F64F6D8C6DB8F8F433C6F1D7EB32ABE
-:10E410003EA9D0FDA669204DF623676411ECB6E94C
-:10E42000B9E47538A733C11F470676657B13E28FC1
-:10E43000CF903BAA7C287E13FDFAA37CD8814FA500
-:10E44000CD0AABF622AFB1650A4D293A1DB0B1E550
-:10E45000FBBEB4A7C27E2E5E6D153F1E5122827395
-:10E46000B927AE0A3E8C982382738ECAFF11FC181E
-:10E4700099105909DCCAADB4AF96F1C991952E1E19
-:10E48000FFB2C2A0A791E40385273257034FEAB534
-:10E49000D1B711376997D9093F89E97B9DA127A297
-:10E4A000C7863B78FC0F41B30BF1614EA562E40BCC
-:10E4B00096F8F9B5B83F8D90EBC041F86793DDDD74
-:10E4C0002BA3C1FDAF201FBC33DBDDE5BA5E6F328D
-:10E4D00087E5CACAFC6A2DEE293BDDFB8F15CCDF30
-:10E4E0005F1CC907CEB1B54B1C6A7BDDBA13FB4775
-:10E4F000CDA37B805F171CDE272B589FAD96A1AD67
-:10E50000A52CD267E6C829A4F84B606F8223BABD58
-:10E510008D14EFB2089F1E562AEB6797710F944B2C
-:10E52000B403F6A1E8F7FCE6C0ABEF006F468666E1
-:10E53000094E8FF5A70B034FA603373EE0F81E9850
-:10E5400013EFFF60F55E0BFA97BFB8C312E1F69EBA
-:10E55000CDC9E7BB7CEDF60CF80B3D9ED00F7BECF4
-:10E5600049A6C7EA0576194EF28380E8FD9CC729C3
-:10E57000F2B7540EB5410FDFD2CB98D612E8136331
-:10E58000E831F3A941CF1FCE7948F8B64E0B0F43BF
-:10E590006F2307CC047CEFE4B826747F5A10EF1A7F
-:10E5A000F500C7AD2C3D6E215EB4A40FADC4BD8C8B
-:10E5B000F45B9D98BFE9C8A7F9383FDB633ECEDB2B
-:10E5C00072E47036C1CE8DF704C7C76C8CB7F41FE8
-:10E5D000C9C6BB24D6DFAA860A211747B812E0476E
-:10E5E000ACDFAF850B217F8B325482F128E496F9A2
-:10E5F0004C6BA049CED1AAE87E4F4734C1F9B1F7A0
-:10E60000F651856EAF8C0F25C807371DBD5412B16A
-:10E61000C7F1A0D9C09513E82FD6FDDFB9C8C0094E
-:10E620005EDA0CBF1F0727BC31DCA3F516C87DAE30
-:10E6300042973BB65EF8CA3B2320E36DAF5D2A9953
-:10E64000598C75C63C4AC0A359717C010EE40A0E70
-:10E650006C3267F3B97CCF2BEE4E5ED2DCB8B1964C
-:10E66000A7D33AD3FDB5D06B1305E45D3756AEB1F1
-:10E6700076F470857EBF3E557F8FFBF628C14E969F
-:10E68000EB22637DEE7CC19B30F0675DF5C65AF8E6
-:10E69000DF7D597E4BE2BBF987F8AFED49A6D7ADD8
-:10E6A000DF589B338E9FFB1EDA7E6A125DCFAFD997
-:10E6B000BBA336DB757D7F4CEE8BB6989C95E64907
-:10E6C00089FA58BEB17612B7EB52FEAFFAD0CF7DC1
-:10E6D000F188358CB8CBFAB5E0FCB7FD71BD2509E2
-:10E6E000B77F805F33056B9D33BE5BFEB16DAB12B0
-:10E6F0001E56804FEC5FBDE267EC3709FB6DAA1830
-:10E7000053A7685A3D1D793779574F4FAC538C6DDD
-:10E710001928A7A8B788BD49CB7EB8D23D8E3E62E6
-:10E72000F36FAED4649F4D861D4FA96F79E6151E19
-:10E730007FB9CC5356C97E55AEA992BF8FDDA7A62F
-:10E7400052CF0F86B21DBF803D4507CD4EF849B967
-:10E75000A6EB334FBDFC2EFC312FDBE1EA647E35A6
-:10E760005569FABC633627EA40D1635FE57BE0FF79
-:10E770005BECCBA5CE62B2D3641E3F953B57F03D18
-:10E78000B6CFC7C63E69A57ABED35E64FEFE3A53D5
-:10E79000B1E3DB3A93E41BC569C1D91287BF90F896
-:10E7A000161D5CE8D45CC0F7A01DFED6FEF57F67A1
-:10E7B000230E8F0CFE67BA0BB875EDD374D8CFB6A5
-:10E7C000818FD3810F27066639D09E1D7239D01FE5
-:10E7D000ADFBB816F3BA8C365E67308B9CB136F65B
-:10E7E0007E8ED51312DED1CDD06BAF73DB2F4B6194
-:10E7F000EFA9DD8263FC8ECE44FC88D7195C39E337
-:10E80000D56512EB0C05B3F53A035AD4190ACC7A44
-:10E810009D0134EA0C685167403FEA0CA051670043
-:10E820008D3A0368D419D0A2CE80FE2BA86BB1BC60
-:10E83000514EDE50DFAAD1EC82FF0FF46A41E4F5BD
-:10E840000F1CD3747A8712C47D7FC6FB230E46AF9C
-:10E85000E875B028C75379E71F34CBFB201ADA5E7E
-:10E860003713F7D6AFB97155171137D914DBCDA3CC
-:10E8700027511F6AEF53DC1B5DE85F2E726C1B5C37
-:10E88000F87E23FA7BCD6ED585FBBA9A8DFA976F09
-:10E89000B057EA58D539C72C72CFFB15CAE1FDEF46
-:10E8A000B0EAEF64BFC6BD2CF7B045953CDA6F1DEA
-:10E8B00092F74BCB8B8A734D421EDA7ECBE78213E5
-:10E8C0009DB6F49D90D71FB239D724C5578FE47DEC
-:10E8D0007EFC74C18D3C43454CAFD5A790DF5E7B79
-:10E8E000013821F948427EB4D6D9FC33E467A45DEF
-:10E8F00033E1FC7E7EE84E64F9D63D6DFE2892B091
-:10E900007F733099F60DF66DCD23C899DC8F4A03DD
-:10E91000E2B23F94DC1FAA74647D92C63FE6D13C0C
-:10E92000E45B75FFB4E6403FEF77B9DB2AF9CA61D3
-:10E930008FF77025FBF149B347EA2F278FD9E4BD44
-:10E94000757EFB9CA4FA4B8D3655EA1F1BCC8AC4FE
-:10E95000F12BE5DE63B0CBAABA7BA5EE5295EB10A6
-:10E960007F8ED9E1D1F28637C077C35C97D4BF6A76
-:10E97000ACF40BE1C77E2FF73C68167FABE95482FD
-:10E980002AD3ABC96D817FAD62758A3D99ED8F2920
-:10E99000EC0FAB78AFC604BBDAB05D91BC420A1095
-:10E9A000ACE795863E570DFEEB570AFBCBBD563DB7
-:10E9B0000FCE5355E19FD7C5718BE7DF475E0BFC48
-:10E9C000661DC755B41C675F8F70BF376D6ABE9EEA
-:10E9D000E7BB72C07FF51933014F6A727E5EE8951E
-:10E9E000785FEDFC84EF5B09DFA57D73D3F7E1A8C9
-:10E9F000893E49C86B4F9A75FC617DCA7BEB14EC6C
-:10EA000055EA3E5E69CF743449BBA28CC4FF0B3417
-:10EA10003D6F2FE0BB72664ADDA20FEB6BDAED6E45
-:10EA2000E83F860BBB8DFCBE40E596E7ED4ED55B1F
-:10EA30000BD329DC3F8D5BCA147E61E77CD4715C0B
-:10EA4000C23F4F3DBBC0057D7C6977431F3539C749
-:10EA5000E6E1DD31CBE0FF7259C355DC97279D021B
-:10EA6000D89F8F43DDACDF5A1C48415D3DE4D15057
-:10EA7000273FA638F1AEBF1E4FB76F71C2CF0A1441
-:10EA800027EAB7B5A9DD35D9CCBF76E60C37F09CBF
-:10EA9000F155EA6123DCEA76706B5053F4B5A66C4D
-:10EAA000D4F30DFF29F7A6544D8AF7D71B7E141D0A
-:10EAB000FC221DF1F547D46D77837F806CEE5E8379
-:10EAC0003FECA0FEA66952BF8DD9D1E5FD393B616F
-:10EAD0004753ABF4758D8DEF99914F0CDDE6CDC1A9
-:10EAE000FE2BD77CBE255BCE397EBD8C713703B83B
-:10EAF0003BB65E16C3F13D46FD1D786B32EABA2681
-:10EB0000A3AE6B32EABA26A3AE6B32EABA26A3AE44
-:10EB10006B32EABA26A3AE6B32EABA26A913AE97D5
-:10EB2000F6DD8E87A41DEA08C87842BCB8B9EAC7EA
-:10EB3000D55D17558D5377A5145786C45DF67BBDFB
-:10EB4000DE3DA6CECAFEAE26F87BD5E0847B1E4312
-:10EB50005ED26371B338546BF1163C60177CF0548D
-:10EB60008D5B6F8DE9CF2EF5D9CB649B8F7BA82C65
-:10EB70009A655251C734EE2356EF84DFE09CF01BB8
-:10EB8000B4F01BD3ECB8DFFCD6C2AE5DAAE7090136
-:10EB9000C9136C72BF5B3732AE307D2F399370E58D
-:10EBA000B331B8C20F9A159063EDA095BA743F23A4
-:10EBB000F84F25377F9C3F0ECE84749C99961ADAC5
-:10EBC000877DA6B5A5BA9117B3BF8B9D9DDCA6889E
-:10EBD000BFAFA106D9771CBC49479E7CEFC4D17357
-:10EBE000BFE1F9F7FE835DF29DAD93D72EFAFFE00A
-:10EBF0004D4D95AE8F5F77847DE75996EA54B643C5
-:10EC00008E57D5162A92BAB89A2AFE50A33DAE580E
-:10EC100080A377D33CDC77B5B5E139C899C3FE2E24
-:10EC2000EFDF2CA3BE6B1A6ADECBF4D9EC3C37BE07
-:10EC3000AB4DCD3D44050B804775C5B0ABB3D4ADEE
-:10EC400060DD6319DEBF83BFDC5ECCA756E3FE96B2
-:10EC50005397B6B34BEE63CE42DCFB32ABAB1FF542
-:10EC6000862D6F9E907AC2B20CD742D41BB6BC7967
-:10EC70005AA7735CFD8A1BE5B213ABAB7F82F866C3
-:10EC8000EB3E9F1067FDA1094974FBC0E4EEF30958
-:10EC900071AE053FF89D4E3F534CB8AF5643945C60
-:10ECA000D5BB1DF2F9EBFE4B7FCFD3A8C4C9A7AAF1
-:10ECB000745C9C7482C2B0E7D1C50EF9FE973371C3
-:10ECC000FD3CD4DBA8D8B510F338AFFD35ECF8E245
-:10ECD000AD9EA7C127CF38770EF1793558C7900D73
-:10ECE000ED19E3BBE429D5DB88B6363D60927E356D
-:10ECF000588AF66D35F420FAD92F76814FED93F3CB
-:10ED00006E2C623ACF1A9AB7DE8E78E9D98DFE73EF
-:10ED1000659E5EEC37B6EEDF699C8FE5D98779C3D7
-:10ED200085AAE4F9C337EA6DCC2EC2553A0E1D37D9
-:10ED3000FCA8AC93E4FBE758FB395EA51A78F9FD13
-:10ED400072B3BC47204F4C7EEA5E5D0A7958DEA361
-:10ED500086BCAF619CEC99528FF96E7B0DC87EC763
-:10ED60000D3B657C6C39AFE3A3B485A6E004E40DEC
-:10ED7000531E0D4E80BC53768CDA5CDCBE1018B589
-:10ED8000217F78E16F476DE87FC14375E3E1BF56AE
-:10ED9000AD09DFC2B251593F9DF71A9277C2E8041C
-:10EDA000E46F854D6F59026CB7739EE67D93F2B7A1
-:10EDB000228963D30D5B9AFEA84AB087E9CF90E41D
-:10EDC000AB549D25E3BE14DDFF7D8F3EA8C28E6E41
-:10EDD00008B2DC09F637E769D3E54812DFB0AC6B5F
-:10EDE000317083F3B5A4713F3347BE3CC5C023E403
-:10EDF0008F8D8C37FEA6B7BE42BEC879DC187E8CDC
-:10EE00004D311C26C45DEFEB1117FC2079DEDABB17
-:10EE10001ED98AF76D53E3768BBC8FD7F46D45DB33
-:10EE2000DAFA9E258724BF4C9ACFF965127D9D9C06
-:10EE300063E4687BF0F3AD39E3ECCB76702DD10E53
-:10EE40004E9A4337E0BD7AD29FEA0E481C09DD0F87
-:10EE50007CD9D96A7723AEECFA55A5D8D7B7F5A9EE
-:10EE6000328FA9FA47D951A7CC0F545211FCE6872B
-:10EE7000DA11E0E1EC243C0C48DD72894370AEDD30
-:10EE80007807B6AD714A3E12F3EB3653E8C3AD983E
-:10EE900097E590EF110CB745A62C7C6F9AE2EE4AED
-:10EEA000C82BCE2E9915049DDD190A83EFE8CF15E6
-:10EEB00037EAC8D5693AAED6A80DAD7B79FC2D35B9
-:10EEC0002CB8F15BE007F36FB7AC977645D94CB13E
-:10EED000DB5C0A29FAFF67702DC47B3DF63DAD6708
-:10EEE0005BB0EF20DEFB4AF099B5A88FFE955DE49C
-:10EEF0008906D58099CFD3338104B77BEE2C94B8A3
-:10EF000013A586C6FB91FF2C4F953A6ACF04D71301
-:10EF1000F86EDAD37CA3E4F587FEA4C7FBD1A5295C
-:10EF20006EE4713DF35C1B71AE9E475D32FE9AA2AA
-:10EF3000F30B3CA1EBA767A97ECE9EE64C799FC55B
-:10EF4000EEA167876732BEBF5932BCE5D5A803186A
-:10EF5000DF1F7B66703FB74F290D77DE073E737565
-:10EF6000795794B9E4DE4EDE79E3137B747D86F144
-:10EF70001DAC7D8923E9FDFEBFFE80CBB3202200BE
-:10EF80000000000000000000040835000000000040
-:00000001FF
diff --git a/firmware/bnx2x-e1h-5.0.21.0.fw.ihex b/firmware/bnx2x-e1h-5.0.21.0.fw.ihex
new file mode 100644
index 00000000000..e78c86378f8
--- /dev/null
+++ b/firmware/bnx2x-e1h-5.0.21.0.fw.ihex
@@ -0,0 +1,12855 @@
+:1000000000003BB8000000600000068800003C20B3
+:100010000000192C000042B0000000AC00005BE0C2
+:1000200000008DC400005C90000000E40000EA586D
+:100030000000E4140000EB40000000940001CF58E1
+:10004000000058E80001CFF0000000C4000228E0E2
+:100050000000F978000229A800000004000323280A
+:10006000020400480000000F020400540000004594
+:1000700002040058000000840204005C0000000636
+:100080000204007000000004020400780000000078
+:100090000204007C121700000204008022170000F6
+:1000A00002040084321700000604008800000005E6
+:1000B0000204009C12150000020400A0221500009A
+:1000C000020400A432150000060400A80000000489
+:1000D000020400B802100000020400BC001000007E
+:1000E000020400C010100000020400C42010000030
+:1000F000020400C830100000020400CC40100000D0
+:10010000060400D000000003020400DC0010000020
+:10011000020400E012140000020400E422140000B3
+:10012000020400E832140000020400EC4214000053
+:10013000060400F000000003010401240000000098
+:1001400001040128000000000104012C000000004F
+:100150000104013000000000020401D00000890603
+:1001600002040004000000FF02040008000000FF79
+:100170000204000C000000FF02040010000000FF59
+:1001800002040014000000FF02040018000000FF39
+:100190000204001C000000FF02040020000000FF19
+:1001A000020400240000003E0204002800000000B9
+:1001B0000204002C0000003F020400300000003F59
+:1001C000020400340000003F020400380000003F39
+:1001D0000204003C0000003F020400400000003F19
+:1001E000020400440000003F020404CC00000001AF
+:1001F00002042008000002110204200C000002008A
+:10020000020420100000020402042014000002195D
+:100210000204201C0000FFFF020420200000FFFF5A
+:10022000020420240000FFFF020420280000FFFF3A
+:1002300002042038000000200204203C00000000DE
+:100240000204204000000034020420440000003575
+:10025000060420480000001C020420B80000000131
+:10026000060420BC0000005F0204223807FFFFFFE5
+:100270000204223C0000003F0204224007FFFFFF6F
+:10028000020422440000000F010422480000000084
+:100290000104224C00000000010422500000000074
+:1002A0000104225400000000010422580000000054
+:1002B0000104225C00000000010422600000000034
+:1002C0000104226400000000010422680000000014
+:1002D0000104226C000000000104227000000000F4
+:1002E00001042274000000000104227800000000D4
+:1002F0000104227C000000000C042000000003E840
+:100300000A042000000000010B0420000000000A85
+:1003100002050044000000200205004800000032F1
+:10032000020500900215002002050094021500202D
+:1003300002050098000000300205009C0810000033
+:10034000020500A000000033020500A400000030F8
+:10035000020500A800000031020500AC0000000208
+:10036000020500B000000005020500B40000000610
+:10037000020500B800000002020500BC00000002F7
+:10038000020500C000000000020500C400000005D6
+:10039000020500C800000002020500CC00000002B7
+:1003A000020500D000000002020500D40000000198
+:1003B00002050114000000010205011C00000001FB
+:1003C00002050120000000020205020400000001F5
+:1003D0000205020C0000004002050210000000406F
+:1003E0000205021C0000002002050220000000138C
+:1003F0000205022400000020060502400000000A59
+:1004000004050280002000000205005000000007E3
+:100410000205005400000007020500580000000813
+:100420000205005C000000080205006000000001F9
+:100430000605006400000003020500D80000000665
+:100440000205000400000001020500080000000190
+:100450000205000C00000001020500100000000170
+:100460000205001400000001020500180000000150
+:100470000205001C00000001020500200000000130
+:100480000205002400000001020500280000000110
+:100490000205002C000000010205003000000001F0
+:1004A00002050034000000010205003800000001D0
+:1004B0000205003C000000010205004000000001B0
+:1004C000020500E00000000D020500E80000000742
+:1004D000020500F000000007020500F80000000718
+:1004E000020500E40000002D020500EC00000027DA
+:1004F000020500F400000027020500FC00000027B0
+:10050000020500E00000001D020500E800000017E1
+:10051000020500F000000017020500F800000017B7
+:10052000020500E40000003D020500EC0000003779
+:10053000020500F400000037020500FC000000374F
+:10054000020500E00000004D020500E80000004741
+:10055000020500F000000047020500F80000004717
+:10056000020500E40000006D020500EC00000067D9
+:10057000020500F400000067020500FC00000067AF
+:10058000020500E00000005D020500E800000057E1
+:10059000020500F000000057020500F800000057B7
+:1005A000020500E40000007D020500EC0000007779
+:1005B000020500F400000077020500FC000000774F
+:1005C0000406100002000020020600DC000000010A
+:1005D000010600D80000000004060200000302200B
+:1005E000020600DC00000000010600B80000000068
+:1005F000010600C800000000010600BC0000000069
+:10060000010600CC000000000718040000A900004B
+:10061000081807C800070223071C00002C2D000043
+:10062000071C800038A20B0C071D000028EF1935AD
+:10063000081D681052FE022501180000000000008D
+:10064000011800040000000001180008000000006C
+:100650000118000C0000000001180010000000004C
+:100660000118001400000000021800200000000122
+:1006700002180024000000020218002800000003F5
+:100680000218002C000000000218003000000004D6
+:1006900002180034000000010218003800000000B9
+:1006A0000218003C00000001021800400000000495
+:1006B0000218004400000000021800480000000179
+:1006C0000218004C00000003021800500000000057
+:1006D0000218005400000001021800580000000435
+:1006E0000218005C00000000021800600000000119
+:1006F00002180064000000030218006800000000F7
+:100700000218006C000000010218007000000004D4
+:1007100002180074000000000218007800000004B5
+:100720000218007C00000003061800800000000290
+:10073000021800A400003FFF021800A8000003FFF9
+:100740000218022400000000021802340000000019
+:100750000218024C00000000021802E4000000FF32
+:100760000618100000000400021B8BC000000001EE
+:10077000021B800000000034021B804000000018B3
+:10078000021B80800000000C021B80C000000020C3
+:100790000C1B83000007A1200A1B83000000013806
+:1007A0000B1B830000001388021B83C0000001F4B0
+:1007B000021B1480000000010A1B148000000000CE
+:1007C000061A1000000003B3041A1ECC0001022711
+:1007D000061AA020000000C8061AA00000000002AF
+:1007E000021A1ED000000000061A1ED800000006E3
+:1007F000061A36E800000004061A36E0000000027F
+:10080000061A500000000002061A500800000004FA
+:10081000061A501800000004061A502800000004B0
+:10082000061A503800000004061A50480000000460
+:10083000061A505800000004061A50680000000410
+:10084000061A507800000002041A404000020228F4
+:10085000061A400000000002061A400800000002CC
+:10086000041A62C00020022A061AD1000000000209
+:10087000061A200000000124061AB000000000281B
+:10088000061AB1400000000C061A330000000014E4
+:10089000061A33A000000068061A81080000000252
+:1008A000061AD1C800000002061AD1D800000020A4
+:1008B000061A249000000124061AB0A000000028A7
+:1008C000061AB1700000000C061A33500000001424
+:1008D000061A354000000068061A81100000000268
+:1008E000061AD1D000000002061AD25800000020DB
+:1008F000021A292000000000061A30000000000241
+:10090000041A30080005024A061A301C00000009CB
+:10091000061A320000000008061A5000000000020B
+:10092000061A508000000012061A40000000000263
+:10093000061AD0C000000002021A2924000000009C
+:10094000061A304000000002041A30480005024F29
+:10095000061A305C00000009061A32200000000868
+:10096000061A501000000002061A50C800000012BB
+:10097000061A400800000002061AD0C80000000253
+:10098000021A292800000000061A30800000000228
+:10099000041A308800050254061A309C0000000931
+:1009A000061A324000000008061A5020000000021B
+:1009B000061A511000000012041A401000020259D9
+:1009C000061AD0D000000002021A292C00000000F4
+:1009D000061A30C000000002041A30C80005025B8D
+:1009E000061A30DC00000009061A32600000000818
+:1009F000061A503000000002061A5158000000127A
+:100A0000041A401800020260061AD0D80000000242
+:100A1000021A293000000000061A3100000000020E
+:100A2000041A310800050262061A311C0000000990
+:100A3000061A328000000008061A5040000000022A
+:100A4000061A51A000000012041A4020000202679A
+:100A5000061AD0E000000002021A2934000000004B
+:100A6000061A314000000002041A314800050269EC
+:100A7000061A315C00000009061A32A000000008C6
+:100A8000061A505000000002061A51E80000001239
+:100A9000041A40280002026E061AD0E80000000284
+:100AA000021A293800000000061A318000000002F6
+:100AB000041A318800050270061A319C00000009F2
+:100AC000061A32C000000008061A5060000000023A
+:100AD000061A523000000012041A4030000202755B
+:100AE000061AD0F000000002021A293C00000000A3
+:100AF000061A31C000000002041A31C8000502774E
+:100B0000061A31DC00000009061A32E00000000875
+:100B1000061A507000000002061A527800000012F7
+:100B2000041A40380002027C061AD0F800000002C5
+:100B30000200A294071D29110200A29800000000E3
+:100B40000200A29C009C04240200A2A0000000005D
+:100B50000200A2A4000002090200A270000000002E
+:100B60000200A274000000000200A2700000000059
+:100B70000200A274000000000200A2700000000049
+:100B80000200A274000000000200A2700000000039
+:100B90000200A27400000000020100B40000000185
+:100BA000020100B800000001020100DC00000001A9
+:100BB0000201010000000001020101040000000127
+:100BC0000201007C003000000201008400000028C7
+:100BD0000201008C0000000002010130000000044E
+:100BE0000201025C00000001020103280000000075
+:100BF0000201607000000007020160800000000137
+:100C00000201055400000030020100C40000000190
+:100C1000020100CC00000001020100F80000000108
+:100C2000020100F00000000102010080003000001D
+:100C3000020100880000002802010090000000006E
+:100C40000201013400000004020102DC0000000186
+:100C50000201032C00000000020160740000000784
+:100C60000201608400000001020105640000003000
+:100C7000020100C800000001020100D000000001D4
+:100C8000020100FC00000001020100F4000000016C
+:100C9000020C100000000020020C200800000211CD
+:100CA000020C200C00000200020C201000000204C4
+:100CB000020C201C0000FFFF020C20200000FFFFA0
+:100CC000020C20240000FFFF020C20280000FFFF80
+:100CD000060C203800000002020C20400000003406
+:100CE000020C204400000035020C204800000020C7
+:100CF000020C204C00000021020C205000000022B9
+:100D0000020C205400000023020C20580000002494
+:100D1000020C205C00000025020C20600000002670
+:100D2000020C206400000027020C2068000000284C
+:100D3000020C206C00000029020C20700000002A28
+:100D4000020C20740000002B060C207800000056D6
+:100D5000020C21D000000001020C21D4000000018F
+:100D6000020C21D800000001020C21DC000000016F
+:100D7000020C21E000000001020C21E4000000014F
+:100D8000020C21E800000001020C21EC000000012F
+:100D9000020C21F000000001020C21F4000000010F
+:100DA000060C21F800000010020C223807FFFFFF9C
+:100DB000020C223C0000003F020C224007FFFFFF14
+:100DC000020C22440000000F010C22480000000029
+:100DD000010C224C00000000010C22500000000019
+:100DE000010C225400000000010C225800000000F9
+:100DF000010C225C00000000010C226000000000D9
+:100E0000010C226400000000010C226800000000B8
+:100E1000010C226C00000000010C22700000000098
+:100E2000010C227400000000010C22780000000078
+:100E3000010C227C000000000C0C2000000003E8E4
+:100E40000A0C2000000000010B0C20000000000A2A
+:100E5000020C400800000411020C400C00000400C9
+:100E6000020C401000000404020C40140000042195
+:100E7000020C401C0000FFFF020C40200000FFFF9E
+:100E8000020C40240000FFFF020C40280000FFFF7E
+:100E9000020C403800000046020C403C00000005F7
+:100EA000060C404000000002020C40480000000A0E
+:100EB000020C404C000000F0060C40500000001FE7
+:100EC000020C40CC00000001060C40D00000003AAB
+:100ED000020C41B800000001060C41BC00000003F8
+:100EE000020C41C800000001020C41CC00000001CE
+:100EF000060C41D00000001A020C423807FFFFFF29
+:100F0000020C423C0000003F020C424007FFFFFF82
+:100F1000020C42440000000F010C42480000000097
+:100F2000010C424C00000000010C42500000000087
+:100F3000010C425400000000010C42580000000067
+:100F4000010C425C00000000010C42600000000047
+:100F5000010C426400000000010C42680000000027
+:100F6000010C426C00000000010C42700000000007
+:100F7000010C427400000000010C427800000000E7
+:100F8000010C427C00000000010C428000000000C7
+:100F90000C0C4000000003E80A0C400000000001B7
+:100FA0000B0C40000000000A020D0044000000325B
+:100FB000020D008C02150020020D00900215002089
+:100FC000020D009408100000020D0098000000338C
+:100FD000020D009C00000002020D00A000000000B5
+:100FE000020D00A400000005020D00A8000000058D
+:100FF000060D00AC00000002020D00B4000000026B
+:10100000020D00B800000003020D00BC0000000249
+:10101000020D00C000000001020D00C80000000227
+:10102000020D00CC00000002020D010800000001CA
+:10103000020D015C00000001020D016400000001CE
+:10104000020D016800000002020D02040000000110
+:10105000020D020C00000020020D021000000040F2
+:10106000020D021400000040020D022000000003E7
+:10107000020D022400000018060D0280000000127C
+:10108000040D03000024027E020D004C000000014C
+:10109000020D005000000002020D00540000000884
+:1010A000020D005800000008060D005C000000045E
+:1010B000020D00C400000004020D00040000000145
+:1010C000020D000800000001020D000C00000001EC
+:1010D000020D001000000001020D001400000001CC
+:1010E000020D001800000001020D001C00000001AC
+:1010F000020D002000000001020D0024000000018C
+:10110000020D002800000001020D002C000000016B
+:10111000020D003000000001020D0034000000014B
+:10112000020D003800000001020D003C000000012B
+:10113000020D011400000009020D011C0000000A4C
+:10114000020D012400000007020D012C0000000721
+:10115000020D01340000000C020D013C0000000BE8
+:10116000020D014400000007020D011800000029D3
+:10117000020D01200000002A020D012800000027B6
+:10118000020D013000000027020D01380000002C84
+:10119000020D01400000002B020D01480000002755
+:1011A000020D011400000019020D011C0000001ABC
+:1011B000020D012400000017020D012C0000001791
+:1011C000020D01340000001C020D013C0000001B58
+:1011D000020D014400000017020D01180000003943
+:1011E000020D01200000003A020D01280000003726
+:1011F000020D013000000037020D01380000003CF4
+:10120000020D01400000003B020D014800000037C4
+:10121000020D011400000049020D011C0000004AEB
+:10122000020D012400000047020D012C00000047C0
+:10123000020D01340000004C020D013C0000004B87
+:10124000020D014400000047020D01180000006972
+:10125000020D01200000006A020D01280000006755
+:10126000020D013000000067020D01380000006C23
+:10127000020D01400000006B020D014800000067F4
+:10128000020D011400000059020D011C0000005A5B
+:10129000020D012400000057020D012C0000005730
+:1012A000020D01340000005C020D013C0000005BF7
+:1012B000020D014400000057020D011800000079E2
+:1012C000020D01200000007A020D012800000077C5
+:1012D000020D013000000077020D01380000007C93
+:1012E000020D01400000007B020D01480000007764
+:1012F000020E004C00000032020E00940215002085
+:10130000020E009802150020020E009C0000003022
+:10131000020E00A008100000020E00A4000000331E
+:10132000020E00A800000030020E00AC00000031E8
+:10133000020E00B000000002020E00B40000000423
+:10134000020E00B800000000020E00BC0000000207
+:10135000020E00C000000002020E00C400000000E7
+:10136000020E00C800000002020E00CC00000007C0
+:10137000020E00D000000002020E00D400000002A5
+:10138000020E00D800000001020E00E4000000017F
+:10139000020E014400000001020E014C0000000199
+:1013A000020E015000000002020E020400000001C3
+:1013B000020E020C00000040020E0210000000406D
+:1013C000020E021C00000004020E02200000002099
+:1013D000020E02240000000E020E02280000001B74
+:1013E000060E030000000012040E0280001B02A281
+:1013F000020E00540000000C020E0058000000070E
+:10140000020E005C0000000F020E006000000010E1
+:10141000020E00640000000B060E006800000003CE
+:10142000020E00DC00000003020E000400000001B8
+:10143000020E000800000001020E000C0000000176
+:10144000020E001000000001020E00140000000156
+:10145000020E001800000001020E001C0000000136
+:10146000020E002000000001020E00240000000116
+:10147000020E002800000001020E002C00000001F6
+:10148000020E003000000001020E003400000001D6
+:10149000020E003800000001020E003C00000001B6
+:1014A000020E004000000001020E00440000000196
+:1014B000020E01100000000F020E01180000000EC5
+:1014C000020E012000000000020E012800000000B2
+:1014D000020E01140000002F020E011C0000002E5D
+:1014E000020E012400000000020E012C000000008A
+:1014F000020E01100000001F020E01180000001E65
+:10150000020E012000000000020E01280000000071
+:10151000020E01140000003F020E011C0000003EFC
+:10152000020E012400000000020E012C0000000049
+:10153000020E01100000004F020E01180000004EC4
+:10154000020E012000000000020E01280000000031
+:10155000020E01140000006F020E011C0000006E5C
+:10156000020E012400000000020E012C0000000009
+:10157000020E01100000005F020E01180000005E64
+:10158000020E012000000000020E012800000000F1
+:10159000020E01140000007F020E011C0000007EFC
+:1015A000020E012400000000020E012C00000000C9
+:1015B0000730040000E10000083007D8000502BD34
+:1015C000073400002ECA000007348000311A0BB324
+:1015D00007350000368B17FA0735800039C6259D80
+:1015E0000736000013D5340F0836307039F202BFC9
+:1015F0000130000000000000013000040000000085
+:1016000001300008000000000130000C0000000064
+:101610000130001000000000013000140000000044
+:10162000023000200000000102300024000000020F
+:1016300002300028000000030230002C00000000EF
+:1016400002300030000000040230003400000001CD
+:1016500002300038000000000230003C00000001B1
+:10166000023000400000000402300044000000008E
+:1016700002300048000000010230004C000000036E
+:101680000230005000000000023000540000000151
+:1016900002300058000000040230005C000000002E
+:1016A000023000600000000102300064000000030E
+:1016B00002300068000000000230006C00000001F1
+:1016C00002300070000000040230007400000000CE
+:1016D00002300078000000040230007C00000003AB
+:1016E0000630008000000002023000A400003FFF2E
+:1016F000023000A8000003FF0230022400000000B6
+:1017000002300234000000000230024C00000000F1
+:10171000023002E40000FFFF063020000000080055
+:1017200002338BC000000001023380000000001A69
+:10173000023380400000004E023380800000001021
+:10174000023380C0000000200C3383000007A1207A
+:101750000A338300000001380B3383000000138834
+:10176000023383C0000001F40C3383801DCD65007B
+:101770000A3383800004C4B40B338380004C4B4095
+:101780000A331480000000000233148000000001BE
+:10179000063220000000010206328020000000C84E
+:1017A000063280000000000206323DA8000000045E
+:1017B00006323D800000000904323DA4000102C150
+:1017C00006323D00000000200632500000000400F8
+:1017D000063240000000000204324008000102C24C
+:1017E0000632400C00000003063240D80000000220
+:1017F00006326B680000000204326B70000202C304
+:1018000006326B1000000002043274C0000202C5F0
+:101810000632DA40000000020632E0000000080054
+:10182000023308000100000004330C00001002C75E
+:10183000023308000000000004330C40001002D7FF
+:1018400006322450000000B406322AD00000000204
+:1018500006321000000001A002323DB80000000076
+:101860000632500000000020063251000000002027
+:101870000632520000000020063253000000002013
+:1018800006325400000000200632550000000020FF
+:1018900006325600000000200632570000000020EB
+:1018A00006325800000000200632590000000020D7
+:1018B00006325A000000002006325B0000000020C3
+:1018C00006325C000000002006325D0000000020AF
+:1018D00006325E000000002006325F00000000209B
+:1018E00006326B780000005206326E080000000CD1
+:1018F0000632DA880000000206322720000000B419
+:1019000006322AD80000000206321680000001A02C
+:1019100002323DBC00000000063250800000002072
+:101920000632518000000020063252800000002064
+:101930000632538000000020063254800000002050
+:10194000063255800000002006325680000000203C
+:101950000632578000000020063258800000002028
+:10196000063259800000002006325A800000002014
+:1019700006325B800000002006325C800000002000
+:1019800006325D800000002006325E8000000020EC
+:1019900006325F800000002006326CC0000000525A
+:1019A00006326E380000000C0632DA9000000002A9
+:1019B00002322A3000000000063240180000000207
+:1019C0000632D0000000000602322A340000000077
+:1019D00006324028000000020632D018000000063F
+:1019E00002322A38000000000632403800000002AF
+:1019F0000632D0300000000602322A3C000000000F
+:101A000006324048000000020632D04800000006BE
+:101A100002322A4000000000063240580000000256
+:101A20000632D0600000000602322A4400000000A6
+:101A300006324068000000020632D078000000063E
+:101A400002322A48000000000632407800000002FE
+:101A50000632D0900000000602322A4C000000003E
+:101A600006324088000000020632D0A800000006BE
+:101A7000072004000093000008200780001002E700
+:101A8000072400002ADF0000072480002E050AB882
+:101A90000824E4A061D202E9012000000000000057
+:101AA00001200004000000000120000800000000E8
+:101AB0000120000C000000000120001000000000C8
+:101AC000012000140000000002200020000000019E
+:101AD0000220002400000002022000280000000371
+:101AE0000220002C00000000022000300000000452
+:101AF0000220003400000001022000380000000035
+:101B00000220003C00000001022000400000000410
+:101B100002200044000000000220004800000001F4
+:101B20000220004C000000030220005000000000D2
+:101B300002200054000000010220005800000004B0
+:101B40000220005C00000000022000600000000194
+:101B50000220006400000003022000680000000072
+:101B60000220006C00000001022000700000000450
+:101B70000220007400000000022000780000000431
+:101B80000220007C0000000306200080000000020C
+:101B9000022000A400003FFF022000A8000003FF75
+:101BA0000220022400000000022002340000000095
+:101BB0000220024C00000000022002E40000FFFFAF
+:101BC000062020000000080002238BC00000000156
+:101BD0000223800000000010022380400000001259
+:101BE0000223808000000030022380C00000000E2D
+:101BF000022383C0000001F40223148000000001CE
+:101C00000A23148000000000062210000000004299
+:101C100006227020000000C80622700000000002AA
+:101C2000022211E80000000006223000000000C07F
+:101C3000062240700000008006225280000000044E
+:101C40000622670000000100062290000000040048
+:101C500004226B08002002EB02230800013FFFFF73
+:101C600004230C000010030B0223080000000000F6
+:101C700004230C400010031B06228100000000A07A
+:101C8000062286000000004006228C000000003C76
+:101C90000622B0000000020006228800000000803A
+:101CA00006228DE00000003C0622404000000006B5
+:101CB00006228380000000A006228700000000406A
+:101CC00006228CF00000003C0622B8000000020052
+:101CD00006228A000000008006228ED00000003C10
+:101CE000062240580000000606228000000000087E
+:101CF000022211480000000006223300000000020A
+:101D0000062260400000003006228020000000080B
+:101D10000222114C000000000622330800000002DD
+:101D2000062261000000003006228040000000080A
+:101D300002221150000000000622331000000002B1
+:101D4000062261C00000003006228060000000080A
+:101D50000222115400000000062233180000000285
+:101D60000622628000000030062280800000000809
+:101D70000222115800000000062233200000000259
+:101D80000622634000000030062280A00000000808
+:101D90000222115C0000000006223328000000022D
+:101DA0000622640000000030062280C00000000807
+:101DB0000222116000000000062233300000000201
+:101DC000062264C000000030062280E00000000807
+:101DD00002221164000000000622333800000002D5
+:101DE0000622658000000030021610000000002866
+:101DF00002170008000000020217002C0000000378
+:101E00000217003C00000004021700440000000814
+:101E100002170048000000020217004C000000906A
+:101E2000021700500000009002170054008000903C
+:101E30000217005808140000021700600000008A12
+:101E40000217006400000080021700680000008193
+:101E50000217006C000000800217007000000006EE
+:101E600002170078000007D00217007C0000076C02
+:101E700002170038007C1004021700040000000F55
+:101E80000616402400000002021640700000001CEC
+:101E90000216420800000001021642100000000174
+:101EA0000216422000000001021642280000000134
+:101EB0000216423000000001021642380000000104
+:101EC00002164260000000020C16401C0003D09075
+:101ED0000A16401C0000009C0B16401C000009C4A0
+:101EE0000216403000000008021640340000000CCA
+:101EF0000216403800000010021640440000002086
+:101F00000216400000000001021640D80000000147
+:101F100002164008000000010216400C00000001FB
+:101F200002164010000000010216424000000000AE
+:101F3000021642480000000006164270000000022F
+:101F40000216425000000000021642580000000035
+:101F500006164280000000020216600800000424F9
+:101F60000216600C00000410021660100000041439
+:101F70000216601C0000FFFF021660200000FFFF39
+:101F8000021660240000FFFF021660280000FFFF19
+:101F900002166038000000200216603C000000209D
+:101FA0000216604000000034021660440000003554
+:101FB00002166048000000230216604C0000002456
+:101FC0000216605000000025021660540000002632
+:101FD00002166058000000270216605C000000290D
+:101FE000021660600000002A021660640000002BE8
+:101FF000021660680000002C0216606C0000002DC4
+:102000000616607000000052021661B80000000160
+:10201000061661BC0000001F0216623807FFFFFFB2
+:102020000216623C0000003F0216624007FFFFFFFD
+:10203000021662440000000F011662480000000012
+:102040000116624C00000000011662500000000002
+:1020500001166254000000000116625800000000E2
+:102060000116625C000000000116626000000000C2
+:1020700001166264000000000116626800000000A2
+:102080000116626C00000000011662700000000082
+:102090000116627400000000011662780000000062
+:1020A0000116627C000000000C166000000003E8CE
+:1020B0000A166000000000010B1660000000000A14
+:1020C0000216804000000006021680440000000551
+:1020D000021680480000000A0216804C000000052D
+:1020E0000216805400000002021680CC000000049A
+:1020F000021680D000000004021680D40000000404
+:10210000021680D800000004021680DC00000004E3
+:10211000021680E000000004021680E400000004C3
+:10212000021680E800000004021688040000000483
+:10213000021680300000007C021680340000003D52
+:10214000021680380000003F0216803C0000009C10
+:10215000021680F000000007061680F4000000055B
+:102160000216880C0101010102168108000000001E
+:102170000216810C00000004021681100000000409
+:1021800002168114000000020216881008012004C3
+:1021900002168118000000050216811C00000005CF
+:1021A00002168120000000050216812400000005AF
+:1021B0000216882C20081001021681280000000851
+:1021C0000216812C00000006021681300000000774
+:1021D000021681340000000002168830010101203F
+:1021E000061681380000000402168834010101013E
+:1021F00002168148000000000216814C0000000415
+:1022000002168150000000040216815400000002F2
+:1022100002168838080120040216815800000005C3
+:102220000216815C000000050216816000000005B6
+:1022300002168164000000050216883C2008100187
+:1022400002168168000000080216816C000000067A
+:102250000216817000000007021681740000000160
+:102260000216884001010120021681780000000159
+:102270000216817C0000000102168180000000012E
+:102280000216818400000001021688440101010148
+:1022900002168188000000010216818C00000004F3
+:1022A00002168190000000040216819400000002D2
+:1022B00002168848080120040216819800000005D3
+:1022C0000216819C00000005021681A00000000596
+:1022D000021681A4000000050216881420081001CF
+:1022E000021681A800000008021681AC000000065A
+:1022F000021681B000000007021681B40000000140
+:102300000216881801010120021681B800000001A0
+:10231000021681BC00000001021681C0000000010D
+:10232000021681C4000000010216881C010101018F
+:10233000021681C800000001021681CC00000004D2
+:10234000021681D000000004021681D400000002B1
+:102350000216882008012004021681D8000000051A
+:10236000021681DC00000005021681E00000000575
+:10237000021681E4000000050216882420081001DE
+:10238000021681E800000008021681EC0000000639
+:10239000021681F0000000070216E40C00000000A5
+:1023A00002168828010101200616E410000000042E
+:1023B0000216E000010101010216E4200000000005
+:1023C0000216E424000000040216E42800000004C1
+:1023D0000216E42C000000020216E00408012004AA
+:1023E0000216E430000000050216E4340000000587
+:1023F0000216E438000000050216E43C0000000567
+:102400000216E008200810010216E440000000084F
+:102410000216E444000000060216E448000000072B
+:102420000216E44C000000000216E00C010101203D
+:102430000616E450000000040216E010010101013C
+:102440000216E460000000000216E46400000004CC
+:102450000216E468000000040216E46C00000002AA
+:102460000216E014080120040216E47000000005C2
+:102470000216E474000000050216E478000000056E
+:102480000216E47C000000050216E0182008100186
+:102490000216E480000000080216E4840000000632
+:1024A0000216E488000000070216E48C0000000118
+:1024B0000216E01C010101200216E4900000000158
+:1024C0000216E494000000010216E49800000001E6
+:1024D0000216E49C000000010216E0200101010147
+:1024E0000216E4A0000000010216E4A400000004AB
+:1024F0000216E4A8000000040216E4AC000000028A
+:102500000216E024080120040216E4B000000005D1
+:102510000216E4B4000000050216E4B8000000054D
+:102520000216E4BC000000050216E0282008100195
+:102530000216E4C0000000080216E4C40000000611
+:102540000216E4C8000000070216E4CC00000001F7
+:102550000216E02C010101200216E4D00000000167
+:102560000216E4D4000000010216E4D800000001C5
+:102570000216E4DC000000010216E0300101010156
+:102580000216E4E0000000010216E4E4000000048A
+:102590000216E4E8000000040216E4EC0000000269
+:1025A0000216E034080120040216E4F000000005E1
+:1025B0000216E4F4000000050216E4F8000000052D
+:1025C0000216E4FC000000050216E03820081001A5
+:1025D0000216E500000000080216E50400000006EF
+:1025E0000216E508000000070216E03C0101012088
+:1025F00002168240003F003F0216824400000000A5
+:102600000216E524003F003F0216E5280000000006
+:1026100002168248000000000216824C003F003F74
+:102620000216E52C000000000216E530003F003FD6
+:1026300002168250010001000216825401000100BE
+:102640000216E534010001000216E5380100010020
+:1026500006168258000000020216E53C0000000049
+:102660000216E540000000000216826000C000C0B3
+:102670000216826400C000C00216E54400C000C01B
+:102680000216E54800C000C0021682681E001E0047
+:102690000216826C1E001E000216E54C1E001E0073
+:1026A0000216E5501E001E00021682704000400017
+:1026B00002168274400040000216E55440004000BB
+:1026C0000216E55840004000021682788000800023
+:1026D0000216827C800080000216E55C800080008B
+:1026E0000216E56080008000021682802000200033
+:1026F00002168284200020000216E56420002000DB
+:102700000216E568200020000616828800000002FC
+:102710000216E56C000000000216E57000000000E3
+:102720000216829000000000021682940000000051
+:102730000216E574000000000216E57800000000B3
+:1027400002168298000000000216829C0000000021
+:102750000216E57C000000000216E5800000000083
+:10276000021682A000000000021682A400000001F0
+:10277000061682A80000000A021681F400000C0868
+:10278000021681F800000040021681FC00000100E2
+:1027900002168200000000200216820400000017CA
+:1027A00002168208000000800216820C000002005F
+:1027B00002168210000000000216821801FF01FFBD
+:1027C0000216821401FF01FF0216E51001FF01FF4E
+:1027D0000216E50C01FF01FF0216823C0000001307
+:1027E000021680900000013F021680600000014048
+:1027F0000216806400000140061680680000000296
+:1028000002168070000000C00616807400000007E9
+:102810000216809C00000048021680A000000048BC
+:10282000061680A400000002021680AC00000048DA
+:10283000061680B0000000070216823800008000F3
+:1028400002168234000025E40216809400007FFF07
+:1028500002168220000F000F0216821C000F000FCC
+:102860000216E518000F000F0216E514000F000F06
+:10287000021682280000000002168224FFFFFFFFDC
+:102880000216E520000000000216E51CFFFFFFFF16
+:102890000216E6BC000000000216E6C000000002BE
+:1028A0000216E6C4000000010216E6C8000000039C
+:1028B0000216E6CC000000040216E6D00000000676
+:1028C0000216E6D4000000050216E6D80000000754
+:1028D000021680EC000000FF02140000000000015E
+:1028E0000214000C0000000102140040000000016E
+:1028F0000214004400007FFF0214000C00000000DE
+:1029000002140000000000000214006C000000002F
+:102910000214000400000001021400300000000155
+:1029200002140004000000000214005C000000001B
+:10293000021400080000000102140034000000012D
+:1029400002140008000000000214006000000000F3
+:102950000202005800000032020200A0031500200D
+:10296000020200A403150020020200A801000030AA
+:10297000020200AC08100000020200B000000033A8
+:10298000020200B400000030020200B80000003172
+:10299000020200BC00000003020200C000000006AA
+:1029A000020200C400000003020200C8000000038D
+:1029B000020200CC00000002020200D00000000071
+:1029C000020200D400000002020200DC000000004D
+:1029D000020200E000000006020200E40000000421
+:1029E000020200E800000002020200EC0000000207
+:1029F000020200F000000001020200FC00000006DC
+:102A00000202012000000000020201340000000266
+:102A1000020201B0000000010202020C00000001ED
+:102A2000020202140000000102020218000000026B
+:102A300002020404000000010202040C0000004035
+:102A400002020410000000400202041C0000000406
+:102A50000202042000000020020204240000000200
+:102A600002020428000000200602050000000012F7
+:102A700004020480001F032B020200600000000F0C
+:102A80000202006400000007020200680000000B60
+:102A90000202006C0000000E020200700000000E36
+:102AA0000602007400000003020200F400000004AB
+:102AB0000202000400000001020200080000000100
+:102AC0000202000C000000010202001000000001E0
+:102AD00002020014000000010202001800000001C0
+:102AE0000202001C000000010202002000000001A0
+:102AF0000202002400000001020200280000000180
+:102B00000202002C0000000102020030000000015F
+:102B1000020200340000000102020038000000013F
+:102B20000202003C0000000102020040000000011F
+:102B300002020044000000010202004800000001FF
+:102B40000202004C000000010202005000000001DF
+:102B500002020108000000C8020201180000000281
+:102B6000020201C400000000020201CC00000000CB
+:102B7000020201D400000002020201DC0000000297
+:102B8000020201E4000000FF020201EC000000FF6D
+:102B900002020100000000000202010C000000C857
+:102BA0000202011C00000002020201C80000000035
+:102BB000020201D000000000020201D80000000261
+:102BC000020201E000000002020201E8000000FF32
+:102BD000020201F0000000FF0202010400000000F8
+:102BE00002020108000000C80202011800000002F1
+:102BF000020201C400000000020201CC000000003B
+:102C0000020201D400000002020201DC0000000206
+:102C1000020201E4000000FF020201EC000000FFDC
+:102C200002020100000000000202010C000000C8C6
+:102C30000202011C00000002020201C800000000A4
+:102C4000020201D000000000020201D800000002D0
+:102C5000020201E000000002020201E8000000FFA1
+:102C6000020201F0000000FF020201040000000067
+:102C700002020108000000C8020201180000000260
+:102C8000020201C400000000020201CC00000000AA
+:102C9000020201D400000002020201DC0000000276
+:102CA000020201E4000000FF020201EC000000FF4C
+:102CB00002020100000000000202010C000000C836
+:102CC0000202011C00000002020201C80000000014
+:102CD000020201D000000000020201D80000000240
+:102CE000020201E000000002020201E8000000FF11
+:102CF000020201F0000000FF0202010400000000D7
+:102D000002020108000000C80202011800000002CF
+:102D1000020201C400000000020201CC0000000019
+:102D2000020201D400000002020201DC00000002E5
+:102D3000020201E4000000FF020201EC000000FFBB
+:102D400002020100000000000202010C000000C8A5
+:102D50000202011C00000002020201C80000000083
+:102D6000020201D000000000020201D800000002AF
+:102D7000020201E000000002020201E8000000FF80
+:102D8000020201F0000000FF020201040000000046
+:102D90000728040000C00000082807A8000B034A09
+:102DA000072C000032FD0000072C8000357E0CC08F
+:102DB000072D00003AE41A20072D800039CF28DAC9
+:102DC000072E00001C3C374E082E3710391E034CCE
+:102DD000012800000000000001280004000000009D
+:102DE00001280008000000000128000C000000007D
+:102DF000012800100000000001280014000000005D
+:102E00000228002000000001022800240000000227
+:102E100002280028000000030228002C0000000007
+:102E200002280030000000040228003400000001E5
+:102E300002280038000000000228003C00000001C9
+:102E400002280040000000040228004400000000A6
+:102E500002280048000000010228004C0000000386
+:102E60000228005000000000022800540000000169
+:102E700002280058000000040228005C0000000046
+:102E80000228006000000001022800640000000326
+:102E900002280068000000000228006C0000000109
+:102EA00002280070000000040228007400000000E6
+:102EB00002280078000000040228007C00000003C3
+:102EC0000628008000000002022800A400003FFF46
+:102ED000022800A8000003FF0228022400000000CE
+:102EE00002280234000000000228024C000000000A
+:102EF000022802E40000FFFF06282000000008006E
+:102F0000022B8BC000000001022B8000000000009B
+:102F1000022B804000000018022B80800000000C73
+:102F2000022B80C0000000660C2B83000007A1204C
+:102F30000A2B8300000001380B2B8300000013884C
+:102F4000022B83C0000001F40C2B8340000001F42D
+:102F50000A2B8340000000000B2B8340000000057B
+:102F60000A2B83800004C4B40C2B83801DCD650024
+:102F70000A2B1480000000000B2B8380004C4B4078
+:102F8000022B148000000001062A29C8000000045A
+:102F9000042A29D80002034E062A20800000004897
+:102FA000062A9020000000C8062A900000000002B7
+:102FB000062A21A800000086062A20000000002022
+:102FC000022A23C800000000042A23D00002035074
+:102FD000042A249800040352022A2C500000000006
+:102FE000022A2C1000000000042A2C0800020356BC
+:102FF000042A300000020358062A300800000100AD
+:10300000062A404000000010042A40000010035A25
+:10301000062A6AC000000002062A6B0000000004B5
+:10302000042A84080002036A022B08000000000042
+:10303000042B0C000010036C022B080001000000A0
+:10304000042B0C400008037C022B08000200000047
+:10305000042B0C6000080384062AC000000000D87E
+:10306000062A24A800000014062A2548000000248F
+:10307000062A266800000024062A2788000000246B
+:10308000062A28A800000024062AA0000000002824
+:10309000062AA1400000000C042A29E00002038C4B
+:1030A000062A502000000002062A503000000002CC
+:1030B000062A500000000002062A501000000002FC
+:1030C000022A520800000001042A6AC80002038E86
+:1030D000062A6B1000000042062A6D200000000442
+:1030E000062ABCD000000002062AC360000000D8F7
+:1030F000062A24F800000014062A25D8000000241F
+:10310000062A26F800000024062A281800000024B9
+:10311000062A293800000024062AA0A00000002862
+:10312000062AA1700000000C042A29E8000203907E
+:10313000062A502800000002062A5038000000022B
+:10314000062A500800000002062A5018000000025B
+:10315000022A520C00000001042A6AD000020392E5
+:10316000062A6C1800000042062A6D300000000498
+:10317000062ABCD800000002022AC6C000000000D7
+:10318000042A29F000100394062A50480000000E7B
+:10319000062AB00000000006022AC6C40000000093
+:1031A000042A2A30001003A4062A50800000000ED2
+:1031B000062AB01800000006022AC6C80000000057
+:1031C000042A2A70001003B4062A50B80000000E2A
+:1031D000062AB03000000006022AC6CC000000001B
+:1031E000042A2AB0001003C4062A50F00000000E82
+:1031F000062AB04800000006022AC6D000000000DF
+:10320000042A2AF0001003D4062A51280000000ED8
+:10321000062AB06000000006022AC6D400000000A2
+:10322000042A2B30001003E4062A51600000000E2F
+:10323000062AB07800000006022AC6D80000000066
+:10324000042A2B70001003F4062A51980000000E87
+:10325000062AB09000000006022AC6DC000000002A
+:10326000042A2BB000100404062A51D00000000EDE
+:10327000062AB0A800000006021010080000000195
+:103280000210105000000001021010000003D000D6
+:10329000021010040000003D091018000200041480
+:1032A0000910110000280614061011A000000018D3
+:1032B00006102400000000E00210201C00000000A6
+:1032C0000210202000000001021020C000000002B7
+:1032D000021020040000000102102008000000017C
+:1032E00009103C000005063C0910380000050641A5
+:1032F000091038200005064606104C0000000100A9
+:1033000002104028000000100210404400003FFF5F
+:103310000210405800280000021040840084924AA5
+:1033200002104058000000000210800000001080D1
+:10333000021080AC00000000021080380000001075
+:103340000210810000000000061081200000000231
+:1033500002108008000002B502108010000000007A
+:10336000061082000000004A021081080001FFFFE1
+:1033700006108140000000020210800000001A8048
+:103380000610900000000024061091200000004A62
+:10339000061093700000004A061095C00000004A15
+:1033A0000210800400001080021080B000000001B4
+:1033B0000210803C00000010021081040000000098
+:1033C00006108128000000020210800C000002B5E7
+:1033D0000210801400000000061084000000004A63
+:1033E0000210810C0001FFFF06108148000000025E
+:1033F0000210800400001A80061090900000002443
+:10340000061092480000004A061094980000004AF6
+:10341000061096E80000004A0210800000001080AC
+:10342000021080AC00000002021080380000001082
+:103430000210810000000000061081200000000240
+:1034400002108008000002B5021080100000000089
+:10345000061082000000004A021081080001FFFFF0
+:1034600006108140000000020210800000001A8057
+:103470000610900000000024061091200000004A71
+:10348000061093700000004A061095C00000004A24
+:103490000210800400001080021080B000000003C1
+:1034A0000210803C000000100210810400000000A7
+:1034B00006108128000000020210800C000002B5F6
+:1034C0000210801400000000061084000000004A72
+:1034D0000210810C0001FFFF06108148000000026D
+:1034E0000210800400001A80061090900000002452
+:1034F000061092480000004A061094980000004A06
+:10350000061096E80000004A0210800000001080BB
+:10351000021080AC0000000402108038000000108F
+:10352000021081000000000006108120000000024F
+:1035300002108008000002B5021080100000000098
+:10354000061082000000004A021081080001FFFFFF
+:1035500006108140000000020210800000001A8066
+:103560000610900000000024061091200000004A80
+:10357000061093700000004A061095C00000004A33
+:103580000210800400001080021080B000000005CE
+:103590000210803C000000100210810400000000B6
+:1035A00006108128000000020210800C000002B505
+:1035B0000210801400000000061084000000004A81
+:1035C0000210810C0001FFFF06108148000000027C
+:1035D0000210800400001A80061090900000002461
+:1035E000061092480000004A061094980000004A15
+:1035F000061096E80000004A0210800000001080CB
+:10360000021080AC0000000602108038000000109C
+:10361000021081000000000006108120000000025E
+:1036200002108008000002B50210801000000000A7
+:10363000061082000000004A021081080001FFFF0E
+:1036400006108140000000020210800000001A8075
+:103650000610900000000024061091200000004A8F
+:10366000061093700000004A061095C00000004A42
+:103670000210800400001080021080B000000007DB
+:103680000210803C000000100210810400000000C5
+:1036900006108128000000020210800C000002B514
+:1036A0000210801400000000061084000000004A90
+:1036B0000210810C0001FFFF06108148000000028B
+:1036C0000210800400001A80061090900000002470
+:1036D000061092480000004A061094980000004A24
+:1036E000061096E80000004A021205B00000000132
+:1036F0000212049000E383400212051400003C1003
+:103700000212066C000000010212067000000000A8
+:1037100002120494FFFFFFFF02120498FFFFFFFF55
+:103720000212049CFFFFFFFF021204A0FFFFFFFF35
+:10373000021204A4FFFFFFFF021204A8FFFFFFFF15
+:10374000021204ACFFFFFFFF021204B0FFFFFFFFF5
+:10375000021204BCFFFFFFFF021204C0FFFFFFFFC5
+:10376000021204C4FFFFFFFF021204C8FFFFFFFFA5
+:10377000021204CCFFFFFFFF021204D0FFFFFFFF85
+:10378000021204D8FFFFFFFF021204DCFFFFFFFF5D
+:10379000021204E0FFFFFFFF021204E4FFFFFFFF3D
+:1037A000021204E8FFFFFFFF021204ECFFFFFFFF1D
+:1037B000021204F0FFFFFFFF021204F4FFFFFFFFFD
+:1037C000021204F8FFFFFFFF021204FCFFFFFFFFDD
+:1037D00002120500FFFFFFFF02120504FFFFFFFFBB
+:1037E00002120508FFFFFFFF0212050CFFFFFFFF9B
+:1037F00002120510FFFFFFFF021204D4FF80200019
+:10380000021204B4F0005000021204B8F0001000DC
+:1038100002120390000000080212039C000000083E
+:10382000021203A000000008021203A4000000021C
+:10383000021203BC00000004021203C000000005D5
+:10384000021203C400000004021203D000000000B2
+:103850000212036C00000001021203680000003F26
+:10386000021201BC00000040021201C00000180852
+:10387000021201C400000803021201C8000008037C
+:10388000021201CC00000040021201D0000000032F
+:10389000021201D400000803021201D8000008033C
+:1038A000021201DC00000803021201E00001000323
+:1038B000021201E400000803021201E800000803FC
+:1038C000021201EC00000003021201F000000003EC
+:1038D000021201F400000003021201F800000003CC
+:1038E000021201FC000000030212020000000003AB
+:1038F000021202040000000302120208000000038A
+:103900000212020C00000003021202100000000369
+:103910000212021400000003021202180000000349
+:103920000212021C00000003021202200000000329
+:1039300002120224000000030212022800002403E5
+:103940000212022C0000002F0212023000000009B7
+:103950000212023400000019021202380000018431
+:103960000212023C00000183021202400000030622
+:103970000212024400000019021202480000000670
+:103980000212024C0000030602120250000003065D
+:1039900002120254000003060212025800000C86B4
+:1039A0000212025C0000030602120260000003061D
+:1039B0000212026400000006021202680000000603
+:1039C0000212026C000000060212027000000006E3
+:1039D00002120274000000060212027800000006C3
+:1039E0000212027C000000060212028000000006A3
+:1039F0000212028400000006021202880000000683
+:103A00000212028C00000006021202900000000662
+:103A10000212029400000006021202980000000642
+:103A20000212029C00000006021202A0000003061F
+:103A3000021202A400000013021202A800000006F5
+:103A4000021202B000001004021202B400001004BE
+:103A50000212032400106440021203280010644084
+:103A6000021205B400000001021201B000000001C2
+:103A70000600A000000000160200A0EC5554000053
+:103A80000200A0F0555555550200A0F40000555510
+:103A90000200A0F8F00000000200A0FC5554000055
+:103AA0000200A100555555550200A10400005555CE
+:103AB0000200A108F00000000200A18C5554000093
+:103AC0000200A190555555550200A194000055558E
+:103AD0000200A198F00000000200A19C000000007C
+:103AE0000200A1A0000100000200A1A400005014E7
+:103AF0000200A1A8000000000200A45C00000C006D
+:103B00000200A61C000000030200A06CFF5C000085
+:103B10000200A070FFF55FFF0200A0740000FFFF2D
+:103B20000200A078F00003E00200A07C000000008A
+:103B30000200A0800000A0000600A0840000000594
+:103B40000200A0980FE000000600A09C0000000703
+:103B50000200A0B8000004000600A0BC00000003A2
+:103B60000200A0C8000010000600A0CC0000000366
+:103B70000200A0D8000040000600A0DC0000000306
+:103B80000200A0E8000100000600A22C00000004D2
+:103B90000200A10CFF5C00000200A110FFF55FFF16
+:103BA0000200A1140000FFFF0200A118F00003E0D2
+:103BB0000200A11C000000000200A1200000A000E3
+:103BC0000600A124000000050200A1380FE000005B
+:103BD0000600A13C000000070200A15800000800F8
+:103BE0000600A15C000000030200A16800002000A4
+:103BF0000600A16C000000030200A1780000800014
+:103C00000600A17C000000030200A1880002000061
+:103C10000600A23C000000040000000000000000BC
+:103C20000000003100000000000000000000000063
+:103C30000000000000000000000000000000000084
+:103C40000000000000000000000000000031003211
+:103C50000000000000000000000000000000000064
+:103C60000000000000000000000000000000000054
+:103C700000000000000000000032005600000000BC
+:103C80000000000000000000000000000000000034
+:103C90000000000000000000000000000000000024
+:103CA000000000000056008C000000000000000032
+:103CB000008C009000900094009400980098009C64
+:103CC000009C00A000A000A400A400A800A800ACD4
+:103CD00000AC00B100B100B300B300B500000000BB
+:103CE00000000000000000000000000000000000D4
+:103CF00000000000000000000000000000B501020C
+:103D00000102010A010A01120112011B011B012417
+:103D10000124012D012D01360136013F013F0148EB
+:103D2000014801510151015A00000000000000004B
+:103D30000000000000000000000000000000000083
+:103D40000000000000000000000000000000000073
+:103D50000000000000000000000000000000000063
+:103D60000000000000000000000000000000000053
+:103D70000000000000000000000000000000000043
+:103D80000000000000000000000000000000000033
+:103D90000000000000000000000000000000000023
+:103DA0000000000000000000000000000000000013
+:103DB0000000000000000000000000000000000003
+:103DC00000000000000000000000000000000000F3
+:103DD0000000000000000000015A015F0000000028
+:103DE00000000000015F016001600161016101628A
+:103DF000016201630163016401640165016501669B
+:103E000001660167000000000000000000000000E3
+:103E100000000000000000000000000000000000A2
+:103E20000000000000000000000000000000000092
+:103E30000167016C016C01790179018600000000C5
+:103E40000000000000000000000000000000000072
+:103E50000000000000000000000000000000000062
+:103E60000000000000000000000000000000000052
+:103E70000000000000000000000000000000000042
+:103E80000000000000000000018601870000000023
+:103E90000000000000000000000000000000000022
+:103EA0000000000000000000000000000000000012
+:103EB00000000000018701BE0000000000000000BB
+:103EC00000000000000000000000000000000000F2
+:103ED00000000000000000000000000000000000E2
+:103EE00001BE01E900000000000000000000000029
+:103EF00000000000000000000000000000000000C2
+:103F000000000000000000000000000001E9021AAB
+:103F10000000000000000000021A02210221022815
+:103F20000228022F022F02360236023D023D0244D1
+:103F30000244024B024B02520252028A000000006D
+:103F400000000000028A028E028E02920292029605
+:103F50000296029A029A029E029E02A202A202A661
+:103F600002A602AA02AA02FC02FC03130313032AFC
+:103F7000032A032D032D03300330033303330336A9
+:103F8000033603390339033C033C033F033F034239
+:103F9000034203830383038A038A039103910395F6
+:103FA000039503990399039D039D03A103A103A511
+:103FB00003A503A903A903AD03AD03B103B103B284
+:103FC00000000000000000000000000000000000F1
+:103FD00000000000000000000000000000000000E1
+:103FE000000000000000000003B203C40000000055
+:103FF00000000000000000000000000000000000C1
+:1040000000000000000000000000000000000000B0
+:104010000000000003C403D903D903DC03DC03DF81
+:104020000000000000000000000000000000000090
+:104030000000000000000000000000000000000080
+:1040400003DF040C0000000000000000000000007E
+:104050000000000000000000000000000000000060
+:10406000000000000000000000000000040C050F2C
+:104070000000000000000000000000000000000040
+:104080000000000000000000000000000000000030
+:104090000000000000000000050F05160516051AB7
+:1040A000051A051E000000000000000000000000CE
+:1040B0000000000000000000000000000000000000
+:1040C00000000000051E055E00000000000000006A
+:1040D000055E056705670570057005790579058238
+:1040E0000582058B058B05940594059D059D05A608
+:1040F00005A605FF05FF0611061106230623062760
+:104100000627062B062B062F062F06330633063707
+:104110000637063B063B063F063F06430643064A74
+:10412000000000000000000000000000000000008F
+:10413000000000000000000000000000000000007F
+:104140000000000000000000064A065000000000C9
+:10415000000000000000000000000000000000005F
+:10416000000000000000000000000000000000004F
+:104170000000000006500653000000000000000090
+:10418000000000000000000000000000000000002F
+:10419000000000000000000000000000000000001F
+:1041A0000653065900000000000000000000000057
+:1041B00000000000000000000000000000000000FF
+:1041C00000000000000000000000000000000000EF
+:1041D0000000000000000000065906680668067727
+:1041E0000677068606860695069506A406A406B3F7
+:1041F00006B306C206C206D106D10742000000007F
+:1042000000000000000000000000000000000000AE
+:10421000000000000000000000000000000000009E
+:104220000000000007420755075507660766077735
+:10423000000000000000000000000000000000007E
+:10424000000000000000000000000000000000006E
+:10425000000000000000000000000000000000005E
+:10426000000000000000000000000000000000004E
+:10427000000000000000000000000000000000003E
+:10428000000000000000000000000000000000002E
+:10429000000000000000000000000000000000001E
+:1042A000000000000000000000000000000000000E
+:1042B00000010000000204C00003098000040E4059
+:1042C00000051300000617C000071C8000082140ED
+:1042D00000092600000A2AC0000B2F80000C344081
+:1042E000000D3900000E3DC0000F42800010474015
+:1042F00000114C00001250C00013558000145A40A9
+:1043000000155F00001663C00017688000186D403C
+:1043100000197200001A76C0001B7B80001C8040D0
+:10432000001D8500001E89C0001F8E800020934064
+:10433000000020000000400000006000000080003D
+:104340000000A0000000C0000000E000000100002C
+:104350000001200000014000000160000001800019
+:104360000001A0000001C0000001E0000002000008
+:1043700000022000000240000002600000028000F5
+:104380000002A0000002C0000002E00000030000E4
+:1043900000032000000340000003600000038000D1
+:1043A0000003A0000003C0000003E00000040000C0
+:1043B00000042000000440000004600000048000AD
+:1043C0000004A0000004C0000004E000000500009C
+:1043D0000005200000054000000560000005800089
+:1043E0000005A0000005C0000005E0000006000078
+:1043F0000006200000064000000660000006800065
+:104400000006A0000006C0000006E0000007000053
+:104410000007200000074000000760000007800040
+:104420000007A0000007C0000007E000000800002F
+:10443000000820000008400000086000000880001C
+:104440000008A0000008C0000008E000000900000B
+:1044500000092000000940000009600000098000F8
+:104460000009A0000009C0000009E000000A0000E7
+:10447000000A2000000A4000000A6000000A8000D4
+:10448000000AA000000AC000000AE000000B0000C3
+:10449000000B2000000B4000000B6000000B8000B0
+:1044A000000BA000000BC000000BE000000C00009F
+:1044B000000C2000000C4000000C6000000C80008C
+:1044C000000CA000000CC000000CE000000D00007B
+:1044D000000D2000000D4000000D6000000D800068
+:1044E000000DA000000DC000000DE000000E000057
+:1044F000000E2000000E4000000E6000000E800044
+:10450000000EA000000EC000000EE000000F000032
+:10451000000F2000000F4000000F6000000F80001F
+:10452000000FA000000FC000000FE000001000000E
+:1045300000102000001040000010600000108000FB
+:104540000010A0000010C0000010E00000110000EA
+:1045500000112000001140000011600000118000D7
+:104560000011A0000011C0000011E00000120000C6
+:1045700000122000001240000012600000128000B3
+:104580000012A0000012C0000012E00000130000A2
+:10459000001320000013400000136000001380008F
+:1045A0000013A0000013C0000013E000001400007E
+:1045B000001420000014400000146000001480006B
+:1045C0000014A0000014C0000014E000001500005A
+:1045D0000015200000154000001560000015800047
+:1045E0000015A0000015C0000015E0000016000036
+:1045F0000016200000164000001660000016800023
+:104600000016A0000016C0000016E0000017000011
+:1046100000172000001740000017600000178000FE
+:104620000017A0000017C0000017E00000180000ED
+:1046300000182000001840000018600000188000DA
+:104640000018A0000018C0000018E00000190000C9
+:1046500000192000001940000019600000198000B6
+:104660000019A0000019C0000019E000001A0000A5
+:10467000001A2000001A4000001A6000001A800092
+:10468000001AA000001AC000001AE000001B000081
+:10469000001B2000001B4000001B6000001B80006E
+:1046A000001BA000001BC000001BE000001C00005D
+:1046B000001C2000001C4000001C6000001C80004A
+:1046C000001CA000001CC000001CE000001D000039
+:1046D000001D2000001D4000001D6000001D800026
+:1046E000001DA000001DC000001DE000001E000015
+:1046F000001E2000001E4000001E6000001E800002
+:10470000001EA000001EC000001EE000001F0000F0
+:10471000001F2000001F4000001F6000001F8000DD
+:10472000001FA000001FC000001FE00000200000CC
+:1047300000202000002040000020600000208000B9
+:104740000020A0000020C0000020E00000210000A8
+:104750000021200000214000002160000021800095
+:104760000021A0000021C0000021E0000022000084
+:104770000022200000224000002260000022800071
+:104780000022A0000022C0000022E0000023000060
+:10479000002320000023400000236000002380004D
+:1047A0000023A0000023C0000023E000002400003C
+:1047B0000024200000244000002460000024800029
+:1047C0000024A0000024C0000024E0000025000018
+:1047D0000025200000254000002560000025800005
+:1047E0000025A0000025C0000025E00000260000F4
+:1047F00000262000002640000026600000268000E1
+:104800000026A0000026C0000026E00000270000CF
+:1048100000272000002740000027600000278000BC
+:104820000027A0000027C0000027E00000280000AB
+:104830000028200000284000002860000028800098
+:104840000028A0000028C0000028E0000029000087
+:104850000029200000294000002960000029800074
+:104860000029A0000029C0000029E000002A000063
+:10487000002A2000002A4000002A6000002A800050
+:10488000002AA000002AC000002AE000002B00003F
+:10489000002B2000002B4000002B6000002B80002C
+:1048A000002BA000002BC000002BE000002C00001B
+:1048B000002C2000002C4000002C6000002C800008
+:1048C000002CA000002CC000002CE000002D0000F7
+:1048D000002D2000002D4000002D6000002D8000E4
+:1048E000002DA000002DC000002DE000002E0000D3
+:1048F000002E2000002E4000002E6000002E8000C0
+:10490000002EA000002EC000002EE000002F0000AE
+:10491000002F2000002F4000002F6000002F80009B
+:10492000002FA000002FC000002FE000003000008A
+:104930000030200000304000003060000030800077
+:104940000030A0000030C0000030E0000031000066
+:104950000031200000314000003160000031800053
+:104960000031A0000031C0000031E0000032000042
+:10497000003220000032400000326000003280002F
+:104980000032A0000032C0000032E000003300001E
+:10499000003320000033400000336000003380000B
+:1049A0000033A0000033C0000033E00000340000FA
+:1049B00000342000003440000034600000348000E7
+:1049C0000034A0000034C0000034E00000350000D6
+:1049D00000352000003540000035600000358000C3
+:1049E0000035A0000035C0000035E00000360000B2
+:1049F000003620000036400000366000003680009F
+:104A00000036A0000036C0000036E000003700008D
+:104A1000003720000037400000376000003780007A
+:104A20000037A0000037C0000037E0000038000069
+:104A30000038200000384000003860000038800056
+:104A40000038A0000038C0000038E0000039000045
+:104A50000039200000394000003960000039800032
+:104A60000039A0000039C0000039E000003A000021
+:104A7000003A2000003A4000003A6000003A80000E
+:104A8000003AA000003AC000003AE000003B0000FD
+:104A9000003B2000003B4000003B6000003B8000EA
+:104AA000003BA000003BC000003BE000003C0000D9
+:104AB000003C2000003C4000003C6000003C8000C6
+:104AC000003CA000003CC000003CE000003D0000B5
+:104AD000003D2000003D4000003D6000003D8000A2
+:104AE000003DA000003DC000003DE000003E000091
+:104AF000003E2000003E4000003E6000003E80007E
+:104B0000003EA000003EC000003EE000003F00006C
+:104B1000003F2000003F4000003F6000003F800059
+:104B2000003FA000003FC000003FE000003FE00168
+:104B300000000000000001FF0000020000007FF8FC
+:104B400000007FF800000CDF0000150000000001ED
+:104B50000000000100000001FFFFFFFFFFFFFFFF5B
+:104B6000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF55
+:104B7000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF45
+:104B8000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF35
+:104B9000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF25
+:104BA000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF15
+:104BB000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF05
+:104BC000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5
+:104BD000FFFFFFFFFFFFFFFFFFFFFFFF00000000E1
+:104BE000FFFFFFFF00000000FFFFFFFFFFFFFFFFD1
+:104BF00000000000FFFFFFFF00000000FFFFFFFFBD
+:104C0000FFFFFFFF00000000FFFFFFFF00000000AC
+:104C1000FFFFFFFF0000000300BEBC20FFFFFFFFFF
+:104C200000000000FFFFFFFF00000000FFFFFFFF8C
+:104C30000000000300BEBC20FFFFFFFF00000000DB
+:104C4000FFFFFFFF00000000FFFFFFFF0000000369
+:104C500000BEBC20FFFFFFFF00000000FFFFFFFFC2
+:104C600000000000FFFFFFFF0000000300BEBC20AB
+:104C7000FFFFFFFF00000000FFFFFFFF000000003C
+:104C8000FFFFFFFF0000000300BEBC20FFFFFFFF8F
+:104C900000000000FFFFFFFF00000000FFFFFFFF1C
+:104CA0000000000300BEBC2000002000000040C047
+:104CB00000006180000082400000A3000000C3C02B
+:104CC0000000E4800001054000012600000146C00C
+:104CD00000016780000188400001A9000001C9C0EF
+:104CE0000001EA8000020B4000022C0000024CC0D0
+:104CF00000026D8000028E400002AF000002CFC0B3
+:104D00000002F0800003114000033200000352C093
+:104D100000037380000394400003B5000003D5C076
+:104D20000003F6800004174000043800000458C057
+:104D30000004798000049A40000080000001038094
+:104D40000001870000020A8000028E00000311802B
+:104D5000000395000004188000049C0000051F80DB
+:104D60000005A300000626800006AA0000072D808B
+:104D70000007B100000834800008B80000093B803B
+:104D80000009BF00000A4280000AC600000B4980EB
+:104D9000000BCD00000C5080000CD400000D57809B
+:104DA000000DDB0000007FF800007FF80000193CD8
+:104DB000000015000000190000000028001000008D
+:104DC0000000000000000000FFFFFFFF40000000A7
+:104DD00040000000400000004000000040000000D3
+:104DE00040000000400000004000000040000000C3
+:104DF00040000000400000004000000040000000B3
+:104E000040000000400000004000000040000000A2
+:104E10004000000040000000400000004000000092
+:104E20004000000040000000400000004000000082
+:104E30004000000040000000400000004000000072
+:104E400040000000400000004000000000007FF82B
+:104E500000007FF8000005C700001500FFFFFFFFFE
+:104E6000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF52
+:104E7000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF42
+:104E8000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF32
+:104E9000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF22
+:104EA000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF12
+:104EB000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF02
+:104EC000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2
+:104ED000FFFFFFFFFFFFFFFFFFFFFFFF400000009E
+:104EE00040000000400000004000000040000000C2
+:104EF00040000000400000004000000040000000B2
+:104F000040000000400000004000000040000000A1
+:104F10004000000040000000400000004000000091
+:104F20004000000040000000400000004000000081
+:104F30004000000040000000400000004000000071
+:104F40004000000040000000400000004000000061
+:104F50004000000040000000400000000000100081
+:104F6000000020800000310000004180000052005D
+:104F70000000628000007300000083800000940045
+:104F80000000A4800000B5000000C5800000D6002D
+:104F90000000E6800000F700000107800001180013
+:104FA00000012880000139000001498000015A00F9
+:104FB00000016A8000017B0000018B8000019C00E1
+:104FC0000001AC800001BD000001CD800001DE00C9
+:104FD0000001EE800001FF0000007FF800007FF874
+:104FE0000000112E0000350010000000000028AD68
+:104FF000000000000001000100150005CCCCCCC56C
+:10500000FFFFFFFFFFFFFFFF7058103C0000000094
+:105010000000000000000001CCCC0201CCCCCCCCC4
+:10502000CCCC0201CCCCCCCCCCCC0201CCCCCCCCEA
+:10503000CCCC0201CCCCCCCCCCCC0201CCCCCCCCDA
+:10504000CCCC0201CCCCCCCCCCCC0201CCCCCCCCCA
+:10505000CCCC0201CCCCCCCC00000000FFFFFFFF89
+:105060004000000040000000400000004000000040
+:105070004000000040000000400000004000000030
+:105080004000000040000000400000004000000020
+:105090004000000040000000400000004000000010
+:1050A0004000000040000000400000004000000000
+:1050B00040000000400000004000000040000000F0
+:1050C00040000000400000004000000040000000E0
+:1050D00040000000400000004000000040000000D0
+:1050E000000E0232011600D6001000000000000081
+:1050F00000720236012300F30010000000000000DF
+:105100000000FFFF000000000000FFFF00000000A3
+:105110000000FFFF000000000000FFFF0000000093
+:105120000000FFFF000000000000FFFF0000000083
+:105130000000FFFF000000000000FFFF0000000073
+:105140000000FFFF000000000000FFFF0000000063
+:105150000000FFFF000000000000FFFF0000000053
+:105160000000FFFF000000000000FFFF0000000043
+:105170000000FFFF000000000000FFFF0000000033
+:105180000000FFFF000000000000FFFF0000000023
+:105190000000FFFF000000000000FFFF0000000013
+:1051A0000000FFFF000000000000FFFF0000000003
+:1051B0000000FFFF000000000000FFFF00000000F3
+:1051C0000000FFFF000000000000FFFF00000000E3
+:1051D0000000FFFF000000000000FFFF00000000D3
+:1051E0000000FFFF000000000000FFFF00000000C3
+:1051F0000000FFFF000000000000FFFF00000000B3
+:105200000000FFFF000000000000FFFF00000000A2
+:105210000000FFFF000000000000FFFF0000000092
+:105220000000FFFF000000000000FFFF0000000082
+:105230000000FFFF000000000000FFFF0000000072
+:105240000000FFFF000000000000FFFF0000000062
+:105250000000FFFF000000000000FFFF0000000052
+:105260000000FFFF000000000000FFFF0000000042
+:105270000000FFFF000000000000FFFF0000000032
+:105280000000FFFF000000000000FFFF0000000022
+:105290000000FFFF000000000000FFFF0000000012
+:1052A0000000FFFF000000000000FFFF0000000002
+:1052B0000000FFFF000000000000FFFF00000000F2
+:1052C0000000FFFF000000000000FFFF00000000E2
+:1052D0000000FFFF000000000000FFFF00000000D2
+:1052E0000000FFFF000000000000FFFF00000000C2
+:1052F0000000FFFF000000000000FFFF00000000B2
+:10530000FFFFFFF3318FFFFF0C30C30CC30C30C322
+:10531000CF3CF300F3CF3CF30000CF3CCDCDCDCD5F
+:10532000FFFFFFF130EFFFFF0C30C30CC30C30C3A5
+:10533000CF3CF300F3CF3CF30001CF3CCDCDCDCD3E
+:10534000FFFFFFF6305FFFFF0C30C30CC30C30C310
+:10535000CF3CF300F3CF3CF30002CF3CCDCDCDCD1D
+:10536000FFFFF4061CBFFFFF0C30C305C30C30C3A6
+:10537000CF300014F3CF3CF30004CF3CCDCDCDCDE6
+:10538000FFFFFFF2304FFFFF0C30C30CC30C30C3E4
+:10539000CF3CF300F3CF3CF30008CF3CCDCDCDCDD7
+:1053A000FFFFFFFA302FFFFF0C30C30CC30C30C3DC
+:1053B000CF3CF300F3CF3CF30010CF3CCDCDCDCDAF
+:1053C000FFFFFFF731EFFFFF0C30C30CC30C30C3FE
+:1053D000CF3CF300F3CF3CF30020CF3CCDCDCDCD7F
+:1053E000FFFFFFF5302FFFFF0C30C30CC30C30C3A1
+:1053F000CF3CF300F3CF3CF30040CF3CCDCDCDCD3F
+:10540000FFFFFFF3310FFFFF0C30C30CC30C30C3A1
+:10541000CF3CF300F3CF3CF30000CF3CCDCDCDCD5E
+:10542000FFFFFFF1310FFFFF0C30C30CC30C30C383
+:10543000CF3CF300F3CF3CF30001CF3CCDCDCDCD3D
+:10544000FFFFFFF6305FFFFF0C30C30CC30C30C30F
+:10545000CF3CF300F3CF3CF30002CF3CCDCDCDCD1C
+:10546000FFFFF4061CBFFFFF0C30C305C30C30C3A5
+:10547000CF300014F3CF3CF30004CF3CCDCDCDCDE5
+:10548000FFFFFFF2304FFFFF0C30C30CC30C30C3E3
+:10549000CF3CF300F3CF3CF30008CF3CCDCDCDCDD6
+:1054A000FFFFFFFA302FFFFF0C30C30CC30C30C3DB
+:1054B000CF3CF300F3CF3CF30010CF3CCDCDCDCDAE
+:1054C000FFFFFFF730EFFFFF0C30C30CC30C30C3FE
+:1054D000CF3CF300F3CF3CF30020CF3CCDCDCDCD7E
+:1054E000FFFFFFF5304FFFFF0C30C30CC30C30C380
+:1054F000CF3CF300F3CF3CF30040CF3CCDCDCDCD3E
+:10550000FFFFFFF331EFFFFF0C30C30CC30C30C3C0
+:10551000CF3CF300F3CF3CF30000CF3CCDCDCDCD5D
+:10552000FFFFFFF1310FFFFF0C30C30CC30C30C382
+:10553000CF3CF300F3CF3CF30001CF3CCDCDCDCD3C
+:10554000FFFFFFF6305FFFFF0C30C30CC30C30C30E
+:10555000CF3CF300F3CF3CF30002CF3CCDCDCDCD1B
+:10556000FFFFF4061CBFFFFF0C30C305C30C30C3A4
+:10557000CF300014F3CF3CF30004CF3CCDCDCDCDE4
+:10558000FFFFFFF2304FFFFF0C30C30CC30C30C3E2
+:10559000CF3CF300F3CF3CF30008CF3CCDCDCDCDD5
+:1055A000FFFFFFFA302FFFFF0C30C30CC30C30C3DA
+:1055B000CF3CF300F3CF3CF30010CF3CCDCDCDCDAD
+:1055C000FFFFFF97056FFFFF0C30C30CC30C30C308
+:1055D000CF3CC000F3CF3CF30020CF3CCDCDCDCDB0
+:1055E000FFFFFFF5310FFFFF0C30C30CC30C30C3BE
+:1055F000CF3CF300F3CF3CF30040CF3CCDCDCDCD3D
+:10560000FFFFFFF3320FFFFF0C30C30CC30C30C39E
+:10561000CF3CF300F3CF3CF30000CF3CCDCDCDCD5C
+:10562000FFFFFFF1310FFFFF0C30C30CC30C30C381
+:10563000CF3CF300F3CF3CF30001CF3CCDCDCDCD3B
+:10564000FFFFFFF6305FFFFF0C30C30CC30C30C30D
+:10565000CF3CF300F3CF3CF30002CF3CCDCDCDCD1A
+:10566000FFFFF4061CBFFFFF0C30C305C30C30C3A3
+:10567000CF300014F3CF3CF30004CF3CCDCDCDCDE3
+:10568000FFFFFFF2304FFFFF0C30C30CC30C30C3E1
+:10569000CF3CF300F3CF3CF30008CF3CCDCDCDCDD4
+:1056A000FFFFFF8A042FFFFF0C30C30CC30C30C375
+:1056B000CF3CC000F3CF3CF30010CF3CCDCDCDCDDF
+:1056C000FFFFFF9705CFFFFF0C30C30CC30C30C3A7
+:1056D000CF3CC000F3CF3CF30020CF3CCDCDCDCDAF
+:1056E000FFFFFFF5310FFFFF0C30C30CC30C30C3BD
+:1056F000CF3CF300F3CF3CF30040CF3CCDCDCDCD3C
+:10570000FFFFFFF3316FFFFF0C30C30CC30C30C33E
+:10571000CF3CF300F3CF3CF30000CF3CCDCDCDCD5B
+:10572000FFFFFFF1302FFFFF0C30C30CC30C30C361
+:10573000CF3CF300F3CF3CF30001CF3CCDCDCDCD3A
+:10574000FFFFFFF6305FFFFF0C30C30CC30C30C30C
+:10575000CF3CF300F3CF3CF30002CF3CCDCDCDCD19
+:10576000FFFFFFF630BFFFFF0C30C30CC30C30C38C
+:10577000CF3CF314F3CF3CF30004CF3CCDCDCDCDE3
+:10578000FFFFFFF2304FFFFF0C30C30CC30C30C3E0
+:10579000CF3CF300F3CF3CF30008CF3CCDCDCDCDD3
+:1057A000FFFFFFFA302FFFFF0C30C30CC30C30C3D8
+:1057B000CF3CF300F3CF3CF30010CF3CCDCDCDCDAB
+:1057C000FFFFFFF731CFFFFF0C30C30CC30C30C31A
+:1057D000CF3CF300F3CF3CF30020CF3CCDCDCDCD7B
+:1057E000FFFFFFF0307FFFFF0C30C30CC30C30C352
+:1057F000CF3CF300F3CF3CF30040CF3CCDCDCDCD3B
+:10580000FFFFFFFF30CFFFFF0C30C30CC30C30C3D2
+:10581000CF3CF3CCF3CF3CF30000CF3CCDCDCDCD8E
+:10582000FFFFFFFF30CFFFFF0C30C30CC30C30C3B2
+:10583000CF3CF3CCF3CF3CF30001CF3CCDCDCDCD6D
+:10584000FFFFFFFF30CFFFFF0C30C30CC30C30C392
+:10585000CF3CF3CCF3CF3CF30002CF3CCDCDCDCD4C
+:10586000FFFFFFFF30CFFFFF0C30C30CC30C30C372
+:10587000CF3CF3CCF3CF3CF30004CF3CCDCDCDCD2A
+:10588000FFFFFFFF30CFFFFF0C30C30CC30C30C352
+:10589000CF3CF3CCF3CF3CF30008CF3CCDCDCDCD06
+:1058A000FFFFFFFF30CFFFFF0C30C30CC30C30C332
+:1058B000CF3CF3CCF3CF3CF30010CF3CCDCDCDCDDE
+:1058C000FFFFFFFF30CFFFFF0C30C30CC30C30C312
+:1058D000CF3CF3CCF3CF3CF30020CF3CCDCDCDCDAE
+:1058E000FFFFFFFF30CFFFFF0C30C30CC30C30C3F2
+:1058F000CF3CF3CCF3CF3CF30040CF3CCDCDCDCD6E
+:10590000FFFFFFFF30CFFFFF0C30C30CC30C30C3D1
+:10591000CF3CF3CCF3CF3CF30000CF3CCDCDCDCD8D
+:10592000FFFFFFFF30CFFFFF0C30C30CC30C30C3B1
+:10593000CF3CF3CCF3CF3CF30001CF3CCDCDCDCD6C
+:10594000FFFFFFFF30CFFFFF0C30C30CC30C30C391
+:10595000CF3CF3CCF3CF3CF30002CF3CCDCDCDCD4B
+:10596000FFFFFFFF30CFFFFF0C30C30CC30C30C371
+:10597000CF3CF3CCF3CF3CF30004CF3CCDCDCDCD29
+:10598000FFFFFFFF30CFFFFF0C30C30CC30C30C351
+:10599000CF3CF3CCF3CF3CF30008CF3CCDCDCDCD05
+:1059A000FFFFFFFF30CFFFFF0C30C30CC30C30C331
+:1059B000CF3CF3CCF3CF3CF30010CF3CCDCDCDCDDD
+:1059C000FFFFFFFF30CFFFFF0C30C30CC30C30C311
+:1059D000CF3CF3CCF3CF3CF30020CF3CCDCDCDCDAD
+:1059E000FFFFFFFF30CFFFFF0C30C30CC30C30C3F1
+:1059F000CF3CF3CCF3CF3CF30040CF3CCDCDCDCD6D
+:105A0000FFFFFFFF30CFFFFF0C30C30CC30C30C3D0
+:105A1000CF3CF3CCF3CF3CF30000CF3CCDCDCDCD8C
+:105A2000FFFFFFFF30CFFFFF0C30C30CC30C30C3B0
+:105A3000CF3CF3CCF3CF3CF30001CF3CCDCDCDCD6B
+:105A4000FFFFFFFF30CFFFFF0C30C30CC30C30C390
+:105A5000CF3CF3CCF3CF3CF30002CF3CCDCDCDCD4A
+:105A6000FFFFFFFF30CFFFFF0C30C30CC30C30C370
+:105A7000CF3CF3CCF3CF3CF30004CF3CCDCDCDCD28
+:105A8000FFFFFFFF30CFFFFF0C30C30CC30C30C350
+:105A9000CF3CF3CCF3CF3CF30008CF3CCDCDCDCD04
+:105AA000FFFFFFFF30CFFFFF0C30C30CC30C30C330
+:105AB000CF3CF3CCF3CF3CF30010CF3CCDCDCDCDDC
+:105AC000FFFFFFFF30CFFFFF0C30C30CC30C30C310
+:105AD000CF3CF3CCF3CF3CF30020CF3CCDCDCDCDAC
+:105AE000FFFFFFFF30CFFFFF0C30C30CC30C30C3F0
+:105AF000CF3CF3CCF3CF3CF30040CF3CCDCDCDCD6C
+:105B0000000C0000000700C000028130000B81582B
+:105B10000002021000010230000F024000010330B9
+:105B2000000800000008008000028100000B8128AE
+:105B3000000201E0000102000007021000020280E2
+:105B4000000F0000000800F000028170000B819837
+:105B50000002025000010270000B8280000803382E
+:105B6000001000000008010000028180000B81A8E5
+:105B70000002026000018280000E8298000803800B
+:105B8000000B0000000100B0000280C0000580E8AA
+:105B90000002014000010160000E0170000382500C
+:105BA000CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC35
+:105BB00000002000CCCCCCCCCCCCCCCCCCCCCCCC35
+:105BC000CCCCCCCC00002000CCCCCCCCCCCCCCCC25
+:105BD000CCCCCCCCCCCCCCCC040020000000000041
+:105BE0001F8B080000000000000BFB51CFC0F0032A
+:105BF0008A59051918F484117C7A607E4ECAF43BE8
+:105C0000F232303803B12B103700F1616E06862373
+:105C1000DCC4EB3F2B8F6007CA3230D402F17E69BF
+:105C200006062B3984B8A10203C312203F0D2AF6C1
+:105C30001A4817CA53E6EEC182555431C51495115E
+:105C40006C552CF2C8580D4DBE411995AF4E40FF12
+:105C500040E3641D54FE042D08FD5E1B42A7A0C94D
+:105C60004F84CABB42FD95AA83DD5C3722FD9DC6E9
+:105C700082CA4F40E3B730A2F2CD38D0DC0F550FC7
+:105C80000000174B67C80300000000000000000080
+:105C90001F8B080000000000000BED7D0D7854D52F
+:105CA000B5E83E3F73E6CCE4CCE4242461C2EF24A3
+:105CB000841034E21022064BEB097F869A7A07AAF9
+:105CC000985AC5012306082452F5E1D37E9948026B
+:105CD000011106B53414D4E14F692FB6918B965A51
+:105CE0008A033E2DB6BEEF059FB57AB57DD152FC35
+:105CF000294ACABB52FBAEAD6FAFB5F74ECE39CC19
+:105D000090E04FDBFBDEA59FDDD9E7EC9FB5D7DF49
+:105D10005E6BEDB5CF78483E29B89C904FE01F2DC3
+:105D2000FF9741087DD4577A7412CFBA98909C3C63
+:105D30002BDE534EC8D03C2B452AE973530B7BA571
+:105D4000FE7EA23C9C332B04EDDAF2AD10A163B4CD
+:105D5000E5CC2331182BD640480121AA4EF09F688C
+:105D6000EF31E7EAA41C1FFDF513F15E21A4DD2C41
+:105D7000CE867EEEF10949127289BD2E1322C6A489
+:105D8000FD7C02DE12FA208F107F959CBCA288C297
+:105D90005D924C41DD0833B80F17BD523386AE63B8
+:105DA0005DB51CF186A1F7AD844C2664058C45EBEE
+:105DB000EB2676D78CC983F76A04DECE54F6B66A32
+:105DC000B4BD5142B07D70623CA5613FCB28A4FDBB
+:105DD00072180824A76C512D091262CED0FAE1C2C4
+:105DE000FFB770FD066FA79738DF1B64FD1F95098D
+:105DF00050EB25D18BE8F8535DEFCB66BD0DE31A70
+:105E0000843E2FE3CFE9BAEE873F0A09F91209E48D
+:105E10009DC8A27F5F4A2E053C909A5C42A69C8D4D
+:105E2000BF7EBCC591BE8430BA68A4EF1FD241E7E3
+:105E300074B862464FA744D7ED8BC8C44B1FCD52F0
+:105E40005ED48B012F4715C4C3BA3A86E77533E495
+:105E5000645CC275D616D2FEA309C363CEF862890C
+:105E60001413B2B185D6C79D8DE7EC928405F4F783
+:105E7000951009F82A9B3E1B42D7953D35857C330A
+:105E8000BA8AE193DCCDF011A7FFFBA4B81F9FD91C
+:105E9000029F1127BEB2393E736A6CF882E755142F
+:105EA0008F13E0BD138F49F883E2AB5EE0319F8C26
+:105EB000453CC67311BF03E1F10A8A832C0ABFFF78
+:105EC000556FD25BD48F57C11702AF26C7EB8699A7
+:105ED000BD3A30C3468BF1392129490EE178925CF5
+:105EE00085EBC3B203F0E6C5FEF85EA7301B7C9ECF
+:105EF000309DC75F9640FCEB141D4324E053435292
+:105F000081AF814FD3CCBB4E4FEA126DBF69AA4C13
+:105F1000805EEB2C998469FD74999A5400EEB8D593
+:105F20001DB2F1A901F8A7F8BA8FE3471B213BF096
+:105F3000A9E6F95D7CEE5CC7A6BEF5597C5D6C1DDB
+:105F4000A43BD901709C99299375D2C0E30E842794
+:105F500031EE80F0F598BE1298F70525B28EF2DA90
+:105F6000BA70B243A6F8DA3883E1E36CFA7EC6F978
+:105F70007A7BF5924ADB7C915EDD2CFF02E62139CB
+:105F8000CE7555993E33ADFE3CBF7988B960743407
+:105F900090991E9F1BFC610ABF0D4F7AD894607CBC
+:105FA0007DFC3D3AA8784276E8A017DDF39C05AF6A
+:105FB0006B5EF73C6A49B3A562CDA987343341D8FB
+:105FC0003C16DBA7087BAE821EA1FAC71F71EA113F
+:105FD000B7FED64638EB6A15D3D72AB13D2F02ED6E
+:105FE0004EF5CB85A45F4F570E4EBF10AB01E17548
+:105FF000EB93315CAEA7EFEDA95329FD4BB6093DFC
+:106000007DF72FCA687D37E8695ADFDD0973D1B2A1
+:10601000CBA9A727F0C1CABFF3920C7A7A47063DF5
+:106020005D9CB0A6819E2E49D08D808E53BC9EE98A
+:10603000E9E28E6619E83481EB097280E149A7FF35
+:10604000B3EBE9623ECF986D4E3C15733D5DBEDF0C
+:10605000F59CEBE962979EDE087F507C154A1C8F09
+:10606000634929E271EA20F73B8E47F77E570C73AC
+:106070008FA1787C90ED7739790C8FED1D3201FD81
+:10608000707A9B8CFA715C51548676424F72D0487C
+:10609000195FFF4EAEAF059C636698D5A04C4B8848
+:1060A000590DF4D1D693482A0C7ABA310EF36C4AC2
+:1060B000303D5D922072CC6607691C9E4DA1DCD9F3
+:1060C00020D7A7136A0496B98B8465BDA81FAF7D3E
+:1060D0007607C7E3D7A095431E9C74CCE17875E39F
+:1060E000675CD2C9DF250FBAE8B1DE59CF71D1E5BF
+:1060F0004AC9657F0C921E5E95C4BDB9504FA25D22
+:10610000A7D3B5E6D3BAF22FCF5AC0D746277BA67E
+:1061100075C8C922CAB7813656F774A8C96A5ABF6A
+:10612000218FF1F5D83849825DA784A204ECCFB164
+:1061300079547FD8F0E9E1F81474833F011F63B804
+:106140007D913D33D707FCBD298FE37B06C33755CF
+:10615000803ED07F02DF1E8E6FA3B21BC023B3C36D
+:106160004E7C4F3AEAD437D7D60D71D4AF890E3F63
+:10617000277D3C9C8E1E4E27C14767E13FEEB20F44
+:106180002B9D758F8B3E2D924BEF0C923EDA115268
+:10619000067C3B4EF64776149DDD2E21C948373AE2
+:1061A00079F2389D7F0135E3B2E9F8CB48CF28403A
+:1061B000D001238CE32C977B0AA07E8AF46E1E39D3
+:1061C000A67FFC512A392051234EA2E85D49411A8D
+:1061D000A693545610C18EEA05B874C48B44FFBB15
+:1061E0001EF94495015FC34DF69CC4B355A887883A
+:1061F000F817463A79F99F852B9FFFB344F128F1B0
+:1062000052013A8E01FCC4506FEA2481753FE9C205
+:10621000D220DD5806A9A686D224A604652E896060
+:10622000492E483E9142FD79B789FCEEFB1DF924C9
+:10623000AB7F3DF7C29F14AFC348F47109FC273A06
+:106240009EAEF4F3A18FF321B5D3906F7593F1ADAA
+:106250005E42F7D372947BF45FDC785ECBF5F28616
+:10626000161DCBF52D262E7268281997297D7CB531
+:106270004C8FE4847A3AC06FF137AB912B68DD6FB5
+:10628000F4BE7A13D87BB76B917B68FDF0CCE74303
+:1062900050EFB8DD60F6611BB353FD1C7B1D637BC3
+:1062A0007B5651B836DCAE47F823873EDA30BEF76E
+:1062B0009D9DA0B76EF34700BF9B4247C2AB405EB7
+:1062C0009A3594176A7B22FDD657FCA208EDB58F4C
+:1062D00029FC943E2842B4BFFE116D3589B61BD10E
+:1062E000DB82767D7377B59287EFE38170FF7A3B2F
+:1062F0008A87E1FEDF71642D09D3973995710BF020
+:10630000E52BA3A62CE5435FA529C50D90CAD8EBC4
+:1063100012E53FFF8C18B128FE0221B3157845E73E
+:1063200074236A2204F2EBC667C7C87868219D37D8
+:106330003E5E8BEC46B632A57969DAF5E17FE61D63
+:10634000D75969ECA96C5942FE3F327E11FABD5E05
+:10635000120B65814E2AD3C86E0AE7BAF18B46C785
+:10636000D2D87B3639E3F64AFA32533F4D21CD5D20
+:106370003678C6CA32F29F24EB4C6E43948FA85CE9
+:10638000E5988C9FB419C44AA681E3720EBFAEC6CD
+:106390008989F6B529819DF545E1EB5D89C1B9563D
+:1063A00022755D69DE6F0778F2413EEE4EC1FE98C0
+:1063B0003D93F135FDCFEAA2F0E7A8AC14ED6B38C0
+:1063C000FC7B78BFF3D043050F027F940FCEFEF223
+:1063D000C2BC69E09DF829E6DD48E79565139F0B8F
+:1063E000BCBBE9294A49F6E1FACE8CDF1C02FB343A
+:1063F000139CE1DB50B79370332D87D2B29697266A
+:106400002BDDF39DEF785F96D93ADCE3925DCC9E6D
+:10641000F2F3FDEBF094572C85D26D749CF0B88AA2
+:10642000537F8C2E93D15FDDB4876EF845A03F5823
+:10643000FD915D24A950549EBEFB1E19E01A49ED42
+:106440007C683F84C464C05B11094B500A3DB88628
+:10645000EBC10F49F43A391FF47417DA45B595B713
+:106460004E4B1737AAE7F2713EFBD45768B9408FFD
+:106470002E82F18DC8318BEEE4447B31BD5CD1EDD1
+:106480002A34D7260F44117CC1E4A99DF33BC8CD23
+:106490001C5A9F777D7A3837CDD48631BBC52C44C2
+:1064A0007F47350BE7DAE471532B952BFA3E09E36E
+:1064B000D9E4E0BB7C7DAD5C1ECE871F6B6869466E
+:1064C0002C4BA1AF6A92891940B7ABA5D86A998EB7
+:1064D00053D11C7956A575634FB7E567CFD7C2F383
+:1064E0007925CDEDC01286D54D40DF3E72F70A0BFF
+:1064F000E8787A045D7A1A3B4194AA253BEC147D36
+:1065000084DF690F0D521E2F8824A601BC65E1634C
+:10651000D5B961A0536C1BD069C4D1C86158A251D0
+:10652000772C956FA357D8646523004DE1D7E2948B
+:106530006E488F6808E8B198447742FF406594C57B
+:106540002B07094726FE0F8798DE0A737E6F8F5050
+:106550007E97FAE5C1CFE5A19DBF3F5D49D0BF68F9
+:10656000CFAB30D3ED1782DF05FF0B7DE86E77F8F8
+:1065700053F0F9785A961213FD9A0F49EC39C0037B
+:106580005D3DCA9F16EA42FF4EC8556DE4D88C2186
+:106590001047AD0C5728B6FDFA7DCE770B74EB97FC
+:1065A000D07FDEF50BDAF3291EC6DD4D22A066AFE3
+:1065B000BD7E01B1F3FBAFFBDA475F42F9BABB1B0B
+:1065C000DDD281FA75F3F55D2D455FB3F3211DE74B
+:1065D000751CA7A43B2EDBF44E0EC7B332B38F3F1E
+:1065E0004D10CD9ADB122AD0A7A236A248B6755C10
+:1065F0005BE7B4E729BFBF03E3BAF9741E69F690FD
+:10660000F3D83F4649B15E80B7B6A4BB0DE0D34294
+:1066100051F4F728DCA7E1F91700F727E782FB1D03
+:10662000887580DE8C545B43C2089FAA5C027E544E
+:10663000AA2D3F0C783FA602DE299E35C586E7C10C
+:10664000CAF9FD7CBF1848DEDBE00FB49763790A16
+:106650006D3F4467724A7A8E11E67739E397C26ECE
+:106660000E8608C659736A7B08F86B171F55D0DE73
+:106670001D5A4B24B0C3845D3BC475DEB001EC668B
+:106680002A3FF7B58450882E367A8FC239C08642A9
+:1066900099D9C753CE0C83FE3FAAEE09813F6856B5
+:1066A0009D59775318ECED30B65FDB12E1FB4F15C7
+:1066B0009689DAB7F6ECA4F36F08F9D15EBEB7A5F8
+:1066C0004CC46B11EE2122DE5BCBEC7B11171670F4
+:1066D000D1FE3A0FB63ADA93900D6FC5B6FE61A6B9
+:1066E0006F06EA9F55E9C47B5F7F6B70FD21DE6F0B
+:1066F000EF5F6DF51C85F89CC9E3FE42EF05791B41
+:10670000B34A46FF59E0D95BE68CCB25F8FC99F8F3
+:10671000C53D1F09FB1DEB27F106846F05978B4CC8
+:10672000E3B473FD28EA1E92DE6E5BA6F07D929FB5
+:106730004B997CAE1F594E7C5C2CE87790E3CF647C
+:10674000F22EFC1A8C0728F6F9D83AB08E719A38D6
+:10675000D3C72EF8457F8DF7CF0487E61EEF381D8F
+:1067600067B26D1C179C99E0739F9391779CE364CB
+:10677000D65FAE7E27074787B3FA119BDC633DD710
+:10678000551FE66A5FEC7A7F81EB7D85AB7E99AB26
+:10679000FD3457FDABAEF6735DF5EB5CED17BADE7D
+:1067A0002F71BD5FE1AAFF5767FBF2C59F0EBFFFC8
+:1067B0009FE149C8D5D978493ACE79DD72554C5216
+:1067C000A352B4DC91F3E22278D5A348EA099847B2
+:1067D000C4B7486A82DD8FFDBD11FB1DEC633B3EF3
+:1067E000B6FC512A57BB122F05617F13CF4F4A6F5A
+:1067F00004C787A97DA8A596B3785002E5C64FD4F3
+:10680000B77ACA804A12C6D174A31E51AE97D0E798
+:10681000367DE52551A4B336C2F99C24981C9640D8
+:10682000808A8E17DFA4A1BD171F499263419EF392
+:10683000D8F8D8BEB81FDE492AD34FA168A21A647F
+:1068400078585DD76128DD780A4D8F4F7C9EEA65C8
+:10685000F200F3CB77CD74FAD5D7F171E6ABE7ED63
+:10686000A7BE3249E91F7FD7B78D482B6DB20B8089
+:10687000A0F5F8B7F524C4374641BC8E1D2260BC94
+:106880006E24E1FF785C6E04FC4DFB8D348E62FC5F
+:106890002DDC601E019DF775B514E17A44EA1D0FE9
+:1068A000F3C9592727B2F3BDBF7E82F1788EAFD0EE
+:1068B000BD937BE2104FD9A845C6229E238867EA84
+:1068C0008FB7792B804D187E57C1EECB9EAB815C84
+:1068D0003877E1F400FD4B4B1FF013EC8B2485F56A
+:1068E00000E9C17A36B773CBD4225C7F0EF7330947
+:1068F0008948607F84AE4CEF9747A5EA32F592FE57
+:10690000B8A51466F14969FDF37F9620AE5546C2DD
+:10691000CC7EE171C2B58AF409C45FCDC1D98BA127
+:106920006F3AE94AD46632C7E65F5EAF0A3F8FE14D
+:106930006B4C88AD3FB4516B06BF66D76C271F8880
+:10694000F6EAF9F3C1E60963BE383EC855C764E00C
+:1069500083EB4D88574B718AB7ACC1E3CD54AC6F14
+:10696000AAB84E82E3FE40B26EB0D75562DDA8E60B
+:10697000F7D77FAD4417C2FBF83452D66CF48F437F
+:106980009FDF0CEDD23C6F48D77E1C8FDBD2FD1908
+:10699000F7F152AE03866E3365B0278B3A57F8EDA8
+:1069A000792EA57CBF7EAC739F0FD6BBB5F1DCF60C
+:1069B000D17D2DC8FC19DB05A5EE28D0835CA29201
+:1069C000DD69CEB17FCAF9BBAFBDCB3E9CD116AF5E
+:1069D00086FEB97532817834DDE7D1BE2BE27EEDDB
+:1069E000E6A97149A372F8C0168276726EDB429FE7
+:1069F0007D3D857C3D9B6B0BFC60B76CAF5FF855B4
+:106A0000F413A8FDAFA0DF1B5B07E317D6B0F37E3E
+:106A1000377CF7F2F525EA199EDCEFB334124B27E9
+:106A2000873F55F9F9834ADDC782FE73947B0FDFF8
+:106A3000F98BF174BED22A39E20BF7C339AECF6EAF
+:106A4000EA417C655DA69AEB400F776A0E7B73FB8B
+:106A5000B6FBB7D4C3B91F7D0EEAE0D12F370F8B39
+:106A600052B81EFBDAA2171603DFB7CB04F49180ED
+:106A7000C32877DABB47FAE4CC392F1DB71AF15295
+:106A80007F6EFFE9D3E2630B97F34C7CE2DE57DDC8
+:106A90007C703EFBC355CA675FDF7E90433A6E0150
+:106AA000F7FB86D685A51EA35F8E849F22E629E08C
+:106AB0007C965B7BBF0FF86C4B5D05CACFE9DA852E
+:106AC00012E8934DD0328D9E10F3658227CB93C090
+:106AD0007C892DF5F74BE9F0561863F122F7F36A3C
+:106AE0000FA3F37A352141FF4CED467BB8BEE67229
+:106AF00055C8D7159A9A8A02BE0A222AB987E2EBAC
+:106B000081DA85D5A5C077540E21BE32A386A0BDFB
+:106B10005068B1732293E2EB69BAEF6DAE2791141E
+:106B20006DB7D9D2F01CC62D876E7EDC5C7F6EFD02
+:106B3000422C5B7BCAFF1E8FC1CE734B4809D853D2
+:106B40000F0CE0BF0D16BFA17A99C54B67540CA07E
+:106B5000CF5BCF378E39EFCBC08F33069907E0D2AA
+:106B600017E4D92DB34BF3201E42F50549871FA723
+:106B70007E18081F6EFC5F0CF8BCF08BC3A7FB7D72
+:106B80009E87C70107898FF575C5FF03522633B568
+:106B900077AF47F41379615F21BD0AC8BF051C3A7E
+:106BA00006BC8A0896334814CB636A2CEAA1ED67C9
+:106BB0009166ACD79004968B5593D199E7C188F331
+:106BC0006E753AE3FB719792249C3B93A973F9612C
+:106BD000B06A9DD00986523F49E35711720F8E3734
+:106BE000DCB51F8B38C5D0C6446D051D77782DCB1D
+:106BF000FB1C5EB5CFB18F05B9FC88F1B6560D6EA2
+:106C00007F7ED4B53F3FAAF6E8409F47ABEE69854B
+:106C1000ED46CD7D2794AEFFB84E275E377CDCE590
+:106C20008BA681676BFD011FE48D6DAD4A9F17EB4D
+:106C30008623D3FB7119CE99BEE265E74C5B73F4F2
+:106C40006FB0649D958EBC04A21845F679B77E4C52
+:106C500072A2E7D4274E79D9E8E1F921011200FEAA
+:106C6000CF840F517ED178786C5AF392689AFEA542
+:106C70005E2637ED39240EE7D28FBDA632FEE37AC9
+:106C800078F237C249B017DA414950FDFB5835E375
+:106C9000CFC939FCFD4361CCAF1ADE49E21ADDCF22
+:106CA00086BF5AFF400E6D775F3DF5206DCFEFAB8D
+:106CB0007CA903CE899F7A59C6B8EE645FB71EA13E
+:106CC000F054F17D706BFD4B989F1CDFA646C6A269
+:106CD0007E97883419BD79A48780F7198FCAE85642
+:106CE00079BF2F0CFB57B8478F50FCDC3EE5253DA4
+:106CF0004CCBFB46A47458E7FAAAFB91CFF7D51703
+:106D00007FBD14D1EACC3B99A54CEDB6E87CEBEB0A
+:106D1000D9B95D4E4F4AF7429CB54E255750F8827F
+:106D2000065BEF7DED24798F047030FA4A640EFA29
+:106D3000C585AEBCAE0257DE9B5939EB5DC86731E5
+:106D4000E19C1F16A1343E7011E8DB2699B95BAEB9
+:106D5000FC68A3D27A17F2036629077D907FB5A558
+:106D60004D3571FF738DEB5E874962872D09C789A9
+:106D7000831FB8E541B64F9A138D483C0C5D39DC52
+:106D800026857B089DB2CD09B7C0AB7B1E77DEF5AB
+:106D9000BB829F8793B1A08744BC59C0EFE6DBBCA0
+:106DA0008AE4FE97281C5B5F3670BFDE5AF5D23747
+:106DB0009B609F2FF362DEC457CFEC69FC112D7FDF
+:106DC000F9C70325505E59B8ABB289B60BF07C0900
+:106DD00011CF2B8091D17EE57A8DF30329DFDEE69A
+:106DE000C9C347984771DF111FD2ABB04D4EFA802F
+:106DF0003E6A8A007FE55D9640BBE9BEEBBA31E9A9
+:106E00002250D725C56D721610F643634C82F3FBF2
+:106E10002BEA12B3810F0D9E47684412681FCD54B0
+:106E20005ED431CECEE966723884DCB9E9525A9F1D
+:106E3000D2212F65789B1A0170873736CB202FA57A
+:106E4000552C6FB9B4B34BE279C2984F3F8E237182
+:106E50005CB481E5156E63F817F9DFC14627DD4C98
+:106E60009EA749FD0C19FCEEA24ED7FB680DE66308
+:106E7000BAE95AACF1BCA8529E47C8F1309CDBB3CA
+:106E8000EB1BF9F99CA127CF65CFEEE3E7734761D0
+:106E9000FDE3CE7E3F2983DEBD0AF42ED5378A9CE2
+:106EA000EA40FFED3219FD37371C1B1A99BEDBA5EE
+:106EB000C90EFBFDB3CE7F03D7FB8ADCD301EBFC0D
+:106EC0005BCFDFD8B7FEBFCFFC77FD9DE75FF777DD
+:106ED000C6FF96BFF3FAF7FC8DD75F532639FCB394
+:106EE0001D909842C7FBB157C4D39C7A5B91D3FBEA
+:106EF000D96F69B2239F58E4294EAFB31668783E24
+:106F00002E137BFE8B186FA6F24607E8D32D5C9FED
+:106F1000523D4A205F207B8AC89761FAAF86EBBF5B
+:106F20001AAEFFF665D0AB15902B96877605DE0777
+:106F3000994412E8C7048FAA9867BC8FD0ED05F476
+:106F40005AD89B362FBB80C3EDD6A7055C9F56BC95
+:106F5000E87ACEF5A87B7F2FEA8B9B128C9BFE777D
+:106F60008DEF8F2EBD2AF0B0A58AD9C97973D3DBF6
+:106F700081EB5D74342A9B31FFC04D8FB734E67FBF
+:106F80000B7A2CD0ADD7B5FCCCF4EEE1F4BE9CD39B
+:106F9000FB571AF33F44BE48267A5779D93C9706E7
+:106FA0008E875A6135D16AA483C2E9A490F5DD18B1
+:106FB000F725B713BB5FB9E1636A7F507A6C358CF4
+:106FC000C83DB47E691E9145D2FDC793FBF3893D50
+:106FD000DD2C7EAAE4692E3FCB6DFFEA9837BED543
+:106FE0009293F122B023766C5D0E76C4CBFE08C47A
+:106FF0000BB6E674BE887E5C62920A70087B91F0E4
+:10700000B82C981204ED26F7B993D3DEDFFA715746
+:107010000AEC2EB348C2785F47F8FEBCB4F7F15CC7
+:1070200076BEE10D38E206E48AC1D9EBAB38BDA9E2
+:107030009F98EFB5C5295705664D62E7E6334C3892
+:10704000DF91AC5932C4D1338D0311DE13B6F3A6F0
+:10705000C5AA3512C693C06F2CEBF71B0919C1E204
+:10706000F262FD83BD3FD0B8989D7B73BCE65DD6D0
+:10707000F5B9F88FC2DF17ED0C6AAFA5BBBFE3F619
+:10708000C36B3CD614EF258387FF116038DAFE8589
+:1070900072A5265DDCA087EBD7C0D1AED973E9FA23
+:1070A0002A5FE4717D6AB6D9CFD3EECB53D3F6FF16
+:1070B0003997935FC1E548D4EBA978BE84F92404DD
+:1070C000D625E4D13DFF443EEFC4CF38FFCB5CAEC4
+:1070D0002772B9262482E73099E6ADE67A43949F79
+:1070E00076DE1EBEEE6ACDE471DF73CF3B87AF73F1
+:1070F000CE675CEF493EEF9C41AE77019F6FC16761
+:107100009CF7233EEF8241CE7B2BC7EFAD9F11CF83
+:10711000AA2EF1710687E7563E5FEB679CD7E4F332
+:10712000B60E72DE4D1CBF9B3E239E47F07937B9E9
+:10713000F09C497E777CC6F9CA74263FBBB8FCBA7E
+:10714000F59A983F502847A1FFD6101DC7A6A7AEB5
+:10715000F4B2F94549529FA0DF3A9C9FE74E597E11
+:10716000C7C27479E1A2BD7B3FCE34CF37799C464C
+:1071700094629E203F079D72199D27CDFA44FB899A
+:107180007058909F79FC251C9E25E7B90ED1BE5AF8
+:10719000637A36D3F8777238EE74C13FD0F8A2FD27
+:1071A0009C01E0EFE070749C27FCA2FD8201C6FF09
+:1071B0002E87E3BBE709BF687FEB00F87994C3F142
+:1071C000E879C22FDAB70E30FE931C8E27CF137EDC
+:1071D000D17ED300F87996C3F1EC79C22FDAEFEAC9
+:1071E0009377A7FC19E2FB06115206F7BC47117F03
+:1071F00004BF6F10E9398CDF3758A985F1FE799704
+:10720000FB5E94ED3E1515F1C37796C6A1FDC38BC9
+:10721000599EF2C31309FA110FE7B3BCFCBE7816EE
+:10722000B7071F9E28633CE9E190338FD9E0FED970
+:10723000C3111E2719C1F2988D72719F964E57C0C7
+:107240004DC430E4D3B0FB55C2DE13F7AC56A97C75
+:107250007E8B245B69FF87CB597DEB0C92948B6C02
+:10726000F7AFCA52780F080C5B88C3F6DF1FB3C8AC
+:10727000CA0A5B1EC6CA14E619A83C5F8422843879
+:10728000F2315CF7B6C4B9E135116B26A8B9A24A50
+:10729000768E571475FA0F8D70998BB6FF2DD79394
+:1072A0006665FA7B357B75169715F99A57F3F50BDA
+:1072B000BC55707A6E98F3C7EEE9749D2F4CF5605B
+:1072C000FEE80B47391EA72A49766E4E3CE9EEE3ED
+:1072D000648AB3199DCD477C143FD7BC482240C671
+:1072E000C036AB3D8C71B58F91FF30AE46E7BD66C1
+:1072F0005B4205FE9BDD199E0EF1C0AB5F0CAF82B9
+:10730000EF0A8CEB24110BD0FBF1B7709CDC36122A
+:10731000493252B59A2CDEE78CCF897BBF3C3E07C1
+:10732000616ABB7F399BAFBBA2CD6C8723BB8A1937
+:107330005E87FD3A9BFB99FF64791D7EE66C7E7F3C
+:107340007AB6CBCFECD49DF13AA3333A13E2DCCA40
+:10735000D5C72C1DE08F4A265C4BB921BA498573ED
+:10736000E4D9DB9AD9BDDA0CE75AD90FCD0DD8EDA7
+:1073700077718EFDAB6DE7B6D7459C41C41D5EE1CC
+:10738000F7F15EE679C57DF9289C3F72AF961C7CCB
+:10739000D2A9333DD2097C92FF9F7CF279F3C96F69
+:1073A0007467FCA113DE51792C8DA43F9F6FD0B57B
+:1073B000FF94D72F800E415F7A3A90C66C471EB17A
+:1073C000C8A772E36D0DC79BA8EB19EEBD8CF0F159
+:1073D0007DD6EDD7BF11AB867589380D2177B9CE33
+:1073E00035A746CE159750C4B98FFC8602EB29F31A
+:1073F00071FDA31215C777AD03E5BE00F20D390C80
+:10740000AEF1DA415F78FBD7E529895A12DE1725FC
+:1074100078CE07F9EAFBCA617F341DEBB67C6CBFFE
+:1074200059C7EF0BAD2B5393592CAFCAF9DDA2927C
+:107430001D7A3ABB4294702FD59EE7E186572B897F
+:10744000C5EDF0681C1EF7387333C2D3E0887F9D0A
+:107450002F3CDEF1847403DFAA948B917FBFE51883
+:107460004F2E4B929E7471283E0EDC55C375B9E8C1
+:1074700092697E7D8433FF49CB73DE4F518D5C571B
+:107480007E948BBFFAE242839B4F7CCF6735E783C4
+:10749000367E1FC5DDDFA72648240DDE7D61771E01
+:1074A0004612E9E00D39BF3BE0315D70BBC65F0FAE
+:1074B000CFD2E4DFB8EF57AE5593686FC5299890E7
+:1074C000E7D9CEF9523593782FEB3B3E29EDFA49B7
+:1074D00024FD7EAB96A487DF7D2F48CBCB75D221D0
+:1074E000C3FDDBB542EECD5D16F00992260CFFE739
+:1074F00096F3839173EDE759426F49BF513EA14B1B
+:10750000DAED737D2F6190F4553F1A029756FBEB2D
+:1075100054AF42BC96CA08E6F1BADB1F13F87B638E
+:1075200007C22FF474D636914FFBE9D601B906ECA9
+:107530007CDCD93FA31C723DA770BE7E6E80F567D0
+:10754000A2AFBFC49D4F3838FAFA40EE61DF532D29
+:107550007E88EE94FB4CF31193ADF77CE5FED3C22D
+:1075600039A42646409F69A11889D17DBE309490E8
+:1075700020CE6048BD71F0C7A84C8581CE1BE1527A
+:107580005DBEB3DD34DACF5324C73DD9207F91C32C
+:10759000D03E1E225DD07E7D9E5AB3A3BCBF9D21EE
+:1075A0009128F0BB91AF46E1B9182F7BAA733C6AD2
+:1075B0002628F67B58EEEF2D78A630FF54A376E808
+:1075C000F674FAC4CFECD0AC677D78AF2F1035924B
+:1075D000C092859549CCE32C6C2011F0E74A3BBB67
+:1075E000498C0EBA96C3515899C0FC80C26D093CB3
+:1075F000B7CFF39266D8970B1B13D202DB3C657EA4
+:10760000C6DFD3E6EAB84F7CAB9ADDDBEB0E2D4C40
+:1076100054C37C55ECDC2B90A79261141F8157BD9D
+:10762000CCFFACEC816F49B07C11FAFE9D16525133
+:107630003F9690F75A742C4FB698589A1FFFCF1068
+:10764000E4B7B45F32390CF90867020DA361DFF8C3
+:10765000A02584EFEFFB76240C7944CA91D7F03B48
+:1076600012FDFC1E574815E4BFF658403FDBFA7781
+:10767000F86CE7FC7DEBA2EB5D40E7B957926F84B5
+:10768000F9A0BE10F95457B4028EEF30C333D89727
+:107690009E76127DA21CBE6792946E2DB73DF75167
+:1076A000BB0DF6D74B4CA47B3F3E93AD1CDF13C103
+:1076B000DF2D7C91E3756ED539CF4DD6B7A4BA676F
+:1076C0008CEDAF1B19EEBBCDF54CBBDC4FE7990938
+:1076D00097D8299F4F9F5B3614F0F5A0C7798F5C30
+:1076E000948A392952026DE38532CA21FFDECA8AA3
+:1076F000F1E1A139B6F16772F895233F41FC669537
+:1077000027C477776A0B6D79FF23620DEC3B7ECD42
+:10771000EC7E8C38871C7D7D4F2B1C498C5EE9BC30
+:1077200037338BDFF32C6A9731EFB5680AEA505292
+:10773000D44A30BF6AA712A900FE7E88BC9C632988
+:10774000B02B1332928A6A51DC39CECE45B5CF4385
+:107750001C40DC1B5DD5C6C61B158E1C0D43FCA44E
+:107760005C467B793489E830FE68432670AF680C4C
+:10777000B18D43EB239B9DE3BAE12D0AC8F8DD02EE
+:1077800001CF28B25FB7F2707C92A4FD4750376FEB
+:10779000781AF8DCF38C11ED2EAAA8489134F392F4
+:1077A000DE5638173A6BFE01C66DF1F7E5DF05418D
+:1077B0009F6F93D8FAE32F2891DD40D75BF760BC29
+:1077C00066C48A4EDCD73BFDCCBE5B4DED01C303E6
+:1077D000760A2DC766E643C5A488CBC6FD232DFFD8
+:1077E0003DE6AFDEE88778987FDA46E043BF1ABE11
+:1077F00016E8E13FEA21708EE9B712287FA484D908
+:1078000019F796176783BCF99BB5B4FE5A9BDF83C3
+:10781000F06DF34B2AE48352DEC275A98DE1EFCE01
+:10782000A2D5FF966F3D02F3BC9F1FC3523C0F2DA4
+:10783000AC0B037F4EBFA51CE35FA73B258C7FBD30
+:107840002D253548D15E7A75F3842B283EE6E4C4B5
+:107850001E857E8D75DDCFB333DAE652F0EB6A21FB
+:10786000CF2F1FA68B337F70C45B1115EE838D5015
+:10787000539E207CCFE7C8ABAC8C5703BFEB7003A3
+:1078800086D2335862BD0B7E5380DF3F52486F5C17
+:1078900002FF682A216FD9E8063E9DBD0E67BAF641
+:1078A0007A26FC0F54D6D3BE6F8D855D3E62496843
+:1078B0001724D97710CCC8048053091D2D28B1EDA9
+:1078C000735EBE3EEFF485FC7B4916F76F22C4EE73
+:1078D000DF7AF9BA4087BF65EBEF0939EB8AF9F92E
+:1078E000AE43D8DDD2337F3901745CF5A407E39E43
+:1078F000D39FF4A42EA7F565DB25DC67E4434CAFEA
+:107900007FB04B42B94F0534D403EF9B3AD69BBCB2
+:10791000DD1BBE44EBBD4F2A6407A2A50EBF2F7529
+:1079200042ECA707587D117790966D3F3C1FC66BC0
+:1079300038E025B04F2CFBC92D577D89D66FA17C2F
+:107940000C4D96ED6ED586D1FAE2A4D405F553D34D
+:1079500008F2593C574B425ECBA96077C13506EE21
+:1079600063243C0ECEB7BB0BAEA6FCB824F9C42CE6
+:10797000E8B764AF049154BA8EDDCF1752B8967D44
+:107980005FC2FD71E99E2C12B6E1F3045DCAE5F415
+:10799000FD0ABA4ED087B790C42CA0D7B2DD9B3475
+:1079A000FB3EF75E4B19A67E88FAB2EFD37968BF2B
+:1079B000E53F9422B0C4E590EF00FBE54F7C753BBA
+:1079C0000D585FAB561A8075ADD1A0DD2DC9054F9E
+:1079D000F9C200DF766D167DBF64DB766D5139E04C
+:1079E0008DDC08FBEAD23D1792B08DAE273A15F434
+:1079F0001756E4E83BF07BA286159A9B261EF25EA2
+:107A00000B71C0B584EB0DEAF769736CED9FCACAC0
+:107A1000413E5DBA4771CC23E81F3F46D83DB49F35
+:107A200005F01E9AA09FD8AF04FD56880FE5A9BDAA
+:107A300093D3C103DFD5027812D4BF81F2FE961032
+:107A4000960FB684914E9B018FE3585E0A3CA77255
+:107A50008BDFF30B5AF0A129B88F625543FE656E98
+:107A600094D50BAE8F49E173D8E9A2DCEC892D00E7
+:107A700023676AD6F766AAD41FDBACC56E8590B5BE
+:107A8000A9EE983983EE798D59D1C959B673BFD50E
+:107A9000FC3B3217678571FDAB0B35C4F7E61B263F
+:107AA000EFE4F127DC2737DFB0E851888FD3FE5FA2
+:107AB000C902FF829FFF65EA5F30BFCAD1BF607E07
+:107AC00083E83F0BFBEBE7EEBF79FE65CEF9E72FCE
+:107AD00011FDAF42F88D73C35F70E354E7FC373696
+:107AE00062FF262FA36F6F8E8E79D66DBE48CA03B4
+:107AF0007456097E875ACD2DDD01EDC4BE432D4B52
+:107B00000BF2B68DBD3915EB889D8FA6CD073802D7
+:107B100054BAEC7C945DE577C8558E95EBA80FA917
+:107B200019E6689F1F2D76BC1F5A77818B2F0DBCDD
+:107B3000B78875000A0C730AA7364C437D543D8CF8
+:107B4000D9C1771CF261FD8ECBD8FAEE1866A01C65
+:107B500003CCE097DFA1C52EB67F2796AE4B82C33C
+:107B60009C9B8DD89DB08EFEE761199EFB79BE93DC
+:107B7000DF4B50DFAD299ABC336EC367C748CA0FCD
+:107B8000B4DE96A531BC733AAC19B92864B7D7579F
+:107B90008FD4EAC0DF80E73719305F7435CCD7A4C3
+:107BA000F59682DDE19EC75B5CE598471FD580F3C3
+:107BB0006CCA62F154318F7754836B1EBD6E077FA0
+:107BC000CEE77900F82CD33C6B8A2F73AE67D412C2
+:107BD0009CE761D73C6B462D71CDE367EBA1CFF9F4
+:107BE0003CC973CDE31D33D5B99ED18D38CF3FBB92
+:107BF000D733BAD1358F81F3C07398871ABE61F835
+:107C00003E96E6ED5D84F47FC687768EE68D3D86F2
+:107C100076CEEB3EB473682B0BBFA355C6FCDBDB03
+:107C2000B272913E67FC94FE869DCE719E7710479E
+:107C3000BFF8660E22495288A87E5BCE79B07EEFEF
+:107C40009C51AD501E981E5A00FEE883018CE37DC6
+:107C50007060BA76531A7D7473C273A2C7C6CF7DA3
+:107C60007A95C7634359EC1C52D44FF0F8CF5B10A0
+:107C700027A2E5DB1E82FED0711E2FEA87B715FB17
+:107C80009DE0E77A27B6B17DEACCA663ECBB3971FB
+:107C9000F272F964F81E0DFB777322CBE18F377116
+:107CA0007AF4FEC49BDC81F4B086E3777F3B8738AF
+:107CB000E285BF39F4B5E759DE1D190EDFCBBBAE47
+:107CC000E389E7A0D92BD282912BE87AEBF66FF209
+:107CD0000CA7F50F3C3DF323866D9C3A0FDEBB17D6
+:107CE0007EC837621E87FDFCCD0667FD06973DFD09
+:107CF0004656B1389F65F386931EA0D73C3863A5DE
+:107D000024BC014A4CBE33915EF34DD657C0D374A8
+:107D10009787A470BFEBC9C738673C1FE33431B104
+:107D20006FB9E09BEFD1AD28A5E7FC3B15C4A31BC1
+:107D3000DE9E4359964CFD9C9ECEFFED81FB3B039E
+:107D4000C17FE34AE77B12F738BE4320F8E0DABA96
+:107D5000EA9DC76DFCF18DD8EC9DC71D789AE3A80C
+:107D6000DFD0FC0D47FB1B572E70BC5F105FEC781B
+:107D70007F53C7AD8EFACD893B1DED6FE96C75BCA5
+:107D80005F9C5CEB78BF74CF26477D59D71647FBC5
+:107D9000A603DB1DEFE543E3FF09FDC05F2978CFB4
+:107DA000F943E3C406B0DF3E34D977FEDFE1E7777D
+:107DB000EFF1EFFD2C07DE9B02F2334907BFA1C9AB
+:107DC0004FE599DA12138CFCD51D53418F10FCA49A
+:107DD0004685317C759C3ABB53F8BD44A55323A915
+:107DE0002170BCD21F87ED55FADFAB3DF4FDA4CC6A
+:107DF000EF954E35ED7BB5474D3BEE29A9B714EC19
+:107E0000C7F86BDEB4F7BFFBE5920C87FD22D3FB0E
+:107E1000933269B0FB6FF30C161F7A3E6BDA3C03AA
+:107E2000FC218DC97BE3BEC269E037346AA9D274F4
+:107E3000E7367DF37549F89DC079069397C549E704
+:107E4000F76F97EE19E390FB57FDB16B0CDAEEE498
+:107E500061857D2F2FF5ECA8AF5F04F35BF3E0396C
+:107E600039908FFBE32B2DD6CEE3D40F78B5A50642
+:107E7000CB7F6D89EE3C4E1DB5375AEAB0FEDB96DE
+:107E800018963D2D0D58BED5D28CEF8FB7ACC4FAE5
+:107E900089963896EFB47460F95E4B02DF9F6CE907
+:107EA000C4FA072D492C851C087B9744B93D290E3F
+:107EB0004C08AB9FE66B500A441C3382DF8F3A6D4F
+:107EC0009C29053BFAF4AB5ECCBBCD842737DF653C
+:107ED000A69F85FBFDA2A433CE2C4A9F9FD1C72726
+:107EE000931AC891583B56C3389AFF990BD11EA7D5
+:107EF000CF55C2BEB71CB17F4FA26F7C481E1E3A41
+:107F0000309D44FB13DFFBF7C90BCB813EC58827AF
+:107F1000FFB34A33A3DBCEC8D72F1A187F68F315F7
+:107F20009E8D47E999DF8C82F8D4FBF9029FDDA38F
+:107F300020B8A51AD12DC087A7F77B715DA70F6662
+:107F4000B17C1408AA0D22FF75E91E5FD2AE1F9600
+:107F500075E5249DFAA23069D717A78FEE0C82DC55
+:107F6000AF0829C9E393803F2CCE1F8CEFC4F8CB18
+:107F7000BA8A9286631C67FD7442AAE9C2B858386F
+:107F8000FBEA34FE87285784349CE7BD3D6330FF0D
+:107F900080FA89C9E32CDE9964F3869276BE6C5C24
+:107FA00099953C3EA41FBE4CE37EDEF011B29FFCCF
+:107FB0004ECF7C0F77A092A8FFA6E1F72D0F7ACEC7
+:107FC000C0BEE3A5FF7D82F9422AD6C5B84D5D4A01
+:107FD000DC0BF778C95EC77CB45F58F8E8F6EFE6CB
+:107FE0009C4D77673EF86F819770DF66F7CA6370C4
+:107FF000AF9C8E774A353AA48BFBEF953771BE5C08
+:10800000A6F76831FAE8FDFD63CE990FF25ECB5119
+:10801000531D0B790409FC604443D7F819A01FDFF6
+:10802000DFBFAA00E2694B95D377A4BB2FFB91C1B8
+:10803000E26C24E9E9EDB1AD47C46708A1E3EAFDCC
+:10804000F003A79FB0D5DDFA5A947280C5DD97EF93
+:108050003D36EB4B14FEE507FEA8011C078C981C6F
+:10806000B0AD5FE2F7EA97EC795383F5BDE389970A
+:10807000DE750E3D75369C46C8711E1A27DD20C779
+:108080000BD96F30003F5DFB3A15CD777FE921F0CA
+:10809000BB0EE2BC42DC7BA827D120E06BE1FEA551
+:1080A000181F7EF7A92BB93D97980CFCF13E916BF8
+:1080B000607DEF939782936CF82B09303F86743084
+:1080C0003B46DC0BA4F6ACC3AEB9A5D3595F44E67E
+:1080D0001680DE58F4A007BEA14A1613DBF797E816
+:1080E000BAF302CCDEBD8534AF067B4EF532FF60BD
+:1080F000A149D4E1549F2EFBF14393C1EEBF30C0A0
+:10810000CE1D451C63712EB3F796E42535384FF824
+:10811000DDFE49F3BE04DCE74DAE867D9964A73FE2
+:10812000FFBBA9C309DF40F0BBE115F7DDCF8AA78C
+:108130007038943D52DAFCB42901CE775C8FDC13A1
+:1081400070DAF96B5CF5DA008FB32A44013ABF6F3D
+:10815000EA71391BDFE3FDDAF83E6F645518BEA7FC
+:10816000158D027F51BB6002B1B5FBBD11C3E7277E
+:10817000A51717E1FD72353501F3F174A2DA7F8F8F
+:1081800041F10727908B214EDA8C4EFD2A5F700754
+:10819000D45707D83DA8269053B83F1D9C7514E2CC
+:1081A000FA3A49A4AC2238FF76C6BF7D61673D0B21
+:1081B000E409F4093C007A4408C68BB2CA9CED027B
+:1081C00011677D491F9E528AFDDE47503752F87B6A
+:1081D0004D55EA49BBDDBC5C67F013F89E2A6D7F04
+:1081E0001BB7E79793701CF316438C0F6E9BCDF271
+:1081F000266E0B84F15EB2A45A783F620D74B5ED21
+:10820000634D1F492469D3EB4D6AAF067CD9F491C5
+:108210008ACF1F3662DF06BC6AC4423B57A7488339
+:10822000F36BD5A871D8BD6404FF2EA02B7F617DB0
+:10823000C074F87B422F78B85EA4FA624D201FF418
+:1082400060EF2C76AEDEA3B1F31DD64EEB6FB71EFA
+:10825000E0C8D4CED7DF6E53BA76CB7EFCF853712C
+:108260002AEF4B7EF49D201CA6BDAB260A20FFA161
+:1082700071777B10F8F81D351E8475BF9B4C9FF7F6
+:10828000FE73AEEF20DF09EEC92FE7747AEF07F730
+:108290005E05783FB3DB83F7EC9BF678535E4AC408
+:1082A000E5FB17337EDAE37D93D5D7E0EF2E341D5F
+:1082B00070CADB92C7BE5310C6C3BD38F31B490A50
+:1082C000EDE7E5BB7E3F0BEC9126D28B7AC2DD0F4A
+:1082D000E6FF2817F7AF0570DFDFFD5EE45B357161
+:1082E000BE6FDA7F2FE65535ED9F8D79544D2E39CF
+:1082F0006FE07EC88180F37736043E4892D9C5ABE3
+:10830000BEFFDD096F52784EEEFA655072C48F9849
+:108310009E38DD75D3234F8733EBF70FB85FDFDF70
+:108320002F89FDC207981D4F0EB2B2D1930A82DF8A
+:10833000D4B8DD13A11A84343EBEF3D1EF017FBF60
+:10834000E6C578C3D2C79F7BE5325A5FFA8427AF70
+:10835000962DC3803C604117B8DB0EF9BA820E4BF4
+:10836000FEE5392D7C117B7E776E3F3D963E715840
+:1083700023179D8DBFE95D8735FC4E909B2E5D6F69
+:10838000CE02BB7BD5F7FFA4817CBD7B4822438B0B
+:10839000CEEEDFB0FD39B4EB004F48474EA73EBAF2
+:1083A0009D45AFD4554F57623B13F6B181E8F53D7B
+:1083B000E0997CE4EB1F3E0DE705FFEA8D001E1AF5
+:1083C0007EF8AD20ACE76DB599F1F743ED05708E01
+:1083D000DEE089179858B2E70D0FDF8E7C77CBB1BE
+:1083E000DB0B581E9455C87F17A010E380DBAEC18D
+:1083F000752E2231E4BF868794289C937DA8929A9B
+:1084000027D2C8C7E541A6C7DEDEE1C58FDEBD0DB8
+:108410000A17FCC5979424BB6FCBF2126F17E71EA7
+:10842000F0DD465AFF5067F4CA0FCAE27B56BA83A2
+:108430006F77ADE9063ABD37D21A0AF14A8A873812
+:10844000C79B047A4839367328A31309AB93793F45
+:10845000AA27A7C37368DFEDB17C131CFDF8BEC665
+:10846000E6BF8DCF4FE1F6837DF67601B577D2ACCE
+:108470006F6950C83FB53F6C7C66937326F7BBD6D7
+:10848000323917729F9C5303EFFFED652647D00FDB
+:10849000F6790A576A28BE3F7CB5847AC14B52E907
+:1084A000E47B9787CBB7F33DF5CAD1BE157C42E19B
+:1084B0005761DFEAE71776CE4BE980F6DBA2076962
+:1084C0007FBB7D0EF3623BADFFB96DBFBF85EB8314
+:1084D000CB82AEDFDDD9963FA8EFE4357A928F7E6E
+:1084E0000FE497CA2BEC3F8D8F7B304FE40F7B9FBF
+:1084F0007DE53ACAE77FE81272EBD4A76EB96DD872
+:1085000077094927B77F302224ADDCD2E769E5D669
+:10851000E8417EFE5BE95381BF8541679E93D08F22
+:1085200099F0E8D68F7F0D84D9EF22B8F423FDF7B8
+:1085300032997C361F0AFE137CB7E49F97E1EF83E4
+:10854000F4F1A7E0BF3EFE14FCE75EAF137FEEF749
+:108550001782A122E2C5B4F4DC43E20188A7FE4CF5
+:10856000C178EA290AD36A4AE7537B8BF01E71BBB4
+:108570008FF9E7A7CCDE606E397EFF06EBBDF9DA36
+:108580006AD017E279AF8FC5BF4F457B83F63C9029
+:10859000370F2A4138EFEA49929A74FE08D5C80885
+:1085A000470FC9F49EC58B4F81FD07F3F94725811D
+:1085B0006E331563D44AF0F313ECBE7C7DEBB5410A
+:1085C000C853387570CC46D05F37BFA010FEBB854E
+:1085D0002AE49BDCC4E9FF0E896F9E4AD779D34118
+:1085E000E657D4AF4FCF2F4B78FB45C66D1AE82521
+:1085F000EA17BC658F872FE1BFC7D4B0CDF5FCE08B
+:1086000095C8574B5C7C15E37EE3E382AF269289E5
+:10861000DC6F93EDF96C3395F28D60979C3ACAE26A
+:1086200090A70F2A488FD37B2596FF04F1E029C03D
+:108630000FBD9A3D8FED24F05F9AEF1BF4BD7FF2E2
+:108640003793EFA24D1A9F7A7DC2565A9E7CEAB5A7
+:10865000D29F42FDC7BF1EF53A39BBFDF4437FC62A
+:10866000F3EC5387BC08C7A9433F1F7517D49FF687
+:10867000E2776A4EDDE365F99F8702C9B1F07E2497
+:10868000CB175AF5B33F4D60DF7F6943BABD1A641B
+:10869000FED8E983FFFE5BC81F3E7DD01B86753484
+:1086A0001DCAC2F3ADA6A77D18A739F5B33F4DB6D5
+:1086B000E7337DD6F52CE7DF413C15207590A77C8C
+:1086C0002A879D1B34FD74CA4EB847B46CFF610DF8
+:1086D000CE63A63FF39709A0774EED63F6C4079EDD
+:1086E0009E87E19CF577C11BD77820BE0BFBF53048
+:1086F000425AB29357C48D747861783845F100EBD3
+:10870000A27869007D99091FFFE71F161F7F9C0F44
+:10871000F3371EBC14E5A61F2F92C59E079270B5B5
+:1087200089AE9F3D3FF4A709601FFDA1AB15F7F986
+:1087300081D65D98FDFFDABAA5D460D65DF50FBB92
+:108740006EC6FF87826196F7E79283B3F9FCC7771D
+:1087500060FD878108C23B48F9AFFB875DFFA7A496
+:10876000FB3E4AF7E0C074FF2FD9EC5CF81F6FDDC9
+:1087700003D1FD054EF780097908A77EF6178CAF67
+:108780008BF50FB4EECDFF41D72DECA175722451BE
+:108790005C0479D8A9EEB004BFC3333701612985E1
+:1087A000E75DBBE17A3E9BF9178AC4E23664248B0D
+:1087B0001F11EE6FF4FD5EACC1EE57A9C66AF63D1F
+:1087C000323582DFD55B77C1C208E676908A57637F
+:1087D000501F31157FE7D6ED77B549C492A8FDA7A4
+:1087E0005EF0D5A360FF7BCAE4947702966F42B92E
+:1087F00086C7BD3CA6E6F0370C979FE00B3BDF7BBE
+:10880000F9783AA948C0EF77EB866A26E9FC463545
+:10881000FBFD68C8ED4CD8CE0DBDC4D69F8EB70306
+:108820007E93C5664F9E2FFEFE94CDFC4F45AAE871
+:1088300086BC58325E66DF3527EC5EF1BA1191E4F2
+:108840003AF443997FD98FCFD5DD80479550FF907B
+:10885000AD0FFD4AC2FD49950FA196C996CFD98E9D
+:10886000FB4B03D287D1635423A7CF0A073D04FEF5
+:10887000D3D0C5410F81DFF3A58B9B1E6EBCFF22B9
+:108880009BC5E7DC7472E483E433BF24450DE49FA9
+:10889000EFDD897191F77FF0E655D07EE94F150243
+:1088A000BF8BF6C1DE004981FCAA490DFCAC25FB5B
+:1088B000158C0BFF5F8242FCFF008000000000006F
+:1088C0001F8B080000000000000BED7D7B7C54D561
+:1088D000B5F03E73CE4C6692493249662633793103
+:1088E00049208246980408A82813020842AF038A48
+:1088F000606FD49167304F90B6B4D51F0389313C77
+:108900006C83220F4B7540545AA90D182928DA415F
+:108910001E62AD5FA3D25B6CB137E203150829ADCF
+:10892000FDE8BDF672D75A7BEFCC399389686F7F2B
+:10893000F7FBE7CB3F27FB9C7DF65E7BBDD7DAEBF1
+:10894000ECB97409FEC63376495C196B66CCC55820
+:10895000EDCF5319733276CF9EA4C8F442B8EEFD22
+:108960006038BB9AB19E55BD4773E17EF8A78AFF78
+:1089700029EC1EEE1E7E0BDCBF476377054B63E3DD
+:10898000C86BA6C3C4D868C6CEEE4F9913B133A640
+:10899000EC3C78278DDB31DB9CA4C4FAD91C669AA9
+:1089A00017FA05F079F8274A6488D27F3CC656F258
+:1089B000F17EA270F8F6992336846FE7364B08E013
+:1089C00068DCF9274B00E0A8FAF9CFD2BA61BEC63D
+:1089D0007D2A8B0E65F47789E173359A349CAEEF6E
+:1089E000E395B1805DA960AC01FFF5C1B5B37E3AF6
+:1089F0004B836BC7DA3FA969F8BEF954B735F67EE9
+:108A0000EDCF5FDE1B06D4D43EFF4C9A0FAE9F75B0
+:108A10003D95C64A69BCBB2DE98C6976CDD01FC790
+:108A2000BD98D97F1C98973137DCE7B75863C76A80
+:108A30003E5FE7374E33848FC138126E58DF67F8D8
+:108A40008F97B1B18E54E7C757C1FF63D8984B2AAF
+:108A50005C776631764D7F3CC5F015E6F4FCD9E7CE
+:108A60008F87013F67F79C791CE1AFFBAF3F3FFE6B
+:108A70007DC01F7BC5E6780AD6DDF8D3DFA6217D51
+:108A8000E57B331D0ABDD793CFC25EE8D7F36E52A4
+:108A9000240CB77A5E3E5DE083F5F6ECFE9BDB07C7
+:108AA000FD97BD3C291BD7BFEC85AA6C661F188EAD
+:108AB0009E158C4592F47045888EBE7D30683634A4
+:108AC0000F886B1C3D0E751E2A4038CF9D48F2273B
+:108AD000219EE0DEF272A40FD069386FDF07F86DD7
+:108AE000D8F5E09FD4E189F01CCE357990AE1F4CCB
+:108AF0004638198BE6320FE2B7B7D561EFDFBF8F8B
+:108B00005EC7819E23BE02DD76ADE6F37600DDD240
+:108B1000FAD3ED1CFE03F46944BAA5C4E8F6390B98
+:108B20003DE12D86766716D13511BEA25F015F3516
+:108B30000A1FFF7A47E07B0E949F3D297DF49A8EB1
+:108B4000F4FAD9E7050CE8FD89B9F74E368AB1DEAB
+:108B500097931CDBE1FE3D2FFF8EE4A4E785B72C45
+:108B60004847F8B32BB0AE1ED6F7D785EB6C50C490
+:108B70003A77A44693D262786F88CC98E24BA3FBF5
+:108B8000EFD3FD08E75FC45F2ED22772F0562501B0
+:108B90003D3A1C45B40E1671D1BAEB77FCC1827C0C
+:108BA00023E984F451C622BDDE9F8CF7259DE4BAEB
+:108BB000E3C773201EC6E8E8B683CB617FBAF65AD6
+:108BC0005871227A01BCF81EC20BED9E6D499A9233
+:108BD000CEEFE7C13A7ACC6C4E07C211517E97882E
+:108BE000BE8CADA2F53C1B2F97627D9793CBCBC17A
+:108BF000FD8FE2E5C70E078D2FF173F68BC4FAF9EE
+:108C000028CA39C0BFCF1E3A82FCC39835F2218CE6
+:108C1000731753587A710C6F12DEB31A23BD7BF6AB
+:108C2000A76A240CEB6FED38447A365EBE615D8135
+:108C30008E04F3FD4ECCD7B0EFE070D443675FDD18
+:108C40004FFCD7B0EB7D4B18C639BAF3794B776937
+:108C50008CDF517F4774FAFBEC73078793BEC5F135
+:108C600013E89B0FC5F88D078CE337EEFA9361FC90
+:108C7000DA7087C561BFFC3C9F6981D9B8DECFBA85
+:108C8000CC0CF5DF671DEA944882795F17F64BE25A
+:108C9000A9F52D0BD9B1516F274792004FCBDE9A22
+:108CA000F28774275E2D3E402DEB5CC9F9AAF3FED6
+:108CB000402ED2A5F3AD6FAA684FF6221EAF888D65
+:108CC0005B71BCA92A15E4B6E2647014B255BC3ECF
+:108CD0001873C264801BE6C946FDDC02E3F8601C21
+:108CE000A6F93D4118574D9B3C05E1511D26872DA6
+:108CF000A15DE5E399ED411602B8CC60B77D3A7EFF
+:108D0000F2CC4C1BCED271795E13EA85A5C05EA869
+:108D10009F3D16365403F89829D9FF148CBB74581C
+:108D2000A0EC08B4972EF0F8C3F0DC7B0B7FEF9C2F
+:108D3000C31E368DC0764104E528E5A2CA7CA0FAA0
+:108D4000CE2ABF5EC84025A408BECAED48213B9389
+:108D5000A2F93655433BA546F30346D947F6507E64
+:108D6000860BDFB3D07BDE0C45FB18D79DC6D250F7
+:108D7000DEE4F8B29F1C9769D1E1B87E66651A03FC
+:108D8000BB92C738DCAA584F31EB5290BF9B67A407
+:108D90006DC7F6D6D41AB2FF05ACF76000E8F664EA
+:108DA000DAE463A8C7E05F13F6CB6F32DAF741CBA2
+:108DB0008DEDC2B01627BF3E5310F8AFB8CD78DFA7
+:108DC0005955B964901FE46C7DE7140DF4B77376C0
+:108DD000E5EE5CC0E9B4356FF3F63395655E681F68
+:108DE0005F5F3755033DE2FC4D655901B4CF3FFC51
+:108DF0009DA9F4BC1690742DA8FEF5574F0D97C68B
+:108E0000E4D60560A6AB24CF37201ECE05CFB6E250
+:108E1000D3FA597FB5C023FC0B221EF2C7723CE483
+:108E2000D94FEE66D07F90A97B25F2E5132FFFDFA7
+:108E30000CECE7630E5AAF83B5383EB6E2E2D9D800
+:108E40004B23BF4C9F69EC63C9876A4C0E5477E88B
+:108E5000E60CE0ABD6B943374D465D5BE727FE82B3
+:108E6000991D640F657F8793E8335FD007E1B402F3
+:108E70009F2DE05DD822356C61346EBB2548F66AC3
+:108E8000A203E753C275EAA5ABBE3E5CF3907F90A8
+:108E90001EA92C15EF6B753E82EFB02BB090F0E65B
+:108EA0000AD155DEF7CC9DE30B019E6FC808D6E0D2
+:108EB0007ABC0B2F16E03AA667301AAF6A913D8054
+:108EC000F6F5C201508309E44B5EB7AF607E6DC812
+:108ED000C0CF8399A16FE3BC45BFF4ED3906E38DA4
+:108EE000986FF1DB608A11CB47F9B52CC61784FE69
+:108EF00087A09F07698AF2F76D1641F93B9FA4048A
+:108F000002D03E7FAF83F473DEFCE9C7D0AE9D4F45
+:108F100029EC88E2FDEFFB482EC11350502EF20FD2
+:108F2000A4476D69C4D77F8DE3EBBF1AF9D838EF3A
+:108F3000F94BBE7DDD349E438C078E113CCF17F478
+:108F40003AAF72FFFCFC0A1FC1016EE441B4BB5F83
+:108F500075BE4733843D15F4B9DF16D8887801FC17
+:108F60006FD6E37FEBC0747C42D0F18944745C68B7
+:108F70006D2A40FD704FB06332686E362323B40310
+:108F8000C73DBDF068AB19D6535FDD54824CDF9FFF
+:108F9000BE0AE973F781BB579AA1DD88F4F1F5A702
+:108FA000E388E565442F1D5D3B108E1107FE64428A
+:108FB000B8253D3729DC0EC4BFFF528622E6AD5BE3
+:108FC00069063C5ED86721FF37BEDF910C1FF59321
+:108FD000EDE1D60ABF06729A6D62A144E31EE9373D
+:108FE000AED59F9400FEBEF11C7C3CC0FB6B7ABCEE
+:108FF000BF21F56F7FBCFF1FEC0778A7EB57C0FBC5
+:109000003B5F8677E96FD70ABD50CBD6919FF95168
+:1090100060A67B30CC3B59B513FF2F7E4A25B98320
+:10902000FED3BDEE981E597C4DD3415CE7E21F2B69
+:10903000C4A7F3435CBF9F5938FD28EAF505ED4608
+:10904000BF69E11CD03300DFA2CDC6FB8B23717159
+:1090500020D3E973E08733317E1DC4F58C87ECA4FF
+:109060002AE4A16A51693AFA49AF987DBF213FFCD1
+:1090700075956D4F80F7FCCC42B2C37DED264086DE
+:10908000CEBEB3F93613EA4939EEC445A5D9E8CFC7
+:109090002C4DF57D69FC3568B9D19E178693994FA3
+:1090A000376E715BA6A13DA43DC7D0FF8ACD458632
+:1090B000E7C322571A9E5FB5B3DCD0BEBAE35A436A
+:1090C000FF11FB2618DA65D19B0CFD471E9B6968D2
+:1090D0008FEEFAA6A1FF9813730DCFAFE9BEC7F0CC
+:1090E000FCBA4F961ADAD7F77ECFE8BF9818E94551
+:1090F00096AC909E3CBCE2938A0F910147291311D4
+:109100009F556379DFC34B2C26471A5E4B4C0EE00C
+:109110008F57174C27FB7F78893BE0A36B4500E313
+:109120001EA68E1B154AE0DF4E727C5AF1A16EDE40
+:109130002AABD9A0D726398CEDF24C11170EE27C60
+:109140003326D328576AD3F4A8059A398B0767E3E7
+:109150007C205FD76672BD46D7AF205FE3B1DFE901
+:10916000B4682BB6A57C31615F2B051FC135602922
+:1091700047864A253B1CC09B3EBA1FD6203E9960BD
+:10918000F5E71DC1F598FC4E64BE89738287CD9CBE
+:1091900003B91D66434D5FC70E4BF9F6987C61B26B
+:1091A0005F998CF2495B1694A4331D5EE764F2FC70
+:1091B00011D87D7E75EC1CA949FC15E9EF4F19AD5E
+:1091C0000D8DDD57164DCF4679F30CA0072D9EE28D
+:1091D000613B40FF5ABC857495F75BE798A6441243
+:1091E000D0B536531170703F6B58CCCFAA257A7822
+:1091F000DEDE3804F0D550DD4B7E96C7D4BEE428C1
+:10920000AEEB572ACF93812785FA6081F09B174CEC
+:109210007D78C951D04B0BDE1C427A49CEB37545DF
+:109220007498DE3FC81B208E7A3A93EBF1C757043F
+:1092300086CD1F4270915E907E7941B87E32C637EE
+:10924000835813C5891B4DAC26D1380F8A71B29152
+:10925000E408AFC34EF2716EE1C9340DD6919C1A89
+:109260007A10D737774457058F0303FE99E07F15AF
+:1092700044EFD888FD0B3C1A8B28FDE7CFAE0EB526
+:1092800015C2FA5A324D7E3BB57B15EC9F741F63B5
+:1092900059D0BFE5BF5482A7E5D56B18C66749F61C
+:1092A00026867EAC5CD7A1CCC7083F6A670AD93D49
+:1092B000862E28E0EF5B82F69F7BE677A17FF1F9AF
+:1092C0000633CDF739ACD101E37FDEA946D0593F53
+:1092D0009A991C35415B6D4B257B5D803E27F45F81
+:1092E000D8991AF115C6F0A26D1EC7A260DF92F2DE
+:1092F000F8FA5B32ED117B21ADFB8799A36370CA4D
+:1093000075E70F1077BE22E06681A1063A7B210641
+:10931000EBC2B93570F6611C758399E2C205197606
+:109320008233B2223C6CBEB9FFFA5A3D336FBE1D88
+:10933000E0693EAE3215C6F175B7133E16023E2205
+:10934000BEFEF83EE72BFCAB4925B85F417AA99BEE
+:1093500027D3BA18FAF1F05EFD130A7BAC10F9328C
+:109360003485E89C63624F1526F00F50DE5C883F21
+:109370009E3FB0784AB89C78060FDB01E3FD2A7364
+:10938000407FEBCD4C6EF7E91AAF97C0FE85118E8A
+:109390000B9B15A2E76925623103CA6A6F8D1AEC2F
+:1093A000BE1A50C9DF88870BF4D8894C9D9FA3A6AD
+:1093B000DF371CC71DD83FDB7DD082FE9983917FAC
+:1093C00026F5E740FE19FA65C87FD22FFB384E0F0D
+:1093D000C3FA3E15EBFB34D1FA12E8DD1ED2BBDF37
+:1093E0008C26F46B5C96C47A29378BEBBB46878559
+:1093F000511E6A80BCBA2B4BFA71DCAF1848CF5DA6
+:109400002EDE285A5B4AFAF642972F3D13AECE0F56
+:1094100094A644E3A8CB9F1D8974596CAB4CCA0237
+:10942000F8EC5946FC6C59DDCF4EA567717CD1B57F
+:109430001FBEEC802F93015FCEAC2FF503B9DECDBC
+:10944000C1BC14CCD723F003FAF722E9DF5B7A6EB4
+:10945000C358B1FE962F449CCBFBBB859E8638F843
+:10946000868F7CD4FFCF48BF583CDC5D817150F3C0
+:109470000B57A4A31F3571EFED0EBC5E700E26BC1A
+:109480009CDB9B14C079CE6582FEB4637BCC51CC4F
+:10949000139C59712C538FD773CFBD55618671CEF4
+:1094A000ED79AB42C37C83C8A7C8E7F597DEA9086E
+:1094B000C2FBE1096C68935D475F2BD7EF1B6C3CE7
+:1094C0001FE1725B5AD908F06B5D19F4FEA36ED3ED
+:1094D0000FF0BE6A7DA7E04394E7B8FCCB06B3AFBC
+:1094E000D90E7C0E31961FF3F84B8705BC0B30FF6D
+:1094F00032C34379936685EBBDF0021E1F3A8BD8C9
+:10950000D04218CF6C52557CAFD7CBFCDBA14BD2ED
+:10951000E1F628AAA9E4AE8E00823F2A3993F07EB4
+:10952000DD598782FEBECCD768557CBCDE5996C813
+:10953000765D9EC63347233B96A27530D4ABB35CB1
+:10954000FC7D99AFA99A39275889703D60A27803AC
+:1095500014A582FA2B57ACA3D0BB67B5F4453437BA
+:10956000B215C3E40C5B0BFC3B18F09CE6330530F2
+:109570003F9A96173D61063F2CB785B1533A7F2F2E
+:1095800005990FD7F3A61AD90EF29FFAC578EB1CEE
+:10959000F0675292B9FCA4055B9760DE1AEFFF6B8F
+:1095A00039D285BF4FF451318DC4C2E90072EA58F7
+:1095B000E3B8927E9D2BACFEC1C0A87B5638E8FA7A
+:1095C000F40A0FC1F5F00A1F5D7FB86228DD1F485D
+:1095D000CE2E777D6805CCABE327E718C00AACD761
+:1095E000A93292C7874657A4CF4DA007E4F5B1151D
+:1095F000C7DC13870804023D72EA1CDBD614129DF7
+:1096000051686075AFAD0E8C63EC0173600903D6D1
+:109610007A20EB8B8998575AAB98288FD49A75701B
+:1096200075380FAF3E4EB743EF32CC477A47B52B74
+:1096300028AFDEBA76E283515D5D2C24EE07A0ED03
+:109640003DCEEF3F60E3785EC7D81484D7AEB0203C
+:109650005E7B6CDC9E7C6CE37AED53712DCC0A3D15
+:109660009C05F7FFE23851F20080672BFD7D01EE8B
+:1096700047A41CFA1BE56BD5E1162BCA87F7C0FB84
+:10968000B44FA19ABA2D0C4CE8F38FBC4BF92FD5EF
+:10969000122CE4ED9FAFC175B8D282DBD0C562E178
+:1096A00077A71EF680DC203F5C4BD808A31CAFB523
+:1096B0008976F8DF080F6BCDBCFDFC23BF5D1DA6CE
+:1096C000767031E205DB2D88978C0E8F09DAF695DE
+:1096D000EFAC3E763DB665FF77A8FF7359DC3E32AE
+:1096E0007BD08BFAA3AFED80F6D5BAB6C6DBCCCA79
+:1096F000AF727DF587FE763417F8B5E180D281A090
+:10970000790FAC57709DDE7DEB09DFF407F281CB5A
+:10971000A03CA6354C79AFA7571C73B4009DB5CCBF
+:109720003637E2FD0A4F281048A0AF7FEE92FE2A9E
+:10973000F4D7E7BF22E6DE6E9DFFEC655C6E580B4A
+:10974000E88704FE4091ABF23D27AC6383125AA335
+:10975000A29EF999D9817A8475713D74568CC5227F
+:1097600039E48FD4D978D3BC2AB46618EA893B345B
+:109770003FC6B9B585ED95688F6BF717FA57B218E4
+:10978000BFD46674B8CB917F328CED669117C9CE89
+:1097900068CAC828C5FD82F50598CF6F60ED777E51
+:1097A0000FE1FDB5CAD0AFFEF4E035E9D741BB1EED
+:1097B000DA68E7EB3BDFB2207F3EE8E4FAB3A113BF
+:1097C000F807C65907F21500C7639BE64846FDF443
+:1097D00074A0E94A74C97A1FF9CB541B3875CF14A9
+:1097E000051C446FE7A5D5566C5B1CC35819B62DF4
+:1097F0006B90DF6ACB4C5C8E98E557014DEC4F4285
+:10980000FBB78F54DD14B6C7EC8D57D8A7C6ADF69D
+:10981000B089DBA7F368D71A369BC2A8BF4CD62EF7
+:109820000BD2D78E7BAF441F07E16D99D4E771FA55
+:109830007AD9D4CC9BB0BDEC812247F84BF28A3563
+:1098400017535844E7CF3CE8E4725CA385699FA3B3
+:10985000E6621A3DFFE7CD676391915F369F9D9E5B
+:10986000CBF9EA62F3115D0F95FF6AE360A0DBB20A
+:10987000DD6653928EEF96ED16FBC9B640368EE349
+:10988000B2308177F0CF01BF5A615F3BAC819C3F22
+:10989000D427E7DE3513C721DD62CFD958831E08F0
+:1098A000607CF850B2D4038589FB27C7F52F92ED71
+:1098B0002BA97F3C3CAEE458DB0AFDB5BF27F5B5CC
+:1098C00011BEF5A6B8F132E5FCE56B26E6C5F8EA6F
+:1098D000B759D7FD2A3C189E67B457627D45EF0201
+:1098E000E643BB8CFCEAD7E9FDDF0ABFAFE662B115
+:1098F00081DE31BC9718EE9F5EE131ECCB2DAA5E84
+:1099000046FB87BF157ABE8685290EAAD99ACB2237
+:10991000BABCC4FF87E31F85E3BA01E0B8E17F1951
+:109920008E42837CC6E0186CB8FF8FC2B1FDB69240
+:109930009B0AA1CBA34AD85A8476E17E13E539D499
+:109940008C89BE95B82F70BF467E1EBA24589F5191
+:10995000A4B1635A39CA4F7B00E372B68AE77BE051
+:109960007E9BB99CEC10F9C1C50792EE463FADA8AD
+:1099700026B018AF2CAF94F61DE4BE1D13792BB999
+:10998000CF30C4C12A3570DE46B8EE263B5514AC44
+:10999000AE45674E4D1D958CF6F15153248CF385E1
+:1099A0001FE6F3B94C910E2BEADEB4C10EB477AECC
+:1099B00034AEFFD89A52B27FDB4D45572E01381E88
+:1099C000502A935F473C6714519E16EF2F85FBDBAF
+:1099D00085DD5233FC0EB453DB85DD6A16FA5DDE9D
+:1099E0004FC90CDE8DFEC44967C34DD66B500F05C1
+:1099F000DAB2C0DEFCC1D9B0C6730DDA1B5F9115B7
+:109A0000ECCB1F36D4AF417BB37DA52FC791116B33
+:109A10000FF93B586BD213F56BD05F69B12FBD07BF
+:109A2000FD1D78FE2B2BACF3994CA177C4F3A23E1D
+:109A30003D057A09F498BAB2AF1D46BD54D4A77754
+:109A4000EA49EFEC785CA5F641980FFD3E5847587F
+:109A5000C5F50ED1C8AFB7012CC9D0B60D2BA2FDEC
+:109A60001B58374B46FF7A187F2EF3EE962126CAF5
+:109A7000BB637FC4A3CDCBFB5B66303FEE3759524F
+:109A8000ED1487C83CBE2AF68F92451D85E298C129
+:109A90002EC1FBD675E54B311EB30E36EE935AE25E
+:109AA000EA2DD4F8FA0B7B94FCAFF79C22FF9EC5FD
+:109AB0003C978A63F719F397E3D57D7B4B25C2BBAF
+:109AC00034953954CC8384A2B40F196FD7AC604756
+:109AD0007D3AF9B0DA5920D17EFF8B2EEED7DA2FFE
+:109AE0006A14DF6C50C0BF413B9ACAF94CFA476612
+:109AF00087E45BA3DD95FE923983AF65D9D409D99C
+:109B0000187FABF68015FD9C838E728AEB55E6BFFD
+:109B1000B952E7EFB444A752BE4C7304C80FCFC686
+:109B20003811F33D0E3FD3FB39AD2B20B0BC82B1D1
+:109B3000272B4A26A03C3C668B5A8B91BE8F9A28D5
+:109B4000DE3B547E4F58C17CD9724672FA64857BE5
+:109B500002E6BBB769C1F43B505E8EC37C3E4E3714
+:109B6000BECFDAAC607EF7736B301DF5C143C8F72A
+:109B70003ABC3CE9E27EFD0527F73B1F3073B9682C
+:109B80000578A2008776F12ACA473DE0E2FAC95279
+:109B90003D91F23516C007E6E3925853D841EBE504
+:109BA000F9B5248FC950B7A75D1C4EEF5F709A0CB2
+:109BB00071751BACD3A7D35F3616A6FC1AE2F8A9C1
+:109BC00004FECB4141372BF8433EF24FE2F6A1FBB6
+:109BD000FB47E4AF48FAF4F9290AF8275F128F35FA
+:109BE00042BCACD7F78D5A2FE9DF468887F17E8FCC
+:109BF000C34AFEA1AC4BB00B7DD6EA09B55F877CAA
+:109C00009E9C361CF3001AEB20A4ACC3BA04D48784
+:109C10001EADB78FFF41E69B6D69DBB15F8BA8532B
+:109C200048F11BE52799B54703289F437572C31078
+:109C3000DF611A37C967BCCF5888619CA179E2EB14
+:109C400018C27DF54A546FA7B12DB8AF2CFDDE5C6C
+:109C5000512F742EE58F1528C7E0F78ECEA2BC4D8C
+:109C60002FC52D325FF375FDE46C1C03E3D1E57F56
+:109C7000AEF810E56CC6E442BC9FA2713E01575C91
+:109C80004B2AC7F06AF2E20C58FF37B238FF39D5D9
+:109C900076AAEB785ED8B1BF38E678298E027C527E
+:109CA0003D4CB2BF9BE245E1A7A97DFAF1DDD501AC
+:109CB000A3DF19D6FB792B1E7D77754B29C52BD4D5
+:109CC0007EFE9117D7603CF8804DB65FA036D8B9BC
+:109CD00028C64B6C6F920FF910DE0FA0BCB1DB4AA7
+:109CE000C8CF568B580EE263629A95F4A6BA3769CC
+:109CF0003BFAC110173F97A5CB739E4B3D5180FE99
+:109D00007082F1C286F10ABEDE78307F27D6CBC8DA
+:109D1000E713D3364755FE9E0FDF63795D7F0CC393
+:109D2000F88FBE90C4D6000A1F331BE55D5E378AEC
+:109D30003813F58DBE5ED1523D3F804C2DE53AC9BA
+:109D400093CCA23A7E9272AE5D1CC6A23A39C97615
+:109D50001512BD342D407924ED62293DBFE0E47C2D
+:109D6000D0BAC27199793207986724E98F81E7A93F
+:109D700010FA85897CA346752F522F0C24E7F1FB3E
+:109D80005AF17A515EA55E4CC1B1E1FA82CB984797
+:109D9000BF6773C75164A1CFECA17DAED158BF742A
+:109DA000320D4D789D293A1CF9F8A3FEF71B70710E
+:109DB00051CC33C0FD929D4B5E45763DEC0A7D8AC9
+:109DC0007ED02B2E919FF5803D54D1DE81BD28E5BC
+:109DD000F96B27E66343BE4D9318CAD36D948F5534
+:109DE000DD419F0BF13BB382720E12EEB52B781D55
+:109DF00099D4B3762D44F8B26A617E7584C08633F7
+:109E0000F6B1EBD24D189B691A97A35F3F7A96FC87
+:109E10000A9B1620BEB2394C3EF40B6C1017A2DE22
+:109E20005DE930F1FD168F95F2F5AD0A4488A03753
+:109E30009666147DE93EB6E5A29BEC2D40E2D1EB9F
+:109E4000ED7FFE3C4E611F8CF3680EEE37B043DCB5
+:109E50000E23123ED0E963E90FC4BF173FBEC4A76B
+:109E6000C4AF15F15A4AF630A1BFF1776137A5FEAC
+:109E7000CC96FAD675A2240A77EB95EE34F46B40B3
+:109E80008FFE1DF9A4E1EADE34938FF4AF9BFB4112
+:109E900061F13EB3EBF95AE6A9E5BA24FC4B5F5FEA
+:109EA00060D5EF97C4C31B6F67EDA5C6FA029BCFC1
+:109EB000585F20EBF6552D487C631E17B0A29CAC72
+:109EC00074943BD0CF69D17CBF0B505D8499FC6DFD
+:109ED000F0DF0DF3CBEB4320FF08C710B7C950F7F5
+:109EE00022AFA9B80F92E0BD496E8EBF870EDE4E3D
+:109EF0007A58F3F37DA178FA31D64EFC925AC21CFF
+:109F0000943F15F0A65D66DC81F8E807076DE4274D
+:109F10006B63AD11ACBB8C9F4F3507030AEADD3292
+:109F2000467EB29ACFE7578730AAD34E1B95C98693
+:109F3000EAF0D8EA9949CF97BA1C0CE9ADA69A8203
+:109F400089F845E2C9E33619F6AD3D926FBCBFA76B
+:109F5000FD151DDF4C74BBFAF38DC7CDF521C2A1F1
+:109F6000A76FABA7283B117D627A91F3D5E5F8A2E4
+:109F7000621CF03BDA79B86E8375746A6CCAEE5273
+:109F8000848B515D7BDD6C3B73805DBBC353799BE0
+:109F90001BC6ABE87A95D78B77BA2868AC13EFC7A6
+:109FA000CFFFB69BEBDBB7DD5C3FA69F083C3B1EBB
+:109FB000F0DCD995EC53E0516766623DFD03B76272
+:109FC000AC37D0BA87A3FF22FB57541BE70B0BFA21
+:109FD000DF2FDF0BDF9C89FEDC74C665A3D8AFF0F2
+:109FE000FA867D29912168575954BB05F0BA53C4AC
+:109FF0008D3B219E9C01E3BA935908D7EDCA827626
+:10A0000029BD1FD86D8F8DF76B8E3236A938B803F6
+:10A01000C79B94ED2D6B2EE4EFE3384792598BB537
+:10A020003C86F79B9380E532F17938674969ECFE0D
+:10A030001150EED8CFEDEE1EAE80FCCF3705DC68B8
+:10A04000473E7CEB7B5427BA88059EFC10E87335AD
+:10A05000DCC4F8AAE244D0827AE1537C08F87EDCC2
+:10A060001E5C8D7CB2A07DEA93FA3A17B6837F8797
+:10A0700022F1D59F1FB8FE0138C3D64C039C6C2C2F
+:10A08000C26DE5EFC5E3575EEF127C2CE909E8B934
+:10A090002A55D0730DA07E6E0AF7973B2D9C4E7DFE
+:10A0A000FCE3B2B4E23ECA592B7FCE0243B97F6FC4
+:10A0B000E5F4999B521041BFBA530BA4A07F3FB760
+:10A0C0006FBF3E40DFF5D4D902E9D720FDDEE2F1D3
+:10A0D000D7E94A7B9B02E39C3607D2516E4FBFA55E
+:10A0E0002A2BA9FE81D747CABAB3D366DFDA2BE1A0
+:10A0F000F9BC1FA98195F4D818579C6581916F62AE
+:10A100009CB54FA57DBBC287EF56AF86FEF321E01D
+:10A1100040BD34B7CA1E467FAEF3F74D7F44BB3611
+:10A12000EFF124DF2A98E7F0E6917FC5F6C7EB52FE
+:10A130007D4994AF2D52BC98475D5FE8A0FDB7E51F
+:10A140004CF8ADF74EAB1ACCD84FF15FB90F026B9C
+:10A15000FE98C9E74FAC9D08EBBCD2D569B2034C61
+:10A1600037643FB1D60AF47E6065D0837988731B6B
+:10A17000BFB516F3106E77A06BBC1FE0DBF49D69D2
+:10A18000D8EE7C4C8C175EBE16F30E2F9942850AD2
+:10A190003C9FB269FD34AA532E96E33FB53600F6D4
+:10A1A0007FEE1357FCF5048CDF90FD8B69E81F00F0
+:10A1B0007D053C0708BE05E364FB604A15F80ECE3A
+:10A1C0001466C8C79A63790DCAF7764A3F9D1D99F0
+:10A1D00086F9D879139AAA34187F53F61B6B4B87EC
+:10A1E0003136A6BDD21180F6D6EC37A7A5009F74F4
+:10A1F000B2402DE64D22D9BF9966BD1EC6CF328E24
+:10A20000EF54455E3FFCCE5A1CAFA23A5086FE4C3E
+:10A21000A9E7C3B55678DF8575AC30DF6D9B87AD98
+:10A2200043BF5EEAD17F117A14F4E61994877A6B02
+:10A23000F7514CF5162CEFB5F0FA66A13FF2385FF6
+:10A24000F7B58776F37A74D9F6F076E7AAC4FAE818
+:10A250002F1ECEF79DC9899FE76673FD23E526FD76
+:10A26000040BEC4A203FA66CFBFF48FEBCD9FF8FD5
+:10A27000F45BC665F45B86D46F029FA5467D0DD363
+:10A2800008BD7F6511EA89636E9FC15E5774CD2456
+:10A290007BF2AE47E8151F7FDF55C5EB817AF7A744
+:10A2A00050BE8B59BB4A904EF2BDD102EF550F4EB6
+:10A2B000DF84FDEABACC8CBEF3D85DF9A57E651DBE
+:10A2C000E6877571489D16A5BC401DE68747E27874
+:10A2D000BFB6A03F84E3E0771CB80F82F95D5773E7
+:10A2E00062FA4BBFAAEE62060B8FEC6F7F63E33B13
+:10A2F000E9F9E5D6151BCF98BFE83F9E45EC27C589
+:10A30000D9494B6238AB259F02BE4D3AFE5A20F820
+:10A310000DB427F9933D7B876D5F53A89F977F5FAF
+:10A3200005FAF9D9F1A82F41DFA3BF59A105A6610C
+:10A33000FF8AAE4CDAA792FC21F942D2B533B38939
+:10A34000F27EBD5B14F2A7E2E19A27E1DAAC703F3E
+:10A35000A43AA4DEAD834FCA038CDF29C61F35960D
+:10A36000E4E7C7DC9F06B9B903E517F7BD711DFE29
+:10A37000EEE133AFEE0FFFAF851F0574E4F87FC148
+:10A3800046750AF1F63286FFDCCBD0B3809E4B7F58
+:10A39000A86E40BB9946EF659F88A6F9A05F97E03D
+:10A3A000FFCE8E0FD2AE43B9D8A732C5C7D78D7AAC
+:10A3B000AB42EAE3F088372668E497C5EC878FFC68
+:10A3C00033A93FA3566BAC7F70E388692DA8BF9378
+:10A3D000B8BC3A55B036E531381ECEE67A6C6C28FA
+:10A3E000717CF303772A3D97F8DEB2BC8A7D00EBDF
+:10A3F0003B21ECFDD8EEB082745920F0D8E7CF08AD
+:10A400007D767352F773E2FB10033FCA36F83B0DBB
+:10A41000A662DD733BD7BB723E80B78561C90A5C1B
+:10A4200015B8DEE62914E370BE3CB5377B1BEA0F96
+:10A430006771A00CF58DE42FB02762BDA6BB66DA6C
+:10A4400039FFCF4C4087E785FE5CB099AFBFF33F43
+:10A45000AAA6211F74BE9D99B14AC7EFA7841F29E0
+:10A46000C795F224DF93CFF78BF15EC94E237C9C16
+:10A4700012F8433812D58BC9F770BDA4AFDBB8BE54
+:10A48000867587914EB0EEB0528EEB560C76A2CF09
+:10A490003E087CD75B00CF80C79DE6700ED631B9F1
+:10A4A000703EFBE5E517D643CF7BF7A792DE891F09
+:10A4B000FF5C368FE7B699789DD51113C833CA99DA
+:10A4C0009DC3DBB3D74BE3760B3EBABC3EFC6AF2CE
+:10A4D000B3CDC2EB62017EAA4FAC7F31779B11FEF8
+:10A4E0009502FE50337E87E7DCC4FCCD8CF0164528
+:10A4F0007CDDEBF171FD640991FFD6BB8551FC3A1F
+:10A5000004FC081FB41B83F672A53026A7251D0A7C
+:10A51000D1B16203D869C49B55E2EDF55DFA793F8C
+:10A52000CF4E357C4F5827E83F04ECFBB300EF10CB
+:10A5300018E739829BC3756A63C77598A7EBB3F7B1
+:10A540009E34C10FF170462DB91C4EAACB407FC777
+:10A55000372A06278E8FF3307B70158EDBF0CE9E68
+:10A560005CFDB8E91ECE6F4E75EE041BEAB1F5A096
+:10A5700057491D840EE17716F30F6438D6308A1BD5
+:10A580004C181FCA79E78B7C2DC865C50C585A49F1
+:10A59000DF3CA03F75FAAFC863E7FDAD5501AA7770
+:10A5A000D3B87D72B59FBE1FF73106B2ABFF2C7ECC
+:10A5B000003AD2BA7B77C3BA7C31FC7576DCBDCA6F
+:10A5C00086FAF204F3A3BE94EB1A52DD9D86753C25
+:10A5D0008D428F025E4CC807CE1FF958B34FA79F1C
+:10A5E00005FD86322E6F323E198A1B2CD0BED63323
+:10A5F0005CEA1BCA179C7AF1E567D7505CC1E9D5C4
+:10A6000058CDE92BE5F50E4FE85E0FCAC1ECFB68AB
+:10A610007F07FA55A0BEABDBC0E7817E1D8CE4B698
+:10A62000ABA01AF0F72F9ED4847473063B6CF4BE73
+:10A63000E0FF73FBAF8E201FBA6EEDADC2FBC00F03
+:10A64000044F67476A04E366F297F1FD97156EBF02
+:10A650005888F032BFDAE1D7F38984AF8FEE0CE887
+:10A660007E75ECFE906A3E6EE33E18978F43F25380
+:10A670007717A37CB3A40F801CC6FCBED43B2EFC72
+:10A680002C3E338647893FF97E03BECF78DE00E358
+:10A69000BD46D64DF9D33A359887F11ACB4EA2EF85
+:10A6A00054210E26FD73C4C6341BBCFF1A5CD1BEF8
+:10A6B0004F5297D0F742938A159273D010326F168B
+:10A6C000453FF2E6F129A41FD817F70EC6F5B85298
+:10A6D00038DFC13856318E95FC54A10F7F5300FAF4
+:10A6E0005089E9F1238A42E31CB9FEAAED549B2963
+:10A6F000D689E3A1DF7044999147FEACC86F00DEB4
+:10A7000086EBFDB318FF86055CDD05F85C1F27614D
+:10A710005CD3176785C7AFBB11E2AC31533AA226B1
+:10A72000074AC384E9DF817927419C6583F5DF8F80
+:10A730007C8CFABE30ACA6215C4360DD70EB6872A5
+:10A74000A8B4C91E9BC72DF25F6E51B78CFE3C5E4C
+:10A75000CD5E6E57D67BB9DDE81657703B12E6CB5F
+:10A76000FE533CFF773BD7E36B2A13D7376FF118C3
+:10A77000F39D378BFD2288B7B620FF40BC25EA77D2
+:10A78000F9FE12F8B584DFAA07AB69DFF4F3AE591E
+:10A79000E9FCBC072EFF0B44FDEC5DF7CFFA21F27C
+:10A7A000DD8758570F74FC48ECEF7DE808A4619DE5
+:10A7B000597D72E23AEA5F7AF83AEB051E4EAFE055
+:10A7C000E7332CC07D4DF083777BB8FD5AD47ECB28
+:10A7D00064A4FB2288E3715F53D64F483AD76C5587
+:10A7E0000DFB130B705F33EB1F8923CA06882346CA
+:10A7F00019E208396F7C3C716A85C7B08F32B7BDEA
+:10A80000589C8FC1FBCF637E827B5E5BAE611F96DF
+:10A81000B5B9BED2B906183F8413C26731DC3FB563
+:10A82000C20A02AE83E393C1547FB2C513FA9DC737
+:10A8300000470A0B1BF2C9E31CB4DF6FE3796CA07D
+:10A840007F58EF57C7C375C6F38FC66BC503E0B912
+:10A85000E47F255EAB18C7F51A6B57A89666CCC483
+:10A8600038FF59D8CB4B9E14431E607EB5B19FEA8A
+:10A87000E5F1BFEA4D31F8CD03E501F47EB3528C2A
+:10A88000FA838FD720EC56E1676F531DEB782FF7D3
+:10A8900033C6E60492BD705D27EAD8D7D9F877FEB3
+:10A8A000DBFE7EC8330FFD8D37CD5477C0F671FEC9
+:10A8B000A9FCF1B2663C37C0DEA138F4DFB57E6397
+:10A8C000B912980FF2E0167AA2CECFD753E78F5A7B
+:10A8D00006DBB1AE99C391D77150D1747A23AF869C
+:10A8E000F7F379CD86FA80C15E7E2E439157E60D4F
+:10A8F0002307A73AB17F40433B93D3A1901DCA6978
+:10A9000062F43D4ECE28EE9F7D63D436655E696C61
+:10A91000BD6DA619A50E78AFCD9DE247BDBD2A2716
+:10A9200074A517E13B198D623A67CCC92E0DE3A7D8
+:10A930000D3981AB100F729D3ED59183F627E5242A
+:10A9400087AFBD2F2FC1F536636B055CDB797CA823
+:10A95000B2638CFBBDB48FEB5E3594EC875C8F3BB0
+:10A9600053E85F370BED21FF9BB591FDB3727BEA96
+:10A970005E55427EB2A46B2C9F32AC1CF329C5EB12
+:10A98000A2DA5C78EFC5ADA684E7584C15788775D8
+:10A990004CD4AFE372F22EFB9907C85349BE4F99CE
+:10A9A0009238FE8308909E57FED8F94D92CF160B31
+:10A9B000C3FCA6C4FF869CE06C8427A7639B82B877
+:10A9C0003925EA234E25F3FCEDA935CF2AE887DDAA
+:10A9D000BB9839543630DC75CBD5C07CBD3CB758FC
+:10A9E000882E320E88C1C3E396262FD7EBAFE7043B
+:10A9F0001721BD1BF6ADA7FCDEE21DEF5BBE74FFA9
+:10AA0000E32BE24DA9E1F14DDD1C2BD55155FE584C
+:10AA100023BAD7B65868BFB26ED76EFA8E8DDDC72F
+:10AA2000FC28FF751DBB95F9306FEDAEDDCA021D28
+:10AA30001E73EB2254377E45AACC5F472DA8CFE387
+:10AA4000F91BF3FF68F78FDAB8FC9FADB487319F2D
+:10AA50007DD61CAAC37E67BD297EDC3F95787F6DBD
+:10AA6000F78D747E40EA9EA4285EDB4CDB3D56E801
+:10AA7000D776A5C58FFCB42127B40EE992A9053B72
+:10AA8000F1FD0C67AA1FF3E1BE24564E76EF2BE2D0
+:10AA9000614C1C5F8CB98FCBCB2B42BFC01FD571D3
+:10AAA0003DEDE5712E6E07A0BE3A6AE6EBD8C338DD
+:10AAB000BC666FE047C4B7C73269DE9CBAA882752E
+:10AAC0001FF1F3C6F82AB0CDEBFA3A70765850CFA2
+:10AAD000D70A7D53F9E31DCA073AB83BBC2AC19790
+:10AAE000B36B9B82F916784EFA06FA33ACB3CAD927
+:10AAF000C5F34CB5F07C814EBFC87524D033BFC0C0
+:10AB0000F5D84F761DE67A26CAF3CB02DE787A1E98
+:10AB1000F2FA68FEC96066E9BE253C14E3D0A3459D
+:10AB2000C9349E94FB78393DE4E5FE58CED61D8AA3
+:10AB3000C94E7978F2CB247CB2DFD89C09AF213C96
+:10AB400063A674111EEAB76AB49E4996E0E0253AFE
+:10AB500079F8AD909B5767FF91CEDBD9F08BB78822
+:10AB60001FEBDB151E0FB4BF6599857626FC131508
+:10AB7000F74DA671D3CE368AF3A8A675723D5CDF79
+:10AB8000B95B9B678FF169E167AFD23956F51D4913
+:10AB90000CF75381FFFE80F48BE753891FA96707E9
+:10ABA000A227E823FEFD43D822F2D7A1C299A931FA
+:10ABB0003D6D167861767EFFA258578C7F42E77014
+:10ABC000FE989EB5915C147E56FE2AD699D6FB154A
+:10ABD0003ABFC359C5F1A9876B46C27D32AE273152
+:10ABE0004FCEF32ADD053375DF93F5E97BF1FE7F68
+:10ABF00022BDB9DD88F2FBAC08EDB7843F9E7E57DD
+:10AC0000E4703F36019F693909EC99B4F3858FEF01
+:10AC1000D1F07B20C93FD390EE3AFEC9CAB1D0B87B
+:10AC200059391AC1B3B192EF5F6D34733BB671A558
+:10AC300095EA425FBB9DD7A9A57ED312C5EB11D380
+:10AC4000DC3A7C7E2487C3D1665A45DFC7815C3AF3
+:10AC5000734623FFA431AE1FB93EDCF03CD76775C5
+:10AC6000617B04CFABA90BDD3A9FEA109C363FD63F
+:10AC7000EFB2D061CBACD4FE7CE5DB73D082F04F79
+:10AC8000EBE0F227E900FA94F84BCA83C46B0C9FFF
+:10AC900011833C497A98FBFC895021F797789C52A4
+:10ACA000CA54DA17AAB1068EE2778C35623F15EFE7
+:10ACB000639DABDC4F9D2BE8F2B83D3812D7D96FBE
+:10ACC0003FF52BFAD9B5CBDFA0B8E61ECFEB7495D4
+:10ACD000720BF1A041BE2708BA0FCBE1F67D6A0ED8
+:10ACE000E79BDA511D2497B51F36913CDBA770BD59
+:10ACF000663F69D4C78C3D24D6BB8EDE9B94D2318F
+:10AD000019F721273DA138304E1E08CE45F81D18F1
+:10AD1000C64B5B0FA5DD8DF8FD02BC75DD7742DF0C
+:10AD2000CC11E743EE048413BF3759BECC1FBFDC00
+:10AD3000782C7A5CA1F342042ECFEEAABAE623DC8B
+:10AD400037D899EEC7EFF3CFECBAE5BB1F01DC674C
+:10AD5000778CF7A39FE06C0E12FFF4BA6CFEED3C0B
+:10AD60001F3A05F33D2B3B0EA5E177459F3E3BA2E5
+:10AD70001CF5F61201E767CFABCB112FAB9EF9F9AB
+:10AD80000DF8BC36A264A1FF7A76E713FF9503E3C2
+:10AD9000D4EC68C413C858F3B3BFA4B8C014D9C660
+:10ADA000EFEF4C273FF7D327D7DF80F86EEE68A68A
+:10ADB000E79F3DB98DDAAF3EF3F357FE03F31FC1B2
+:10ADC00034FA3EFAB3E70F125DEA421AD5C50FC452
+:10ADD000D71B771FE4FA12ED3CCAC11CAEC7245F33
+:10ADE0004BFEFDF499BBAED1DB0D79BF4DE441DAEA
+:10ADF00092B91D3923E4B67682BD0DAF677E66A396
+:10AE0000733B1B2CDD25181FD79572BE5891C3F5D7
+:10AE1000605DC71273839DDEA771FE0DE41DAF5701
+:10AE2000037F62FD19F4DA7189EAA89EA3FED06F50
+:10AE30002CE6496657BFCFBF2B2D6D32D7129CCF62
+:10AE4000F2E7B06AFDF38A6589F735B6E4D80DF903
+:10AE5000D19CCE19793ED20349FE213AFF37A7266D
+:10AE6000D48C7502372D0BF9F13BFA173F797B3201
+:10AE7000E6D39E19AA8C24FAAB0AB773613BCD5373
+:10AE80008FFB0E107F3C2BE4C4ED60CE6B613D93D5
+:10AE900034E6B4E395B1E366D20B4FD1F8E0E79026
+:10AEA000FFE6FBE5ECA7D0EFD9680E7947E3386DF4
+:10AEB000C23EEEE0F0C3FB0E7B398DE7B896FBEBAC
+:10AEC0004BF1BDF32BA73BD1BF8771BBCCBA780C3C
+:10AED00038B200ED238E370AF134253C87EC94CF4D
+:10AEE00042EB93E781C2FA297F2AE5333E4F83FA8A
+:10AEF00009F3ADAFE7541ECE71C5AEEE01F21CD61C
+:10AF00005CFE7C4A6E80AE5FF57CD15767F7703B84
+:10AF1000FFD2FBC4B70DC8B7387FE843839D97F5D0
+:10AF2000111BF7BF4F7C3B7F1FD7C70DFB2A2D1886
+:10AF30006F9D5911601F80A3DB20F86FA3D2BD90D5
+:10AF4000BE4FDB6FA3EF0E7B247FB6BFFF31EA9FBE
+:10AF5000A27D5EAAE7E9D9CFF9F488C944798023B4
+:10AF6000DBAFDAD6ACF4B7ABE06F939C343431E1AD
+:10AF70006F2F7B1BFDB3FA1A5E07DF10C747858F63
+:10AF80009F6A457EC900EF18EB32C09F994CDF6D78
+:10AF9000D6B1D128A7391303FB7369FF9BC7E739E3
+:10AFA00035A04FA07D9373B11F4B073226825F8C73
+:10AFB000FCE7BCDE8FF9A68DF91DADE83F87273190
+:10AFC0003A7775A3B97D02C6C11B27F91C8049C019
+:10AFD000DB0EF2AFD9508BB067F3C92F6FF0FCAB2B
+:10AFE0009FF2C1F1F2BF7F25F9770DBE643F9E83CA
+:10AFF0003B6D9FB294FB337686F037007EB13D2DDA
+:10B00000725D04E13927F027F1D863EEA2F3787B73
+:10B010005E48A2F30DA74DE4FC9A31B183F4C76BEF
+:10B02000FB6F247B2DF932756F12D9ED4CCDA1F851
+:10B03000295F744B12C2334FC0D32EEA8433841D70
+:10B04000295EC7FDB8CC5C2E4F99B92671B518EBB7
+:10B05000AC1C61CA3B9C13F42736D19DFB543F3F87
+:10B060004AF254B78B8FE74C0A94DDABE35FE95F9C
+:10B07000C97A03AC1B989180BFC7E6723B58F8F8B9
+:10B0800052A2FBBC1A713EC43AEE5730E00BC41B0F
+:10B09000D091F8E026E722A2DBBC75CA37898EE1A1
+:10B0A0000ACA1B4AFF2C7EFC71627D3B6DC1515860
+:10B0B00067D8EB4AF5E37ED7CE8C8089F2EE65192E
+:10B0C00094077165717FD125FCC598DC07479960AD
+:10B0D0009E4FDCA99CDE91DF6898179E92EB4BE8AF
+:10B0E000E7F58FF3F978D3DBC3C331EE91F5611245
+:10B0F0001F9195C973F4FA7482A04B64189B837AEC
+:10B1000003E2093BE5AF1D300FE613B65FF724CF2E
+:10B1100027F073A1AFCAE5DF354FCA0A8EA2FDBF83
+:10B12000E2E0326E3FF93AE3F1F1BAB09BAFCEBE46
+:10B13000B30CE3D8865BED7E94BB0D2F297389AFEA
+:10B14000C3563C3C08F89ECB21384C540FC5421ADC
+:10B15000D1A3A1291849CCF73348CE1AC0EFC33880
+:10B16000601AF2B993F83EC2F99EDB3F996F403DF9
+:10B17000A9F7B7A53E907A06ED1BF2B3948B861B18
+:10B18000BA4B90BE5F55AFF498B99CF7001E508E35
+:10B19000A4DCA4BEC8E565CD4A5F253E5F0372AF5F
+:10B1A000A7777C7C867062BC22F5FBAA9CE0B77313
+:10B1B000114E53B495BE7D15FAB8E1C5D52589BEAB
+:10B1C0005F92FAD82ACED3B4465222FA7D06DCB377
+:10B1D0004F2DA76B18ED51CAF2C4F998D5B9D2BE5C
+:10B1E000F6AB775A9DEBEA5FEFE446DB85F2B33DC1
+:10B1F00085BEA393F9A9F871BF2FF84DD245C62992
+:10B20000B85F80FD9F12F2B359C8E973E2AA8B7F41
+:10B2100088FF7DA6D0FBB8DF3F901D93EFFDB3F212
+:10B2200065721E694FE3E92FF73B703D334A07EE25
+:10B23000D77E50C48171FCF882F0A7EECD65746DA5
+:10B2400037473F27B95A92CA689F6D330B64E17E36
+:10B25000D92B57707908F496E0F857E68732F24612
+:10B26000C7F2C2781FE3935A8D85719FAC76A739D8
+:10B27000A2FF8E67277E4809FDCFA75AC32AF0F99F
+:10B28000B8FCD061A4677802FF5E2FFC3D1BEDFF88
+:10B2900080233D1AF54B23EB4E433C37A85D2598A0
+:10B2A000C7DCE20EBD8EFD4F99BA0A78BD05DF9F5F
+:10B2B0003A29F2BE2745DEB7D312CDFF8E3376CEC4
+:10B2C000DD05C6EB752E749932310E7C6FDF3B3F86
+:10B2D0007B09DEBEE3A573777C1FB1B526E5CE1FE3
+:10B2E000C1B5DAAA06F5E7FF9C4C4DAC674F093EA5
+:10B2F000EAABA759999430EFBF278FF34163DCFE87
+:10B30000EF9E3C1FBFDFF75D16DFFF7D6F8073B2DE
+:10B3100026E771FA748A3A9FF8E7D3C43C3BCDAC78
+:10B320006433C2B32D95F6D799C6CF37AB79A4D085
+:10B330008FFB929D45FCFCFCDE4715B20327CD5CDC
+:10B34000FFC0DFADD68A981D453705FDC41A4738C2
+:10B350006A02FD51B32C358AE767C27D6D1CCA5A5B
+:10B36000D841F5A673857D9CD7F4DADF30EF51A381
+:10B3700031EB3878EFB47D7E1A9A8785DFBA178F64
+:10B38000C061D9D5EDA22E519CD71698AE5E4AF970
+:10B3900032BFCEF85DCBDEBCA015F9AC3A9DE3BB65
+:10B3A000FA5E7E4EAFECFF9290DB7EFC86BC0AF02C
+:10B3B000FE51E1F6257E1E77FE84E751BF2DF7048E
+:10B3C000B368FC7BCF19F45A8FD2FDF48F902F977E
+:10B3D000A48A73D45881BE5ECA9FC7ED4B2DEE3749
+:10B3E000816A3C5FD655B2BC10F9BFB7E077987759
+:10B3F0003B904475B1B5B8EFA4AB671B68DF69E05B
+:10B40000FD269F05F9BCE1A2427C32F7C06B2750B4
+:10B41000AF3768DDC43F73AD76A24FC3458D9EB391
+:10B4200036F359FD777AED9EC0705C5FF8C17119F3
+:10B43000B46F950DF709CF43E99C8FA5A21ED99D46
+:10B440001F1A8DFD36A5A4DD85F1E1052B3F97A9D7
+:10B45000D1C2EB8E99F8FE59F209CB4B35F2C1817E
+:10B46000D7FF8670CDB786E81CCB05739AE8DCDC85
+:10B47000EAF4E86847A99EFEE3BED6B9B95EA137F3
+:10B48000DEB3F0FA9CFEFCCFE9B0278FEBAFF7728A
+:10B49000B81CBD57C06AF6E0F54AB8C27BEF158903
+:10B4A00076396FC78FD328E4E8BDE1DC7E8597A6A7
+:10B4B000243C97E46E218F7BF302B723BEE4FDA703
+:10B4C000051CEEFC40759E8BF46348F06D3403C69A
+:10B4D000ABFE25FF1D03D6D24B75257DEB2A11F05F
+:10B4E000BA13C3D5121B77118E07FD02E4C7BF62E2
+:10B4F000A3EFEFD874D0D7A89F97E633D4CF306F9F
+:10B50000631E1F379A41FD92681DAC0DF436F0EFB3
+:10B51000F9D13EA2CB9A4AE0D351E25C7E5F8CAF78
+:10B52000243FC5F3D17D79CA40FBE2F7E17CF1FB12
+:10B53000E28C0D267A13BF7D8DEFD8466471BC80F6
+:10B54000DCB7E691FD8D5EAD973B8967A92FDF4B98
+:10B5500036F245AA80F307A25F1F9EC5395ACE6214
+:10B560006E0765BCF0B8E89F21E82FAFD2AEC5EFFB
+:10B570000F64887133F2D2245D1E13F4CE4848EF75
+:10B58000AD9CDED0EF09EC579DD47B6716D8B3DBBA
+:10B59000C04FC2732FE13D2FDEEF97B798C8ED7013
+:10B5A000E3D254867EC24FF244DE6F542FDFBF1BBE
+:10B5B000DA4BFA682E03BDA35C9E7E9823F0823E90
+:10B5C0007C43D40F2958CF93496AC087E301BE3B1F
+:10B5D000F35C317CC7CF77121F815FF84A9EF8BEBB
+:10B5E000AF8C9521BDEE7CEBCFA977F8F01C74FEF3
+:10B5F0005DF147F6D0AB38CED9EFBE4E71C0494BA6
+:10B60000B4A4DD9EE0B925FAF82625F6FCAE9FA885
+:10B6100061FCDD8BCEAEB38FCE06BE9CDBA5FA718E
+:10B62000CAB9F77DFEE618F4AFBBCCB40F05FEC572
+:10B630003A3C179435717FF4A4C948FF33DF36D6FE
+:10B6400075740B7995DF3B4B7D25FD86C5CCCFF519
+:10B6500054323F87FDD49245F4BDF37C163C8AE713
+:10B66000B07FBA742AF9D38B58887E8F605E9BF1C5
+:10B670003CDEF8737CE3CFEFC5043FE22FFE1CDF16
+:10B68000BE7C7B55623F23359FF3E1198BA82F18B1
+:10B69000C0CFB828F857D61734CAFA8297BFBCBEB5
+:10B6A000A031AEBE20E68FC8FA822F284F68CEF7B1
+:10B6B000D1F8389EBECEE0CC84C4702BF9D2EF49CD
+:10B6C000318C2FC789CD9346CF1BF13C9F84DFABD4
+:10B6D000DBE9FE998589E749CFE7EB6E8CAB67889C
+:10B6E000BDCFEB18649C2FF9A2F1A297ECB16CF7D7
+:10B6F000FD0E43DF7B79F43CFEFB7C99A79772F04B
+:10B7000081C2AC5ECA9BAD177AD13F1CFDDF0FD062
+:10B71000AF4239BCD1F74A378038EFFBD794684540
+:10B720003139895F07F0D367FAEFE087E48B7379EB
+:10B73000FDCC4FDF490A3EBFF3BB93D2719FF5DFCB
+:10B74000EFAB327CFFD6F77DBC45FA7376835D663E
+:10B7500071767BDEBED7C95F9B6F0DD277781FBD38
+:10B76000FC5DB2D70B59D08DFC7DFEE52B0A42FF64
+:10B77000037B2DE1B9257CB799FBE94EF233660ACC
+:10B78000786E39C0FD45933560A67902CCE77053D9
+:10B7900028CEE105A589E7F05DDF077F299DDF3130
+:10B7A0004EC0AFE0FB80DFEBC595CD0D79106E7913
+:10B7B000AE00709307AFCDD7F87D781DAF0435A6E6
+:10B7C000FBDE74326BCAC3FE266BB72ACE3BA3F3F3
+:10B7D000E39362F8A276AA68B7DC7AE1CE0578DF57
+:10B7E000CECF27B6083816E68BEFA8ADCC8AEB4E45
+:10B7F000B2473FA57D40710D4FE0FE77B888D7ED89
+:10B8000026E3790A30AFDD7E2E8C8B7530079D13D1
+:10B8100060735C88621CA2FB1D897BF25DBADF91BC
+:10B8200060519E9F1AE879DCEF4C640AF89A857E95
+:10B83000F3E27987C574AE03E9B7875317D239E4C9
+:10B840002EFB32DA9FDE923685F62FDD8878AC53F8
+:10B850009FA23B97019EBB82C6F318B2E718DBDEBE
+:10B8600090B16D6527A93E4A89063D97B262E74EC1
+:10B870009A85BEB83599C3756B328FD756E71BBF13
+:10B88000130DCADF7FC9E4E736F4B8AD56ACB7C0D4
+:10B89000F83F9FC7FF7F044A435CC87F1FA66C7CAC
+:10B8A00060C8A3A3F0774F54FF2AA0536BAA6FA5DB
+:10B8B00086FEDBEDE277C2B40EAA63D8766706D5C2
+:10B8C00089B6DA1C9598F70CE7F37C4FA3A8F70725
+:10B8D0008AD4EE82F7B6CDCCA57ECEAA5ECA97F604
+:10B8E000AE66E41FF5E3D32F80FF01DF4F621BCF6D
+:10B8F0009398EFEFC2EF88BD0195EA74E5F31DF868
+:10B900001CE054045FE0FDF115B1DF712A3E507672
+:10B9100008CFC36421C5CFD38F3EE2F759C22F6F42
+:10B920003C5079F36880ABB86B24B1F1E00362BF9F
+:10B93000C59924F68DF9F9BDF1FD07637F68A71C51
+:10B94000F3FD6B1D3E32419C8DEF4D48A1751F17D5
+:10B95000F92626F4C39838F9BB2E260FF4BC4CB454
+:10B960001B457D1D9E6111A8E0E90CEAE7E4F2E1C8
+:10B9700067F28FCBEDB52CF687E354C5C6253D3570
+:10B9800031F6382687B0C472ABBFB90EFA1D99C123
+:10B99000F7D7C768D18328EFD7896B99B8B2B9EDCB
+:10B9A00084DF352B032AA3128890BA1EDA63AD5DBB
+:10B9B00059C8DFE3ACDD2B5D30CE3573EEF660BBEE
+:10B9C000A4A098F80DFC2F3A7728C36E8AF0EF28D0
+:10B9D000CBFC2847B3E7F07CECAC3956AA3B9EA5DC
+:10B9E000F1F3A198162ABC0D9EDF56CDF3C0D8AE58
+:10B9F000D6E559E4BEC7718853762788374B0AB815
+:10BA00005D94EF378AFA1FF9BC080F8AC63C59C10A
+:10BA1000E48FF2C99EF0FDDD3352CF0C6543E37E27
+:10BA20006FE67C3EEE5F56BE31909E303E177A62E6
+:10BA300056E01133F9E9425F48BD1C14754D5DE2D3
+:10BA40005C97772770BCBF5DB998F4C5ADAC89F43D
+:10BA5000F96D2C6C467CF7E9FF293ABF06E699158B
+:10BA600034FA39B3E7C4FB3D9C5FE5BCB7878CCFA4
+:10BA7000674AFF758AD17FADFECE17196417B39F51
+:10BA8000AEBF342856BFD41857BFD420EA971AF750
+:10BA90002D39E2D2D52F351EE0F54B0DFB2E57BFC9
+:10BAA000D44BFB48C7CD9183B8BF727C318804C0AA
+:10BAB0007948D4BB1CC67A97F2185FA6CEE47956B3
+:10BAC000605FDA2FC973A4F8D15F6F3395535EB608
+:10BAD0002D2DD5AFCF83AE59199AA4CFC7CA7AA559
+:10BAE000E303C4B7C30BB8FFBA51E179F1F0ED56E7
+:10BAF0008AE75CC541C33E844B652730BFF811FA25
+:10BB000059A3A93FE53D701F6F245C230AAFB3EF33
+:10BB10007B1FBF3BC27C649C3E7265F9691FC09568
+:10BB20007E35E5F3E71C28DB41FAC66EF3E3EF222E
+:10BB3000CAF1E784B6695847D478609B36DF1EE3C4
+:10BB4000BBCA02C1AF292C05F9B52FBFB72789F2AF
+:10BB50007B1FD983930AE0FD3A4B743833F233DD0F
+:10BB60001FC8AE2D12FC629E10BC7D01C073FE4D3D
+:10BB70000BCF73DDC7485E9FDF9F41F9496D2623D8
+:10BB8000FBD252C9F8EFC06CE3DF0B9CCEE0E718A4
+:10BB9000B5CC6064077B322713FD16B3C8513CA7B0
+:10BBA000A866ABD9701ED13D3B8CED3AD641F6A6C6
+:10BBB0006E573F7E26BD25F5633DF3A966DC07E899
+:10BBC00034BECF061BF56399B00723674D6CC67A68
+:10BBD0008D91A6A04AF6F73E7FEE4C8A9FABB91D29
+:10BBE000654FD3F957E7533F51B99C737D3C3AA653
+:10BBF000350D7669B4F0AF6ED0F8EF2A487F69B49E
+:10BC0000F89D85C3A6032AFD768F806794784FFA46
+:10BC100069525FF7D1732CE852E0FB07255D8B5822
+:10BC200011D215C627795030C0C9A4F1E9F71AAE70
+:10BC300013F301DDF9F977266B04F9A85569223D64
+:10BC40006D65425F2BA1667CF917E130E9ED6B5819
+:10BC5000D32DF87B9FE3AC5D29E497DA436B0B5C53
+:10BC6000313E6966D182DD8A815FE8F9D98C37126D
+:10BC7000F28BB42BD177B9BF318D811F08F3067ECB
+:10BC8000CFFDA0C30A8FF3C01F3C8C71DE1BA6A999
+:10BC9000C40F536119D86F92C348E71B3DC6F654D1
+:10BCA0005F3F3E50F5BF5F0112A7213CD3861AFBD0
+:10BCB00005A47E6346FD56C8BEE075E5AB8F7E0BDE
+:10BCC000E3FF94E56C28FA31E039FA13FD1EE973BD
+:10BCD0000503EE933C5790609FE4BCC8F75ECBBA77
+:10BCE00017EE52FAF34DCF91E5AA47C75F929F5FD7
+:10BCF000147515CA2FC57EEC289EF78BD979CE37DF
+:10BD000015A2752DF25D267E7F22F845FCBEC8F592
+:10BD1000FB6C51FCFD9C3231CEB5C83FE531BB1EFA
+:10BD200035D97D9622E4137F9BAAF6F7E7DD993E8D
+:10BD3000E297912669E7FD598CEC7C47B386F0EFDA
+:10BD40001F931BB21BF8E31DAE4F803F282FD5CFAA
+:10BD50003E1A9FC7F18FA4E331E147DFC87C144747
+:10BD60004C117E74B490F34F95FD560DDF7FAD8876
+:10BD7000E70926E206227DEF69B48B5556231FC4DE
+:10BD8000F317CC68D2CF1BCF6F03F1CD20E41B6932
+:10BD900017B32ECF379F0B3F2301DF7C5E307A60D5
+:10BDA000BE89E717A95776DB1C5578A670638D42CC
+:10BDB000FA78E49B839BB17D457D21D5BDECCEF027
+:10BDC0001FA2E74DFCF9A8AE808A7531C5CBC4F33C
+:10BDD000C26015B61B97F37D89D1C779DDCCE0FB36
+:10BDE000F8F3B2554D87F0BBB8C6307FFFC54F5B47
+:10BDF000E97BA148AB78BFB2BD0ADB8D6DFCFDD3FA
+:10BE0000B8BF3402EBDD22CD787FD8BA423F0F4B6A
+:10BE1000B95F3B5EF0E96E65CF217AAF9DBFB7E8B1
+:10BE2000A835997E6750F8AD3788758EDFCAD7E997
+:10BE3000FCE026FADDD105BD61F29F3E36D5559076
+:10BE4000DE1920FEAC54DAF3F07A23EA1315E90781
+:10BE50007C5DC4F71FB7C314658378FE42EEDB61D7
+:10BE60001D81BE6EA06C10B7FBB29F3B937FD7C500
+:10BE70001E4BA5BCAFDC578C6E620ACA19AE51F8D6
+:10BE80000109F7196F2C6EA2FDC51B07C9FDC56E10
+:10BE90000DCF752FBBF4E7C989F22B63C5BC9F8812
+:10BEA000BA0879BF265248BF23B61B9984BEC77E05
+:10BEB000F237D416E79433F11DD8EE42DE9E3CE80B
+:10BEC000891FB6E5017E4D4D1A9EEBC60A14FA0E87
+:10BED000EE5FBA58343DAD3FFC376A2C6AE1DFB102
+:10BEE00011FC0B9B2DDBF9F7885C2FCD926A67DC88
+:10BEF0001092D35B059D6E1924F29223D948D43752
+:10BF0000B304DD6EB382DF4A7AADDD1C27FFB307D1
+:10BF1000A1FDD832A0FF6C7C1EA71F6AC4BC0B8594
+:10BF2000DFBC187FAF54C5F3E6B9FFFCC916EE3786
+:10BF3000DFC33A288F78FE31EE2FD6C3F2905FFA36
+:10BF4000FDAED74E63BBBE23FE7764F9EF10F6FB60
+:10BF50009DD6529E9F3DBFA5BE02F373359BDFA4C5
+:10BF60003C708DD41711A3BE000783EB8B4D575245
+:10BF70005EC764E5BFA33912F405D6978CC4BA51E5
+:10BF8000187FB838876735BEC2CFDFF9EE20B237E9
+:10BF900053A8AE94C653693FF7CD802F461F69372B
+:10BFA000E2F54599CCD70CCEA47C96D41F658CDBEA
+:10BFB0008B78FFE811494F11F7483FA30CFD0CE0C7
+:10BFC0008F2E933D6232E9FD8A08C921C48DD36C5E
+:10BFD00045C83ADC9F1A79FB28ABA03F8BA3EF261C
+:10BFE000A2EFC0F193F1791CFD65FC5221E87F3B83
+:10BFF0000B505CB457D0FFED77F9EFBDCDB22F23D6
+:10C00000FE7BF7F7DCDF94F1D3D78F9B02EA3F1278
+:10C0100037F5D1DB067E640AFE1EC6D4218FE27E90
+:10C0200078A78DFFAEB5C2E9EBBEFD78813EAFF8D3
+:10C0300036FE7E8BEE77259AA72659711FB0D9CC94
+:10C04000E38A99D3DEAB98ABD31B8559952F0D1A94
+:10C050008DF4E8FAF61F30CE785D9CE37AC045F4A3
+:10C06000BED0C5EF5FD87A953F0CB7CF98C579465B
+:10C070004AD3422C8192702C14BFF7F259CA2BB4C8
+:10C080007F3C2323740CE970CF1B7B295F59C7BA0F
+:10C09000F8EF028B7107CE4B86497F595EE5F6B00B
+:10C0A0005749F6F3EF86C325FAFDA4633EAE67C792
+:10C0B000E5078FE33CD2DEC5D7159C5C72237DD7A4
+:10C0C000F9171648C7FD4C45E3BFDF1C3F2FD611BB
+:10C0D000B4E8F2D9276D89BF333D3588E7038A106C
+:10C0E000475807911BF800F1F78988033F11FB5A65
+:10C0F0009FA4F17DAE9EBEFEFCAAF9847E16FB6075
+:10C100009F641AE347D9CF22AE1FAEB0065B74F42A
+:10C11000F46D4A6A8A501D95A81B59C678BCB43F75
+:10C12000C3700E4186AFB2C887FB14C5010BFEBEBB
+:10C1300077EF7E6E8771FF19F7872339A12F10EEF5
+:10C14000061F0BE0FE2AF3755B6EC17D46F17DEBA9
+:10C1500079C12FE76DFC2AE1FA6FC3AFB72E0080DB
+:10C16000000000001F8B080000000000000BD57DC0
+:10C17000097854D5D9F0B9732733133213261B84A9
+:10C180002D4E16B2906DB261D8270920B860C25208
+:10C1900051B661DFB209D88FB6F6CF601090475B19
+:10C1A000A8B6C5CFE51910A8562C1183460D1A94D0
+:10C1B00022585B4704454B75A4CA222189602DF69D
+:10C1C000A3E57FDFF79C93997B3361FBD5E7FFC83D
+:10C1D000F37072EE3DF72CEF79F7F3BE27518E8A9C
+:10C1E00024471C63ED77FB4D4C652C4AD62BA09E53
+:10C1F0008CF5F2244711D4A7C8F7A2FE10AFC33FB5
+:10C2000003EBC5D81CFCCD01A5C5DAA2E6C0EFEB57
+:10C21000C25AFDE9F49E5D4A624C51998745432517
+:10C220009D39CA6DF874B8FD442614E1F01EFAA9D0
+:10C230003159D729B9D4BCDC02FDCD10FDB1FE3691
+:10C2400023F63F9D77C566341FFC5689646CA6852E
+:10C25000ADE907EF6735F736C10CD8A2484FAA3DC4
+:10C260000B5B8CB69F8071154F847A2902FAC67FCA
+:10C27000A3BA968C19D909393F5A8787315CF700E0
+:10C280001FAD6B7D4947C27F1732D6B1C76CDF0245
+:10C29000E35435BF7554817555C9F5356AD797EBA9
+:10C2A00050E87BC62CDECF2D8CDDCE14D613FA6978
+:10C2B000B2BA73115E55163FCD137A349567C368D1
+:10C2C0006B8747D1FA7BC3F7309F17EB5CECEF61CC
+:10C2D00001782EB3F3F58F512BCB4CB18C9D9BC7BE
+:10C2E000EC6678B4ECE0DC7A0BD4973DC0EC7C745F
+:10C2F00097810D86FE05BCBA9B5F5CB981392CA283
+:10C300008EC34EEDC11CE9817A1F77B4A60EFD32B3
+:10C310009CC752D16FBF457D35DF0FA84DD2B4BF4A
+:10C3200061E520CDFB444FBEA69EBC6EA8A6FDC015
+:10C330000DA59A7ADAA69B35EDF358524F06F0AF69
+:10C3400039A0322F8036C33B51F33EF3E9BB34DFD3
+:10C350009F64B5BF190EED1AC3237318E0517D78A1
+:10C36000E4162C99C7E5CB02F8CC13EBC86E98A362
+:10C37000E9E74CE4D803B8AFF37C0B6E658057B99E
+:10C380004D4B34FD2E552BF9BE6D083BEE87EF6A01
+:10C39000E107E199CF3AF6F783F9557B15670BBCB6
+:10C3A0005EB889BF97DF2D6EDA4CDF2DF66A9F2FBE
+:10C3B0007D5A5BF794B2F45A2B63CB1DB658C287F3
+:10C3C000BEACEFA520BA0AE0013482F1CE3DAE7AD0
+:10C3D000CD89089FD4DF0E27F88431AFA3EB7E9D73
+:10C3E00063CCD982ED77D89C1EA82F3C3897E663A2
+:10C3F0008ED7E241B8438B0711E95A3CB039B5FBFF
+:10C40000DEB358BBEF7AF846B9065D16BE31E3B429
+:10C410007821E15A0C3FDF255C9FD0C1B3609FAB10
+:10C42000DE4A7062932D83117E7CBE6656AE229FDB
+:10C4300063B1C067E0B99377C1CEDAAD1E03E0CF38
+:10C44000730EC578C212E827CFD8B217D7B346F11A
+:10C4500030FC2E9C79E3915FD417B724B4C0BEE4BE
+:10C460005B6A71E7D817D6F2E791EE2B4D2D39F8BC
+:10C470005EF6F785D54DCF5B95771630582F33B6DE
+:10C48000E4103FB4301A5FC271700F8EC74B593938
+:10C49000F1E117053E7FFED12282E30256BBDF05A4
+:10C4A000E39DF998C37731F350BBF91BB470E802F0
+:10C4B0003F1DDC006D1C386E8D58F712C6BC86E43B
+:10C4C000AEF0549A95165B0E82A159F26DF7A50253
+:10C4D0008E7608CFA1ACF31FF16F095F68A004F35B
+:10C4E000271CCFDE2B309E84A7E45B721C33AB5538
+:10C4F000E3910E747C8CA56BF709368E617DB0A834
+:10C50000BD023CD4122D06EB85FDE0E419BB518C35
+:10C51000C3E6B8E3114E16B681F66FBDE25CA7C262
+:10C5200038EA0D89F50CE0596077A9B85F45CC373A
+:10C530000D9F175B1AEA8DD0D50DECA2FD04C81330
+:10C54000D67B7BD5A598C03A14B92E8FC28C501FCC
+:10C5500021EA933C8AFFB1445CCF5BDFE2B823441D
+:10C5600039094BD83F58E6DFFF0A1F0F571C0370ED
+:10C57000BC89AFA4C521DEAC516A996E7E475F8548
+:10C580007E5443470CB61BC3DC462E77BD3849F6B4
+:10C5900096E2A779FF88B9EEC752CAB76AD6307655
+:10C5A0001AD4AB1B416E456219DEA242C99A74F0DF
+:10C5B00064C6E35837C04A10BF97625DEE7B62E005
+:10C5C0003DD5D5AEF555B0863ED15796EF1B13ED50
+:10C5D000345F907FA9FC3DE76F8B04BC1649B9E539
+:10C5E000D5CEEF18FED287B13F9A0026F9484716FC
+:10C5F0008FA127A805894097D82E87E560FF40576F
+:10C600008E44E8BF5734D0A1124C77BCBD7CDF8587
+:10C61000EE74EB67B5B0B94300DEB642931B58EE3B
+:10C62000DCE0F55E053CA41E310FDB42F92F878369
+:10C63000D65DD5E3D8072E7C5DE84B40F92FF7A9EE
+:10C64000C6C4DC0DA8B734C4D1B8F2F9E84483D02D
+:10C6500027001FAF024EDDEF430AE943721FAE56BB
+:10C660001FCA451C2F0AC0EFE6AEF09E90181704B3
+:10C670004F06F0CCD6C05BFB5EC05BC2E36C916F33
+:10C680003BEE936A3BDC0BE1BC32BE7C12EECF800A
+:10C69000A3FE138A2130AF316AEBF6C7508E35A95D
+:10C6A0004EA4E5EA119CCF55BFAC12E9B7359BBD4E
+:10C6B0000AF4B3A8E94DD2CF5AEB809186750FA743
+:10C6C000CEF5EAE0DD151E7C1FE57A96EAD63FF34B
+:10C6D000BDF3B6190E5A67CD15E050130A0E677EEA
+:10C6E000CC669567E1FAB27AFAB302E366E1BE037B
+:10C6F0001C7E1E597E0FC2A3F0FDFE91089F316A79
+:10C70000F3FEBE0887158AD30CE38E32334F38EC24
+:10C71000739F9565ECEFB057C5FE5AA71DE011DF7A
+:10C72000DFEA54011E69F7A8E55EE8F76F2B96472C
+:10C73000CF85F2CB3A187A203C570CE5846F6CD742
+:10C74000273F85FED26CD39DEBA136C30CF38171DC
+:10C75000127F1CD1920C7CE27513B320BD8525D5C8
+:10C760001E1A0FFD7644A94ED4836355361AF14B39
+:10C77000C2393682AF433E2F7962ABE2B7069E8F55
+:10C78000AAEF285806654522DF77B9CE51651D0509
+:10C79000A8F74838C726F3F6CCD8913031883E72D6
+:10C7A000053C8EA15E07F0AC8E33AD4139D866E111
+:10C7B00075E64A27FD778585D3C7B1F0042FCAC730
+:10C7C00063B0561FF5D76263D620BE18EEEA792310
+:10C7D000AC9BBDA7B26D507C6D77F58C2278D87973
+:10C7E0003F42DF6A636C1CC269C5F8D2DED150C615
+:10C7F000D573F8E8F1A43191EBFD951780F00A02AA
+:10C80000CF2B8D2D26BB159F9B34CF8F03DC3CE6B1
+:10C81000407DCEA994B18CF88C730DB69FBB2E824F
+:10C820007982F4AB46318FEEE0521D656446804755
+:10C83000B5C2CA2FD7EED5FFA8045FFDFCFF2AF8CA
+:10C840004C5C59E8F51D12EB2B5B7BEB6F51FFAC99
+:10C85000F68531333C5AF172496F16A2BF4E385FEC
+:10C8600018C6BC314175A39FE0517D61243D2F5B0B
+:10C87000DB6A42BCC77E1CF07C45B8ABB7F33270B4
+:10C88000CEC579E07A2F44314F4CF0738E5781FE3C
+:10C8900063E9FDEF118080B79E26D5BB0D3EFDFDFF
+:10C8A00001C3B82DA1E62BD63F28CE48F492D9C2B9
+:10C8B0005C9B438C2FDBF58A067E6DE570AEC8EE7F
+:10C8C0003ABFC652FF4C9CFF8DA3992BD478E74406
+:10C8D0003B39EFC668FF0281F7A915B6A0BA5DBB68
+:10C8E0008F3DC5F88D37FB13B0FFB6F16C6A4388F6
+:10C8F000FEE57ECF88776722DFA9BC031A037E0C92
+:10C9000036D62AF6207AEB6EBF037006BBABE07218
+:10C910007036D17BD9DFE943821E99CBAA001DCDA9
+:10C9200016F26AF6D6A5B702CFECB45F4E6F02FBE3
+:10C93000058638CD6ADFB4617D8342F6C91C37C8ED
+:10C9400000E0370BB615AC41B1353B9EB191D1FC3F
+:10C95000F9BD58AE0E0BC859FADFC582E5A21C7F9F
+:10C96000DE835ABD75117BF02BD47B4E1FE27C0118
+:10C97000D453B2BF173CA2ED6FD1D65B4EE23C1749
+:10C98000E9F49F3454F040FF484B12F6C460361867
+:10C99000F9FFB26DE74D918EEEF1FF4BA0F394815C
+:10C9A000C827ED540E4D72E524A17FE13D3ECFF145
+:10C9B00049EEFC24F4A3BCC7E775AEF21C970F8FB9
+:10C9C000C7925C322313875FCDD32CDE7A98C75A87
+:10C9D0006023E1001FB399EB4152FF53D5E56A2470
+:10C9E000BC1FF2C58A6837F2E1676F1A87FDC53D43
+:10C9F0001BE1C2F5AC2F71E5A1BF607D85D5590F54
+:10CA00005D5AE07B941BDEDF0F79A32F6A070D1BB5
+:10CA10004BFB21BA35EF6D417FCA3AC357FBFB414F
+:10CA2000FB752399B39E05C6A969AE781EE79330BE
+:10CA300099CB97F589AE3C7B50BF4CE873D5027615
+:10CA4000ED7BD27E390CF6F7B103A44EC3FAC09E3B
+:10CA500087F90D627C9FD9458013E0098E1DACB724
+:10CA6000B6829C626981FAA006A5250CD653D5F83A
+:10CA7000BC01E560E57D2DBDA6A13C7AC6E8DC12CF
+:10CA800034BFD8D7FB943A220372689A62273D419B
+:10CA9000EAE57732F92F8BF066AAC09B3B853E3ED4
+:10CAA0002D82C3770E7326E077775958A401486921
+:10CAB0005A594311C9A9A5615128FF712DA1F65BEF
+:10CAC00096DDF995AAB7DB3C0AEC7B9BD2918A9D57
+:10CAD0007C89BE1EEE5FF26E49ECDA4F5D92A0C318
+:10CAE00054A11FA630970DD65DFD5ADAE6F5F0CABF
+:10CAF000DC03F6319FF891A5389FF4630BDA3D8B88
+:10CB00005F0D6F512203706176579E01BEAB99D8BD
+:10CB10003F7F3DEAA44781AF0081B585F913888E38
+:10CB200081DF2820F336258DAD3002DE55F705FD77
+:10CB30000BEAFBB74CAA3002DE5727F91718A0DE24
+:10CB40009654C5EB83FC27B07E216925AFE7FB1720
+:10CB5000A8508F495EC3EB6808026239921FAAF0A1
+:10CB600040FF5F4609B9EEF4CF44FCA97E25CDB065
+:10CB70003E68BDD664CEAFBE0CE7EDBE4C64B326B6
+:10CB800022BCD3FDA9384FD9AE2349EAC31BA8BDA7
+:10CB90005CA7FC8EC587EEFF7749BCFFC565421FC9
+:10CBA0008960EB106EB04D9E4880FFBEE6B42DD874
+:10CBB000FEC1A468DEBF1DFA290CF423E128FB9313
+:10CBC000E32E41798B7C380CF870101F6D4CE2F22B
+:10CBD00012C6594DE3A400FCB1BF89FDF370DF60BC
+:10CBE000BF8C62BF8CDC4EDD4CEDB1DFA81CE2FBDC
+:10CBF000054658C7BE8BD03E31306F3D7EEC15F8F0
+:10CC0000B1B81E1821E967C98447A322B85EC80AD3
+:10CC1000B5EB8849E6F0B32647F17576EE476F85A8
+:10CC2000C6A91770EC0F70CFBEF675BF2FE6F35D87
+:10CC3000AF3B68BF5C2ABE6FCAD812BC1EB02C3591
+:10CC4000FD7CB94AF75D311020AE333A99BE5B1BCB
+:10CC5000CE2CF49C6DE9FC2E3187EBA3A8A75609D6
+:10CC60007D9A79469253A152708DAA753E9303DF47
+:10CC700037282EAF35787DB7168AF5D9C5FAEC7C02
+:10CC80007D5E0D9EB2C31D09936D5DF1B713EE9DE0
+:10CC9000FD65E58BFE34741DAA3FA48FEEF6232CB0
+:10CCA000F93BDE0F394F1D3C3BE1AC9B9F8427D203
+:10CCB000337D97A5C54739CF0B823EBBD075E27552
+:10CCC0008E57C2BFABFA09EC23EA270E2D3E57352B
+:10CCD000261AE66405BE6BC2BD2C0AF8E7D293851E
+:10CCE0009DD79FF547FEED29E57E54CF2EB3B3DEE9
+:10CCF000417EBDACE4B8907E3D7AAEB7F3DAA34C8A
+:10CD00004C21BD48EB67688F73FA5CA89F9E65CE87
+:10CD10006DD0EF309DDED10EFBB9CB1AF82E204F2F
+:10CD2000B4F59F083AE8EA37EA48C0F9159A4B5F2C
+:10CD30007038191B9BFC14F1F7C29EA5CB13A17E82
+:10CD40004BF236E2D785FD4ACFA36BE6B6E4EDBCE5
+:10CD50009E597A3E09EB4F6DE7ED47B95E40FECE36
+:10CD60003CDB2B460F09E80F13921D5CFF28333084
+:10CD7000C423B37AB713E5A484677765A1D9501BA0
+:10CD80004A6FBDA3939EF97946B190CFC5D28EF775
+:10CD90001B35767C7BA4C5A3025CDB519EC27AE77F
+:10CDA00024BBA723FC6B225A67A20A7C5FC42726F8
+:10CDB000D4871417E81BE81771D8D97498A7D2BA8A
+:10CDC000BE9CF4C0254E8B91E029FC54B0F64BD0AC
+:10CDD000CFABAF3DF3B37E7C98729CC71041FF355B
+:10CDE000AF7DFBCD5F518E7E6975A21B7048F3A3AA
+:10CDF000CB51BF1AD2FCA76FB9BCB5D239959CF7FD
+:10CE000010F437C2F3E22633CD7F4873C67C6C3F03
+:10CE1000ECFDE664C48F11C75AEA911DB4EF79A9FD
+:10CE20009F3BF8DC8A9D542E655EBB7ED1098F2F17
+:10CE30004C0CF54B80C7FFE1F0B8B800FD8A6D716E
+:10CE400087D6F8494FEBCFFD98E27BD0CBD391CE7C
+:10CE5000CFB11E4E3C5768B7F17EF4FECDA315B09E
+:10CE60003E783EA2036610A4378FBA60010612A86E
+:10CE700097B0284DBDCCD247D37E8C3D51F3FEA652
+:10CE8000F80CCDFBF18E3C4DFD96F4219AF6B739A6
+:10CE90004B34F5DB8BC76BDA57B82A34F5BC9606F2
+:10CEA0004DFB82034DDAF7871DB40F05C7CACB507F
+:10CEB0009F77FADCF558DED8BAA1ACA78375F1EB01
+:10CEC00016FABDF5F87CD8C5DAA216D6D5BFCB9632
+:10CED000B8E93CC08CFBA2069D0F94F8881EDB0CC1
+:10CEE0004E47B01FF7D15EEE17709FDE5200EC0088
+:10CEF000EC91968E18DCAF31B31E5223715F3A1855
+:10CF0000F9BD1A4DFE5F0C43393F4325BDB7D1C86B
+:10CF1000487F6C9C9AED45DFDF51C5FFE25F914F82
+:10CF2000CD88207E3202345C5A379E812AB84F6EFB
+:10CF3000CDBA4BD862DD3EDDADA98FB1FF44D3FE43
+:10CF4000A6F8559AF7E31D0FE8F669A3A67E9BF3B2
+:10CF500051DD3E6DD6EDD3339AF7233EF7D7231933
+:10CF60008D6AF5A83698FFD0A31BCA705F861DF3A3
+:10CF7000CC407A296C71D7130BD957FB26962D60BC
+:10CF800057A13FEB8DBA782AF7D539C81FB5BF2E08
+:10CF90009DCA03754E7AFE765D3195EFD4B9A8FC33
+:10CFA0004BDD382A7D75E55436D43550FB5D754D23
+:10CFB00054020407A0BC888D11F207EA68E7B7198C
+:10CFC000FCD578E27AFAA96F884FB6F5F0B761FD23
+:10CFD0003EF68F8AD1503F9CC288BF59A14FA4C74B
+:10CFE0007329AECA14A85F48E6CFDBC3ACEB500E82
+:10CFF00034185C79A85FFFFBA9FF6C340E60ECFE6F
+:10D0000055E5F1F6285EB7409D361B0D33CF7F36D0
+:10D01000BA8633F61C8A8CA154AFC07A7B387F7FE6
+:10D02000E1A9FF907E2DCF9B2707CE9BFF9D1CE2A1
+:10D03000BCF9B9530E1BFA590E5D4CB3E1BA0E0997
+:10D04000BF928BE585CD86B2C498178672F1A84E43
+:10D050008F90E5A7D612534A1CCEDF3905F508CFCD
+:10D06000CD616C1BF08B890AB7473BF5C0142ECFFE
+:10D07000DB6F3393BD73D8E09A8F780E7CFA4984C6
+:10D0800057424ACF892857DA6D1D090887FE299132
+:10D09000BC1ED7F1A4E20CAA87F175C6A5D82676E6
+:10D0A000B3CEBE381FFD3A6F4811E70C2DAE0128F4
+:10D0B0007F65FD7085AB0AE5C4E112D7409CCFA126
+:10D0C0007233D18FA7DCE61D884CCEE82A9A12E491
+:10D0D0006F7934258CBE9B6CE274C6EE52BDDB4288
+:10D0E000D8692FA5707D9FF60DEDB93B23480F3F02
+:10D0F0006C608B768580E3BB295CCE9DE911DAFFFD
+:10D10000E213F02B9D64A3FEDA5784D3796F7B7909
+:10D110001AE941EDB50025A08FF653B56777D37BAB
+:10D12000B33C0AA373CD69824F3DD7BCFC1F47A017
+:10D13000FD272B229CC4C3ED83483EDD251ACF88F2
+:10D14000B190DE3263E28052944BD3C4F9D84C9B49
+:10D15000B1171D9319A34C76E8679E356F0D8AFFB2
+:10D1600005B115A628A82FEA7FF71A2C97A46C34CE
+:10D1700045435999F5FC1A541FAB80B48AC85EF236
+:10D18000FFB90EE6356BA5EAE0F693906BAEA5D736
+:10D19000148F21F110E188780AF025BBF03D016F72
+:10D1A000F9DD7B029EB352C4396D36CBBEA43DF788
+:10D1B000998B78D23AE3CFA9DDF8E7B5EF85DEF6B3
+:10D1C00081898FBBF4E9306FB03F498E7B48CCE357
+:10D1D000B089B914D4E3EEB2117EE44C3D7F5F1107
+:10D1E000AC3FA7D96EA0737BC9C77D8CFCF6459F69
+:10D1F000BB89CFDDD8EADF7E84119E37219D5C4953
+:10D200004E4DF2AC22F930E46B903FC8172FBA3F75
+:10D2100039427C7091E083B5C4BFF6D5ADA4FAFE67
+:10D220003A0F9507EAD6093EB881DEBF53B749F0F9
+:10D2300041AFE0834FD3F3E6BAA954BE56E7167C5C
+:10D24000909FAB4E14F8B432DEBD0EF9993CBF9CF2
+:10D250006C718721BCFEF8A899A9782ED16C263C68
+:10D26000050A78F2B1588C9731DBD73BBAC6CDE8C6
+:10D27000F96DE7FEEBCE7937C4BB1EC1F13AE3642A
+:10D28000503FBBA17BFC39C41C36E4273BB64E247F
+:10D29000FE71C8E1B0A1DEFA5CCAA489C8AF0FB9BB
+:10D2A0001CB630A8FF61EB24FEDEEDB099A1BE33C1
+:10D2B00065327FEF71D8C2A1DEB055D4BD8C0EB5FA
+:10D2C000776FBD93F84F0953F6213D9459124703E8
+:10D2D000BB06F958B20FE9E0A6F8D9A3910E525255
+:10D2E0001C840FE31DABF661FD96F4CDC618077ADA
+:10D2F00043F356E377A5B11546FC6E74FFBB57E3C5
+:10D30000776353361A83BF1B97F5FC6AACDFEADC00
+:10D310006C447D3005F9565CA01F5997EF257F4579
+:10D320003B01F134B7B99CF8784E5339F171099744
+:10D33000D2C915F7A39FAEA649B12B388FC94AE7CA
+:10D3400061BD023A44F545A016E0B3FBB6CE8B5E54
+:10D3500005DFD5607D28D57FB52A34DF3D981242A0
+:10D36000BE7C28E814E566057CF721D0CF2EA8679F
+:10D37000E0FAC87F38DB369BFA73DB50BEE6A67056
+:10D38000395920E4E65C512E12CF3FB5BADE47BAD8
+:10D39000FC3845D8635DE9FA1341B70BF83CBAD0C5
+:10D3A000B5F6BDA06BBF940F851D0958AF621BC8B1
+:10D3B0004F78A5F8AEC5C1F65B22C6493450FC854E
+:10D3C0003E4EA292F9787F0DBA380BE637D1796CD0
+:10D3D00053D073E247C2FEE8C1F9DE5464D6809FA1
+:10D3E000DF76CFCFFE8DF0BFCCBAB5EFC5BA17331D
+:10D3F0002FC5B5E9D7C1DC71445B4BAD87693FBB35
+:10D40000AEC71F7A3D5DD6C1ED7719C722FDF2A0E8
+:10D4100007D90616211FB431F4DF04F3892397E1FD
+:10D42000137A7EF45DF1B9CBF09BA48121F88D8C49
+:10D43000CFD297529F83BA07E3F33CAF85939FFE09
+:10D44000A4C39D8DFDB497767C6340FB2CD64F78AA
+:10D45000E6E9E776E273C5C4CFE9E1492AEEDB29C4
+:10D4600083E70FA8170DDFF624F19D36140E408FC9
+:10D47000855047BEE3ED5B3E18BF63E91C7FDA15BC
+:10D480002E1725DD833E48E588815C1E752D395DAC
+:10D49000C9B8C6F6CDDF26901FEB0AF8DE1D1CC604
+:10D4A000A8C3FD1EE4F7C511A4F2B42AAC4501FDE2
+:10D4B000AFB5A417E911AD034C462CBF6B3BB1755A
+:10D4C000402AF5AFB7175BFB145BF8B863C761D9A7
+:10D4D00064726F9A8D76D21033D949EF8A78C00979
+:10D4E000113C7EEA5D3C1F8676138E5F8C45F9A564
+:10D4F000B7375B0F4E2F75E474B53B619DA3719DEB
+:10D50000959F19EEC767D76A8756AEFC86196340A8
+:10D510006EAFBCC88C055763973215D945FE51E7ED
+:10D520009B58167DEE8BCE71A0FD29F507619F5E9D
+:10D53000210EA9B883EB0BA32EB2746321FA997A5A
+:10D54000D0F98D52FC276EB78A529E8B0CE7536040
+:10D55000330D56AF29491387146F8472BAEA1F8CB2
+:10D56000F536E6A37312BD3DFB96F043815DFB0BE0
+:10D57000C4DB35223E09762406F177CC4F3F9AF979
+:10D5800033E203E1A40F75DAB5BB0D145FD0687404
+:10D59000F51C8176EDCA81CE5550FFD417F7EB57B5
+:10D5A000A1ACB17F437093F45BB9F23CC153D65B3D
+:10D5B00085DF774318C81F282BFFA3921CAA646C31
+:10D5C0001DED1B7BC3B42C482EB286AF3AE19F0BF6
+:10D5D0007CAF02014876D6C8492E685721EC0FE689
+:10D5E000799DD785DD0516C52417F45B1127DAB3BD
+:10D5F00087F9FB01F2FD23FCFD40D9DFF989F4BE78
+:10D600008FAC8BFE3264FD4FBC9E28C76BE5F56C7A
+:10D61000590FE7FDD978FB9706364CF26405F8FD03
+:10D620009E81423EE6B13C1197B377E0E5E351B409
+:10D63000EF857C98F58CEA31E5E2FE8C8FF833D2E9
+:10D64000778342B17395F78691BFFB4C7443CEF25A
+:10D65000207B45C6AF9497D95CA8FF55BD98B645C9
+:10D6600015F13CA87FFCCBC1ED9831AA95CE27CE11
+:10D670003DC8F97E77FADB8295AF6AF6B3CB7B556E
+:10D68000E1F6381EDCC178671FEABD99EC8B141FE8
+:10D690009D9B7F2AF85D2FE0ADC5D18178B1D8641C
+:10D6A000E6427B35F625E0CFB8C79FFB881F2F7871
+:10D6B00089FB7FAB1E7D93E4DE1CD541FEDCB159B6
+:10D6C000EE2F106FDB6C3EF22B2E58F91ACDEB9B30
+:10D6D0000CA137D83BB282E179B62BFCBFBA02FC71
+:10D6E000BFFA21E1AFF73B2FB1EEA3F52EB9C6B8D3
+:10D6F000B6361B3F17758A7D3A6E700C16F08A4855
+:10D7000045FFF97C5F6A948A41C7BE5E3C5EE99D35
+:10D7100022B48BCED5DA18EEFBF4E57FCB7187F01F
+:10D72000FBEAED811938665C005E7D52851E14802F
+:10D73000EF001CEF32F0D5BEFF9EE1DBDBE83739AE
+:10D74000F11CF528A37E06FB8E9B82E36246A47241
+:10D75000BCECD9C4CF8DF4F15E23526DDCEF2DCE3D
+:10D7600067AA26BE331CCF67243D8C8A600DE86F04
+:10D7700007BC760ABC76225E4BFC0D9CD3C0772199
+:10D78000E82B80BF5AB88E4EED82B7E3AE00D7715A
+:10D790003F245C1B411FA673CDDDE1E44FD1C3796B
+:10D7A000A980AB84F7BD5780F3BDDF139CEF4D75A7
+:10D7B00068FC1112DEDDC927FDFEC87987A0D3A25F
+:10D7C000EBA1D34B69DC4E64463FC599EAF7BDBE79
+:10D7D0002B3DADBDC2BEAFFD21F75D0F377D592991
+:10D7E000CE3BF5CFB7A576CBEFBE1338FE6FF3A7D0
+:10D7F000CFA8DDAB793F6BE541CDFBD99EF734F582
+:10D80000E17E5F19A2B9F48F8F3CD5F126D6AFD750
+:10D81000CFDE9D7F7DC20B0B0D78FE56ECE3FEFD47
+:10D8200005E9EE7FA5029CDF3578EB6D00D71B8FF5
+:10D8300035A8741EE6CDA373C0E5628EE787FFF3BB
+:10D84000939F01DE9C6766F27FB6ECCD303AB2BBA7
+:10D85000E241C90595B982F4C4124B9411F5A9129D
+:10D86000D09443E1CD258137140F04F43ED5C2C2D4
+:10D870006281CEA74E5528FE692AE3F1D450B6B88E
+:10D88000E1FD04236B3143BDC26A6C31D3B91FCFB4
+:10D890007798C2A7C9CC46E6C1F72C3686ECE0C91A
+:10D8A000F810E6ABBA548A679B52CCCF0BEFB23676
+:10D8B00084A13CBDF3C07D677F06EFD96A4F118F0D
+:10D8C000D796F96B1F1BAEE51CF0522AA7F37645DD
+:10D8D0009C2B2B614E8C6FD57FF77E2AF7974E508D
+:10D8E00057A918FFD2F11E23BD5BD21DACEF8039C2
+:10D8F0009FE7670CC575B2B096B448D49F37966160
+:10D90000FBCAC30E824B4DF1AA1CDCC79AD1CA6771
+:10D91000E69C807D53B3F26BD2D3C7A83BEAB1FD3E
+:10D92000B9A3DC357E63AB47457B25E0BFF4CF442C
+:10D93000BABC921D24E77DACAE85F0E993BA0354DE
+:10D94000BE3BF24F45A867F8EB7C21FD97D7EB2F44
+:10D95000907E02E937907CE0D37BCB7A235E66A48D
+:10D96000093DD0A2F443BEC08CBC94FC3237AD8BD1
+:10D970005C2D48BBBC3EA87DFF3DF3D7ABC5F3CAC9
+:10D98000782E17F5F8ADC76B89CFF0599102E3DE19
+:10D9900005FA1ECAD569CC935D097C76EAC20D6191
+:10D9A000C394EBC7EB25D6CF1358883C956BE7E7BC
+:10D9B0000EDA47B54C25FB40C62BC87D5890D6459E
+:10D9C0002E2EB9C2BE2DF921F7ADAB5CFB7CE6F57E
+:10D9D000C935A6C9EBB8BF2BBE3E9076797D40FB1A
+:10D9E000FE7B5E7750FECC4CD510C817C178628C98
+:10D9F0006B6CF7F27CC845891B222938B3B8231217
+:10DA0000F5C6C57B54C243667419FB00BE2E14F8DC
+:10DA1000DACA5A3E407C5C387C21E5D12D7A3C74D0
+:10DA20005C71B568BFC4DA68C2752ED9AA6D572D6E
+:10DA3000E28A2B7768FDA2D5C36F3A89FD56EBE2E7
+:10DA40007976A689F8E17C96CFE32EB4FAA9BE6C6C
+:10DA5000AB631A7F65DBC53AF207BCF4BBD6873DE2
+:10DA6000FD83ECFFAE78BBF70AFBB7F787DC3F3DE1
+:10DA7000DEAAB6AD945775AD78FBD341AE0F70DE1C
+:10DA8000921F4F47DE04E34E7FD5ECF5E0F9689135
+:10DA900083FB37156F3D9EB7B57FCBC87F3447F802
+:10DAA00039BBCB4B97F106430E7BEB79BC814BC561
+:10DAB0003CD1C107CACBF0B8A2E09D5AD247BA3DCB
+:10DAC000B792F955227EE86AF99AF4EB0D3E554B70
+:10DAD0007A96D367277D68E8858637513E7E57FE64
+:10DAE0006E290F736338DC0AFDE5A4E7B585B5142C
+:10DAF0007D887AC2CBE121F5841EE95C4F98E499D8
+:10DB00001DC6F30DBB9C07F648C7F340C1FF0D16B9
+:10DB10005718C2698CDAFAEB3B107F7C2AF9F7566A
+:10DB2000FCFCFD3F3CE6B8B2DD5F633F4F7A4377D4
+:10DB3000FA7F8D81E75DE4973928CE0FED29F4EF68
+:10DB4000497F9FBE7DF1A0D2FEE971E4AFF6B970C6
+:10DB50003E9BF87CBADB9F9A955F69FC8BDD8D5FFD
+:10DB6000B3A7C83E27880E66A42B12CFED272C81C1
+:10DB7000FDBD5A3C18D13155A3FFFCFF6E574C50E8
+:10DB800041B504F999AD78B9FECAB81E3B9DF9A814
+:10DB90009CC93AA874331E7F3F8739A99C27F29805
+:10DBA000DFCE7057A4533C4C472F8A9F7CF17FB245
+:10DBB000106FCE8E1CB60163EDBE2F3DAE3DCF4142
+:10DBC000E3B7EFFE9F048C83B9125FD810EF9A97EA
+:10DBD0001EE23CE82F252A9DB7B0538F919CA810D8
+:10DBE000B730B0D1FC1CED5F8E44A29B005FECBD52
+:10DBF00059F2453C9FCDFECCC0E349162BDE81D0C7
+:10DC0000B4C96F20D2CA9E9FE855B1DEC8DF6757FE
+:10DC1000457915A8670F09E7EFEF8EF2A21F7D0681
+:10DC2000F3133DCE628CF8DD6CC6F9DE5CE6E2F9FA
+:10DC30000EAC2309F5B0F9CD161EEFCFFC29C8DFD5
+:10DC400073BAB17F5A049DE726717E9E5BAAF55395
+:10DC5000AC49E77CFC6446E967484F67D25D6BB12D
+:10DC6000CC8DF6AD7FB890FCF60CED8793437E42E9
+:10DC7000E78DF2BBC841A50F62BB9D0A8F4FF7EC41
+:10DC800031537C047CD1AB3C28AEFFED8CB25F619C
+:10DC9000BB4711F645DDC315BED3E4CD06E8C9C3C5
+:10DCA000E78F3617F9DFE141318D4BF5DF3F3D61FD
+:10DCB000F26A2BF9F83DA8F7460E723F85FB9A6B86
+:10DCC00062CC8AF37FC2ECDD42FA696D02FA2B174F
+:10DCD0003E6936A0DEF011885BCC43F96B9D85CAA6
+:10DCE000BF811D8CE5A7600763F919D8C158FE1DD7
+:10DCF000EC602CE75FC80361C1D8D80C5733C7EF7D
+:10DD0000D0F959BB053C3BC7DF63A2F14F66B809A8
+:10DD1000BE9DFBFD32F3E2A1CECEA88EBED197C14F
+:10DD2000B7EEF98C47D883A1E3B99E15F3C86934DF
+:10DD3000927CCF69F2472E086AF776BA89DE67EFE0
+:10DD4000FE9CF24FDBEC9DF07529B0E409065E7F86
+:10DD5000FBE979935767E1FC5D9FE1BA81BEFF82E1
+:10DD6000654ED3FBBFC2FC1FE89FE20EDA958EDF43
+:10DD7000901DA05B871E0E725D3BA37CEBF1FB9DAB
+:10DD8000BB937025C06F18A71BC42325D47A57D125
+:10DD90007C6F377714625ECBED97D49071C62733D2
+:10DDA0004A08CE3F97F826E124F6EB7AE9BAF3FC6D
+:10DDB0005BE02993F77720EF74A01CBA1889FA5E0C
+:10DDC0008538DF6F6A4C7917D7E739A0B2810EC268
+:10DDD0005F0DDDC566F0FD9165F61E5339EED3CEBD
+:10DDE0003D2752E659695F52E6437B63C6408DFF8B
+:10DDF000317BC8B7FFFD702CB5B7E35077B2CD6368
+:10DE000030FE649A65EF1F714933EC9F8DC1F89322
+:10DE100059F1CA7E2C673B12C762DC898C8F9F9BAD
+:10DE20005EB21F49E9566705E96925C85C82E4418D
+:10DE30009925020F053BEB63EC319AFA4DF1FD3465
+:10DE4000EDC73B9235EF6F49CFD4BC97E3DEEA2CA8
+:10DE5000D0B4CB8DEE4842FB0CD641F4C0B6A91429
+:10DE6000A797BDFBF0CD99509FB07D8A13D5929DA9
+:10DE7000E2FD845D655EDC8F7680A70914A853C53A
+:10DE80000FFCE661EC4CA7FF57EE796ABFCB710D32
+:10DE9000FA7F377ABFE4B34B9B2D45C867AFD60EE8
+:10DEA000D0EF4F7E86D62EE80E6F3AE9427170BCF5
+:10DEB00039A8B26D21F0062352391EF272C2219E9A
+:10DEC0003F76ADFCEC0BE4673101FAE82C757EB9C6
+:10DED0005C93F3DDE5E8A7FFB3CA281F4FE4F52DF7
+:10DEE000C0DFD500BEB3799BEFEF134BCF3DA8E762
+:10DEF000627EA90BFA5F9221F4A7CABDF7F7290C3D
+:10DF0000BC672B3ED3B467F72A6B34F5D589DAFAB0
+:10DF100083256B82BFEF8E2F2ED834DBE4A6FC4F17
+:10DF2000C5E50DC11FE47CC6BC114E717DB761BC57
+:10DF30000A3CAA2E7CCF88E7B0B775234725FFB9E6
+:10DF40005365B5A1DEDF93C1FDFCB7BE114E713044
+:10DF5000D7DAEF47004B8A337C89CBD18F7AFA8CA2
+:10DF6000C1FBEE11FD9F2DDAF8F36FF07CF46546EE
+:10DF7000719F67A338FFCF693C6930A01CECC1F1E9
+:10DF800025C7EE37A05C695F14E1C1B8FE9AC536BB
+:10DF90008A07CD4DEAF8C0025BBFEE99038F5800A7
+:10DFA000DF3EC624C820B9DA8E4611D437661C205D
+:10DFB000B97ACB1BE12D86EB58CF463C97403958B8
+:10DFC000CAE97C26E28D902FE863AFB99F75CA1B22
+:10DFD000E40BB87EAC1F78E64F871F8179D71CE42D
+:10DFE000748E11767AFB7E5A907DCF1EE77469811C
+:10DFF0001F1EA7A4A3EF7D1B4CD6CBD27903C5DD92
+:10E000005C2D7DEF407A8EB82C3D1FBA05F6A7E651
+:10E01000657E9FC5B9E6819417DB9D3CAFD9A412FC
+:10E020001DCA7A5BB33A0EF1569F7F2EE1CA5C4E51
+:10E03000A24F796FD4B211FF9C887273D91E230F3F
+:10E0400012E96E9C752A73048DB3F335F322CA73FB
+:10E0500013F36F97F27ACF3FA24BB278B92A84DCE0
+:10E0600003391D168B72BA4221BBF2C89EDEA50889
+:10E07000A7230A6B7150DE168F539EC4BBC3E756AD
+:10E08000BAAF243E9DE293A57D29EDCA297BA60C5B
+:10E0900044BDF283C6394760E7D8A719C984E7773A
+:10E0A000300FE9C147A2CA07A05F6282880F381209
+:10E0B000D5D18A7CF9C8880805CFFBA1FFD5D8BF88
+:10E0C0005CD791B0F201FCDE0919973CE8BAEE8901
+:10E0D0001BA3DE5B720B9E6F4F6776B42B6F57B935
+:10E0E0009ECB5EE7F429F95E8DE28BC679BE9D3149
+:10E0F000F1AB0C3C2F5EF90BE157157033F238C4CD
+:10E10000ABD5733BEDD9A7157E1F8A93EBFFD5C323
+:10E11000CFFCFA0ECC9303BB5B81F9CC69DA4BF7E9
+:10E12000FEE8EDEC4E7BE7FFD19FDAD55E2A8F1833
+:10E130005414F093EBEDA64E3D5DEA7BDB789CFC3E
+:10E140009B237EDBB614EA2BB645101C4F3F69F6C5
+:10E15000201F3FBDC54CF6CFE9E88E63CBB1BE2B87
+:10E16000DBE9A1D19C9A7BD1161A1C1FA2FC616F1E
+:10E1700087D17D1E279F30B7E0F9EEE2A732B6A027
+:10E180003D757280E3D91DE80F7C368EEE19606E06
+:10E19000FEFD6D821E91BE1CA07AA8BFB3911EB178
+:10E1A000F8853EC4C7E4FE9D7A229CF2E84F1F9892
+:10E1B000D413FD65AD86E7298F87A9560FF2E3A535
+:10E1C0005BC2490F5C697767E3FACB7E77DB1D059D
+:10E1D00038FEFB710CD7D3DEFC02F92B03FB1B5A74
+:10E1E000BE9F6B4EE67CA053DEF2B8DB5918779BDE
+:10E1F0004C71B70583E2305E55DEBBC8E36EF35564
+:10E20000C54579070F85CE231F3D489CAB4AFF4982
+:10E210000CB3C4231DBA19ADB7FDA1B42D68EF4CE2
+:10E220001F24F29F5987C89794F876ACFA55F29F4D
+:10E230009879BC5F78E873ECF2413CAF7881E56B8C
+:10E240008DFFA67AE5B71ABF4A751623B99B5FEF13
+:10E2500028B81BCAE502CE5549E593107E4B1A3605
+:10E26000BEF80EC1E5F11F7F8CE31EB092DF86BDC4
+:10E27000C3E1A7B7671658BE12F4B459A3079F7835
+:10E28000F4438A3739B13B3307F76D8EEA3B81F7A8
+:10E2900071B5D97C9FFC0CCA5D070ED1BEE8E7DBE7
+:10E2A000E5DC5EE17CA512D71183F12EE58B07D169
+:10E2B000B930A7F7E3EBB3097ED29FDB7E3AB4BD5A
+:10E2C00025E729FB97F393FDCB76FF25F6EBACC949
+:10E2D0009783F2B97FBA4393877D36D2971365C58A
+:10E2E000E7FC1CEA6C34D483F0E6FB3ADFB94BF868
+:10E2F000798E1A56DD6302FC6B6D7838CC1DCC47E5
+:10E30000AFF15C47CE57C695CA3CDA4D83843F7B5C
+:10E31000001BD04DFEEDE38827955DF36FE979771B
+:10E32000F9B79DF9B6FFE0F9B632BFB6B0CC501BD5
+:10E330009C672BF96161263CCFC2737FAD7C2FCCEB
+:10E34000D5B6EF8E3F0ECEE47E95C298D0F9AE7F63
+:10E350001EC4DFD7B3167EFFA0908BC304DCE5BDDF
+:10E360005F524FA9167C5BE6790E6BE6719BC34446
+:10E37000DE0E7001CA73ED72BF5B7C26C955793F12
+:10E380009F027D4D8F0E952FECA3798C641D54BA9E
+:10E3900098DD8825809FCAD1AC9CCAB1AC96CA7161
+:10E3A0006C039537B3062A6F653E2AD9A01611EF84
+:10E3B000792FCF331DBFD080F2B5F08ED07A71FBAC
+:10E3C00015E1E0A1FB03AF150E6319BFE7AF0B3CEE
+:10E3D000FAA7137EEBE1A1CFD71CC1FC7471C92849
+:10E3E00044DC64B4831D14DF5AC65C541F739570FB
+:10E3F00028F6BB8D3CBF57078FB2D0787141C06300
+:10E4000015CACEA2C03E65673AE8B9DC2F30C4E237
+:10E4100091FFEBF7513E2F8C283DEFB0E37D30AB01
+:10E42000A6501E7741E9F264A8A766FE6A0AE5795C
+:10E430000F2B7D01F3BCD39F7D98BFCF2D2D08738B
+:10E44000C2B8AB1E9982F98C6E1137ED16F1D2CCA1
+:10E450009DA7B91FCBBDEA1EBA6FCC3DC0EAC475FB
+:10E46000CABC7035999FAFEEB1BB7B66C27C13C648
+:10E47000F9D6704897F69E0A74DCEA0B6318EFBF72
+:10E48000D6C4DBCBFB6CE4FAE43D37BB76652E5794
+:10E4900092AE3C0F1867008EE35E3590F2E3DCBB72
+:10E4A00015E7E5C60B4F722765A2DE8549F14017D7
+:10E4B000FD841C6EDD959989FB949D29E27E621393
+:10E4C0000B108ED392CAB3B17F99179D2DF6A5BBC1
+:10E4D000724AA62B13DBEB9FCBBCEC9199EE3C1C54
+:10E4E000BF26E222E59BB5E5BDBFC69FD8354FBD2F
+:10E4F000DEC5BC26E22BDAFCF4F6F926BACFA9B0C9
+:10E50000DC5D8F21CA374EEF188CFA31F43B1CC703
+:10E51000AD31F913F2548C42E6F9EFFA7CEF3DAFDE
+:10E520001DD4E4B74B3AEBCC6F3FC7F3DB03F4F5F4
+:10E53000E8721694DF2EE946D2DD50CC6F8FC47A94
+:10E54000C67C6C37E2FD6394DF3EEA985FE4B77FF8
+:10E55000A8CD6F77FDF3BAF2DB4F8AFBDE4E5AF897
+:10E560007D49F23EA965BBF9F9EF3285DF27B5ECAD
+:10E57000397E9F94B40B1789F5551DDCB606CFF98B
+:10E58000163D3E97EEA362E21E5407FC04DB85F2C3
+:10E590005E527D1E4C0DDA83A437B790DEA5CF877F
+:10E5A000A979BC8CECC11A9D1E5D9D29EC4121CF3F
+:10E5B00098D0FF168A6F711D56B2CF4CA4772E7B70
+:10E5C00062B9D38E7541576CC70E3A7793EDD9E394
+:10E5D00031840B92CE16AF53487F95F0CBDD6E762B
+:10E5E000D13DC6DB7B93DE0AFAB6C863F6727B1BAD
+:10E5F0007005E3E177467524A19EBC734FBA1338CA
+:10E600002C7BA5DBFBA777E8EE9F7E4A73FFF439EE
+:10E61000FC0FF5B453062FF63398A5FF12EF252E05
+:10E620003A65747A1D81FB98AF74EFB084BF59ECE2
+:10E63000D7B5DE43ACBFEF59E63FE8EF235E2BEEE4
+:10E64000231ED1CD7DC466B55925FDE16BA3E65EE1
+:10E65000E21BC53A8B1DCC8BF7FC0E6D356AF6BFFD
+:10E66000D8BF81A13E147ED8A8F123981DDA7A8301
+:10E67000C40771BF4857785B3BE1692678A6D03D57
+:10E68000CF45BA7B9E259C3AEF79EE6F25BC1F7A69
+:10E69000F00515F9C1B5DEF7FD43DFEF7DA5FBBC45
+:10E6A000F5F774EBEFE5EEEE9E6FB9EF792DCB3415
+:10E6B000EDF5FB5E70E0A7DA7BA8C57E7BE0E7BBEB
+:10E6C000DCEFB64CE1DF15FBFD355E800674F89794
+:10E6D000C8530F22594E88E07CADD3AE1F1E46763C
+:10E6E000D6BB8E98321BD2BF9053E5424E8115C7E0
+:10E6F000EB025F9C3E1E47907F94DF5F51E8E7F19D
+:10E7000004834F85CE0FBABD58D19CEF76BDB79824
+:10E71000E7190FBBC8E3F4F4E7FE326FA8C215AEE9
+:10E72000BDBFA19B3C22E9C7013D9E99508F37F0A8
+:10E73000FBEC42DC73BC494D0ECE2372937F67B273
+:10E74000C59780F86C4B74C7671505F28D46615EFE
+:10E750009142F6A0104A513FC238CF764CB2ED8BB1
+:10E76000F9A3913FC23C1998BEDD3F989BBBF86F5F
+:10E7700060963B310BE4C971C5BEA600BEFDCBD08F
+:10E780003309289FCC78AE9D4FE7BEC9F85E7F3F26
+:10E79000BFDFE020FDC2F35385EC8733D8D990204A
+:10E7A0007A5D1726F21A757FBF40D853F2EF171C17
+:10E7B000872E1601DF9ED1C4F3A897C6B70A3B8CFB
+:10E7C000DFDF3AB7BF95EE7F62AE0227B7C3A57D04
+:10E7D000D54FBD16B979A5F8A2A5F1A735762EDBE0
+:10E7E000117355E7898175F3FE8F3F1041F2E6F80A
+:10E7F0000303C8CF17E8BF8DECFE19B5DA38E3592B
+:10E800002B3FD2E0DF6CCF679AF7FED88EB07EB098
+:10E810007EFF8B7DC64E03F89DDD6D1E8C7406FB5E
+:10E8200036352BC80EF63F94369AEB01575AE71946
+:10E830009AC73111272AD7F949DD51AAFBEBFCBA57
+:10E84000781E8FC62E95A5E90D46F7E474283D9CE9
+:10E85000A1FC2C9F6671BDFD98C8833C26F2208FD9
+:10E8600089BCC563224FF198C85394F9A3C714E635
+:10E87000C2788AE94AF993B315CA1FBD07F1AF669A
+:10E8800049470EE6DBD5E4FA672A2AE58FAEC4F5E0
+:10E8900087C81FCDC1BCF75D5977FE08F5F8533D19
+:10E8A0003C742FC9EF774CE67513A78F57B246110A
+:10E8B0003D78FBBAEFC37EBE50D416C2E797153A37
+:10E8C0004F652EBF69E265F24B1FC8E2E70BEB759F
+:10E8D000E5D62CCECF5E11E518F5C154CAFBD9643C
+:10E8E000A6BC1F18C765083AFFD7E767E5BF6E6E7D
+:10E8F00041BE21FD304F6425F273CF64EE5F89FD88
+:10E90000A599E76DF97D0998E785F13E786F063B9B
+:10E91000CC5C3C0F8CDFDF27F7E109B10F74917EEF
+:10E9200061204FACEAE0F14F908F8CCD726FC6F54D
+:10E93000CBFCA5AAC8BD1437F1429683BE83F9D299
+:10E94000FA811FAC5608CE5DFC70CFE0FEE8F3DF25
+:10E95000BB5BFFD9F9BEDF642506F2A782F2A65E93
+:10E96000C079C875CB7904FAB93C5E4B7F52C0DFE1
+:10E97000B53615E944DE4F9BAF2AB32686F8FE0371
+:10E98000B16F5549E57B711D4B6AB9BFADD31E57B9
+:10E9900036FCF863DCAF8356E273DD7DAF5F67D58D
+:10E9A0006B07091EB0CE99B8BEA075BE9B15E417C3
+:10E9B0003CBBE7C3DF20A8AF777DD79AC76CEEC119
+:10E9C000EF43ECEA8F860D0DD2A3CCF2FBFEDA7B8F
+:10E9D000C6CCF8F71060BC46617F340AFBA3294C13
+:10E9E000FCBD1A9D3DDAE8E3F13C8DF1268AD76142
+:10E9F000E2EF2B48F9BBE23D1EDFB32291D17B9CB5
+:10EA00001FD281E2DF4FF2A0F3BE2805E41CE0C371
+:10EA100019BBFB02C28FB997937C506FB03A119F1C
+:10EA200077BD7DB3B0ABB8BC2912F2A508FBC175A8
+:10EA300064F524B95328C61D6CA925BD7608F308D2
+:10EA40003F8BF0473CB05F638FFD5F0DF62D3910B3
+:10EA500068000000000000001F8B0800000000009C
+:10EA6000000BFB51CFC0F0038AD7983330385A31AE
+:10EA700030E45933305C07E2307384DC4B71049B23
+:10EA80009AF8A73C65FA374832306C02E22D40BC58
+:10EA90004D9274FDB7B410ECBDAA0C0CB781FC6E9E
+:10EAA00020FD5D9D816117907D07882F83F840CC04
+:10EAB000ACC6C0200EE4AB00693F20D607E2BB40E5
+:10EAC0007E9A1A6EF3EF69E1B77F9B062AFF1D1A43
+:10EAD000FF923A7EFD999AF8E5DF1190C7861FDB19
+:10EAE000911F1FEAF6B44927B4C207D0D2F54E13DE
+:10EAF00006860BA60C0C22D0B4BF17495E0D28B6B3
+:10EB0000CB04C29EAB074C7B66403E8E7C310F2807
+:10EB1000BF11286F648EDF7E056654BE002FA69A53
+:10EB20006F4C08F6042154B9C3C298EAB9441918C5
+:10EB30000065838486D80300000000000000000008
+:10EB40001F8B080000000000000BE57D0D7854D5F8
+:10EB5000B5F63E73CE9C99644E269310C240024E89
+:10EB60007ED0A8098E1030261372263F242401C3BC
+:10EB70004F695A699DA045DA8222DA5E6F2F5F19CC
+:10EB80007E1A2245C516ADDADEDE812A4FDBEB7335
+:10EB90009F60A9E586442610100D3F11ADDE7EB6BC
+:10EBA000DF8DDA8BA10D38C160E9F760F9F65A7B89
+:10EBB000EFCC9C939904D4EFDEEF071F9F9373CEA5
+:10EBC0003E7BAFBDF65A6BBF6BEDB5F758C944E25B
+:10EBD000AA20E40AFCA357DF6442E8A391AB785E65
+:10EBE000692741C72D84A4D9F7F6CEC820649E2694
+:10EBF0007B6B3D844CB2B7F4906242CA89CD63CB43
+:10EC000021A45BFA4DEF0C7A7F34C5EAB511F8F711
+:10EC1000002173085967A77FD2F2472FD22BFDFE40
+:10EC2000E85F2D2122115223371209BEB74BBCBC1D
+:10EC3000AE2DC824A49AB07F732F926A5A8C54BB0D
+:10EC4000EF6D243308A972D15276F6EE0A2B4F08E5
+:10EC50002D5F4658FDBADDF8BE8C6C1F929D701773
+:10EC6000919B8A687D9755E37B77ED07C409E56240
+:10EC70009E433FE00FCA83EB494AC61907FDFB36A6
+:10EC800072DB15995E950984DC1EE58BF94A481004
+:10EC9000F9D6C1BF5748D30CB827E4456C3F5DF0A7
+:10ECA000B1AE9FB869BF334A88B7967670529DDE81
+:10ECB0000D7C29AB563D367ADF5D336772BF46C89F
+:10ECC0000FCFB5679142FA796835F23183F3B1FB22
+:10ECD000DC4BEFDC47BFF7D511AF8DDE1FB07A27D5
+:10ECE00037158EA6C757979E44683D4F341D7260F6
+:10ECF0003D84FCED4A26AF278F90CEA6DCD4409C05
+:10ED0000EFC4F5F10D2E426CD1FB1D3AA96BD7462D
+:10ED1000977B0906733654BF1CE92CE3BCFCA14465
+:10ED20009ADBB1DD661CA7039CFE1EFD90A3BF10FD
+:10ED3000DE871D16DA8FE090853C4FABE81CAC4CAB
+:10ED4000067A37E996303CEF1C5443C00FE26ECF91
+:10ED50005A54349AFE03432B6662BF02AB0DEDFE9C
+:10ED60006090F65783FEBDE89847EBB9306871C9EB
+:10ED7000745C9FE0CF0F04DA1D2EF86E201DC7F3E0
+:10ED8000F10DF4EF1B12F3E3F1B9DFC80D6850CEBB
+:10ED90006EE4C7E085637974DC3A772A5EE8D77859
+:10EDA000FCFC016F47DCA77BC3552E5AAF2FE295C1
+:10EDB000408FD207099990037AD179D809E3DB48CB
+:10EDC000502F7C4D9549D3593FBCB207DE1F974168
+:10EDD0003E7CAE30F663841EA0EF06A0D38DD7A78D
+:10EDE000797B4FC13862FF36255D4FE9BD50A26087
+:10EDF0003DBBF54D7E05EBBB1C96411E573379CAD2
+:10EE0000F004365A81FFF7106FD003F512ECF74F7C
+:10EE100079FF7FC2EB13ED740EA6FB15A0AF9978B6
+:10EE2000414D6AE4F5DDF0BD6F15A37FDAC36B25B4
+:10EE3000E0DF75EBFBF11AE274EE80EF6981ECB56F
+:10EE40001109F836F5A1305E776EFC7D37D097BAA0
+:10EE50008524812D78A2DA9206DF3D316F4A12BCFB
+:10EE6000773651C5A7F6C0E7753DD043FBB3B35A1B
+:10EE7000413A770E52FED372CEA0CB0B7AED0C7ACC
+:10EE8000F8D5EB85F207393F0EF076BB381DCEA0E2
+:10EE9000CECBAD2D8472CE6010AF21DE4FE2598310
+:10EEA00072B78ECBDD416BE026E07BC6207113AAE2
+:10EEB000CF07CED74F867645FDE6F27B9EFD9FB30A
+:10EEC000E0FDC441F2AE75065CC32DD0DE0DD00F5F
+:10EED00027DCF7B54868A742A847FA650B2105511A
+:10EEE0003B9571A969FE1D1EB8AB413D1276A06C21
+:10EEF00050B548A9B17A568D7AB093EB41F56018B8
+:10EF0000E584EAD9610BE553F01CD5332A5F079AF3
+:10EF10002C38DECF4554B4C3A4209CB52865B41E5C
+:10EF2000750EAD9C09FC16FA34DA7EFCBFA15F3B7E
+:10EF3000693F0271EC9A684FE89BF9FDB8FAE60A5E
+:10EF4000A2BE75527D0B023F9B2C49F9A07F6D1626
+:10EF5000D41377757B37D397D5A86F19F7307A26F6
+:10EF60002D0FA11E8CA7773B3D2EBF02F537333DF9
+:10EF7000ED1C7C6FA30DC66339E176E27237DCFBD2
+:10EF80001E667A6DD633B31EA6FAFA503F73B644A6
+:10EF9000085C3D9B1B51AE692B49A87F09F4B01357
+:10EFA000F4B0F8FF1F3DAC82799CEA5D9A766B8FD6
+:10EFB0008BF67B7E84303CA43DD103F3784DB68D37
+:10EFC000CDE353DFBEF37E7A7FCCEA40FE1F9B4841
+:10EFD0001F16C3BD8C7AD79DB3357B1D7D3F3F4344
+:10EFE000C2F784AC42FDAE1578091E51FDF1F74B16
+:10EFF000644E3A947B7F4715FDFED501E28557AFFD
+:10F0000066CB58DFE141C2F498EB672DEFEF61FE6C
+:10F01000FEC2251202FDAC0048429F7F7C3632CDF5
+:10F020004E5F7D68B95C4472E97C2CF8C571460D71
+:10F03000D7FF5733641DECC6E1F529219283F5858E
+:10F0400041DE5E7DD81692697B17F2F35E0813C02D
+:10F050007F91EBD7D1F73DAE8F5262F57380CBEF46
+:10F060009FB8FC0E723CB1E3E6A64512E5EFABF9A2
+:10F0700079A85F17F23F9A4628ABEFCFFBCB19B8C0
+:10F080001212B6025E32D723BE7FD51DF8B244718C
+:10F09000D540E87D278CE7B97D1FCD802B714F408F
+:10F0A000DC351E3EF3091C16E9DB0C388454533959
+:10F0B000991395934991BEC3C037DF30C363A46EE3
+:10F0C0000D8E4BB98BF1A5FBE25B59F05D07E75B59
+:10F0D000D7505F16DAC73A633D5DD6FEE54DAC7E8C
+:10F0E000FCDEE762E32AE87999F7EB6949220C270D
+:10F0F000B2F1F3F1EFE72A7D136EA174CC3D267BCC
+:10F1000037D2477307FAAB491C3BB45B4A4379AD2E
+:10F11000B86494D7AE8B4765E00BA557067ACB232E
+:10F120007D32B3E34CCE7C5CCECA23A70DF65DB432
+:10F13000DF1539DD00ED5F1860F62A115F85FC1CD4
+:10F14000E2E3FCB2D0571272DC42E5E508A57FDBB2
+:10F1500018DFD7B86403DD42FFAAEC0E035EAFB838
+:10F16000946EC2FF467A4B9530F2AB14F8E549CC69
+:10F17000AFF5523AD65F36F0E9F865B62BA2DE2E2F
+:10F18000E063E168BA0808B5A05BFE3F9FAF9DF061
+:10F1900007F35F8E829E92FEBD72530ACC271ADA65
+:10F1A00093B26A89E172DECF46F896365527F4CAE3
+:10F1B00023A19F57EF9342B58037BC3F433FF142B5
+:10F1C000B1CD03766892E709A53F46DEEAF9F72359
+:10F1D0007CDCA0633FBB67BF9D05E5BAA66FCC860C
+:10F1E0007198EF79DBB18EF2FF28D79B8E0D7558A1
+:10F1F000AEEC1279F45618977CA66773795F7A386B
+:10F20000DF0E71BB7190CF9B6F6D08E0F5CD0DAB3C
+:10F21000F07A7AC35ABCBE7AE9450DC6AFB7200F63
+:10F22000E7AF3AA55D89E757950E1AE5E6650FC584
+:10F230003BB47CC3E08AEDB7D27E1FBF6441FB7C48
+:10F24000BC206F4CBC22EC8728F78AFB6755C0B7FF
+:10F25000C6014A6ECEE8F266792D23523BE0BF32FA
+:10F26000EFEB0AA1F67241F12E2D16C71C38975903
+:10F2700004F51E90FEB0649627311D65BE3EECE796
+:10F2800082F0EF144F4AE2722794BEC659E8A732C3
+:10F29000FD2AF3BE5BADD3F66A0B7735A25C0C2B6F
+:10F2A00016908BC6C2BD7C7C5D381E0BC47C562C70
+:10F2B000D785809EC10B48676FA13C11E8DB669142
+:10F2C000512E17786C886713B63FAC9030E89712D0
+:10F2D000C6713A4EEB01B93841ED1E7BDEC7EE69CF
+:10F2E000BDF0BE3BC7A679819F6E118F5865908F88
+:10F2F000C6FC59C7BD94EE5EB78CF8B2F752A59222
+:10F3000046EF4FC0FCEA89CA671997CF1330EE2049
+:10F31000C72119E73F8197457D5D97721F2DA6EDA7
+:10F320009D0859E37EDF546DD4C73BDC0EC37D7569
+:10F33000F604C3FD89C1996F36417B947EC0732466
+:10F34000B8DA407F17D87B68CF25E1FC7FF472F5EF
+:10F35000E0FD502E64A4CB4C47EFA5DC2797D27A72
+:10F360008FEF93514EABDD46BAAA2EBE791CE23820
+:10F370000DD4BE00DF5ED6151DFA7D625F4A68239C
+:10F3800095CB970B5F77006EA0FFB405B49D2AC2A2
+:10F39000C6B732C358CFF1C1F7BE0F76EA825D46D9
+:10F3A0003B57F9D7435B005E9D2A7EB007F87C800F
+:10F3B00048C8A7F273BB65A86F59C8F8FDD2E546E7
+:10F3C000FEAC593AC164FF8DF1A52A0F8B13CDF520
+:10F3D0000E617DA510FFA1F7959A312E34178C414F
+:10F3E0004CBDE5A6B850A987C5854A212E24CAE59B
+:10F3F0009051769FDE63FBE679DDACDF09F5DF42F5
+:10F4000056413C8544168F835B36F1F88AD1DE1273
+:10F4100065A704F250CADBEFB0B63B802EDFADCC5F
+:10F420007E91487ADC7895D98E10F220CA95E02337
+:10F43000710549C61CE83F2F63B67F9C2F6D743859
+:10F44000AEE03C10E4F8C51357DFCDDF67737D9F56
+:10F450003740ED66068C97EC02BB71FC12D1401F61
+:10F460004F5179672DF75F8995DB868176944B5AEA
+:10F470001E469096F7A2FE364D66FADB9D53ABA46E
+:10F4800031FB1957DFCD7A3040824F15D3713D9E45
+:10F490009FF7E452FA5DEF3E61072C3AEAD53E86CB
+:10F4A0007B4F0CAE4379BD40E515D83E5AEF4F6B0C
+:10F4B000B1F3FE7F96BE9BF57C44FF47E93BB35B0F
+:10F4C000C7872DD89FAA8B0AD6D37099E03C6ED6F9
+:10F4D000FF13DC7F7B597F53F3C27C58F83EFAC799
+:10F4E000E453EB3BF3430E0C106CBFFCDC7B32EDC2
+:10F4F000F9E7A6EF42CF85DE5EB3BEFF27E9B9F993
+:10F50000F9B72D1CF727D0D3A8FE07B1DCE61452BB
+:10F510000071B60E29D9BB2907F49DC57DCCE5271E
+:10F52000C8221E6B0FFE91F6AB850A4B2A65F51AB1
+:10F53000D23F0DE461E2640FD6779FA53F13EE3F03
+:10F540002491CC9B65C0CF643FCCBF924EC8C3947E
+:10F5500024C9E322CB6712F2B81CB0CBB43E6920B9
+:10F56000FC5789F2993C443C80076F90020E786EFC
+:10F57000A37CD26879A29C469C48FD37E4D742AE72
+:10F58000740BED5A18E3F025D6C17EC1779C3F96E7
+:10F59000BBCEDC4CEB2561E9CACDD17EEEB186B2A3
+:10F5A000BC1AF433F4E3FB206EF58CEA7D3E0EDFEB
+:10F5B0002D9FB29F607E909F16C6CFA025D9FB7C61
+:10F5C0001CBC35FFDAEB7F2B995ECB808FB78CE6C6
+:10F5D000A33448F9077C50FE7605FCC43237932FDC
+:10F5E000F9435587380D91EDA1E971E858C3E978E1
+:10F5F0005CD66FA3C886C855EDC89F0330FE1AF0CD
+:10F600002F837C3B46BEE6C92AD2253790B538BF4A
+:10F6100090B005ECC878E361558822C338F65D41A7
+:10F62000BBDBCAE9B3D1E7DACCC4E3253778236181
+:10F630003A4EE443364E07E61BE5723DA7FF414EC6
+:10F64000179827A8BF14EAA7FC92FFACAE8D374FDE
+:10F650006C17FCE7FC32973FF025D67F517EABCC90
+:10F66000F42978EDE3B66C525EE27113F22E0D1EB2
+:10F670004D347E6B4371F47B8E6CE1FD0D4A57A3D4
+:10F680000FF3B85CCA5574DCA07F35463E6EE6FDCC
+:10F690005ACEEBBD4BD2FF1EE4E106A9E91FE04ABA
+:10F6A000AAFB50FF40C6A1DCCD44FF6FFCFD06D095
+:10F6B0005352677C4F9F6FC2EF9AFB707D4A3C3F6D
+:10F6C0002CE95B64F6BE15BFD38DEFA91CB6C173E0
+:10F6D0002A2F449E09CF193FA99C103BBD6FDD75B1
+:10F6E000F79781AFF4FBC7B07E72DAF0BD150C441A
+:10F6F0003ABB4A33D9F559903BEE9F6E6ED691AF27
+:10F700002A59CBFD67369FCDE5F399FDAF6C1EBC42
+:10F71000E05231AEA524E9A130BDA6BBC23AC40374
+:10F720002790BE20F863CB96CA063BDF6C9A5FBE7B
+:10F730007C8F71FE5DBE3ACB70FFD587F20CF781EE
+:10F74000F5371BEA5BB16596E1FE9EED6586FB959C
+:10F750003BAB0CDFAFFA4983E1FD379E5B62B85FDC
+:10F76000FDC29D71D737C57CF788E5DDD54DB45F07
+:10F770009BE1550C5E54A2EB971686C78CDF51F1C6
+:10F78000F32873A01CC15084594E15D3FA67FF8823
+:10F79000FEAC33CCB7878239190015F41C4543FC05
+:10F7A0001FD4FBF233A378A0CAB3B231DEFC2BE83E
+:10F7B0005178393FE9AF8271D315633985AFD76A84
+:10F7C000DE08C661CCEBB58A671ECEEF667ADF91A4
+:10F7D0005332C02ED1BA3DB84EAB5DDD7C3A6EFFE0
+:10F7E000A825BCAAFEF1F6FCD0CFBCC4FD9A5B1CD8
+:10F7F0009181BCABED57944E23EE11EBE40B5851C5
+:10F80000529AF31CFA630B803E989F8B19DEB1D39A
+:10F81000FFD83CCBF8DFC0CB373DE4B2023E6EAA46
+:10F8200036D2D9C07114D54305EC446981E93DD085
+:10F830003903CA19F1520F97474DE1EBE573C81C24
+:10F840001C07AEB78B84DED6B0380771C55F47AFF3
+:10F85000BF440BCDC2F651FEC4F3D70AF292E1BB0E
+:10F86000056DC463A3F8E491D91B5D9580F375AB76
+:10F87000B78E96AEF2F278932E239EBDAE80DD3722
+:10F8800056B3F8537DA00FE3808DF78436C275CA56
+:10F89000AAB0827498F8FAAC279486D880F3378B94
+:10F8A000F32B4BF095F351D8F129AB8DE3D8586C7D
+:10F8B000E4D742CE4F339F17723E2E34F1B10BFE88
+:10F8C000A07C999D808F0B381EB5CFE6FEDD707A47
+:10F8D0005CBFF1591E1F13F2A398E635613F46E65F
+:10F8E000372EBF8F831D079CE7E23885CF7B89F4D5
+:10F8F000C89FDFB2C30FF1D60CAB61FD621EEF6B88
+:10F90000693E5BEF28CD9011F797BADF30C4994B71
+:10F9100047E2A3BA5633272A9F5D03CCFF68759F41
+:10F9200096619C1AF219CEDFC2F923E27F07F8BA7A
+:10F930009199AEA3D382D9808F8E5D0C66AF2B8652
+:10F94000F88F8472D279EB03D92C5F80C773797BEF
+:10F95000AF0C05D17F3B3630F6FAA2C0F966B92963
+:10F96000F586709DB174A05D86FED645E81C44BB4B
+:10F970003E2FFC0BD95384716905E86974AF503090
+:10F980005EE66E5120BE5CE7DE5505FCF091D06668
+:10F9900027C4D53C92370C7C2C64FABB8AFE17AB8B
+:10F9A000BF82DEDAC18002FA5EEB31FA353E2E6F9D
+:10F9B000356ED3F3FC5A94379F49DE3609399B4E96
+:10F9C000A6C7CA99885BAB43B95C5FE3CB5927E70D
+:10F9D000C7BFF338EB1F787CFA1DBEAEF7BB0D1E18
+:10F9E000BCBEB2A1009F1FD9E0C5FBB73794E0FDB4
+:10F9F0006F21CE4BEFDFE071DCD73734E1FDA90D8D
+:10FA0000CD78DFCBE3B4428EB7F2F5941AB913E3A5
+:10FA10008B0DDE80DD15234F0D9C6E147DC021857E
+:10FA2000F1E3AFB669FB1590AFD3237A42D05E2CD9
+:10FA30006ECCD9BD8DF2C5F65D12005C693BF4AFAA
+:10FA4000CAF554FE1BEA72AC2BA1BD60BB320BE4BD
+:10FA500031FCAF4A1E3C6FBCD57A779CF6453B899A
+:10FA6000DA37DBB72575463FB854C4D1070241E801
+:10FA7000E7A4814018E82B75AB9E7871E1EEC92BA5
+:10FA8000DD204FAD67036E90A7D6C97B64E6AFB3A8
+:10FA900078B8CAE554942F75EF36E8A1CAE9EEA00C
+:10FAA000CF81DE8E71F4E000E79B28E753C2B24BB2
+:10FAB0004BDC3F9F295EBE458AEFB7265B19AE75CA
+:10FAC000F2F5556A3315D0331051A07F12151BD0B3
+:10FAD0002F4D63710B8737C0EDB2711E4F2B696AD2
+:10FAE00002BBA465106F2D9837ADDF0D722397CC44
+:10FAF0003B0BF32C298CB1DBE0F798FDFFD87B1989
+:10FB0000A7AE604A3A5CCDE5187F352E426DB7321C
+:10FB1000FA1EE3710EC15F8DF3B7D473ECDFC0AE94
+:10FB20003EE665F198C732D8BAEC85921588CB4A83
+:10FB3000B95F60233BB07C3269C7EB66AE67174A9A
+:10FB40004E13D07B59A1B83903E8B18782F47BA763
+:10FB5000C9BE2B9A91DF12E5C972C0D7038AC1DFF3
+:10FB6000904A989DB783BF0E7E0CC72F513F2F4000
+:10FB7000AE00F3AF124F6DB11AFD31711D502C283C
+:10FB80000F2EAB299FEEFF7AFE1DFD5CF927FCC40A
+:10FB9000119C77F8EB04D663443EA128FF8A29DE46
+:10FBA000A466B3751873BD775819DF2BAC1C1F0BF7
+:10FBB0003CE133B79314047EAAD49F4A9246D7936C
+:10FBC000A83D3230739CB8F5466CFF94E262FE04A7
+:10FBD000CF07A26EB964F04FECBA3B76BD7FE47BF1
+:10FBE000B7C5A0A7A3E966FCF9BCE95D401D52B802
+:10FBF0002E1476B884E1C9451E8A27E99F8B3426E6
+:10FC0000A727FD526813CAA96EF0B7EA4A6ACFA2C5
+:10FC10005DA2FE883A87E3744A7F1BD44BEB797D63
+:10FC2000B2F86EC49E58AEDC32BA9EA66A867B4895
+:10FC3000F097F363E3074D545C0A6642BDEC7B5AD0
+:10FC4000B4FB4A3C3AB8DD6A2A7960A1E6847B5D60
+:10FC50007A1AF05E610C3E00BEE6DB8C7C36D9BFC2
+:10FC6000EA5176CF686FE751F9DD4FDBA993D736BC
+:10FC700042C8BBF68915FB5E4572841FE2895BEFC3
+:10FC800071F8E376407F46BC42BC2C8FA32AE8691A
+:10FC900044BE6748249403F41BE998976DF2C3327D
+:10FCA000CCFDD881E37848A1F3081DAF43741C77DD
+:10FCB000A07F1CDF9F127E5E45CE30FA53C2DF2349
+:10FCC000DCDF73D1FF62F158392FEF7FC8A300FE4C
+:10FCD000F5DB4D71E691FC6382FE540531D25BCEBB
+:10FCE000FDBE7293DF27F4FD25612F855FCBEDE12B
+:10FCF0001DC29F2A1F7B7DB9C7944F574D096FBF07
+:10FD0000063D204015AC3791113E19E4AB3BE7FAB4
+:10FD1000F630E5EB1DDE24B6DE42E954843D473E75
+:10FD2000319CBD9097BFC3A3A2FCFB34B67ED138F3
+:10FD30004EDCC257C2D60D4ED925361F04C99B24AE
+:10FD4000263FBCCAC3ECB566928B6C4F5335AC03EF
+:10FD5000698AE40D91D1F25ACDFD39F87E3D6545B1
+:10FD6000753EF5C967C6CB2FEF83D02A29A7343C4F
+:10FD70009B93787C756FA40A86E76AC7979870F69C
+:10FD8000A9C87B98D775A150C2759FEE9C8FD13FB3
+:10FD900010EB3B51FE1DC57C145FC947E8AF8CE4F6
+:10FDA0006DF1FA168AFA4A0EE37ACDF75C87314F85
+:10FDB000E424ACE3D2EF4F2A110DFC90F9025F511D
+:10FDC0008E86053F73204F82D517E67ED529FB1B13
+:10FDD0000EB09B22EFA4CB27D7C58B7356C82CCE71
+:10FDE0002CAE37A96CDE99A3323C27EEC5F88EC83D
+:10FDF000937CBC98F9E1DF318CBBB97E28DF8CF1B4
+:10FE0000C170E158FE68A389CFD3543EEF71BCD1D5
+:10FE100019191BD78A7E9AF960EEA7F93BA7CAE2A7
+:10FE200065F758F59BD5D9D176C47C672EBFC81E1F
+:10FE30003F2FC75F628C4F9AF372EEB1064A55CAE4
+:10FE4000CF2A45DA92EA41BB86FA74E8B28638E6F0
+:10FE500042E4D01618D623C32C3E5A4EE4908DCDE2
+:10FE60000B8DB06E27F446C8BF998EF1DA2F1FEEC6
+:10FE7000477FDC7F29520DF27787AF1BEDEA026ADC
+:10FE80005727C4B1ABF3E4C12D13407FBD6C7FC7CE
+:10FE9000A9DFF755E3BD26613EAC5E9EA74C003955
+:10FEA00070C58F57CDE572327A3D4FD8559702B85D
+:10FEB000C11C6F9BCBF56EAE491E02EA080EBAED6F
+:10FEC0004ADEF8E394481E2E442E3C182F8E2AAEAC
+:10FED0005509C6F73E62E26FA731FE6CAE47C48398
+:10FEE00088DC990DFA2CFC5F73B93695AD7B1C2923
+:10FEF000BA97C4E655097BA096B46B1017EF2D197D
+:10FF00007BBE30E70FFA89314FACCA6E5C8F7D4AF9
+:10FF1000D11F01798CE2A416E6AF96B4A0BFBAB0A7
+:10FF200090EF0B2ABA17FD53E157B7DEBE17F3B9AE
+:10FF300044BE96F04FCD74F74E7E11F379C6A35BA5
+:10FF4000F8F1C76D325B87A07EBB07FD768AFBE2C6
+:10FF50007CF78A8DF1EB578ABE0BF4758B5577B71A
+:10FF6000C03A6391CDFB7C9C7118B031FDEE4DB071
+:10FF7000DEFA0758F8988DFD403E98E71BE1C78AE6
+:10FF80007D4A93DC4C6F1BB81F5B56D882FA98E60B
+:10FF9000A67E2BF0CDCBFC563268F453176A7D5900
+:10FFA00030FEE6F94E1EE67EED55FAAD5B93981CE9
+:10FFB000055CC4EEA6EF93140A4DE9FCF7A45C7946
+:10FFC00018F8B1358DA03F70324D0DED8E136F785E
+:10FFD0009BCB5B8DBCDA206FE51C97A8D5FD1AC4BE
+:10FFE000034E0EB3385EA271DB66C2E9B905C46F79
+:10FFF00073C235E2077ED07BDD86D708E6677FBF18
+:020000021000EC
+:1000000068656EBCFA76B72971E7A53FF3715B2C82
+:10001000F2B5EB583CF2BE4215E3C293EADE3D8AEC
+:1000200072DAC8E574810DFBDD5BA4E0B8F4DE9EF6
+:10003000D30EEB9ABD4576CC47E92EFACDEF215F82
+:10004000BBBC4432E49708F92D075C0DF5DB59BCC5
+:10005000F33E37B3C3BD1AC72F3C6F640D1FD39354
+:10006000FBDE77C6E68D2C1172DFC8E3E426FC4484
+:10007000CD48DC751C91477CBE91C585EF13FDDD35
+:10008000BF770BE85D03979BEE8B2BDDA89FFB5999
+:100090007E5E6B510BC68BBA27BFA5C2FD1AF7193E
+:1000A00015EECDB8428CEB7D25BF62F9917C5CD713
+:1000B000403C9ECAFBCB99375B3DF47E71F8762BB2
+:1000C000C43B457C76D43A145F4FA965DD27B56EF5
+:1000D00086AF8F663A487206F04B0E49C0B7701271
+:1000E0004986FC33B7359444EF1B94FE69805B1C52
+:1000F00026BC78FED77BB341BF8FCCF8408176AF6A
+:100100002B79B715FA31A5642FC6FBB3F6EFED498D
+:10011000A7F52C2C205EDD339A9E1A3E3FDD97C159
+:10012000F285EEF38682B0EFECDC65B69FA2F2D7E3
+:100130006F54C1B4367A5D46278043C4BA8EE2E676
+:10014000EB227C7D825CBE22C58E5B8312B083FD78
+:100150006D2D79C309F42EE67CCBDD27B7807C5763
+:10016000FF7AD657404EC8ED36D774DAE039D76FEC
+:100170009DD76BECFDBDACDEB9015ABEA1706FF628
+:10018000CAA2D1F665447F0AFFB22140E93939FF9E
+:1001900037D980DBDEA076D703ED72BB65F697CC4E
+:1001A000F3AA392FC6DCEF4C65519D6D368CF78F65
+:1001B000DD39317246EDC00AA07FCDD376CCE34A5B
+:1001C000DBFFBA2A837DA3F8BD568ACAD11A2E470F
+:1001D0000D1AB37FAD4524B44902F93BD358067AD2
+:1001E000F72ACB379CB4FF5D963F6A9A1F7AF9BC19
+:1001F00021E6E3DEC9EFA1FE9CDFC7F52568916229
+:10020000E3495A4964298C8BE04FA7C9DEF8ECF129
+:10021000E326EFD8185E2DD7D87B8DDA6F58D73606
+:10022000BFAFE4FE54155C63E685076D0CF78AEBFF
+:1002300035E4213CF55DAAFFDDDB0FB9EF463BA5B8
+:10024000216E5FB37F6F01ACD964EEDB5BCDED0552
+:10025000FA6532EFE724E2413BB550B3B3F50393BF
+:100260009C5B4B7685013E8B791A1C7225336A475D
+:10027000E4D838441C3F8C04F537F363F2BEE8FC45
+:100280004EC0AE54B959FCD52C276925D4EEE020D8
+:1002900050EEC5ACFB9AE5B6410BB8613D9BEACF89
+:1002A00059B6FE49E72B884FC88D5E1C4F2E9F160E
+:1002B000FA1FCC7F0EAF513EAD05AA01AF98E9F809
+:1002C000A9CD88FFC5FC9CE6EE47FA166AEDD9D0A9
+:1002D000FE24773FFA5BD4BE67C355C899B0D723D5
+:1002E000F257745B3DD877906B58223F59322B19E7
+:1002F000EC60839BE114628AA7F7BAC7F6377A4CA1
+:10030000F278D2C5FCAB861292EC4A057D6771A7E4
+:10031000DE47D3773962E272FF640D74D862E2EB94
+:10032000CEC22FD6BB9C606758FE5629355FD6BC1F
+:10033000683C53C44DC57A9F88938E8A671676634E
+:100340007E9755E45DF0F5BF51793F09D61DC5553F
+:10035000C4336D9BDA152F5F2F413CD6C8E370C3C1
+:1003600033C78987B2F803C567BFB54D1C1F9FED22
+:10037000E17EE600180F7A5D6573E155837C144ACF
+:100380006A6F527CDC7690FB6DD7A29FC764F88EB3
+:10039000B5F327937C89E7513CCCF46052C9DE9ECB
+:1003A000583C5CDE467943C7496D23D3486A62B93D
+:1003B0005B3862F77E6590AF117C3C0E2E16F275AD
+:1003C00051D6FF669B98B85C03A723D1FBD6225B6E
+:1003D00033E45BD17264522ABBDE40AF3D33F66634
+:1003E0005BE8F3D7007FC5D0D1FBCC7EECC71F54B0
+:1003F000B6CFA6F7E2CA5CC007A7143DD53EF1EA26
+:10040000E5C7AC4FF6D9BA6723D5BFAE6C3BCECFAC
+:100410005D6E86435E879231F2B44E0D5C679F8DB0
+:10042000104427E9DCC8093907A3597D75FBC4EEE0
+:1004300072F43FD414333F6C875793619D8FC9CDBD
+:10044000236A3FE6E3DC456BB7D1760E6B72E60AB2
+:100450007A3FD3CEE4F170D01A37FF79A69DE1E759
+:10046000756AD34CA093B4AF453D6B91E426D07F21
+:10047000E2BDBAF8DCE68EF879A555D1FAE762FD5F
+:10048000FB68FD801BBC3CFE4E5C9971E3EDBCDF5C
+:100490006142EA405F1E4B33FA9B3E3B9BF7E646C8
+:1004A000EBAF8FAD1FF3B366E3F30538CE2FB0E7A4
+:1004B0000576A617FE3C96D726F828EA5D1AAD6F9A
+:1004C00029D6B79F7D976FE7EB069C6E81F3CDF938
+:1004D0004F35496C3CA2FBFA08DACD528AC3F17C55
+:1004E0008548E830DCFB09DF9729319CDE95C2F6B0
+:1004F00031755987F09C85EE4F3E7E07F66B2A8A50
+:1005000011DFDBB8EC2897F7C850AE34FB8223F636
+:10051000DC8172FEBE7BD8B8AEAA73BC7390F07C4F
+:100520000D5E9F3F419C4BE0F80E5E3EBA0ECCF64E
+:10053000294E1A60FB122B5CFC9C88B46FA35F2DC4
+:10054000F47CEB276B199E9FCAF7AF65EF9163E9C7
+:1005500051383DA5CAFBDFDC0BFD8F1017C659C310
+:10056000BF73E4D07EEBC7646F129436F9193E8EE8
+:100570006BCB396E4D84EF8F4A81E7C22CBE69C0C8
+:10058000F94733FF59061C5A1A66EB4C151CD7570E
+:1005900028A12C981F6AB3593CAAE3625F16E2F9BE
+:1005A0008F3371BEB84ED985FD9EA20C619EC43CAE
+:1005B00013FECF1A20E837F8A9DFA0C7C12D357286
+:1005C0007635ECCF2DF5B0FDB5A55E56BE8BB61FCA
+:1005D000A4E52B2FFEA007E0FA687C6FC429E59EF6
+:1005E000A12A342326DC7FCD783A9BC5A52A4C7EF0
+:1005F000829007CA0FDC37DFA13C68073EE4665BE8
+:10060000987F30D5B21CF846ACCC3FD8EAFA961D9C
+:10061000FD03FA1EFC830AEE1F545C8E64817F602A
+:10062000EE8F90AFDCCB1FA37FD03DF431F239FCCD
+:10063000C99E2CB0CB228F5CE07A513E53F11F0152
+:100640003D2E37E17C9BC0F9C36B09E0FC0AC588ED
+:10065000F36D5CCE2A38CEEF80F52E90D7B399C7D4
+:1006600073683F0E0A9C3FEC32E0FC52CE8783A0B9
+:100670008F3138FFE059B6AFB22B3BD780F347FC40
+:10068000C84F89F37D49CCEE081C5FCBF18278FF1F
+:1006900021B7E3667C6F7E7FADF89E70FC1EC5C5FA
+:1006A00046B9EDDE9E8BEB2AA52E3BCA6DF9406064
+:1006B000F801FA2A7378ED1F9F007EBB1D5EF8CC0F
+:1006C000C6C765DCFC4F13DE9F44228753416FF29F
+:1006D00059BE515AB60BF5A482EA496D3C7D30E310
+:1006E000FF6C366E554A8BC88B1B13E757682EC4B8
+:1006F000D98A527B5538DFAC5775F9B631FDD2AC8B
+:1007000024230EF30BBBA93C1044BBA93C1006FDEF
+:10071000F15F66F933DD9F7CDB1D7B9EC3566EFF68
+:10072000853D17FA78F0938F791E8D49AE958F1C11
+:10073000B1FB8A0F66331CF2332582FA7BF0F2CCD0
+:10074000E4D8389519E71FE438BF82E3FC8ACB4C24
+:100750004F0E8EC6F9B725C5E036E7E56588F3AFDD
+:10076000369F40F8AFB526FFF55DBBD17F4D24D74E
+:10077000FFC1E7F3283F8736239E5586D87CCAF908
+:10078000A9703C6B031C790BCEA3B83F5EE8F1283F
+:10079000BE5A3F32CC937E8EEF0E2A578D679B93C5
+:1007A00066272E57310E9EDDFA89DA8CFCE778B683
+:1007B00042E0D9BF45B262F12CD1180E3BF8CC25EE
+:1007C000ECC7C1348663CD382C31EE60F77E4DE244
+:1007D000EB30463C21EAE94821D9189F93DE46BE1A
+:1007E0007559FF12178F08FC61C61DC4843746EA8D
+:1007F000059C027860F88203F6C1761C93F9BEBAB4
+:10080000CF8A4322722CEE10DF75A5E8E8CF0B5C8F
+:10081000B2F593338833B60E113C3941E0128A3772
+:100820000E833FA7D3F93BC913A55FE01381374679
+:10083000FAA1B0BCD12E17B7FF09E2A09F373E1135
+:10084000B8C4CC9F8356865B3A2EBEF599F08A19C0
+:100850009F98E99DB76B474F2A2D373F7F08ED5092
+:1008600087B70FF799770DE766001FC6C72D7E5C27
+:10087000871F895372FC71ADB825115E4984330E10
+:10088000028ED1A238C68C5FCCFCCCCD262D10F7C1
+:1008900017B82691DE42B97B9D51BC93A81CB5DBED
+:1008A000888312D6733972AD38E84CD298388810E4
+:1008B00026372C3F28113ED9EA7569B1F9AA623E64
+:1008C000E9CEBEF00EEE2B1F50F17C84EEB3CC7E51
+:1008D00026C247874C7A7710EC85169DAF12F265D9
+:1008E000809DF3217054A272578B9FC43CE24B62EF
+:1008F000F344A2F5C9AC6486B31EC965FEB2F97DA6
+:1009000034DFC488A3484611CAF3FD7CDF65225C4E
+:100910004548C4C9E254417CBE8CFB9B181B9CC358
+:10092000F30D28A94DF9241FE685263B1BAF93B391
+:1009300025F40316C1732A4FFE6AB63E74BA88D9ED
+:10094000EB937E1BDAEFE3E7593E62770A8BB39EA7
+:10095000BC35C9BB9B92701EEAA5F3F0E9A4BE6248
+:1009600098F767887EA6B37E2E708457E3FAF8ACBA
+:100970009B2DC19CD1FAFD4832A7235DC375B606F5
+:100980008E3F619D306BE6E8FD04CF24E7209F2079
+:100990004F3E8B96DB62E9FB7E2E7D946461EBAA71
+:1009A00066BEFE99D3038CB1C5F0A131DFAE2751ED
+:1009B000F94FBA89AD4F7555DB301F270996D269BB
+:1009C000BDDB0A7253E2C991E897F9F94F9399FF99
+:1009D0007D7A6A04E7B1533CBF778D22050973B075
+:1009E000B09FCA8429BBB6D1A25F4E66E7D59CFAF8
+:1009F000F5EB18273A91C6F9A04B98C770126C21F5
+:100A0000C4FB5C5A08F665D2EFADCBC6C8FBE8F371
+:100A1000D716B0F53242245847833F7247F37B49DB
+:100A20009D8CFD5EE2DAFE00E8E3E9BA371C70FE59
+:100A3000E4C2610B01BD5BE22ABD179E77A7303986
+:100A4000063E036E5A52FDC56FC2F3C646E3781CDC
+:100A500049CE65E7C8286C3C60FCB2668E6E97CEC6
+:100A60007E01353386FFBEDFFC9D1433AF88BC1595
+:100A70007B823CBE44FD9662EDAF1C8D3B4E2AD975
+:100A8000B503F6C73415B3732F1A3C2408EBBC0D1D
+:100A90005E12CEE1F285F9343DF96C5F10D7AFB448
+:100AA000925D6DB910A71C56D8FAB3693E29A363AD
+:100AB000959D0E7173363E2767CBE8D79595305CD0
+:100AC0005FC6717D83DE82EB7A8D8FF66CCF85F702
+:100AD00072768DDFC3D74763F847F6B338DC2293CD
+:100AE0009CA798E2FC655E537E20CFEBEB2A78CE84
+:100AF00005F2F3483A979F9912EAD1EB92E7D1DCDD
+:100B000098F9A83E59E41F118F35463E46E4818F7F
+:100B1000AF99EF89F869E693592ECCFC3E9962E2D1
+:100B20005702FE27E2775989FFBF94BFE7AC362B07
+:100B3000C86DB7F5836CEE0F1139C69E98F9764EE5
+:100B4000F3A4809D383DCCE69B13533D5FC173B049
+:100B5000A81EE3399E5C1FA2E340F5C119ABCF6F1D
+:100B60004F037DA67266857A1A75494F02FDDBB781
+:100B7000F501EC37E8A933AA4766FE8FD23FFABFEA
+:100B800022E8CD1BAD47E6BCB14FAB7FDF017B0E4A
+:100B9000F182640FF24FD8D346E2FA4AEC3E56B1E6
+:100BA0009EDE9DD3DA04FBCF1B062C78DE4FC7F008
+:100BB0008BCA0AD8D75A27E1B4A6913EA4576B63D3
+:100BC0007911D73FFB3081BCF547A7122FD82BAD49
+:100BD0008DE549D0F798272170BD38BF91BED75910
+:100BE0005E88F19CA514AF31CF67F16025AE2FF47C
+:100BF000F0738F46FC0B22E4D2B8BFA5159E4C8E35
+:100C0000EE876ABB18C2F84C4782FD2EE26AF617DF
+:100C1000CCD723877EF1CDBD905F91AFBA005294BF
+:100C20000F87ED50DFF70B0FD5613E5B9DE48275BA
+:100C3000B7231FB76F86F38E1617BE1737BFE7C0EF
+:100C4000B9A7BCD08F03D61DDE74B00F9BD8BC955E
+:100C50007443E1D41563E0A3409DBF2E6746E27C58
+:100C600092D50E1EF7EFFEFAEE47607D7B50F582BF
+:100C7000FF52CFFD8E066547F30A3A9E3DF325EFFE
+:100C800046FABCE7C627D61E8238EB5915384E7A8D
+:100C90002FEEC9063FE3B567ECE87F1EF978CF4F2A
+:100CA000309F64509D03FD1DA17FBAC6DE9F7FE982
+:100CB00018D899C5058B8BA19D2485EC0079BA6E57
+:100CC000B8FD1D3817A161409D0DF66771DD2EFB43
+:100CD000D7804F75BFB24F07FF63D85303E3999D89
+:100CE0001CD01D541EB30A73BE9701ED7889574777
+:100CF000BEF611E0ABC84310B85EF8931DF3735213
+:100D0000480C5F4F0FE7A6603CB28EE72BCC979B59
+:100D1000C03F3EED9A9E8271C83A96A760E6D762C0
+:100D2000C0E9A9405FCED49571E6EFDCBABF6C088C
+:100D300040DCF7465B733C7E0738BF93FEBC7237DE
+:100D4000F437E9C77617C0EBA4047998790E1E8FA3
+:100D5000735F5D7C44E019CA57BB3526EE47F1FE50
+:100D6000D71C3171976B6DFF4EC8D99E0D718AC02B
+:100D7000FD504F198F8F94F3F84822BA4AC7895B08
+:100D80005039423E2D86B8C52DEC7A03BDF6D4E726
+:100D90004C35C42D88EE063B7B1AD6E1008F298B9B
+:100DA0003638601DEE1C8B5F2492DFC5F97BEE3C6C
+:100DB0001463EF7AAD7A36F8B93D37BE8D7ED2FF37
+:100DC0002EF91D91B3BA5FB5C1F959DB0A174F046B
+:100DD000FB1723C7CF00FDD72AC766FE75CCCF4BC4
+:100DE000215A549E851C8F964B09FD5121DF89C6DF
+:100DF00003CA813F2AE43C51B9D3F36F882BFFD15A
+:100E00007A86C6D4832F38187E0938D8FC524E749F
+:100E100017D8E17959EFA0DFFA0AB7C7237292D247
+:100E200077E7FDD4EE049FB7E37A79D74515CF591C
+:100E3000EF7A6ED5CF60DEE819AE749DC179DCEF34
+:100E40005A42E9BA11FC87421C9F1E25264EF827FC
+:100E500087F01F8C79BDFFE2FA63BA9FCDB39A9FEA
+:100E6000F2FB163E4FDC94F35C32CCE7B7F07D1317
+:100E7000333AD5B8F3328710A430E3750B40FFC284
+:100E80007DC672DAC83EF4760BAC03DEF482E93D2F
+:100E9000DF3F6DCE83FCBDC3B4CFC934DFDA2F8E04
+:100EA000EDF7FE12E6270A255EE079BEFFC2CF0D00
+:100EB0006CE7E706BE08FB59E9751FEC67A5CF5F35
+:100EC00082FDACF47E3FDFCF4AB2AFEE7C7871AEEC
+:100ED00093CAF9D036396488878A7DDE1D706E1218
+:100EE000E001B7CACE9B7351B405F9281C2F5A1CD8
+:100EF0003EBB4AC755FD13C17C946F9DED4379D825
+:100F0000CEE759338E11E73A9AE952A37C54204E2A
+:100F1000D53535D0DC54C8070CE466F6A45DDB6239
+:100F2000F0B4A631B968E57E5BF022093D2F45CBD0
+:100F30009FB848F66C6371B6A00CB803FEA2225CA1
+:100F40003F4010C7D5176F45FF0B7020E0323C675C
+:100F50002C17F6A5BE8478AE7E78CEBD0CB7E8A37C
+:100F600070DC08DF64E413C3E7C5AFE3F9CCF50335
+:100F7000F1E52D9AC7D4DC931FB3FFA07138D0C818
+:100F8000F1912BF67C04D52457E67AD28A251C975A
+:100F900005053CDEC3D73FC4786E5EDB87F91EBD16
+:100FA000C5360FC417CC38D18CF3D562B65F4CB9B7
+:100FB0009DED5BADBF48303F1E0526337A0E9BCAC0
+:100FC000F3793B5C012FC4311BBC26DCCBCF912ACB
+:100FD0002F30E27933DE57075413DE0FB2F9701366
+:100FE0001BCF93E709FA51CFEF64F181036E0F93A2
+:100FF0003F1242BFA7C26DB9759B07D6A9D83ECC98
+:10100000D26182F192D2010FEEABAE1824E1EB6710
+:10101000E079C36D789E90897F1510EA4D877A3C00
+:101020003D13219EA7902D708E4CA6BD45073D50C7
+:10103000DD6B71DF0DE4314C6072648FE5AF9A7C3B
+:101040007C33A840058FAB89DFA79864DF8B7210D3
+:10105000337E63AE87A95CEEC4FA969FD7EF1F6418
+:10106000796D663948B30F613CBE7258C3F39ECDAB
+:10107000E36E1ED74A2DF2FEE3B03FE362B2771370
+:101080008CB39D8DB3184755EE94611F0751D878E6
+:1010900089F52F73FCB5CCB43FCE4C97381761BDA2
+:1010A00066DA2FC6717C25A7AE2D69AFE17CDA4ADE
+:1010B0006E6746E66D7B1E5FC762E7991E181C7B54
+:1010C0001DEB808B9DEF475C8BC7B17B9B98FFCD61
+:1010D000CF11282B21C98073CA060993AF472D2150
+:1010E000474E6CF99061FFB87370593D9EC7E87226
+:1010F00055439CAD8CB0F54A7D80E0FAA54EF6CA0A
+:1011000081987E89751095C7C55489F54BF0C94CF7
+:10111000DF5DC3467FE82B41E3BE873B1F36EED33E
+:10112000F8D2DA2CC3FBDA557986F7359E9B0DF79A
+:101130005F741BCF09FA42C0784ED092E62A43F979
+:10114000454DC67382EEA8339E13D4A0DF69D25FEB
+:10115000DD20DF5D52DF0FA1FF16C7EFF3C68A0760
+:10116000978FB76E1C64E706A11F1867BF8B795F66
+:10117000DB079AC00B463DE809FAD9B93A039E9DB0
+:101180007E7A7F8878157470F9F941358495AB7152
+:10119000B3F596EA8CF8FEBCB083E6F50A71FE5F03
+:1011A000D9601FCA41B9E9BCBF52F7BCB8E779BEE4
+:1011B000A771BC20CEBF4870CEC5A8F9FB6AFBC79B
+:1011C000D799C6ED1F6FB794F41D76E624EEDFD5F0
+:1011D000F66B248F0BCE1DA4FCE8834793D97B8D3F
+:1011E000EADB96B4023CE722C35E29A54C8CC63BE1
+:1011F000893EEBAAF2CEBA791C9FE84BAEEADCD26C
+:101200000CBB87E9BFCEF0D116490FC13979E6751D
+:101210005395CFA79322ECBC0B1F3FEF22690BD154
+:101220000B298B829504D7F183B9F6D06609F2C6F3
+:10123000D97ED2D61B2D38FFB40EE93BE0772DDAEC
+:101240006E54703F638DAC6179359BCD4F3EC8B114
+:10125000877C89D7F466C3391DEE4D2ED013F52750
+:10126000EC7DA2FE744E569BE3F90BC5294CEE4F64
+:10127000294D8529281FBA9BAD4784F0DC33917F27
+:101280009B28EF96024717DA6D22F0011BBFEFC1D2
+:101290007A4A1CFDF5A730BFD8572885AC9047BACD
+:1012A0009484AC63F8959D6E4BDC78C64D29DC5F69
+:1012B000BE7C05CFB353C5F97A59EC7CBD6ED3B96A
+:1012C0009537F17E1E4AB1E3B53B670FDBA76A3A5B
+:1012D0001FBDDEB392C4E25971CE8F1A790FE34C71
+:1012E00027C7395F44AC3F6DE7FB97AB2E5A9AE2B4
+:1012F000D1FF618A82743CAF59E3F6EF5B9CDECE8E
+:10130000695E3C57B5F5490B9EA3EF73B74EC1FD1F
+:10131000DD295F232CDEC5E8AFE77AEA73873693D1
+:10132000145CA77E1A7E27442DB1412C8F9CBCB142
+:1013300005CF85DD0E797339D1FEA58875EB9D87C4
+:10134000EAF28AD9F9F310EFA91D6079E50B4B7623
+:10135000F13C927EDCAF68FE9D92D2BA800EF3F231
+:10136000C2C6F066C43F5E8F1F7FB7847837E2EF56
+:10137000A88CDA57A921EEEA1C6672DFF9736F3781
+:10138000FE0E885BE046BDB126337A3E58F9D0A107
+:101390002DB004633E1FCC7CBE90F0CB5413AE1432
+:1013A000FE5803091D56A4D171E644FED863291CDA
+:1013B0008FDC48FD313AFE77D9583EAD6FBD5402FF
+:1013C0004E63D27A6932D8AF1FF1717AB33C80E7AD
+:1013D000B4B426D8677769A45C18F73375E604DCE3
+:1013E000DE31CADF9422B37D7997D9F91EAA9DE533
+:1013F000718D5C79FE8B90EB594E1B962F7132BD2F
+:10140000A8B8F242D658F367A92F40A03FD4BEC473
+:10141000CD0F7B3185ED4754C3EC9C0AB5EDBDEA99
+:1014200078FA2CF4709DDAB40FECC716696D2809B0
+:10143000EDC0D59F5F798BFCD9EDCD654D3F9C42CA
+:10144000FBFF9AF5471ED08FCD01E3EF4B89EB6B85
+:101450005AC08EFC771F7280BF793E39701CE886B7
+:101460007837EC23EC8CBC68477B6AE2BBB99EB54D
+:101470004EC677D5C3DE937FD33D8B63E224754E92
+:1014800089CF1FFA5B40D74CABFE36B4F34865FCFE
+:1014900075C84CA5F21D785FA935FD01AE9D91DDA3
+:1014A000183F4E4ED6FF077C5FAEE8FF0ECFFFC958
+:1014B000AAF7333B5DED3A5310DDD790689C61E1AC
+:1014C000E24C412CBF3E1B9F33EC4D436C9CF5809E
+:1014D000768DE3ECA4D72FC1DC429FF797C75F6FEF
+:1014E000FF119727AA6798AF20F6BDF8DC448F3725
+:1014F0007F89F274FC6527E6B5079B20AFF3E414FF
+:101500000BD91D63E7C47905AD11E6175E7848DA9B
+:10151000CDFC4282F73FFF7ACE6E58DF5D3A8DEB0D
+:1015200031DF7771F743C6FDD0A2DD39A97CFCC756
+:10153000D1CF365E6E732AD3CF1FA4B278D855EBC5
+:101540006706AB47E8A9AAB0EB5D2E265FEFA7B20E
+:10155000AB2D4D12F9EBD3810F540FFB53AE6D7CC5
+:101560009E5A92F7D9E543E883EA35E6E76DE3FA58
+:1015700022EC15A5B3D4C9EC4520F9DAE8CC2CFD52
+:101580001CE458EC3F901D92211EBEC0C9E3955C3F
+:101590007F4F29FA42A093EAEF1D285F89F57789EA
+:1015A00093E9EF179C46FD5DE664FAFB4527D3DF20
+:1015B00066E767D0DF0FB8FEF8791C9F1C37DA1D8D
+:1015C0008A8BEF81FAEB1589EFE7267F9462FC8F17
+:1015D000FA8100D1D964F95C2C6EA0F855C7FD1BC7
+:1015E0006F1AEB7B8B8F17B563F743BD6F41FBB46D
+:1015F0003F9BFF3BE31FF0F1C5387A29F828DB5AFF
+:10160000DCB0FF35D13CB7C0C9E619BF8DEDAF20C6
+:10161000C768FB4586FE7C17F837D29F20F5ECE2C1
+:10162000F72718B73F7DC6FA62FAF308D42BFA53AE
+:1016300071E5F898FAE813FAE80ACB306FFB94F8F2
+:10164000F342AF93CDDB1F3AF427A17EB37C89EB45
+:101650003F727D48B40FE69452F98FC0EF5285D99E
+:1016600041A285FBE598FE9516B4887E072CB171E2
+:10167000B681F876F217CE11FBF00B94BF9D6CDFAC
+:101680000E95EB5FC2FD5D135CCB709FD747CC6EB0
+:10169000BEF5C97A6B1A6DA739E389EFC1F51D67ED
+:1016A0001AD2DB3294EB8461E82F67FB1F5B27B310
+:1016B00073D35A25E3F969EFF0F66EE2F6E91AF40E
+:1016C000FBAD5CF9D3EBC767B50B943F2784FD4CAA
+:1016D000CABB36BB34FB73687FE93482F8B87597B0
+:1016E0008AE76C09BDB90BC6969D77A0431EC55706
+:1016F000E9BD85DE0F81D30DF62A9B10F74C2C1720
+:1017000054F13C04FD3F983DD2CFC095DAA10FB80B
+:101710001D1A802BB543673F8B1D3AEC6476A88D6C
+:10172000CA501FC8A11262F9BDDC9FAAE77D2D2D0A
+:10173000386C88DB097FAA7360B71684BCC102B617
+:101740001F3551BB61F037207125C1EF5689ABFFC2
+:10175000C91576700236535C077154F13B7A9DD0FF
+:10176000BE06ED59F0777E5E2332AEC39BEB6B9DD8
+:10177000CAE7FD142ECF9357A27F65FE1DBD2A77C1
+:1017800068FB4C5A8FEFD8DD6C9FD5E5BBC9B22200
+:10179000C0270102E76DAAF40AF99B82EE69A9D776
+:1017A00093D8DF235689A4CC2B8CDA91AA08095749
+:1017B0001423BEC1FD5C508F87D7132882F93E4D9C
+:1017C00081F5BED712FC1ED39372607A6A4CFD7EFF
+:1017D00062C42B74FCAF4F9D8DE37F0394A3E35F42
+:1017E00090CAE6A11BE1F95927B37F4FCA4D85F096
+:1017F0003C90C196A069F9225E7E46EAE720279BCD
+:1018000009FBFD5D90DFD8F5EADDDC3E744C0C94FD
+:10181000433BD53F5FD433857EB2BABD05CF39AEE9
+:10182000B82EF2D129C8BFCD52713DB0F551E33C7D
+:10183000F21CFFFE40AA88DF5D1B8EA0F6AF3E15AE
+:10184000E963F62FE866BF33DA3239F731061FA9AC
+:101850008399193DBFB6DAB508CFE7FAC60B39331D
+:10186000E1BC2B95DBE779EE6E75058C6BA43F6EC2
+:10187000BEE95746EC20B5DE86792AFE392FF7A758
+:10188000325C4BF5F8AB7CFCEE023A5F9CA8075249
+:1018900067FFD7D9476187020AB337D46F0A82DF5F
+:1018A000B4ECD2DA23304D3593276A607D83CAE5E4
+:1018B000DF019D5FB6EF3DC27E7A303805DAA5F2D2
+:1018C000F8702AB3477F9FCAECD17752993DFA87C7
+:1018D000CF2267F7A69231F1A7C0E1027F533BBF49
+:1018E0002D95E14F8FF3F3993776F2FA02CE6B9C88
+:1018F00037BEF439B44FF1C6CF505F391F12E1DB68
+:101900005F70B9FA65AA88FBE9BF04FE2FB4EBFF4C
+:101910009C1A8B370A8FFD11F2E4A278A35BE6785C
+:1019200043898D67FB28FEE27975F758E644F54454
+:101930008DC4C721F353477048078EF7768643E678
+:101940008FD0ED1D08811E4EE1FAFE3B668F5BD401
+:10195000FE7BF01CDC7446B794CEC6F128EFC7BB03
+:10196000524ADCF8E6B1687BC7B0BDF5AC3DD97131
+:101970002BFBDD0F6157AC12B623E2C3F3D3D9774B
+:10198000A29D79FC2A70AAB99DDF46DBF92DB6F33A
+:1019900090D807ACBF05F7BE285FC3B17C05FB62DA
+:1019A0009913C34F8EEB12E1B818FEBD8776A08D58
+:1019B000B533C2BF407C3BBBCC250B3919481D4316
+:1019C0003ECE71F9381F958FF35C3E3E4C457CC28C
+:1019D000C6E1AE09C6FDE5C35CAF1EE17C12E3655E
+:1019E000A6BF95BF1FE187E7D873B1B8D65790B6A9
+:1019F000AC19E2966DB2D7E2192D6FF45F3EE0DDCF
+:101A0000FF05CC52B1EF0080000000001F8B0800E2
+:101A100000000000000BE57D0B6014D5B9F0999D26
+:101A2000D9D94DB29B4CDE1B48C226800D1A7009D5
+:101A30002106083A79F20A10111014617985F04AEA
+:101A40002262EBF36731213CD5E8556B5BB40B8226
+:101A5000628B3660AA8801372088EFD02A68F5B6F5
+:101A600041ACA0225950EBDADAF29FEF3B67B23378
+:101A70009B5DC0DAF67AFF3FDEDEC339739EDFFB83
+:101A8000FBCE37B34584FDC927BD923B9790B17E0D
+:101A9000A27A6D849C83BFAB82A555110849266448
+:101AA000995C655586D20165F5CEAA8184B4977498
+:101AB0002EA90AD3FFB604DA9FF69B9EBEA92CD9A5
+:101AC00049FB7B687B0A21C31DF4DF2221D7D5B4F3
+:101AD0008B6EDDB8E99F7E3C4F0D33CF4F124CB873
+:101AE0006EC30CD721673E9DC661726D253DFB35E7
+:101AF000C7CBB8DEA86CAF1447FBBD7986289B69BD
+:101B0000BFEB260BAA979EAB829FCB96C0CE91A52A
+:101B100048D85FE5FB1C2577CE0B778E7CFE7CB426
+:101B200093A82D749ED10A517786E95708FB8479D2
+:101B3000A2C3CF338DCF3386B079429FCFE0FB1A5B
+:101B400055127EFC083EFF34C78EF20402FBD964B6
+:101B500006F8E599D5610A1DB736021E52A4929186
+:101B600080AF280A3A731E2133E958139D6016E0AE
+:101B70009C960F8AEE5278EEA6E070E40125787A02
+:101B8000015E4B6C6A19B44747ABE530FF4849AD7D
+:101B900080F297667514E29FF80829206402A79FD7
+:101BA00009569B4F8CA5FF28349FEAB4B2B673D96F
+:101BB000F0FF67281F5F4688407CC2B9CBA0EE15B6
+:101BC00061FEE1CE43EF0AB4FF706DDC4929645C2D
+:101BD000BAF2710CAF8BB82F84CF6EF34F9D365392
+:101BE000CF736AE56E9BDB0A70381DED9E09FB6CB6
+:101BF000706CB63929BC5F75B7585DB4FD641C4183
+:101C00003876C5A86E7CBE9BD4B4D0763146A86F1A
+:101C1000D1C16FBEC2E05DAD30BCBD25A9D570FE9F
+:101C2000095675018C9B9C49F144E79D95D8B95C98
+:101C30000FF77A8EA7859C6E67CAAC5FE83EABF95A
+:101C4000F32249F0C4C09E6C873E12813F48F75F83
+:101C50003F13AD8F857F51FE293AA94C9D96447163
+:101C6000B6467499685DCE11C2F2E99D7CBF944F6F
+:101C7000EF84FD1227E5533BA50F393C7D7CC5FB66
+:101C80009747A0CB3C7E9E32781E66FCA59CAECBCF
+:101C900092DA4542C717717E0BED373741C47E0D8E
+:101CA0002E323ADC3C0F04E5CB03485F0ADB779E1B
+:101CB000B9EA21A8CF500E97C7D3E6E2BB93A6920C
+:101CC0002480878958B2104E5642E1247138D16D74
+:101CD00012A82FB3B2BA14BD84C4D132D3E15D3F90
+:101CE00008E0D768763969FDC3931F8A84D2D9D6B4
+:101CF00007CE0A84CA8BDD7E4212B3601E19668449
+:101D00003FD339A1E77CF49953D2D6A3A0B9F224EA
+:101D1000512D947EAF2CF44F22B186F1E41C9DCF5F
+:101D2000E6EFF008803F2BF1C45C8E64FC76BF14B4
+:101D30009C15E74BA5EBC279E42F8917CEA33ADCBB
+:101D400095641021F1FECE5FD461BBCD350ACF453D
+:101D50006CC06FC1732E43FED3F625DB3A1FBB97D1
+:101D6000F66FFB2ADA75179CDB5FF109DB0FF1D800
+:101D700081AFC54A17C877422CB83F13FD0FF86CE6
+:101D80006480EE3787EF1716C9D7ED9FF43CCF83F9
+:101D900062D521C0C72C2B5163F3503EBC02F5BE67
+:101DA00066DA81C2B14911BC1EDAAFE981796BB242
+:101DB000405E6F905CFD09D039D925503A1F41D75C
+:101DC000BD85CA1DB990D8145A971DECFC4D7727D4
+:101DD0006D8A11E0B94465212DFDBE6F040A875854
+:101DE0004775A542CF21F3F102051C8C179C0A9977
+:101DF000910774DB2112940F0E8487C63FEA8F8807
+:101E0000F0B115550D01FA2A9388C74AFB0B0E361F
+:101E1000EF95C42F92BE8007AA086859425C58DE2D
+:101E20002BBA3F06BEB1CA14AF74FF5693D5BB524E
+:101E300000FC55BD3E1AE15EA67C9C13946791E4BC
+:101E40001040EE630DAEE2F7977BE5CBC3F3D5DF31
+:101E5000827CF3372697995E9E9CCDE4CE017BE78A
+:101E60000C3DDFAF5298DC59C5C71189F1D9325901
+:101E700035C59F87CFD7F2719782F2017D4CC2F3AF
+:101E8000714B3C930793EFF236F5A2F09B9020B88C
+:101E9000400F976F9F2DF57606FBA5727DA7A4A82E
+:101EA000F1F130DF6ED7496F12681F19F57BD37BD4
+:101EB000641ACC3F9BCBCF009FF72FF16C1FE9BC7E
+:101EC0007E4CB04F0B0797CCF86EB864C2B9889BB4
+:101ED000C1458C19ECF7D175486FBE8E59C075DAC3
+:101EE000B3997CCCE6FBD2D6E9C3E51F95FB97C03E
+:101EF0003E27677AD3A1DFAB66B6BFD0750706D79A
+:101F00001D88EB2E61EB8E05390FFCEF3CF412C8F7
+:101F1000F9224EA763FD6E02760FF0B0A92028EFDC
+:101F200065A74FACA7ED4511E4FCF0E03AC3719D05
+:101F30007A86C73D29EA08D827B50B8AA0BD3D5B44
+:101F40004179F9662F13D94CF972765AF63D20364D
+:101F5000B57976F273B6673539E6507CC97EE2B260
+:101F6000209DD7A0DC2BE2F2A561B79BC0734F2F59
+:101F70002A3375E365FF1C2BB1E151FE714EEB4F27
+:101F8000F9A8C99F1DE70E8317AD5CBF828922E2C5
+:101F90005C8AE396F171A1FD6C0FEE8B81F93740FD
+:101FA000FF1F113291EB1B7A60DCDF58CE3B0DFE38
+:101FB000CD319DB4DFEE9CB986FDE073CA474D3943
+:101FC0008FC580BDD49641F500C8A9574494934D60
+:101FD0007686C7A6B46AA2B7474B1D3EF16398E761
+:101FE000DBB9642AC55F91C34D2EA1F05DC7F751DF
+:101FF000E4AAF60849D8FE6C149D6779FC250847C9
+:1020000039C74D2A72012E5E524DC7CB8A4F74D10B
+:102010007AA99FF8AECA87FE54CE0B6C3EA75D3FEF
+:102020000F698179E45C460FB2BF8500FC769F3C66
+:102030003F1C63724C06F9ADF125B5EB56001D94BB
+:10204000295797C5D3F9176DCFCA13E9FC158E76BA
+:10205000794E2ECA6D0FD0C7CE647565FCFFA03DCA
+:10206000378D78CD80F751994C0F4CA815BC9B2922
+:102070007C9A42EC849FC6333E2C0CCABB9FE1BEC7
+:102080000B353B41FD39D4CF63073F0AF0388F1D34
+:10209000BC059E87B183B7423B85D7E3F1CC0E7E6A
+:1020A00002D6A176F0B6EF03B7090A93A3D40EDDEA
+:1020B00001F3C6837103F6D11F983D1ABAFFDBF80E
+:1020C000F9D7D0B376005D4A5E89D139E3D3E19C7C
+:1020D0004FC79EA4FC92DB93FEDB28FD7B28FD9D71
+:1020E000A576939815999E7C17C997C50F32BE6F38
+:1020F00070EC43BE7B91F3451B5FBF2D47AC047C66
+:10210000BE4A4445147ACED794E176805C0FE53F11
+:10211000F55B233D973ABC1BF2806F0ECD75C1B6BF
+:1021200042F951A665F5C0E0BE8F031F0ED5C92741
+:102130002248C88F17E04398C73D10EC8C7849CDF2
+:10214000053E62EB7A0E89A82722F111A59B5380E8
+:10215000BF6EB800B075FBA774F3393CA77C76FA64
+:10216000FBD0CB1A4E1FD40FF91AE6EB1FCFE8674E
+:102170007604FFE21FF1DD7EC03FA03F99C1F4501D
+:1021800066BC938D234932E81755CCC804F942E761
+:102190003525D0F6B7B87F1469DEA8846EFE8B4A69
+:1021A00080F3DCC2E63D0446F6D09EF38E4AA0F6EC
+:1021B000479879D2B81CBF2E82BF90C5FD1292DB22
+:1021C0006D9FA4C07A599C6F7627AB8E041DDF14D7
+:1021D00071BBE565C1A89773BAFD7DC63F4909ACDF
+:1021E0003F99D73D6F56820E9E9A1D309BCB076D4F
+:1021F0009EFE9CFF9C090A1B5FC3C6C7439D8EAB16
+:10220000E0FE13854B2ECC47ACECF985FCA27B1489
+:1022100019C7CFE5FB12E2154DBF215C4747F2BB62
+:1022200082727038E2C1C5FA5FAA100DEF23711FE8
+:10223000956C1F850AC37B68FC20127E34F8276BDF
+:10224000E7CD61F3134F37DC46EBE92512DCDE8A7C
+:1022500063F6C5280E27D2C8E7099107774B1D56AC
+:1022600025CC39AF8D771AF8D9EE32CA8748F19468
+:10227000BC207C66221CF2D9BE23C5570AF87947D8
+:1022800070FB968E9B8F70B5B1FDDEA374B7D7E05F
+:102290007CE96CBEFA20BC1763BB83F58FE4F7D7EB
+:1022A000F37D5527748F5B86EB24B171A1F104ADEA
+:1022B0005CC2F7B73038EE565CAF1F1B971CDCC70B
+:1022C0001DD83E9AB57FDFF85B32DFEF4F82EBAE71
+:1022D000C1FDAAECFC81B86EB8ACC7F622B66E247C
+:1022E000F9118863E768E270BE12FC623A477C80AD
+:1022F000E44849E03545BB46D12EA901D507FAA3EC
+:10230000E44BD90972BA5CB479042A8F25A715FD6C
+:10231000E42889A8E0D7B67FF56347672ED67DA06D
+:10232000D75747155BC1EF5C9325B9401F16DF27D0
+:1023300031FFFA9409E57D85B804E7D9A76876EE00
+:102340008D063FDAA9382BA3601F56913899FF5F9D
+:10235000399E3EBF8ACBEB7DD64413CC372283C552
+:102360000BAE7256A3BF4EBE657EB44AFF63F25BEE
+:1023700045BD2CF371527A3D11B034FADB32D9707D
+:10238000461C847A01EDA8117EA3FF2D3B2B4EC085
+:10239000FC32D18DA3EB3E9F604F427BAA1FE97FA9
+:1023A0008EF28F25472016EA5F944BEE3D808731F1
+:1023B000CE6AA5849EC792EEB6821CEE67F6F586BD
+:1023C000784263BAECF2001B3E5066CD027FAB99B7
+:1023D000FAE7080735E1EA81413C598A540274481A
+:1023E0007182FCD55DDA589990C8F0F8498205CB26
+:1023F000125ED79E87E27D486234E37F62F57C946B
+:102400000372422071940E9792CE4CA0C7E43426FA
+:102410009F6A4D9D2950EF22FE94245A36344BA3D7
+:10242000C3F93F1B79FC6CAD29BCBDF44BF3980F8D
+:10243000000E12C40D2EC7B880DBD237183FD0EC87
+:10244000552D8E10C96EBD57ACFA18E61114DF3742
+:10245000D0BFA7FDEBC17D48E94C4E6BA5B68F9967
+:10246000898C7F1C895684CFDE3B4AC91C27E2E950
+:102470002CF029C5D3A12B002A59F314C0D32B5912
+:102480000FF583B89435EB8124E0CFD184D9A7E54B
+:10249000748C83960FD9DCDF24E8E4E1987EB3D115
+:1024A0006E2ACAAC477B6A7504BFF4C77C1F12A7AB
+:1024B00093129BDB943814E25FCBAC305E52AAA23D
+:1024C000A1DC1B988425B57BA544DA7F753AAB5F08
+:1024D000080FEF72F91069FFA3402F40BC26BDFB27
+:1024E0001C09303F7DEE91F382E7D0ED2F25DCFE15
+:1024F000CC894C1F69FB92FA71BACC31D2DD784E8F
+:102500008F39899ABF78D17477E462E82EF4BC637E
+:10251000B2968F1E4082FBD7CEAB9D9F9ED705E71C
+:102520002D97D8F9B72A6E15A6A0701E0CED3DCEDA
+:10253000650DAFF733124DDFF53C0F25F4BDF8F311
+:102540007C8779A7267E07381D18A93A409E342635
+:1025500053FAA4786A1458A9F58FE6786AE174FAF8
+:102560005DE444FFEF70BE6287F012E8C3ABDCC7E6
+:102570004A6199B2A2C1A076801FE701BD95E4DE51
+:1025800027CDA1F5A63BE6A2FC3C30B21EF7BDDA92
+:102590006EDCAF5626707C1465AAC87F8D9CFFCA7E
+:1025A00009F323B57E6DFC5CA1FC113A5F285F3F07
+:1025B00064536F06FA484864FA32E8FF75887AFF78
+:1025C000AF84EBAF91D69B0CF18F91DCFF5BFD6587
+:1025D000B6CD430F7A96EAB57F89FFF70D7D027E6F
+:1025E000527A8955EFFF355A4BB17D75863AFAF22A
+:1025F00024D0C7A2EB2E82F0437FD02388CAD630E6
+:10260000FEE0EA0CD977157D6E51C8E3B0BF52AA3F
+:102610002F21FE62515472C9C09E7EE13E6B29811A
+:10262000B8C959853C0BFED885CEF378A2D12F943A
+:10263000C02FE4F3A35FA8D4934E8CF79412B06B31
+:10264000A0DD3910E48E4ADC76D023D42FD4C9A77C
+:10265000B3D69B90DF43D7A372EB69A0A34685F165
+:1026600071A83F28723ED7E46C283D943B18DD44A6
+:10267000D1AD9B99DC782E31B9275D7C77F934AFE9
+:102680000C5C806BC9CA03E0AA4D09F825707996E5
+:10269000273AB15F956D47233CD7E60FC50F3DB98B
+:1026A0000AF174B06758FC86DA6BD48E32537B6DB6
+:1026B0009D105C7F358777247CAC067D1D868FDE80
+:1026C000EE966BA171A29B8CF72F8A872415B0B868
+:1026D0003E09037F91DB496B28BFC0FDCD6AB3CBB8
+:1026E000A1009D6614BDEB067F3E43C6FB0822D5C4
+:1026F0003BAEB6F73CE71A889F85D9DF17890908F2
+:10270000576BBAC9609F1172A7C17E8C746EC2F7F5
+:1027100065E6E712009E397A78869CBB4CC17383CC
+:10272000590FF3C69A5CC447F9223693B85060C576
+:102730009A300EABF1B9C2F95C930736858DAB4C7C
+:10274000EACBEEF7449B5FA4E75F9F44ED693A4F05
+:1027500083BA0FF5AA363E8E9FDF3692C51B6D7683
+:102760009FA28481C3BD9CCF239DB35995E2CBE842
+:10277000FEEE5598FD2D8D345579311EC5E2B50A12
+:10278000879D589C6F05BB7D54523C8B7BA93B15A4
+:102790007DDC4AE4FB89B1D3FD9C474EAE0DD94F99
+:1027A000544E6719EC5FCA529578DDFE4B9234BDEA
+:1027B000D281FC1D69BEBBB99C8FEAE7C2F8ADD5DA
+:1027C000E6F2C1BD56945A5D0062313AC745E6EA69
+:1027D000DAA3D58221161D1D3667C861EF236EE787
+:1027E000EBDB25B50AC6D91589C03D999DDBCB9198
+:1027F000E68DB48F0BAD372D89E9D31EEB39C3DBE2
+:10280000157D9218FF49237756819C260325D23FD8
+:102810008C9E484862F22556EE7482BF4EE9D11D67
+:102820006E3E9224737EFE37F187667717B71ECA15
+:10283000A6FB6DB0492E01E457E1C90EA70E3E5428
+:10284000AFCF4AD2C97DD1E646F9263AD9BDFB6859
+:102850000BF3B70F8C34DE93CDE7F8FA80C33192D7
+:102860005C28E2F0F8779DF3BBE2AF2489C97D0DC7
+:102870002ECD001702FC757F6343187949E1D39090
+:1028800094FCDDE1B396C3E5E90BC067D07F183E49
+:1028900017E2EB209F79C9F130706CB0CB69730DF2
+:1028A000FCDF8C7648B87ED5BAF346E2438D3E20F5
+:1028B0007703E1D0AC1AE2027292A783F995371B35
+:1028C000F59CB8C4C5E533F996C22D9EF78FB711B4
+:1028D0005F4C6C707EB9CC184F684BE27181281246
+:1028E00005F039EB9A24409E82C53463B0920D4BBB
+:1028F000340BA02752609E4184DCC7E567A81E4CBC
+:1029000056999FDC9BD40B4CAFA4E3FE92F83E4259
+:10291000F5601AF56B201E0347047FBA37AD5BC123
+:1029200006212ADE830B1E13FACB0EE21560FE741D
+:10293000D289651F4845A0F367910EA11FC5DF7DB1
+:10294000E5D583417EBF13728E0BD9A35AA9D91F37
+:102950006BFF43F0FEF47F2FBC5796EAE02D267FF5
+:102960003F78CFE77227349E5704F1BC2C88E7F9F3
+:10297000F6039FCADF32FBA3FDEF32C6F71AB35846
+:102980003CAF5CAC7C18EF419D32BA1F524EE77AE7
+:10299000C873D2EC4ED4797D83713FEB99FB2588C7
+:1029A000A310E924C209EF869C28CF329351DE3070
+:1029B0003BE22ABE7F396B9E15EEBD83FE934F64CA
+:1029C000F606B397644E07458E12F45F1ABF3DBFFB
+:1029D000DD71B17ED25EE900DE5F6BFE51837F0E5A
+:1029E000FA4BA1E37C92EF7D38BFCF2F3B21DFA4D0
+:1029F0008DDF8BB59D396888D386FA419A5D751550
+:102A0000DF7FA9DF7DE872B8DF52E61016DF647061
+:102A100090F93A8D8EB3780FFEE2B726F4B7CE72F6
+:102A20007FAB08FC2C3BF377AAED3DCF392139BCB5
+:102A3000FF04E320AFAE54F18960CF69FE13B43BCD
+:102A4000ED3DFDA7D116FF6BB0BF09AF89981712F6
+:102A500009BEA17E53A8FE999ECCF4CE4DC9DCAE32
+:102A60000B81A716EF0BBD976ED2F84FF2087AFED6
+:102A70000F5D5FDE3706F74F145D3C363B184F1491
+:102A8000540FB9252F183F0C13375C0A74A8C50DD5
+:102A9000353DA6D1B185F6B5E23D73F878625BD6D7
+:102AA000C1BECC2F7C2911F8B35C6171236D7FD43A
+:102AB0002FBC2D59878F223FD3DB96FF53DFB9926E
+:102AC000C297241017F30FEA9D565AAF5048E23AC6
+:102AD000E4331BE669152509C877922F0AEB15A781
+:102AE0005CDE285AB7EC7B45149360BD39244A0854
+:102AF000D28F96D7D1E8FF703DE0EFEC29C9753E43
+:102B0000BFBB028268063F293A884F946F0986FA54
+:102B10004392FBA164B4177B05C789900F966DC8DB
+:102B20003F7B46527F0A709D6A551FC6FE3F3CBCE4
+:102B30006F4FC678F1C17F0AEFC175983E009B8D3B
+:102B4000A4E9D6B3D1C661B08E93DD176A71E9E509
+:102B500004EF63B601CE20CEF239F1429CE505F3D5
+:102B6000CB22E8A3263ECF70D2EC94FBB2FD42BF4D
+:102B700027B73A36015DFC2E390BD77FC1E6DE3030
+:102B800098B61FDA220D86B84D83F3192BE4CFEEE9
+:102B9000DBDA94DEA9E3BF434FBAFB84F30FB592AF
+:102BA000FEC5990AF15CB1AC54459303DB45A8F727
+:102BB000B0CFB6B42AB0CE935BADD3C2C535C41482
+:102BC000C6EFC3B730BB76748EC905E2AD8878A472
+:102BD00004B88F7111978F36C40CDCD9813670968A
+:102BE00088F71AB4BE3F96D66386AAE81F0C18B8B9
+:102BF00013C70FF8BCC4C5F2283DB63C5A5F9F53BB
+:102C000032741DADA747BB3F06FAA27AA659427D92
+:102C1000DA1203790031032725AFA3B51881548553
+:102C2000B373FF9ACCECEF27CD1A5C25CC83DCB7CD
+:102C30005546FE3A9426E2FD1385DB12A8FF252DAA
+:102C400086504A2465AAA70CE0584E5A1AC09F2AFB
+:102C5000735EFD522CF927E097BF5301FE5F1FC141
+:102C60000EFF1DDF1F0A114A3F07B7345E47C2E45B
+:102C7000516B74F85C8C2AA5D0FE6BF9BD2E714C9B
+:102C800042FA898CEFBB98BFD9E26B88A6701CBE54
+:102C9000BDB9977EFE2310744DEE896FC87F2697CD
+:102CA00043FEAD1BF3691B4E9A107EAFE60A5E81B0
+:102CB000C2E7608E486D36BAAB7E566F7F5ADFC072
+:102CC000E9B872FBE1C65EC0C22949B8EEAB398FE4
+:102CD00059597EEBC5C7AF87503E5804F953141FAE
+:102CE000A39468AF93E26B314C41EB2315ABD7470C
+:102CF000D76BB77794C6D1255E48165C9B815E7210
+:102D00008802F2035D1013439442EB2032909E92AE
+:102D100008E673AD2FC8DD0C71B175E9CE16C83762
+:102D2000DC33D08AF966A1F9C47B84FA97E2212EBC
+:102D3000152FA0BC3E98F33BBCA73B986E2140AF3B
+:102D400098F04B9F3726303E8DC937DA9FE52959D9
+:102D5000DCCF261E4B41705F31FDAC6A1425A49771
+:102D6000E3D9F843FD042FD0DB2127970FF4BC5B98
+:102D7000C120929AA5A90323E3F595FEA39C9A5D31
+:102D80002C68E734F53CC70B82774D369C63003DD9
+:102D900007ADDB73045CDFAEACBB916059B800EEED
+:102DA0003143F7BF2285F9473225BB1C906F2D6B4D
+:102DB000C6E8F363E4C21B27D862318F09EDCAD499
+:102DC0001C01CF33E624BBCFED919FAD10B76CC093
+:102DD0000FB53A5282F3C57CF9EC4F20FF775CA126
+:102DE000E08B82FDF0FC66FA7FEDA05FE47EB359D4
+:102DF000FE75CE263CCFD842B30BEE72C6DABCCD00
+:102E000025B4FECA2712C6B3C7F51B85F9D5A1EBB9
+:102E1000AF53886F3485EF2BB912C23BEA92C7706B
+:102E20009E37734D286FC6413E36E42FEBF3AA510F
+:102E30001F1AF3B9C7891FA8C5D0EC62FC4A244FFA
+:102E40002F90EF131C46F8D94F1AEF8B2BF32D86DA
+:102E5000FAB85C39440F7B10DE2F6730BA7879807E
+:102E6000E0DD9C15A4B3B12713BC4067F02716180A
+:102E7000E06838678C5F56017E87063CF15F704FD3
+:102E800012E35C7D23DE8373F86B7412C3F16E4F23
+:102E90007FEE27A0A734F887D2C1C5E3FFEAAA6274
+:102EA000C07FBE767F1F82FF107C630C523B47DFE2
+:102EB0009E78C7F5B37AE25BA3831EE7BEBB754D70
+:102EC00036C5EBAB76FA00F0BC49F6DE2504F174AA
+:102ED00041BCF62B46BA59A734DB40EE475D72DCA5
+:102EE00006FE814617446CCBD7DBFBFF2A7C976C30
+:102EF000109833E912BC10D77B0B1E0D0BAEF352AA
+:102F00004A77BECC4B20F74915CBE36850F3D87B0A
+:102F100057F94C9F86CA873FA4B0F73ADACD2FA75E
+:102F20009F2F4FB5D2E626703FD600F976F47CF29B
+:102F300086D9F046039127CF46794936082C0FA150
+:102F4000E8F728DFE739BCAB8430EBA12583FB74BD
+:102F500032BBBF2811FB93695A5E52D507B8FFC92F
+:102F6000AC7EB1FB7AE35FB4AFA3945688CEFF9CEE
+:102F7000C8E3F29ADD3DC1C6F20E271489888F3767
+:102F8000B7085ECC8FA4FD3C944E1671B29DC8ED7F
+:102F9000C0B385CF340D76823DA81AEC4EA1A81D92
+:102FA000EDBEB842A33F18AF461BF09F383AC15060
+:102FB0004FAEEA65E89F3A2DDB1857705F6A78DEFE
+:102FC000BB26CF50CFA81F6EE8DFE79612433DCB5C
+:102FD00033D6D0BFEF9A49867AFFE6EB0CFD7FF43B
+:102FE000F01CC3F301DE4586E7976D5B66A80F6CA6
+:102FF000B9CDD0FFF25D77199E0FF6AD333C1F724D
+:10300000E87E437D68C7CF0DFDAF7877B3E1F9B0B7
+:10301000CE5F199E8F38B9D3501FE9DF6DE87F5519
+:10302000609FA15E4C5E33F42FB5FEDE502F57DE5D
+:1030300037F41FE5386E783EC6F999E1B94607E3E3
+:1030400072BE30B48F77FD2DE43D9D2A16E780785F
+:10305000405F78D48C65346961F73AA403CB850569
+:10306000EEE254E08F473D4D9090D4E0F1FF11AE79
+:10307000A6DF2CEC1BC7EC2795E8E5A7969F4AFD39
+:10308000164F142585D800A5DB2194EE0202964A3E
+:10309000804AD64488F74461991048C4F6C4403C3D
+:1030A000964981DED89E1C48C33225D017CBD44028
+:1030B00016968EC06558A6050660D92B3004C7F554
+:1030C0000E0CC6323D3002DB3302C3B0CC0C94622E
+:1030D0007B9F403196CEC0382CB30263B0CC0E5CDF
+:1030E00083FDFA06AEC6B25FE07A6CEF1F988EE5FC
+:1030F0002581B958FE28301BCB9CC0622C070416D2
+:10310000627969E0261C7759E0462C7303B763FBAC
+:10311000C0C0AD580E0A34607979602596AEC07A89
+:10312000EC3738B016CBBCC07F61FB90C07D58E651
+:10313000077E81ED43033FC3B220F0189657043653
+:10314000615918F83596C3024F62393CF00C8E1B5A
+:1031500011D8816551E0056C1F19781ECB2B03FB3C
+:10316000B1FDAA403B966AE0356C2F0EBC826549E2
+:10317000E0F7D85E1A388C6559E07D6C2F0FBC875C
+:103180006545E03896A302C7B01C1DF80CCB318111
+:103190004FB01C1BF802C78D0B9CC1B232F0376CCC
+:1031A0001F1FF806CB6E7917315FD96D427F96FBF2
+:1031B000A991FD050FCA49337F2F0E72AB31FFBFB6
+:1031C0005EF062BC30A9F325A89B0B2D182FBC81A3
+:1031D000F8F13D81FF269D7690A7EDC34EA443BC38
+:1031E000E9CD645F863EDFC1CCE300E5E22909FC5E
+:1031F000D50949FB92419FDE409B21CF88A8E7304B
+:103200000F7202CF83BC41A20E16DDEA61986118ED
+:10321000F6F359687D462551F368FFA661168CEBDD
+:1032200037E5513F88967767B17CD91DA94C5FFE81
+:103230008A97BB52991DEB2960F7FB336EECCFF8F0
+:10324000A92CF1027E1383C3DF07F23C5B9B3F1383
+:10325000F3632F72DC67297C1CEFDF9C5AD5960A3A
+:10326000FB282139F5B6603FDAFE6284F67DE1DAAB
+:10327000F799183E3C4744EE2754C54D3A8F9FF0CE
+:10328000E68A8E4B5FEA1FACBF15C10F256425EEA1
+:103290003776DF2795D7527D38B1507451C9413EFA
+:1032A00058B16BE447FDD9BA909FE92911317E31BD
+:1032B000A3E8F081445A9FB13C1EF3EEBBF7556280
+:1032C000C6E7131C472E7D891EFD86FAE7477E64FC
+:1032D000888BBAD1EEBA89D32851CD7FEDD49E2305
+:1032E000BDB2B8EF4DB0B813E49F19E7ED50CDDE95
+:1032F000F3E5C710D5425403DD3378AD87FD83EF86
+:103300004FAC26583796F7A17045BDEF8995BD0D96
+:103310000238EFCE38A0BB985C3F395F7C19E029BA
+:1033200061A242A70DEC9848F04C7030FA8B2B52FA
+:103330001D1E8A9FC6BF8B78CFB53FBE4001FABF26
+:10334000C7D62F15F823D9C1E2278DEDEF617C2B6D
+:103350002EDF4F3C36767FEEB4401CDF8AE5AA159F
+:103360002E2C1B571462B92EFD7E2BC44BC464094E
+:1033700032814954C63C8C0769EB9BE3E7588B5D6F
+:10338000946C1D722584904488330C87F736E5CA07
+:1033900095FD08F92695E57DBFE9F8C806FCF04DD6
+:1033A000AA13EBA289DD1BC7E4FB54C84B88712923
+:1033B000259233D88E7F49D8BE19FC913749E786CC
+:1033C0006B008E2A7B1FA381BF6FDA50DC9FC35531
+:1033D0001B1782F7103C8BB20BEFADC568DA3F3795
+:1033E000325E0738E2719F405F12A52F3FDF3751F1
+:1033F000634C309F86DFB3921FF3A91A84F079974C
+:1034000043387E1A155539DF3D0A51A4BFEAE5A9B4
+:103410002D7757083DDB50BE621DF2B9B8BCDA9F6C
+:10342000AA0E73D0F9C75CC9F3EBD313500ED0F6D4
+:1034300001C3219FCE44153AC02D41467EA140884C
+:10344000833C5F6275C64D3A4F1EC4DA150E553285
+:10345000C3FD80330EE0B5969F0FDE50D6CB817F43
+:1034600057BFA0BCF022DD86F66FD1E4408215E59F
+:1034700093C8E1A18D5BE860F2D8945D35D33194B7
+:103480008D033EA27537C08B58697D20D6E7E07367
+:10349000A5BB3E0FEB0ED61F13692E420ED3718BC8
+:1034A000719CD43DCF52ACDBBAD7ADC37593BAEBA8
+:1034B00037623D9DF5BFD875B4B2FBFCBF6372F2B5
+:1034C0004B498D4BA0F43CF696B955A00AC6DFB225
+:1034D000B0AA8CEAEF3FAE785705B9F40195278D75
+:1034E000B41C3B607F22F839E387EE8F71EAE8F580
+:1034F000061ED76CBBC53C1AF45DD1AD62D51684EF
+:10350000F74AC3BDCF1A8799C79BD83E664884DC6B
+:103510009100F2F7F0A58D06BF93F3A1C2DABAF7D6
+:103520007B9B80FBFDA09EC9DB0F960B286FBBF930
+:10353000349E703FDE970C709AB95C27B74918B873
+:10354000D45B88DB20D723C18790BFD2FA97B67EA1
+:103550001897A5969AB52A8C3ED3E014090F3744E4
+:1035600088FF6A70D2E0ADB5FFE98E210AB3ABBD2A
+:103570000638CEBA7328C62B6FE0F17A126FE5FCDD
+:10358000C9FACDA0EBECCC457A7202BD433D6C9EEE
+:103590000D5F7706FDD71D79178507CC97FFA0FE35
+:1035A00080DDADBBFF0C857B443A8C00EF3A0BC14C
+:1035B000F72AFC5BED2C9E94340DE7ADE1EB92A471
+:1035C00019B88F1ABECE4B7B637C26B887DA6ADFC8
+:1035D0000CFE705789276522E06BB319F3DAEEDA37
+:1035E000BBFEC82FE03E789319EF4E167EF14001E6
+:1035F000DCCB76713D4615413B7C47C14DB43F5510
+:1036000080F91710367F97760FB2350EE17AB26CDB
+:103610004BD3085A76EE595A09F197137BC71F040A
+:10362000FF79613491D2C0DEABDF21233C3CE68FD1
+:103630008C768214AC8B3DEB0BA0AE8B232DF49AD1
+:103640008375FABFC5DB8C753DBC4C7A7839CB8C61
+:10365000F072961BE025BC68F7893A78959D792928
+:1036600011F4FB518713E7AB39D39802F0A9D9B312
+:1036700016CBC5DBA23C1FE9D65DDA126FA8D7EDE9
+:103680004AF3E8F5CBD9438FC5C2F9973944CF4700
+:10369000547E9C5AA136001D9F5E31BA414FCF4BDC
+:1036A0005BB23C36C33CC6FAD96601ED14D0339305
+:1036B000CF632F2E73C8B8CEA7DB98DFF9E90AAB2A
+:1036C00007D639B542F1B0751D1E664F31782DB958
+:1036D00025C6F3D190E0FE22CDFBAFDE1F21ADE485
+:1036E000B895E0BB3BE7CEA3BF23F28BF4A58CF2E9
+:1036F000BDCDFC17A01B2BFDDF398CA74A58D7E6A0
+:10370000AD6B113D90574CC876C37A749CF3639DA2
+:103710005D10593F18BF373102626228A7D97D88F2
+:103720001BEE43E87C5D926D0DC413B4FB903A58D8
+:1037300088F65D6AED94DDB4E9F3D6BEE77DDF9CE3
+:10374000E2290BF4738DB55906A55BD332A00CF8B2
+:10375000E9F3D68614B067178B677F1CEEBDAF29DF
+:10376000699C6FBD66BFD16FF46AFBCC920C7C463E
+:103770006CDDE7A6F55311DEF399C5E7ADDD7EB844
+:103780006204DD7FEDAE3332EC2339CD3D2B2D3994
+:10379000787E81DF072DDA760CF9FCA4D973C9EDA8
+:1037A000E7B3F37BECD3E630E41F7A4807F0E79CFD
+:1037B00042A231ECB5EF5379F3C96B6602F788E4A6
+:1037C0005BDA8B3ECFE44FE791AA5880D79CD6C5F1
+:1037D000287F3E7976DC419687D45C00F4F139315C
+:1037E000E1FBEE9F93DFC50ED1C16F5D9A9647C98D
+:1037F000BE73A3E5B9D00DA6619E7A4D5307BC3FB9
+:1038000066219287CB25817DB7C62BA0FD52C3DAF6
+:103810003DC4BA12CFB186C9230FFD0FEAF39B8DC9
+:10382000F269C1C3C67A3599940279DED50F982121
+:1038300093882CD4CB3F0ABF1BD398FFB980D437D1
+:10384000815DF788CCF2BBE72844EA4DF5D1D2E799
+:103850001E29984DEBF7A5317BEC53EE6FC07B8CA6
+:1038600069F4F9A25BBCB29ADBF37CC75B874C1DA1
+:1038700041703EE63F2DD2EC57E284787E6FF857D8
+:1038800076E4F3F76E15F1FEA937B4EBE4F3DC351B
+:10389000C6F35DE8FCA1E725E47E3CC7A26D57A313
+:1038A000FFA69D47C397761EF3B6F0EFFB6E4B1352
+:1038B0000C76DC2E0E3FCDFFDE1352DF97C6EC7A7E
+:1038C000ADFE72485DA36F33E76F4AF77B80EE97DA
+:1038D0005AFD158C4E3A65FDBDA81CECB72F6D68DE
+:1038E000E47E16CE2FB4DFCBE7EB17159CEFF57017
+:1038F000EB2E7DEEA967C12F5DF49B0763E152E8D3
+:1039000013A93905DEB758B275552CC0E9A4E4896E
+:1039100005BAF9C42B8E0E072F532F0D5EAA4DA0AA
+:1039200078AFD5E8BF68E504D0EF7FD96A56C03FCD
+:10393000ACDB66F1C177986A5B17E2BD0DAD1F6322
+:10394000F5D5F87E65DD2EF3877ABC2E7AE2C114B8
+:10395000CCF3209EDEEC5EDDD71B3E2154BBE5CFD1
+:1039600015E02FD7113FD273E838583F9080F27A94
+:10397000B61CD7F3B9163FAD634DA4AE75FD1988DB
+:103980009FD6B58E39017C5F47A40FF5F4540334FC
+:103990004DFD962FD278FEDD15E40A902F1A3C8853
+:1039A0003719E573C3933F1D748CEEE7D496D76245
+:1039B00005BDDFCAEFDDCFB6CCFD53E279F4C369B4
+:1039C0004AA7FAF73234B9EBDC4537904AAB6DAC15
+:1039D0005C62F6C58EA0705DB2C98CEF892E79EA63
+:1039E000B1C77F0EF944EF59F01E64F153078E0CF6
+:1039F000A7F5C53BCC4995EC1836B817D6F0524719
+:103A0000FF07F7141A1E163D734086F768A01DFCC9
+:103A1000040D1F8B77B4CB64604FF895B6B4CB9D83
+:103A2000B6307869395681EF1B3DF9B50C78FF64E3
+:103A3000AF4052B37A8EAFD97400ED188013E29183
+:103A4000E3A91B6F3DF0E59BB03B1FFB2920B72F7F
+:103A500084AF77B85EA574FDF46EBA8F9A3F585C58
+:103A600000879AA76F8A85F39C90EA197D3FB22A56
+:103A700005F2DD6ACC9E14054BD65EF3E8CD48779F
+:103A80000B0EDF9CC2F20FD5349EE79106E79CBF78
+:103A9000710A9EB39AB891FE6A1E11AB201FE62BE5
+:103AA000898CDE11863F6EE3FC716233452E3DE763
+:103AB0000990973ABF477BBFF9E6EE7808BB8FFCC9
+:103AC0008ADF4756F53219F44B37DD6E598D72F5A2
+:103AD000D30C3515EE29291C34398AF2553C5C9EED
+:103AE000CAF0C4E4318EA3F4570AEDD0BFC38CF7FB
+:103AF000C3BA715C7EB2F597F3F5E9BEA3C11E3976
+:103B00009112FEBDA0C77B09DAFE3A888ECE747C86
+:103B1000CEF87ECB5AC6E71ADF7BAF1E0DCFBF7C37
+:103B20009BF1118C037D44F7E54BC5E7ED930594BC
+:103B30000B16E20BC7DF5BCC9CBF8DCFA9C58EF601
+:103B40009C462774FF127C972C482F749D04C40355
+:103B5000DA2BD50FD0F13A3BBB0ED6C57E72B03D05
+:103B60002BC8C70BB83CB8B91795079705E501D91D
+:103B7000987C51F1812566EFE33F07FEA5FCEA71D1
+:103B800002FF9AF1FD9BCFB6EF3F721DA5F3CF5A0E
+:103B900034BE35CAD350BEADD97933C60943F9F620
+:103BA000B3F47A12966FD3F9FB73A17C9BDEF91FF5
+:103BB00095A71AFC1E09811F958FBFDCED8C0CC7E1
+:103BC00050F938AC9733AC7CA47F6F93829E74A875
+:103BD000D19F46778B7EBDB40FC8A16EFAD4E8AFF3
+:103BE0009B3E35FA0B3DAF117EA1CFAB21E9496772
+:103BF0003F98EF221E3BC5B77F8F88DF4DEA72FAF0
+:103C000063210EB42A8ACC023BBC4BE1F57856F70F
+:103C100027CB4D2027B4767F148BAB7555F963E322
+:103C200075F6F5B1363116E2BC9DDEF0DF79C3CC16
+:103C300044BA7E6784EFC0697189AEE8D841B85E46
+:103C400074A617F0552EDA326F81FCD16611BFE7EA
+:103C5000336FE5B5B19027D2D5D677E234DA3EFF9F
+:103C600015FE393F8F2AA55138CFE5783F493C0FE3
+:103C700015D1F3CD6D63F6F3BC0DE1E944BB3FAF65
+:103C8000B62D97411E51BBF5437DFC6811FFDE4206
+:103C9000CDC690F6B671484F8B42E8C9CDFDA3134F
+:103CA000BDB87E1E4C0673FFC4A4CF0B2917732723
+:103CB000C23B1E5D8744CCBB3EDB26922638E776AE
+:103CC000C14B80BF3DC94897B5547EE8E3C0A7808B
+:103CD000EECEF33EDDA9DFFE77C1EDB4CB9267DF18
+:103CE0001FF40B5A9E7AF6BD4B5E80FA734733DFA2
+:103CF000273DFB97EEFD6626C8FFAEBD1682719587
+:103D0000BD2F67DE0EF5DD16CC3FEABACBC2E2C1AD
+:103D10007BED984FD795C1DE8B69D8F3F520CCDFCA
+:103D2000268D88B784DECCEF38DBF6B73FE27BB672
+:103D30006DF454A06FF7C6A03D5EB73BCA0B4E6A48
+:103D4000D79EAF0BF4F718DFF73CB5328BE377D98A
+:103D5000C934887F75C5B33C9BBA17863DB692AE11
+:103D6000BFB4B55D86F7774A5FFCFB2090375D3BBB
+:103D7000991D71DADCF928711192D1FB8EBBCD143B
+:103D80005FA7C1B6A3BCF27CEF3DE3E19EA3275C35
+:103D9000181CBA281CE05C142E35202723C123BF31
+:103DA00037FB4ECF0F0F1E6766C2FA4BDAAEC07BF1
+:103DB00088205C0495B5DBBD5601CFCFDAF77E3D98
+:103DC00008E4F1672D2B51BF5FE8DCD7FC60E9E028
+:103DD0009F3DB7E0BB98732FFBC19E9BD17F00F442
+:103DE00053724F3EE849E7CFFD18EB4FDB5DB8DF7C
+:103DF0008BE4FFFBFF5FA3F79D02E6B15C08EF3B9E
+:103E0000FED7E2FD158E77BB02F9125D7BFE9E495F
+:103E100074E7BFD0B93B7EB0F83EFFB9353BA8C3CD
+:103E200054AFE4D3FDBD479AA764D1F22DF58B249E
+:103E3000705B2D91EE6BD2995F611158FE3799221C
+:103E400068F1A50E43FE537A0DDA1B13D4BBD97764
+:103E50009AA4FA0EC83FED2899EB5A873DF2F0BBC1
+:103E6000021D9347F2BAD1DF7A5320AA40EDDB0955
+:103E700025E30E81BD375115D11EA425DA81EF64EB
+:103E800056B0F642A39F313DC43FB8769AF1F9147B
+:103E90003EDF54B24CC9A7F09A9A2E295E0AA2E9D5
+:103EA000C5F56638CFF41B04D2AC8B6F4E0999EF81
+:103EB0000308A0E9ECC8EF0ABFBC74E6775A846532
+:103EC000080F522CF2F78D2E003FC2E0DD31793021
+:103ED000CB33965C0C7E5397BA306ECAFD50331FBD
+:103EE0006FB6ADE900BE3513A3FFA9F99191E04C7F
+:103EF000B85F8AF36407E16E5645F44B75F3213CD5
+:103F0000347C7C573C68F8FBBEF890D289E15E5562
+:103F10002B175A672F867B082BE4BDD379276E6059
+:103F2000EF91587305846355A119DFE3FAB3A9AA89
+:103F3000000CE7CA2157D4DEC6A675017C1672387C
+:103F400056937AB43BC9B7E7CE1515E0AD1FDAAD8D
+:103F50000B5542C653BFA4BA48F045D3F32F9088FF
+:103F6000272E0FE2A002F9501F07F51AEBF0776534
+:103F70004A709E0BF58F241FFED5E59FA83CFA9052
+:103F800022FD1894983F4324BDFF38AB8DC1B16E1C
+:103F900089E0CD463AF299F5F7C04F70BAFED31DCD
+:103FA0004350CE15DF3B308EF9B5F998D753C7EDA6
+:103FB000FDB31E671CC473CEB6F58D8378CDD9438F
+:103FC000A5B1E1F2790E73BFF2F72BAC58769509E3
+:103FD000CD621CBE7F3201F570591401B9133A6EDF
+:103FE00075BA1697A997318E4F583E7E353FC70256
+:103FF0003A342E4187B70DE33F9106F5C403FC7DAB
+:10400000A8BB57F9BEF0053F16E07A38AAB322DC08
+:10401000770A7FC6E56AE5BE6F64881F4C6ACBC22B
+:10402000EF4C4E2A33BE0F785F3AF7CF879021B01E
+:10403000AFCA7D636287015E0E89AE280ADFBAB619
+:1040400033B23BCCFD5C283C617E88231F37BBAA82
+:10405000019EC7EF8EC2EF00BCC1EF8B72F9F72152
+:10406000E11342103FDB9CCEEE21BE4E6771F46B34
+:104070002A8BCDC974DDDC566530E497F5E2FDBFCF
+:104080004E77E2F3DE7C9CD6AFD712D6EF98ACD455
+:10409000863B7F4626A39F05C4F5E342E18787B7A9
+:1040A000E27BED3E783FEE6C99C0DF9F09A56B8205
+:1040B000FC7176B4E005FD0B7E2CD62B05D4FF6F8A
+:1040C0006879159398BED4E83E14CE6F71FAD5D6B0
+:1040D000EFE2707F9BD38706670DBEA1FBD5FA5335
+:1040E0007975953EDE3271D7E0A7C13EA96D1314F4
+:1040F000139DAA56EA94810FEB76DD6786FB85E96E
+:10410000FC775A885435487FBFFB75BA84F3EDCFEE
+:104110001B81F6E3171B987DACCE3B130B76D01BAF
+:1041200026D75B23801FDF140DDF370F2DDF5FA144
+:104130002C2A33EBE7CD627ED29262338487AE5F66
+:10414000D26E4ED5D1D3D7908F3534D8DE6B89134C
+:10415000F318E97AB80FCF3D1602F94BB92D1D259A
+:1041600031F4F9F5F5F18C0E6B5ADA65ACB3EF0D5D
+:104170006BEB69EB84F2D3E4CA18437D6E69673A4E
+:10418000C0A5D2E25BEE0A43A7F76774C755BF9B91
+:104190009E5029DD0EFAFF414F9CA908F73DD4D966
+:1041A0001C6E3AFD901A4E3F2C5BE94C05F82FDB54
+:1041B000D337159863D92BE529E1F4C33B2BD8FD00
+:1041C000E1519E7FD93599EA87CB75FA617214D295
+:1041D00047E8B87119DA77552EA01F347CFD87E5C2
+:1041E000CC3BA01FC2F0F5CC0CA37E98DA361BF5B1
+:1041F000C3D4C92271EAE27153322EA41F8A53A696
+:1042000063DDEC8A094337EF70BF04E00A25AC0395
+:104210007AE2EE0C26F743F54524799E7DB1F2FC57
+:104220007F08CE9A3C5F3685BDCFDF930E09CAEB7F
+:1042300065D305FC1D93657B983C5F76038F4B86A9
+:10424000C8D72A90AFF97AF9CAC6D7BA993EA8DB7F
+:1042500095F5D319F4F975CD669795F6BF2E286FAD
+:104260000BF4F2F6EE0C498373A61206BFD366C4B4
+:1042700010A7515EF50339757CF0CBB9CF00DDBFD7
+:10428000C1DE37FB33D7E3AF0F7E391FE2E91FF101
+:10429000795B33185E4EAF208BCA281C4AE7317B0E
+:1042A00078E97611E150DBCAECBCDA6D02BED75B6F
+:1042B00091F70DDE1B2EDEC3EE0DE1BBBEC53A3C11
+:1042C0002E7EA3B3A9373CDF24E0BD67B56B317BFD
+:1042D000FFEF611627B6D2FF205F626D74EC668235
+:1042E000793A2AC69B9772B8555AFC07617CE51348
+:1042F000826B13CA35637C7A69BFB19F807FB078C7
+:104300005B48BB6B2DDE672C85B8B3CE1FF93DE74C
+:1043100093F9A22FF719C80F7C4B0CFBBB675ABF50
+:104320006E38D47C4F381CA670C8FFE7E150D776B2
+:104330001FE6DF7CDFF3BF93C1E3ED79241FF8E5CF
+:10434000CF2615F9DFF3AA88EF17CFBBAF7FAA3EC0
+:104350004FE93887C31B2677531AF4AB65EF212F3B
+:10436000D8B8E300BC223EA3850C86B0FD82878DC1
+:104370007AB25B2FB73A51EFCEA8DF21C077FDE7C5
+:104380008B047F0F6C6E9EC50DF7AF87A3FC28CF03
+:10439000343AB467B2DF8F8BC964EB1EEFE52F436D
+:1043A000BF6297A0209FC07735A04EF100DFD5D81F
+:1043B0003FECEB0A0E778CCFD4ED6278AAA378019C
+:1043C0003EABA0F62EE891EBA9DEC1FBB2B6763388
+:1043D000F4AFA1FD1251EEB8D0DFD5F413DCDF1538
+:1043E000A7E8F0B6E718A3DFAD828B84C15B0EFDB2
+:1043F000EF7C788B842FCD7EB858BC69F0B0671AFB
+:10440000F17738AAA37208DE53B1DF03226DF17889
+:10441000AFF251735FC4636F2E6743E91BEC7DA756
+:104420002EBE74356C1C3F601F857972B86E36B332
+:1044300087F4F225D48FAE231D68D724A7B97F9DBA
+:10444000AECB8B9BCAF357BAEF7583FDE6679CA78B
+:104450001F7194E0FD8F96570BBF2085F960BCBE9D
+:104460003FA3E0E80C7ADE2FD688F89EF2B526E767
+:104470009122E0E375660274F9C5EB6695D9A13126
+:10448000288767BF71DC0CA191D9905F40FBCDBE3E
+:1044900093C9DBE330196DFB03D5632A7CBF84B479
+:1044A0000C85FCFDC9AEF672C8DF9E927F7815DCE4
+:1044B000D35D53AA1C3902F05D2B1280EF876B4A43
+:1044C000D15FB9E94601E9FADD15F89B5864CAE401
+:1044D000AC2347E8BA37AC49C67BB619EA8172A06B
+:1044E000B7B913ED36B8A71B972306F37B09BC0FAA
+:1044F000D5B10AE4F78CFA1BA7C07E6BA85E80B822
+:104500006B4DDBE1F254A86F14F0F7D4EA3C6E195E
+:104510005E85EA78F88C0CF18F6ADA0FD053B79188
+:10452000F5ABDB22E07B3ED5543EC0F9AAB70804C8
+:104530005E28E9A0F69F95CDEB850F34756CA4E35A
+:10454000697D018C8779B7C4E3EFDED5BDCEDE137C
+:10455000AA2E5C7910E453351D471F938E2D37E248
+:104560007C0B370A0452836B0AB3EE2984F95E3759
+:10457000E3F7418EB6FF4C867DCFA4EBA5D1F9E7DA
+:104580008A9DE5986F7DBBA0E07B4D65B7211F74C8
+:10459000713E2049B7B2FB6681D7B95DA8E9C7C7AC
+:1045A00032B391BEAB6F59D904E7EAF42467814B6B
+:1045B00054B7EB8C0C76DE472BE00334146F3C0FC2
+:1045C0006EBFE7B8DCA99353BECCBE488FF3761517
+:1045D000239FCF2755782FEE5EC9F4F2B155515E77
+:1045E00001EC11B3827A73FFAA1F3D04E73FFD94EB
+:1045F00019EF4B4F6774627CF6C446337E3FA4616B
+:10460000A38872E4C4761617121F99529106F0A37C
+:104610007200E86EFFC65219E4E109AF80E34B1F58
+:10462000B93985C57D8DF2A3DAB908E5C523514CAA
+:104630003E2C7838FCFD6A4479B1BC82C9F7107908
+:10464000B034BD09E37EA172A28ED834F99007F58B
+:104650000E5F1AD26FEDEB6602F65DADA4CC7C184E
+:10466000E8664614DC2453BEF01D00F9F685577049
+:104670007AE8F3EB673D3F14E0F731C01BF8624383
+:1046800022DEAF567B67235CB57CC4050F1BE9595E
+:10469000CB7B9AEE1683EFFBD0FF5D5F1343545D37
+:1046A000BFA37752BAA4EBCDDA2578E13B4847EFB8
+:1046B0003C76F0E67CAC2B4087B5B770BDBAC18EB6
+:1046C000747BF4D633AB802E67DE21E0FE89C7DD34
+:1046D000047AA5F661C10971CD0577B0F10BE878D0
+:1046E000A097A33F63F443E9D809745EBBF1BE838E
+:1046F000D87F8BE084F98F6E9A8D7AB8C623127CAE
+:10470000BEE518DACB541F60DED07E8F9802745E4F
+:10471000DB685100AF1ABD68F4778C7F879A585DCB
+:1047200083AEA1E36ECC7486A53B715A16D257DDD9
+:104730007633D24B9D87D1D3B1A744A4C3FDABAE92
+:10474000AD00FA39BD5588407F94BEF283F4253E12
+:1047500062C6F10B9E64F185FD1B195D9F6865F6CD
+:1047600069E923FDD1AF59F08699B0F803B1E9EDBD
+:104770008F0BD16128DDF5D04B9C0E23D19DDBDC66
+:104780003215F20F663F4DF7EF0CC2ABB4E9568C11
+:104790000394364DC7F36AFC532DB1BC8D79CD2BF4
+:1047A000593EA3C4F27BBEF3BE42F6715F503FE6B2
+:1047B000817E84FC131FDDC7CBDB1F433BE0F35F2F
+:1047C0001DC3FCC6C52F50FCD3FEA7B7DB890FED78
+:1047D0006C2FCA9945AD22E69712C957708DEE7DB0
+:1047E0000D2D2F63F16FEC08F7453B2DDE4A3A7E25
+:1047F000D1B3C707E13DF95DCC4EF5FC8A7D6F86EC
+:10480000783A075D03F99912CB0F09D5BFD17D58CE
+:104810001CE7D4F331F85D26615B3BDE332D6AB9CA
+:10482000D66CD1C52D853E66AD1FDEDF7828FEE152
+:104830007E11F6A7FF5D092D2FE4D4938C7F16ED32
+:1048400032A37DB468DB268CF7D56D3B83F9B3A525
+:10485000BF792A16E050B74B34E64F6D137D16CC66
+:10486000F3128F59D8F7390C794CB5ADECFD8EDACF
+:10487000169E2714923FB3F8377B9EF550D02C7EBE
+:10488000E68958E0A74F3BB6C6023CE97C987F34E6
+:10489000B130427ED285F2925AD6F2BCA4F1F87BB6
+:1048A0001DA179499FC23FA81E77F531E679926D27
+:1048B0004C6E51EC17847B1F49B35F163FF5D5A3AF
+:1048C00090477B6AE7678FC2FE97FCE38B4721AF77
+:1048D00083EC8D52C09EA8FBD53B987FA88D1BDB37
+:1048E00087FB474F3E81F99BA7DFB3A05D787ACF66
+:1048F000894CB0174EEFF82605F23297EF29C7F82A
+:10490000C4F2DF96E27BA291FC4DA04FEF45E48F0D
+:1049100086E2637FABE8B3D17D7EFEAE05F9BF3B97
+:10492000CFAC6529CBDF73F2FCB2EDE1F374B57C5B
+:10493000A8DAD66B268E0479D7CAF47A777ED48526
+:10494000F2CADEA678BDFC22F0B79DE70FB68C0F49
+:104950009B57F639FC83E2A9A68F31AFECABD6F9B1
+:10496000BFFC393C6B0DFFBEB6C6D717829B9607BE
+:104970003CB48F7A531FE08F9DBFC63C3EC05BA501
+:1049800013F4FF579910DF3C69F663DCD0BFC7A270
+:1049900040BED7A23D47915F4EFFF630E6D9129E4A
+:1049A0008F7B9A74FFB1BC491EBBA8DB6267F968B4
+:1049B0001CFE90AFE68CC5769E97C6E858CB578B09
+:1049C00094A7F6649F6C665FF3FCE4A5CE0E59B124
+:1049D00005F105F8110A015FC70CF97FDAB943E761
+:1049E00053000E57E8F32F23E503723BBD07BE9833
+:1049F0005C3EBD89E76376E75912929E07F9414C08
+:104A00001FD67985A3E1F0ABE55F6E09C1AF76BE35
+:104A1000487CA1F1E785F7FDCFC1E5A13EEC7D0023
+:104A20000D3EA7BE0D2FA75FE4FC4EFD96BD7D7425
+:104A3000EFBDCCE27E8B9677A6EDB7A985E9E5536D
+:104A4000DB98DD18CADFB5117E57EB0DBE4EEDAE1B
+:104A5000F64120874EED7B9ED39D97BF87734CF622
+:104A600070B9EDD5CBED08BF6376B40FF317A9BFCE
+:104A70001B76BEBAED67C2CEF7A9A45E0BFBFFB4EE
+:104A800083D9219FB688617F0FA1BD8FF17DD52687
+:104A9000BB8C7E97181B8DF268B9BDF05DF8BEDB4C
+:104AA00072BB8CF90E0D2B797EC49D2EFC3D8F06BA
+:104AB000FB58FC1D8855001F9D1F6A56DCF8FB1330
+:104AC0006647553EF857A1EF77CA4926E2D5E35F1E
+:104AD000F2A4E3F7BBB2BF9640EF74AC30BE37D25E
+:104AE00021290712E97C1D65820BECDD9E74669C12
+:104AF000FF6A5534C4CF20560DE73AEB62DF45B369
+:104B00009B7C0AED42EC511D0E74F49CEC77ABE1FA
+:104B1000E7BAE03E7CDD0A6B3F788FEBFF022FB6F1
+:104B2000D5840080000000001F8B080000000000FA
+:104B3000000BB57D097C54D5B9F8B973EF4C26CB81
+:104B400024936560202C37FB1E261012D058261B9C
+:104B50000609382255D480376C610B89686D6CFD6D
+:104B600097613145E5B5A12E50A5CF01C1C7A3F886
+:104B70001A166BAC510708142DDAD0E293FA571BC2
+:104B8000942A28981194F25A2CFFF37DE79CCCDCF0
+:104B90009B0984BEFEA3FEAEE7DEB37EFBF79DEF6E
+:104BA0009C89252E89C884D85C8AB7279BE0DF15AD
+:104BB000FA5F1CA1652B2FA7E0E3787A092131EC7D
+:104BC00015FD6EDF6F920889CA26D94A3121761207
+:104BD000E59269F98958F761299690F536AD96D036
+:104BE000E715F89BD4FF495CCA2918CF4AFFB99250
+:104BF0004AFB9B40CBD6E0F8F16E7D3991849471ED
+:104C00003E6E4286C07BFAA7123259A633A3F388C0
+:104C1000AF36F92224FC5E9B312438DF780771F926
+:104C2000E1FBB4189797D68F8961F313F3A5F3F9D5
+:104C300018E6A3D27F703EF93D5E13C1797D1C3A20
+:104C40000FFA27796C38BF8F0DF3FB38747E05AAF5
+:104C50002DE9D3685A50887285C237C6DA4D389C20
+:104C6000CF87C299102F514A009E02AEF43BED2728
+:104C7000457A52B922015CED1249C3F10CED46D8D8
+:104C8000B17F28D37EC7C09A271252E694DCA7C60C
+:104C9000D1FFEF4C22641821A92D95E4135A96DA1E
+:104CA00008C2277D3DF145D0F9A5074C58266BA3D6
+:104CB0007C19B46D84957823C7D27A0AF19AC742D9
+:104CC000AF3E42C62370579B6857CA3A421EA3EDB7
+:104CD0003A0315A60514A8EDF089F63F51754F511A
+:104CE00069BDD6DB34A7A9089693D7D65546081DCB
+:104CF0002E477211625A95DB7D6424214950FF06CC
+:104D0000F89EDBED8EC1EFAC4C889FD075B545F5B4
+:104D100095DD56272DA7B2F29DBEDCB675B4BF0F48
+:104D2000D23D77AA0EFACE6ACF05F8137F02AE778E
+:104D300040FAA270258EE03CB3B7F92BA3E8246EAD
+:104D400009508052FC67D03EBAF3013FDD16209235
+:104D5000ED31A2ECB710FAF4EC3B66E9A1CFC6F650
+:104D600063F8DD0465FA1C9DE8AF4CA6EB7C50BDF2
+:104D7000D1E3CCA1FDEDAB779AEC84AC546FEC564B
+:104D80001CA17098A48383B2FA26031C6EBA2E3835
+:104D9000ACF4DD847018ECBACFA99E1F015EA69614
+:104DA0009B8844072D3D11E393181F477A0A82FD23
+:104DB0006C319145ED31E1FA59C5F0CFEB093A1A62
+:104DC000884ED2883D17E8D4482F747D35ED148E77
+:104DD00053B57A4F5562904E895D1B37A300E63973
+:104DE000F74998A718776AF90A3995CEE7498A23CF
+:104DF000E8D7D1E28DCCA474EA709B5CC0E7E7549D
+:104E0000EDE7503F7656C06FA6554A8976BF941697
+:104E1000EC5FD07DEB6B32D2776BBDC9B71AE54141
+:104E20008F04EB0EE2BDC780F700C37BC749C4FB0C
+:104E3000F2CE930CEF1DAB2AA28AA12CD923545891
+:104E40004FA008F0F92BDF9D1E85E2737474A01546
+:104E5000E8C14CBEEBA9CD41B8BF0874DA0FEE7CB7
+:104E60005E02FE03E1ADED48EAE3F9B4AAF7A8C992
+:104E700095A106E125EA1D572D586F63AAF61B1868
+:104E8000A76942CF61BA52B2E7C81F62353ADFD88C
+:104E9000A333F643FBD89914136A70DCB6A3AB2B8B
+:104EA00080FEDB80FE51CE04BCF698ABC183F14599
+:104EB0001F3CF69D44F898A04CDFEFB430BA29EBC4
+:104EC00090DC3EE08B6872AF873EDF564D38BF9373
+:104ED000AACC9F12C3E3D103B24ADB97AD35617D03
+:104EE000073CF343D7BF16EB9D54152E77183C04AF
+:104EF0005E051D51C289BE8DCE797896F63EAC3FD7
+:104F0000483709D1A9F47B69D7DCFB496AB0DD4F8A
+:104F10005612CF7C73B01EA59F9775F456608E0411
+:104F2000B8F5D10FA54B902F46FCD076A7193F2599
+:104F300044ABB4FEEEAE15B2963F78BC9644906694
+:104F4000987F493469DE43DB97C4D127941379797C
+:104F5000282F27F3E768FE3E8F95D33E7099245A99
+:104F6000DE0270073CA498189C147B2EF0912985D2
+:104F7000C1B9CC198DF25FF0AB42C11997006A88B4
+:104F800078E1991A4835011E05FF2A0193DF46F59D
+:104F90005FAAA29A5CF4FD5B2B354F55C6C0F2E5C3
+:104FA000961CD9E30B232FE25218DEA980F69ECA85
+:104FB00006ED2C91382081615A5C0A9D57A3B5E714
+:104FC0002733E8D7E539172C809FD5D1CB6FD4F2A2
+:104FD000071EC7388FB72EFF361AE8ABF352444D81
+:104FE00038795503EBA7E31F59390BDB3D1A155BE5
+:104FF000C8952ADA2DDF41D1449FE94B6A4921E067
+:10500000C3AB2480FE8B965CDB09E285E9C3A12952
+:10501000BEED29801F5F2D96F3D2C87609F0A4ADAE
+:10502000B141594EC1FA1472C23E92AE4460DFAA39
+:1050300042ED0D44792AE0B3F9A00D847D04ADAFB3
+:10504000C27BBD3D45E7B7958C017CB7552540BD7A
+:1050500038DEEF2566E708BBA83AFD963312CC7719
+:10506000B45701B94AD252703EE5C4ACB38F4AB2CC
+:1050700028C8617E59B93EF85E69357CE77454DD15
+:10508000CF8E6A73CDA0F43E359BD23F7F7F81FEE9
+:10509000373A82DC7B5B7E50BE4F51EFF254E9EC35
+:1050A0008F3617F0E1EFBE9591EF8DF8D8CAE9F190
+:1050B000C84A8FA78AF2DFAF22293EE87A2B5469CB
+:1050C000AD4DBD36FC8C7833C2EF3B9D0BD17E33AA
+:1050D000C2ABFC03575582DA1F3E467808F8D3F579
+:1050E000AD07B85567CBA8AF04BCFBC389D1C3EFEC
+:1050F00072683D89D10FC38744905E04FDC4A52129
+:10510000FC4B80F6E07B740A968DF035C293CA01A1
+:1051100037D6E7F83B0C70CB80AFEEDAEA214138A6
+:1051200050BAEA8A0FA12B01877E72238B9739DE52
+:1051300085BD5CCDFBA1F632DAC3950E9B0BC05F3B
+:10514000D9C8E65B9911B3D59B82F8DA8AFCE3A74C
+:105150001829C17FD9DF2566E752BB94D167E7E400
+:1051600033603F8F8ED0D6027F04A478B29520FCA6
+:105170003F36C05F57AE36D8CB4678FC0AFE676232
+:105180007FB809BAFB790AB5AFF36871381901F62F
+:105190006FE12BC57120C7496702CA63233D969E04
+:1051A000F0F4F5C3E917E953225ADF7B3BB5233A04
+:1051B000B21F7902CC9A1BAD6D32D0E18DC4BDE631
+:1051C0009415D62FE33CC5BCFEEEF4EC4CA1F26680
+:1051D000624FCD9A53A17CC1C717F0BE89C3FB268D
+:1051E000E2DD2FC7C253F9BACF8E0FE96F6F0AF70E
+:1051F00017924932ACC79EA232F9CEFB13EB1B9D2E
+:1052000046FC12C2D9EADB2AC1FC89D792101CCF16
+:10521000CCD1949131E3B51494C7CD04ED656A5EA9
+:105220000212CBF8F7326B8C1FE64302CAD93E3C20
+:1052300020DFD5D901AE142EE44A74707EBF4B91A5
+:10524000944FB383F33BB7C3EA95819F8769BF87C8
+:1052500071CE4A470B916F157F26E841E3F70B1D8E
+:105260005DCBE13BADB710EBF1752D05A791D25D9C
+:10527000E0B508DFD694ABD8A156AAC242E44159A2
+:10528000149327D5242083DDD919C9F8F9F5AF1671
+:10529000213FB8897D6D1EEDEFD0F9C947809F2B66
+:1052A000A978817A932EE9FDB66BD1691509CC8175
+:1052B00076D576B3C10FF4A2BE59CBE59AB0D34CE4
+:1052C000A9DAB9147C3FCA077AA6F3ABC92AE06D04
+:1052D0006BF6F85B6EA7555273C6CD00F7CC64ED44
+:1052E0003683FE9BCDE96B02D097845690A0AF8B9E
+:1052F000D04FDA3A037DD913747EDD2DC48FEB2FA6
+:10530000CB36FF4D373F6E9718EDF5A09DDE16D6D4
+:10531000BF235D0AC9A6709EC3E1BC36DEE205B9B3
+:10532000A6DC27F9480ACC978C5A45E739BBD9AC9B
+:10533000F347E7C42B88C739AB227D84F9DFCE7AE7
+:105340005AD6E8FBC7A098ED7686DA55A425A43D89
+:10535000D0438C8AF43BC7CEDE7D44FB189600FD1B
+:105360009E72A013EF359F0FA553E3F803F66B6809
+:10537000B75622B3C07E5A6B763B5D21F6C7A85460
+:1053800066BF9CB7576D32A50E6C9768D664B7920E
+:10539000182CF7C45B67F9C2D831A23F4127651AC0
+:1053A000F3CB07EA373D50857699E949BF0CF6768D
+:1053B0007A80A07D5C16709BE6E9EC74E69FF6B3FC
+:1053C000D3DBF7A39DBE6CDF7E66A7B7AF427B7FC2
+:1053D00019B5F741BE53BB1164259B503EDAEF7DF2
+:1053E0007E26E52D52D62EF5F9A10A45455A1BAB6E
+:1053F0007FF7D6ECF847D3C14FD49C66EAF7DC9D23
+:105400005AB0C14AFD9ED6141249A8DF332BB5E02D
+:10541000B6F513283525B825128FE50D311307EFA2
+:10542000D7DE9D9ABF01FCDA81FCCBEA54F5AAFED7
+:10543000E507E99EBB5343E202543E86B54732324C
+:105440002AE6403D2137CAA2187F3E6AF2A7FD1422
+:10545000FCADB76402FAF4969679E8074C6B59EC08
+:10546000A9A2F3E93D70399398405E32BC37A63269
+:10547000BBA6299AD9974DD1B41F2A6FDE746A8DC5
+:10548000D07F77F6F3EBC7527EA9EB905DE02F4615
+:10549000665D1E05FC3F6DFCF34F8EA5E37C185046
+:1054A00030FED069A37448DF7F4824B467CB8E45B3
+:1054B00078F651BC7CDF59DE961AE29F7CDF598575
+:1054C00065524B1D2BCA1F2BAC8C2F3F24FBD37E68
+:1054D0004AC7F1364B68079C6F4E89033AE834D3CC
+:1054E000F587D0E3EA5405E96F35A7C7BA4B320612
+:1054F000CD3ACDFEE4665ABF4EF19BC10FACBB6402
+:10550000C1F7300F984F67A4BE9FC7793F8FF7F55B
+:1055100043E1300EEA19FB51D87B89ADCF8887D3A0
+:1055200029953F85F57CDFE96E43BC51F905FAA268
+:10553000ACB8EB04D811D7D64B6E09F452D365C979
+:105540003F9AC2F3EC3E33FAF767C13FA4E39DDB19
+:105550007770C85CFA6CDCFDC758F007B7707C9DAB
+:1055600053BA63617ECB5EA2FE0BDA43FE21F76085
+:10557000FB79258FB161ACA1FA7AECB707933D2C8A
+:1055800078A8427C4ED8A53759BD3E985FE72A19C6
+:10559000E508D5E7226E2A81FC9EB44F7647C6F611
+:1055A000B7575F4E350B796B023DF6809D8D33907A
+:1055B0003C28BB94487C21F2A24CF1CB30FFB24B8B
+:1055C00043F0FDB923A94FD402DD12B30BCD4485BE
+:1055D00074A1BD2C11F1D7954ED7F33A2FBCB1EF82
+:1055E000C2ED37223352BD48EB7CC7AF25A1FD0C7D
+:1055F00021D292A05D38E9923EEE6AB4A3859EADB9
+:10560000E82C5A9B4C00EEEAED37021D1E51907FAC
+:105610008C76767560F200F6F406A4A33DFBD2A268
+:10562000212EB091F379D3BE0B93413E2D27FE3B43
+:105630006E4C82B8836CF793ABC5BBD6FE6E121D61
+:10564000FF8D80A2823C7823D0652DC4B209E31C73
+:10565000656F97E501FF7606941AF05BCBBEEA8A88
+:105660009E971FB46B3A2F9BF0FD1B970FE07BD1E9
+:105670006F6720210FF4F36E13F3B7BB0EFF2D1AE3
+:10568000E4EB1B97CF27A2DF2FEC92FE7635FA01D1
+:105690009536B92F0E1D6ABF13B9ECB815FC8D38BD
+:1056A0003391110FCC1FED67977C40D6DA487FFB12
+:1056B00044C01FC812F8A69F5D1D84B7CEBEBE921F
+:1056C000CAEDE59164EC15B0732F272E057DDDDB67
+:1056D000196D5F8DF1296657F4767DFEB3A9F0FE52
+:1056E000A88CF1B6DECB32F2D581D7978EEE890940
+:1056F000857B2BE2EFE2B0AFBE7C95D6BF78280A5F
+:10570000E3EA4471E5858B9F04E3C9FEE126273C6B
+:10571000BDC34D1390ED305EF09D60BCC09186F12D
+:1057200082C0645057999B4F5A20DEB231D5333432
+:105730000DDBB747C3BA174531F9E42515C9D4784D
+:10574000222F1D315500BD14AF5211EF3BCDD4C4F3
+:1057500002FED8CEFCFB9D54DE825FB4B8BDCD9274
+:105760001282E7C51441B0BED366EFA88490F73B20
+:10577000D2583CE1F4A125CF019CBC7F8A2019615D
+:10578000ECD387D2983CDC6BF14EDD05F53E36114B
+:1057900018AFEBF06F0E0FA7785E7C422D023D3004
+:1057A0002B4DC57A1D4777B60EA7F53A3E00ED4959
+:1057B0004DF26DF5B2898EFB2A5159DCEFB809E73D
+:1057C000DB172725EE4458EF1D694C8EBD7A84D136
+:1057D000AB18FFD528A6EF26A731F95296C6E26E80
+:1057E0007B8E5424CE45BED22601DC9A4EF5B4C63B
+:1057F000AAC138A1B00F271EDF33B580FEEFC4B3B6
+:10580000263BA04F3DBE5586F5AAA7098997FAC742
+:10581000B1687F53D21CC1FE5E3DCBFAA3F33800C2
+:105820007C175845EC5B91EA3C8FE7D3F2ABDD4A3D
+:10583000C2632AE203F581C083588F9887DA4EDC71
+:105840005B629045DC7BAE168FA67E27F0DB382EA0
+:105850003FDF4D75DF95C6ECAC514077A70F45A1F2
+:105860003DB697C7B589B37E34C04FE0E97BFC698C
+:105870009CCF40E337733A10CF9D66D58BF4F0127E
+:10588000D3BB3B6D7E6B1AC8BF57D2B0AC7ABDD1CB
+:1058900085F47B5347864B56919E9B19DD323ABF68
+:1058A00089D3B9DA1EB0A484E06160F9C6E0DE47AE
+:1058B0003F4A3BD255C70982FCB664C77D2C0E49CE
+:1058C000FCC98C9FBCC9C05FC0178CCFFCC324F639
+:1058D0008C053E99D8B9654D326DD700749F1F84F1
+:1058E000830A7C017C26D6696376F2CF78597C6F77
+:1058F0004B6371C76A393FAEE72AF1BB37563A8925
+:105900001212BFFB199FFF62B201EDD3C597DBD026
+:105910006E559BD973F103EC99B9B9DE02FA60F1C7
+:1059200026C91DCEAEB673FC9DE37C404C51C389A5
+:1059300033F8DDC1F9E0CCBE270EC23A29BD3E07DF
+:10594000F0BFA163C3D3002641FF67B699B1BD90F4
+:1059500023A2FD36DEFF4BC719FF4CDC66AEB89BB9
+:10596000C27BA297D8219EFEEAB6ED32C8F75781D6
+:105970003F5298DC00BD7CFAD063D13F003A3869D1
+:105980002210B7DF6B218B7687E0B76BCBCB3A79F0
+:10599000B064C7AAA9D04F694F82047A40C8018178
+:1059A000EFBD16D7149427D30DF2A48AB53F06F0A5
+:1059B000A4EB7A82CB93276AA83CA1AFE2B7C54B90
+:1059C000D0CF5E1E2736C2AF8BE353D0E38D41B9F3
+:1059D000DBC5E46E4F2C74BD7CDA798CD3F68DC3B5
+:1059E000E9EE892A41772912C091DAF9A67458376D
+:1059F000850FD03FB5F3EF9D918F5C7A44C1FD21B7
+:105A0000BEDF44560BFB47C7BF42CEBD9BAA1D87D6
+:105A1000F14BAA9AD780FF9158EB45BA3E2369A370
+:105A200013A8BE3A037C1D462EBCCAE5C845B33652
+:105A3000DA1EE67B908FC870E083454433C13AC8D4
+:105A400066C90E7015DFD5CD8CDE3EE7F011EF3F55
+:105A500037C06B12C02B0DE1F539D753162B9D6F54
+:105A6000A68FE9292255203D12D32DC381DFCE9880
+:105A700009D2CF192A17016E8BA3F4FE8958D737A4
+:105A80009CAF2EC6B375ECE5E3FE097C9EF1580F82
+:105A9000ED0A6FB909F76B813E90DEA627A0DD45C0
+:105AA0001D2605F9BC6F3FC22F4B4C1EC8300F3B63
+:105AB000F8751827DA82FD2EDDB505E926BEC65E2B
+:105AC00004FB474F28AEC8F890786FD7F68DE84FA3
+:105AD000023D015F0E448F8B801E49183AF4513A03
+:105AE000A4ED126A9A118F14BFF674DA6F7C9526B2
+:105AF00003DD18F12BF619053CF61AF62567A633D7
+:105B0000F8A4A433FE54B9FC1A584FE8E52DC59704
+:105B10009AEED0D337E04DF05B4C3A934F03D1F976
+:105B200043E976ECB7F5C3794E9017623F4AEC2F04
+:105B30008BF1C7A6337A1C683FE99CAA15A51BF612
+:105B40003BD5FC209F5473FB71C5F608DCA7DF0D25
+:105B50005F00EE5D51B82FD1270715E2067C96A7AE
+:105B6000A7E07802BF6A8B85A4D3712FA6D477C52E
+:105B7000D04F37777B6B0BE83A765BBC33A7A1DD60
+:105B8000ED9A02FD4FA935D9218E1DEFB64B1007B6
+:105B9000411207BE38CAC621AA4B37EFA91CEE0234
+:105BA0004F020E03E9AB81F0F310878F837F37F24A
+:105BB0007506FF6E4E67F47F6DBEF6CA40F7B144BE
+:105BC0005B2DC3FCCB981CEAE3EB3282FB8D0BD23E
+:105BD000F57C2DCA61F87A417A285F4FE8D1F33518
+:105BE000B570B93E45FE726C33BB993FC9F8EC62A3
+:105BF000249BEF8A74A6871CA03F28FE1C5EB6EF8C
+:105C00003A95D319A5A03900EFB66D11B89F20F8C9
+:105C10003E7626A930C3FE2DE81BA835533B7113F1
+:105C2000ECDB3A2D2AEC239F3107104F67A8A3DA4B
+:105C300086F8F4603ECA994337307930AD4FFFB8EB
+:105C40004D507E7F04EE2754CB9D48D72BAA09EAFE
+:105C50008FAEEDA548078B6A5325A0B3253BE225FF
+:105C6000F89E506537C92172B1B445467AA274BB1B
+:105C70002E3D047EA5DE6619E0323A51739AE3A9FF
+:105C80009EDD367546685CE8495A5EEF0CC685684D
+:105C9000F96731C3061F17DA987ECBCFD68DA04A9D
+:105CA00024CDFD148C7B4EF56C04BC94243763BC6E
+:105CB00073B079104D3CAEF4C1236F6DAFA7EBAE5E
+:105CC0007B34F0087CBD17E2AED9903FC0E2AE4D08
+:105CD0009DC7301EDBC9F9F9EF4ECF0B30EEECE675
+:105CE00029FAF86B6070E32671BE251F10847F923D
+:105CF000A75986B884900BFBD21384FF28C1FE9B62
+:105D0000E007902B607F8A3C088887D9128272193D
+:105D1000CA71217A757D2DB583C2F0D9C1F498B0CE
+:105D2000729074FEFDD73FA0FE7E137C6272F1601C
+:105D30007A88DE7FA2F6E3211A8B7B60BCE97EEED7
+:105D4000433EB7DAF5FB2C9043EFC828FF8B222C9B
+:105D50005E09F687DC44B50FE1FD019B744A7E1BAA
+:105D6000F53F9BFE261137C4CFFE26E3F3B91F791A
+:105D70006A52C09FEF30B9A82500F91448C7AED1C8
+:105D8000C467A5F4D7CEF76BCB0FC6B8CDF47DAF03
+:105D90006445F9D7BB3FCA0B7CDD6B33615CB9EB63
+:105DA000B50884EB85F428EE5FFB747EB8D8FF88D5
+:105DB0008CE8F943196DBF3592F5BB3592C5E9B64C
+:105DC0003E9A1907F6E740FBE3652D6918E713F1E2
+:105DD000C7D4806A6249646C1C2540707D62BF7CB8
+:105DE00013E46B140F9CAFF1D7F4BE7C8D00D0533D
+:105DF000D3AC9EC33047A31F36E4E8C7FBA19F2165
+:105E00002D2C4CB0E9E80A09D6B9A92EBC1F26E80A
+:105E100068138F7B85E4457CABD32FF509D1A9218D
+:105E2000F253B47B9AE7459476CDDD0B761EE5EF11
+:105E300073A1FC3DB5E091C870FBF39E961F625CB8
+:105E40007420FAF79888162EEE373A83CB5B25300C
+:105E50001CEDC1372E46A961F2253CAF991C0017F5
+:105E6000119FE93FFE8F70FC61197DFB7FC307B373
+:105E7000FF679C77B7998C0CA757049E8DE38569C3
+:105E80003FDB15D2DE6321DAEE98FEED84DDEB9187
+:105E9000F8FEEE8704F5ABA0130AF77119F47BE165
+:105EA000DBF3C64541C2A1B559067970A1A32B19F0
+:105EB000E25603F987623EF42F235CBC858EE70926
+:105EC000878769194CBF7ACCCC0E95CA0FDD03F3D6
+:105ED000F27C65912242E86C22AF67DCC7ECFCEAF9
+:105EE000BFC7A19C34FB93C3C1CFB8BF3911829304
+:105EF0004CDFB171395C5ACB49454412C60BC856C8
+:105F000015FC40262FD516827C3E4672E3BAEB2064
+:105F1000E8E2003AEFC63CC80B4765AC57789FEA09
+:105F200003BF89EA85BB017EA544DB6B4A0BC24BEC
+:105F3000D043EB8BD44ED1C5AD18FF08FF75248F2D
+:105F4000FF5055E30EC5DFD059945443E4FE30CDE5
+:105F50004A9490385BF222BBAE3CB2D9A9ABEFF4C5
+:105F6000FA25E02B678BAA7B1F94576CBD23BD6479
+:105F70000BE8FF4DA407D7378ACF678CA4217D5C3F
+:105F800038FA4902C4257FC0F987AEB705D7DBA22E
+:105F90005D08A50FB1DE6BADEB8395743E94EF3FCA
+:105FA00002FF9C3E673F70521A8A70B7833AA07A0C
+:105FB00091B51BF9F031F423473677A31D3FA76550
+:105FC000BF04FA8BCA0D6CB769A5159FCFACB4A3FB
+:105FD0009F2FF03B82D6833C256F05C9867D81814A
+:105FE000F4D3C68C41EBA78D1961F493C91A7813C9
+:105FF000F6C11B3B6515E860CDC30998FFF25CBB99
+:1060000084FB2E073B59FEDF73AD51A847C4B85F30
+:10601000BE1487FB3F5FF27D40D2158FF4DD14CFB5
+:1060200071B2361EF7C97BF93E6447BAF61F1921D3
+:10603000F2E0B9CE6F22417FE4893C5B83DE01410F
+:106040002CD1F6E013011DB7A614AD93615D7768FE
+:10605000E32265E4F7DD8C5E997EFAE5AE0A9316DD
+:10606000829F0B1D5FCF39A0F6DF5F12FB50627F6E
+:10607000EA4DA7F66A4688BC36EE3B19F74BE45862
+:106080002BE669BBE42897ACD7B748876B32983EBC
+:106090005DB33F0AE1B8262306F77BE97C8FC03861
+:1060A0005D360B1946DF5F381183F5C4FCE97C0BC4
+:1060B0008F86996F932930E780A49BEFB1ABCF57C0
+:1060C0009FCF2CE6D7871F1E2F906D0AAEA3974453
+:1060D000B900AFED16D7090DF4EF3B512C7F8AE3E1
+:1060E0006F39E7CD5E8A2F89E2ABB7E34224D0F166
+:1060F000C174ED24CC431E198805FFE560E7851CBB
+:10610000E09781F60D958C8ABF00BE20FF0FF166E7
+:10611000D72EEC228C2FB5ABB4CBC8A8380BF5AF7B
+:10612000033EDF5C0F7C9A949875A1F697C4E5B3A3
+:10613000911EA5CEFDFF03FB01941F311FD53B8AA5
+:10614000F8D650B8B51670BA9C4954169FD1D34BA7
+:1061500047BAC79CE908F2F155E01309F57E99EEBC
+:10616000898627CC23792CCA291B94A95EDB6B492D
+:106170000DDA5BA3D398DC0BC413CC5F31EEF7666A
+:1061800064CC48CAA4704BCD564DF6FCEBE2879127
+:106190009957859F1FE9A291C3A911F619295CC8D7
+:1061A0003EF3595DBE80010E07D33D590C0E413AB6
+:1061B0005BA35E151E790C1E5A21ACC366A6F402C1
+:1061C000409950EFC4BC18D57D37EC7FEE5CC5E03C
+:1061D000D0FB2283C3EE2E13D2F516928BFC996B63
+:1061E0003A3F07FAA7F26702F453DCDD66827CC20D
+:1061F0000C9F6A82B8724E77BBC97475BA2DCB44B6
+:106200007DA14DCA64F6C5FD8087BC5D2C1E73154B
+:10621000BAADCC1C7F5D70AFCD1C3F783944E9CA64
+:10622000134A5783CD4BA2F4419213FAF747480F14
+:10623000C6FDF7BF1281F27EF91E09E5D3F2D73F02
+:106240009B03F05DFE9B0824CAAADF44E2F7F3FB40
+:10625000D8F72FCBC3EF4FDF9599807AB6B1FD3ECB
+:106260004FA87E1776C34FDDE7EDE972709F2F715F
+:106270001A3B6FB22652E49BB2FDBE584E6789238B
+:106280003D6ED05389D52C9E141BB310F7FBFA9F9B
+:106290002B617CEBE0EDEC7615ED07E33913398AE1
+:1062A000E5E539C8FAAF004E8935FAEF8E981ACC79
+:1062B000C77318F6FF04BCBD99DC6EB61027CA5927
+:1062C000C33EBF78FE2593DBEB6BE34DA1F204F4F4
+:1062D00000C07585CD8AEB5EE12089B51057B029E5
+:1062E0002E1CCBD08F78C6BB4D440D3D2F5313458C
+:1062F000D410BBC8E149D09587CE1AAEAB3F4C4B0A
+:10630000D57D4F5E94ABFB3EB279ACAE3CBAE506B0
+:106310005DFD140A80D072DABA5B74F533DA66E890
+:10632000CA599BEED6D5CFF1CDD57DCFDBB144F7A1
+:10633000BDA07D85AE3CA6E307BAFAF200F6B880B0
+:10634000B32CEC715BB1067425DBAC52A8DDF222F4
+:10635000AF571E6B45F83FC2F5F523360BEAEB4706
+:10636000B8BEEE72945C755FE69FF5DFDE16F4C092
+:10637000EDB50A1E2FFBF280C504F4B8FC20A58BF6
+:106380003168AFBD9DC9ECB5E9F5B8FA8005E45EAA
+:10639000F700F920EF65723F43A17E4C187FF09320
+:1063A0004C5517B713FE03956BEF73FDC2FC26D255
+:1063B0002C831C1072A9299AA09DD7146DC73C9FED
+:1063C000DED84B99C04F545E7D0CEDBAB39F683E4A
+:1063D0000072AA3302E5D45BD99FA03F7E4BCB422B
+:1063E0006CFF62A69DE1C5E252ED28A7F4FAF7A87A
+:1063F000B9BB16F07074BC4C56811DE42A1D4AAE20
+:1064000002F777C0DFA676F2B62C82FD5ECB5F3D49
+:10641000BA7211E64D0FD4DFD1A2488C9BD6025D33
+:10642000858C1B9DC5E099C19FD41045BFF3DCAF9F
+:106430006D3E2FF84B63DF8D2536C893F9E3382F77
+:10644000E823D27D3FECDF7BBF8EC1B84E6DD1BB60
+:10645000E35661BEA89BF97D13D89A6F7AF9ED587F
+:10646000F0D76B771F4CF286E0D1E8EF65F0F511BD
+:10647000A52713F34E5F3D3344A5CFDA570E25B160
+:10648000B8923EFFC5E8E7D7B62CD7D167E3A54859
+:106490005D1E4CA3D26D017C345E8AC1F7BD99FAB2
+:1064A00038C080F01A243C8DEF053C8F169D1905ED
+:1064B00071FA2F23C3D3F16DBC9E281BCF2F0C94F0
+:1064C000273F81B7BBE09A3814E24CB5167FFA60DB
+:1064D000E212024E6F5D6EC07311BF1EE05C44514C
+:1064E00016DB37F975F602CC6B9E686DAE04FD3D88
+:1064F00091C73FC3E4355767819D7BE25F93D73CEB
+:106500003D8BE387E70D0FCF52C3E6355FEBDCC968
+:10651000540B954B61F82BB70F7E7F9A398ED2F1D1
+:10652000FDBF30DB615E0DA0F320DEB2C58CF1D77C
+:10653000B72F471088877FB6D9FC3CE4BB2CFAC53F
+:10654000C1114F40FCBB2802F3F11AB69859BCB6F2
+:1065500028D2072187455BBE3704F22EBFA07CBB43
+:106560008CCEABE1170ECC077ABBEBB12180A73301
+:106570009C9F177DFBE33B00FEBB2DF6BC22FA5C23
+:10658000B64BD2E5992FD916A92B8B7C22813F22BD
+:1065900005F3CF552A4F5BB2F4E768C605F7255AD5
+:1065A000B2B85CBD9DCE77F9F80B16C0E3C1C351FC
+:1065B00038EF376264F473FD457FFDDD185AAEFC99
+:1065C00056C1BC7E637E12218874B290E71156BE1C
+:1065D000A2F49D0380B27F6533F2096D17531D92BB
+:1065E0006F5DF973E64F5746B23CE001F3960CF944
+:1065F0004AE29C45BF3CA5E0390B9D9D22E8E6A9F7
+:106600002C3D5F1F3CCCF292161EE576E535E4E6A4
+:106610003BB08E0CC0D75B75B06FF93687C6DB9781
+:106620003F5B3B8C963F9B2041648E7C76393CDF00
+:106630007C26F4129C0FC80EE2679A6B715F19D822
+:10664000F2D609F7E9CE2D0C5EDE5C5D9EDC956529
+:10665000C1F18DF2DD48F7FFBFE47B6DD1A1515E42
+:106660001B3E5F80E7D9DD4C3E1AF9DC28CF730D65
+:10667000723028C7659D1CCFE5722028CF2DF89D6C
+:106680009A69B81E6F89E25B23A1FFF31ED07D7E5D
+:106690008C9A584E9BACB5A7466B57F747FF2FD443
+:1066A000EF4AD13ECAA27C34FA97B955608CE7ED27
+:1066B0006A3301FFF60E608714A41AF282787C48D0
+:1066C0007C3F9B555E00F9AA7B54F614FC594C990B
+:1066D00090EF2F9FCD62FBCB3F01BB67F97F5E44FC
+:1066E000FEDC12A5391558CF708B2B74FF563C2F4A
+:1066F000727E1FF87CAD3EDFF9743A6178CFCED65A
+:10670000EDCF807F8FF90107A2106ECF3ADD9701A0
+:106710000EED4EF7B730AF32A7FB1F59217859CB9A
+:10672000D7A998F4716BF12CCD16F4EF413DBEA0C2
+:1067300022BCFC4DCD6679C1E54FDF350AECCEBFFA
+:10674000ECBF7B14C8C7AEA74AAF6A876EE0FCF9FE
+:106750006F5CEEC7F3B8E34F816F683901E296B41E
+:10676000FD028B27333EA41F73763CDBEF2EFF83A5
+:10677000278DC2E5D47A19E5F7A9181667FC2446D7
+:10678000A9D9C6DB25E9DAB179CA40F7948F951803
+:1067900045775EA21468DA31F03A4BB3991EB51012
+:1067A0009715DA5B0EDC6205FCCA92DBCEF2D219D9
+:1067B0003D4CA423003DFC98CBB1BF3BB5A26C6C13
+:1067C000C7F4ED44AE6F9518837E1D115E9E89E778
+:1067D0004B4E7709F473A7D35D9AED80B817C903C0
+:1067E000BE698F0A9FE77313C7DFDF853D4662D01E
+:1067F0006FC6F164DC577567635CCB5301FDC1BEA6
+:10680000AA59023EB0F3FA6E89C52B3C37C377E232
+:10681000744BD328BC4BFE4CF03CC7DE231512EC66
+:10682000FF2675574920C79238FE8CF3E8E170DBEC
+:10683000C3F325FAF31DF32B6670F8EF513DC85FE3
+:10684000AD299A13FC55C8CB03BC1AF32C7E99CD05
+:10685000F6D5B644F5E0FEA0F76E82F97743CBBCDF
+:1068600012E40F25D7B695538C93F9D9CC9F4FA836
+:10687000D19CE0870F775AF09E8AC1F25B7EBB1BEA
+:10688000E325C51A3BAFBCA9DB1B9949E735A45BDF
+:106890002BB7D0677ACE105CDF50D2BC8AF909AA38
+:1068A0002EBFA958ABC07D7231EF92F9CD6B2C2A67
+:1068B000E6C3ACC80EF16B929779C3E63B19F7B902
+:1068C000D708BEE4F908C53CFFA078DB53984F50C9
+:1068D000BCED66450A91339BB2CDB8FE3387968CEA
+:1068E00086F50F94C7DA96CDF0F0FD6C265F06CAE8
+:1068F0001F5BDF2717FAE58FADCF7684E4D7349E90
+:1069000047F9D798CDE4FCB3905743E1FAEC7C917A
+:1069100057B34582F5EEB5B44FD905F35A6EC23C74
+:10692000A6BEBCA2F92CCFADAF3DE417D1F7CF2E58
+:1069300062F945C37C1B705FE26224CBA3B8B83D0B
+:1069400082C0B9A467B76D1C02E7109FD54C6807D9
+:106950001AE70F0782785EA419F225018F20AF0491
+:10696000FEFAF28F78FE5ED7F69771DE623E9450A3
+:106970002C00F7F41C36AF253B764F01E21FBE2CEE
+:106980004182B89D98D7B5E4FE4B9C2F064B872FCC
+:10699000E430FE08A31F5FCDBE3EFDF806E089EAA5
+:1069A000C703D0EEBAF523D78B424F8AEFDD9C2E7A
+:1069B00066660FA81FBBB3C3E84715F29E31EFC848
+:1069C000E4DA1E065F3378BF37BAB54AE0E7A2348F
+:1069D000ED4FD0CFC409BE8310072DADF11E047E4C
+:1069E0002F96F879EB294C0E24F690FD10838B3FFF
+:1069F000D1E3863CE5AA6C966F71C36937EEB3C7E5
+:106A0000798804EDC53D066D09ECBCB371FC499C69
+:106A10002F4C4F06301F2EA9337C5E6A412AB3D714
+:106A2000A8BC3C0B702D194DE5694A7F791A067F89
+:106A300017A07ECE2EFF01A835363E3D1ACCAAAB5C
+:106A4000E0EFAF0C7FEE4BF014F8CABD22EBE2781A
+:106A5000025F57F8FC6FCD70FF03C639CCF97B207D
+:106A60003CC6E650FC8D07FA66781479C03B0D767B
+:106A70006A450EC3CBE41C7D5C2804DFB139E3FB1F
+:106A8000E35BC8F1BD47F6C880B792AAB635800768
+:106A90008AD7A41CDACF0D65FAFC4F235E853C34FF
+:106AA000E2D78857910748F1313A278CFE12FD183A
+:106AB000F558889CE0FBCE6A5F7E07D8CF224F5CFA
+:106AC000AC43F0CF240E8F1B35ADD2C2E8B410C654
+:106AD0009D38CB77D00C74BAC87BD0124AA78B09EB
+:106AE000DBAFE2F348EEF1E27A869DD0CAE179C3EA
+:106AF000693FDEE331B499AE8704D733B2FB38E6A1
+:106B000063C2BE2CC49BF61E3980F31ED1DDC59E28
+:106B10003C8FC8A86F83F9B7AC9F17B8FC6A3DC714
+:106B2000F2F85ACB99BEBD37C35D99837CECAE8237
+:106B3000F9AFC8705743B92095D14D6C8EFB6628CC
+:106B40008F1C40DFDF9AD3B74F3D1DEA253D40BC87
+:106B5000E21E1488C327412410B6F09BBD9285C263
+:106B600035C94DD0EF1C9DA8AD82BCB7C044E282B0
+:106B70007C80B83A7B39C02B61916B3FC0B3F51C68
+:106B8000BFCFE53E82E7BDFAF2ABB454CCA700FE1E
+:106B90000DE5977A3E8FFA1CC607D4DE9993C3E6BB
+:106BA000A5C1BC84BD23F87220FB2584AF1BA0FDCA
+:106BB00075F0F5F29CEBE3EB15398CAFEF8776D7E8
+:106BC000E2EB1FE4F4F1F543D0EE5A7CFD28E7EB4D
+:106BD00017AEC1D73B78BFFFC5EB87E1EB47C3F1E9
+:106BE000B5CAE94EF0C59E2363A3215F601BEF2F5A
+:106BF000447E6F80F6D792DFFF049F6F867EAF657D
+:106C0000A78A7E05BEAFC527B1B91E8483B0474FA2
+:106C1000A733BC0BBEA7FCF29F007FCA2F3B39BF36
+:106C2000FC92F18B8AF58CFCD5A7EFBA4DFC1E11B6
+:106C30007B7468DCFBCD9C7EFAEEE59C30FA6E241A
+:106C4000E1F0AA61726404F1CAB1D06FAD1DCBF658
+:106C5000B37674F3634F05BC00B7F77298BD513C2F
+:106C6000403CE1779C4F92BA2B50BE50781ECA0927
+:106C7000D16349C43E15FC9CCF73D8BAC64D701F72
+:106C800004B964777B309FDB91CBE022E044DBBF2B
+:106C9000134EEEEE037CE4F7F71B8C7838C8E7FB65
+:106CA00039A71F63FF42FE40FF05D8BF6A82FE4539
+:106CB000FB3F07E5D047B08ED2079A65585712714F
+:106CC0004783FC1172928CA0ED8BFBB7FF34D8FE8A
+:106CD00053584769336D9F1F6C3F92F8315F2761AE
+:106CE00011955304EC7717DAB3EB55CFB91C9C27F9
+:106CF00061F2AADC84F2202BDD8D7C174EFF43FD70
+:106D0000EBD1FFB01ED0FF83911357383D81FE8732
+:106D1000713ECEBA86FECF65EB8ECBBDBA9C88CFD6
+:106D200065FD3A7207D6FFB961E4C41ED58DFC1427
+:106D3000868F12721D10677127423BCA4749501651
+:106D40007A87B61B02EFD7AB0C8EEB6B4DD9685F21
+:106D5000932857387F262D3766B0F945697C9ED732
+:106D600095FFFADC8F7A2C006F91A722C635E6BD1D
+:106D70000A3C2EEF94C6415CAEFCE0658C93F4EEC9
+:106D8000FF1BC649948CB9E360FCAED758BC44E401
+:106D90009588F157703FB25ACE6F8738EDF91D16BE
+:106DA0008C7FCA44DD5846E7D374C44C7C2807D98D
+:106DB000F965B14F6BDED1DA0D71793309B9670727
+:106DC000F59D1A0774693EC2EEBB2149EC7B33B1D5
+:106DD000AE62F730EAF769E3DDFA7DDAC41AFD3E08
+:106DE000AD88232E256C9E0E8F7EDF76E82CFDBEAF
+:106DF000ED304DBF6F9BBC68AC611F57BF6F3BBA96
+:106E0000A5C2B08FABDFB74D5B37C3B08FABDFB779
+:106E1000FD8C343F5D46D79D2BEEFBF1BABBE15CA8
+:106E2000F47C3EDFAC4DFA7DDD2F76D6E07D21F39C
+:106E3000797C3BC7A7DFE75D2A2F433A266DEC9CA0
+:106E40007333FD07E0A690C0E164C83FF0492E3FD0
+:106E5000FDDCB0497F0E7A71C7166CB7D8A77FBF2B
+:106E60007487BEFC402EBF0786C7BDFBD3410CCB49
+:106E700063D8CCE2FDB237CB40077A7CFC6FE942A5
+:106E8000E57411E1D4D345A4AAA78B8637F796C041
+:106E9000BA8DF08DCED6D38B11BE36979E5E045C34
+:106EA000A99EE4F9386E5CEFC20E893C23F587EBAE
+:106EB000A2CE0DAD700EDD0857427CB8EF6C84AFEA
+:106EC000CF00DF73AAF63CF0DF858E07F0BE1FA26D
+:106ED00069E3A0DD55F263FE83D51F747E4C3BD47D
+:106EE0000FFAC9FAFC985EC8E31A430691C775F019
+:106EF0007F20AF2382CED00CF1C6092E6BF8BC2DBB
+:106F0000EDF55CD4336E82F19E3F10D71A5A6B8D2B
+:106F1000AD24EF1A718103B9684769789F466937D4
+:106F2000CB73234AB71DE2BFE1EE6F349C6B3A0A84
+:106F3000EDFFD9FBF184DD48EDF43FE632BDFB2ED9
+:106F40003CFBEC746EB7097B7BA07EFAF25C0678A2
+:106F50004A0764CCB30A4851AE70F70D9DCE95C276
+:106F6000EA0DAA274EE73A42E25BDFBB7018F4074E
+:106F700085F717F0DE66A3FA5B1A94FEEE05386D0E
+:106F80008C8E45BA0EBC29FBB26883F356350ECE03
+:106F90009F1BEF2711794FCD70FF08D52765E7B309
+:106FA000E3AE96675066B89FC6788F47EB589E67EA
+:106FB00092C7D6F96B7E8FA0334FD29D9711F1A85F
+:106FC000A6752CFE0AF70E7686F4E3CC6387566E20
+:106FD00056CB9D790E8877B178616B8A847642AB07
+:106FE00024A1DDB039BDC29947FB3F945B3E14EA52
+:106FF000D9F9B84E88458FC7F33E381FD5705EEC7F
+:1070000018AF7F2CB7029FCE3CE16FD97301FF13FD
+:107010005537F66B91C3EFAB8FCC63F64F35F0B4B9
+:1070200023C84FD7734F8325A9FF3D0DC6FBCFDC87
+:10703000D9F62E5007C67DCF17AF754FC3BEF0F7F8
+:107040003400DCA31382FC5092A7BFE7AC23AA074D
+:10705000F741036FCBAEADA4FFBA6FE6785CCFCF3C
+:10706000853878FEF728BE9FD2BF3E83D39601E2D3
+:10707000BD13D5F26A80F307E99E9B010FE29E9D46
+:107080000E8BB606FC8FC04B04E791ED2307A05C86
+:10709000E055318FBC35C51B8DF7011499D09F5732
+:1070A00037B51D8C4CC273B609921A942766857841
+:1070B0006D94CE16C2655D60DFF5CC3D60A3DF1D2B
+:1070C0009B6F93E0FE9636D256190B76D766123632
+:1070D0003E58CFE9696AF9018CB33B02ECBC5FFF13
+:1070E0007A26E1276AB08ED280364E4A0DCA251420
+:1070F000B9E03F75997CE1E2B559E9950BA15D8155
+:107100008F848DFF55F37B66EA54CF32ACB7CF8FB7
+:107110007E518390EFF34D04EE37BC9DCBF3DB370C
+:10712000B3BC5C72F9CA15B924787E8AF64F403E2A
+:1071300035CCB4E1BDB10D9D2978FF16F14878CF6B
+:107140004B53E7310F941B8A8BED106F76BF4F24A2
+:10715000B8970DCFECA11C54C8A742DFA2FD9084C4
+:10716000FBFD33385D8BFB94A81E591F4DE1DEB04B
+:1071700079D501C8EB7EF779DA07FD7442D64EFC6B
+:1071800090F6FB5DAAC45AC6C2532175188F766269
+:107190003F33793FDEBFD171ADC171BFDBF926AEA0
+:1071A000E7849978AD947ECD156C68F30FE230DFFB
+:1071B00058E4AFDC616DAB063DDB6B0914C2F9A985
+:1071C000DED7DE1B09FBD41FFE9F0B36B08FFFAC52
+:1071D000046CF0FEF4C37FB4C1FDC81F3E2CE3BEB7
+:1071E000DE1CAE7704BC9FE7747E31CFF30CD0E792
+:1071F000BD2BBF2D09CDA3272D0EE49FC53E1953EE
+:107200001E04DF2DDD110D16515FB9B13D5157162A
+:107210007AA411EE6B0D43472738BF2CDEB5C502AB
+:10722000F70B5CCCD376C1F8A715463FA7F7D97CFE
+:10723000707FA298CFDC5D4516B04FFEDC1941FC93
+:10724000A00F956E333B4FE6AE95283D681CEFC608
+:10725000791E7E3D1AFB5BF014934FF574AC160A51
+:1072600057AD7331CA21E33A167CA84E86731C0BC6
+:107270001E9508ECAF40FD8729DEB4961F639EA8DB
+:10728000719DF55EE37D766E948F0D1CBFF3D6E99C
+:10729000BF37743E8EFDCC27EA7AB0A717B419BF6A
+:1072A0004FF90CEC9F06833C7B278FDB5B25A414F6
+:1072B000EE9D39604D8BBBDABDAF6757DA91383F31
+:1072C0005F69C5E7E995049FCFE4A908F7659DC705
+:1072D0001E04FA59DEB1DB02FD1CF48D4F82E3A3DC
+:1072E000533BA72860774DE5FBACB3F9B94E74AAC0
+:1072F000D979CE1EC053558CE13C275F771DC7035B
+:10730000B126229DD5C17A0BE1BDF275E87ACE1F78
+:10731000498BC17D3AB1AE52BA2E79F0EB12EB1126
+:10732000EB13DF1B65763FB0B19DA0F36738DDCD71
+:10733000DF765BEB700A8A35AF7D36AA87F9A968DC
+:10734000DF5772BC555A1F47FBBE92E8EFA5A27FDC
+:10735000C7817F05BD35109702CC6BA42B816712C6
+:1073600063F6F2FBF9D1FEEFA3A7CE7F43B8087C0A
+:10737000537E71F2FD3427ECA751BAD2D9DB948E3B
+:1073800074E5056DFAF297E69E51C0EF0D86FBA1FC
+:10739000BE34E45F88E7A5BC540607D53D19CE0787
+:1073A0002C209E56B6EFCACE1F9D56DA0EFF10F85F
+:1073B000701BE3833F73FCB7E47B46E783FE52DC3C
+:1073C0008520EF2B560F939368BDFAF5921DF86B4D
+:1073D000DEDAA2C9C09763891BFB9B9D18DE7EABDA
+:1073E000C8677A646EB39958A8DD3F978E01726EB4
+:1073F000EE3E19F91EF2A6A60D817B26183E1A1F35
+:10740000DD6D19469F8B9A1B98FDE0637C23EEABE4
+:1074100015F427E4FF92F5FBF1DE0DEAB7E8F8ABCF
+:1074200009F2BD0B818F0DEF9B6F463C3411F6FBCB
+:1074300005027E37E573BBC1455C409FDA83362B7E
+:107440009C17B9D6BA49FFB803C625CE1FC940BBA1
+:10745000F3BCAA0E857A1A1DB31BEC48452B85F7A1
+:10746000145EA8A702ABA2F11ECF939764A2427E3E
+:107470009B5D2B053BAAE7FD9178CE5DD0AB586FA5
+:1074800093753DD26B13D1FBA3F5D4F181FDCFFAF7
+:10749000ED8998D744FB2FEC007B63BB19ED092FD6
+:1074A00059E184F3F69E47CC2827E776C4A33F3CF6
+:1074B000772DDB2798BB2B1ECF07527F14EF1116B9
+:1074C000F838B9B6D2320CF19582F7F3900E3D9DA3
+:1074D0000B3CF5F7270D785AB7FFB053EDEF5F86F9
+:1074E000E0E9D400783A158AA715F95C8E703C91D2
+:1074F00087B9FCB9EF5006DC5F75BE3912CF83182F
+:10750000E950E82932FF06CCBF1271AA9AE10C2F8C
+:107510004471619EE285F5E3116F467CD5FC631EE4
+:10752000E285BC6FC3FB8B67A7B17B5BEE9518BF91
+:10753000CC5E33A506F4F9E3F9CCAEF93D955BEEEC
+:107540002C6A8F53B9E5A672EB8F549E41F9DD95F5
+:107550004E2CBFB752C5E79F5666E3F314DF5715AD
+:107560007C4409C10276E3867C26C736E48BB8E109
+:10757000034E302D6AFEF1C7F1F03B0A0EEF943B4B
+:10758000AA471272AB5BAF0F67CDD4EBBB1EB37DC6
+:10759000B213FCDB47D93D4C733D37EAEA1345B5DE
+:1075A000C07968923D2EF81EF94DB5C07DE977D5BA
+:1075B00026EAEADFB12E5957FECF7C15D77D5B4D09
+:1075C0009AEEFDDD7579BA723DDC9B0874AE4E40D3
+:1075D000BE7980E75552079DE1859F23FCBAB974B7
+:1075E000E8F7E97CBF3E6AC6EF467C08BCCEDF24E4
+:1075F000138DF6376F13955F748AA7DA289E68BBE0
+:107600002F4ED8D00F69DD35EE9D09B47C729719E5
+:10761000E30727D726FE04ECA793BB1CB1843EB535
+:107620005699DB1976BC4F49F45BB976159E87A94C
+:10763000F745B8D09EE8F2FEBB28ABE0B7C2248184
+:107640006F8ECB3EBF84F863F1839D11680F9FA6B8
+:10765000761D5C3D7B5A226BE10907E6E3E8F76F94
+:10766000BA1D3EE0EB9A7FC86E27D0D3CE48767F16
+:107670000838C3F4FBE7C732B63E86F4A5B6FB91E3
+:107680007F23D05F98D7C3D647A4B1C980FFD3F179
+:10769000C41D4F27D1B8E2BD8F148AA7C599DD85D7
+:1076A0007EDAAE2EC5EFB893B63BBBCDCCEE97A33A
+:1076B000FDDA69B9F197115B983C710FBDAD2014EB
+:1076C0009EBE425877D670CF87F9B07FB0D057882A
+:1076D00072ED6107F29511EEA72C1AC2D70B7C2030
+:1076E00005E56490CFD87E10156EC340DECC33BB69
+:1076F0008680BE3AB5DE8C7629D527B1B7611C6687
+:107700000FD2F129459D0CEB3EB52E8580DC12E3AE
+:10771000CE5D2FF37B42285D42FD0DB2466D072200
+:10772000F496779DA491A1FDE9E6FEFB4A312FDC9A
+:1077300068FF8AE7979457B5103B62C96BEC7E7E71
+:1077400052DCA3CC2C085D07FB7D05A24DD0E56B78
+:107750002E4BFDED473126B46BE2209E7EE6B88CC1
+:10776000747626B5ADC44949FFACE940C9F769F95B
+:107770008B69DE4F155ABE6FB416554097B4D4B41A
+:107780007E14F84FBD9D9FFC04EEDDFBFC45331CD1
+:1077900087274B762E1E8D711F6E7FF7975BE2FE5B
+:1077A0003FF730B83F65A9DA8E7A5C854372B87EC0
+:1077B0001FCE53E875FB9312D858E493F1B6C7C0B7
+:1077C0009F9E67389FF28999D909230A989C12FADB
+:1077D000FE1E5E9E6762744D5E97300F9CF07BE5E7
+:1077E000853E10F25AC8FDFC02665F08790D997655
+:1077F00020B716C2ED2D749DCB7644F87C29D8D6DF
+:107800000E705CCCD0441617A8D86E89E5C5A78148
+:10781000971A4837CEFF73B36F61770AB4DFB23679
+:1078200001DB9B5D18A7E5FA05AEB506B9D4C0F932
+:10783000AFB14DF2F9917F989E5CC0FB27A06742E3
+:10784000E4583FFD62D02B0BB85E5D400C71DE3614
+:10785000BDBEF344DB705D4BE8B8A03F83F3A2F6F6
+:107860003385DD42CD77783ACE5B72F9C2CCA38105
+:1078700004FC907FD7B88BC5BD8DF332AE63B0F3F7
+:107880005CE8BAAD2ABE38645CC3BC05BC31501C90
+:10789000820701F7855E06CF859D12E2EB2FDC5E45
+:1078A000A37F189F36E2BF8178A6439E42C39354BC
+:1078B0007EA604E941D0C1E2DD3E0BD8CB5F90B695
+:1078C000D818CA07CB36EDBE63A20AFEF331F443E3
+:1078D000EA12FC19A6784212BD2F3D5D73D3B5E3C1
+:1078E000FCFF2A38C12AE07E5A6C47E1B2609BEC6B
+:1078F0008E2CD4D5E379DA5E84D722AFD70271D04B
+:10790000453CAE78AD793629EC3CEFB5E7CBE0F8F5
+:10791000AF9EF7D3057A3B36681F6584F5B7FAEC5E
+:10792000A26BE8E30FCCFE91A08F032315D4475F31
+:107930002BAEF7CA93403F67A0DF3090BC5DC8F51F
+:10794000F202D0D3F4F9E9A6BD786EEC2F4FEEC564
+:107950007D43CB8B0B62C15EFE74D3BC9F40DEFCCB
+:10796000A7BBE6A15E6E7846E865CD12AAEF2B377D
+:10797000D53FF77F804E7744E20985855D1AB7C70A
+:10798000A9FC03B9B889C93FF224938F0DB1ECDE8D
+:107990006FAABFB2A0DE830BB52CA0F790F7A8D7D3
+:1079A0001E9CA795627B62F7B37B21ED7ED05F4280
+:1079B000BF0ABD7B7498D655007A413EFAEE4374F7
+:1079C000FDE7F6C818D36994B78C82DF4318488E58
+:1079D000FFF3F036F5C13B6510F09E0BF0467B8857
+:1079E000C1FBE3750CCE9FAC67706FDD95160B7E07
+:1079F000F0C7EBD2D00EFA785706C27BFE6314DED6
+:107A00006807AB7A3B681D8537D8FF006F3AEEDC1C
+:107A10002E95C3DBC5E0BD8EEBA1F5EC39BF1F5C35
+:107A2000BD986FFAE0F3112ED0EFA723FD0EF053AF
+:107A30004EEF9609ECE7F7D949DC9E1170FE86B44B
+:107A4000FD3BD855FDEC9B0D11C44EFB5BFC920D2C
+:107A5000CFD57C2E950F05049C6DFB6D2C8C171CCF
+:107A6000BFCFAEB954106AD70C123FCB8907F3DEF3
+:107A70009777FEF604D8F570BD0AF8FDCBC539F846
+:107A80000EFD397849059906210A97D50A7430C246
+:107A9000784F8086BF0F7131E3AB392B909F0399EC
+:107AA000A1FB414D517E33C4A302BB25C477E30340
+:107AB000E5B1E504F6B39A711E8E42A69F25B71B69
+:107AC000E38C11946EA2E878CE4215E72BA97616C6
+:107AD00077DC4CC7B505E76B7C3F1D0411E8F71850
+:107AE00013EA77E3FA27F3711A6513FA21CB2CCC4A
+:107AF0001F11791319FC7B4621F3EBF30AD93E439E
+:107B00006F2441FDD1BB21DAB70AD75785F14F85E4
+:107B100030FA5604DCECCA97BA7BCA797C017EBF86
+:107B2000008CEAF9113CFE4B552DB4BF87B7BFA7B7
+:107B3000ED6DDCCFA39ECC2F40FFCE6E8970813DD2
+:107B4000EB85FBAD28DDFD388AEDBF90A43805F844
+:107B5000EA6E2E67EF697BDC03FA68765BB41B9EE6
+:107B6000741C2FE1F1D662D8BF1D6EC1786B9DB534
+:107B7000E74530AFEF757EF23D2B5DDA2A13B35F38
+:107B8000562510CC3B1943CD7888DFD24FFBAE246D
+:107B90005E8D7EF4F1E46510D765F7B579519EC826
+:107BA000265D7919FF5D81BAC2CC3B9F1C41C81F7D
+:107BB000885A00F85E06B0017AA88FC3F8C0AD10ED
+:107BC0005F4E80A782743643215E137BAE8BC173F8
+:107BD000FE2CDE3C9DAFFBBB13883F8EAED7FFA6CD
+:107BE0003EDE7DA7DFE4CFA278B855F1EF07BA36C5
+:107BF000595533F8079E1A692CF8CDCB560F6EBE37
+:107C00004D854538DF6526139BE74312DECB700FA9
+:107C10006572A0CF390AE992C732FC01FD3525B063
+:107C20007B8003F731FA16717681A722DA7D287CF2
+:107C3000EFE1F3A3FDAC8B85F696F0F1A51F160AD4
+:107C4000BF98D99D4B39BF2E15F4B64BCFA7CF02A5
+:107C5000BF001F819D4BE1760F7F0E44EF9B38BD27
+:107C60006FE2F4DECACB831DAF3182F8437FAF45AC
+:107C70008C7B2B7F3E5D988AFD8979087A263C3E75
+:107C800065A29203E8E854DB1AB49B1619E2C524F6
+:107C9000348E25872BF7C91FD315785A02F3613E1E
+:107CA000D277225D40D7F758DA33D8BD12FA7A621C
+:107CB000FFB70E6EEEC2F33A44F77B0AD5720CE6BC
+:107CC00013D549EC5E99DE729BD744EDC50FF8BD24
+:107CD0000EE79BD9F9D0BA87F8EFA0C43D381DEC68
+:107CE000C3BA588B02CF0FF8FD72F7926E5B4A4A07
+:107CF000D03E692D97F9EF6ECCBDD39D0FF74410A0
+:107D000051DEE81E8151255E6E780FF63B665EA659
+:107D10007480E54577BAA9DCE83DC4BF7B6919F0FA
+:107D2000F888A0E746ECAFF729F1FD3E567E547C7B
+:107D30007F9095FF4DF4CFCB1B0CDF5719BEFF9CF6
+:107D400095DF2C7CF04E2FD8B57C1FA7EE0609E5F9
+:107D50008A95D35BDD6A3FC2B9CE74803D2B881F04
+:107D6000CED75EABDE37851E6BA103EE37386503D9
+:107D7000FDFDADCB8DE5F3F9DAF1425A7FC96D9285
+:107D8000D702F2F2B82F93CBF7B079B9564EBF179E
+:107D9000C6D0FEC607E14DFBF9F09FE96775FF7E8F
+:107DA0003E85795D6F3FD35D6C7D21FDF4FE33FD33
+:107DB000EC75E9E723ECA3A963DD5163403E54DD94
+:107DC000A88BFB2DFD912B0EEC2BF20EFB1D93A52A
+:107DD000ABDB478DA3FD2FFDAF57462D0CF1C797A9
+:107DE0005F92891BEE47B824E1F38BFD7FB2C0F9A7
+:107DF000FCE5FBF65B26E7C3EF2FECB75486CC6BB4
+:107E000099C8B3243DCA8C10FD1E37C6C4E506FBD5
+:107E10001D87A5FF7546017C2E35B57FFA0CC48100
+:107E20006E90C2EED7FE95AFEFA301CE8339C63078
+:107E3000F95756EC4E82755E041944EB57AE09BFF4
+:107E4000CF3F670C8B27D6F17B95E795D8AC2A8579
+:107E5000F3F8E36C7F7AE1E694B110E77514548C83
+:107E60001A03F31D305E1A60F1D24E162FAD4BE8A7
+:107E70007E00EE31BDEB574F6D847B4DA76E147CB9
+:107E800042F0F7726A2204DFEDBAB3AA0CE35F583E
+:107E90002E1BF3C246E09B23FC5EF1D9A5055120C1
+:107EA0001F7A52A24D762A4746E4D7DF05F3985D44
+:107EB0007AD364785F1E61CBAC677177A48B11F9BC
+:107EC0009E62F80EF521DEA15958FC4B7B4BC6F89B
+:107ED000975618AD85DB7F1ECBE170D718764FF132
+:107EE00011139DE7D8E03CC4F8D46079A09BF677E5
+:107EF0006AF5B022B897BF25BF7C16D2131FBF25E5
+:107F00005FAB86B2189F2EB710DE0F761E159C2E23
+:107F1000668D6178F394517A0BF11B675445EBCA77
+:107F2000336B13893B340E3B3359579E5597A6ABA1
+:107F30007FF7FC3CDDF76911DDC5CDD7610737D987
+:107F40006C51608F7DD8F9CD7FDF03F6DD36D92502
+:107F5000D1F52C7E6DFB7FC3EFA39C871F5C60E790
+:107F6000AF301EF6F911F67B7FD4AE5342F775CED3
+:107F7000916ECC2B0CD92F08BB9F2AF60B96DABB3F
+:107F800030FFEF7FBBAFD33286EF178C2563411FE5
+:107F90009E6F7E17E370CB63D8BACEBDC2EF2107C8
+:107FA0003D42E9FC666808F7855D5A85BFEF53C915
+:107FB0007FBF75D81895F90523EE53E0DC77137D64
+:107FC00082FC9F4CE5541CA593EEFDA4601FE45D6C
+:107FD000A4D8309FBCF1D2ED18E73E12E5CDBF8F9B
+:107FE000D65BBA6E0A96975F8AC67E7F2F774FC69A
+:107FF000BCE697D9EF214E4B9EBD1AE60FF5EFA7D1
+:10800000E34DFBD5CD3500A7E5FBD8F9A969F21FF3
+:108010008AA19F656D53B0FD34991C91A8BD10775E
+:10802000E91EEC771AE87A5A964B6C8F81FE952DF3
+:10803000FECC6741AE586C28579A2E4562BBA99575
+:108040004C4FFBC6303BC6DCC3E6557DE936FC2E03
+:10805000F0FFC29854DD3D3266C73605CE27987BC7
+:1080600024AC7FCBA53C7C8A75BE95FD3CDE576277
+:10807000767C3D19F23ADF4A92EC687E18E4EE8590
+:10808000E6D23812462EF58D7389E501475C627998
+:10809000C12F14B93B81BFA73FDCA3C0FE0E89B13D
+:1080A000DA015ED32714A90B43F8493E709705F017
+:1080B000627EF29805F47E047D56867C6F14F9EB9F
+:1080C00006B97C80CB01717E41E819A276E87E5F1B
+:1080D0004DF0CBAF38BF8AF6DD40EB80C79722D09A
+:1080E0009F7AA3487B17E6DB5DCE7E278328DDA33E
+:1080F000605FE55F357F8A67AB84F67E0FE6C54F2C
+:108100009FA09A60BFE0FDBE7530BEBDD63A7ECB63
+:10811000EBFF5E262DD0EFEF274DEA76D3FEF6FF7C
+:1081200070DC3890FF62DC2FC6B073C3C41EB80C7D
+:10813000FE5DD3EBD12AF0F73470968A83762D7DDD
+:108140008FF7E535BD1EB155A2DF9B62A97F4BC7F6
+:10815000AF7C23D20F74BCFF8D48057FA7A858FBC6
+:1081600002E465E51B5955E0CFB93B231482768EB6
+:10817000FB2CCAD501E67B2D3965A433C197DA3AC9
+:10818000C62FF59C4EE772FED3381F5D681E8A7CB1
+:1081900078E1613A69D80F7D582AD80776816AC399
+:1081A000FB89055F4E033F88BEFF7F46E48E2C00AF
+:1081B000800000001F8B080000000000000BC57D40
+:1081C0000B7854D5B5F03E73CEBC9299C9E44942C0
+:1081D0001E9C400841024C26218410601202A2021B
+:1081E0000E501530C88008110909515BACF6CF84D8
+:1081F0002410452D56DB068B74C04751696F406CC7
+:10820000D31661786863F5D368EF6DF1D6DAF8B804
+:10821000888A3582F5A3B728FF5A6BEF9D993349B9
+:1082200010EDBDFF1FE53B5967EFB31F6BADBD5EA2
+:108230007BED9D79E312432D0A63EBCE253296CC7C
+:10824000D83C95752B498CD59DCB65AC98B1F5E79D
+:1082500092E97DFD393B3D579E1B47EFADE754E664
+:108260000378D53985F900BE6AA633684A60EC42C6
+:108270005120D3930AEDB45C3E87B9180B6CCA2821
+:108280000938189B7F57AF664B618C392CEEC7A11C
+:10829000BFF96545E9ABE1FD05FC99C158CB9125D6
+:1082A0004C7742BB297E8B0FDEAF82E7CCA8F29BD6
+:1082B00018F37502CC987B765A097CDF9A6BBA87E3
+:1082C00045CA758F89B14958DE4CCFF9B2BEDEC5BB
+:1082D000581A6337B819FFD90883CB60CC29EAAFA5
+:1082E0007484479BA03D7383DDB309C67526459F03
+:1082F000CD006EBC1B004041A3D93FD309E36EDC27
+:10830000AE7882F0F98DA54E1B8379969E68B004F5
+:108310000A23FD2F393781E9808745E7F2E8993A4A
+:108320003E3001F1B0E2DCB584AF95508E4FA69798
+:1083300099703CB7D9F0771C10C0A58CDD2AC6F720
+:1083400059C3E461DF81FE3F7BD94CE5937CC11BBF
+:10835000703CE690D5B30BC673CA1E50198CE75417
+:1083600036733F08433C65664137D0EBC60E950532
+:10837000A1FD55F00CC0F35422F3257A119F30CFA4
+:1083800002DEF605F8F7776D5B0E1B05F46DFCD386
+:108390005BDA48C66ECEEF991086766B2AC3A9D7F2
+:1083A00041BBA71F337B82D0EFBA23AF979AA0FCC3
+:1083B000C35CDF30A632366678600ECE67EDC2D081
+:1083C0002FCC00DF72DF33AE297A049F9D5A78B438
+:1083D00006DF77021E8330AECE7BD53921A2178B04
+:1083E0005F301E1F803DA83A7B81124C00FCB1EA31
+:1083F000A97CDE363EB6B5E746117ECE3658C71F9D
+:108400008076CEEA4E0FBEAF3BB788DEDFD27E0568
+:108410003DCDBD5708BE8CE7FC9AB96C13F2599D4F
+:108420000695E1BB3A47422808F399F76FC07F8071
+:10843000F2F50716F82B91EF0A14CF6878ACDB76CB
+:1084400085E0F3DDF797035EE77D92E26981F7BF90
+:108450006A4A076445F87FD6B905542FE1DCF5D4A4
+:108460009FE47FABE07733F27F14DFC3778CC17773
+:1084700081A2C09D88A7AAA7FFF9CC7FC2AB2BB56C
+:1084800070FE4F52F0E924FE89AC039BFBF15C5A6D
+:1084900007FAEA283E528F2EB1E8802FF3436FD3BC
+:1084A0003AB0C2736654F97AE4EB42C44CAFB6D02A
+:1084B00019791FFC9AFCBF5ED49F6365CBFDD89EE3
+:1084C000D69313DDDEE1A2AA073D50DEE151787BB1
+:1084D000FF43E3063CD910BF307E1FD26B7E996EFE
+:1084E000BA2717FB91E3E77CF255E36F13F55F556D
+:1084F000D9466CF7D519337A7CD0DE913B8B8B55FE
+:108500003DD2EFD31E0BB5370F6887EBA8EF396B61
+:1085100068772E8A11C614A8FFC9736343F7C01485
+:10852000DF627DE7713CC183F13ACEAFFE503CD5AE
+:10853000AF8F4B0829505EEFEACBF7C378661EB6C3
+:108540008791AF8E1CB66B0CFAAD28B9F169C4D314
+:10855000CCC363AA15E043DF41ABC6A0DEDF27F83A
+:10856000F6221F0C357E39BED8A79CBFE42BB95E1E
+:10857000E4FA90EB2176FDC8F570D5564FC277909E
+:108580004E8098C771FD68C1BD388F3A3DBE08D78F
+:10859000A55C47EB0F28B4CE40E87A46EB917524F2
+:1085A000D74D649D98080FF3849E186A9DD48975F1
+:1085B00071935817723D1C533B1F2C87EF661605AD
+:1085C000FE827892EB62DDFE58BD30245F31E4AB71
+:1085D0009B521A18F2551D3CA3F9CA3AC47A78077F
+:1085E000F923F5D2D743CF25F2D3DF919F26FDAFF4
+:1085F000F2D3DF916F06E1A7CFFF157E8AE597B32F
+:108600000D7F2AD1613C674B40CEE646F8EDAA9734
+:10861000D8F803F09E8D727A907FBAE3F83CBB2DB8
+:10862000D9A116AC778135201EA5FEBF09E99E1C95
+:10863000E153AF3730BC685284FEDD71C1C20D8595
+:10864000974E676B4A8FC55788F4EE31E8FFBA2121
+:10865000E83CA2E8EBD1D929EA7F159D3D455C6E47
+:108660003037D0B184E8A7235D63E98E7445BAD76B
+:108670001FB2EEBE185DD79704A6160D2227988F5D
+:10868000DB0311BA581721DF9C0D83425386A6AB3A
+:10869000B983E35DC26D614DEADB64D4B7C02F15C9
+:1086A000D8DF37E5977933E1D7E1083EB5D89705AC
+:1086B00074FFBE80D92F16237DAE2D93E54F77F83A
+:1086C000F250EEC0EFE5D4838FD908BF1C0EEE3D0B
+:1086D000510DF5AF7AB0BF3C88E5B32A12447BCC8C
+:1086E000A7B048FDEBF73D79E25E9AC736AE0F02C0
+:1086F000BD9A7F7C145C02B0330A2E8B8177F0FA2E
+:108700002EAD97B9A99D105FAFD0BEE2E5FCE38F17
+:10871000B2478092B313D19E3CA0B8EF01FA2FADBF
+:10872000F8C482F48ACCFF00CD7FFD4145C05D27AF
+:1087300070BE4B0F70B879DFC18EA026DA033CAF54
+:10874000136836772A3E15DA5D57A68446E60EC4CE
+:1087500073739151DFE18F66FC9E5952BEDEF7B80C
+:10876000BEE9FB91F47DD8FA35FABFAE82F9428EAC
+:1087700081F51E90EBEB3CC0B27DC0E522985FA86E
+:108780007060FDEDA2DD1E9349E0EBB50EC45F8F76
+:1087900045E2B3A7C35701F4671C7E745FCFE26064
+:1087A000211FBE2F66FE171B7F5BFFBA8FCC5F3782
+:1087B0007E1FBE18FEB60EC09FE09F5A233F25685D
+:1087C000FEE367A19D8414C58D76F17ABFFD5EB48A
+:1087D000FF23FCF167E28F1E3BEBE76723FFBFB986
+:1087E00018F97F3D93F5DFEAC0F5E337F5D7E7EBFE
+:1087F00041F2177C5F00FC8426327EFFDCBEBF7432
+:10880000041D441F2A2738EF22EBA13306AE8859F6
+:108810003F82FF69FDA29C07FC8C1E44CEBC29F060
+:10882000FBB1C216A39CECA9E27662CF48FE3C5F86
+:10883000C4EDC2F7041E4F8BFA3D715178C88AD03F
+:10884000197EC2E88744CD9BF0B42445CEFBCBC54E
+:108850007361DE3D49BCFCF3A2FFEE086645E0D83B
+:10886000F6CE157D497C1369FFFC09C4EB1281B774
+:10887000F3455F9C107CA5E0BAAC230601BE38A08E
+:108880000455F413902F0699F7F1817C158CF9DECD
+:1088900067BEC8F7BF1FB82E7D31DF3373C9D7F964
+:1088A0005ED06D6E0C5DE7C4D0B53A06AE9170C86F
+:1088B00020FFA45C5CD9F5405B1ACCE3963D0AAA84
+:1088C00099287E762CC1F5798B5BF2AFF30DB4BBA2
+:1088D00022FCEC227861A7948709DB511E2E407997
+:1088E000581E8117A1BC20D8BDC437315A5F24520D
+:1088F000F975EDB27E12C14B5B657BC9DB7D5A8495
+:108900008E2C98B204FB5B5222F44530F50DACBFBF
+:10891000F620FF7EE2FEB4372EBA1EB6C5E06547EC
+:108920000C1C8CA9FFD057E897D698EFEF8A29BF87
+:108930003706EE8881DB8DDFAF58A5D03A5C01FCAD
+:108940008084F8AA7539C3DB6FA7F6EB53C541766F
+:108950009B615D5DD5C2E12BF68F5AD2EE8882BD58
+:10896000A397041D91756166FCC79AC2685D9887DC
+:10897000909793BDB1EB42CCA72056DFF2F2BFE255
+:10898000AF19680733835D704C35C2475439EEE246
+:10899000376E2BC49712F62EC1F8CA553F36CE0B50
+:1089A000FC55017B96545744D925C1894B70FDCBAA
+:1089B00079CAFAB3BFB8A0627FCBBD13973C06E576
+:1089C0003555E1D10D30CE9A24FE04BDA6A2DEAC11
+:1089D00017F198D9CFA97ED46B3571E1D18D85512E
+:1089E000F3649DF938CF2377AA449F600BD007F03A
+:1089F000B492814300AED99184848D4F40FD63775A
+:108A0000AA1B518FBEB531390DFD9B835EEE2F1C25
+:108A10004B18917613C047E2975B74A87764CB2C10
+:108A20007A1E557D9BFB60AD7D6FFFF4258EB1589E
+:108A30009E40F8B9C35BBEA419F8FA2EAF4EF80CED
+:108A400024B9D3BAD07EBEC7CC1ED769FE3B896F8E
+:108A5000EEB316A1FFBCA2795C1ADA932B7FB86043
+:108A60007606D45BD966F628548F4DC07107EE990F
+:108A700065C1F255ADE219BC9C9E87BF7CB4C505AB
+:108A8000F5FB1E513CBBA1FEB4CF3A5F9A00F09AB1
+:108A9000F6511E24CDA17326E6867EDEE918135218
+:108AA000811FDFB537BC309FD767587FCD79FD95E3
+:108AB000F925585F756F82FA27E13DDAC327EF5633
+:108AC000772B382E97334E81299DFC427F05ED5A36
+:108AD00028776F82F727DB6E4E433BEBA4A2BB14D3
+:108AE00098FFF6FD7397A403BFACE9B00A7ACECD28
+:108AF0005801F35F61EAE717D21FAB1339BCDD3BC6
+:108B000077C9E330FE93DBC7B810CF89C5BE87BDF8
+:108B100080E7B78A7D3FF1A6E238B99E3AFCA5BA54
+:108B20001CEDF1DF9E5E9986FCF4B8583F87CEAD10
+:108B30004C5B1965EFACFE5823BA1FB6E8B7E138B5
+:108B40000FC7652BE82F03DD9317C0FA5D25FC0FD7
+:108B5000E0DF8DCF0C62F704BD2AB57B646B6A85BC
+:108B60006EE0E3EBDF40BE24BF01E05FEEBF6E3B93
+:108B7000EAB5F7AC1BD9BBB8F8EE828229F03C66A7
+:108B8000A7F89579AF3D64CFC5F8A76F36CA3D9673
+:108B9000DE99BFD019B5EE44FDBF049D54FF2F50A0
+:108BA0001FFDB7BF04FFEC648E8176FC1A973388F3
+:108BB000C6C4FB4EA78674784B6B3A79077CB7FA2C
+:108BC0001133C9FDD58FA4DED587F206F805E3631E
+:108BD000B1F3528BCD34AF21D761B0D6B80E592D39
+:108BE000C9EBA1D661CFFE35175D876B849F32FB41
+:108BF00011B31FD7D19A494E8D81FEA87AE4F9C7E7
+:108C000091DFD76CB07BAD30F0358F58895EBD4EAB
+:108C100067D00DE50197534B84E75B82BEAC98AFFC
+:108C20009B992AD36C5E7AB6629CF40C8C2719E06F
+:108C30000F363EF8A3C950ED4316BA7632E0EF0C7A
+:108C4000120CF072E6804AF143A6F9B479201F6B4A
+:108C500019970B752F3E63A9C4D935AC998B7EDD6E
+:108C6000CD21F33BBDC267BB20A689F2B49EBF02F3
+:108C7000BD6A2CAF67F77EAA4E2036B6E07AACEB21
+:108C80008C296FB8FC7D8CBFD433ED9D5E19AF8508
+:108C9000717CEE75A69C8C4771C8BC802176A6C1FC
+:108CA0009CCF608A6B1CB0AE60BE33772834EE3543
+:108CB0001BD59015EACF4CE671DFF79A80FE63680A
+:108CC000DE4137C06B1EE27A660D534236F8F5F28C
+:108CD0001D1B345C0FEB857C59A1303FF2F7BB764E
+:108CE0004F0EFAEBAB1FB1137ED7ECBCF98FDBE173
+:108CF000BBDEE67929D1FEB143F005B4CF6C4991D2
+:108D000076DE6FFE5E0EF2FFCC9F829F0BF35D93CB
+:108D1000C87EB12417E99591A33B22F5D66CBA33EE
+:108D20009FD7033F19E6BDE26E95E6C19EB592DE80
+:108D300083B59E4E7259E07355EB8B164B21CAE9F1
+:108D40007B7B54A8FF0EC0AA83F0151478B420BE14
+:108D500096E3B719FC9BF4526177EB24470238BFC6
+:108D60001A93B27C21C9F53E0BAEEBF26285C63395
+:108D7000B198DBB32B723C37501CF97EAB07E5147E
+:108D8000FEA8721CE057D5997A56633C97FDD24AEB
+:108D9000F191FA56BBCFEE22BFC3B71FC7A731CDA3
+:108DA00002F858A77379512EF8B05E5F7039F20D52
+:108DB000949FD0707FC5C9E5625D22E09DEB639F03
+:108DC00009FAF9047F1BC5DBCD9810D5BF22DE431D
+:108DD0003BBA2BD26EB789B5639C05EB8F9D80782B
+:108DE0004CBE76318EEFE72AAD6798FCFD6568E7EB
+:108DF000FD5C2D46FF76C5DDC7667720BCAFC88D0C
+:108E00004DAEF8C51F486FDC22E8DF8BF63EEA1155
+:108E100080F7C1735131D7FB0195C77D16097C4995
+:108E20003E90E575779B79FCBDCD4A764C5DF39F0E
+:108E3000A8DD3A674F1ACADFBA67CDA528A7AF15D4
+:108E4000E35ED99C5D7102F86AA539C1ADC0AB750E
+:108E5000C1791684D76D53088E7C979A837CFA511A
+:108E6000EBAF5CC83FEFDAC3A3511FF56DB07B7663
+:108E7000E30444DCEDA3D6D1BB313EB3CADDE354F9
+:108E8000A07CD56DA392507EBFE50E5BB0FCADCE4D
+:108E90005C13C23EB7BB02619F3691E08F40947570
+:108EA0000AFF13F96DBDC2E9BC6EEF31CB48E8EFA4
+:108EB0004E31DF8F7FFE877CD45775393DF9A85737
+:108EC000800FF23311CF4F29A48FD7EF557DF609CC
+:108ED000113E588F7C00EB6EADE083F5077EF51DEB
+:108EE0005C0FEB91FEDE817C047C7A9CDEEFDF354B
+:108EF0009BF1EF8F239F483D0670AB19E369160184
+:108F0000433F08DF85F89C44E5D5BC3C5848F294C3
+:108F1000F55AD0EEACEF32077BA3F67F86A2F3764C
+:108F200041C795CD5692BBDBC5BC7BEF7ED6857421
+:108F3000FCF8E7C75EC0FD92BAFDA0ADF541D6854D
+:108F4000C04B3DE2C145F320FBA21EE7ED8AE0A144
+:108F50009FFFC57AAC677C9E72DEF59AC0832C17A2
+:108F6000DF3F2CF8661D13783B3086AF3FB1DE70D3
+:108F70003DA35C95F30B24F1EF259F1E2EE67A614D
+:108F80008F78AE03BEF01412FFF82C524E40D1C7BA
+:108F9000FB7651FC47D24B8EFBB5883EF12526452A
+:108FA000E8D86B62B59D83C44DBA04FEDE6E1B9695
+:108FB000D30578FB08FC2CB4A7905FB5A8FE24DF8E
+:108FC000C8FE663EBDE04A9C2FB41FC6F665BF6F63
+:108FD00005E3356CE72DC6D707F227CA4FB92E67D0
+:108FE000B62CBBB2C885F53E768E423B46C8B3D799
+:108FF0008ADDF4BD0FED05F8DED7A550FCF96DE173
+:10900000D7BFDDF62BD7CA283CBD2AC62DF90C7F69
+:10901000302E25C7DB9DC4E3B9B1E39672488E7B41
+:10902000E696EBAEC4F772FC925F257F4A3C4A3E5F
+:109030006577A5925D13CBAFC46B52AFAA06794F8B
+:10904000FAF1F2AC4F2D01C7C0F7B1B0B487DEC55D
+:10905000380DCA8F27D510C98FD6F4E379517A1EFF
+:109060007E1CD17AA779C3E5EE4ADC7FDDAB78D0F0
+:10907000E489D22FF76A51FA45DA0525252309EF4D
+:10908000F529BE0F908EEB4EF5CC76E9113B74DAE4
+:1090900067613501E3520772BDD1FA74DDE9E3C4BB
+:1090A000FF75AC6733FA512BEEFEC3BCC9C8E74F5E
+:1090B0009A697F6645DB2C0BDAF5373F7E6329F230
+:1090C000D13BEDA348AE7FF0D8A462E22BE64EBBC5
+:1090D00016F87FD5630F5EBB14DEAFEA523D24DF86
+:1090E000A11D5CB72B6E2F66C837EFDA7BE795A31F
+:1090F000FD7E87EA46FB7DEAE393EEC2FA539D23A9
+:1091000012711EBEC79209F66909A41FA4DDFB9661
+:1091100090932D66CE1739257C1DA59670B9915A6E
+:10912000C2F966664B4B3EEEA7F7ED02F98CFBCA1F
+:1091300016BD338CFD3D378CFC8B7A7087D281EE67
+:10914000A7146E97D55A982DC34BEF6D19F0FE45B5
+:1091500073CFEDA8475EBCDD59D48C0350CF97AEDA
+:10916000E4F634DF3F4CE6FD4BBCC9716497707E7A
+:109170008F6D4F7EDF8D7E04CA5331FE0F5A9FBC28
+:1091800016F5E0077B4627E1BCDF7FCEDE8EF6D406
+:10919000FB662E1765FB60E7BD176DA7815D6780D5
+:1091A000C18E33C0C0BFEF19EDC24D34AE8925600A
+:1091B000C78D63FD769CE4F79A0DA313A2F30862B2
+:1091C000ED779617BB6F3339810D226FE4F374137B
+:1091D000200A18F52CEE1142BFD5F15F3CD383F67F
+:1091E000FE36ABDB0AF37C0FF91FF7A59E5543B89B
+:1091F0000F83B639AE87F7F61585D08F5CFD6660B4
+:1092000036B67FFC812D94677013D897C39428BB22
+:10921000F9A107AE45F63FE3096CCE80EFCEECE155
+:10922000791150EC88B1975FC8D0FF757BF952ED8A
+:1092300064196FA82911F6B2877910CF12BFD26FC7
+:109240003A0C7C50E68DE0EB6F4DB564279F6E0ABB
+:10925000D0F313E5EDFBA722FF3A133CBBE1B3DFEC
+:10926000763DA866229D0F149D47BFB7DC91E0C6EE
+:1092700075FBB7A68DB4F978BAA9819E92CE32DE7D
+:1092800036EDC011FAEE6F5DC507A7C277871C09DE
+:109290005CFE0FD8EFE1F48CCD03B975C3E461F83F
+:1092A0005ECEEBC33B385DE5B83FDC73A30BE775DF
+:1092B000E427C907A7203DE313DC68EFAD11F91FD0
+:1092C000273BB83D7DCA96F0C45CCC1BD9B1288D34
+:1092D000819CBDE9C8B7AEC5F7AB9F53DCE8077802
+:1092E0009E5BE042FFF4BFB45E971B9FF05D18C722
+:1092F000A385549447E57318ED47958735A6E7D2C3
+:10930000562FF1CB94D35A08F3463EC27D2A8C8760
+:109310009C8FA3780813FB4F37FD9AC751FAFD5B6A
+:10932000E1DF4D15F3EE2A4992FB0AF47E66197FC0
+:10933000FFFE8E67E6637B1F3C6676E3B8FFF69818
+:1093400099DA5F0B7E9909C67B6A0FF777D6762A82
+:10935000E4277FB007F435CCAB6E83D9674918C8D2
+:109360008733A1BCD711E1C3B5BE10F13713FC6838
+:1093700083FF2E8C1CC88F89AC7333E2E35FE5CB8F
+:109380005FC4ACFB7E7E1C8A0F04BE701D233F4A67
+:109390007AAFEDE0FBEA499D4595C85792FE524EE3
+:1093A00004AB5801EAD5160B2BC03C9CA029CE83F8
+:1093B000EB7B8143372B80874529BDD5284E33274A
+:1093C0007139ADCE34F94CA85F5AAC240762E5C8B8
+:1093D000EF845C9F8F3C0DFFDE2DE1768499359004
+:1093E0001F229FA077B2517F2F884FFABB0E55FEE8
+:1093F000FD40ED520DC6BF606AD2EDA33C8CBD7935
+:1094000060FD520DF8774171D2B323017EABA48E7B
+:10941000C313932699016E6EAE5F5A0DF5FF59E2A4
+:109420007BBD24AA1FD92EBCFF8F1280378D0B9CC9
+:10943000C067BDC54172FA13A56FC2C6DC48FDD72F
+:1094400014F6D66F9508DC6B663968DFBD5B22C702
+:109450003FF8336F92EFED9241DEAF64AC0DE32A3B
+:109460002B83BF3BA1703FCC6F037A5D2DF86AA5BB
+:10947000CD11267FBEDD7CBA9FDEC8479E040DE974
+:109480003A5FF0D1D55AF8087E3F96B5BA4FDAC8A0
+:1094900084DA71217968F90D0B8F9D94ED01BF7C01
+:1094A0006286F9025F2BC09E1B61C92880E41A9076
+:1094B0005FCAC1DFFD03DB6D09B25E3BD1A1C68D82
+:1094C0007CA6B080E9023CEBE25D13306E52179F40
+:1094D0001342BE6F7CF6E3E3C85E374BFB25504674
+:1094E000FC7E9B9BCF8705CA891F6F17FCF87E13F4
+:1094F0006BC883A577754F8F4B87419F9E1FCEC743
+:10950000F5FE694E206E12FAF93B5AB21A817F3E7F
+:10951000DE6FF5CC85FAA742CF501C6E9DB047D9BF
+:1095200063A962DDABE11950AF3B77EC6ED42F2914
+:1095300093385F9DCE0DE7DC89722397FB3F508FF8
+:10954000F2DCE66CBA3C15EB9DDEB725EF26A09F5A
+:1095500055634167123D990BE67D05B45D06B01970
+:109560006095F67343442FACE7427DAFDF98CEE3BE
+:10957000EDCC8F7245D24BD261007D600868AF9A06
+:109580006CCC8CE31FCB76B8517F483ABD6F033C5F
+:1095900062FCCC067884F53D0B830E25884F1E6F48
+:1095A00069547A5B9311FEB942797303F5E0E316CF
+:1095B0004479ED8E1B49FE48B9A3C37F83C99DAF93
+:1095C0001D37DA317350B9336D92D08345ACE80260
+:1095D000371089BE6BC4B7B3D41A5DC371A7DA3C28
+:1095E000184F6B7C6414E91BD6FA07165D8FED48A3
+:1095F000267ED99CAB12DE6FEE5228BF715E5726D5
+:10960000D3A1686E57323D5DE732E8FD074FBC5489
+:10961000C2E512A7CBBC9F0DABA2BCA29F8DA1A798
+:109620001C47A3E0BB596A616718ED08078C03E08B
+:10963000C617B9DE6ABC46A5B82643119D86C4E4A8
+:109640003F7E473BC57FFCACDFBE572E509C564F3C
+:1096500040BAF8BB5586FC03DE4690E3D9D68C7839
+:10966000B6A69B983E88FD611574B2EB714C8FF2E3
+:109670003BB4E0D8EF57603CF65B664F08CA5BEC42
+:10968000AEDDB89E58D0D783FEC262F15D8F9DF3E8
+:10969000477C4192E1FB2DAED9DDC86F8B7D5CEF3D
+:1096A000383DC30DFD5BD57566643216E0F6A2E465
+:1096B00007E24BE8F76ABF42FAF59AC5501ED5AEED
+:1096C000B9E25392E3E60AA39D69F51BEB7D6F9225
+:1096D000D03B63D9D868FA47F0EEF0A19D7EC6E78B
+:1096E000243E06EDFEE30A80AFED36339CAF358EA7
+:1096F000CFEB0C620AE3A23E3584F1922D88077805
+:109700009F5066C467A2CF88BFE439467CA4FA8D17
+:10971000F31FB678A4A13C237099A13CB3D66B800B
+:10972000B31BCA0DF5476CAC32C0B9C12B0DF54760
+:10973000B52F34C0A3B72D35D41FD3B1D2503E3688
+:10974000B4D6503E6E4FA3011EDFF95D43FD895D27
+:109750009B0CE545E17B0CE5C5DD3F30C0937A1EEF
+:1097600036D49F7C62B7A17C4AEF5386F2A9A7F654
+:109770001BE0697DBF31D49F71EEA801AE642F1943
+:10978000EACFB4FDC100CF72FFD950FFF2F4770DDC
+:10979000E557E81F19CAAF2A386BE4D7382EFFE621
+:1097A00079FE69F84EC90ABC3C096D04F5B4867CA3
+:1097B000DBB24C61C9184FEF5E644339F08A9443C1
+:1097C000820F9F47FD8CF5F3580ECAB3596A4518AE
+:1097D000D7ED992E85D67FACBED33EF2FB309EC727
+:1097E0007EA57830CE96006A4B8BEA3FD16703475F
+:1097F000320227CF711BE0547FBAA1FEB0C5BAA1D7
+:109800003C23506028CFACF518E0EC863243FD11C4
+:109810001B7D06383738C7507F54BBDF008FDEB65C
+:10982000D8507F4C47C0503E36546B281FB7A7C155
+:10983000008FEFDC68A83FB12B68282F0AB71BCA3E
+:109840008BBBB719E0493D1D86FA934F840CE55355
+:109850007AF718CAA79EEA34C0D3FABA0CF5679C07
+:109860000B1BE04AF6A2A1FE4CDB6B067896FB0DC3
+:1098700043FDCBD3DF36945FA17F602897F6CD55AB
+:10988000059F1ADF0B7B679EE71F86EF83553E8699
+:10989000FC11DCAF785A74C60A4B47927D0172BD49
+:1098A000D7AEA27DE4A7B851122608025F26801029
+:1098B00043BE4257A186E24F2914F725D5A463BEC3
+:1098C0000FD8090024997273D19E8E8FD86D5917C5
+:1098D0008A2FDD6E2B2F65C4E73797062696A6A242
+:1098E000BFB26F36DAED37B3E0661C07E8BD845EC1
+:1098F0005C1F76633C433EAFB0015EA2FA7BD1BEF3
+:109900002DCB7B11BFFF0ADB69AADFDFAE8873288E
+:1099100030BFC6A8F6EF07BF4203BB6E5B13AC1B9C
+:1099200070187FD0E426F8A1A674827FD4A4D3B3A4
+:10993000A3A9809E0F3779A87C475319C13B9B7C14
+:1099400004879AE6D07377939FDE3FD6B498E027DA
+:10995000C08FC6E71EF0ABF1F914F8C758BE17FC6C
+:1099600065847FD114A46767533BBDDFDFB48DE00E
+:10997000034D1D04FFB22944CFAEA63DF4FC4D5368
+:1099800027951F6CEA22F8505398E0705337C1476F
+:109990009B7A083EDE7482E0179A7AE9D9DD748AF0
+:1099A0009EBF6FEAA3F2979BCE11FCA188D7AE2988
+:1099B000E5F12289170933564DFC20EDC3F968E71C
+:1099C00023739499FF66B0F363ECED587AC87ECCAC
+:1099D00055181384E7F0FCDD2D517ED6ADA2BF2DC6
+:1099E000712C68077E6F3671BFB63989519E351369
+:1099F000F6EB1AC1972C85DBADABC5B8D688F53030
+:109A000009F9B380F8F3E5AFE35748BFF14C61A023
+:109A100085F833DB1424FFD911CA47FB39757C6004
+:109A200073E924DC6FBCE905EACFEDA17DC779D6E7
+:109A300070EA75181F7951A578DE50FDD58BFCF1C1
+:109A400021CB0F7D9085F6F69C2FD500E2E915B36A
+:109A50007331C60BB69772FF747BA9C9F0FCC9F8C5
+:109A600040078EE77367C30D2618FFE7D3373C71B5
+:109A70006B6EC49FBE1A5D52F0831630DD4CF989BF
+:109A8000CCF77C2E34750D1858085FC782F4CC2AA9
+:109A90000CECC2F92E01431CE140B93567B079C521
+:109AA0008E6BAF18D75E311EF97C717CE0696CEF6C
+:109AB00073A78FC6F5CA94CBF3715E725C71137491
+:109AC000719EA16F278EEFF3E73E3DA98C8AE05F80
+:109AD000FAED9B2B455EC90685C7E5A4BD26F2526B
+:109AE000A4DF5173BB12427B7D19F83BB8BFF4A6CB
+:109AF000B03FDFB473FD7CA6C15C80767D8D12E73C
+:109B0000C17DB8330DFFE540771AEA33DC2769C120
+:109B10009C03286FB943A17CEE1A68C704EDD4609A
+:109B20002010BFBB4B21FEFB627C2E8DAF06CC3FCD
+:109B3000F2B352FA7270BF14F8E545A4C3DA296A89
+:109B4000D002F6F02BA650BE42FBD237591418E7CC
+:109B50009A14E0939143F3C37A71FE40BE073EFB33
+:109B600003B6F7B75F4F2EA038FEA1293AE2ADC584
+:109B7000C4CF23057FAF7A78BE0B17D5EAD4F11492
+:109B8000A7649AC78371A679E2FCCA11956DDC3788
+:109B9000881CFDBBA0DB2BE9E639216AD7B85FF34F
+:109BA000B1A0E3C7A2DEBCA32F66E3F9ABF5DD6687
+:109BB000B24758496FA1DF39C87C366EFD765E1416
+:109BC0007FD777BDCDF335586F61747EBA6B326F36
+:109BD00057F2936A71067639A2C7D7CFDF9F117FFC
+:109BE00027027F8F22FE3E89F6F67CAB9E701D3CDD
+:109BF0007B01456178067EEAA67C239977B48AF9D1
+:109C0000E9B906D801F9D91F7CC082F85FCB3AE9DF
+:109C1000FDFAB21B7310AE677DD5E9E84FB4373F4C
+:109C20009F0EA35CB4ED8159189F5D185AF13C3E1C
+:109C3000173CA69C44FF15D6877932C64F9486B64A
+:109C4000E1D0DFD2BD956D99F07EBECAE9C15EE27A
+:109C5000F400BEF1A94903E709EBC13999E6E1A394
+:109C600079A8AE3986F550B389F9949448FE7CFF03
+:109C7000FA28BBE5AF99E80F697DB4FF5E7FC89A0B
+:109C800084745ECBB8FE8EC43FA4DE66C4E7B7B072
+:109C9000380FD6FB50F0F587D98CF8FA43051C3CF9
+:109CA0006FC49E64398174EFA888FEFDD0142A75B4
+:109CB0008D22FD9C87F37D217D918E71B35B526C6B
+:109CC0001E15CB1343397C1FB55FCEB30BF191B892
+:109CD000D7FD661E878A1D9752F6C23FD07EB05AC6
+:109CE0005810F737607DB3525CD7C32DB4AE5A100D
+:109CF000B5183FABF2EB83B5DF2ADAEDFE82FBC18C
+:109D000041980F9E971CD08F5BF413C7FB917A0488
+:109D1000FB233992C60CFDCDC22417A0CB2B4E1FBE
+:109D20008DBFD9944872E7E311816AA4978CFF48EC
+:109D3000FFB03BF7FD3CF2E3CFB764A19D0EFCCB37
+:109D4000F312A773F9F48A590F22FC4A652EC5FF56
+:109D5000A5DCBDBA8CC7CBAE96F1B18A98F8584C49
+:109D60005C86550C1E2F63CC63C67EC7B237257E3A
+:109D7000281E73B44223BA0781EE186F3E2AFCD422
+:109D8000CA78EE9F774E4E267E4ABA226FD07D1556
+:109D9000F9BC47C457EF053B8845C5D5EF2969B4E1
+:109DA000619EC1964285F6BBEEAB8AAB8DCE73DF6A
+:109DB0003BCDCCF753A757EE44BC153A4255A4AE61
+:109DC0007D9A8EF350C4BCC6B901EF266CDA2FE23F
+:109DD000A41E1B8F4B5593BE96F4BE547DFD941666
+:109DE000DA1487F34E61B4FE9C1D7692A36AA72F06
+:109DF0008C29D75F4E5B7827D151F317603F474AD4
+:109E0000E39803EA7F7EC442FEFD21D3CA9F623EEF
+:109E10007CDF1B5686FB9E9DCE4C0DF545E71797C4
+:109E200055D3D3397536E371CE7813088822377B42
+:109E3000F4DF9058E2DC59A7C2BA19C5DB7CF126E1
+:109E4000F0C13A4DECEC0C18D77E87F7C189C4728B
+:109E50007E15E7D95511B81FD753296B20F83E8BD3
+:109E6000BF7617F47B5F928DF8C45FE17F808F939C
+:109E7000B5CD85F14D9FA9303CC7DB6601B95C8843
+:109E8000719238BE27C5B87DEF3F974FFDEF98CC54
+:109E9000F7F95AD37D3D78606448BCB9B5BEFEB8C9
+:109EA00008F15B16C5F3241EA3E9E52E35D02B601F
+:109EB0008EA65719D06B7C34BD7CCAD7A1D7ED983C
+:109EC0005C3669207F06ABF407AA4BB85EC314B9B1
+:109ED0004A6B7621DAEB47E2320BA3F7F5245F4AAF
+:109EE0003E1D843F371C43F990A5B9317E6A9D170A
+:109EF00047FB2D925F259FFE754A3FBF7ACBE1B9A4
+:109F0000CCE19F853224965F311E16CD973543F202
+:109F10002F7347AFD7F9603F2424A1DD73EAB1CE98
+:109F200028BEAC69F854E3F2E3C28CB8D248FC6EA8
+:109F30007E85C2DE89A62FFC7BA740CC8FEC1E8DD0
+:109F4000FC2D89C74BC5B7F95BCD0568C76DC6F356
+:109F50008980AF76C5E31B8671AD86B76FC5F76D97
+:109F6000E27C70B0D0C2ED2BB14E647B5F4EAB7A19
+:109F700007F9D639F974FC6AA8F7799A4947E4B425
+:109F8000E92BFF8DD6DD897886DFB9927B6A1FA524
+:109F9000753486E1FEE0E7370746E07EFDDD40A749
+:109FA0007728993A34CC447B59BDC3701D0172D3D4
+:109FB000F93390CEDF33511E22F83B53460ABFC31C
+:109FC00027EAF752FDBB2DDB6C71D84FAECDBD3B00
+:109FD0008ADF6788F83A1E23E7FB672D3ADA657A4D
+:109FE00019D7BF0F36ED99F6DE681C4FE7B4F7605E
+:109FF0003CC973432C007C1C5710D43105C4F6E5D2
+:10A000004C05CF2FB0CB5827F20DBE6F1E1F69DF56
+:10A010005CC6D7990DED15A09F6D53504F8A927F66
+:10A02000369312182CDFE58E291AFF6E13A372DB0C
+:10A03000D1ED749E3F39CFA360DEB36DD33686FB7E
+:10A0400031F6307F9F92E7535645B59B3217C61DB8
+:10A05000C517F3F12401C81BDB6E60CC12A4431CAE
+:10A06000C51F63FB9D9F5AD5ADB986E693587E63A5
+:10A0700082DF24DFC879D2C994A873F9D523B93D0A
+:10A08000DCB6D1B20BEDEDF2B244C2EF672955094F
+:10A09000EC227A6527F041D08AFEB18D9EBBC1BF0C
+:10A0A0000E8E41FF389DE027C0BFC6E71EF0AFF11E
+:10A0B000F914F8D758BE17FC6B847F01FE35C29D9A
+:10A0C000E05F23BC1FFC6B840F807F8DF02FC1BF2E
+:10A0D000C66717F8D7F8FC0DF8D7587E10FC6B84CC
+:10A0E0006758813F703E05C1F48540D7F63B2C3E52
+:10A0F000CC17DC20E87ACC3732D903F4B71798288C
+:10A10000F66D7FF9070CE7634F37D1F9AFCDE93F23
+:10A110006037A2DF5AEA24BBA9EDE7DC1EB16B0F62
+:10A1200032943B3B95602DF330B6B86C6C0DEEF37A
+:10A13000E5A56FA84A02F886B2893B6CB03EF2F5FD
+:10A14000058B9BA360DDE95DBBCF1D814714EED27B
+:10A15000C03361377615EDC0A33F380ECC13AE2B5C
+:10A160002BA96906160A8F646457F4E55A283F67DD
+:10A1700015D26B348E9FC70DAF622DE9B86F39428F
+:10A1800007EF47A1FA619672E9F53794E9F43EF6D4
+:10A19000BB8BD533955C523DA65EA43D2C572ED289
+:10A1A0008E4D5964EB81B16F350B3995EA2039D565
+:10A1B0008E711CC07BBB9D3FBBA7F0B8C1AE2955BB
+:10A1C000DE29F0F44EE1746DB707DD55D8FF781342
+:10A1D000E52DB08DB97F1809FD7DFBF71AC3BC4F83
+:10A1E000C99FED820F468F70D2F97B76A78DF6ED71
+:10A1F0002F1FF1F3D62480473FEAF1607EC356E675
+:10A2000089433E09DE6BA2FCC6A74B46252D80EA9A
+:10A21000E3263D9B8472FDA49037219117D4DCB6D0
+:10A220007A04EAB1CF5FE3F2F0C7423EED32F73491
+:10A23000103D2739C8EE606C1BD917CDE9406CD0B2
+:10A2400091A60CFEB498DD4BB19E050C01CCBFB6B7
+:10A250007C31D9867E5DCB39EB1C9E1FDB43768734
+:10A26000C51E7027C2FB6D4113C98516DD41F96C0F
+:10A270005B1DDE6E3CCF1C749B28EF756BA189F0D3
+:10A28000D8EAB83684F6BCA634D7A21E0BB9F7DBE1
+:10A2900072E17DA8D044798C21DFC2390807031A06
+:10A2A000E559D10F960792E81CF756D6F7D2442C01
+:10A2B000AFE176575BDA7F1F8DC738F7356E0FDF5A
+:10A2C00056613AE681514A9809FDEBDE4DF1388E30
+:10A2D000254CF8AD41F2535D564EBFEF1FB9C23D5C
+:10A2E00092EC8AA8FD2B2BC6E43C360F944F707875
+:10A2F000E7A01FA939BD36CCEF6B757B6D2B68FECF
+:10A300003C2F8DF22FA0DD16B789FC592CBFB190E0
+:10A31000D4E1F1BC529172AFE3BC7F7004F1A1DDD6
+:10A32000C458AE8EE3D382D1FB83B65115DD3ACC4F
+:10A33000A37D7512CD43533C04B39B341AF7703D93
+:10A340008ECE2F3F6899D78DF6E170DB2DB48F95B7
+:10A3500051AB19F69986058C70EA62239CCCB4C87F
+:10A360003E15F4FBAEE09B58BCC5E223C3DDFA1AF0
+:10A370008E3F2340876B078C7FBBFBA1C44A86E3DB
+:10A3800074D038D31C2B2BD17E4A65FE66E4BF7F88
+:10A39000759C13DC0B6DB9D0FF84141399471359C6
+:10A3A000DF266C77ABE0F7F65C4ECFC8BA5239BF08
+:10A3B0004FA9CA9C928AFB042670CC22EDE706C105
+:10A3C0004133EC132419E0D1DB861BEA8FE91869CD
+:10A3D000281F1BBACC503E6E8FD7008FEF2C37D47E
+:10A3E0009FD85565808BC2571AEA17772F34C093D0
+:10A3F0007A961AEA4F3EB1D2503EA577ADA17CEADB
+:10A40000A946033CADEFBB86FAD29E8FD58FA953E8
+:10A41000BE991D6F4D1F6EB8C726D64F88B5F36D18
+:10A420005FB6E89B909F5D16E2670DF539EE2BDF76
+:10A43000C1FD21DB748F8EF2255EC8D357A6FB4683
+:10A4400022DD2A5D36D20B9A83D7D31CB3C95EC9ED
+:10A45000E9B0D0FD3A9A9BF597C7A37C6E0A4ECB24
+:10A460001B1D19B7DDBD8DEEA9A874CD61987724A9
+:10A47000BFD7DC3E1670627F3AB793DC41AA67D73C
+:10A48000E1FBA8791C32999803E538F86D181F197B
+:10A49000CA4F93FE99F4CB86F2C7A41F96636271EC
+:10A4A000F8DCA5F4DE8A7E7A61C36B55C318F96BBC
+:10A4B000D5A847EEC3F3D9E8A74DE076565BDA9509
+:10A4C0003AC66DDA733BBB47E278524D141705BBB1
+:10A4D000D9B330CA5E5C2FE8A98D6CEF45FDD798E3
+:10A4E00068D3D15ED26CBBA6BD07F8DA69EE7D12E7
+:10A4F000E310AD8A7B5D27CAC53B1C94EFF1A0C079
+:10A500009BEE34156F82763B9B7D1A9EC3EFBC9BFE
+:10A51000795A717DA4546E4A84F7A3B3569830DCFF
+:10A520003326AF79133E03C25E1E5BB8CB940CE5B5
+:10A53000E34A2A17637C4B75437F178937ABAE0E0E
+:10A5400086F36179DA49E42BB4EE2FC0D02B936CFB
+:10A55000B4FF68477A2BF4243CD8CF39427684F391
+:10A56000385EEC3E2514AF70BB15F3E52A933A88AC
+:10A57000BED29E453B17DBF75704D6231FA5CC352B
+:10A58000D255B33D46F8D86AE2EBA23D517F19F5AA
+:10A59000737B6E5E12EE5BF5CB112157EE10FA5312
+:10A5A000BE9772E523F41D5223F60DF07907C6D944
+:10A5B000ECDA363A7F69BF6B1B43BEB6E36975B20E
+:10A5C000F783BA9FF487DF906F563D72B10DF5F5B2
+:10A5D000D9142FD9B3F68DBFA4F1C5E2CDDECBF3EC
+:10A5E000CE86C2AB2BFF61D2EF2080753CB77334AF
+:10A5F000CD511B1DDF94CF6421F7CD323F083C09BC
+:10A60000D4676765FE912F9E8F2F91C3C7F297D2B3
+:10A61000F86E4DF50EBB98BD6D077F331045F7BB47
+:10A6200035BF0DF1D0767EC11C9AB7468B816DFD8A
+:10A63000A27017C58D85BF942CF0AB233E018F39D6
+:10A64000167E5EC0933297EE2D93718FE7A724514B
+:10A65000B927C8541EAFEBCF4F375D984863D52D4F
+:10A6600052EF9229CBF514FC7F04F35246B56BC62A
+:10A670007C76A1C7A59E1EBDCD583EA6C3088F0DF2
+:10A680000DF8FEDF51CF5FC37F073D602C7F58E898
+:10A69000EB6B505FE3BED5B7785E880D467481EBF7
+:10A6A000D988DE033990DD19AE44B199759B66C82F
+:10A6B00027191EA30FFD153AE1CBDFAD9951CFCA83
+:10A6C000B84CAC1C56EE3CBD01D74B657CBC8EF241
+:10A6D00013E318012BF7CB03E0A7DCA779FE548323
+:10A6E0007E55B74AF952924EB1749D5A2EED5CFFD9
+:10A6F0001FA7907FDC5B8CFE3AF61788EA4FC6579F
+:10A700000E4D0FBC89F5649CE5CC1CED79458FC4DA
+:10A7100051645CC03B85AF9FAD9ED71B8EC1388E08
+:10A720009DB0520C6496FA727713E643656B24BFB2
+:10A73000DC93D7FD14FDEFAA3F4339CCE398AE0F6D
+:10A7400023BBBCDB4C71802AC1C755C2DF92F19696
+:10A75000CF843EE99B22ED9C601CF7EBC37168BF80
+:10A760008EDB03B2D748CF785ECEE36AE33B63CBA0
+:10A770007D94A77499E017CC2FAB4CC3B42E0E7701
+:10A780003225D90D749CB8B8F728BA0E852F3E1F14
+:10A79000877CB8CFCEEDB5A7043FA431C58379F847
+:10A7A000697B1C9E10D473AA6C5F0FCCC3735C339F
+:10A7B000E4934D3868840B59149C8BE330C2F7EA5C
+:10A7C0000DB8C5CCEEAD019B1CA6EC28177947F956
+:10A7D0002C1FF96B96EA2842FFA9B1D2C110AFD65F
+:10A7E000B7C7FCB807E5C56BFC7E2A77BCFE4035D1
+:10A7F0007CEF7E29D9D3AC47E8FF14F8D1A81F7E9F
+:10A8000074C1C35ACD51712DA0671EED23BBA9BCE5
+:10A8100013E88AF07EF0ABF3681FB980DEFF12FC0C
+:10A820006A84BBC0AFC6E76FC0AFC6F707C1AF460B
+:10A83000D837BD722CC6C3DE847AC8177145076C41
+:10A84000A3309EED50E97C4D2C3F6E6978D7711D89
+:10A85000C8AAA91DD97353911F6E53E91CF2D8DF02
+:10A8600064CF45BF353AAE161D578CC4D57A15193D
+:10A8700057B3027D5E98ACF3BC45195F0BF0F8DA74
+:10A8800057B7E393ED50BC72403BFD714B5BF0BD9D
+:10A89000023C9AA5B00478FFF11DFFF904EA99D4AF
+:10A8A0008CC0549C77DDA4772CDCEEE6E7A6B2C41E
+:10A8B0003ADA61E779A35922DF27365E397DE6DB94
+:10A8C000B7A602CAE6978F5986FEFFF45BDE2ECE4E
+:10A8D00001F887E53F588679BDD37FF6F633998036
+:10A8E000A77FFE66112F7FF0EDB3591ECCBBF8DEBB
+:10A8F00032CCF3752573FDB6439C3F92F8BD5EAC38
+:10A90000F7FA8D8F921E073B83213E5AD2FCA45F3B
+:10A910003F49E973AD80FAF5A97D692B2FA20FEAB3
+:10A92000373E41DFEF503CA74238EE29369E5F2A82
+:10A93000F4CD19C1BB52DF34DA3928C7C3583ABD48
+:10A940007F50C481982F93BE4BB673F898AB9CF49C
+:10A95000D2FD55FAAB3ADF9F24FFF898EBB2EF63D4
+:10A96000FE5CCB1C8DF60D1F7478EDA8B7368B7985
+:10A9700041FB41CA539965A3FD1C96B298D67592C6
+:10A98000EC27A586F20E92C4788E97C785313ED00B
+:10A99000526DDB8D72F4078E91D45E4B99258871D0
+:10A9A00019096F2A87F1003E135D49B9D49F90734E
+:10A9B000326ECC70F70CDAAD12D3AE92F90C36F3DE
+:10A9C000E968FBDAC17A887F3C265D45FB3079AACD
+:10A9D0004EF2AB987916E37B8BD2104466C479981B
+:10A9E000A2E7A1571BE7A1CF32CC4369B485D12E92
+:10A9F0006C9905F380FAC79DA534DE58BAC9F97C75
+:10AA0000B79CF373EC3C99D83792E704AADC15079E
+:10AA1000705CB34CBE561CD7F3FFA849C10B23672B
+:10AA2000B3060DDF8F8AE4EDB47E9DBC88E9EF2A82
+:10AA30007C9FEB160BCD6FE7348E87872DA15C3A98
+:10AA4000C0A18532707F77283EEE2AE7723FC2C7E9
+:10AA50003E86EBAB25C9C7F9D8DDE76A463E4EEC2A
+:10AA60004BDB44F30A0F4A9F587E8EA5D731BC13A7
+:10AA700081F4625045FC7F157D255D63F7BD24BFE1
+:10AA8000244F754B7AA7D33CC33986FD4068411FDC
+:10AA90006C1F7C33B4A747ED9F59D2FD64679B536D
+:10AAA0003C05186F6EF9521DF47CE45981A7665776
+:10AAB0001CD9DF2D2E6E7F1F715D69F09BAAC18F9F
+:10AAC000C2FD62359975E2BA521396521C4D1D862D
+:10AAD0009617B185D1AE4D98CBED5AB7F7A2E7A442
+:10AAE000B45ED5707FDA00BB36E94A6ED7BA2C6403
+:10AAF000D7EE705A16EF1A44EEBC54CEFD9F2338A1
+:10AB00008F41FC46F017299E29FD458B3B407E9FD7
+:10AB10009CE74B82DF657DABBB81617C4DB5787472
+:10AB2000B46355718E15F3970BA2EC02D9FF0BE5B8
+:10AB3000FC1CFE33D339FD641EFBF4579586C1F02F
+:10AB4000AE4D9576C9E07CF72FF00DC909AFC3E291
+:10AB500043BBC3EB48A77CEFA1BEC3ADEA53491189
+:10AB600039E3F9B254257DA479287FBFD3DCFBCC2F
+:10AB7000ABE80F3EEF20BD23ED71305629FF18FCE6
+:10AB80005E9F071AD9F74F5889A688BF0BFE57F664
+:10AB9000D4A8FDC7A38D2769FF27D64E8D8D27F436
+:10ABA000AF73D713B97C1CA10C5CB74A63D930E4EE
+:10ABB000A7D8752E9FD9E9C597AD8271656714D165
+:10ABC00053BE7F84A97306BB1FADA41FFF5C3F8FDC
+:10ABD00085CE1254D2CB2553818E1FDFF67A9A4749
+:10ABE000C773B49F927E3ED35096B005F9BC2089BE
+:10ABF000E46A96381F26C79375F391C42407E6E9E3
+:10AC0000F58DC5FCB65093FFB26A33F917BEC1C6C5
+:10AC10001B98CAF5110B8F60D1F7FFE8293D578CBF
+:10AC2000017CEB0E9347A775E526BD27D77FA59638
+:10AC300058ED06FECE6E621E878E5723BB291E96E8
+:10AC40007D41253ECB3EC6EF6F1E91D2A7E0BD5B96
+:10AC5000FDFD883C26B9AFF2594335ADCBEC618C94
+:10AC6000F550DCD24FFB0F9FA58417E0BAFEEC2114
+:10AC70003EA2EC478DE5A06B295EBDFAB6B8900EFA
+:10AC80004D8FB80BC687E3F9A9C2B272711CC772A7
+:10AC9000B760BCE757F114EF513BF2285EB32623AF
+:10ACA0003007F9E1E390FE6DD3283159A857F79D9D
+:10ACB00038BA2F6087D27305E54BDC6E628F0F12B6
+:10ACC0008F5A3395FB89B582CFB3D34B39BDD34B64
+:10ACD0002E5B957CE9EBE887425E6F4D08D1FE9CC8
+:10ACE000CCFBBAD73C385FBD3ED524E89463C8039B
+:10ACF000B3A1F703FCA22AC2DEDBF3D4534FA53184
+:10AD00007E847024DF878CDE2F8ECB0B51619CC735
+:10AD100047724771FBB87C7537A40781BFB77CA128
+:10AD20000EDAFFA3827ECDD9DF4EC7FAD5BA879E51
+:10AD300047B24B4FAC00FC391C16668D92BF924F48
+:10AD400062F57BA373E445FD770BC861FD22F10535
+:10AD50008BC8EFDA7C748A0DEF07DDECF0F6A0DD2E
+:10AD6000B5D991E2A5F8BB03E445543CCAE178812A
+:10AD7000F8D0E1E1713A07CA5D8C47E1FC0B71FC48
+:10AD80002FD0FC65BD26217F1C9E30ED93DA3DDB84
+:10AD9000A89E4DF3D3F9385B0AA3BC059B9BDF2B20
+:10ADA0001A976762B641E4F0C6A9DCFFDB5CE8ED08
+:10ADB000A9A2F169786C8A6D4EF7A6931E443CC334
+:10ADC000F7C79CA509D1F87956C88396237C7EFEE7
+:10ADD0008D19EEEA62F467FD7B511E6C76ACB4E12E
+:10ADE0007D5DAAB3E4A2ED1C12F48AB4B33DAD3A82
+:10ADF00099DA7916F95F757ADDD88E59DC8F3A4089
+:10AE00008F89717CD3381A6090F274082F4498B0FF
+:10AE1000812EB14F07C6C39207FB8ECBC55CE1B74D
+:10AE2000805CFC138EBFAEF09D17F81AE3FE4AD289
+:10AE3000153C0FE80C7036DE4B159B67116BBF4855
+:10AE4000BD23F510B4A3623B0FA3FD3226B28E647E
+:10AE50001C27B3D6CFD74B8A9FF805EC191DD78B8B
+:10AE60002AF2F806E8810A8E3FC555A6A3BEA83E81
+:10AE7000DF9B89DF1D729ECAE4F6AB717FF9F83F54
+:10AE80009EB063F967B55517B553E47EF250FBC821
+:10AE9000AEEF7EB821DA4E196A5FF9ABF6938FBA3E
+:10AEA0002C14B7DBA918CFBF0FABE0F22F49CC6F42
+:10AEB000D79480BD2215EBF93DFC40338FCBBC32DB
+:10AEC0003DE0A8C0385ABB850591EFFE519A1E8817
+:10AED0006AE752F12CE3EFC3851D35DCF18482EB88
+:10AEE00074786D48C1F879666DA7E2BB48BDFF1262
+:10AEF000EB59D6378BF667687D2AEAAB196EAE1729
+:10AF000033CF69AC204AEEF44EE5769459D8EDAED5
+:10AF1000A34FDAB1BDA3267F7B3EEA0797497F3C6A
+:10AF20006ABD9B6FF6DAAAA2E6D782FB4283D0D134
+:10AF30005721F56098F4B7D4B766A9275234839E99
+:10AF4000A88FE77C2CED9DFA72EE07D5C7737FFCC6
+:10AF5000C5F4C014C4F327E51FCE1FA5E339D8B04C
+:10AF60003925F7ABF747FAED1B536885F46390FF7B
+:10AF70003BCD7A572FD9592E3A3F21EDAAA29F29CE
+:10AF8000A3B09E47F191FD37096F1A5171AB96DB63
+:10AF90008360675D5991CAAFE48FE6031673AFE033
+:10AFA00050F3F4E27DA6A9180FECA178ED7DE795AA
+:10AFB00041CF41DC5721EDA5FEFD4143DC3553E88F
+:10AFC000BD4C51AE63DC3517F7BB8C71D1E26E23FB
+:10AFD0003CA9C7084F3E1113670DFAFE03CFF96174
+:10AFE0003E0136BA03D61FCA8F55621F342B18AAEA
+:10AFF000C4F3E1D9AC93F61B336B930CF89EAE8A85
+:10B000003C0CBCDE588E137E32B5791FE0F79BFAFC
+:10B01000E7156486BCFEEA55DFC6AB30D9367EBE86
+:10B02000CF069D23BED65CB17016D27B40FCB6C164
+:10B0300018B7CD8C2E073CACDE613C27E8F71591A4
+:10B040007FB0E85BC6F382321F1DE79BE91DD8FF86
+:10B0500057F70BFF9206F62FDB7D18E412C95D71DE
+:10B060008F703616613B5A58C17DEFE10D8CEE139F
+:10B07000CEBC8DF906DB3F3820F0158B67169C415E
+:10B08000F89B29DE0D77F03CD5E1B799C84E1C0E30
+:10B09000F282FECEC03AF03500CE5CA7939D797562
+:10B0A000AD89A1DE60E79B0CDFC37029BE2AE9FEF3
+:10B0B000B083E7E166D7B19009E7D37019AD331AD1
+:10B0C000D7C8083F00BE0CF7095C5D663CA79B1D16
+:10B0D000733E57F24166CCFB6B2ADC867501FAEFB2
+:10B0E0004005C90FAE1747A35E84217D3CE5C4131C
+:10B0F000986F377D13E3F7D924C6F1FB6C22FB135D
+:10B10000EA05E0D7A3B6990568C76C75C799300FF3
+:10B11000E25062EF4F5822F88D152C589D85F71C90
+:10B12000F68D53007EBDA27E67FB3428B7F73D8DB8
+:10B13000C16587E3DB37CCC98EC02ED73D04B3325F
+:10B14000A6E37D4098738AEB2ECE7DE51EBCE73AE0
+:10B15000AED041C1CA3866BC77A7B55CBF17F3480B
+:10B160005A479BC4F9E8A87298C78C696E99FF4644
+:10B17000F9786C0ECF0B886E1FF3B2876CFF4A68AC
+:10B18000BFE46BB46FE3E34FC357A07FD270FC18EA
+:10B1900017C7F691BE18448AEE5FB4A7B1E02EDC63
+:10B1A000CF81FE1C0AEFCF8D792A69CC9897D0DF2A
+:10B1B0009F1BFA1BFFFF603E8B07D2C37C317A2CAA
+:10B1C000FD7AF46835F968BCC1090EF28FF0FE2AE9
+:10B1D000BCA7CE2EFAB38BFBBA10AFADA511BC82C3
+:10B1E0007D48ED42F5E60B02CF987798E6B6109EC3
+:10B1F00087C2DB5137CF93BADB1D176ACEFDFF4004
+:10B20000AF744EAFE8FED0CEBCE4FE96427F2997E5
+:10B21000DE1FE217D74F3F7E81269BD22E1DBF3007
+:10B22000AAE0A5E0F728B46B8AC26B241F69BB1B98
+:10B23000FD05BBD96FC3FCCCB9D312697C85290B42
+:10B240006D949F90BA90F28DDB0A1DF4F705DAF247
+:10B25000BE653347E9E9B6C21A2A87FA94475518FA
+:10B260008EC3F0051BCF7A283E707745753AFA8B6E
+:10B27000C1069E9725F394A43E64623F94E6051FA1
+:10B28000264C3BD07714EADFDD504279680989FF0C
+:10B290004DF9575B6B3D1E2CFF899DEF6BFE48EC13
+:10B2A0006B21A3527C6D42F9A3B8BFEB1DDDA8D082
+:10B2B0007EE6BA8BEF677A3FEDA9C23C2EB682E7F5
+:10B2C00069A5D76831FAD0B86EB7225E793E554885
+:10B2D000E1F835B4B7695A2AE1EDEEBCDD0CFFDECA
+:10B2E000D033D0966A5C5F26CC6B8A5D8F9AC54757
+:10B2F000F78BB146138D2313530540C579C7CF4D46
+:10B300005F01EFB36ED2E81EDF618577517E13587F
+:10B31000FF646F1416BE5C85F08079AE32CE237662
+:10B320005EB1E396F71B4B7A793FF5C4A3DFE51DC9
+:10B33000BD90F2CFE847AE7735663E6027DB534CD1
+:10B34000740F5C5C5ED4BC98A19EF0EBFE67E106D6
+:10B35000D055B48E62F7C9FE0F3F2F64651E9B85E2
+:10B36000BE93E76BF8FEDB705C3B48F71CC6F3C08E
+:10B3700063BF2FE5DFB374BE1F678D63363C5FA3E9
+:10B38000AC8DA3B8A6D50A309EBF11F78C3D2CE238
+:10B3900070CD0AD332BCD1FD85298F5EB55D95870E
+:10B3A000FEC451DB22379D6B13FE9539D14F798C4A
+:10B3B000AC20C9E0A71E15E7D31A6FCE1D8671BD5C
+:10B3C0000428EB417F5BF3D890DE329EE21AD57BF6
+:10B3D0003DEAF1DF3EF7C90D36D4DBE81C9733D6E2
+:10B3E0003DEDC39D78BFB05C9FD673FC9E8E7E58AA
+:10B3F0006BA03C11EBB91CC3FBB0F0CFFAFD961467
+:10B40000AD9AEE9F127E432573B7E27795801CC3F9
+:10B41000BD00E2DE8F81ED6719DE87C1EF8EDE278A
+:10B4200018BAFD78C3FD0256F083066F3F3FA67D34
+:10B43000F7A0ED47DA4D36B4DBA671B9114C890B94
+:10B440000D16F7FB725AD57BB8A487CA63FB629AC4
+:10B45000C8BFB78144C37D29C13F5BD21B28AF4D14
+:10B460008DE3FBA8661023C84FC79CB53C1F23CBB8
+:10B4700098D726EF1569C3FB42A0BCCA61B4D72B8D
+:10B4800059DFB1890AFAAF467B7D3A4A52DCAF6296
+:10B49000B1767C03ED9B9AB38C72A143AC1793B346
+:10B4A000A487F2E0521D94E73054DCE1CD2646F942
+:10B4B00059E6787F03EABCB4E9DA88B632801338FB
+:10B4C0009FE54DCF588E71DE37053FB7811CA0F345
+:10B4D000A38DC376A951EDD658C2A351AFD498F825
+:10B4E000B900FA81FEDF4C1D4EF1D7D87EE5BD31A3
+:10B4F000125ED6A04CCB8B9ADF9B627DF4F7776B04
+:10B50000E62EB46BFBFBB38627517FFD7946A2BFC5
+:10B51000B46FD6DF5FC4FA96FD2DFBB6717ECB2CDF
+:10B520003D34BF65E2BE52D9DF5F707EB9DFA03F18
+:10B53000911FD6DFDF778CF35B66EDA1F92DEBF77A
+:10B540002F457F69DFAC3F99FF60B536D4223F0DB0
+:10B55000950721F31F2677641AF21F5830736E6522
+:10B560001E630F289C2F561D1AFD53E48BB3731BCB
+:10B570003D64A7087F8FCE0BA9745E88F4E8D55987
+:10B58000DC0E91EDEF692A63BE313C4E84CF820A16
+:10B5900085CE238C2D537CB8EFB603E407DE7FB74E
+:10B5A00013D63996879AD2E9B9BB49A7E763E05F1A
+:10B5B000FA282EE621F887D379DCE5810CF792553D
+:10B5C000687F54C6F17CEC8AA960D946FC37582FB5
+:10B5D00047ED98F7782D2BC27368F91D1C9F29D56C
+:10B5E0006974DF7D5CD1F19E2680B794A93AE69913
+:10B5F0006FD1078FF36C9BCEE3BF5B441E6510CF0A
+:10B60000499252017F12E6BF5C908AA973E9FCCD92
+:10B61000D5DF4924FBA6E65BBD4E378CE306A5E8E3
+:10B620003FF2001F7F15F6CDF29C2B491EC4FAA7EE
+:10B6300029A8A94A30BF500D85E0D745CE45E4DFA3
+:10B640002EBA86B124F8FE6AFC0EF4D4ABC23E7A60
+:10B65000A5D7CAD0FF0B56F3FDEC1BEE32FAA50FAF
+:10B66000D8C36EB40B1F284A61488F9ADB8CE55B08
+:10B670002C7CBD2D8AF153AF8EC90392F71F6EC18A
+:10B680005FA7003EA78B7B5F441ED055D375AEAF3E
+:10B69000B39228E95B9ECFB45AD9A0FB94B2BDBD4A
+:10B6A00028B750CEA6F8080F326F8EA97B8BF07B9F
+:10B6B000D99FFCEE61656FC6C5E2A960079EEC2DBF
+:10B6C000E0FA1EEDF5DDD38DF94A67E78EFC7E3595
+:10B6D0001B8C6FFB348C53C8F1FF6FF16BCD743E44
+:10B6E000DF57677E56C2CFDD65B1E8F376321F6C57
+:10B6F000513FACD17DC2321F90A5F71522BDFF7D11
+:10B700005ABCE71EE23F618F84DF305D88FFFAEDAF
+:10B71000F58F23DD976D38BF2ADA1B0ACF43DD375B
+:10B72000413F51F9922DCD9E743A5F97CAF7DF865B
+:10B73000A7547D80E7B9B0FC1D037F19CF6DB51C00
+:10B74000795241BFE52778DECD1CE917E3C36D0EC2
+:10B750006C37C4E34AE127292E9C551B565A0B230C
+:10B76000E78362E562D63AE3F9B3D87B14E7397A26
+:10B770003545C77D803E3AD7983343ECDB208EB108
+:10B780005E2AB727D54C13CF1F19A173FB32AF2FF9
+:10B79000277A1F449DC1ED8679F1AFDFA683E8FDCE
+:10B7A000C7A1BB96639ED4BC84D76FCB05F8FCA120
+:10B7B000EF2DC73CAA7999AF7F960BF2F6CB43FFEA
+:10B7C00087978F7BFDB39168231E6EE2E5531921A5
+:10B7D000C97438B89CF68766C87B137BE8BC762AA8
+:10B7E0001EAC98F4CD9FAAD534E8BA74CC90714BB6
+:10B7F00046E7B3FD077F7702E5945FC6797DC67D96
+:10B800004F26EE4DBC4AB2578A8BECA52BF177C080
+:10B81000E755E2BE1D932D4C781D13B9CFE4A1AFBF
+:10B8200073DF4EE47C3CBF3FA865230B18EF45F463
+:10B8300009FEE77944723CB2FF01E3C27B0193A2A7
+:10B84000C7B583DA91E3FAA4C81A542646F671E51F
+:10B85000B83E51FA7662D0A3EED82F5720DD3E7164
+:10B86000F6E5E0DF37393EE31DA2E327A97D3B156E
+:10B870004F146CE674F41EDE4EF6544586CF3B231F
+:10B8800015EF0FE0F716B40B3B726B6A20887E3D14
+:10B89000F01BE57106B3F9B986EA12E3DF61AB107C
+:10B8A000FCF59B197CFF7896755BC36B25788FBA86
+:10B8B000C29AA17EFDF9B316F4FBE71DE47FA775DC
+:10B8C000FD81B72DF47719108676D6EFB00CFA7794
+:10B8D000E00ECF5025DD0DFECAF3D9F96D29309E5B
+:10B8E000F5ABF8FDD88DBF4E9C8570E30A9C25FE14
+:10B8F0003DBD7DB3F0B365FE236DF85CCE7A9FC786
+:10B90000737F4B02463FE2FA5AA3DDBFACC168AF7A
+:10B910002FDF06D401BDB67C6366CC3D7EFC7EC0C5
+:10B9200025829E4BD2EFEDC17B0796B098FB018339
+:10B930003C8E743D9F013C8DF19179F8F7A4701E07
+:10B94000EB548AF33E9FBD59C3F370F50DFC5EB214
+:10B95000595D9F5AA81CEAE17E53DA707E0F9E94CF
+:10B960009F52BF5FFFDC2E33C60B62EF095CBE78CF
+:10B970000EDD07BE585FCBF5FB883FCE4A82F7B19C
+:10B98000F7FFD57471FD5EB35109E17DBBD7D71ABE
+:10B99000FD8165ACA70DFD99650DC6F7CB371AE1A2
+:10B9A000EFCD107A6D1C1B87EB63D30C45A373D5C9
+:10B9B000023E9DFDC757C2D07F5586BF6D06F0C9B8
+:10B9C0003A4B7802EAB9AA8C00C1B21CDEAFE77A22
+:10B9D00088EB7F13AC2492BF661EB708D6F17BD9E3
+:10B9E000AE1F600F44D90BEA40B84BCA4FBBFF36BD
+:10B9F000F2C39E53E8EF82576B3E2D29CA4F8EE566
+:10BA0000C35F0BBE7E85F516E2B8F291E9802EF990
+:10BA10008BF8DF7DCE3FBC82F22CF38B158F89D65D
+:10BA2000B1896DC4FBC4405EA05C40FB13EFC9C884
+:10BA3000573B17939C9E6871F3FB76D259F4FAF743
+:10BA40003DC914C4170E1DFBBD2AAB9BEEDB98DF6E
+:10BA500071EFA728E7F246F9BC0FC0F8B68AFBB42D
+:10BA6000B7FE5A217B767DE10B240F87015B60BF17
+:10BA7000EBD3855CEC32DE83310CE5141E68995BF8
+:10BA800048FD66C8FD0799E71BAEA27BA586897EA7
+:10BA90007F3F4BA779A7ADED5470DED92CD88C71C0
+:10BAA000A83D280B53234FB94F704D64FFBC02E9EA
+:10BAB0005997DE4BF7C2C8FDF341EACD46B933A032
+:10BAC0009E8F19F28066A9E75DB8BFDDF8DCA88B10
+:10BAD000E675A836E3FD9066B7F17EC8AB0A8CEB3D
+:10BAE0007B9EC7B8AEAF2E1B65285FE01B67285F43
+:10BAF00034A7D8005FE39F6AA87FDDE299C6384289
+:10BB0000BAF17E48BB6EBC1F32BEC0783FA4D3637F
+:10BB1000BC1F92A574525E9AC516EC0DE878BF0062
+:10BB2000BF8756CAE9712E1B5D2A17576C77E0B3A1
+:10BB3000BDC81A46BAB50FE7FBB9D6176F4F0F232A
+:10BB4000D613F6DA2AE1F9B412AAC2FD289BF01B3B
+:10BB50002FBB8B19E4F89533B91C974FE60BC457EC
+:10BB6000625C768F9EC9F3B67B2EBB587EC5A53E20
+:10BB7000FF2FC2784B6B0080000000001F8B080075
+:10BB800000000000000BED5A7D505457963FB7FB64
+:10BB900075D30D880D281F41F4A1A0262069418C82
+:10BBA0004E6636AFBB81693F3269FC986010D3ECBA
+:10BBB000E816138126D14C91AADDA255863466FE83
+:10BBC00048AC4CC6A452B5AD153399A9711713569C
+:10BBD000DB4DEB362AAEC99AB1DD31194D2A2974F5
+:10BBE000DD4CAC8C0A31E3985D77DD73EE7D8FEE32
+:10BBF000D73C12B23595AA9D5A28EA72DFBB9FE75F
+:10BC0000FBFCCEB3A503C022FC3B680BEF2B01B8B5
+:10BC100097E1FF4B01EED0CF0300A7EB5C16A50622
+:10BC2000A0E2AF9565300DDF45C05186E3F65A417D
+:10BC3000A17EF0A095CFAB880C9B94CCC4BCE7143C
+:10BC40005C683AC04F7DEE65B47E47943900C77595
+:10BC5000ECBE64952BA83F98A5605BE9BB6485CCDE
+:10BC6000E4E717ADF4BC431A497760FBF7FD666F54
+:10BC7000B822B1AED6BA142B5FFF6431B6788EE627
+:10BC800027CDE1343A3B282B5D8B011AE95F199FE0
+:10BC90001F18899971FFE676E60CE2A346F9B19583
+:10BCA0009085FFF82D97866D0036FCBD331BCF596C
+:10BCB00098B517EEE5F301F2001E05F1F3C892986E
+:10BCC000054C004DAD623CFDDCC1BF47D7D45F6180
+:10BCD00095B86E67CAF319BDA3E62C9A2F5D1A9E1C
+:10BCE000AF3E27BA2A53A67D5C8E9D72A8B8330753
+:10BCF000E0BCCF6478AF873C12BFD779BF87D3FB56
+:10BD0000A7483733233AA6D249D0EFABE8B31FCFC9
+:10BD10009ECCA7D4716B3C824FFB1934F6678E7FA3
+:10BD2000FF33958F7B59BC0ACC00011F0ACC54A469
+:10BD300087AD65F3E56AA2FFCD5E46F4FF070669AD
+:10BD4000B8FE07836FE5C95300AC0786F28671BD64
+:10BD500040FF501E2C0068B3C8DBA4695C0E9CDB5E
+:10BD6000902F1D91183F7F7B7FF5203D6F8F30A76F
+:10BD70001D8F1A1818ADE7F784E15E4726ED6B7C3E
+:10BD8000AE66C5C4CFD5AAC8BC0DF871CF69343F23
+:10BD90002D1C66C4F7612B978BC30C9EC5FEDE3E3F
+:10BDA0005B63D8609D75446F94EF137D5690504E41
+:10BDB000DA703EDDE364F149AB8DE4E600DE8BD161
+:10BDC0003DCEAECDA0F5B75A406689F35D2D8E7F8E
+:10BDD00044F7BFB0D102417CBE63A399D3FBC256E6
+:10BDE000335FC7BCE9DF7B8BB0BF0EE52F0D8F7AC9
+:10BDF0007CE38D9345B8EE8556ECE37D3D9B2C5C52
+:10BE0000FFD63DCEF8F854F9D5E4F525553ED7F9DF
+:10BE1000F5F2962AAFE3E4B4F5EBC9690FC96906F8
+:10BE200097D3CA3B66CEF7BA7C929FA7C0B98FF46E
+:10BE3000E7F6714B3E9E7776AFC3B91DFB0BCCE1A5
+:10BE40001FE7915D382EDE2F6CDBC3485FF0F08F6B
+:10BE5000D0BD8A4256D8C9488E04BF7EA6F24B8612
+:10BE6000119641FA2AC567FB503E706B85F8FCBA03
+:10BE7000051A0F54D073615F161C2AD8B333496E6C
+:10BE8000EB5579B499C0DF8FE3CAADE03F9049E349
+:10BE9000FBEF6AC075F6E37C7A3E535DAF6CCE482B
+:10BEA0007D03B687687FE4F31EF51C5AFF0724FF65
+:10BEB000D8C2CB260648F7076D82EECBBB62EBE912
+:10BEC0001E8B66F87F4EF66FE5CCF7DA00ED44681E
+:10BED000F6DB157E3A1F384D44F7804AF7E34B7F77
+:10BEE000F7F216BCAFFDEE74CED786632FC689CFAE
+:10BEF0001DA51210DFED658BF2FD06F2A7B5815B83
+:10BF000025E0CF4DF43BA2A3F58A815E6F50F57515
+:10BF10008155DC1FA248A4426E8FA525558971DA90
+:10BF2000FD01B6F3FBD9CB5EE17CDAF2382C34F3B9
+:10BF3000133FC7D7696A3BCB5A709D872D8A25135B
+:10BF4000E9FCDED4C6CD97CB00DEEE461389173967
+:10BF5000DD6D03FF3C805F773B783FDE5DC0FBFF1C
+:10BF6000DA2DF376DE4CDFDB0AAEB3F6446719D187
+:10BF7000EB78F10B3E37EE73FDB485D301C0CDE90C
+:10BF8000B44595BD1B5133D8F0FD8D01160696388A
+:10BF9000FF865B45E0477BF23EED8713DBBB7EC34C
+:10BFA000ED9CB375B45ECE24B9BAD84BFD40D71F13
+:10BFB000EA01DB8FD04F907C05220C0A709DF5B70B
+:10BFC00072F9FCF6C859AB4C72601AA927FA078FB0
+:10BFD0003220B90C748E72FBF932DE4BC173A7BBF1
+:10BFE000B2395D02D18526C1CF4526E2FF132AFF73
+:10BFF00007EFF98F2CB25FB62EF9CCFDC4C753669C
+:10C00000CEC79DEE912C87015FCEE3BA9026CE4F2E
+:10C010006DEAFB466BB0CC89F31A55B94D7D6F754F
+:10C0200009B9440A5B7C5304AD18D26DBD2A5FCDBB
+:10C030007895A939D88FB0583AEA6D73D47345A270
+:10C04000B693C1259D3D00B8A4E9B37962799B6C94
+:10C05000DB41EB9525D94B3F2E3A3FB15F536B0641
+:10C0600039D1A4FD83FC1E69C5A5F97E837B8EC9E9
+:10C07000FB7011C8C8AF8E100319E5BEFD56396FAD
+:10C08000AF1D7E5A263DB1A58FBC407E01E69A1CAD
+:10C09000FB90BFED415092FDDCA85BE8EDA85BE8AA
+:10C0A000F14C17933EB671BB554EF77617FA4B5CC1
+:10C0B000788EDF17BF97750C1FB759639560FCBC6E
+:10C0C00003D01FDB489F70DF72E4CFEB06E7BEE9C9
+:10C0D00076CFA57933E1592EDF80F24D72957ACF74
+:10C0E000852E712E4D9FD71DBB621D26B98D18EB75
+:10C0F00033F3B816D2BA7D005E233FF747F59EEDC5
+:10C10000BB19A75760772EA7D355D8ED73A35C5EF4
+:10C11000C573EC45B9BCEEF36564E3FCEB7E5F46AA
+:10C120004E6642FF3B7667F0797DA5AB725BB05FF0
+:10C130004F728FFB5D8B786C44E70DBB85DE69FB2E
+:10C140007D145B974BFA536319B13AF1FD8CE8C546
+:10C150002C8AEB6A0EAFCE25FD9BE89C8BDDC22EB0
+:10C16000B5776DD97C3957C88319F569B3EAC70229
+:10C17000DB6356A2FFE62EE0F23B78F0830ED2DFBF
+:10C180006BD10C07F9BDAB47328264EFAF1F4D0B8B
+:10C19000A32586369277B467572DC3DFE3F1E361B9
+:10C1A000B32388E302473F7D81F4317010B511D786
+:10C1B000DD1C7D7A94FC5B5B74D91589DA5F7DB3F5
+:10C1C000FAD0DEF5237E5FADFF69B74D26FB794DD2
+:10C1D00012766273E40D1ECF6EBE7DA3D25741F777
+:10C1E000FCCFC564CF02FF746331D9B1C09B371651
+:10C1F000D3FBC0A18C4EA3F8A4D563E6FCD7FC63A7
+:10C20000C93949491E97ADFAAF929E67BDB3917E79
+:10C210003567D738CD72E27D4D99C947E36BDEAD06
+:10C22000CDDD9434AF272E79E9F9A2B3B5191B936C
+:10C23000E4D2EAB1A87608B51AEDCF3A9586EB0AB2
+:10C240007E123757525F0AAA7104BBC3E36D902573
+:10C25000E47313FD87AAD81797783C136C3587CB06
+:10C26000F07D53DCA4D82BE93DCE4B8A33007C2BE8
+:10C270001610BF7F38DDB953E6FE1EBAA9FF545928
+:10C2800098FC3D046D43A54971D0BAB829968672D1
+:10C29000D3184D8B513CB42E2E5DE47D353EFAC84B
+:10C2A000F1FA8F67038F8F2E27C739180F5DD6C716
+:10C2B0004B3085CEABC54BEF515C85F16CF3D69816
+:10C2C00085FC15C649BAF18F367EF70AA338A94B0B
+:10C2D000FFBC242E991EC47B96A0B92332F4C59FBF
+:10C2E000B7917E687126F16BC040DF2B553DD1F4CC
+:10C2F000A8276EE27CE889BB6DA5D8CE53DF0F3846
+:10C300004C10C4F57BA2ABF7318ACB6E3F9C41F455
+:10C31000EA39B70AB693BE3BDCB6329A77FBBBB6B6
+:10C32000B51509F918673F5CAA7D1C8B078CFDDCED
+:10C33000272E35AEFA86FCDDE53F177FA7F83F25AF
+:10C34000FB5DF19ADC44F121DEE71E8A6753FD8430
+:10C35000667FB5758B543E8FB7BF5778FC82F92F37
+:10C36000B7BF456E998F9B116DC8E579F1B935B9A5
+:10C3700072E6F8F5E7484E534EC5F8F5B5782D103E
+:10C3800054866C94C72866AE9F81352CCCA8EF6389
+:10C390003CCE0EACB784E9BD769EF81AC6C7AD7523
+:10C3A000B2B09D25E23F2D3E1C7BBF08DF9724E203
+:10C3B000452D2E8CFB18CF83D62816FE7EDE4C7FB3
+:10C3C0008EBB86EE67E7CF6B968A75D10E0C517ED9
+:10C3D000F4F0F719703BA0C68B9A7CA6C6939F45D4
+:10C3E000E74C852F892B5E56E552D3AF99297AA168
+:10C3F000F9A97AD54F77909FAE263FFD8595F460D9
+:10C40000A2B81BFDF45C379F077CFEA277259F51E5
+:10C41000DE7D585D77B1C6B7F809179DB718E2DB26
+:10C42000285F9CC87FE6794C3ABB90FABE7E927A30
+:10C43000DCA2C60BDF941E37ABF1D7FF753D1E8B18
+:10C44000FFACC6F7BCE976FD15C96FBAB933EE2269
+:10C45000BDFB17D43B79FCB8222D9F9440C79FA108
+:10C4600062AB89F29E40ABC00142D9F2199E9FBCDB
+:10C4700065065A67F3AD421EA73D762B9BB7A142D6
+:10C48000107EF4C9128EDB3CF6DA598B82F39BB630
+:10C49000B285840735B5EAEF139AAE709C2D788487
+:10C4A000F1783954D87F92F42AB86F8E4CEB37D399
+:10C4B00065090F69CD0EEF20FC82709C7BE9797ACB
+:10C4C000820EB84FBBFAFC7E15DF819438E0CDC1F7
+:10C4D0000B1CEF090C3020FDB546D17E903D39256F
+:10C4E000F08E8EA8B00B9F74D9B93DF94412F708AD
+:10C4F00074B1F036968823AE449FCB233D1B174F73
+:10C5000028184FE425E289F657DEE5F630357EC877
+:10C510001910FB04DACC61C263868A1733EAB76369
+:10C520003E984F71A22C3F5424CE05616E57141DC6
+:10C530004EB2F72EE1F73F3BF56F3C8F6C3ACC20C3
+:10C5400097C71D4ABC342F11773C1A5ACEFDBF162F
+:10C55000673C3AEBE45011ADA7C6190EFC25FC3040
+:10C5600035CEE8889CB5505E302E9E4889235E7794
+:10C57000EB71C15992C05967459983F0A4592A3D7E
+:10C58000EFEB4BE77171FD871B7349CF35FE5C6B99
+:10C5900010FCBA76E17317CD5BFCA1E4207BFBE6CF
+:10C5A00085ADBF29127DD926D3BCAD1994875CFB1C
+:10C5B000F0890CA2E79BD802EAEBA1F392217E2836
+:10C5C000ABF608FDDB3FBB39FE2B17715C4742FF22
+:10C5D000362581BFA4CE7BC023EC4108D30C8E3B13
+:10C5E0001E062EBFA142FF72DE7F7136ECE3B88FCC
+:10C5F00090D737A2D90E8AF7CAF1B25D6827FE2E0E
+:10C600001D7AEC5524CFFEB7B97EBC68E2F28BF3FD
+:10C61000838CFA0764EEEF8864EB717CA515CF522A
+:10C62000056233D4B77B54BE15621E4AF9209E665C
+:10C63000CD1DA453F98C535F101F2BD341A2F59F3E
+:10C64000B1F877DE8D539E19949CDB688EE4CC6D37
+:10C65000C07B3D63174B3D7318E515CF85D2CDCF19
+:10C66000D55171F23CCD67B203D6E3FC8E82CC1873
+:10C67000E16710B1FC7E4C2E510E18ED5329E4ED0C
+:10C68000E3F9141B2AEC0E9A9AB7EB646117BEEF1C
+:10C6900003CA83762CE904CA3B4FD6811A07D98294
+:10C6A0009771FC5A9C31159F4F2FF417525CD15E45
+:10C6B000306C1571C58895E28AB92E6DBCC0ED4C01
+:10C6C000389EECE5CEF9AF73796BA2E749FA0CC955
+:10C6D000F89E797CBFC53DD1FEB2C8E752F65F94A3
+:10C6E000FD591ECF5FFEEB8F59DC9F456F70BF7306
+:10C6F0007D240DE21CB71B163875D4C2F3F5EB98F8
+:10C70000074D4FF2673B5C820EC7A21E2E8F03F1CE
+:10C71000DA0C1AFF4B97D8AFEFDC9AD50F929CC476
+:10C720002567193FA5C86B06E2528D880FC6D1A9AF
+:10C73000CA6D704E5BBAB0E7A9F279C92DE4FA125E
+:10C74000DD1BCFE1B920F295C056513F70A8FA1613
+:10C75000E864DCAE9C2CCE631A8E9C6F545F383C30
+:10C76000C2ED6CF30F9933284F5C5FD8A5E619A989
+:10C7700076A8237240F02D15B7F5D673BB3359DC7C
+:10C7800016281B5E9CB0D3DFF1A8766581C0714F7F
+:10C79000B81DFCBE399D0B5DF990B8BF013DF77B1C
+:10C7A0006AC6D3D3605CB4D680EE06E3FEF0C0E484
+:10C7B000D6AB5626B79E6B92E35A94C9ED7B68922E
+:10C7C000EBED99E47A4F1AE92DB25DC4030E2137DF
+:10C7D00075E6DB5924FF4F1C9993FF65F1AC190DE9
+:10C7E000AD9CC47F8B231DE424BFBF627EAEAEFF31
+:10C7F000A0B34837FEA1257374EF1B9472DDFBD5FF
+:10C80000DE6A5D7FADEF7EDDF8871B3DBA7E5AC1E3
+:10C8100072DD78BBBC4AD7CF98FF886E7C087566FE
+:10C8200009DACF346B6688A1FC4F71FEA56E7C7A65
+:10C83000B53D93F422B4302D46F29EF6D6A620BD27
+:10C840007B9AFD642446D4CD3AD8C85065A5EC57F0
+:10C850006CA4272B978ABA405FAD2DBC87E29CBBA6
+:10C86000B22A69BE46AF7D7522FE72548C06739162
+:10C87000CE3395786D2EEAF3F5A5C0F387EB7651AC
+:10C880001F00C951D8C0F9E7285C85763F6437AEF0
+:10C890003335D6A979F104F6E4749DEB17A42F0E75
+:10C8A0008ACB0DF8A8A878BD23021CB701492E5CDD
+:10C8B000C5F7950BC9DF4C3D219E67C540D9C3CF55
+:10C8C0002597ACE271B45C42E7DBA5D6BF7296CF88
+:10C8D0002D21BC2E07FD2ED5479EA33A09CF031C60
+:10C8E0007C9CB69FB356ECB7CB028CEA59C1BB19FE
+:10C8F0008F53C1315557DF386D895D6E61BCBE7194
+:10C9000082CEFF8E2956B1B744F085E85B31E0E076
+:10C9100075975F2FFDF97C3FDF47D43BB638C49055
+:10C92000E3946FE039B61CA9E6F2DB746CE96FD7CB
+:10C93000535C582A713A8F8BC7D53CEBBC9A276A57
+:10C9400079D630E58B4979C7798F6922BB74DE636C
+:10C95000A057BB98C88383EF883CB8DAEA9CD39988
+:10C96000C4A7CB6A3CDE121378AC96DF562A61531B
+:10C970001ED2A1FA29732C0DFD7575EF022BD9ED8E
+:10C98000EADEE2748E2F6D3C60D2E86DC4F76BEA8C
+:10C9900039FB4E8DF0FAC41B29754A67AD95BFFF70
+:10C9A0005B551E9DB5C0DB2D65D20E72C353BFED26
+:10C9B000301BE1E3CD18FFD3F95A42E2BC5A3DA443
+:10C9C00039267B689F8B4323BDD456B59678387E35
+:10C9D000D836DA4BFE3370FBC6C907381E6095297E
+:10C9E000BE4A5DF7509D99CBC51B149010BD96496A
+:10C9F000611A57BD4CE2FCCE69B6F37C3CC702E637
+:10CA00004CEA37087F56E59DE6A13EACC9E6FEB884
+:10CA1000EA949CBDA92291EFE72CDB3A9DE8F455FE
+:10CA200075220D37983753994A7EE3EBD689DA4F52
+:10CA30009FB3D2BD370CEBEB445ADD67A23A915657
+:10CA4000A70D783FD7D59503D2483DE12BD5472E8A
+:10CA5000F23A7120C21C052589FA516060D4CAE9F6
+:10CA6000ABD68D70BC95E60D748BFAD141DC9FDAA4
+:10CA700008DE57C173FC23DE97DA28DE979E1FED90
+:10CA80009ECFDB58B793B7C7BA97F0B61AC5A63092
+:10CA900087EA4EA3BCEE5453ABAF5B68750977A130
+:10CAA0006F496D8DAE6EC1FBA9750B73BAC8470394
+:10CAB000A72CCEBDF83C70DAC6EDAC2BDA328BE297
+:10CAC000B29B67FDB31CBC0E90CBF3CA31F9559CE9
+:10CAD000F66CCA077C4E3BD50BAA07AF58656E773C
+:10CAE00062455040F853DC4A793FD141E1F19CCB9B
+:10CAF0004E74FD4A7C3FF2FFF8FED7C1F7A37502E2
+:10CB0000DFD7EC4795CFA4ECA1F69462DF94641FC5
+:10CB1000FA7C0227EE2B9DCDF5EF79DFECEC8DC989
+:10CB200078BE57E47139CB4AEDC9CF59BD45C47DB4
+:10CB30000C7C4676ACB776427BDB6B1CDF19D705E5
+:10CB4000FABCC28E68B8FFF83A81F3ADD224BCFFBC
+:10CB5000DA3B28A798B70E1E4EE3FEFCE691B4BD63
+:10CB6000147F577937CE9A82FDAAF3695022FC913F
+:10CB7000AEBED0E43529F62CA37A82526442B91DA8
+:10CB80005737F09AB87D1FAB1B78A58BBCAFC6E9B1
+:10CB90001B467F37A58411FDC321CA33DE6867CEEB
+:10CBA00041185F47C0858B6009DEC27B8ED7959D9B
+:10CBB0009DCC29CB5F5D5FC85371868E48B699E4E2
+:10CBC000BCF904402E33AA337879BC5F05CF866A5E
+:10CBD000E97BAC529383FC592A5E407242FE3F15BA
+:10CBE000278CAA7C8CD60A7F53E711FEA64A8D4B70
+:10CBF000B479A9FCCF56FDD344B82353E39F1E6FED
+:10CC0000551FF12FB8D204E4077ABC6E5B69D27A63
+:10CC1000676AC5774BBBA86E312DB96E21EA13A99F
+:10CC2000F50ACD4E550F7E514FFC7F3E2AF0A440B1
+:10CC300081C037AB8FBA4E91DE27CE29EEF73CF29A
+:10CC400038CEE3286736887B814DE05E1C67A85AA2
+:10CC5000F9F9B10CA29F0FFD15D9A5D3A53B32C997
+:10CC60009EAC946A98CCF1EE31FC9BF0A9D5675A42
+:10CC70009703F9FFB50BCF12DDD7AEB7F0EF9034C5
+:10CC80007FB5FA4C63BD78BF677B3ABD9FCF9C767A
+:10CC9000999E7BDDF47CC5AF6284F4C183747BD440
+:10CCA0009BF8E9CB12E9CBBC99FEEBA43FD50D2A4A
+:10CCB0000EBE5EF8D7B5D1060B648EF777C78B6FC3
+:10CCC000F23CFA46B49AE3DBB9547FAD48F88BEAFC
+:10CCD00023E887A6FCE9FC50769DC807EF453F4452
+:10CCE000E7C9691075C254FE9F51E3C989FCCA4463
+:10CCF0007694FC886989D01B5690F0BF32E5D7F74F
+:10CD000025FCB02382FDFC2FC1BD55B9CE9E200E5F
+:10CD100073ABF23BE1F71B916F0607FF8BBA3F8FB6
+:10CD20007A9696E76878B89617BDA8D2596B5F5285
+:10CD3000DB54BC4CC3C9F21580AE2FC1C9F2094700
+:10CD4000CB21B35DC171BB42F50C63B8592CC774DC
+:10CD5000A71CC7A9B89D869FE56DE86714671443B3
+:10CD6000701BD997212BB80E4CA3EFF6186C23FD3E
+:10CD70000E37F03867E8A5F77B7F41DF1B0E3007E1
+:10CD8000B99FF6FEB3DC4FB7635CC3E3A1E8A7022B
+:10CD9000A7EA17DF9BB647986284830EAAFEB956AE
+:10CDA000016E37DAD5EFFAEA07845E2770A21F49D1
+:10CDB000C93851408E4FD7BE170C0BFF64F85D5F2A
+:10CDC000078CF0EF013B5A993386CF5371A354BCC3
+:10CDD000E859F53BC0097123E5EB7DEFB7BD6EEC7B
+:10CDE0007B3F8E3FEFF308BBD0E8678CD6B7997CCA
+:10CDF0006DFCBBDFA3CC61F4FDE86E55EE57A8F8DF
+:10CE0000EDAB56210FAF7E8B85299E5B0102A77D7E
+:10CE1000F5680BC76F5FAD624E13DD53C56B97AB03
+:10CE2000F4B83B81D73E4F78EDF7D09D104EBB4212
+:10CE3000E53F40989FAB61777A8CE28D672CFD05CA
+:10CE4000A48FDAF7465E15474D4F834E23FDECA9BC
+:10CE50007379EB6A68DC84F1CE2B7506F8CE558FBA
+:10CE600058F7977518A7CF07A3387D7FDD745D9CB1
+:10CE7000CEFBA971FA9F0AAFF5D03D8DCFFFDF93AE
+:10CE8000C4ED1EAF9DDCB84D7506F1DF0E153F49B0
+:10CE9000A56F66BD66876738B83C8D9D1F443D57BA
+:10CEA000C5BD86543F1762F26FEFE7F52F0BAF7FDA
+:10CEB0006976263445ACFF816A5FB4F6A6DA862C23
+:10CEC000C6380DAB177EEADB85CAFBC4C7F2D7F4C0
+:10CED000B8D9827E3D6E766F2447D75F18BB4B373B
+:10CEE000BEFAD46CDDFB9AF83DBAF7F79DAFD2F5E8
+:10CEF000970E7F4B37FEFE4FDCBAFE7746F4B8D96B
+:10CF000003B7F4B89926DF2E9488E4791EDB0F74FA
+:10CF1000E38A5AF5F72AEED4DF6B5697FE5EDABA4B
+:10CF20002541FDFDE684F4F7CB215CBFE27F8FEB6A
+:10CF3000FF4DADCCE97F2C3AC74EF376794BED141B
+:10CF4000C74C2F14F2AA8DFB1FAC27E8D970300014
+:10CF500000000000000000001F8B0800000000001F
+:10CF6000000BE3146060F8510FC1D3F9191836F3C0
+:10CF700023F8F4C0C79819188E83302303C33E20CA
+:10CF8000DE0AC46B80F83D0303C352203D078827A7
+:10CF900003711710BF048AD5B1623787858D8181EF
+:10CFA0000D884F02CD3AC54CBCFD8A7C08F6215E47
+:10CFB0000686B5407C9497BE6130D8F00C41FAD912
+:10CFC000F50C6AD76ED181F73708B38A3330304A0F
+:10CFD00020F8FD12A8F26CE20876960C65769501B1
+:10CFE000F50300295128158003000000000000000F
+:10CFF0001F8B080000000000000BED7D09785445F0
+:10D00000B670DDEE7B7B49BA3B9D90952574802000
+:10D010002A4BCB1201113B2189010306440928D276
+:10D020006C2184249D01661E3EFDFF6E0842C4D122
+:10D03000898A1AFC195F83E004079DE0A0139DC054
+:10D04000348B8833E804C70597795F401E2042126D
+:10D05000A338E8F3C9AB73AA6EBAEB763769B7FFAA
+:10D06000F97FFF840F8ABA55F7D4A9B3D5A95375B0
+:10D070004F14924292FA1372097E6E20E455851085
+:10D08000FAA8BBEC903A87CB0383ED6BBD2EE2325E
+:10D0900012F280D784E57A6F3A715D419F8FD61581
+:10D0A000F92D84DCEFB5E3F3C7BD25583EEA2DC565
+:10D0B000F211AF1BFB3DE42DC7F257DE1A2CEFF542
+:10D0C00016617B9D7715D66F5416A4C1B884B84CF1
+:10D0D00059C984785E1E387203ADADCF1C9F208F76
+:10D0E000A6F5BFEA893E8BBE375A2EF20FA50D7208
+:10D0F0004951D6E8603F15CF1B95BCBE00E7F1B1A2
+:10D100003AD6CF54F35A76E47E59640CC573AC8C8E
+:10D11000F8134BC9E4ECE488FD0603BC4786B279FA
+:10D1200012BBF3B54191E15D0DF01E1ACAF14BB689
+:10D130004F1E14199E13FAFDCAC9E1A5771E1E18C9
+:10D14000B9DF18E857E7E4F0FAFA4C03228F3B1EE8
+:10D15000FAC5C0278A1321BE16A33F3BEBFBF38B16
+:10D16000B8E85F8A4FC75EF3D60D12F26F1AD06926
+:10D17000AD7DF9992D749CF696614EBD8390CF5C80
+:10D18000CE04BB2526BEDD02F388816FA5304E0C90
+:10D190007C9B1B23DF1640BF18F8B604FAC5C0B746
+:10D1A000CA18F9F6B39F08DFEE053CBE07DF36C4A8
+:10D1B000A86FBF8A916F1B63E4DBA618F5EDC91851
+:10D1C000F9F65428DFD4E76AB9834868176F544AE0
+:10D1D00076403F4F669B6D40D64F827F7BBEA7DE79
+:10D1E000ED8F917FAFC6C8BF23409F18F8773446B4
+:10D1F000FEBD1323FF3E8851EFDA709DB1C85FB5C5
+:10D200000D21F8736900FC6BB19FBA9AD7F580774E
+:10D21000122119E172A09694A3280F3271B7B37549
+:10D22000ABE09B4B3984AC30D1FFD2F77D7924A0A1
+:10D23000A7E3FB6CC45F2B09FD3F073C09C9FFE670
+:10D2400052AAD0DFA78BD89FE8A0FD61902BCAFF20
+:10D25000CDDE2158D67339DA5CA44379F0251B5012
+:10D26000BE9EF03AB1BDC13B16CBC7B85C6EE4724E
+:10D27000F400C8DD152087A55CAE98DC1152E228C9
+:10D28000A774EDD8134F363850AECC12E02933795D
+:10D29000BB77CF955B3750F89B6B74576E0B91B390
+:10D2A000278A54F9A292991CECF744F909DB82A170
+:10D2B000486F1BC06928D6A9FD7CA1FD1ADCDDFDE5
+:10D2C0007A41BFC78AB97CC924103AEE63A5DDFD57
+:10D2D000D2254A977B2552DA6409E7CB1489E929DC
+:10D2E0005514E487CCE9BB3FEF2C69A3EFDBEC23BB
+:10D2F000D3082D9F04FD44FD7360A9BE5F4FE9EC88
+:10D30000A6F4C834929A26C097B44A0AC5571EEBB1
+:10D310004804397A689C8B485642FA433B1DBFCF7C
+:10D32000E8369245CBC4F16D441A06FD683BADA7C3
+:10D33000F0F68CA1B49DC27908DAADC1F654DE9E38
+:10D34000E6E0EF5FC7DA1FF6121C5FED771FE5B36B
+:10D350009BE2B78EE28BCF8B890BE8285376FA439A
+:10D36000E63F5BD2E3BC2B79A9E27F5FF6A98CF99B
+:10D370004383F89A075FCC981F82DF7D83E7605D67
+:10D38000C5C77C4525D6FBAFEA4D3D31AE0F249C89
+:10D39000CEA9330708ED0ED9897E9AE3889EF82836
+:10D3A000BF1C543C23F1E70B2ACE3FA8FEB9183D21
+:10D3B000B4ED776BE8B02E43A483A1B7488775BD61
+:10D3C000453A18FA5C9E0E532407C28F460F75DC4F
+:10D3D0000D578AE3C65D258EBBE12A71DCB8AB7FB1
+:10D3E0009871D7F713C735668AE3AECF14C735F601
+:10D3F000FF7EE312D9491F3273411CF0CF3CC1BEFE
+:10D400005D20EE8741BFC1CEE99383764EB697107B
+:10D41000B725C84F22D3977342E1DC29D8550AE7D4
+:10D42000FF7038AECBC3B16BE0CCD5C2D9C6E190AA
+:10D43000503B1D0687DCA19DC76FF97B015DC8F8D5
+:10D44000747D2525D6D0F79C9AF16FD78EBF1BEC43
+:10D4500018CC4377D9F11D1ABACED1E2B387C321D4
+:10D46000BACBD183D83570666BE11CE27002D2650D
+:10D47000E1946AE7F1BACA574958BF283D8605DFEB
+:10D48000EBC8EB3C857ED08B8A633B6D97FE640DC9
+:10D49000DC40FB1FD922F98DB41ED81B8FEBC7F9D6
+:10D4A0006DD3B1BEEF1A23AE13E79D93FD466A4FCD
+:10D4B00026BDF0B60DEC4BD50B7A19EABABD1FDBD1
+:10D4C000DA285E1E63EB83D7D1E79D2FE8C9569417
+:10D4D000C6421DD0FD14974DB28AD5CBCCAC5AB5FF
+:10D4E00065DF9D00B7BCD948CC144ED54B4BA65D2B
+:10D4F00047EB4B0E2B04BA546D5F6DE84DEB4BFDC3
+:10D500005213D43BF24839E8D39ABDFFD90EEBD180
+:10D51000F9DD4A368C7F96AE130E6A8F8F585B53B7
+:10D5200067523C2AFCBB0AE1BD8A9D92935A388A15
+:10D53000EFF6431980EF0EC969A4F45ED6184F1CAC
+:10D54000AABDA37F4FEDD6E3FC97D3F9130A6F0969
+:10D55000A92F047A560171607CA7D16F9682FA7662
+:10D56000D67B18C753EB553BE878F4FDEAE7242750
+:10D570004CB55A47DC8067FB4BE6D2A72C30CFD5A1
+:10D5800086C15698DF7A03F45BE29FFFA2D9017847
+:10D590006E311402BE9BB718CA8602FDC8BC92A1A8
+:10D5A00080DF5F44FC1AF42E98EFF26B8C5BF5C0C1
+:10D5B0004F4B60D00C6BB89D3D4BD72B47C8FA59E9
+:10D5C0004198DD27B2DF307D58F0F94BFA4494835F
+:10D5D000658D7AE208B51B5C3E7C4709F363F6581B
+:10D5E000FDDBB3827C5C6EE7F2CAF9B83C91F3557F
+:10D5F000EECC99312C1C9F07812F46E61F41F93054
+:10D600005D371DE8FF38907E8F51FFC981FE911371
+:10D610009F3F41FD242837533F09CA27A99F04A5EE
+:10D620009FFA49D06F2BF593A0DC46FD2478FE3499
+:10D63000F5CFA16CA4FE393C7F86FAE550EEF4FAF2
+:10D64000F0F973DE3A2C9BBCF5583EEF6DC072B713
+:10D65000D78FFD5EF43662D9EC6DC2E72F7B9BB1AC
+:10D660006CF106B0DC0B7CA665C0DB8AE57EEF3191
+:10D670002C0F7ADBF0BD43DE3358FE92D3DD3681CA
+:10D68000E4CA545E6C2E6207362515BB72C15F4931
+:10D690002A61F5D43B7CB9065A4F75D33AA563EF9E
+:10D6A000CA40AE91D67BD7B0F6CC7B489E89D633A4
+:10D6B0007DAC7DC02F5D79665A1F50CFDA076FF6BB
+:10D6C000E5C5D1FA603F6BBF6A67202F9ED6AF6A6F
+:10D6D00062EDC35BC8240BAD0F0FB0FAC823AE498F
+:10D6E000565A1FD9CAEA391FFA26D9683DA78DBDF7
+:10D6F0003FFE5C605202AD8FEF64ED13BF26F976FA
+:10D700005A9F4824ACE75972F313693DCFCEEA859E
+:10D710007DE7CB8E08EBFB5EA56D2198B49FEB7285
+:10D720007265EA27EC35B4AD0093BB5E7743AE3C3F
+:10D730008ED24F218BA07D93AE88D50D6425B4FF8A
+:10D7400056371DEBFB1507B6EFD1CD61758303DBB3
+:10D75000FFAA5B88F5838A0BDB8FEB2A59DDE0C2D9
+:10D76000F6CF743FC7F10E296E6C57F4FF9BD50DB1
+:10D770006E6C7F585E9F9B4FFB57EADD1E1D95EB3D
+:10D780005AC95D4E0682BC36A5833D5CC7FDD6599D
+:10D790003A07CAFDBA0C03EAD9DEFFCA790AF50CCA
+:10D7A0007E92A15EF634F8BD14CE2A84A35038FAD6
+:10D7B0009EE14CFC66AC0067E237E52A9CD508C7C1
+:10D7C0001C1B9CBDDF8C17F1F9A64285B34147EDC8
+:10D7D0007DAD35B6794DBC3441C4E752A50AE71199
+:10D7E000C42731367C02CAB5029C80B24485B31985
+:10D7F000E1A4C4868FCB304E80E3322C55E16C47D8
+:10D800003819B1C10918AE13F1312C53E13C87F43A
+:10D81000E917DBBC5CC6EB457C8C552A9C3F203E5F
+:10D8200059B1C1D96F15E9B3DFDA4D9F00C2C98E76
+:10D830006D5E7936913E79B66EFABC8670AE8C0D0F
+:10D84000CE7E9B489FFDB66EFABC897086C536AF0A
+:10D85000BC04913E7909DDF4F900E15C131B3E073D
+:10D860005344FA1C4CE9A6CF49843326367CF25344
+:10D8700045FAE4A776D3E73CC219171B9C83A9227B
+:10D880007D0EA676D3E70B84737D6CF3CA4F13E944
+:10D89000939FD64D9F4B0827D7DD88F8100AC71AEB
+:10D8A0001DCEA17E227D0EF5EBA68F490F700A28B2
+:10D8B0009C813DC329CC14E95398D94D9F443DE840
+:10D8C000C5E4D8E01CCA14E97328B39B3EBD119F80
+:10D8D000A9B1CDABB0BF489FC2FE8C3E1E63E7240A
+:10D8E0003BF88D89C4B995BE3229F9670761DD51CE
+:10D8F0002CC409608F48816D009FAEADE897CA4E79
+:10D90000D50F7212F0738B6D0E27C403F4AABF43B8
+:10D910005A713F62D99928C49B5ED2E70D077CAD4E
+:10D92000D42B0CF57B12C6C609FE56A22B49A8F7CC
+:10D930002AEA2DF44F291920B4A7955E25B467B8BB
+:10D94000470AF53EE5E385FEFD6AF2847AFF55530A
+:10D9500084FE59BE19427D60DD1CA17F76FD02A1C7
+:10D96000FD8A860AA1FD4AFF72A17E75E3BF0AFD0A
+:10D970008735AD11DA47346F10DAAF093C2CD44744
+:10D980001D7E42E83FA675ABD07EEDB16784F6718F
+:10D990006DCF0BF5EBCEBC2CF4BFBE73BF50BFE117
+:10D9A000E29F85FEB9E46F427D92E903A17F81FD8C
+:10D9B00023A1FDC6F44F347EAC18BFA8CD25CC9F63
+:10D9C000CD30A03F1BB01AB06ED86B66FB1BA827EA
+:10D9D000431CA218EB86FD0B1DC9100F0000D49F3D
+:10D9E000C8ED5D7E05C4AB7E31DE7D05C4717F610F
+:10D9F000708FB047F083DA65F73D7A8C27B64A24FA
+:10DA00001D4A870ECA383D8F271899FCAECFCA79B8
+:10DA1000CA17A20775FDA87F41EBEBF5148F3141C2
+:10DA2000FD59DFAF2C7D7EC838EBFA194AB70E6579
+:10DA3000CF175A60BC92FB603C8FA17330E0A51DEC
+:10DA4000C73860AC308E29B31CC7D908E3A404C71B
+:10DA50003166966BC631956EE5CFF9388F81DE441D
+:10DA60001B67FD80F1E27C322B709C2D9A71D6678A
+:10DA70005668C68963F3A1CFF9384F5D6E1CE3C0C9
+:10DA800009E27CFA57E238CF69E7D3BF52338E05FB
+:10DA9000C781E7300EE94B77316994CFC6CE329417
+:10DAA000833F99314E66E853F11BA8930FCC241B9A
+:10DAB000C671D071693F3224890A3521FFA24F42D5
+:10DAC000FE7C1147F91F124F0BEEC77DB8AF5FCC3C
+:10DAD00051247E8A11DD275573D95CB4737AE60A26
+:10DAE000072D9B0F0C7A04C6D9687566D37A7BF331
+:10DAF00024C3C208F2B4B85E39D51622E7DDFBB301
+:10DB00003C32A4868EBF22CE8EF8A875B54CD28941
+:10DB1000CF4FD07D17A1FB930FE93E85D0FDCA47BB
+:10DB20000ADB67FE3BDD9F41BD8DEECFA09D90D50A
+:10DB3000F8DE091E673EF14BC90FF4FEE2AE9F29E5
+:10DB4000B84EF8C85BE9A9104D603FF356C553269F
+:10DB500004F19BEFEB25D4A939EEA34BC77D2DC66D
+:10DB60000F3A5F32FAB7025DEBFA509AF27E030881
+:10DB70007977EFD443920DAB7D746309995933BD26
+:10DB8000200DB548EAB79CE23963F7350A7D83B4C6
+:10DB90002B6D773A2D41B8C4A59C00FA98E81F80F8
+:10DBA000734B11AD878C7F6B89589F45E4609DF264
+:10DBB000FBA47E0061F17F3EAEC3A5005F4BE81C75
+:10DBC0003328AB674139129A59BCA6D4CEDE55F141
+:10DBD000F12C544800F7D7BE148863135F32F69BCC
+:10DBE000A3EE9335F8952A265709A56BE97C3DD21B
+:10DBF000558BEFFB7BE35DBAE1B4AC7B4481D06C29
+:10DC00004FF8CF768BEDA49C8DA7D2559597539C5A
+:10DC1000BF2780FFB43C0DFCA7789FE4FC0FCA31FE
+:10DC2000E3BFC7E89E06FCEFDCA427C82FCEF7DBD6
+:10DC300038DF17D78B7CBF0DCEE368FFDB5666B1AC
+:10DC40007853432F81BF74E2221DEA1F2AA0663554
+:10DC50000CFFBF73399853B7EB1560EFEDE59AF9F8
+:10DC6000713EDCC9F93057438FDB38DFE672BE2DD9
+:10DC700021BE7B33307EE15720AE37BB5C22602F64
+:10DC80003C77AB7C6B13F8E656F9A6C1F74ECEB7DE
+:10DC90003BEF627CD3E2DDC6F9D6D6F0994206842A
+:10DCA000E3ADC573DE2ACDBC7C5ABED573B9B41BB7
+:10DCB000C09F9AEECA5D7132A4FF2D4593579C0C0C
+:10DCC000B10BB7964C17EAB34A670BFD67BBE70B7E
+:10DCD000EDB7972F15DAE7D6FC4CA8CF5B7597D038
+:10DCE0007FBE6FB5D0BEB0EE3EA17D71FD43427DDB
+:10DCF00049C326A1FF52FF16A17D59E30EA1BDAA7B
+:10DD0000699750F734BF24F4D7EDBDF26690AF2386
+:10DD10006FEB09C4FB2E384F639CF1825371429F15
+:10DD2000935E07CAF129EF102CCF789D28E767BDD5
+:10DD300063B1AC06991C0776F68005E2A79E386AA7
+:10DD4000F713E93A2E8F5B533701D61BDA3E9E90CC
+:10DD50007F956F58E3EB4BB500E2DE94FEC50D06F0
+:10DD6000121845A874F7EE96E74E7D487B5B0FEDE1
+:10DD70000D3209F40A6F2F6E8BFCBC43EA1C9C0128
+:10DD800071D9F78C647B48BC31FCBC85F401BF229F
+:10DD90005AFB391D290F3DEFD92AB3739E23FABCD4
+:10DDA000AD32C5ABD2C0F4BFF2F98C3C62837A606D
+:10DDB000708DE532E3355164D280CF0305BD5FD26B
+:10DDC000707550CF098CC3ECE952FF28E1F9B2C657
+:10DDD000EB84F7DE90DC5B008F73FBF4B85E93C0DE
+:10DDE00081CC5B86017EAEAD32ACA3CD29E877B5A0
+:10DDF0007A5D2B4E2A84BCE92DC2F22D6F0996EF75
+:10DE0000784BB13CE67563F9BEB71CCB0FBD3558F6
+:10DE1000FEBB7715966D5E1F9627BC75589EF4D68F
+:10DE20006379CADB80E519AF1FCBB3DE462CCF790F
+:10DE30009BB06CF73663A9DACF9EE4EF0C5F5FCF3F
+:10DE4000821C1AC3E5ECE0DA796BEAFA06E5ECB07D
+:10DE50005C8672A6D2B7B8C1C8E521559087BFC20B
+:10DE60003A9C02F2D2437B83C2E530DAFB91DB417C
+:10DE7000DE7AFF08F246C81A94030BC8DDF7903724
+:10DE800002A70829204F7D34F224CAA12A47AA9E5E
+:10DE9000BF21959C03F952E5CA22337F4895ABFB1D
+:10DEA000C14F8CE06FF55624BEFE31FF88047275B9
+:10DEB00040B2E5FCBC82F85C58EFE263D75270AD2B
+:10DEC000D04FF60F8175A46BC8578321BEDF758CC8
+:10DED0000A4156F4F969E5253ADD5DB87F28F35328
+:10DEE000E6F70A6F37C731BA9A75A4888C84F3E5D0
+:10DEF0009C636ECACFB83F5D3D12F6CDF4B94C922B
+:10DF0000008EDF393DC27901194490CE3DD157EDE5
+:10DF10007FEA89FFCC81737F0BE8399D7BDC017D33
+:10DF20000DD3DFA79CB7849C2F798CCE7488837720
+:10DF3000661BECCC7F9824D2914CC2F303958E07DC
+:10DF4000B2BF180CE733F7513904FDEA1A343881AF
+:10DF50005C463E7AB2F73DD17301CC37267A1A0877
+:10DF60009C73517A6E85FB8EB1D2B3273BD9937DDA
+:10DF70003CB181D1F908F74FA3D1593D0FD3E271DC
+:10DF80008B22733E7039267768E85F2AD0BFAFD501
+:10DF900081FD0FEEFD2013CEF1BA765F91408686AB
+:10DFA000BE5FC0CE7BBADFCF17F440FAD3DF336158
+:10DFB0007F7CF08577B15C4B981E6EB494CC55C6CF
+:10DFC00004E1C57A8F20DABC3C8A24CEAB07FDEC95
+:10DFD0004855F5B33513E46937B70361F3EB413EB8
+:10DFE000D5F91D80F951385341A6E93CF2E592BBC1
+:10DFF00084F98D4EC179F7343F4F82814823287EC2
+:10E0000056838124507954DC6B15DCD739DB7C10C6
+:10E01000A7D81BEFACA52CF1D8CEBE1170C07B6287
+:10E020003C6359A3B946F49F126B44FF29A326D43D
+:10E030007FEA3AFC94CD4DF15B9EAEAF39D90BD659
+:10E0400039175FE7D8BAAAE257D594556311E0882B
+:10E05000F5AE7AA988DDC37124CC8C70DEA796CB8F
+:10E06000D30D38CED9C6810930EE59AFA986ADAFF0
+:10E07000F61A366E7A4DE8FA5AB92ABEE6E4A820B6
+:10E080007ED1E0FED0F85189201F99605DA46D0318
+:10E09000A3F78FCA4FF973039EABB7285F80FF6E5B
+:10E0A0001EA2FAEF32D655B89E26BDCF38029EEF9B
+:10E0B00014C6A3EF39D4B371782FBADCC8E494CA7C
+:10E0C0004F3D9C7711BE3F30219FDD14620285D702
+:10E0D000215BEA40AEFC0AD3670F97D32A539BC15A
+:10E0E000ED4072B7825C2F18ABCAB963D607D44E25
+:10E0F0007FFC1705EF9991AF29F49CE0558745A463
+:10E10000C40641D505BB9715C3BAFDF18B37F17D28
+:10E110007A7D0ECCFB3CD115815D3A4FDEB48D0A81
+:10E12000D1D7D30A8B63913AB6CFF1D13F30BFC577
+:10E13000F5E2BE674983582F233352C1DE966D54F2
+:10E14000889FE2BE14F64DEABCA9FD7D57B123724B
+:10E150004B48CD3AD8A73FA6B078CF023B91FB50B1
+:10E160007B5DF5875FE740DCA75D61FEAE7A1EBE92
+:10E170003489ED072B66FA0D2EDAFFA3DDA36EA31B
+:10E180001697BEEF5F87FECF74E2DC4EC2E9BEB0E9
+:10E190004EC4AF27FCB5F8AA7E50D8B93CC723B906
+:10E1A000518A785FEA6B6EE754FD4832D885B84FE4
+:10E1B0009AA6AECA81C2E5C0AFB8AD8614C677E0F4
+:10E1C000A324771ADC21FD0CC17E498631D1FB19CD
+:10E1D000A19F1EFBA5B17E9D85B83F26549E860655
+:10E1E000FB9983F0FAB271C57E557F78F6451F958D
+:10E1F000978ADF3D6A2374DDFC58AE4F75D2E795F0
+:10E20000DBEFB5B9687946F6D9809F1FFBF511EFB2
+:10E21000FBDE6250E9E1B248104FE3F249EA7C18B4
+:10E22000A7F862BB62C773844663C048E5B37AF758
+:10E23000D262321CEBC7597DFDA77AA8378BFCAAA6
+:10E24000F8CDA3A90E764F88C5934800FDDCEA6D92
+:10E25000FF5108EB858774A29C69DF83F12F26A10B
+:10E260005ECF372484B7E3C5E054789FFD7876DF2E
+:10E27000FFA9DE06E5E4D3A0471E8D9C9473BF156D
+:10E28000E805FBFD7C833519EDFDB5E45AD07795A3
+:10E290002EC4CFFCD7DA1D8F0F3F4EF13AB7ED2FCA
+:10E2A000366968A89D60F2D6D5B4F0DF4CBAE8F6BE
+:10E2B000A49DCA63A89F4401E37B8E66EE77B7B046
+:10E2C000B25209D8E03E4EE516C5492591543EAB01
+:10E2D00027703F81BC67F4437C74D9B3AFBC339ED5
+:10E2E000D27FD92E25B9984DC722A506F9E3A17F83
+:10E2F000578D0CF2A3E2F7AF181CC3D8F37B9282C0
+:10E300007C59B66B9F810C0BA7E3A4A67D86364B88
+:10E3100004FE341D2F84F5B676C73F0C1057FC78E9
+:10E32000AF44D2B2C2DF2FDFF20AAE7B4027E42730
+:10E33000E75737FFC2F81698F6F268EC67077BD804
+:10E3400013DFB2613F9782F2FDDCCB708FE97DA3D2
+:10E3500013E850FEDC0A1BCCE7B45CC3E4FCD7F73F
+:10E36000A682BE972BBE543B96EC79F9933F47F9B2
+:10E370005B72F4E7A9E83F1057860E6DB32F03E6F2
+:10E38000B978F3AD38CF32E246392CFFB5BE04EE92
+:10E39000995E9049D1AE087AF21703DBBF9CDE4A42
+:10E3A000994BE7791AF003FBF6A6DEBF1DE3E63FC3
+:10E3B000C37B703FE773A62B21D62F9818BFB618E2
+:10E3C000746A3CD424C8EFB6F5ADC0A7B3FD5C6950
+:10E3D00070EE41E9E0E374932E51B8FAA305698C1D
+:10E3E0004FC421E7F0F7A8BD9F04CFA17FABE23275
+:10E3F0000F17DEE3F6918DBF928F4FF18E83F5EB11
+:10E40000746A64FFEF1F7C7EF4A79584C85988BEA8
+:10E4100033FDDF761FD37755FFFDD38BA0FDF3B718
+:10E42000981EC17BB05E50BC0269D8BE6FA684F650
+:10E4300081EEB323E9F93685EBB9D84E7738B8FECB
+:10E44000AB7242F197A5845079A1E324211F707F1C
+:10E450005CB691BE1FE29779605CEC67083E0F598D
+:10E46000379670BB7048630FC8E69498FCE84AC5BD
+:10E47000FFF413A0BFEF199D3E07E8AF5202F3FF70
+:10E4800064E78177E65039FFA449D55BD1AE6AF5E0
+:10E49000B6FCF9312492DE7E62A1FBAE487A4B9F36
+:10E4A00047D45B4B1BCAF3FF2DBBAAD2AF5D433FE2
+:10E4B000B08F2F3BA2D3516B1F37181C11ED23FDDA
+:10E4C000798BE484CBA12A7FAADC55FCB6AA3FD87D
+:10E4D000A16EF954E5AF5B3E55F9D3CE57A49FB674
+:10E4E000FD0FA0DF14AFDB4D9BA681FF6CEA241863
+:10E4F00087CF9DA9C77B9AA6CF09BBA771473CD6FA
+:10E5000067E9DB7E0F3EE10755B386C13A7F3BF1F9
+:10E5100029ECDCBE5E413FF6EB4B9726D0F9CCE10F
+:10E52000F4BD9D927B2AE547A92C05E2289EB365A0
+:10E53000E24B488278B2444E84E0717BB958879FA1
+:10E5400089A941383DF5FFB67EF7772D8F52BE9EE3
+:10E55000C826E46F50E2FE833AD621F234BD859D91
+:10E560006378464BFE01A8876D7249C83EC263645A
+:10E57000F6E768FE2D63807EB9B3862530391F8C9F
+:10E58000FB450FB7635D3E4702D8F7AE9681B82FC3
+:10E59000EC3ABCD0EA8E60CF0E70397B859FC37495
+:10E5A00058A47A3D95FB0ED2897E8DCF628E189746
+:10E5B0009B6354ED34E71BFDD1D3F14BB91CCEA6C0
+:10E5C000AF268C0CE1DBCCA91FCBB6703EC0CF8947
+:10E5D000907DC5F7A52FC835D0F780B9ADB02442DE
+:10E5E000FCA692D36FE2FE2F0DB0EEE5B7E4CA4071
+:10E5F000C77C8B5E88872C32727D1D4A86025E1333
+:10E60000F72F7D600C9563CF61BDD34CE7E769F9C7
+:10E61000D4E08EB0BFD3D213E0837FB9D5C8FCE578
+:10E62000B79592C540D7B76F65E7BD7F3338AB224A
+:10E63000E1996E66FEE66C527261B4F4D3A36FEE9C
+:10E640002C6B208FD2A3CBC2EE6B87CB1FD3FB2EBC
+:10E65000BBE45F2D811CEA593D99DD6F2E24EE0746
+:10E660002648A8EF3784DAAFDCE6E9CFC27D9AEA24
+:10E6700016C9AEA3EDD5729B01E4D8D3BC4B06BF3F
+:10E68000FD260771E1FE5AAE19363324FE45973D4B
+:10E69000A4D781AFE6CC05FA7E36D348002FD7D079
+:10E6A0004F6DB0FE7FD6320AF520DABC5EF7926974
+:10E6B000F90AC061F64C2B0F85C9F142FDD649A479
+:10E6C0002F9C034F34B6AD7046E05FBE89C959CC6C
+:10E6D000F6CDF4FF997D9B40ED1B936B25D4BE597D
+:10E6E0004C61F62D2D927D5BBEDA910672B17CCF26
+:10E6F00040FC7E6BF96B8B5322D9B757F9BEF735C7
+:10E700007E0FBCA32FB56F2342EC5B5F6ADF22C490
+:10E71000C9BF88D5BE99FE67F4EF55B06F11E66B9F
+:10E720003689F6ADA86535DAB7A2BE7AE1BE1231F8
+:10E7300051FB167F39FB36FFD15BB1AE38E323C8FE
+:10E740000FD015ECDB6BDCCEC13860E76E30B1F872
+:10E7500066AC76AE5FAC76EE7F88CEAA9D5BDE4F70
+:10E7600042FF255C0E999D5B9EC5ECDCF23DCCCE54
+:10E770002DCF66764E6BDFF2C2EC1B7BBF7A087D35
+:10E780001FF78F598FDF01F7094B15A789F62F76F1
+:10E79000A8DF4FD48C09B577379864A47398BD73FC
+:10E7A0007E8ADFC1F464EFFE0AF62E1BEDD820D07E
+:10E7B00023AD7C4C19142FDC677BFBCB53BFFD1DB5
+:10E7C000E8CBEB7ABC2FF4AE8EED8FF67E796A142F
+:10E7D000E8DD4326667F9798183FDBBD3EB4A793DC
+:10E7E00086327DAFBA87D1AF7AB7C4E6BB52EF7736
+:10E7F000C03AF0D545DC3FCFDDC3F6CFB38CAD29B1
+:10E80000F1702FE95F14C2BEFB20C5F343E4A1F40D
+:10E810006205C6019F8FB36D85FD65A94C4CE0C7AD
+:10E82000CE3B3CE563F05FE75DAC43BF771E3C87C2
+:10E8300073127E4F42BD4731A779D72B7D48F8FD33
+:10E84000888946C687892B24FF962CB88F20B6CF9F
+:10E85000D3F8F5EBF83CA93F8B74217FD5478CDFCB
+:10E86000ADD3D2C3C9E65FB5522FD2A3468A480FB3
+:10E87000CAD1E2F9A9C1F9CF7DA16D5D1F685F2AF8
+:10E88000E17E4AA587769E2A7DD4FDCA3CAE239EB2
+:10E89000965D0AF04B3B7F957E61F356E9A9997F1F
+:10E8A0009D6A3FAE26C340DFDED5B91F1803F2F1E3
+:10E8B000674A078AD76DB3B3D342EDF183DC2E4D9F
+:10E8C000751FCF4F7500DDD8778973CA77BD924A1F
+:10E8D000E773B32B6B247C3F7CEB570637C4170ED2
+:10E8E000983BD1BEA9F2F50997F70087F3766F7BC5
+:10E8F0003EAE23CD921DF526A0B15FFCFE98E71E2B
+:10E90000A65707A47FACEB331AE90ACB002954D7EA
+:10E9100021E003FDEFD416C6070FF081FE771AE958
+:10E920003C0474AE4E969C01E8DFBCEB5E909B57B6
+:10E93000CDF439E86FB9E464DF97114B46EA65E539
+:10E94000538E249F189CC809AE8BF3A05F52B8DF8A
+:10E9500031D1D8FA36E03191EAC31612EE87A87C9D
+:10E960001F42FF5C8A74EFA70739FE98CBE7AB40E4
+:10E970006F0BD0B5D300FE8C27C0D60FB5DD233B7F
+:10E98000F2913E2ABD9BE9FA309AD15B17819E37FE
+:10E99000AB754E4F4F8BA4C0FB93E9FEB59704A710
+:10E9A0005B5F1E52E518BE87D3D203E20119217ABC
+:10E9B0000FF629F47CB2BAF928D265CA4AEA5E8514
+:10E9C000D01DECD6E5E8134D2FAA9B7F18BDF84467
+:10E9D000A3177BCD9D7F1901F1AF3D12DA07D292CB
+:10E9E00028ECF7E3CDCCCF386076A3FC76BEA6E06A
+:10E9F000FD73AD1DF99ACB3DEC2F42BFFB9B041379
+:10EA0000013B6737938F543C0630390AB5DFAF9A24
+:10EA1000DDC8AF68F0E3F83A1CCD7F52EB37C2781F
+:10EA2000701FD1218E17E65FF0F84F4FF34AE3E3F2
+:10EA30007ED779759F6792560361F1FF15C6907373
+:10EA4000A9DBF8B940779C2CD8CF6EBA4C3F88BF71
+:10EA500004E8BC5FDDF914C67FCF3F737C1AC8EFB2
+:10EA6000B23FEA8989F2B97DA79504D8BD0B03AC02
+:10EA7000B315BBF511CF5108A965DF39FECE8AF673
+:10EA8000A5E279A3BF98BE5FF1E247C3216ED5BE70
+:10EA900086D919DF335C3E7C6DC3E17CBD4266E7FD
+:10EAA000C25A78D7717939F7527C29D849A9917D12
+:10EAB000BF5AD1344B3186ECD3479A151C97F6C315
+:10EAC0007BCBBE1D12C6CBC3F15BCDE0ED60F6AFD4
+:10EAD000A259F1C377B0158D5B707FEB69FCD40050
+:10EAE0007EDDA4DF3DCBBEAF6DD68BF1C3467DC0CE
+:10EAF00088714EFD71E370A6B792108FAA42BDAC2B
+:10EB00006EE271324DFC68D9EFF6BCE8A3A459F669
+:10EB1000FBDFD8C0DE9C6DDD6EC3F85C238BBFC904
+:10EB20001639727CAEA7B85CD37D3C2E37F534190C
+:10EB30001E1E973B0BFFA17A38DFCCF5558D6B3647
+:10EB4000F68AE9FC7CD9B3179E84F3A473CF7FF2D5
+:10EB500024E05FF9CD674FDE0DE7127BCD7658FFDD
+:10EB60003CCFBC8DF177F5BDBBB99CB7EFF8CDD3E9
+:10EB70004F503D6C7FCF88F7B6DAF79CCE84EF1903
+:10EB8000DB777D990AF1CD957B0A703FB3F2854919
+:10EB90006997BB7F02F2E98FE1FC44CB8F03BBF5A1
+:10EBA00004BEE73C7FCC88FE47779CB5A98AC5AFF9
+:10EBB0001D3CBEBA33F279951A0FACDE7DCBCDD7B2
+:10EBC000C33AB85B713AF0398F0FF614577D8BF268
+:10EBD00075440CFCDBC9E3E74D5323C655CFC37F17
+:10EBE000289F3699C5B8EA85DD8BFFED0968DBDD26
+:10EBF0002B6A5C351003DDD4F3B032B36B9B19F490
+:10EC0000E3F9DF621C1BF8467D72D2FEEC854C886E
+:10EC1000479C513AEFC47BCA7B8C78CFA862CFBBAC
+:10EC2000A82FED2F1CC57326C2CFA3DA49F70F3BDF
+:10EC300037E07B1DCF362B8BC772FA43BCD661C33E
+:10EC4000E73C2ECBE4588DD7468BD3BE6F66F7A139
+:10EC5000D4F3B9AA6D1F188826FE2D8D057E1D17C9
+:10EC6000CE15D5796BE1D9810ED7869E3F448B872F
+:10EC700073BB1AC62F76EED0BE859F47749F3310A4
+:10EC8000D277249C8FB373738F5F7A37127FD5F35B
+:10EC900087B7B5FAE98FEDDCA167BCBF1B5D5E35B8
+:10ECA000B3FDAD4A9F735F47B6D39D5CDFE93AD3AE
+:10ECB00061C67363B6CECCE3EB4C35A51BFBEE8D82
+:10ECC000E17B8EEF03CF3DA3F7C37E795DD301B423
+:10ECD000B75A3DAF262CFEA51D4F8A63FE4175F342
+:10ECE000BEE1608FCEED7F09E5AF7AE771838FC219
+:10ECF00039D4F87B43DBD0A0BC831DF787D8F173F0
+:10ED0000CFED1BCECE4522E769B171F89E1611BE3C
+:10ED100067E7A702FC65BE2683DDD2F3386765D7B7
+:10ED20002C98EFD95685C07DF6B34DFA227F8471B9
+:10ED30003F83756C4C904EEBACEC3B3E7D9201FDFD
+:10ED4000CC95D6B1C7E0FBF195568303F6DBB5ABA6
+:10ED5000D9BDCADAFFE54C07BED426DE86E746F504
+:10ED60001A3ADA93EDB9B00FB7E7978C06B1D2DA59
+:10ED70008344974EC07BA5B528CD6181BC5ECC4F46
+:10ED800021B213BF33D4DB0A8B601E7ABBCE6E8EEA
+:10ED9000B8BE32788A85E5CD50ECE2777FDF210F6F
+:10EDA00006817C1CDF3A0F46A7260F46F98DFFAF80
+:10EDB000E5C1F0C1383F813C18018CEFA879309251
+:10EDC0007FE43C18105F1A1D9207A353930783F347
+:10EDD000F19F7930FE9907034A350FC63B1BCA0ADB
+:10EDE000204F859A07E3CC064F01E4A550F3607CE1
+:10EDF000B56115ABF33C1896FB571784E6C1C8BC48
+:10EE00007F03B6AB79309CF73F52109A0723EFFE91
+:10EE1000CD05A1793066DEBFBD20340F46D9FDCFC8
+:10EE200015087930D6FEA100F260BC1EEF6E8D4B46
+:10EE3000899E07A339CE11531E0C0AE73D84132582
+:10EE40000F86164EB43C1814CE89B831D1F36084C5
+:10EE5000E113250F0685F309C2899207230C9F2829
+:10EE60007930289CCF715E51F26068E144CB8341D8
+:10EE7000E1FC17C2899207430B275A1E0C0AC710E0
+:10EE80009F123D0F46183E51F26050380908274A3C
+:10EE90001E8C307CA2E4C1A070D2114E943C185A52
+:10EEA00038D1F26050385908274A1E0C2D9C6879D9
+:10EEB00030289CABE2C744CF8311864F943C181492
+:10EEC000CE28C4274A1E8C307CA2E4C1A070262024
+:10EED0009C287930B470A2E5C1A0700A705E51F22E
+:10EEE0006068E144CB8341E14C437CA2E4C108C3A8
+:10EEF000274A1E0C0A6716E213250F46183E51F2E8
+:10EF00006050386EC4274A1E0C2D9C687930289CAE
+:10EF1000A508274A1E0C2D9C687930289CE50827F7
+:10EF20004A1E8C307CA2E4C1A070EE463851F260DB
+:10EF300084E1F35DF360980383A481980703F37180
+:10EF400076E7C148FED679307E05F8FE330FC63F1E
+:10EF5000F360FC1879306EB5BAFF1E8FFBC6EF96D2
+:10EF600007E34CBC266F440F79306EB5969C05794B
+:10EF7000FEB679302EC47FBB3C18749C7F5C6E9CBF
+:10EF800068793074966F9707838E235BC65C663E04
+:10EF900051F2602458C4FC213F561E8C63F149385D
+:10EFA0009F6879307E72F926E8360BF669D35114E2
+:10EFB000C94F26FFC4680B8F1BFE50F92760D2395A
+:10EFC0003FA5FC136A1E832605D6C3F739DFDFE1B0
+:10EFD00072F101CF43712C6A1E0AFF548CEF2E157B
+:10EFE000F3504CE17C9CED16E5610A61E72853F291
+:10EFF000B3FCB5B05F2FD7E4A118229ED317BB8F07
+:10F00000E6537064AA539CC7512E0FD34A3F3D0864
+:10F01000ECB9796CE43C1433383FA66BE83285F3E5
+:10F020006D3A2F6F874F73A83C17971F9581AED30A
+:10F030001C6D32C6E96F52F9E710F83793C3D5E279
+:10F040003B83F36FC664C63F2DDE6F01FF28DE6F82
+:10F05000958F42FE69F1D6E2A9E53F09E57748FEC2
+:10F06000905C22E69F986412F34F14D8C5FC1337C6
+:10F07000A68BF927263BC4FC13370D11F34F4C75B3
+:10F080008AF9276E1E2BE69F98EE5AADC97F719FB5
+:10F0900026FFC5439AFC179B34F92FB668F25FEC44
+:10F0A000D0E4BFD8A5C97FF19226FFC53EA1BEB06E
+:10F0B000EE35A1FFE2FAA3427D49C37B42FFA5FEE4
+:10F0C000E342FBB2C68F85F6AAA64F85BAA7F94BD5
+:10F0D000A17F4FF907DEE2DF43BFC3BF873EC6BF54
+:10F0E000877EBF87FC17EF5896AE0BCD7FF1BEC56C
+:10F0F000B30EF2121CB738785E81C8F92DBADBA3C3
+:10F10000E4BF08BEFFEDF35FA424FFF0F9087456D6
+:10F11000F63D606F4B9ECE9AF2DDF311DC5A227EF3
+:10F12000D73DAB54FCAE5B6765DF6BCF768BDF778B
+:10F13000DF5E2E7EDF3D22CE2D011EDAFC17BD2DB7
+:10F140002E9D15EC25CF531080EF74B321DE56842D
+:10F15000E541C87F910DF1B6522C0F43FE0B5AFECC
+:10F1600019F25FD0F208E4BFA0E51B90FF221BF26A
+:10F1700067F878FE8C3A9E3FA39EE7CF68E0F933AC
+:10F18000FC3C7F4623CF9FD1C4F36734F3FC1901C5
+:10F190008473C27B18CB93DE562C4F798F6179C66E
+:10F1A000DB86E559EF192CCF793BB16CF75EC432A1
+:10F1B000D6FC19AA5C7E087EC315303E9367554E77
+:10F1C000AF7EE09175A1F933463CB009E5345ADED3
+:10F1D0008C1CF8A62F257ADE8CEEF628793382EF88
+:10F1E00047CF9B9136FAC7CB9B31D7F2C3E4CD987A
+:10F1F0005B23E67598B7EAF2793346C495DC82F270
+:10F20000C7E571AE25B6BC193EABC4BFCBA7740130
+:10F21000BF8BD205D7EB1EF20E1CB43E3D04F61395
+:10F220005D43AEBA6CBE07AD5C44A737CBEF30E7A9
+:10F2300047CE97D1135DD5FEEF57B03C0E732DDF4F
+:10F24000325F460FF9160E667F817632D67C193D05
+:10F25000AD0F3DD173C68F9C2FA327BBDA933D7DA5
+:10F26000730AA373EF1EE8AC7E2F5D696A3D842F9D
+:10F27000DB5DA8DA32FF1E3E77A61DE3331D3BF9A6
+:10F28000BD381771D853D9F7FAE06F763C9F309CA0
+:10F29000E077FC76E2A2FC89E7CFA59DFBF6C1BD35
+:10F2A00080B536E24A4C02678F38F403611F768DD1
+:10F2B00009E23555BB3F7DE38F14AEB9458FF7E5C5
+:10F2C0003A280EADE8F7B912816FF1E497B84F878D
+:10F2D00033BA4BBD42BFEBD6FC1E0EE8921A3C7F00
+:10F2E0002AD05B70DFD4B599DD67D593AB1E9F90B4
+:10F2F0008CF7C689DF81FC433F7519C7B38B106754
+:10F3000000FAEFB4E2FDD525AF2D34C0A070DE1AAF
+:10F310001A37E85524C6811ACCB6E1706F2F5DBD4F
+:10F32000BFE773B5821FBE88C34D2911E3449F2CEC
+:10F33000283A0CFEF3227719DEAB482B15E34684FE
+:10F340007F470FDB32F03365C2EF75FAD97DCFB05E
+:10F35000EFEA9BB7209E4BFD9AFB4B8D625DA5DBD0
+:10F36000392BBF9762219698E8D636F8F109A3BFEA
+:10F370003DDD8CE922DDCC0E916EF14344BA68E9A3
+:10F3800066758A74D1D22D61AC185F53E9A6DEA7E9
+:10F39000FCA1E89664E3F73C82F42A31A5A2C947B0
+:10F3A0003C33E400CAB7561FFA5802F01B7E48BF30
+:10F3B00064FF6A7CCB6995C16EA533D0445AC4DE24
+:10F3C0008B077D80FCBDC489FAA0FE3E8A78F221BD
+:10F3D00097FB8FC8255AAE987EF0F802DABA19E486
+:10F3E0006D04FB3D1A18AF4A22B89F5388D30EFB19
+:10F3F000A826AFC9B94881734DE25C940DE79976B0
+:10F400002C1FE4DF3B770C25B8EF6F0A7C9E0AF7D0
+:10F41000061E1CD9390DE20F9EC5A404D6AF5909AA
+:10F420006C7D5DC64B5B028BCF6C28D111D768F821
+:10F430007D4A7ABF44C76BB7BB5EBB01FCD1167671
+:10F440003F80D83BDFB81DDB47E1F7E119BAFA6B23
+:10F45000001FDA1FBF2BEE68F9C8B630C40EB737ED
+:10F460003F7225DC6BDDA48BFC3D73818DFFFE1D9F
+:10F470007E3F654430DF42816D0CE6657870001D8B
+:10F48000A77A7A17F25195CBEB38FD0F964D41FCD8
+:10F490005E68911C10AF2BD4DF71D3308ADFB8B710
+:10F4A000657EAF97DD5F1FCDFBD79AA9FEA2FDAAAF
+:10F4B000FF1BFC9E95974ECA980F71744D19DE1371
+:10F4C000FCA3ADF030F02BC7D5340AE429BF2511D9
+:10F4D000CF713D1F12277E9AD52ADE07CCE1F7B601
+:10F4E00073DA881F84E2DA6362FBB836B17E9D6608
+:10F4F000FF39DFC6F5D4465241EE367EAD9760FD4A
+:10F50000E8E824CE3514DF8E45BD71FC8ECF09FAB4
+:10F51000891D5FEB8B22DD8F596E63FCDB642068F5
+:10F52000BF379559F0DEF9FEB28AFEE05F7C719735
+:10F53000BB7FA43865889F96C0BEBB772590B1205D
+:10F54000876B2546EFFA8C9208EB962A77AA1CAABD
+:10F55000F2975116E78E740FF5339B8472965736E7
+:10F56000443280FCEC9530FCD5BE86E2759975DBA3
+:10F5700047D6F4017C3CCD9FE17D32538BE48A7405
+:10F580004FE7619B8DDD6F5CE35B0DF7467E419538
+:10F5900008EC5486A13E2B127C1FD9887EE95D368B
+:10F5A000077BCFC4F320C9F519709FA2BD79D2E4BF
+:10F5B0007514CF27A83EC07AB5497122DEBE2A4213
+:10F5C000F09E2C8FD7F59D46B66C08F17F37DB7225
+:10F5D0001B6D145EA38D7D6FD9CBED94006FE77F1B
+:10F5E000FDC306F03B2E1A917FBDB9BFA9BE77803F
+:10F5F000D3675C826B2BBC4FE0979F51E3E374DBD6
+:10F600009C8B46415C9ED23BC40E06F9E663F951E1
+:10F61000DC04CF3F922C3A9443E27239ECC27D76FF
+:10F620001FEA8DAA07242011C853A0DA37A9450A7A
+:10F6300058A9DC8F365902708F2EA99CCE3B19F247
+:10F640009A9818BC56F99C18D7A2F29803CE3DC1DF
+:10F65000ABF3104805F8AADD53EDE5DA44668FD622
+:10F660003E24635ED4CD729B19E2A9592E471EA495
+:10F67000884C921D78AFA65F3971520C49FCC05F6F
+:10F680002776FB0154C9AFF9463F2FD2775B176D40
+:10F69000CCDF1E97E0FE33D06BF8E1CEFDE02E38D4
+:10F6A000CDA417BBFFC5ED04F76B0AF97A37EE3F1F
+:10F6B00074EC7BD1C00D24F43B2AAD9DD86466EB7D
+:10F6C000FCB8EBD9BA37EEBC05D7BD6E3B515688B6
+:10F6D000EBD4C8965107E09EC5C80F997E126E1FE5
+:10F6E000ECF40FD029E7B04F0FF4F9B67641CB6FA9
+:10F6F000123075D787EAE01C86EA5BC8FB6735766F
+:10F7000064C5F441B5185EE672D4FF1EA7DE1D4243
+:10F7100047EDFBDD714AC9D4FDDC3110ECC8113D69
+:10F72000DC0BE9C8A5F3A3F3DFC8F525F173FF648B
+:10F7300098D7C6961BCD20DF6B0379F662FA4EA2EE
+:10F74000A9049997485C18CF19493D32C88F518B4D
+:10F750004241FD41A58424A4C03DB42221DE432CB6
+:10F76000493CFF4B00F9D22DA7548E43EFE5AAF296
+:10F77000A99547557E6BE1A005CE0721624E4BBD92
+:10F78000D484878146B2D90EEBBBEA5FD6727FAED6
+:10F79000D69CE9C7EF977C19E81FADE4FE51ADA5F3
+:10F7A000D084E6605F32AEEB2B217E42E9B0328539
+:10F7B000D979753E5AB9F45CD4137FC83EC123771A
+:10F7C000E27D44CF45033E5FA7B807C0FC55FA5C15
+:10F7D000C3E9A3A58794C0F79D9C2E3DE39B638757
+:10F7E0007BC1892617598FF8E6E13DEEA6C0481384
+:10F7F000ACBFF76AF08D01CF6B13C684E3295BA21F
+:10F80000E099CCF0BC8EB8FFD846E53767455D6D12
+:10F810003CEA15792B3D275CAFB47AA4EA8D1AE750
+:10F82000BDB6B2FE005EBBED416F3CF18C2E4EA525
+:10F8300004EF5739F7C4A31DD1EAD3E77CFE9E78C5
+:10F8400046BF058A7B06CCCFA3EBCC043919EE204A
+:10F85000BD8A2992C39BF5A8E7A435B67BF8AA7F99
+:10F86000A5FA55DA7EAA5FA5DA63F51EFCDA04F77D
+:10F870007C9003A999CA2DC5A7D6CEF64B9B6DEEF9
+:10F880004580573CC53D0EF68D430259ECFB5F5158
+:10F890002FA2E941BC46CE9B0232AE0B3EBA2E648B
+:10F8A0004BE178A8E30F4A48647CA45A0EEB7DDF55
+:10F8B0001CC206AB269837A7EF70E28675ABEF48FF
+:10F8C000769F714D02B3BFB5096CDD52CBCDB692B8
+:10F8D000BB51BF65E2338EFCEE7803AA70DF7C6D0E
+:10F8E00082EB2EA087A9C885F3E863274EF04BFB77
+:10F8F000C84D127C379A54E990D83D7312FC7E8B28
+:10F90000C2EB53ECC8057DED03FB6BE8DF1239CF8A
+:10F91000D8A309EAFD5EE67F3A49771EAF47139800
+:10F92000FF7908529FF42A56F382A9E7394E09E875
+:10F93000D46EBD0D916EBF20313F3D91D14BBB4F79
+:10F9400000C287FEFEBD7B0D44362791E0EF59D5FE
+:10F9500099D0BF8F27CE26B057BB1206F0734C67E5
+:10F960001DD47F25779A128706E55D95E30727CC9E
+:10F9700070422A52DBF55DC3614F45E57A27D0BF5F
+:10F980007D42D760CC41493A3399FCB8F442BE205D
+:10F99000950FCD8AC00733ECC343EDA4D53004FCEA
+:10F9A000D17629CE09F72CDA974A0C5FC9C4F3291E
+:10F9B000C9C23CD3E3997FDDC1EDD53B0959282766
+:10F9C000AA3DA6F3AB83523B0F8F11EF7490CE3D4F
+:10F9D000F1FEAD706EA5C93FA9CD4F3969A105EF04
+:10F9E0007F6CDC63C6FD6B57093BC7EF6A31A27DB4
+:10F9F0008EA6B7696DE688711CB5A4F47B0BE897F9
+:10FA0000A6D424823D4C9B7BD2067CD7D2A543F260
+:10FA10005D7308F645AF2B11BFBB55CBF4F49B12B9
+:10FA200017D1FEE91993B1549F3758E488F7CD4FA9
+:10FA300073BD52E5F14A3A22DF0F9D06793CEF7E15
+:10FA4000F31D1709DEDF6F8863746C886374EC72D2
+:10FA50008F4F781AE4CD9781FAB0583D07E5FB7FC8
+:10FA600035CF943ADE46AF2951A62AD0B0608A1924
+:10FA7000D68914E29A3C1B9475A342E03BA2C7BC12
+:10FA80003B12F3318E6D12EFF9DAD9BDE1CF3716A3
+:10FA9000E077DEA9648D7930A5475989CE09F183D5
+:10FAA000F30BDEB7E9A83C2DE8D39A03F2FBBAE2E8
+:10FAB00026F63118EAC2FDC99252833F40F996DC1E
+:10FAC000400D05A5CB7F03F4A15473008000000016
+:10FAD0001F8B080000000000000BB57D0B7854D58B
+:10FAE000B5F03E73CE3C92992433794E1EC009E1A5
+:10FAF0009D108724BC1F4E9E448830BC0485EA803C
+:10FB000028CF2488D6DFB6DECBC444F4A2B745E9BB
+:10FB1000AFF4D6DB7FB0A2A8200182069AA41340DE
+:10FB2000E4113408A8A8AD5129620BC908EAC5D66A
+:10FB30007BFDD75A7B9FCCCC4922D8DE4E3EBFED11
+:10FB40003E8FBDD75EEFB5F6DA872EC977134B64CB
+:10FB5000CCB7D8C0B64A8C7D87BF1B43ADD96E6089
+:10FB60002C89B196383BB54EE70CC7D284F07E8520
+:10FB700063693E63D5D6D85C16876D7F3F8B85F170
+:10FB80008A58EAD202685BACAE5A95B12546AFDD21
+:10FB90000ECF774EBA3CA48EE12FD8DF3392B12E30
+:10FBA000236B94E2B01F606C0C4350F8CFED56ED20
+:10FBB000D097F0FFE1FD448B2D20C3B8CCA35CECC3
+:10FBC000B0F047BE1B281E4D66CC285E939ADEF827
+:10FBD00046CA652C7672116370DFCA5C8FB22CB88E
+:10FBE000318CA99E18C6A2D833F6F3D98C19F07DB2
+:10FBF000584757F3BBFD7C00C71FFEE54A0C83FB4B
+:10FC00001F29C118570E63171E3C15E3B6C1F5072F
+:10FC1000E5723FF46F4740C687F0926F870BA319D8
+:10FC20007BC4EE1981EBBA63DD7F8FF1DA42F7D93D
+:10FC300003703195B1157E19E7E6F0C27FABB65976
+:10FC400019B384FA95F509117DC018E1B5D2CCD667
+:10FC5000D4DB7AD26305D203E65DB17D8B295DC525
+:10FC6000F9BD93ECD0BFA0C0AB80EF0B0D317E5F30
+:10FC700066089E25DB4799D2E1D6474D661680750A
+:10FC800030A5DDC86C84B50A09F0E61578D3C379D0
+:10FC9000B8C54AE3DDF57F65BF1996BA18E67A2044
+:10FCA0001E9E6F5A51C1727BAEE3AE3FA8652940DC
+:10FCB000BCBBFE4D623E953FFF601E3CFFC0235F14
+:10FCC00020DDF4EB5CEC337ED211B16E376300CFF4
+:10FCD0003241EF3B1F8DBCBFACE9311A6729F39A63
+:10FCE000909E776DD4DFBFE933E4BB654C095D07B7
+:10FCF0003C5C3E9265453CDC618F493C0F20038FA4
+:10FD00008DFD0EDEDF7D64609C37A7277EB5F6E2B1
+:10FD10003AE06F33637F5E67A1F6C23A46ED08BBF7
+:10FD20004AF459DD74F27EE4AFAAC65D261CA7C56D
+:10FD3000FFA78409F04861D3373232572173DF7B44
+:10FD40000EF0F92326B3EF007FBB19E79FF546CFEE
+:10FD50003D48AF1BAF96D37DFDFA1769FC7F249E0B
+:10FD6000F86711AE3B17AF2B5FF6B6AE9FE2BA80D5
+:10FD70009FD95858977CFDEBD2D6A3AD4FBB5F29D6
+:10FD800003DFF5F2BEC6EF23843E58FADCACF5691A
+:10FD9000808ADAE6CFFA77103FB1D328BF1A3F2D19
+:10FDA0001374D2F38D46C76EFE68FA775A9F463FAA
+:10FDB000E07FA7C1896DC06918D7934FF47CA1E794
+:10FDC000834E63477F945F3D1F744A6C416FEBFA2B
+:10FDD00037FB405AD752D55D6687FB7731CF7A3BE8
+:10FDE000AD67235DBFA06C3CFC3394ABE7385F7715
+:10FDF000EB3933973776DCE847BDB936464D71D8D5
+:10FE000004FD80CE9DBBCC3E7C4E9BE7FC3AB77B8D
+:10FE10009011F15E4EED9FD779DC830687EEDFFD12
+:10FE2000AB2BB12ABCDF358C95A3DC77C644C2BBB3
+:10FE3000CF2E133CFB900EC87F4AFBFF7C803AE933
+:10FE4000B9F631A847CF7FFB5FB11E78BEEB5B737D
+:10FE5000796FEB3C2DE807EAE5B413F8EC762167FF
+:10FE6000B73755125D963C33CB84FCCC1EE0F8B41A
+:10FE7000C01FEAD7B6A8D867711D8B1B24D2237A7E
+:10FE80007ADCE59AFA39EADB3BFD85F47E0FFAB0BD
+:10FE9000C789BE77213D8685E831D6A1727854F8AE
+:10FEA00003BEB943F0CD79658DC9007AE4FC338097
+:10FEB0006F007995C2DCBDE9C1FE0ECE877DAD47EE
+:10FEC000BF8EBEE05FF65CCDFA3486EB1F654AEB71
+:10FED00045EF68EBBF8BB96249EF88F5B28E1B49DD
+:10FEE0005EAB2D7C5E6D9D2B9AEE9C817C51B5198D
+:10FEF000E895D973DDA87717F7026F997CD16881EF
+:10FF0000F7BA1E905CA86FFBA283A627EE12F85AE0
+:10FF1000B96DF10C349A8B613E3913F5D1176FC668
+:10FF200024A25C415FFA1E7A35C91F9B711D8CE3C8
+:10FF30007B09E07B8374FDF45BB6B9D03D28ECB956
+:10FF400015FE9BDC83C2F5998EAE6CDBACD0F364FE
+:10FF5000B7DD26B4C7F10EA1BF845EEE5BBE60E1E3
+:10FF600000E7DA1D0EB26F6C8D83F46375D3165300
+:10FF7000B8DDD5E44B93B7B10E3BF15955E313F41B
+:10FF80001CE85FD501FD4A4BC7CF6F55C3F0394E12
+:10FF9000D051AE30A1FEEE4B7F82BEF9B2236C9DF4
+:10FFA000231CC2AE08FD7B2DFDA0C1AD1F57D3079A
+:10FFB0001ADC1ADF6BEBD1F37D5FF0E9E9C2989FA1
+:10FFC000FB0B3AFAAC427A84F5115E05F0DBD66C95
+:10FFD000F53F04F0B6491C7E5F7314C1DFE92C764F
+:10FFE0009F033FAF2A7521B527F0C554F4EB3CD3EE
+:10FFF000109F9A3FC70A1222FC247DABF93779C2C1
+:020000022000DC
+:100000009FDA1BE5CE0713093F4F02F2C3949A8E85
+:10001000391620D9AD8EEDE50A8C3FE5898E395130
+:10002000D05FE8D8C1FB5B3B4E595C8CD5B057CA5A
+:100030004BA07F3BA013C7BB565B60F62C44F95D19
+:100040000D7E9205ECD1EAD3430EA1DCAD6EAF2854
+:1000500097C0EEAC068323813DAA74C706ACB9D421
+:100060006713E0B9E7EDDE65C42F57EBC86EAD3E10
+:10007000AD70B9399248EB5700F62878AF2E1AFCCC
+:1000800055C0575DBCC5559B49D77D51F1D877AB5D
+:100090006AD8758D1EF81EC25167606E07B4AD47F1
+:1000A00087C4757C8FDD6E5DC72A14E08383EB2CDB
+:1000B000D4EAEF179AEC83D0EE151A98B7377DF98A
+:1000C000A483FB8DC0E4E948E7AA23269277FCA12C
+:1000D0001F5829F4511510280EE0A93CCD02D1B1CA
+:1000E000F85CD9E70AB60D12FB24C25F61A1BEDC41
+:1000F00037DCD7DB56E17883C3F984E3A948912A3A
+:1001000094B0794B6C51117D39C5300CD7C3E4687C
+:10011000D756C0AF9C6E58B31BD62F0F8016F0A1D8
+:10012000D85DF2626837164F9197405B6BE476B505
+:10013000D6C09687E3E905811FADFDC0E1D98A7479
+:10014000BFF456FB182BE9AB0C3BC9B9586FADE4B3
+:100150000A50DCD4CA5C5BE15A9DEC619C8FEB19C0
+:10016000F2F11B621C97D9B047057E6D747C40FC90
+:10017000EB8A33DC9B09FDC0131FF17EBAE14A26EE
+:10018000F0F781273ACA15900757B6E1CA40E81F31
+:100190007AE2637E7F220C0906EAF0139F94FB6CDF
+:1001A000382ED7676CBB3B1BE7510C12C9A972C034
+:1001B000E4AF85FFAD8BE5FC54073C82FCF786B0CD
+:1001C000B3EB6B8A5EB602FF2B456E750D8CE3C7F1
+:1001D0008069F4DFDF6A7894AD068A53B0457CBF4E
+:1001E00029D6ADD18135B8B367A15EA87767CF8E28
+:1001F00041BC7A4F225EF3DBDAA7A03E6E78FBFDAE
+:1002000031E8AF22BD709CFC3688DD603D975EEB27
+:10021000B7450E8B473F7014BEE3003996DCDC9F78
+:1002200094543B5B047257EB66AA09D695A28BEBFC
+:100230001A18D72FCFDB3D7FC4F7584680EC4DA16D
+:10024000C3FB31CEAF8F57597B7CAF7A59AFB74CD8
+:10025000B90FC8E8E7C4A737BEB704F5FBEFCDAECA
+:10026000C12AC2E5660F003C3B0D4C61F1C426C3B8
+:1002700094028C3FA35D1B50EE5DCCE90339C33083
+:100280008D80845FE298B0B855AC07DE2F61D08EC8
+:1002900045F86EA0F5C9C857A3984746FD3586F9BD
+:1002A000ADD87635BFE644BC3D19C5EE40BFCFB2F0
+:1002B0008DB9FD61FA63403CF7F726251809EE6811
+:1002C00063FD6CE4D7E82F981DFDAAAEFF342938F2
+:1002D0003E08C874BCEE3A6C6008E70B46BF3D0EA2
+:1002E000FAC1E18AFA2C0B8DD725E8AD8DFBA44924
+:1002F0001DEE407D93C0FB2F1472FB1CFCDCE47FE1
+:100300003613F16359E30F932F673CF75BBD494503
+:10031000F1F1D0D63747339C7F6C4BB401E9F0F252
+:10032000F6BC28E4879D881B587FBCD97E0F8E17AA
+:100330007F05E0CDA4EB6EC2ABA28E8A03BC4E98C3
+:1003400066533700DE5F88AA9F86FC1FDC6160CFA2
+:10035000C2143B4DAE59D8DF7959B5A3BE7D21B348
+:100360003E9AD6B3C340EBD9191D1CB116E0DE305E
+:100370004C2947F8142B53500F2B8622F51EB83EFC
+:10038000349EDB574D2F2F88E7F2F3A404F3E7E107
+:100390007385243FA5B28DE4AE2BC8FC669827690F
+:1003A0006EBB8CF4889E05AC847CAF046406FD496A
+:1003B0001E46498D4936A35F257DEBB62D06BA4F03
+:1003C00011FA76CA87AB2B78DCE33A3D11C63B685D
+:1003D00033325CD764D621A33F38F92A7305907F66
+:1003E000AEF278C60E7FE83F3DAFF3074BC578EE1F
+:1003F000A0BD042F17B2483FAE7473D9E712CDA346
+:100400002A68A78B2DBAFBE8E7C5621B193795C58B
+:100410000BFFA63FEBFF1DE937E05E98EF3E3B9FE9
+:10042000AF54CEF915AEAFABDCE4423CECB2B9DF71
+:100430009D887AB1DDC8B6B2BEE5E979883FFDE0B6
+:10044000730CBB6A65FE7CE2471BAE67C4E68DBEDB
+:100450002858F788417C7CE43BD42343FF333101A7
+:10046000F5F855A15FB456E333E4277B1CE727FB7F
+:100470000D2139BC333E939ED3E40AF90CC7D96FE2
+:10048000F42FF4F46227813FEF44FEDC65631447E8
+:100490003D966A598072A5CDF3BCE0637DBBBE6614
+:1004A0006DAB11D7FD15D80380BB24EDAA29DC9EC6
+:1004B000EF49E27C552A7F4BFE766793C4D0CF4F3D
+:1004C0006EE2FA3B9C3F527BE78F5F225EAFC51F17
+:1004D0005ABCB0FB87F2C791BF8F3F365C933FBEDB
+:1004E0008D453CDCD75C9CC2BEC7BF6914FCD0D72D
+:1004F000FDF156AEE7F4D75F1178DD67DA383D17C6
+:10050000F5C0CD0617CA39503F7D36AC635F347FE6
+:100510008F296BB2B0BF4BE17A65579399F4CA2E1D
+:100520009BD74B76DC6961E83F30C5DBF133D4877C
+:100530006916754318FF2E8DE7FC566F0C8CFF0C67
+:10054000FDE2A39CCEE36ECE934DF05CEA522EE723
+:1005500005174C5B300E2B4D28DC817C7402751620
+:10056000B4D5E7E029407CD53913E9BBD75A4E967C
+:10057000617E11FC1E37F2D9D8FD27CB8A72F07943
+:10058000AE4FF78A56EB8FC735C5B3EE78D723EC5D
+:10059000C678C6F59207F92437D4676E23C56B1A5F
+:1005A0003FD447033F805CCC67AA3116869C73CE4C
+:1005B000F330984336A73C92CEF303D3283E9C7B7E
+:1005C000BAFD55D0CC6C9E47775FF0C17C1D1F8073
+:1005D0009D3D1E8FFED2F180C980F399D664737F52
+:1005E000684D16F293264FF4033CD5FF61D8B31B38
+:1005F000C2EC7B6C0297A3C75D0ADDF77598FC839C
+:10060000E1D2BF33FE5EBDB03F9FA33C63FC70DF11
+:100610002B0BD18EE62F771F44FC4F4F92E9FA2F18
+:1006200058C09285F47129E497D51BD5E2CFA4D0A8
+:10063000734CF10CB3C1FDFD49D1F9387F6982F7E4
+:1006400022D28929C123F8DED80979F9285FB65169
+:100650007509688F34B801AEF2ADB6101C1A5C672C
+:10066000055F94262CBE88EBC7F750BF347E7CDE36
+:1006700082EF6B74AF6FFE82D33B8CFE48EF10FDB0
+:10068000A53BB0AFE1E12BA157B4FE3F4A7F2D7FE0
+:10069000704DFA637E20F6EFA2BF352129447FF02A
+:1006A000B3E2B1AFF7B3EA4DE077E7F4BC5EE82818
+:1006B000A4E75D265821FA552D1077A23C7A1DB487
+:1006C0002FB0C7CEE7EAFAC3F9FEE022B2C109F1C2
+:1006D00084F76A537008FA21A30212F985A340F047
+:1006E0001791FF95417ACF25F0C4CE4BD2F961DC4A
+:1006F00045FF2E1DFDC34002FA51A3CC1501E4F7BE
+:10070000DDD629E9E8D7E5592765215FBD3AECBE7A
+:10071000E368825E4D5BBEE73935E4FF68FAEDA021
+:1007200018569BBF2081EBA11B41DDA21F882E63C1
+:10073000381C9A3E47F2201C5260BEE13B2BE9E593
+:10074000A60EA0C78D0807E0A155620DA8CF0B0D1E
+:10075000EEC462F4D392020AF7F7BEE98FF9C18AB8
+:10076000A637DE43782B703F04E35097F162773E63
+:1007700062604F3F58F357B4B840F367B4F813FDC5
+:100780001EBC3F405CB79B0140B447018BBF06E6EF
+:100790007FF2B23ADC2DE4568175548875CC64ED55
+:1007A0000417FBF6BBEF26017D66087C541C81B85C
+:1007B0003117EF337633E0E16685C79337BB207E90
+:1007C0000CE3A399E322FBF89B921C1AE75ACFEBA8
+:1007D000EDC044DDFECC3FDA1E017BF409B8CEC784
+:1007E000D6F1B874C240D9A7A0E11C9769407EAC8D
+:1007F00016F60DC2E85EEDD24BC22F9E60E8C875BA
+:10080000017E5BF7FF8DECE081FD7F7B07FDBCF196
+:100810009F2BCC0CEF4FF8BC200EF5041BA7125FEA
+:1008200069E356FFA9C1CAF875E2FF2AB1F6C30011
+:100830008F7B28C267A1F677179FDC84E37D794E12
+:10084000E1BC2DE62F337907611EBBCCC4F30187D1
+:1008500025EEFF68F70F1B016EB8BE2941CB0BB424
+:1008600093DDC79F398CCE37633E202F44D79B2F13
+:10087000947FAEE4F6A40FFEFE37F2015A1E60AB81
+:10088000C01F3B78D6A4025C531BEE51D0BF9EEA3A
+:1008900094993B6CDE9B542B7387E5039E49D0F9FA
+:1008A00023075FDC3403EC49759BEC8A42796DDAEF
+:1008B000753C17FBEDB2CBDA0B1FE9F13BB5E91E36
+:1008C00005F9DF98A8927C5F6BFE0923804F6E408C
+:1008D000BA33F2EB3AC74824477AFA1ED8FFEB84C2
+:1008E0008E9CBEF1DD17FDF574F8DDC522DAEFB997
+:1008F000163DF47CDB02EBF4C1FA02B04E1FF85D4A
+:1009000007D6D9A97F689D93FA1ABF5637FF3601DB
+:10091000FD368D4F4B1338DF8CDFB72981D942F478
+:10092000D2F0F5A1B0577BA3347FC3356F065C3A94
+:1009300005768718D4C7DA9D6342F66BFEE932F27A
+:100940003734FB355F5E544A6A53D82F4C23A35E7D
+:10095000D3DBA9B9EA6223EBCD3E2D88EC97B76DC6
+:100960005462A867203A4992C087F0B33538CE3038
+:100970000FC1A9A7A706971E1E6D7D9A7F3D5FD068
+:100980006FCEA04C23C2DFC3AE8A75E2409887B811
+:100990005EBBFAB58E9FAF5C28792BB717BEED8B87
+:1009A0007FF5F7357D508613E451EB43BFC298982D
+:1009B0004C742BBB6A626EB01B2C238A7D1A66575F
+:1009C00058C550E29F7B851DEE8B7FAAAECACC9B9B
+:1009D0001FE22363E31356E4A37DCA462BE62727D1
+:1009E000DB66D5C6019E4AFE543417FDBCEA0E03F1
+:1009F000C3145669D3170731AEAF7E8FB9502F1687
+:100A000035B51623DF1D52DA658AB3BF64EC893031
+:100A10007FB1B1A9D68AFE5463A24C71FC6107E78D
+:100A20004BEDFE9644AE3F1ACF5D9EE1EEE5FE191A
+:100A300071BFE4E33CE2A3B24741AE310E4D8AA15F
+:100A4000BC4489649F53817EC84D46F2F3218EF9E0
+:100A500023EE035E6A34EFC2D47E69E323F7D881C4
+:100A600010F5FFFD698D19F30BB324D7B3F05C9932
+:100A70001A6CC57ED9DC4CAA7B18FB3F32F9B3C196
+:100A80005B25CA8B9401BB60BF6C51A61FF313FB9F
+:100A900025DEF735F37D0266F725CC8079DEAE489A
+:100AA00018B581784AEB0FCEDBC0042387C557F712
+:100AB000ED9549CFDC572AF971BFA9D49ECE7C6150
+:100AC0007C55F6A889D635BB29A508F9784EB9CC4E
+:100AD000FC61FC1D107EE13C0FC4E161EF1D8EE264
+:100AE00070051703DC52486EA7093E9FC5B89F38B2
+:100AF0007F4142C47BF0C62D688F6E6D8238157AB7
+:100B0000D344FC7AAB373D625E0FE37ECD09162CF1
+:100B10008983F1FB250D24FE9B11B48F0EA8A877C5
+:100B2000CE24A25E63C3B89C6872572AAFAE237E00
+:100B300070F27DB2791248938CFA2F529E668E8B9A
+:100B4000ECCF72F7A83788907FBD5ED7E47E5EB3A6
+:100B50004CFB72F30A2517EB453FE8FDECB1D17D64
+:100B6000E8856FD587E37AD30B1F96FF5D7AE13571
+:100B7000082BC681FCFE3451E8877EAC1FEA875201
+:100B800079FB26E4972EB077E65EF845B3175A3C1A
+:100B90005E06F24AF27E91EF67945E4D65BEFC50B0
+:100BA0003CDEAD2FC09F70F5E2E73C9D984572D4C6
+:100BB000AD5F34FD11E64F18C7FCE3FE4429F89100
+:100BC000A63C842F83E02B633C1F5886854398976F
+:100BD000737E41F9966A88F329DE67BF25B850CF46
+:100BE00049F12139D0FB195A5ED72AF2087ABEE8BA
+:100BF000CEF3CD35521D8CC61765762E1F657365F5
+:100C0000CABBEBF9449B4FCF1F015D5EE69AFC2106
+:100C1000E4EC87F24773A2D8571DC4065D0F5F68E6
+:100C2000FCA0F187DE8E1CD3E567FAB2236FA21D0C
+:100C300019DDB71D797D9891F4B5DE7E68F6E2770F
+:100C4000495C2F6724F27D8E69C3E7D9D0EFB026C7
+:100C5000F13A0DCD0E75E79736737E78BD63892224
+:100C6000A13D41BD9019867F916FD5F8AFEA5189BA
+:100C7000F28D15422F7536F3FC5B7589ECB7C0FF1A
+:100C800016373DB189F78D949F2B545A150B8C3B29
+:100C9000D325B930AFE316F9BA196E89E7EB5C9149
+:100CA000FBF42D3AFACE117C349305EBD01FD7EB31
+:100CB000A53957B95FA0D74F73C4BEFB1CDDBEFB7F
+:100CC000554DDE07B001FF4C7FC09CF4FDFE80F661
+:100CD000BE46478D7E2AEEC5A11C1DFCC6A4C6706B
+:100CE000FF19E937F5AA42E3D893045F0A7FE6CB00
+:100CF0008B79BFA0984F3C5FDDF485C93BB26FF89C
+:100D0000AFE5B7C6A29F3E3AE4B76BF34E53184B1C
+:100D100047C74C674F6689EB3FD47E0CD7AD43A3E2
+:100D200083A6477BE059E8D9BEE8742D3DABE9B313
+:100D30007FB69ED5C6D7EC8036AF5EFFF615B76995
+:100D4000FA74FD1603E54B268BF878B2C8C3CE4F74
+:100D5000E2F1C1AD493CEEECFACA62407BB9B38521
+:100D6000FB272EB3FD38FA05A17C1FA7E7C331CCC2
+:100D700087FBEC4C69B7D0BE67119012F73DD3F8F2
+:100D8000BEE77625E0213DED52580DC8C9397C0FEC
+:100D9000E679F8806F21EAE9873F1962A0FD77259F
+:100DA000D08EFEC9D83C85F68F1C6695F2C19DCDCC
+:100DB000663BBED7B5EFFFB41A719CAF980B43B832
+:100DC00043CDE6EEFD1BD407A5729B8CF9FBAE204C
+:100DD000C8083C3F6941A018E3A0C9ACBD16E57B3B
+:100DE00002D2B117FAFD2A498BB37BCFEF173773C5
+:100DF0003FAE3846263F6E8AAFBD18F7ADA62892A3
+:100E0000AB169FD5E5F75FD1C51FA1FCBEAAF0FACE
+:100E1000435DFEBE91EB99EBCDEB4F40DD067CBC14
+:100E20005EE373A16F581FF9FD9D26BEEF133C6969
+:100E300064E807B30B89BDE663AE95E7DFD712ED33
+:100E40005663719F8EFBEBFB5AD2DC6A6EDFCFE7F5
+:100E500076048BD03CEEDC3E5BA1FA35911FEDB100
+:100E60007FD2C7FE88BBD17E08D5695FFB21C55FF5
+:100E7000AA94F6B95EBC69750B4CD43FDDC8B49F2B
+:100E80009BE474E7F96837F2F9CEF3696E84EB7985
+:100E9000C1A71ADFEF3B77399AF6414D6E15F78FF0
+:100EA000830E8BEB59E25BCEEFF5A943FCB84FFB09
+:100EB0001B21173BA383C7B213C3F73DF83E47CBB3
+:100EC000BA47679F33D27EB984F9486D7FD90772DC
+:100ED00043753DF18CE20F23AB67386FAD9BFD1A74
+:100EE000DB2993D438C4FBE5446D1F538DA33CC468
+:100EF000B757A8CE508FFFDDEB9807EB511AD659A4
+:100F00003C0AC8FFABEBECD46F5CE7A476FF3A95E4
+:100F1000DA878EC73E8076BFDA6DF22861FAE39DEC
+:100F200064EE77E5657F524CC5DF7F6354873EE50D
+:100F3000C10E19F5C58D57611D117527CA65C437D6
+:100F4000E537B342FD4C69710CF66FBC0AFDB0E7A2
+:100F5000AF2439B83DAA53EA462793B4105FFC2D5D
+:100F6000C9DD9104D7EF71783EC176B734FFE02533
+:100F700046FD73BC7FAB7C099ECB0F14525E391FBC
+:100F8000F3CA7934EC42C4DFE85613ED976BF9DD10
+:100F90003C4DFEBE8ECC33E78BBCEEABAC83F2CDCA
+:100FA000051608B40C0817A79F5B9AE794301F98A2
+:100FB000647261BDC3E82C4F3EE6635B9318C5477E
+:100FC000ADADC9196A0E720FCFFBBAB5BC2FFBFECF
+:100FD000BCEF918F627DA4B7AE9A687FFAC8A9581A
+:100FE0005780F60B2DE4FF69F5C82DD1BCCE806586
+:100FF0002CA03CD38DA29ED162F69A93495F050E38
+:101000009E80F77E7F99F17DC7F60F695FBBD83070
+:101010003C05EB7E0F4A43E3B07DEAA3D81C6A4F40
+:10102000C55E44FCB418AC2ACE7B669D5A82756DB1
+:1010300027D6B112AC637B6B9D85DA93EBECD49E23
+:101040005AE7A4F675B88EFC731C9E477E71BF6587
+:10105000A37D92296FD9146CF316C650BBFBB6184A
+:1010600013C2DB12CBB66BF360BD5A203AD080C9F5
+:10107000FED6A7BC8F59FA81DD337B474AA3186B94
+:101080007BCA3B5D990CE34EEDFF93AFE0FE9BC93D
+:10109000CB1EB3005C734FD91ADAA0FF76F2F2C709
+:1010A0006CA86F8F4783D2C3F5AE38EE1E0474432D
+:1010B000A590C605978D837E82D65F31BD6412638D
+:1010C000B71477643360ADECE495D32D80C75BAC87
+:1010D000DE1F63DFE44B9A5ED20FFBCC87F56041E5
+:1010E000C948713FCB9012B1FE65A6C3FB4672584A
+:1010F000FD9E5BFA13ED338D714BCC41871F8CB491
+:10110000EFC5EC1F2784CBDB4C47E91B488F89C90F
+:10111000BC0E78F424C91D5E5FA17F6EF439B5045E
+:10112000E934E642591DB633CB1DD4F72C185B8742
+:10113000F25C62EBEBFD627ABF3C99D78D142952C9
+:10114000445D89FEB97C6026F48F8347A3294F3024
+:10115000FAB4B716EB4F4B9D9979B2A6FAA8EFD81F
+:1011600082FB6DA32BCE9424A0FCD824179A89313E
+:10117000ACA32E01EE17DAB1A00AD7F54431D6FFA1
+:101180008C562517A2ADD0DDDA80EF17BA625C85E8
+:10119000E88F9F564BD0F49C52469D2880E7A60EC0
+:1011A000925D1618E854E0A68997A05F382C8EF25D
+:1011B000BC85CA9A2B27A81FE3AA51711D5B7E5DCF
+:1011C00045E398C9AEEF9E51FC2FC83F459E38CAF3
+:1011D00009023E4AC2EBCA60DD0477A15DF64749C9
+:1011E000C8DFFF5A6287FEEEFE1296CBC37CC3FFB8
+:1011F00042F78F44AB5100E86E93BD04C7DB6D929C
+:10120000EC0F51DF538CCFFB861855CC1F9525462C
+:10121000458C3FB5441A7F0EE1CF891B85D7CA3371
+:101220001C11F7DB6EB3929DA8782B87FCA2B6DB6E
+:10123000D2C95E54BC35A908DB3603F7D32BDEAA2E
+:1012400028A7FB061E07572CFC915BF429EEAD582E
+:101250005849FD5629E52738DF959CB83CCCAF4D61
+:101260001B945AA244F8810349FEF3447EAFD03068
+:101270007CD32480FFDEA37C9FA2222733E2F919CE
+:1012800005524978FDA8675254447F7689A324BC4F
+:101290000E756E456A44FF96B99911FD92A30564D7
+:1012A000BF410F5494801E380AED5260C1025107AD
+:1012B000A5E59F0A054B15B68BBCACC2E3EB61F00C
+:1012C000877AB0C41669A77747733B5FCED6D0063E
+:1012D00049F911BEBF5D9668FC24DC4E94CB1536EF
+:1012E0005E97158987BCA346B2977931921FE3FABE
+:1012F00092A34BEBD0F4966744BEAFF961E5023E92
+:101300006D5EE673B7A33FA2C1ADCDAFC15F2E2F17
+:101310002AA17CF735D6A18797C17A503FE8E168CA
+:101320004A16FE1AF81FE4AF897324F04BECCD7E09
+:101330006BFE7A05E82B47B8BEB2498958B7D797F4
+:10134000BED2C6EDCB2FD3C69DE9F0D0FBEE1D9FDC
+:101350009E9A2087F5333F4E880FEFBFF8E9A688A5
+:10136000FB491FCF7184F7B77E3A07EF4F51D45A2C
+:101370001BF0E53126B97CC8076DAA1203F4283E9C
+:10138000EDAEC3B6F4432F96ABB2A9E77C75D84E49
+:10139000BCE86F33C3BA6E1A26AB18BF6B7E881ECB
+:1013A000DEBF26F3BCC3B1ABAA15F75977FB542BAC
+:1013B000FAF3BB1F54ADE887EC76F37319EE2C03F8
+:1013C0009D8F7167F37AC5BF24F3BA834EF1BED601
+:1013D000FA8DDE4E841BEBCCD137A8FA264875E592
+:1013E000C7D0BFCAE9E95F1D53FC369CEFD8837EA6
+:1013F0005BF87EE2F5FA577F041E43380A99E40948
+:10140000D723C596284FB8DC96DA1D11FD93C20F7D
+:1014100099EA4C8D78EF263533E239F01B87A15FCE
+:10142000526B62546FEB33F07A5B3D1E57A4F0F8B9
+:10143000CE65B3A33B83FB66726FE7915CC5865EA6
+:10144000CFB7A5A4707FF03F5218C1352B85C3A735
+:10145000AFAFD5F76BF17C0FE293B99CC8E72EAB29
+:10146000E10AB8BCACE0E927A6535D6DBEE1DE2C15
+:10147000E8573CBD753AAFAB35ECC13ADB194F3F8D
+:10148000CFEFDF60C837823FB0CDF7C274AC2BAF6F
+:101490008AE2F5095551A23EB46E7444DCA3183EAD
+:1014A0007E6A21C69FFB8D0CF3FC8F99C00EE685EA
+:1014B000F6D9AD661EAF5A4DBC0E7C7DE6A9F5A8E7
+:1014C0003F3E8BF2E6A5509EB148453C5EB45BA81A
+:1014D0003EF4BE7DA529C807B35278DE2B7BCF44EE
+:1014E000279D2FFBE7C151FC7D7060FD308E73712D
+:1014F0007736F9E5D903189D27D1E801E1335D8FEF
+:1015000082F081CE6330B713F36FB50E138D332B9A
+:1015100085F3E3F5B63DEA89E30C6B7641BB2085A4
+:10152000C7CDB7E2BC046FB0FF2CDCD0B307FBCF54
+:101530001EC9FB486F59CE0BA27F1BFC510CEDC39B
+:10154000BC1FCDF1C63282B46FF3EEA26CD706BADF
+:10155000CEF1B8C03FB0B643C5FA0F7F3FACB71865
+:10156000E8F42E457CDC66F60F26BEB2AD89C17963
+:10157000AEB7DEB8EFF921E0047B327F3CA79736A7
+:101580003FE0D882747C579C3BD1E001387E8C7060
+:10159000687075C3A3AB3FEF147E7B278E971BCA81
+:1015A0005357FFC940798A6A09F424F4F77CC85C70
+:1015B0003E95E8437950DCD2C2F9C69F58526C83FD
+:1015C000B6A071158F8FDB9588BC9866CF268AE709
+:1015D000C7BEA744D8A38922FE1DAFCB4F4E6C9C3B
+:1015E0004EE7F826EAE2E25FA488BC651A4B0BCF0F
+:1015F00023AC15F1C6E5B68171E89F2A10E7CA80D1
+:101600006F932AB371F121BDD0B08E459C53D4F8AD
+:1016100070E469FB9D38DFC8D3EC0EF207B471BBF0
+:10162000F3131C2F97DFE37819D531ECE949D03754
+:101630001E3132BF1A5AE7040E2A833087E2A4CB48
+:10164000176C645FC61C9D43F5DE66A781A961EB3C
+:101650008F52A3991AA62FADC3E223FAB2A04F5D11
+:1016600054A41F902FE68971A5458CB73FBEEC08A6
+:10167000FA05F9B6E5E417C48D1B18311E6B532229
+:10168000FC833CE67163DCE802FAE27ED998D34A37
+:10169000841F302EB091CEA18EFB30F2FA8473916C
+:1016A000FD037DD1A52FFCB1DCA7D12FFCA1F873E0
+:1016B000B823F197501E89BF244F24FE521644E2EE
+:1016C00027D51B898FF4E52322EEF75B9317D11FF3
+:1016D000F0C08488E733C18085F7B31E9D16F1FC06
+:1016E000E08DB323FA4337DF16F1FC70FF9288FBDD
+:1016F000D9DB56FE207A8FAC5F1BF1BC9EDE3734FF
+:10170000FE34627C8DDE3EF8FBDFA437730AFF50A7
+:10171000D03B51D859879BD7AD75196D8FE2797C35
+:101720003C3682FACE81E7E963D1FEAB5497E79B62
+:10173000C6685FFB97B24742BD940EA8356451BDA1
+:101740003CD5F5FDDC6088D867B73BB93F6477725C
+:101750003DFE6B133F2F950EFE26D929030BC5D9ED
+:1017600016AC77648299AC8F639C5DE7E818A63A63
+:10177000306F07FDC921BDAAE9D1DBCC6A6D07E84E
+:10178000975132D793A03FFB39619EF7A5078DDCB7
+:10179000FFF019D1FF48B7305F6C1ED919CA433B1F
+:1017A00058A284E700E2427A5CFD0E8875706536C7
+:1017B0009DC37A134140BF5975D17ED3AD9A9E5ACD
+:1017C0003E9CF4D4655BA4FF767969165D3F7BBBD4
+:1017D00099EA07CE8A3A470D0FFAF3D6DA396CED5B
+:1017E000FEF22D9B62D0EF3C2BCEFF6AD7270BFC7D
+:1017F0004D76CAC2FE59D6603E6C1118F138C07BD6
+:10180000E5918ED8DB18F99B9370DD555BAEDCFE5D
+:101810002AF4AB0DC1646E377CF4DEFC77F9B9EEC7
+:10182000F97F8BFCAE408593C7F91562FC5BA0B1D4
+:10183000039E6E013A38B07D635219F2275CA7F31C
+:1018400071338F3023CAF32C6F26D54D9C62AE3393
+:101850007B01C4F94E95E09CCB3C46CC5BBD737BD1
+:10186000650C3ED73D9E360E300CFA25EF3A7CC60D
+:1018700064CC1B4CE67513309F05AF7B16A53F8CDF
+:1018800076499BEF1DE6BD7406E83B9BB9685C6D2D
+:101890007C86E9F9303DB57BF9AA8F1260BEB54769
+:1018A0000D948F58DB6CA678AD6BE57FED780AEE72
+:1018B000DF91DED10FEDF6FB2BFF3604F9E1D6CD3B
+:1018C000325381DEAADD7BA7336C5FE5ECD22B318E
+:1018D000781FECEED6A7D058BE6CA63AE2F757BEFA
+:1018E0003C24DC8FAD74162EC7F7D8B8EB3BEF580D
+:1018F000FCD2F014AAF712FCB442F0D3DA178792A4
+:10190000BFB536A69B9F787F2BAF1BD1D67146F013
+:10191000E3CA97BE89F8CEC46EE023D5CCF7C5D410
+:10192000A160EFDB2EE7D2771F8CDE7F75C2BC2D66
+:10193000573F89C5FE9E37FF4AF0B3B9D7072FCA74
+:10194000A26F4C687F5A3BEFB9A029211FE90E72A4
+:10195000B601C7BFED772F5EFA00F1D3FCF2D69F38
+:10196000E133D779FE7397967714F6C625F001F622
+:1019700086E28B2E16CDCF9308FF46C11DF92CFAB7
+:101980009E874A7CED66C7711FA7B6D5407526B104
+:10199000B8091496AF8B950D9A51725B9CA0AF85D8
+:1019A0009EF97FCEDB2AEAA83E20D21F2A38B43225
+:1019B000C20FF2C05FAF7ED033DE5ACC2FE9FDA15B
+:1019C000F101C36253DCF7F84587A6F5EA174140F9
+:1019D000ED96C688AD21F835E8F4F37E2157F53849
+:1019E00016E6FF03D1FCFC33980EF47B7F9ACAF510
+:1019F000B72D83F1F36952E7300BE8CB16E7A2C7A6
+:101A00001F856B96417CDDD8AFA53335F9C47FDDEA
+:101A10007ED7A111A4B7D8B7301BE243E43DF474DC
+:101A20002BC0F3ECF9617227DE0F1CFE6B2CE67DF8
+:101A300077C4AB6F213D824765DAFF89523A4C8EFD
+:101A40005EE2BB57510F029FCAA9DC1E581A797E6D
+:101A5000D1A2BA19C60F5176FBA8F0737F8D4E1E26
+:101A60004F561E7EBFBF09E871C9D0169B03E3AF76
+:101A7000DEBB3B16DDFF0C93F703E4C35567DF1EA7
+:101A800063A7FCCD96FE180FD607F87730462ACC10
+:101A9000A7E4F584A37A332C2601CFE927503BB283
+:101AA000297F19F2597580AF13C7C642BEE18D1266
+:101AB000F53B1B6BE371BCEADF37A7A13CBD9CC4BF
+:101AC000E3CD97AE66F3F715A6E0F341A74310D335
+:101AD0006FC0F8E46511D7745E95E9396DFE918D9C
+:101AE00085B21DF82127B0F100C5514D6615E91AE0
+:101AF000F51CE378688A22B9AF6E99CAD0EE7739BF
+:101B0000984B82FB3BA2837FA4F36ECD6615F3ADA9
+:101B100051F68D2C1EC6DF21F659870347E179293E
+:101B2000EDBA365F54D3D31873203F50DE374AD90D
+:101B3000C826DBC2F11C437876A4723EDA111D3050
+:101B4000609E253898B16709AE109C8CE6D5E01CE4
+:101B5000EEC7F3843B4CC1F3786E06E0B223FD87F9
+:101B6000330E276B1AAA629E20CAEEA67544D95579
+:101B7000974FEA0957752EF3A35DFFF943AC5B6EEF
+:101B8000518EABA3437D0BC8C08E814CC8F9CF1FCB
+:101B90002FC908EF836219177A7FC8AF363E5E37C8
+:101BA00089E2099F8CF12FB431F1B84E95D6A76028
+:101BB0008A298FE301F7DBAD167EBFFB79E06F1B4F
+:101BC000F66DFC39579CDD3A4D2239E1F5B8421FDC
+:101BD000DC2705CEDF08A4FD2A702057055856BF24
+:101BE000B19FF87495A1E9A99170FFEE28AF2B156C
+:101BF000E67BED43039D6BFDF38B51FE0AC0C7B03E
+:101C00007D5B92DDBDC8877EFC47DE7BE8C974A49E
+:101C1000FF3E49C53C6C973148DF37A96AFACC448E
+:101C2000F50D8D1F53DDD39BA9DE4938CFB8C61AF9
+:101C3000DA8F1ECF36D27E74B6380F5EEFE4FAE349
+:101C4000F2E921CFD684E17F492A972F16F40E407E
+:101C5000B96912F2D9827E0AB47B85BFB4B7F5D6D2
+:101C60002C352C7F58C30EA423BE1F6287A8D5AE87
+:101C700077F9F9B9CAEC772C77B8C3F86F9190F778
+:101C800045A9224F96EA9D8DF0AE6AFDC414ABE2E1
+:101C90003999FAFE6857EAC19FB2F782976EB9D5B3
+:101CA000C951B51234E1F3D517F8F957A0731D9E49
+:101CB0003778F99DC6118BE1FA5EC035D695FACE1C
+:101CC0009AA9BE72AFD1938ECFD79CF93A17F55629
+:101CD000090201F07CDDBC6A00E20DF8BE281AE5BD
+:101CE0006B17233DA6C9670ECA27BC9F837C5F8004
+:101CF000FDE1A4877798DAF9F9D3BDFCFC29F03D22
+:101D0000C901F0BD1DFD861C3BC801BD3F94E47BAD
+:101D100047BB81CEC9FA408F0FA67ED11CECEF687D
+:101D20002FB1937C635E3F0FE5347080C6A987D8DE
+:101D3000044927314FB83FD9E88C25BA69FAF1B088
+:101D400093093BA1C6E17903AB2C47C845983DE414
+:101D50007D612F4FFC2AF0F82FD176B8855D10FEFB
+:101D600014F3E6939EBF57D8AAB5AF4F98B91DD6C6
+:101D7000B9F684DC5D3F8EFE6B40F0C901E1CFA275
+:101D80009D5013783D0E5E1FBD99D7D58E71AF293A
+:101D9000C6B3CFE3CA371EC47682A7BE18CF3E4F64
+:101DA0005AD07E909F81E6E7D91B0EDC948DFBDE36
+:101DB0005D67CD0CF75D1AFE1AFCE34B8087FB5B79
+:101DC00000FFBDD825580EF11F58EC74E6EC79BF22
+:101DD0004BD2F4C7A90AE4C7CE0639D40740AA807B
+:101DE000C1B1FFDBD4938FFBA09F95E67E3E15FD2E
+:101DF000ED742FB55D27FF9A8CB660EF69EE47351D
+:101E000098DCD9C83F0D0323BF1FA0B54FA61A8980
+:101E10000E057D7CBFEB482ACF6F0EF1B1C7908FC6
+:101E2000AA1A64BB1FE87EA941769BC01F3AEFF651
+:101E300026E3D99C0BCC77CB44B4F3228ED4BEF7E7
+:101E40007217FA2960A7EEFE65EFFB0FAB99F65B00
+:101E50006340BE5AD624B1FF001C2C7F26F2F9D570
+:101E6000DAF76A1AB71CC6EF88AD7C4E771FFD15EE
+:101E7000FA0E46A41F732455F827592C0BFD13E0C6
+:101E800023D20F46851D3103DFAE48F7EE437BFCBE
+:101E9000B2F8BE02E85192C77D4E615744FD4170D1
+:101EA00007AF2B1EBECD2F1BE0FD098A5F467BC509
+:101EB000A0C57D87716E6F197D87C9E73E8DFB3E9A
+:101EC000CB853E5CAEF9697EBE3F026637C24FAB42
+:101ED00016AB1FCFFCB5B1B8FE6D12C5CBABB64586
+:101EE000EEA7548BF5AFDE7CF2309ABCCA7ADD7D6A
+:101EF000B1FE6ADDFAB57DF3CF5323EBBFAE773F7A
+:101F0000E42F46EE37BC2DC6D1EE9BD2B87EAC8214
+:101F10006520DD56FB65BF9FFB7936FC5ED09D6278
+:101F20005D770AFAD33AE1B9CA6D923F803CFE78F8
+:101F3000649DE95DF58BCB90AE7A3E5929D6BD7C88
+:101F4000BB91FC55FCFE0FCA9D9E3F568AF5AFD44F
+:101F5000ADBFCA2BE9E0E37E744FF8EA6F413A5710
+:101F60006E37B2DEE0D3E8B552E3EB3EE0D5E0D425
+:101F7000E0FEA1F0F64F13F9AD116C04D1A93CE1DC
+:101F8000BAE8A4F773771D1E41DF5BBB7C6420C5F4
+:101F9000FB1A1FE8DF2F137EF2D4CDDC6FBCD458C0
+:101FA0006C1D89F14C9BC125A9149FC58E04BCE40E
+:101FB00037CBAC02FA5D4D599BF0FB8379270AE6DB
+:101FC00060FC9F7FC240E7EFF61C29A07DE7FCA3E1
+:101FD0008312B228CFEDA2EFE3C038645FBBDAF220
+:101FE00036E1F984AEB692021C5782E7D00FC813CF
+:101FF00076A2A62DCF1A7EFE7C4C1A8FEFD73B3FE0
+:10200000FD39FAE9537719E99CC55463F04DACDB0F
+:10201000DA7344A17DF2D527963C1485F47D51A254
+:102020007DF2C3ED6B1317229F3519EDB8EFDDD5A7
+:10203000F4E30378DFB75DA2EF5E54379766EF8075
+:102040007EDE967C57F8F9B33C874AF0B1542BC535
+:10205000CF53FB19C96E5E4CB3FE16FD9F95EE2D56
+:1020600024DF17F7EF3151DDDE0E89A1293BEC3C6F
+:10207000F80AE2E3E2AB274DE88417379C34757C1D
+:102080008F3F70C92FB300C5CD1B4D18C7546ED1FB
+:10209000FA1D26A49347F84755CF7D4CFD95E8CF10
+:1020A000C37C2B9F91A97EF760F36B26E4E7AAED32
+:1020B000124BC90CBBBF598AF85EC312C6F96089BE
+:1020C000D03FAB987F7D1A3CB76A23AF5B608F46E9
+:1020D000D6016BFCBD42F0F7AAEDB3E8FB533DBE61
+:1020E0005B8871E30DF81CE7EF659B23EFAF107C75
+:1020F000BD42C7D73F4913FA67381B8E7CFD75A1D7
+:102100001A9703D7BF3EB972406FE7ECDB84BDD6A8
+:10211000ECE5E58081EC8DFEB9CEC62B046775DB5E
+:102120006513FAA7654D5F10FE2B9A5AA97EE466E7
+:10213000E65D8DF8BAB9C96A47B9AEE8E07A685A7F
+:1021400093D9EF97F07E3DD53977B5F0BA49DF7E68
+:1021500089FC1C4D8F69DF775C26F0B80C14787A07
+:102160001EFABB3C6EAE1271F28A615B0EE33E7BDF
+:1021700095B8BFFAE8C158F40FA7B12F6E47FAC05F
+:102180007C0CE763CF44E27DBAD08BD3B773BDA894
+:10219000B76B5DA9D933298F09712AC2B57A7B241F
+:1021A000BEAB74F1F963693C3FF6820EDF15416600
+:1021B000CD413854D9E5A7A7DB159CF7482ED85B4D
+:1021C000B4936AD6F77E87F14DE1676BFD99E21C07
+:1021D00078BD7DA32D3C6E8E4AE7FEC2CAF1B20FD8
+:1021E000E9D51D6F0C3A98AB1A42F106C419CD69B6
+:1021F000493CEEC082923732649698188A371E7135
+:102200006EAAC8837EF5762EF79DE3603C3C7FADD9
+:1022100030F247ABB79BE99C6235D09FE28A267EBD
+:102220009EC2D3249522DDC15F3F9A86FBB19852AE
+:102230008575CF6AE47C3FABE40BE297A383F87A21
+:102240002F2B6A4A6FFEBBE6B7E3F93035CC7FAF80
+:102250000239C5E7AB9A783D52C3816FFA67A29EF7
+:102260006BFEAFFE8BA1FD5AD845CD2F0C825F3897
+:1022700090FB45F4BDC9BB857C2DB3F37DBABB850E
+:10228000FD61521DF17995B1FE503CFA593B78BD84
+:1022900000DB871F8503FDF8F64B75F1B0EECE9796
+:1022A00024AA87C3F7F17B949D4BEA3F41BFFBEB28
+:1022B0001D16F237EF06BF654A5E4FB9D4E45BFBEB
+:1022C0006E560D7B88FCCF87581DB595829F3B1BB2
+:1022D0006BE9FBA09ABF42EF0FECE98F540ABEAF47
+:1022E000D4F15F547A24DFD5BC1D4D7E63D751D91C
+:1022F0008EFB3180AFDFA485E345F8210D07A2886E
+:10230000AE5D276D6447FE2CF8EDA2C83FD78C93D5
+:10231000090F86F1BCCD6E796D20D211F18EF5F7E3
+:102320002FB7BC36829FFBF613FE576D9323BE0F6B
+:102330005B591FF9FDD79AB76FA3EF0855EFEF86EA
+:102340006B88293104575F7220493C8E3448917163
+:1023500064F53ED9135E7706EBB903F551BA9007E1
+:10236000A6049331FF35009D0680AFA689D3D5D052
+:10237000CC5B98FF169E2731D2FC3DEE17F956E351
+:10238000FDAF33AD7CFFFAAAAF02FBF70F94A9AE05
+:10239000F3FEB7570E0DD7A30CE104BA561B83C941
+:1023A000146F9E34107CD5272F270FB2A15EDA520E
+:1023B00082DF0F9D2EF4DFE181D6E5C8CF3E9C374A
+:1023C0002534CECB69BC7E8FE17A9DE86DFC928F7F
+:1023D0002BD6FB109B2DE26ACE4F39697CBD108F46
+:1023E0008C4BEF251EB95EBF13ECC3A98512D63303
+:1023F000293E8C87F7BCC7F5424DF3B28F90DFAB17
+:10240000DF37539DD7FD2DCB8652BDAFD77B03FA67
+:102410001B5FB7ACB881F283D24304970FE173A27C
+:102420005F732619EB522B9BCF2493DDDD3B7A9310
+:102430002F06FD97BCE9781DFC09E23FF06B88FF91
+:10244000F6B415687E8C15C7AD3CAA78103F954749
+:102450000B8E57A07F71A2A800D5B974A280FC98FA
+:102460007CF4636C21BFA65B4FA6733FA6AB358A95
+:10247000F20B121BC8F9870D8AE09FD50DAF93BDF3
+:102480005FDD2847D42F6AEFDD99AED038CB34FE1C
+:10249000A997DCC41FBB78BBBA710FAD6F95B19E15
+:1024A000E85DB3DDC8EFEFE0ADF67D581F8BF72197
+:1024B0003E8EE325A0C334933F03F3D3C732B99FC5
+:1024C000AFA7C7E7E93CFF71ECAC7700F2CBB142B4
+:1024D000EF507B2F76C2C78A785C2B097C37F0736C
+:1024E00053FAE73E4B97C4774222CFB76AEDA974FF
+:1024F000AE3FA7997AFF2EE06FD2B57309EC314356
+:102500000146C546FB06E1D7A7867DD761CECD46FD
+:10251000F2174E31FBEB58EF3843D3B3E3B87DD518
+:10252000E7CBE789F73C9B55BE5FA43B3F334F3B6E
+:10253000DFA43BEF364FF83BF374FECED3E9C28FF6
+:102540001FC286A01EAC17E7EFD60E8FF287E7B347
+:10255000F4ED61B12F82E787B0AD19FE2EE57D8ED7
+:10256000B59E7D85EADDCE46B1813CAF47F9EFCA25
+:102570003EF2DF35DD72393782CF34BA5C12DF8349
+:10258000D1D365B7A6AFC4BE5DB4D8B7F31BBDBB8E
+:10259000519E2B2D174DBCEE3068427D56339CFB6F
+:1025A0004D974A25DA6F0738FB9BC3F4FBA5541EF1
+:1025B0007FDD7F8B4479D7567C1EE3AC7A89EABCF9
+:1025C0002B03ED26E4A7210D8B1F26B9F5B1D32CE3
+:1025D000ECBB1A332DDC4E76D34F5B77B71D8BF7F0
+:1025E000717D9C482D3E8F767186B083FA7351437E
+:1025F000597B593AC033DF2DB9B01EA02F3ACF5EB8
+:1026000030EA7544C3F5D2BB33DDFB4E3ACA79FBE1
+:10261000E55B308F7A6CF867FDD18E56F5C1C71F28
+:102620000B3CEBBF2BE31AAAD6E2F7556A9DDE0EF0
+:10263000D29F866F6347301CA7E3376B25A4132313
+:10264000FEEF4B7E3E13E37E96CEBF770FB8A77D9D
+:102650009755E9BC4EEB98D19F41798A9CEBDBF70B
+:10266000AAD9F7462EEAB3CED6A3B9A630BA5E5C95
+:102670000B7A00ED4AF3C164D516CE7706E23749EE
+:10268000D2F84F11F632920F2F221FE6607B26768A
+:1026900010EAE35DA76207E3787B79DBCDAF4DFC01
+:1026A0007BF6101F0D9917130EDFC304DFA57A3ECA
+:1026B0000E631D43E68C0CBF5FDB171F5B33888FF7
+:1026C0003B22F8585B6F3D7ECF07E38016337DCF0A
+:1026D00007F3D78E3039199AC1F5CF58F1FD9EF125
+:1026E000CC47DF391C2BBEE3335E6101251EF7CDDD
+:1026F0000232DFF7E5E72DC6087E1EAB045AB18E25
+:1027000062BCD8E799C0DAE9B9292C48AD9BD9E970
+:102710001C451173513BCE12988EEE544E7D3DD523
+:1027200025069215C7798B38AFD10BDD42EB57E800
+:10273000BB3DC49F329ED7E9FDBB2FB333B8DCD37A
+:10274000C74590BE9718E5B9F07B6D38C9448595AB
+:10275000637DD3648559A201DE5D870C24CF2D1DD6
+:10276000AA1FEB535D09E2BDCF19D5E18E757379D0
+:10277000459383F518DA7AF5789800E3619E6DAC9D
+:10278000029128E13140F3DDC8F8399242A652FDAA
+:10279000736946A6D0F7418AA38A218E427D6FB025
+:1027A000F8081FD33354BA8FFB25B130CE848D1275
+:1027B0007B0FF73FB2F87AB5F1270023E0F9C2E9C1
+:1027C00019DC9E614AF5BD78BE8F124B05CD25768A
+:1027D000FE9DA364FACED1F5E2B52B997FEF32F6D8
+:1027E000CE60E7CF0A42FB492EFCEE516CE83B9BE2
+:1027F0002EEDDF830844FE7B1077642CF911F2A3E1
+:1028000056AFC7BCFCDF7DD0D7EB85D5E7B10B61F8
+:10281000E7B0B5BA926DFED92A9EF35B9068A173BA
+:10282000BF7996FEF968C7063ABD34FEFBD2F6C101
+:102830003498E21FED8909F1BB95B9C721BE4375F4
+:1028400083FC3B50DDE7AE92199D57B49A797DE544
+:1028500063201FF81D26902E15EB68D883C5548F72
+:10286000B9DE6171E1790933C26D0DC15D6B11DFB4
+:1028700005B5F07D717D3D68ADCD40DF1DAD65D105
+:10288000740E3D29DABB2E03E0BA2FA688CE7767F7
+:10289000EF9CE444BF317CFD93B4F51B7AD647C26C
+:1028A0007A1FC9E8A51E515BA7F6EF76D805FEB4DE
+:1028B00075DBB5734A6E25E29C92868FC7A2F9BA82
+:1028C0008DB8F39F45EFAAA837F4EBFDFFDC29BCD8
+:1028D00016A06400000000000000000000000000DE
+:1028E0001F8B080000000000000BD3D76660F85172
+:1028F0008FC02E9A0C0C5DD2A862B4C41D120C0CB1
+:102900009780F80B106702EDF5926460F006E26DB7
+:1029100040BC1D88C5A518180280381088FB80FCB3
+:102920007E204E07E224A81BB30519187281381FB8
+:10293000880B815848808141588078FBCB15191845
+:102940005EAB22F85A6A0C0CC91AF4F3FF60C38E0E
+:10295000B6F4B5EF14D0BEE56E08BE0490BDC20D4E
+:1029600055CD4A37FC66AC42935F8DC65F83477F87
+:10297000A20D2A7F99292A7F9D3903C3432435CB91
+:102980004DF1BB051D0B02FD2784274C9730A2F2A9
+:102990002732A1F2F9A17C00BA0B8074A8030000D1
+:1029A00000000000000000001F8B08000000000075
+:1029B000000BED7D0D7854D599F0B93F73672699DA
+:1029C00099DC24433260126E7ED0A001879860B0FB
+:1029D000586E20E147A30E082CB440262888166DB7
+:1029E000C49FC6DD500609BF0921E14F70D11D10FB
+:1029F0005DEA63FBC5565B75BB7682D646AB356830
+:102A0000D787767765A015BFBA761BD96D976EBB51
+:102A1000F57BDFF79CCBCCBD9900FEECB7BBDFF3B9
+:102A2000C5C7E770EE3D3FEF79CFFB7FDE73C7C5CB
+:102A300046B1E058C63EC6BF698C4DCC658CD5A664
+:102A4000CA160F8B65E73096DB213156C3D8CA769C
+:102A5000253E0BFE59D8D1F20AD697B7B90D772982
+:102A600063FD0FB8FD35503FBD5D09BBA16BA3E20F
+:102A7000A3FAB22E57D86DC0F3AD1FBD9C8FEF37B0
+:102A80004A610675C6EE666C32636B3CF04FA82F48
+:102A9000AB4876E0FB77B748E118BE66A66F12BC7C
+:102AA000BF95F1F7CD0F281A93A1BEEFB626369148
+:102AB000B15B7A60160F35641FF3F68C153016E1A2
+:102AC0008F58CB16785F997A1F615D1F29D0AF3977
+:102AD000E678BE6FD6FB2C80EFB5D47358CF31FCAF
+:102AE000C714C62E65FEE0E96CF87798853F56A0BE
+:102AF0006CC8676C740A5FCE9231807E1463731960
+:102B000073B17218A7F632172B83F559786CE378F6
+:102B10005CD624111E97F918D5DF9D2BC51F2CA557
+:102B20007E6C7A3594F0BC200FCA20330BA18C78D0
+:102B300058221BE09FDB76D97BB8FE0D38D5686A3A
+:102B40009F08C0FB052CEA6200DF9FB118958B59E6
+:102B50009CCA2FB304C1B1940D95A850BF4B496CCA
+:102B600062304F38149D8EFBFBBBFA63EF4AF0FED8
+:102B7000FE6AA9760A94CC9747EBBED0FAACF95519
+:102B800016B90EC7614C7645FC8C8DB7D67998C5C1
+:102B90002A828CE93D3E4E2F87593F83FAF8064141
+:102BA0002F8DEFCB215877CFF32C8CF5106CE614DA
+:102BB000A887BAB2E21BA0DEF378AC1EF172AC05B6
+:102BC000300FFD8F35BAA56815942EDD158132A41E
+:102BD00032A6009EEA1BD64B0AB49B1BE5E38C375A
+:102BE00035995D09F5C3314915CFB1BFAEC7241D75
+:102BF000EAE3A1FEA084EF751783711A1A725DC90A
+:102C00002AC477CF181DCA8AC35A4206FCD69B3AFB
+:102C10003D676C11D1D578416B734DDE6FEEE13CB1
+:102C20003FA3F7EC4F1F5BEF01BF9714F17D3B769D
+:102C3000B82C07E165517BFF2295C53C79293CEF13
+:102C40005C072FDC29FCEE3A5CB615F176AC4F0D33
+:102C50000B52B68D0FE3F636C0FB335572583190E8
+:102C6000CF8A38FC15BA5FF7A5C6D9B90EDA5F96D8
+:102C700082A35199DA4FF83019F1E3DC1A685F95B5
+:102C80006AFF04B60738F6203CD46FCD512FCE131F
+:102C90006134CF48F4F0C23A9DFA0D8A755CF3BFF7
+:102CA000C3B44F731B5A243EAF80AFC10E9F555A19
+:102CB000F08D34FE31019735BE35DF13EB425436CB
+:102CC0002A558FDC8BEB3AA2F175CD371EDF8DF8DC
+:102CD0003BE209C7A0FEE4757F33E65E18E28AE9AD
+:102CE000CF5FFE0CC3F9963F7C3BAEEBB92C5AD7B5
+:102CF000531F9E79ED46367CDEB7041E7E7A6EFE4B
+:102D000010D5ADF9E79AD21809E8ACD294122EA0EA
+:102D10009763F55F79F85E03EBFD26CA934AF39853
+:102D20002941391186A1FD66EA9F3E06795609DDE3
+:102D3000911F2735482DD8EE891B1FFAD27DF0E868
+:102D4000A72E0EF7157FC9E1BEECFAB54F22BC974E
+:102D5000DDB8F6E7CF40FD0A1482C07797DEB47F76
+:102D6000CDDFC13FBFB1F02F97EF61241762D900CB
+:102D700047AE2931DCDF65DF77DBE4CAB1E7FD244C
+:102D8000570ACDD218F2DFB23E89E4737FA39B05C8
+:102D9000F1FDCFDC7137F2D7039249ED9F75C75132
+:102DA0003E1C733186F278D9716F1CF985AD5A4695
+:102DB000F23A62C96B337FE9BD30DEBB0D963CE76A
+:102DC000744AEF617DEF9ABFD87E35F43F63BAC293
+:102DD00028362D79E1C4F3BB02BF91FA72A2836554
+:102DE0006AD215CE400FCD6D8A4D6ED7379C24BA6E
+:102DF0005A06254BE3D3B982CF9635FC42F0A74E55
+:102E000072C909CF1BB585C599E8EE94802729E8DA
+:102E1000ED5DDCEFCB103EE88574D3A5C495343965
+:102E20000D7FAEC804AAC790A56FD96287D392DB85
+:102E30002DB16C9BBE02F9FB2F28379BDBF26DCFC7
+:102E4000E7E6B0DAA99F4E0EFF81E4705222784087
+:102E5000FFD2FE47E2521CE5A2B53F7788FD8954B8
+:102E6000305ACFAF0E48F118ECEFAF8E88F5ED93E6
+:102E7000E28A44F46A9EF6E0B83067796AFF6F1719
+:102E8000FB9FDA3F8E1F0B5F293D97BB290920B4BA
+:102E9000F8222528AF2DFEB1F0DBBFE74725B87F2C
+:102EA000856DA5DD7508E70185F8F7C3FA93C5B808
+:102EB0006FEFBA00AFD03F72F8B100F3A5E06F1129
+:102EC00072F0830EA017782E219C9569700AB85D68
+:102ED000588776B737487DC8A7BF14F35AFD7EB42C
+:102EE00065C64CC4CF1D3D1243FCDC7EA477D99F40
+:102EF000C3FA57C7B3C338C5AF1A8B0397003C2B2F
+:102F00007AECFB796ACBCD01A49B0FFBF20B709C92
+:102F1000DBA72634847375E255CD003A9B65F66ACB
+:102F2000C90C74F561DF8600B6FF50EDB9F11A9C4B
+:102F3000679F125E0FE3AF3E523AD3E4744AF4BB8C
+:102F40005AE0F7A4DA33730CC0D7F28D729207EF10
+:102F5000F529B3E319E4E7D72585E860759B5BC6DF
+:102F6000758E442F1F76B85802E7511384CF91DA3B
+:102F70007DD0D742EFFB1F28BC01EDB7DBDB5D2422
+:102F80002F6E6F73133DAD6E90E24C4AF1DB0A0178
+:102F9000EFEADD0ABD3F694A243FACFDBA5DD0DBF4
+:102FA000C9C357BD82FAFE0CC81F94BB3336FE500E
+:102FB000BB04F0B0620B97472777E72EBD07E58883
+:102FC000D0977788716F8B2B36FE58D99E6DDB8F2B
+:102FD0006857BEAD7EFA48FE8D7548D75D0AE9CFC9
+:102FE0005B363EA685483ED9ED4DE4B0490529FB48
+:102FF000F2041B5A708D94A2278B7E6E6D037B3377
+:1030000030DCDE6C3922913D7AD176661BD899137B
+:1030100087DB99961C89A07D569E922396DCB84B3F
+:10302000898E0D021CBF76452FCB2F27B9F1805416
+:103030008B74A2FF16ED4A16536A51BE5DACBCA05C
+:10304000C55A7C047FEF75005D65A0D719485730DD
+:10305000CFCC9EFE8CF43C433268BC14DDDC1220E5
+:10306000BEC541018E668FD985705E02137BABA908
+:10307000644A1E2F55A86F4698811E4EAD95E28773
+:103080004A793B1FCA5380EB1A78DEDC75797C9B4A
+:10309000847621FCA1FE6CE37637B433FD79F4DC51
+:1030A00094A02C6A2F7D19F7E71210005A356F8F04
+:1030B000F3809D452881F6097735758D05A02C860E
+:1030C0007E32EF4FEFB15D80E4789CD68BE3E3383E
+:1030D000154A7C0DCA198B8E9709B90372B5520532
+:1030E000FA6A665961D49BCD6DE5E7B55F6E08DB82
+:1030F000E5C74D75763D30D7B4CBFF9B675F626BFC
+:10310000BF20526E7BFF678BAEB0BD5F1CBDCA5641
+:10311000FFF2AA2FD8DA2F6D9D61F7937E9A4BEBC1
+:103120005923F87224B85F17F2F2270EFBD42A9BBA
+:10313000AE4FD4BC0DFBC4D6B9C38F4371620E5BD6
+:10314000D49726577CB244F8FC0DB009F70FFEF473
+:1031500031E131C4E76DFA0B776B26BAD3443F34C3
+:1031600097D05E72B63FB118E649EBF76F924474A0
+:1031700078AE1FF3F4FC12406E014ECE01D4DFC9CD
+:103180009225B86FEE5C83DEDF25270BB0FE1B3681
+:10319000B4371FF7D7972C46FE6956D973520EF6EF
+:1031A0000B7BDC301F5843AC0DE8A3A5ED47C7D11E
+:1031B0008E938C205B82758F2F81FCCD3A5C1F260D
+:1031C0002DBC031FF686A21F4A0087D4DEFF7B09B1
+:1031D000DF7F9F19A88759B22817FD479C2A9D0FAA
+:1031E0009B66B056C4D789463BDEBC621D3F9764E0
+:1031F0006AF71C337F8B7C7452D2F9FA04BCDB244F
+:10320000F32CCE67C1FD6EAEAEB14F07B722D72209
+:10321000DC3F22B837B4B264B63232DC5730D32D3B
+:103220008F1A0ECF596666657A3E0BD835D3F3CB2D
+:10323000DDAC12EDD5135256787D299643FFF83553
+:10324000E0ABD8377CE1C78DE1743155CEA5F99B51
+:1032500085BD5BD82E25B2D13E651EB25F59CF43E6
+:10326000A607E59A10712D6DD2495C3FEB68349347
+:103270009ED47A9921B1F476E7F6BDCD4DED2D7946
+:1032800063C92D0B9F965CB1E4978557E7F823C976
+:10329000191C4FCD43F8A393E4743AD1011F1310C6
+:1032A0001EB31AF7CFDA377023639EEA91F7CD92F7
+:1032B00053D08EA1FF3FD27E019EC8AE738519E127
+:1032C000E9DDE0D0D2A760DD036D5C5FBF5BC4C801
+:1032D0003E3CD376D5400EE2C7E3A940FC14F2A9E8
+:1032E000586170681DCA579F9AE847B80A85FEF270
+:1032F00032AEBF0A99B1E36AF4EFDB4F2EC176D646
+:10330000FEE48AFD6986FD417FA4D937548C76920C
+:103310001BF51AB47383DC45B95CD8FEFE7FA05E52
+:103320002C74E8458484A5C39155B5E36A237DFCDC
+:103330008F36A27D698D4B1DD2F73FA89D44FC16A8
+:10334000B66FBE5B09D8C6973E463C08B98D66D7B6
+:10335000B9794AD15E9513EE408A2E9C7059FD468C
+:10336000A213963E4FB9AD4EF684B3EE0E6B36F90E
+:10337000FCEE1FCB735A7DE7A137E7784EFA76F261
+:1033800081C0C3A7A0D34D9C4EB95CB0F8F63F8B6B
+:103390004EA3D6BEC672EF3882FAB54B0BCF32D0F1
+:1033A0004E18FA21B713DCC621A4B398945509EF3F
+:1033B000A31D2AD98D965DD1BFF6AFB794C1F31383
+:1033C000B532F91127D673BADFF300B7472DBD1D0B
+:1033D000157A1BED02C42BD80D036E5E7A701CFFAC
+:1033E000FA9B4B2580DB630CF5BBB17D9B41F66AF4
+:1033F0004E5D5C6F84325E71C833CE48C9A5642CC3
+:103400003F6F39ECD7B7728D6511B2AFA3A3E7FA5E
+:1034100053EF7F2C73FD34AD84E5CD86F1925BE5EF
+:10342000F083D03FE9B2EB31AB5CA3707D99F4B28D
+:1034300012F483476A37A4587A55D7685FE60F1CA1
+:10344000C77D1A691F6007748A639EA3438E7798AD
+:1034500087C64FFAED7AE8A4D04316FC9F40AF2E02
+:103460002C06FAD82B6586FB23315EF4390000F672
+:103470003BAA3233533BE7BAFF41F44BC82ACDB7DE
+:10348000A362E76CDCEF584C09A7EF8755FE85C2B5
+:10349000F567CEDC86DC4668C7D6676E9727DA3DCF
+:1034A000765FD622F4AF00752AC66B42317DDE6CA2
+:1034B0008C474ECD9B843EF68F51FFC0BCBB23672B
+:1034C000F416DF27C247414819191F6FCA32DF4778
+:1034D00007DFEE01770DE56752F250FCA525E6CE39
+:1034E000C8C7969C72CA23A79E934C93B5550F9755
+:1034F0002BD6B89F549F817CC85246A5ECF673FA30
+:10350000EC62E97104395022B3685F06FFF46A8502
+:10351000E3A93FC6E314AA2993DE9AA9343109F03E
+:10352000B421C8481EE4E15E23DF36B038A080E550
+:10353000B3F0800FE549506609F25B9D7EA0D98407
+:103540007E609083C6F45165FD85F03C387F259DF3
+:1035500033B00897B73AFCC7F9C8247DE116788DD7
+:10356000C626519C33AFC92EC7DDE807827CD41B29
+:103570001CCFE7CFA4F306374B7B0EEBB84AF1071D
+:103580004F8369CFAA590DF267F5FEAB762D86F110
+:103590006B1EB9F96D2C271FBC27FF4B50D63DBEC3
+:1035A000EB662C4B5E8B8ECD144FB54AE01426D7BC
+:1035B000017C3E66B873466E67AC57226857C33EBF
+:1035C00076203D2463E55948DFAB14CEFFFD0BB4F4
+:1035D00000C667D42D5CAEAAF3017944FFDC4F6FBF
+:1035E0004EF9D3E457A8C24F52DA158A2324F53294
+:1035F0008AB71CDA226B58829C8DE13CD6FCBD2236
+:103600004EDD29E2AD4EF87A4B868A510E9E58FF68
+:1036100011D9878A9E159E0DF375F95909C121E2CA
+:1036200005CD62FF926BEB3DE9F12245F8391D476C
+:10363000E70C184807034AD86B10DF68386E74CB64
+:103640007486F197597A98A13DD129FC1EC567323D
+:10365000DCD76C9DCD44BF165E6921EC5FC5C20905
+:10366000ECDFDE8FB885F59AB7231FFCE05A6E8732
+:103670009C28B5CB6D20A12ED85336AB68BD8AB43B
+:10368000D9149C7415D2FCEF9502215739BDBE5157
+:103690003BE5B16D4007CFB9CD7B94519F808F1C26
+:1036A00072FD07C026B86F8F4A76796E95079D7CAC
+:1036B000D426915DA89A7C9D33950F1B514F6E04C3
+:1036C000BBB1D018CE2F1B5F6764376E04FE8B959D
+:1036D00066E29F6A0965C4C5F24F5E7BAE84718C59
+:1036E000CFCA3F7FA988733AC13F406709B4631EC0
+:1036F000958CCE29B0BEEFEC6BFCF11478FDEC811B
+:1037000015D9D740F9BDF8C6EBAF81F96F7F7C4F73
+:1037100036EEF3A3AF023F9DC78FB7F8A9196DD856
+:10372000F3C4D98CB5767E32D657103FBDA570FD57
+:10373000D5BFE0776F5CFDFFF9E97CFCF4B602F4DD
+:1037400039ED4F678BA3E7916FCD454C437B0BDA87
+:103750009848E7D1A0BDF4A95984EF752E2EC7FC77
+:103760002E2FB73B42FCBD73BCBF513F79FC60417B
+:10377000F967E7D3753EF3A3CF83DF41EE90BC3901
+:1037800031CECEF79D2E4E77BF727DE2F5BDF3852B
+:10379000CF617D60D7937D779DCA0CF40326BEE090
+:1037A0002161F1EAB88D479025A6C1F3501E7FEF45
+:1037B000CE237919473B6648A9A4FE26E3767C53BD
+:1037C000CDE623FC5C62B06211F8CB73E05F688FDA
+:1037D0005CE7E37E058CC34230FE6A6FB4581D453A
+:1037E000E3917FF9EAF3FB82285F5EF79825F89C66
+:1037F00025D55C3C1FB0EC8E91F95D65A7D3FCAC80
+:10380000A73546709CBA54A378258AB100D4B796E0
+:103810005E4A714A168E1D97B03E4A6728C795606A
+:103820006431D9216D6E6316D4B78201150B12DD98
+:1038300092DC54DA7B430194036097E07B3536D702
+:10384000A3A1FF324AC6203473B77D447EF7896254
+:103850002E6F3BA6303AA71978E0DF96CA68EFB41E
+:10386000BBE9DC02EC46E2D7A8901BC9E0F4500BA0
+:10387000FA19455A5882FAA6D82F8E7F8DCB13D3CA
+:1038800033393D3EC2E31D2D21EEEF3AEDBECD5F53
+:10389000BFEC4D03C7FBE16B5D9743F9FA933F7FA4
+:1038A000FD7278F7C6B75EABC1B8B7BB4EB3C51DE6
+:1038B000DDCC7813ED2DF099121ACAE7D8C925B8D6
+:1038C0009929BF4E8A217EA235FE38AE17791BF1A9
+:1038D000939CA2F0F345F80B017C01015F77F05453
+:1038E00015CD137BFF3F32C97BFA9B2CF408B4DB68
+:1038F0009C777F1CE5486ABE49249FA2209FD08FF9
+:103900008CFA7A96ACA1F9FCE107B1CF1F61572779
+:10391000A7CE0B0F6D99D782789EBBC0A3239DB90C
+:10392000639BEF463A77AEF38CEFC14B3134679B24
+:103930001FF8C45DA1995EB27FD961DA0FD1C4824C
+:103940005B0705827107E8BF6C05CBD0DF80FEB84E
+:103950004E9067686F5BFD808C4D5CEF19DFF44B18
+:1039600029DE2FE21556BF9B62129D13DC540E6CAC
+:10397000503E1C4F1B7CF24FBE86E72E3145573818
+:103980001D842AD2F0867FF6B819A78BCBF6D9F51D
+:103990002ECCBFB014DFC714A21727BF8C8FDBDB80
+:1039A0006FF09DFF5C7FF87E723C4F14FC66F5B7AC
+:1039B000E02378A54CF175FBB9CC4D75F6FADC61C6
+:1039C000F8383F5CD355FBB94D83CF3EDECCA0FD2C
+:1039D000FDEC227B7D03C66F3EC9BA1D7CF7F4184F
+:1039E000F33BEA67F0EB2DB9FBBE27F2B7348E1A32
+:1039F00066384EFF82BDF3E7011D14EADCEE289C19
+:103A0000BFB021B706E51413792699ED8F42A1EFD7
+:103A100095F697941CF4474DDE3EB9E4AD1939781C
+:103A20005E5CC7E83C3DAADE13CB3152F648BF5A74
+:103A30009E8578FEFCED91BBBDE97937297BE48159
+:103A4000578D9A0CF6887A8F64C238B396803D52AF
+:103A5000956E8FB44A2883B297803D427647F43DF5
+:103A6000C4D74876C98F2DFBDE9FD9AEFE83CAF539
+:103A70002CE8997FFA2C7A669CD7FC17F573B0076F
+:103A8000A695182B2319E8F00395C73B2CFDD918F0
+:103A90004C2878760E7A5375C1F36BEB922FA138D0
+:103AA000EED0770671DDB01E97ABF6D3AFE78CCAC8
+:103AB000E199A8F23C9891FA7D6B047FC5AB7985BA
+:103AC000DD62DFEFFE05EFE832FA2FE0C7A0FF92DC
+:103AD000F4956DC3B8E099984AF13A75FECADD7362
+:103AE000919EC0CEE6F47C7EFBFADA21D9C6C7D31C
+:103AF000CE66D9F8BE9ED9CFE96678ECE7748DBA68
+:103B0000FD9C6E56C87E4E37C7B09FD35D5F693F40
+:103B1000A773DAF73347BBFE7BDAF7A14646FC749E
+:103B200001FB1EF8E926A4A791F8E9BA7CE3FE4858
+:103B300086FDAED6B89DBADA1B59807437CDE076D3
+:103B40005D34B69EF201F3A2206F4A296E48712FB0
+:103B50002BAE65C5BDACBC402B9EE58C5F59712F6B
+:103B60002B8E25C578DCAAD9135D81F036B79F94DA
+:103B7000518EE8CFC13CC808D639DEB0F81C970793
+:103B80002DED99E372CEF8DB88ED3E255F7D0EFAD0
+:103B9000613DAED7D20FC0E70F7E163E07B9B50D17
+:103BA000C7FB17E4F751244FBA69FF2A00D768A76B
+:103BB000C33E6818A75F707A3FC6E3D4E36EE2DBCA
+:103BC0008BF57F31D141864D8B820F8EF1AC68AC85
+:103BD00094F48BC537169F38FDE361FCF15FCD3F50
+:103BE00017E91F03FF7CCF751E7D04FCF13CE27BCF
+:103BF0005A25C7AF931F2CFA07924848D5B8DFD192
+:103C000004B6B7E89DBD183611CE89C2AF39315A16
+:103C100023FFE2C4F3FFCECF619FF784C78935E26B
+:103C2000FB89DD05F16DA5293EB3F8A9DD13FDB1D2
+:103C30002B2D0FC4CA773CEC315FC7E721B52F812C
+:103C4000FE4A68360B6F3088CF8EF1E79C4F7D615E
+:103C500046F1D3CFEC97ED75C5F17CA8451A5ACA49
+:103C6000C86F651AF2AD2AE4C98B59D19388CFE6A3
+:103C7000E991124E4F43E37C00D72F3A14F2D73E1E
+:103C80002B3F358F84FF73F8880EB96A87E707A446
+:103C9000CB2D946FA19016DF20659057025F7116AF
+:103CA0001E83EB83FDFC77C4635E15936839828FB6
+:103CB0009B3DE61F5C9FCDFE50B4DA141F03DE3C33
+:103CC0001ACAC56AC05BF970BC9D74F1F53BE92F57
+:103CD000A42665A4FF10C8D10D52DA39A9C08BB54E
+:103CE0009E91E4B345A769E70D212D7DBDFF8FCAE5
+:103CF000654B5E5EEE894EC67D709B1121FF4CDAEE
+:103D00005FA79C196E07C974CE7806EC1EEC76B1DD
+:103D1000F275DA592F1E96B0A967152AAF3D4B8769
+:103D200027EC8B67B3A934CFE653597F3697CAE99E
+:103D3000672FA172C6D9D154369C0560C0C4693CB6
+:103D40005B4AE5CCB3575039EBEC782A679FBD8AC4
+:103D5000DACD393B89CAEBCE7E81CAEBCF4EA1D2F8
+:103D600069FF18EB5592DF96FCB2E4BB537E5BF221
+:103D7000EFFF9AFC8E355C94FD03FAEFABDA79E441
+:103D8000F748F202F8FA3E2D5D4EA4F4F3FDDA672F
+:103D9000E0EBE3824F817FDFC3388C07BC388A5366
+:103DA00085799C2A606806E669ECC326B0A5FED238
+:103DB000C8498C1B342FF0E831807BA05423F9B420
+:103DC0002DA8D1B9DB66491FCDE5413281F4B73367
+:103DD000A4D178DBFEA878317FE1A55105019CA72D
+:103DE000DB2FEBD8FE5BB9C97DB7E039FE14163E78
+:103DF00004E3ADD8B3C793EE87EF47E300E00BC40D
+:103E00009E660CF87AE3A8DF2DC5F97C5319C563CB
+:103E1000A03433E58B7DD32DCEA7D5A110E269ABBD
+:103E20004F267DD0AD7B441E6A72A005FDDC3A9919
+:103E30006D8379378C7E670B82AD8E2BDB5106F557
+:103E40009D75655EDCA4A75FF92044F604BC435071
+:103E5000A04C88D2CC81FDE9F4868DF39DB729C6AC
+:103E6000D03A2456ECEFAE1EB9DD26FF4008E9A398
+:103E700063D2E4CA5B60FEDE4905A371FEED3547FF
+:103E80006DF850747B3C45C18023FAE175498AABDB
+:103E90006D908D1D65B0BE80C8B706302B23697943
+:103EA00007161C4A18D6C1E14A287C3DAC009EE7A3
+:103EB000D6256249BE5E13E3AE3E5F3284FEA25257
+:103EC000779AE26D9DFEE422AA3BE0B0C6FFAD66A4
+:103ED000E50570BEF109BE699EF4ED4594475EA507
+:103EE000D1BE75BB8616603DB6D6C51ECF10BFD9F4
+:103EF00020F8795BE5F9E332AACF0E47B7D7EE2F6A
+:103F00005AF0BC2F4A271CCDAEA15199F6EFD3CE63
+:103F10007FA1757FDEF3758E903F70B9DBBE0F0118
+:103F200021CF9BA77C3B84E7E2163C9D12EC43CD5E
+:103F3000E7BF0FCD53B8BCFEBCD7FB3F6DDCDF6BDA
+:103F40003CAE027C3ABB1CE38C632687305EEBB34D
+:103F5000E2D1E138E52705301E4DBD0CD243AACE93
+:103F6000C7505496403E94B33F4CE03E29D59AA1A9
+:103F7000909CCDBCEF4A7813E5B539F9D3829BFE0E
+:103F8000260BD381CE0FBD567CDA5027F3FB1218D7
+:103F9000FF5598753ECBE3D3567FB542A6783405DE
+:103FA000B2D3C651410FE3398E8271EABCE1F37F8F
+:103FB00037458FF6F98B787C5C51B91FF89EC4F1B8
+:103FC000117B55A17CCFAEE7B97C63C719C9EFAEB1
+:103FD0005A83CE5576C0FFE83FC46A7D71A45BC5A5
+:103FE000918F77A6727A08E5A81517A7F9F8F90056
+:103FF000C5B9314F91E2E606ABC0F7DD02346B1C68
+:10400000D58ACB57AE9984EDFC06F33C07EBF3D78A
+:10401000B1C425006FD0DDBAF5F2D20CF1F0CA358B
+:10402000DF7812E6DDFDD4F45F3D09F55D72F8D569
+:104030003A6897FFE53AC2AB331EBEAD523675946F
+:104040000F3EDF21DC57B0A1892E6EED9162F83C66
+:10405000DBE73BC8F7BB35A4205E404F225EBCCEF9
+:10406000BCC8747C97211C3B07E6C1BFBD5BE72D34
+:10407000C379116ECCAF5CD15BAFA19E092EB19F0D
+:104080005FF89BEC756F951DCEAD62FF2E44FFCEA1
+:104090003CC41E73DE22A4DB33418DA1BCD9B8F62B
+:1040A000EA1B49EE6F57D8B8D20CF4EB5857A7E685
+:1040B00022FDDF6DD4EFAD40BDD1A0515E4F77DC66
+:1040C0001BC714EFED75A973139BFD6E68FC1CAB49
+:1040D000464EB833D9F1E27C2C209E31C73958F7CF
+:1040E0006C99EC9AEE1E3E8F355E77DD5B1E941365
+:1040F000238DFBF418F3881BEDA968DE45DDBBB802
+:104100006FA38BD3F5142D2E95A23DAA2F5C04F539
+:10411000CDE364B28798F0FFBAAFE5E7890F6B860D
+:10412000ED7EC5A6292BC96EB8C9AD0BFE02BB70CA
+:1041300042EABEC501AFF9821B9EABCFC148600FFA
+:10414000BC971BBE11E9A231F811D951B716C93A73
+:10415000D2D78A3D8DB4AECDBACC1268F7AAAD6481
+:10416000A436B15613CF03305113E96E0EBC91E95A
+:104170005E44F25027C039675CE1A46D507317B5F7
+:10418000521E4BA321911F761D6006E5414B7144E1
+:1041900095AAB0DFFC77D0EE9B132C95D1DFBF4EF4
+:1041A000650D5A9A7D0E76F13177DABA4E8CDB13B3
+:1041B00094AB707E9807E75FE4A1FB046EB48FAF09
+:1041C0004CD9C71311916976F2AFD1A8C478465182
+:1041D000E2F794E7FDFDA48CF3B21758F536E993A6
+:1041E000FBD5E05FFE12F733CE8C7E4C35FCAC7114
+:1041F00089AF6B629FC4BD95C39EC86F707C2B1E38
+:104200003051E3F79B37B7B0702C2DAEB2F9F93FC0
+:104210003F8EF6AA157F39977727E0B4E0DE24B108
+:104220002CD2F39EE81FDCE97E314B96CD9DF0F950
+:10423000C19D215FCE570BFC3456F04F5E6D851744
+:10424000E5E658CCF7C17D68E7F2C484FFD2F37D80
+:1042500014C17CC1706BBF6C0C974B8AB837057466
+:104260002DA11DEBCC075230EF67E270B97140D041
+:10427000FF251E91FF33994DE67EB8FDFCCABF9421
+:10428000EB7DD69A97F11EEAF785DE7F51F8950906
+:1042900071AFF1A8B8B7F8F23A83FCBC57D65552C3
+:1042A00039B02E4CCF5F5B574765EA7E159F375F6D
+:1042B000D8612A06D5F09CDFC7E206C0EB1FB566C1
+:1042C000A014F9BC8EDFEFEE6E3AB5A59CEC467EED
+:1042D0006EB1B9A83A5188FE0BC09A0F7597AFCF4F
+:1042E000C3EF79998395055CCD21DEFFABCF2B9C85
+:1042F00074A15BFBEFD86F1F6B6528EF02A67DBF33
+:10430000B3C34EFF86EFBFABE8E2F6BD17FF01FB7C
+:10431000F8256BDFAF6657F3EF335C9C3C463EAA53
+:104320001472600CF0D301F0E7DD0ACF57CFE779C4
+:10433000AE6688F39BA9F27A6CBC68EFE224C406EF
+:10434000F2785E7B313F4FA07E98578EEF312CF98B
+:10435000028F6FB11C91FF3E568CB35A8C3BB19AC1
+:10436000EEEDF2F37FD6A763E96349AAE7021F6087
+:104370001964AD1222730C1B247FBB581AA2BA21F8
+:10438000E959582F93C265DC0F8F93FE2C57CC6FE1
+:104390005710F223328F172517933D097A19E562DA
+:1043A0005C8D2C42F9B2A14D0B0326CEE5C9E1FD8F
+:1043B000392C37F4D50CE0F9472C2693FC519E6339
+:1043C00059FA9564EF91FEDAB03EEF6036E56B2462
+:1043D00029CF7DBFA7D4A6A726FA165EA7C37E6DF8
+:1043E00014F9742EE8CF32E49F5AF974306E49A65E
+:1043F000F756B9D1AF2DCAE4F73FEC91443C2339CD
+:104400009AE280625FE353E58CF719F779B85DF3C0
+:104410006869667B9AB10769BCFD1EDD316EB285A5
+:10442000EECFE83CBE91E53229BF66631BBFA76FA4
+:10443000E16F34D8B5680F6FEC9B3F1BF93B56A971
+:1044400052BE39ACDF87F87389BCE48DE38307B3D0
+:10445000795CA214E5743FE2AF360D7FC1954D88BB
+:10446000BF8E57797E2FE8731FCB906F68E1CFE541
+:10447000635FCCF4DE2A3B46698B32DD1B3EEAB13A
+:10448000ECF46429A7138EBFAC6BD548A6F609815E
+:10449000EF9232163D1FFEFA3DBA6D5CEBDC571908
+:1044A00021DE25F91214E79AA8713B63C3628ED707
+:1044B0000DCF5F733C9A760EF14B1C724A2A1E6C2C
+:1044C000C58D2DBDD9EE89FEA367544A5FB2EF3387
+:1044D00092BBEC05CF41DCB70CE710A73CB519CE79
+:1044E000217A2EEEFB2E6305DF1EDA72741ECEF3E8
+:1044F00057758CECABC0337CDE5C9DC5E552FC4E41
+:104500008129619CE59A885E8FF69BAB9D99983FC7
+:104510003356C46D0ADBFB14A48B20EC65A184F731
+:104520009A9231FC9EC9D8DD8CFC44B570E6AAF5A0
+:104530008610A569F9510A1BEAA7F5B56BC6E3A574
+:1045400004D64F513F8C11EF03ED337F8572734CCE
+:10455000244A79B8D02FE647FB42E0B1C0CBF976C8
+:1045600079435892A07D3098A4F8A453AE8F01FCF3
+:104570005C9266BF05449DADE2725A86FF50CFE75C
+:1045800047EC727B9CE35E74C091F792EB15F9EEF9
+:1045900096DC2EE29B3A411D9433F9E529FDEA8031
+:1045A0000F655875AA7FC0AA7F46F88010889E2D97
+:1045B00078F02A25CADD3D2EFD2B4FA17EAED7789F
+:1045C0001E99B82F972DF0EE438719DA0D4C79C557
+:1045D000C47DDD11E6DFA53933751EF9A1D975D685
+:1045E0007D3A7E5F19CA18C6E9B2C5FCD6BDBA6C61
+:1045F00066BC590EF4906D26E95E9D6E7D57C164D0
+:1046000009CCC3D17D32E5D1E9BE08C9A79E051EFC
+:104610001DBFF3A1897B7A2E717F3CDB3C4DF7EB0C
+:10462000B287AD8FDFAFB3E0CECEAA7AB3DCB0CD28
+:10463000B31EE3DBB0F6D119EFD7D5713F29DBE428
+:104640007188B4F1E97EDD8EA965B6FB75340FFA89
+:104650007182FEAC7B764EB8CEF5ABC96CA74D0827
+:10466000DBED880BDDAF7385ECED775C203FEB1362
+:10467000DFAF137818D6CE610FBA2C3B7494CC7090
+:10468000FFCE34C8F41D91DC8F92911912C52548D4
+:10469000DF5B765E1E1FEABF9D9D9767E5F53BECED
+:1046A0003CCB7ECB9D6DC7B7D3EE735745A8CFC526
+:1046B000DA79BBF01F402F0F791D765E5366FA70D2
+:1046C000CA8B7C36B8FB4A18E768ED8F14CC57DBF1
+:1046D00095CBBF7FC486F9076FCDA07DF1F1EF1DAB
+:1046E000ED9AD2AFE2F76F7EB794919D64C511DC6D
+:1046F00002E65D45F27A0ABB773D44F8090A3C348C
+:10470000E107C86A0857F171C467A617F316F29B50
+:1047100018352AAC08D3BEE3670964BAB4155351FF
+:104720008FD72356D2F034C363FF4E40A39EEFD8F9
+:1047300047FB3E9F3B077F907F4F618E61DF77CBCA
+:104740004F427316E7BBBED24E0727A4C8A0025D36
+:104750009ECE2A15F6CFA08EFAB27BAD8BECC68723
+:1047600096946DBD12FDD5A0ACF3E3C8A171681F8E
+:10477000351F35BD68E76D8F4CF78E83F70F7528B1
+:1047800061340F9F5AB2E655ACC776BBC80E7AAA01
+:104790006F5EC18A34BEDBBC7BC1C2C5F8BEC345F7
+:1047A000FA7DC59EFB064A83D8DF559BFEBDA996C0
+:1047B0008DF7E9E8B7BD51EBCD68C75C9DC5ED92BB
+:1047C0008D5A92E24F1BE7690C5DAE8D25F5A3571C
+:1047D000A0FD708D96F13EF95D596E7E9FCFD52A72
+:1047E000A17C2F8C66BE1760B51B5BF35B3AC708D4
+:1047F000CE9619FA71AEEBE7C9587F08F655975275
+:10480000F49427E86963D1BD5B2B707D0399EF1D9C
+:104810005AE5DAAC719C4E23763E7715368DC67517
+:10482000BBDC91817A24AE4259C7B888CBDD1AB976
+:1048300019EDD1AB5D48E16C73C70F1B16E1BE8467
+:10484000255D8279826A6415D159308BA13E685802
+:10485000126945BC1482FEC3D05E61D12FE99CA2CF
+:10486000B04E635EA87B96F4245CF0DE5311BD0A63
+:10487000F1FED25AFE9D97C2A08FEE051546F8397B
+:104880005C61BB9BA1C9B0115C6017F90712C589B7
+:104890009C7C64ADAB792997E3BBD7FE7654A6EF39
+:1048A000CD546495115EBD867DDD1ED4BB30CE54E3
+:1048B000737009E1BBC6CDE2C4BF6EA2EF5DB52E39
+:1048C000826BD794935F41B87EF7FB2CDAEF6B993C
+:1048D00029215CF943FC9CD59A27BF6950E1F1700E
+:1048E000CE874EBEB3F8C109DFCED9F3E83C6E33B4
+:1048F0001B9C8FF88E9D95898E3617ADF1A6C74506
+:104900005B05FDC13E907C89E98CF65BF957B61ECC
+:10491000F361377E315289FCF1B697DF5BBD6FA939
+:1049200046EB7868AE46F1C687FCAD44F7A736BAC9
+:10493000C287101C555F88FBB9BBB8228CF1B6BF8B
+:10494000C3C3E734FF60F7A82F55223EBFF8872C7A
+:104950003ECE14D51AE76744EFB55E827386D2FE69
+:10496000B31568872E912753EEF4AA2524BF5C4225
+:104970008EBFBC24AF1EFD94C00DCB1997873C4E53
+:1049800011585BCDEF3338E47EA24EDD3D8376894E
+:10499000C77FEA85BC1B7BC3F47A5C67BDD00BA6DE
+:1049A0009AF9BB8CB9A27DE150044DB261F19F5CD4
+:1049B000A13FC6EE763C177A2177581C7CB0E266A0
+:1049C000903F5FCA1276E408719F5D4BE6113F9CF1
+:1049D000017EA0B874C949A2FF18C809B49BDF9032
+:1049E00092A11569E761D677E67E22E24111B39480
+:1049F000F284DF12F1A09F8AEFCEBD23E241C745CA
+:104A00003CE8E7221EF40F180FC2EF87792FA77D2D
+:104A10001B57F7513FC67176D62CF01830CE547D17
+:104A2000F02504F28BE6A04FE4DF13BC414B0FCD21
+:104A30003D7F9C2A8170B9312EC5E17C597C8FEE77
+:104A40001501D78080EB350197A507516E209DB1E8
+:104A5000B1AA9E491E06D55609CF7B515EF407497F
+:104A60005EF03CF1E01AC998305C4EC078A3D3EDFB
+:104A7000748BFE4E8DF2111D3BC77F348BDF3B7C68
+:104A800069EDACFD2C98268F220B5721DDE5C3FE86
+:104A9000A03C8A3671391EC57B176972D58AA7C1B9
+:104AA0008E8449EFDCC0F134927CB9905C2974C8E3
+:104AB00095DD2857A0BE1BE54A305DAEB4F6E3BADB
+:104AC000832857584A0F05239F4CAEFCCC5B668B5E
+:104AD0009358F2E56A6063B213C3A04FFD9F5E9FD7
+:104AE000BE2DE4C485F4AA95FF113019E9F53D986F
+:104AF0001782FECC7846F770147390F28972DB5DF2
+:104B00000CF341B66297D1E8CF2CA47C901DF33D05
+:104B10003AD2C5C3522284F8DC27F578F9BEE8FD05
+:104B2000682F6C9BC0E3243BFE788F17EDEC976EEB
+:104B30002F08E0394E6FAE9507A22FBE15EAA71ACF
+:104B400019D1C98A3D2B6C790F3FCFCA237CE4C6AB
+:104B500040FE003E1EBE9DEB1FDDE079205066CC7E
+:104B60000371FB443C488D85903EB649510FC561A9
+:104B70001A65D253BD619EBFD20B7E399E0FF636A9
+:104B8000EC9C83FA79C3AD32A37CF1CA9E7B50CEF4
+:104B9000744C5868205FBA4697BD89E6F8069FECCA
+:104BA0004DCF23C5E304AD9A9F1B8AD2CC01903729
+:104BB0007B4DE37CF74755E1F7617FF779F2E03B06
+:104BC0007343A3314ED0DBB83084F3F68E8A84F27F
+:104BD000283F650CD9031B476D5A8CF1A78EE51A47
+:104BE0004BB79386CD17B4DBD7569C516DE0F923B4
+:104BF0001D32F72F73C5F934F05525E22D7D9D0840
+:104C0000A76AF2FC115CAFC2D74BDF37CD6D00FF56
+:104C1000B08AAF1FFD57DDA78F46F9A136F0FC9192
+:104C2000CD7E7D31FA8D4E38ACF1AFCD966CFE91D4
+:104C30006EE52DD4AFE1E788453C6FA1D775FEBC8A
+:104C4000850E210F2DBF71247CB81CE7D4BD5E7B7F
+:104C50001CD082E74A513AE118295FE0D3CE7FA108
+:104C6000757FDEF38D9447B0265BB2DDAFC8B5F239
+:104C7000591AD784504E58F06CBE40FEC8A785AB79
+:104C8000B991B7FFBCD7FB3F6DDCFA6CAE1F814F0B
+:104C900007F01E65C7C499219443A978CCD0403948
+:104CA000DA73E23EA3953FE2D2F93F55957FE74E96
+:104CB000CE2EA2EF2CABD379FE08FD65C803D9C474
+:104CC000D86CF4775411BF71F2E985E077E68DDC9A
+:104CD000EC137E63D4319FC813618EBC1335C4F3CB
+:104CE0004BAC7C922E09D6174CE5838C38AF036F02
+:104CF000E385DC7FCFD17FD8BAC3FC7EA5957F3218
+:104D00002C8F64AABC1FB760581E89C847E9C935F3
+:104D1000E23C4F9CE795A0DAC478DEB03C92A9D380
+:104D200043F84DC96925A2DF0D8CBEBFDBE3E5F575
+:104D3000DE392C8EDF3BEBC53AF2532DA3BC9661D6
+:104D4000F92553D7109E341659C6CF77F879BF8509
+:104D500007677EC905E9ED027924419FF53D8A0880
+:104D6000CDD3E30FFFA48EE093E93CBEE04BC7C375
+:104D7000E9E35FE2E372B247E4E1F5E4DAF3F1EE8E
+:104D800013FB5221DA39F7572FE274DD55AF53DCAC
+:104D9000DDDDC0E395C3BE035163F7079CF1BC138F
+:104DA000425E5F68FDCEB8DEB611EE9B2DF0F13CA1
+:104DB000AE87961CA2BCD833AB40CF02BE1EC67CC9
+:104DC000969A8BCF67793D8BE7B3F41AF50B2F4595
+:104DD0003D16D518CAD35ECC6781F71B1A46C86743
+:104DE00011F1442B3E3A523E4BEEB9F3787B3E4BE9
+:104DF000EFAD3C9FA5B787CF638DD7DB504D76D6FF
+:104E000048E33E3DC6947DB8FF1517777E3AAD2442
+:104E1000F26798BFD253AAE90F1A482F9C9EBB1A7B
+:104E200035A2EF2E17F76363A3B9DFCCD4786821DE
+:104E3000B4D9E24F2CA278B2C8CBE815F7E7FF3E11
+:104E4000CBB0D9C79D8DDF0DA15D0F74F8B2CEF93F
+:104E500084C6C9574BD7830DC8DC7A8B893EE540A1
+:104E6000368F23B842C706EAD2E8748BD077881F02
+:104E700019F0932B9DC357542EA0E83EFDAD11F4BD
+:104E8000F946369FDFA243A64E0AF3F33F568172DE
+:104E9000C4F25F87B5F3F076C3E48F438EF4607E8F
+:104EA0001B562C797283254FEC7469C90FE6903339
+:104EB000E7E4C91C6EA79F9327203FF053674E3944
+:104EC000D4EBE5FAC282C78D8219E4C87BAEB02D5F
+:104ED0004EE3943B17E2A3CF5BEEBC949D2FEC0F07
+:104EE0002E7782481BC837D9D63922BFF77066EAB9
+:104EF00083240F3D2A5FB727C2E87702B08EF2DC29
+:104F000083E72819E57AB544F106712E922FBE3F4A
+:104F1000F8B02B4CF9690F033FA39F37C170DA67D4
+:104F2000E73F57709E273DBCF66BDC3F037CA3DF59
+:104F300075B172C892131F66F3759FA32F93C3694F
+:104F4000D1571A3DD3F7052CFAB5C6B5E898218399
+:104F5000169C875E055D63389AE2D431298E711004
+:104F60002B8FCC1AEF0D1FB74746BA5F65B5FB8E86
+:104F7000E5779D8B07EB019DF2C97AE8BE39EBE23C
+:104F8000F43787ED56D754513E81CA289F2052826C
+:104F9000FECC619FDD2FB6F2C1A69584432827364B
+:104FA000083BDDCA23B3F2D20EFB72AD73665B7EA3
+:104FB000DA8611EE67BF790E3F17FFFD13FC6EDB3B
+:104FC0006AAFF938CA45C09729BEE7447968D6B8B0
+:104FD000DF15787ADD633EE9FB0CF7275FCCB2E79B
+:104FE0005D75FA0C475C80E375A21EABA7FB785198
+:104FF0007EAFCA79AE3ED2FD57E7BDBD73F75FC540
+:10500000F97BB327FA32C1FF22CF7FD3C3D1839D6F
+:10501000ECF35BCF01AFF9131CBF53F0F7B420BF23
+:10502000B7F3BE27FA363EBF8E71BFDAB2730E6396
+:105030003BE8EF7F19A436D0CBA65A4EAF45958CEE
+:10504000BE3F3EBD95D7772CE5DF35ED7F9DDFFB7D
+:10505000D816E5DF33857E7D32E065C778AE0FF781
+:1050600057F17EFBF17E13F26905B7BBF2307AAFE0
+:10507000A0B88E5239BDA6C73B01DE1F582A535C2B
+:10508000748FE08B003329CEB1AD92CFB3AB427EAB
+:10509000427C8F66D12D50EF9CBD7232DE2FD92E0F
+:1050A000E229FB16AF7C02F3FA3E08940BBA4BD010
+:1050B000BDD79EE3B7517CE4A12579D24A58E3BE1F
+:1050C0008399F35BAAFCAAE817738B789228131ACA
+:1050D000965B4D91B7DACAC4F7D8631AC69F9E197A
+:1050E000E479ABDDAB9F393613F571A54C79665D7C
+:1050F0008347BD97E1BAEB785E4F919A90D2FD1746
+:10510000AFDFC5EDB49AA31EA36A78FB67068F12C2
+:10511000DD6D07BC2B69FE9F2CE0EC467F02FAEDAB
+:1051200075F50CCC84767BC7E5493123D56EB49FE9
+:10513000F35FF712597C879ED1771C3ACD531E94AA
+:105140009B9D78FE01EDBB6BACBCD41EBA97B577C6
+:10515000CEE4399827BEED061E2CED0A1F223FB97A
+:105160006736B7CBF64AD00EF6655F8B763DDD63CA
+:105170006AE571222833C6897A311118F12ACEEDF9
+:1051800028F505E6ED6CE81BC0798AEAF8F72D8A68
+:105190006A32F77F21E0A6FEFB5C318A7F8EB47F06
+:1051A000FFEAE3F8ECACE2E7058CC5292EB55BF825
+:1051B0005D4C8D1AE9DF096D0970FCEC743113E365
+:1051C00065BE3A8DF4BA1C36C80EF583FD88F1B879
+:1051D0006D526C31E687C42669EC71C288E91D877F
+:1051E000F1BB097961A4BF4D522284DF558E8DE356
+:1051F000F1EDA3919D74EFEA00D8D1140E6609D2A7
+:1052000053DDD13CBA0F7534523D48FD7D15BADBF4
+:10521000D22898374F1F8A646CD2659BB6A25DD3A3
+:105220003945D6316FB353AA8FE278B15C0FC5917F
+:105230005D53E6D1FEB946E549E9FAE8463FD70BAA
+:105240002727446EF4C3BA42534EE562DC727BED0D
+:105250002BFB70FF1EB9DF4374F448EDE0DD38CF5F
+:10526000FEB3571D8F125FF2F3BA476B4F97A2DD63
+:10527000B3ABE9542EE2AF18E373A00F8B2B781C6D
+:105280000D3520D9676A0FBB19F058DCA631234DC4
+:105290001F7B193FCFC33FDF64927BF4F7CCE0293B
+:1052A0004F0B8EB784252E0DD0730FC6B32C3953F8
+:1052B0005CC71205200FF7AF78278679728F4C2CC8
+:1052C000A07B9445E23D494E18AF448CD7FFC62BD6
+:1052D000EBB1DDA3D50506CA8BE281A179A8248AAA
+:1052E000AB4E539C2D64DDFF881AFB6F25FA94E9C1
+:1052F0003B95C5E177FE02D711F0F5919E83F61438
+:105300003773AEE3E309E67D88BF6F4AADAF8E0B1E
+:10531000A6FC31FA437EBC97DFCB2ECEFA87B94A82
+:105320005ABE6D89880B6C920667935DFA00B7C30D
+:10533000C7B238C9B9E2AAD8DD3CDF364AF9B6CEE1
+:1053400079B7FBCFE95789EE51E737897B25FC77A1
+:105350006C4AC4EFD838E93E14CAAFEAB82A55DF20
+:10536000173D45F4FFB466DC95E97B0FFB845CD800
+:1053700024FC316BFCB1B97C7CABFEA8CEE9F1E931
+:1053800097F3AEAF82F5FC555BD9248C7FEE18C144
+:105390008F5B19E0F4973D00160EE881FED75EF3AF
+:1053A000623ECBD3325B8572AABE2AE14956093CE4
+:1053B000C2F8E48BC1F807C2DFF6A05CFA6AA092DB
+:1053C000E05A3195C70D3AAB1EA473A090CEF50EEE
+:1053D000F227CA775F282661DC7B790DD30F8978A5
+:1053E0004B0CF04F77E76596CAEBDF9E4B7E0EF0D5
+:1053F0000ABF5783B94993C5EF4F94E339D1A6BB90
+:1054000045FEAC8CF8EE14F300DFD23C078AC438BA
+:10541000F771FB1FFD0BEC5F2EE629AFFBEED750BB
+:105420008F17E99C2E52F0F57908BE5699117C6AC7
+:10543000E255F443B74F2A30906E0E84C26F374165
+:105440007DF92295E2F1E5351C8E03AD32FD1E900B
+:10545000BF4E3B48F7C74CD01769F832C4BC45353E
+:105460000909CFB58C56BE2E68E745B96884011E80
+:10547000A81B625DE7E09FA411FC459E41CC2D3A3C
+:10548000878795381ED0EFCA3ADECF1FEADB8272DB
+:105490006C791D871BF43BC15314D60EA2BE2F0A94
+:1054A000F1F196037E0E4929B8B22DB8EA64CABF5D
+:1054B0002AAAD10EA21F9C2DE05B19E6F0F4BF7E54
+:1054C0006A40E2E319385EB680375BAC9F12760B18
+:1054D000847E80F19E7225EAF15ECEA929CC38C483
+:1054E00067A37896F57E572BE001F0E317F3B0DD64
+:1054F0006EE2275862EC6399FF7E889116B7A8D8B0
+:10550000ADD9EA7EB17FAC8B3F273F8E5422AFCB23
+:10551000C2AF5B5965EFC76AD2EA6578BF8CD3FB2F
+:10552000FA6BF979C78109DC3E42BFE31C7F239DFA
+:105530004F311EEB0AE27B8DF45D49BB7DDCE2D688
+:1055400082E9281F8A071E9E27C37A8AEE65B292D7
+:1055500043F42C9D937F30DFB7D724E8FE6CF640F0
+:10556000240FE55D496BDE74FCFE5BF64094EAD9DE
+:1055700003AD26CF3F0317260FF3F5D2E6294539B1
+:10558000CDF3E958ABD68772AD361D4E785FF27217
+:10559000CF5CECBFF9EE574623FF1638FA7B72B8A2
+:1055A000FF50FC32B40AE0FCA7D7627B2BBE938D80
+:1055B00010E751F93296C53E90C7509688FC3B4B98
+:1055C0005E744E786752D427E887F2F15822DDCE18
+:1055D0007796D07EBC681F93CEDBEE34B51B29DEF8
+:1055E0003410E0F1A680B0577B98B19FF47B0DCFCB
+:1055F000F7F0E173D01F7D3547A7D37EF6B130D2E7
+:105600007371DB9FDCE9F2FAE640A9B8079D20BA86
+:10561000D74AB2E87C0FF898BE6F7A406DA573D672
+:10562000BE227EAE7974CE2B12E2B3E8399EA76D0E
+:10563000D9CBD36B12217CDEF56AF432E2CF11ECC8
+:105640004FCBDE74AEE792FA07491E8C8D322F9E47
+:10565000AFF957AB94C75A1205B8AA502E00491794
+:1056600002FC35B1F548374694D78DD5A25C05E5E7
+:10567000D560DFAE1B28FFA52B35EED60AB06BD167
+:105680007E1ADCEDB901ED9556B0460CB4174F7992
+:10569000F07B2ADDADD3F311CFCF442CFB3221E1D7
+:1056A000F8453F35C95EACD5351DE33013DC89D1F3
+:1056B000E9E77407E6BC534DDF139B7F71F9642360
+:1056C000E91384454ED323FD554749BF3CE11F4FA5
+:1056D0007AC8D22B961EA11141BEDC22F8A8CB4875
+:1056E00078249257C0BB00E72D2847808EFD455C8B
+:1056F0009E831CE672CED2277773BD6FC9CF0A3165
+:10570000CE2D286FA15F77ED13B937A05C1172D64B
+:105710001F3266E2F95C8590AF4C8D4938DF8129F4
+:10572000FC7B9501873CAD68E5E3748518D113E8EF
+:10573000A1834837078A12744FFC40EB5129FD9E24
+:10574000A9A5EF02AD4986FB3FAE8ECBC17142AE3B
+:105750007EC76F70FAF470B97A4EEF0979BBD53C09
+:10576000CAC4776133E661FDBDD0E73D1587C82F18
+:10577000D876EB29C2A7150F0D89786877D55BF429
+:105780007E7B94DF03D8654E9F43F047966B947FF2
+:105790005A73744E19FA1B4DCB35B4EB4E060AAC56
+:1057A000F32FEF42B4275B5791FDEB13FBF85098B2
+:1057B00009BF53233FEBBEA5DF1EC0FE21F08B24A3
+:1057C000031BF579DC48E7F83D05C47774903AFB94
+:1057D0006A0CFA0E84731DDF0BF0EFD2FAA3C981B5
+:1057E00071B4AF325DE9F1D530F23B97835F87C387
+:1057F000EE56C3DE09F07E7793ACAF67A9FEFF2BB0
+:10580000C0F3D126FAF93D859D8B4F6FC138DFCEAD
+:10581000A5E23B670EF8EF6BECF328340FC60428C3
+:105820008F39E3F7F6ABFC59FCFB0B357D0368CFF2
+:1058300007AA385C2F060C8EF7418EC79E884C7CD9
+:10584000B46BB0DA8BFACE69373E92FDEE249ED768
+:1058500062D73717AA173BE4FE0477DF7524EFBE43
+:105860002993BC628CCB3B89C906FEAE464B80D3E4
+:10587000539590D71DAEC47ECC2BE878D6C7D61BE7
+:1058800029BA28126376B6CA197F3FED5040E1FB72
+:105890003F7CDFB9FD20F6FD4981870BED3F86593E
+:1058A000D09EEE8B6F1A7307CAF156EE3FF725DED6
+:1058B000A2BCA3A2D90BC9EF3972F052F2078AAA8F
+:1058C0004CDBEF6B668FE0B756E478CE1B0F1849C0
+:1058D0001EEF5BDD417EF6BEC1CCF7620A72785ED8
+:1058E0005A1FC84BFCBEC948F3EB399CFFFE292068
+:1058F000E86ECE3BF4BD8C343DFBB2D0B3A46F8BCD
+:10590000551653D2F21C2608FC39F52753E39E4B5B
+:105910006B88CE097FFBC4F9C543A64C78B7E81C59
+:10592000CF0F10AFB00E53D0219D6FF4B0B807F970
+:1059300026D6C4F33C9C704FF0CB17B5BE600EF773
+:1059400043CECD27FCF5897E0EF7CEDAFBE99E2308
+:10595000CC1742FA907EF01FA7E93ED4B32EFA3D51
+:10596000DB19CFBA1218D3BAF320FFBD45F9452F82
+:10597000C1F9CF87F9F7D5137E6E8FFD5AE7BF5770
+:10598000F455F760F717A03EF4ACC2C89E8C83E2D2
+:10599000027A3D2DE8953DC7EB2BBDBC7AE7C1FEF1
+:1059A0006538DEAAE7781EE69DCFDF76E317A07E96
+:1059B000DB808BEE0CDCF9F87A6D0CD46F8F4B7DAD
+:1059C00058FFCD7446BFF719CBD328CEF59BC060E6
+:1059D000C102C0F707EB3CCCB80CE3A48305F3018C
+:1059E0000F77C49F9E89FDEE784A0A23DBCE78F6B6
+:1059F000F15746035C777E43A2FCAFAF1CC9B6D912
+:105A000085A76129D3E0FD9A83FC77236F633D333B
+:105A1000111F773EDE4BBF7F68E1F3837595CC485D
+:105A2000FBDDB03BBFF134FD9EE15DDF92E8F71591
+:105A3000EF92F93DA27F7EDEBBE8311FAE6FBD76EF
+:105A4000A91FD7B559C376B7C55BBE8B294D77C49F
+:105A50000F6A33E1FD1D070E6A2BD12F73B366D495
+:105A60003F5F3972854DEE9CDEA7907FB026D7430D
+:105A7000F7EB99CF0CCD9B307C9F3F58C76C70DD06
+:105A800061C509D4B83637ADBD4BE7FEEF578E2858
+:105A9000B6792C3B20768CEB85D8DFFA297E6EED2B
+:105AA000DF1AE1775BFBB7C60AC4AB439333C1D3BC
+:105AB0008DFB01F0F4ACD3A9DCB92E44E5EE7506FC
+:105AC000EDD35EC423945D02EEC054568FDFE70F22
+:105AD000983CED38AFC9ACC7BB6579115E2F581241
+:105AE000253F64243BC62AF7BAA22DE84376EEE8A8
+:105AF0009FA582DDB3578BDE8D912FBDE3D5590D68
+:105B000050FF9B9CC8C61C92376103F9CEF2CFBFF1
+:105B10009EC3E5EEA6D11AE17BEFD2C98F2996FF8D
+:105B20008571BFA52B9F407B02FA6FCF21BE0DD39D
+:105B300077BA46EA5FB0ACCED6BF60D92AABFF1EBB
+:105B4000EAEF397FFFBDCBAEB1CFBFEC0EABFF2389
+:105B500004BFEFFCF017344FB5CFDFBC9AFA7FD506
+:105B6000CDF77728D743F9F41DDE70C245FE33A385
+:105B7000EF73A879971EA2EF279D8B330D9AA86724
+:105B80007D4FE556A31C4BD1D1F46FE23AFCC05DCA
+:105B9000E97494539765E3AB5C33CF56CF9F3DC612
+:105BA000D67E54A4CCF6BE70D1E50EBAF4E99407C3
+:105BB000CBB83E3531CE09706A63F8F79AEAC778F8
+:105BC000687DF7BFE8A5FAFDD7F0F5DD3FC6477C55
+:105BD0004CBA0BF6FD7E2D7A65BA7D0CEB9230E463
+:105BE000F58C1E1DC8A94D7F6EC8F83C4BE1BF6304
+:105BF00097E5E6FA7273E9E4C76269F8DC520CF4DF
+:105C000000F5B773345B9C6773F1CA504BDA3C9B69
+:105C10008AB54587AAF8F35BD08ED7237F87F37DBB
+:105C2000551BBA14ED57E73CEEB23ADB3C9E925559
+:105C3000344FD2318FBB6495631ECFA243E2B99833
+:105C4000E714D2C948F36C2EBBC6BE9E923B689E39
+:105C50005FE33CB569EB29B9C3314F165F0F3C17C1
+:105C6000F3FCE6BCEB299F6A5FCFD8D534CFBF3BAE
+:105C7000E6718F5DED98C747F3E0739C8715713F20
+:105C80004A730FADA4FDFF8197611C487347FF9ACB
+:105C90002EA9FCBD97E2C2D0CAC476FF07FE2263DC
+:105CA00096008000000000001F8B0800000000002C
+:105CB000000BE57D09785445B670DDBE4B7727DDD6
+:105CC0009DCEBE10C20D288B86D88190015CA6594E
+:105CD000E4A122065770810E4BF6A4A3E23C1C758A
+:105CE000D2104554D446518306A6C1A0E0800626B2
+:105CF0006880800DA883332E719EE3320B368804B2
+:105D000021260DA2E29BC5BFCEA9BAE97B3B1D604F
+:105D1000DECCFFBF79EF8FDF4C51B7EAD6AD3AFB4F
+:105D20003975AA9A0C4F22641C21FB12683986909F
+:105D30006FE33C17396D84FC007F3F26F4CF474862
+:105D40002A2FD3085940F85F60A9408A08A9B5B046
+:105D5000EAFC4D33721643D93629A3A490FE63A5FD
+:105D6000DD75BE4A4877DB24655E5E643CAD5CE071
+:105D7000978F8486B3777F2091EFF82692E175F4B0
+:105D8000FB65094E9C8F563F524FEB66420ED51372
+:105D90002C3B6532A7983E3F5C4F27304C3FDFC518
+:105DA000F8DE1189FE3385964D42C027D075ADF8D7
+:105DB000402643F0331F0EA7EBB8912F63813F9E1F
+:105DC000104B641E5E3371C37BE1EDE6C03A019E69
+:105DD000BA07983268D1984C8836DFC184FC69F7DD
+:105DE000D56F090EAC0E308D25E4E6655BDE846E62
+:105DF0001F092503EFA0EB9DD9BA421E40EBDD72CF
+:105E000068B6CBA61B67A67C08D66DA1FFC138B3C8
+:105E10003CB4AEFBFE2DE5C6FA6D448AD47309B9D5
+:105E2000D03998E3837F570DC880AF1BE99A322998
+:105E30000A6F837214343B115FB39DEC5D6D3EDEDF
+:105E40007B641284F948A15492072DA9D8CF03FD91
+:105E5000D4BEF39B2D5BDCC5149FB3EF16118ED11E
+:105E6000F30DED8E779BF269D9F8B54C069F7DFE58
+:105E7000731619DB898F7D4F83AB460737CD9CF0B6
+:105E8000E4611D7DCCF25CF1E461039C6618EAB725
+:105E9000D5CD32F49FB3A8C4D05EE2AB30B4CF5BB3
+:105EA00076BBA1BEC07FB7A17F59E362437B45E0CB
+:105EB00021437BD58615867A4DCB2A437F6FDB5AEB
+:105EC00043BB69F7886B088563C3EF4462A670FC27
+:105ED000C676E4B18B53A0945C00F7A3F51948D7BC
+:105EE000C7EA552C6B81F6C601FF8CB678289EBC9C
+:105EF00071E1529248C87DFE4B962DBB84D615DACF
+:105F00003E9E52BB7FE2325F3621CB9C2AD2BDD867
+:105F1000A8902025558124F5D27558D4B587CED2C6
+:105F2000DE2891E0E8BEED6228F6F31E213C348BBA
+:105F3000AEC3F7A999AC17FAF279842FC90092D1B0
+:105F40007F7B978994B7E8E4CE7AA709E793EA9C28
+:105F5000B8DE49E9A15A61FC5EBD35732271403D4E
+:105F600038B4CE7686EFB5D0C9A4C3388C5F2A0288
+:105F70000322FC8BF81B62E0FB61099E6627FD5E35
+:105F8000D71E7126CC8304F7E55C3712BEEF5E0F97
+:105F9000CF491B1D2493F277BDFBC9C3E713F24918
+:105FA000FD542C7F5F5FFCE46199903FD6CFC4FA2B
+:105FB000817A0F96A1FA722C0FD5D761FBE1FA45D1
+:105FC000583F52EFC3F268FD322C8FD5FBB1BDAB09
+:105FD000BE11EBDDF5012C353EA0F2684E31F069C3
+:105FE00071B109F8F40E2BE17FAC7E92AF41A4FFB2
+:105FF000EE40BE7665005F9FB47D3B348BD2DBC93B
+:106000004F2831E5F60FA768BAEB1F7F6E13E0AF9C
+:1060100034408927B96FBB358EE1C76A2253099591
+:106020003F0F9DAF10897E3FEEF50BD789B9F85C25
+:1060300002D2A18AC335C31E63FCF308E2EB6C787D
+:10604000D2FA1F79F6CF4573F3003F83914EE2F603
+:1060500089750C6FCFBB006F67839FC4F92B1A8EB5
+:10606000C2EB7FCA09D1FE5FA56AF0ECC821B4BCBF
+:10607000CE597C14E8E064AB19D775B23D3E406060
+:106080000C670AD245FF7063F3A8DA60F5EBE543CD
+:106090004D4BA2DF282F32FD7A797172FFF30EE0AB
+:1060A000FB3B3244FFE1D1401F6E4E1F8CEEB4F13A
+:1060B0006B5A72FD36C338C6FA49BF30B505E5BC28
+:1060C0009A70FDC8FEE779478682DF39B6614802DB
+:1060D0007CF758BDC50FDFE9AA77FAD97733FC7A88
+:1060E000BAAC5E14EF3F9C1C995F7FE3FEB3E747B9
+:1060F000482BF9DC4210F43F0CE9BF7FBFF8904E0B
+:1061000029C5401FEDF2B7A077E2866B7A47C2BA85
+:1061100036AEB745F4992F82E79B0CDFA3EFA94772
+:10612000343C0D3E13DE2572445B27959323A9EC86
+:10613000063AA5C48C78F6D01113E8783D926D9993
+:1061400040BF634E54B1DD0B1FA2F4546309291EF6
+:1061500015C1DD0176D6DCB11ADFAB37FD8192DCEB
+:1061600097BF91C9C3D0FE173A3A6D9779EB7C522D
+:10617000EC20F47B735BABA6819CFCF2D5ABB89DA5
+:10618000E22F82757F454C53814FBE22BF758CD65E
+:10619000D965D3131536BF654C3FFBE87FB03E6A27
+:1061A000A719F47559A3B15E4AAE4D037E285D2947
+:1061B00093009D7B05E87B6DDD94EF2F4B64765C4F
+:1061C00019A95B0A76CAC3329909F89EEB24D2005A
+:1061D0002A276A5E5B5D5442EB37249A90AE8E515B
+:1061E000FB4EA572A82289D931952901C54DDB3F07
+:1061F0006F1D7DE3C504DE0F2C05B9E6B313D77A16
+:10620000D217EEF39619E777B6F947CF979025386E
+:106210005F6D1EDAB8DA3CC40D823B10C39E9D97B9
+:106220002844EC645ADE9968B45F17415D67DFDE8D
+:1062300017555F1255D7E844E674624EF42C4A4C69
+:1062400005BA084F413B8D50FAC88BF45322FDEE3E
+:106250003B533F33F413B1DF9233F5B346C67B3083
+:1062600056BF9AD736BFEAA3F454F9CA530E42E593
+:10627000F997923FCD459F57AF7FC001703A2AF9F9
+:106280001C80EF2F03E2D458F0DADD0B2FB74D005E
+:106290003F02499BC2FDA547A6839DF4ED7AD9290B
+:1062A000D22EDE0DE6A099D26F6D6BC534928FF5BC
+:1062B00083ACFEE00911EA6D467C56BEF8549A6A3A
+:1062C000473C307B9B04D1EEA86DFE620AC8712F5B
+:1062D00009231D46BF07DF3F9D847C5FA224F46D28
+:1062E000A7F3443BD9CBF9CCDBFAC809D101E515BA
+:1062F0009DC067DE283A2AEFD52F21A598CEE795D5
+:10630000447BCA910B69F547E447200F34B89000ED
+:10631000B32B1A363E937F90CEABABF9370E214F9D
+:106320002F47183D9E6C99F7F31D6AFFF2A69BFB61
+:106330004591F702F89EDAC6EC20D2CECA6A39E857
+:1063400000BBB37AADECA2944AAA373FFFC2B3E0D8
+:10635000AF7D6A467FAD6AF39B1F8DA7F5AA2D72AC
+:10636000CA34B61C9B9016C18F97FE6FD1A8083E09
+:106370002A7FF9A6A28E64CFEF4D8AE0A56ACB1ED4
+:10638000858CEC0BC7492D7B94902D067E5A0E4EC2
+:1063900001BBA561E3770AF85F5FEE16487A6EDF0E
+:1063A000F7CBD7BE897A11E084F8E4F8EAC55F1F1D
+:1063B000BC05A7EF28C47E4E909767C39B9FCBE98F
+:1063C0009AD7EC2491CEA3FCF7E6C034C0E7CB7794
+:1063D0003A603D9D521DA3F3D50FA4B9E9F7CB65F3
+:1063E0005F9A134BF6BC7CCD5D487F65425D9A1386
+:1063F000F9C99D6942D9EDCB84752E68BA01D75988
+:106400004A3C4887E5ABC5E2002DBF91C8D42D3189
+:10641000F8A42889F149E73A8A5CBACE4EB0FBC1AC
+:10642000DEFEAD18588FFEE9ED04E4FF5D7CCD542F
+:106430005362FD1B0BC3972DC9A4F98B1603FD36C0
+:106440003FD801783A36D09D0EF3A470F071B809A8
+:106450003FD071C50F2E4F677822AA54C4DFA3FA2C
+:1064600060123C87FE1DB2DB9A6F788FCB4FF6FD32
+:1064700085FCFB74DE71A0DF3AD3A87D1F637D73BA
+:10648000617DA817A99ED3D1998EDF19FF373FC42C
+:10649000F85DE3FFC08CA9D07EEA43C647F01EE852
+:1064A000133AAF603AB6EFB95E40F96026C1587C46
+:1064B000DE2C733E37B67B29BF429C40A3133A7F44
+:1064C0004948D0D30BFD4E12E201FD95D295F47DE3
+:1064D000BD7D03DFC57E4AE4B94EAF9471B95090DB
+:1064E00044E5417C441E90A6D473B223AB65E2031D
+:1064F00093B3FA5333FAE3D59BE56258FFF14DFBB2
+:106500003EBA99D2F9F1168D6F8D72359A6FCBB76D
+:10651000AE17804EA3F9F67839D5E2B1F8963E8FE2
+:10652000C9B7E5A1FFA7725583DFAC24A33CA5F250
+:1065300071109810FDC1315A3E7E03F6566A5FF91C
+:1065400048FF3E24457DE950A33F8DEEA80537085E
+:10655000E47A2F7D6AF4D74B9F1AFD45AFD708BF69
+:10656000E8F6C1E023513A29DE4E2D3A8ACFEA7689
+:106570002160463EF7BD35A010E1E446F546FC6FCC
+:106580000D48D1D70351F596A8FEEEA87A71547F35
+:106590004F54BDCED0BFBA6D9F4210FF41433FF371
+:1065A000A2E7C8E731FC414DFF785B4F283EA08B46
+:1065B000ECB002724F5E424D3788AFED1231BED65D
+:1065C000A3861D49F4F90356E6A7F538793D91D520
+:1065D000C3A9CA52907BDAF3B095A07FDE531C7634
+:1065E00024EAFCFF83EDA243A5EDA10099AA8F2325
+:1065F00044E6D380F80E91FEDA59DCB027CE918FB5
+:10660000DF8BCB0900FD5D2EDA721681BFE7175DC7
+:10661000947CC8FCC5373908A5B39EF621D7CCA415
+:10662000CF17BC2D82B94DD1E3963229DDCCE3746E
+:106630007C94F89EBE84AE6F5E3BB3C3E72F8F4D54
+:10664000F795BC7FA96DA102F295DAD187F471D1DB
+:106650004AB21CE9AEBC29EA79FB55C81F9551FC2A
+:10666000E1E1FEC32E8D3F0A4801CA174298FFCBD5
+:10667000E5F2E562DE3533291E7AF68BC4AC823F43
+:106680002B92A5B0CE4D4200E205C4978A7C564BB2
+:10669000C2280F353875011F0DEB5F4E756DFB532A
+:1066A000D13D402FAFFE21FF395A76BDFAE9D09D8A
+:1066B000507FEDE39C3F90BEFD27EDFE7E36E8B3B4
+:1066C0009EDD668C8BF5ECFE55CE3D50DF61C6B885
+:1066D00058CF12B31BF8C0B7DB1E381FDA0732FFE2
+:1066E000A161D777F921D4AFF723DE8E2631FFE5FC
+:1066F00064FB9F0F082950D25581FDB03B1EF9C89D
+:10670000BBC38AFE7ACFAEEF8A3CB67FDE7A6A15CB
+:10671000E2417AB493995B817E1359FCD8BB73DC58
+:10672000F38BE9F76B5AF728F368FBA4D7FF9A0FAE
+:10673000F2B3672BB38BBAE5D01AE222E4EBA4B232
+:10674000876488F301336511F278F2862B7C79B186
+:10675000E0C2E0D043E100EBA2702907B9DF1F3CA3
+:10676000E29215A4F77F3D789C98CDE4DA8F08C4B7
+:1067700085227011DCECB93D601170FDECF9EEEF93
+:10678000F241EE1C6F598CF6CAD9D63D22F95F95BD
+:106790000EFEABEB1682E7B2EEA9FFB2F866F4FF8D
+:1067A0005E928AF38CE683BE74FEDA4FB0FEB2DDF1
+:1067B00085F33D47FE2FFFDF86F7AD14EF8EB3E381
+:1067C000FDC1FFB1787F9BE3DDEE34833CDBF55701
+:1067D0008CB36AEB3FDBBA5FF81FBA6ECD8EFF95C4
+:1067E00049FDB080F67F9BF83F1C4AE7D994BDEF86
+:1067F0008302DA3A5120C5B1EC938F92991F385138
+:1068000030A1FF471205EEFF31BF6900B723062C08
+:106810002C457B6340F6A3683710495D09FB77BFC1
+:10682000CA99E77A187B8CFAC40375E7A5BC6EF4A5
+:106830001F9F13885BA036E8809CABF683FD9A9D72
+:106840002DA27D4B4BB46BDF704C65CFAB1583DF56
+:106850007405D1D5E9BAA6A418FDA2C97CBCCBC9E0
+:10686000E00F0BE8FC2FB7C8CE0005D115133C1282
+:10687000ACE78A4C81F875FB4793A3FCA7ADD4C65F
+:10688000D4C7D7FE5EF85952989F395118BCB21838
+:10689000E03750C4F8E159E107C61EC2AB20F03022
+:1068A000D845928BC12FA9C685F157EE57C37633D1
+:1068B000D82B926D6907F0AD44A85FCCE68FFEB48B
+:1068C000E617F70767C2FD6C897F5283BB942DBA28
+:1068D000ADC6F1101E1A3EFE5E3C68F8FB47F1F1B2
+:1068E0007BC0C798083EB24F3925E0CF49DC1F98DE
+:1068F0007CAA43C47AB64BC2FD17EE0F4CB0254AB2
+:10690000E00F5C2A7D20025F9659B657C23E82C5D1
+:1069100025205D0FEB32A1BF63291410EEC31B25A8
+:10692000AC7F60728E01437BFAC5AF1DBF9B403CBC
+:10693000D9AD30C3BB98C5F3FFF2C30F9714415CC8
+:1069400085FD95D1FF5D4DFDB1F94D241847E1B4AA
+:1069500040223E487158401775C8100F36D6E1EFF7
+:10696000B2B4C83867EBDF9F1CF96797AF51B975B0
+:10697000E87C42B643C982FD92DE6FFE513B8397AD
+:10698000F71D12188CF106B758ACDB67FBF714261D
+:106990003F5EFBE3D6D1103F9BD09397C0E469A143
+:1069A00009E8D2CBFD8293444D807C8593ED431260
+:1069B000701F71BF68F7C488DB6CE4FEF42FEA3106
+:1069C000A84C7A9A895F04BF8984317EEB6BB6C488
+:1069D000DC0F9E9B62E274C3F146FFC422D8B7600D
+:1069E000DF5F405F4DD0E3AD6BDA97527E5F3CC016
+:1069F000DF21DDFECA3F0A5FF0DF01BE1BADA1292A
+:106A0000C531E4C7420EBFE97BBFC778E705ED6B30
+:106A10004D40BF17349B0CFB93D529DCEF1A45463C
+:106A2000C1BCA6EFB5DA0B012FFB459795AECFDBC6
+:106A30007E42F1C4D8E78A86278C0F71F49752D82A
+:106A4000BEC04EB9651EC075E75716E2A3F8DDAEAD
+:106A5000F8AB62CD33258DC9B905A4E5CEFCDC7F4A
+:106A60003DF84EE8B10527829FD94C785C239AFE09
+:106A700008D2F1C90D2400FA14FC52900B273711EB
+:106A8000D4E714248F825F4DF9FDC7FA38CDB0B634
+:106A90002DBF003BA0B65D709A687BAD1452201EDE
+:106AA000EB6D4B1441EF16A8C48DFBC39273E4F554
+:106AB0003ABE78294542F8EE1BBFF316F8EED75DD3
+:106AC0000A017BC4FD46D8017AFBEBF6D1C807FD6D
+:106AD000ADEB97F5A472B20CE33079184D0F799BAA
+:106AE000E20CF58B454F16F0D7747368A12B06FEA8
+:106AF000A6A5323A3B67F916F8FF4CBE7DA8C93708
+:106B00008F58ACE3A3945446F73AF9961E4BBEDD7A
+:106B100021A8E900F73B760D4907BCDEF1B69C1AC7
+:106B20004BBE6DAE67FB7FAF507E84B2A795CAB7F0
+:106B30008B74F2AD95CAB7DCBEEFFDED5CE55BE0B2
+:106B4000BF87FF36837C8BB1DE440E3F4DBEE5B779
+:106B50001F44F996DF6A22AACE7EB0A49E4DBE09DC
+:106B6000A9D7833DBC5F76C5C7A09FCDDCFE7E85DF
+:106B7000E7EDC17740CEFD5B2ADB2F3D5739979972
+:106B8000C6F8E4AC72EEBF09CE9A9CBB631B95734A
+:106B9000B9B1E890C9B93BB6533927003D323977CE
+:106BA000C72EC2E26F51F26D781FF946B07F6D902B
+:106BB000BDEF6DCB7DE6563ADE28B7ECB2D0FEA332
+:106BC00022F26E8C5EDEFD5BAA8470EE23EFF69FF0
+:106BD0009BBCDBC6E51D95638341BE46D387AB3DB9
+:106BE000CE50DF39AE73D32F815FDE15717FF10395
+:106BF00013DB077A6F5C6721D0D72A3E1F2FA7BF10
+:106C0000EE7A1F8E3FE90DB6BE9A4D2CFE5DDBCAB3
+:106C1000ECC3DA6631A0D27F4E19FFBD02F3AFD8C4
+:106C20002590745A9F61F63F6D0319FCA24CB85F22
+:106C300034AD40470FF3C756611CBFC1EA5847281F
+:106C40001FCF978805E2F555B6295F821D5C359602
+:106C5000C5F7ABF873C2F306B43CC8D2B6DBDF1A93
+:106C600040FAE60F4C37333C4E7F5E08ACCD85FCD6
+:106C700025637B5554FEE3637C9D33C410C285BC01
+:106C80002FC6CC63782C1A1EFB393CE8FA0DF008AD
+:106C90000831E141313AAD202DB2FE8A77434B21D4
+:106CA0009E5FB14AC07D5F0D1ED1EBD4E0A3C5A7A6
+:106CB000ABF8FBDEF6DB71DF3F7AFD1AFCFAAC5B6A
+:106CC0008367D4FAFDA97CDFAB808C867C1A4A0FDF
+:106CD000283F7CBFA670A0DF299E707EBA5E1E3F53
+:106CE000CDE130DA3F61522601B8913AA09FD2C679
+:106CF000DBDFCAA4EB1FF3893A0AD4E4C5E3CD1E57
+:106D0000D847DD680DA37CD3E8AB53A3773ECECE46
+:106D1000ACBA89E8AFB7094EB02FBC412BC2D14BFA
+:106D2000E9CC4ABBEC5BF5ED140E47A719F98AEBE9
+:106D30001D0A7713F8539A1EA27007BE19DD7E0252
+:106D4000F7730B4918F74B6A1B055790AEA3B68D26
+:106D5000C14B93B7F4CFA6C7470C7A9462D1238175
+:106D6000207151440F56F17ED3CDFE8F601F663ADD
+:106D7000A5F7B52482C7E1F43FC063349E34789E02
+:106D80008D3EBFE0F6C76680A30DE0156676549091
+:106D9000EA057BA4DD2BF90C709CF4EC69465FBB23
+:106DA0000415F6137AE104F44ADBC7B4337A05B864
+:106DB000A900F7F61211EAA514BEC9B97DD709FBDF
+:106DC000977AFEADD875908DBF5A709118F4ABAD1F
+:106DD000BB3FFAFD47E9B6338A6EDFB386DF190D94
+:106DE00074BB4B607184F644C3BEA3398DEDBB6F99
+:106DF000B452FA86FDAEB765D73AB52F9F9FE6F03D
+:106E000004FB5FD5C5A546C002602F708305F3CF94
+:106E1000701E83997DA997AF9BAD24F5FAC2FEC77A
+:106E200057B83FD09F7DA3D547C2F740EEB5D1EF0D
+:106E30000D8F7C2F5ABE6BFEFED9D6959CF68FAD7A
+:106E4000AB377F9374E0FE9339D1734F0AC67F58F6
+:106E50007ED28D3C3F89CE00ED2C5DBF8CD431FDC0
+:106E6000F7231916D4C377F2BCF8CB451BF1D175C3
+:106E70007CED96914EA996FEDD25209727523D4246
+:106E80008BAFDF19F3F1ADD82EE27ED435EF26D7E4
+:106E9000C03EDD35208CE8F36B0A04D4BF1FC06010
+:106EA000E3C08EB510B79993306D1FFBA3C4C0C368
+:106EB000B4BDA0D93F49A5FC346A43A0014AD7A478
+:106EC00070CA7B00BF092201F875B8932781FEBA0A
+:106ED000F30B5220AAA867719C51FB492AF41BEFBF
+:106EE0004E4577605CEBCA49101F9DB1CF66033AEF
+:106EF0001FDE64221E1DFD8E278106D8871F77D8CE
+:106F00007D1DF05F39B51720EE5CDEBEB6C101F520
+:106F100026C1A5D2F1BD3ECF14079DD7E6C61353B7
+:106F20002E043EA4FD60186F13EBE76D165C902AEB
+:106F30005BDABE02F3714A9B05E284FE018158D8F8
+:106F4000B8010B1D7773137D9FD6CBE07D18B7F981
+:106F5000C487D7019FBF23B2F737B17DEB52FA9EAA
+:106F60000AF4DA7C3B8E57D124900C3A5EF926263F
+:106F7000FFCBDF915DD0DEBA6715EAB169F47B998A
+:106F8000B920EF8393A14E460B4EB0B749F6CDC85A
+:106F9000D73D9CAF49D74C2637045EE77E836637E2
+:106FA000ED4D63F9C1A5AEC54A321DE7BDB1A9B922
+:106FB0009026E06D3B81FBD187299C3D14CE1FF0CC
+:106FC0007C8E7D633F57423AFDF359DA10A4C3F932
+:106FD0006D1330CF610129C63C87E9E398BDF6FE09
+:106FE000A5D68040E7F5BE1CCE86E7FB2E35A3FD77
+:106FF000DBBD59C6FDE2EE81218C4F7736C904F224
+:10700000351A9A44948B9D9B981E1757DF30251391
+:10701000E0B75E7081DCDCD7344901BDD61910F0D1
+:10702000FD49ABEF4A637E0C93879ADF56EAAC309A
+:10703000E88F68F9A6C9BF1A0E87683957A3E9997E
+:1070400028395703FBCD0E288DCFBDC4C6E41FD809
+:10705000FD80F7E0F748BFB5EFC804EC7EE1F3AE82
+:107060002998B7057A93B68F6B17DCB0CF5FFE898E
+:107070003980F66AA064CE4F417E7F6A26820A7903
+:10708000F014EE542E8C3587FFF8247DFEE50716AC
+:10709000C890A174528270D6F2450BD7B3FC96C249
+:1070A0000F56A695021C2627A39C2D6B14894727F3
+:1070B0002FBE14DCD7DDCCE4B173BD4E1E152AFE05
+:1070C00052D05FCE742607D5F532E48C906D5C3ECD
+:1070D000517BDA0D7643C5F615690AEDB794E7835F
+:1070E00054EC5A914645036900BD45FB57286CFC9A
+:1070F0008ADD8273AD6E7CED7D6D3C6D1C65BB7170
+:107100009C21BB78FD1CC7D1E6A17DBF3F7B7CECF9
+:107110007F9C5E29D0F1C6BE2F6292F2D8CFA70D18
+:10712000D1EF7768A5167F2DFAD044DC3AB88DFDF3
+:10713000631C71EBE8A2750CE56F8AB7ABDB983D79
+:10714000D43AE6A05253887527F0732D8FD3D64ECC
+:1071500066FB56AD051FDC0FFC3DAD50403A203EAE
+:107160008F929C8276900AF1F1B242F67E197D1FD1
+:10717000F8AE7515E3432A0F549017B54D2BA66052
+:10718000FF664185F15BD796A09E2F1F2B126C6F77
+:107190003E88764779DBC114E057CA9F2B41EFD672
+:1071A0005E6276027F687CA7F1F1FB32CB0F21167D
+:1071B000E74838075096A6C6E45FF11DC2FCD44DDF
+:1071C00032F29D772CE3CBF7378BC8CFFB2EBD690E
+:1071D0000AF061F77AA11F3EA67C5A18E153713577
+:1071E000CBD729DBC8FC957D4D4C3E74B6323B7144
+:1071F000D26AF96AA897BD2B1316F762F6E0B9F2C6
+:10720000731F3B65436C7EEE8F7FA7CB2D1FDD493F
+:10721000E777CDCB74FE6A045E932EBBDB8171FAF7
+:10722000CB66E17A3539542AB17CA6F9FEC52CDF4C
+:107230005762796F7FF7BCA2E6F1609A3D2247441E
+:10724000A0F7449627DD2C23BD47F3E33FCA47FF51
+:107250002CBEDEC6E9489B8FB88BBD0F7965410A0D
+:10726000C75F6D7A1EF35ABF7AE9E074C073D54EDA
+:107270004ABF74BDDD9BEC2408724B0AA0BEA96C0A
+:1072800015317F9C48C1A2EBEC7AFE64F94955AFF9
+:10729000D8916E2AB7B2BCD3CA573FCFC77C9125CD
+:1072A00061CCBBF2BDC4ED4D5F281FE8BB526279D3
+:1072B00052D1FC3E219DD99F5DDBE367C23A840D2C
+:1072C0007B70BFB5B2E52619E8AF577EA4CB5A3F15
+:1072D000DCC7F451FA857D7698DF8C91FAF92D465A
+:1072E0003C756D64FC5FD92607AC30BF0D6B319ED9
+:1072F000EDDD7002F3E327BDB219E308DE36D19865
+:1073000017B9410C9A317F533C6846BFC6989F58C5
+:10731000DB5A83FB6EB52D3CFF2F2A2FAEEA955D1D
+:10732000AFFA2868AA7EF9A203E4C1B18EF50E80F7
+:10733000271D0FF30A2F3B2519F2A3FACF07761B5F
+:10734000F30D5B1EE2F986577792FCBEF986C7E023
+:107350001FA06FD2A3F2353724F3FCEE6051718C7D
+:10736000787EEFB99FCDDFAC813CF9AEADC7D7C019
+:10737000FCABFFF6F51AC86F22BBADA8A7BC2FFD6A
+:107380000EF38AB5F716A7337AEBDEF822E66577B7
+:107390007F6A467FA77B57670EE4B7756FF93E0D8E
+:1073A000E2730B775D8EF1CB85DB26A59318F25E39
+:1073B0002B813E03E790171E8D8F7DADFB300FEBC9
+:1073C000AB4FCC28DF7AF3475B6A585EAECAF34610
+:1073D00037C5CEC3D7F21C6B5BAFBBE65290D7ADBF
+:1073E000CCBEEBCD7B3C5BBEE88714AF179D03FEA4
+:1073F00036F1BCE096AB63E68B7E05FFA078FA79A8
+:10740000BA315FF49BD6053F7F16DA5A93FBCD174E
+:107410000D9E03DCB43CFFEA74F74BE9C0475BE325
+:107420007D190C6F816902D881DFE4C0F988A372ED
+:1074300018F340C2BBCC4EC87BACDCF531F24BF745
+:10744000B60F30DE4A789E7D37E9FD63F9D0025FE2
+:1074500067B39DE59972F8431EAAEAC0E73CDF9442
+:10746000D1B19687DA5FFE69289D9F1FE6E70E6A15
+:10747000A8DFC4F2D42379A9C258C0D741435EAF74
+:10748000B6EEE8F19C5C8E46F2AA63E7F96A79846D
+:107490007DF1C5F48A9637DDBD96E75BD3E7D9A3C6
+:1074A000204F8EE9736F40F838167EB5BCEA3F4432
+:1074B000E1575B5F7F7CA1F1E7D9E6FD5F85CBBB40
+:1074C000E92C9EADC1A7EB2FB1E5F4B79CDFA9DF96
+:1074D000FA4DBACEBF9DC3FD560D6EDA7C97B6301D
+:1074E000BBA26B03F31FA2F99BAEC71D2BCF5ECAD5
+:1074F00060F66F6DDB9E7C90435D7BB773BA6374FF
+:107500005DBBE920CBD3A5723BA097DB84C591A3DB
+:10751000C773F0F1BCEDB1C7F36E3A1173BC63925F
+:10752000FB2698FFB10E66471D6B11A706628C7F84
+:107530009AEBA5DE75DB15CC97121D71684F2DB443
+:107540008FFD2421054A05F37E1A16F33CA1FB5C4E
+:107550001900E706FB9504E6F300C047177F909DEE
+:107560001E02769C9C515C28AA91F96AED4A8A8990
+:1075700004F4F89782D920DF0F1474CA30DE675103
+:107580007193CF24B2349DCEEB339FE05AACF66FAB
+:10759000776B75CFBDA221CE516B0E1F00FB9DBC3A
+:1075A0006EC5B8B5B8DBEAC3B8D91A2BAE73DFB66F
+:1075B000EF5E007875FFDC4CD83E02250C2A17CA16
+:1075C00078FCA273DB776BFE0C7626BC4CBF5FB6F3
+:1075D00086F607FB7A533CFA033D5B13F2D19E7C9F
+:1075E000FD9EE92037CA4087819DF74A7AA0818EA7
+:1075F000772495D58F6C1E88E709AAB6DA31DF703B
+:10760000DFB6D76A41FE77BF120FDBD1E42B39F426
+:1076100037A87B772690B52ADA81AA5EDF56104913
+:10762000D5DB79555037E4BF10F4D3311E47E9B9A3
+:10763000AA2D01CF8FE8FA717EF665B1F332C12C25
+:10764000E03B6A4F1ABEA3B55F9F31989FEF0DFFD5
+:1076500084DDAFC0FA7B957029ABFBB318DF766091
+:10766000FF128D5E797BDF7159FF3919830DFDB4EF
+:10767000F76BCDA42E161F546708FC7CEF5F87C5FF
+:10768000BACF22C6FCF1F95D02F199C00ED8620DA5
+:10769000405CA35A090E85FCF65715B63F52ED081B
+:1076A0000E85FCF69D5CFE55C7D13A7D9EC5E7016F
+:1076B000FDA14E2CA19701DF35AF5909E427D5BCB8
+:1076C0006E77039E6B5EFDEEC8738590CF168F714B
+:1076D000AB9AD7FF1DF15F630ECE06FA0F6F3193A1
+:1076E00075B47FD796B773C08EE89283394967D84F
+:1076F000F7A969311BF6B1B5751CAB0F9C07E7D72D
+:10770000B5738B95FDC88B5D19CC1E5D91E17E3CF8
+:1077100003F9DAE644790DE389304EDB10FDB9E672
+:107720004A35B61C6BCA900DE768C5C839C526181E
+:10773000F72B125A9A455152238471FFBC72C389A8
+:1077400091E00F7FF6B30B715FEB33253C12E4F64B
+:107750006739E1917A797CB4DEA24A32C625B0EC71
+:10776000597BA2348B40FEA075662CF9B439231ED8
+:10777000E751796F7CCCF3A03B38BDAD061A4C6560
+:10778000DF853884F6DDCF948002F3C8CB54B1BDD9
+:10779000323BA0C0F3AA0DDB8718EE9D90FCD88F7A
+:1077A000F217C2A382AC540A6D7DE54AC5229B2A1A
+:1077B000E1F968E93F7BE94D8CE009839C90A7C61D
+:1077C00071483513C641B5F300925C6C017829A469
+:1077D000D82989806A3FF2691C69C1D246CD11A6B9
+:1077E00087EA08E4151DE5FBB766497D1CE4877947
+:1077F000BF88F2FC6C70FB558603E76D96EA880B38
+:10780000ED8E694EB0AB059F87FC40E9A1A17EC318
+:1078100090C36CFFDF0DF9700EC2E6E770BEF53D58
+:10782000D80794CED0CFF65D46020DF47B92C2EA23
+:10783000642209C4DA8FEFE27820BE3D287F6C24F1
+:10784000F217A6F5789450F4BB097F1B0B7EAECDE2
+:1078500049826037C5DB48309E96B63CE9989E7FEA
+:107860001D84D507537206B9E6BCC4D81E4DD7C4D3
+:10787000259DEA958B22BE7F2AEAFD53677A5F83B6
+:1078800087D73224979D7F677089E36BF04D749D95
+:107890000E013CF21DAE06C0A3123E700FC023DFE6
+:1078A000C6FCC49446A2F7E38664327975BFC0F47F
+:1078B00025FD2BB6E9C6234E0BC64F1FE270EFED38
+:1078C000AFC555FAF4B74A00D73EFDADFDF58F8B35
+:1078D000DDDFDEDF7CE263CF27B19FF17DB1FBD737
+:1078E000BEFEF17B41151E32B9211193760E7A4806
+:1078F00026F85B0907D24A1855B07D8228BCC5011D
+:10790000FD517A883B4FF71CFE2F4F87BFC131F0E6
+:107910004F824877257C3EB46ECBA4F3BB994F775A
+:107920007233DBC7BC75218B23DD7C2F3B2F74F0BA
+:1079300067ECDCFEAD8DCCDFBE7511DB3723E5ECEB
+:107940001C9093FE07DFBB0D06A1F8BECD2F04826D
+:10795000B9700F4E94FDDA7BDFCE5D12F42F898A69
+:10796000C768F4A49D5B9AC7EDEB5C4E9F0B48D8AB
+:107970000E7C1F7D8EBE3583E5A55177CC0DEBBB0C
+:1079800085AF4FD303BE156438DC0B209AE25CB0A0
+:107990003F22F273ABC4A1B0BCE5EB930CF2E7E479
+:1079A000703501F41D79833FE7F711DD71859AAEDB
+:1079B0003FE7259D8EC7FB471A645706C845F9F473
+:1079C0005544A57CA19C1E4254DD39346ADF21B3A5
+:1079D000CB4E82711CC9594CCAC02E4CE4749672AD
+:1079E00065AF1DF63E85CB1D2B543C077B5326D33C
+:1079F0002F0F67152F00BA101D635D1E5B5FBCFA69
+:107A0000B6B1F535C0FA72FBCEBB4171B9D00EBD2F
+:107A1000925A1018EF7159603EA259FD5805FEFCAC
+:107A20008D4CC0FFEF0B0786CF93294901C87F9982
+:107A3000EF78F800D0EDF27A27EEA32DAB1F8EE59C
+:107A4000C3F51968872EAD7761A9C1C5E2F2BB45C0
+:107A50000A67CB796C3C8BD3C3EC0CAA8720FF421E
+:107A600072D605A16EC9AE2360FF5A7BE1E347F8E9
+:107A700028BD750FD6CD50A7A5DC380DE14BDF270B
+:107A8000651047CDF22C07F858D50B88AAA30B73C5
+:107A9000C62843BD0FDC34FAD8CCE0F7A8C0E823F1
+:107AA0001A7E8FCA1D2AEC3F3F7A45EFBD36083F4C
+:107AB0006AEE33F8FD9AEDCFF50B3F6712DAB3F3B8
+:107AC0008B96CE6EA08F1EE1FB900FD68F45783D32
+:107AD00004795DC3C03F70632902FC281D99F37CC3
+:107AE00044A4EF9B553667B3ADD86D2A64B40BF050
+:107AF000136D0C9EE68C3ADC8FB3D818BC449B0FF8
+:107B0000E122DB18BC441BA33785D72580DF687CC6
+:107B10001F9F53F8B5668E013C8C37C04B4999784E
+:107B20006EF05B45E147E791C2F92B1A0E29704EC2
+:107B3000212FC257FDD9754FD1F5831E7F86C2070D
+:107B4000CAD47EFCC7D42C2647534C757B6480472F
+:107B500012E1FAC547B28B084B5584BF0C1F51A1E7
+:107B60002EB0799066235E45A71475EF9BFA0CD072
+:107B7000C1CAB76513EC938A8BAE329C271567BADE
+:107B8000135584A74700FDFC48BD8AF85B01781CAB
+:107B900006FA91F9630F707C3E087C82F865FCF16F
+:107BA00028E797C7399F34B8D8F989E553595E5605
+:107BB0004A8189DF871624FABCA744570B51E8BCD9
+:107BC000D0C656B10CA29DF18939703E7D2F3E8FF3
+:107BD000B8814E123FB93B806B25C599601725725D
+:107BE000FB975CA226CEC283B44189F9215414A22A
+:107BF0005FD3618A750F56836BAF05E2A6FDCD6733
+:107C0000CF8C57912E4B2FC2F46092EC299EB580F9
+:107C1000D66D8DF1181F8C77798A1E003E6FB423C4
+:107C20009DDAE8FCCB74788FEF07AFCF665D61CA51
+:107C3000A2742882D146F1FB44E3102BC0F929B984
+:107C40003813E4EB535CCF521CA8FA7DA82E2E27E4
+:107C50001D851718FCD995B21BDF735E6294032B48
+:107C6000B9DC4D9A6CA4774DEE7ED42B773DA930CC
+:107C70009FB4D393911F53AE8D2D7F1B64C507F71F
+:107C80000A348C64FCEE2B51D0FE8B210F30AE7D7C
+:107C9000D233741DC8538DBE9610267F7C24CE85AA
+:107CA000FA88DFA3A3D9C7CBE0BE412E67A114CFCA
+:107CB00053906ED26E35617EDE727E5FD66394BE67
+:107CC000A0F453FA82F2D22CB69FB1C4320AEF6DFF
+:107CD0006BB099505E489F9A0336B057F78C734249
+:107CE0001C41925D1D6E8807DAA5967504FA155A37
+:107CF000E03E0921B1D00974F0AD7DFEA033E5E18D
+:107D000051740A4047CE946272280F770FF05CB32B
+:107D1000ECBC96405CF199943A2BC02D2F8BF95D09
+:107D20008D254508470ADF8959A99171D2675ED927
+:107D30007BDF160CFB4C3FE7A3A767713B3ADB47A1
+:107D4000CED3F17BA3C0ED30D54786EBF87EC9F9E1
+:107D50005308EC2BF5E5F77EE4D97A26CFEE1762CF
+:107D6000CB33CDFED4E4991C2527B472E9A0A986B3
+:107D7000F35D4A8A0B68174A9F89A248F25DF4E8CE
+:107D80002D890887790007927165AF5FFBE3C160B9
+:107D90005716C5A4B7683936BF57AFBBD3004F4796
+:107DA00065357D16D0D3DBFDE9757729D2A17F80BB
+:107DB0000A7A69CF1357615CE7F0137615E450D95E
+:107DC000E987503F949E1E876579E315A8CF8527E4
+:107DD000AF2E027AE86CBA3CFF5388F3F8EDA8B7EF
+:107DE0003B1B270DC5FD487FBC0AF91D9D8DB4BD09
+:107DF00030D20EF9E2A22E5F8040F45D77FE9B1434
+:107E0000AA68976AF79E51BFCE311EE242AB453C4D
+:107E1000D754FAA4DD0DF6677FF457DA143B1E0041
+:107E2000BA16E2AEF483C3C18EDEE3181F0ED27120
+:107E3000E7AF63FB080D8AFB4810ECA627ACB80F30
+:107E4000D99014FB5E900559972F0739B020CBFDD0
+:107E500014E2C9C6EE29ED9F1FD8F78FC02633EC78
+:107E6000633DCBEF47913C8E19867D36B68F758486
+:107E7000C75988A59FF638DEAEF6D3EE60F922C466
+:107E800019BB5DF333E2237E460BACA3A6F1F8D217
+:107E90004F115EDCCFE0F33E2AB3791F7DC11C5841
+:107EA0001283FE8FF2FC940A81C157E383A3BDF6CF
+:107EB0009107EFC389A65361DD8867C6D171BFDE24
+:107EC0002FA3DEA8A6F48574B56E1CE6C70B4F8CF5
+:107ED0007B1CF2864FBD23627BE5692BB677DDE71D
+:107EE0007A06F29EC2EFCA04E4D3A9FD9727B03800
+:107EF00091318E7DDB0026170E71F9507AFA11A4AC
+:107F0000DF5E3AF12F5080FF4A4F3FC6E87B838007
+:107F1000F756125FF5BB13CEE3F4391EDEAFB87A25
+:107F200009C0FB123FEE9394AD37BBC01E88C6F369
+:107F3000A12CD510F7280B2DC77109B5BF5274FBC2
+:107F4000E947799E71D969765F2171FA4806F00395
+:107F5000974F113A36DE43DB658D1DA73FC9ED9F74
+:107F6000D2D3171BFC8CC8FA2EC3E7A55CFF9785FC
+:107F7000C6613DB29E67C6C55A4F641D9760FFAE8D
+:107F8000C4D8DFCFE4703E525F4EDC54BE952BACBC
+:107F90005FA9FF2E05E44E69536292A05B575963B7
+:107FA0009521CFA3ACA94499AB1B378287A5EF4E8F
+:107FB000902278C87C6EF1D54B6C601714CB03808F
+:107FC0009FD65514FD5485F1987CFA52F6E780BC93
+:107FD000EE6CBCD311EBDC44E68028FC3472FC5020
+:107FE000BBBA50871F0D2FD1EF1F595B56F4538832
+:107FF00047AF62B790F42F7FA2F0961B1B6EA37A57
+:10800000E1361CF38DCE0EB70B0D79457DE0C6F140
+:10801000ABC1457B4EEDA80B078C81EF11767EA797
+:1080200091E1FF6CF08A7C97E37F42EC75CCEC5DCC
+:10803000C722E2A38C3AFFACEBB887F82C675887CD
+:10804000867FF28201FF339F5B8B7CA8E17BFEDEA3
+:108050005548BFF3293FC27E7FA7FF2E47ACFCA245
+:1080600099FDE1FD3C1FC92BFABF87F72F655F0E15
+:10807000E495F95658D11F39BAEE911C3D9C17640E
+:108080004DB80DF0429A53CF497FF826BAF6837F58
+:10809000E97B42C678DA962C4F19BC5FCEFDF0FB27
+:1080A00013A70C8D651F3C50BF7F04C4E91AEA3B3F
+:1080B000B094B97D49C0BECC457BC91DEB7EAF6590
+:1080C00003985C79A0BE83C53D2D3EE2D49F272650
+:1080D000CC7EFA4FC2E235DA7B8AEC7142FC54E185
+:1080E000E79D65C9B32CB710E21E29053E1DFC961D
+:1080F0000E60E7919667EC75C2B962331D1FE239D5
+:10810000966CE9A4719F93D50B844F45C86F965325
+:108110005A08C643F3E8731DBC95940E437C3A1A83
+:108120000E92C581FB4D1261F69CB67EFA04F5D223
+:10813000835C2FADE471CDA7EB5B30EEBF24DE8115
+:10814000FA6FE92013F3A72C12DE57634E64FD95F6
+:1081500004366F2BC4BD45D0AB41ACDBE1461F11EB
+:10816000AF4613A09E485401EAC924B814EF4999B8
+:1081700010FA093C7765780280C76F333B0E081010
+:10818000C72EF60C03FDDB28FA0A54DAFFE762B8C3
+:1081900000FAE5D0A64F92583908F2A13DBA7D2DDC
+:1081A000764FA8AA8F0B46D7072D92A2F67BFE32F8
+:1081B0004CDFBE22C3FD0ACCA3C1CAEE194AF95C4A
+:1081C000C0FD9C062BBB6FA8C17E6302E8F15F0F68
+:1081D00060763BD201D0D17E66CF9C94D4842416A5
+:1081E0002755DF30C4F92DEA1BBAEF48DCDF6BA658
+:1081F0007429E9F655CE93DC26A09BF3FDF4B97EF5
+:108200009E31E2714936BC9637E67E8E363FC8DB3A
+:1082100007388AA7A7A0BF164D0F3B7BE3CC3E11C2
+:10822000F0394BBBBF58BA9FD51389F687FED7A745
+:10823000BDF6E8FDACCEF739BD73D93E66434902C1
+:10824000E6C769F398D5FE6007D8A9B3DA33E7C16A
+:10825000FED62CDBD02FA0DC2987F7C6831D7897AC
+:1082600080E74A6EFEDD1B723C2DB77DB80ECF3322
+:108270007FC1E5E96C12C67BE13DC4C9F7D903F8BB
+:108280007C2E71F17A8B0C7EFDADC1C00D57D3DA17
+:108290006D6F04AE06B36DF6FEF09B20063C2DCE4E
+:1082A00029B887A0BDD7E67A8BD5D97BBDEB972CB3
+:1082B000B89EC87A2DB87E6D7D74A608FF5EF8F072
+:1082C000FB9A34788873E9BA29BDCC4AB8F14A726E
+:1082D00006BB7C966DF8176CD384CD271A3EA7A0F9
+:1082E00089DA8F5D03DC249BE2EF0F03DC0294D577
+:1082F00096708E3418F944867AADE81904A9CF5FD8
+:108300000DF40C4B053874249F93FC3C6065FC7F96
+:1083100000E819F2BC4EA7E0BAB47BE8F7DDDD69EE
+:1083200007BB73E9B68FF19EE51A31F4E84D180FDB
+:1083300015D16F3AD93AEC8CE7CF0E409C8AEABF50
+:1083400081D9DA394BB6CE3912E39339ADF1988F32
+:108350003F679168B8477ACE2296CF47A48EFCEB50
+:108360000DF6FAFDFD8E03F182E871E62D9A443E8A
+:108370001F0DFBB4CE09183F58C3E86BDE64B70885
+:10838000F9CEE39709B8DF3AEEB0DA16A2F57981B3
+:108390004417B0E7BCBBFF6308DC7350DBC1E2816C
+:1083A000E9E2ED05F7419C652FD3E350BF1DE8C41A
+:1083B000E6566DBAFD822EB9AE00EEFBF3DD6673B4
+:1083C00003FF975CEFFE14EFF3E5F10A4DAFBED665
+:1083D000588279B225B7AA6301FF252D5637961624
+:1083E00022C551395622110B94E90A91AC50C6119D
+:1083F0000B94454BD8BDDDA58D33D03E708C2D56EA
+:10840000E03EDE92F617BF81F7CBA4E01E763F0573
+:10841000834F49FBDBDF035E17B88B319FF1C20D41
+:108420008AC10F1CD962AC5FD466AC17048DF5D13C
+:10843000FB8DF5F5D904E968AEE5BA3C80D7DE5D81
+:1084400066AA8B20FFCF8CF92E8704861FDF462B70
+:10845000CAC34955ED45E0071F7FD96E023F7AE751
+:108460005F7F89FBE1E1CDF104F2ACF6FC3E8EC406
+:1084700041BEE22BD675D05E457107F1CBAA57AC51
+:108480006BC10F7FF502CD8F0FE4C37A5EFD1BCB6E
+:10849000AF096F3407607FFCF8F6175F86FDB4E321
+:1084A0001B07A07D7548F099E2E0FB5FB2F8678892
+:1084B000DF1717E2F7C5556D30FAC5776433391306
+:1084C0005A7271422CBB492B876724E74DA673EB88
+:1084D00079C83C07E240C31A8D70D1FA8D08189F05
+:1084E000DFC3C71F4F94089DE6429E40A0C101FA1A
+:1084F000F7F9D8F7242FE1FCF3D24BBDEF89FC9EAE
+:1085000038A2EACE4D45E437593800F23700FE83F1
+:1085100023CFAB886E3E3AFB642A1FFF6B0BCB6701
+:108520004EE1F7F71FABDF8F7ABFD7EEAB77BB27F4
+:10853000EBEAA58D7BD24AC07F6ADA93365707AF44
+:10854000EA8DFBD26EC1BC270922B8A47AD60B8F64
+:1085500041BCA27AA3D802F38476805B57CB9B0EF2
+:10856000E847EDE151100789D8A397BB27EBF8F84E
+:10857000EFA55B8DDFAAB9FDF2DAD88E2990A75E50
+:10858000D528B8A05B55CB0DD75D0DF06E62E75CCA
+:108590008B24522C52FEAADE72C35523216F66F53E
+:1085A0001817CC870E713D3CAFDA7402CF333C1CF8
+:1085B000F5BB075AB9239BD985B47FD044FB3F7CD8
+:1085C000A3AD1CE4171DF70DA8EF1DBE0EEF5771EC
+:1085D0001C65FB0FF4F927266AB71C9DE87BEF1694
+:1085E000FAEA71D2F2D1D510576A34D223A56F01BD
+:1085F000ECB2F07AC1B50E9F2E29BA164C6EF76216
+:10860000CCF7A5ED73629DB7AE0818C789C6FB47C6
+:108610007CBEF46FB89E7EA2FB254FF3613E79F5D8
+:10862000222A0F757182EAC37EBC5F32FA3B444F47
+:10863000D7CC9E202AC8C3CD2C6F86FE0996229ED9
+:10864000A73B84D5F15E45A0534A28551790C92A07
+:10865000C0FB5A3215CAF12057E03EFDB12DF9D0CA
+:108660007F87107AE1391CCF8E72BCCB19C47B2670
+:10867000B3F839D32E95D57B789C536BAF6CB7622A
+:108680009ECDF1AF1494B38B5BF6611E7DD7CB56B4
+:108690009389CA83E35B9227423E66570BBBA7F8D8
+:1086A000584BF244E50C7A3B5A6E68FAF420FC937E
+:1086B000EADD3F67BBBFCD063D753FCB574D4FAEA3
+:1086C0002B88F5FB17DA7B294A5D01F831E1DB6C79
+:1086D000AE7508275FAE8471F00C17E40995086C3D
+:1086E000DCB841C5E240DADF4EFB423C3A69BF8864
+:1086F000BFD7F0B9E8FA897308DE278F76D0FC423D
+:108700000FDE4F49EE677995F324129428BDCD030F
+:108710007D948F7594CBF39A04CC2B9BBFDCB81E51
+:10872000B82757AF472B4880DD6FA18F230E867C7B
+:1087300017AA6FE05E4B0BCBBFA86C36BE574582C5
+:10874000389FEA4D3F9863C1EB1BA2ADCB9D0DEB6B
+:1087500012AEB5E0BCEE7C2A81EDF728C40DFA34E8
+:10876000FC941DE57B15F1E0783773BDEEBDBBC40D
+:108770003D1FE4F0A279EEF9C970DE96E93F74F985
+:1087800090BFD9BD5B5593497020BB7783805EADA8
+:108790006A178223A16E213EC728F61CEE1F807542
+:1087A000EBCFD794133F7EAFBCC9F89C7CC8F05A7E
+:1087B000CDCF3192665DFB60B0CF183CAA37990DE2
+:1087C000719DF19B049F1DCFBB061AD2E8FC6A8FF6
+:1087D000525941204FF507B3617CC8E719837A9F4E
+:1087E0005829DE9EEA95EB8111B1F2FC0F70383EFC
+:1087F00075436926F0EBE360B76671408F45B9C5F4
+:10880000E3072468A1DF891BDD5BC7F6A225AC3E28
+:108810007DF50BD31B2FA17E9EECC17DA17962F16A
+:108820005B701EECC5419E6B013FF34CEE1C09F9D9
+:10883000D63D14E3A18B181C9E195537A22E861D18
+:10884000A8E1F969A12508FBB2BEEDCCFEB21786FE
+:1088500065BD7EAD1EC8E451C2DE109E9B086F133D
+:10886000F09CE52AE1209E475C75854AC0BFCFA0F9
+:10887000780279BC4A20F7C37D5C85AD336E7F13E7
+:10888000F05C18E7829FBBA8699D20D6D870FDCC0C
+:108890004E8BAF5B0BFB39E973868F023AA7EB9ED9
+:1088A000732D7D7EFB4015BF97696378CF58E2CB6F
+:1088B00085DF814AD85B7CFB9BC08723E3F09C6CFF
+:1088C0003A85953D09CB65607F6590C502F47BCA0A
+:1088D000C1C64F35897366407D14AB27DD2BB8D7F1
+:1088E00021F1ADC0F1D3CD642ACC139E831D6981E3
+:1088F000B802B607187E27D515C078E9435899A263
+:1089000004B3619C777AF1ED41BF6221D7630BB765
+:108910004C48073FEF9D2EEA7053B9F54E86660F1F
+:10892000056DF8FB50E70D67FDB95FB8B0809D3766
+:1089300048C931F6EB91DD09A3418E7EC0ECF853B6
+:108940003637C6A72F5662C7B39E1BC8EC16EF6911
+:108950008104747AC03BF35BB42BBDA725C3F3AE8F
+:108960007A8B21CFB9BA7C2F9EBBAF211D98875D32
+:10897000D3126FC8DBBD382EF67735FAF69E16890E
+:108980002FE67715E3F3D3C9C4971CAB5F9AF1398F
+:108990005D87A1DEF65DEF3AE039191B72803F3842
+:1089A0008DDBB53D01934FBE2882976E67C8A077D7
+:1089B000BA5556EFE1FB715ABB367EF74C859F2BBB
+:1089C00062F72A037C7CC30879B6FD04C6A3ABDB3F
+:1089D000F74C61BFEFC5E8420F279F4E7EA4357468
+:1089E000044D94B77F3BF0E86379232889EDD5F8EF
+:1089F000F8D8636ECAB769A2C9C0D7F185BD7C8EAD
+:108A0000E2E52993C8E5C2F1C7265FA2AFB3FE91A4
+:108A1000F7BBA64FA6B67D611E7BFF8F03BF7A6FA3
+:108A2000C97911B944D791536CD7D52D51751BAD68
+:108A30008FD4D59D51ED2951ED1951F56CD6BFCB91
+:108A40001ECC115D84740E3C315D1A07FBD8C1D970
+:108A500070A3C0F286AFA74FA6F59AC20ECC9FA90D
+:108A60006D175CB8ADAFE5C7BB989D657385F0F732
+:108A7000ECE20B3BDE023950DD2638054AEFB696B4
+:108A80002D9857530DEFA9BAF75A98DF59DD721098
+:108A9000DFEB77FCE126E4E787871FC27EDAFED1B1
+:108AA0004DA4F7F73A4E0F043CB674323D1CB57F27
+:108AB000D49DE9DE87F230EAFCAB17C6B545E85E27
+:108AC000EBFF8791EDBF8361E2179E582CD1FE7FAB
+:108AD000AAE91C03F612DC710972FF69213002F465
+:108AE000F3B3C43302F4D16D35E7EF31D17E07E43F
+:108AF000D06AB8AA61688EF51A89CAE903F6D0402F
+:108B000081CA92E16B92AF01781E480DE10D0D3FD5
+:108B10005B93C2DA078606C2BE6B5ECE8F59FDFC40
+:108B2000D06AA85FBFE602561F191A28D2F707FBC2
+:108B30002EBC06E0BFDE199B6F07E63079AECD6F25
+:108B400066813B2307ECCD6AA62FE0F8A585CAC550
+:108B5000D995C736AFA77098FDD3789457EBBBAEC5
+:108B6000BBB218D7EF2B863C3776C53BD767289723
+:108B700025B4033241872545F061CFE95051DE5FCE
+:108B800050B705F47EFAEC3C94F7A7B2DDF53963F3
+:108B900022E59F87B0B23E879DF748174D986F90AA
+:108BA0007E8F1DEDA0C7F97E12E51BC4AF8DE36378
+:108BB000540E937FA372989F9435F0F27A58CFCDDC
+:108BC000DC3E5DF95060A395C2FFF740242918DF11
+:108BD000467BF796B5546E24403E853B13E4C12D89
+:108BE00010FFCD8BD435FB7D6501ADDB227EDACA6B
+:108BF00019EE4C7D1ED0CAB5AC5D93372B73D9FBF3
+:108C00009ADE496F60F0497F7CC43A5847BC44F013
+:108C1000FCC5829943D72D46FD7D2DAE9BB8DD99CD
+:108C2000E07F1FAE186C02BB52C3CFA202F7345CC8
+:108C30008FC8F2D5353C69DFAFE7EB9E2752FD4F79
+:108C4000D7593FC883EBA7F6403E4B2E60F6403D18
+:108C500004625323F02552680C3CFF5F04A7DBA19C
+:108C6000FD1F85530C79F133E857B388CA0B934E37
+:108C70005E70F83D2D04E5F442DDFD25F439F88100
+:108C8000370DF43C90A3DBC7997D4F0DDA7FDABC3A
+:108C9000E2FFFDB5A93791BE7C166D9F1DF8BD653D
+:108CA00039C6019516948B07AE24AEC5203FF8BE99
+:108CB000AC665F16FDB4EA1DF0A34EE688F89E553B
+:108CC000C3AB50BCA594C2E921AA56E13CBA6F06D9
+:108CD000CBEFD1F4E64A7EEFEECABB2FC43CBF1EF9
+:108CE00012C2DF65F38D2528FF7ADB670DC5768A12
+:108CF0006F9F15F8BD220E7F77606501C173362B1B
+:108D0000675D80ED3BB5B8D22C0B7E67E50C464F16
+:108D10002B2B581E26E811805B7FF490D6C0E21BF7
+:108D20004472E7EBF301DEE5F88B2F0C6DFB18ECDA
+:108D3000CAE556B42B4177E2FE883F1DBF47F1BA22
+:108D40000DE599E6473D99C9EE9B252EF4CF1FB45A
+:108D5000BB4B505EDD17AFC2FC9BAC64996514B889
+:108D600023E47E947B7C3EC4FF0CE679CCE1F6DA0A
+:108D700067E527ED600FBCC1E50D100CF8CB73095A
+:108D80006B9F7B6FFC41F06FE6DECBEE9B25CB2E1D
+:108D9000771BF73BE85CD3203ECEFF1AC376808377
+:108DA00007DE73C0F8FF6987FB4C3CF7B2F3BDC424
+:108DB00047DFD7E5437F0CFC0B717691CD9FD4C77D
+:108DC000ABB1EE05FD98CB773A7FB7FE7BDA77A2A1
+:108DD000C7A5FEDD2740A714EE41380716BE4FE4B5
+:108DE000BFD76A9C6F8A127ED44ADB67D78B894BC8
+:108DF000283C3D8BECB85E6DBE73D2C397B2DF8565
+:108E0000358E7F24BEB608E2E19A3F42EE35FA6322
+:108E10001097E8AD8B98278D7E4D9FE7DC9F8DF6F0
+:108E20000309F99B59DFAFF79C862A44CD9FD39560
+:108E30002A4880370FCF5F5094F06CBC572A6ADE07
+:108E40001A3C9541260E774617D1F05606717A885E
+:108E500082778A121A08E37A1699114ED1E36BFAD7
+:108E6000F1192BF1811FD9280848AF8D77C7A3BE10
+:108E7000231686676F659C0AF4FBAC12C63C27DF9D
+:108E80000EF6FBA03DD6F0AB28B7CE63F1869EF779
+:108E9000C4B5D0AF3B95D17DF77699F31B61F74C04
+:108EA000BC27AEC376818DDBBD381EF3A7E07CA85E
+:108EB00002E7367D7FAE87F88BE6E77FFE2ABB6F41
+:108EC000017ED747EF27C3B9DAF25111F981F7C70D
+:108ED00000BFB7C5F33892A702BF774B1C813C8D0A
+:108EE0005A938079BFB59517E03913C2EF79AEE692
+:108EF00053AB35517F7154440ED49A0E0D057FABA0
+:108F0000DAB21CEF7FA6ED6F809F063FC3DBFB3B11
+:108F10001FB97DF150BBFCF85FF1DC7BAB913EAA41
+:108F2000237484E7E72AF574951BA117B4C7418E13
+:108F30004C26786EDFCEEBF1533B0210C7F1F2B84E
+:108F400046EA5E76AFADBDB085405CD57B94D92353
+:108F5000E3DBD7EE03FF38716A077864B43F8BCB4D
+:108F6000459F2F1AD7BE4204BF4FB363747EE78874
+:108F70006B47EA4B761E17FC58F85E081E01FF4847
+:108F80004CFF3DCDF51FD59328AF17F887A19E0460
+:108F90003D06724EF38341EE819C7971D0C45B072C
+:108FA000A5C27D86136F1AC4F66946A0DDEF3BB7F4
+:108FB000FD28AD1FF8C3678E9731B8855725303926
+:108FC000023F100A71E4DFC86B1FC6F949ECBEC648
+:108FD000D5B92897B5384E358F6395F2B84F298F9C
+:108FE000FB40DC559F170B714D7DBD9ACB851AF860
+:108FF000BD29BC4FC01CC98B8578CF6412B4433BDC
+:10900000C47D1CECFC9DFE7D2F094C9290CE7F30E0
+:109010001BEECD5AC9D63B87E37D9595C57BC6DF50
+:10902000BB5664412CB6DE8451EEDC070A23F77789
+:109030007DC1F1A4C1256ED0C412807B9CC8EE3FD7
+:109040000F3FC07E0FFB30D5DF5B783CE45A1B9EA0
+:109050003F769F07790B9233E7DA18BFEBFAF00EF1
+:109060002BDEE3EFE7F2487B3E6510CBF7C5381106
+:10907000C07D713CDAE114CCF940474583357D4A27
+:10908000F2213E7590E77FD6DE68F3C078211E3767
+:109090005F3D88E98DD583D8EF3F68F55EBF8FD3FC
+:1090A0008BB6CF05F11A7D7CBBB9B73F8BAF68FAA1
+:1090B000F7E98AB8B5ECBE778D6E4D78BE323EAF1B
+:1090C000588138D30E2E474AB83FBF033670419EB1
+:1090D000B4F0B8B4E49C0DBF1BB4E3681EE653A61D
+:1090E000284CBEECB8398E407EDFFE632F3DF21E69
+:1090F0006D3F7954C1FBF2E6F378EC0EB8171EE42D
+:10910000E53633C619AB15664F56EF1EC9EC18C5C8
+:10911000B30AF2BE7D5B658C7B553B021B5FC0F6DC
+:109120004C17C52C9C176576F0F678F67E5CE01738
+:109130002F835FBA3BDDE5A3FD176578F6021F6557
+:1091400099D504A2EDBB0A91F3A48702CC6E3E042C
+:109150008207BED36EE7BF33E0CE5C40C7F9FCA107
+:10916000745C0F95B7685F7DFE9819F7D59EEEFD8C
+:109170002E8B8F1E928BF13E9943DB0A5CD4F32435
+:109180003DC54A10E2DFDEC799BD37CFA4AE01F876
+:1091900090DDF12E83BFFA5819BB5FA2F2DEE967BA
+:1091A000DAE706F9AE8FFF7693700EFAABE5835BD4
+:1091B00020DFB4BB7D848B6D6765E0264A2DDF7FA1
+:1091C0003E2C33F88677C948CFE73A3ED045EFEFDB
+:1091D000E089047FDF4DBFDF16BD4FD1B7CEF0E889
+:1091E000DD91CEED3A63FB75D99E53C06FB54F7CD0
+:1091F0007760910ADF0BA33C247E166F3F2CBB6780
+:1092000003DD264E0E1AF2B86C2AF70FCCDCFE23D3
+:109210004145CF875A7BD14412735FE7FF002E3F51
+:10922000E0290080000000001F8B08000000000003
+:10923000000BC57D0B7854D5B5F03E73CEBC92992A
+:1092400064663209931739790792C01043448B3A08
+:10925000090103469D002A5A8BC31B943C046D638D
+:109260004B9B814408881A2E01010127084AAFD878
+:10927000062F20D64807448AADDE3F3EDA8B7A2F90
+:109280005F508A6805225A7EDAABF55F6BED7D92FE
+:10929000394322D8DBDB3F7CB0D967BFD65E6BEDAC
+:1092A000B5D65E7BED9D5855622C91317B37F385A9
+:1092B0008A18FB067F6EE84F635503953336C5CC9D
+:1092C0009218BB96F19F8CD350DFC6984D55191B51
+:1092D0000DDF4F874DB3209FB1246C9A2BD200A491
+:1092E000278D2C6C298574A33DB42D135BFA18F6D9
+:1092F00033770CFC179ACE95598BA504BFABFB7B3B
+:10930000DC8C9DDAEBF4AE82EFECAB6F6456C6D822
+:109310000C26EA9959ABC5C5D88B2D52D802F566F3
+:109320006C306FB3427F65CB7CB21DF2BD5B24EF26
+:1093300036A837A3A53C6F23E4EFDD53EC95A16974
+:109340001C8E83F990332443FD6B1BC7B18FAE6233
+:109350006C96396452E03B7B4E623B18F5DF82FD30
+:109360002F8446C92597E261DE063363163EF76F08
+:10937000F09F50443E0BFAEDEC9019CC97ED84EF42
+:1093800005FDDF172AE183521C63B59D51EDD9DF3E
+:10939000CC7DF5105016243CBB4DEC1EBF8D263DF8
+:1093A000A4A698B13FE27F93198BC9F05FAD121D5F
+:1093B00072864CB6C3BC2BF8BC7A774B84D75AD68E
+:1093C0006062D84F7B0263D7448C6B61E158484F91
+:1093D000C9412A9F6B5E4369B59A4974BB97F5985A
+:1093E0005836F6DB6BF2170FCE07D597E1839B0556
+:1093F0001F2C3CCDC2D7C1780B97B070ED089EDA18
+:10940000219DABB0601CE0752EE0205EA431251CD0
+:10941000AF6A413F5E1684F479C4A71A8167C463BA
+:109420006479FDFE6FCC91F92126C6ACAE7E3A037D
+:10943000A108AE21E31A4635009CD72E09C90CE6D7
+:109440009792EEBB3107BEC796F2F9D61FB358D438
+:109450009198F7B32CA8F7655AF90BB930DF7A85E4
+:10946000F93AA13C16F0D201DFB7585910FB7F2A18
+:1094700097CFD763E2FC6B54FC6C940DE9D21D3698
+:10948000205D129903F951C3E7163BB42BC1761244
+:10949000B5EB6B6F612D3111ED2B7E65650CD6CB75
+:1094A0008597EC213354654A20C309FD257D60660C
+:1094B000AB207FF657F6F9D8DF59239BD609F5DDA7
+:1094C000326BE8247E594EF4F919D23511B9A9222C
+:1094D0009521EF4B93529907CB97D178B54EE0AFDA
+:1094E00001E8DB579ED97D3BE72BB3BA0DC6BBE045
+:1094F000ECF921E6011E1684FC0F91CE88973DE31E
+:1095000046FD04BED7FB6D5E8EFDC028E457B3FC5C
+:10951000C0ED16E0AF09F292DE87601EB5E936872E
+:10952000199A5466FCE71FEE84FC277B8CCC8C7464
+:10953000DE316E1ACBBA140E2D5D10327ED813B107
+:109540005EEEDBA9CFD776EAF3F54CF9B047E3033B
+:1095500040C116D5EE3E5548B2C3FB0DF0B7D9DC7D
+:1095600070BA03E035BF6CF62E85CF8BD4C0365C65
+:109570004F7586DE23886773C667230280978A8CBF
+:10958000AF8EA422FE7FCABC08F7056BF90CA2C7F8
+:1095900046AB1A8C905FF582FFDB87565379FB262A
+:1095A000B32AF1F2EAD120B7E6D312A62A1603E0D5
+:1095B000BF7EC3C44FA411546E417AB4039F52BB03
+:1095C00017A4D05268377FC3BC6A06E56758C864E1
+:1095D00001783ED1F02C774DB0C07FDB5D55C35094
+:1095E000BE285F2B7EA4FF0AECEA9A7E7CFDBA6F50
+:1095F0007D5ADA4E025E6E62128BC7793B03BFC69C
+:1096000079D65A7A4CE5D0CF0D5F7F4972795EE307
+:10961000ABD927AF4279E39B41F486F9A11C99F7B6
+:10962000D041FA2E4DB6107CA7D26D21337C7F75C8
+:10963000A399E79D26CA9FDA22517E5EA714B264E1
+:1096400062FD8B09E528BFB7181D6676299EA2F139
+:10965000F2F1E6FF886300F2C78C55E1FA628E866C
+:1096600038BF1DCB1AE2261723BE6EFC04E5D7BC1B
+:109670002DB2378C72FA15BB3797617EFCB0393644
+:109680006CFF454239E26FEB78874CDF653FCA21BA
+:10969000A6F8BA6F80EFCAD6AB555C2F87B770B803
+:1096A000E7392DCF209D6FF85A26FE570C2CB0DBE2
+:1096B0008674F00DC375A76EDE3101F1FB714D8A22
+:1096C00081EA3F2F3107E2C3D99884DFE7498A1F37
+:1096D000D7D9FC0D0BAA595C3FDE57A932AD9BF2DE
+:1096E0008C25493D36E2FBDB51DFD56E013EC7F1EB
+:1096F00027BFFF873BDDFD7C2F4DDE70CBB5D8FF4C
+:10970000B346E22FAD9FFACD370BFE602C0C789A52
+:1097100027F064CE589287E35F6E3DCC5BD690E72E
+:10972000B05D7E5DF4ADF7CD7C7D489912C955964C
+:10973000E6223D33D87AD4F493ADC040F2DEE26540
+:10974000BE1D900E31339F04F22B2F53213CE46554
+:109750009AA89EF297453BDF04F8F7A981F84CF8E8
+:109760009EC17CA350CFA8BD8E8A78E8CD860C52CE
+:109770008A7098433B48CE411EF0B43E913DB32AD7
+:1097800002CE2CEC6F34AD574F26F47BF6BDAF8E76
+:10979000201EEB867E3602F576FDC52F4D2AD0D3EE
+:1097A000D625919CB579FD0CF9A3BEAB86CD2EEAEA
+:1097B000978FF55E2EBFA3E7559B69E4EBCCDD4B9D
+:1097C000FDDC9CC5D75DBB93AFCF4D8D3121947B24
+:1097D0009BDC212B021D5B1A6428DF6F2995BD08D5
+:1097E000B666A7F82D9C5E16DFAB4C467EF5CA5ECA
+:1097F00014F1DDBE8F5A1220FF66E978AF0C799B19
+:10980000EFE9D62C9CB7D728CAB38338EF37C69672
+:1098100093BD728B4FA671D9FCB810AA8A6EDF3B3C
+:10982000EED930EEADCCB7F624D0B10A9437D2B130
+:109830001BC7067A9D7104C6225EB4F9DCEC9DB8A4
+:10984000F664A49DE1E3F6007CE27AAC74603C949B
+:10985000A8E51548A71BAEE774F8F4797368198C6E
+:10986000FFA915F44C84BEF8D4CEF5CED44CAEC7C7
+:1098700018EB1C8A72BF2FAF0C33E0BA7FC0C1F166
+:10988000E136750EC5F5F62749DFCFBDAD320B8148
+:109890009C59D02AB11080F8E9CF5F1C8AF2F79367
+:1098A0001D2F0E9D19015F743B2D9DAE8DD7F68443
+:1098B000CF02E3CD64DA78E1341C6FA6D77C02E5F1
+:1098C000076B1DEFEB89B01F484246D4671B7C2411
+:1098D000BFCFC16A44BED3DA9D9B1FE3433BF31C59
+:1098E000B38424186A66971C36637F3E5F8E1BE83C
+:1098F0005DA7B58FEA7F03F20FC025ED97C276A86A
+:109900001F5BD44BF27681C57F24158A16201DA1DA
+:10991000FE44A4A384FCEA33E1BC1589CBF3330EE7
+:10992000FF834887396D7A3A66663AB87C77B8899A
+:10993000EEA63A9B82FA22A999713BF0414308F5C1
+:10994000B53B266E04033BC694E2B1A19CBA212F1D
+:10995000A6C5108FDF8786B07E7A4A01B50B567098
+:10996000FE0E26B150B3845D364864073A7A9802F9
+:10997000DFD3C630C72A944599DC4EF430EF069900
+:10998000ECC44E09ED440D0F9A7C47BE41B9F7A9CE
+:109990006421BE91BA24B2FB6443E774EC77303E95
+:1099A000DA12C5475BFEC97CF4ECA07C1450898FA9
+:1099B0003C9681F908F64DDFA93E0BFA15C0D71089
+:1099C00081AFC7857CE97DD04274831F09E75B2D99
+:1099D000FAABB6D8C2F20892139FF5C96FE86733A5
+:1099E000D89FB84F4946FB19D2D4E6192AB7DFBB36
+:1099F0007B24E82FF66A0BE9BD470CDD9968E70F79
+:109A000019DEB01BF963C8F4A29266B24FD29C284B
+:109A1000F751D6E0FCEB1AC7F9B91D00FD221FD59E
+:109A200098683F51F750B99FDB0155B43EEA575B48
+:109A300055D467E3BA3297227FD42F01FB08E5EFB4
+:109A4000FE8E8D73215F37D5E6453BC56A995284FA
+:109A5000ED58AB7E9DAD943AC92E0E4E645E94DBFC
+:109A6000E74286A07124CAD99EAD3F413DBEA0C841
+:109A70001B5471BD09BECC61A417DA9DBE6417E00A
+:109A800075DFDF64DA17B58F823CA42F0B7AB6D767
+:109A9000F8929D909FB9DA4A786FEFE0E5E7EC80A5
+:109AA00020E83F45E6FDB1780BD73397CA030BE2B8
+:109AB0003D690CD37E36603E45CBB73D41768CB6D2
+:109AC000DEDB33393CF6227F265ABE017574770CF3
+:109AD000F04F926CD0364541B4BB63714C9EF7E1B8
+:109AE00070EB0C00480A66BF5E53393632CFEBF795
+:109AF000B77F6472651AE9D7BE72041BF4AE96F79D
+:109B000059018E15F6FE7205EC49CB7E49B4BF763D
+:109B1000F2F81C98BF24C60F9AD6F800DEC7AD4CE9
+:109B2000375E247C4A54FF4615F7F5A27E70A47F69
+:109B30003C545857A2B56F6EF301FC8F1BF5FD1115
+:109B40004A457BCC68E3FD2EE7776B568FEDD7FF58
+:109B5000600F38B346F7DB012BDEAF6E1B0963C520
+:109B60003ABE30A17ED5F479BD5B223B237ABDA6F7
+:109B700066717F05D8B5A95911F66E35DABB32D9B1
+:109B8000B9137069D52FF133B42FC16EC8C0F1CEAF
+:109B9000BEF7D9A983F0BD7DF2A764E7D75F54C8AB
+:109BA000FEA807FB03ED764B17B767D97E23E95D67
+:109BB0008DEEF70AF9D3EE04BD8F7CFA8A341AF9D8
+:109BC00094B186A1B7010D9AB37CC3100E6D3F16F8
+:109BD0000D6F4516B7CBEB0B2A36E661FFDB25860A
+:109BE0007A7F55C18749689FD4779D489A13D16E73
+:109BF000C1FE758487053B8D03CEBF228BDB9B7531
+:109C00002FEDF5E17AFF3424D15A9EAF8456A25D40
+:109C1000397FBE012D35561A9A7127AE7B36CDC4D9
+:109C200072617E05C2AEA9DF3925782DEEDBE0AF8B
+:109C3000049F36F9E7D2FADE34CD62639908E7CCA7
+:109C4000FB090F8E181FE261554145328E53573381
+:109C5000C181FE937AB0B3B0BCEEA1BBC89FD267FE
+:109C600007EF3756A1FD5506F6D6BF01DCE9AE4930
+:109C7000555E588FA9F2EE518B21BF7E10F9FB5E25
+:109C800036A7678BE40FDE8AEBFE2589ED50FBCB10
+:109C900033F673BBEEAE2C6E076ADFEFCA52A8DD57
+:109CA000D860F738E4BD034A4F2CDABFF5CCF7395A
+:109CB000EE3B99DFA6EE203A71B9E36E52C9AF646C
+:109CC00071F73C3212CBC72AB49F604ACF5A1CF7B7
+:109CD000EC4AB7771513FC8BF9878A4228478F66C1
+:109CE00005E621FF94093BF2EC4B378E9A59D46F6D
+:109CF00027ADECB08696011E56DAD57FA942F9F65B
+:109D00001785E41BB3F4768F437AFCD545FDAEB4DA
+:109D1000865622FD836B8C54BE3B25B008F9E67451
+:109D20004D551EEE83992D985703FC6474B731B4DA
+:109D30001760FB407E068BDBCF54C88F0BCE5024C0
+:109D400094F351F6C738F4F3D0BE010687EF1542FD
+:109D50006CE502179CB2D01268F926A1DF1E39FA11
+:109D6000D554053F6A768AC11258804D2BA7C5305D
+:109D700019F97E79EF1103CC27D6DD4D766C6DA7EE
+:109D800044E3D416BC6042BFC97D9D7C5DD68B7D0B
+:109D900000E06F28DA038F64C58AFD670BF55BCF9F
+:109DA000BA691FCD76717A3206F5EC91FB89A5541C
+:109DB0004FEBCFB48CFBBD6A853F067AA4F2F56207
+:109DC000BD6BFE095898C23EE0E3AE97BA7D32E221
+:109DD0007594E48DE41B2D7D3E8BEBF7F843BD13AA
+:109DE00070FDF6027FA15F66A35473FF6B30BF8DD9
+:109DF000A3877BD184F2003BC925F81D5811F05E82
+:109E0000BAFFF309C8376070D37AADDB5F2ED7DABB
+:109E1000486FD3FE71486C4307960FB9A780F46A68
+:109E2000CC55EC9EC9F0FD05B1CE926DDCCFE55965
+:109E300016CC5C5484E3FBEF7F0DC72F8E213FE5EA
+:109E400010A08DDD45692BFA853C6CA984F5D6C53B
+:109E5000F1FE130DF23D3545247729EFF24ABE6D30
+:109E600090766539A97FD87755219CF89DF663C017
+:109E700019B89F453F17F633249BA76793C30A0A77
+:109E8000884DAC67EB0EE4CFFD6607E2A97AFF6F61
+:109E90008EA1BEACB6B04E19ED95283B6349FA943D
+:109EA000D7903FCF9D39B5F561F8B6EEB67DDE00AF
+:109EB000D1456F3F44EF17B66195E4C1EDBD0FFA90
+:109EC000E8C9EDBDBEFC3FDCDEE3767D7047ACBA91
+:109ED00023429ED78B7DDAB9F9E7E350CF7CDC07CC
+:109EE0000FE8E9B27E7B65E6F6D813B8AEFAECFE71
+:109EF00028BBE1E833B141A4FFF94E2BF9E914B4D2
+:109F00007B009E33F6DE1F2272DC26BF4FC2FDC3EC
+:109F10006EA37719F4577FEFA7BF30C0BA533AC08A
+:109F2000EE89477B5F8D2739FBBACC76A05DA6F81A
+:109F30001CE8F7D0E0579C133CA8B75BC4FC179A09
+:109F4000C279640799D87CCAC785F3D0EE7959E8FD
+:109F50009D85319087EF8D9EC0D748B714339757B2
+:109F6000D80EBF77087BAB0350E240BC1C837D77E3
+:109F7000A6D0DFB8FF79343DB48AFC3816A2E74793
+:109F800007CCDBD0CFF35181216CE27E09F263A9CB
+:109F9000AD0A4B86FAEA316B48E5FE2E8B01F4FFE1
+:109FA000ACC7EF7B03F715B30E703FD6AC7B97DCE5
+:109FB00082FB8F8F264F30A1BC99C302E4779EC7E6
+:109FC000B81F7A010B717F35731870BCFB406C6C45
+:109FD00042511304EC5F0D9F2583847685DA027964
+:109FE000329A7D6D5530EECC1603ED4B66B5EAFD29
+:109FF000E91756DD5F857A7C458B81DB8FAD12E9F1
+:10A00000F159CCE741BB43C36B617602C983608BD6
+:10A01000C187E38CCBE67A054814A2F989B4C52838
+:10A02000FCF0028EA5CC10C6D420F1748543A91A89
+:10A03000483F6BFDB5181B2CE80FEB4D37901FF810
+:10A0400082C9378DFCA8AE3C867EC4167B436B1557
+:10A050002FA73573C1DAEBA7F2EB146EF031D5857B
+:10A06000F23233DB40FD45CF774E9B3E1F7D3EB144
+:10A0700020A4CFCF6281FCE46CF41BE9BF67667358
+:10A080003D706155A63807F0D239408B517D3B13A6
+:10A09000E5D54A85E4E5D2348E2F433A4FB39C95FB
+:10A0A000D3887F9D605F10BC1CFEACEBDC12EACD58
+:10A0B0001627E7CBFF29DCD1F0DE949DC7F18B4654
+:10A0C0001E8CD7B2520A717C71B8AFD47FB1305BAD
+:10A0D000BFEFECCBFFE3F79D9C1F57CA62BD394829
+:10A0E0000ECD74F0397D24799F09E3771BD80700E2
+:10A0F000F7AC957209DA29E3A6D8681E7507ACE4B7
+:10A100006FAD5DD23314D7515D454F5EC3007845C6
+:10A1100068154D7E41BD996ED827E0BA6DD59F5325
+:10A1200081A66591E74E53D27C4BB313713FF2D1B8
+:10A13000EEDF20BD775B493FC1FF0E9A517EBD9493
+:10A140004976535E5A606536EAF598F0D66733D1A2
+:10A150004EE176526D97B903EDC0992D11E75EF887
+:10A16000CF6AFD39186B75917F83B5EBBFCFDF1CCC
+:10A17000D5EE927331AEEFD79B02C3D0BEBBE17A6E
+:10A180005F32CAD5330B0C0CE93B4BF6CE45397226
+:10A19000C6AAB7BFCFD839BD76666BF2DD9B877490
+:10A1A000EECB5F42676F1ED27996810522FBA945EF
+:10A1B0003A037D170A3A9FD97B751ED2F9B3DD5752
+:10A1C000E7219DD71BDB7CB86E9ECD08EC423C9E00
+:10A1D0001CEF27FB09E455DE77E1C70351FC78E06B
+:10A1E0007F8F1FA9DD60FAF0B77D70E8F5A1DBA4D1
+:10A1F000A6A13C9C69317FAB5EC49F01FD6B163309
+:10A20000F9250E7CF5C563CFA01DD225931DA2F5BF
+:10A2100077400964A35FE1C0318F37280DDEFF83EB
+:10A22000C26EF5585810FD1F9ADDAFD98FD1F2F8E4
+:10A23000B898CFD96C5F0DED1785BF76BEE8D31205
+:10A24000FA82DBA9DB25F2C75AD44E1FDABD75AFFF
+:10A25000CC70A0BFF67488FB67EBF68E22FFED8210
+:10A26000D0ABE154B40BBB2407EE1F166C3F118733
+:10A27000E7DDB01F3D934D78E3FBD1F1623F7A3AC1
+:10A28000F4511C9E8BC3F837E33E22D6DD6B42FEB1
+:10A29000AD837D1A5461754AEF11ECAFCECDBC4150
+:10A2A0001415FBF5FB36EDFC7293DF44F26E539709
+:10A2B00014C27D5A9229909986FA89A5394EC5F61D
+:10A2C000AF97FFCEF6A5E0B966FFB9B1EF6B84CBCF
+:10A2D0008DE74DD0BE67633CF1618F91F9C80ED810
+:10A2E000681772492139F5E7CD4EDAF7D00FD4FF60
+:10A2F000732893F29ABE9EABB0B002789F3BD5F71D
+:10A300001ED20DE577384A7E47E6FBCEA35937D7F4
+:10A310002F20CFC3039D8F8B736A3CDF8D6C5FC78B
+:10A320007AA91D9EF3EAFAD5F601AC61940A70DFB2
+:10A3300077B7CD8BF64B3DF07563493F1F2E145315
+:10A34000D1F8B04EF879EBE77F48FB81FAFD920334
+:10A35000FDBB0BBD9C0F17C23EC93CE2D275CB3A88
+:10A36000810F23E01E6C1D5F9DA35FC77DF97F9267
+:10A370003FB322476FCF6AF3D7FCE27DF3EC92F84C
+:10A38000FA8A9A57F4FE32DA9FADED0FAF54AEDD84
+:10A39000D9070FC7475FFE9F2CD7E644E165B0F3AE
+:10A3A00082EF2CD7A2CF0D72B81F1CCF0DF05CF737
+:10A3B0007F7A6EF089DA9664203DE8D39DA7A29D4E
+:10A3C0008EE3B46E91C93E9820F373E85ABB99FCB2
+:10A3D000B4D1E7ADF5EA0471BED8FD876B507FEECE
+:10A3E0003132D4EBF36DF3E83CB35EDE6572A80363
+:10A3F0009C332A07C97EFFAEE7EF8FE6F49DBF6767
+:10A40000E2F97B59855E3EBF6AFB22211041E78A53
+:10A410002230FC07E0678B1264AE88EF4FE6707B5A
+:10A42000F8551127E331B1568CBF78DC1EEBC37DA4
+:10A4300087C7C0E3789AB3FC5B500E5A548EC7A707
+:10A440005EBA8319607E4F193B495E046B6D5E9462
+:10A450007B9A9F45EBDF2EFC0557CADF7BA3D6FB1B
+:10A46000DE7FF27AFFB536DE773D07DB00B8D1AD8F
+:10A470000346E75D6FE0F94DE6A5FC3A583F83F1EE
+:10A48000EDDB39FE377368BDF946D0B9FE15CA95C4
+:10A49000D8D2DE8FD09FC3F69855DC57A05F83F4E7
+:10A4A000E1EA64AEA7146F19E219ECB9328C833A71
+:10A4B0008EFFBD6670FBEF74DFBAE7F6DFE941E5BA
+:10A4C000CFDF67FF3565F83FC5799E2CF7E5A17EA4
+:10A4D0005C6107F8715FF7731E3FB3D9CAF973B3B4
+:10A4E000C4F992352668FE119A57F0797EFE1DCD8B
+:10A4F000572C57CF577DF97FB2DCB4F5C1F1BF2C93
+:10A5000037E7FF350EFD9C83F71324BA9555741376
+:10A51000DE7A5F91D8B608FF737D378F434B17F013
+:10A520006ADFFF2AECBFB9B9BEA118CFF5D97B16F7
+:10A530000B8B075307790CED2EBF8DFCFF759D3CEF
+:10A540004EA46E09A3F3DE3AF46F16A1DFAF86A125
+:10A550007DB74F0D1460FB15EFDB82723CFAC52707
+:10A5600033B2EBDEE3F9456AA088E2C596F4E8CEA3
+:10A5700019CABEF96239FA2D005EF203B8D12F1361
+:10A5800041A769B9FC7C404B6F8B821FFDF4C4FF6F
+:10A590009D7208EDC158B59BFCFE757BB89156269F
+:10A5A000FBC83FCFEE7331E4A3BA3DE5A35EA3FA47
+:10A5B000D65168CF967D50ED403FC467D7B929BECC
+:10A5C00060A8DCB300EDA9A359817108AFBD343494
+:10A5D00011EDD10CB047D1BEFD6CF7C45108B726C0
+:10A5E000FFD6A37F1BFA5D6FD7FBAF99C597F930F4
+:10A5F000FAB7B70DA1FDE1EE94C0CDB9B84FB37273
+:10A6000078836BAC7CBD0ABF76F4FAD7D6FD10D93F
+:10A6100040E30CF9BE85CEA135B9B0DEC80296EC98
+:10A620007E7972958897037CF078BDAE1A1EE7217B
+:10A63000F236B73E6EF16CF6F8AB707E57E5F2B8C5
+:10A640009439965E09FDEC73C4F9FB8D228E428B22
+:10A65000A33AE3F0CFC6FA6C4955FFB97B16B6773B
+:10A6600070FE17F131B117B99D9CE53011DFD85B51
+:10A67000193F3702BE41FA8CEDED1E170FF3C96981
+:10A680000F8F457C1EB868207C28356FD079493CF7
+:10A69000920DFAC95EDDB3321FFD258E77AF43BA46
+:10A6A000A86D8E0A44DD3ED5FF00C1A13414E0FE42
+:10A6B000B1E2F7461E0FF84A2CE9F9F6A10B291E64
+:10A6C000F0ECFBC0AF9997EA032D0DB26514FF972C
+:10A6D000B5FF1DF2DBDBF74803C6753E9E6BE3E773
+:10A6E00049C16E8A336363DD840FE5950F82685F2D
+:10A6F000282B15F254B4187D062BD27529233F7BE5
+:10A700006EBBC38074C9107125E70EFCF78800ED9D
+:10A7100047343F7D8852C5D8B31CF757CAD29EEB49
+:10A720006105B3DA3D4E431DFA358DBD75E41779E9
+:10A730002596FC9F19FBB3977D0FF219AD0E26A14C
+:10A74000FCF9D57D19C8D7419867EE00F36CCCE5CC
+:10A75000713BCA2BB106D45BCA1A4671888A33A9E9
+:10A7600082E05E0779E86791E01BEDFC11C0F5A07F
+:10A770003E9A9B1BD88E788E15728035C690BFD0BE
+:10A78000AE70BF86BDF1FDE797427EABF0B71E3AD3
+:10A79000503899FC732B1509E970C13923C301DFC7
+:10A7A0007F99CBED11BBD2CD1CB648FC1FA2B8CB14
+:10A7B000AC57785C9A62E47CA2AC7477A0FFEFCBD4
+:10A7C000B400C5975ED71296E9FCCA71726D951AEE
+:10A7D000B17FD9C0F548DD4EBE6F8EDEAF5C4E7FD7
+:10A7E0001CCDD5DBDD7DF97F925DF24EDFF87FE792
+:10A7F0003E84E9F76FD1F649F47EED12FB3AAABF29
+:10A80000C1EC142D8EA3A27F1CE28757ED9A1D1474
+:10A81000D4C5B954D8F8B8CCA2EFFFF94C2E27B460
+:10A82000B897A4667529C697F7FE94913F4D8BCBD8
+:10A83000D1E27082157C9F103480DCCBC4F39F364C
+:10A840008ABF49656149227BBF8761FB2118870365
+:10A85000ED7B72B3A8FF2DCCDB2A935C542584DFFB
+:10A860008AF11B09087768E35C1CEF361B8D67C50E
+:10A87000F88D04DA27D03A4EF1F3B8CD71F379BCF4
+:10A88000670AE85FCCA7E470BEB44E33511CA7162C
+:10A8900097A1C56F6878A910F84EC99F9B89FB01E5
+:10A8A0002DCE637D4CE8E75619E33B84DC5F6020E6
+:10A8B000B9AFC5CFB5E7AA21E4F77318E769BBF2D2
+:10A8C000788E68FC6A711D37A40792F346535C07C3
+:10A8D000E9512D1E43E397083A06AD30FEA657B85E
+:10A8E000FD5E31DF44F09F5B3089FC87E716181866
+:10A8F000AEA38A2E33E7BFA8F1364D33B130F6ABA5
+:10A9000084AC283F353EB89CFD0A742D40FFECA175
+:10A91000A69DD92761CD1F6EEAA4F49C55EA944701
+:10A9200062DA3B1D25D58867874E51AEC13895DE6A
+:10A93000A112B04EC9CE9CA9944FEC3D8EF949F9B5
+:10A94000374F55404F9CCBEDDD2A619C49FE89294C
+:10A9500094479E4C616CCC33BF9F12A479737FD314
+:10A9600038E16F323B03D7E525E27D809EE5DDE4EB
+:10A97000D7E171FD18F787F4F0D84C64DF7844BC58
+:10A9800025AB14F19778F202F9E6E451745E6D6339
+:10A99000EA9E6E2C4F33737DCF383F37E7727F309E
+:10A9A000A948949D699AFFA82788F2AA39D349ED4E
+:10A9B000FBE4EA1E7388FBB1F8F86FED2DA6732651
+:10A9C0002D8E943147FAD4628A37D1E51FB7F273DE
+:10A9D0004FA638D2D17E68360A3B55E463D202775F
+:10A9E000E545D8496F8DFF5111AE8733FB7E9283C9
+:10A9F00072EA4613D8F103C8A5D4022E97CE196D7A
+:10AA0000AD12D86D6FA4066621BE8EC54E9FE08440
+:10AA1000794D4B28373911DEE0CF6594938982DE7A
+:10AA2000CEA91C3E67A55F9A03FD365B613D43FBE3
+:10AA3000C480E2237B3D3055BA0DE06E9684FDCE96
+:10AA4000D478B2DB0BD4783CD75BD8F80EC555CBA5
+:10AA5000420EC8420EBCDDD493A3E482CAED5C234F
+:10AA6000A3BDFD8E385F7E2793DD5333803F737D1A
+:10AA70001EB70F27CB6A31F291FBE1B1EF54035FB0
+:10AA8000C8266F88E8976E5791DF0FDACB3C3DD030
+:10AA90008F94F1D3528C4B6E4EFF6929C695C82E08
+:10AAA000AFC71F915F9FC7F9B812EB21DE621B4A47
+:10AAB000518FFDC3FA8B87FE8AFEFEFEFAFA3173D0
+:10AAC000B8165A7A872AB03EBD9EC026A4DB8519E7
+:10AAD00027E8BCF587296F1DC7F888B78C6DE3E2BE
+:10AAE000500E654A826FB9BD76245FF36BF2B8F6FB
+:10AAF0002385DCAF097288C74F16F37B34D5531911
+:10AB0000ADE76A115731C1C1EF254D28CDF436C3E9
+:10AB1000D46E61BD0ACAE909C7FC71483F36355099
+:10AB2000EA2F1EDC0E631EA31A295726AA1179F8F4
+:10AB30007B53813E7FB3579FBF75CCD7F991F935D1
+:10AB40001EDF8B38EF97251EA719BC8639689E6ECD
+:10AB50002988F652E18B291DC27F4BF184FF2AF62A
+:10AB6000732F8E61549EB4D3B20DEF17687E705967
+:10AB700094177A9825C345F8203DDB2B89B84437D4
+:10AB80009DF5B07DF73B38FEA0AE09FAD93743A555
+:10AB9000759C6433B0EB71AD975AC87ED2D645B37D
+:10ABA00015F81BF058966A89417E6F367A37605FD8
+:10ABB000728C5945BD5A1E67A1BEE59F29A4979680
+:10ABC0005ACD14DA7AE8D118CA9729CC8FF1180037
+:10ABD000E2544CDF327A430D385FA887F36D76324A
+:10ABE0009257729989F434F44B743DB4C6106234B0
+:10ABF000FF7285E22D05CCDABA8391E8FB13625D22
+:10AC0000CB06162639966221397618FAC77E0FBD13
+:10AC10002E77901FAD40BD1BCBCF5BF2E9FE4D7D83
+:10AC2000DFBD22C580C015083BCAD9C5EF7F69EBDF
+:10AC300059932FD1EB19A4608E3B89711055FC07F5
+:10AC4000A691847A9F913DAF9D0FA65BB472C58794
+:10AC5000E324F7D5E7F7AF92443E353F93D61B5434
+:10AC6000091B4AD0FEF8CD5F906F35F9B075C5CF9E
+:10AC7000483E5C8AFF8207293FC9EEE0F8CF4FC308
+:10AC80007528C7E4A7A1BE6B767A557F44BE0096AF
+:10AC9000D13417E207EA417E4AD5891C25C2FF97C5
+:10ACA0009AAF92B0847ABE0480E390554DC3F53AD2
+:10ACB000C0B8B57CDCD87FECB81E1817EA1DB2C34B
+:10ACC000B8506FBBD51C36C40D34FE1815C7BBDC9D
+:10ACD000B8804E42EA248167E08B20FAA50ED90D98
+:10ACE000C49F93447CEEA1443E1E2BD0C7CFE4C446
+:10ACF000C0F8E46FD5C7CBDC286D6E41BDFC843550
+:10AD00006E1BF2E36F049F1C89FD590EDA55BF9943
+:10AD10009E7718E5CA84F8A52DC824935827C91B27
+:10AD20004DEE5D483E518679907FD7E603DD7F98F2
+:10AD3000F5D674ECFCB0F3891CD47F201FBE979F1E
+:10AD40007829FC1A3F6A70231FE23AE8E3C328F827
+:10AD5000353E62B7745280E116B04B31D5EC54C623
+:10AD60001A781CB89ADE3F3F60E20996063E8FA52E
+:10AD70004182FB46E75A8A371B312CE047B8A68D43
+:10AD8000FC7CA882953D33F2711F06F0D6FCFF844F
+:10AD900037DA2EBF5C3CB40657F43AD6C69726EF96
+:10ADA000A478E8FAA9368A8F1E27E24AEBE71B2827
+:10ADB0004E08F66F64F7D7314B08E5F0B5C28ED672
+:10ADC000E2F47F2571FF6770AF59DD11618F5F1A63
+:10ADD00027AD521C7670098FA7EEB3B76BB9BDDDF6
+:10ADE000A7D7C4BD80F6515C96B7DFAF52BCC4CBC9
+:10ADF00012AF1F9CC1B8BD5E23CAE738443C05CCE6
+:10AE000025A93F5EBDBD8311FFB7DBB3A83C45E676
+:10AE1000FA877D8FEB9FF64C6E4FB6DF9947E5B012
+:10AE20002F1886789F2583FDCCCFE7F9FE20978FDA
+:10AE300017EDA75D9FCFEDB23E3B47E4A3FDB2CF38
+:10AE400066043622DFCF29F20D9580AF6699B8DF10
+:10AE500015F86E33DE89A9620DDB956CBC5FD1F00D
+:10AE6000AE219BF8EE29E2BB42E0BB6C1DDF85F210
+:10AE70004773F98BC254E3BB3E7E2B888E870BFC55
+:10AE80001CFB6977767E5087FB8A2E33D1418B6B12
+:10AE90008C5EE711F09C347278DCB24CF0EC1E084A
+:10AEA0009E2BE1FF487E1BC2389F0FB60E86282CD2
+:10AEB000682FE95F076B3C81308EDBB71E96F37D10
+:10AEC000E42570CB36E28BDBEF9439BFC6727D8E02
+:10AED000E749C9307E8D18FFF695FE4A27D6AB911B
+:10AEE000080F355DB514F7C52AF9B99017FE203C57
+:10AEF000CD42CE69E757D344FB298E1A23FAE3A645
+:10AF000056EBCF91A6D9F839D5ED538D1F46DA3DD2
+:10AF1000D3D8EACF314E711A9E3369F5818FDECFD7
+:10AF2000B7BBE9FC5B65F978CE7458F859CE015F80
+:10AF300023DFBF96386FF3FDC077F94F1695A03F1A
+:10AF40006E7CD282ED6B20FFECA6E1947F2DE9FBB5
+:10AF50000FBC85E55BF3285F6990884FCFD5F2F68B
+:10AF60000565774ECA8C43F92FFAC5F584FBF59831
+:10AF7000407B0DD4F38CC82AC1F8D14AE137387729
+:10AF80003FA3F29B46DA7948EE3C95FC7E9531A2D0
+:10AF9000FC07BCDF3746FD4709C6115766F54E472B
+:10AFA000FE7EA3E4E5E1983F2C7D3E7DA03886C27D
+:10AFB00002293C0CF052E9E2F5AB4B7E9E827E9872
+:10AFC000CA0A9E2FF496AFCCC672C3F9E903DDEF2F
+:10AFD0008D11FB9EBEFB6A625DBFE83B41F7D3FC6F
+:10AFE00016C98B53F48F39417E0766931CE83AF3F8
+:10AFF000FB3215F4738FF3F138D30ACBD264945F2C
+:10B00000B7044CA5182FECB08C3A8C7104F163CACC
+:10B0100047235DC75918D115F83CAE00D6D7B4AB5D
+:10B020003F1F1A87CC65D3F3B9C647351A7F57EA55
+:10B03000F918D6A71BDB5F4EDE0EC6C730FED00266
+:10B040005C67DFD3EB9BBEFEA2D65B74FF83C901B6
+:10B05000FC89948BFD7074D2BA4AC3E8BD6C5C77EE
+:10B060006DDABA1B89F33019BAE99E4E86E41D4E9B
+:10B070001756C7782DA48FA2E0D6E04B07D9C64A51
+:10B080002E850B7F14CD5EE43F6EF44BA48972686D
+:10B09000E763AE7EB860FC1B100F6C3987678BD4FA
+:10B0A000C0E586D81F68FE8C3A6DBEFBF5F32D8B8C
+:10B0B000E1F7D63DE877C276EE51C3BF0DEE7AA137
+:10B0C0004FA75AFC8F9A610EB73967113FDC011AFE
+:10B0D000CD09F3FF5B6AA006F1D12C055FE9C92415
+:10B0E0007F3CC57700BD271744D8011A5CD1F8A86A
+:10B0F0001B441E46C31D8D877EFA742763AADD7725
+:10B10000EB9B57D47CA2ED02B749EFCF7309BF9BED
+:10B11000ABDFCF5680E5D52CC64B7E36AF44FBA8BF
+:10B120006AD0F32847ABAB18F9475C3603F9D9343A
+:10B130007D3F187FDF703D9737D50B99B84FC7E734
+:10B1400011CD5F4358CF83F49E8345DD381BD7ED87
+:10B150007C9B2E0EBEDAC6FDF32B0B24E197EF1974
+:10B160008D7E89BEFC25FEE09ED1283FA6CBFA73DA
+:10B17000AAEA8BDC1FECBA28515AED3D311AFD2C9E
+:10B18000AEAA9ED128871E19EA5B85743D6EE0FE4B
+:10B19000F24BFC160506CD1F7C457C174D0FEDFCD0
+:10B1A0002F26CDBF01C73923759761E1862C713EEB
+:10B1B000C30299C8974E476639FA7140CE7DF30DA8
+:10B1C0006E1EB108F035262310C2767730FF78BCAA
+:10B1D0006BE9AA0A18F97905A3F92F12F31F2FF4C6
+:10B1E000DFF9CD3CAEA2D257F0041E89D41F35B290
+:10B1F00010AD3F1FE9B1FB04FCE741D585B1FE2E40
+:10B200003BE9C179AFCFA27889FC0D86FE772BE0B0
+:10B21000EFB0508CEEDD8AC29D2E5DBEB83345572F
+:10B220007FE4FE2C5DF9A8F0705DF955474B74F989
+:10B23000D1DDD7EAEA5F7DAC4297BFA66792AEFE4A
+:10B24000F74E4FD6E5AFEBBD4B57FFA3BE7DBCD04D
+:10B25000DF415F7701CC7BB6C69F1767EADAFF292B
+:10B260006EC251E4CFD9AB79FC77396048F78E478D
+:10B270001BD7F30DF007E93B9EF552DC5D5D48F20C
+:10B280008619C691E9ED8005FB3B088F97BBF79EB9
+:10B29000EF9E6140D3F78302116F7235BB9AC78D61
+:10B2A0007E3B5DF358CEDF4557B3474F57ABAAA758
+:10B2B0006B6C819EAE76AF9EAEF163F47475FAF45A
+:10B2C000744DA8D2D335D1AFA7EB90697ABA2607CF
+:10B2D000F4744D9DAFA76B7A839EAE198D7ABA65D3
+:10B2E00006EFD5950F466F4D1E66B72ED2D5EFA34C
+:10B2F000BB7F3EC511E5B6FD58D7BF46F720FC41E0
+:10B30000BAE73311EFF83FA47BF2303DBD417FA493
+:10B310000C1B4D7A3F1DD369F9C2BEF60FACF73551
+:10B32000F913A96723F79783C9A54BF48AD86F0E41
+:10B33000AA57A2F69BEF31D07B34C86AF21FDD29F1
+:10B34000F8F3500CC7FB1758740DD4833A6300AE62
+:10B35000F7106E18E7BD9842F20BDCC53A8DD8FFA6
+:10B36000DDAC9BD2E9AC97D20073901E9DC9BC9412
+:10B37000CE667E93F013DC302C11FD073D65A88767
+:10B380002FCC78EB389D2FBD917045EF3D7C88E741
+:10B3900018B98C9D12F2E0249E6740FEAC55F8D39C
+:10B3A0007C4C7547E0ED94F0FBCD1C27913E647218
+:10B3B0000CC559CDBC43227D32F3FFF2F48E61DC23
+:10B3C0001E8D4E9B1B35FCF17DCADA612AC9F7340C
+:10B3D000D629F41E0BD8B2A91F7EFEF0B489F693CD
+:10B3E0001E0B87EF798929635C74ED8CE8EAB170F4
+:10B3F000789E37320BE2F339165091188F2820A22D
+:10B40000F87D87E1C81F33FFEF5B59E82F8B59B5F3
+:10B410007B6AE535783E125C4AFEEA1F30BDBFFA12
+:10B42000EE0689FCD53F003821F538BC1ED4975A6A
+:10B430003E88F0C23C2AB11E7C1FE26990D03FF4E6
+:10B440000FEB6FCF8F79BDBFB3BFBE7E18870B7F69
+:10B45000907E9AFFB1C0C0E3157AEFE7FB94ED3F11
+:10B4600060DC8FD6182C0FE2F9A40C1B4A8C6732D3
+:10B47000F27BE86B8765F2FB6EAC9BF6F9EC8866B5
+:10B480005F0648FE16897B0E67C5F9DEDC0E0BC32E
+:10B490007899A2DD075D789E371778B01BF5B0125A
+:10B4A000A077568A36BEE6E2FE37A313EF2F6AFA7C
+:10B4B0007F703E55D8A988FB02C0770D03D91F7B4A
+:10B4C00086F373FAE6A6EE61781EA7C1F370D35136
+:10B4D000CACB8A97E20CF11D2667447B931BCA23D3
+:10B4E000E49D6283F61172C868F3D36326CB9BBADE
+:10B4F000E99CCF28DE8B5A91B6C81188D8C7BD30D9
+:10B500008C8FCF2C41E64862C204C754398572ED56
+:10B51000AF8CEF67CD1EE827527E5E4C64917EFAB9
+:10B52000D6A66304EF722910C04ECC392C6C05FAF4
+:10B530009815BC730BDF37DE7814E3A94CF645DEB3
+:10B54000B03A38DECC1EE542A43C7D7598D8470B56
+:10B5500079FA2F4DBD85384E73538F862F86E7A617
+:10B56000C1647E8FBEB9E913FA6EA85289DF5EDD31
+:10B57000987F5085F2E3F017DFB531BB395CECA260
+:10B580009BF4EA74C107E8134B07FE39DE68243EDA
+:10B590005B9C6E237FFDE237730FFA603D9B60BAC0
+:10B5A000F27780BB7F1C8E279390A7C04F7E940FAD
+:10B5B000A61485FCF62EC764A2D3DFDB9F865F93BB
+:10B5C00095D17B44A6741BD905570AE7B9287D0598
+:10B5D0007821F9BF58E0457B5FE9F8038CF60B8BC7
+:10B5E0001FE2FEBBC5B58CE2FD5923FC94F5F38D3B
+:10B5F000A66712F12518F8D8D6042B0EBA78ACC974
+:10B60000C202F96087607C7C763F1DDB7C8A138FE9
+:10B61000FAD754BA6B307D6CCCC936147F8F8FFD4E
+:10B62000B21B53F4D5E3F88E061642FB98CEE061C8
+:10B630007CE77CC8C3F871A23C2EC0F3F1A23C7E2B
+:10B640001ACFA7FB5E902A11B0A873A5749B6B62FA
+:10B650000ECAE9D98CDFB716EF2D6C11FA22D5E6A8
+:10B66000AAA9C4F2BB19DDBFD0CA9F14E5C9B60FA1
+:10B670005BB3518F4CD5B7DF28F030C4F661DB38AF
+:10B680003A7FD2976BE73B89B6F347A97D91BE7CA1
+:10B690009D686FB79DEF1E87E539FAF11F15E5B17B
+:10B6A000362E0F999FF1770144F923A2DC8AE53801
+:10B6B000BE9797CBDAFB17A2DE4A0107C6B691FF09
+:10B6C0007318F77F6E6DB214115D9A2E127D1E6B8A
+:10B6D00062949F34DCC5EF6557717CBBDC9C1F1CFA
+:10B6E0008D6CC0F700260DE7FBAA38B5C7E71B40F5
+:10B6F000EE69E52E077FEF40F698889FCC3621371C
+:10B70000C47AEC931B5283973319F7975F8EAF611E
+:10B71000A15D40FB6828FC205FA73D60608108793F
+:10B7200099B230860522EA7B66BB74F9A4BB5374D8
+:10B73000F5DD53B374E5B6D2E1BA7236D545EB66A2
+:10B7400091E0AF98A2125DB9F60E03DB2EEA89F5FF
+:10B750006BCCB95657EF7C811A8F3C7E6A22E81F6A
+:10B760008A2BF05A503E2CB2670D41FDF35CD31882
+:10B7700042CEF3B0AEC06865BB9C3CDE7C179EE356
+:10B7800041F9BF36F9E8FB0E2857217D1AD69D0AEC
+:10B79000F53B9A1C947FAAC943E9962695D2279B2C
+:10B7A0000AA87C639397F24F40FF98AE837EF0FB2C
+:10B7B000DAA62ACAAF69F253FEF1A669947FB429CA
+:10B7C00040E9234DF3E9FBCAA606CAAF686AA4F4B0
+:10B7D000E1A620A5CD4DAD541E14F4DE25EEAFEE4E
+:10B7E0002AE7F7D2A3E9F8F07049F75E9CBD3F7EE7
+:10B7F000E4E1E1183FD2D94376B8163F82F3A6FEC2
+:10B80000AC7CFED1FD6D1ACEFD09C359F7D258BEEE
+:10B810009EE99C3677BF77592CF07D6A03A743E6F3
+:10B82000FE5E2A4F9ECF69B149E865E60EB2B4329A
+:10B830003AADA77A67A5EE8A587EBE4DFE0CE6812A
+:10B84000799689779288ED4206844B19C3F5A7460D
+:10B85000D7BE793B399C38FF81E0DD21E0954B3B39
+:10B86000F9FB27556D6164FB185F03BD7F6299E6A4
+:10B870000F2B90BAFD017A8F61F8C509B0390379B1
+:10B8800073F17AA6429AB650BF6F4B995DA2DB174F
+:10B89000C9171F632AC8015B917E7F1593B348D7F0
+:10B8A000CE92F6635DB9C9BD4C573EF3BECCE51EE2
+:10B8B000C4672A3FE731AF5ECA9201AE39ED6B082B
+:10B8C000AE77041DCF4A2ADDE30EEED6E21EF8FE67
+:10B8D000E259A15F986535D963F94E9ECD8B0F1A59
+:10B8E000503F7CF66FF124979E79CA10427F2E88D4
+:10B8F0002703AEFF4230FBB0BC98F5501E435630D4
+:10B900003F8AA932E6AF62BDB4BF82FDC5EF866350
+:10B91000FCA81C78CA0AF933E9816779FC5A98F4C3
+:10B92000679EA0679EB69FDAA044FB79DF1A4E7C23
+:10B93000A8BFC7D622F6172D56EE7F5BEA2C1B82D6
+:10B9400076EBD941E20DED9E578FCC067CDB930F51
+:10B9500052AA7D7F54350C784FFB8F51FC3F0C98D9
+:10B960005DF0FF1F119E33A56F27A11BAA2EA7977D
+:10B97000D6C159C9E79981F87D5DE6FC083B2E9C4C
+:10B980009F22F0ABEC2EF7CC003C2A6F667B83AC99
+:10B990007F9C679A8E65633C8096CF13F1B23B9B88
+:10B9A00092732A23BE3B0B393C05ACBB0AF55541CB
+:10B9B00091C11BC28E7D0E9D1FC39AD3E6C377072C
+:10B9C0009412E64531378CB52D43DDADFC4DA6789C
+:10B9D00027E5D0354C85FD8CCD1666181FA6F5CB16
+:10B9E000843FE4012137BF7454C6D37B92297DF292
+:10B9F0000F7524FBD2E6EB463EFAB2DDC8E7754888
+:10BA00005F5E60E3715C730B4C2155C2F7CBDAE8E3
+:10BA1000BD4465ABC4D232118E718407B62F96F83F
+:10BA20003076C3081684F552EA0CFC05F9E44C584C
+:10BA3000DD67C8163C09F56A0B4DDBD03ECB47BC31
+:10BA4000D8102F77E654E2D0390584DF3962DE79E9
+:10BA5000857CBDB6A447C1C3BC3E7C57746EBBE6B3
+:10BA6000C7D1CFF3D1D28A5BF1FDC5E66E99ABB5F4
+:10BA7000287CAE32768F98015D9FE901B8648233ED
+:10BA8000AF10E5C2863216243DCEE757FB94C4368C
+:10BA900065925CAA223D3EDAC022CF31B5B4B8909F
+:10BAA000CBDF9786F3F7DAEC9E23C48FFDF9C3470B
+:10BAB00066033E9E33B0023ABF35F0FDB116372320
+:10BAC000A31F00D29F146AFED2163609F5B6D340E2
+:10BAD00071A072470CDD4F959D0AC59FB7D82A1DEE
+:10BAE000F7623F0E85CE6B26C863BBD18E363B0D09
+:10BAF00057A11D7E78DB8FBB317E474E5718FABDAC
+:10BB00005A1C0AB743D20C1497A7382B2D78BE9332
+:10BB1000673B598EF83CD8F1437A8F417E50C4CEB2
+:10BB200008BF985190AC853550FFC13445BCEBE25D
+:10BB3000AB1E95248E2654DC0F557D82FBEDC38E03
+:10BB4000F356DC17A8B6B9E40FAC2BE4FB44239EF4
+:10BB5000E341FEA925E79D28BF5EEF58EECA447B6E
+:10BB60003AA4902D52F075730ABD3BD061A27711B3
+:10BB700034BC660415DD79607AA33E6F8E3A1734C3
+:10BB800046DD479B85E3939F781A0B47CCC7E8E1D6
+:10BB9000FB37E6B6D1FEA7AE50BC8729F273300F53
+:10BBA000A4D8690CA678013F873AE666E0BC2EBCB3
+:10BBB00014A0F8EFC1ECFFD242558C17B41AE8FD7F
+:10BBC000DDB015E3C1B737312FDA79969042F1F83D
+:10BBD0003B843CCBB171FEF717713E8F4E73DAF8A0
+:10BBE000BA5376C58462916E8ECE9220ACF3C25762
+:10BBF000273215F4608EC367407F7C4EA3C98BF655
+:10BC0000E7845FDA884FCEDB783C95D2F8888ADF0C
+:10BC10009BB7951544DEB30B3539BC289FB6355913
+:10BC2000BC18A31E1A44BE663B0D14C7AE1A785C3E
+:10BC300065BB588FED85B194AE1572E6692538194C
+:10BC4000E17C1AE889F1F3075773FB78D1520BC1F5
+:10BC5000B1E8F56CB2AF06C3DB334D1E6F0EC2B355
+:10BC6000DA9082FEAAF29539ABF09D8C4576FE8E75
+:10BC7000B01C3F9CFCB6EC774686F67C73DCB5DEE8
+:10BC80005911F25D8E1F5B807C25CBC114F4E7FC5B
+:10BC9000BCF0DC6D18570BF4DB84F9DDCFFDE13629
+:10BCA0008CA3DD690FA6609CED4BCFBDCFCB13837A
+:10BCB0009B30CEF6E073C779797A30C500F9D79F0B
+:10BCC000FB9097E7063761FEADE74EF1723C030348
+:10BCD000D9F9DE739FDE16447F8BC93B1F05F22F17
+:10BCE00000FE2258629D22FD40E0452B7F01BFC32C
+:10BCF000066C8F48A3CBF78976FB0729FF9528EFC1
+:10BD00001AA4FF03A25D7890F68744BBC383B43FB7
+:10BD100022DA1D1DA4FCB7A2FC8D41FAFF77D1AE3B
+:10BD20007B90F66F8B76EF0ED2FE0FA2DDB141CA8B
+:10BD3000DF17E5FF19D5FF7151BF477CCFB2AF7E4A
+:10BD40001FFDF7592047502E15D857BB709D6F6BBC
+:10BD50002D25FE6F2EE3E7541ABF67498CDEF7AD41
+:10BD60002EE2EF8A551771F9FB67D13FF0E1E3C886
+:10BD7000778BDE9429AEA7D9E03D1D4239BACA407F
+:10BD8000F6C0A2D7F97E7DD14A2514792FE7CF518D
+:10BD9000F02F47F880715B3085F576A690C7F59B4C
+:10BDA0003D1E6F75843C333AF47990170CE52EC82C
+:10BDB0006F8ADF2E5859D15A00F95497812C10A55B
+:10BDC000D612C6F73A14BBD00B8ED2B60284CFA6D9
+:10BDD000D03B059A9C67368FCEAFD16253E8DD36F3
+:10BDE000D9CECB27FC72AC03EDAC1616E8F6617B1E
+:10BDF0008F4276FCC1D61207CA3D937DB603D7EFBA
+:10BE0000BBC57C5E9575053128AFE5470D24BF0F96
+:10BE10003BF87ADFEAE1F14EA057E89E13C86B2F9A
+:10BE2000EA887C165E8A7273E763FB66703F1FB315
+:10BE30008F2AA37B44DAF9B6A444EC03AE2BE2F8D4
+:10BE4000C9107A4441FD02E9D3A5E2FE4B90FBA361
+:10BE50003214E6498DB8C77B5D91CCEF1F2988234A
+:10BE6000E84BAEA6F7AB862E5174E708690FE8F3EE
+:10BE7000A628BDA144E995EC569093BAF313872EFA
+:10BE80005F5424FC3C5EE6453B76C22F57933C3C16
+:10BE90008FFA4D1A5CEEF5C95F218F9F4604A01CF6
+:10BEA0000DF27BE4075797FC16E9BD68A581DE8D8E
+:10BEB000BE5239FA678405F0901B90482FC0845217
+:10BEC00070DF74393CE41AFD2E7A57E332F8C85D0E
+:10BED00057EA42799B1B50A8FF4BF4C665F0F5BCAE
+:10BEE000E43D16403A3A63845D0D0C807E3B574C2E
+:10BEF00007C6179B843F458B17568628FC5D7C71CF
+:10BF00005F55167CFC30F3A9AE6C7C17A881FCFB56
+:10BF10008B773FE041BB7D8521E0C0FC51D7A45E1B
+:10BF20001C67116CFA117F3BB10F7A1FF3B7B7FB97
+:10BF300000FECE90497BBF328CFFECC63820ED7DF1
+:10BF40004C0FD96BA2FEB5B75702DE3B1547219ABD
+:10BF5000A04B775DB7DE781DD437B1BEFA78EFEE2F
+:10BF6000B9C306F17EE6B8F595209776C730DDFBBC
+:10BF7000A0BBD1CF4EFD4D588FEF81C27837C9B0ED
+:10BF8000375B5B74F37A5B723F3CEB8AA7AC5F8AEA
+:10BF90000E3BB14F7132FEAEFB19B5270E970FEC79
+:10BFA000577E5204F4ADED389914B95FD7EAC78BC8
+:10BFB000FA755DBD75BB54AABF94EAEFEF8D2B22D5
+:10BFC0007CF79645D68F137E8088FA2BBEAD7E8196
+:10BFD00006CFAEB76F2FE2F51FC5FA67D59E248A4C
+:10BFE000AD898227E1D2FED77E5BFFC345FD33E1F9
+:10BFF000B7A9FE59D693549C49ED3661BB736FBC0B
+:10C000005D26E69D84E738EFDA7C4F16815C6AC0D6
+:10C010003ED07E561A54FCDE696973A0FD6635B6C3
+:10C02000F9510EE7E03B5F63FAD3ADA83C465FFAF7
+:10C030003D9A9F3B2D2CA11AF9B5D140FB9BFD3DAC
+:10C040008647902FB7A68D75E0FE79B7A9BBA408E7
+:10C05000EDD7BD36B25F0D199F59D16F6ECEE7EBAC
+:10C06000DFEA6CF01641DE9A5E44EF74CA0F2DEAE7
+:10C07000A4F7C27FCADFD1527E660A6C477E0C2FBE
+:10C080002A9813B1BED7151B09BE95AFD956E3FE4A
+:10C0900060A5D1DB968F76B85DA1F84BE567FB26EE
+:10C0A000917DF80B0323F90FF3AC807E5B6628F4D7
+:10C0B000FB0E4E14CF3C5844F8F0FB2BA0DED044CE
+:10C0C00045C27B3A0F2B7E0B9E7798855DB7D5CB0B
+:10C0D000EF6969E37E2CECCF8F8BF8BBEE5BD32E40
+:10C0E000BC37CF8DEF3098E87EA56DA1216C8AC357
+:10C0F000FB66DB4ECF437AC6F6ACC4FBC631298A59
+:10C1000003E7F7643594D1B95C277D0FD61A68DF51
+:10C1100090B0D0E043FF634C8E49E7EFB0C1389157
+:10C12000FE906F8A03C710EEABDE546E423C7BEE8E
+:10C1300037D03BA48F7ADEB51800CEB8527D7BC7CE
+:10C14000587D7B57A5BEDC5DAD2F4F9AAA2FF7DC3B
+:10C150006D8AF2EBE8F33334BE029960033D15C3F8
+:10C160008B588CED4213EE7B56BC16C3883E4BD6E3
+:10C17000B7E5E3FA8CED257CC50C8F21BFC08A643E
+:10C1800013C9F515C5DCAF7F28DD7413E5615EC802
+:10C190001F5BD38ED07EE412BCD84E7F8DFDDB5862
+:10C1A000C477B4338A7D7F291ACDF39E32F4E3310C
+:10C1B0009287CF4B3EEF41C4F75BDC5FB1B591FB9B
+:10C1C000B11F9DCAE311690665B8DE79FD38CBEA77
+:10C1D0006EDC97C5D95AEFC738CB68BC2689F38681
+:10C1E000AD78CB16F92EC0DF675EAEDD77C2EF65A6
+:10C1F000747B81DE1F1B3F82F38B53D809F19E8431
+:10C20000A296887B1349C26FF2F8D89956D41FBB07
+:10C21000C57B1E7DFDA934280F3D45BF72B124F6B4
+:10C2200053BCFD7AED9C47E4139D3CBFFBB0EB266D
+:10C230005C5FEBA7BA4A70BFBF42D877F16926DFCF
+:10C240003098D7DAA3A6A03412F20A3B6C04BB6084
+:10C25000B78B8F6B7A3D2688F7F3D67A4AE9BEDF33
+:10C260007562BC17CABDEFE07AEF857584715F6BAC
+:10C27000DD5E6B8938370D027C685AE03EE56075FB
+:10C2800009ED77D7FABC56D49B6BD3BC568C97B6C6
+:10C29000262B0E8C077579147A8F6DAD25E040FB47
+:10C2A000C7058AD484E749E96D13E99E1BE0DA509B
+:10C2B000C68F1A988833C438BF0481CFAD9ED90E7B
+:10C2C0007C1FC19DB3E747E8A74FC0FEE2783BC49F
+:10C2D0009353E0697CB14A70BB45FF09B35FA0FA94
+:10C2E000F8D35216D19FA0A369220BE13E4D1B5FEC
+:10C2F000EBA7AF7FE6A37380E5BFE5785B9ACEDF5F
+:10C30000A132DDC7683FF742796027F2596F720C9E
+:10C31000C9BB144F4A05F251CAD14D93F1FEC3F285
+:10C32000DFC6F071E6707E4F5198E57A9C7762C067
+:10C3300081788C5EAFC987DB6A902935BA44AFDF5C
+:10C340006485B5CAAE4BD771B2C75D91376280F5CF
+:10C350001CB55E928FF63E88FD47AFEB2DB1C74707
+:10C36000713D12F15DBE7CBE45EA5949723859A152
+:10C3700075961E351EBE6787798919548C4F5E5796
+:10C38000ECD4DEAD5211AFBB4D8E71367EDE4EFC6D
+:10C3900055F1E2EABB7E07F90BF87B73A056EAD1B0
+:10C3A000B66ED28BFB03F9587FB312780AFDE99B76
+:10C3B0008F0DA17722CDB1FC9D4F53D4BB259ABEE2
+:10C3C0005857CCF7316AD4FB96DF35ED4C4B2B74C4
+:10C3D00000CFAC7BFEB77FB024FEE3ED9FB4C39DDE
+:10C3E0004B6DB0A6B7ECBA653DC6475ADFE4E59B96
+:10C3F000211F54102F0BC9EF7268E8BD34FFE6F718
+:10C40000CCE4CF2A96BD1B30CF3EB0923F6EE7DE24
+:10C41000B1D3709D34DBCB54B4F79F11F267BB5896
+:10C42000CFD1F3924DDE00DA03D1DFB7168B73095B
+:10C43000E63DD601F42D7EDA44EF25F5C547745864
+:10C44000F9EF331376E86C21CF66EF5B35F420C348
+:10C45000F7306AF615C3B8B3ED9549084FEA458938
+:10C460000540FE6D16E7B3A9EE1724943369EEC3B9
+:10C47000E528EFD359F752941BE90DFAF3B2D48BA8
+:10C480000AB5DB9DE2A3FEF007EF399B9858D3AEC7
+:10C49000005B8A723E859FB7981C31FC7EBAA7521A
+:10C4A000779F597B47F655810F13E0D45802A94D69
+:10C4B000E1F7E7A3EA1F15F892D16F8FCE7FC791FE
+:10C4C00063D4AF4DF92CF25D16DC9792D05AC8CFE9
+:10C4D0003F014F41DC87B278173F2FF5F9D4C8B838
+:10C4E000D65490BBE6128C3F09529C48B2B89FA02C
+:10C4F000C5F500069CE877D3E23EB631BD3DA2A566
+:10C50000DAFE3CA751A67D47E1AB56BE3F686521E8
+:10C51000AB84FE3046722767353F9FD6FC62D5B8A4
+:10C5200098683D380C3CFEA793E29935BB0AE84B6E
+:10C53000726765D47B4FDA7BD55F88F5B4B9C941A2
+:10C5400074D4CAD302D174D49F736AF5522FA6B2A1
+:10C55000404264BF21EA37B5710FF143EAC5A154E7
+:10C56000BEB949BD4CFF5983F49F4CFC3278FF693A
+:10C5700054BE25FCAEF31640C593BD7B9C7E15E5ED
+:10C580004A78A277003CA73EA0979323F7EBE5AE4D
+:10C590008697CD8ACF5D03F8DEFC80C1DBC130FE1B
+:10C5A000545FAF2AF3F74EFE7EB4563FEC9E82F501
+:10C5B00017F2FADF3BADAFEF2FDF1B5D9FE0BBE172
+:10C5C00062947D18459F687801AEC4DB22E01A674B
+:10C5D000D1FFFEB869332E812BF18E08B86EF4E8D6
+:10C5E000EB07960E0CD74D05E66F854BAB77EB98B6
+:10C5F0002BAB173D8F2955E641F0CEEBDF31EDCA6D
+:10C60000FAFDFEFC6FAF774F63F43841EDFC4867ED
+:10C610008F243472FBDDC17A29CE44B33B5CCC213C
+:10C62000E2BFB8DDF00EFE17F6B34B46F86F1D31D2
+:10C630001AF1EFBB7B9D8AF754B8BE62D5FC7D48EA
+:10C64000D8971447BE7FDD0FD732EAF7658C772283
+:10C650003D6BF1A2DD5998CA2CC9687C794259F822
+:10C660000ED8F4119ABCE6F1E5C305EE9E4FE95CE5
+:10C67000E4A4751E72213CDF75DC7B47F8E68C482C
+:10C68000ECAF3F98BF45C393C9D449BF3FA1B7D6CC
+:10C69000E645FDF02E1641BBA76F3787D1AED6E237
+:10C6A000508FC54E3F92A8D2FB038BB1FF69774CE8
+:10C6B0005C8E79E95082BAC886F7977AB47B9E3F40
+:10C6C00042BC2DB40432920C74BE9A8FFB61E64FCB
+:10C6D000109782FDC503C56968F0544A1CFF316993
+:10C6E0008120F65369E8DEEAC76F4A37DF673B12FD
+:10C6F000F9FB47F8CECD00EB5FC34385E8E7A0D157
+:10C70000FB552FCCEFE09A78BA0F3F3BE18EE9F86A
+:10C7100036CA1C833F090FD023E07E8CE0B6CDC81B
+:10C720004846B88D026E4BA2C0BB2FE7DBE0EE8B14
+:10C7300097F9A9A4BD534EF917834EBA776E367C8C
+:10C74000F1EE14D4C3C5062FDA9D9BC1BEC077D6C7
+:10C75000FE8FC0F7163C6371D1777A7FCD23EE5FF1
+:10C7600079D61BE8BD157FC54B44A7A7EB6C5EDCF3
+:10C77000B7CF602ABD6F3A4BDC47F963F97FBFD270
+:10C7800003F3DB3522F02CD2E79E04C3D077098E69
+:10C790004021BD6735F6CAE267B573F8C9C23E9855
+:10C7A00023F03885F9286EF7361630E2B86F9F35DA
+:10C7B000F9D02E7D5BC423DFC182F4FD4E16A2F4B6
+:10C7C000FB2C4CF57F802FB742FEADD811E98D00D0
+:10C7D0005FCD13F9B9B81E23F0FE8AE0977BDC9C8D
+:10C7E0005F3E1E82786F4FBC22FEAD9138FE968C64
+:10C7F000081CC1798FB3A86E2FC2E41897867E9467
+:10C80000BEF55399C8F94F71E47EDBFAE93EAFDD1E
+:10C81000BBF7D992CBF0DD2DFE73A3EF3E8A17C78D
+:10C82000B87C37D0A15BE5F70D416CD88340A7AA4F
+:10C830007299E2F6567C2EEE49A31303EAFD669444
+:10C840004CEF8469E792B788FE6E49E3F706ABCBFD
+:10C85000A7B4C4035E267CD5531A86B42A4D7F8FB5
+:10C8600070A2BB839E0E9F94A3FF7E136BA303E273
+:10C87000EA227D9CF92D51FECF833836F0D527234F
+:10C8800044BCE470363CF2BEC1ADA2EDF9EA2F4CD7
+:10C89000E760FCF491815EC4E3A29BFF389DF675CE
+:10C8A0000A7BF32A985FDDBFCB644F7ED80433C97F
+:10C8B000C7B86A0BF381C17F0AEC0ACC9F6EF250B5
+:10C8C000FA29D801987ED65440E5679BBC941F3F57
+:10C8D000D2FF17A4F3CCD6CF15D4472BB4786C0174
+:10C8E000871657B842C44F2CB62F3A86F10B8B29C6
+:10C8F000E09DC1626F9B80E0DFBBBFF308A6F05DE7
+:10C90000C67DC8E23512F975E61C0E2C4732CF7B86
+:10C91000A3E7161413A37F7F3209F7E9B568C702AE
+:10C92000EB2F76F92C23617C5FD789230950FFE335
+:10C93000A63104DF274D3E82EF4F4D55944E1FE93F
+:10C940008FA37AEC737A6FE9E65D2714FC3D68E308
+:10C950007D12F9EFAFF7B15008F0BAC1C8E5FB0698
+:10C9600090EFB83ECB8B276F7900E11B11F08C0460
+:10C97000FCDDE69A353E01BEDF32668682F5EEF8D2
+:10C980000A7450663F1F5E8EAFCF1C90083F670E43
+:10C9900038091F1A9E6A05BDCEEC2BBC15DF1F3B64
+:10C9A0007054A6F8D3F3170D04DFF96331149F1AFE
+:10C9B000DD7ED1DEEC21688FFD09E887071F8BF64D
+:10C9C00016923FFE4FCFFF488D8CFBFD93ABF3C219
+:10C9D000FB28A7FE8BCB29B0374F6D423996964284
+:10C9E000EFE8F4C5ABB18658D4637526B1BE40CE2E
+:10C9F00060FE4F317C1F5CF68BD40A5C2F381EC65C
+:10CA00007B99C5EF9B80FE8EFF18FADBB7C943EF19
+:10CA1000EE7CB6FB892C1C7F67E79CF73741FF67EC
+:10CA200042FCF74D9C619D677F85F274BB8DFC963F
+:10CA30002B24800BF5E98E14CA17484A4C2339334E
+:10CA400042B46E0B2455C177C816BEB03105F90B40
+:10CA5000EF8B635CFDCB6B62494EBD6CF41E6FC403
+:10CA6000FEB6F0FE9E7DECA10FF763FA686DC94338
+:10CA700090DE3ED245789FFD2F0B86637BD0D7F4A6
+:10CA80007B959F7B510AA31FA4B8FDE0328C631AEB
+:10CA9000B9F9842105D251DBA5664C0BD3271D457E
+:10CAA000FFC1DD235582E3AA5D9932C6A60F4F0967
+:10CAB000BD7F038F1BD1E9F7A2F6CF2B709BA9E9AD
+:10CAC000F9E152E7A71DB82F1E7AAC84DFEFE2EF41
+:10CAD00044EFED9AF2CEF719CE032C08847B8689B9
+:10CAE000E22E5828D881743E1328F0D2FB26FEE0AF
+:10CAF00046E4AF3381247A4F7A9F211887BF2F29CC
+:10CB0000789CFF5E9F17B7BF1587F114F17B8C0CE3
+:10CB10007FFF74EDA8DE09141F92AED27E3C7DEB40
+:10CB20008D55889FBA3D7B3BA89F85162FFA63E7FA
+:10CB3000EFFD82EEBDB0893C0EF5CC1E9E7FA4D2E7
+:10CB400047EF8ACFEFF833CF77FB29EF97839974BC
+:10CB50007F6216B7779E10FA8CF58C6091EF1269A0
+:10CB6000F47A048AB17C43663019DF9FD2F420E85E
+:10CB7000AF265C7FE876A4F68E29FCBEFA15EA2F74
+:10CB800093D0475A7F4F98F87BB92846F0F7CF6C7F
+:10CB90003671BDBB03E40DF28BA67761DCC7715C17
+:10CBA00093B82F930A4A7614CC27F5093397DF57A9
+:10CBB000387EF4BD52CD0E9996D04CF7473F4B0DC1
+:10CBC0003C89F241BB47CA142FBDEFF741AA6FF36E
+:10CBD000C8D1FCDD0C9C03E8C510D6AB93C18ECA4E
+:10CBE0008EB0A32C57A617FF96EA7B06DB5F69FD84
+:10CBF00068393C56C0BFD86E203C2C5E67267FD873
+:10CC00005871BF74ECF963B1284F16FFB984E44A38
+:10CC1000336303E2E795261EE7FD6BF423407ADDDC
+:10CC2000973D32ED470E1B161E01FD4A2090FFB0C6
+:10CC3000B739BE94F23E24F7F55F1A06DC2F6A2955
+:10CC4000D0EB359C9FEF2BBDFFE186AF1CF4FB2999
+:10CC500099CD7545F3EE7F67473F7FEDBD2B985F1C
+:10CC60000FEAF7C59F1B887F177F5E4272B3EB0AFE
+:10CC7000E76B75FBFE03E91A3D1F80FFBF0682BF0D
+:10CC80008FDF7BAF0CFE072546BFD707D415F9B75A
+:10CC9000BBC47B025D0B8AE85D8B7DF82E08CACD94
+:10CCA000C9FCDE5117F60DF5BB121DF4EEC6CB46DE
+:10CCB0009E0FDE29DA8B771ABBEE4CE1EF66981BEC
+:10CCC0007E578CFD37F3F8B82E63887E1F6CD74FE4
+:10CCD00013E83E81163F7E4CC8ED6629FC7D7A0F35
+:10CCE000E47313E3EFEA8553EB4BF11D90E154FF3E
+:10CCF00098F8FDC957FAAEDE5D823EED1DA11DEB31
+:10CD0000018EFF07358A15A9008000000000000091
+:10CD10001F8B080000000000000BED7D0B7894D500
+:10CD2000B5E8FEE79F99CC24936412421E8484C91F
+:10CD3000831024E0E40501421820A1A8680308023A
+:10CD4000C638212184BC0848CF492D3583090F15E9
+:10CD50006B38468D8A3A58A0A0600705440D9E01A5
+:10CD6000D4521F35D5EAB1DA6202880F1E0941FD9F
+:10CD7000B0D7DBDEB5D6DE3B33FF2451DB73FDEEEF
+:10CD800077BEEFA65FDDEC7FBFD75A7BEDB5D763EB
+:10CD90004FDBBC74BBCBC6D80895357832186B4BCB
+:10CDA00072C44542FAA1812DC6FC9F19FCC531F61B
+:10CDB0009881B9CC918C5D655F166D1FCE98F38616
+:10CDC000103D0BC742479C92C3D82315A3D9DD0A57
+:10CDD000645B1F622C9AB1C526467F4B83C326B085
+:10CDE000ABE99F0ED344C616F2CF6CC9F29D66A77D
+:10CDF00005F255E66E6502631F54DD196A83F1166C
+:10CE00003A556F501854B8B1C8D195CEEBFE2319DE
+:10CE1000C775D0B8AC6218639321D57BCB198CFB56
+:10CE200072AF89DD9D0475F06FBA2F65CCC518D43B
+:10CE3000FFCCCCC7AFF3CCB8FF8CEC0FFE5F65B472
+:10CE40006C56C2B13CD1CD60FCFD239CA3EDB98CE6
+:10CE5000AD3A7CCDFD674CBE7A15CB8BD298CE37E0
+:10CE60006EE03881E335BB752E038C37CAB420E3FE
+:10CE70000C346986021DCCD3E531BB7726E1BC7B3F
+:10CE8000FFBC02F2CD8BAFB2DF0DD939F34D0E25C9
+:10CE90008AB1BE0341EE2005BF073B705DCD47421E
+:10CEA000DD3AC8DFAA70F8372B8CBEBBF61BDC3B23
+:10CEB000E15BADD1BD6717B4AB7D79AC1D4666872C
+:10CEC0008CF01F2C7F31849787399236E460790C7F
+:10CED000E1F725832D9CCA7FAF322A0FF6A64500C5
+:10CEE000BC1B639DB310AE238200FF16EC977F3FFF
+:10CEF00089EB00F89C846E11BFAE8650EA9789BC1E
+:10CF0000F317C3DC77D37A1C71CB317FDB385A8FB0
+:10CF100013E701F362F50AADF7A4D57D571A949F84
+:10CF2000EC184EF38812F470B2F8EBB72641BD93BB
+:10CF300087553BF6F99746D56B0CC3728E0F65BECD
+:10CF400029AD1DDA9D7E31D41E04E525F7D5BC89B7
+:10CF5000DF4BEEAC9B4B69F5BA1B18D4EFBAF3A3C9
+:10CF60004467C6407C94D4422B3F3CAEB23B4A114E
+:10CF7000BFF7D89D65B8DE55195D950CE8EAA2B1FA
+:10CF8000F371A632F6FE4867057EEF79E1D35DF8CE
+:10CF90001DF094563C1E96A1073A41FAED9A407452
+:10CFA000BD4AD0EFB04C6735F607702C65298C85EB
+:10CFB00064741A711E6CDDF01F44275F74EC3CA48E
+:10CFC000C03835C11DF594AAEE09D8CF39C51BA6C6
+:10CFD000A4101C9DB8FFCE5BBD61880FA70EF28028
+:10CFE0009F9ADDDA75E19F1EE65583FF8076351E38
+:10CFF000D561C6FDC3DC469C7F0D33FAEA27F17D7F
+:10D00000887400FD3C49FBD5F297D25F001EAAF759
+:10D010008CCDBA1BF0531371F85753A91EB493FB70
+:10D02000451D9897EB19381FBEBEF3621F9C872FD2
+:10D0300006A49FBD419CFE19A78F8B7BE204FD7067
+:10D04000BABDB8678C1BE7132DF6CD45C5A50BC639
+:10D0500076BF64F69D302F66F74C9C371E67EF99BC
+:10D06000383F94B10715CE9F6A86792622BF92FC7D
+:10D070008B993C13E641394BF74C980FF55F12F54D
+:10D0800058B1278DBEBB3D69D8FE908E55213CE539
+:10D090007CAA9F8EDF4EF030F1FD5AFDF438828F6E
+:10D0A0001CA719F94838A6409F6103D7FD5BBBC296
+:10D0B000F77FE8C418E46B43E13F3D765806B2922F
+:10D0C0008B4B8CB73AA0DF31ED464D3FB2DE58B7FF
+:10D0D000F6FB61D1FFA8007C8E507B8F06C17CD906
+:10D0E000AF014E6CE078FF89ED804E9F7AAA1F7FDA
+:10D0F0002AC72763364937368213C7D39F8D124F0D
+:10D100006BE3815FD7204C927DF03A94E98C8F8459
+:10D11000F422E661FE8722200F69BD80BFCC4BB8A8
+:10D1200007D2DF9D7FAE8CEF82F6E7ED3A9A57206B
+:10D130005CD703FCB0BCD9C06E2D86F65F349D4829
+:10D140003963F0ADE76C93C301474D7FBEB23DD369
+:10D1500084FB6EC5B64CD3323FB837EFCE3E610389
+:10D16000BC9EDFADC79158B3DEFDAB2951F85DF52C
+:10D17000B818959B1C380FCBB13F60BDCA6D1159D3
+:10D18000AACDD77E457B91A3C20FFEE3766BF1312A
+:10D19000DEA3CD5F7D589BFF1AB95AEE3FDF2ED339
+:10D1A000ABCD679FD0E63FFDD3DA45B80D9ECFE308
+:10D1B000FBE63377A8DB0470ADFA68F6093C473F1D
+:10D1C0003BF47C18E2ABE6AF15AFC5335C87964EF7
+:10D1D000018F8A1ED6EBDAA510BDAC7407EE5FC1D5
+:10D1E0003706ECEBF5B41EDC59FE741388DF73CC04
+:10D1F000B3C801F455DBF86ECA996C98D75C20640B
+:10D2000098CF64CF5623B30C1C6F28FEC12C0E1B85
+:10D2100003FA2BCBE365531A67B1D3D01FDBF2C7F8
+:10D22000D9B85FCBEE5148DE287B6ECC2B4837DD7A
+:10D23000FB975C4BE9A239048772E630223F5CD150
+:10D24000A17843216FCDB31DEE8276CBDD8A1DE739
+:10D25000BDAC25C8C7CFE0FF155B02E6D1E6570E8F
+:10D26000F35F71F8E8370AF45FB54DDB6E25C00B4C
+:10D27000CF8FEA1DFF08F2FF0E8210C16B4AC776FE
+:10D2800015D7BD5CCC5F9E7FCC55C0707D537813A5
+:10D290007606FF03E746F028676E66AEEF1C9CD269
+:10D2A000C6DB03E32BC375D7598C365C779D897930
+:10D2B00043603E27428D0E2B7CBFDC1E4AF2436545
+:10D2C000107399B22865E62C6C670FC77667DF5636
+:10D2D000494EAA03DE43FD3CA1B89BB11F55E1F9BD
+:10D2E0005FF3FC4AE6A5F520DD38FCD7E9D6E65920
+:10D2F000EB30924B6AF5DEA308976AD645F066805C
+:10D300004F878423C0AD16D6F94124CA5FDAF6AB45
+:10D310009887EAAF3AFC8F20FFEF20673213D4DF03
+:10D32000160C29CDDF4D70548DCCA18379AA7704DA
+:10D33000BB5D24871407239D1AF0BC00B8B6DDE559
+:10D3400048C3796F501C6956E4635BCD76E4634B48
+:10D35000B7F373A82D02E45768DFB6F22A6ABF1448
+:10D36000E529945396707ED716E1F122DF6F7B207A
+:10D3700089CB537F57092EBDF79ADD4F42FDB64C3E
+:10D380002EF7B46D1D43ED915F923C756F286F3F92
+:10D390008FC3B56DB8D5ED82FC873845804FDB76FD
+:10D3A000479A89DA819C96E43BA7A43CFD9B51CE29
+:10D3B000DB10DF72BD52FE66553F4CDEDC29CECF5E
+:10D3C000DEAD304FE8FF8C52FC9ACE4F1E6EC9E4A2
+:10D3D000FC7FE24CC72E51CF8EF52A74F3EE9E0EE1
+:10D3E000F3AD7850676B4EF2C19D391C6908E73385
+:10D3F0005BCD5948671367021F06FA3B99C9F97953
+:10D40000480E73B821BD57F47B6FA64E93C6060332
+:10D41000FD413F678ABC06C46F684EB111CF4338E7
+:10D42000C3899F07AEE361D14F85B1F8F56983CC1D
+:10D43000A79F0E0AB9DC7266B5F2249F17C7F3C422
+:10D44000FF30DB9B69DD7C7E12EE4037B974DE0B6A
+:10D45000BE15D14F27EE3D6640ED56294F23FE15F0
+:10D460000D9D103CDBEE1D4F785C2AF0CCEE350BA9
+:10D470003A61EC6F585E64A372A013824F5B26E0A2
+:10D48000CDE23BF7DAE639E222FCCE23A0032A07FD
+:10D490007CEFCF1C3EF0BE25F1CDF4EEDCE2D0A156
+:10D4A000F1BD2C2F62A202A08ED7335710C005CF3A
+:10D4B0003C82CB5D7AF79D309F917A0EFF043DA7A9
+:10D4C0002FE0CEAEE02CAAEF3042BEECFE15CC0130
+:10D4D000F5CBE2995DE1F55938D6876E5448F1CC29
+:10D4E000C07665E1BCDFB218E6BE53C8FDC8AF52D6
+:10D4F000314DA67E1DBA48DE3E2C8BDABB74BCBD16
+:10D50000430FE9A814BE5F7A3704D1FE29DB94905B
+:10D5100086743077A6960E52B338DDC8B435CB2664
+:10D52000CE197B2CEEEF652D63E9DC683617D71D2D
+:10D53000447CED0B2179B06CE32DD7E7E2FC9E191A
+:10D5400086120EFBE286FD1391DE96B52CF9D97B8F
+:10D55000781FD96DA6EFFBB29C1FE3FEFA42B1958E
+:10D560001E840FCB161E37C6427BA767DE851721A8
+:10D57000BDC1B5FF0F2817DC70A34AF56F609EAFE1
+:10D580003F44BED0C2C7B9DE75491F0BFD5D9FAFDA
+:10D59000302CEF365B1357C3FCCB04FECE09FA6D7B
+:10D5A00036B3C5CF5A705E0969C9F0FD7A94540745
+:10D5B0009103C76609397186B20DE59E51B3F8FE35
+:10D5C00092F5B11FECF76A8407D4FB5AEC2B99074C
+:10D5D000B852FD8ACD41DD2961981ABC63205D9463
+:10D5E00033F36FB8CEB9C96C36DE9B7A7FAEB22703
+:10D5F00069BEBD65B4EF43D36CB8EF9D8C7989EFFC
+:10D60000B9C712DD77CFE8EDDE04F9EEED63ECCDBE
+:10D61000C4D7F9FD7DB995D1F9DE3D83F335C95FF6
+:10D620004E5ABB42895EC57DBE5C90C6278DB31E37
+:10D630009C04F5CB2DC66E3C0F963FB020CC06F374
+:10D640002C6F83FB3C9C636C8BF63E0FF7EDA8AC14
+:10D65000DC81F7F2C0FB37D20CD251C51685E870D9
+:10D6600054B3DD18477C4CB1E2FA2A2CDE543CFF5F
+:10D670002AEC663B969F6F72DC7F06E4C38B4D738A
+:10D680002865DF02DC619E5721F260DFA7673B93CC
+:10D69000B2008E65AD65749F0CC970127F720ABAB4
+:10D6A0009B0B605690DFE8BBE2701FBE9329BE471C
+:10D6B0005AD32C44CF668670E83658D3705EDD1B93
+:10D6C000CC3A3C37E7DEC9E91AF699490FEDEFD2BB
+:10D6D000B360DCEF3DD81EC62B59AF2FDE0EF9919B
+:10D6E00026A60F8D44BACA24BA6ECF717E8DFCE097
+:10D6F000B35FB23C940BCAB76CA5F948BA60FACED6
+:10D70000C26128E7ED4CCAC2FBB5A4A3F69C997987
+:10D7100008BF7E7AB851213A80F4680AD1C3FC6907
+:10D72000583E77A637750DCCAB48AD650ED433C4E3
+:10D73000327B10CCBF8FF5923CD107F2049E6792EA
+:10D740009F48BE0174E03045FBF0BBAB09A6023C2C
+:10D7500079779389D2A79AAC4C0FF0DDDB144BF9A3
+:10D76000679A6C947A9AD2E9FBB34D76CA1F68CA5D
+:10D77000A3FCA12607E50F37CDA1F4C5A662FA2EBA
+:10D78000F912C085F890E42B921F497A927C299077
+:10D790008E4A01BC0559D49EF89EE477B80E5D967A
+:10D7A0008F1F49FC262BC5AED824E4635D4B905FE8
+:10D7B00014A9E7F73D0FF0EDABB2D8836C0817CE94
+:10D7C000F7FA2C263AE7138DEC30DEFF9B573BBA75
+:10D7D00037F99DAB3757294CEF47B7B7349899DEE7
+:10D7E0008F6E6F6D8CD0E44B1ADF7D3506FAFF47E4
+:10D7F000827335D2DFC93BCE3EF65FF0FD893BBE7A
+:10D80000188DF88679EC7C08C75D17DC3F8F48CC13
+:10D81000B718E89C1915CCEF49A382F93D09FF1010
+:10D820003FCB18DFA74FDCF137DAE7DD8D41361546
+:10D83000E50FC417C0F72F025FCB1A83088E651B54
+:10D840004EEF7B1EF7FB3A23F1BB652D627F6E0620
+:10D85000B8FAC96DA7E218C9678A83B14680DFA903
+:10D860005F1ABD70F6B3538AC9AD4043052E4D25EE
+:10D8700008D7CDBFFB00E56DA5F104C9C74E93C520
+:10D88000ABE2FC5C86F3FEFD298DAF513DD635320F
+:10D89000E26C086D4586700CC97118914F206D239C
+:10D8A000FE96A51F63B8BF59AB621D0DEBAA10DF32
+:10D8B0002B362B247748F83F92A5D2BE7A2F534FB0
+:10D8C0006936EED9E1C4C0E89C92740B7CC3E1C612
+:10D8D000FDD19A69ACF4E3C7CBC4F7F2741DA5F28D
+:10D8E000FB7BB02D914EB2114990DE9D9E6C5C4E3B
+:10D8F000FCCE66447E20EB2F4BCFDA989C83FDCC88
+:10D9000088627EFB7257969EDABD9769E5F331C156
+:10D910003906ED6A87380FA47CF219FE7332CD9F69
+:10D92000EE5FD5CF3CFDCC8BA897F82888F0547DCE
+:10D93000B5D06F64B8272E20B9C66151609DF5023D
+:10D94000FF854FFF35AC0BCA571DE0FA5348BB317A
+:10D95000AD5F5745FAB27AB88F1644227F359CEAFC
+:10D96000F2A3CB579EF928AC8BEE17AE785D2CA6B0
+:10D97000DE780669FD81D3B319F6C77A375A2D03CD
+:10D98000DBAD52BEA57BA65C47D191AFA2697CE519
+:10D990004A34D53FB2217A303DC82AA63FD5BF7F51
+:10D9A00049CFE0D0E8D556B12D975498EFAA7573BA
+:10D9B0003E453A0FACFF41566814D20F9BC42691E6
+:10D9C0001E43CF7488EF35260E873EF7E870F61DAC
+:10D9D000FA9755EDD00844AD3EBD2DDC0EF3ED6158
+:10D9E0006CCE607849C8E6E7F405D8470CEE523DA6
+:10D9F0007B55BA2FF4EC0D25FAAFDF7BFF6B53217B
+:10DA00005FBF43C161591DEB2438D51F5099C9FF31
+:10DA10003C43FDCEB0A1E759F3746803D2D34A8FDB
+:10DA2000E2D809F3E933D9C287FBCDE76F829E6A5A
+:10DA3000823C1309AE62FEBD829FC97A2B3BEE3752
+:10DA400022BEA0DE45925F7E1BC2486FC67AFF8071
+:10DA5000F33CB72DDB8EFABD959EFDF574FEEF0D00
+:10DA6000B18E86757C21F4FCB21F6336DF4FC66C25
+:10DA70002E6F9C13FADC73CFA8C487709EB80FBFBB
+:10DA80004039D76F9E16D1CE22E0F61CEEC75C5F00
+:10DA9000FD959EEEB054A8FFE9E177298DCEE6EB27
+:10DAA0005A69E99C80E7E6A70742E6B8297D74F643
+:10DAB0004B30DE05CF8C28C56F5FA5641B383EB6A2
+:10DAC000A973105ECC3D4CC8F91E5ACFB9BDF10AFE
+:10DAD000DD6F11DE20E79F3BF05C988EF6AD4B8347
+:10DAE000479D89EB6983226C42CE34B5A2BCB11448
+:10DAF000A4BB70E07775072ED1F91BF85DD6A7FDA2
+:10DB00001687F7EF5ED26BC09F0EE9B7CECA715E83
+:10DB1000A466C4E03E28BDDA76D3CDC8C7DE307037
+:10DB20003C8CB43D84F7AAD2B78791DE628DC116D2
+:10DB300083F92FDF848B20CCBB345BECEFD8AE5C59
+:10DB4000D4737627F173BD76335C54603D2300EFC8
+:10DB50002E5872AD5B654EC8ABE23E734D7632AD6A
+:10DB6000EF912A9DC34876166F1AEA3D4F1A994BDA
+:10DB70004579F95933B7072473BDFE2348EF90D692
+:10DB8000467AD386A1FE4BE0B1763E94FBE1B3F634
+:10DB9000496F1ACA2FE78D5CCF87E5564CB378BD25
+:10DBA000664137D80FF6DB9D64BD4872E6C15086EA
+:10DBB000F2BEEEF950AE57F88DF9C920BF737389E4
+:10DBC000A02B90995CB87ED74E3E3F9C17CACF2BB6
+:10DBD0008DAD69285FCA715786B5D278E7C5782BB5
+:10DBE000835BB97DC2C8F591589FC63730B2A3F4A4
+:10DBF000EE092239F58BB8CE4338FE177BC6323C8E
+:10DC0000C7BB93DC9587A91CE437C047F553415E39
+:10DC10009CEFE77B42DD0CEA7F6EE0F2D0E7A1D11A
+:10DC2000240F9D087DB094EC323B8214D4AB7CAEC3
+:10DC300030632C96EFE4768CEAA646B23F54C37666
+:10DC4000675994CE6191583E96F42D9FFF1EF6A918
+:10DC500042DF37E377276B2DBD1DF7DDEE10D2BB1A
+:10DC60007DF1D4FF1A3B98DDA27A8756BF24E940A4
+:10DC700096DF9ECDEF1BB767F37BC11DD9FC9CA936
+:10DC80000BF13C984CEBE4FB15F040F72ED81FD17C
+:10DC9000A8EF3EE979215AB1209CBD698F22DC773B
+:10DCA000F3FBCD177B0D6477A97E3ED4417A9C4D62
+:10DCB0009374785E54AB5C0EAED601F82055EED866
+:10DCC0009D867276F31E7316C203E04DF7C8DE9D83
+:10DCD000AA18878FFBF9AE04AED7F78AFCA1F1A48E
+:10DCE000D79F1BC96E9D4F72CEB60908D7CB3B425A
+:10DCF000744817308E4301F854DFFE0B0ECFF04A04
+:10DD000092CB61FF11BFAC15FCB26ED3D4F0A9B8B1
+:10DD10009FDE5619CA0597F5F618E48781F07A4B0D
+:10DD2000F0959A438F19D16E570BFBC609FBA64697
+:10DD3000D8C76A9E5248AEABD938F521E2837F300E
+:10DD4000B0D1308FF39EFBC3FCF1F1BCE067BEF6AF
+:10DD500076AA5F03F579FB37C2683EBB0C769C4F11
+:10DD6000201E7F70FBA7D41FD4BE9F3E3C70AE4FD9
+:10DD700018B8EECBACF3DF3E427EB2D74CFA2BC0E4
+:10DD80007B22CA1DE70C9E4A5CF7B97D66E233E749
+:10DD900022F87EFF14F8A16B0CCEE3BAFB48BFF16A
+:10DDA000CE0286E7C10AB7B65F396E87E0BF75C39A
+:10DDB000ECE1A827AB033C607F80979F52FBB70D37
+:10DDC000D43E701D8F8A76FDFB735F08D1CBB911ED
+:10DDD0001C1FE79E1943E74A7704A773986F22DE5A
+:10DDE00057CE45F094A1300274502DEEA3E766782B
+:10DDF000E8FE7D4ED94F69B781B7AB6E147663A04C
+:10DE0000BB58A41BA449B48799B674A23C81FAEA12
+:10DE10008959947A832207EA9D913EF11C8ACAE1CE
+:10DE2000FB8BE178D1C2FE41728AC7887CD929E494
+:10DE3000B8DABD03ED7088DFDABD0AD9912E8B7395
+:10DE400010671D25F5E5408F352EC561C6F9B4ACC8
+:10DE50005E4976A486AD3723BDCB75D4E8D91CBC0A
+:10DE60000F752B2ACDA7DB0CFB06E1E03F9E9FDC64
+:10DE7000F577C10FF0CF1A4D722609D7BA1C1BA730
+:10DE80001FC8B6427FB52DCA161A2749DE2BF9FAEC
+:10DE9000249C002C46D497C17D9F970FB17E39CF2B
+:10DEA000C0F5CBF944E770FEDE9D64BB2F1FF1FD8A
+:10DEB000966AC77BFAE56FB3C323BF432EC39B5B50
+:10DEC000BFDE18E69F823405EB3A8BFC0DF733EA90
+:10DED000A5619E69DBB4F690F41DDAFC557BB5F9BB
+:10DEE0008C03DAFC840E6DDEFE8A361F22C6957026
+:10DEF000C27BAF6D0CBFF7628AF75E5B10BFF76243
+:10DF00001EEFBD98E2BD17BFE3BD17F378EFC53C28
+:10DF1000DE7B318FF75E4CF1DE8BDF6F1470AA155C
+:10DF20007A47C403DA65D80B666967A7FDD2B324C4
+:10DF30009AF8A7B493F6ACCCA07CBF5E679E89F438
+:10DF40003AA4BB01B964C1486741CE70B49F766EF4
+:10DF50008C43BCE9BB489FBBEA45AECFADCD325B3D
+:10DF600050CFD0B5E1D38D283EA58D74CECA81F5B2
+:10DF7000F6187A77111DE8BDC437BAD6DBDE9ECE1F
+:10DF8000F147FA0E6689A4FB49199E779143E33164
+:10DF9000D0AEC2B668ED28817695407B4A201D48F8
+:10DFA0003BCA1386DE38E4F7A7F798B6E0FC4F0BC0
+:10DFB0003D195B6C22F94BCAD545AA85E0B4E65EF3
+:10DFC000E5493CA72A7222A97DDF0990B707396F7E
+:10DFD000655A7E259BE4EAFEFC164547761AA78320
+:10DFE000CEA1DBC49C1295DEEE4D4823A13A3AC780
+:10DFF0002F5B74742FB8FC2795E48831ED3ACD7A05
+:10E00000C6BA8335F4356E7764803D7084A6FED53C
+:10E01000879303EC815769ED5437AE3F8AF7EB05E0
+:10E020005BB235F52A8AA706C051CC5BC8A5CDEBFB
+:10E03000DA1391FFDC16DA47F3BFEDA099FC2E2A24
+:10E04000E07C71C0BAAB3003FCB1CAE4B801E1575F
+:10E05000E53144A05EAB5C9C3FAC517B1E57E99917
+:10E06000CB1AE9A3BB2A2B734440FB0B99ADBB74BD
+:10E0700080B70BBA6D0FE6DBD0BEB43DD10A74B5E4
+:10E0800056F1444F86FE4E4738FF03E933D1E0FD99
+:10E090005509F2CBFD296C3DD43BBDE5B93092BBAF
+:10E0A000059D251AACC188EFEDAD2ADD0B503F85EB
+:10E0B000FA20490FDB5B8705A75A7CEBF4E1FF5B95
+:10E0C0005A1FE085FC46FA2CC746DE86729C87AF55
+:10E0D000B76A86E2223959AC678D3857580BEF671B
+:10E0E000ADC89F11F705B9BEF3638F4EB0A15DB304
+:10E0F000E970A28A7C5CB777571CCA1731CE7DB80D
+:10E100007FAAB68FFEAF7C18B7FA3D95A11DF99393
+:10E11000B659619351FEDC67B0CF85FCA6D65F1B74
+:10E12000F15E50AD771BF1DE59B567BB11EDFF3FD6
+:10E13000D9BD9DBE57EE2EA3FBF60AD640F7C8CF39
+:10E140000CFC9C96F0A89AA96CB3C2BC87E772B984
+:10E15000AF2A98FB8314A9F9AF46E17A772B99B8D7
+:10E16000DE1B8BF71BCBE0FBEF047F09DC1F7D6F11
+:10E170002E281A8E7A250FB7830EB51F167AC7D2AE
+:10E180007E58702589D21BAF8CA37BD57BAC783CA5
+:10E19000F1898C80FBEC9B2AD79B75F07D5065F450
+:10E1A000462DC07DF2B281F6491DF0AFBC2CBC27D4
+:10E1B000333605D2E27C5543AFAB0A4334F4BC9806
+:10E1C000456AECCA8BD8084DFEC6B9299AFA37DDE4
+:10E1D000382E80FEB37CE5C447A668FC57EAD6B962
+:10E1E0006C0AE9D1666ABF43BA8EE8EC5A4DFB3A35
+:10E1F00036DF570FEFC13BFE487066ACD388F7ADF2
+:10E200002A1DF7D759ECEC16DFBBE83B2C44B30FC3
+:10E2100047A5D8FF8B9F8B06D2CF4BFDF462FC77CE
+:10E22000CA60E722205A8C1BAE72FD82532B777492
+:10E23000D2FD93713CD4097D4F5D3AD7F7D4B93AFA
+:10E240008D0D1682BF3E1E4052DFAA903E0FEA9B04
+:10E25000E223797E1D7E3F60F0E95918EFEF0A96C0
+:10E260009F50CB70BF0496D7C3BA51CEA8477D0D3F
+:10E27000E999E67C4A7A26398EE85FD2E98A76AD5A
+:10E28000FEA81EF53A7EF85C9A6B237AADDEBDFFE0
+:10E29000B511009F05C51199B88F6A3DF30C65193A
+:10E2A00003E94DF2F9CB553AB27BF7BD799CE8AD65
+:10E2B000AF4A4F74FD7D70A97770BD66201D56C2B0
+:10E2C000BA4C307EE501C5EE56783D84CF08A4CF28
+:10E2D00000F8C40F023709AF7EF80594AFC07FE4A1
+:10E2E000A03F81E2F6260D06970078CA7102E0C5CC
+:10E2F000F2B4F0A874DADE46FE53794265EE1FB040
+:10E30000FE15B84E9C07AC13E731FF0AD79B487B3C
+:10E31000C2A22B7ACAF7D34D31C02B0BF79D769F43
+:10E32000F6D35131DF370BAF4453BB1F8B9EBE8FEB
+:10E330008EE4FC25DFF6EDA33B896F3A7343A3CE51
+:10E3400002AB807FE7125F10FC7568B9D4C5F9A8ED
+:10E35000537BCE8CBA238FFC8EFA2CC92457F49FA2
+:10E3600043566DF99AD0E4182C770ABD9DE4C74E48
+:10E37000514F8E5306E5B66148D723A3511FBBB159
+:10E380002525B1CB4F5E716E3044A3BE3071FD3098
+:10E390004ACBCCD6683C47CAD6ABC5783E9EBA2B92
+:10E3A000263A0FF5F31B0C5173A1EB533FCF496491
+:10E3B000E3315F44E9E9AD418BFDF5DC32BD4B9CB7
+:10E3C0002775777C40E7DA05DD9B618B71DF6D385F
+:10E3D0001886AE37351BDE9D6805916453847373D0
+:10E3E0002ED951B7EFB222DCACDB27A09EBA1DEFCD
+:10E3F0001EC37DF243F586A218D48BD5FEFDF8E34B
+:10E4000078EE3BD71BA251FEFCFC4F702E2A74AE57
+:10E4100091DCF09999D17DE9B39D216EB4DF7FA69F
+:10E420003007DA7756AA47275835E76CC7229CC7CA
+:10E43000EE18673B1FDFBD2B16C7B7BBC83FD3B96C
+:10E440007E74F8607A1499AE6AE772DD2EA9C7155A
+:10E45000FA5E94E7318FF23C1BC3E579CCA33C8F85
+:10E4600029CAF3F8FD90D0E38F6AEECDC4FBA86B08
+:10E47000264B6FA073D7928EF2FA6D4AB01DF9CF7A
+:10E480006D8A3D06F563EC4F11FCBC0DC0AF4CA787
+:10E49000F582CCE547F7D3AF9898BF9FD90C16A16A
+:10E4A000C9CF32C569EA17599334E53F891DAB29B5
+:10E4B000BFC696A9C95F973E5953FF7AFB0C4DFE24
+:10E4C000A779D768EACF73CCD3E417CC59A2A9BFF8
+:10E4D000B0B84C537ED3E2959AF225CED59AFCCDB6
+:10E4E000553FD7D4BFA561BDA6DCC1AC7A3CF73A95
+:10E4F000F09E05707F19EF5990DEF6D6688B3F5E6F
+:10E50000F367E91A06D3D37F2CE8376392E343A479
+:10E510008F041DA743481D28425C10E74A3CF32A9C
+:10E52000FC9EDB19877413582FB03C3FE4D8651B61
+:10E53000E0F0A6892137EB813FE44F3A969D02F93E
+:10E54000270ECDE3F9A9C79E4B86FC6F26DEC7F3E5
+:10E55000571FBB8CE5A39E5F74B31EF84EFE0246A8
+:10E5600022C77387BE5EEA8275E44F4FDE62E77AA8
+:10E570009241FD34FBF52C0007F46F443860EA0546
+:10E58000FAC4F418D027A6AF007D5618187B0DE802
+:10E5900013D31370DFC4EFAFC37D13D337E1BE894C
+:10E5A000E91FE0BE896927DC37317DA76931A57F86
+:10E5B0006A7252BBF79BAA28FDA0A981BE7FD8D45E
+:10E5C00048E95F9A5CF4DD3C51EA2FBCA47F917668
+:10E5D000A67AB4EFA17EEEB0E1BCBF1D56DA09A564
+:10E5E0005DB0B9817585E03EEDD2479C35F9EC7D93
+:10E5F00043F3593D3BEB27876D8D75444D24BDC6D4
+:10E60000482BD97BC4F799CA820434FDCD9DE01C08
+:10E6100081E50BB3CA378403FF98FE6D8301E9E5FA
+:10E620003DE1A71AD8FF855C2E0F1B2639464D8485
+:10E63000B4C0C4FDF00A4CDCCFAE40DFD58CFCA8E2
+:10E64000F92B66433F9AA3A146E24FCD77E9DDA8B7
+:10E65000A754BE64949F16C528DFFC5527F9E5151D
+:10E6600058EDB174DE887CBFFD1CFFFCFC65A43D49
+:10E670005BFAC9147ED9350BE5806916A32D28C035
+:10E68000FE8E76EBA3A1EFCBF9301C4FDAC9777C75
+:10E69000C5BCBA093E7B7881A93309F504D3D69A63
+:10E6A000ECFEFE3FD2EEAD7CD9A9E27922FD7CE4FE
+:10E6B0003872BEA17AE82FCBE7C75360F564A25F3A
+:10E6C00043739D85FA8B81EFC62CAAE750A99D273D
+:10E6D00013F5C0D36A2D76D46F4B7B7B8C5837D41F
+:10E6E000A375167EE9247F8369C2DF00FB31F172D6
+:10E6F00017F6332DCA1BA7C7F53718EDA80F7D4CA9
+:10E7000081F6593EFB3FD60FF1DBBF384FEC37F5B2
+:10E710006B982FCAED0E07C17781BCBFD9445E9CB0
+:10E72000CFCC3493F457AAC81F9BE07422DE8B83AE
+:10E73000AC7F0DA17D9E92807A8E79426EFF0E7A1B
+:10E74000598E74F6DFA71707C7F74846FAB440BAE0
+:10E75000917891781E8A8E24DEFDFCB508CFFDFEEF
+:10E7600057A29F40FA1A8AAE243D159838DE11AFA1
+:10E77000E84723E948F9D2B39DD6516BA2734ED234
+:10E7800051201D0CA4234E97CD3F33517F03E9C880
+:10E79000877F84C7BF4E479D2A9EBBFF2CFDDCDAD6
+:10E7A000CB668743D12FAE765EC8457FA02BB6D708
+:10E7B000305FCE66CC469292E52D439407D297AC5B
+:10E7C000FF34D6CF1D58DFF965AF21DC8F2EA78926
+:10E7D00033F0F521FA7F43F8C5BF6196FE1E0E4B5C
+:10E7E00026D0C12CC1876F2BE2F4352749257BC683
+:10E7F000AC8C1524DF330B978F6DF03FD2B709FB3C
+:10E80000FAB5A2DDEC6F8B5B709CD9515AF9FB5ABB
+:10E810002177CF09B0B75F9BF11392C3AF0D90B3CF
+:10E820007F3F51C8D1492C89DFAFB790FC5B28F6F8
+:10E8300063BCC0778A4D65F900F722E6D4E321F086
+:10E84000CA45A303FBFB097351FE1AE6A6F43AE698
+:10E850002539E07A383030FF53D87A983F1E72431A
+:10E86000C92AE86F56F6AC54FC5E6BEA4D34EAD028
+:10E870003BD0F921EEE77AD5F931CA9917129C639A
+:10E88000F07E7CACD04672D831530AC985B89F0C53
+:10E890007EFACADFC3399A0AE7DC713867317D1521
+:10E8A000CED95438EF7E07E72CE6AF4D5FCFB0DD11
+:10E8B0006C9BD6BF47B6BFCE3A8BE9870D7D8E5D88
+:10E8C00037E18591A8C77A23624C21E2ED8D884912
+:10E8D00085B8DE372262743C0D32523AFEF9D4C15B
+:10E8E000E45649AFBEF166D37881F095F00C84A36D
+:10E8F00084EFBF004FFDA4DC81F0BC806730EA4F9D
+:10E900004DEF86C526A39D51C4D385703E58F7FCB4
+:10E91000F8185C47AD89C3655AE3544A0B1A27338C
+:10E920007D36D9995C08DFCF7109A8700ED0B3315C
+:10E93000FD4CCAFF4CD0567A8C331AE7713ECB9B04
+:10E94000061219FB745B7318FA675E7846B5E3BD6F
+:10E95000A656B56DB1A39EFC0D95C7057D7B3C11F8
+:10E96000ED9B6CC7E0FED2B526093F17C1B5ED6A35
+:10E9700007ED3786D6D9689F5C333288FB199379C7
+:10E98000216B6839676230E7332383387F94F882DC
+:10E9900076FCDC857E26025F8BBF2F98EE3579A34F
+:10E9A0001CE3713DAC9069EE05527FD117A5D2F9F9
+:10E9B00050C0D21EC2FB7BE10903DDDFFB0A192F29
+:10E9C0008FE5F6CABE139755DCEF45A10A1B96E406
+:10E9D0008B9B098AD5319B9F3C6DB605339B1FDD10
+:10E9E00086A4476AF2A1F6119AFAE179C99AF20867
+:10E9F000C7559AF26173B234F9E1C55334F5631621
+:10EA0000CFD4E4E39CD76AEAC757CDD7E4253F8A41
+:10EA1000E79F5842C3524DFB518DCB34F5935CD5E3
+:10EA20009A723538EC498A3B75393AD3A3915FF134
+:10EA3000BF94CD6B34F51E0DE37120732C9573716B
+:10EA40001F8E6EBD5D3B2FF54D85E23A6D9C0FBA72
+:10EA5000E07F88DFA2582D5F9C65D5EA1BE21BF49E
+:10EA60009A7CF524E18F34814D203EF87D78765EE6
+:10EA7000A5C173203C00EF762FD68773D505F9A288
+:10EA8000DF97EBF1DC47BB82FFFCD1AEE0BF5EB4A9
+:10EA90002BF8E7D1AEE05F1FED0AFEE56857F02FD7
+:10EAA000CF3EA1C5736EA716CF933ED0E259D2DFF9
+:10EAB00050F898DCA5A583407C4CFD2C802E041ECC
+:10EAC00016C3FF06C3035D1180FE673530D29B7D00
+:10EAD0001F5E1E9B24CE278117C003C5F5F58D0C44
+:10EAE000253C3C26E65FE01D4771B145A8374BF257
+:10EAF000ADE73171EEFE769873F724D8DFBFB365CA
+:10EB0000C5223F9ACEB85D7376ADCEEE85EE9F0AF4
+:10EB1000C0FF84B1CE7D587FF1B0CB8946A4875E1B
+:10EB2000E718BC4F7E28F424817E9C2E1007280E07
+:10EB3000E17695E26F4EEA5A15E4CBDE04E721E474
+:10EB40001BB76634109DC6B2E2FD9530BFD2FF0CF4
+:10EB5000223B4EE9281EAFCB32BA28CE41F2BBD2BF
+:10EB600078EE47F4F2246117B6737FA2A393B83C02
+:10EB70001B6AB792DF7159068FE3806B5762E978A1
+:10EB800084CF9BE631089F366E37E9C278E1285F73
+:10EB9000BC30CA9B28DF2508F9AAF9CF2613AE633B
+:10EBA0004C3BD39C9363DD268DDFEBB8DD564D7E69
+:10EBB000BC275653FFEAC3364D79A6375D539E7D79
+:10EBC000C2AEC9E776E669EA4FFAC0A1C94FEE9A2C
+:10EBD000A3A93FF5B3624D3E9EF53E8CF01DA5F016
+:10EBE000FBFE3793B8FF14EC55B2E3956E8AE071E3
+:10EBF000A0420F20E569E90FED14F41D28A78F321C
+:10EC00007239B5398EF17B9849DCB798565E770A30
+:10EC10007F6629A73297D69F59FA31F7CBF5426E16
+:10EC200097F2B19F1FB3C3DF8FB954C46F079E7FA4
+:10EC3000863CAE1F099CFF28235F6FF3CF8D1437EE
+:10EC400022E715381F6716A7DB9DA6C1E37786E587
+:10EC5000713DC1F8CCE2903C481F37D8DDA447197C
+:10EC6000309EBDCB85F7CA5F1AED77DABE7FBCD286
+:10EC7000ABF97A4A74BA5BE76590BFD8E267FDC624
+:10EC80004F11E3064D51065D5F6938F7E762E146D3
+:10EC90001BD2EFD0E37178C61A590BC51909BFFF13
+:10ECA0005BB678EE1D034525C65603292F98DB80F9
+:10ECB000F4307726C853998C1DDAFFEC2316906741
+:10ECC0001E6FD4939EE7AAC33125AE545F1CC7289C
+:10ECD000B86F207DA0CC82F7944727737FE5EBF2D5
+:10ECE000F8FA8AD46FFBFDEFC97EC198382718F96E
+:10ECF000C30C426F4487721D3F963FBEA4DB403871
+:10ED0000C9FB2513FE8EA9625E127E723F48F8C9C8
+:10ED10007808DB6A43F193168AAB98837E64127F8E
+:10ED2000BF9DCCF9D12F053CB01EF2A3A1EA15A9D5
+:10ED300019E1A80FEF63B670EB77E87B7FC4380565
+:10ED400082FF50F15543F187017C618878ABA1E8DF
+:10ED500093FEFE89B82B3FFEC0FD7A043EDCA93A43
+:10ED6000B2A36F0AD5EEE3A7047F9827F6139CE3BE
+:10ED7000964C2D9F60A8BF6FDEA00A3EC1CF6F9456
+:10ED80006BF0FBF20D063A4F192B7E10E3883E69BB
+:10ED900033907F6B81C336DBCEEDF324DF90DD0B48
+:10EDA000A656E6D29EDB20473C89F789E9CCBE1106
+:10EDB000ED19E59BB5E52B2CB33F47B96179C0BD93
+:10EDC0007485B8AFAE08B8976ECB13E7B19DD9493B
+:10EDD0001E1376FE2A51A79F8EDC29E142EF42FBEB
+:10EDE0001352F20B9370B1A1BD26DB9707F805A76C
+:10EDF000E339DDA21FD45FAF1F7E43F8239C477F1A
+:10EE0000041BEEF73E8AB7EA3B60E6764A690F12CA
+:10EE1000F5CFBB2E5339D6C7DE2E64764E4079A788
+:10EE2000DF7E146087EAB3E8C2F2B0BFBD06EA4FE6
+:10EE3000FA5B54FFCD3DC1EA674F7676A91AFF967B
+:10EE4000C0D4B9FE20F95F6C8A70BE8A7CFC9CDE5F
+:10EE50006E42FCDD6539168D71F27385DE2670BE5B
+:10EE6000FDF26DBEC2EDB02E1E37DB3747213F00ED
+:10EE7000E0830CF78DF41B98C7BC51984A7B8C73C8
+:10EE8000F36482B3B4C7947927D33C1736AF300408
+:10EE90004395AE87D71505DB7C769AAE04EEF73343
+:10EEA00094BD66C1954CEAEFC62B53A99F337949AF
+:10EEB0005CEE6AB97735D2D155BB9901D7D915E047
+:10EEC000F72ED31B27F3FDB01A633172FDFC89D6F0
+:10EED0002B44E76B1426FD8B884FCBFCE556912F16
+:10EEE000E2F9DB36F07C9781BF33B34BE81B709DB2
+:10EEF00098E27AF05EBC57E823701D98E23AF03B46
+:10EF0000F225CC235FC23CF225CC235FC214F91258
+:10EF10007E5FC68A1333556E572AF4DB3768572A4B
+:10EF2000F4937BD0AEE49F47BB927F7DB42BF997DF
+:10EF3000A35DC9BF1CED4AFE79B42BF9D747BB923C
+:10EF40007F9EE55DE3CB231F73CCD3E417809C5FEA
+:10EF5000E8B76FD1AEE4DF3FDA9534FD39576BDAAD
+:10EF6000DFCC1A35EDD1AEE45FFFD646456377BA04
+:10EF700055BC0750DE3E8CE863EF84E2A4C980DF15
+:10EF80008F43FEFE3303DE37D48E9548B76BEA829B
+:10EF9000ED1CCFAD7338DE758CE3B97709E1799D4F
+:10EFA00091E78BB8FFF160F69B4203B7DF608AF60A
+:10EFB0001B4CD17E8329DA6F0A4773FB0DA668BF0D
+:10EFC000C1EF68BFC114ED3798A2FD0653B4DF60EE
+:10EFD0008AF61B4CD17E83EDD07E8329DA6FF03B1D
+:10EFE000DA6F3045FB0D7E3F897624BF7733504E74
+:10EFF0004FD5DC1F810E35F747AB268F72BA7F7D68
+:10F0000094D3FDCB514EF72F4739DD3F8F72BA7F36
+:10F010007D94D3FDF3CBF36CB4BF505EF76F87F2F2
+:10F02000BA7F7E7CABEB55D41D5DBFEDE22B9876AD
+:10F03000852A8F2BC00A964DDE578276B62EB39264
+:10F0400018019CD2B0FED99242D8B34EE1C73781A5
+:10F05000F5EA10DF646707BC39BD8CFC8EC77F13EF
+:10F0600047E5D2AE4B7F80F7CC038CE4FE43225EB3
+:10F0700053B6B733AB8AA9ACEFCB0F5E2F707C5978
+:10F080008FF8A5DF3CE06298897E2699EB2C59E841
+:10F090002FBF4BA7707FD33BB9BF6F205D3D28E4E6
+:10F0A000A05DBAFDC782D17FA84CB1631C439A9E74
+:10F0B0009D3064219C1AB2503EB8637284F0076E92
+:10F0C0009882FE4772DE520F087C82E2D7F27B996B
+:10F0D000B102C699F625332E47FE6EE47201B6C31F
+:10F0E000FBE23897E278D28FBE374FE6E79BD3B585
+:10F0F0007A4A057C1FB7B7610AC6C5CD0DE6ED7E1D
+:10F10000F34418C1F18616E5498C3FCCDFCB1C18BF
+:10F11000EFBA55F0D3717BADC60A1AD74AF174B273
+:10F12000DFB26D8914FF57C6BA0A31BE82E5280CDA
+:10F13000EDA3126EB0BE57707D69B0550C247FF2FE
+:10F14000B89C60119723E37182228A17E6E5FAE200
+:10F1500072A6E54414A15F1CEB60760C03BE3EA7CB
+:10F160006CC370E8DFE976D8D1AF68DA970DAF529B
+:10F170007E4731E5890C26D23874AE8D7129F4BEF4
+:10F18000C60DAEEDBA281BC6EBAE374463FDBDCC51
+:10F190008EE20E1C3514772AE797C13A756605F1A1
+:10F1A000CE8E0FF3A323E0003722DE33ED067A7F05
+:10F1B000639EDE6A40BE11788E0FF45B0C901302E2
+:10F1C000FC4B9AD77D90A826A37F89CEEE45BE75CD
+:10F1D0003084E40529EF94097FB3CB2DAF0EBF092E
+:10F1E000CACBF673F9C0D9AE10FF93FE267529EE8F
+:10F1F000441DCA0B23B64F8854F9F98F7CF19CEB60
+:10F20000B945B845CB36BC4A7111651B72C3795CF0
+:10F2100014B7435408385508BF2296618D4639F318
+:10F2200014F01DC718F24B0CA7B8C2562ECF49BD1B
+:10F230008E9407E5FB31656F65BF86782F7B4CBCEC
+:10F24000CBB2B98CE2AF02FD7C6A84BCB7B2C540D8
+:10F25000FE432B03E4C11AE12F5413200F9E9C2C74
+:10F26000F440521E14F717E9CF5BF6D6F18524AFB0
+:10F270003418C82E57B29ECB2F6C3F73633C43C9E2
+:10F28000FA593A7C37A4E4A0C3AE0C42276F0B397D
+:10F29000666E9799E03AFF4A3CA58BAEC4517AD38B
+:10F2A00015EE4789B12F48075D2F3092A3DF157205
+:10F2B000CB42F4ABC478445790F09F642437653256
+:10F2C0006B11F28FAB1CCA7114FBE61A9C1BD06F3A
+:10F2D00073EE7646F147D7A37C03FD2F467907F5F9
+:10F2E000EE39494514873147A17896EB73560BFAEE
+:10F2F000067A6748EF2E41BFC594EF3F17049D3B48
+:10F300005DDD7A84FBF52EC588EFF039C53D56D218
+:10F310007120BD978608FD9385EB97FAF54F385914
+:10F320007AD4C6740BFAB796A26E7004E388079875
+:10F330008766F0F2D829A65B5AF052F3DFD44B94DB
+:10F34000E8743CDE09E42DE4ABB7ACCD342EF3E336
+:10F350002F9F4C9D39696AAE0FEFCB02E2F4D6DCE9
+:10F36000353AE6BBE245CB01CEB84F4AC3BB7E0679
+:10F3700014CAF2A6304721889E4B985C27F3A25FFF
+:10F38000E052915F3E25F3AF9B33083E94CF793135
+:10F39000FA1617F155CEB76E46BEA522BF72664D5E
+:10F3A000217ED5351BF11192D12BDE21E0F10E81AA
+:10F3B0007A88E553381E02F511E5199C9F33BD2D5F
+:10F3C000F1668A0BB6913E4FCEFF94411BA729D31D
+:10F3D0005BA670BEFC63C537FCAF14E70DB8BE0773
+:10F3E000753C6E7E84DACA845E88F6BFE41F4CBC2E
+:10F3F00023E1C33FC869644757ACFEF8776E56787F
+:10F400009CFA10FA1B96DEFBF04ED4DF351919C6B4
+:10F41000B93E91C6E9E889DB8D248797183B5FC523
+:10F4200077B2241C3F6AFC0F03E9FF997734BEFFD3
+:10F43000B5B4C16C47FEFCC9D4E28A29C3111F765A
+:10F44000C2C724D866D8FFC984E215F8BD6ECBD1F7
+:10F45000C7316E7F554712C591961DCEDC88EF8966
+:10F460007C32D5598BEB2DB3588D788ED7B744D0DD
+:10F47000B9561A23E23A592FD9A924FC5BA6F0F316
+:10F48000744A3EEFBF47DC479061CED3D4137EDC95
+:10F4900001FB44EA0503F50B81EF380CB57FA41E90
+:10F4A00001F506463FBDA2D44B18D24F2DC173B40F
+:10F4B000C4A88D3F94E941A97713F7C1E5FDE7584A
+:10F4C000C6EC18949BB72A563CC72A2CB69B2643F9
+:10F4D000BEE284013D30D9DC481B7FBFE32EFE7EB7
+:10F4E000C732D8AFC86F4A843F5645FB64DA6F1500
+:10F4F0006E48B387DE97376F3D9EF002D28FD741BB
+:10F5000071F915568731D26FDF97B72A9AB87E996D
+:10F51000DF3945A5799780988EF0BB656D9211DF34
+:10F52000D02901F102FDFB0E4EB169E2AAA11EF93C
+:10F5300035CC4D66AFF1F79360DE497CBC2CBFFE45
+:10F5400097B56ADF2780FA2417FD764A28E1AFCC09
+:10F550000AEB4EC2D44AF30438109C7AEF85FE6C55
+:10F56000340EE1A3DCEB36E0BDBB04FD2920BFD4A3
+:10F57000EA36E038CB5AF87B21CE2D7C1CE7E60832
+:10F58000E378949BF4566302C20F2FCB51343FE2D1
+:10F59000831500178CB792719781F02913F3AD682A
+:10F5A0008DD0CA63AD5B0D888F2543BC57D02DE845
+:10F5B0007659CB0C8A37AFD03B289EC129E0FBC9D6
+:10F5C0006AF3DD681758D2F6902109F27F14F4DB54
+:10F5D0002DF6DDDC64EF687A1768B5D98EF35C62CE
+:10F5E0006DA5F5F5C3F701808782EFCF14137C81F9
+:10F5F0002E5CE89F57D1A6C5A76F3E1CBE156D6552
+:10F60000B4DF2AF54EA3D57F1EED4747A31FCA12CC
+:10F61000D8DFF8DE11B33A29BEE9EC033725D23A38
+:10F62000619EE40765B7CDC6777E804E888E25BD86
+:10F63000C8B86C39DE3753785CE637DFBB2F1D2442
+:10F64000D734037E51DF3DD4BE346260178C6BAC7F
+:10F65000E0EFAF05EE53B93FFBED07629FCAFDFB3C
+:10F66000B8A1D81BABF8F80C9CB70DCF0E02A74978
+:10F6700053F97C970ABC025C5FF18FE3B24DE578E9
+:10F680002D49D6EE77EC0FFB0D93E533BDA331EE9C
+:10F6900052D697E39644F27648F7486F61623CACE5
+:10F6A000BF86EA6BE351CAFBF9C5DE0DD1C82FF660
+:10F6B0002B24F7AEB9F778C2BFA33CBB8FCBB3E71F
+:10F6C0006A77D6C7A1DCA87727FABF8B55E1E5FC9E
+:10F6D0006139C83FC82F2AC539BD2FCB9930D5CF46
+:10F6E0007FA2E2FE7D694ECE5FBCC85FFEB2EFA591
+:10F6F000F7A6D87CE7A79CFFB2CD7F349459FCE1F4
+:10F70000C5D777777A1FC5D9955B8C36F45F2E6F96
+:10F7100029237ECB62E15EA1F8F01D4807652D0A22
+:10F72000BD2F56DE38D1ADFE5FE4CBE55BE6D19B65
+:10F7300048124FF2BD13799ECAF93BC4FC970A3AAE
+:10F740009E3595EFBFA55549C64ADAF749C672A45A
+:10F750007F51BEA442FBBD1F4FFD76EC8C8DB83FA0
+:10F76000306E88EE275B0C5CCFB73794E4D5736BB3
+:10F770009EFFC322A8F7C583DB13513E91F35821A6
+:10F78000F479CB855EAE52C8AD80A7F953FDF8EC95
+:10F790008A27389ECA9F79EBAFF82E5749B2E067A7
+:10F7A000F7F278FE659EFD84B7259BB71A92105F2D
+:10F7B000F848AD5FFBF206B8E8023C976EDE6E409B
+:10F7C0003EB04CAE3780DE4B84BFAF842B9E3B8A6D
+:10F7D0009FDD42D647FEB71FC659BBDA1C86FA69C1
+:10F7E00039CE3D53B9DC54DE101189E3953794FDD1
+:10F7F0000AEF1D92DF07EEBBD366BE1F96417FB8AE
+:10F800002F4FCFB0535C33DAB5063B57EF9CCACFCE
+:10F81000D5470DFCFDC6F810CF1E8443FCAA603B03
+:10F82000F287D4D42EB21B233DE3BC8D3AFEDE63B7
+:10F830006A6DD7259C0788D4E49F8229BE33852230
+:10F840007634E49FD4F1F8AB6495A7BB057CA0DCCB
+:10F850008BE52CAA8BDE9DEB7F3729805E8D6CC7F4
+:10F86000667CEFC618C5ECCD361F7DCA7E247D4A66
+:10F87000FA1D6A7DEE1FB8BED349421F916E4FC478
+:10F880003895D2FBC6D8513FF37DEB348AF707FB9E
+:10F89000D70BC49A1739C87A53F9BD65E8F5B61580
+:10F8A000450FB2DEC075CA7D227DDAFBED0BADDC03
+:10F8B000BE705A81F30BDA9D5E6D26FF2FB92EA91B
+:10F8C000FFFEA17108AF4C8D147A9DAE5094234B6E
+:10F8D00082C5FEF7F23C7E9FE7F75D9EFBF2BD36E8
+:10F8E000C99FCF3488739175DD8BFB9935A6D0FB0A
+:10F8F00024275B4F87E27B29A767F0F9C9766B0D58
+:10F900003CCE98851A6DF8FE21DCAF4E36A2DDA7FD
+:10F910002586EE91B734A6105FB8C515C1F50F4224
+:10F92000BEAF147C30646DD9467CE77B797B925501
+:10F930008171965BEC67DBA9FD383BCA83216DF3CF
+:10F940008CC924F7F27B80B413AD555831C58D2195
+:10F950009FC4FDA53B9A8AE7CE8A767E0F98AB635B
+:10F960009BD14E38AAB978761CF28987158A3367FD
+:10F97000DBB4EF58A567177F4CF7BF8077E0D61A46
+:10F980003C8E18E4E3206FA0BE69B9A598E4F65256
+:10F99000412727DBBAE93D7A09D701F13F461E0727
+:10F9A000DC1BAA233DDC0F8D03AA1076254937D234
+:10F9B0002EF508FE6732C249A573AD482DA1F79414
+:10F9C00036B6CDA2B4626BD183AEF1187F5C1C3D1C
+:10F9D00085E66D203D5945DD2C1EAFFB645004DEED
+:10F9E0006F120DAE447FB9B462FB268AFFF96CBB7F
+:10F9F00099E27F0AADF30A23A2E8BD638AAF93F5CB
+:10FA0000C2F3F979515D374B13BFB31CFAC4773693
+:10FA1000BFF284901F9A8CCBA98D7106E7E7F2F8AC
+:10FA20009CC9361E971347F56D83EAC5657AB6897A
+:10FA3000C779F8C51BDDB004DAD7D63D1786FDD4EB
+:10FA40003CF0EE44AB8EF450D1F9C3FDE28DDA798F
+:10FA5000BC518CB82FCD8D2C5EB404E1FF7B95E0BA
+:10FA60003FD4785587158D1DEF167738C9AD4E2FC9
+:10FA700033A21DD9696524177FA6B2469403A4FC5E
+:10FA800022BF5F95CFF9D567E1AD89481F2B773D40
+:10FA90009488E7CBE7A13C5FB2EBA6D7915F3977BB
+:10FAA0000471F95CCF481E2E7771F99A5545CAF753
+:10FAB00048CDA5404739F921FCDDA3766DBCB97C62
+:10FAC000E7F6733D7F9F07E38D90DE3FD27B972360
+:10FAD0007E3F02F915EFB1E1F99C3E3F6A5567930D
+:10FAE000DF106C1494433E6A7D2E14E3A1A5BC562E
+:10FAF000A4FEC581EFFFAC39C8E382F17D7A7A2B91
+:10FB000054E841EA851E64CD0B86D9F151247FD19A
+:10FB1000975ABDD73818FEAA857CD59F3FB09FEE77
+:10FB20006DB57BB9FC50EBE926F941CA2332EEB042
+:10FB3000666F37C913B25DFD010E97BA03FC7B599E
+:10FB4000BA4EEA511C4A2ADEA715CAAF9E9251BA94
+:10FB50005E931F57BA5E8FA9D0DBEB7B491EBC3B7F
+:10FB6000FD1DBA87D7B5887E216FF01B6F0912D1B2
+:10FB700070FE3DC582ED6D1AFFDABA0311D4DE5B6B
+:10FB800017BC19CF7947BD458F69739D85CEFD6D33
+:10FB90000DBA74F4537728C17694E33A84FFD6F013
+:10FBA0009AF7CDA83F8863BDC7F1BD5D6F82B316DC
+:10FBB000F7430CBEEEA2FAE2897A8E7C9A8DFD178D
+:10FBC0008CEABA8C6F6A18D64F2A453BC5DA7CB1ED
+:10FBD0008E8CAE6CA4EBE1C7387F7ECCC036D3BB35
+:10FBE000CDFA6286FA7BAFB02FBABED1D1FBB31D7E
+:10FBF0008AF7D7FEF2D51EB16F8B83B89DF1FE094F
+:10FC0000CE5FE23C7EAA18C667927FA33A1AFBEF4A
+:10FC100011764829A7CE14FC3941DCAF8C23622D24
+:10FC200048C7D2AF4F713828DEF3CE8C63E5783EFB
+:10FC3000DFD36BA2788199BDC124B7268C9843E7A6
+:10FC4000997CB75DB1E95909D43F96A1F3625CDCB8
+:10FC50003DCCC4FD024C01F2ADCE4CFEC94AC7EF0B
+:10FC6000BE41BE1EAF5E3A1E8EFEB2FFAED0FBA3FB
+:10FC7000A57D671F7B9BE17DD89D49F1D009CE878B
+:10FC8000108527FBE6743B0175F7583D263B3F2F57
+:10FC900098FF3A3A7EFE4D58A4CE37BF9EDEB3F4AD
+:10FCA000AE634FAF89F4B6333BC43B8701F3E989B8
+:10FCB000B5919F34D42379B3C7A2A3F7DD66761C30
+:10FCC000A7F70A67CAF70C4DDAF70C992D2102F550
+:10FCD000CAA44B05E120BA99E3AF205C7B5FECC876
+:10FCE000E7F26287E02381EFDDCBB81579AEBC6C1B
+:10FCF000D9750BD74BF17DBA4ADAF9AF24933CD1D1
+:10FD0000D791F29DEF58BC8B7205C80BA7AE76BC9D
+:10FD1000923FDC77AE2E147092E7B38C5B5828E0EC
+:10FD2000B5D0A2E3F009F8DD1549378174E1C33B92
+:10FD30008FF792F864B777BE8AF15880C7F1F73130
+:10FD4000C2DFDB488F27BF7973033EBB3042757437
+:10FD50003B937E14FCD1FBDD3F187F9D81F8F39A25
+:10FD6000C7A01CF1808EE408E9EFE814EFB54BBFA3
+:10FD70004796CE881F94AAC1A42F748A77DA810F80
+:10FD8000BC8A7C40EEFF5173BAC6E3397A12AEE802
+:10FD900038BF2E9D87BE874FE3FE862359679CF0B0
+:10FDA000CFC945F94DF5BD4F4D74DFACB81FAE441A
+:10FDB000FFCB8516F273EF7107BC4F2DDE31EF617B
+:10FDC000823F2C96EF98C37E86766D4B7879FF3B09
+:10FDD000E6A319DDA3DA32591ACA5F6DE2777F868E
+:10FDE0007CC77C6524E94D1F79C43D16CF03F97E9D
+:10FDF000F5F404A779DAF081EF573FA8142FC1DF9B
+:10FE000081718DE7F3ED5A12FCCC2E0E6E2FEA7B3A
+:10FE10004E3686D2BBDD924EA59E7B94ABFB6184B1
+:10FE2000938CABFD58D09B84BF8C2B8C0AC083A4D1
+:10FE3000BBFEDF8B59C7E9AFDF9FB69E913E6524BD
+:10FE40004C2584FC23ED3684EB3D89CE249C7FF346
+:10FE50006A8033E9D1B99FE749F17B1681FB2963B9
+:10FE60009A4EDA89295EA0549C6BA5323EA0511BA4
+:10FE70001F10F8BE69F0C8E209D3609D1794772778
+:10FE8000E2C737FFB73AA8DFC9A4699C8FA7C63A73
+:10FE9000274EA3F36DA6468E7C33F3D304FA7D99E7
+:10FEA0006F8F8FC473EFA684E2C9D8AF3995DB0D8D
+:10FEB0003E8EEBA2F88E8F97FC2D81F4CEEBF8BB33
+:10FEC000AC3F749E03E399391DDCB69CFB23C6B39B
+:10FED00006A2DF585F9CAC19E7F13F2D9ED9176F42
+:10FEE000BC9B7E57E4E5264FCA99D103F1911F745C
+:10FEF000EC391BDC681A8E1C2AA5F8DEF063B725E6
+:10FF000041BEF1C84B3C1F7FEC7212E0E6F6231DA8
+:10FF10003C3FEED8658C075E77E44829C5FFA2DD3B
+:10FF2000600463771C79B9D405F8A89EE06C427C24
+:10FF30002DBAD2F02A1EC3EFAD9FBF3C89E259E72C
+:10FF400025A4F378D6B558BE307AD98670C517CFB8
+:10FF5000BA6D1AB4037AE8B9C4E9BFE712A7F7206B
+:10FF6000E403C3FFF554C6F54AFE3B149F94FBEF30
+:10FF7000C78A4B96FB98EDB26F362031BAFEE57812
+:10FF8000E14768DF04C40BF7187A1F277BD2256688
+:10FF9000C338C4A3A1EFDBF09C68CEE5F18C4A6FB7
+:10FFA000A70DFD30F27378BEF952A70DF93BE6516B
+:10FFB000AFD513C1E31C653C6CF3256F1CEE937C3D
+:10FFC0008C5B84FA85BDBDA5C86FF2D18F3709FB64
+:10FFD0007FEDB8188F617F3B2EF178C31E73A7CDDC
+:10FFE0002AC6C17E60DC24E48BF96B4DE46FD47CBF
+:10FFF000A96135F55362E91F570918D7F4DDE3CE3F
+:020000023000CC
+:1000000052FCC64DEDE3719D38AE4D33AE97E281A3
+:10001000A13F8A3BED89B0C7E27D5FE60BB11CF2E0
+:100020000F89DFA7C8B77955E4FF323E2AC628DE1C
+:10003000E116F715A847F1983BFAF83A2F3679AB55
+:10004000713F150A7E5D68E4E725D305DBD10FBB60
+:1000500048FDF6B578BC97BCC0EF258541C5DB707F
+:100060003FD6EB39BF6151F277D23A57FE06EABD6F
+:10007000131D4FBF2B3632F6104BC57BF1AA391931
+:10008000785E80BCFD11E2FB1DD6AAF0DFDFE2ED59
+:1000900017CC0921FF939E23637271FFCC0FB21D11
+:1000A00064B06F4F4DBB44FB747EB82D176F3AA7F9
+:1000B0008E5CE6F918DB41B4EB9AD8A5D242BAA718
+:1000C000713BED4D3E3BEDA7B82FEBE65C3072B9CE
+:1000D000AC97DE673E378D9F5F20B793DCD17B8D79
+:1000E000786F33C3968BE58986DE30845BCFB77A31
+:1000F000FE5E2DEB0DBBD1CF2EFB78077FC7369070
+:10010000AEF715F0736055AA85DE39AB8F359928A7
+:10011000EDB8349B7E07465F9C8AF7028771707D3D
+:10012000E313055CDE4CDA68F4D9DDE1FC700433DE
+:100130009977B13CC6B6FF5B70FFBD0B8F18E368C3
+:10014000710F73599F284CD5D47760FDFE72C69FFE
+:100150006793ED47BEAC7F02EDF8341EE2B992FB27
+:100160004D049E17A5D32335FE568F4599C9DF2A26
+:1001700055157A3CA86B257D20B7DBC6FFA799E211
+:10018000E77698391DA6EA78BA4327E27C859E4F28
+:10019000DE5F7E31DD397E7A2EF5E3A57ED4FD99D2
+:1001A000284FC4310F8D2FE532590FE42F33311909
+:1001B000F13B6FF9AA6E5078BE5230C351908B74E8
+:1001C000ED629FF89D131743C21AFDF157AF6AF510
+:1001D0009DAF14CCA476B27D5DE32CF609C5217ADF
+:1001E000897EEA5275745FAD57D92BF47B03AC93CB
+:1001F000EC98B2DDFBC0273FA1F71A1C947E00FCEF
+:10020000F213F2F35B4CE95F9A9CF4FD645315A57D
+:100210005D4D0DF4FD545323A58B6E0ECD41FA5F59
+:1002200075783DFBC4EF7CACF3189CFE7E35EFCFB8
+:10023000189C8E2A051DBD9F3478795301978BDE5B
+:100240002FE0F8EC59CEE54BA0CB166BE4D0F24290
+:100250004F28F747786926A7F39E389E7716F077E0
+:10026000421D3AD68EED5F9AC9DF617F3F5947EF55
+:1002700039382279BFEFA7E9484EBB76F68C528415
+:1002800093231ABE67F9F2EF5FC5CB1D23F87739C8
+:100290005F593E7E7ABFFE208DDF8BB9DD1DE89D64
+:1002A000FAEFC76F219F5F607DE9471F088FA36248
+:1002B000DFD2BE40B91DF74192DFBEA8B7D1BE90D4
+:1002C0007428E9AF743A87736A90A07338BB087ECC
+:1002D0007886E1BD38C64C72AC03ED16B09E1D2287
+:1002E000CE7DC07E107600B91FE43E90F41E0FFB59
+:1002F0008CDB39F83AA6A983EBE73715F07B6A6700
+:1003000074E8CF08AF1D062B9E37D3546E6FE8E913
+:10031000589883FEE0459B2C0D83F1AF9745FB7FFA
+:10032000190E921F0C018701EB370A7DFD3FB97E44
+:10033000E26FC8B797737FCC407ADD5B20F915A7D1
+:10034000DB570A1CBB907E7A14B31EEF273DE6C133
+:10035000FDC75F9AC9F785A49FD2E94CBC3F03EB68
+:100360004C19C8EFE47AFAD7B98211DF4B1571C680
+:1003700081F895EBF2E37B1D057E7A27C6405E810E
+:100380007E46D65AE87E2AE9F7E2F06F2AF1FC9A17
+:100390005360E3F6179D2ADE81E5E749FF7745A51F
+:1003A000782BBF7386A1DCD27B84DBE1BC704F422B
+:1003B0003B16EA9EFDE3ADBF16FCA26F71AE0EF5D3
+:1003C0000317BFB6B8F0DCBA38A2F724CA2517DB8A
+:1003D000F93BE7D0E35C05FD4530EEC786BFD7C2E9
+:1003E000ED1FEAC35F9D4479A8F26195E4978B788D
+:1003F0005D8676AB1EE0BF6F27FD066B45BBE6F65C
+:10040000CB8BE877CD803E51FEF9C45C9F8C72F1B6
+:10041000AC871F3881EFAE571E5450CDCC8EA3BE93
+:100420001DF26777ABFCF75545BCC96CE1D75FBDE2
+:1004300093FBF5D7629C09CA2F07B63F88BF3B598B
+:10044000B7DBC0CCF07D36BE8F06E3ACF084C205CE
+:1004500012FA6DD3C6A5FE84B936A21EB96A9BF600
+:100460007BF50E6DBE36C05FF15281F04B1CCB3276
+:10047000C92FB18DEB8925DF1E28EFBA387F5C23A9
+:10048000FD74BFA477BDD5235F259EB2F0FC3C91DF
+:10049000EF86FC85AF38FC25DCEA05CFBF10C772BC
+:1004A0003CB0BEFA23662BDEFFEB5FE0FA818B9E49
+:1004B0007082F3AAE02EB227B017552BCA61771DC0
+:1004C00056499F50D761FE35FE1E6DFD4185DEA960
+:1004D000AD3B1CE4E6F0B95489E52B0E9BAD362C00
+:1004E0007F3188A1DEF922E00DFD612F267411FE17
+:1004F00011AFA88F80BFB9F8BB1512FFEAC3DC8E1D
+:100500005CB947E0A7FD363DE1D5ADB098A4817850
+:100510009278FE9DEEE97E3C61BB590FBFF79AC011
+:100520003BC3389BE3EDE5F47B1812DFC6239F2421
+:10053000A2DC2BF1AC029E7F21DBDBC43B78DF81A8
+:10054000E72AC4B3E59FC7F3EB054CC6FB9D7D14BA
+:10055000E5DE5023D9CFA53E43EA2F86D7BCFF6AFC
+:10056000140C3C3AF63992734B23CFD5AD66A43FB9
+:100570009B341DF59FD7BC853FE7CBDEB9F6E94C30
+:10058000A48F664317FD5E8C2B82BF27DF93346FE9
+:10059000DBF3305E61E43789FB71DFBC1C4466939A
+:1005A0005982AFE29FC9FF3DC00E33E9D9EA3A82D2
+:1005B000B85EED80D66ED613C77F9FAFC8D85BBA42
+:1005C0001AE572E80FC791F7C19A0EF1BB2FE2FE50
+:1005D0005623F50C7B03DE85B2BE45F54AA627D32C
+:1005E0003C5262A6D9900F352F61CEE094EFE2F72E
+:1005F0005C7F237F276F48397008BE2FE53FE6D226
+:10060000EA3924FF59217E57B27F7F887CD57A57FB
+:10061000984925BAA378F1DAC7F8EF2A7E8A7417C9
+:10062000E6A3A77A1197F6EABFBDAEC7DF67EAD99E
+:10063000C1FD2280433E88FEF9E73D3C0EAE3AA75D
+:100640007BA2D786BFCFC1F9D0CABD8ADB9634085A
+:100650001D31F746FE9E7D003DEDFDEEF70E6F9FCE
+:100660002EE2DDC6B2F1FF00786EC7F8A35C1FBFB3
+:10067000088C9BEC3FBF027EBFE37F5A1C775F066E
+:10068000ACE73BEC8C3F89D5BEDF728D4DFBFB4C5C
+:10069000D7A56B7F9FA9CF22E023E44129A7EE9E37
+:1006A000CEE599C054C2F77ABB761C792FFE699EBD
+:1006B00076BC790EED783F142F3F563CEBF7C1EF37
+:1006C0003531EE0931EEEB62DC7F154E321D6ABC2E
+:1006D000FF9FFEBF49FF0F426139640080000000A8
+:1006E0001F8B080000000000000BB55B0B7C94D54D
+:1006F00095BFDF7CF3CC7308210904C22424216058
+:10070000880324542B96C9D300D6065C2D68840137
+:1007100052C83B80B5D2167F190411105BA8D1A234
+:10072000224E82E1A1619D08C144431D14B288D6C6
+:100730008D748BFDFD56DCF828F23213A374E55757
+:100740002D7BFEE77E1F990CA1DAEE6EF2D3937338
+:100750005FDFB9E77DCFBDD414E718BE9A22446E9F
+:10076000CC59734F8410AE953D4589D942F4BDA94B
+:100770008A268710C2ED3D561F2B446DC770B129E4
+:1007800099F092BEB70CC0DBC6D93751FFC6F63F11
+:10079000BC83FEDE03AAC342FDAFB77F1C85752E66
+:1007A0007C152EC470CCFB384A105E7D49617C13E9
+:1007B000F53B089FD9AA0A7F26AD67F499D17F211E
+:1007C00055C7BD6641B0A4A5D5DC43B06A4F2BF731
+:1007D000BFE9330DEEDFD338A8DF8EF104AB8CDE3A
+:1007E000283BC173EDFA7A7E1E5F9DAAB8BC68DF14
+:1007F000F387B8A518D7F26EDC128297F133E36A5B
+:10080000F8D9C11732DD34AFA683D6891858A7A608
+:10081000C3A4E192EEEAD4D6A218E2976851441A32
+:10082000810B628B5845FCAC6A6FAE16D45E957135
+:10083000B749105F023EB518DFA71F8388A37976FA
+:10084000FA8BF877C1F745D4125AF735DFD1DB5C64
+:1008500004039D6F44E1BB8103343E73809EE92E07
+:10086000E25F0EA059881134EFC01B510EEADFE899
+:100870007B43F2DBE8E77DBFAEE10182CCE7769512
+:10088000F75DF195CAFCD7D7BBC5A5F23A33DBD3E8
+:1008900022B1AF133EF9BD392E876C4F5D5406FA75
+:1008A0008F27CCCF5193996E17F0C0C4D9CD9B88B8
+:1008B000942A1FAD9B7935DF9668EB7699C43C1F6F
+:1008C000E496BABF6B14E9C7F1E2E193A9E7CAB8AD
+:1008D000BB5D061E576476A72EA77127221C917652
+:1008E0005AEFC1E2719190EBEB80682FDE697613CD
+:1008F000AC3C20BF77C2DE1D057D3B7160AAEA518A
+:1009000006D6BB43FBAE101E860372F3B09CCABD75
+:100910008D115867407EB27D8ECBCEE38F7BDFBDDD
+:10092000F36EDADF898C7027E4D26516E53ED613C4
+:10093000FA08BED799D8083EE8DF9B0379D0BC40BF
+:100940008681E5DADB6ED2C6DDDD2C068D33B1DCC7
+:100950002E3C37981EBBF7C35FDD4DE3AB9F51853F
+:10096000859AAB4DCBE3B0FF4FB70FA6AF5CE373F7
+:10097000B5C91F1717A4AFD51D57EC2582F5BB438A
+:10098000B70F07CB5397E3890C55D29560F10A2234
+:10099000B9BAB599F59ACCCD639BC250D8092686D1
+:1009A00077272BB4FFC4FBADCEB544FF738AD66F57
+:1009B000201843B841E266825682CF98643BCC1639
+:1009C000F3C7903815C24DC5E3720C29B48EDA3ADC
+:1009D00019727D7186EB5117EDFF97334A26CD20B2
+:1009E0007842F42D15F4CD9A8B111E112D44A1FAE5
+:1009F000FE13F86EFF019380FFA8B176547E427A11
+:100A0000DAEF244321BAFBB79BBC1ED63F57843292
+:100A10004D88A53748BBF9D4E19EA68EA3F16B0C97
+:100A2000BCBFEA16D56BA371BDF5C40262F967AD10
+:100A3000C93F82BE561F53ED56DA77BE2FF9D7D382
+:100A400081B7989C169A5FEBA346C26BF7285E8726
+:100A50005C5FC02E6B6E605D17A76DB529228BE0C1
+:100A60009A3E33C69D3EA488C768DC2361514DA0E1
+:100A7000BB2673D659258AA0BA797D22ADB76C9B67
+:100A8000E9A31EAB9C7B99FEABEBDCCA7A5BE11D54
+:100A9000DC5EB567305E238C0338ADDF8C3F6E14AF
+:100AA000A2CD15197BFA3AFA7B82987059059FA658
+:100AB000C7C31E8E43AEC447D140CC1E29C4BD93CC
+:100AC0009CF1B0FB8D46C72CF021D069B2835F75D5
+:100AD00087F657806E6F7598D3405BAD5DF52AF34E
+:100AE00035F025F1FD7A820982F71F1092BF8176D9
+:100AF000A9E77526C56BC57CE221AF6755BC6BA81D
+:100B00002BE0E98F62FF244431EC62E5FC1C03FC1E
+:100B10001CCC581029BFD6ED41B11995684069FF2A
+:100B20003F30F6A8C382FCC47FB95298FE02B3706E
+:100B3000FBA8FDDE486734F47EAC352A0B748DB516
+:100B40002679C1F7B1C6BE35F8FE23A314C783B416
+:100B5000F4E1AC57262BC06B239CD0132561911177
+:100B6000FC7864D42223F47DACDD97519239801750
+:100B7000A01FF620BCFCBDA208B711DF796EA4E26D
+:100B800037D0FA011BD1073B31DA4DA02F6092B864
+:100B9000106B06D1471E89F1FF77FAEC445FC40061
+:100BA0007D24EF68CCFF229BF84330698E10DDEC8A
+:100BB0001796B35FD0F97981F4BD806495A648BDDE
+:100BC000A9DE7EB808FD35A27B3DE61545C97D143A
+:100BD000613FC0C3245473A5BC7235785FAE8C2FBF
+:100BE000BAFFECC8751973096ECB2D310316AA999B
+:100BF000F13D43F8FB958A95F5E40BB23FF8E37BB2
+:100C0000962BF6D48C01FDD6EDAA4E365DB19FAA87
+:100C1000DFEF348B147CCED59D41FDE542DAF5C281
+:100C200055367B6AB01DC1CE881FE5F68A5B05D9B3
+:100C30009B7B559C3D752AB5AB17CC02BAA7D957FB
+:100C40002CFD5E4E19C2BE7C2176D93E18F7DBA47E
+:100C50009EFB2315EF5AA23F3577B0DD256976D08C
+:100C6000E856787F8D5F1B19F7942A5EF0FC0E6AB8
+:100C70005C15A36D0EE3CA73BD888F77105A8AF690
+:100C80008658B653EE24FFF52FDA3EEF30FA0FC345
+:100C90007F1C35F992EDD475B4C6EAC4FAF3052584
+:100CA0003AE4D74A4537C393E1B56D7E5EDC33063F
+:100CB000FAF59EDBE2441ED6B8AE29127E3C4BAC60
+:100CC000B39FCE405221F65C9E7AED7C8614479C01
+:100CD000D6E582404C790AE4ADCB755BAE2B2F375D
+:100CE000E7DAF3ABFED876DBF7E0BFEE6B36C74B47
+:100CF00035E9CE983620375DAE75C2C374EBF2BAD3
+:100D0000223FA27D34F8A15E98C37EE65955705EFD
+:100D1000A1C9CF4ABF43C94FE7EF0C4D0ECB3AA450
+:100D20003F0A95ABCEEF1FD382F83EC5D1ED2C0F15
+:100D30006161FF172AF76F930B6598A5E8CA8FB515
+:100D400008C833D120FD63E252D213A2FB6EE13E0C
+:100D5000D443F0CEF0B74DAC879A7CEE817C68E846
+:100D60007BC2FBC38CE4FF3BF974E496DC1F6C8709
+:100D7000A176772D3BAB7638FF5D8F7BE469C8BEEB
+:100D800042EC33C4FE7479B95745B19D5D91A3DA45
+:100D900022ED55935704FD0E696FF883BE57D3AE0D
+:100DA00078FDC9DFC1FE14229CE4F65888DDE9F223
+:100DB000B996DFD1FDD429E13F6AA7FD9F4C917917
+:100DC00080E767166F33F0744339FCDEC98912EE91
+:100DD000D7FC5B283C45798E42716C53C6891188DB
+:100DE000D727CDFA3A366F33D17F6A4DF79815344D
+:100DF000FF54AE8427911706E1AE30B1107EFDD4CA
+:100E0000488B077C3AA54CC8437C38A5DC7F9BC443
+:100E1000E3CD0EE0F3E3F3EC849F34C9F17A5CD1C7
+:100E2000FDFFA9F9DF2BE0718A38027E381451C228
+:100E3000DF51949862A2E7D47D6953D68A81FD3749
+:100E4000E51A789E57F3DF4407F3BDEFE78AB789C9
+:100E50009A1622A410FDC979BF2D4EA1F60F7E313E
+:100E60006E32E4EB5A39F8FB88D7C9D703DFCAEBF7
+:100E7000FCE0AB3ED3A2A0B874254E167C2EDBCB93
+:100E8000720CB097724D86AE9809D1904FBF775CC7
+:100E900034E28E1E87FA8FED8F7007C9ED2CC529BD
+:100EA000313E089FF06852701C3BBCEB9174AC5310
+:100EB0006EF66439A9FD4CE3D349C837CA773D9C27
+:100EC000CE79F0AE8DE938CF94373D92EE623CDCBE
+:100ED000CDE729A3DCF7F97D37EEDC14947757E5ED
+:100EE000AB4C7FA9F57021E2EDACEB3E7BC84EE345
+:100EF000D27EA1D8A15EF788EE87101F17203FC6CB
+:100F0000F9ADC1CAFE9CD67341FECD137EF81CEC30
+:100F1000F878C6C7A6321A7729D7C8FC5920BC9BD7
+:100F2000E3A95F6C50ECCD2278FC98468C5FB44E00
+:100F30003127C00F2C1F36597560DE30A663F1864D
+:100F4000C95D685FB05AB6CFB2780F9CC03ABF3562
+:100F50003B9B1DEC6F524A260DD07F29D7CCF31650
+:100F60006E5638FFD7BF93F6445C63F03E2F69F2AC
+:100F7000175F5B14C8E5479A5C6E5DFDEE91045AFD
+:100F8000D71EEBBE0CBFF1CEE3A753FDD45E1073AA
+:100F900036137A9E66763F55817D37599CD84776C1
+:100FA00056A21A4FE3A7FC34F731C085AB173D5565
+:100FB000017FBBCDCAE7369DBE958AD3007FFC4634
+:100FC000E38F17836F671EB772DEBEB2717CBC18E9
+:100FD000C24E75B89BE4EFA083CEDE7A2BC317EA2E
+:100FE000EDC241FAB0AF3E81F117EB1D0CC53CA933
+:100FF0005F2BB5F3F1B5D69BFA55B870503E9BBD4B
+:10100000C1261CE4A792E25CA3F2689F69136B9A65
+:10101000366AFB4AA3F9933DC9F9E043F6C6155D6C
+:101020004879CD79F23CF6D6890D4970CACB567F06
+:10103000B8A382FAE7E4958CCBA376EBF6CFB9AEF2
+:10104000F046C7C30BC0EFF2268BDC9FB6EF338FA1
+:10105000A7C73F45EB7BDE34F179BF6EFB873B369C
+:10106000125CB279853958DFBFEB7E93357ABECDFD
+:10107000AEAEC5877FDCAE1E4962FB6922BBCAFCEF
+:10108000E7EDAA6EF51AE6DFFD7925B3C0F7332642
+:101090004F12ECE9CC849B59CF3D8714E6BFEEC7D5
+:1010A000F5F9C5DA7EAB0CBECDD39307FCF84591BC
+:1010B000CDFC3DDCF1693AF2DE8BEDF3FFEEBE0FC5
+:1010C000D2BEFDB4EF76E2AF7FFCD5FDD3CCEE719E
+:1010D0004EDADF3483CC77AFCA5BF30C5ABDA0DBAA
+:1010E0005C122979AEA02EA3C54F8A639E68A2A781
+:1010F000BA53F18765219EDD72D688F31E9D1B3F92
+:101100000ACE23E8E7A3A0B87D2D7ABF0DD6629D55
+:10111000B401BFFBBD3F19843F284EDFD81326FC26
+:1011200041DFBD723EA13633C9A9B76324FB05C8B0
+:10113000CD887A5CC78426E067CD528EBD07296FC3
+:1011400092751CA14E1BD8E7D98EF359F0B3A1FBC1
+:10115000AD7DE53CEB4775FBC39F2BBCFF99678DCD
+:1011600059DFBEFFC3BBCE67417E674D3DD370DE06
+:10117000EA35F764410EB5AF4A7FFE8FF2416FAF9B
+:10118000D8401B213BAF55ACAC2785EA05AE1BF41C
+:101190001E937583DA8E9DEC4FFB3B65FDA6CED08A
+:1011A0005D148F7AC7F20FBBE0CFFA13E4398AD609
+:1011B00077816FD3C76971D0D8973487FCDA4B57E2
+:1011C000F4419EFFCEC07EC7631D5F35FC80C80A18
+:1011D00017C82BCEC19EA97DC1AAE4F5D0F333DE9A
+:1011E0001153E01FDFCAFA6B2DD7FB5E0BB7AB9C28
+:1011F000F7506B90FCAEECC3AB0AD7A07A40B87046
+:10120000058DAB333B7EC4F9F1715520AFAB9B2804
+:10121000ED49BC22EDA966DD617342D07A3B604F97
+:101220004CB7CC1767BDF657B6CBD5335C9DB0CB6A
+:1012300070F842AC9710ED55146D1CC9BF56A32130
+:10124000A2533BF717ABDC5FD7AE8A91989310E9B6
+:101250004DA37D148B2D46E4D3B3846F3AEA36C296
+:10126000D8F3AB9BA87FF66BEAD44D82CF4F0B4BE4
+:10127000F85CE94E5D89FCC8A0687CF565CF098EF5
+:101280006779324E4D57158E637D23C3394F993997
+:10129000AFA614F4EAE3B286C971B40EE759C2DB13
+:1012A000973507F6E9EFCB9A1B3930EECED7C297C8
+:1012B000735C14BEEC3B83BE13962FEBA35F501CF4
+:1012C000819ED45D94F58E42F5EB27909FAF3C4410
+:1012D000FA82FCD090FC9E017E9CF80CB99E27B946
+:1012E000BA107FDCC2E582FD4C1AE185FDD4ED53D6
+:1012F000841175A20E4B13EA48B5A69E38E8F3C6D2
+:10130000F63F9AA1CF756DEF9A1D93305FD69DC8B9
+:1013100020D98FD769F1ABA67DFC7BA8F3D51C93B0
+:1013200051B4C6F82E9FDFAB0EB4F239BD5AF8F9AE
+:101330009C5EDD32585FFA131C5C1709B58FB07CD8
+:10134000C720BB98B94DDAC59DAA580E3F27B43ABD
+:10135000EDCC8478CE4706E6C97CD7A59E7F08F9F8
+:101360004B2045712AB45420CCB30E7991275DE609
+:101370003381DFBD90BD94FD8A37FB76DA5740CBD1
+:1013800077676ED86A5483E899D929EB92813051F6
+:101390007E90E5ED1E0D39085749447E0EDB55164B
+:1013A000FC6AC020EBA8A1FBA8D7EA45C7514FCAE9
+:1013B0001CA07B7662A2F463C2CBFAD36590DF7780
+:1013C00019A87FCAC0FCC5F972FEC07948D6C1AE63
+:1013D000E55776917CCA483E7B48CE80CF533C2E61
+:1013E000233FD342F118F8BF523C06F4D56770FB97
+:1013F0004BF54EC60FD4DFC0F8C17A17E3EDF5C543
+:101400000C5FA92FE1F6E320F5FBF8DFD38DD08741
+:101410002ED8D8A801FC644C083E6AF0F89331CA73
+:10142000607C94C2E3B3F39F6EF464A26E6AD7EC5F
+:10143000DB1189FCEB8C4DD6A1CED8641DAA759426
+:10144000FBA67CEA2F9BB976973C87BAD231AE20B7
+:10145000663E9F5FFBE9FC0A7FB422DF9D07B91C53
+:101460003B969FBA95FDA48DEBA027EFBA2E9AEB81
+:10147000806FD2799C3E9D9B31755D36E1B9110A32
+:10148000EB2FF98BEB4BF47325AD93DF29EF510A6A
+:10149000D5EA32ACBF72A46D2AFCEF172EF7ADA0CF
+:1014A00043E777D1A865A9C887BA4C8EF750C7F52E
+:1014B000FCDE24709ED2EB7DFAB80E57EE5D9837B5
+:1014C0003363DCBA29F03B6464F0732EB368015DCA
+:1014D0002E43B8B296FD96C3083F7097A6C7790E03
+:1014E0009917FBCD0E630CEA3761B9B11E9AD7A5E7
+:1014F000C9F99826E7E39A9CDF469D8CE03BD40E21
+:10150000D84DED809374FE1AFB986F4FE49594B11B
+:10151000FE8ABE24E07A5D7016EC4BFA9B24E8F557
+:10152000664D7F13347FD3955B5225E7F9789D2A6A
+:10153000ADDE765EBB07D1F7ABCF1B982F18CEBDC3
+:101540005E78ACF0F32FCB73A7184DF908E1735F09
+:101550008E673FA45A6FCFFC84EC7CEE54790E105A
+:10156000FB2D725C82230776B256ABB7F67A0D1E5E
+:1015700013EAD331DDE93188BF9A7DE9F8C1BFA90B
+:10158000ECAF6BA6104EF05545EEAF666E77FA30B5
+:10159000CC576C06AE6F37C9FE139AFDD5A468EB25
+:1015A00069FB11565F12E41138F472D262C23745FA
+:1015B000F8974ABFEF4F677F2DFCE973E11715DFFE
+:1015C00007C2497965C1D4C5C691E0876F07F0EAC3
+:1015D000829CC5C61BD1DFFA813DB87F842F49B1FB
+:1015E00003CF96FD235A770C7306E1A6973E40BFC2
+:1015F000D990B3B880F0D916EFB17AE8CD8B52BF4D
+:101600006CFBDA4E836F551D326FCFDBD776E12549
+:10161000C4E5B64827DCFBDEFC64E6F7DA8EDD9B2A
+:10162000A16FBDADF23E6053CB1F77FC92C75970DE
+:101630004D42EBFAB2057D67C591FF5804BA668743
+:10164000FBBE04FEE091194CE7ECE1D2AE1F3E92E6
+:10165000B71876DADBB6EF67B0BFD9D194D0829EE7
+:10166000176C5C87A8DC3FA10076DA1BD9BD00EBC4
+:10167000D73E6F71424F2BF7C7E7A13E70305FD660
+:10168000C32B266E49429C35BCB277D72F71BFFA67
+:10169000BC8DEF85EA62649E57A9364E5BC1F2DBD2
+:1016A000B9EB69D0BDD7C6F7B315A855115EB12BFC
+:1016B0008DEBF8AF7EF3F102C8A150DDBE0BED5FFC
+:1016C0003E6733800F27CCAEE89B6187274C7CDEDA
+:1016D000ACD0F08A93C3253DE13D452CBFD82D49C0
+:1016E00088B395C37F7E1BE89EAD6ED981F38ED8FB
+:1016F0006DE1BB89B37B896F34EF6CB3690AA4DCFD
+:10170000BB37D2087D39AF6C59F014D66F96E3CE53
+:10171000DBB6303F3DCDE305BE47E304FCD679653B
+:10172000EBA0F6B3CDBBB3701E3DF7FC6C3E97EA61
+:10173000FAABDB4BE573964171913D01F9A34AED9C
+:101740006F61F788088AB7151A7AEEE093BD4F8962
+:1017500081F9E75A4C7E33F1A8C222D6596306ECD0
+:10176000A132F19662ECAFD2D0988EBCA5626ACF5E
+:1017700002D8C5599BB026D0B8B7B4B8557960CD5A
+:101780001CE4BFD7A2E7B2E68F2E26C8F875B1DDFC
+:10179000E60DBE970C85EFD70BFBDB6903F83DCB5D
+:1017A0002D9CC3EBEBBD65F655E39C561B23FDC793
+:1017B0000734BE85FCD8375ABC5BB86AF0F8FEFC2B
+:1017C00018FE7EADB9271DF14F5F3F90AFFBB59E70
+:1017D00074F8ABD079B3918EC08FBCA0B01FA93C78
+:1017E000A07CA8129F2AAD1EAF0ABE08B3BE4FE36D
+:1017F0006545CE4B98A6F19DE66E2848E6EF56B6B5
+:10180000D85C369A5715D61385BCA83AB2270AF980
+:101810004EEF2BAA68D2C4151BA7C92745135950F0
+:10182000BDB1C26772D9B2869033F2271AB70C7F66
+:10183000D3F79F2948E1FD94B787F3F784BD671A72
+:10184000F4B47CFBE079D8973DC8FE7ADB77C60517
+:101850009FCB5334BA03CA876C27816F3E4A82DC20
+:101860002B0D621DEE2FCFD11CDC6B122EAC12E7BC
+:101870007BCFCABF4484415FCE5DAC66BBED557A79
+:10188000D8AFBD533087FD52AFA987FDDA1B47EEB5
+:1018900064FFD03BAC6701FCD43B05CB64FFC89E22
+:1018A000050EEADFA7E36304C7FDF78FD4B0FF9806
+:1018B000ADCA771562A7C92EEB411B4ED6F3F9C20C
+:1018C000E4083E7F9F2AD0EA3D03F2E173976E372A
+:1018D000BDC2B1EF00ECB03C82EB3A9447B5BC849A
+:1018E0007C6F7E9C13EF35CA314FEA8139F8BE31E7
+:1018F00036E6D252C8E7F6D1EEA2821CDC6FF6F0D3
+:101900003982B49AE34DEDEF2C7C9E0C98FA76C1A7
+:101910004FA58F76CF2A203AAACDDDEBB389A40B51
+:10192000A69E2E94C867A9D21F89DD52AF7A33775D
+:10193000CA7B1AEDBEF22E8DFF820E318DD00B4583
+:10194000CAF78DF6FD6FC3AFF4768F637F1C6A37DD
+:1019500067DB1F8B827FF813C5714FD079FF4F8BE8
+:1019600076F33DEB3CBC0721B878DD607DE8FFFAFB
+:10197000763EF789CD41EDD0C386C178A81E411FC0
+:10198000FD83FC8E87F9BE4DB3ABAABCEE5AF0E1E5
+:101990000A3E977035087F3D040F192F4A649EB0A8
+:1019A0000DF19FF8513DC67F92CFE9FB4C027E7C42
+:1019B0002DC52FC6DBC2BD38AF18F6517C8A95F114
+:1019C0000971A12AAA9BEB53BD6D16BEEF7DB0E352
+:1019D000D324EC9FF490EB30551D2FC7E1FCBE578C
+:1019E0003B2F501C8CE3F7316D1D713877E8EDD536
+:1019F000065F3AE8A28C88F375BDBD46F5A783FE65
+:101A00002AA53B0BFD7B41378F275C052E781FD520
+:101A10008AB477D1A1B23F0F95DB939ABE925FC88B
+:101A2000E2F71DAFC8FA80EE072A347FF23ADA33C4
+:101A3000A5DDDBF57B259A5A017B1FC23F2414E804
+:101A400079F172AEDF3C5EE090B8369FD795F52510
+:101A5000EEAF7DF57C564A26E669E382FDD0B801FB
+:101A6000BF02FB4F60FB7FD01447FBAADCA138D735
+:101A7000C24F95AE29A2E16299714511D7CD8487F5
+:101A8000CF6DA17485EAD1E402C9A74AC3B0C2D818
+:101A9000A0F5CE914F4F98C27EC60FBFF393D847A3
+:101AA0008B50A7F871A97C377025DE04DB39F6B3BB
+:101AB0005DFA7198CD65C3D57ABC6C79E3FAF821EB
+:101AC000E808A5B3C2DD5814E7B8BA5DA7F79C4D86
+:101AD000A72FCF3422980FF3D6148D20B8CCFACF8D
+:101AE000F241EEF75C87C58FB85A51BA627DF410A7
+:101AF0007A73553CD81E14BF52205F2FDF6F5C8B6A
+:101B0000FE5058ADF84FA25E24C8AE9AD9BEC85E4A
+:101B100082E2C28D05217587F2456391570BF7A2CA
+:101B2000B1883364570B9C439C2FC9418E32F09B84
+:101B3000110FC3507AFE5C20DF25DD5820ED7CF5C7
+:101B40000C57007EF366D5C07978E87A5F15C87CBB
+:101B5000A23B2EF23EFD3D07847DB32AF99668E84C
+:101B60007F07F6961817E9C07D50617EB81C77C8CC
+:101B70006647FD2670E812D777030F45CC93F7062A
+:101B8000116224F577254C6A0A8E23BF2994FB0D38
+:101B9000CF96794B5D86E9EFD7873223AFD487386C
+:101BA0006FC80CE7FB92DEF62F386E053A73ECB87F
+:101BB000D7E8EDA6D321D953DD37FF1D87F8DADB4F
+:101BC000F9677E87D6FBF5A7FC3E6DA3F63EF0F5E0
+:101BD00076ED7D57B72312ED81E28F8B306E930641
+:101BE00007EA04B25EAC43FDFCABD70382CEC1A3CF
+:101BF0000B873E07C7B82382EB048EF8A1EA2AC1FF
+:101C00007582D434592700449D20D524EB04C0515B
+:101C10002700449D00EDA81300479D0038EA04C04A
+:101C2000512700449D00ED5FCE93EF6502A4C4B23E
+:101C30007E19C1FEFDDE66D58BFCFCDE43F21EEA9A
+:101C4000DE4685DF695DA0EF23CE5DF55EE780F6B9
+:101C50005EC7B795EFF5EADA5427445567EA3B8A41
+:101C6000BA4E5DABE25C03FF523F8FBFBFB133E7BB
+:101C7000BD52B4379B9C0607E474310EF5AACACE58
+:101C800066AE3F15C41F32B37C5B14817AE99D16A2
+:101C900079CEAD51A9750ADF87721E5C63E9E6F360
+:101CA00047D51EC55E167C9F7BC3E7EC07D6DAA23C
+:101CB0009A40678DCF662F1BE2FD07DF0B3BC49573
+:101CC000FBE6A57288A88928E2FBE6A5B867262866
+:101CD000D4AF8D7C7F4C07D3E1D047BCABCA805BCF
+:101CE000B74BBB0F794F55D9D9BA3E515C7D0F8D9B
+:101CF000CA00E41F7AFFEC2E8C8C3D1D0E47212676
+:101D0000236F2A7EBC6C5F1B7DAF7F8B85F38E15A6
+:101D1000F9EE65D0A3A32617D7498E1EB2F1F9E8D4
+:101D200093ADE307D549BE70B9AB0BF97E7E34D7CE
+:101D30002D569A148ECBF9C5E3E2F9DDC03113C7F5
+:101D40009F0E57492DC6AD9CE4E0FA54A145DCC76F
+:101D5000EB68EFB408B23D15AE55BC06C21709A733
+:101D600019F6B390D8C6FA628AD880F7540B857CEE
+:101D7000DFA0EBCDCAAD0AE7055C2888C3BDA4E4AB
+:101D8000EFC2CE7FBB84F70B4B2C327F4D34C8FBA8
+:101D9000ECC44DF27DCB4F84DB8C78BB8CE22220EF
+:101DA000C5C9DFF550BB3B7C7492CCCF1DF1587F89
+:101DB000D17113BFF72D8CFF61BA9BE37501BF632F
+:101DC00050FC77AB97AFBBB6FD84BE63386A92FE1A
+:101DD00085F8C8E7A22EE825D767DC0C8FD79733A4
+:101DE0009C3443FAC72BEF12494676D01FDEF70129
+:101DF000CE8B89F1914EF83BDDEEAF7A9F1826A18C
+:101E0000FE3E710C4111F43E71B3CBC1FE2ED17078
+:101E100062AA03FCF84B8413FCD0DF29AE9E51B2BA
+:101E200013727245090FBE8B7B942DC4D7226C446C
+:101E3000419DDBE75251B73EA4D8F95DF4557E725F
+:101E4000EB4378C75397AAD81507EAE15B0AE38802
+:101E5000EEA29464A6BBAE5DD64B994371A8A76B66
+:101E6000F6E072B7158E18689FADD9452F8D977A19
+:101E7000729317FAF61DEAA8CF61BC47D89CCDDA59
+:101E8000790D729F7DDD18AEA7EA7AD3DF12DF04E9
+:101E9000BD79B350C699D2D2774DC803BA72DD4727
+:101EA000B0FF05659F3F14C7FB1BBA8E457E94EFBC
+:101EB0002543EB58BA5FDEA5D5C1E13F8D5A9DD5CC
+:101EC000A8D5598D5A9DD5A8D5598D5A9DD5A8D537
+:101ED000598D5A9DD5A8D5598D5A9DD5C8F5BBE5C4
+:101EE0000CDFA95FC5B0BBDEC3FD41FEFFFD6BF893
+:101EF000FFD03AE8C718175A0715564734C751B2EA
+:101F00006F597F0EA97B160F5FBC81F897DF607653
+:101F1000A249AF83E2FDF2BD11EC0F2E140E59FF62
+:101F2000D4F916C1F5D27E619B02FEE7658C331AA7
+:101F3000A8FF2F9A1CF4FA23EC03FB837D00C23E1A
+:101F40008C6903F6F18C994C385BC67B0FC77B1B01
+:101F5000CB75FD1AF21F842F11F641FEE34288FF74
+:101F6000A083C75DA06369A77CD7A4BFDFCC23F0A3
+:101F7000D59421FC894FFA933161BEBDF8CE98DA31
+:101F8000307E1F7C547B8F7574A37C1757264AF8CC
+:101F9000BB43F89528C863C9F0BE0F9EA6F14B1E3F
+:101FA00089E0BC65FDC8A5D3FE377EE5F342C98F45
+:101FB000DFD6FB2B3F215A0AC2A4FE15984506EE38
+:101FC0006B84218CEDA050DDACE07E74E53D623287
+:101FD000E45C6029D90E3AE3B5FB6D11ABD55B8D9E
+:101FE000DD15BB093F1197E8C4BDD6E8848302EF35
+:101FF0009F0AEB8A33E117FD63DC138A72F07E7966
+:102000008B82F9E19972FFB717873741AF0287C614
+:10201000E740DE732D8E36D4019C45094B70CE9F70
+:102020001BEDC8411DC0D9354AE2F18E36C5895431
+:1020300036614901BF3FB36EF9C48A776B8A88A6BF
+:102040007D5986B973F09D9AE2CFE4B959F4711CB9
+:10205000BBB1489EBF46BC2EFCB8B7EA9B19C9F776
+:102060006722D391837ECA2BBF5F44FA77E407AE21
+:102070009B0013353AE3718BA842AADD36C0E3DA40
+:102080007D5E97C15D0A5814E53172BBC19B0DF8A6
+:1020900096C1F753B4933E17619DA2C7264FCC203B
+:1020A0003CD1E2633FD9E172DD02FA5E9CE12A068F
+:1020B0000CAD9F43B638E7133DB7A23FF41D962EF3
+:1020C000CF254552EFCB8AA4FF98BE56DEC786CAFD
+:1020D000BDACC8A0F9B7BF4F37D15B8AEFE9F48B2D
+:1020E0002D8BB2410FD17B0FF641F42E001411312C
+:1020F0005CEFB8B69E79F87B654552BFC89F557DA9
+:1021000022FD19C374A37718F2C7510F788781DEB7
+:10211000518D7D36FC3B8C673D7D36C4F76757F7A4
+:10212000D9D0FEAC4BBE930E5DBFB148BE9F489F59
+:10213000DEC7F3C7D2B7BA394FEF1B863C2ABDFCC6
+:1021400093F5F2DE2583E3CB582DBE8C7D20A5BD13
+:1021500087F46DEC93D17CBF2D0A62B9BFD22AED12
+:10216000B4F281B2836D04C76F237A83F2AF095E44
+:10217000A27B505E64EC97EF2D09079FF6981887B5
+:10218000CE22BFAA11F2BDE528CD6F206F2B25BF4F
+:1021900050537EE412BF03C07CAC8F3B5BE85FBB57
+:1021A00049E214AE711E5D366F4D179F0FB75D6922
+:1021B000D7CE9BADEB717EA6FC6D507B65D9E12E31
+:1021C000C49BAA3D83DB6B967FCEE758CADF06B57A
+:1021D000DFF3D30FF99D4D5DFBE07692EF5390BF97
+:1021E0002EDFA326DF049CF78ED68439E5BF1FF0CF
+:1021F000AD80BD375547F0FBD99DBFC963BDD1E563
+:102200004DF39BBE9B7EACE5F19E3C91017BF83685
+:10221000D80BFF9436C83F79B8CE372B92FD4E9D30
+:1022200076BEAA2DB3739C4FACB5B2FF2A54C39CA3
+:10223000C06B8DD2CF886255F3533EB6FF13B70DF6
+:10224000E37A1E6F0078CC247E771CB756E27D239C
+:102250002CEC1F0A0D25D5BB091E312C673F908041
+:10226000179724F767E01F54D8AFBC7FA833FB143F
+:1022700079BFEFC8C17957BF6F6AD8E86D3D80F369
+:10228000B2E27D7229EA8A7744F0FD4100F546DA30
+:102290004FC330E9471BE6A7731C088892D215C8C4
+:1022A00043E68571FDB16198E351DC2736544CE477
+:1022B0003CFAE0DF64DCED9B6375228F6A98EC5892
+:1022C00083F72A0D0F38B8FF5545AEE77954F2A7CA
+:1022D000618EDC7F43450C9F7B74393434BA46E20F
+:1022E0007E6AC618F77F426EA3B4FBB986646A277C
+:1022F000F8845232FF27586792A477D20C07CBEDAF
+:10230000E8FC898FEE727038F1E39EA86E56E4A067
+:1023100073F1FF008751D9F610370000000000006C
+:102320000000000000000000050015000000000093
+:00000001FF
diff --git a/firmware/cxgb3/ael2005_opt_edc.bin.ihex b/firmware/cxgb3/ael2005_opt_edc.bin.ihex
new file mode 100644
index 00000000000..c1d6e5d3bea
--- /dev/null
+++ b/firmware/cxgb3/ael2005_opt_edc.bin.ihex
@@ -0,0 +1,69 @@
+:10000000CC002FF4CC013CD4CC022015CC0331051C
+:10001000CC046524CC0527FFCC06300FCC072C8BF5
+:10002000CC08300BCC094009CC0A400ECC0B2F7207
+:10003000CC0C3002CC0D1002CC0E2172CC0F301241
+:10004000CC101002CC1125D2CC123012CC131002DD
+:10005000CC14D01ECC1527D2CC163012CC171002DF
+:10006000CC182004CC193C84CC1A6436CC1B200755
+:10007000CC1C3F87CC1D8676CC1E40B7CC1FA74634
+:10008000CC204047CC215673CC222982CC2330028D
+:10009000CC2413D2CC258BBDCC262862CC273012A1
+:1000A000CC281002CC292092CC2A3012CC2B100262
+:1000B000CC2C5CC3CC2D0314CC2E2942CC2F300287
+:1000C000CC301002CC31D019CC322032CC333012AB
+:1000D000CC341002CC352A04CC363C74CC37643591
+:1000E000CC382FA4CC393CD4CC3A6624CC3B5563D5
+:1000F000CC3C2D42CC3D3002CC3E13D2CC3F464DC1
+:10010000CC402862CC413012CC421002CC43203289
+:10011000CC443012CC451002CC462FB4CC473CD452
+:10012000CC486624CC495563CC4A2D42CC4B300296
+:10013000CC4C13D2CC4D2ED2CC4E3002CC4F100230
+:10014000CC502FD2CC513002CC521002CC530004F0
+:10015000CC542942CC553002CC561002CC572092B8
+:10016000CC583012CC591002CC5A5CC3CC5B03176C
+:10017000CC5C2F72CC5D3002CC5E1002CC5F294289
+:10018000CC603002CC611002CC6222CDCC63301D39
+:10019000CC642862CC653012CC661002CC672ED2BB
+:1001A000CC683002CC691002CC6A2D72CC6B300264
+:1001B000CC6C1002CC6D628FCC6E2112CC6F3012E1
+:1001C000CC701002CC715AA3CC722DC2CC73300209
+:1001D000CC741312CC756F72CC761002CC772807D2
+:1001E000CC7831A7CC7920C4CC7A3C24CC7B672452
+:1001F000CC7C1002CC7D2807CC7E3187CC7F20C4FC
+:10020000CC803C24CC816724CC821002CC83251482
+:10021000CC843C64CC856436CC86DFF4CC876436F1
+:10022000CC881002CC8940A4CC8A643CCC8B40168C
+:10023000CC8C8C6CCC8D2B24CC8E3C24CC8F643518
+:10024000CC901002CC912B24CC923C24CC93643AD9
+:10025000CC944025CC958A5ACC961002CC97273165
+:10026000CC983011CC991001CC9AC7A0CC9B01003E
+:10027000CC9CC502CC9D53ACCC9EC503CC9FD5D5A0
+:10028000CCA0C600CCA12A6DCCA2C601CCA32A4C1E
+:10029000CCA4C602CCA50111CCA6C60CCCA7590093
+:1002A000CCA8C710CCA90700CCAAC718CCAB0700B4
+:1002B000CCACC720CCAD4700CCAEC801CCAF7F5092
+:1002C000CCB0C802CCB17760CCB2C803CCB37FCE7F
+:1002D000CCB4C804CCB55700CCB6C805CCB75F11B8
+:1002E000CCB8C806CCB94751CCBAC807CCBB57E18B
+:1002F000CCBCC808CCBD2700CCBEC809CCBF000010
+:10030000CCC0C821CCC10002CCC2C822CCC30014CE
+:10031000CCC4C832CCC51186CCC6C847CCC71E02D7
+:10032000CCC8C013CCC9F341CCCAC01ACCCB04464C
+:10033000CCCCC024CCCD1000CCCEC025CCCF0A0074
+:10034000CCD0C026CCD10C0CCCD2C027CCD30C0C3A
+:10035000CCD4C029CCD500A0CCD6C030CCD70A0094
+:10036000CCD8C03CCCD9001CCCDAC005CCDB7A069A
+:10037000CCDC0000CCDD2731CCDE3011CCDF10012D
+:10038000CCE0C620CCE10000CCE2C621CCE3003FAB
+:10039000CCE4C622CCE50000CCE6C623CCE70000C6
+:1003A000CCE8C624CCE90000CCEAC625CCEB0000A2
+:1003B000CCECC627CCED0000CCEEC628CCEF00007C
+:1003C000CCF0C62CCCF10000CCF20000CCF3280617
+:1003D000CCF43CB6CCF5C161CCF66134CCF76135D8
+:1003E000CCF85443CCF90303CCFA6524CCFB000BC6
+:1003F000CCFC1002CCFD2104CCFE3C24CCFF21051A
+:10040000CD003805CD016524CD02DFF4CD034005D4
+:10041000CD046524CD051002CD065DD3CD070306BE
+:10042000CD082FF7CD0938F7CD0A60B7CD0BDFFD2A
+:10043000CD0C000ACD0D1002CD0E00007CC7AE59C8
+:00000001FF
diff --git a/firmware/cxgb3/ael2005_twx_edc.bin.ihex b/firmware/cxgb3/ael2005_twx_edc.bin.ihex
new file mode 100644
index 00000000000..9b5e9e51fcb
--- /dev/null
+++ b/firmware/cxgb3/ael2005_twx_edc.bin.ihex
@@ -0,0 +1,93 @@
+:10000000CC004009CC0127FFCC02300FCC0340AA22
+:10001000CC04401CCC05401ECC062FF4CC073CD4AD
+:10002000CC082035CC093145CC0A6524CC0B26A25E
+:10003000CC0C3012CC0D1002CC0E29C2CC0F3002E9
+:10004000CC101002CC112072CC123012CC13100242
+:10005000CC1422CDCC15301DCC162E52CC1730121C
+:10006000CC181002CC1928E2CC1A3002CC1B10029A
+:10007000CC1C628FCC1D2AC2CC1E3012CC1F1002A9
+:10008000CC205553CC212AE2CC223002CC231302BF
+:10009000CC24401ECC252BE2CC263012CC271002DB
+:1000A000CC282DA2CC293012CC2A1002CC2B2BA28A
+:1000B000CC2C3002CC2D1002CC2E5EE3CC2F0305CD
+:1000C000CC30400ECC312BC2CC323002CC331002BB
+:1000D000CC342B82CC353012CC361002CC37566360
+:1000E000CC380302CC39401ECC3A6F72CC3B1002A4
+:1000F000CC3C628FCC3D2BE2CC3E3012CC3F100288
+:10010000CC4022CDCC41301DCC422E52CC433012BB
+:10011000CC441002CC452522CC463012CC471002EC
+:10012000CC482DA2CC493012CC4A1002CC4B2CA288
+:10013000CC4C3012CC4D1002CC4E2FA4CC4F3CD422
+:10014000CC506624CC51410BCC5256B3CC5303C493
+:10015000CC542FB2CC553002CC561002CC57220BC7
+:10016000CC58303BCC5956B3CC5A03C3CC5B866BCE
+:10017000CC5C400CCC5D23A2CC5E3012CC5F100274
+:10018000CC602DA2CC613012CC621002CC632CA2C8
+:10019000CC643012CC651002CC662FB4CC673CD452
+:1001A000CC686624CC6956B3CC6A03C3CC6B866B2F
+:1001B000CC6C401CCC6D2205CC6E3035CC6F5B53C3
+:1001C000CC702C52CC713002CC7213C2CC735CC395
+:1001D000CC740317CC752522CC763012CC77100264
+:1001E000CC782DA2CC793012CC7A1002CC7B2B8229
+:1001F000CC7C3012CC7D1002CC7E5663CC7F0303C6
+:10020000CC80401ECC810004CC822C42CC833012A6
+:10021000CC841002CC856F72CC861002CC87628FA2
+:10022000CC882304CC893C84CC8A6436CC8BDFF424
+:10023000CC8C6436CC8D2FF5CC8E3005CC8F865689
+:10024000CC90DFBACC9156A3CC92D05ACC9321C299
+:10025000CC943012CC951392CC96D05ACC9756A30E
+:10026000CC98DFBACC990383CC9A6F72CC9B1002E6
+:10027000CC9C28C5CC9D3005CC9E4178CC9F565354
+:10028000CCA00384CCA122B2CCA23012CCA3100209
+:10029000CCA42BE5CCA53005CCA641E8CCA7565381
+:1002A000CCA80382CCA90002CCAA4258CCAB2474BF
+:1002B000CCAC3C84CCAD6437CCAEDFF4CCAF64378F
+:1002C000CCB02FF5CCB13C05CCB28757CCB3B888B5
+:1002D000CCB49787CCB5DFF4CCB66724CCB7866AAC
+:1002E000CCB86F72CCB91002CCBA2D01CCBB301196
+:1002F000CCBC1001CCBDC620CCBE14E5CCBFC62101
+:10030000CCC0C53DCCC1C622CCC23CBECCC3C623EA
+:10031000CCC44452CCC5C624CCC6C5C5CCC7C625A2
+:10032000CCC8E01ECCC9C627CCCA0000CCCBC6289E
+:10033000CCCC0000CCCDC62BCCCE0000CCCFC62C74
+:10034000CCD00000CCD10000CCD22D01CCD33011C8
+:10035000CCD41001CCD5C620CCD60000CCD7C62139
+:10036000CCD80000CCD9C622CCDA00CECCDBC62358
+:10037000CCDC007FCCDDC624CCDE0032CCDFC62551
+:10038000CCE00000CCE1C627CCE20000CCE3C628DC
+:10039000CCE40000CCE5C62BCCE60000CCE7C62CB4
+:1003A000CCE80000CCE90000CCEA2D01CCEB301108
+:1003B000CCEC1001CCEDC502CCEE609FCCEFC600BA
+:1003C000CCF02A6ECCF1C601CCF22A2CCCF3C60CB0
+:1003D000CCF45400CCF5C710CCF60700CCF7C71806
+:1003E000CCF80700CCF9C720CCFA4700CCFBC728D3
+:1003F000CCFC0700CCFDC729CCFE1207CCFFC801FE
+:10040000CD007F50CD01C802CD027760CD03C80377
+:10041000CD047FCECD05C804CD06520ECD07C8054C
+:10042000CD085C11CD09C806CD0A3C51CD0BC807DB
+:10043000CD0C4061CD0DC808CD0E49C1CD0FC80906
+:10044000CD103840CD11C80ACD120000CD13C821FF
+:10045000CD140002CD15C822CD160046CD17C844D4
+:10046000CD18182FCD19C013CD1AF341CD1BC01ACA
+:10047000CD1C0446CD1DC024CD1E1000CD1FC025AF
+:10048000CD200A00CD21C026CD220C0CCD23C027C3
+:10049000CD240C0CCD25C029CD2600A0CD27C03001
+:1004A000CD280A00CD29C03CCD2A001CCD2B000050
+:1004B000CD2C2B84CD2D3C74CD2E6435CD2FDFF487
+:1004C000CD306435CD312806CD323006CD3385654B
+:1004D000CD342B24CD353C24CD366436CD371002B7
+:1004E000CD382B24CD393C24CD3A6436CD3B404524
+:1004F000CD3C8656CD3D1002CD3E2807CD3F31A7DD
+:10050000CD4020C4CD413C24CD426724CD431002D0
+:10051000CD442807CD453187CD4620C4CD473C2466
+:10052000CD486724CD491002CD4A2514CD4B3C64FB
+:10053000CD4C6436CD4DDFF4CD4E6436CD4F100238
+:10054000CD502806CD513CB6CD52C161CD5361345A
+:10055000CD546135CD555443CD560303CD57652455
+:10056000CD58000BCD591002CD5AD019CD5B2104C6
+:10057000CD5C3C24CD5D2105CD5E3805CD5F652485
+:10058000CD60DFF4CD614005CD626524CD632E8D55
+:10059000CD64303DCD655DD3CD660306CD672FF7C5
+:1005A000CD6838F7CD6960B7CD6ADFFDCD6B000A45
+:0C05B000CD6C1002CD6D000052A76B0E48
+:00000001FF
diff --git a/firmware/cxgb3/ael2020_twx_edc.bin.ihex b/firmware/cxgb3/ael2020_twx_edc.bin.ihex
new file mode 100644
index 00000000000..8b1337f4c32
--- /dev/null
+++ b/firmware/cxgb3/ael2020_twx_edc.bin.ihex
@@ -0,0 +1,100 @@
+:10000000D8004009D8012FFFD802300FD80340AAEA
+:10001000D804401CD805401ED8062FF4D8073DC48C
+:10002000D8082035D8093035D80A6524D80B2CB229
+:10003000D80C3012D80D1002D80E26E2D80F30227C
+:10004000D8101002D81127D2D8123022D81310029B
+:10005000D8142822D8153012D8161002D817249296
+:10006000D8183022D8191002D81A2772D81B30128B
+:10007000D81C1002D81D23D2D81E3022D81F10023F
+:10008000D82022CDD821301DD82227F2D8233022E3
+:10009000D8241002D8255553D8260307D82725225F
+:1000A000D8283022D8291002D82A2142D82B301241
+:1000B000D82C1002D82D4016D82E5E63D82F0344BA
+:1000C000D8302142D8313012D8321002D833400E05
+:1000D000D8342522D8353022D8361002D8372B52C2
+:1000E000D8383012D8391002D83A2742D83B3022BB
+:1000F000D83C1002D83D25E2D83E3022D83F10022D
+:10010000D8402FA4D8413DC4D8426624D843414B9F
+:10011000D84456B3D84503C6D846866BD847400C5A
+:10012000D8482712D8493012D84A1002D84B2C4B45
+:10013000D84C309BD84D56B3D84E03C3D84F866B9E
+:10014000D850400CD8512272D8523022D8531002C5
+:10015000D8542742D8553022D8561002D85725E215
+:10016000D8583022D8591002D85A2FB4D85B3DC481
+:10017000D85C6624D85D56B3D85E03C3D85F866B5F
+:10018000D860401CD8612C45D8623095D8635B5349
+:10019000D8642372D8653012D86613C2D8675CC39E
+:1001A000D8682712D8693012D86A1312D86B2B522C
+:1001B000D86C3012D86D1002D86E2742D86F30221A
+:1001C000D8701002D8712582D8723022D8731002EC
+:1001D000D8742142D8753012D8761002D877628F41
+:1001E000D8782985D87933A5D87A25E2D87B3022EA
+:1001F000D87C1002D87D5653D87E03D2D87F401EBB
+:10020000D8806F72D8811002D882628FD88323047D
+:10021000D8843C84D8856436D886DFF4D8876436A1
+:10022000D8882FF5D8893005D88A8656D88BDFBA7A
+:10023000D88C56A3D88DD05AD88E2972D88F301228
+:10024000D8901392D891D05AD89256A3D893DFBAA7
+:10025000D8940383D8956F72D8961002D8972B45FF
+:10026000D8983005D8994178D89A5653D89B0384AA
+:10027000D89C2A62D89D3012D89E1002D89F2F0594
+:10028000D8A03005D8A141C8D8A25653D8A303821C
+:10029000D8A40002D8A54218D8A62474D8A73C84B4
+:1002A000D8A86437D8A9DFF4D8AA6437D8AB2FF51B
+:1002B000D8AC3C05D8AD8757D8AEB888D8AF9787AB
+:1002C000D8B0DFF4D8B16724D8B2866AD8B36F72D9
+:1002D000D8B41002D8B52641D8B63021D8B710010D
+:1002E000D8B8C620D8B90000D8BAC621D8BB0000FB
+:1002F000D8BCC622D8BD00CED8BEC623D8BF007F8A
+:10030000D8C0C624D8C10032D8C2C625D8C3000080
+:10031000D8C4C627D8C50000D8C6C628D8C700008C
+:10032000D8C8C62CD8C90000D8CA0000D8CB2641EE
+:10033000D8CC3021D8CD1001D8CEC502D8CF53ACFF
+:10034000D8D0C503D8D12CD3D8D2C600D8D32A6EE2
+:10035000D8D4C601D8D52A2CD8D6C605D8D7555753
+:10036000D8D8C60CD8D95400D8DAC710D8DB0700C3
+:10037000D8DCC711D8DD0F06D8DEC718D8DF0700D4
+:10038000D8E0C719D8E10F06D8E2C720D8E3470064
+:10039000D8E4C721D8E50F06D8E6C728D8E7070074
+:1003A000D8E8C729D8E91207D8EAC801D8EB7F50A6
+:1003B000D8ECC802D8ED7760D8EEC803D8EF7FCE6E
+:1003C000D8F0C804D8F1520ED8F2C805D8F35C11A1
+:1003D000D8F4C806D8F53C51D8F6C807D8F740611C
+:1003E000D8F8C808D8F949C1D8FAC809D8FB3840A4
+:1003F000D8FCC80AD8FD0000D8FEC821D8FF0002EA
+:10040000D900C822D9010046D902C844D903182FFF
+:10041000D904C013D905F341D906C084D9070030E7
+:10042000D908C904D9091401D90ACB0CD90B000485
+:10043000D90CCB0ED90DA00AD90ECB0FD90FC0C045
+:10044000D910CB10D911C0C0D912CB11D91300A02B
+:10045000D914CB12D9150007D916C241D917A0005B
+:10046000D918C243D9197FE0D91AC604D91B000E86
+:10047000D91CC609D91D00F5D91EC611D91F000EF9
+:10048000D920C660D9219600D922C687D923000475
+:10049000D924C60AD92504F5D9260000D927264132
+:1004A000D9283021D9291001D92AC620D92B14E501
+:1004B000D92CC621D92DC53DD92EC622D92F3CBE57
+:1004C000D930C623D9314452D932C624D933C5C50F
+:1004D000D934C625D935E01ED936C627D93700000C
+:1004E000D938C628D9390000D93AC62CD93B0000E2
+:1004F000D93C0000D93D2B84D93E3C74D93F6435AA
+:10050000D940DFF4D9416435D9422806D9433006B1
+:10051000D9448565D9452B24D9463C24D94764362E
+:10052000D9481002D9492B24D94A3C24D94B6436E6
+:10053000D94C4045D94D8656D94E5663D94F030202
+:10054000D950401ED9511002D9522807D95331A78A
+:10055000D95420C4D9553C24D9566724D957100200
+:10056000D9582807D9593187D95A20C4D95B3C2496
+:10057000D95C6724D95D1002D95E24F4D95F3C644C
+:10058000D9606436D961DFF4D9626436D963100268
+:10059000D9642006D9653D76D966C161D9676134D1
+:1005A000D9686135D9695443D96A0303D96B652485
+:1005B000D96C00FBD96D1002D96E20D4D96F3C24C0
+:1005C000D9702025D9713005D9726524D9731002EC
+:1005D000D974D019D9752104D9763C24D97721054D
+:1005E000D9783805D9796524D97ADFF4D97B4005E3
+:1005F000D97C6524D97D2E8DD97E303DD97F2408C4
+:10060000D98035D8D9815DD3D9820307D98388872A
+:10061000D98463A7D9858887D98663A7D987DFFD61
+:10062000D98800F9D9891002D98A0000878C30D97D
+:00000001FF
diff --git a/fs/dlm/netlink.c b/fs/dlm/netlink.c
index ccc9d62c462..55ea369f43a 100644
--- a/fs/dlm/netlink.c
+++ b/fs/dlm/netlink.c
@@ -63,7 +63,7 @@ static int send_data(struct sk_buff *skb)
return rv;
}
- return genlmsg_unicast(skb, listener_nlpid);
+ return genlmsg_unicast(&init_net, skb, listener_nlpid);
}
static int user_cmd(struct sk_buff *skb, struct genl_info *info)
diff --git a/include/asm-generic/socket.h b/include/asm-generic/socket.h
index 5d79e409241..538991cef6f 100644
--- a/include/asm-generic/socket.h
+++ b/include/asm-generic/socket.h
@@ -60,4 +60,7 @@
#define SO_TIMESTAMPING 37
#define SCM_TIMESTAMPING SO_TIMESTAMPING
+#define SO_PROTOCOL 38
+#define SO_DOMAIN 39
+
#endif /* __ASM_GENERIC_SOCKET_H */
diff --git a/include/linux/connector.h b/include/linux/connector.h
index b68d27850d5..47ebf416f51 100644
--- a/include/linux/connector.h
+++ b/include/linux/connector.h
@@ -136,7 +136,7 @@ struct cn_callback_data {
void *ddata;
void *callback_priv;
- void (*callback) (void *);
+ void (*callback) (struct cn_msg *);
void *free;
};
@@ -167,11 +167,11 @@ struct cn_dev {
struct cn_queue_dev *cbdev;
};
-int cn_add_callback(struct cb_id *, char *, void (*callback) (void *));
+int cn_add_callback(struct cb_id *, char *, void (*callback) (struct cn_msg *));
void cn_del_callback(struct cb_id *);
int cn_netlink_send(struct cn_msg *, u32, gfp_t);
-int cn_queue_add_callback(struct cn_queue_dev *dev, char *name, struct cb_id *id, void (*callback)(void *));
+int cn_queue_add_callback(struct cn_queue_dev *dev, char *name, struct cb_id *id, void (*callback)(struct cn_msg *));
void cn_queue_del_callback(struct cn_queue_dev *dev, struct cb_id *id);
int queue_cn_work(struct cn_callback_entry *cbq, struct work_struct *work);
diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h
index 9b660bd2e2b..90c4a3616d9 100644
--- a/include/linux/ethtool.h
+++ b/include/linux/ethtool.h
@@ -368,6 +368,7 @@ struct net_device;
/* Some generic methods drivers may use in their ethtool_ops */
u32 ethtool_op_get_link(struct net_device *dev);
+u32 ethtool_op_get_rx_csum(struct net_device *dev);
u32 ethtool_op_get_tx_csum(struct net_device *dev);
int ethtool_op_set_tx_csum(struct net_device *dev, u32 data);
int ethtool_op_set_tx_hw_csum(struct net_device *dev, u32 data);
diff --git a/include/linux/icmpv6.h b/include/linux/icmpv6.h
index b6a85183c33..c0d8357917e 100644
--- a/include/linux/icmpv6.h
+++ b/include/linux/icmpv6.h
@@ -171,8 +171,6 @@ struct icmp6_filter {
#ifdef __KERNEL__
#include <linux/netdevice.h>
-#include <linux/skbuff.h>
-
extern void icmpv6_send(struct sk_buff *skb,
u8 type, u8 code,
diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
index a9173d5434d..21556a2d9e7 100644
--- a/include/linux/ieee80211.h
+++ b/include/linux/ieee80211.h
@@ -802,6 +802,31 @@ struct ieee80211_ht_cap {
#define IEEE80211_HT_AMPDU_PARM_FACTOR 0x03
#define IEEE80211_HT_AMPDU_PARM_DENSITY 0x1C
+/*
+ * Maximum length of AMPDU that the STA can receive.
+ * Length = 2 ^ (13 + max_ampdu_length_exp) - 1 (octets)
+ */
+enum ieee80211_max_ampdu_length_exp {
+ IEEE80211_HT_MAX_AMPDU_8K = 0,
+ IEEE80211_HT_MAX_AMPDU_16K = 1,
+ IEEE80211_HT_MAX_AMPDU_32K = 2,
+ IEEE80211_HT_MAX_AMPDU_64K = 3
+};
+
+#define IEEE80211_HT_MAX_AMPDU_FACTOR 13
+
+/* Minimum MPDU start spacing */
+enum ieee80211_min_mpdu_spacing {
+ IEEE80211_HT_MPDU_DENSITY_NONE = 0, /* No restriction */
+ IEEE80211_HT_MPDU_DENSITY_0_25 = 1, /* 1/4 usec */
+ IEEE80211_HT_MPDU_DENSITY_0_5 = 2, /* 1/2 usec */
+ IEEE80211_HT_MPDU_DENSITY_1 = 3, /* 1 usec */
+ IEEE80211_HT_MPDU_DENSITY_2 = 4, /* 2 usec */
+ IEEE80211_HT_MPDU_DENSITY_4 = 5, /* 4 usec */
+ IEEE80211_HT_MPDU_DENSITY_8 = 6, /* 8 usec */
+ IEEE80211_HT_MPDU_DENSITY_16 = 7 /* 16 usec */
+};
+
/**
* struct ieee80211_ht_info - HT information
*
@@ -1196,6 +1221,10 @@ enum ieee80211_sa_query_action {
#define WLAN_CIPHER_SUITE_WEP104 0x000FAC05
#define WLAN_CIPHER_SUITE_AES_CMAC 0x000FAC06
+/* AKM suite selectors */
+#define WLAN_AKM_SUITE_8021X 0x000FAC01
+#define WLAN_AKM_SUITE_PSK 0x000FAC02
+
#define WLAN_MAX_KEY_LEN 32
/**
diff --git a/include/linux/if_ether.h b/include/linux/if_ether.h
index 70fdba2bbf7..580b6004d00 100644
--- a/include/linux/if_ether.h
+++ b/include/linux/if_ether.h
@@ -139,10 +139,10 @@ extern ssize_t sysfs_format_mac(char *buf, const unsigned char *addr, int len);
/*
* Display a 6 byte device address (MAC) in a readable format.
*/
-extern char *print_mac(char *buf, const unsigned char *addr);
+extern char *print_mac(char *buf, const unsigned char *addr) __deprecated;
#define MAC_FMT "%02x:%02x:%02x:%02x:%02x:%02x"
#define MAC_BUF_SIZE 18
-#define DECLARE_MAC_BUF(var) char var[MAC_BUF_SIZE] __maybe_unused
+#define DECLARE_MAC_BUF(var) char var[MAC_BUF_SIZE]
#endif
diff --git a/include/linux/if_tun.h b/include/linux/if_tun.h
index 915ba5789f0..3f5fd523b49 100644
--- a/include/linux/if_tun.h
+++ b/include/linux/if_tun.h
@@ -62,6 +62,7 @@
#define TUN_F_TSO4 0x02 /* I can handle TSO for IPv4 packets */
#define TUN_F_TSO6 0x04 /* I can handle TSO for IPv6 packets */
#define TUN_F_TSO_ECN 0x08 /* I can handle TSO with ECN bits. */
+#define TUN_F_UFO 0x10 /* I can handle UFO packets */
/* Protocol info prepended to the packets (when IFF_NO_PI is not set) */
#define TUN_PKT_STRIP 0x0001
diff --git a/include/linux/isdn/hdlc.h b/include/linux/isdn/hdlc.h
new file mode 100644
index 00000000000..4b3ecc40889
--- /dev/null
+++ b/include/linux/isdn/hdlc.h
@@ -0,0 +1,82 @@
+/*
+ * hdlc.h -- General purpose ISDN HDLC decoder.
+ *
+ * Implementation of a HDLC decoder/encoder in software.
+ * Neccessary because some ISDN devices don't have HDLC
+ * controllers.
+ *
+ * Copyright (C)
+ * 2009 Karsten Keil <keil@b1-systems.de>
+ * 2002 Wolfgang Mües <wolfgang@iksw-muees.de>
+ * 2001 Frode Isaksen <fisaksen@bewan.com>
+ * 2001 Kai Germaschewski <kai.germaschewski@gmx.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __ISDNHDLC_H__
+#define __ISDNHDLC_H__
+
+struct isdnhdlc_vars {
+ int bit_shift;
+ int hdlc_bits1;
+ int data_bits;
+ int ffbit_shift; /* encoding only */
+ int state;
+ int dstpos;
+
+ u16 crc;
+
+ u8 cbin;
+ u8 shift_reg;
+ u8 ffvalue;
+
+ /* set if transferring data */
+ u32 data_received:1;
+ /* set if D channel (send idle instead of flags) */
+ u32 dchannel:1;
+ /* set if 56K adaptation */
+ u32 do_adapt56:1;
+ /* set if in closing phase (need to send CRC + flag) */
+ u32 do_closing:1;
+ /* set if data is bitreverse */
+ u32 do_bitreverse:1;
+};
+
+/* Feature Flags */
+#define HDLC_56KBIT 0x01
+#define HDLC_DCHANNEL 0x02
+#define HDLC_BITREVERSE 0x04
+
+/*
+ The return value from isdnhdlc_decode is
+ the frame length, 0 if no complete frame was decoded,
+ or a negative error number
+*/
+#define HDLC_FRAMING_ERROR 1
+#define HDLC_CRC_ERROR 2
+#define HDLC_LENGTH_ERROR 3
+
+extern void isdnhdlc_rcv_init(struct isdnhdlc_vars *hdlc, u32 features);
+
+extern int isdnhdlc_decode(struct isdnhdlc_vars *hdlc, const u8 *src,
+ int slen, int *count, u8 *dst, int dsize);
+
+extern void isdnhdlc_out_init(struct isdnhdlc_vars *hdlc, u32 features);
+
+extern int isdnhdlc_encode(struct isdnhdlc_vars *hdlc, const u8 *src,
+ u16 slen, int *count, u8 *dst, int dsize);
+
+#endif /* __ISDNHDLC_H__ */
diff --git a/include/linux/mISDNhw.h b/include/linux/mISDNhw.h
index 7f9831da847..4af841408fb 100644
--- a/include/linux/mISDNhw.h
+++ b/include/linux/mISDNhw.h
@@ -168,6 +168,7 @@ struct bchannel {
extern int mISDN_initdchannel(struct dchannel *, int, void *);
extern int mISDN_initbchannel(struct bchannel *, int);
extern int mISDN_freedchannel(struct dchannel *);
+extern void mISDN_clear_bchannel(struct bchannel *);
extern int mISDN_freebchannel(struct bchannel *);
extern void queue_ch_frame(struct mISDNchannel *, u_int,
int, struct sk_buff *);
diff --git a/include/linux/mISDNif.h b/include/linux/mISDNif.h
index 45100b39a7c..536ca12442c 100644
--- a/include/linux/mISDNif.h
+++ b/include/linux/mISDNif.h
@@ -37,7 +37,7 @@
*/
#define MISDN_MAJOR_VERSION 1
#define MISDN_MINOR_VERSION 1
-#define MISDN_RELEASE 20
+#define MISDN_RELEASE 21
/* primitives for information exchange
* generell format
@@ -153,6 +153,18 @@
#define HFC_VOL_CHANGE_RX 0x2602
#define HFC_SPL_LOOP_ON 0x2603
#define HFC_SPL_LOOP_OFF 0x2604
+/* for T30 FAX and analog modem */
+#define HW_MOD_FRM 0x4000
+#define HW_MOD_FRH 0x4001
+#define HW_MOD_FTM 0x4002
+#define HW_MOD_FTH 0x4003
+#define HW_MOD_FTS 0x4004
+#define HW_MOD_CONNECT 0x4010
+#define HW_MOD_OK 0x4011
+#define HW_MOD_NOCARR 0x4012
+#define HW_MOD_FCERROR 0x4013
+#define HW_MOD_READY 0x4014
+#define HW_MOD_LASTDATA 0x4015
/* DSP_TONE_PATT_ON parameter */
#define TONE_OFF 0x0000
@@ -224,6 +236,8 @@
#define ISDN_P_B_L2DTMF 0x24
#define ISDN_P_B_L2DSP 0x25
#define ISDN_P_B_L2DSPHDLC 0x26
+#define ISDN_P_B_T30_FAX 0x27
+#define ISDN_P_B_MODEM_ASYNC 0x28
#define OPTION_L2_PMX 1
#define OPTION_L2_PTP 2
diff --git a/include/linux/mmc/sdio_ids.h b/include/linux/mmc/sdio_ids.h
index 39751c8cde9..2dbfb5a0599 100644
--- a/include/linux/mmc/sdio_ids.h
+++ b/include/linux/mmc/sdio_ids.h
@@ -22,6 +22,12 @@
/*
* Vendors and devices. Sort key: vendor first, device next.
*/
+#define SDIO_VENDOR_ID_INTEL 0x0089
+#define SDIO_DEVICE_ID_INTEL_IWMC3200WIMAX 0x1402
+#define SDIO_DEVICE_ID_INTEL_IWMC3200WIFI 0x1403
+#define SDIO_DEVICE_ID_INTEL_IWMC3200TOP 0x1404
+#define SDIO_DEVICE_ID_INTEL_IWMC3200GPS 0x1405
+#define SDIO_DEVICE_ID_INTEL_IWMC3200BT 0x1406
#define SDIO_VENDOR_ID_MARVELL 0x02df
#define SDIO_DEVICE_ID_MARVELL_LIBERTAS 0x9103
diff --git a/include/linux/net_dropmon.h b/include/linux/net_dropmon.h
index 3ceb0cc1bc7..2a739462cae 100644
--- a/include/linux/net_dropmon.h
+++ b/include/linux/net_dropmon.h
@@ -3,7 +3,6 @@
#include <linux/types.h>
#include <linux/netlink.h>
-#include <linux/types.h>
struct net_dm_drop_point {
__u8 pc[8];
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index d4a4d986779..9f25ab2899d 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -72,10 +72,6 @@ struct wireless_dev;
/* Backlog congestion levels */
#define NET_RX_SUCCESS 0 /* keep 'em coming, baby */
#define NET_RX_DROP 1 /* packet dropped */
-#define NET_RX_CN_LOW 2 /* storm alert, just in case */
-#define NET_RX_CN_MOD 3 /* Storm on its way! */
-#define NET_RX_CN_HIGH 4 /* The storm is here */
-#define NET_RX_BAD 5 /* packet dropped due to kernel error */
/* NET_XMIT_CN is special. It does not guarantee that this packet is lost. It
* indicates that the device will soon be dropping packets, or already drops
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index dbea93b694e..a8d71ed43a0 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -242,6 +242,29 @@
* @NL80211_CMD_LEAVE_IBSS: Leave the IBSS -- no special arguments, the IBSS is
* determined by the network interface.
*
+ * @NL80211_CMD_TESTMODE: testmode command, takes a wiphy (or ifindex) attribute
+ * to identify the device, and the TESTDATA blob attribute to pass through
+ * to the driver.
+ *
+ * @NL80211_CMD_CONNECT: connection request and notification; this command
+ * requests to connect to a specified network but without separating
+ * auth and assoc steps. For this, you need to specify the SSID in a
+ * %NL80211_ATTR_SSID attribute, and can optionally specify the association
+ * IEs in %NL80211_ATTR_IE, %NL80211_ATTR_AUTH_TYPE, %NL80211_ATTR_MAC,
+ * %NL80211_ATTR_WIPHY_FREQ and %NL80211_ATTR_CONTROL_PORT.
+ * It is also sent as an event, with the BSSID and response IEs when the
+ * connection is established or failed to be established. This can be
+ * determined by the STATUS_CODE attribute.
+ * @NL80211_CMD_ROAM: request that the card roam (currently not implemented),
+ * sent as an event when the card/driver roamed by itself.
+ * @NL80211_CMD_DISCONNECT: drop a given connection; also used to notify
+ * userspace that a connection was dropped by the AP or due to other
+ * reasons, for this the %NL80211_ATTR_DISCONNECTED_BY_AP and
+ * %NL80211_ATTR_REASON_CODE attributes are used.
+ *
+ * @NL80211_CMD_SET_WIPHY_NETNS: Set a wiphy's netns. Note that all devices
+ * associated with this wiphy must be down and will follow.
+ *
* @NL80211_CMD_MAX: highest used command number
* @__NL80211_CMD_AFTER_LAST: internal use
*/
@@ -310,6 +333,14 @@ enum nl80211_commands {
NL80211_CMD_JOIN_IBSS,
NL80211_CMD_LEAVE_IBSS,
+ NL80211_CMD_TESTMODE,
+
+ NL80211_CMD_CONNECT,
+ NL80211_CMD_ROAM,
+ NL80211_CMD_DISCONNECT,
+
+ NL80211_CMD_SET_WIPHY_NETNS,
+
/* add new commands above here */
/* used to define NL80211_CMD_MAX below */
@@ -449,10 +480,6 @@ enum nl80211_commands {
* @NL80211_ATTR_SCAN_FREQUENCIES: nested attribute with frequencies (in MHz)
* @NL80211_ATTR_SCAN_SSIDS: nested attribute with SSIDs, leave out for passive
* scanning and include a zero-length SSID (wildcard) for wildcard scan
- * @NL80211_ATTR_SCAN_GENERATION: the scan generation increases whenever the
- * scan result list changes (BSS expired or added) so that applications
- * can verify that they got a single, consistent snapshot (when all dump
- * messages carried the same generation number)
* @NL80211_ATTR_BSS: scan result BSS
*
* @NL80211_ATTR_REG_INITIATOR: indicates who requested the regulatory domain
@@ -511,6 +538,52 @@ enum nl80211_commands {
* authorized by user space. Otherwise, port is marked authorized by
* default in station mode.
*
+ * @NL80211_ATTR_TESTDATA: Testmode data blob, passed through to the driver.
+ * We recommend using nested, driver-specific attributes within this.
+ *
+ * @NL80211_ATTR_DISCONNECTED_BY_AP: A flag indicating that the DISCONNECT
+ * event was due to the AP disconnecting the station, and not due to
+ * a local disconnect request.
+ * @NL80211_ATTR_STATUS_CODE: StatusCode for the %NL80211_CMD_CONNECT
+ * event (u16)
+ * @NL80211_ATTR_PRIVACY: Flag attribute, used with connect(), indicating
+ * that protected APs should be used.
+ *
+ * @NL80211_ATTR_CIPHERS_PAIRWISE: Used with CONNECT and ASSOCIATE to
+ * indicate which unicast key ciphers will be used with the connection
+ * (an array of u32).
+ * @NL80211_ATTR_CIPHER_GROUP: Used with CONNECT and ASSOCIATE to indicate
+ * which group key cipher will be used with the connection (a u32).
+ * @NL80211_ATTR_WPA_VERSIONS: Used with CONNECT and ASSOCIATE to indicate
+ * which WPA version(s) the AP we want to associate with is using
+ * (a u32 with flags from &enum nl80211_wpa_versions).
+ * @NL80211_ATTR_AKM_SUITES: Used with CONNECT and ASSOCIATE to indicate
+ * which key management algorithm(s) to use (an array of u32).
+ *
+ * @NL80211_ATTR_REQ_IE: (Re)association request information elements as
+ * sent out by the card, for ROAM and successful CONNECT events.
+ * @NL80211_ATTR_RESP_IE: (Re)association response information elements as
+ * sent by peer, for ROAM and successful CONNECT events.
+ *
+ * @NL80211_ATTR_PREV_BSSID: previous BSSID, to be used by in ASSOCIATE
+ * commands to specify using a reassociate frame
+ *
+ * @NL80211_ATTR_KEY: key information in a nested attribute with
+ * %NL80211_KEY_* sub-attributes
+ * @NL80211_ATTR_KEYS: array of keys for static WEP keys for connect()
+ * and join_ibss(), key information is in a nested attribute each
+ * with %NL80211_KEY_* sub-attributes
+ *
+ * @NL80211_ATTR_PID: Process ID of a network namespace.
+ *
+ * @NL80211_ATTR_GENERATION: Used to indicate consistent snapshots for
+ * dumps. This number increases whenever the object list being
+ * dumped changes, and as such userspace can verify that it has
+ * obtained a complete and consistent snapshot by verifying that
+ * all dump messages contain the same generation number. If it
+ * changed then the list changed and the dump should be repeated
+ * completely from scratch.
+ *
* @NL80211_ATTR_MAX: highest attribute number currently defined
* @__NL80211_ATTR_AFTER_LAST: internal use
*/
@@ -582,7 +655,7 @@ enum nl80211_attrs {
NL80211_ATTR_SCAN_FREQUENCIES,
NL80211_ATTR_SCAN_SSIDS,
- NL80211_ATTR_SCAN_GENERATION,
+ NL80211_ATTR_GENERATION, /* replaces old SCAN_GENERATION */
NL80211_ATTR_BSS,
NL80211_ATTR_REG_INITIATOR,
@@ -619,16 +692,42 @@ enum nl80211_attrs {
NL80211_ATTR_CONTROL_PORT,
+ NL80211_ATTR_TESTDATA,
+
+ NL80211_ATTR_PRIVACY,
+
+ NL80211_ATTR_DISCONNECTED_BY_AP,
+ NL80211_ATTR_STATUS_CODE,
+
+ NL80211_ATTR_CIPHER_SUITES_PAIRWISE,
+ NL80211_ATTR_CIPHER_SUITE_GROUP,
+ NL80211_ATTR_WPA_VERSIONS,
+ NL80211_ATTR_AKM_SUITES,
+
+ NL80211_ATTR_REQ_IE,
+ NL80211_ATTR_RESP_IE,
+
+ NL80211_ATTR_PREV_BSSID,
+
+ NL80211_ATTR_KEY,
+ NL80211_ATTR_KEYS,
+
+ NL80211_ATTR_PID,
+
/* add attributes here, update the policy in nl80211.c */
__NL80211_ATTR_AFTER_LAST,
NL80211_ATTR_MAX = __NL80211_ATTR_AFTER_LAST - 1
};
+/* source-level API compatibility */
+#define NL80211_ATTR_SCAN_GENERATION NL80211_ATTR_GENERATION
+
/*
* Allow user space programs to use #ifdef on new attributes by defining them
* here
*/
+#define NL80211_CMD_CONNECT NL80211_CMD_CONNECT
#define NL80211_ATTR_HT_CAPABILITY NL80211_ATTR_HT_CAPABILITY
#define NL80211_ATTR_BSS_BASIC_RATES NL80211_ATTR_BSS_BASIC_RATES
#define NL80211_ATTR_WIPHY_TXQ_PARAMS NL80211_ATTR_WIPHY_TXQ_PARAMS
@@ -642,6 +741,12 @@ enum nl80211_attrs {
#define NL80211_ATTR_SSID NL80211_ATTR_SSID
#define NL80211_ATTR_AUTH_TYPE NL80211_ATTR_AUTH_TYPE
#define NL80211_ATTR_REASON_CODE NL80211_ATTR_REASON_CODE
+#define NL80211_ATTR_CIPHER_SUITES_PAIRWISE NL80211_ATTR_CIPHER_SUITES_PAIRWISE
+#define NL80211_ATTR_CIPHER_SUITE_GROUP NL80211_ATTR_CIPHER_SUITE_GROUP
+#define NL80211_ATTR_WPA_VERSIONS NL80211_ATTR_WPA_VERSIONS
+#define NL80211_ATTR_AKM_SUITES NL80211_ATTR_AKM_SUITES
+#define NL80211_ATTR_KEY NL80211_ATTR_KEY
+#define NL80211_ATTR_KEYS NL80211_ATTR_KEYS
#define NL80211_MAX_SUPP_RATES 32
#define NL80211_MAX_SUPP_REG_RULES 32
@@ -650,6 +755,9 @@ enum nl80211_attrs {
#define NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY 24
#define NL80211_HT_CAPABILITY_LEN 26
+#define NL80211_MAX_NR_CIPHER_SUITES 5
+#define NL80211_MAX_NR_AKM_SUITES 2
+
/**
* enum nl80211_iftype - (virtual) interface types
*
@@ -1168,6 +1276,7 @@ enum nl80211_channel_type {
* in mBm (100 * dBm) (s32)
* @NL80211_BSS_SIGNAL_UNSPEC: signal strength of the probe response/beacon
* in unspecified units, scaled to 0..100 (u8)
+ * @NL80211_BSS_STATUS: status, if this BSS is "used"
* @__NL80211_BSS_AFTER_LAST: internal
* @NL80211_BSS_MAX: highest BSS attribute
*/
@@ -1181,6 +1290,7 @@ enum nl80211_bss {
NL80211_BSS_INFORMATION_ELEMENTS,
NL80211_BSS_SIGNAL_MBM,
NL80211_BSS_SIGNAL_UNSPEC,
+ NL80211_BSS_STATUS,
/* keep last */
__NL80211_BSS_AFTER_LAST,
@@ -1188,18 +1298,37 @@ enum nl80211_bss {
};
/**
+ * enum nl80211_bss_status - BSS "status"
+ */
+enum nl80211_bss_status {
+ NL80211_BSS_STATUS_AUTHENTICATED,
+ NL80211_BSS_STATUS_ASSOCIATED,
+ NL80211_BSS_STATUS_IBSS_JOINED,
+};
+
+/**
* enum nl80211_auth_type - AuthenticationType
*
* @NL80211_AUTHTYPE_OPEN_SYSTEM: Open System authentication
* @NL80211_AUTHTYPE_SHARED_KEY: Shared Key authentication (WEP only)
* @NL80211_AUTHTYPE_FT: Fast BSS Transition (IEEE 802.11r)
* @NL80211_AUTHTYPE_NETWORK_EAP: Network EAP (some Cisco APs and mainly LEAP)
+ * @__NL80211_AUTHTYPE_NUM: internal
+ * @NL80211_AUTHTYPE_MAX: maximum valid auth algorithm
+ * @NL80211_AUTHTYPE_AUTOMATIC: determine automatically (if necessary by
+ * trying multiple times); this is invalid in netlink -- leave out
+ * the attribute for this on CONNECT commands.
*/
enum nl80211_auth_type {
NL80211_AUTHTYPE_OPEN_SYSTEM,
NL80211_AUTHTYPE_SHARED_KEY,
NL80211_AUTHTYPE_FT,
NL80211_AUTHTYPE_NETWORK_EAP,
+
+ /* keep last */
+ __NL80211_AUTHTYPE_NUM,
+ NL80211_AUTHTYPE_MAX = __NL80211_AUTHTYPE_NUM - 1,
+ NL80211_AUTHTYPE_AUTOMATIC
};
/**
@@ -1224,4 +1353,39 @@ enum nl80211_mfp {
NL80211_MFP_REQUIRED,
};
+enum nl80211_wpa_versions {
+ NL80211_WPA_VERSION_1 = 1 << 0,
+ NL80211_WPA_VERSION_2 = 1 << 1,
+};
+
+/**
+ * enum nl80211_key_attributes - key attributes
+ * @__NL80211_KEY_INVALID: invalid
+ * @NL80211_KEY_DATA: (temporal) key data; for TKIP this consists of
+ * 16 bytes encryption key followed by 8 bytes each for TX and RX MIC
+ * keys
+ * @NL80211_KEY_IDX: key ID (u8, 0-3)
+ * @NL80211_KEY_CIPHER: key cipher suite (u32, as defined by IEEE 802.11
+ * section 7.3.2.25.1, e.g. 0x000FAC04)
+ * @NL80211_KEY_SEQ: transmit key sequence number (IV/PN) for TKIP and
+ * CCMP keys, each six bytes in little endian
+ * @NL80211_KEY_DEFAULT: flag indicating default key
+ * @NL80211_KEY_DEFAULT_MGMT: flag indicating default management key
+ * @__NL80211_KEY_AFTER_LAST: internal
+ * @NL80211_KEY_MAX: highest key attribute
+ */
+enum nl80211_key_attributes {
+ __NL80211_KEY_INVALID,
+ NL80211_KEY_DATA,
+ NL80211_KEY_IDX,
+ NL80211_KEY_CIPHER,
+ NL80211_KEY_SEQ,
+ NL80211_KEY_DEFAULT,
+ NL80211_KEY_DEFAULT_MGMT,
+
+ /* keep last */
+ __NL80211_KEY_AFTER_LAST,
+ NL80211_KEY_MAX = __NL80211_KEY_AFTER_LAST - 1
+};
+
#endif /* __LINUX_NL80211_H */
diff --git a/include/linux/nl802154.h b/include/linux/nl802154.h
index 2cda00ccfcc..9a1af5f871a 100644
--- a/include/linux/nl802154.h
+++ b/include/linux/nl802154.h
@@ -69,7 +69,7 @@ enum {
#define IEEE802154_ATTR_MAX (__IEEE802154_ATTR_MAX - 1)
-extern struct nla_policy ieee802154_policy[];
+extern const struct nla_policy ieee802154_policy[];
/* commands */
/* REQ should be responded with CONF
@@ -111,6 +111,8 @@ enum {
IEEE802154_RX_ENABLE_REQ, /* Not supported yet */
IEEE802154_RX_ENABLE_CONF, /* Not supported yet */
+ IEEE802154_LIST_IFACE,
+
__IEEE802154_CMD_MAX,
};
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index 73b46b6b904..fdc3110c90c 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -1984,6 +1984,8 @@
#define PCI_VENDOR_ID_SAMSUNG 0x144d
+#define PCI_VENDOR_ID_GIGABYTE 0x1458
+
#define PCI_VENDOR_ID_AMBIT 0x1468
#define PCI_VENDOR_ID_MYRICOM 0x14c1
diff --git a/include/linux/rfkill.h b/include/linux/rfkill.h
index 278777fa8a3..21ca51bf4dd 100644
--- a/include/linux/rfkill.h
+++ b/include/linux/rfkill.h
@@ -47,6 +47,7 @@ enum rfkill_type {
RFKILL_TYPE_UWB,
RFKILL_TYPE_WIMAX,
RFKILL_TYPE_WWAN,
+ RFKILL_TYPE_GPS,
NUM_RFKILL_TYPES,
};
@@ -82,6 +83,20 @@ struct rfkill_event {
__u8 soft, hard;
} __packed;
+/*
+ * We are planning to be backward and forward compatible with changes
+ * to the event struct, by adding new, optional, members at the end.
+ * When reading an event (whether the kernel from userspace or vice
+ * versa) we need to accept anything that's at least as large as the
+ * version 1 event size, but might be able to accept other sizes in
+ * the future.
+ *
+ * One exception is the kernel -- we already have two event sizes in
+ * that we've made the 'hard' member optional since our only option
+ * is to ignore it anyway.
+ */
+#define RFKILL_EVENT_SIZE_V1 8
+
/* ioctl for turning off rfkill-input (if present) */
#define RFKILL_IOC_MAGIC 'R'
#define RFKILL_IOC_NOINPUT 1
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index f2c69a2cca1..df7b23ac66e 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -304,7 +304,6 @@ typedef unsigned char *sk_buff_data_t;
* @tc_index: Traffic control index
* @tc_verd: traffic control verdict
* @ndisc_nodetype: router type (from link layer)
- * @do_not_encrypt: set to prevent encryption of this frame
* @dma_cookie: a cookie to one of several possible DMA operations
* done by skb DMA functions
* @secmark: security marking
@@ -380,12 +379,9 @@ struct sk_buff {
#ifdef CONFIG_IPV6_NDISC_NODETYPE
__u8 ndisc_nodetype:2;
#endif
-#if defined(CONFIG_MAC80211) || defined(CONFIG_MAC80211_MODULE)
- __u8 do_not_encrypt:1;
-#endif
kmemcheck_bitfield_end(flags2);
- /* 0/13/14 bit hole */
+ /* 0/14 bit hole */
#ifdef CONFIG_NET_DMA
dma_cookie_t dma_cookie;
diff --git a/include/linux/ssb/ssb.h b/include/linux/ssb/ssb.h
index 5ae8fa22d33..17ffc1f84d7 100644
--- a/include/linux/ssb/ssb.h
+++ b/include/linux/ssb/ssb.h
@@ -27,24 +27,54 @@ struct ssb_sprom {
u8 et1mdcport; /* MDIO for enet1 */
u8 board_rev; /* Board revision number from SPROM. */
u8 country_code; /* Country Code */
- u8 ant_available_a; /* A-PHY antenna available bits (up to 4) */
- u8 ant_available_bg; /* B/G-PHY antenna available bits (up to 4) */
+ u8 ant_available_a; /* 2GHz antenna available bits (up to 4) */
+ u8 ant_available_bg; /* 5GHz antenna available bits (up to 4) */
u16 pa0b0;
u16 pa0b1;
u16 pa0b2;
u16 pa1b0;
u16 pa1b1;
u16 pa1b2;
+ u16 pa1lob0;
+ u16 pa1lob1;
+ u16 pa1lob2;
+ u16 pa1hib0;
+ u16 pa1hib1;
+ u16 pa1hib2;
u8 gpio0; /* GPIO pin 0 */
u8 gpio1; /* GPIO pin 1 */
u8 gpio2; /* GPIO pin 2 */
u8 gpio3; /* GPIO pin 3 */
- u16 maxpwr_a; /* A-PHY Amplifier Max Power (in dBm Q5.2) */
- u16 maxpwr_bg; /* B/G-PHY Amplifier Max Power (in dBm Q5.2) */
+ u16 maxpwr_bg; /* 2.4GHz Amplifier Max Power (in dBm Q5.2) */
+ u16 maxpwr_al; /* 5.2GHz Amplifier Max Power (in dBm Q5.2) */
+ u16 maxpwr_a; /* 5.3GHz Amplifier Max Power (in dBm Q5.2) */
+ u16 maxpwr_ah; /* 5.8GHz Amplifier Max Power (in dBm Q5.2) */
u8 itssi_a; /* Idle TSSI Target for A-PHY */
u8 itssi_bg; /* Idle TSSI Target for B/G-PHY */
- u16 boardflags_lo; /* Boardflags (low 16 bits) */
- u16 boardflags_hi; /* Boardflags (high 16 bits) */
+ u8 tri2g; /* 2.4GHz TX isolation */
+ u8 tri5gl; /* 5.2GHz TX isolation */
+ u8 tri5g; /* 5.3GHz TX isolation */
+ u8 tri5gh; /* 5.8GHz TX isolation */
+ u8 rxpo2g; /* 2GHz RX power offset */
+ u8 rxpo5g; /* 5GHz RX power offset */
+ u8 rssisav2g; /* 2GHz RSSI params */
+ u8 rssismc2g;
+ u8 rssismf2g;
+ u8 bxa2g; /* 2GHz BX arch */
+ u8 rssisav5g; /* 5GHz RSSI params */
+ u8 rssismc5g;
+ u8 rssismf5g;
+ u8 bxa5g; /* 5GHz BX arch */
+ u16 cck2gpo; /* CCK power offset */
+ u32 ofdm2gpo; /* 2.4GHz OFDM power offset */
+ u32 ofdm5glpo; /* 5.2GHz OFDM power offset */
+ u32 ofdm5gpo; /* 5.3GHz OFDM power offset */
+ u32 ofdm5ghpo; /* 5.8GHz OFDM power offset */
+ u16 boardflags_lo; /* Board flags (bits 0-15) */
+ u16 boardflags_hi; /* Board flags (bits 16-31) */
+ u16 boardflags2_lo; /* Board flags (bits 32-47) */
+ u16 boardflags2_hi; /* Board flags (bits 48-63) */
+ /* TODO store board flags in a single u64 */
/* Antenna gain values for up to 4 antennas
* on each band. Values in dBm/4 (Q5.2). Negative gain means the
@@ -58,7 +88,7 @@ struct ssb_sprom {
} ghz5; /* 5GHz band */
} antenna_gain;
- /* TODO - add any parameters needed from rev 2, 3, or 4 SPROMs */
+ /* TODO - add any parameters needed from rev 2, 3, 4, 5 or 8 SPROMs */
};
/* Information about the PCB the circuitry is soldered on. */
diff --git a/include/linux/ssb/ssb_regs.h b/include/linux/ssb/ssb_regs.h
index a01b982b578..9ae9082eaeb 100644
--- a/include/linux/ssb/ssb_regs.h
+++ b/include/linux/ssb/ssb_regs.h
@@ -162,7 +162,7 @@
/* SPROM shadow area. If not otherwise noted, fields are
* two bytes wide. Note that the SPROM can _only_ be read
- * in two-byte quantinies.
+ * in two-byte quantities.
*/
#define SSB_SPROMSIZE_WORDS 64
#define SSB_SPROMSIZE_BYTES (SSB_SPROMSIZE_WORDS * sizeof(u16))
@@ -327,8 +327,11 @@
#define SSB_SPROM5_GPIOB_P3_SHIFT 8
/* SPROM Revision 8 */
-#define SSB_SPROM8_BFLLO 0x1084 /* Boardflags (low 16 bits) */
-#define SSB_SPROM8_BFLHI 0x1086 /* Boardflags Hi */
+#define SSB_SPROM8_BOARDREV 0x1082 /* Board revision */
+#define SSB_SPROM8_BFLLO 0x1084 /* Board flags (bits 0-15) */
+#define SSB_SPROM8_BFLHI 0x1086 /* Board flags (bits 16-31) */
+#define SSB_SPROM8_BFL2LO 0x1088 /* Board flags (bits 32-47) */
+#define SSB_SPROM8_BFL2HI 0x108A /* Board flags (bits 48-63) */
#define SSB_SPROM8_IL0MAC 0x108C /* 6 byte MAC address */
#define SSB_SPROM8_CCODE 0x1092 /* 2 byte country code */
#define SSB_SPROM8_ANTAVAIL 0x109C /* Antenna available bitfields*/
@@ -354,14 +357,63 @@
#define SSB_SPROM8_GPIOB_P2 0x00FF /* Pin 2 */
#define SSB_SPROM8_GPIOB_P3 0xFF00 /* Pin 3 */
#define SSB_SPROM8_GPIOB_P3_SHIFT 8
-#define SSB_SPROM8_MAXP_BG 0x10C0 /* Max Power BG in path 1 */
-#define SSB_SPROM8_MAXP_BG_MASK 0x00FF /* Mask for Max Power BG */
+#define SSB_SPROM8_RSSIPARM2G 0x10A4 /* RSSI params for 2GHz */
+#define SSB_SPROM8_RSSISMF2G 0x000F
+#define SSB_SPROM8_RSSISMC2G 0x00F0
+#define SSB_SPROM8_RSSISMC2G_SHIFT 4
+#define SSB_SPROM8_RSSISAV2G 0x0700
+#define SSB_SPROM8_RSSISAV2G_SHIFT 8
+#define SSB_SPROM8_BXA2G 0x1800
+#define SSB_SPROM8_BXA2G_SHIFT 11
+#define SSB_SPROM8_RSSIPARM5G 0x10A6 /* RSSI params for 5GHz */
+#define SSB_SPROM8_RSSISMF5G 0x000F
+#define SSB_SPROM8_RSSISMC5G 0x00F0
+#define SSB_SPROM8_RSSISMC5G_SHIFT 4
+#define SSB_SPROM8_RSSISAV5G 0x0700
+#define SSB_SPROM8_RSSISAV5G_SHIFT 8
+#define SSB_SPROM8_BXA5G 0x1800
+#define SSB_SPROM8_BXA5G_SHIFT 11
+#define SSB_SPROM8_TRI25G 0x10A8 /* TX isolation 2.4&5.3GHz */
+#define SSB_SPROM8_TRI2G 0x00FF /* TX isolation 2.4GHz */
+#define SSB_SPROM8_TRI5G 0xFF00 /* TX isolation 5.3GHz */
+#define SSB_SPROM8_TRI5G_SHIFT 8
+#define SSB_SPROM8_TRI5GHL 0x10AA /* TX isolation 5.2/5.8GHz */
+#define SSB_SPROM8_TRI5GL 0x00FF /* TX isolation 5.2GHz */
+#define SSB_SPROM8_TRI5GH 0xFF00 /* TX isolation 5.8GHz */
+#define SSB_SPROM8_TRI5GH_SHIFT 8
+#define SSB_SPROM8_RXPO 0x10AC /* RX power offsets */
+#define SSB_SPROM8_RXPO2G 0x00FF /* 2GHz RX power offset */
+#define SSB_SPROM8_RXPO5G 0xFF00 /* 5GHz RX power offset */
+#define SSB_SPROM8_RXPO5G_SHIFT 8
+#define SSB_SPROM8_MAXP_BG 0x10C0 /* Max Power 2GHz in path 1 */
+#define SSB_SPROM8_MAXP_BG_MASK 0x00FF /* Mask for Max Power 2GHz */
#define SSB_SPROM8_ITSSI_BG 0xFF00 /* Mask for path 1 itssi_bg */
#define SSB_SPROM8_ITSSI_BG_SHIFT 8
-#define SSB_SPROM8_MAXP_A 0x10C8 /* Max Power A in path 1 */
-#define SSB_SPROM8_MAXP_A_MASK 0x00FF /* Mask for Max Power A */
+#define SSB_SPROM8_PA0B0 0x10C2 /* 2GHz power amp settings */
+#define SSB_SPROM8_PA0B1 0x10C4
+#define SSB_SPROM8_PA0B2 0x10C6
+#define SSB_SPROM8_MAXP_A 0x10C8 /* Max Power 5.3GHz */
+#define SSB_SPROM8_MAXP_A_MASK 0x00FF /* Mask for Max Power 5.3GHz */
#define SSB_SPROM8_ITSSI_A 0xFF00 /* Mask for path 1 itssi_a */
#define SSB_SPROM8_ITSSI_A_SHIFT 8
+#define SSB_SPROM8_MAXP_AHL 0x10CA /* Max Power 5.2/5.8GHz */
+#define SSB_SPROM8_MAXP_AH_MASK 0x00FF /* Mask for Max Power 5.8GHz */
+#define SSB_SPROM8_MAXP_AL_MASK 0xFF00 /* Mask for Max Power 5.2GHz */
+#define SSB_SPROM8_MAXP_AL_SHIFT 8
+#define SSB_SPROM8_PA1B0 0x10CC /* 5.3GHz power amp settings */
+#define SSB_SPROM8_PA1B1 0x10CE
+#define SSB_SPROM8_PA1B2 0x10D0
+#define SSB_SPROM8_PA1LOB0 0x10D2 /* 5.2GHz power amp settings */
+#define SSB_SPROM8_PA1LOB1 0x10D4
+#define SSB_SPROM8_PA1LOB2 0x10D6
+#define SSB_SPROM8_PA1HIB0 0x10D8 /* 5.8GHz power amp settings */
+#define SSB_SPROM8_PA1HIB1 0x10DA
+#define SSB_SPROM8_PA1HIB2 0x10DC
+#define SSB_SPROM8_CCK2GPO 0x1140 /* CCK power offset */
+#define SSB_SPROM8_OFDM2GPO 0x1142 /* 2.4GHz OFDM power offset */
+#define SSB_SPROM8_OFDM5GPO 0x1146 /* 5.3GHz OFDM power offset */
+#define SSB_SPROM8_OFDM5GLPO 0x114A /* 5.2GHz OFDM power offset */
+#define SSB_SPROM8_OFDM5GHPO 0x114E /* 5.8GHz OFDM power offset */
/* Values for SSB_SPROM1_BINF_CCODE */
enum {
diff --git a/include/linux/tipc.h b/include/linux/tipc.h
index bea469455a0..3d92396639d 100644
--- a/include/linux/tipc.h
+++ b/include/linux/tipc.h
@@ -209,5 +209,7 @@ struct sockaddr_tipc {
#define TIPC_SRC_DROPPABLE 128 /* Default: 0 (resend congested msg) */
#define TIPC_DEST_DROPPABLE 129 /* Default: based on socket type */
#define TIPC_CONN_TIMEOUT 130 /* Default: 8000 (ms) */
+#define TIPC_NODE_RECVQ_DEPTH 131 /* Default: none (read only) */
+#define TIPC_SOCK_RECVQ_DEPTH 132 /* Default: none (read only) */
#endif
diff --git a/include/linux/usb/rndis_host.h b/include/linux/usb/rndis_host.h
index 37836b937d9..1ef1ebc2b04 100644
--- a/include/linux/usb/rndis_host.h
+++ b/include/linux/usb/rndis_host.h
@@ -70,12 +70,13 @@ struct rndis_msg_hdr {
#define RNDIS_MSG_KEEPALIVE_C (RNDIS_MSG_KEEPALIVE|RNDIS_MSG_COMPLETION)
/* codes for "status" field of completion messages */
-#define RNDIS_STATUS_SUCCESS cpu_to_le32(0x00000000)
-#define RNDIS_STATUS_FAILURE cpu_to_le32(0xc0000001)
-#define RNDIS_STATUS_INVALID_DATA cpu_to_le32(0xc0010015)
-#define RNDIS_STATUS_NOT_SUPPORTED cpu_to_le32(0xc00000bb)
-#define RNDIS_STATUS_MEDIA_CONNECT cpu_to_le32(0x4001000b)
-#define RNDIS_STATUS_MEDIA_DISCONNECT cpu_to_le32(0x4001000c)
+#define RNDIS_STATUS_SUCCESS cpu_to_le32(0x00000000)
+#define RNDIS_STATUS_FAILURE cpu_to_le32(0xc0000001)
+#define RNDIS_STATUS_INVALID_DATA cpu_to_le32(0xc0010015)
+#define RNDIS_STATUS_NOT_SUPPORTED cpu_to_le32(0xc00000bb)
+#define RNDIS_STATUS_MEDIA_CONNECT cpu_to_le32(0x4001000b)
+#define RNDIS_STATUS_MEDIA_DISCONNECT cpu_to_le32(0x4001000c)
+#define RNDIS_STATUS_MEDIA_SPECIFIC_INDICATION cpu_to_le32(0x40010012)
/* codes for OID_GEN_PHYSICAL_MEDIUM */
#define RNDIS_PHYSICAL_MEDIUM_UNSPECIFIED cpu_to_le32(0x00000000)
diff --git a/include/linux/usb/usbnet.h b/include/linux/usb/usbnet.h
index 310e18a880f..09514252d84 100644
--- a/include/linux/usb/usbnet.h
+++ b/include/linux/usb/usbnet.h
@@ -53,6 +53,7 @@ struct usbnet {
struct sk_buff_head rxq;
struct sk_buff_head txq;
struct sk_buff_head done;
+ struct sk_buff_head rxq_pause;
struct urb *interrupt;
struct tasklet_struct bh;
@@ -63,6 +64,7 @@ struct usbnet {
# define EVENT_RX_MEMORY 2
# define EVENT_STS_SPLIT 3
# define EVENT_LINK_RESET 4
+# define EVENT_RX_PAUSED 5
};
static inline struct usb_driver *driver_of(struct usb_interface *intf)
@@ -86,6 +88,7 @@ struct driver_info {
#define FLAG_FRAMING_AX 0x0040 /* AX88772/178 packets */
#define FLAG_WLAN 0x0080 /* use "wlan%d" names */
+#define FLAG_AVOID_UNLINK_URBS 0x0100 /* don't unlink urbs at usbnet_stop() */
/* init device ... can sleep, or cause probe() failure */
@@ -97,6 +100,9 @@ struct driver_info {
/* reset device ... can sleep */
int (*reset)(struct usbnet *);
+ /* stop device ... can sleep */
+ int (*stop)(struct usbnet *);
+
/* see if peer is connected ... can sleep */
int (*check_connect)(struct usbnet *);
@@ -118,9 +124,8 @@ struct driver_info {
* right after minidriver have initialized hardware. */
int (*early_init)(struct usbnet *dev);
- /* called by minidriver when link state changes, state: 0=disconnect,
- * 1=connect */
- void (*link_change)(struct usbnet *dev, int state);
+ /* called by minidriver when receiving indication */
+ void (*indication)(struct usbnet *dev, void *ind, int indlen);
/* for new devices, use the descriptor-reading code instead */
int in; /* rx endpoint */
@@ -187,6 +192,10 @@ extern void usbnet_defer_kevent (struct usbnet *, int);
extern void usbnet_skb_return (struct usbnet *, struct sk_buff *);
extern void usbnet_unlink_rx_urbs(struct usbnet *);
+extern void usbnet_pause_rx(struct usbnet *);
+extern void usbnet_resume_rx(struct usbnet *);
+extern void usbnet_purge_paused_rxq(struct usbnet *);
+
extern int usbnet_get_settings (struct net_device *net, struct ethtool_cmd *cmd);
extern int usbnet_set_settings (struct net_device *net, struct ethtool_cmd *cmd);
extern u32 usbnet_get_link (struct net_device *net);
diff --git a/include/linux/wireless.h b/include/linux/wireless.h
index cb24204851f..5b4c6c772a9 100644
--- a/include/linux/wireless.h
+++ b/include/linux/wireless.h
@@ -1132,6 +1132,14 @@ struct __compat_iw_event {
};
#define IW_EV_COMPAT_LCP_LEN offsetof(struct __compat_iw_event, pointer)
#define IW_EV_COMPAT_POINT_OFF offsetof(struct compat_iw_point, length)
+
+/* Size of the various events for compat */
+#define IW_EV_COMPAT_CHAR_LEN (IW_EV_COMPAT_LCP_LEN + IFNAMSIZ)
+#define IW_EV_COMPAT_UINT_LEN (IW_EV_COMPAT_LCP_LEN + sizeof(__u32))
+#define IW_EV_COMPAT_FREQ_LEN (IW_EV_COMPAT_LCP_LEN + sizeof(struct iw_freq))
+#define IW_EV_COMPAT_PARAM_LEN (IW_EV_COMPAT_LCP_LEN + sizeof(struct iw_param))
+#define IW_EV_COMPAT_ADDR_LEN (IW_EV_COMPAT_LCP_LEN + sizeof(struct sockaddr))
+#define IW_EV_COMPAT_QUAL_LEN (IW_EV_COMPAT_LCP_LEN + sizeof(struct iw_quality))
#define IW_EV_COMPAT_POINT_LEN \
(IW_EV_COMPAT_LCP_LEN + sizeof(struct compat_iw_point) - \
IW_EV_COMPAT_POINT_OFF)
diff --git a/include/net/ieee802154/af_ieee802154.h b/include/net/af_ieee802154.h
index 0d78605fb1a..75e64c7a296 100644
--- a/include/net/ieee802154/af_ieee802154.h
+++ b/include/net/af_ieee802154.h
@@ -54,7 +54,9 @@ struct sockaddr_ieee802154 {
struct ieee802154_addr addr;
};
-/* master device */
-#define IEEE802154_SIOC_ADD_SLAVE (SIOCDEVPRIVATE + 0)
+/* get/setsockopt */
+#define SOL_IEEE802154 0
+
+#define WPAN_WANTACK 0
#endif
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index d1892d66701..0b146bb2dd1 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -80,7 +80,6 @@ enum ieee80211_channel_flags {
* with cfg80211.
*
* @center_freq: center frequency in MHz
- * @max_bandwidth: maximum allowed bandwidth for this channel, in MHz
* @hw_value: hardware-specific value for the channel
* @flags: channel flags from &enum ieee80211_channel_flags.
* @orig_flags: channel flags at registration time, used by regulatory
@@ -97,7 +96,6 @@ enum ieee80211_channel_flags {
struct ieee80211_channel {
enum ieee80211_band band;
u16 center_freq;
- u8 max_bandwidth;
u16 hw_value;
u32 flags;
int max_antenna_gain;
@@ -372,6 +370,10 @@ struct rate_info {
* @txrate: current unicast bitrate to this station
* @rx_packets: packets received from this station
* @tx_packets: packets transmitted to this station
+ * @generation: generation number for nl80211 dumps.
+ * This number should increase every time the list of stations
+ * changes, i.e. when a station is added or removed, so that
+ * userspace can tell whether it got a consistent snapshot.
*/
struct station_info {
u32 filled;
@@ -385,6 +387,8 @@ struct station_info {
struct rate_info txrate;
u32 rx_packets;
u32 tx_packets;
+
+ int generation;
};
/**
@@ -444,6 +448,10 @@ enum mpath_info_flags {
* @flags: mesh path flags
* @discovery_timeout: total mesh path discovery timeout, in msecs
* @discovery_retries: mesh path discovery retries
+ * @generation: generation number for nl80211 dumps.
+ * This number should increase every time the list of mesh paths
+ * changes, i.e. when a station is added or removed, so that
+ * userspace can tell whether it got a consistent snapshot.
*/
struct mpath_info {
u32 filled;
@@ -454,6 +462,8 @@ struct mpath_info {
u32 discovery_timeout;
u8 discovery_retries;
u8 flags;
+
+ int generation;
};
/**
@@ -538,23 +548,26 @@ struct cfg80211_ssid {
* @ssids: SSIDs to scan for (active scan only)
* @n_ssids: number of SSIDs
* @channels: channels to scan on.
- * @n_channels: number of channels for each band
+ * @n_channels: total number of channels to scan
* @ie: optional information element(s) to add into Probe Request or %NULL
* @ie_len: length of ie in octets
* @wiphy: the wiphy this was for
- * @ifidx: the interface index
+ * @dev: the interface
*/
struct cfg80211_scan_request {
struct cfg80211_ssid *ssids;
int n_ssids;
- struct ieee80211_channel **channels;
u32 n_channels;
const u8 *ie;
size_t ie_len;
/* internal */
struct wiphy *wiphy;
- int ifidx;
+ struct net_device *dev;
+ bool aborted;
+
+ /* keep last */
+ struct ieee80211_channel *channels[0];
};
/**
@@ -584,7 +597,6 @@ enum cfg80211_signal_type {
* is no guarantee that these are well-formed!)
* @len_information_elements: total length of the information elements
* @signal: signal strength value (type depends on the wiphy's signal_type)
- * @hold: BSS should not expire
* @free_priv: function pointer to free private data
* @priv: private area for driver use, has at least wiphy->bss_priv_size bytes
*/
@@ -605,37 +617,59 @@ struct cfg80211_bss {
};
/**
+ * ieee80211_bss_get_ie - find IE with given ID
+ * @bss: the bss to search
+ * @ie: the IE ID
+ * Returns %NULL if not found.
+ */
+const u8 *ieee80211_bss_get_ie(struct cfg80211_bss *bss, u8 ie);
+
+
+/**
+ * struct cfg80211_crypto_settings - Crypto settings
+ * @wpa_versions: indicates which, if any, WPA versions are enabled
+ * (from enum nl80211_wpa_versions)
+ * @cipher_group: group key cipher suite (or 0 if unset)
+ * @n_ciphers_pairwise: number of AP supported unicast ciphers
+ * @ciphers_pairwise: unicast key cipher suites
+ * @n_akm_suites: number of AKM suites
+ * @akm_suites: AKM suites
+ * @control_port: Whether user space controls IEEE 802.1X port, i.e.,
+ * sets/clears %NL80211_STA_FLAG_AUTHORIZED. If true, the driver is
+ * required to assume that the port is unauthorized until authorized by
+ * user space. Otherwise, port is marked authorized by default.
+ */
+struct cfg80211_crypto_settings {
+ u32 wpa_versions;
+ u32 cipher_group;
+ int n_ciphers_pairwise;
+ u32 ciphers_pairwise[NL80211_MAX_NR_CIPHER_SUITES];
+ int n_akm_suites;
+ u32 akm_suites[NL80211_MAX_NR_AKM_SUITES];
+ bool control_port;
+};
+
+/**
* struct cfg80211_auth_request - Authentication request data
*
* This structure provides information needed to complete IEEE 802.11
* authentication.
- * NOTE: This structure will likely change when more code from mac80211 is
- * moved into cfg80211 so that non-mac80211 drivers can benefit from it, too.
- * Before using this in a driver that does not use mac80211, it would be better
- * to check the status of that work and better yet, volunteer to work on it.
- *
- * @chan: The channel to use or %NULL if not specified (auto-select based on
- * scan results)
- * @peer_addr: The address of the peer STA (AP BSSID in infrastructure case);
- * this field is required to be present; if the driver wants to help with
- * BSS selection, it should use (yet to be added) MLME event to allow user
- * space SME to be notified of roaming candidate, so that the SME can then
- * use the authentication request with the recommended BSSID and whatever
- * other data may be needed for authentication/association
- * @ssid: SSID or %NULL if not yet available
- * @ssid_len: Length of ssid in octets
+ *
+ * @bss: The BSS to authenticate with.
* @auth_type: Authentication type (algorithm)
* @ie: Extra IEs to add to Authentication frame or %NULL
* @ie_len: Length of ie buffer in octets
+ * @key_len: length of WEP key for shared key authentication
+ * @key_idx: index of WEP key for shared key authentication
+ * @key: WEP key for shared key authentication
*/
struct cfg80211_auth_request {
- struct ieee80211_channel *chan;
- u8 *peer_addr;
- const u8 *ssid;
- size_t ssid_len;
- enum nl80211_auth_type auth_type;
+ struct cfg80211_bss *bss;
const u8 *ie;
size_t ie_len;
+ enum nl80211_auth_type auth_type;
+ const u8 *key;
+ u8 key_len, key_idx;
};
/**
@@ -643,35 +677,19 @@ struct cfg80211_auth_request {
*
* This structure provides information needed to complete IEEE 802.11
* (re)association.
- * NOTE: This structure will likely change when more code from mac80211 is
- * moved into cfg80211 so that non-mac80211 drivers can benefit from it, too.
- * Before using this in a driver that does not use mac80211, it would be better
- * to check the status of that work and better yet, volunteer to work on it.
- *
- * @chan: The channel to use or %NULL if not specified (auto-select based on
- * scan results)
- * @peer_addr: The address of the peer STA (AP BSSID); this field is required
- * to be present and the STA must be in State 2 (authenticated) with the
- * peer STA
- * @ssid: SSID
- * @ssid_len: Length of ssid in octets
+ * @bss: The BSS to associate with.
* @ie: Extra IEs to add to (Re)Association Request frame or %NULL
* @ie_len: Length of ie buffer in octets
* @use_mfp: Use management frame protection (IEEE 802.11w) in this association
- * @control_port: Whether user space controls IEEE 802.1X port, i.e.,
- * sets/clears %NL80211_STA_FLAG_AUTHORIZED. If true, the driver is
- * required to assume that the port is unauthorized until authorized by
- * user space. Otherwise, port is marked authorized by default.
+ * @crypto: crypto settings
+ * @prev_bssid: previous BSSID, if not %NULL use reassociate frame
*/
struct cfg80211_assoc_request {
- struct ieee80211_channel *chan;
- u8 *peer_addr;
- const u8 *ssid;
- size_t ssid_len;
- const u8 *ie;
+ struct cfg80211_bss *bss;
+ const u8 *ie, *prev_bssid;
size_t ie_len;
+ struct cfg80211_crypto_settings crypto;
bool use_mfp;
- bool control_port;
};
/**
@@ -680,16 +698,16 @@ struct cfg80211_assoc_request {
* This structure provides information needed to complete IEEE 802.11
* deauthentication.
*
- * @peer_addr: The address of the peer STA (AP BSSID); this field is required
- * to be present and the STA must be authenticated with the peer STA
+ * @bss: the BSS to deauthenticate from
* @ie: Extra IEs to add to Deauthentication frame or %NULL
* @ie_len: Length of ie buffer in octets
+ * @reason_code: The reason code for the deauthentication
*/
struct cfg80211_deauth_request {
- u8 *peer_addr;
- u16 reason_code;
+ struct cfg80211_bss *bss;
const u8 *ie;
size_t ie_len;
+ u16 reason_code;
};
/**
@@ -698,16 +716,16 @@ struct cfg80211_deauth_request {
* This structure provides information needed to complete IEEE 802.11
* disassocation.
*
- * @peer_addr: The address of the peer STA (AP BSSID); this field is required
- * to be present and the STA must be associated with the peer STA
+ * @bss: the BSS to disassociate from
* @ie: Extra IEs to add to Disassociation frame or %NULL
* @ie_len: Length of ie buffer in octets
+ * @reason_code: The reason code for the disassociation
*/
struct cfg80211_disassoc_request {
- u8 *peer_addr;
- u16 reason_code;
+ struct cfg80211_bss *bss;
const u8 *ie;
size_t ie_len;
+ u16 reason_code;
};
/**
@@ -726,6 +744,8 @@ struct cfg80211_disassoc_request {
* @ie: information element(s) to include in the beacon
* @ie_len: length of that
* @beacon_interval: beacon interval to use
+ * @privacy: this is a protected network, keys will be configured
+ * after joining
*/
struct cfg80211_ibss_params {
u8 *ssid;
@@ -735,6 +755,42 @@ struct cfg80211_ibss_params {
u8 ssid_len, ie_len;
u16 beacon_interval;
bool channel_fixed;
+ bool privacy;
+};
+
+/**
+ * struct cfg80211_connect_params - Connection parameters
+ *
+ * This structure provides information needed to complete IEEE 802.11
+ * authentication and association.
+ *
+ * @channel: The channel to use or %NULL if not specified (auto-select based
+ * on scan results)
+ * @bssid: The AP BSSID or %NULL if not specified (auto-select based on scan
+ * results)
+ * @ssid: SSID
+ * @ssid_len: Length of ssid in octets
+ * @auth_type: Authentication type (algorithm)
+ * @assoc_ie: IEs for association request
+ * @assoc_ie_len: Length of assoc_ie in octets
+ * @privacy: indicates whether privacy-enabled APs should be used
+ * @crypto: crypto settings
+ * @key_len: length of WEP key for shared key authentication
+ * @key_idx: index of WEP key for shared key authentication
+ * @key: WEP key for shared key authentication
+ */
+struct cfg80211_connect_params {
+ struct ieee80211_channel *channel;
+ u8 *bssid;
+ u8 *ssid;
+ size_t ssid_len;
+ enum nl80211_auth_type auth_type;
+ u8 *ie;
+ size_t ie_len;
+ bool privacy;
+ struct cfg80211_crypto_settings crypto;
+ const u8 *key;
+ u8 key_len, key_idx;
};
/**
@@ -764,6 +820,26 @@ enum tx_power_setting {
TX_POWER_FIXED,
};
+/*
+ * cfg80211_bitrate_mask - masks for bitrate control
+ */
+struct cfg80211_bitrate_mask {
+/*
+ * As discussed in Berlin, this struct really
+ * should look like this:
+
+ struct {
+ u32 legacy;
+ u8 mcs[IEEE80211_HT_MCS_MASK_LEN];
+ } control[IEEE80211_NUM_BANDS];
+
+ * Since we can always fix in-kernel users, let's keep
+ * it simpler for now:
+ */
+ u32 fixed; /* fixed bitrate, 0 == not fixed */
+ u32 maxrate; /* in kbps, 0 == no limit */
+};
+
/**
* struct cfg80211_ops - backend description for wireless configuration
*
@@ -781,7 +857,8 @@ enum tx_power_setting {
* @resume: wiphy device needs to be resumed
*
* @add_virtual_intf: create a new virtual interface with the given name,
- * must set the struct wireless_dev's iftype.
+ * must set the struct wireless_dev's iftype. Beware: You must create
+ * the new netdev in the wiphy's network namespace!
*
* @del_virtual_intf: remove the virtual interface determined by ifindex.
*
@@ -841,6 +918,12 @@ enum tx_power_setting {
* @deauth: Request to deauthenticate from the specified peer
* @disassoc: Request to disassociate from the specified peer
*
+ * @connect: Connect to the ESS with the specified parameters. When connected,
+ * call cfg80211_connect_result() with status code %WLAN_STATUS_SUCCESS.
+ * If the connection fails for some reason, call cfg80211_connect_result()
+ * with the status from the AP.
+ * @disconnect: Disconnect from the BSS/ESS.
+ *
* @join_ibss: Join the specified IBSS (or create if necessary). Once done, call
* cfg80211_ibss_joined(), also call that function when changing BSSID due
* to a merge.
@@ -857,6 +940,8 @@ enum tx_power_setting {
*
* @rfkill_poll: polls the hw rfkill line, use cfg80211 reporting
* functions to adjust rfkill hw state
+ *
+ * @testmode_cmd: run a test mode command
*/
struct cfg80211_ops {
int (*suspend)(struct wiphy *wiphy);
@@ -865,8 +950,9 @@ struct cfg80211_ops {
int (*add_virtual_intf)(struct wiphy *wiphy, char *name,
enum nl80211_iftype type, u32 *flags,
struct vif_params *params);
- int (*del_virtual_intf)(struct wiphy *wiphy, int ifindex);
- int (*change_virtual_intf)(struct wiphy *wiphy, int ifindex,
+ int (*del_virtual_intf)(struct wiphy *wiphy, struct net_device *dev);
+ int (*change_virtual_intf)(struct wiphy *wiphy,
+ struct net_device *dev,
enum nl80211_iftype type, u32 *flags,
struct vif_params *params);
@@ -939,9 +1025,16 @@ struct cfg80211_ops {
int (*assoc)(struct wiphy *wiphy, struct net_device *dev,
struct cfg80211_assoc_request *req);
int (*deauth)(struct wiphy *wiphy, struct net_device *dev,
- struct cfg80211_deauth_request *req);
+ struct cfg80211_deauth_request *req,
+ void *cookie);
int (*disassoc)(struct wiphy *wiphy, struct net_device *dev,
- struct cfg80211_disassoc_request *req);
+ struct cfg80211_disassoc_request *req,
+ void *cookie);
+
+ int (*connect)(struct wiphy *wiphy, struct net_device *dev,
+ struct cfg80211_connect_params *sme);
+ int (*disconnect)(struct wiphy *wiphy, struct net_device *dev,
+ u16 reason_code);
int (*join_ibss)(struct wiphy *wiphy, struct net_device *dev,
struct cfg80211_ibss_params *params);
@@ -953,7 +1046,23 @@ struct cfg80211_ops {
enum tx_power_setting type, int dbm);
int (*get_tx_power)(struct wiphy *wiphy, int *dbm);
+ int (*set_wds_peer)(struct wiphy *wiphy, struct net_device *dev,
+ u8 *addr);
+
void (*rfkill_poll)(struct wiphy *wiphy);
+
+#ifdef CONFIG_NL80211_TESTMODE
+ int (*testmode_cmd)(struct wiphy *wiphy, void *data, int len);
+#endif
+
+ int (*set_bitrate_mask)(struct wiphy *wiphy,
+ struct net_device *dev,
+ const u8 *peer,
+ const struct cfg80211_bitrate_mask *mask);
+
+ /* some temporary stuff to finish wext */
+ int (*set_power_mgmt)(struct wiphy *wiphy, struct net_device *dev,
+ bool enabled, int timeout);
};
/*
@@ -996,6 +1105,12 @@ struct cfg80211_ops {
* @frag_threshold: Fragmentation threshold (dot11FragmentationThreshold);
* -1 = fragmentation disabled, only odd values >= 256 used
* @rts_threshold: RTS threshold (dot11RTSThreshold); -1 = RTS/CTS disabled
+ * @net: the network namespace this wiphy currently lives in
+ * @netnsok: if set to false, do not allow changing the netns of this
+ * wiphy at all
+ * @ps_default: default for powersave, will be set depending on the
+ * kernel's default on wiphy_new(), but can be changed by the
+ * driver if it has a good reason to override the default
*/
struct wiphy {
/* assign these fields before you register the wiphy */
@@ -1010,6 +1125,9 @@ struct wiphy {
bool strict_regulatory;
bool disable_beacon_hints;
+ bool netnsok;
+ bool ps_default;
+
enum cfg80211_signal_type signal_type;
int bss_priv_size;
@@ -1048,9 +1166,35 @@ struct wiphy {
/* dir in debugfs: ieee80211/<wiphyname> */
struct dentry *debugfsdir;
+#ifdef CONFIG_NET_NS
+ /* the network namespace this phy lives in currently */
+ struct net *_net;
+#endif
+
char priv[0] __attribute__((__aligned__(NETDEV_ALIGN)));
};
+#ifdef CONFIG_NET_NS
+static inline struct net *wiphy_net(struct wiphy *wiphy)
+{
+ return wiphy->_net;
+}
+
+static inline void wiphy_net_set(struct wiphy *wiphy, struct net *net)
+{
+ wiphy->_net = net;
+}
+#else
+static inline struct net *wiphy_net(struct wiphy *wiphy)
+{
+ return &init_net;
+}
+
+static inline void wiphy_net_set(struct wiphy *wiphy, struct net *net)
+{
+}
+#endif
+
/**
* wiphy_priv - return priv from wiphy
*
@@ -1063,6 +1207,17 @@ static inline void *wiphy_priv(struct wiphy *wiphy)
}
/**
+ * priv_to_wiphy - return the wiphy containing the priv
+ *
+ * @priv: a pointer previously returned by wiphy_priv
+ */
+static inline struct wiphy *priv_to_wiphy(void *priv)
+{
+ BUG_ON(!priv);
+ return container_of(priv, struct wiphy, priv);
+}
+
+/**
* set_wiphy_dev - set device pointer for wiphy
*
* @wiphy: The wiphy whose device to bind
@@ -1134,6 +1289,13 @@ extern void wiphy_unregister(struct wiphy *wiphy);
*/
extern void wiphy_free(struct wiphy *wiphy);
+/* internal structs */
+struct cfg80211_conn;
+struct cfg80211_internal_bss;
+struct cfg80211_cached_keys;
+
+#define MAX_AUTH_BSSES 4
+
/**
* struct wireless_dev - wireless per-netdev state
*
@@ -1157,22 +1319,43 @@ struct wireless_dev {
struct wiphy *wiphy;
enum nl80211_iftype iftype;
- /* private to the generic wireless code */
+ /* the remainder of this struct should be private to cfg80211 */
struct list_head list;
struct net_device *netdev;
- /* currently used for IBSS - might be rearranged in the future */
- struct cfg80211_bss *current_bss;
- u8 bssid[ETH_ALEN];
+ struct mutex mtx;
+
+ /* currently used for IBSS and SME - might be rearranged later */
u8 ssid[IEEE80211_MAX_SSID_LEN];
u8 ssid_len;
+ enum {
+ CFG80211_SME_IDLE,
+ CFG80211_SME_CONNECTING,
+ CFG80211_SME_CONNECTED,
+ } sme_state;
+ struct cfg80211_conn *conn;
+ struct cfg80211_cached_keys *connect_keys;
+
+ struct list_head event_list;
+ spinlock_t event_lock;
+
+ struct cfg80211_internal_bss *authtry_bsses[MAX_AUTH_BSSES];
+ struct cfg80211_internal_bss *auth_bsses[MAX_AUTH_BSSES];
+ struct cfg80211_internal_bss *current_bss; /* associated / joined */
#ifdef CONFIG_WIRELESS_EXT
/* wext data */
struct {
struct cfg80211_ibss_params ibss;
- u8 bssid[ETH_ALEN];
+ struct cfg80211_connect_params connect;
+ struct cfg80211_cached_keys *keys;
+ u8 *ie;
+ size_t ie_len;
+ u8 bssid[ETH_ALEN], prev_bssid[ETH_ALEN];
+ u8 ssid[IEEE80211_MAX_SSID_LEN];
s8 default_key, default_mgmt_key;
+ bool ps, prev_bssid_valid;
+ int ps_timeout;
} wext;
#endif
};
@@ -1352,20 +1535,6 @@ unsigned int cfg80211_classify8021d(struct sk_buff *skb);
extern int regulatory_hint(struct wiphy *wiphy, const char *alpha2);
/**
- * regulatory_hint_11d - hints a country IE as a regulatory domain
- * @wiphy: the wireless device giving the hint (used only for reporting
- * conflicts)
- * @country_ie: pointer to the country IE
- * @country_ie_len: length of the country IE
- *
- * We will intersect the rd with the what CRDA tells us should apply
- * for the alpha2 this country IE belongs to, this prevents APs from
- * sending us incorrect or outdated information against a country.
- */
-extern void regulatory_hint_11d(struct wiphy *wiphy,
- u8 *country_ie,
- u8 country_ie_len);
-/**
* wiphy_apply_custom_regulatory - apply a custom driver regulatory domain
* @wiphy: the wireless device we want to process the regulatory domain on
* @regd: the custom regulatory domain to use for this wiphy
@@ -1433,27 +1602,34 @@ int cfg80211_wext_siwmlme(struct net_device *dev,
int cfg80211_wext_giwrange(struct net_device *dev,
struct iw_request_info *info,
struct iw_point *data, char *extra);
-int cfg80211_ibss_wext_siwfreq(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_freq *freq, char *extra);
-int cfg80211_ibss_wext_giwfreq(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_freq *freq, char *extra);
-int cfg80211_ibss_wext_siwessid(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_point *data, char *ssid);
-int cfg80211_ibss_wext_giwessid(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_point *data, char *ssid);
-int cfg80211_ibss_wext_siwap(struct net_device *dev,
- struct iw_request_info *info,
- struct sockaddr *ap_addr, char *extra);
-int cfg80211_ibss_wext_giwap(struct net_device *dev,
- struct iw_request_info *info,
- struct sockaddr *ap_addr, char *extra);
+int cfg80211_wext_siwgenie(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *data, char *extra);
+int cfg80211_wext_siwauth(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *data, char *extra);
+int cfg80211_wext_giwauth(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *data, char *extra);
-struct ieee80211_channel *cfg80211_wext_freq(struct wiphy *wiphy,
- struct iw_freq *freq);
+int cfg80211_wext_siwfreq(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_freq *freq, char *extra);
+int cfg80211_wext_giwfreq(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_freq *freq, char *extra);
+int cfg80211_wext_siwessid(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *data, char *ssid);
+int cfg80211_wext_giwessid(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *data, char *ssid);
+int cfg80211_wext_siwrate(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *rate, char *extra);
+int cfg80211_wext_giwrate(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *rate, char *extra);
int cfg80211_wext_siwrts(struct net_device *dev,
struct iw_request_info *info,
@@ -1488,6 +1664,21 @@ int cfg80211_wext_siwtxpower(struct net_device *dev,
int cfg80211_wext_giwtxpower(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *data, char *keybuf);
+struct iw_statistics *cfg80211_wireless_stats(struct net_device *dev);
+
+int cfg80211_wext_siwpower(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *wrq, char *extra);
+int cfg80211_wext_giwpower(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *wrq, char *extra);
+
+int cfg80211_wext_siwap(struct net_device *dev,
+ struct iw_request_info *info,
+ struct sockaddr *ap_addr, char *extra);
+int cfg80211_wext_giwap(struct net_device *dev,
+ struct iw_request_info *info,
+ struct sockaddr *ap_addr, char *extra);
/*
* callbacks for asynchronous cfg80211 methods, notification
@@ -1569,7 +1760,7 @@ void cfg80211_unlink_bss(struct wiphy *wiphy, struct cfg80211_bss *bss);
* This function is called whenever an authentication has been processed in
* station mode. The driver is required to call either this function or
* cfg80211_send_auth_timeout() to indicate the result of cfg80211_ops::auth()
- * call.
+ * call. This function may sleep.
*/
void cfg80211_send_rx_auth(struct net_device *dev, const u8 *buf, size_t len);
@@ -1577,6 +1768,8 @@ void cfg80211_send_rx_auth(struct net_device *dev, const u8 *buf, size_t len);
* cfg80211_send_auth_timeout - notification of timed out authentication
* @dev: network device
* @addr: The MAC address of the device with which the authentication timed out
+ *
+ * This function may sleep.
*/
void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr);
@@ -1589,7 +1782,7 @@ void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr);
* This function is called whenever a (re)association response has been
* processed in station mode. The driver is required to call either this
* function or cfg80211_send_assoc_timeout() to indicate the result of
- * cfg80211_ops::assoc() call.
+ * cfg80211_ops::assoc() call. This function may sleep.
*/
void cfg80211_send_rx_assoc(struct net_device *dev, const u8 *buf, size_t len);
@@ -1597,6 +1790,8 @@ void cfg80211_send_rx_assoc(struct net_device *dev, const u8 *buf, size_t len);
* cfg80211_send_assoc_timeout - notification of timed out association
* @dev: network device
* @addr: The MAC address of the device with which the association timed out
+ *
+ * This function may sleep.
*/
void cfg80211_send_assoc_timeout(struct net_device *dev, const u8 *addr);
@@ -1605,41 +1800,30 @@ void cfg80211_send_assoc_timeout(struct net_device *dev, const u8 *addr);
* @dev: network device
* @buf: deauthentication frame (header + body)
* @len: length of the frame data
+ * @cookie: cookie from ->deauth if called within that callback,
+ * %NULL otherwise
*
* This function is called whenever deauthentication has been processed in
* station mode. This includes both received deauthentication frames and
- * locally generated ones.
+ * locally generated ones. This function may sleep.
*/
-void cfg80211_send_deauth(struct net_device *dev, const u8 *buf, size_t len);
+void cfg80211_send_deauth(struct net_device *dev, const u8 *buf, size_t len,
+ void *cookie);
/**
* cfg80211_send_disassoc - notification of processed disassociation
* @dev: network device
* @buf: disassociation response frame (header + body)
* @len: length of the frame data
+ * @cookie: cookie from ->disassoc if called within that callback,
+ * %NULL otherwise
*
* This function is called whenever disassociation has been processed in
* station mode. This includes both received disassociation frames and locally
- * generated ones.
- */
-void cfg80211_send_disassoc(struct net_device *dev, const u8 *buf, size_t len);
-
-/**
- * cfg80211_hold_bss - exclude bss from expiration
- * @bss: bss which should not expire
- *
- * In a case when the BSS is not updated but it shouldn't expire this
- * function can be used to mark the BSS to be excluded from expiration.
- */
-void cfg80211_hold_bss(struct cfg80211_bss *bss);
-
-/**
- * cfg80211_unhold_bss - remove expiration exception from the BSS
- * @bss: bss which can expire again
- *
- * This function marks the BSS to be expirable again.
+ * generated ones. This function may sleep.
*/
-void cfg80211_unhold_bss(struct cfg80211_bss *bss);
+void cfg80211_send_disassoc(struct net_device *dev, const u8 *buf, size_t len,
+ void *cookie);
/**
* cfg80211_michael_mic_failure - notification of Michael MIC failure (TKIP)
@@ -1648,6 +1832,7 @@ void cfg80211_unhold_bss(struct cfg80211_bss *bss);
* @key_type: The key type that the received frame used
* @key_id: Key identifier (0..3)
* @tsc: The TSC value of the frame that generated the MIC failure (6 octets)
+ * @gfp: allocation flags
*
* This function is called whenever the local MAC detects a MIC failure in a
* received frame. This matches with MLME-MICHAELMICFAILURE.indication()
@@ -1655,7 +1840,7 @@ void cfg80211_unhold_bss(struct cfg80211_bss *bss);
*/
void cfg80211_michael_mic_failure(struct net_device *dev, const u8 *addr,
enum nl80211_key_type key_type, int key_id,
- const u8 *tsc);
+ const u8 *tsc, gfp_t gfp);
/**
* cfg80211_ibss_joined - notify cfg80211 that device joined an IBSS
@@ -1692,4 +1877,137 @@ void wiphy_rfkill_start_polling(struct wiphy *wiphy);
*/
void wiphy_rfkill_stop_polling(struct wiphy *wiphy);
+#ifdef CONFIG_NL80211_TESTMODE
+/**
+ * cfg80211_testmode_alloc_reply_skb - allocate testmode reply
+ * @wiphy: the wiphy
+ * @approxlen: an upper bound of the length of the data that will
+ * be put into the skb
+ *
+ * This function allocates and pre-fills an skb for a reply to
+ * the testmode command. Since it is intended for a reply, calling
+ * it outside of the @testmode_cmd operation is invalid.
+ *
+ * The returned skb (or %NULL if any errors happen) is pre-filled
+ * with the wiphy index and set up in a way that any data that is
+ * put into the skb (with skb_put(), nla_put() or similar) will end
+ * up being within the %NL80211_ATTR_TESTDATA attribute, so all that
+ * needs to be done with the skb is adding data for the corresponding
+ * userspace tool which can then read that data out of the testdata
+ * attribute. You must not modify the skb in any other way.
+ *
+ * When done, call cfg80211_testmode_reply() with the skb and return
+ * its error code as the result of the @testmode_cmd operation.
+ */
+struct sk_buff *cfg80211_testmode_alloc_reply_skb(struct wiphy *wiphy,
+ int approxlen);
+
+/**
+ * cfg80211_testmode_reply - send the reply skb
+ * @skb: The skb, must have been allocated with
+ * cfg80211_testmode_alloc_reply_skb()
+ *
+ * Returns an error code or 0 on success, since calling this
+ * function will usually be the last thing before returning
+ * from the @testmode_cmd you should return the error code.
+ * Note that this function consumes the skb regardless of the
+ * return value.
+ */
+int cfg80211_testmode_reply(struct sk_buff *skb);
+
+/**
+ * cfg80211_testmode_alloc_event_skb - allocate testmode event
+ * @wiphy: the wiphy
+ * @approxlen: an upper bound of the length of the data that will
+ * be put into the skb
+ * @gfp: allocation flags
+ *
+ * This function allocates and pre-fills an skb for an event on the
+ * testmode multicast group.
+ *
+ * The returned skb (or %NULL if any errors happen) is set up in the
+ * same way as with cfg80211_testmode_alloc_reply_skb() but prepared
+ * for an event. As there, you should simply add data to it that will
+ * then end up in the %NL80211_ATTR_TESTDATA attribute. Again, you must
+ * not modify the skb in any other way.
+ *
+ * When done filling the skb, call cfg80211_testmode_event() with the
+ * skb to send the event.
+ */
+struct sk_buff *cfg80211_testmode_alloc_event_skb(struct wiphy *wiphy,
+ int approxlen, gfp_t gfp);
+
+/**
+ * cfg80211_testmode_event - send the event
+ * @skb: The skb, must have been allocated with
+ * cfg80211_testmode_alloc_event_skb()
+ * @gfp: allocation flags
+ *
+ * This function sends the given @skb, which must have been allocated
+ * by cfg80211_testmode_alloc_event_skb(), as an event. It always
+ * consumes it.
+ */
+void cfg80211_testmode_event(struct sk_buff *skb, gfp_t gfp);
+
+#define CFG80211_TESTMODE_CMD(cmd) .testmode_cmd = (cmd),
+#else
+#define CFG80211_TESTMODE_CMD(cmd)
+#endif
+
+/**
+ * cfg80211_connect_result - notify cfg80211 of connection result
+ *
+ * @dev: network device
+ * @bssid: the BSSID of the AP
+ * @req_ie: association request IEs (maybe be %NULL)
+ * @req_ie_len: association request IEs length
+ * @resp_ie: association response IEs (may be %NULL)
+ * @resp_ie_len: assoc response IEs length
+ * @status: status code, 0 for successful connection, use
+ * %WLAN_STATUS_UNSPECIFIED_FAILURE if your device cannot give you
+ * the real status code for failures.
+ * @gfp: allocation flags
+ *
+ * It should be called by the underlying driver whenever connect() has
+ * succeeded.
+ */
+void cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
+ const u8 *req_ie, size_t req_ie_len,
+ const u8 *resp_ie, size_t resp_ie_len,
+ u16 status, gfp_t gfp);
+
+/**
+ * cfg80211_roamed - notify cfg80211 of roaming
+ *
+ * @dev: network device
+ * @bssid: the BSSID of the new AP
+ * @req_ie: association request IEs (maybe be %NULL)
+ * @req_ie_len: association request IEs length
+ * @resp_ie: association response IEs (may be %NULL)
+ * @resp_ie_len: assoc response IEs length
+ * @gfp: allocation flags
+ *
+ * It should be called by the underlying driver whenever it roamed
+ * from one AP to another while connected.
+ */
+void cfg80211_roamed(struct net_device *dev, const u8 *bssid,
+ const u8 *req_ie, size_t req_ie_len,
+ const u8 *resp_ie, size_t resp_ie_len, gfp_t gfp);
+
+/**
+ * cfg80211_disconnected - notify cfg80211 that connection was dropped
+ *
+ * @dev: network device
+ * @ie: information elements of the deauth/disassoc frame (may be %NULL)
+ * @ie_len: length of IEs
+ * @reason: reason code for the disconnection, set it to 0 if unknown
+ * @gfp: allocation flags
+ *
+ * After it calls this function, the driver should enter an idle state
+ * and not try to connect to any AP any more.
+ */
+void cfg80211_disconnected(struct net_device *dev, u16 reason,
+ u8 *ie, size_t ie_len, gfp_t gfp);
+
+
#endif /* __NET_CFG80211_H */
diff --git a/include/net/genetlink.h b/include/net/genetlink.h
index 1b0e3ee4ddd..2a1c06874c4 100644
--- a/include/net/genetlink.h
+++ b/include/net/genetlink.h
@@ -3,6 +3,7 @@
#include <linux/genetlink.h>
#include <net/netlink.h>
+#include <net/net_namespace.h>
/**
* struct genl_multicast_group - generic netlink multicast group
@@ -27,6 +28,8 @@ struct genl_multicast_group
* @name: name of family
* @version: protocol version
* @maxattr: maximum number of attributes supported
+ * @netnsok: set to true if the family can handle network
+ * namespaces and should be presented in all of them
* @attrbuf: buffer to store parsed attributes
* @ops_list: list of all assigned operations
* @family_list: family list
@@ -39,6 +42,7 @@ struct genl_family
char name[GENL_NAMSIZ];
unsigned int version;
unsigned int maxattr;
+ bool netnsok;
struct nlattr ** attrbuf; /* private */
struct list_head ops_list; /* private */
struct list_head family_list; /* private */
@@ -62,8 +66,32 @@ struct genl_info
struct genlmsghdr * genlhdr;
void * userhdr;
struct nlattr ** attrs;
+#ifdef CONFIG_NET_NS
+ struct net * _net;
+#endif
};
+#ifdef CONFIG_NET_NS
+static inline struct net *genl_info_net(struct genl_info *info)
+{
+ return info->_net;
+}
+
+static inline void genl_info_net_set(struct genl_info *info, struct net *net)
+{
+ info->_net = net;
+}
+#else
+static inline struct net *genl_info_net(struct genl_info *info)
+{
+ return &init_net;
+}
+
+static inline void genl_info_net_set(struct genl_info *info, struct net *net)
+{
+}
+#endif
+
/**
* struct genl_ops - generic netlink operations
* @cmd: command identifier
@@ -98,8 +126,6 @@ extern int genl_register_mc_group(struct genl_family *family,
extern void genl_unregister_mc_group(struct genl_family *family,
struct genl_multicast_group *grp);
-extern struct sock *genl_sock;
-
/**
* genlmsg_put - Add generic netlink header to netlink message
* @skb: socket buffer holding the message
@@ -170,7 +196,21 @@ static inline void genlmsg_cancel(struct sk_buff *skb, void *hdr)
}
/**
- * genlmsg_multicast - multicast a netlink message
+ * genlmsg_multicast_netns - multicast a netlink message to a specific netns
+ * @net: the net namespace
+ * @skb: netlink message as socket buffer
+ * @pid: own netlink pid to avoid sending to yourself
+ * @group: multicast group id
+ * @flags: allocation flags
+ */
+static inline int genlmsg_multicast_netns(struct net *net, struct sk_buff *skb,
+ u32 pid, unsigned int group, gfp_t flags)
+{
+ return nlmsg_multicast(net->genl_sock, skb, pid, group, flags);
+}
+
+/**
+ * genlmsg_multicast - multicast a netlink message to the default netns
* @skb: netlink message as socket buffer
* @pid: own netlink pid to avoid sending to yourself
* @group: multicast group id
@@ -179,17 +219,29 @@ static inline void genlmsg_cancel(struct sk_buff *skb, void *hdr)
static inline int genlmsg_multicast(struct sk_buff *skb, u32 pid,
unsigned int group, gfp_t flags)
{
- return nlmsg_multicast(genl_sock, skb, pid, group, flags);
+ return genlmsg_multicast_netns(&init_net, skb, pid, group, flags);
}
/**
+ * genlmsg_multicast_allns - multicast a netlink message to all net namespaces
+ * @skb: netlink message as socket buffer
+ * @pid: own netlink pid to avoid sending to yourself
+ * @group: multicast group id
+ * @flags: allocation flags
+ *
+ * This function must hold the RTNL or rcu_read_lock().
+ */
+int genlmsg_multicast_allns(struct sk_buff *skb, u32 pid,
+ unsigned int group, gfp_t flags);
+
+/**
* genlmsg_unicast - unicast a netlink message
* @skb: netlink message as socket buffer
* @pid: netlink pid of the destination socket
*/
-static inline int genlmsg_unicast(struct sk_buff *skb, u32 pid)
+static inline int genlmsg_unicast(struct net *net, struct sk_buff *skb, u32 pid)
{
- return nlmsg_unicast(genl_sock, skb, pid);
+ return nlmsg_unicast(net->genl_sock, skb, pid);
}
/**
@@ -199,7 +251,7 @@ static inline int genlmsg_unicast(struct sk_buff *skb, u32 pid)
*/
static inline int genlmsg_reply(struct sk_buff *skb, struct genl_info *info)
{
- return genlmsg_unicast(skb, info->snd_pid);
+ return genlmsg_unicast(genl_info_net(info), skb, info->snd_pid);
}
/**
diff --git a/include/net/ieee802154/mac_def.h b/include/net/ieee802154.h
index 8cb68463565..d52685defb1 100644
--- a/include/net/ieee802154/mac_def.h
+++ b/include/net/ieee802154.h
@@ -23,8 +23,8 @@
* Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
*/
-#ifndef IEEE802154_MAC_DEF_H
-#define IEEE802154_MAC_DEF_H
+#ifndef NET_IEEE802154_H
+#define NET_IEEE802154_H
#define IEEE802154_FC_TYPE_BEACON 0x0 /* Frame is beacon */
#define IEEE802154_FC_TYPE_DATA 0x1 /* Frame is data */
diff --git a/include/net/ieee802154/nl802154.h b/include/net/ieee802154/nl802154.h
deleted file mode 100644
index 78efcdf52b5..00000000000
--- a/include/net/ieee802154/nl802154.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * nl802154.h
- *
- * Copyright (C) 2007, 2008, 2009 Siemens AG
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-
-#ifndef IEEE802154_NL_H
-#define IEEE802154_NL_H
-
-struct net_device;
-struct ieee802154_addr;
-
-int ieee802154_nl_assoc_indic(struct net_device *dev,
- struct ieee802154_addr *addr, u8 cap);
-int ieee802154_nl_assoc_confirm(struct net_device *dev,
- u16 short_addr, u8 status);
-int ieee802154_nl_disassoc_indic(struct net_device *dev,
- struct ieee802154_addr *addr, u8 reason);
-int ieee802154_nl_disassoc_confirm(struct net_device *dev,
- u8 status);
-int ieee802154_nl_scan_confirm(struct net_device *dev,
- u8 status, u8 scan_type, u32 unscanned,
- u8 *edl/*, struct list_head *pan_desc_list */);
-int ieee802154_nl_beacon_indic(struct net_device *dev, u16 panid,
- u16 coord_addr);
-
-#endif
diff --git a/include/net/ieee802154/netdevice.h b/include/net/ieee802154_netdev.h
index e2506af3e7c..e2506af3e7c 100644
--- a/include/net/ieee802154/netdevice.h
+++ b/include/net/ieee802154_netdev.h
diff --git a/include/net/ip6_fib.h b/include/net/ip6_fib.h
index 7c5c0f79168..15b492a9aa7 100644
--- a/include/net/ip6_fib.h
+++ b/include/net/ip6_fib.h
@@ -22,6 +22,12 @@
#include <net/flow.h>
#include <net/netlink.h>
+#ifdef CONFIG_IPV6_MULTIPLE_TABLES
+#define FIB6_TABLE_HASHSZ 256
+#else
+#define FIB6_TABLE_HASHSZ 1
+#endif
+
struct rt6_info;
struct fib6_config
diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h
index bbae1e87efc..98978e73f66 100644
--- a/include/net/ip_vs.h
+++ b/include/net/ip_vs.h
@@ -99,47 +99,47 @@ static inline const char *ip_vs_dbg_addr(int af, char *buf, size_t buf_len,
return &buf[*idx - len];
}
-#define IP_VS_DBG_BUF(level, msg...) \
- do { \
- char ip_vs_dbg_buf[160]; \
- int ip_vs_dbg_idx = 0; \
- if (level <= ip_vs_get_debug_level()) \
- printk(KERN_DEBUG "IPVS: " msg); \
- } while (0)
-#define IP_VS_ERR_BUF(msg...) \
- do { \
- char ip_vs_dbg_buf[160]; \
- int ip_vs_dbg_idx = 0; \
- printk(KERN_ERR "IPVS: " msg); \
- } while (0)
+#define IP_VS_DBG_BUF(level, msg, ...) \
+ do { \
+ char ip_vs_dbg_buf[160]; \
+ int ip_vs_dbg_idx = 0; \
+ if (level <= ip_vs_get_debug_level()) \
+ printk(KERN_DEBUG pr_fmt(msg), ##__VA_ARGS__); \
+ } while (0)
+#define IP_VS_ERR_BUF(msg...) \
+ do { \
+ char ip_vs_dbg_buf[160]; \
+ int ip_vs_dbg_idx = 0; \
+ pr_err(msg); \
+ } while (0)
/* Only use from within IP_VS_DBG_BUF() or IP_VS_ERR_BUF macros */
-#define IP_VS_DBG_ADDR(af, addr) \
- ip_vs_dbg_addr(af, ip_vs_dbg_buf, \
- sizeof(ip_vs_dbg_buf), addr, \
- &ip_vs_dbg_idx)
-
-#define IP_VS_DBG(level, msg...) \
- do { \
- if (level <= ip_vs_get_debug_level()) \
- printk(KERN_DEBUG "IPVS: " msg); \
- } while (0)
-#define IP_VS_DBG_RL(msg...) \
- do { \
- if (net_ratelimit()) \
- printk(KERN_DEBUG "IPVS: " msg); \
- } while (0)
-#define IP_VS_DBG_PKT(level, pp, skb, ofs, msg) \
- do { \
- if (level <= ip_vs_get_debug_level()) \
- pp->debug_packet(pp, skb, ofs, msg); \
- } while (0)
-#define IP_VS_DBG_RL_PKT(level, pp, skb, ofs, msg) \
- do { \
- if (level <= ip_vs_get_debug_level() && \
- net_ratelimit()) \
- pp->debug_packet(pp, skb, ofs, msg); \
- } while (0)
+#define IP_VS_DBG_ADDR(af, addr) \
+ ip_vs_dbg_addr(af, ip_vs_dbg_buf, \
+ sizeof(ip_vs_dbg_buf), addr, \
+ &ip_vs_dbg_idx)
+
+#define IP_VS_DBG(level, msg, ...) \
+ do { \
+ if (level <= ip_vs_get_debug_level()) \
+ printk(KERN_DEBUG pr_fmt(msg), ##__VA_ARGS__); \
+ } while (0)
+#define IP_VS_DBG_RL(msg, ...) \
+ do { \
+ if (net_ratelimit()) \
+ printk(KERN_DEBUG pr_fmt(msg), ##__VA_ARGS__); \
+ } while (0)
+#define IP_VS_DBG_PKT(level, pp, skb, ofs, msg) \
+ do { \
+ if (level <= ip_vs_get_debug_level()) \
+ pp->debug_packet(pp, skb, ofs, msg); \
+ } while (0)
+#define IP_VS_DBG_RL_PKT(level, pp, skb, ofs, msg) \
+ do { \
+ if (level <= ip_vs_get_debug_level() && \
+ net_ratelimit()) \
+ pp->debug_packet(pp, skb, ofs, msg); \
+ } while (0)
#else /* NO DEBUGGING at ALL */
#define IP_VS_DBG_BUF(level, msg...) do {} while (0)
#define IP_VS_ERR_BUF(msg...) do {} while (0)
@@ -150,29 +150,27 @@ static inline const char *ip_vs_dbg_addr(int af, char *buf, size_t buf_len,
#endif
#define IP_VS_BUG() BUG()
-#define IP_VS_ERR(msg...) printk(KERN_ERR "IPVS: " msg)
-#define IP_VS_INFO(msg...) printk(KERN_INFO "IPVS: " msg)
-#define IP_VS_WARNING(msg...) \
- printk(KERN_WARNING "IPVS: " msg)
-#define IP_VS_ERR_RL(msg...) \
- do { \
- if (net_ratelimit()) \
- printk(KERN_ERR "IPVS: " msg); \
- } while (0)
+#define IP_VS_ERR_RL(msg, ...) \
+ do { \
+ if (net_ratelimit()) \
+ pr_err(msg, ##__VA_ARGS__); \
+ } while (0)
#ifdef CONFIG_IP_VS_DEBUG
#define EnterFunction(level) \
- do { \
- if (level <= ip_vs_get_debug_level()) \
- printk(KERN_DEBUG "Enter: %s, %s line %i\n", \
- __func__, __FILE__, __LINE__); \
- } while (0)
-#define LeaveFunction(level) \
- do { \
- if (level <= ip_vs_get_debug_level()) \
- printk(KERN_DEBUG "Leave: %s, %s line %i\n", \
- __func__, __FILE__, __LINE__); \
- } while (0)
+ do { \
+ if (level <= ip_vs_get_debug_level()) \
+ printk(KERN_DEBUG \
+ pr_fmt("Enter: %s, %s line %i\n"), \
+ __func__, __FILE__, __LINE__); \
+ } while (0)
+#define LeaveFunction(level) \
+ do { \
+ if (level <= ip_vs_get_debug_level()) \
+ printk(KERN_DEBUG \
+ pr_fmt("Leave: %s, %s line %i\n"), \
+ __func__, __FILE__, __LINE__); \
+ } while (0)
#else
#define EnterFunction(level) do {} while (0)
#define LeaveFunction(level) do {} while (0)
@@ -740,7 +738,8 @@ extern void ip_vs_protocol_cleanup(void);
extern void ip_vs_protocol_timeout_change(int flags);
extern int *ip_vs_create_timeout_table(int *table, int size);
extern int
-ip_vs_set_state_timeout(int *table, int num, char **names, char *name, int to);
+ip_vs_set_state_timeout(int *table, int num, const char *const *names,
+ const char *name, int to);
extern void
ip_vs_tcpudp_debug_packet(struct ip_vs_protocol *pp, const struct sk_buff *skb,
int offset, const char *msg);
diff --git a/include/net/ipv6.h b/include/net/ipv6.h
index f27fd83d67d..ad9a5113025 100644
--- a/include/net/ipv6.h
+++ b/include/net/ipv6.h
@@ -441,6 +441,18 @@ static inline int ipv6_addr_diff(const struct in6_addr *a1, const struct in6_add
return __ipv6_addr_diff(a1, a2, sizeof(struct in6_addr));
}
+static __inline__ void ipv6_select_ident(struct frag_hdr *fhdr)
+{
+ static u32 ipv6_fragmentation_id = 1;
+ static DEFINE_SPINLOCK(ip6_id_lock);
+
+ spin_lock_bh(&ip6_id_lock);
+ fhdr->identification = htonl(ipv6_fragmentation_id);
+ if (++ipv6_fragmentation_id == 0)
+ ipv6_fragmentation_id = 1;
+ spin_unlock_bh(&ip6_id_lock);
+}
+
/*
* Prototypes exported by ipv6
*/
diff --git a/include/net/irda/ircomm_event.h b/include/net/irda/ircomm_event.h
index c290447872d..bc0c6f31f1c 100644
--- a/include/net/irda/ircomm_event.h
+++ b/include/net/irda/ircomm_event.h
@@ -74,7 +74,7 @@ struct ircomm_info {
struct qos_info *qos;
};
-extern char *ircomm_state[];
+extern const char *const ircomm_state[];
struct ircomm_cb; /* Forward decl. */
diff --git a/include/net/irda/ircomm_tty_attach.h b/include/net/irda/ircomm_tty_attach.h
index f91a5695aa4..0a63bbb972d 100644
--- a/include/net/irda/ircomm_tty_attach.h
+++ b/include/net/irda/ircomm_tty_attach.h
@@ -66,8 +66,8 @@ struct ircomm_tty_info {
__u8 dlsap_sel;
};
-extern char *ircomm_state[];
-extern char *ircomm_tty_state[];
+extern const char *const ircomm_state[];
+extern const char *const ircomm_tty_state[];
int ircomm_tty_do_event(struct ircomm_tty_cb *self, IRCOMM_TTY_EVENT event,
struct sk_buff *skb, struct ircomm_tty_info *info);
diff --git a/include/net/irda/irlap_event.h b/include/net/irda/irlap_event.h
index 2ae2e119ef4..4c90824c50f 100644
--- a/include/net/irda/irlap_event.h
+++ b/include/net/irda/irlap_event.h
@@ -120,7 +120,7 @@ typedef enum { /* FIXME check the two first reason codes */
LAP_PRIMARY_CONFLICT,
} LAP_REASON;
-extern const char *irlap_state[];
+extern const char *const irlap_state[];
void irlap_do_event(struct irlap_cb *self, IRLAP_EVENT event,
struct sk_buff *skb, struct irlap_info *info);
diff --git a/include/net/irda/irlmp_event.h b/include/net/irda/irlmp_event.h
index e03ae4ae396..9e4ec17a744 100644
--- a/include/net/irda/irlmp_event.h
+++ b/include/net/irda/irlmp_event.h
@@ -79,8 +79,8 @@ typedef enum {
LM_LAP_IDLE_TIMEOUT,
} IRLMP_EVENT;
-extern const char *irlmp_state[];
-extern const char *irlsap_state[];
+extern const char *const irlmp_state[];
+extern const char *const irlsap_state[];
void irlmp_watchdog_timer_expired(void *data);
void irlmp_discovery_timer_expired(void *data);
diff --git a/include/net/iw_handler.h b/include/net/iw_handler.h
index 51b9a37de99..2b3fbbb8669 100644
--- a/include/net/iw_handler.h
+++ b/include/net/iw_handler.h
@@ -443,7 +443,7 @@ extern int dev_get_wireless_info(char * buffer, char **start, off_t offset,
extern void wireless_send_event(struct net_device * dev,
unsigned int cmd,
union iwreq_data * wrqu,
- char * extra);
+ const char * extra);
/* We may need a function to send a stream of events to user space.
* More on that later... */
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index c0610447697..76d43e12cc2 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -73,6 +73,21 @@
*/
/**
+ * DOC: mac80211 workqueue
+ *
+ * mac80211 provides its own workqueue for drivers and internal mac80211 use.
+ * The workqueue is a single threaded workqueue and can only be accessed by
+ * helpers for sanity checking. Drivers must ensure all work added onto the
+ * mac80211 workqueue should be cancelled on the driver stop() callback.
+ *
+ * mac80211 will flushed the workqueue upon interface removal and during
+ * suspend.
+ *
+ * All work performed on the mac80211 workqueue must not acquire the RTNL lock.
+ *
+ */
+
+/**
* enum ieee80211_max_queues - maximum number of queues
*
* @IEEE80211_MAX_QUEUES: Maximum number of regular device queues.
@@ -224,7 +239,14 @@ struct ieee80211_bss_conf {
* @IEEE80211_TX_CTL_AMPDU: this frame should be sent as part of an A-MPDU
* @IEEE80211_TX_CTL_INJECTED: Frame was injected, internal to mac80211.
* @IEEE80211_TX_STAT_TX_FILTERED: The frame was not transmitted
- * because the destination STA was in powersave mode.
+ * because the destination STA was in powersave mode. Note that to
+ * avoid race conditions, the filter must be set by the hardware or
+ * firmware upon receiving a frame that indicates that the station
+ * went to sleep (must be done on device to filter frames already on
+ * the queue) and may only be unset after mac80211 gives the OK for
+ * that by setting the IEEE80211_TX_CTL_CLEAR_PS_FILT (see above),
+ * since only then is it guaranteed that no more frames are in the
+ * hardware queue.
* @IEEE80211_TX_STAT_ACK: Frame was acknowledged
* @IEEE80211_TX_STAT_AMPDU: The frame was aggregated, so status
* is for the whole aggregation.
@@ -241,6 +263,15 @@ struct ieee80211_bss_conf {
* it can be sent out.
* @IEEE80211_TX_INTFL_RETRIED: completely internal to mac80211,
* used to indicate that a frame was already retried due to PS
+ * @IEEE80211_TX_INTFL_DONT_ENCRYPT: completely internal to mac80211,
+ * used to indicate frame should not be encrypted
+ * @IEEE80211_TX_CTL_PSPOLL_RESPONSE: (internal?)
+ * This frame is a response to a PS-poll frame and should be sent
+ * although the station is in powersave mode.
+ * @IEEE80211_TX_CTL_MORE_FRAMES: More frames will be passed to the
+ * transmit function after the current frame, this can be used
+ * by drivers to kick the DMA queue only if unset or when the
+ * queue gets full.
*/
enum mac80211_tx_control_flags {
IEEE80211_TX_CTL_REQ_TX_STATUS = BIT(0),
@@ -259,6 +290,9 @@ enum mac80211_tx_control_flags {
IEEE80211_TX_INTFL_RCALGO = BIT(13),
IEEE80211_TX_INTFL_NEED_TXPROCESSING = BIT(14),
IEEE80211_TX_INTFL_RETRIED = BIT(15),
+ IEEE80211_TX_INTFL_DONT_ENCRYPT = BIT(16),
+ IEEE80211_TX_CTL_PSPOLL_RESPONSE = BIT(17),
+ IEEE80211_TX_CTL_MORE_FRAMES = BIT(18),
};
/**
@@ -316,6 +350,21 @@ enum mac80211_rate_control_flags {
*
* When used for transmit status reporting, the driver should
* always report the rate along with the flags it used.
+ *
+ * &struct ieee80211_tx_info contains an array of these structs
+ * in the control information, and it will be filled by the rate
+ * control algorithm according to what should be sent. For example,
+ * if this array contains, in the format { <idx>, <count> } the
+ * information
+ * { 3, 2 }, { 2, 2 }, { 1, 4 }, { -1, 0 }, { -1, 0 }
+ * then this means that the frame should be transmitted
+ * up to twice at rate 3, up to twice at rate 2, and up to four
+ * times at rate 1 if it doesn't get acknowledged. Say it gets
+ * acknowledged by the peer after the fifth attempt, the status
+ * information should then contain
+ * { 3, 2 }, { 2, 2 }, { 1, 1 }, { -1, 0 } ...
+ * since it was transmitted twice at rate 3, twice at rate 2
+ * and once at rate 1 after which we received an acknowledgement.
*/
struct ieee80211_tx_rate {
s8 idx;
@@ -397,6 +446,11 @@ static inline struct ieee80211_tx_info *IEEE80211_SKB_CB(struct sk_buff *skb)
return (struct ieee80211_tx_info *)skb->cb;
}
+static inline struct ieee80211_rx_status *IEEE80211_SKB_RXCB(struct sk_buff *skb)
+{
+ return (struct ieee80211_rx_status *)skb->cb;
+}
+
/**
* ieee80211_tx_info_clear_status - clear TX status
*
@@ -478,7 +532,7 @@ enum mac80211_rx_flags {
*
* The low-level driver should provide this information (the subset
* supported by hardware) to the 802.11 code with each received
- * frame.
+ * frame, in the skb's control buffer (cb).
*
* @mactime: value in microseconds of the 64-bit Time Synchronization Function
* (TSF) timer when the first data symbol (MPDU) arrived at the hardware.
@@ -901,12 +955,6 @@ enum ieee80211_hw_flags {
*
* @conf: &struct ieee80211_conf, device configuration, don't use.
*
- * @workqueue: single threaded workqueue available for driver use,
- * allocated by mac80211 on registration and flushed when an
- * interface is removed.
- * NOTICE: All work performed on this workqueue must not
- * acquire the RTNL lock.
- *
* @priv: pointer to private area that was allocated for driver use
* along with this structure.
*
@@ -942,7 +990,6 @@ enum ieee80211_hw_flags {
struct ieee80211_hw {
struct ieee80211_conf conf;
struct wiphy *wiphy;
- struct workqueue_struct *workqueue;
const char *rate_control_algorithm;
void *priv;
u32 flags;
@@ -1224,10 +1271,13 @@ ieee80211_get_alt_retry_rate(const struct ieee80211_hw *hw,
* mac80211 needs to do and the amount of CPU wakeups, so you should
* honour this flag if possible.
*
- * @FIF_CONTROL: pass control frames, if PROMISC_IN_BSS is not set then
- * only those addressed to this station
+ * @FIF_CONTROL: pass control frames (except for PS Poll), if PROMISC_IN_BSS
+ * is not set then only those addressed to this station.
*
* @FIF_OTHER_BSS: pass frames destined to other BSSes
+ *
+ * @FIF_PSPOLL: pass PS Poll frames, if PROMISC_IN_BSS is not set then only
+ * those addressed to this station.
*/
enum ieee80211_filter_flags {
FIF_PROMISC_IN_BSS = 1<<0,
@@ -1237,6 +1287,7 @@ enum ieee80211_filter_flags {
FIF_BCN_PRBRESP_PROMISC = 1<<4,
FIF_CONTROL = 1<<5,
FIF_OTHER_BSS = 1<<6,
+ FIF_PSPOLL = 1<<7,
};
/**
@@ -1289,7 +1340,8 @@ enum ieee80211_ampdu_mlme_action {
* is disabled. This should turn off the hardware (at least
* it must turn off frame reception.)
* May be called right after add_interface if that rejects
- * an interface.
+ * an interface. If you added any work onto the mac80211 workqueue
+ * you should ensure to cancel it on this callback.
* Must be implemented.
*
* @add_interface: Called when a netdevice attached to the hardware is
@@ -1411,6 +1463,8 @@ enum ieee80211_ampdu_mlme_action {
* @rfkill_poll: Poll rfkill hardware state. If you need this, you also
* need to set wiphy->rfkill_poll to %true before registration,
* and need to call wiphy_rfkill_set_hw_state() in the callback.
+ *
+ * @testmode_cmd: Implement a cfg80211 test mode command.
*/
struct ieee80211_ops {
int (*tx)(struct ieee80211_hw *hw, struct sk_buff *skb);
@@ -1461,6 +1515,9 @@ struct ieee80211_ops {
struct ieee80211_sta *sta, u16 tid, u16 *ssn);
void (*rfkill_poll)(struct ieee80211_hw *hw);
+#ifdef CONFIG_NL80211_TESTMODE
+ int (*testmode_cmd)(struct ieee80211_hw *hw, void *data, int len);
+#endif
};
/**
@@ -1606,9 +1663,11 @@ void ieee80211_free_hw(struct ieee80211_hw *hw);
*/
void ieee80211_restart_hw(struct ieee80211_hw *hw);
-/* trick to avoid symbol clashes with the ieee80211 subsystem */
-void __ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb,
- struct ieee80211_rx_status *status);
+/*
+ * trick to avoid symbol clashes with the ieee80211 subsystem,
+ * use the inline below instead
+ */
+void __ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb);
/**
* ieee80211_rx - receive frame
@@ -1624,13 +1683,10 @@ void __ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb,
*
* @hw: the hardware this frame came in on
* @skb: the buffer to receive, owned by mac80211 after this call
- * @status: status of this frame; the status pointer need not be valid
- * after this function returns
*/
-static inline void ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb,
- struct ieee80211_rx_status *status)
+static inline void ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb)
{
- __ieee80211_rx(hw, skb, status);
+ __ieee80211_rx(hw, skb);
}
/**
@@ -1644,13 +1700,8 @@ static inline void ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb,
*
* @hw: the hardware this frame came in on
* @skb: the buffer to receive, owned by mac80211 after this call
- * @status: status of this frame; the status pointer need not be valid
- * after this function returns and is not freed by mac80211,
- * it is recommended that it points to a stack area
*/
-void ieee80211_rx_irqsafe(struct ieee80211_hw *hw,
- struct sk_buff *skb,
- struct ieee80211_rx_status *status);
+void ieee80211_rx_irqsafe(struct ieee80211_hw *hw, struct sk_buff *skb);
/**
* ieee80211_tx_status - transmit status callback
@@ -1917,6 +1968,31 @@ void ieee80211_iterate_active_interfaces_atomic(struct ieee80211_hw *hw,
void *data);
/**
+ * ieee80211_queue_work - add work onto the mac80211 workqueue
+ *
+ * Drivers and mac80211 use this to add work onto the mac80211 workqueue.
+ * This helper ensures drivers are not queueing work when they should not be.
+ *
+ * @hw: the hardware struct for the interface we are adding work for
+ * @work: the work we want to add onto the mac80211 workqueue
+ */
+void ieee80211_queue_work(struct ieee80211_hw *hw, struct work_struct *work);
+
+/**
+ * ieee80211_queue_delayed_work - add work onto the mac80211 workqueue
+ *
+ * Drivers and mac80211 use this to queue delayed work onto the mac80211
+ * workqueue.
+ *
+ * @hw: the hardware struct for the interface we are adding work for
+ * @dwork: delayable work to queue onto the mac80211 workqueue
+ * @delay: number of jiffies to wait before queueing
+ */
+void ieee80211_queue_delayed_work(struct ieee80211_hw *hw,
+ struct delayed_work *dwork,
+ unsigned long delay);
+
+/**
* ieee80211_start_tx_ba_session - Start a tx Block Ack session.
* @hw: pointer as obtained from ieee80211_alloc_hw().
* @ra: receiver address of the BA session recipient
@@ -2090,6 +2166,29 @@ static inline int rate_supported(struct ieee80211_sta *sta,
return (sta == NULL || sta->supp_rates[band] & BIT(index));
}
+/**
+ * rate_control_send_low - helper for drivers for management/no-ack frames
+ *
+ * Rate control algorithms that agree to use the lowest rate to
+ * send management frames and NO_ACK data with the respective hw
+ * retries should use this in the beginning of their mac80211 get_rate
+ * callback. If true is returned the rate control can simply return.
+ * If false is returned we guarantee that sta and sta and priv_sta is
+ * not null.
+ *
+ * Rate control algorithms wishing to do more intelligent selection of
+ * rate for multicast/broadcast frames may choose to not use this.
+ *
+ * @sta: &struct ieee80211_sta pointer to the target destination. Note
+ * that this may be null.
+ * @priv_sta: private rate control structure. This may be null.
+ * @txrc: rate control information we sholud populate for mac80211.
+ */
+bool rate_control_send_low(struct ieee80211_sta *sta,
+ void *priv_sta,
+ struct ieee80211_tx_rate_control *txrc);
+
+
static inline s8
rate_lowest_index(struct ieee80211_supported_band *sband,
struct ieee80211_sta *sta)
@@ -2106,6 +2205,17 @@ rate_lowest_index(struct ieee80211_supported_band *sband,
return 0;
}
+static inline
+bool rate_usable_index_exists(struct ieee80211_supported_band *sband,
+ struct ieee80211_sta *sta)
+{
+ unsigned int i;
+
+ for (i = 0; i < sband->n_bitrates; i++)
+ if (rate_supported(sta, sband->band, i))
+ return true;
+ return false;
+}
int ieee80211_rate_control_register(struct rate_control_ops *ops);
void ieee80211_rate_control_unregister(struct rate_control_ops *ops);
diff --git a/include/net/neighbour.h b/include/net/neighbour.h
index d8d790e56d3..18b69b6ceca 100644
--- a/include/net/neighbour.h
+++ b/include/net/neighbour.h
@@ -24,6 +24,7 @@
#include <linux/err.h>
#include <linux/sysctl.h>
+#include <linux/workqueue.h>
#include <net/rtnetlink.h>
/*
@@ -167,7 +168,7 @@ struct neigh_table
int gc_thresh2;
int gc_thresh3;
unsigned long last_flush;
- struct timer_list gc_timer;
+ struct delayed_work gc_work;
struct timer_list proxy_timer;
struct sk_buff_head proxy_queue;
atomic_t entries;
@@ -178,7 +179,6 @@ struct neigh_table
struct neighbour **hash_buckets;
unsigned int hash_mask;
__u32 hash_rnd;
- unsigned int hash_chain_gc;
struct pneigh_entry **phash_buckets;
};
diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
index ded434b032a..a1202841aad 100644
--- a/include/net/net_namespace.h
+++ b/include/net/net_namespace.h
@@ -26,6 +26,7 @@ struct net_device;
struct sock;
struct ctl_table_header;
struct net_generic;
+struct sock;
struct net {
atomic_t count; /* To decided when the network
@@ -57,6 +58,7 @@ struct net {
spinlock_t rules_mod_lock;
struct sock *rtnl; /* rtnetlink socket */
+ struct sock *genl_sock;
struct netns_core core;
struct netns_mib mib;
@@ -78,6 +80,9 @@ struct net {
#ifdef CONFIG_XFRM
struct netns_xfrm xfrm;
#endif
+#ifdef CONFIG_WIRELESS_EXT
+ struct sk_buff_head wext_nlevents;
+#endif
struct net_generic *gen;
};
@@ -106,6 +111,8 @@ static inline struct net *copy_net_ns(unsigned long flags, struct net *net_ns)
extern struct list_head net_namespace_list;
+extern struct net *get_net_ns_by_pid(pid_t pid);
+
#ifdef CONFIG_NET_NS
extern void __put_net(struct net *net);
@@ -208,6 +215,9 @@ static inline struct net *read_pnet(struct net * const *pnet)
#define for_each_net(VAR) \
list_for_each_entry(VAR, &net_namespace_list, list)
+#define for_each_net_rcu(VAR) \
+ list_for_each_entry_rcu(VAR, &net_namespace_list, list)
+
#ifdef CONFIG_NET_NS
#define __net_init
#define __net_exit
@@ -229,13 +239,15 @@ struct pernet_operations {
* needs per network namespace operations use device pernet operations,
* otherwise use pernet subsys operations.
*
- * This is critically important. Most of the network code cleanup
- * runs with the assumption that dev_remove_pack has been called so no
- * new packets will arrive during and after the cleanup functions have
- * been called. dev_remove_pack is not per namespace so instead the
- * guarantee of no more packets arriving in a network namespace is
- * provided by ensuring that all network devices and all sockets have
- * left the network namespace before the cleanup methods are called.
+ * Network interfaces need to be removed from a dying netns _before_
+ * subsys notifiers can be called, as most of the network code cleanup
+ * (which is done from subsys notifiers) runs with the assumption that
+ * dev_remove_pack has been called so no new packets will arrive during
+ * and after the cleanup functions have been called. dev_remove_pack
+ * is not per namespace so instead the guarantee of no more packets
+ * arriving in a network namespace is provided by ensuring that all
+ * network devices and all sockets have left the network namespace
+ * before the cleanup methods are called.
*
* For the longest time the ipv4 icmp code was registered as a pernet
* device which caused kernel oops, and panics during network
diff --git a/include/net/netns/x_tables.h b/include/net/netns/x_tables.h
index 9554a644a8f..591db7d657a 100644
--- a/include/net/netns/x_tables.h
+++ b/include/net/netns/x_tables.h
@@ -8,8 +8,11 @@ struct ebt_table;
struct netns_xt {
struct list_head tables[NFPROTO_NUMPROTO];
+#if defined(CONFIG_BRIDGE_NF_EBTABLES) || \
+ defined(CONFIG_BRIDGE_NF_EBTABLES_MODULE)
struct ebt_table *broute_table;
struct ebt_table *frame_filter;
struct ebt_table *frame_nat;
+#endif
};
#endif
diff --git a/include/net/nl802154.h b/include/net/nl802154.h
new file mode 100644
index 00000000000..e554ecd3727
--- /dev/null
+++ b/include/net/nl802154.h
@@ -0,0 +1,126 @@
+/*
+ * nl802154.h
+ *
+ * Copyright (C) 2007, 2008, 2009 Siemens AG
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#ifndef IEEE802154_NL_H
+#define IEEE802154_NL_H
+
+struct net_device;
+struct ieee802154_addr;
+
+/**
+ * ieee802154_nl_assoc_indic - Notify userland of an association request.
+ * @dev: The network device on which this association request was
+ * received.
+ * @addr: The address of the device requesting association.
+ * @cap: The capability information field from the device.
+ *
+ * This informs a userland coordinator of a device requesting to
+ * associate with the PAN controlled by the coordinator.
+ *
+ * Note: This is in section 7.3.1 of the IEEE 802.15.4-2006 document.
+ */
+int ieee802154_nl_assoc_indic(struct net_device *dev,
+ struct ieee802154_addr *addr, u8 cap);
+
+/**
+ * ieee802154_nl_assoc_confirm - Notify userland of association.
+ * @dev: The device which has completed association.
+ * @short_addr: The short address assigned to the device.
+ * @status: The status of the association.
+ *
+ * Inform userland of the result of an association request. If the
+ * association request included asking the coordinator to allocate
+ * a short address then it is returned in @short_addr.
+ *
+ * Note: This is in section 7.3.2 of the IEEE 802.15.4 document.
+ */
+int ieee802154_nl_assoc_confirm(struct net_device *dev,
+ u16 short_addr, u8 status);
+
+/**
+ * ieee802154_nl_disassoc_indic - Notify userland of disassociation.
+ * @dev: The device on which disassociation was indicated.
+ * @addr: The device which is disassociating.
+ * @reason: The reason for the disassociation.
+ *
+ * Inform userland that a device has disassociated from the network.
+ *
+ * Note: This is in section 7.3.3 of the IEEE 802.15.4 document.
+ */
+int ieee802154_nl_disassoc_indic(struct net_device *dev,
+ struct ieee802154_addr *addr, u8 reason);
+
+/**
+ * ieee802154_nl_disassoc_confirm - Notify userland of disassociation
+ * completion.
+ * @dev: The device on which disassociation was ordered.
+ * @status: The result of the disassociation.
+ *
+ * Inform userland of the result of requesting that a device
+ * disassociate, or the result of requesting that we disassociate from
+ * a PAN managed by another coordinator.
+ *
+ * Note: This is in section 7.1.4.3 of the IEEE 802.15.4 document.
+ */
+int ieee802154_nl_disassoc_confirm(struct net_device *dev,
+ u8 status);
+
+/**
+ * ieee802154_nl_scan_confirm - Notify userland of completion of scan.
+ * @dev: The device which was instructed to scan.
+ * @status: The status of the scan operation.
+ * @scan_type: What type of scan was performed.
+ * @unscanned: Any channels that the device was unable to scan.
+ * @edl: The energy levels (if a passive scan).
+ *
+ *
+ * Note: This is in section 7.1.11 of the IEEE 802.15.4 document.
+ * Note: This API does not permit the return of an active scan result.
+ */
+int ieee802154_nl_scan_confirm(struct net_device *dev,
+ u8 status, u8 scan_type, u32 unscanned,
+ u8 *edl/*, struct list_head *pan_desc_list */);
+
+/**
+ * ieee802154_nl_beacon_indic - Notify userland of a received beacon.
+ * @dev: The device on which a beacon was received.
+ * @panid: The PAN of the coordinator.
+ * @coord_addr: The short address of the coordinator on that PAN.
+ *
+ * Note: This is in section 7.1.5 of the IEEE 802.15.4 document.
+ * Note: This API does not provide extended information such as what
+ * channel the PAN is on or what the LQI of the beacon frame was on
+ * receipt.
+ * Note: This API cannot indicate a beacon frame for a coordinator
+ * operating in long addressing mode.
+ */
+int ieee802154_nl_beacon_indic(struct net_device *dev, u16 panid,
+ u16 coord_addr);
+
+/**
+ * ieee802154_nl_start_confirm - Notify userland of completion of start.
+ * @dev: The device which was instructed to scan.
+ * @status: The status of the scan operation.
+ *
+ * Note: This is in section 7.1.14 of the IEEE 802.15.4 document.
+ */
+int ieee802154_nl_start_confirm(struct net_device *dev, u8 status);
+
+#endif
diff --git a/include/net/phonet/pn_dev.h b/include/net/phonet/pn_dev.h
index 29d12673661..44c923c9e21 100644
--- a/include/net/phonet/pn_dev.h
+++ b/include/net/phonet/pn_dev.h
@@ -49,4 +49,6 @@ void phonet_address_notify(int event, struct net_device *dev, u8 addr);
#define PN_NO_ADDR 0xff
+extern const struct file_operations pn_sock_seq_fops;
+
#endif
diff --git a/include/net/pkt_sched.h b/include/net/pkt_sched.h
index 82a3191375f..f911ec7598e 100644
--- a/include/net/pkt_sched.h
+++ b/include/net/pkt_sched.h
@@ -87,6 +87,9 @@ extern struct qdisc_rate_table *qdisc_get_rtab(struct tc_ratespec *r,
extern void qdisc_put_rtab(struct qdisc_rate_table *tab);
extern void qdisc_put_stab(struct qdisc_size_table *tab);
extern void qdisc_warn_nonwc(char *txt, struct Qdisc *qdisc);
+extern int sch_direct_xmit(struct sk_buff *skb, struct Qdisc *q,
+ struct net_device *dev, struct netdev_queue *txq,
+ spinlock_t *root_lock);
extern void __qdisc_run(struct Qdisc *q);
diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h
index 964ffa0d881..84b3fc2aef0 100644
--- a/include/net/sch_generic.h
+++ b/include/net/sch_generic.h
@@ -45,6 +45,7 @@ struct Qdisc
#define TCQ_F_BUILTIN 1
#define TCQ_F_THROTTLED 2
#define TCQ_F_INGRESS 4
+#define TCQ_F_CAN_BYPASS 8
#define TCQ_F_WARN_NONWC (1 << 16)
int padded;
struct Qdisc_ops *ops;
@@ -182,6 +183,11 @@ struct qdisc_skb_cb {
char data[];
};
+static inline int qdisc_qlen(struct Qdisc *q)
+{
+ return q->q.qlen;
+}
+
static inline struct qdisc_skb_cb *qdisc_skb_cb(struct sk_buff *skb)
{
return (struct qdisc_skb_cb *)skb->cb;
@@ -387,13 +393,18 @@ static inline int qdisc_enqueue_root(struct sk_buff *skb, struct Qdisc *sch)
return qdisc_enqueue(skb, sch) & NET_XMIT_MASK;
}
+static inline void __qdisc_update_bstats(struct Qdisc *sch, unsigned int len)
+{
+ sch->bstats.bytes += len;
+ sch->bstats.packets++;
+}
+
static inline int __qdisc_enqueue_tail(struct sk_buff *skb, struct Qdisc *sch,
struct sk_buff_head *list)
{
__skb_queue_tail(list, skb);
sch->qstats.backlog += qdisc_pkt_len(skb);
- sch->bstats.bytes += qdisc_pkt_len(skb);
- sch->bstats.packets++;
+ __qdisc_update_bstats(sch, qdisc_pkt_len(skb));
return NET_XMIT_SUCCESS;
}
diff --git a/include/net/scm.h b/include/net/scm.h
index f45bb6eca7d..cf48c800e92 100644
--- a/include/net/scm.h
+++ b/include/net/scm.h
@@ -26,7 +26,6 @@ struct scm_cookie
#ifdef CONFIG_SECURITY_NETWORK
u32 secid; /* Passed security ID */
#endif
- unsigned long seq; /* Connection seqno */
};
extern void scm_detach_fds(struct msghdr *msg, struct scm_cookie *scm);
@@ -59,7 +58,6 @@ static __inline__ int scm_send(struct socket *sock, struct msghdr *msg,
scm->creds.gid = current_gid();
scm->creds.pid = task_tgid_vnr(p);
scm->fp = NULL;
- scm->seq = 0;
unix_get_peersec_dgram(sock, scm);
if (msg->msg_controllen <= 0)
return 0;
diff --git a/include/net/sctp/constants.h b/include/net/sctp/constants.h
index b05b0557211..8bc25f7b04c 100644
--- a/include/net/sctp/constants.h
+++ b/include/net/sctp/constants.h
@@ -241,7 +241,9 @@ const char *sctp_tname(const sctp_subtype_t); /* timeouts */
const char *sctp_pname(const sctp_subtype_t); /* primitives */
/* This is a table of printable names of sctp_state_t's. */
-extern const char *sctp_state_tbl[], *sctp_evttype_tbl[], *sctp_status_tbl[];
+extern const char *const sctp_state_tbl[];
+extern const char *const sctp_evttype_tbl[];
+extern const char *const sctp_status_tbl[];
/* Maximum chunk length considering padding requirements. */
enum { SCTP_MAX_CHUNK_LEN = ((1<<16) - sizeof(__u32)) };
diff --git a/include/net/udp.h b/include/net/udp.h
index 90e6ce56be6..5fb029f817a 100644
--- a/include/net/udp.h
+++ b/include/net/udp.h
@@ -207,4 +207,7 @@ extern void udp4_proc_exit(void);
#endif
extern void udp_init(void);
+
+extern int udp4_ufo_send_check(struct sk_buff *skb);
+extern struct sk_buff *udp4_ufo_fragment(struct sk_buff *skb, int features);
#endif /* _UDP_H */
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 9e3a3f4c1f6..223e90a4482 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -1280,7 +1280,7 @@ struct xfrm6_tunnel {
};
extern void xfrm_init(void);
-extern void xfrm4_init(void);
+extern void xfrm4_init(int rt_hash_size);
extern int xfrm_state_init(struct net *net);
extern void xfrm_state_fini(struct net *net);
extern void xfrm4_state_init(void);
diff --git a/include/trace/events/skb.h b/include/trace/events/skb.h
index e499863b966..4b2be6dc76f 100644
--- a/include/trace/events/skb.h
+++ b/include/trace/events/skb.h
@@ -5,6 +5,7 @@
#define _TRACE_SKB_H
#include <linux/skbuff.h>
+#include <linux/netdevice.h>
#include <linux/tracepoint.h>
/*
@@ -34,6 +35,25 @@ TRACE_EVENT(kfree_skb,
__entry->skbaddr, __entry->protocol, __entry->location)
);
+TRACE_EVENT(skb_copy_datagram_iovec,
+
+ TP_PROTO(const struct sk_buff *skb, int len),
+
+ TP_ARGS(skb, len),
+
+ TP_STRUCT__entry(
+ __field( const void *, skbaddr )
+ __field( int, len )
+ ),
+
+ TP_fast_assign(
+ __entry->skbaddr = skb;
+ __entry->len = len;
+ ),
+
+ TP_printk("skbaddr=%p len=%d", __entry->skbaddr, __entry->len)
+);
+
#endif /* _TRACE_SKB_H */
/* This part must be outside protection */
diff --git a/kernel/taskstats.c b/kernel/taskstats.c
index 888adbcca30..ea8384d3caa 100644
--- a/kernel/taskstats.c
+++ b/kernel/taskstats.c
@@ -108,7 +108,7 @@ static int prepare_reply(struct genl_info *info, u8 cmd, struct sk_buff **skbp,
/*
* Send taskstats data in @skb to listener with nl_pid @pid
*/
-static int send_reply(struct sk_buff *skb, pid_t pid)
+static int send_reply(struct sk_buff *skb, struct genl_info *info)
{
struct genlmsghdr *genlhdr = nlmsg_data(nlmsg_hdr(skb));
void *reply = genlmsg_data(genlhdr);
@@ -120,7 +120,7 @@ static int send_reply(struct sk_buff *skb, pid_t pid)
return rc;
}
- return genlmsg_unicast(skb, pid);
+ return genlmsg_reply(skb, info);
}
/*
@@ -150,7 +150,7 @@ static void send_cpu_listeners(struct sk_buff *skb,
if (!skb_next)
break;
}
- rc = genlmsg_unicast(skb_cur, s->pid);
+ rc = genlmsg_unicast(&init_net, skb_cur, s->pid);
if (rc == -ECONNREFUSED) {
s->valid = 0;
delcount++;
@@ -418,7 +418,7 @@ static int cgroupstats_user_cmd(struct sk_buff *skb, struct genl_info *info)
goto err;
}
- rc = send_reply(rep_skb, info->snd_pid);
+ rc = send_reply(rep_skb, info);
err:
fput_light(file, fput_needed);
@@ -487,7 +487,7 @@ free_return_rc:
} else
goto err;
- return send_reply(rep_skb, info->snd_pid);
+ return send_reply(rep_skb, info);
err:
nlmsg_free(rep_skb);
return rc;
diff --git a/kernel/trace/Kconfig b/kernel/trace/Kconfig
index 019f380fd76..f09d7635c0e 100644
--- a/kernel/trace/Kconfig
+++ b/kernel/trace/Kconfig
@@ -234,6 +234,16 @@ config BOOT_TRACER
You must pass in initcall_debug and ftrace=initcall to the kernel
command line to enable this on bootup.
+config SKB_SOURCES_TRACER
+ bool "Trace skb source information"
+ select GENERIC_TRACER
+ help
+ This tracer helps developers/sysadmins correlate skb allocation and
+ consumption. The idea being that some processes will primarily consume data
+ that was allocated on certain numa nodes. By being able to visualize which
+ nodes the data was allocated on, a sysadmin or developer can optimize the
+ scheduling of those processes to cut back on cross node chatter.
+
config TRACE_BRANCH_PROFILING
bool
select GENERIC_TRACER
diff --git a/kernel/trace/Makefile b/kernel/trace/Makefile
index 844164dca90..ee5e5b1b928 100644
--- a/kernel/trace/Makefile
+++ b/kernel/trace/Makefile
@@ -49,6 +49,7 @@ obj-$(CONFIG_BLK_DEV_IO_TRACE) += blktrace.o
ifeq ($(CONFIG_BLOCK),y)
obj-$(CONFIG_EVENT_TRACING) += blktrace.o
endif
+obj-$(CONFIG_SKB_SOURCES_TRACER) += trace_skb_sources.o
obj-$(CONFIG_EVENT_TRACING) += trace_events.o
obj-$(CONFIG_EVENT_TRACING) += trace_export.o
obj-$(CONFIG_FTRACE_SYSCALLS) += trace_syscalls.o
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
index 8b9f4f6e955..8a6281b2330 100644
--- a/kernel/trace/trace.h
+++ b/kernel/trace/trace.h
@@ -11,6 +11,7 @@
#include <trace/boot.h>
#include <linux/kmemtrace.h>
#include <trace/power.h>
+#include <trace/events/skb.h>
#include <linux/trace_seq.h>
#include <linux/ftrace_event.h>
@@ -40,6 +41,7 @@ enum trace_type {
TRACE_KMEM_FREE,
TRACE_POWER,
TRACE_BLK,
+ TRACE_SKB_SOURCE,
__TRACE_LAST_TYPE,
};
@@ -171,6 +173,21 @@ struct trace_power {
struct power_trace state_data;
};
+struct skb_record {
+ pid_t pid; /* pid of the copying process */
+ int anid; /* node where skb was allocated */
+ int cnid; /* node to which skb was copied in userspace */
+ char ifname[IFNAMSIZ]; /* Name of the receiving interface */
+ int rx_queue; /* The rx queue the skb was received on */
+ int ccpu; /* Cpu the application got this frame from */
+ int len; /* length of the data copied */
+};
+
+struct trace_skb_event {
+ struct trace_entry ent;
+ struct skb_record event_data;
+};
+
enum kmemtrace_type_id {
KMEMTRACE_TYPE_KMALLOC = 0, /* kmalloc() or kfree(). */
KMEMTRACE_TYPE_CACHE, /* kmem_cache_*(). */
@@ -323,6 +340,8 @@ extern void __ftrace_bad_type(void);
TRACE_SYSCALL_ENTER); \
IF_ASSIGN(var, ent, struct syscall_trace_exit, \
TRACE_SYSCALL_EXIT); \
+ IF_ASSIGN(var, ent, struct trace_skb_event, \
+ TRACE_SKB_SOURCE); \
__ftrace_bad_type(); \
} while (0)
diff --git a/kernel/trace/trace_skb_sources.c b/kernel/trace/trace_skb_sources.c
new file mode 100644
index 00000000000..40eb071afdb
--- /dev/null
+++ b/kernel/trace/trace_skb_sources.c
@@ -0,0 +1,154 @@
+/*
+ * ring buffer based tracer for analyzing per-socket skb sources
+ *
+ * Neil Horman <nhorman@tuxdriver.com>
+ * Copyright (C) 2009
+ *
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/debugfs.h>
+#include <trace/events/skb.h>
+#include <linux/kallsyms.h>
+#include <linux/module.h>
+#include <linux/hardirq.h>
+#include <linux/netdevice.h>
+#include <net/sock.h>
+
+#include "trace.h"
+#include "trace_output.h"
+
+EXPORT_TRACEPOINT_SYMBOL_GPL(skb_copy_datagram_iovec);
+
+static struct trace_array *skb_trace;
+static int __read_mostly trace_skb_source_enabled;
+
+static void probe_skb_dequeue(const struct sk_buff *skb, int len)
+{
+ struct ring_buffer_event *event;
+ struct trace_skb_event *entry;
+ struct trace_array *tr = skb_trace;
+ struct net_device *dev;
+
+ if (!trace_skb_source_enabled)
+ return;
+
+ if (in_interrupt())
+ return;
+
+ event = trace_buffer_lock_reserve(tr, TRACE_SKB_SOURCE,
+ sizeof(*entry), 0, 0);
+ if (!event)
+ return;
+ entry = ring_buffer_event_data(event);
+
+ entry->event_data.pid = current->pid;
+ entry->event_data.anid = page_to_nid(virt_to_page(skb->data));
+ entry->event_data.cnid = cpu_to_node(smp_processor_id());
+ entry->event_data.len = len;
+ entry->event_data.rx_queue = skb->queue_mapping;
+ entry->event_data.ccpu = smp_processor_id();
+
+ dev = dev_get_by_index(sock_net(skb->sk), skb->iif);
+ if (dev) {
+ memcpy(entry->event_data.ifname, dev->name, IFNAMSIZ);
+ dev_put(dev);
+ } else {
+ strcpy(entry->event_data.ifname, "Unknown");
+ }
+
+ trace_buffer_unlock_commit(tr, event, 0, 0);
+}
+
+static int tracing_skb_source_register(void)
+{
+ int ret;
+
+ ret = register_trace_skb_copy_datagram_iovec(probe_skb_dequeue);
+ if (ret)
+ pr_info("skb source trace: Couldn't activate dequeue tracepoint");
+
+ return ret;
+}
+
+static void start_skb_source_trace(struct trace_array *tr)
+{
+ trace_skb_source_enabled = 1;
+}
+
+static void stop_skb_source_trace(struct trace_array *tr)
+{
+ trace_skb_source_enabled = 0;
+}
+
+static void skb_source_trace_reset(struct trace_array *tr)
+{
+ trace_skb_source_enabled = 0;
+ unregister_trace_skb_copy_datagram_iovec(probe_skb_dequeue);
+}
+
+
+static int skb_source_trace_init(struct trace_array *tr)
+{
+ int cpu;
+ skb_trace = tr;
+
+ trace_skb_source_enabled = 1;
+ tracing_skb_source_register();
+
+ for_each_cpu(cpu, cpu_possible_mask)
+ tracing_reset(tr, cpu);
+ return 0;
+}
+
+static enum print_line_t skb_source_print_line(struct trace_iterator *iter)
+{
+ int ret = 0;
+ struct trace_entry *entry = iter->ent;
+ struct trace_skb_event *event;
+ struct skb_record *record;
+ struct trace_seq *s = &iter->seq;
+
+ trace_assign_type(event, entry);
+ record = &event->event_data;
+ if (entry->type != TRACE_SKB_SOURCE)
+ return TRACE_TYPE_UNHANDLED;
+
+ ret = trace_seq_printf(s, " %d %d %d %s %d %d %d\n",
+ record->pid,
+ record->anid,
+ record->cnid,
+ record->ifname,
+ record->rx_queue,
+ record->ccpu,
+ record->len);
+
+ if (!ret)
+ return TRACE_TYPE_PARTIAL_LINE;
+
+ return TRACE_TYPE_HANDLED;
+}
+
+static void skb_source_print_header(struct seq_file *s)
+{
+ seq_puts(s, "# PID ANID CNID IFC RXQ CCPU LEN\n");
+ seq_puts(s, "# | | | | | | |\n");
+}
+
+static struct tracer skb_source_tracer __read_mostly =
+{
+ .name = "skb_sources",
+ .init = skb_source_trace_init,
+ .start = start_skb_source_trace,
+ .stop = stop_skb_source_trace,
+ .reset = skb_source_trace_reset,
+ .print_line = skb_source_print_line,
+ .print_header = skb_source_print_header,
+};
+
+static int init_skb_source_trace(void)
+{
+ return register_tracer(&skb_source_tracer);
+}
+device_initcall(init_skb_source_trace);
diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c
index fe649081fbd..a1f16303703 100644
--- a/net/8021q/vlan.c
+++ b/net/8021q/vlan.c
@@ -225,12 +225,6 @@ int vlan_check_real_dev(struct net_device *real_dev, u16 vlan_id)
return -EOPNOTSUPP;
}
- /* The real device must be up and operating in order to
- * assosciate a VLAN device with it.
- */
- if (!(real_dev->flags & IFF_UP))
- return -ENETDOWN;
-
if (__find_vlan_dev(real_dev, vlan_id) != NULL)
return -EEXIST;
@@ -468,6 +462,19 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event,
}
break;
+ case NETDEV_CHANGEMTU:
+ for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {
+ vlandev = vlan_group_get_device(grp, i);
+ if (!vlandev)
+ continue;
+
+ if (vlandev->mtu <= dev->mtu)
+ continue;
+
+ dev_set_mtu(vlandev, dev->mtu);
+ }
+ break;
+
case NETDEV_FEAT_CHANGE:
/* Propagate device features to underlying device */
for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {
diff --git a/net/8021q/vlanproc.c b/net/8021q/vlanproc.c
index b55a091a33d..6262c335f3c 100644
--- a/net/8021q/vlanproc.c
+++ b/net/8021q/vlanproc.c
@@ -107,7 +107,7 @@ static const struct file_operations vlandev_fops = {
*/
/* Strings */
-static const char *vlan_name_type_str[VLAN_NAME_TYPE_HIGHEST] = {
+static const char *const vlan_name_type_str[VLAN_NAME_TYPE_HIGHEST] = {
[VLAN_NAME_TYPE_RAW_PLUS_VID] = "VLAN_NAME_TYPE_RAW_PLUS_VID",
[VLAN_NAME_TYPE_PLUS_VID_NO_PAD] = "VLAN_NAME_TYPE_PLUS_VID_NO_PAD",
[VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD] = "VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD",
diff --git a/net/Kconfig b/net/Kconfig
index 7051b971067..041c35edb76 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -23,6 +23,26 @@ menuconfig NET
if NET
+config WANT_COMPAT_NETLINK_MESSAGES
+ bool
+ help
+ This option can be selected by other options that need compat
+ netlink messages.
+
+config COMPAT_NETLINK_MESSAGES
+ def_bool y
+ depends on COMPAT
+ depends on WIRELESS_EXT || WANT_COMPAT_NETLINK_MESSAGES
+ help
+ This option makes it possible to send different netlink messages
+ to tasks depending on whether the task is a compat task or not. To
+ achieve this, you need to set skb_shinfo(skb)->frag_list to the
+ compat skb before sending the skb, the netlink code will sort out
+ which message to actually pass to the task.
+
+ Newly written code should NEVER need this option but do
+ compat-independent messages instead!
+
menu "Networking options"
source "net/packet/Kconfig"
diff --git a/net/Makefile b/net/Makefile
index ba324aefda7..1542e7268a7 100644
--- a/net/Makefile
+++ b/net/Makefile
@@ -24,7 +24,6 @@ obj-y += ipv6/
endif
obj-$(CONFIG_PACKET) += packet/
obj-$(CONFIG_NET_KEY) += key/
-obj-$(CONFIG_NET_SCHED) += sched/
obj-$(CONFIG_BRIDGE) += bridge/
obj-$(CONFIG_NET_DSA) += dsa/
obj-$(CONFIG_IPX) += ipx/
diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c
index 875eda5dbad..0d42d5da50a 100644
--- a/net/appletalk/ddp.c
+++ b/net/appletalk/ddp.c
@@ -1400,7 +1400,7 @@ static int atalk_rcv(struct sk_buff *skb, struct net_device *dev,
__u16 len_hops;
if (!net_eq(dev_net(dev), &init_net))
- goto freeit;
+ goto drop;
/* Don't mangle buffer if shared */
if (!(skb = skb_share_check(skb, GFP_ATOMIC)))
@@ -1408,7 +1408,7 @@ static int atalk_rcv(struct sk_buff *skb, struct net_device *dev,
/* Size check and make sure header is contiguous */
if (!pskb_may_pull(skb, sizeof(*ddp)))
- goto freeit;
+ goto drop;
ddp = ddp_hdr(skb);
@@ -1426,7 +1426,7 @@ static int atalk_rcv(struct sk_buff *skb, struct net_device *dev,
if (skb->len < sizeof(*ddp) || skb->len < (len_hops & 1023)) {
pr_debug("AppleTalk: dropping corrupted frame (deh_len=%u, "
"skb->len=%u)\n", len_hops & 1023, skb->len);
- goto freeit;
+ goto drop;
}
/*
@@ -1436,7 +1436,7 @@ static int atalk_rcv(struct sk_buff *skb, struct net_device *dev,
if (ddp->deh_sum &&
atalk_checksum(skb, len_hops & 1023) != ddp->deh_sum)
/* Not a valid AppleTalk frame - dustbin time */
- goto freeit;
+ goto drop;
/* Check the packet is aimed at us */
if (!ddp->deh_dnet) /* Net 0 is 'this network' */
@@ -1449,7 +1449,7 @@ static int atalk_rcv(struct sk_buff *skb, struct net_device *dev,
* AppleTalk iface
*/
atalk_route_packet(skb, dev, ddp, len_hops, origlen);
- goto out;
+ return NET_RX_SUCCESS;
}
/* if IP over DDP is not selected this code will be optimized out */
@@ -1465,18 +1465,21 @@ static int atalk_rcv(struct sk_buff *skb, struct net_device *dev,
sock = atalk_search_socket(&tosat, atif);
if (!sock) /* But not one of our sockets */
- goto freeit;
+ goto drop;
/* Queue packet (standard) */
skb->sk = sock;
if (sock_queue_rcv_skb(sock, skb) < 0)
- goto freeit;
-out:
- return 0;
-freeit:
+ goto drop;
+
+ return NET_RX_SUCCESS;
+
+drop:
kfree_skb(skb);
- goto out;
+out:
+ return NET_RX_DROP;
+
}
/*
diff --git a/net/atm/br2684.c b/net/atm/br2684.c
index 2912665fc58..848af113ba2 100644
--- a/net/atm/br2684.c
+++ b/net/atm/br2684.c
@@ -238,7 +238,7 @@ static int br2684_start_xmit(struct sk_buff *skb, struct net_device *dev)
/* netif_stop_queue(dev); */
dev_kfree_skb(skb);
read_unlock(&devs_lock);
- return 0;
+ return NETDEV_TX_OK;
}
if (!br2684_xmit_vcc(skb, dev, brvcc)) {
/*
@@ -252,7 +252,7 @@ static int br2684_start_xmit(struct sk_buff *skb, struct net_device *dev)
dev->stats.tx_fifo_errors++;
}
read_unlock(&devs_lock);
- return 0;
+ return NETDEV_TX_OK;
}
/*
diff --git a/net/atm/clip.c b/net/atm/clip.c
index e65a3b1477f..64910bb8608 100644
--- a/net/atm/clip.c
+++ b/net/atm/clip.c
@@ -373,7 +373,7 @@ static int clip_start_xmit(struct sk_buff *skb, struct net_device *dev)
printk(KERN_ERR "clip_start_xmit: skb_dst(skb) == NULL\n");
dev_kfree_skb(skb);
dev->stats.tx_dropped++;
- return 0;
+ return NETDEV_TX_OK;
}
if (!skb_dst(skb)->neighbour) {
#if 0
@@ -387,7 +387,7 @@ static int clip_start_xmit(struct sk_buff *skb, struct net_device *dev)
printk(KERN_ERR "clip_start_xmit: NO NEIGHBOUR !\n");
dev_kfree_skb(skb);
dev->stats.tx_dropped++;
- return 0;
+ return NETDEV_TX_OK;
}
entry = NEIGH2ENTRY(skb_dst(skb)->neighbour);
if (!entry->vccs) {
@@ -402,7 +402,7 @@ static int clip_start_xmit(struct sk_buff *skb, struct net_device *dev)
dev_kfree_skb(skb);
dev->stats.tx_dropped++;
}
- return 0;
+ return NETDEV_TX_OK;
}
pr_debug("neigh %p, vccs %p\n", entry, entry->vccs);
ATM_SKB(skb)->vcc = vcc = entry->vccs->vcc;
@@ -421,14 +421,14 @@ static int clip_start_xmit(struct sk_buff *skb, struct net_device *dev)
old = xchg(&entry->vccs->xoff, 1); /* assume XOFF ... */
if (old) {
printk(KERN_WARNING "clip_start_xmit: XOFF->XOFF transition\n");
- return 0;
+ return NETDEV_TX_OK;
}
dev->stats.tx_packets++;
dev->stats.tx_bytes += skb->len;
vcc->send(vcc, skb);
if (atm_may_send(vcc, 0)) {
entry->vccs->xoff = 0;
- return 0;
+ return NETDEV_TX_OK;
}
spin_lock_irqsave(&clip_priv->xoff_lock, flags);
netif_stop_queue(dev); /* XOFF -> throttle immediately */
@@ -440,7 +440,7 @@ static int clip_start_xmit(struct sk_buff *skb, struct net_device *dev)
of the brief netif_stop_queue. If this isn't true or if it
changes, use netif_wake_queue instead. */
spin_unlock_irqrestore(&clip_priv->xoff_lock, flags);
- return 0;
+ return NETDEV_TX_OK;
}
static int clip_mkip(struct atm_vcc *vcc, int timeout)
diff --git a/net/atm/lec.c b/net/atm/lec.c
index ff2e594dca9..8e723c2654c 100644
--- a/net/atm/lec.c
+++ b/net/atm/lec.c
@@ -289,7 +289,7 @@ static int lec_start_xmit(struct sk_buff *skb, struct net_device *dev)
skb2 = skb_realloc_headroom(skb, LEC_HEADER_LEN);
kfree_skb(skb);
if (skb2 == NULL)
- return 0;
+ return NETDEV_TX_OK;
skb = skb2;
}
skb_push(skb, 2);
@@ -307,7 +307,7 @@ static int lec_start_xmit(struct sk_buff *skb, struct net_device *dev)
skb2 = skb_realloc_headroom(skb, LEC_HEADER_LEN);
kfree_skb(skb);
if (skb2 == NULL)
- return 0;
+ return NETDEV_TX_OK;
skb = skb2;
}
#endif
@@ -345,7 +345,7 @@ static int lec_start_xmit(struct sk_buff *skb, struct net_device *dev)
dev_kfree_skb(skb);
if (skb2 == NULL) {
dev->stats.tx_dropped++;
- return 0;
+ return NETDEV_TX_OK;
}
skb = skb2;
}
@@ -416,7 +416,7 @@ out:
if (entry)
lec_arp_put(entry);
dev->trans_start = jiffies;
- return 0;
+ return NETDEV_TX_OK;
}
/* The inverse routine to net_open(). */
@@ -935,9 +935,9 @@ static int lecd_attach(struct atm_vcc *vcc, int arg)
}
#ifdef CONFIG_PROC_FS
-static char *lec_arp_get_status_string(unsigned char status)
+static const char *lec_arp_get_status_string(unsigned char status)
{
- static char *lec_arp_status_string[] = {
+ static const char *const lec_arp_status_string[] = {
"ESI_UNKNOWN ",
"ESI_ARP_PENDING ",
"ESI_VC_PENDING ",
@@ -1121,7 +1121,8 @@ static void *lec_seq_next(struct seq_file *seq, void *v, loff_t *pos)
static int lec_seq_show(struct seq_file *seq, void *v)
{
- static char lec_banner[] = "Itf MAC ATM destination"
+ static const char lec_banner[] =
+ "Itf MAC ATM destination"
" Status Flags "
"VPI/VCI Recv VPI/VCI\n";
@@ -1505,7 +1506,7 @@ lec_arp_remove(struct lec_priv *priv, struct lec_arp_table *to_remove)
}
#if DEBUG_ARP_TABLE
-static char *get_status_string(unsigned char st)
+static const char *get_status_string(unsigned char st)
{
switch (st) {
case ESI_UNKNOWN:
diff --git a/net/atm/mpc.c b/net/atm/mpc.c
index e5bf11453a1..1ac4b94bf62 100644
--- a/net/atm/mpc.c
+++ b/net/atm/mpc.c
@@ -554,7 +554,7 @@ static int mpc_send_packet(struct sk_buff *skb, struct net_device *dev)
while (i < mpc->number_of_mps_macs) {
if (!compare_ether_addr(eth->h_dest, (mpc->mps_macs + i*ETH_ALEN)))
if ( send_via_shortcut(skb, mpc) == 0 ) /* try shortcut */
- return 0; /* success! */
+ return NETDEV_TX_OK; /* success! */
i++;
}
diff --git a/net/atm/proc.c b/net/atm/proc.c
index 38de5ff61ec..ab8419a324b 100644
--- a/net/atm/proc.c
+++ b/net/atm/proc.c
@@ -151,8 +151,9 @@ static void *vcc_seq_next(struct seq_file *seq, void *v, loff_t *pos)
static void pvc_info(struct seq_file *seq, struct atm_vcc *vcc)
{
- static const char *class_name[] = { "off","UBR","CBR","VBR","ABR" };
- static const char *aal_name[] = {
+ static const char *const class_name[] =
+ {"off","UBR","CBR","VBR","ABR"};
+ static const char *const aal_name[] = {
"---", "1", "2", "3/4", /* 0- 3 */
"???", "5", "???", "???", /* 4- 7 */
"???", "???", "???", "???", /* 8-11 */
@@ -178,7 +179,7 @@ static void pvc_info(struct seq_file *seq, struct atm_vcc *vcc)
static const char *vcc_state(struct atm_vcc *vcc)
{
- static const char *map[] = { ATM_VS2TXT_MAP };
+ static const char *const map[] = { ATM_VS2TXT_MAP };
return map[ATM_VF2VS(vcc->flags)];
}
@@ -335,7 +336,7 @@ static const struct file_operations vcc_seq_fops = {
static int svc_seq_show(struct seq_file *seq, void *v)
{
- static char atm_svc_banner[] =
+ static const char atm_svc_banner[] =
"Itf VPI VCI State Remote\n";
if (v == SEQ_START_TOKEN)
diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c
index 0250e060015..8cfb5a84984 100644
--- a/net/bluetooth/af_bluetooth.c
+++ b/net/bluetooth/af_bluetooth.c
@@ -49,7 +49,7 @@ static struct net_proto_family *bt_proto[BT_MAX_PROTO];
static DEFINE_RWLOCK(bt_proto_lock);
static struct lock_class_key bt_lock_key[BT_MAX_PROTO];
-static const char *bt_key_strings[BT_MAX_PROTO] = {
+static const char *const bt_key_strings[BT_MAX_PROTO] = {
"sk_lock-AF_BLUETOOTH-BTPROTO_L2CAP",
"sk_lock-AF_BLUETOOTH-BTPROTO_HCI",
"sk_lock-AF_BLUETOOTH-BTPROTO_SCO",
@@ -61,7 +61,7 @@ static const char *bt_key_strings[BT_MAX_PROTO] = {
};
static struct lock_class_key bt_slock_key[BT_MAX_PROTO];
-static const char *bt_slock_key_strings[BT_MAX_PROTO] = {
+static const char *const bt_slock_key_strings[BT_MAX_PROTO] = {
"slock-AF_BLUETOOTH-BTPROTO_L2CAP",
"slock-AF_BLUETOOTH-BTPROTO_HCI",
"slock-AF_BLUETOOTH-BTPROTO_SCO",
diff --git a/net/bluetooth/bnep/netdev.c b/net/bluetooth/bnep/netdev.c
index d7a0e9722de..9c42990126a 100644
--- a/net/bluetooth/bnep/netdev.c
+++ b/net/bluetooth/bnep/netdev.c
@@ -175,14 +175,14 @@ static int bnep_net_xmit(struct sk_buff *skb, struct net_device *dev)
#ifdef CONFIG_BT_BNEP_MC_FILTER
if (bnep_net_mc_filter(skb, s)) {
kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
}
#endif
#ifdef CONFIG_BT_BNEP_PROTO_FILTER
if (bnep_net_proto_filter(skb, s)) {
kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
}
#endif
@@ -203,7 +203,7 @@ static int bnep_net_xmit(struct sk_buff *skb, struct net_device *dev)
netif_stop_queue(dev);
}
- return 0;
+ return NETDEV_TX_OK;
}
static const struct net_device_ops bnep_netdev_ops = {
diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c
index 18538d7460d..15d43ba86b5 100644
--- a/net/bridge/br_device.c
+++ b/net/bridge/br_device.c
@@ -39,7 +39,7 @@ int br_dev_xmit(struct sk_buff *skb, struct net_device *dev)
else
br_flood_deliver(br, skb);
- return 0;
+ return NETDEV_TX_OK;
}
static int br_dev_open(struct net_device *dev)
diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c
index d2c27c808d3..bc1704ac6cd 100644
--- a/net/bridge/br_forward.c
+++ b/net/bridge/br_forward.c
@@ -22,7 +22,8 @@
static inline int should_deliver(const struct net_bridge_port *p,
const struct sk_buff *skb)
{
- return (skb->dev != p->dev && p->state == BR_STATE_FORWARDING);
+ return (((p->flags & BR_HAIRPIN_MODE) || skb->dev != p->dev) &&
+ p->state == BR_STATE_FORWARDING);
}
static inline unsigned packet_length(const struct sk_buff *skb)
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c
index eb404dc3ed6..e486f1fc363 100644
--- a/net/bridge/br_if.c
+++ b/net/bridge/br_if.c
@@ -256,6 +256,7 @@ static struct net_bridge_port *new_nbp(struct net_bridge *br,
p->path_cost = port_cost(dev);
p->priority = 0x8000 >> BR_PORT_BITS;
p->port_no = index;
+ p->flags = 0;
br_init_port(p);
p->state = BR_STATE_DISABLED;
br_stp_port_timer_init(p);
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c
index d22f611e400..4fde7425077 100644
--- a/net/bridge/br_netfilter.c
+++ b/net/bridge/br_netfilter.c
@@ -905,46 +905,62 @@ static unsigned int ip_sabotage_in(unsigned int hook, struct sk_buff *skb,
* For br_nf_post_routing, we need (prio = NF_BR_PRI_LAST), because
* ip_refrag() can return NF_STOLEN. */
static struct nf_hook_ops br_nf_ops[] __read_mostly = {
- { .hook = br_nf_pre_routing,
- .owner = THIS_MODULE,
- .pf = PF_BRIDGE,
- .hooknum = NF_BR_PRE_ROUTING,
- .priority = NF_BR_PRI_BRNF, },
- { .hook = br_nf_local_in,
- .owner = THIS_MODULE,
- .pf = PF_BRIDGE,
- .hooknum = NF_BR_LOCAL_IN,
- .priority = NF_BR_PRI_BRNF, },
- { .hook = br_nf_forward_ip,
- .owner = THIS_MODULE,
- .pf = PF_BRIDGE,
- .hooknum = NF_BR_FORWARD,
- .priority = NF_BR_PRI_BRNF - 1, },
- { .hook = br_nf_forward_arp,
- .owner = THIS_MODULE,
- .pf = PF_BRIDGE,
- .hooknum = NF_BR_FORWARD,
- .priority = NF_BR_PRI_BRNF, },
- { .hook = br_nf_local_out,
- .owner = THIS_MODULE,
- .pf = PF_BRIDGE,
- .hooknum = NF_BR_LOCAL_OUT,
- .priority = NF_BR_PRI_FIRST, },
- { .hook = br_nf_post_routing,
- .owner = THIS_MODULE,
- .pf = PF_BRIDGE,
- .hooknum = NF_BR_POST_ROUTING,
- .priority = NF_BR_PRI_LAST, },
- { .hook = ip_sabotage_in,
- .owner = THIS_MODULE,
- .pf = PF_INET,
- .hooknum = NF_INET_PRE_ROUTING,
- .priority = NF_IP_PRI_FIRST, },
- { .hook = ip_sabotage_in,
- .owner = THIS_MODULE,
- .pf = PF_INET6,
- .hooknum = NF_INET_PRE_ROUTING,
- .priority = NF_IP6_PRI_FIRST, },
+ {
+ .hook = br_nf_pre_routing,
+ .owner = THIS_MODULE,
+ .pf = PF_BRIDGE,
+ .hooknum = NF_BR_PRE_ROUTING,
+ .priority = NF_BR_PRI_BRNF,
+ },
+ {
+ .hook = br_nf_local_in,
+ .owner = THIS_MODULE,
+ .pf = PF_BRIDGE,
+ .hooknum = NF_BR_LOCAL_IN,
+ .priority = NF_BR_PRI_BRNF,
+ },
+ {
+ .hook = br_nf_forward_ip,
+ .owner = THIS_MODULE,
+ .pf = PF_BRIDGE,
+ .hooknum = NF_BR_FORWARD,
+ .priority = NF_BR_PRI_BRNF - 1,
+ },
+ {
+ .hook = br_nf_forward_arp,
+ .owner = THIS_MODULE,
+ .pf = PF_BRIDGE,
+ .hooknum = NF_BR_FORWARD,
+ .priority = NF_BR_PRI_BRNF,
+ },
+ {
+ .hook = br_nf_local_out,
+ .owner = THIS_MODULE,
+ .pf = PF_BRIDGE,
+ .hooknum = NF_BR_LOCAL_OUT,
+ .priority = NF_BR_PRI_FIRST,
+ },
+ {
+ .hook = br_nf_post_routing,
+ .owner = THIS_MODULE,
+ .pf = PF_BRIDGE,
+ .hooknum = NF_BR_POST_ROUTING,
+ .priority = NF_BR_PRI_LAST,
+ },
+ {
+ .hook = ip_sabotage_in,
+ .owner = THIS_MODULE,
+ .pf = PF_INET,
+ .hooknum = NF_INET_PRE_ROUTING,
+ .priority = NF_IP_PRI_FIRST,
+ },
+ {
+ .hook = ip_sabotage_in,
+ .owner = THIS_MODULE,
+ .pf = PF_INET6,
+ .hooknum = NF_INET_PRE_ROUTING,
+ .priority = NF_IP6_PRI_FIRST,
+ },
};
#ifdef CONFIG_SYSCTL
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index d5b5537272b..8319247dad5 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -81,6 +81,9 @@ struct net_bridge_port
struct timer_list message_age_timer;
struct kobject kobj;
struct rcu_head rcu;
+
+ unsigned long flags;
+#define BR_HAIRPIN_MODE 0x00000001
};
struct net_bridge
diff --git a/net/bridge/br_stp.c b/net/bridge/br_stp.c
index 0660515f399..fd3f8d6c099 100644
--- a/net/bridge/br_stp.c
+++ b/net/bridge/br_stp.c
@@ -21,7 +21,7 @@
*/
#define MESSAGE_AGE_INCR ((HZ < 256) ? 1 : (HZ/256))
-static const char *br_port_state_names[] = {
+static const char *const br_port_state_names[] = {
[BR_STATE_DISABLED] = "disabled",
[BR_STATE_LISTENING] = "listening",
[BR_STATE_LEARNING] = "learning",
diff --git a/net/bridge/br_sysfs_if.c b/net/bridge/br_sysfs_if.c
index 4a3cdf8f381..820643a3ba9 100644
--- a/net/bridge/br_sysfs_if.c
+++ b/net/bridge/br_sysfs_if.c
@@ -143,6 +143,22 @@ static ssize_t store_flush(struct net_bridge_port *p, unsigned long v)
}
static BRPORT_ATTR(flush, S_IWUSR, NULL, store_flush);
+static ssize_t show_hairpin_mode(struct net_bridge_port *p, char *buf)
+{
+ int hairpin_mode = (p->flags & BR_HAIRPIN_MODE) ? 1 : 0;
+ return sprintf(buf, "%d\n", hairpin_mode);
+}
+static ssize_t store_hairpin_mode(struct net_bridge_port *p, unsigned long v)
+{
+ if (v)
+ p->flags |= BR_HAIRPIN_MODE;
+ else
+ p->flags &= ~BR_HAIRPIN_MODE;
+ return 0;
+}
+static BRPORT_ATTR(hairpin_mode, S_IRUGO | S_IWUSR,
+ show_hairpin_mode, store_hairpin_mode);
+
static struct brport_attribute *brport_attrs[] = {
&brport_attr_path_cost,
&brport_attr_priority,
@@ -159,6 +175,7 @@ static struct brport_attribute *brport_attrs[] = {
&brport_attr_forward_delay_timer,
&brport_attr_hold_timer,
&brport_attr_flush,
+ &brport_attr_hairpin_mode,
NULL
};
diff --git a/net/compat.c b/net/compat.c
index 8d739053afe..12728b17a22 100644
--- a/net/compat.c
+++ b/net/compat.c
@@ -743,6 +743,18 @@ asmlinkage long compat_sys_recvmsg(int fd, struct compat_msghdr __user *msg, uns
return sys_recvmsg(fd, (struct msghdr __user *)msg, flags | MSG_CMSG_COMPAT);
}
+asmlinkage long compat_sys_recv(int fd, void __user *buf, size_t len, unsigned flags)
+{
+ return sys_recv(fd, buf, len, flags | MSG_CMSG_COMPAT);
+}
+
+asmlinkage long compat_sys_recvfrom(int fd, void __user *buf, size_t len,
+ unsigned flags, struct sockaddr __user *addr,
+ int __user *addrlen)
+{
+ return sys_recvfrom(fd, buf, len, flags | MSG_CMSG_COMPAT, addr, addrlen);
+}
+
asmlinkage long compat_sys_socketcall(int call, u32 __user *args)
{
int ret;
@@ -788,10 +800,11 @@ asmlinkage long compat_sys_socketcall(int call, u32 __user *args)
ret = sys_sendto(a0, compat_ptr(a1), a[2], a[3], compat_ptr(a[4]), a[5]);
break;
case SYS_RECV:
- ret = sys_recv(a0, compat_ptr(a1), a[2], a[3]);
+ ret = compat_sys_recv(a0, compat_ptr(a1), a[2], a[3]);
break;
case SYS_RECVFROM:
- ret = sys_recvfrom(a0, compat_ptr(a1), a[2], a[3], compat_ptr(a[4]), compat_ptr(a[5]));
+ ret = compat_sys_recvfrom(a0, compat_ptr(a1), a[2], a[3],
+ compat_ptr(a[4]), compat_ptr(a[5]));
break;
case SYS_SHUTDOWN:
ret = sys_shutdown(a0,a1);
diff --git a/net/core/datagram.c b/net/core/datagram.c
index b0fe69211ee..1c6cf3a1a4f 100644
--- a/net/core/datagram.c
+++ b/net/core/datagram.c
@@ -55,6 +55,7 @@
#include <net/checksum.h>
#include <net/sock.h>
#include <net/tcp_states.h>
+#include <trace/events/skb.h>
/*
* Is a socket 'connection oriented' ?
@@ -284,6 +285,8 @@ int skb_copy_datagram_iovec(const struct sk_buff *skb, int offset,
int i, copy = start - offset;
struct sk_buff *frag_iter;
+ trace_skb_copy_datagram_iovec(skb, len);
+
/* Copy header. */
if (copy > 0) {
if (copy > len)
diff --git a/net/core/dev.c b/net/core/dev.c
index 6a94475aee8..09fb03fa1ae 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -272,7 +272,7 @@ static const unsigned short netdev_lock_type[] =
ARPHRD_PHONET_PIPE, ARPHRD_IEEE802154, ARPHRD_IEEE802154_PHY,
ARPHRD_VOID, ARPHRD_NONE};
-static const char *netdev_lock_name[] =
+static const char *const netdev_lock_name[] =
{"_xmit_NETROM", "_xmit_ETHER", "_xmit_EETHER", "_xmit_AX25",
"_xmit_PRONET", "_xmit_CHAOS", "_xmit_IEEE802", "_xmit_ARCNET",
"_xmit_APPLETLK", "_xmit_DLCI", "_xmit_ATM", "_xmit_METRICOM",
@@ -1704,7 +1704,7 @@ int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
skb_dst_drop(skb);
rc = ops->ndo_start_xmit(skb, dev);
- if (rc == 0)
+ if (rc == NETDEV_TX_OK)
txq_trans_update(txq);
/*
* TODO: if skb_orphan() was called by
@@ -1730,7 +1730,7 @@ gso:
skb->next = nskb->next;
nskb->next = NULL;
rc = ops->ndo_start_xmit(nskb, dev);
- if (unlikely(rc)) {
+ if (unlikely(rc != NETDEV_TX_OK)) {
nskb->next = skb->next;
skb->next = nskb;
return rc;
@@ -1744,7 +1744,7 @@ gso:
out_kfree_skb:
kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
}
static u32 skb_tx_hashrnd;
@@ -1786,6 +1786,40 @@ static struct netdev_queue *dev_pick_tx(struct net_device *dev,
return netdev_get_tx_queue(dev, queue_index);
}
+static inline int __dev_xmit_skb(struct sk_buff *skb, struct Qdisc *q,
+ struct net_device *dev,
+ struct netdev_queue *txq)
+{
+ spinlock_t *root_lock = qdisc_lock(q);
+ int rc;
+
+ spin_lock(root_lock);
+ if (unlikely(test_bit(__QDISC_STATE_DEACTIVATED, &q->state))) {
+ kfree_skb(skb);
+ rc = NET_XMIT_DROP;
+ } else if ((q->flags & TCQ_F_CAN_BYPASS) && !qdisc_qlen(q) &&
+ !test_and_set_bit(__QDISC_STATE_RUNNING, &q->state)) {
+ /*
+ * This is a work-conserving queue; there are no old skbs
+ * waiting to be sent out; and the qdisc is not running -
+ * xmit the skb directly.
+ */
+ __qdisc_update_bstats(q, skb->len);
+ if (sch_direct_xmit(skb, q, dev, txq, root_lock))
+ __qdisc_run(q);
+ else
+ clear_bit(__QDISC_STATE_RUNNING, &q->state);
+
+ rc = NET_XMIT_SUCCESS;
+ } else {
+ rc = qdisc_enqueue_root(skb, q);
+ qdisc_run(q);
+ }
+ spin_unlock(root_lock);
+
+ return rc;
+}
+
/**
* dev_queue_xmit - transmit a buffer
* @skb: buffer to transmit
@@ -1859,19 +1893,7 @@ gso:
skb->tc_verd = SET_TC_AT(skb->tc_verd,AT_EGRESS);
#endif
if (q->enqueue) {
- spinlock_t *root_lock = qdisc_lock(q);
-
- spin_lock(root_lock);
-
- if (unlikely(test_bit(__QDISC_STATE_DEACTIVATED, &q->state))) {
- kfree_skb(skb);
- rc = NET_XMIT_DROP;
- } else {
- rc = qdisc_enqueue_root(skb, q);
- qdisc_run(q);
- }
- spin_unlock(root_lock);
-
+ rc = __dev_xmit_skb(skb, q, dev, txq);
goto out;
}
@@ -3927,6 +3949,7 @@ int __dev_addr_sync(struct dev_addr_list **to, int *to_count,
}
return err;
}
+EXPORT_SYMBOL_GPL(__dev_addr_sync);
void __dev_addr_unsync(struct dev_addr_list **to, int *to_count,
struct dev_addr_list **from, int *from_count)
@@ -3946,6 +3969,7 @@ void __dev_addr_unsync(struct dev_addr_list **to, int *to_count,
da = next;
}
}
+EXPORT_SYMBOL_GPL(__dev_addr_unsync);
/**
* dev_unicast_sync - Synchronize device's unicast list to another device
@@ -5347,6 +5371,7 @@ int dev_change_net_namespace(struct net_device *dev, struct net *net, const char
out:
return err;
}
+EXPORT_SYMBOL_GPL(dev_change_net_namespace);
static int dev_cpu_callback(struct notifier_block *nfb,
unsigned long action,
diff --git a/net/core/ethtool.c b/net/core/ethtool.c
index d9d5160610d..44e571111d3 100644
--- a/net/core/ethtool.c
+++ b/net/core/ethtool.c
@@ -30,10 +30,17 @@ u32 ethtool_op_get_link(struct net_device *dev)
return netif_carrier_ok(dev) ? 1 : 0;
}
+u32 ethtool_op_get_rx_csum(struct net_device *dev)
+{
+ return (dev->features & NETIF_F_ALL_CSUM) != 0;
+}
+EXPORT_SYMBOL(ethtool_op_get_rx_csum);
+
u32 ethtool_op_get_tx_csum(struct net_device *dev)
{
return (dev->features & NETIF_F_ALL_CSUM) != 0;
}
+EXPORT_SYMBOL(ethtool_op_get_tx_csum);
int ethtool_op_set_tx_csum(struct net_device *dev, u32 data)
{
@@ -1004,7 +1011,9 @@ int dev_ethtool(struct net *net, struct ifreq *ifr)
break;
case ETHTOOL_GRXCSUM:
rc = ethtool_get_value(dev, useraddr, ethcmd,
- dev->ethtool_ops->get_rx_csum);
+ (dev->ethtool_ops->get_rx_csum ?
+ dev->ethtool_ops->get_rx_csum :
+ ethtool_op_get_rx_csum));
break;
case ETHTOOL_SRXCSUM:
rc = ethtool_set_rx_csum(dev, useraddr);
@@ -1068,7 +1077,9 @@ int dev_ethtool(struct net *net, struct ifreq *ifr)
break;
case ETHTOOL_GFLAGS:
rc = ethtool_get_value(dev, useraddr, ethcmd,
- dev->ethtool_ops->get_flags);
+ (dev->ethtool_ops->get_flags ?
+ dev->ethtool_ops->get_flags :
+ ethtool_op_get_flags));
break;
case ETHTOOL_SFLAGS:
rc = ethtool_set_value(dev, useraddr,
@@ -1116,7 +1127,6 @@ int dev_ethtool(struct net *net, struct ifreq *ifr)
EXPORT_SYMBOL(ethtool_op_get_link);
EXPORT_SYMBOL(ethtool_op_get_sg);
EXPORT_SYMBOL(ethtool_op_get_tso);
-EXPORT_SYMBOL(ethtool_op_get_tx_csum);
EXPORT_SYMBOL(ethtool_op_set_sg);
EXPORT_SYMBOL(ethtool_op_set_tso);
EXPORT_SYMBOL(ethtool_op_set_tx_csum);
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index 163b4f5b036..e587e681969 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -692,75 +692,74 @@ static void neigh_connect(struct neighbour *neigh)
hh->hh_output = neigh->ops->hh_output;
}
-static void neigh_periodic_timer(unsigned long arg)
+static void neigh_periodic_work(struct work_struct *work)
{
- struct neigh_table *tbl = (struct neigh_table *)arg;
+ struct neigh_table *tbl = container_of(work, struct neigh_table, gc_work.work);
struct neighbour *n, **np;
- unsigned long expire, now = jiffies;
+ unsigned int i;
NEIGH_CACHE_STAT_INC(tbl, periodic_gc_runs);
- write_lock(&tbl->lock);
+ write_lock_bh(&tbl->lock);
/*
* periodically recompute ReachableTime from random function
*/
- if (time_after(now, tbl->last_rand + 300 * HZ)) {
+ if (time_after(jiffies, tbl->last_rand + 300 * HZ)) {
struct neigh_parms *p;
- tbl->last_rand = now;
+ tbl->last_rand = jiffies;
for (p = &tbl->parms; p; p = p->next)
p->reachable_time =
neigh_rand_reach_time(p->base_reachable_time);
}
- np = &tbl->hash_buckets[tbl->hash_chain_gc];
- tbl->hash_chain_gc = ((tbl->hash_chain_gc + 1) & tbl->hash_mask);
+ for (i = 0 ; i <= tbl->hash_mask; i++) {
+ np = &tbl->hash_buckets[i];
- while ((n = *np) != NULL) {
- unsigned int state;
+ while ((n = *np) != NULL) {
+ unsigned int state;
- write_lock(&n->lock);
+ write_lock(&n->lock);
- state = n->nud_state;
- if (state & (NUD_PERMANENT | NUD_IN_TIMER)) {
- write_unlock(&n->lock);
- goto next_elt;
- }
+ state = n->nud_state;
+ if (state & (NUD_PERMANENT | NUD_IN_TIMER)) {
+ write_unlock(&n->lock);
+ goto next_elt;
+ }
- if (time_before(n->used, n->confirmed))
- n->used = n->confirmed;
+ if (time_before(n->used, n->confirmed))
+ n->used = n->confirmed;
- if (atomic_read(&n->refcnt) == 1 &&
- (state == NUD_FAILED ||
- time_after(now, n->used + n->parms->gc_staletime))) {
- *np = n->next;
- n->dead = 1;
+ if (atomic_read(&n->refcnt) == 1 &&
+ (state == NUD_FAILED ||
+ time_after(jiffies, n->used + n->parms->gc_staletime))) {
+ *np = n->next;
+ n->dead = 1;
+ write_unlock(&n->lock);
+ neigh_cleanup_and_release(n);
+ continue;
+ }
write_unlock(&n->lock);
- neigh_cleanup_and_release(n);
- continue;
- }
- write_unlock(&n->lock);
next_elt:
- np = &n->next;
+ np = &n->next;
+ }
+ /*
+ * It's fine to release lock here, even if hash table
+ * grows while we are preempted.
+ */
+ write_unlock_bh(&tbl->lock);
+ cond_resched();
+ write_lock_bh(&tbl->lock);
}
-
/* Cycle through all hash buckets every base_reachable_time/2 ticks.
* ARP entry timeouts range from 1/2 base_reachable_time to 3/2
* base_reachable_time.
*/
- expire = tbl->parms.base_reachable_time >> 1;
- expire /= (tbl->hash_mask + 1);
- if (!expire)
- expire = 1;
-
- if (expire>HZ)
- mod_timer(&tbl->gc_timer, round_jiffies(now + expire));
- else
- mod_timer(&tbl->gc_timer, now + expire);
-
- write_unlock(&tbl->lock);
+ schedule_delayed_work(&tbl->gc_work,
+ tbl->parms.base_reachable_time >> 1);
+ write_unlock_bh(&tbl->lock);
}
static __inline__ int neigh_max_probes(struct neighbour *n)
@@ -1316,7 +1315,7 @@ void pneigh_enqueue(struct neigh_table *tbl, struct neigh_parms *p,
}
EXPORT_SYMBOL(pneigh_enqueue);
-static inline struct neigh_parms *lookup_neigh_params(struct neigh_table *tbl,
+static inline struct neigh_parms *lookup_neigh_parms(struct neigh_table *tbl,
struct net *net, int ifindex)
{
struct neigh_parms *p;
@@ -1337,7 +1336,7 @@ struct neigh_parms *neigh_parms_alloc(struct net_device *dev,
struct net *net = dev_net(dev);
const struct net_device_ops *ops = dev->netdev_ops;
- ref = lookup_neigh_params(tbl, net, 0);
+ ref = lookup_neigh_parms(tbl, net, 0);
if (!ref)
return NULL;
@@ -1442,10 +1441,8 @@ void neigh_table_init_no_netlink(struct neigh_table *tbl)
get_random_bytes(&tbl->hash_rnd, sizeof(tbl->hash_rnd));
rwlock_init(&tbl->lock);
- setup_timer(&tbl->gc_timer, neigh_periodic_timer, (unsigned long)tbl);
- tbl->gc_timer.expires = now + 1;
- add_timer(&tbl->gc_timer);
-
+ INIT_DELAYED_WORK_DEFERRABLE(&tbl->gc_work, neigh_periodic_work);
+ schedule_delayed_work(&tbl->gc_work, tbl->parms.reachable_time);
setup_timer(&tbl->proxy_timer, neigh_proxy_process, (unsigned long)tbl);
skb_queue_head_init_class(&tbl->proxy_queue,
&neigh_table_proxy_queue_class);
@@ -1482,7 +1479,8 @@ int neigh_table_clear(struct neigh_table *tbl)
struct neigh_table **tp;
/* It is not clean... Fix it to unload IPv6 module safely */
- del_timer_sync(&tbl->gc_timer);
+ cancel_delayed_work(&tbl->gc_work);
+ flush_scheduled_work();
del_timer_sync(&tbl->proxy_timer);
pneigh_queue_purge(&tbl->proxy_queue);
neigh_ifdown(tbl, NULL);
@@ -1752,7 +1750,6 @@ static int neightbl_fill_info(struct sk_buff *skb, struct neigh_table *tbl,
.ndtc_last_rand = jiffies_to_msecs(rand_delta),
.ndtc_hash_rnd = tbl->hash_rnd,
.ndtc_hash_mask = tbl->hash_mask,
- .ndtc_hash_chain_gc = tbl->hash_chain_gc,
.ndtc_proxy_qlen = tbl->proxy_queue.qlen,
};
@@ -1906,7 +1903,7 @@ static int neightbl_set(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
if (tbp[NDTPA_IFINDEX])
ifindex = nla_get_u32(tbp[NDTPA_IFINDEX]);
- p = lookup_neigh_params(tbl, net, ifindex);
+ p = lookup_neigh_parms(tbl, net, ifindex);
if (p == NULL) {
err = -ENOENT;
goto errout_tbl_lock;
diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c
index 3994680c08b..ad91e9e5f47 100644
--- a/net/core/net-sysfs.c
+++ b/net/core/net-sysfs.c
@@ -141,7 +141,7 @@ static ssize_t show_dormant(struct device *dev,
return -EINVAL;
}
-static const char *operstates[] = {
+static const char *const operstates[] = {
"unknown",
"notpresent", /* currently unused */
"down",
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
index 197283072cc..1c1af2756f3 100644
--- a/net/core/net_namespace.c
+++ b/net/core/net_namespace.c
@@ -6,6 +6,8 @@
#include <linux/delay.h>
#include <linux/sched.h>
#include <linux/idr.h>
+#include <linux/rculist.h>
+#include <linux/nsproxy.h>
#include <net/net_namespace.h>
#include <net/netns/generic.h>
@@ -127,7 +129,7 @@ static struct net *net_create(void)
rv = setup_net(net);
if (rv == 0) {
rtnl_lock();
- list_add_tail(&net->list, &net_namespace_list);
+ list_add_tail_rcu(&net->list, &net_namespace_list);
rtnl_unlock();
}
mutex_unlock(&net_mutex);
@@ -156,9 +158,16 @@ static void cleanup_net(struct work_struct *work)
/* Don't let anyone else find us. */
rtnl_lock();
- list_del(&net->list);
+ list_del_rcu(&net->list);
rtnl_unlock();
+ /*
+ * Another CPU might be rcu-iterating the list, wait for it.
+ * This needs to be before calling the exit() notifiers, so
+ * the rcu_barrier() below isn't sufficient alone.
+ */
+ synchronize_rcu();
+
/* Run all of the network namespace exit methods */
list_for_each_entry_reverse(ops, &pernet_list, list) {
if (ops->exit)
@@ -193,6 +202,26 @@ struct net *copy_net_ns(unsigned long flags, struct net *old_net)
}
#endif
+struct net *get_net_ns_by_pid(pid_t pid)
+{
+ struct task_struct *tsk;
+ struct net *net;
+
+ /* Lookup the network namespace */
+ net = ERR_PTR(-ESRCH);
+ rcu_read_lock();
+ tsk = find_task_by_vpid(pid);
+ if (tsk) {
+ struct nsproxy *nsproxy;
+ nsproxy = task_nsproxy(tsk);
+ if (nsproxy)
+ net = get_net(nsproxy->net_ns);
+ }
+ rcu_read_unlock();
+ return net;
+}
+EXPORT_SYMBOL_GPL(get_net_ns_by_pid);
+
static int __init net_ns_init(void)
{
struct net_generic *ng;
@@ -219,7 +248,7 @@ static int __init net_ns_init(void)
panic("Could not setup the initial network namespace");
rtnl_lock();
- list_add_tail(&init_net.list, &net_namespace_list);
+ list_add_tail_rcu(&init_net.list, &net_namespace_list);
rtnl_unlock();
mutex_unlock(&net_mutex);
diff --git a/net/core/netpoll.c b/net/core/netpoll.c
index df30feb2fc7..0ac309154b0 100644
--- a/net/core/netpoll.c
+++ b/net/core/netpoll.c
@@ -9,6 +9,7 @@
* Copyright (C) 2002 Red Hat, Inc.
*/
+#include <linux/moduleparam.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/string.h>
@@ -50,6 +51,9 @@ static atomic_t trapped;
static void zap_completion_queue(void);
static void arp_reply(struct sk_buff *skb);
+static unsigned int carrier_timeout = 4;
+module_param(carrier_timeout, uint, 0644);
+
static void queue_process(struct work_struct *work)
{
struct netpoll_info *npinfo =
@@ -732,7 +736,7 @@ int netpoll_setup(struct netpoll *np)
}
atleast = jiffies + HZ/10;
- atmost = jiffies + 4*HZ;
+ atmost = jiffies + carrier_timeout * HZ;
while (!netif_carrier_ok(ndev)) {
if (time_after(jiffies, atmost)) {
printk(KERN_NOTICE
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index d78030f88bd..b44775f9f2b 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -35,7 +35,6 @@
#include <linux/security.h>
#include <linux/mutex.h>
#include <linux/if_addr.h>
-#include <linux/nsproxy.h>
#include <asm/uaccess.h>
#include <asm/system.h>
@@ -52,6 +51,7 @@
#include <net/pkt_sched.h>
#include <net/fib_rules.h>
#include <net/rtnetlink.h>
+#include <net/net_namespace.h>
struct rtnl_link
{
@@ -725,25 +725,6 @@ static const struct nla_policy ifla_info_policy[IFLA_INFO_MAX+1] = {
[IFLA_INFO_DATA] = { .type = NLA_NESTED },
};
-static struct net *get_net_ns_by_pid(pid_t pid)
-{
- struct task_struct *tsk;
- struct net *net;
-
- /* Lookup the network namespace */
- net = ERR_PTR(-ESRCH);
- rcu_read_lock();
- tsk = find_task_by_vpid(pid);
- if (tsk) {
- struct nsproxy *nsproxy;
- nsproxy = task_nsproxy(tsk);
- if (nsproxy)
- net = get_net(nsproxy->net_ns);
- }
- rcu_read_unlock();
- return net;
-}
-
static int validate_linkmsg(struct net_device *dev, struct nlattr *tb[])
{
if (dev) {
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 9e0597d189b..80a96166df3 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -559,9 +559,6 @@ static void __copy_skb_header(struct sk_buff *new, const struct sk_buff *old)
#endif
#endif
new->vlan_tci = old->vlan_tci;
-#if defined(CONFIG_MAC80211) || defined(CONFIG_MAC80211_MODULE)
- new->do_not_encrypt = old->do_not_encrypt;
-#endif
skb_copy_secmark(new, old);
}
diff --git a/net/core/sock.c b/net/core/sock.c
index bbb25be7ddf..3ac34ea6ec0 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -142,7 +142,7 @@ static struct lock_class_key af_family_slock_keys[AF_MAX];
* strings build-time, so that runtime initialization of socket
* locks is fast):
*/
-static const char *af_family_key_strings[AF_MAX+1] = {
+static const char *const af_family_key_strings[AF_MAX+1] = {
"sk_lock-AF_UNSPEC", "sk_lock-AF_UNIX" , "sk_lock-AF_INET" ,
"sk_lock-AF_AX25" , "sk_lock-AF_IPX" , "sk_lock-AF_APPLETALK",
"sk_lock-AF_NETROM", "sk_lock-AF_BRIDGE" , "sk_lock-AF_ATMPVC" ,
@@ -158,7 +158,7 @@ static const char *af_family_key_strings[AF_MAX+1] = {
"sk_lock-AF_IEEE802154",
"sk_lock-AF_MAX"
};
-static const char *af_family_slock_key_strings[AF_MAX+1] = {
+static const char *const af_family_slock_key_strings[AF_MAX+1] = {
"slock-AF_UNSPEC", "slock-AF_UNIX" , "slock-AF_INET" ,
"slock-AF_AX25" , "slock-AF_IPX" , "slock-AF_APPLETALK",
"slock-AF_NETROM", "slock-AF_BRIDGE" , "slock-AF_ATMPVC" ,
@@ -174,7 +174,7 @@ static const char *af_family_slock_key_strings[AF_MAX+1] = {
"slock-AF_IEEE802154",
"slock-AF_MAX"
};
-static const char *af_family_clock_key_strings[AF_MAX+1] = {
+static const char *const af_family_clock_key_strings[AF_MAX+1] = {
"clock-AF_UNSPEC", "clock-AF_UNIX" , "clock-AF_INET" ,
"clock-AF_AX25" , "clock-AF_IPX" , "clock-AF_APPLETALK",
"clock-AF_NETROM", "clock-AF_BRIDGE" , "clock-AF_ATMPVC" ,
@@ -482,6 +482,8 @@ int sock_setsockopt(struct socket *sock, int level, int optname,
sk->sk_reuse = valbool;
break;
case SO_TYPE:
+ case SO_PROTOCOL:
+ case SO_DOMAIN:
case SO_ERROR:
ret = -ENOPROTOOPT;
break;
@@ -764,6 +766,14 @@ int sock_getsockopt(struct socket *sock, int level, int optname,
v.val = sk->sk_type;
break;
+ case SO_PROTOCOL:
+ v.val = sk->sk_protocol;
+ break;
+
+ case SO_DOMAIN:
+ v.val = sk->sk_family;
+ break;
+
case SO_ERROR:
v.val = -sock_error(sk);
if (v.val == 0)
diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c
index a27b7f4c19c..f596ce149c3 100644
--- a/net/dccp/ccids/ccid3.c
+++ b/net/dccp/ccids/ccid3.c
@@ -52,7 +52,7 @@ static int ccid3_debug;
#ifdef CONFIG_IP_DCCP_CCID3_DEBUG
static const char *ccid3_tx_state_name(enum ccid3_hc_tx_states state)
{
- static char *ccid3_state_names[] = {
+ static const char *const ccid3_state_names[] = {
[TFRC_SSTATE_NO_SENT] = "NO_SENT",
[TFRC_SSTATE_NO_FBACK] = "NO_FBACK",
[TFRC_SSTATE_FBACK] = "FBACK",
@@ -646,7 +646,7 @@ enum ccid3_fback_type {
#ifdef CONFIG_IP_DCCP_CCID3_DEBUG
static const char *ccid3_rx_state_name(enum ccid3_hc_rx_states state)
{
- static char *ccid3_rx_state_names[] = {
+ static const char *const ccid3_rx_state_names[] = {
[TFRC_RSTATE_NO_DATA] = "NO_DATA",
[TFRC_RSTATE_DATA] = "DATA",
[TFRC_RSTATE_TERM] = "TERM",
diff --git a/net/dccp/feat.c b/net/dccp/feat.c
index b04160a2eea..972b8dc918d 100644
--- a/net/dccp/feat.c
+++ b/net/dccp/feat.c
@@ -213,7 +213,7 @@ static int dccp_feat_default_value(u8 feat_num)
*/
static const char *dccp_feat_fname(const u8 feat)
{
- static const char *feature_names[] = {
+ static const char *const feature_names[] = {
[DCCPF_RESERVED] = "Reserved",
[DCCPF_CCID] = "CCID",
[DCCPF_SHORT_SEQNOS] = "Allow Short Seqnos",
@@ -236,8 +236,9 @@ static const char *dccp_feat_fname(const u8 feat)
return feature_names[feat];
}
-static const char *dccp_feat_sname[] = { "DEFAULT", "INITIALISING", "CHANGING",
- "UNSTABLE", "STABLE" };
+static const char *const dccp_feat_sname[] = {
+ "DEFAULT", "INITIALISING", "CHANGING", "UNSTABLE", "STABLE",
+};
#ifdef CONFIG_IP_DCCP_DEBUG
static const char *dccp_feat_oname(const u8 opt)
diff --git a/net/dccp/proto.c b/net/dccp/proto.c
index 1bca9205104..923db06c7e5 100644
--- a/net/dccp/proto.c
+++ b/net/dccp/proto.c
@@ -124,7 +124,7 @@ EXPORT_SYMBOL_GPL(dccp_done);
const char *dccp_packet_name(const int type)
{
- static const char *dccp_packet_names[] = {
+ static const char *const dccp_packet_names[] = {
[DCCP_PKT_REQUEST] = "REQUEST",
[DCCP_PKT_RESPONSE] = "RESPONSE",
[DCCP_PKT_DATA] = "DATA",
@@ -147,7 +147,7 @@ EXPORT_SYMBOL_GPL(dccp_packet_name);
const char *dccp_state_name(const int state)
{
- static char *dccp_state_names[] = {
+ static const char *const dccp_state_names[] = {
[DCCP_OPEN] = "OPEN",
[DCCP_REQUESTING] = "REQUESTING",
[DCCP_PARTOPEN] = "PARTOPEN",
diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c
index 1d6ca8a98dc..9383d3e5a1a 100644
--- a/net/decnet/dn_route.c
+++ b/net/decnet/dn_route.c
@@ -774,7 +774,7 @@ static int dn_rt_bug(struct sk_buff *skb)
kfree_skb(skb);
- return NET_RX_BAD;
+ return NET_RX_DROP;
}
static int dn_rt_set_next_hop(struct dn_route *rt, struct dn_fib_res *res)
diff --git a/net/econet/af_econet.c b/net/econet/af_econet.c
index f0bbc57926c..0e0254fd767 100644
--- a/net/econet/af_econet.c
+++ b/net/econet/af_econet.c
@@ -1073,7 +1073,7 @@ static int econet_rcv(struct sk_buff *skb, struct net_device *dev, struct packet
skb->protocol = htons(ETH_P_IP);
skb_pull(skb, sizeof(struct ec_framehdr));
netif_rx(skb);
- return 0;
+ return NET_RX_SUCCESS;
}
sk = ec_listening_socket(hdr->port, hdr->src_stn, hdr->src_net);
@@ -1084,7 +1084,7 @@ static int econet_rcv(struct sk_buff *skb, struct net_device *dev, struct packet
hdr->port))
goto drop;
- return 0;
+ return NET_RX_SUCCESS;
drop:
kfree_skb(skb);
diff --git a/net/ieee802154/af_ieee802154.c b/net/ieee802154/af_ieee802154.c
index af661805b9f..d504c349cb0 100644
--- a/net/ieee802154/af_ieee802154.c
+++ b/net/ieee802154/af_ieee802154.c
@@ -34,8 +34,8 @@
#include <net/tcp_states.h>
#include <net/route.h>
-#include <net/ieee802154/af_ieee802154.h>
-#include <net/ieee802154/netdevice.h>
+#include <net/af_ieee802154.h>
+#include <net/ieee802154_netdev.h>
#include "af802154.h"
diff --git a/net/ieee802154/dgram.c b/net/ieee802154/dgram.c
index ba8b214dda8..77ae6852b93 100644
--- a/net/ieee802154/dgram.c
+++ b/net/ieee802154/dgram.c
@@ -26,9 +26,9 @@
#include <linux/if_arp.h>
#include <linux/list.h>
#include <net/sock.h>
-#include <net/ieee802154/af_ieee802154.h>
-#include <net/ieee802154/mac_def.h>
-#include <net/ieee802154/netdevice.h>
+#include <net/af_ieee802154.h>
+#include <net/ieee802154.h>
+#include <net/ieee802154_netdev.h>
#include <asm/ioctls.h>
@@ -40,9 +40,11 @@ static DEFINE_RWLOCK(dgram_lock);
struct dgram_sock {
struct sock sk;
- int bound;
struct ieee802154_addr src_addr;
struct ieee802154_addr dst_addr;
+
+ unsigned bound:1;
+ unsigned want_ack:1;
};
static inline struct dgram_sock *dgram_sk(const struct sock *sk)
@@ -50,7 +52,6 @@ static inline struct dgram_sock *dgram_sk(const struct sock *sk)
return container_of(sk, struct dgram_sock, sk);
}
-
static void dgram_hash(struct sock *sk)
{
write_lock_bh(&dgram_lock);
@@ -73,6 +74,7 @@ static int dgram_init(struct sock *sk)
ro->dst_addr.addr_type = IEEE802154_ADDR_LONG;
ro->dst_addr.pan_id = 0xffff;
+ ro->want_ack = 1;
memset(&ro->dst_addr.hwaddr, 0xff, sizeof(ro->dst_addr.hwaddr));
return 0;
}
@@ -86,18 +88,18 @@ static int dgram_bind(struct sock *sk, struct sockaddr *uaddr, int len)
{
struct sockaddr_ieee802154 *addr = (struct sockaddr_ieee802154 *)uaddr;
struct dgram_sock *ro = dgram_sk(sk);
- int err = 0;
+ int err = -EINVAL;
struct net_device *dev;
+ lock_sock(sk);
+
ro->bound = 0;
if (len < sizeof(*addr))
- return -EINVAL;
+ goto out;
if (addr->family != AF_IEEE802154)
- return -EINVAL;
-
- lock_sock(sk);
+ goto out;
dev = ieee802154_get_dev(sock_net(sk), &addr->addr);
if (!dev) {
@@ -113,6 +115,7 @@ static int dgram_bind(struct sock *sk, struct sockaddr *uaddr, int len)
memcpy(&ro->src_addr, &addr->addr, sizeof(struct ieee802154_addr));
ro->bound = 1;
+ err = 0;
out_put:
dev_put(dev);
out:
@@ -235,7 +238,10 @@ static int dgram_sendmsg(struct kiocb *iocb, struct sock *sk,
skb_reset_network_header(skb);
- mac_cb(skb)->flags = IEEE802154_FC_TYPE_DATA | MAC_CB_FLAG_ACKREQ;
+ mac_cb(skb)->flags = IEEE802154_FC_TYPE_DATA;
+ if (ro->want_ack)
+ mac_cb(skb)->flags |= MAC_CB_FLAG_ACKREQ;
+
mac_cb(skb)->seq = ieee802154_mlme_ops(dev)->get_dsn(dev);
err = dev_hard_header(skb, dev, ETH_P_IEEE802154, &ro->dst_addr,
ro->bound ? &ro->src_addr : NULL, size);
@@ -380,13 +386,59 @@ int ieee802154_dgram_deliver(struct net_device *dev, struct sk_buff *skb)
static int dgram_getsockopt(struct sock *sk, int level, int optname,
char __user *optval, int __user *optlen)
{
- return -EOPNOTSUPP;
+ struct dgram_sock *ro = dgram_sk(sk);
+
+ int val, len;
+
+ if (level != SOL_IEEE802154)
+ return -EOPNOTSUPP;
+
+ if (get_user(len, optlen))
+ return -EFAULT;
+
+ len = min_t(unsigned int, len, sizeof(int));
+
+ switch (optname) {
+ case WPAN_WANTACK:
+ val = ro->want_ack;
+ break;
+ default:
+ return -ENOPROTOOPT;
+ }
+
+ if (put_user(len, optlen))
+ return -EFAULT;
+ if (copy_to_user(optval, &val, len))
+ return -EFAULT;
+ return 0;
}
static int dgram_setsockopt(struct sock *sk, int level, int optname,
char __user *optval, int __user optlen)
{
- return -EOPNOTSUPP;
+ struct dgram_sock *ro = dgram_sk(sk);
+ int val;
+ int err = 0;
+
+ if (optlen < sizeof(int))
+ return -EINVAL;
+
+ if (get_user(val, (int __user *)optval))
+ return -EFAULT;
+
+ lock_sock(sk);
+
+ switch (optname) {
+ case WPAN_WANTACK:
+ ro->want_ack = !!val;
+ break;
+ default:
+ err = -ENOPROTOOPT;
+ break;
+ }
+
+ release_sock(sk);
+ return err;
}
struct proto ieee802154_dgram_prot = {
diff --git a/net/ieee802154/netlink.c b/net/ieee802154/netlink.c
index 27eda9fdf3c..cd0567f0671 100644
--- a/net/ieee802154/netlink.c
+++ b/net/ieee802154/netlink.c
@@ -19,6 +19,7 @@
* Written by:
* Sergey Lapin <slapin@ossfans.org>
* Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
+ * Maxim Osipov <maxim.osipov@siemens.com>
*/
#include <linux/kernel.h>
@@ -26,10 +27,12 @@
#include <linux/netdevice.h>
#include <net/netlink.h>
#include <net/genetlink.h>
+#include <net/sock.h>
#include <linux/nl802154.h>
-#include <net/ieee802154/af_ieee802154.h>
-#include <net/ieee802154/nl802154.h>
-#include <net/ieee802154/netdevice.h>
+#include <net/af_ieee802154.h>
+#include <net/nl802154.h>
+#include <net/ieee802154.h>
+#include <net/ieee802154_netdev.h>
static unsigned int ieee802154_seq_num;
@@ -73,7 +76,7 @@ static int ieee802154_nl_finish(struct sk_buff *msg)
/* XXX: nlh is right at the start of msg */
void *hdr = genlmsg_data(NLMSG_DATA(msg->data));
- if (!genlmsg_end(msg, hdr))
+ if (genlmsg_end(msg, hdr) < 0)
goto out;
return genlmsg_multicast(msg, 0, ieee802154_coord_mcgrp.id,
@@ -260,6 +263,60 @@ nla_put_failure:
}
EXPORT_SYMBOL(ieee802154_nl_scan_confirm);
+int ieee802154_nl_start_confirm(struct net_device *dev, u8 status)
+{
+ struct sk_buff *msg;
+
+ pr_debug("%s\n", __func__);
+
+ msg = ieee802154_nl_create(0, IEEE802154_START_CONF);
+ if (!msg)
+ return -ENOBUFS;
+
+ NLA_PUT_STRING(msg, IEEE802154_ATTR_DEV_NAME, dev->name);
+ NLA_PUT_U32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex);
+ NLA_PUT(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN,
+ dev->dev_addr);
+
+ NLA_PUT_U8(msg, IEEE802154_ATTR_STATUS, status);
+
+ return ieee802154_nl_finish(msg);
+
+nla_put_failure:
+ nlmsg_free(msg);
+ return -ENOBUFS;
+}
+EXPORT_SYMBOL(ieee802154_nl_start_confirm);
+
+static int ieee802154_nl_fill_iface(struct sk_buff *msg, u32 pid,
+ u32 seq, int flags, struct net_device *dev)
+{
+ void *hdr;
+
+ pr_debug("%s\n", __func__);
+
+ hdr = genlmsg_put(msg, 0, seq, &ieee802154_coordinator_family, flags,
+ IEEE802154_LIST_IFACE);
+ if (!hdr)
+ goto out;
+
+ NLA_PUT_STRING(msg, IEEE802154_ATTR_DEV_NAME, dev->name);
+ NLA_PUT_U32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex);
+
+ NLA_PUT(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN,
+ dev->dev_addr);
+ NLA_PUT_U16(msg, IEEE802154_ATTR_SHORT_ADDR,
+ ieee802154_mlme_ops(dev)->get_short_addr(dev));
+ NLA_PUT_U16(msg, IEEE802154_ATTR_PAN_ID,
+ ieee802154_mlme_ops(dev)->get_pan_id(dev));
+ return genlmsg_end(msg, hdr);
+
+nla_put_failure:
+ genlmsg_cancel(msg, hdr);
+out:
+ return -EMSGSIZE;
+}
+
/* Requests from userspace */
static struct net_device *ieee802154_nl_get_dev(struct genl_info *info)
{
@@ -272,7 +329,7 @@ static struct net_device *ieee802154_nl_get_dev(struct genl_info *info)
dev = dev_get_by_name(&init_net, name);
} else if (info->attrs[IEEE802154_ATTR_DEV_INDEX])
dev = dev_get_by_index(&init_net,
- nla_get_u32(info->attrs[IEEE802154_ATTR_DEV_INDEX]));
+ nla_get_u32(info->attrs[IEEE802154_ATTR_DEV_INDEX]));
else
return NULL;
@@ -431,6 +488,12 @@ static int ieee802154_start_req(struct sk_buff *skb, struct genl_info *info)
blx = nla_get_u8(info->attrs[IEEE802154_ATTR_BAT_EXT]);
coord_realign = nla_get_u8(info->attrs[IEEE802154_ATTR_COORD_REALIGN]);
+ if (addr.short_addr == IEEE802154_ADDR_BROADCAST) {
+ ieee802154_nl_start_confirm(dev, IEEE802154_NO_SHORT_ADDRESS);
+ dev_put(dev);
+ return -EINVAL;
+ }
+
ret = ieee802154_mlme_ops(dev)->start_req(dev, &addr, channel,
bcn_ord, sf_ord, pan_coord, blx, coord_realign);
@@ -466,6 +529,67 @@ static int ieee802154_scan_req(struct sk_buff *skb, struct genl_info *info)
return ret;
}
+static int ieee802154_list_iface(struct sk_buff *skb,
+ struct genl_info *info)
+{
+ /* Request for interface name, index, type, IEEE address,
+ PAN Id, short address */
+ struct sk_buff *msg;
+ struct net_device *dev = NULL;
+ int rc = -ENOBUFS;
+
+ pr_debug("%s\n", __func__);
+
+ dev = ieee802154_nl_get_dev(info);
+ if (!dev)
+ return -ENODEV;
+
+ msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
+ if (!msg)
+ goto out_dev;
+
+ rc = ieee802154_nl_fill_iface(msg, info->snd_pid, info->snd_seq,
+ 0, dev);
+ if (rc < 0)
+ goto out_free;
+
+ dev_put(dev);
+
+ return genlmsg_unicast(&init_net, msg, info->snd_pid);
+out_free:
+ nlmsg_free(msg);
+out_dev:
+ dev_put(dev);
+ return rc;
+
+}
+
+static int ieee802154_dump_iface(struct sk_buff *skb,
+ struct netlink_callback *cb)
+{
+ struct net *net = sock_net(skb->sk);
+ struct net_device *dev;
+ int idx;
+ int s_idx = cb->args[0];
+
+ pr_debug("%s\n", __func__);
+
+ idx = 0;
+ for_each_netdev(net, dev) {
+ if (idx < s_idx || (dev->type != ARPHRD_IEEE802154))
+ goto cont;
+
+ if (ieee802154_nl_fill_iface(skb, NETLINK_CB(cb->skb).pid,
+ cb->nlh->nlmsg_seq, NLM_F_MULTI, dev) < 0)
+ break;
+cont:
+ idx++;
+ }
+ cb->args[0] = idx;
+
+ return skb->len;
+}
+
#define IEEE802154_OP(_cmd, _func) \
{ \
.cmd = _cmd, \
@@ -475,12 +599,22 @@ static int ieee802154_scan_req(struct sk_buff *skb, struct genl_info *info)
.flags = GENL_ADMIN_PERM, \
}
+#define IEEE802154_DUMP(_cmd, _func, _dump) \
+ { \
+ .cmd = _cmd, \
+ .policy = ieee802154_policy, \
+ .doit = _func, \
+ .dumpit = _dump, \
+ }
+
static struct genl_ops ieee802154_coordinator_ops[] = {
IEEE802154_OP(IEEE802154_ASSOCIATE_REQ, ieee802154_associate_req),
IEEE802154_OP(IEEE802154_ASSOCIATE_RESP, ieee802154_associate_resp),
IEEE802154_OP(IEEE802154_DISASSOCIATE_REQ, ieee802154_disassociate_req),
IEEE802154_OP(IEEE802154_SCAN_REQ, ieee802154_scan_req),
IEEE802154_OP(IEEE802154_START_REQ, ieee802154_start_req),
+ IEEE802154_DUMP(IEEE802154_LIST_IFACE, ieee802154_list_iface,
+ ieee802154_dump_iface),
};
static int __init ieee802154_nl_init(void)
diff --git a/net/ieee802154/nl_policy.c b/net/ieee802154/nl_policy.c
index c7d71d1adca..83cb4ccef90 100644
--- a/net/ieee802154/nl_policy.c
+++ b/net/ieee802154/nl_policy.c
@@ -24,7 +24,7 @@
#define NLA_HW_ADDR NLA_U64
-struct nla_policy ieee802154_policy[IEEE802154_ATTR_MAX + 1] = {
+const struct nla_policy ieee802154_policy[IEEE802154_ATTR_MAX + 1] = {
[IEEE802154_ATTR_DEV_NAME] = { .type = NLA_STRING, },
[IEEE802154_ATTR_DEV_INDEX] = { .type = NLA_U32, },
@@ -50,3 +50,4 @@ struct nla_policy ieee802154_policy[IEEE802154_ATTR_MAX + 1] = {
[IEEE802154_ATTR_DURATION] = { .type = NLA_U8, },
[IEEE802154_ATTR_ED_LIST] = { .len = 27 },
};
+
diff --git a/net/ieee802154/raw.c b/net/ieee802154/raw.c
index 9315977c4c6..60dee69a1d0 100644
--- a/net/ieee802154/raw.c
+++ b/net/ieee802154/raw.c
@@ -26,7 +26,7 @@
#include <linux/if_arp.h>
#include <linux/list.h>
#include <net/sock.h>
-#include <net/ieee802154/af_ieee802154.h>
+#include <net/af_ieee802154.h>
#include "af802154.h"
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index 566ea6c4321..197d024b253 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -1187,6 +1187,7 @@ static struct sk_buff *inet_gso_segment(struct sk_buff *skb, int features)
int proto;
int ihl;
int id;
+ unsigned int offset = 0;
if (!(features & NETIF_F_V4_CSUM))
features &= ~NETIF_F_SG;
@@ -1229,7 +1230,14 @@ static struct sk_buff *inet_gso_segment(struct sk_buff *skb, int features)
skb = segs;
do {
iph = ip_hdr(skb);
- iph->id = htons(id++);
+ if (proto == IPPROTO_UDP) {
+ iph->id = htons(id);
+ iph->frag_off = htons(offset >> 3);
+ if (skb->next != NULL)
+ iph->frag_off |= htons(IP_MF);
+ offset += (skb->len - skb->mac_len - iph->ihl * 4);
+ } else
+ iph->id = htons(id++);
iph->tot_len = htons(skb->len - skb->mac_len);
iph->check = 0;
iph->check = ip_fast_csum(skb_network_header(skb), iph->ihl);
@@ -1425,6 +1433,8 @@ static struct net_protocol tcp_protocol = {
static struct net_protocol udp_protocol = {
.handler = udp_rcv,
.err_handler = udp_err,
+ .gso_send_check = udp4_ufo_send_check,
+ .gso_segment = udp4_ufo_fragment,
.no_policy = 1,
.netns_ok = 1,
};
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c
index 63c2fa7b68c..fe3c846b99a 100644
--- a/net/ipv4/fib_trie.c
+++ b/net/ipv4/fib_trie.c
@@ -164,6 +164,14 @@ static struct tnode *inflate(struct trie *t, struct tnode *tn);
static struct tnode *halve(struct trie *t, struct tnode *tn);
/* tnodes to free after resize(); protected by RTNL */
static struct tnode *tnode_free_head;
+static size_t tnode_free_size;
+
+/*
+ * synchronize_rcu after call_rcu for that many pages; it should be especially
+ * useful before resizing the root node with PREEMPT_NONE configs; the value was
+ * obtained experimentally, aiming to avoid visible slowdown.
+ */
+static const int sync_pages = 128;
static struct kmem_cache *fn_alias_kmem __read_mostly;
static struct kmem_cache *trie_leaf_kmem __read_mostly;
@@ -319,6 +327,8 @@ static const int inflate_threshold = 50;
static const int halve_threshold_root = 15;
static const int inflate_threshold_root = 25;
+static int inflate_threshold_root_fix;
+#define INFLATE_FIX_MAX 10 /* a comment in resize() */
static void __alias_free_mem(struct rcu_head *head)
{
@@ -393,6 +403,8 @@ static void tnode_free_safe(struct tnode *tn)
BUG_ON(IS_LEAF(tn));
tn->tnode_free = tnode_free_head;
tnode_free_head = tn;
+ tnode_free_size += sizeof(struct tnode) +
+ (sizeof(struct node *) << tn->bits);
}
static void tnode_free_flush(void)
@@ -404,6 +416,11 @@ static void tnode_free_flush(void)
tn->tnode_free = NULL;
tnode_free(tn);
}
+
+ if (tnode_free_size >= PAGE_SIZE * sync_pages) {
+ tnode_free_size = 0;
+ synchronize_rcu();
+ }
}
static struct leaf *leaf_new(void)
@@ -602,7 +619,8 @@ static struct node *resize(struct trie *t, struct tnode *tn)
/* Keep root node larger */
if (!tn->parent)
- inflate_threshold_use = inflate_threshold_root;
+ inflate_threshold_use = inflate_threshold_root +
+ inflate_threshold_root_fix;
else
inflate_threshold_use = inflate_threshold;
@@ -626,15 +644,27 @@ static struct node *resize(struct trie *t, struct tnode *tn)
}
if (max_resize < 0) {
- if (!tn->parent)
- pr_warning("Fix inflate_threshold_root."
- " Now=%d size=%d bits\n",
- inflate_threshold_root, tn->bits);
- else
+ if (!tn->parent) {
+ /*
+ * It was observed that during large updates even
+ * inflate_threshold_root = 35 might be needed to avoid
+ * this warning; but it should be temporary, so let's
+ * try to handle this automatically.
+ */
+ if (inflate_threshold_root_fix < INFLATE_FIX_MAX)
+ inflate_threshold_root_fix++;
+ else
+ pr_warning("Fix inflate_threshold_root."
+ " Now=%d size=%d bits fix=%d\n",
+ inflate_threshold_root, tn->bits,
+ inflate_threshold_root_fix);
+ } else {
pr_warning("Fix inflate_threshold."
" Now=%d size=%d bits\n",
inflate_threshold, tn->bits);
- }
+ }
+ } else if (max_resize > 3 && !tn->parent && inflate_threshold_root_fix)
+ inflate_threshold_root_fix--;
check_tnode(tn);
@@ -1435,7 +1465,7 @@ static int fn_trie_lookup(struct fib_table *tb, const struct flowi *flp,
cindex = tkey_extract_bits(mask_pfx(key, current_prefix_length),
pos, bits);
- n = tnode_get_child(pn, cindex);
+ n = tnode_get_child_rcu(pn, cindex);
if (n == NULL) {
#ifdef CONFIG_IP_FIB_TRIE_STATS
@@ -1570,7 +1600,7 @@ backtrace:
if (chopped_off <= pn->bits) {
cindex &= ~(1 << (chopped_off-1));
} else {
- struct tnode *parent = node_parent((struct node *) pn);
+ struct tnode *parent = node_parent_rcu((struct node *) pn);
if (!parent)
goto failed;
@@ -1783,7 +1813,7 @@ static struct leaf *trie_firstleaf(struct trie *t)
static struct leaf *trie_nextleaf(struct leaf *l)
{
struct node *c = (struct node *) l;
- struct tnode *p = node_parent(c);
+ struct tnode *p = node_parent_rcu(c);
if (!p)
return NULL; /* trie with just one leaf */
@@ -2391,7 +2421,7 @@ static inline const char *rtn_scope(char *buf, size_t len, enum rt_scope_t s)
}
}
-static const char *rtn_type_names[__RTN_MAX] = {
+static const char *const rtn_type_names[__RTN_MAX] = {
[RTN_UNSPEC] = "UNSPEC",
[RTN_UNICAST] = "UNICAST",
[RTN_LOCAL] = "LOCAL",
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
index cb4a0f4bd5e..b902ef55be7 100644
--- a/net/ipv4/ip_gre.c
+++ b/net/ipv4/ip_gre.c
@@ -821,7 +821,7 @@ static int ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
stats->tx_dropped++;
dev_kfree_skb(skb);
tunnel->recursion--;
- return 0;
+ return NETDEV_TX_OK;
}
if (skb->sk)
skb_set_owner_w(new_skb, skb->sk);
@@ -889,7 +889,7 @@ static int ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
IPTUNNEL_XMIT();
tunnel->recursion--;
- return 0;
+ return NETDEV_TX_OK;
tx_error_icmp:
dst_link_failure(skb);
@@ -898,7 +898,7 @@ tx_error:
stats->tx_errors++;
dev_kfree_skb(skb);
tunnel->recursion--;
- return 0;
+ return NETDEV_TX_OK;
}
static int ipgre_tunnel_bind_dev(struct net_device *dev)
diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c
index 93e2b787da2..98075b6d619 100644
--- a/net/ipv4/ipip.c
+++ b/net/ipv4/ipip.c
@@ -486,7 +486,7 @@ static int ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
stats->tx_dropped++;
dev_kfree_skb(skb);
tunnel->recursion--;
- return 0;
+ return NETDEV_TX_OK;
}
if (skb->sk)
skb_set_owner_w(new_skb, skb->sk);
@@ -524,7 +524,7 @@ static int ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
IPTUNNEL_XMIT();
tunnel->recursion--;
- return 0;
+ return NETDEV_TX_OK;
tx_error_icmp:
dst_link_failure(skb);
@@ -532,7 +532,7 @@ tx_error:
stats->tx_errors++;
dev_kfree_skb(skb);
tunnel->recursion--;
- return 0;
+ return NETDEV_TX_OK;
}
static void ipip_tunnel_bind_dev(struct net_device *dev)
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c
index 9a8da5ed92b..06c33fb6b32 100644
--- a/net/ipv4/ipmr.c
+++ b/net/ipv4/ipmr.c
@@ -212,7 +212,7 @@ static int reg_vif_xmit(struct sk_buff *skb, struct net_device *dev)
IGMPMSG_WHOLEPKT);
read_unlock(&mrt_lock);
kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
}
static const struct net_device_ops reg_vif_netdev_ops = {
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 278f46f5011..fafbe163e2b 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -3442,7 +3442,7 @@ int __init ip_rt_init(void)
printk(KERN_ERR "Unable to create route proc files\n");
#ifdef CONFIG_XFRM
xfrm_init();
- xfrm4_init();
+ xfrm4_init(ip_rt_max_size);
#endif
rtnl_register(PF_INET, RTM_GETROUTE, inet_rtm_getroute, NULL);
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index bd62712848f..4e004424d40 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -59,6 +59,7 @@ int sysctl_tcp_base_mss __read_mostly = 512;
/* By default, RFC2861 behavior. */
int sysctl_tcp_slow_start_after_idle __read_mostly = 1;
+/* Account for new data that has been sent to the network. */
static void tcp_event_new_data_sent(struct sock *sk, struct sk_buff *skb)
{
struct tcp_sock *tp = tcp_sk(sk);
@@ -142,6 +143,7 @@ static void tcp_cwnd_restart(struct sock *sk, struct dst_entry *dst)
tp->snd_cwnd_used = 0;
}
+/* Congestion state accounting after a packet has been sent. */
static void tcp_event_data_sent(struct tcp_sock *tp,
struct sk_buff *skb, struct sock *sk)
{
@@ -161,6 +163,7 @@ static void tcp_event_data_sent(struct tcp_sock *tp,
icsk->icsk_ack.pingpong = 1;
}
+/* Account for an ACK we sent. */
static inline void tcp_event_ack_sent(struct sock *sk, unsigned int pkts)
{
tcp_dec_quickack_mode(sk, pkts);
@@ -276,6 +279,7 @@ static u16 tcp_select_window(struct sock *sk)
return new_win;
}
+/* Packet ECN state for a SYN-ACK */
static inline void TCP_ECN_send_synack(struct tcp_sock *tp, struct sk_buff *skb)
{
TCP_SKB_CB(skb)->flags &= ~TCPCB_FLAG_CWR;
@@ -283,6 +287,7 @@ static inline void TCP_ECN_send_synack(struct tcp_sock *tp, struct sk_buff *skb)
TCP_SKB_CB(skb)->flags &= ~TCPCB_FLAG_ECE;
}
+/* Packet ECN state for a SYN. */
static inline void TCP_ECN_send_syn(struct sock *sk, struct sk_buff *skb)
{
struct tcp_sock *tp = tcp_sk(sk);
@@ -301,6 +306,9 @@ TCP_ECN_make_synack(struct request_sock *req, struct tcphdr *th)
th->ece = 1;
}
+/* Set up ECN state for a packet on a ESTABLISHED socket that is about to
+ * be sent.
+ */
static inline void TCP_ECN_send(struct sock *sk, struct sk_buff *skb,
int tcp_header_len)
{
@@ -362,7 +370,9 @@ struct tcp_out_options {
__u32 tsval, tsecr; /* need to include OPTION_TS */
};
-/* Beware: Something in the Internet is very sensitive to the ordering of
+/* Write previously computed TCP options to the packet.
+ *
+ * Beware: Something in the Internet is very sensitive to the ordering of
* TCP options, we learned this through the hard way, so be careful here.
* Luckily we can at least blame others for their non-compliance but from
* inter-operatibility perspective it seems that we're somewhat stuck with
@@ -445,6 +455,9 @@ static void tcp_options_write(__be32 *ptr, struct tcp_sock *tp,
}
}
+/* Compute TCP options for SYN packets. This is not the final
+ * network wire format yet.
+ */
static unsigned tcp_syn_options(struct sock *sk, struct sk_buff *skb,
struct tcp_out_options *opts,
struct tcp_md5sig_key **md5) {
@@ -493,6 +506,7 @@ static unsigned tcp_syn_options(struct sock *sk, struct sk_buff *skb,
return size;
}
+/* Set up TCP options for SYN-ACKs. */
static unsigned tcp_synack_options(struct sock *sk,
struct request_sock *req,
unsigned mss, struct sk_buff *skb,
@@ -541,6 +555,9 @@ static unsigned tcp_synack_options(struct sock *sk,
return size;
}
+/* Compute TCP options for ESTABLISHED sockets. This is not the
+ * final wire format yet.
+ */
static unsigned tcp_established_options(struct sock *sk, struct sk_buff *skb,
struct tcp_out_options *opts,
struct tcp_md5sig_key **md5) {
@@ -705,7 +722,7 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it,
return net_xmit_eval(err);
}
-/* This routine just queue's the buffer
+/* This routine just queues the buffer for sending.
*
* NOTE: probe0 timer is not checked, do not forget tcp_push_pending_frames,
* otherwise socket can stall.
@@ -722,6 +739,7 @@ static void tcp_queue_skb(struct sock *sk, struct sk_buff *skb)
sk_mem_charge(sk, skb->truesize);
}
+/* Initialize TSO segments for a packet. */
static void tcp_set_skb_tso_segs(struct sock *sk, struct sk_buff *skb,
unsigned int mss_now)
{
@@ -909,6 +927,7 @@ static void __pskb_trim_head(struct sk_buff *skb, int len)
skb->len = skb->data_len;
}
+/* Remove acked data from a packet in the transmit queue. */
int tcp_trim_head(struct sock *sk, struct sk_buff *skb, u32 len)
{
if (skb_cloned(skb) && pskb_expand_head(skb, 0, 0, GFP_ATOMIC))
@@ -937,7 +956,7 @@ int tcp_trim_head(struct sock *sk, struct sk_buff *skb, u32 len)
return 0;
}
-/* Not accounting for SACKs here. */
+/* Calculate MSS. Not accounting for SACKs here. */
int tcp_mtu_to_mss(struct sock *sk, int pmtu)
{
struct tcp_sock *tp = tcp_sk(sk);
@@ -981,6 +1000,7 @@ int tcp_mss_to_mtu(struct sock *sk, int mss)
return mtu;
}
+/* MTU probing init per socket */
void tcp_mtup_init(struct sock *sk)
{
struct tcp_sock *tp = tcp_sk(sk);
@@ -1143,7 +1163,8 @@ static inline unsigned int tcp_cwnd_test(struct tcp_sock *tp,
return 0;
}
-/* This must be invoked the first time we consider transmitting
+/* Intialize TSO state of a skb.
+ * This must be invoked the first time we consider transmitting
* SKB onto the wire.
*/
static int tcp_init_tso_segs(struct sock *sk, struct sk_buff *skb,
@@ -1158,6 +1179,7 @@ static int tcp_init_tso_segs(struct sock *sk, struct sk_buff *skb,
return tso_segs;
}
+/* Minshall's variant of the Nagle send check. */
static inline int tcp_minshall_check(const struct tcp_sock *tp)
{
return after(tp->snd_sml, tp->snd_una) &&
@@ -1242,6 +1264,7 @@ static unsigned int tcp_snd_test(struct sock *sk, struct sk_buff *skb,
return cwnd_quota;
}
+/* Test if sending is allowed right now. */
int tcp_may_send_now(struct sock *sk)
{
struct tcp_sock *tp = tcp_sk(sk);
@@ -1378,6 +1401,10 @@ send_now:
}
/* Create a new MTU probe if we are ready.
+ * MTU probe is regularly attempting to increase the path MTU by
+ * deliberately sending larger packets. This discovers routing
+ * changes resulting in larger path MTUs.
+ *
* Returns 0 if we should wait to probe (no cwnd available),
* 1 if a probe was sent,
* -1 otherwise
@@ -1790,6 +1817,7 @@ static void tcp_collapse_retrans(struct sock *sk, struct sk_buff *skb)
sk_wmem_free_skb(sk, next_skb);
}
+/* Check if coalescing SKBs is legal. */
static int tcp_can_collapse(struct sock *sk, struct sk_buff *skb)
{
if (tcp_skb_pcount(skb) > 1)
@@ -1808,6 +1836,9 @@ static int tcp_can_collapse(struct sock *sk, struct sk_buff *skb)
return 1;
}
+/* Collapse packets in the retransmit queue to make to create
+ * less packets on the wire. This is only done on retransmission.
+ */
static void tcp_retrans_try_collapse(struct sock *sk, struct sk_buff *to,
int space)
{
@@ -1957,6 +1988,9 @@ int tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb)
return err;
}
+/* Check if we forward retransmits are possible in the current
+ * window/congestion state.
+ */
static int tcp_can_forward_retransmit(struct sock *sk)
{
const struct inet_connection_sock *icsk = inet_csk(sk);
@@ -2145,7 +2179,8 @@ void tcp_send_active_reset(struct sock *sk, gfp_t priority)
TCP_INC_STATS(sock_net(sk), TCP_MIB_OUTRSTS);
}
-/* WARNING: This routine must only be called when we have already sent
+/* Send a crossed SYN-ACK during socket establishment.
+ * WARNING: This routine must only be called when we have already sent
* a SYN packet that crossed the incoming SYN that caused this routine
* to get called. If this assumption fails then the initial rcv_wnd
* and rcv_wscale values will not be correct.
@@ -2180,9 +2215,7 @@ int tcp_send_synack(struct sock *sk)
return tcp_transmit_skb(sk, skb, 1, GFP_ATOMIC);
}
-/*
- * Prepare a SYN-ACK.
- */
+/* Prepare a SYN-ACK. */
struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst,
struct request_sock *req)
{
@@ -2269,9 +2302,7 @@ struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst,
return skb;
}
-/*
- * Do all connect socket setups that can be done AF independent.
- */
+/* Do all connect socket setups that can be done AF independent. */
static void tcp_connect_init(struct sock *sk)
{
struct dst_entry *dst = __sk_dst_get(sk);
@@ -2330,9 +2361,7 @@ static void tcp_connect_init(struct sock *sk)
tcp_clear_retrans(tp);
}
-/*
- * Build a SYN and send it off.
- */
+/* Build a SYN and send it off. */
int tcp_connect(struct sock *sk)
{
struct tcp_sock *tp = tcp_sk(sk);
@@ -2493,6 +2522,7 @@ static int tcp_xmit_probe_skb(struct sock *sk, int urgent)
return tcp_transmit_skb(sk, skb, 0, GFP_ATOMIC);
}
+/* Initiate keepalive or window probe from timer. */
int tcp_write_wakeup(struct sock *sk)
{
struct tcp_sock *tp = tcp_sk(sk);
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 80e3812837a..29ebb0d27a1 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -110,11 +110,12 @@ struct udp_table udp_table;
EXPORT_SYMBOL(udp_table);
int sysctl_udp_mem[3] __read_mostly;
-int sysctl_udp_rmem_min __read_mostly;
-int sysctl_udp_wmem_min __read_mostly;
-
EXPORT_SYMBOL(sysctl_udp_mem);
+
+int sysctl_udp_rmem_min __read_mostly;
EXPORT_SYMBOL(sysctl_udp_rmem_min);
+
+int sysctl_udp_wmem_min __read_mostly;
EXPORT_SYMBOL(sysctl_udp_wmem_min);
atomic_t udp_memory_allocated;
@@ -158,7 +159,7 @@ static int udp_lib_lport_inuse(struct net *net, __u16 num,
*/
int udp_lib_get_port(struct sock *sk, unsigned short snum,
int (*saddr_comp)(const struct sock *sk1,
- const struct sock *sk2 ) )
+ const struct sock *sk2))
{
struct udp_hslot *hslot;
struct udp_table *udptable = sk->sk_prot->h.udp_table;
@@ -221,14 +222,15 @@ fail_unlock:
fail:
return error;
}
+EXPORT_SYMBOL(udp_lib_get_port);
static int ipv4_rcv_saddr_equal(const struct sock *sk1, const struct sock *sk2)
{
struct inet_sock *inet1 = inet_sk(sk1), *inet2 = inet_sk(sk2);
- return ( !ipv6_only_sock(sk2) &&
- (!inet1->rcv_saddr || !inet2->rcv_saddr ||
- inet1->rcv_saddr == inet2->rcv_saddr ));
+ return (!ipv6_only_sock(sk2) &&
+ (!inet1->rcv_saddr || !inet2->rcv_saddr ||
+ inet1->rcv_saddr == inet2->rcv_saddr));
}
int udp_v4_get_port(struct sock *sk, unsigned short snum)
@@ -383,8 +385,8 @@ found:
void __udp4_lib_err(struct sk_buff *skb, u32 info, struct udp_table *udptable)
{
struct inet_sock *inet;
- struct iphdr *iph = (struct iphdr*)skb->data;
- struct udphdr *uh = (struct udphdr*)(skb->data+(iph->ihl<<2));
+ struct iphdr *iph = (struct iphdr *)skb->data;
+ struct udphdr *uh = (struct udphdr *)(skb->data+(iph->ihl<<2));
const int type = icmp_hdr(skb)->type;
const int code = icmp_hdr(skb)->code;
struct sock *sk;
@@ -439,7 +441,7 @@ void __udp4_lib_err(struct sk_buff *skb, u32 info, struct udp_table *udptable)
if (!harderr || sk->sk_state != TCP_ESTABLISHED)
goto out;
} else {
- ip_icmp_error(sk, skb, err, uh->dest, info, (u8*)(uh+1));
+ ip_icmp_error(sk, skb, err, uh->dest, info, (u8 *)(uh+1));
}
sk->sk_err = err;
sk->sk_error_report(sk);
@@ -474,7 +476,7 @@ EXPORT_SYMBOL(udp_flush_pending_frames);
* (checksum field must be zeroed out)
*/
static void udp4_hwcsum_outgoing(struct sock *sk, struct sk_buff *skb,
- __be32 src, __be32 dst, int len )
+ __be32 src, __be32 dst, int len)
{
unsigned int offset;
struct udphdr *uh = udp_hdr(skb);
@@ -545,7 +547,7 @@ static int udp_push_pending_frames(struct sock *sk)
} else if (skb->ip_summed == CHECKSUM_PARTIAL) { /* UDP hardware csum */
- udp4_hwcsum_outgoing(sk, skb, fl->fl4_src,fl->fl4_dst, up->len);
+ udp4_hwcsum_outgoing(sk, skb, fl->fl4_src, fl->fl4_dst, up->len);
goto send;
} else /* `normal' UDP */
@@ -553,7 +555,7 @@ static int udp_push_pending_frames(struct sock *sk)
/* add protocol-dependent pseudo-header */
uh->check = csum_tcpudp_magic(fl->fl4_src, fl->fl4_dst, up->len,
- sk->sk_protocol, csum );
+ sk->sk_protocol, csum);
if (uh->check == 0)
uh->check = CSUM_MANGLED_0;
@@ -592,7 +594,7 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
* Check the flags.
*/
- if (msg->msg_flags&MSG_OOB) /* Mirror BSD error message compatibility */
+ if (msg->msg_flags & MSG_OOB) /* Mirror BSD error message compatibility */
return -EOPNOTSUPP;
ipc.opt = NULL;
@@ -619,7 +621,7 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
* Get and verify the address.
*/
if (msg->msg_name) {
- struct sockaddr_in * usin = (struct sockaddr_in*)msg->msg_name;
+ struct sockaddr_in * usin = (struct sockaddr_in *)msg->msg_name;
if (msg->msg_namelen < sizeof(*usin))
return -EINVAL;
if (usin->sin_family != AF_INET) {
@@ -684,7 +686,7 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
}
if (connected)
- rt = (struct rtable*)sk_dst_check(sk, 0);
+ rt = (struct rtable *)sk_dst_check(sk, 0);
if (rt == NULL) {
struct flowi fl = { .oif = ipc.oif,
@@ -782,6 +784,7 @@ do_confirm:
err = 0;
goto out;
}
+EXPORT_SYMBOL(udp_sendmsg);
int udp_sendpage(struct sock *sk, struct page *page, int offset,
size_t size, int flags)
@@ -871,6 +874,7 @@ int udp_ioctl(struct sock *sk, int cmd, unsigned long arg)
return 0;
}
+EXPORT_SYMBOL(udp_ioctl);
/*
* This should be easy, if there is something there we
@@ -892,7 +896,7 @@ int udp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
* Check any passed addresses
*/
if (addr_len)
- *addr_len=sizeof(*sin);
+ *addr_len = sizeof(*sin);
if (flags & MSG_ERRQUEUE)
return ip_recv_error(sk, msg, len);
@@ -923,9 +927,11 @@ try_again:
if (skb_csum_unnecessary(skb))
err = skb_copy_datagram_iovec(skb, sizeof(struct udphdr),
- msg->msg_iov, copied );
+ msg->msg_iov, copied);
else {
- err = skb_copy_and_csum_datagram_iovec(skb, sizeof(struct udphdr), msg->msg_iov);
+ err = skb_copy_and_csum_datagram_iovec(skb,
+ sizeof(struct udphdr),
+ msg->msg_iov);
if (err == -EINVAL)
goto csum_copy_err;
@@ -941,8 +947,7 @@ try_again:
sock_recv_timestamp(msg, sk, skb);
/* Copy the address. */
- if (sin)
- {
+ if (sin) {
sin->sin_family = AF_INET;
sin->sin_port = udp_hdr(skb)->source;
sin->sin_addr.s_addr = ip_hdr(skb)->saddr;
@@ -995,6 +1000,7 @@ int udp_disconnect(struct sock *sk, int flags)
sk_dst_reset(sk);
return 0;
}
+EXPORT_SYMBOL(udp_disconnect);
void udp_lib_unhash(struct sock *sk)
{
@@ -1044,7 +1050,7 @@ drop:
* Note that in the success and error cases, the skb is assumed to
* have either been requeued or freed.
*/
-int udp_queue_rcv_skb(struct sock * sk, struct sk_buff *skb)
+int udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
{
struct udp_sock *up = udp_sk(sk);
int rc;
@@ -1214,7 +1220,7 @@ static inline int udp4_csum_init(struct sk_buff *skb, struct udphdr *uh,
if (uh->check == 0) {
skb->ip_summed = CHECKSUM_UNNECESSARY;
} else if (skb->ip_summed == CHECKSUM_COMPLETE) {
- if (!csum_tcpudp_magic(iph->saddr, iph->daddr, skb->len,
+ if (!csum_tcpudp_magic(iph->saddr, iph->daddr, skb->len,
proto, skb->csum))
skb->ip_summed = CHECKSUM_UNNECESSARY;
}
@@ -1355,7 +1361,7 @@ int udp_lib_setsockopt(struct sock *sk, int level, int optname,
int err = 0;
int is_udplite = IS_UDPLITE(sk);
- if (optlen<sizeof(int))
+ if (optlen < sizeof(int))
return -EINVAL;
if (get_user(val, (int __user *)optval))
@@ -1426,6 +1432,7 @@ int udp_lib_setsockopt(struct sock *sk, int level, int optname,
return err;
}
+EXPORT_SYMBOL(udp_lib_setsockopt);
int udp_setsockopt(struct sock *sk, int level, int optname,
char __user *optval, int optlen)
@@ -1453,7 +1460,7 @@ int udp_lib_getsockopt(struct sock *sk, int level, int optname,
struct udp_sock *up = udp_sk(sk);
int val, len;
- if (get_user(len,optlen))
+ if (get_user(len, optlen))
return -EFAULT;
len = min_t(unsigned int, len, sizeof(int));
@@ -1486,10 +1493,11 @@ int udp_lib_getsockopt(struct sock *sk, int level, int optname,
if (put_user(len, optlen))
return -EFAULT;
- if (copy_to_user(optval, &val,len))
+ if (copy_to_user(optval, &val, len))
return -EFAULT;
return 0;
}
+EXPORT_SYMBOL(udp_lib_getsockopt);
int udp_getsockopt(struct sock *sk, int level, int optname,
char __user *optval, int __user *optlen)
@@ -1528,9 +1536,9 @@ unsigned int udp_poll(struct file *file, struct socket *sock, poll_table *wait)
int is_lite = IS_UDPLITE(sk);
/* Check for false positives due to checksum errors */
- if ( (mask & POLLRDNORM) &&
- !(file->f_flags & O_NONBLOCK) &&
- !(sk->sk_shutdown & RCV_SHUTDOWN)){
+ if ((mask & POLLRDNORM) &&
+ !(file->f_flags & O_NONBLOCK) &&
+ !(sk->sk_shutdown & RCV_SHUTDOWN)) {
struct sk_buff_head *rcvq = &sk->sk_receive_queue;
struct sk_buff *skb;
@@ -1552,6 +1560,7 @@ unsigned int udp_poll(struct file *file, struct socket *sock, poll_table *wait)
return mask;
}
+EXPORT_SYMBOL(udp_poll);
struct proto udp_prot = {
.name = "UDP",
@@ -1582,6 +1591,7 @@ struct proto udp_prot = {
.compat_getsockopt = compat_udp_getsockopt,
#endif
};
+EXPORT_SYMBOL(udp_prot);
/* ------------------------------------------------------------------------ */
#ifdef CONFIG_PROC_FS
@@ -1703,11 +1713,13 @@ int udp_proc_register(struct net *net, struct udp_seq_afinfo *afinfo)
rc = -ENOMEM;
return rc;
}
+EXPORT_SYMBOL(udp_proc_register);
void udp_proc_unregister(struct net *net, struct udp_seq_afinfo *afinfo)
{
proc_net_remove(net, afinfo->name);
}
+EXPORT_SYMBOL(udp_proc_unregister);
/* ------------------------------------------------------------------------ */
static void udp4_format_sock(struct sock *sp, struct seq_file *f,
@@ -1741,7 +1753,7 @@ int udp4_seq_show(struct seq_file *seq, void *v)
int len;
udp4_format_sock(v, seq, state->bucket, &len);
- seq_printf(seq, "%*s\n", 127 - len ,"");
+ seq_printf(seq, "%*s\n", 127 - len, "");
}
return 0;
}
@@ -1816,16 +1828,64 @@ void __init udp_init(void)
sysctl_udp_wmem_min = SK_MEM_QUANTUM;
}
-EXPORT_SYMBOL(udp_disconnect);
-EXPORT_SYMBOL(udp_ioctl);
-EXPORT_SYMBOL(udp_prot);
-EXPORT_SYMBOL(udp_sendmsg);
-EXPORT_SYMBOL(udp_lib_getsockopt);
-EXPORT_SYMBOL(udp_lib_setsockopt);
-EXPORT_SYMBOL(udp_poll);
-EXPORT_SYMBOL(udp_lib_get_port);
+int udp4_ufo_send_check(struct sk_buff *skb)
+{
+ const struct iphdr *iph;
+ struct udphdr *uh;
+
+ if (!pskb_may_pull(skb, sizeof(*uh)))
+ return -EINVAL;
+
+ iph = ip_hdr(skb);
+ uh = udp_hdr(skb);
+
+ uh->check = ~csum_tcpudp_magic(iph->saddr, iph->daddr, skb->len,
+ IPPROTO_UDP, 0);
+ skb->csum_start = skb_transport_header(skb) - skb->head;
+ skb->csum_offset = offsetof(struct udphdr, check);
+ skb->ip_summed = CHECKSUM_PARTIAL;
+ return 0;
+}
+
+struct sk_buff *udp4_ufo_fragment(struct sk_buff *skb, int features)
+{
+ struct sk_buff *segs = ERR_PTR(-EINVAL);
+ unsigned int mss;
+ int offset;
+ __wsum csum;
+
+ mss = skb_shinfo(skb)->gso_size;
+ if (unlikely(skb->len <= mss))
+ goto out;
+
+ if (skb_gso_ok(skb, features | NETIF_F_GSO_ROBUST)) {
+ /* Packet is from an untrusted source, reset gso_segs. */
+ int type = skb_shinfo(skb)->gso_type;
+
+ if (unlikely(type & ~(SKB_GSO_UDP | SKB_GSO_DODGY) ||
+ !(type & (SKB_GSO_UDP))))
+ goto out;
+
+ skb_shinfo(skb)->gso_segs = DIV_ROUND_UP(skb->len, mss);
+
+ segs = NULL;
+ goto out;
+ }
+
+ /* Do software UFO. Complete and fill in the UDP checksum as HW cannot
+ * do checksum of UDP packets sent as multiple IP fragments.
+ */
+ offset = skb->csum_start - skb_headroom(skb);
+ csum = skb_checksum(skb, offset, skb->len - offset, 0);
+ offset += skb->csum_offset;
+ *(__sum16 *)(skb->data + offset) = csum_fold(csum);
+ skb->ip_summed = CHECKSUM_NONE;
+
+ /* Fragment the skb. IP headers of the fragments are updated in
+ * inet_gso_segment()
+ */
+ segs = skb_segment(skb, features);
+out:
+ return segs;
+}
-#ifdef CONFIG_PROC_FS
-EXPORT_SYMBOL(udp_proc_register);
-EXPORT_SYMBOL(udp_proc_unregister);
-#endif
diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c
index 0071ee6f441..74fb2eb833e 100644
--- a/net/ipv4/xfrm4_policy.c
+++ b/net/ipv4/xfrm4_policy.c
@@ -264,6 +264,22 @@ static struct xfrm_policy_afinfo xfrm4_policy_afinfo = {
.fill_dst = xfrm4_fill_dst,
};
+#ifdef CONFIG_SYSCTL
+static struct ctl_table xfrm4_policy_table[] = {
+ {
+ .ctl_name = CTL_UNNUMBERED,
+ .procname = "xfrm4_gc_thresh",
+ .data = &xfrm4_dst_ops.gc_thresh,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = proc_dointvec,
+ },
+ { }
+};
+
+static struct ctl_table_header *sysctl_hdr;
+#endif
+
static void __init xfrm4_policy_init(void)
{
xfrm_policy_register_afinfo(&xfrm4_policy_afinfo);
@@ -271,12 +287,31 @@ static void __init xfrm4_policy_init(void)
static void __exit xfrm4_policy_fini(void)
{
+#ifdef CONFIG_SYSCTL
+ if (sysctl_hdr)
+ unregister_net_sysctl_table(sysctl_hdr);
+#endif
xfrm_policy_unregister_afinfo(&xfrm4_policy_afinfo);
}
-void __init xfrm4_init(void)
+void __init xfrm4_init(int rt_max_size)
{
xfrm4_state_init();
xfrm4_policy_init();
+ /*
+ * Select a default value for the gc_thresh based on the main route
+ * table hash size. It seems to me the worst case scenario is when
+ * we have ipsec operating in transport mode, in which we create a
+ * dst_entry per socket. The xfrm gc algorithm starts trying to remove
+ * entries at gc_thresh, and prevents new allocations as 2*gc_thresh
+ * so lets set an initial xfrm gc_thresh value at the rt_max_size/2.
+ * That will let us store an ipsec connection per route table entry,
+ * and start cleaning when were 1/2 full
+ */
+ xfrm4_dst_ops.gc_thresh = rt_max_size/2;
+#ifdef CONFIG_SYSCTL
+ sysctl_hdr = register_net_sysctl_table(&init_net, net_ipv4_ctl_path,
+ xfrm4_policy_table);
+#endif
}
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index caa0278d30a..bf85d5f9703 100644
--- a/net/ipv6/af_inet6.c
+++ b/net/ipv6/af_inet6.c
@@ -772,6 +772,11 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb, int features)
struct sk_buff *segs = ERR_PTR(-EINVAL);
struct ipv6hdr *ipv6h;
struct inet6_protocol *ops;
+ int proto;
+ struct frag_hdr *fptr;
+ unsigned int unfrag_ip6hlen;
+ u8 *prevhdr;
+ int offset = 0;
if (!(features & NETIF_F_V6_CSUM))
features &= ~NETIF_F_SG;
@@ -791,10 +796,9 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb, int features)
__skb_pull(skb, sizeof(*ipv6h));
segs = ERR_PTR(-EPROTONOSUPPORT);
+ proto = ipv6_gso_pull_exthdrs(skb, ipv6h->nexthdr);
rcu_read_lock();
- ops = rcu_dereference(inet6_protos[
- ipv6_gso_pull_exthdrs(skb, ipv6h->nexthdr)]);
-
+ ops = rcu_dereference(inet6_protos[proto]);
if (likely(ops && ops->gso_segment)) {
skb_reset_transport_header(skb);
segs = ops->gso_segment(skb, features);
@@ -808,6 +812,16 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb, int features)
ipv6h = ipv6_hdr(skb);
ipv6h->payload_len = htons(skb->len - skb->mac_len -
sizeof(*ipv6h));
+ if (proto == IPPROTO_UDP) {
+ unfrag_ip6hlen = ip6_find_1stfragopt(skb, &prevhdr);
+ fptr = (struct frag_hdr *)(skb_network_header(skb) +
+ unfrag_ip6hlen);
+ fptr->frag_off = htons(offset);
+ if (skb->next != NULL)
+ fptr->frag_off |= htons(IP6_MF);
+ offset += (ntohs(ipv6h->payload_len) -
+ sizeof(struct frag_hdr));
+ }
}
out:
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c
index eab62a7a8f0..e2325f6a05f 100644
--- a/net/ipv6/icmp.c
+++ b/net/ipv6/icmp.c
@@ -323,7 +323,7 @@ void icmpv6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info,
int iif = 0;
int addr_type = 0;
int len;
- int hlimit, tclass;
+ int hlimit;
int err = 0;
if ((u8 *)hdr < skb->head ||
@@ -469,10 +469,6 @@ route_done:
if (hlimit < 0)
hlimit = ip6_dst_hoplimit(dst);
- tclass = np->tclass;
- if (tclass < 0)
- tclass = 0;
-
msg.skb = skb;
msg.offset = skb_network_offset(skb);
msg.type = type;
@@ -488,8 +484,8 @@ route_done:
err = ip6_append_data(sk, icmpv6_getfrag, &msg,
len + sizeof(struct icmp6hdr),
- sizeof(struct icmp6hdr),
- hlimit, tclass, NULL, &fl, (struct rt6_info*)dst,
+ sizeof(struct icmp6hdr), hlimit,
+ np->tclass, NULL, &fl, (struct rt6_info*)dst,
MSG_DONTWAIT);
if (err) {
ip6_flush_pending_frames(sk);
@@ -522,7 +518,6 @@ static void icmpv6_echo_reply(struct sk_buff *skb)
struct dst_entry *dst;
int err = 0;
int hlimit;
- int tclass;
saddr = &ipv6_hdr(skb)->daddr;
@@ -562,10 +557,6 @@ static void icmpv6_echo_reply(struct sk_buff *skb)
if (hlimit < 0)
hlimit = ip6_dst_hoplimit(dst);
- tclass = np->tclass;
- if (tclass < 0)
- tclass = 0;
-
idev = in6_dev_get(skb->dev);
msg.skb = skb;
@@ -573,7 +564,7 @@ static void icmpv6_echo_reply(struct sk_buff *skb)
msg.type = ICMPV6_ECHO_REPLY;
err = ip6_append_data(sk, icmpv6_getfrag, &msg, skb->len + sizeof(struct icmp6hdr),
- sizeof(struct icmp6hdr), hlimit, tclass, NULL, &fl,
+ sizeof(struct icmp6hdr), hlimit, np->tclass, NULL, &fl,
(struct rt6_info*)dst, MSG_DONTWAIT);
if (err) {
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
index 52ee1dced2f..0e93ca56eb6 100644
--- a/net/ipv6/ip6_fib.c
+++ b/net/ipv6/ip6_fib.c
@@ -164,12 +164,6 @@ static __inline__ void rt6_release(struct rt6_info *rt)
dst_free(&rt->u.dst);
}
-#ifdef CONFIG_IPV6_MULTIPLE_TABLES
-#define FIB_TABLE_HASHSZ 256
-#else
-#define FIB_TABLE_HASHSZ 1
-#endif
-
static void fib6_link_table(struct net *net, struct fib6_table *tb)
{
unsigned int h;
@@ -180,7 +174,7 @@ static void fib6_link_table(struct net *net, struct fib6_table *tb)
*/
rwlock_init(&tb->tb6_lock);
- h = tb->tb6_id & (FIB_TABLE_HASHSZ - 1);
+ h = tb->tb6_id & (FIB6_TABLE_HASHSZ - 1);
/*
* No protection necessary, this is the only list mutatation
@@ -231,7 +225,7 @@ struct fib6_table *fib6_get_table(struct net *net, u32 id)
if (id == 0)
id = RT6_TABLE_MAIN;
- h = id & (FIB_TABLE_HASHSZ - 1);
+ h = id & (FIB6_TABLE_HASHSZ - 1);
rcu_read_lock();
head = &net->ipv6.fib_table_hash[h];
hlist_for_each_entry_rcu(tb, node, head, tb6_hlist) {
@@ -382,7 +376,7 @@ static int inet6_dump_fib(struct sk_buff *skb, struct netlink_callback *cb)
arg.net = net;
w->args = &arg;
- for (h = s_h; h < FIB_TABLE_HASHSZ; h++, s_e = 0) {
+ for (h = s_h; h < FIB6_TABLE_HASHSZ; h++, s_e = 0) {
e = 0;
head = &net->ipv6.fib_table_hash[h];
hlist_for_each_entry(tb, node, head, tb6_hlist) {
@@ -1368,7 +1362,7 @@ void fib6_clean_all(struct net *net, int (*func)(struct rt6_info *, void *arg),
unsigned int h;
rcu_read_lock();
- for (h = 0; h < FIB_TABLE_HASHSZ; h++) {
+ for (h = 0; h < FIB6_TABLE_HASHSZ; h++) {
head = &net->ipv6.fib_table_hash[h];
hlist_for_each_entry_rcu(table, node, head, tb6_hlist) {
write_lock_bh(&table->tb6_lock);
@@ -1483,7 +1477,7 @@ static int fib6_net_init(struct net *net)
if (!net->ipv6.rt6_stats)
goto out_timer;
- net->ipv6.fib_table_hash = kcalloc(FIB_TABLE_HASHSZ,
+ net->ipv6.fib_table_hash = kcalloc(FIB6_TABLE_HASHSZ,
sizeof(*net->ipv6.fib_table_hash),
GFP_KERNEL);
if (!net->ipv6.fib_table_hash)
diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c
index 6d6a4277c67..2d9cbaa67ed 100644
--- a/net/ipv6/ip6_input.c
+++ b/net/ipv6/ip6_input.c
@@ -63,7 +63,7 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt
if (skb->pkt_type == PACKET_OTHERHOST) {
kfree_skb(skb);
- return 0;
+ return NET_RX_DROP;
}
rcu_read_lock();
@@ -133,7 +133,7 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt
if (ipv6_parse_hopopts(skb) < 0) {
IP6_INC_STATS_BH(net, idev, IPSTATS_MIB_INHDRERRORS);
rcu_read_unlock();
- return 0;
+ return NET_RX_DROP;
}
}
@@ -149,7 +149,7 @@ err:
drop:
rcu_read_unlock();
kfree_skb(skb);
- return 0;
+ return NET_RX_DROP;
}
/*
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 87f8419a68f..6ad5aadf81a 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -57,18 +57,6 @@
static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *));
-static __inline__ void ipv6_select_ident(struct sk_buff *skb, struct frag_hdr *fhdr)
-{
- static u32 ipv6_fragmentation_id = 1;
- static DEFINE_SPINLOCK(ip6_id_lock);
-
- spin_lock_bh(&ip6_id_lock);
- fhdr->identification = htonl(ipv6_fragmentation_id);
- if (++ipv6_fragmentation_id == 0)
- ipv6_fragmentation_id = 1;
- spin_unlock_bh(&ip6_id_lock);
-}
-
int __ip6_local_out(struct sk_buff *skb)
{
int len;
@@ -206,7 +194,8 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl,
struct ipv6hdr *hdr;
u8 proto = fl->proto;
int seg_len = skb->len;
- int hlimit, tclass;
+ int hlimit = -1;
+ int tclass = 0;
u32 mtu;
if (opt) {
@@ -249,19 +238,13 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl,
/*
* Fill in the IPv6 header
*/
-
- hlimit = -1;
- if (np)
+ if (np) {
+ tclass = np->tclass;
hlimit = np->hop_limit;
+ }
if (hlimit < 0)
hlimit = ip6_dst_hoplimit(dst);
- tclass = -1;
- if (np)
- tclass = np->tclass;
- if (tclass < 0)
- tclass = 0;
-
*(__be32 *)hdr = htonl(0x60000000 | (tclass << 20)) | fl->fl6_flowlabel;
hdr->payload_len = htons(seg_len);
@@ -706,7 +689,7 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
skb_reset_network_header(skb);
memcpy(skb_network_header(skb), tmp_hdr, hlen);
- ipv6_select_ident(skb, fh);
+ ipv6_select_ident(fh);
fh->nexthdr = nexthdr;
fh->reserved = 0;
fh->frag_off = htons(IP6_MF);
@@ -844,7 +827,7 @@ slow_path:
fh->nexthdr = nexthdr;
fh->reserved = 0;
if (!frag_id) {
- ipv6_select_ident(skb, fh);
+ ipv6_select_ident(fh);
frag_id = fh->identification;
} else
fh->identification = frag_id;
@@ -1087,11 +1070,13 @@ static inline int ip6_ufo_append_data(struct sock *sk,
if (!err) {
struct frag_hdr fhdr;
- /* specify the length of each IP datagram fragment*/
- skb_shinfo(skb)->gso_size = mtu - fragheaderlen -
- sizeof(struct frag_hdr);
+ /* Specify the length of each IPv6 datagram fragment.
+ * It has to be a multiple of 8.
+ */
+ skb_shinfo(skb)->gso_size = (mtu - fragheaderlen -
+ sizeof(struct frag_hdr)) & ~7;
skb_shinfo(skb)->gso_type = SKB_GSO_UDP;
- ipv6_select_ident(skb, &fhdr);
+ ipv6_select_ident(&fhdr);
skb_shinfo(skb)->ip6_frag_id = fhdr.identification;
__skb_queue_tail(&sk->sk_write_queue, skb);
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
index 51f410e7775..a1d6045c469 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -1063,14 +1063,14 @@ ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
goto tx_err;
t->recursion--;
- return 0;
+ return NETDEV_TX_OK;
tx_err:
stats->tx_errors++;
stats->tx_dropped++;
kfree_skb(skb);
t->recursion--;
- return 0;
+ return NETDEV_TX_OK;
}
static void ip6_tnl_set_cap(struct ip6_tnl *t)
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c
index c769f155c69..07ded5075b3 100644
--- a/net/ipv6/ip6mr.c
+++ b/net/ipv6/ip6mr.c
@@ -427,7 +427,7 @@ static int reg_vif_xmit(struct sk_buff *skb, struct net_device *dev)
MRT6MSG_WHOLEPKT);
read_unlock(&mrt_lock);
kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
}
static const struct net_device_ops reg_vif_netdev_ops = {
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c
index a7fdf9a27f1..f5e0682b402 100644
--- a/net/ipv6/ipv6_sockglue.c
+++ b/net/ipv6/ipv6_sockglue.c
@@ -315,6 +315,9 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
goto e_inval;
if (val < -1 || val > 0xff)
goto e_inval;
+ /* RFC 3542, 6.5: default traffic class of 0x0 */
+ if (val == -1)
+ val = 0;
np->tclass = val;
retv = 0;
break;
@@ -1037,8 +1040,6 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname,
case IPV6_TCLASS:
val = np->tclass;
- if (val < 0)
- val = 0;
break;
case IPV6_RECVTCLASS:
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c
index 4b264ed40a8..71c3dacec1e 100644
--- a/net/ipv6/mcast.c
+++ b/net/ipv6/mcast.c
@@ -2107,7 +2107,6 @@ static int ip6_mc_add_src(struct inet6_dev *idev, struct in6_addr *pmca,
for (j=0; j<i; j++)
(void) ip6_mc_del1_src(pmc, sfmode, &psfsrc[i]);
} else if (isexclude != (pmc->mca_sfcount[MCAST_EXCLUDE] != 0)) {
- struct inet6_dev *idev = pmc->idev;
struct ip6_sf_list *psf;
/* filter mode change */
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index 9eb68e92cc1..1ba42bd6557 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -955,8 +955,8 @@ static void ndisc_recv_na(struct sk_buff *skb)
*/
if (skb->pkt_type != PACKET_LOOPBACK)
ND_PRINTK1(KERN_WARNING
- "ICMPv6 NA: someone advertises our address on %s!\n",
- ifp->idev->dev->name);
+ "ICMPv6 NA: someone advertises our address %pI6 on %s!\n",
+ &ifp->addr, ifp->idev->dev->name);
in6_ifa_put(ifp);
return;
}
diff --git a/net/ipv6/proc.c b/net/ipv6/proc.c
index 590ddefb7ff..c9605c3ad91 100644
--- a/net/ipv6/proc.c
+++ b/net/ipv6/proc.c
@@ -101,7 +101,7 @@ static struct snmp_mib snmp6_icmp6_list[] = {
};
/* RFC 4293 v6 ICMPMsgStatsTable; named items for RFC 2466 compatibility */
-static char *icmp6type2name[256] = {
+static const char *const icmp6type2name[256] = {
[ICMPV6_DEST_UNREACH] = "DestUnreachs",
[ICMPV6_PKT_TOOBIG] = "PktTooBigs",
[ICMPV6_TIME_EXCEED] = "TimeExcds",
@@ -144,7 +144,7 @@ static void snmp6_seq_show_icmpv6msg(struct seq_file *seq, void **mib)
/* print by name -- deprecated items */
for (i = 0; i < ICMP6MSG_MIB_MAX; i++) {
int icmptype;
- char *p;
+ const char *p;
icmptype = i & 0xff;
p = icmp6type2name[icmptype];
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index d6c3c1c34b2..506841030fb 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -877,11 +877,8 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,
hlimit = ip6_dst_hoplimit(dst);
}
- if (tclass < 0) {
+ if (tclass < 0)
tclass = np->tclass;
- if (tclass < 0)
- tclass = 0;
- }
if (msg->msg_flags&MSG_CONFIRM)
goto do_confirm;
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c
index 98b7327d094..d335a306a4d 100644
--- a/net/ipv6/sit.c
+++ b/net/ipv6/sit.c
@@ -753,7 +753,7 @@ static int ipip6_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
stats->tx_dropped++;
dev_kfree_skb(skb);
tunnel->recursion--;
- return 0;
+ return NETDEV_TX_OK;
}
if (skb->sk)
skb_set_owner_w(new_skb, skb->sk);
@@ -794,7 +794,7 @@ static int ipip6_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
IPTUNNEL_XMIT();
tunnel->recursion--;
- return 0;
+ return NETDEV_TX_OK;
tx_error_icmp:
dst_link_failure(skb);
@@ -802,7 +802,7 @@ tx_error:
stats->tx_errors++;
dev_kfree_skb(skb);
tunnel->recursion--;
- return 0;
+ return NETDEV_TX_OK;
}
static void ipip6_tunnel_bind_dev(struct net_device *dev)
diff --git a/net/ipv6/sysctl_net_ipv6.c b/net/ipv6/sysctl_net_ipv6.c
index a031034720b..0dc6a4e5ed4 100644
--- a/net/ipv6/sysctl_net_ipv6.c
+++ b/net/ipv6/sysctl_net_ipv6.c
@@ -40,7 +40,7 @@ static ctl_table ipv6_table_template[] = {
{ .ctl_name = 0 }
};
-static ctl_table ipv6_table[] = {
+static ctl_table ipv6_rotable[] = {
{
.ctl_name = NET_IPV6_MLD_MAX_MSF,
.procname = "mld_max_msf",
@@ -130,7 +130,7 @@ int ipv6_sysctl_register(void)
{
int err = -ENOMEM;
- ip6_header = register_net_sysctl_rotable(net_ipv6_ctl_path, ipv6_table);
+ ip6_header = register_net_sysctl_rotable(net_ipv6_ctl_path, ipv6_rotable);
if (ip6_header == NULL)
goto out;
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index 33b59bd92c4..20d2ffc15f0 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -638,6 +638,47 @@ static void udp_v6_flush_pending_frames(struct sock *sk)
}
}
+/**
+ * udp6_hwcsum_outgoing - handle outgoing HW checksumming
+ * @sk: socket we are sending on
+ * @skb: sk_buff containing the filled-in UDP header
+ * (checksum field must be zeroed out)
+ */
+static void udp6_hwcsum_outgoing(struct sock *sk, struct sk_buff *skb,
+ const struct in6_addr *saddr,
+ const struct in6_addr *daddr, int len)
+{
+ unsigned int offset;
+ struct udphdr *uh = udp_hdr(skb);
+ __wsum csum = 0;
+
+ if (skb_queue_len(&sk->sk_write_queue) == 1) {
+ /* Only one fragment on the socket. */
+ skb->csum_start = skb_transport_header(skb) - skb->head;
+ skb->csum_offset = offsetof(struct udphdr, check);
+ uh->check = ~csum_ipv6_magic(saddr, daddr, len, IPPROTO_UDP, 0);
+ } else {
+ /*
+ * HW-checksum won't work as there are two or more
+ * fragments on the socket so that all csums of sk_buffs
+ * should be together
+ */
+ offset = skb_transport_offset(skb);
+ skb->csum = skb_checksum(skb, offset, skb->len - offset, 0);
+
+ skb->ip_summed = CHECKSUM_NONE;
+
+ skb_queue_walk(&sk->sk_write_queue, skb) {
+ csum = csum_add(csum, skb->csum);
+ }
+
+ uh->check = csum_ipv6_magic(saddr, daddr, len, IPPROTO_UDP,
+ csum);
+ if (uh->check == 0)
+ uh->check = CSUM_MANGLED_0;
+ }
+}
+
/*
* Sending
*/
@@ -668,7 +709,11 @@ static int udp_v6_push_pending_frames(struct sock *sk)
if (is_udplite)
csum = udplite_csum_outgoing(sk, skb);
- else
+ else if (skb->ip_summed == CHECKSUM_PARTIAL) { /* UDP hardware csum */
+ udp6_hwcsum_outgoing(sk, skb, &fl->fl6_src, &fl->fl6_dst,
+ up->len);
+ goto send;
+ } else
csum = udp_csum_outgoing(sk, skb);
/* add protocol-dependent pseudo-header */
@@ -677,6 +722,7 @@ static int udp_v6_push_pending_frames(struct sock *sk)
if (uh->check == 0)
uh->check = CSUM_MANGLED_0;
+send:
err = ip6_push_pending_frames(sk);
out:
up->len = 0;
@@ -900,11 +946,8 @@ do_udp_sendmsg:
hlimit = ip6_dst_hoplimit(dst);
}
- if (tclass < 0) {
+ if (tclass < 0)
tclass = np->tclass;
- if (tclass < 0)
- tclass = 0;
- }
if (msg->msg_flags&MSG_CONFIRM)
goto do_confirm;
@@ -1032,9 +1075,102 @@ int compat_udpv6_getsockopt(struct sock *sk, int level, int optname,
}
#endif
+static int udp6_ufo_send_check(struct sk_buff *skb)
+{
+ struct ipv6hdr *ipv6h;
+ struct udphdr *uh;
+
+ if (!pskb_may_pull(skb, sizeof(*uh)))
+ return -EINVAL;
+
+ ipv6h = ipv6_hdr(skb);
+ uh = udp_hdr(skb);
+
+ uh->check = ~csum_ipv6_magic(&ipv6h->saddr, &ipv6h->daddr, skb->len,
+ IPPROTO_UDP, 0);
+ skb->csum_start = skb_transport_header(skb) - skb->head;
+ skb->csum_offset = offsetof(struct udphdr, check);
+ skb->ip_summed = CHECKSUM_PARTIAL;
+ return 0;
+}
+
+static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb, int features)
+{
+ struct sk_buff *segs = ERR_PTR(-EINVAL);
+ unsigned int mss;
+ unsigned int unfrag_ip6hlen, unfrag_len;
+ struct frag_hdr *fptr;
+ u8 *mac_start, *prevhdr;
+ u8 nexthdr;
+ u8 frag_hdr_sz = sizeof(struct frag_hdr);
+ int offset;
+ __wsum csum;
+
+ mss = skb_shinfo(skb)->gso_size;
+ if (unlikely(skb->len <= mss))
+ goto out;
+
+ if (skb_gso_ok(skb, features | NETIF_F_GSO_ROBUST)) {
+ /* Packet is from an untrusted source, reset gso_segs. */
+ int type = skb_shinfo(skb)->gso_type;
+
+ if (unlikely(type & ~(SKB_GSO_UDP | SKB_GSO_DODGY) ||
+ !(type & (SKB_GSO_UDP))))
+ goto out;
+
+ skb_shinfo(skb)->gso_segs = DIV_ROUND_UP(skb->len, mss);
+
+ segs = NULL;
+ goto out;
+ }
+
+ /* Do software UFO. Complete and fill in the UDP checksum as HW cannot
+ * do checksum of UDP packets sent as multiple IP fragments.
+ */
+ offset = skb->csum_start - skb_headroom(skb);
+ csum = skb_checksum(skb, offset, skb->len- offset, 0);
+ offset += skb->csum_offset;
+ *(__sum16 *)(skb->data + offset) = csum_fold(csum);
+ skb->ip_summed = CHECKSUM_NONE;
+
+ /* Check if there is enough headroom to insert fragment header. */
+ if ((skb_headroom(skb) < frag_hdr_sz) &&
+ pskb_expand_head(skb, frag_hdr_sz, 0, GFP_ATOMIC))
+ goto out;
+
+ /* Find the unfragmentable header and shift it left by frag_hdr_sz
+ * bytes to insert fragment header.
+ */
+ unfrag_ip6hlen = ip6_find_1stfragopt(skb, &prevhdr);
+ nexthdr = *prevhdr;
+ *prevhdr = NEXTHDR_FRAGMENT;
+ unfrag_len = skb_network_header(skb) - skb_mac_header(skb) +
+ unfrag_ip6hlen;
+ mac_start = skb_mac_header(skb);
+ memmove(mac_start-frag_hdr_sz, mac_start, unfrag_len);
+
+ skb->mac_header -= frag_hdr_sz;
+ skb->network_header -= frag_hdr_sz;
+
+ fptr = (struct frag_hdr *)(skb_network_header(skb) + unfrag_ip6hlen);
+ fptr->nexthdr = nexthdr;
+ fptr->reserved = 0;
+ ipv6_select_ident(fptr);
+
+ /* Fragment the skb. ipv6 header and the remaining fields of the
+ * fragment header are updated in ipv6_gso_segment()
+ */
+ segs = skb_segment(skb, features);
+
+out:
+ return segs;
+}
+
static struct inet6_protocol udpv6_protocol = {
.handler = udpv6_rcv,
.err_handler = udpv6_err,
+ .gso_send_check = udp6_ufo_send_check,
+ .gso_segment = udp6_ufo_fragment,
.flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL,
};
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c
index 3a3c677bc0f..8ec3d45cd1d 100644
--- a/net/ipv6/xfrm6_policy.c
+++ b/net/ipv6/xfrm6_policy.c
@@ -306,9 +306,26 @@ static void xfrm6_policy_fini(void)
xfrm_policy_unregister_afinfo(&xfrm6_policy_afinfo);
}
+#ifdef CONFIG_SYSCTL
+static struct ctl_table xfrm6_policy_table[] = {
+ {
+ .ctl_name = CTL_UNNUMBERED,
+ .procname = "xfrm6_gc_thresh",
+ .data = &xfrm6_dst_ops.gc_thresh,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = proc_dointvec,
+ },
+ { }
+};
+
+static struct ctl_table_header *sysctl_hdr;
+#endif
+
int __init xfrm6_init(void)
{
int ret;
+ unsigned int gc_thresh;
ret = xfrm6_policy_init();
if (ret)
@@ -317,6 +334,23 @@ int __init xfrm6_init(void)
ret = xfrm6_state_init();
if (ret)
goto out_policy;
+ /*
+ * We need a good default value for the xfrm6 gc threshold.
+ * In ipv4 we set it to the route hash table size * 8, which
+ * is half the size of the maximaum route cache for ipv4. It
+ * would be good to do the same thing for v6, except the table is
+ * constructed differently here. Here each table for a net namespace
+ * can have FIB_TABLE_HASHSZ entries, so lets go with the same
+ * computation that we used for ipv4 here. Also, lets keep the initial
+ * gc_thresh to a minimum of 1024, since, the ipv6 route cache defaults
+ * to that as a minimum as well
+ */
+ gc_thresh = FIB6_TABLE_HASHSZ * 8;
+ xfrm6_dst_ops.gc_thresh = (gc_thresh < 1024) ? 1024 : gc_thresh;
+#ifdef CONFIG_SYSCTL
+ sysctl_hdr = register_net_sysctl_table(&init_net, net_ipv6_ctl_path,
+ xfrm6_policy_table);
+#endif
out:
return ret;
out_policy:
@@ -326,6 +360,10 @@ out_policy:
void xfrm6_fini(void)
{
+#ifdef CONFIG_SYSCTL
+ if (sysctl_hdr)
+ unregister_net_sysctl_table(sysctl_hdr);
+#endif
//xfrm6_input_fini();
xfrm6_policy_fini();
xfrm6_state_fini();
diff --git a/net/irda/ircomm/ircomm_event.c b/net/irda/ircomm/ircomm_event.c
index c35b3ef5c2f..d78554fedba 100644
--- a/net/irda/ircomm/ircomm_event.c
+++ b/net/irda/ircomm/ircomm_event.c
@@ -49,7 +49,7 @@ static int ircomm_state_waitr(struct ircomm_cb *self, IRCOMM_EVENT event,
static int ircomm_state_conn(struct ircomm_cb *self, IRCOMM_EVENT event,
struct sk_buff *skb, struct ircomm_info *info);
-char *ircomm_state[] = {
+const char *const ircomm_state[] = {
"IRCOMM_IDLE",
"IRCOMM_WAITI",
"IRCOMM_WAITR",
@@ -57,7 +57,7 @@ char *ircomm_state[] = {
};
#ifdef CONFIG_IRDA_DEBUG
-static char *ircomm_event[] = {
+static const char *const ircomm_event[] = {
"IRCOMM_CONNECT_REQUEST",
"IRCOMM_CONNECT_RESPONSE",
"IRCOMM_TTP_CONNECT_INDICATION",
diff --git a/net/irda/ircomm/ircomm_tty_attach.c b/net/irda/ircomm/ircomm_tty_attach.c
index 9032a1d1190..eafc010907c 100644
--- a/net/irda/ircomm/ircomm_tty_attach.c
+++ b/net/irda/ircomm/ircomm_tty_attach.c
@@ -80,7 +80,7 @@ static int ircomm_tty_state_ready(struct ircomm_tty_cb *self,
struct sk_buff *skb,
struct ircomm_tty_info *info);
-char *ircomm_tty_state[] = {
+const char *const ircomm_tty_state[] = {
"IRCOMM_TTY_IDLE",
"IRCOMM_TTY_SEARCH",
"IRCOMM_TTY_QUERY_PARAMETERS",
@@ -91,7 +91,7 @@ char *ircomm_tty_state[] = {
};
#ifdef CONFIG_IRDA_DEBUG
-static char *ircomm_tty_event[] = {
+static const char *const ircomm_tty_event[] = {
"IRCOMM_TTY_ATTACH_CABLE",
"IRCOMM_TTY_DETACH_CABLE",
"IRCOMM_TTY_DATA_REQUEST",
diff --git a/net/irda/iriap.c b/net/irda/iriap.c
index 4a105dc32dc..294e34d3517 100644
--- a/net/irda/iriap.c
+++ b/net/irda/iriap.c
@@ -44,7 +44,7 @@
#ifdef CONFIG_IRDA_DEBUG
/* FIXME: This one should go in irlmp.c */
-static const char *ias_charset_types[] = {
+static const char *const ias_charset_types[] = {
"CS_ASCII",
"CS_ISO_8859_1",
"CS_ISO_8859_2",
@@ -966,7 +966,7 @@ static void iriap_watchdog_timer_expired(void *data)
#ifdef CONFIG_PROC_FS
-static const char *ias_value_types[] = {
+static const char *const ias_value_types[] = {
"IAS_MISSING",
"IAS_INTEGER",
"IAS_OCT_SEQ",
diff --git a/net/irda/irlan/irlan_common.c b/net/irda/irlan/irlan_common.c
index 774d73a7685..62116829b81 100644
--- a/net/irda/irlan/irlan_common.c
+++ b/net/irda/irlan/irlan_common.c
@@ -69,14 +69,14 @@ static int eth; /* Use "eth" or "irlan" name for devices */
static int access = ACCESS_PEER; /* PEER, DIRECT or HOSTED */
#ifdef CONFIG_PROC_FS
-static const char *irlan_access[] = {
+static const char *const irlan_access[] = {
"UNKNOWN",
"DIRECT",
"PEER",
"HOSTED"
};
-static const char *irlan_media[] = {
+static const char *const irlan_media[] = {
"UNKNOWN",
"802.3",
"802.5"
diff --git a/net/irda/irlan/irlan_eth.c b/net/irda/irlan/irlan_eth.c
index 724bcf951b8..64230cffcfe 100644
--- a/net/irda/irlan/irlan_eth.c
+++ b/net/irda/irlan/irlan_eth.c
@@ -177,7 +177,7 @@ static int irlan_eth_xmit(struct sk_buff *skb, struct net_device *dev)
/* Did the realloc succeed? */
if (new_skb == NULL)
- return 0;
+ return NETDEV_TX_OK;
/* Use the new skb instead */
skb = new_skb;
@@ -209,7 +209,7 @@ static int irlan_eth_xmit(struct sk_buff *skb, struct net_device *dev)
self->stats.tx_bytes += skb->len;
}
- return 0;
+ return NETDEV_TX_OK;
}
/*
diff --git a/net/irda/irlap.c b/net/irda/irlap.c
index e4965b764b9..356e65b1dc4 100644
--- a/net/irda/irlap.c
+++ b/net/irda/irlap.c
@@ -63,7 +63,7 @@ static void irlap_init_qos_capabilities(struct irlap_cb *self,
struct qos_info *qos_user);
#ifdef CONFIG_IRDA_DEBUG
-static char *lap_reasons[] = {
+static const char *const lap_reasons[] = {
"ERROR, NOT USED",
"LAP_DISC_INDICATION",
"LAP_NO_RESPONSE",
diff --git a/net/irda/irlap_event.c b/net/irda/irlap_event.c
index 16c4ef0f5c1..c5c51959e3c 100644
--- a/net/irda/irlap_event.c
+++ b/net/irda/irlap_event.c
@@ -78,7 +78,7 @@ static int irlap_state_reset_check(struct irlap_cb *, IRLAP_EVENT event,
struct sk_buff *, struct irlap_info *);
#ifdef CONFIG_IRDA_DEBUG
-static const char *irlap_event[] = {
+static const char *const irlap_event[] = {
"DISCOVERY_REQUEST",
"CONNECT_REQUEST",
"CONNECT_RESPONSE",
@@ -120,7 +120,7 @@ static const char *irlap_event[] = {
};
#endif /* CONFIG_IRDA_DEBUG */
-const char *irlap_state[] = {
+const char *const irlap_state[] = {
"LAP_NDM",
"LAP_QUERY",
"LAP_REPLY",
diff --git a/net/irda/irlmp_event.c b/net/irda/irlmp_event.c
index 78cce0cb073..c1fb5db8104 100644
--- a/net/irda/irlmp_event.c
+++ b/net/irda/irlmp_event.c
@@ -33,13 +33,13 @@
#include <net/irda/irlmp_frame.h>
#include <net/irda/irlmp_event.h>
-const char *irlmp_state[] = {
+const char *const irlmp_state[] = {
"LAP_STANDBY",
"LAP_U_CONNECT",
"LAP_ACTIVE",
};
-const char *irlsap_state[] = {
+const char *const irlsap_state[] = {
"LSAP_DISCONNECTED",
"LSAP_CONNECT",
"LSAP_CONNECT_PEND",
@@ -49,7 +49,7 @@ const char *irlsap_state[] = {
};
#ifdef CONFIG_IRDA_DEBUG
-static const char *irlmp_event[] = {
+static const char *const irlmp_event[] = {
"LM_CONNECT_REQUEST",
"LM_CONNECT_CONFIRM",
"LM_CONNECT_RESPONSE",
diff --git a/net/irda/irnetlink.c b/net/irda/irnetlink.c
index 8dd7ed7e7c1..476b307bd80 100644
--- a/net/irda/irnetlink.c
+++ b/net/irda/irnetlink.c
@@ -115,7 +115,7 @@ static int irda_nl_get_mode(struct sk_buff *skb, struct genl_info *info)
genlmsg_end(msg, hdr);
- return genlmsg_unicast(msg, info->snd_pid);
+ return genlmsg_reply(msg, info);
err_out:
nlmsg_free(msg);
diff --git a/net/lapb/lapb_iface.c b/net/lapb/lapb_iface.c
index 2ba1bc4f3c3..bda96d18fd9 100644
--- a/net/lapb/lapb_iface.c
+++ b/net/lapb/lapb_iface.c
@@ -407,7 +407,7 @@ int lapb_data_indication(struct lapb_cb *lapb, struct sk_buff *skb)
return lapb->callbacks.data_indication(lapb->dev, skb);
kfree_skb(skb);
- return NET_RX_CN_HIGH; /* For now; must be != NET_RX_DROP */
+ return NET_RX_SUCCESS; /* For now; must be != NET_RX_DROP */
}
int lapb_data_transmit(struct lapb_cb *lapb, struct sk_buff *skb)
diff --git a/net/llc/llc_proc.c b/net/llc/llc_proc.c
index f97be471fe2..be47ac427f6 100644
--- a/net/llc/llc_proc.c
+++ b/net/llc/llc_proc.c
@@ -143,7 +143,7 @@ out:
return 0;
}
-static char *llc_conn_state_names[] = {
+static const char *const llc_conn_state_names[] = {
[LLC_CONN_STATE_ADM] = "adm",
[LLC_CONN_STATE_SETUP] = "setup",
[LLC_CONN_STATE_NORMAL] = "normal",
diff --git a/net/mac80211/Kconfig b/net/mac80211/Kconfig
index 7836ee92898..9db4ff836a3 100644
--- a/net/mac80211/Kconfig
+++ b/net/mac80211/Kconfig
@@ -6,7 +6,6 @@ config MAC80211
select CRYPTO_ARC4
select CRYPTO_AES
select CRC32
- select WIRELESS_EXT
---help---
This option enables the hardware independent IEEE 802.11
networking stack.
@@ -14,22 +13,6 @@ config MAC80211
comment "CFG80211 needs to be enabled for MAC80211"
depends on CFG80211=n
-config MAC80211_DEFAULT_PS
- bool "enable powersave by default"
- depends on MAC80211
- default y
- help
- This option enables powersave mode by default.
-
- If this causes your applications to misbehave you should fix your
- applications instead -- they need to register their network
- latency requirement, see Documentation/power/pm_qos_interface.txt.
-
-config MAC80211_DEFAULT_PS_VALUE
- int
- default 1 if MAC80211_DEFAULT_PS
- default 0
-
menu "Rate control algorithm selection"
depends on MAC80211 != n
@@ -83,12 +66,12 @@ endmenu
config MAC80211_MESH
bool "Enable mac80211 mesh networking (pre-802.11s) support"
depends on MAC80211 && EXPERIMENTAL
- depends on BROKEN
---help---
This options enables support of Draft 802.11s mesh networking.
- The implementation is based on Draft 1.08 of the Mesh Networking
- amendment. For more information visit http://o11s.org/.
-
+ The implementation is based on Draft 2.08 of the Mesh Networking
+ amendment. However, no compliance with that draft is claimed or even
+ possible, as drafts leave a number of identifiers to be defined after
+ ratification. For more information visit http://o11s.org/.
config MAC80211_LEDS
bool "Enable LED triggers"
@@ -222,3 +205,15 @@ config MAC80211_DEBUG_COUNTERS
and show them in debugfs.
If unsure, say N.
+
+config MAC80211_DRIVER_API_TRACER
+ bool "Driver API tracer"
+ depends on MAC80211_DEBUG_MENU
+ depends on EVENT_TRACING
+ help
+ Say Y here to make mac80211 register with the ftrace
+ framework for the driver API -- you can see which
+ driver methods it is calling then by looking at the
+ trace.
+
+ If unsure, say N.
diff --git a/net/mac80211/Makefile b/net/mac80211/Makefile
index 0e3ab88bb70..9f3cf712932 100644
--- a/net/mac80211/Makefile
+++ b/net/mac80211/Makefile
@@ -3,7 +3,6 @@ obj-$(CONFIG_MAC80211) += mac80211.o
# mac80211 objects
mac80211-y := \
main.o \
- wext.o \
sta_info.o \
wep.o \
wpa.o \
@@ -41,6 +40,9 @@ mac80211-$(CONFIG_MAC80211_MESH) += \
mac80211-$(CONFIG_PM) += pm.o
+mac80211-$(CONFIG_MAC80211_DRIVER_API_TRACER) += driver-trace.o
+CFLAGS_driver-trace.o := -I$(src)
+
# objects for PID algorithm
rc80211_pid-y := rc80211_pid_algo.o
rc80211_pid-$(CONFIG_MAC80211_DEBUGFS) += rc80211_pid_debugfs.o
diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c
index a24e59816b9..bd765f30dba 100644
--- a/net/mac80211/agg-tx.c
+++ b/net/mac80211/agg-tx.c
@@ -391,9 +391,6 @@ static void ieee80211_agg_splice_packets(struct ieee80211_local *local,
if (!skb_queue_empty(&sta->ampdu_mlme.tid_tx[tid]->pending)) {
spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
- /* mark queue as pending, it is stopped already */
- __set_bit(IEEE80211_QUEUE_STOP_REASON_PENDING,
- &local->queue_stop_reasons[queue]);
/* copy over remaining packets */
skb_queue_splice_tail_init(
&sta->ampdu_mlme.tid_tx[tid]->pending,
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 3f47276caeb..5608f6c6841 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -57,36 +57,21 @@ static int ieee80211_add_iface(struct wiphy *wiphy, char *name,
return 0;
}
-static int ieee80211_del_iface(struct wiphy *wiphy, int ifindex)
+static int ieee80211_del_iface(struct wiphy *wiphy, struct net_device *dev)
{
- struct net_device *dev;
- struct ieee80211_sub_if_data *sdata;
-
- /* we're under RTNL */
- dev = __dev_get_by_index(&init_net, ifindex);
- if (!dev)
- return -ENODEV;
-
- sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-
- ieee80211_if_remove(sdata);
+ ieee80211_if_remove(IEEE80211_DEV_TO_SUB_IF(dev));
return 0;
}
-static int ieee80211_change_iface(struct wiphy *wiphy, int ifindex,
+static int ieee80211_change_iface(struct wiphy *wiphy,
+ struct net_device *dev,
enum nl80211_iftype type, u32 *flags,
struct vif_params *params)
{
- struct net_device *dev;
struct ieee80211_sub_if_data *sdata;
int ret;
- /* we're under RTNL */
- dev = __dev_get_by_index(&init_net, ifindex);
- if (!dev)
- return -ENODEV;
-
if (!nl80211_type_check(type))
return -EINVAL;
@@ -338,6 +323,8 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
{
struct ieee80211_sub_if_data *sdata = sta->sdata;
+ sinfo->generation = sdata->local->sta_generation;
+
sinfo->filled = STATION_INFO_INACTIVE_TIME |
STATION_INFO_RX_BYTES |
STATION_INFO_TX_BYTES |
@@ -924,6 +911,8 @@ static void mpath_set_pinfo(struct mesh_path *mpath, u8 *next_hop,
else
memset(next_hop, 0, ETH_ALEN);
+ pinfo->generation = mesh_paths_generation;
+
pinfo->filled = MPATH_INFO_FRAME_QLEN |
MPATH_INFO_DSN |
MPATH_INFO_METRIC |
@@ -1177,123 +1166,29 @@ static int ieee80211_scan(struct wiphy *wiphy,
static int ieee80211_auth(struct wiphy *wiphy, struct net_device *dev,
struct cfg80211_auth_request *req)
{
- struct ieee80211_sub_if_data *sdata;
-
- sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-
- switch (req->auth_type) {
- case NL80211_AUTHTYPE_OPEN_SYSTEM:
- sdata->u.mgd.auth_algs = IEEE80211_AUTH_ALG_OPEN;
- break;
- case NL80211_AUTHTYPE_SHARED_KEY:
- sdata->u.mgd.auth_algs = IEEE80211_AUTH_ALG_SHARED_KEY;
- break;
- case NL80211_AUTHTYPE_FT:
- sdata->u.mgd.auth_algs = IEEE80211_AUTH_ALG_FT;
- break;
- case NL80211_AUTHTYPE_NETWORK_EAP:
- sdata->u.mgd.auth_algs = IEEE80211_AUTH_ALG_LEAP;
- break;
- default:
- return -EOPNOTSUPP;
- }
-
- memcpy(sdata->u.mgd.bssid, req->peer_addr, ETH_ALEN);
- sdata->u.mgd.flags &= ~IEEE80211_STA_AUTO_BSSID_SEL;
- sdata->u.mgd.flags |= IEEE80211_STA_BSSID_SET;
-
- /* TODO: req->chan */
- sdata->u.mgd.flags |= IEEE80211_STA_AUTO_CHANNEL_SEL;
-
- if (req->ssid) {
- sdata->u.mgd.flags |= IEEE80211_STA_SSID_SET;
- memcpy(sdata->u.mgd.ssid, req->ssid, req->ssid_len);
- sdata->u.mgd.ssid_len = req->ssid_len;
- sdata->u.mgd.flags &= ~IEEE80211_STA_AUTO_SSID_SEL;
- }
-
- kfree(sdata->u.mgd.sme_auth_ie);
- sdata->u.mgd.sme_auth_ie = NULL;
- sdata->u.mgd.sme_auth_ie_len = 0;
- if (req->ie) {
- sdata->u.mgd.sme_auth_ie = kmalloc(req->ie_len, GFP_KERNEL);
- if (sdata->u.mgd.sme_auth_ie == NULL)
- return -ENOMEM;
- memcpy(sdata->u.mgd.sme_auth_ie, req->ie, req->ie_len);
- sdata->u.mgd.sme_auth_ie_len = req->ie_len;
- }
-
- sdata->u.mgd.flags |= IEEE80211_STA_EXT_SME;
- sdata->u.mgd.state = IEEE80211_STA_MLME_DIRECT_PROBE;
- ieee80211_sta_req_auth(sdata);
- return 0;
+ return ieee80211_mgd_auth(IEEE80211_DEV_TO_SUB_IF(dev), req);
}
static int ieee80211_assoc(struct wiphy *wiphy, struct net_device *dev,
struct cfg80211_assoc_request *req)
{
- struct ieee80211_sub_if_data *sdata;
- int ret;
-
- sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-
- if (memcmp(sdata->u.mgd.bssid, req->peer_addr, ETH_ALEN) != 0 ||
- !(sdata->u.mgd.flags & IEEE80211_STA_AUTHENTICATED))
- return -ENOLINK; /* not authenticated */
-
- sdata->u.mgd.flags &= ~IEEE80211_STA_AUTO_BSSID_SEL;
- sdata->u.mgd.flags |= IEEE80211_STA_BSSID_SET;
-
- /* TODO: req->chan */
- sdata->u.mgd.flags |= IEEE80211_STA_AUTO_CHANNEL_SEL;
-
- if (req->ssid) {
- sdata->u.mgd.flags |= IEEE80211_STA_SSID_SET;
- memcpy(sdata->u.mgd.ssid, req->ssid, req->ssid_len);
- sdata->u.mgd.ssid_len = req->ssid_len;
- sdata->u.mgd.flags &= ~IEEE80211_STA_AUTO_SSID_SEL;
- } else
- sdata->u.mgd.flags |= IEEE80211_STA_AUTO_SSID_SEL;
-
- ret = ieee80211_sta_set_extra_ie(sdata, req->ie, req->ie_len);
- if (ret && ret != -EALREADY)
- return ret;
-
- if (req->use_mfp) {
- sdata->u.mgd.mfp = IEEE80211_MFP_REQUIRED;
- sdata->u.mgd.flags |= IEEE80211_STA_MFP_ENABLED;
- } else {
- sdata->u.mgd.mfp = IEEE80211_MFP_DISABLED;
- sdata->u.mgd.flags &= ~IEEE80211_STA_MFP_ENABLED;
- }
-
- if (req->control_port)
- sdata->u.mgd.flags |= IEEE80211_STA_CONTROL_PORT;
- else
- sdata->u.mgd.flags &= ~IEEE80211_STA_CONTROL_PORT;
-
- sdata->u.mgd.flags |= IEEE80211_STA_EXT_SME;
- sdata->u.mgd.state = IEEE80211_STA_MLME_ASSOCIATE;
- ieee80211_sta_req_auth(sdata);
- return 0;
+ return ieee80211_mgd_assoc(IEEE80211_DEV_TO_SUB_IF(dev), req);
}
static int ieee80211_deauth(struct wiphy *wiphy, struct net_device *dev,
- struct cfg80211_deauth_request *req)
+ struct cfg80211_deauth_request *req,
+ void *cookie)
{
- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-
- /* TODO: req->ie, req->peer_addr */
- return ieee80211_sta_deauthenticate(sdata, req->reason_code);
+ return ieee80211_mgd_deauth(IEEE80211_DEV_TO_SUB_IF(dev),
+ req, cookie);
}
static int ieee80211_disassoc(struct wiphy *wiphy, struct net_device *dev,
- struct cfg80211_disassoc_request *req)
+ struct cfg80211_disassoc_request *req,
+ void *cookie)
{
- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-
- /* TODO: req->ie, req->peer_addr */
- return ieee80211_sta_disassociate(sdata, req->reason_code);
+ return ieee80211_mgd_disassoc(IEEE80211_DEV_TO_SUB_IF(dev),
+ req, cookie);
}
static int ieee80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
@@ -1374,6 +1269,16 @@ static int ieee80211_get_tx_power(struct wiphy *wiphy, int *dbm)
return 0;
}
+static int ieee80211_set_wds_peer(struct wiphy *wiphy, struct net_device *dev,
+ u8 *addr)
+{
+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+
+ memcpy(&sdata->u.wds.remote_addr, addr, ETH_ALEN);
+
+ return 0;
+}
+
static void ieee80211_rfkill_poll(struct wiphy *wiphy)
{
struct ieee80211_local *local = wiphy_priv(wiphy);
@@ -1381,6 +1286,85 @@ static void ieee80211_rfkill_poll(struct wiphy *wiphy)
drv_rfkill_poll(local);
}
+#ifdef CONFIG_NL80211_TESTMODE
+static int ieee80211_testmode_cmd(struct wiphy *wiphy, void *data, int len)
+{
+ struct ieee80211_local *local = wiphy_priv(wiphy);
+
+ if (!local->ops->testmode_cmd)
+ return -EOPNOTSUPP;
+
+ return local->ops->testmode_cmd(&local->hw, data, len);
+}
+#endif
+
+static int ieee80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev,
+ bool enabled, int timeout)
+{
+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+ struct ieee80211_conf *conf = &local->hw.conf;
+
+ if (!(local->hw.flags & IEEE80211_HW_SUPPORTS_PS))
+ return -EOPNOTSUPP;
+
+ if (enabled == sdata->u.mgd.powersave &&
+ timeout == conf->dynamic_ps_timeout)
+ return 0;
+
+ sdata->u.mgd.powersave = enabled;
+ conf->dynamic_ps_timeout = timeout;
+
+ if (local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS)
+ ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
+
+ ieee80211_recalc_ps(local, -1);
+
+ return 0;
+}
+
+static int ieee80211_set_bitrate_mask(struct wiphy *wiphy,
+ struct net_device *dev,
+ const u8 *addr,
+ const struct cfg80211_bitrate_mask *mask)
+{
+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+ int i, err = -EINVAL;
+ u32 target_rate;
+ struct ieee80211_supported_band *sband;
+
+ sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
+
+ /* target_rate = -1, rate->fixed = 0 means auto only, so use all rates
+ * target_rate = X, rate->fixed = 1 means only rate X
+ * target_rate = X, rate->fixed = 0 means all rates <= X */
+ sdata->max_ratectrl_rateidx = -1;
+ sdata->force_unicast_rateidx = -1;
+
+ if (mask->fixed)
+ target_rate = mask->fixed / 100;
+ else if (mask->maxrate)
+ target_rate = mask->maxrate / 100;
+ else
+ return 0;
+
+ for (i=0; i< sband->n_bitrates; i++) {
+ struct ieee80211_rate *brate = &sband->bitrates[i];
+ int this_rate = brate->bitrate;
+
+ if (target_rate == this_rate) {
+ sdata->max_ratectrl_rateidx = i;
+ if (mask->fixed)
+ sdata->force_unicast_rateidx = i;
+ err = 0;
+ break;
+ }
+ }
+
+ return err;
+}
+
struct cfg80211_ops mac80211_config_ops = {
.add_virtual_intf = ieee80211_add_iface,
.del_virtual_intf = ieee80211_del_iface,
@@ -1422,5 +1406,9 @@ struct cfg80211_ops mac80211_config_ops = {
.set_wiphy_params = ieee80211_set_wiphy_params,
.set_tx_power = ieee80211_set_tx_power,
.get_tx_power = ieee80211_get_tx_power,
+ .set_wds_peer = ieee80211_set_wds_peer,
.rfkill_poll = ieee80211_rfkill_poll,
+ CFG80211_TESTMODE_CMD(ieee80211_testmode_cmd)
+ .set_power_mgmt = ieee80211_set_power_mgmt,
+ .set_bitrate_mask = ieee80211_set_bitrate_mask,
};
diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c
index 6c439cd5cce..96991b68f04 100644
--- a/net/mac80211/debugfs.c
+++ b/net/mac80211/debugfs.c
@@ -175,7 +175,7 @@ static ssize_t queues_read(struct file *file, char __user *user_buf,
for (q = 0; q < local->hw.queues; q++)
res += sprintf(buf + res, "%02d: %#.8lx/%d\n", q,
local->queue_stop_reasons[q],
- __netif_subqueue_stopped(local->mdev, q));
+ skb_queue_len(&local->pending[q]));
spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
return simple_read_from_buffer(user_buf, count, ppos, buf, res);
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c
index e3420329f4e..e9ec6cae2d3 100644
--- a/net/mac80211/debugfs_netdev.c
+++ b/net/mac80211/debugfs_netdev.c
@@ -95,33 +95,9 @@ IEEE80211_IF_FILE(force_unicast_rateidx, force_unicast_rateidx, DEC);
IEEE80211_IF_FILE(max_ratectrl_rateidx, max_ratectrl_rateidx, DEC);
/* STA attributes */
-IEEE80211_IF_FILE(state, u.mgd.state, DEC);
IEEE80211_IF_FILE(bssid, u.mgd.bssid, MAC);
-IEEE80211_IF_FILE(prev_bssid, u.mgd.prev_bssid, MAC);
-IEEE80211_IF_FILE(ssid_len, u.mgd.ssid_len, SIZE);
IEEE80211_IF_FILE(aid, u.mgd.aid, DEC);
-IEEE80211_IF_FILE(ap_capab, u.mgd.ap_capab, HEX);
IEEE80211_IF_FILE(capab, u.mgd.capab, HEX);
-IEEE80211_IF_FILE(extra_ie_len, u.mgd.extra_ie_len, SIZE);
-IEEE80211_IF_FILE(auth_tries, u.mgd.auth_tries, DEC);
-IEEE80211_IF_FILE(assoc_tries, u.mgd.assoc_tries, DEC);
-IEEE80211_IF_FILE(auth_algs, u.mgd.auth_algs, HEX);
-IEEE80211_IF_FILE(auth_alg, u.mgd.auth_alg, DEC);
-IEEE80211_IF_FILE(auth_transaction, u.mgd.auth_transaction, DEC);
-
-static ssize_t ieee80211_if_fmt_flags(
- const struct ieee80211_sub_if_data *sdata, char *buf, int buflen)
-{
- return scnprintf(buf, buflen, "%s%s%s%s%s%s%s\n",
- sdata->u.mgd.flags & IEEE80211_STA_SSID_SET ? "SSID\n" : "",
- sdata->u.mgd.flags & IEEE80211_STA_BSSID_SET ? "BSSID\n" : "",
- sdata->u.mgd.flags & IEEE80211_STA_PREV_BSSID_SET ? "prev BSSID\n" : "",
- sdata->u.mgd.flags & IEEE80211_STA_AUTHENTICATED ? "AUTH\n" : "",
- sdata->u.mgd.flags & IEEE80211_STA_ASSOCIATED ? "ASSOC\n" : "",
- sdata->u.mgd.flags & IEEE80211_STA_PROBEREQ_POLL ? "PROBEREQ POLL\n" : "",
- sdata->vif.bss_conf.use_cts_prot ? "CTS prot\n" : "");
-}
-__IEEE80211_IF_FILE(flags);
/* AP attributes */
IEEE80211_IF_FILE(num_sta_ps, u.ap.num_sta_ps, ATOMIC);
@@ -184,20 +160,9 @@ static void add_sta_files(struct ieee80211_sub_if_data *sdata)
DEBUGFS_ADD(force_unicast_rateidx, sta);
DEBUGFS_ADD(max_ratectrl_rateidx, sta);
- DEBUGFS_ADD(state, sta);
DEBUGFS_ADD(bssid, sta);
- DEBUGFS_ADD(prev_bssid, sta);
- DEBUGFS_ADD(ssid_len, sta);
DEBUGFS_ADD(aid, sta);
- DEBUGFS_ADD(ap_capab, sta);
DEBUGFS_ADD(capab, sta);
- DEBUGFS_ADD(extra_ie_len, sta);
- DEBUGFS_ADD(auth_tries, sta);
- DEBUGFS_ADD(assoc_tries, sta);
- DEBUGFS_ADD(auth_algs, sta);
- DEBUGFS_ADD(auth_alg, sta);
- DEBUGFS_ADD(auth_transaction, sta);
- DEBUGFS_ADD(flags, sta);
}
static void add_ap_files(struct ieee80211_sub_if_data *sdata)
@@ -317,20 +282,9 @@ static void del_sta_files(struct ieee80211_sub_if_data *sdata)
DEBUGFS_DEL(force_unicast_rateidx, sta);
DEBUGFS_DEL(max_ratectrl_rateidx, sta);
- DEBUGFS_DEL(state, sta);
DEBUGFS_DEL(bssid, sta);
- DEBUGFS_DEL(prev_bssid, sta);
- DEBUGFS_DEL(ssid_len, sta);
DEBUGFS_DEL(aid, sta);
- DEBUGFS_DEL(ap_capab, sta);
DEBUGFS_DEL(capab, sta);
- DEBUGFS_DEL(extra_ie_len, sta);
- DEBUGFS_DEL(auth_tries, sta);
- DEBUGFS_DEL(assoc_tries, sta);
- DEBUGFS_DEL(auth_algs, sta);
- DEBUGFS_DEL(auth_alg, sta);
- DEBUGFS_DEL(auth_transaction, sta);
- DEBUGFS_DEL(flags, sta);
}
static void del_ap_files(struct ieee80211_sub_if_data *sdata)
diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c
index 90230c718b5..33a2e892115 100644
--- a/net/mac80211/debugfs_sta.c
+++ b/net/mac80211/debugfs_sta.c
@@ -120,45 +120,38 @@ STA_OPS(last_seq_ctrl);
static ssize_t sta_agg_status_read(struct file *file, char __user *userbuf,
size_t count, loff_t *ppos)
{
- char buf[768], *p = buf;
+ char buf[30 + STA_TID_NUM * 70], *p = buf;
int i;
struct sta_info *sta = file->private_data;
- p += scnprintf(p, sizeof(buf)+buf-p, "Agg state for STA is:\n");
- p += scnprintf(p, sizeof(buf)+buf-p, " STA next dialog_token is %d \n "
- "TIDs info is: \n TID :",
- (sta->ampdu_mlme.dialog_token_allocator + 1));
- for (i = 0; i < STA_TID_NUM; i++)
- p += scnprintf(p, sizeof(buf)+buf-p, "%5d", i);
-
- p += scnprintf(p, sizeof(buf)+buf-p, "\n RX :");
- for (i = 0; i < STA_TID_NUM; i++)
- p += scnprintf(p, sizeof(buf)+buf-p, "%5d",
- sta->ampdu_mlme.tid_state_rx[i]);
-
- p += scnprintf(p, sizeof(buf)+buf-p, "\n DTKN:");
- for (i = 0; i < STA_TID_NUM; i++)
- p += scnprintf(p, sizeof(buf)+buf-p, "%5d",
- sta->ampdu_mlme.tid_state_rx[i] ?
- sta->ampdu_mlme.tid_rx[i]->dialog_token : 0);
-
- p += scnprintf(p, sizeof(buf)+buf-p, "\n TX :");
- for (i = 0; i < STA_TID_NUM; i++)
- p += scnprintf(p, sizeof(buf)+buf-p, "%5d",
- sta->ampdu_mlme.tid_state_tx[i]);
-
- p += scnprintf(p, sizeof(buf)+buf-p, "\n DTKN:");
- for (i = 0; i < STA_TID_NUM; i++)
- p += scnprintf(p, sizeof(buf)+buf-p, "%5d",
- sta->ampdu_mlme.tid_state_tx[i] ?
- sta->ampdu_mlme.tid_tx[i]->dialog_token : 0);
-
- p += scnprintf(p, sizeof(buf)+buf-p, "\n SSN :");
- for (i = 0; i < STA_TID_NUM; i++)
- p += scnprintf(p, sizeof(buf)+buf-p, "%5d",
- sta->ampdu_mlme.tid_state_tx[i] ?
- sta->ampdu_mlme.tid_tx[i]->ssn : 0);
- p += scnprintf(p, sizeof(buf)+buf-p, "\n");
+ spin_lock_bh(&sta->lock);
+ p += scnprintf(p, sizeof(buf)+buf-p, "next dialog_token is %#02x\n",
+ sta->ampdu_mlme.dialog_token_allocator + 1);
+ for (i = 0; i < STA_TID_NUM; i++) {
+ p += scnprintf(p, sizeof(buf)+buf-p, "TID %02d:", i);
+ p += scnprintf(p, sizeof(buf)+buf-p, " RX=%x",
+ sta->ampdu_mlme.tid_state_rx[i]);
+ p += scnprintf(p, sizeof(buf)+buf-p, "/DTKN=%#.2x",
+ sta->ampdu_mlme.tid_state_rx[i] ?
+ sta->ampdu_mlme.tid_rx[i]->dialog_token : 0);
+ p += scnprintf(p, sizeof(buf)+buf-p, "/SSN=%#.3x",
+ sta->ampdu_mlme.tid_state_rx[i] ?
+ sta->ampdu_mlme.tid_rx[i]->ssn : 0);
+
+ p += scnprintf(p, sizeof(buf)+buf-p, " TX=%x",
+ sta->ampdu_mlme.tid_state_tx[i]);
+ p += scnprintf(p, sizeof(buf)+buf-p, "/DTKN=%#.2x",
+ sta->ampdu_mlme.tid_state_tx[i] ?
+ sta->ampdu_mlme.tid_tx[i]->dialog_token : 0);
+ p += scnprintf(p, sizeof(buf)+buf-p, "/SSN=%#.3x",
+ sta->ampdu_mlme.tid_state_tx[i] ?
+ sta->ampdu_mlme.tid_tx[i]->ssn : 0);
+ p += scnprintf(p, sizeof(buf)+buf-p, "/pending=%03d",
+ sta->ampdu_mlme.tid_state_tx[i] ?
+ skb_queue_len(&sta->ampdu_mlme.tid_tx[i]->pending) : 0);
+ p += scnprintf(p, sizeof(buf)+buf-p, "\n");
+ }
+ spin_unlock_bh(&sta->lock);
return simple_read_from_buffer(userbuf, count, ppos, buf, p - buf);
}
@@ -203,6 +196,22 @@ void ieee80211_sta_debugfs_add(struct sta_info *sta)
DEBUGFS_ADD(inactive_ms);
DEBUGFS_ADD(last_seq_ctrl);
DEBUGFS_ADD(agg_status);
+ DEBUGFS_ADD(dev);
+ DEBUGFS_ADD(rx_packets);
+ DEBUGFS_ADD(tx_packets);
+ DEBUGFS_ADD(rx_bytes);
+ DEBUGFS_ADD(tx_bytes);
+ DEBUGFS_ADD(rx_duplicates);
+ DEBUGFS_ADD(rx_fragments);
+ DEBUGFS_ADD(rx_dropped);
+ DEBUGFS_ADD(tx_fragments);
+ DEBUGFS_ADD(tx_filtered);
+ DEBUGFS_ADD(tx_retry_failed);
+ DEBUGFS_ADD(tx_retry_count);
+ DEBUGFS_ADD(last_signal);
+ DEBUGFS_ADD(last_qual);
+ DEBUGFS_ADD(last_noise);
+ DEBUGFS_ADD(wep_weak_iv_count);
}
void ieee80211_sta_debugfs_remove(struct sta_info *sta)
@@ -212,6 +221,23 @@ void ieee80211_sta_debugfs_remove(struct sta_info *sta)
DEBUGFS_DEL(inactive_ms);
DEBUGFS_DEL(last_seq_ctrl);
DEBUGFS_DEL(agg_status);
+ DEBUGFS_DEL(aid);
+ DEBUGFS_DEL(dev);
+ DEBUGFS_DEL(rx_packets);
+ DEBUGFS_DEL(tx_packets);
+ DEBUGFS_DEL(rx_bytes);
+ DEBUGFS_DEL(tx_bytes);
+ DEBUGFS_DEL(rx_duplicates);
+ DEBUGFS_DEL(rx_fragments);
+ DEBUGFS_DEL(rx_dropped);
+ DEBUGFS_DEL(tx_fragments);
+ DEBUGFS_DEL(tx_filtered);
+ DEBUGFS_DEL(tx_retry_failed);
+ DEBUGFS_DEL(tx_retry_count);
+ DEBUGFS_DEL(last_signal);
+ DEBUGFS_DEL(last_qual);
+ DEBUGFS_DEL(last_noise);
+ DEBUGFS_DEL(wep_weak_iv_count);
debugfs_remove(sta->debugfs.dir);
sta->debugfs.dir = NULL;
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
index b13446afd48..4100c361a99 100644
--- a/net/mac80211/driver-ops.h
+++ b/net/mac80211/driver-ops.h
@@ -3,6 +3,7 @@
#include <net/mac80211.h>
#include "ieee80211_i.h"
+#include "driver-trace.h"
static inline int drv_tx(struct ieee80211_local *local, struct sk_buff *skb)
{
@@ -11,29 +12,37 @@ static inline int drv_tx(struct ieee80211_local *local, struct sk_buff *skb)
static inline int drv_start(struct ieee80211_local *local)
{
- return local->ops->start(&local->hw);
+ int ret = local->ops->start(&local->hw);
+ trace_drv_start(local, ret);
+ return ret;
}
static inline void drv_stop(struct ieee80211_local *local)
{
local->ops->stop(&local->hw);
+ trace_drv_stop(local);
}
static inline int drv_add_interface(struct ieee80211_local *local,
struct ieee80211_if_init_conf *conf)
{
- return local->ops->add_interface(&local->hw, conf);
+ int ret = local->ops->add_interface(&local->hw, conf);
+ trace_drv_add_interface(local, conf->mac_addr, conf->vif, ret);
+ return ret;
}
static inline void drv_remove_interface(struct ieee80211_local *local,
struct ieee80211_if_init_conf *conf)
{
local->ops->remove_interface(&local->hw, conf);
+ trace_drv_remove_interface(local, conf->mac_addr, conf->vif);
}
static inline int drv_config(struct ieee80211_local *local, u32 changed)
{
- return local->ops->config(&local->hw, changed);
+ int ret = local->ops->config(&local->hw, changed);
+ trace_drv_config(local, changed, ret);
+ return ret;
}
static inline void drv_bss_info_changed(struct ieee80211_local *local,
@@ -43,6 +52,7 @@ static inline void drv_bss_info_changed(struct ieee80211_local *local,
{
if (local->ops->bss_info_changed)
local->ops->bss_info_changed(&local->hw, vif, info, changed);
+ trace_drv_bss_info_changed(local, vif, info, changed);
}
static inline void drv_configure_filter(struct ieee80211_local *local,
@@ -53,14 +63,18 @@ static inline void drv_configure_filter(struct ieee80211_local *local,
{
local->ops->configure_filter(&local->hw, changed_flags, total_flags,
mc_count, mc_list);
+ trace_drv_configure_filter(local, changed_flags, total_flags,
+ mc_count);
}
static inline int drv_set_tim(struct ieee80211_local *local,
struct ieee80211_sta *sta, bool set)
{
+ int ret = 0;
if (local->ops->set_tim)
- return local->ops->set_tim(&local->hw, sta, set);
- return 0;
+ ret = local->ops->set_tim(&local->hw, sta, set);
+ trace_drv_set_tim(local, sta, set, ret);
+ return ret;
}
static inline int drv_set_key(struct ieee80211_local *local,
@@ -68,7 +82,9 @@ static inline int drv_set_key(struct ieee80211_local *local,
struct ieee80211_sta *sta,
struct ieee80211_key_conf *key)
{
- return local->ops->set_key(&local->hw, cmd, vif, sta, key);
+ int ret = local->ops->set_key(&local->hw, cmd, vif, sta, key);
+ trace_drv_set_key(local, cmd, vif, sta, key, ret);
+ return ret;
}
static inline void drv_update_tkip_key(struct ieee80211_local *local,
@@ -79,32 +95,41 @@ static inline void drv_update_tkip_key(struct ieee80211_local *local,
if (local->ops->update_tkip_key)
local->ops->update_tkip_key(&local->hw, conf, address,
iv32, phase1key);
+ trace_drv_update_tkip_key(local, conf, address, iv32);
}
static inline int drv_hw_scan(struct ieee80211_local *local,
struct cfg80211_scan_request *req)
{
- return local->ops->hw_scan(&local->hw, req);
+ int ret = local->ops->hw_scan(&local->hw, req);
+ trace_drv_hw_scan(local, req, ret);
+ return ret;
}
static inline void drv_sw_scan_start(struct ieee80211_local *local)
{
if (local->ops->sw_scan_start)
local->ops->sw_scan_start(&local->hw);
+ trace_drv_sw_scan_start(local);
}
static inline void drv_sw_scan_complete(struct ieee80211_local *local)
{
if (local->ops->sw_scan_complete)
local->ops->sw_scan_complete(&local->hw);
+ trace_drv_sw_scan_complete(local);
}
static inline int drv_get_stats(struct ieee80211_local *local,
struct ieee80211_low_level_stats *stats)
{
- if (!local->ops->get_stats)
- return -EOPNOTSUPP;
- return local->ops->get_stats(&local->hw, stats);
+ int ret = -EOPNOTSUPP;
+
+ if (local->ops->get_stats)
+ ret = local->ops->get_stats(&local->hw, stats);
+ trace_drv_get_stats(local, stats, ret);
+
+ return ret;
}
static inline void drv_get_tkip_seq(struct ieee80211_local *local,
@@ -112,14 +137,17 @@ static inline void drv_get_tkip_seq(struct ieee80211_local *local,
{
if (local->ops->get_tkip_seq)
local->ops->get_tkip_seq(&local->hw, hw_key_idx, iv32, iv16);
+ trace_drv_get_tkip_seq(local, hw_key_idx, iv32, iv16);
}
static inline int drv_set_rts_threshold(struct ieee80211_local *local,
u32 value)
{
+ int ret = 0;
if (local->ops->set_rts_threshold)
- return local->ops->set_rts_threshold(&local->hw, value);
- return 0;
+ ret = local->ops->set_rts_threshold(&local->hw, value);
+ trace_drv_set_rts_threshold(local, value, ret);
+ return ret;
}
static inline void drv_sta_notify(struct ieee80211_local *local,
@@ -129,46 +157,57 @@ static inline void drv_sta_notify(struct ieee80211_local *local,
{
if (local->ops->sta_notify)
local->ops->sta_notify(&local->hw, vif, cmd, sta);
+ trace_drv_sta_notify(local, vif, cmd, sta);
}
static inline int drv_conf_tx(struct ieee80211_local *local, u16 queue,
const struct ieee80211_tx_queue_params *params)
{
+ int ret = -EOPNOTSUPP;
if (local->ops->conf_tx)
- return local->ops->conf_tx(&local->hw, queue, params);
- return -EOPNOTSUPP;
+ ret = local->ops->conf_tx(&local->hw, queue, params);
+ trace_drv_conf_tx(local, queue, params, ret);
+ return ret;
}
static inline int drv_get_tx_stats(struct ieee80211_local *local,
struct ieee80211_tx_queue_stats *stats)
{
- return local->ops->get_tx_stats(&local->hw, stats);
+ int ret = local->ops->get_tx_stats(&local->hw, stats);
+ trace_drv_get_tx_stats(local, stats, ret);
+ return ret;
}
static inline u64 drv_get_tsf(struct ieee80211_local *local)
{
+ u64 ret = -1ULL;
if (local->ops->get_tsf)
- return local->ops->get_tsf(&local->hw);
- return -1ULL;
+ ret = local->ops->get_tsf(&local->hw);
+ trace_drv_get_tsf(local, ret);
+ return ret;
}
static inline void drv_set_tsf(struct ieee80211_local *local, u64 tsf)
{
if (local->ops->set_tsf)
local->ops->set_tsf(&local->hw, tsf);
+ trace_drv_set_tsf(local, tsf);
}
static inline void drv_reset_tsf(struct ieee80211_local *local)
{
if (local->ops->reset_tsf)
local->ops->reset_tsf(&local->hw);
+ trace_drv_reset_tsf(local);
}
static inline int drv_tx_last_beacon(struct ieee80211_local *local)
{
+ int ret = 1;
if (local->ops->tx_last_beacon)
- return local->ops->tx_last_beacon(&local->hw);
- return 1;
+ ret = local->ops->tx_last_beacon(&local->hw);
+ trace_drv_tx_last_beacon(local, ret);
+ return ret;
}
static inline int drv_ampdu_action(struct ieee80211_local *local,
@@ -176,10 +215,12 @@ static inline int drv_ampdu_action(struct ieee80211_local *local,
struct ieee80211_sta *sta, u16 tid,
u16 *ssn)
{
+ int ret = -EOPNOTSUPP;
if (local->ops->ampdu_action)
- return local->ops->ampdu_action(&local->hw, action,
- sta, tid, ssn);
- return -EOPNOTSUPP;
+ ret = local->ops->ampdu_action(&local->hw, action,
+ sta, tid, ssn);
+ trace_drv_ampdu_action(local, action, sta, tid, ssn, ret);
+ return ret;
}
diff --git a/net/mac80211/driver-trace.c b/net/mac80211/driver-trace.c
new file mode 100644
index 00000000000..8ed8711b1a6
--- /dev/null
+++ b/net/mac80211/driver-trace.c
@@ -0,0 +1,9 @@
+/* bug in tracepoint.h, it should include this */
+#include <linux/module.h>
+
+/* sparse isn't too happy with all macros... */
+#ifndef __CHECKER__
+#include "driver-ops.h"
+#define CREATE_TRACE_POINTS
+#include "driver-trace.h"
+#endif
diff --git a/net/mac80211/driver-trace.h b/net/mac80211/driver-trace.h
new file mode 100644
index 00000000000..5a10da2d70f
--- /dev/null
+++ b/net/mac80211/driver-trace.h
@@ -0,0 +1,648 @@
+#if !defined(__MAC80211_DRIVER_TRACE) || defined(TRACE_HEADER_MULTI_READ)
+#define __MAC80211_DRIVER_TRACE
+
+#include <linux/tracepoint.h>
+#include <net/mac80211.h>
+#include "ieee80211_i.h"
+
+#if !defined(CONFIG_MAC80211_DRIVER_API_TRACER) || defined(__CHECKER__)
+#undef TRACE_EVENT
+#define TRACE_EVENT(name, proto, ...) \
+static inline void trace_ ## name(proto) {}
+#endif
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM mac80211
+
+#define MAXNAME 32
+#define LOCAL_ENTRY __array(char, wiphy_name, 32)
+#define LOCAL_ASSIGN strlcpy(__entry->wiphy_name, wiphy_name(local->hw.wiphy), MAXNAME)
+#define LOCAL_PR_FMT "%s"
+#define LOCAL_PR_ARG __entry->wiphy_name
+
+#define STA_ENTRY __array(char, sta_addr, ETH_ALEN)
+#define STA_ASSIGN (sta ? memcpy(__entry->sta_addr, sta->addr, ETH_ALEN) : memset(__entry->sta_addr, 0, ETH_ALEN))
+#define STA_PR_FMT " sta:%pM"
+#define STA_PR_ARG __entry->sta_addr
+
+#define VIF_ENTRY __field(enum nl80211_iftype, vif_type) __field(void *, vif)
+#define VIF_ASSIGN __entry->vif_type = vif ? vif->type : 0; __entry->vif = vif
+#define VIF_PR_FMT " vif:%p(%d)"
+#define VIF_PR_ARG __entry->vif, __entry->vif_type
+
+TRACE_EVENT(drv_start,
+ TP_PROTO(struct ieee80211_local *local, int ret),
+
+ TP_ARGS(local, ret),
+
+ TP_STRUCT__entry(
+ LOCAL_ENTRY
+ __field(int, ret)
+ ),
+
+ TP_fast_assign(
+ LOCAL_ASSIGN;
+ __entry->ret = ret;
+ ),
+
+ TP_printk(
+ LOCAL_PR_FMT, LOCAL_PR_ARG
+ )
+);
+
+TRACE_EVENT(drv_stop,
+ TP_PROTO(struct ieee80211_local *local),
+
+ TP_ARGS(local),
+
+ TP_STRUCT__entry(
+ LOCAL_ENTRY
+ ),
+
+ TP_fast_assign(
+ LOCAL_ASSIGN;
+ ),
+
+ TP_printk(
+ LOCAL_PR_FMT, LOCAL_PR_ARG
+ )
+);
+
+TRACE_EVENT(drv_add_interface,
+ TP_PROTO(struct ieee80211_local *local,
+ const u8 *addr,
+ struct ieee80211_vif *vif,
+ int ret),
+
+ TP_ARGS(local, addr, vif, ret),
+
+ TP_STRUCT__entry(
+ LOCAL_ENTRY
+ VIF_ENTRY
+ __array(char, addr, 6)
+ __field(int, ret)
+ ),
+
+ TP_fast_assign(
+ LOCAL_ASSIGN;
+ VIF_ASSIGN;
+ memcpy(__entry->addr, addr, 6);
+ __entry->ret = ret;
+ ),
+
+ TP_printk(
+ LOCAL_PR_FMT VIF_PR_FMT " addr:%pM ret:%d",
+ LOCAL_PR_ARG, VIF_PR_ARG, __entry->addr, __entry->ret
+ )
+);
+
+TRACE_EVENT(drv_remove_interface,
+ TP_PROTO(struct ieee80211_local *local,
+ const u8 *addr, struct ieee80211_vif *vif),
+
+ TP_ARGS(local, addr, vif),
+
+ TP_STRUCT__entry(
+ LOCAL_ENTRY
+ VIF_ENTRY
+ __array(char, addr, 6)
+ ),
+
+ TP_fast_assign(
+ LOCAL_ASSIGN;
+ VIF_ASSIGN;
+ memcpy(__entry->addr, addr, 6);
+ ),
+
+ TP_printk(
+ LOCAL_PR_FMT VIF_PR_FMT " addr:%pM",
+ LOCAL_PR_ARG, VIF_PR_ARG, __entry->addr
+ )
+);
+
+TRACE_EVENT(drv_config,
+ TP_PROTO(struct ieee80211_local *local,
+ u32 changed,
+ int ret),
+
+ TP_ARGS(local, changed, ret),
+
+ TP_STRUCT__entry(
+ LOCAL_ENTRY
+ __field(u32, changed)
+ __field(int, ret)
+ ),
+
+ TP_fast_assign(
+ LOCAL_ASSIGN;
+ __entry->changed = changed;
+ __entry->ret = ret;
+ ),
+
+ TP_printk(
+ LOCAL_PR_FMT " ch:%#x ret:%d",
+ LOCAL_PR_ARG, __entry->changed, __entry->ret
+ )
+);
+
+TRACE_EVENT(drv_bss_info_changed,
+ TP_PROTO(struct ieee80211_local *local,
+ struct ieee80211_vif *vif,
+ struct ieee80211_bss_conf *info,
+ u32 changed),
+
+ TP_ARGS(local, vif, info, changed),
+
+ TP_STRUCT__entry(
+ LOCAL_ENTRY
+ VIF_ENTRY
+ __field(bool, assoc)
+ __field(u16, aid)
+ __field(bool, cts)
+ __field(bool, shortpre)
+ __field(bool, shortslot)
+ __field(u8, dtimper)
+ __field(u16, bcnint)
+ __field(u16, assoc_cap)
+ __field(u64, timestamp)
+ __field(u32, basic_rates)
+ __field(u32, changed)
+ ),
+
+ TP_fast_assign(
+ LOCAL_ASSIGN;
+ VIF_ASSIGN;
+ __entry->changed = changed;
+ __entry->aid = info->aid;
+ __entry->assoc = info->assoc;
+ __entry->shortpre = info->use_short_preamble;
+ __entry->cts = info->use_cts_prot;
+ __entry->shortslot = info->use_short_slot;
+ __entry->dtimper = info->dtim_period;
+ __entry->bcnint = info->beacon_int;
+ __entry->assoc_cap = info->assoc_capability;
+ __entry->timestamp = info->timestamp;
+ __entry->basic_rates = info->basic_rates;
+ ),
+
+ TP_printk(
+ LOCAL_PR_FMT VIF_PR_FMT " changed:%#x",
+ LOCAL_PR_ARG, VIF_PR_ARG, __entry->changed
+ )
+);
+
+TRACE_EVENT(drv_configure_filter,
+ TP_PROTO(struct ieee80211_local *local,
+ unsigned int changed_flags,
+ unsigned int *total_flags,
+ int mc_count),
+
+ TP_ARGS(local, changed_flags, total_flags, mc_count),
+
+ TP_STRUCT__entry(
+ LOCAL_ENTRY
+ __field(unsigned int, changed)
+ __field(unsigned int, total)
+ __field(int, mc)
+ ),
+
+ TP_fast_assign(
+ LOCAL_ASSIGN;
+ __entry->changed = changed_flags;
+ __entry->total = *total_flags;
+ __entry->mc = mc_count;
+ ),
+
+ TP_printk(
+ LOCAL_PR_FMT " changed:%#x total:%#x mc:%d",
+ LOCAL_PR_ARG, __entry->changed, __entry->total, __entry->mc
+ )
+);
+
+TRACE_EVENT(drv_set_tim,
+ TP_PROTO(struct ieee80211_local *local,
+ struct ieee80211_sta *sta, bool set, int ret),
+
+ TP_ARGS(local, sta, set, ret),
+
+ TP_STRUCT__entry(
+ LOCAL_ENTRY
+ STA_ENTRY
+ __field(bool, set)
+ __field(int, ret)
+ ),
+
+ TP_fast_assign(
+ LOCAL_ASSIGN;
+ STA_ASSIGN;
+ __entry->set = set;
+ __entry->ret = ret;
+ ),
+
+ TP_printk(
+ LOCAL_PR_FMT STA_PR_FMT " set:%d ret:%d",
+ LOCAL_PR_ARG, STA_PR_FMT, __entry->set, __entry->ret
+ )
+);
+
+TRACE_EVENT(drv_set_key,
+ TP_PROTO(struct ieee80211_local *local,
+ enum set_key_cmd cmd, struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta,
+ struct ieee80211_key_conf *key, int ret),
+
+ TP_ARGS(local, cmd, vif, sta, key, ret),
+
+ TP_STRUCT__entry(
+ LOCAL_ENTRY
+ VIF_ENTRY
+ STA_ENTRY
+ __field(enum ieee80211_key_alg, alg)
+ __field(u8, hw_key_idx)
+ __field(u8, flags)
+ __field(s8, keyidx)
+ __field(int, ret)
+ ),
+
+ TP_fast_assign(
+ LOCAL_ASSIGN;
+ VIF_ASSIGN;
+ STA_ASSIGN;
+ __entry->alg = key->alg;
+ __entry->flags = key->flags;
+ __entry->keyidx = key->keyidx;
+ __entry->hw_key_idx = key->hw_key_idx;
+ __entry->ret = ret;
+ ),
+
+ TP_printk(
+ LOCAL_PR_FMT VIF_PR_FMT STA_PR_FMT " ret:%d",
+ LOCAL_PR_ARG, VIF_PR_ARG, STA_PR_ARG, __entry->ret
+ )
+);
+
+TRACE_EVENT(drv_update_tkip_key,
+ TP_PROTO(struct ieee80211_local *local,
+ struct ieee80211_key_conf *conf,
+ const u8 *address, u32 iv32),
+
+ TP_ARGS(local, conf, address, iv32),
+
+ TP_STRUCT__entry(
+ LOCAL_ENTRY
+ __array(u8, addr, 6)
+ __field(u32, iv32)
+ ),
+
+ TP_fast_assign(
+ LOCAL_ASSIGN;
+ memcpy(__entry->addr, address, 6);
+ __entry->iv32 = iv32;
+ ),
+
+ TP_printk(
+ LOCAL_PR_FMT " addr:%pM iv32:%#x",
+ LOCAL_PR_ARG, __entry->addr, __entry->iv32
+ )
+);
+
+TRACE_EVENT(drv_hw_scan,
+ TP_PROTO(struct ieee80211_local *local,
+ struct cfg80211_scan_request *req, int ret),
+
+ TP_ARGS(local, req, ret),
+
+ TP_STRUCT__entry(
+ LOCAL_ENTRY
+ __field(int, ret)
+ ),
+
+ TP_fast_assign(
+ LOCAL_ASSIGN;
+ __entry->ret = ret;
+ ),
+
+ TP_printk(
+ LOCAL_PR_FMT " ret:%d",
+ LOCAL_PR_ARG, __entry->ret
+ )
+);
+
+TRACE_EVENT(drv_sw_scan_start,
+ TP_PROTO(struct ieee80211_local *local),
+
+ TP_ARGS(local),
+
+ TP_STRUCT__entry(
+ LOCAL_ENTRY
+ ),
+
+ TP_fast_assign(
+ LOCAL_ASSIGN;
+ ),
+
+ TP_printk(
+ LOCAL_PR_FMT, LOCAL_PR_ARG
+ )
+);
+
+TRACE_EVENT(drv_sw_scan_complete,
+ TP_PROTO(struct ieee80211_local *local),
+
+ TP_ARGS(local),
+
+ TP_STRUCT__entry(
+ LOCAL_ENTRY
+ ),
+
+ TP_fast_assign(
+ LOCAL_ASSIGN;
+ ),
+
+ TP_printk(
+ LOCAL_PR_FMT, LOCAL_PR_ARG
+ )
+);
+
+TRACE_EVENT(drv_get_stats,
+ TP_PROTO(struct ieee80211_local *local,
+ struct ieee80211_low_level_stats *stats,
+ int ret),
+
+ TP_ARGS(local, stats, ret),
+
+ TP_STRUCT__entry(
+ LOCAL_ENTRY
+ __field(int, ret)
+ __field(unsigned int, ackfail)
+ __field(unsigned int, rtsfail)
+ __field(unsigned int, fcserr)
+ __field(unsigned int, rtssucc)
+ ),
+
+ TP_fast_assign(
+ LOCAL_ASSIGN;
+ __entry->ret = ret;
+ __entry->ackfail = stats->dot11ACKFailureCount;
+ __entry->rtsfail = stats->dot11RTSFailureCount;
+ __entry->fcserr = stats->dot11FCSErrorCount;
+ __entry->rtssucc = stats->dot11RTSSuccessCount;
+ ),
+
+ TP_printk(
+ LOCAL_PR_FMT " ret:%d",
+ LOCAL_PR_ARG, __entry->ret
+ )
+);
+
+TRACE_EVENT(drv_get_tkip_seq,
+ TP_PROTO(struct ieee80211_local *local,
+ u8 hw_key_idx, u32 *iv32, u16 *iv16),
+
+ TP_ARGS(local, hw_key_idx, iv32, iv16),
+
+ TP_STRUCT__entry(
+ LOCAL_ENTRY
+ __field(u8, hw_key_idx)
+ __field(u32, iv32)
+ __field(u16, iv16)
+ ),
+
+ TP_fast_assign(
+ LOCAL_ASSIGN;
+ __entry->hw_key_idx = hw_key_idx;
+ __entry->iv32 = *iv32;
+ __entry->iv16 = *iv16;
+ ),
+
+ TP_printk(
+ LOCAL_PR_FMT, LOCAL_PR_ARG
+ )
+);
+
+TRACE_EVENT(drv_set_rts_threshold,
+ TP_PROTO(struct ieee80211_local *local, u32 value, int ret),
+
+ TP_ARGS(local, value, ret),
+
+ TP_STRUCT__entry(
+ LOCAL_ENTRY
+ __field(u32, value)
+ __field(int, ret)
+ ),
+
+ TP_fast_assign(
+ LOCAL_ASSIGN;
+ __entry->ret = ret;
+ __entry->value = value;
+ ),
+
+ TP_printk(
+ LOCAL_PR_FMT " value:%d ret:%d",
+ LOCAL_PR_ARG, __entry->value, __entry->ret
+ )
+);
+
+TRACE_EVENT(drv_sta_notify,
+ TP_PROTO(struct ieee80211_local *local,
+ struct ieee80211_vif *vif,
+ enum sta_notify_cmd cmd,
+ struct ieee80211_sta *sta),
+
+ TP_ARGS(local, vif, cmd, sta),
+
+ TP_STRUCT__entry(
+ LOCAL_ENTRY
+ VIF_ENTRY
+ STA_ENTRY
+ __field(u32, cmd)
+ ),
+
+ TP_fast_assign(
+ LOCAL_ASSIGN;
+ VIF_ASSIGN;
+ STA_ASSIGN;
+ __entry->cmd = cmd;
+ ),
+
+ TP_printk(
+ LOCAL_PR_FMT VIF_PR_FMT STA_PR_FMT " cmd:%d",
+ LOCAL_PR_ARG, VIF_PR_ARG, STA_PR_ARG, __entry->cmd
+ )
+);
+
+TRACE_EVENT(drv_conf_tx,
+ TP_PROTO(struct ieee80211_local *local, u16 queue,
+ const struct ieee80211_tx_queue_params *params,
+ int ret),
+
+ TP_ARGS(local, queue, params, ret),
+
+ TP_STRUCT__entry(
+ LOCAL_ENTRY
+ __field(u16, queue)
+ __field(u16, txop)
+ __field(u16, cw_min)
+ __field(u16, cw_max)
+ __field(u8, aifs)
+ __field(int, ret)
+ ),
+
+ TP_fast_assign(
+ LOCAL_ASSIGN;
+ __entry->queue = queue;
+ __entry->ret = ret;
+ __entry->txop = params->txop;
+ __entry->cw_max = params->cw_max;
+ __entry->cw_min = params->cw_min;
+ __entry->aifs = params->aifs;
+ ),
+
+ TP_printk(
+ LOCAL_PR_FMT " queue:%d ret:%d",
+ LOCAL_PR_ARG, __entry->queue, __entry->ret
+ )
+);
+
+TRACE_EVENT(drv_get_tx_stats,
+ TP_PROTO(struct ieee80211_local *local,
+ struct ieee80211_tx_queue_stats *stats,
+ int ret),
+
+ TP_ARGS(local, stats, ret),
+
+ TP_STRUCT__entry(
+ LOCAL_ENTRY
+ __field(int, ret)
+ ),
+
+ TP_fast_assign(
+ LOCAL_ASSIGN;
+ __entry->ret = ret;
+ ),
+
+ TP_printk(
+ LOCAL_PR_FMT " ret:%d",
+ LOCAL_PR_ARG, __entry->ret
+ )
+);
+
+TRACE_EVENT(drv_get_tsf,
+ TP_PROTO(struct ieee80211_local *local, u64 ret),
+
+ TP_ARGS(local, ret),
+
+ TP_STRUCT__entry(
+ LOCAL_ENTRY
+ __field(u64, ret)
+ ),
+
+ TP_fast_assign(
+ LOCAL_ASSIGN;
+ __entry->ret = ret;
+ ),
+
+ TP_printk(
+ LOCAL_PR_FMT " ret:%llu",
+ LOCAL_PR_ARG, (unsigned long long)__entry->ret
+ )
+);
+
+TRACE_EVENT(drv_set_tsf,
+ TP_PROTO(struct ieee80211_local *local, u64 tsf),
+
+ TP_ARGS(local, tsf),
+
+ TP_STRUCT__entry(
+ LOCAL_ENTRY
+ __field(u64, tsf)
+ ),
+
+ TP_fast_assign(
+ LOCAL_ASSIGN;
+ __entry->tsf = tsf;
+ ),
+
+ TP_printk(
+ LOCAL_PR_FMT " tsf:%llu",
+ LOCAL_PR_ARG, (unsigned long long)__entry->tsf
+ )
+);
+
+TRACE_EVENT(drv_reset_tsf,
+ TP_PROTO(struct ieee80211_local *local),
+
+ TP_ARGS(local),
+
+ TP_STRUCT__entry(
+ LOCAL_ENTRY
+ ),
+
+ TP_fast_assign(
+ LOCAL_ASSIGN;
+ ),
+
+ TP_printk(
+ LOCAL_PR_FMT, LOCAL_PR_ARG
+ )
+);
+
+TRACE_EVENT(drv_tx_last_beacon,
+ TP_PROTO(struct ieee80211_local *local, int ret),
+
+ TP_ARGS(local, ret),
+
+ TP_STRUCT__entry(
+ LOCAL_ENTRY
+ __field(int, ret)
+ ),
+
+ TP_fast_assign(
+ LOCAL_ASSIGN;
+ __entry->ret = ret;
+ ),
+
+ TP_printk(
+ LOCAL_PR_FMT " ret:%d",
+ LOCAL_PR_ARG, __entry->ret
+ )
+);
+
+TRACE_EVENT(drv_ampdu_action,
+ TP_PROTO(struct ieee80211_local *local,
+ enum ieee80211_ampdu_mlme_action action,
+ struct ieee80211_sta *sta, u16 tid,
+ u16 *ssn, int ret),
+
+ TP_ARGS(local, action, sta, tid, ssn, ret),
+
+ TP_STRUCT__entry(
+ LOCAL_ENTRY
+ STA_ENTRY
+ __field(u32, action)
+ __field(u16, tid)
+ __field(u16, ssn)
+ __field(int, ret)
+ ),
+
+ TP_fast_assign(
+ LOCAL_ASSIGN;
+ STA_ASSIGN;
+ __entry->ret = ret;
+ __entry->action = action;
+ __entry->tid = tid;
+ __entry->ssn = *ssn;
+ ),
+
+ TP_printk(
+ LOCAL_PR_FMT STA_PR_FMT " action:%d tid:%d ret:%d",
+ LOCAL_PR_ARG, STA_PR_ARG, __entry->action, __entry->tid, __entry->ret
+ )
+);
+#endif /* !__MAC80211_DRIVER_TRACE || TRACE_HEADER_MULTI_READ */
+
+#undef TRACE_INCLUDE_PATH
+#define TRACE_INCLUDE_PATH .
+#undef TRACE_INCLUDE_FILE
+#define TRACE_INCLUDE_FILE driver-trace
+#include <trace/define_trace.h>
diff --git a/net/mac80211/event.c b/net/mac80211/event.c
index f288d01a634..01ae759518f 100644
--- a/net/mac80211/event.c
+++ b/net/mac80211/event.c
@@ -7,8 +7,7 @@
*
* mac80211 - events
*/
-
-#include <net/iw_handler.h>
+#include <net/cfg80211.h>
#include "ieee80211_i.h"
/*
@@ -17,26 +16,12 @@
* driver or is still in the frame), it should provide that information.
*/
void mac80211_ev_michael_mic_failure(struct ieee80211_sub_if_data *sdata, int keyidx,
- struct ieee80211_hdr *hdr, const u8 *tsc)
+ struct ieee80211_hdr *hdr, const u8 *tsc,
+ gfp_t gfp)
{
- union iwreq_data wrqu;
- char *buf = kmalloc(128, GFP_ATOMIC);
-
- if (buf) {
- /* TODO: needed parameters: count, key type, TSC */
- sprintf(buf, "MLME-MICHAELMICFAILURE.indication("
- "keyid=%d %scast addr=%pM)",
- keyidx, hdr->addr1[0] & 0x01 ? "broad" : "uni",
- hdr->addr2);
- memset(&wrqu, 0, sizeof(wrqu));
- wrqu.data.length = strlen(buf);
- wireless_send_event(sdata->dev, IWEVCUSTOM, &wrqu, buf);
- kfree(buf);
- }
-
cfg80211_michael_mic_failure(sdata->dev, hdr->addr2,
(hdr->addr1[0] & 0x01) ?
NL80211_KEYTYPE_GROUP :
NL80211_KEYTYPE_PAIRWISE,
- keyidx, tsc);
+ keyidx, tsc, gfp);
}
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index 0b30277eb36..920ec8792f4 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -57,7 +57,7 @@ static void ieee80211_rx_mgmt_auth_ibss(struct ieee80211_sub_if_data *sdata,
*/
if (auth_alg == WLAN_AUTH_OPEN && auth_transaction == 1)
ieee80211_send_auth(sdata, 2, WLAN_AUTH_OPEN, NULL, 0,
- sdata->u.ibss.bssid, 0);
+ sdata->u.ibss.bssid, NULL, 0, 0);
}
static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
@@ -494,7 +494,7 @@ static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata)
capability = WLAN_CAPABILITY_IBSS;
- if (sdata->default_key)
+ if (ifibss->privacy)
capability |= WLAN_CAPABILITY_PRIVACY;
else
sdata->drop_unencrypted = 0;
@@ -524,9 +524,8 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata)
return;
capability = WLAN_CAPABILITY_IBSS;
- if (sdata->default_key)
+ if (ifibss->privacy)
capability |= WLAN_CAPABILITY_PRIVACY;
-
if (ifibss->fixed_bssid)
bssid = ifibss->bssid;
if (ifibss->fixed_channel)
@@ -705,7 +704,7 @@ static void ieee80211_ibss_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
struct ieee80211_mgmt *mgmt;
u16 fc;
- rx_status = (struct ieee80211_rx_status *) skb->cb;
+ rx_status = IEEE80211_SKB_RXCB(skb);
mgmt = (struct ieee80211_mgmt *) skb->data;
fc = le16_to_cpu(mgmt->frame_control);
@@ -743,7 +742,7 @@ static void ieee80211_ibss_work(struct work_struct *work)
if (!netif_running(sdata->dev))
return;
- if (local->sw_scanning || local->hw_scanning)
+ if (local->scanning)
return;
if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_ADHOC))
@@ -782,7 +781,7 @@ static void ieee80211_ibss_timer(unsigned long data)
}
set_bit(IEEE80211_IBSS_REQ_RUN, &ifibss->request);
- queue_work(local->hw.workqueue, &ifibss->work);
+ ieee80211_queue_work(&local->hw, &ifibss->work);
}
#ifdef CONFIG_PM
@@ -836,8 +835,7 @@ void ieee80211_ibss_notify_scan_completed(struct ieee80211_local *local)
}
ieee80211_rx_result
-ieee80211_ibss_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb,
- struct ieee80211_rx_status *rx_status)
+ieee80211_ibss_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb)
{
struct ieee80211_local *local = sdata->local;
struct ieee80211_mgmt *mgmt;
@@ -852,11 +850,10 @@ ieee80211_ibss_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb,
switch (fc & IEEE80211_FCTL_STYPE) {
case IEEE80211_STYPE_PROBE_RESP:
case IEEE80211_STYPE_BEACON:
- memcpy(skb->cb, rx_status, sizeof(*rx_status));
case IEEE80211_STYPE_PROBE_REQ:
case IEEE80211_STYPE_AUTH:
skb_queue_tail(&sdata->u.ibss.skb_queue, skb);
- queue_work(local->hw.workqueue, &sdata->u.ibss.work);
+ ieee80211_queue_work(&local->hw, &sdata->u.ibss.work);
return RX_QUEUED;
}
@@ -874,6 +871,8 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata,
} else
sdata->u.ibss.fixed_bssid = false;
+ sdata->u.ibss.privacy = params->privacy;
+
sdata->vif.bss_conf.beacon_int = params->beacon_interval;
sdata->u.ibss.channel = params->channel;
@@ -913,7 +912,7 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata,
ieee80211_recalc_idle(sdata->local);
set_bit(IEEE80211_IBSS_REQ_RUN, &sdata->u.ibss.request);
- queue_work(sdata->local->hw.workqueue, &sdata->u.ibss.work);
+ ieee80211_queue_work(&sdata->local->hw, &sdata->u.ibss.work);
return 0;
}
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 68eb5052179..a6abc7dfd90 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -24,7 +24,6 @@
#include <linux/spinlock.h>
#include <linux/etherdevice.h>
#include <net/cfg80211.h>
-#include <net/iw_handler.h>
#include <net/mac80211.h>
#include "key.h"
#include "sta_info.h"
@@ -227,86 +226,81 @@ struct mesh_preq_queue {
u8 flags;
};
+enum ieee80211_mgd_state {
+ IEEE80211_MGD_STATE_IDLE,
+ IEEE80211_MGD_STATE_PROBE,
+ IEEE80211_MGD_STATE_AUTH,
+ IEEE80211_MGD_STATE_ASSOC,
+};
+
+struct ieee80211_mgd_work {
+ struct list_head list;
+ struct ieee80211_bss *bss;
+ int ie_len;
+ u8 prev_bssid[ETH_ALEN];
+ u8 ssid[IEEE80211_MAX_SSID_LEN];
+ u8 ssid_len;
+ unsigned long timeout;
+ enum ieee80211_mgd_state state;
+ u16 auth_alg, auth_transaction;
+
+ int tries;
+
+ u8 key[WLAN_KEY_LEN_WEP104];
+ u8 key_len, key_idx;
+
+ /* must be last */
+ u8 ie[0]; /* for auth or assoc frame, not probe */
+};
+
/* flags used in struct ieee80211_if_managed.flags */
-#define IEEE80211_STA_SSID_SET BIT(0)
-#define IEEE80211_STA_BSSID_SET BIT(1)
-#define IEEE80211_STA_PREV_BSSID_SET BIT(2)
-#define IEEE80211_STA_AUTHENTICATED BIT(3)
-#define IEEE80211_STA_ASSOCIATED BIT(4)
-#define IEEE80211_STA_PROBEREQ_POLL BIT(5)
-#define IEEE80211_STA_CREATE_IBSS BIT(6)
-#define IEEE80211_STA_CONTROL_PORT BIT(7)
-#define IEEE80211_STA_WMM_ENABLED BIT(8)
-/* hole at 9, please re-use */
-#define IEEE80211_STA_AUTO_SSID_SEL BIT(10)
-#define IEEE80211_STA_AUTO_BSSID_SEL BIT(11)
-#define IEEE80211_STA_AUTO_CHANNEL_SEL BIT(12)
-#define IEEE80211_STA_PRIVACY_INVOKED BIT(13)
-#define IEEE80211_STA_TKIP_WEP_USED BIT(14)
-#define IEEE80211_STA_CSA_RECEIVED BIT(15)
-#define IEEE80211_STA_MFP_ENABLED BIT(16)
-#define IEEE80211_STA_EXT_SME BIT(17)
-/* flags for MLME request */
-#define IEEE80211_STA_REQ_SCAN 0
-#define IEEE80211_STA_REQ_AUTH 1
-#define IEEE80211_STA_REQ_RUN 2
+enum ieee80211_sta_flags {
+ IEEE80211_STA_BEACON_POLL = BIT(0),
+ IEEE80211_STA_CONNECTION_POLL = BIT(1),
+ IEEE80211_STA_CONTROL_PORT = BIT(2),
+ IEEE80211_STA_WMM_ENABLED = BIT(3),
+ IEEE80211_STA_DISABLE_11N = BIT(4),
+ IEEE80211_STA_CSA_RECEIVED = BIT(5),
+ IEEE80211_STA_MFP_ENABLED = BIT(6),
+};
-/* bitfield of allowed auth algs */
-#define IEEE80211_AUTH_ALG_OPEN BIT(0)
-#define IEEE80211_AUTH_ALG_SHARED_KEY BIT(1)
-#define IEEE80211_AUTH_ALG_LEAP BIT(2)
-#define IEEE80211_AUTH_ALG_FT BIT(3)
+/* flags for MLME request */
+enum ieee80211_sta_request {
+ IEEE80211_STA_REQ_SCAN,
+};
struct ieee80211_if_managed {
struct timer_list timer;
+ struct timer_list conn_mon_timer;
+ struct timer_list bcn_mon_timer;
struct timer_list chswitch_timer;
struct work_struct work;
+ struct work_struct monitor_work;
struct work_struct chswitch_work;
struct work_struct beacon_loss_work;
- u8 bssid[ETH_ALEN], prev_bssid[ETH_ALEN];
+ unsigned long probe_timeout;
+ int probe_send_count;
- u8 ssid[IEEE80211_MAX_SSID_LEN];
- size_t ssid_len;
+ struct mutex mtx;
+ struct ieee80211_bss *associated;
+ struct ieee80211_mgd_work *old_associate_work;
+ struct list_head work_list;
- enum {
- IEEE80211_STA_MLME_DISABLED,
- IEEE80211_STA_MLME_DIRECT_PROBE,
- IEEE80211_STA_MLME_AUTHENTICATE,
- IEEE80211_STA_MLME_ASSOCIATE,
- IEEE80211_STA_MLME_ASSOCIATED,
- } state;
+ u8 bssid[ETH_ALEN];
u16 aid;
- u16 ap_capab, capab;
- u8 *extra_ie; /* to be added to the end of AssocReq */
- size_t extra_ie_len;
-
- /* The last AssocReq/Resp IEs */
- u8 *assocreq_ies, *assocresp_ies;
- size_t assocreq_ies_len, assocresp_ies_len;
+ u16 capab;
struct sk_buff_head skb_queue;
- int assoc_scan_tries; /* number of scans done pre-association */
- int direct_probe_tries; /* retries for direct probes */
- int auth_tries; /* retries for auth req */
- int assoc_tries; /* retries for assoc req */
-
unsigned long timers_running; /* used for quiesce/restart */
bool powersave; /* powersave requested for this iface */
unsigned long request;
- unsigned long last_probe;
- unsigned long last_beacon;
-
unsigned int flags;
- unsigned int auth_algs; /* bitfield of allowed auth algs */
- int auth_alg; /* currently used IEEE 802.11 authentication algorithm */
- int auth_transaction;
-
u32 beacon_crc;
enum {
@@ -316,10 +310,6 @@ struct ieee80211_if_managed {
} mfp; /* management frame protection */
int wmm_last_param_set;
-
- /* Extra IE data for management frames */
- u8 *sme_auth_ie;
- size_t sme_auth_ie_len;
};
enum ieee80211_ibss_request {
@@ -339,6 +329,7 @@ struct ieee80211_if_ibss {
bool fixed_bssid;
bool fixed_channel;
+ bool privacy;
u8 bssid[ETH_ALEN];
u8 ssid[IEEE80211_MAX_SSID_LEN];
@@ -364,7 +355,7 @@ struct ieee80211_if_mesh {
unsigned long timers_running;
- bool housekeeping;
+ unsigned long wrkq_flags;
u8 mesh_id[IEEE80211_MAX_MESH_ID_LEN];
size_t mesh_id_len;
@@ -478,20 +469,9 @@ struct ieee80211_sub_if_data {
union {
struct {
struct dentry *drop_unencrypted;
- struct dentry *state;
struct dentry *bssid;
- struct dentry *prev_bssid;
- struct dentry *ssid_len;
struct dentry *aid;
- struct dentry *ap_capab;
struct dentry *capab;
- struct dentry *extra_ie_len;
- struct dentry *auth_tries;
- struct dentry *assoc_tries;
- struct dentry *auth_algs;
- struct dentry *auth_alg;
- struct dentry *auth_transaction;
- struct dentry *flags;
struct dentry *force_unicast_rateidx;
struct dentry *max_ratectrl_rateidx;
} sta;
@@ -588,12 +568,44 @@ enum queue_stop_reason {
IEEE80211_QUEUE_STOP_REASON_CSA,
IEEE80211_QUEUE_STOP_REASON_AGGREGATION,
IEEE80211_QUEUE_STOP_REASON_SUSPEND,
- IEEE80211_QUEUE_STOP_REASON_PENDING,
IEEE80211_QUEUE_STOP_REASON_SKB_ADD,
};
-struct ieee80211_master_priv {
- struct ieee80211_local *local;
+/**
+ * mac80211 scan flags - currently active scan mode
+ *
+ * @SCAN_SW_SCANNING: We're currently in the process of scanning but may as
+ * well be on the operating channel
+ * @SCAN_HW_SCANNING: The hardware is scanning for us, we have no way to
+ * determine if we are on the operating channel or not
+ * @SCAN_OFF_CHANNEL: We're off our operating channel for scanning,
+ * gets only set in conjunction with SCAN_SW_SCANNING
+ */
+enum {
+ SCAN_SW_SCANNING,
+ SCAN_HW_SCANNING,
+ SCAN_OFF_CHANNEL,
+};
+
+/**
+ * enum mac80211_scan_state - scan state machine states
+ *
+ * @SCAN_DECISION: Main entry point to the scan state machine, this state
+ * determines if we should keep on scanning or switch back to the
+ * operating channel
+ * @SCAN_SET_CHANNEL: Set the next channel to be scanned
+ * @SCAN_SEND_PROBE: Send probe requests and wait for probe responses
+ * @SCAN_LEAVE_OPER_CHANNEL: Leave the operating channel, notify the AP
+ * about us leaving the channel and stop all associated STA interfaces
+ * @SCAN_ENTER_OPER_CHANNEL: Enter the operating channel again, notify the
+ * AP about us being back and restart all associated STA interfaces
+ */
+enum mac80211_scan_state {
+ SCAN_DECISION,
+ SCAN_SET_CHANNEL,
+ SCAN_SEND_PROBE,
+ SCAN_LEAVE_OPER_CHANNEL,
+ SCAN_ENTER_OPER_CHANNEL,
};
struct ieee80211_local {
@@ -604,17 +616,30 @@ struct ieee80211_local {
const struct ieee80211_ops *ops;
+ /*
+ * private workqueue to mac80211. mac80211 makes this accessible
+ * via ieee80211_queue_work()
+ */
+ struct workqueue_struct *workqueue;
+
unsigned long queue_stop_reasons[IEEE80211_MAX_QUEUES];
/* also used to protect ampdu_ac_queue and amdpu_ac_stop_refcnt */
spinlock_t queue_stop_reason_lock;
- struct net_device *mdev; /* wmaster# - "master" 802.11 device */
int open_count;
int monitors, cooked_mntrs;
/* number of interfaces with corresponding FIF_ flags */
- int fif_fcsfail, fif_plcpfail, fif_control, fif_other_bss;
+ int fif_fcsfail, fif_plcpfail, fif_control, fif_other_bss, fif_pspoll;
unsigned int filter_flags; /* FIF_* */
struct iw_statistics wstats;
+
+ /* protects the aggregated multicast list and filter calls */
+ spinlock_t filter_lock;
+
+ /* aggregated multicast list */
+ struct dev_addr_list *mc_list;
+ int mc_count;
+
bool tim_in_locked_section; /* see ieee80211_beacon_get() */
/*
@@ -653,6 +678,7 @@ struct ieee80211_local {
struct list_head sta_list;
struct sta_info *sta_hash[STA_HASH_SIZE];
struct timer_list sta_cleanup;
+ int sta_generation;
struct sk_buff_head pending[IEEE80211_MAX_QUEUES];
struct tasklet_struct tx_pending_tasklet;
@@ -687,9 +713,9 @@ struct ieee80211_local {
/* Scanning and BSS list */
struct mutex scan_mtx;
- bool sw_scanning, hw_scanning;
+ unsigned long scanning;
struct cfg80211_ssid scan_ssid;
- struct cfg80211_scan_request int_scan_req;
+ struct cfg80211_scan_request *int_scan_req;
struct cfg80211_scan_request *scan_req;
struct ieee80211_channel *scan_channel;
const u8 *orig_ies;
@@ -697,7 +723,7 @@ struct ieee80211_local {
int scan_channel_idx;
int scan_ies_len;
- enum { SCAN_SET_CHANNEL, SCAN_SEND_PROBE } scan_state;
+ enum mac80211_scan_state next_scan_state;
struct delayed_work scan_work;
struct ieee80211_sub_if_data *scan_sdata;
enum nl80211_channel_type oper_channel_type;
@@ -834,10 +860,6 @@ struct ieee80211_local {
static inline struct ieee80211_sub_if_data *
IEEE80211_DEV_TO_SUB_IF(struct net_device *dev)
{
- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-
- BUG_ON(!local || local->mdev == dev);
-
return netdev_priv(dev);
}
@@ -937,21 +959,20 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata,
void ieee80211_configure_filter(struct ieee80211_local *local);
u32 ieee80211_reset_erp_info(struct ieee80211_sub_if_data *sdata);
-/* wireless extensions */
-extern const struct iw_handler_def ieee80211_iw_handler_def;
-
/* STA code */
void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata);
+int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,
+ struct cfg80211_auth_request *req);
+int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
+ struct cfg80211_assoc_request *req);
+int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
+ struct cfg80211_deauth_request *req,
+ void *cookie);
+int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata,
+ struct cfg80211_disassoc_request *req,
+ void *cookie);
ieee80211_rx_result ieee80211_sta_rx_mgmt(struct ieee80211_sub_if_data *sdata,
- struct sk_buff *skb,
- struct ieee80211_rx_status *rx_status);
-int ieee80211_sta_commit(struct ieee80211_sub_if_data *sdata);
-int ieee80211_sta_set_ssid(struct ieee80211_sub_if_data *sdata, char *ssid, size_t len);
-int ieee80211_sta_get_ssid(struct ieee80211_sub_if_data *sdata, char *ssid, size_t *len);
-int ieee80211_sta_set_bssid(struct ieee80211_sub_if_data *sdata, u8 *bssid);
-void ieee80211_sta_req_auth(struct ieee80211_sub_if_data *sdata);
-int ieee80211_sta_deauthenticate(struct ieee80211_sub_if_data *sdata, u16 reason);
-int ieee80211_sta_disassociate(struct ieee80211_sub_if_data *sdata, u16 reason);
+ struct sk_buff *skb);
void ieee80211_send_pspoll(struct ieee80211_local *local,
struct ieee80211_sub_if_data *sdata);
void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency);
@@ -967,8 +988,7 @@ void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata);
void ieee80211_ibss_notify_scan_completed(struct ieee80211_local *local);
void ieee80211_ibss_setup_sdata(struct ieee80211_sub_if_data *sdata);
ieee80211_rx_result
-ieee80211_ibss_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb,
- struct ieee80211_rx_status *rx_status);
+ieee80211_ibss_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb);
struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata,
u8 *bssid, u8 *addr, u32 supp_rates);
int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata,
@@ -983,16 +1003,9 @@ int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata,
const u8 *ssid, u8 ssid_len);
int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata,
struct cfg80211_scan_request *req);
-int ieee80211_scan_results(struct ieee80211_local *local,
- struct iw_request_info *info,
- char *buf, size_t len);
void ieee80211_scan_cancel(struct ieee80211_local *local);
ieee80211_rx_result
-ieee80211_scan_rx(struct ieee80211_sub_if_data *sdata,
- struct sk_buff *skb,
- struct ieee80211_rx_status *rx_status);
-int ieee80211_sta_set_extra_ie(struct ieee80211_sub_if_data *sdata,
- const char *ie, size_t len);
+ieee80211_scan_rx(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb);
void ieee80211_mlme_notify_scan_completed(struct ieee80211_local *local);
struct ieee80211_bss *
@@ -1008,8 +1021,6 @@ ieee80211_rx_bss_get(struct ieee80211_local *local, u8 *bssid, int freq,
u8 *ssid, u8 ssid_len);
void ieee80211_rx_bss_put(struct ieee80211_local *local,
struct ieee80211_bss *bss);
-void ieee80211_rx_bss_remove(struct ieee80211_sub_if_data *sdata, u8 *bssid,
- int freq, u8 *ssid, u8 ssid_len);
/* interface handling */
int ieee80211_if_add(struct ieee80211_local *local, const char *name,
@@ -1025,7 +1036,6 @@ void ieee80211_recalc_idle(struct ieee80211_local *local);
/* tx handling */
void ieee80211_clear_tx_pending(struct ieee80211_local *local);
void ieee80211_tx_pending(unsigned long data);
-int ieee80211_master_start_xmit(struct sk_buff *skb, struct net_device *dev);
int ieee80211_monitor_start_xmit(struct sk_buff *skb, struct net_device *dev);
int ieee80211_subif_start_xmit(struct sk_buff *skb, struct net_device *dev);
@@ -1092,7 +1102,8 @@ u8 *ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len,
int ieee80211_frame_duration(struct ieee80211_local *local, size_t len,
int rate, int erp, int short_preamble);
void mac80211_ev_michael_mic_failure(struct ieee80211_sub_if_data *sdata, int keyidx,
- struct ieee80211_hdr *hdr, const u8 *tsc);
+ struct ieee80211_hdr *hdr, const u8 *tsc,
+ gfp_t gfp);
void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata);
void ieee80211_tx_skb(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb,
int encrypt);
@@ -1129,8 +1140,8 @@ int ieee80211_add_pending_skbs(struct ieee80211_local *local,
void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata,
u16 transaction, u16 auth_alg,
- u8 *extra, size_t extra_len,
- const u8 *bssid, int encrypt);
+ u8 *extra, size_t extra_len, const u8 *bssid,
+ const u8 *key, u8 key_len, u8 key_idx);
int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer,
const u8 *ie, size_t ie_len);
void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst,
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index b7c8a448429..e8fb03b91a4 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -190,10 +190,6 @@ static int ieee80211_open(struct net_device *dev)
ETH_ALEN);
}
- if (compare_ether_addr(null_addr, local->mdev->dev_addr) == 0)
- memcpy(local->mdev->dev_addr, local->hw.wiphy->perm_addr,
- ETH_ALEN);
-
/*
* Validate the MAC address for this device.
*/
@@ -224,18 +220,17 @@ static int ieee80211_open(struct net_device *dev)
local->fif_fcsfail++;
if (sdata->u.mntr_flags & MONITOR_FLAG_PLCPFAIL)
local->fif_plcpfail++;
- if (sdata->u.mntr_flags & MONITOR_FLAG_CONTROL)
+ if (sdata->u.mntr_flags & MONITOR_FLAG_CONTROL) {
local->fif_control++;
+ local->fif_pspoll++;
+ }
if (sdata->u.mntr_flags & MONITOR_FLAG_OTHER_BSS)
local->fif_other_bss++;
- netif_addr_lock_bh(local->mdev);
+ spin_lock_bh(&local->filter_lock);
ieee80211_configure_filter(local);
- netif_addr_unlock_bh(local->mdev);
+ spin_unlock_bh(&local->filter_lock);
break;
- case NL80211_IFTYPE_STATION:
- sdata->u.mgd.flags &= ~IEEE80211_STA_PREV_BSSID_SET;
- /* fall through */
default:
conf.vif = &sdata->vif;
conf.type = sdata->vif.type;
@@ -246,12 +241,19 @@ static int ieee80211_open(struct net_device *dev)
if (ieee80211_vif_is_mesh(&sdata->vif)) {
local->fif_other_bss++;
- netif_addr_lock_bh(local->mdev);
+ spin_lock_bh(&local->filter_lock);
ieee80211_configure_filter(local);
- netif_addr_unlock_bh(local->mdev);
+ spin_unlock_bh(&local->filter_lock);
ieee80211_start_mesh(sdata);
+ } else if (sdata->vif.type == NL80211_IFTYPE_AP) {
+ local->fif_pspoll++;
+
+ spin_lock_bh(&local->filter_lock);
+ ieee80211_configure_filter(local);
+ spin_unlock_bh(&local->filter_lock);
}
+
changed |= ieee80211_reset_erp_info(sdata);
ieee80211_bss_info_change_notify(sdata, changed);
ieee80211_enable_keys(sdata);
@@ -282,10 +284,6 @@ static int ieee80211_open(struct net_device *dev)
}
if (local->open_count == 0) {
- res = dev_open(local->mdev);
- WARN_ON(res);
- if (res)
- goto err_del_interface;
tasklet_enable(&local->tx_pending_tasklet);
tasklet_enable(&local->tasklet);
}
@@ -323,7 +321,7 @@ static int ieee80211_open(struct net_device *dev)
* to fix this.
*/
if (sdata->vif.type == NL80211_IFTYPE_STATION)
- queue_work(local->hw.workqueue, &sdata->u.mgd.work);
+ ieee80211_queue_work(&local->hw, &sdata->u.mgd.work);
netif_tx_start_all_queues(dev);
@@ -346,7 +344,10 @@ static int ieee80211_stop(struct net_device *dev)
struct ieee80211_local *local = sdata->local;
struct ieee80211_if_init_conf conf;
struct sta_info *sta;
+ unsigned long flags;
+ struct sk_buff *skb, *tmp;
u32 hw_reconf_flags = 0;
+ int i;
/*
* Stop TX on this interface first.
@@ -366,18 +367,6 @@ static int ieee80211_stop(struct net_device *dev)
rcu_read_unlock();
/*
- * Announce that we are leaving the network, in case we are a
- * station interface type. This must be done before removing
- * all stations associated with sta_info_flush, otherwise STA
- * information will be gone and no announce being done.
- */
- if (sdata->vif.type == NL80211_IFTYPE_STATION) {
- if (sdata->u.mgd.state != IEEE80211_STA_MLME_DISABLED)
- ieee80211_sta_deauthenticate(sdata,
- WLAN_REASON_DEAUTH_LEAVING);
- }
-
- /*
* Remove all stations associated with this interface.
*
* This must be done before calling ops->remove_interface()
@@ -408,13 +397,23 @@ static int ieee80211_stop(struct net_device *dev)
if (sdata->flags & IEEE80211_SDATA_PROMISC)
atomic_dec(&local->iff_promiscs);
- dev_mc_unsync(local->mdev, dev);
+ if (sdata->vif.type == NL80211_IFTYPE_AP)
+ local->fif_pspoll--;
+
+ netif_addr_lock_bh(dev);
+ spin_lock_bh(&local->filter_lock);
+ __dev_addr_unsync(&local->mc_list, &local->mc_count,
+ &dev->mc_list, &dev->mc_count);
+ ieee80211_configure_filter(local);
+ spin_unlock_bh(&local->filter_lock);
+ netif_addr_unlock_bh(dev);
+
del_timer_sync(&local->dynamic_ps_timer);
cancel_work_sync(&local->dynamic_ps_enable_work);
/* APs need special treatment */
if (sdata->vif.type == NL80211_IFTYPE_AP) {
- struct ieee80211_sub_if_data *vlan, *tmp;
+ struct ieee80211_sub_if_data *vlan, *tmpsdata;
struct beacon_data *old_beacon = sdata->u.ap.beacon;
/* remove beacon */
@@ -423,7 +422,7 @@ static int ieee80211_stop(struct net_device *dev)
kfree(old_beacon);
/* down all dependent devices, that is VLANs */
- list_for_each_entry_safe(vlan, tmp, &sdata->u.ap.vlans,
+ list_for_each_entry_safe(vlan, tmpsdata, &sdata->u.ap.vlans,
u.vlan.list)
dev_close(vlan->dev);
WARN_ON(!list_empty(&sdata->u.ap.vlans));
@@ -452,29 +451,32 @@ static int ieee80211_stop(struct net_device *dev)
local->fif_fcsfail--;
if (sdata->u.mntr_flags & MONITOR_FLAG_PLCPFAIL)
local->fif_plcpfail--;
- if (sdata->u.mntr_flags & MONITOR_FLAG_CONTROL)
+ if (sdata->u.mntr_flags & MONITOR_FLAG_CONTROL) {
+ local->fif_pspoll--;
local->fif_control--;
+ }
if (sdata->u.mntr_flags & MONITOR_FLAG_OTHER_BSS)
local->fif_other_bss--;
- netif_addr_lock_bh(local->mdev);
+ spin_lock_bh(&local->filter_lock);
ieee80211_configure_filter(local);
- netif_addr_unlock_bh(local->mdev);
+ spin_unlock_bh(&local->filter_lock);
break;
case NL80211_IFTYPE_STATION:
- memset(sdata->u.mgd.bssid, 0, ETH_ALEN);
del_timer_sync(&sdata->u.mgd.chswitch_timer);
del_timer_sync(&sdata->u.mgd.timer);
+ del_timer_sync(&sdata->u.mgd.conn_mon_timer);
+ del_timer_sync(&sdata->u.mgd.bcn_mon_timer);
/*
- * If the timer fired while we waited for it, it will have
- * requeued the work. Now the work will be running again
+ * If any of the timers fired while we waited for it, it will
+ * have queued its work. Now the work will be running again
* but will not rearm the timer again because it checks
* whether the interface is running, which, at this point,
* it no longer is.
*/
cancel_work_sync(&sdata->u.mgd.work);
cancel_work_sync(&sdata->u.mgd.chswitch_work);
-
+ cancel_work_sync(&sdata->u.mgd.monitor_work);
cancel_work_sync(&sdata->u.mgd.beacon_loss_work);
/*
@@ -485,12 +487,6 @@ static int ieee80211_stop(struct net_device *dev)
*/
synchronize_rcu();
skb_queue_purge(&sdata->u.mgd.skb_queue);
-
- sdata->u.mgd.flags &= ~(IEEE80211_STA_PRIVACY_INVOKED |
- IEEE80211_STA_TKIP_WEP_USED);
- kfree(sdata->u.mgd.extra_ie);
- sdata->u.mgd.extra_ie = NULL;
- sdata->u.mgd.extra_ie_len = 0;
/* fall through */
case NL80211_IFTYPE_ADHOC:
if (sdata->vif.type == NL80211_IFTYPE_ADHOC) {
@@ -507,9 +503,9 @@ static int ieee80211_stop(struct net_device *dev)
local->fif_other_bss--;
atomic_dec(&local->iff_allmultis);
- netif_addr_lock_bh(local->mdev);
+ spin_lock_bh(&local->filter_lock);
ieee80211_configure_filter(local);
- netif_addr_unlock_bh(local->mdev);
+ spin_unlock_bh(&local->filter_lock);
ieee80211_stop_mesh(sdata);
}
@@ -536,10 +532,20 @@ static int ieee80211_stop(struct net_device *dev)
* the scan_sdata is NULL already don't send out a
* scan event to userspace -- the scan is incomplete.
*/
- if (local->sw_scanning)
+ if (test_bit(SCAN_SW_SCANNING, &local->scanning))
ieee80211_scan_completed(&local->hw, true);
}
+ /*
+ * Disable beaconing for AP and mesh, IBSS can't
+ * still be joined to a network at this point.
+ */
+ if (sdata->vif.type == NL80211_IFTYPE_AP ||
+ sdata->vif.type == NL80211_IFTYPE_MESH_POINT) {
+ ieee80211_bss_info_change_notify(sdata,
+ BSS_CHANGED_BEACON_ENABLED);
+ }
+
conf.vif = &sdata->vif;
conf.type = sdata->vif.type;
conf.mac_addr = dev->dev_addr;
@@ -555,14 +561,11 @@ static int ieee80211_stop(struct net_device *dev)
ieee80211_recalc_ps(local, -1);
if (local->open_count == 0) {
- if (netif_running(local->mdev))
- dev_close(local->mdev);
-
drv_stop(local);
ieee80211_led_radio(local, false);
- flush_workqueue(local->hw.workqueue);
+ flush_workqueue(local->workqueue);
tasklet_disable(&local->tx_pending_tasklet);
tasklet_disable(&local->tasklet);
@@ -575,6 +578,18 @@ static int ieee80211_stop(struct net_device *dev)
if (hw_reconf_flags)
ieee80211_hw_config(local, hw_reconf_flags);
+ spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
+ for (i = 0; i < IEEE80211_MAX_QUEUES; i++) {
+ skb_queue_walk_safe(&local->pending[i], skb, tmp) {
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+ if (info->control.vif == &sdata->vif) {
+ __skb_unlink(skb, &local->pending[i]);
+ dev_kfree_skb_irq(skb);
+ }
+ }
+ }
+ spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
+
return 0;
}
@@ -604,8 +619,11 @@ static void ieee80211_set_multicast_list(struct net_device *dev)
atomic_dec(&local->iff_promiscs);
sdata->flags ^= IEEE80211_SDATA_PROMISC;
}
-
- dev_mc_sync(local->mdev, dev);
+ spin_lock_bh(&local->filter_lock);
+ __dev_addr_sync(&local->mc_list, &local->mc_count,
+ &dev->mc_list, &dev->mc_count);
+ ieee80211_configure_filter(local);
+ spin_unlock_bh(&local->filter_lock);
}
/*
@@ -652,11 +670,6 @@ static void ieee80211_teardown_sdata(struct net_device *dev)
kfree_skb(sdata->u.ibss.presp);
break;
case NL80211_IFTYPE_STATION:
- kfree(sdata->u.mgd.extra_ie);
- kfree(sdata->u.mgd.assocreq_ies);
- kfree(sdata->u.mgd.assocresp_ies);
- kfree(sdata->u.mgd.sme_auth_ie);
- break;
case NL80211_IFTYPE_WDS:
case NL80211_IFTYPE_AP_VLAN:
case NL80211_IFTYPE_MONITOR:
@@ -695,7 +708,6 @@ static void ieee80211_if_setup(struct net_device *dev)
{
ether_setup(dev);
dev->netdev_ops = &ieee80211_dataif_ops;
- dev->wireless_handlers = &ieee80211_iw_handler_def;
dev->destructor = free_netdev;
}
@@ -798,6 +810,7 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name,
name, ieee80211_if_setup);
if (!ndev)
return -ENOMEM;
+ dev_net_set(ndev, wiphy_net(local->hw.wiphy));
ndev->needed_headroom = local->tx_headroom +
4*6 /* four MAC addresses */
@@ -814,7 +827,6 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name,
memcpy(ndev->dev_addr, local->hw.wiphy->perm_addr, ETH_ALEN);
SET_NETDEV_DEV(ndev, wiphy_dev(local->hw.wiphy));
- ndev->features |= NETIF_F_NETNS_LOCAL;
/* don't use IEEE80211_DEV_TO_SUB_IF because it checks too much */
sdata = netdev_priv(ndev);
@@ -931,7 +943,7 @@ u32 __ieee80211_recalc_idle(struct ieee80211_local *local)
struct ieee80211_sub_if_data *sdata;
int count = 0;
- if (local->hw_scanning || local->sw_scanning)
+ if (local->scanning)
return ieee80211_idle_off(local, "scanning");
list_for_each_entry(sdata, &local->interfaces, list) {
@@ -939,7 +951,8 @@ u32 __ieee80211_recalc_idle(struct ieee80211_local *local)
continue;
/* do not count disabled managed interfaces */
if (sdata->vif.type == NL80211_IFTYPE_STATION &&
- sdata->u.mgd.state == IEEE80211_STA_MLME_DISABLED)
+ !sdata->u.mgd.associated &&
+ list_empty(&sdata->u.mgd.work_list))
continue;
/* do not count unused IBSS interfaces */
if (sdata->vif.type == NL80211_IFTYPE_ADHOC &&
diff --git a/net/mac80211/key.c b/net/mac80211/key.c
index ce267565e18..659a42d529e 100644
--- a/net/mac80211/key.c
+++ b/net/mac80211/key.c
@@ -67,6 +67,8 @@ static DECLARE_WORK(todo_work, key_todo);
*
* @key: key to add to do item for
* @flag: todo flag(s)
+ *
+ * Must be called with IRQs or softirqs disabled.
*/
static void add_todo(struct ieee80211_key *key, u32 flag)
{
@@ -140,9 +142,9 @@ static void ieee80211_key_enable_hw_accel(struct ieee80211_key *key)
ret = drv_set_key(key->local, SET_KEY, &sdata->vif, sta, &key->conf);
if (!ret) {
- spin_lock(&todo_lock);
+ spin_lock_bh(&todo_lock);
key->flags |= KEY_FLAG_UPLOADED_TO_HARDWARE;
- spin_unlock(&todo_lock);
+ spin_unlock_bh(&todo_lock);
}
if (ret && ret != -ENOSPC && ret != -EOPNOTSUPP)
@@ -164,12 +166,12 @@ static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key)
if (!key || !key->local->ops->set_key)
return;
- spin_lock(&todo_lock);
+ spin_lock_bh(&todo_lock);
if (!(key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) {
- spin_unlock(&todo_lock);
+ spin_unlock_bh(&todo_lock);
return;
}
- spin_unlock(&todo_lock);
+ spin_unlock_bh(&todo_lock);
sta = get_sta_for_key(key);
sdata = key->sdata;
@@ -188,9 +190,9 @@ static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key)
wiphy_name(key->local->hw.wiphy),
key->conf.keyidx, sta ? sta->addr : bcast_addr, ret);
- spin_lock(&todo_lock);
+ spin_lock_bh(&todo_lock);
key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE;
- spin_unlock(&todo_lock);
+ spin_unlock_bh(&todo_lock);
}
static void __ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata,
@@ -437,14 +439,14 @@ void ieee80211_key_link(struct ieee80211_key *key,
__ieee80211_key_replace(sdata, sta, old_key, key);
- spin_unlock_irqrestore(&sdata->local->key_lock, flags);
-
/* free old key later */
add_todo(old_key, KEY_FLAG_TODO_DELETE);
add_todo(key, KEY_FLAG_TODO_ADD_DEBUGFS);
if (netif_running(sdata->dev))
add_todo(key, KEY_FLAG_TODO_HWACCEL_ADD);
+
+ spin_unlock_irqrestore(&sdata->local->key_lock, flags);
}
static void __ieee80211_key_free(struct ieee80211_key *key)
@@ -547,7 +549,7 @@ static void __ieee80211_key_todo(void)
*/
synchronize_rcu();
- spin_lock(&todo_lock);
+ spin_lock_bh(&todo_lock);
while (!list_empty(&todo_list)) {
key = list_first_entry(&todo_list, struct ieee80211_key, todo);
list_del_init(&key->todo);
@@ -558,7 +560,7 @@ static void __ieee80211_key_todo(void)
KEY_FLAG_TODO_HWACCEL_REMOVE |
KEY_FLAG_TODO_DELETE);
key->flags &= ~todoflags;
- spin_unlock(&todo_lock);
+ spin_unlock_bh(&todo_lock);
work_done = false;
@@ -591,9 +593,9 @@ static void __ieee80211_key_todo(void)
WARN_ON(!work_done);
- spin_lock(&todo_lock);
+ spin_lock_bh(&todo_lock);
}
- spin_unlock(&todo_lock);
+ spin_unlock_bh(&todo_lock);
}
void ieee80211_key_todo(void)
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 092a017b237..b03fd84777f 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -77,81 +77,23 @@ void ieee80211_configure_filter(struct ieee80211_local *local)
if (local->fif_other_bss)
new_flags |= FIF_OTHER_BSS;
+ if (local->fif_pspoll)
+ new_flags |= FIF_PSPOLL;
+
changed_flags = local->filter_flags ^ new_flags;
/* be a bit nasty */
new_flags |= (1<<31);
drv_configure_filter(local, changed_flags, &new_flags,
- local->mdev->mc_count,
- local->mdev->mc_list);
+ local->mc_count,
+ local->mc_list);
WARN_ON(new_flags & (1<<31));
local->filter_flags = new_flags & ~(1<<31);
}
-/* master interface */
-
-static int header_parse_80211(const struct sk_buff *skb, unsigned char *haddr)
-{
- memcpy(haddr, skb_mac_header(skb) + 10, ETH_ALEN); /* addr2 */
- return ETH_ALEN;
-}
-
-static const struct header_ops ieee80211_header_ops = {
- .create = eth_header,
- .parse = header_parse_80211,
- .rebuild = eth_rebuild_header,
- .cache = eth_header_cache,
- .cache_update = eth_header_cache_update,
-};
-
-static int ieee80211_master_open(struct net_device *dev)
-{
- struct ieee80211_master_priv *mpriv = netdev_priv(dev);
- struct ieee80211_local *local = mpriv->local;
- struct ieee80211_sub_if_data *sdata;
- int res = -EOPNOTSUPP;
-
- /* we hold the RTNL here so can safely walk the list */
- list_for_each_entry(sdata, &local->interfaces, list) {
- if (netif_running(sdata->dev)) {
- res = 0;
- break;
- }
- }
-
- if (res)
- return res;
-
- netif_tx_start_all_queues(local->mdev);
-
- return 0;
-}
-
-static int ieee80211_master_stop(struct net_device *dev)
-{
- struct ieee80211_master_priv *mpriv = netdev_priv(dev);
- struct ieee80211_local *local = mpriv->local;
- struct ieee80211_sub_if_data *sdata;
-
- /* we hold the RTNL here so can safely walk the list */
- list_for_each_entry(sdata, &local->interfaces, list)
- if (netif_running(sdata->dev))
- dev_close(sdata->dev);
-
- return 0;
-}
-
-static void ieee80211_master_set_multicast_list(struct net_device *dev)
-{
- struct ieee80211_master_priv *mpriv = netdev_priv(dev);
- struct ieee80211_local *local = mpriv->local;
-
- ieee80211_configure_filter(local);
-}
-
int ieee80211_hw_config(struct ieee80211_local *local, u32 changed)
{
struct ieee80211_channel *chan, *scan_chan;
@@ -259,7 +201,8 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata,
}
if (changed & BSS_CHANGED_BEACON_ENABLED) {
- if (local->sw_scanning) {
+ if (local->quiescing || !netif_running(sdata->dev) ||
+ test_bit(SCAN_SW_SCANNING, &local->scanning)) {
sdata->vif.bss_conf.enable_beacon = false;
} else {
/*
@@ -310,7 +253,6 @@ void ieee80211_tx_status_irqsafe(struct ieee80211_hw *hw,
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
int tmp;
- skb->dev = local->mdev;
skb->pkt_type = IEEE80211_TX_STATUS_MSG;
skb_queue_tail(info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS ?
&local->skb_queue : &local->skb_queue_unreliable, skb);
@@ -330,19 +272,16 @@ static void ieee80211_tasklet_handler(unsigned long data)
{
struct ieee80211_local *local = (struct ieee80211_local *) data;
struct sk_buff *skb;
- struct ieee80211_rx_status rx_status;
struct ieee80211_ra_tid *ra_tid;
while ((skb = skb_dequeue(&local->skb_queue)) ||
(skb = skb_dequeue(&local->skb_queue_unreliable))) {
switch (skb->pkt_type) {
case IEEE80211_RX_MSG:
- /* status is in skb->cb */
- memcpy(&rx_status, skb->cb, sizeof(rx_status));
/* Clear skb->pkt_type in order to not confuse kernel
* netstack. */
skb->pkt_type = 0;
- __ieee80211_rx(local_to_hw(local), skb, &rx_status);
+ ieee80211_rx(local_to_hw(local), skb);
break;
case IEEE80211_TX_STATUS_MSG:
skb->pkt_type = 0;
@@ -375,6 +314,31 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local,
{
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+ /*
+ * XXX: This is temporary!
+ *
+ * The problem here is that when we get here, the driver will
+ * quite likely have pretty much overwritten info->control by
+ * using info->driver_data or info->rate_driver_data. Thus,
+ * when passing out the frame to the driver again, we would be
+ * passing completely bogus data since the driver would then
+ * expect a properly filled info->control. In mac80211 itself
+ * the same problem occurs, since we need info->control.vif
+ * internally.
+ *
+ * To fix this, we should send the frame through TX processing
+ * again. However, it's not that simple, since the frame will
+ * have been software-encrypted (if applicable) already, and
+ * encrypting it again doesn't do much good. So to properly do
+ * that, we not only have to skip the actual 'raw' encryption
+ * (key selection etc. still has to be done!) but also the
+ * sequence number assignment since that impacts the crypto
+ * encapsulation, of course.
+ *
+ * Hence, for now, fix the bug by just dropping the frame.
+ */
+ goto drop;
+
sta->tx_filtered_count++;
/*
@@ -428,6 +392,7 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local,
return;
}
+ drop:
#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
if (net_ratelimit())
printk(KERN_DEBUG "%s: dropped TX filtered frame, "
@@ -685,6 +650,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
if (!wiphy)
return NULL;
+ wiphy->netnsok = true;
wiphy->privid = mac80211_wiphy_privid;
/* Yes, putting cfg80211_bss into ieee80211_bss is a hack */
@@ -719,7 +685,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
mutex_init(&local->scan_mtx);
spin_lock_init(&local->key_lock);
-
+ spin_lock_init(&local->filter_lock);
spin_lock_init(&local->queue_stop_reason_lock);
INIT_DELAYED_WORK(&local->scan_work, ieee80211_scan_work);
@@ -755,30 +721,11 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
}
EXPORT_SYMBOL(ieee80211_alloc_hw);
-static const struct net_device_ops ieee80211_master_ops = {
- .ndo_start_xmit = ieee80211_master_start_xmit,
- .ndo_open = ieee80211_master_open,
- .ndo_stop = ieee80211_master_stop,
- .ndo_set_multicast_list = ieee80211_master_set_multicast_list,
- .ndo_select_queue = ieee80211_select_queue,
-};
-
-static void ieee80211_master_setup(struct net_device *mdev)
-{
- mdev->type = ARPHRD_IEEE80211;
- mdev->netdev_ops = &ieee80211_master_ops;
- mdev->header_ops = &ieee80211_header_ops;
- mdev->tx_queue_len = 1000;
- mdev->addr_len = ETH_ALEN;
-}
-
int ieee80211_register_hw(struct ieee80211_hw *hw)
{
struct ieee80211_local *local = hw_to_local(hw);
int result;
enum ieee80211_band band;
- struct net_device *mdev;
- struct ieee80211_master_priv *mpriv;
int channels, i, j, max_bitrates;
bool supp_ht;
static const u32 cipher_suites[] = {
@@ -818,9 +765,9 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
supp_ht = supp_ht || sband->ht_cap.ht_supported;
}
- local->int_scan_req.n_channels = channels;
- local->int_scan_req.channels = kzalloc(sizeof(void *) * channels, GFP_KERNEL);
- if (!local->int_scan_req.channels)
+ local->int_scan_req = kzalloc(sizeof(*local->int_scan_req) +
+ sizeof(void *) * channels, GFP_KERNEL);
+ if (!local->int_scan_req)
return -ENOMEM;
/* if low-level driver supports AP, we also support VLAN */
@@ -877,19 +824,9 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
if (hw->queues > IEEE80211_MAX_QUEUES)
hw->queues = IEEE80211_MAX_QUEUES;
- mdev = alloc_netdev_mq(sizeof(struct ieee80211_master_priv),
- "wmaster%d", ieee80211_master_setup,
- hw->queues);
- if (!mdev)
- goto fail_mdev_alloc;
-
- mpriv = netdev_priv(mdev);
- mpriv->local = local;
- local->mdev = mdev;
-
- local->hw.workqueue =
+ local->workqueue =
create_singlethread_workqueue(wiphy_name(local->hw.wiphy));
- if (!local->hw.workqueue) {
+ if (!local->workqueue) {
result = -ENOMEM;
goto fail_workqueue;
}
@@ -921,17 +858,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
}
rtnl_lock();
- result = dev_alloc_name(local->mdev, local->mdev->name);
- if (result < 0)
- goto fail_dev;
-
- memcpy(local->mdev->dev_addr, local->hw.wiphy->perm_addr, ETH_ALEN);
- SET_NETDEV_DEV(local->mdev, wiphy_dev(local->hw.wiphy));
- local->mdev->features |= NETIF_F_NETNS_LOCAL;
-
- result = register_netdevice(local->mdev);
- if (result < 0)
- goto fail_dev;
result = ieee80211_init_rate_ctrl_alg(local,
hw->rate_control_algorithm);
@@ -956,13 +882,13 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
/* alloc internal scan request */
i = 0;
- local->int_scan_req.ssids = &local->scan_ssid;
- local->int_scan_req.n_ssids = 1;
+ local->int_scan_req->ssids = &local->scan_ssid;
+ local->int_scan_req->n_ssids = 1;
for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
if (!hw->wiphy->bands[band])
continue;
for (j = 0; j < hw->wiphy->bands[band]->n_channels; j++) {
- local->int_scan_req.channels[i] =
+ local->int_scan_req->channels[i] =
&hw->wiphy->bands[band]->channels[j];
i++;
}
@@ -984,23 +910,17 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
ieee80211_led_exit(local);
ieee80211_remove_interfaces(local);
fail_rate:
- unregister_netdevice(local->mdev);
- local->mdev = NULL;
- fail_dev:
rtnl_unlock();
ieee80211_wep_free(local);
fail_wep:
sta_info_stop(local);
fail_sta_info:
debugfs_hw_del(local);
- destroy_workqueue(local->hw.workqueue);
+ destroy_workqueue(local->workqueue);
fail_workqueue:
- if (local->mdev)
- free_netdev(local->mdev);
- fail_mdev_alloc:
wiphy_unregister(local->hw.wiphy);
fail_wiphy_register:
- kfree(local->int_scan_req.channels);
+ kfree(local->int_scan_req->channels);
return result;
}
EXPORT_SYMBOL(ieee80211_register_hw);
@@ -1022,13 +942,8 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw)
* because the driver cannot be handing us frames any
* more and the tasklet is killed.
*/
-
- /* First, we remove all virtual interfaces. */
ieee80211_remove_interfaces(local);
- /* then, finally, remove the master interface */
- unregister_netdevice(local->mdev);
-
rtnl_unlock();
ieee80211_clear_tx_pending(local);
@@ -1043,12 +958,11 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw)
skb_queue_purge(&local->skb_queue);
skb_queue_purge(&local->skb_queue_unreliable);
- destroy_workqueue(local->hw.workqueue);
+ destroy_workqueue(local->workqueue);
wiphy_unregister(local->hw.wiphy);
ieee80211_wep_free(local);
ieee80211_led_exit(local);
- free_netdev(local->mdev);
- kfree(local->int_scan_req.channels);
+ kfree(local->int_scan_req);
}
EXPORT_SYMBOL(ieee80211_unregister_hw);
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index 11cf45bce38..3185e18c821 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -47,14 +47,14 @@ static void ieee80211_mesh_housekeeping_timer(unsigned long data)
struct ieee80211_local *local = sdata->local;
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
- ifmsh->housekeeping = true;
+ ifmsh->wrkq_flags |= MESH_WORK_HOUSEKEEPING;
if (local->quiescing) {
set_bit(TMR_RUNNING_HK, &ifmsh->timers_running);
return;
}
- queue_work(local->hw.workqueue, &ifmsh->work);
+ ieee80211_queue_work(&local->hw, &ifmsh->work);
}
/**
@@ -320,30 +320,6 @@ struct mesh_table *mesh_table_alloc(int size_order)
return newtbl;
}
-static void __mesh_table_free(struct mesh_table *tbl)
-{
- kfree(tbl->hash_buckets);
- kfree(tbl->hashwlock);
- kfree(tbl);
-}
-
-void mesh_table_free(struct mesh_table *tbl, bool free_leafs)
-{
- struct hlist_head *mesh_hash;
- struct hlist_node *p, *q;
- int i;
-
- mesh_hash = tbl->hash_buckets;
- for (i = 0; i <= tbl->hash_mask; i++) {
- spin_lock(&tbl->hashwlock[i]);
- hlist_for_each_safe(p, q, &mesh_hash[i]) {
- tbl->free_node(p, free_leafs);
- atomic_dec(&tbl->entries);
- }
- spin_unlock(&tbl->hashwlock[i]);
- }
- __mesh_table_free(tbl);
-}
static void ieee80211_mesh_path_timer(unsigned long data)
{
@@ -357,63 +333,79 @@ static void ieee80211_mesh_path_timer(unsigned long data)
return;
}
- queue_work(local->hw.workqueue, &ifmsh->work);
+ ieee80211_queue_work(&local->hw, &ifmsh->work);
}
-struct mesh_table *mesh_table_grow(struct mesh_table *tbl)
-{
- struct mesh_table *newtbl;
- struct hlist_head *oldhash;
- struct hlist_node *p, *q;
- int i;
-
- if (atomic_read(&tbl->entries)
- < tbl->mean_chain_len * (tbl->hash_mask + 1))
- goto endgrow;
-
- newtbl = mesh_table_alloc(tbl->size_order + 1);
- if (!newtbl)
- goto endgrow;
-
- newtbl->free_node = tbl->free_node;
- newtbl->mean_chain_len = tbl->mean_chain_len;
- newtbl->copy_node = tbl->copy_node;
- atomic_set(&newtbl->entries, atomic_read(&tbl->entries));
-
- oldhash = tbl->hash_buckets;
- for (i = 0; i <= tbl->hash_mask; i++)
- hlist_for_each(p, &oldhash[i])
- if (tbl->copy_node(p, newtbl) < 0)
- goto errcopy;
-
- return newtbl;
-
-errcopy:
- for (i = 0; i <= newtbl->hash_mask; i++) {
- hlist_for_each_safe(p, q, &newtbl->hash_buckets[i])
- tbl->free_node(p, 0);
+/**
+ * ieee80211_fill_mesh_addresses - fill addresses of a locally originated mesh frame
+ * @hdr: 802.11 frame header
+ * @fc: frame control field
+ * @meshda: destination address in the mesh
+ * @meshsa: source address address in the mesh. Same as TA, as frame is
+ * locally originated.
+ *
+ * Return the length of the 802.11 (does not include a mesh control header)
+ */
+int ieee80211_fill_mesh_addresses(struct ieee80211_hdr *hdr, __le16 *fc, char
+ *meshda, char *meshsa) {
+ if (is_multicast_ether_addr(meshda)) {
+ *fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS);
+ /* DA TA SA */
+ memcpy(hdr->addr1, meshda, ETH_ALEN);
+ memcpy(hdr->addr2, meshsa, ETH_ALEN);
+ memcpy(hdr->addr3, meshsa, ETH_ALEN);
+ return 24;
+ } else {
+ *fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS |
+ IEEE80211_FCTL_TODS);
+ /* RA TA DA SA */
+ memset(hdr->addr1, 0, ETH_ALEN); /* RA is resolved later */
+ memcpy(hdr->addr2, meshsa, ETH_ALEN);
+ memcpy(hdr->addr3, meshda, ETH_ALEN);
+ memcpy(hdr->addr4, meshsa, ETH_ALEN);
+ return 30;
}
- __mesh_table_free(newtbl);
-endgrow:
- return NULL;
}
/**
* ieee80211_new_mesh_header - create a new mesh header
* @meshhdr: uninitialized mesh header
* @sdata: mesh interface to be used
+ * @addr4: addr4 of the mesh frame (1st in ae header)
+ * may be NULL
+ * @addr5: addr5 of the mesh frame (1st or 2nd in ae header)
+ * may be NULL unless addr6 is present
+ * @addr6: addr6 of the mesh frame (2nd or 3rd in ae header)
+ * may be NULL unless addr5 is present
*
* Return the header length.
*/
int ieee80211_new_mesh_header(struct ieee80211s_hdr *meshhdr,
- struct ieee80211_sub_if_data *sdata)
+ struct ieee80211_sub_if_data *sdata, char *addr4,
+ char *addr5, char *addr6)
{
- meshhdr->flags = 0;
+ int aelen = 0;
+ memset(meshhdr, 0, sizeof(meshhdr));
meshhdr->ttl = sdata->u.mesh.mshcfg.dot11MeshTTL;
put_unaligned(cpu_to_le32(sdata->u.mesh.mesh_seqnum), &meshhdr->seqnum);
sdata->u.mesh.mesh_seqnum++;
-
- return 6;
+ if (addr4) {
+ meshhdr->flags |= MESH_FLAGS_AE_A4;
+ aelen += ETH_ALEN;
+ memcpy(meshhdr->eaddr1, addr4, ETH_ALEN);
+ }
+ if (addr5 && addr6) {
+ meshhdr->flags |= MESH_FLAGS_AE_A5_A6;
+ aelen += 2 * ETH_ALEN;
+ if (!addr4) {
+ memcpy(meshhdr->eaddr1, addr5, ETH_ALEN);
+ memcpy(meshhdr->eaddr2, addr6, ETH_ALEN);
+ } else {
+ memcpy(meshhdr->eaddr2, addr5, ETH_ALEN);
+ memcpy(meshhdr->eaddr3, addr6, ETH_ALEN);
+ }
+ }
+ return 6 + aelen;
}
static void ieee80211_mesh_housekeeping(struct ieee80211_sub_if_data *sdata,
@@ -433,7 +425,6 @@ static void ieee80211_mesh_housekeeping(struct ieee80211_sub_if_data *sdata,
if (free_plinks != sdata->u.mesh.accepting_plinks)
ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON);
- ifmsh->housekeeping = false;
mod_timer(&ifmsh->housekeeping_timer,
round_jiffies(jiffies + IEEE80211_MESH_HOUSEKEEPING_INTERVAL));
}
@@ -470,10 +461,12 @@ void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata)
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
struct ieee80211_local *local = sdata->local;
- ifmsh->housekeeping = true;
- queue_work(local->hw.workqueue, &ifmsh->work);
+ ifmsh->wrkq_flags |= MESH_WORK_HOUSEKEEPING;
+ ieee80211_queue_work(&local->hw, &ifmsh->work);
+ sdata->vif.bss_conf.beacon_int = MESH_DEFAULT_BEACON_INTERVAL;
ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON |
- BSS_CHANGED_BEACON_ENABLED);
+ BSS_CHANGED_BEACON_ENABLED |
+ BSS_CHANGED_BEACON_INT);
}
void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata)
@@ -568,7 +561,7 @@ static void ieee80211_mesh_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
ifmsh = &sdata->u.mesh;
- rx_status = (struct ieee80211_rx_status *) skb->cb;
+ rx_status = IEEE80211_SKB_RXCB(skb);
mgmt = (struct ieee80211_mgmt *) skb->data;
stype = le16_to_cpu(mgmt->frame_control) & IEEE80211_FCTL_STYPE;
@@ -597,7 +590,7 @@ static void ieee80211_mesh_work(struct work_struct *work)
if (!netif_running(sdata->dev))
return;
- if (local->sw_scanning || local->hw_scanning)
+ if (local->scanning)
return;
while ((skb = skb_dequeue(&ifmsh->skb_queue)))
@@ -608,7 +601,13 @@ static void ieee80211_mesh_work(struct work_struct *work)
ifmsh->last_preq + msecs_to_jiffies(ifmsh->mshcfg.dot11MeshHWMPpreqMinInterval)))
mesh_path_start_discovery(sdata);
- if (ifmsh->housekeeping)
+ if (test_and_clear_bit(MESH_WORK_GROW_MPATH_TABLE, &ifmsh->wrkq_flags))
+ mesh_mpath_table_grow();
+
+ if (test_and_clear_bit(MESH_WORK_GROW_MPATH_TABLE, &ifmsh->wrkq_flags))
+ mesh_mpp_table_grow();
+
+ if (test_and_clear_bit(MESH_WORK_HOUSEKEEPING, &ifmsh->wrkq_flags))
ieee80211_mesh_housekeeping(sdata, ifmsh);
}
@@ -619,7 +618,7 @@ void ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local)
rcu_read_lock();
list_for_each_entry_rcu(sdata, &local->interfaces, list)
if (ieee80211_vif_is_mesh(&sdata->vif))
- queue_work(local->hw.workqueue, &sdata->u.mesh.work);
+ ieee80211_queue_work(&local->hw, &sdata->u.mesh.work);
rcu_read_unlock();
}
@@ -671,8 +670,7 @@ void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata)
}
ieee80211_rx_result
-ieee80211_mesh_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb,
- struct ieee80211_rx_status *rx_status)
+ieee80211_mesh_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb)
{
struct ieee80211_local *local = sdata->local;
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
@@ -686,12 +684,14 @@ ieee80211_mesh_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb,
fc = le16_to_cpu(mgmt->frame_control);
switch (fc & IEEE80211_FCTL_STYPE) {
+ case IEEE80211_STYPE_ACTION:
+ if (skb->len < IEEE80211_MIN_ACTION_SIZE)
+ return RX_DROP_MONITOR;
+ /* fall through */
case IEEE80211_STYPE_PROBE_RESP:
case IEEE80211_STYPE_BEACON:
- case IEEE80211_STYPE_ACTION:
- memcpy(skb->cb, rx_status, sizeof(*rx_status));
skb_queue_tail(&ifmsh->skb_queue, skb);
- queue_work(local->hw.workqueue, &ifmsh->work);
+ ieee80211_queue_work(&local->hw, &ifmsh->work);
return RX_QUEUED;
}
diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h
index c7d72819cdd..eb23fc639b2 100644
--- a/net/mac80211/mesh.h
+++ b/net/mac80211/mesh.h
@@ -44,6 +44,23 @@ enum mesh_path_flags {
};
/**
+ * enum mesh_deferred_task_flags - mac80211 mesh deferred tasks
+ *
+ *
+ *
+ * @MESH_WORK_HOUSEKEEPING: run the periodic mesh housekeeping tasks
+ * @MESH_WORK_GROW_MPATH_TABLE: the mesh path table is full and needs
+ * to grow.
+ * @MESH_WORK_GROW_MPP_TABLE: the mesh portals table is full and needs to
+ * grow
+ */
+enum mesh_deferred_task_flags {
+ MESH_WORK_HOUSEKEEPING,
+ MESH_WORK_GROW_MPATH_TABLE,
+ MESH_WORK_GROW_MPP_TABLE,
+};
+
+/**
* struct mesh_path - mac80211 mesh path structure
*
* @dst: mesh path destination mac address
@@ -61,7 +78,7 @@ enum mesh_path_flags {
* retry
* @discovery_retries: number of discovery retries
* @flags: mesh path flags, as specified on &enum mesh_path_flags
- * @state_lock: mesh pat state lock
+ * @state_lock: mesh path state lock
*
*
* The combination of dst and sdata is unique in the mesh path table. Since the
@@ -174,6 +191,7 @@ struct mesh_rmc {
*/
#define MESH_PATH_REFRESH_TIME 1000
#define MESH_MIN_DISCOVERY_TIMEOUT (2 * MESH_DIAM_TRAVERSAL_TIME)
+#define MESH_DEFAULT_BEACON_INTERVAL 1000 /* in 1024 us units */
#define MESH_MAX_PREQ_RETRIES 4
#define MESH_PATH_EXPIRE (600 * HZ)
@@ -193,8 +211,11 @@ struct mesh_rmc {
/* Public interfaces */
/* Various */
+int ieee80211_fill_mesh_addresses(struct ieee80211_hdr *hdr, __le16 *fc,
+ char *da, char *sa);
int ieee80211_new_mesh_header(struct ieee80211s_hdr *meshhdr,
- struct ieee80211_sub_if_data *sdata);
+ struct ieee80211_sub_if_data *sdata, char *addr4,
+ char *addr5, char *addr6);
int mesh_rmc_check(u8 *addr, struct ieee80211s_hdr *mesh_hdr,
struct ieee80211_sub_if_data *sdata);
bool mesh_matches_local(struct ieee802_11_elems *ie,
@@ -208,8 +229,7 @@ void ieee80211s_init(void);
void ieee80211s_stop(void);
void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata);
ieee80211_rx_result
-ieee80211_mesh_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb,
- struct ieee80211_rx_status *rx_status);
+ieee80211_mesh_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb);
void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata);
void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata);
@@ -247,7 +267,8 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata,
/* Mesh tables */
struct mesh_table *mesh_table_alloc(int size_order);
void mesh_table_free(struct mesh_table *tbl, bool free_leafs);
-struct mesh_table *mesh_table_grow(struct mesh_table *tbl);
+void mesh_mpath_table_grow(void);
+void mesh_mpp_table_grow(void);
u32 mesh_table_hash(u8 *addr, struct ieee80211_sub_if_data *sdata,
struct mesh_table *tbl);
/* Mesh paths */
@@ -266,6 +287,8 @@ void mesh_path_discard_frame(struct sk_buff *skb,
void mesh_path_quiesce(struct ieee80211_sub_if_data *sdata);
void mesh_path_restart(struct ieee80211_sub_if_data *sdata);
+extern int mesh_paths_generation;
+
#ifdef CONFIG_MAC80211_MESH
extern int mesh_allocated;
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c
index f49ef288e2e..ef1efd36269 100644
--- a/net/mac80211/mesh_hwmp.c
+++ b/net/mac80211/mesh_hwmp.c
@@ -397,7 +397,8 @@ static u32 hwmp_route_info_get(struct ieee80211_sub_if_data *sdata,
static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata,
struct ieee80211_mgmt *mgmt,
- u8 *preq_elem, u32 metric) {
+ u8 *preq_elem, u32 metric)
+{
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
struct mesh_path *mpath;
u8 *dst_addr, *orig_addr;
@@ -430,7 +431,7 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata,
if ((!(mpath->flags & MESH_PATH_DSN_VALID)) ||
DSN_LT(mpath->dsn, dst_dsn)) {
mpath->dsn = dst_dsn;
- mpath->flags &= MESH_PATH_DSN_VALID;
+ mpath->flags |= MESH_PATH_DSN_VALID;
} else if ((!(dst_flags & MP_F_DO)) &&
(mpath->flags & MESH_PATH_ACTIVE)) {
reply = true;
@@ -660,14 +661,14 @@ static void mesh_queue_preq(struct mesh_path *mpath, u8 flags)
spin_unlock(&ifmsh->mesh_preq_queue_lock);
if (time_after(jiffies, ifmsh->last_preq + min_preq_int_jiff(sdata)))
- queue_work(sdata->local->hw.workqueue, &ifmsh->work);
+ ieee80211_queue_work(&sdata->local->hw, &ifmsh->work);
else if (time_before(jiffies, ifmsh->last_preq)) {
/* avoid long wait if did not send preqs for a long time
* and jiffies wrapped around
*/
ifmsh->last_preq = jiffies - min_preq_int_jiff(sdata) - 1;
- queue_work(sdata->local->hw.workqueue, &ifmsh->work);
+ ieee80211_queue_work(&sdata->local->hw, &ifmsh->work);
} else
mod_timer(&ifmsh->mesh_path_timer, ifmsh->last_preq +
min_preq_int_jiff(sdata));
@@ -686,11 +687,11 @@ void mesh_path_start_discovery(struct ieee80211_sub_if_data *sdata)
u8 ttl, dst_flags;
u32 lifetime;
- spin_lock(&ifmsh->mesh_preq_queue_lock);
+ spin_lock_bh(&ifmsh->mesh_preq_queue_lock);
if (!ifmsh->preq_queue_len ||
time_before(jiffies, ifmsh->last_preq +
min_preq_int_jiff(sdata))) {
- spin_unlock(&ifmsh->mesh_preq_queue_lock);
+ spin_unlock_bh(&ifmsh->mesh_preq_queue_lock);
return;
}
@@ -698,7 +699,7 @@ void mesh_path_start_discovery(struct ieee80211_sub_if_data *sdata)
struct mesh_preq_queue, list);
list_del(&preq_node->list);
--ifmsh->preq_queue_len;
- spin_unlock(&ifmsh->mesh_preq_queue_lock);
+ spin_unlock_bh(&ifmsh->mesh_preq_queue_lock);
rcu_read_lock();
mpath = mesh_path_lookup(preq_node->dst, sdata);
@@ -784,7 +785,6 @@ int mesh_nexthop_lookup(struct sk_buff *skb,
mesh_path_add(dst_addr, sdata);
mpath = mesh_path_lookup(dst_addr, sdata);
if (!mpath) {
- dev_kfree_skb(skb);
sdata->u.mesh.mshstats.dropped_frames_no_route++;
err = -ENOSPC;
goto endlookup;
@@ -792,7 +792,7 @@ int mesh_nexthop_lookup(struct sk_buff *skb,
}
if (mpath->flags & MESH_PATH_ACTIVE) {
- if (time_after(jiffies, mpath->exp_time -
+ if (time_after(jiffies, mpath->exp_time +
msecs_to_jiffies(sdata->u.mesh.mshcfg.path_refresh_time))
&& !memcmp(sdata->dev->dev_addr, hdr->addr4,
ETH_ALEN)
@@ -804,17 +804,17 @@ int mesh_nexthop_lookup(struct sk_buff *skb,
memcpy(hdr->addr1, mpath->next_hop->sta.addr,
ETH_ALEN);
} else {
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
if (!(mpath->flags & MESH_PATH_RESOLVING)) {
/* Start discovery only if it is not running yet */
mesh_queue_preq(mpath, PREQ_Q_F_START);
}
if (skb_queue_len(&mpath->frame_queue) >=
- MESH_FRAME_QUEUE_LEN) {
- skb_to_free = mpath->frame_queue.next;
- skb_unlink(skb_to_free, &mpath->frame_queue);
- }
+ MESH_FRAME_QUEUE_LEN)
+ skb_to_free = skb_dequeue(&mpath->frame_queue);
+ info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING;
skb_queue_tail(&mpath->frame_queue, skb);
if (skb_to_free)
mesh_path_discard_frame(skb_to_free, sdata);
diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c
index 479597e8858..751c4d0e2b3 100644
--- a/net/mac80211/mesh_pathtbl.c
+++ b/net/mac80211/mesh_pathtbl.c
@@ -38,6 +38,71 @@ struct mpath_node {
static struct mesh_table *mesh_paths;
static struct mesh_table *mpp_paths; /* Store paths for MPP&MAP */
+int mesh_paths_generation;
+static void __mesh_table_free(struct mesh_table *tbl)
+{
+ kfree(tbl->hash_buckets);
+ kfree(tbl->hashwlock);
+ kfree(tbl);
+}
+
+void mesh_table_free(struct mesh_table *tbl, bool free_leafs)
+{
+ struct hlist_head *mesh_hash;
+ struct hlist_node *p, *q;
+ int i;
+
+ mesh_hash = tbl->hash_buckets;
+ for (i = 0; i <= tbl->hash_mask; i++) {
+ spin_lock(&tbl->hashwlock[i]);
+ hlist_for_each_safe(p, q, &mesh_hash[i]) {
+ tbl->free_node(p, free_leafs);
+ atomic_dec(&tbl->entries);
+ }
+ spin_unlock(&tbl->hashwlock[i]);
+ }
+ __mesh_table_free(tbl);
+}
+
+static struct mesh_table *mesh_table_grow(struct mesh_table *tbl)
+{
+ struct mesh_table *newtbl;
+ struct hlist_head *oldhash;
+ struct hlist_node *p, *q;
+ int i;
+
+ if (atomic_read(&tbl->entries)
+ < tbl->mean_chain_len * (tbl->hash_mask + 1))
+ goto endgrow;
+
+ newtbl = mesh_table_alloc(tbl->size_order + 1);
+ if (!newtbl)
+ goto endgrow;
+
+ newtbl->free_node = tbl->free_node;
+ newtbl->mean_chain_len = tbl->mean_chain_len;
+ newtbl->copy_node = tbl->copy_node;
+ atomic_set(&newtbl->entries, atomic_read(&tbl->entries));
+
+ oldhash = tbl->hash_buckets;
+ for (i = 0; i <= tbl->hash_mask; i++)
+ hlist_for_each(p, &oldhash[i])
+ if (tbl->copy_node(p, newtbl) < 0)
+ goto errcopy;
+
+ return newtbl;
+
+errcopy:
+ for (i = 0; i <= newtbl->hash_mask; i++) {
+ hlist_for_each_safe(p, q, &newtbl->hash_buckets[i])
+ tbl->free_node(p, 0);
+ }
+ __mesh_table_free(newtbl);
+endgrow:
+ return NULL;
+}
+
+
/* This lock will have the grow table function as writer and add / delete nodes
* as readers. When reading the table (i.e. doing lookups) we are well protected
* by RCU
@@ -55,7 +120,25 @@ static DEFINE_RWLOCK(pathtbl_resize_lock);
*/
void mesh_path_assign_nexthop(struct mesh_path *mpath, struct sta_info *sta)
{
+ struct sk_buff *skb;
+ struct ieee80211_hdr *hdr;
+ struct sk_buff_head tmpq;
+ unsigned long flags;
+
rcu_assign_pointer(mpath->next_hop, sta);
+
+ __skb_queue_head_init(&tmpq);
+
+ spin_lock_irqsave(&mpath->frame_queue.lock, flags);
+
+ while ((skb = __skb_dequeue(&mpath->frame_queue)) != NULL) {
+ hdr = (struct ieee80211_hdr *) skb->data;
+ memcpy(hdr->addr1, sta->sta.addr, ETH_ALEN);
+ __skb_queue_tail(&tmpq, skb);
+ }
+
+ skb_queue_splice(&tmpq, &mpath->frame_queue);
+ spin_unlock_irqrestore(&mpath->frame_queue.lock, flags);
}
@@ -167,6 +250,8 @@ struct mesh_path *mesh_path_lookup_by_idx(int idx, struct ieee80211_sub_if_data
*/
int mesh_path_add(u8 *dst, struct ieee80211_sub_if_data *sdata)
{
+ struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
+ struct ieee80211_local *local = sdata->local;
struct mesh_path *mpath, *new_mpath;
struct mpath_node *node, *new_node;
struct hlist_head *bucket;
@@ -175,8 +260,6 @@ int mesh_path_add(u8 *dst, struct ieee80211_sub_if_data *sdata)
int err = 0;
u32 hash_idx;
- might_sleep();
-
if (memcmp(dst, sdata->dev->dev_addr, ETH_ALEN) == 0)
/* never add ourselves as neighbours */
return -ENOTSUPP;
@@ -188,11 +271,11 @@ int mesh_path_add(u8 *dst, struct ieee80211_sub_if_data *sdata)
return -ENOSPC;
err = -ENOMEM;
- new_mpath = kzalloc(sizeof(struct mesh_path), GFP_KERNEL);
+ new_mpath = kzalloc(sizeof(struct mesh_path), GFP_ATOMIC);
if (!new_mpath)
goto err_path_alloc;
- new_node = kmalloc(sizeof(struct mpath_node), GFP_KERNEL);
+ new_node = kmalloc(sizeof(struct mpath_node), GFP_ATOMIC);
if (!new_node)
goto err_node_alloc;
@@ -225,23 +308,13 @@ int mesh_path_add(u8 *dst, struct ieee80211_sub_if_data *sdata)
mesh_paths->mean_chain_len * (mesh_paths->hash_mask + 1))
grow = 1;
+ mesh_paths_generation++;
+
spin_unlock(&mesh_paths->hashwlock[hash_idx]);
read_unlock(&pathtbl_resize_lock);
if (grow) {
- struct mesh_table *oldtbl, *newtbl;
-
- write_lock(&pathtbl_resize_lock);
- oldtbl = mesh_paths;
- newtbl = mesh_table_grow(mesh_paths);
- if (!newtbl) {
- write_unlock(&pathtbl_resize_lock);
- return 0;
- }
- rcu_assign_pointer(mesh_paths, newtbl);
- write_unlock(&pathtbl_resize_lock);
-
- synchronize_rcu();
- mesh_table_free(oldtbl, false);
+ set_bit(MESH_WORK_GROW_MPATH_TABLE, &ifmsh->wrkq_flags);
+ ieee80211_queue_work(&local->hw, &ifmsh->work);
}
return 0;
@@ -256,9 +329,46 @@ err_path_alloc:
return err;
}
+void mesh_mpath_table_grow(void)
+{
+ struct mesh_table *oldtbl, *newtbl;
+
+ write_lock(&pathtbl_resize_lock);
+ oldtbl = mesh_paths;
+ newtbl = mesh_table_grow(mesh_paths);
+ if (!newtbl) {
+ write_unlock(&pathtbl_resize_lock);
+ return;
+ }
+ rcu_assign_pointer(mesh_paths, newtbl);
+ write_unlock(&pathtbl_resize_lock);
+
+ synchronize_rcu();
+ mesh_table_free(oldtbl, false);
+}
+
+void mesh_mpp_table_grow(void)
+{
+ struct mesh_table *oldtbl, *newtbl;
+
+ write_lock(&pathtbl_resize_lock);
+ oldtbl = mpp_paths;
+ newtbl = mesh_table_grow(mpp_paths);
+ if (!newtbl) {
+ write_unlock(&pathtbl_resize_lock);
+ return;
+ }
+ rcu_assign_pointer(mpp_paths, newtbl);
+ write_unlock(&pathtbl_resize_lock);
+
+ synchronize_rcu();
+ mesh_table_free(oldtbl, false);
+}
int mpp_path_add(u8 *dst, u8 *mpp, struct ieee80211_sub_if_data *sdata)
{
+ struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
+ struct ieee80211_local *local = sdata->local;
struct mesh_path *mpath, *new_mpath;
struct mpath_node *node, *new_node;
struct hlist_head *bucket;
@@ -267,8 +377,6 @@ int mpp_path_add(u8 *dst, u8 *mpp, struct ieee80211_sub_if_data *sdata)
int err = 0;
u32 hash_idx;
- might_sleep();
-
if (memcmp(dst, sdata->dev->dev_addr, ETH_ALEN) == 0)
/* never add ourselves as neighbours */
return -ENOTSUPP;
@@ -277,11 +385,11 @@ int mpp_path_add(u8 *dst, u8 *mpp, struct ieee80211_sub_if_data *sdata)
return -ENOTSUPP;
err = -ENOMEM;
- new_mpath = kzalloc(sizeof(struct mesh_path), GFP_KERNEL);
+ new_mpath = kzalloc(sizeof(struct mesh_path), GFP_ATOMIC);
if (!new_mpath)
goto err_path_alloc;
- new_node = kmalloc(sizeof(struct mpath_node), GFP_KERNEL);
+ new_node = kmalloc(sizeof(struct mpath_node), GFP_ATOMIC);
if (!new_node)
goto err_node_alloc;
@@ -315,20 +423,8 @@ int mpp_path_add(u8 *dst, u8 *mpp, struct ieee80211_sub_if_data *sdata)
spin_unlock(&mpp_paths->hashwlock[hash_idx]);
read_unlock(&pathtbl_resize_lock);
if (grow) {
- struct mesh_table *oldtbl, *newtbl;
-
- write_lock(&pathtbl_resize_lock);
- oldtbl = mpp_paths;
- newtbl = mesh_table_grow(mpp_paths);
- if (!newtbl) {
- write_unlock(&pathtbl_resize_lock);
- return 0;
- }
- rcu_assign_pointer(mpp_paths, newtbl);
- write_unlock(&pathtbl_resize_lock);
-
- synchronize_rcu();
- mesh_table_free(oldtbl, false);
+ set_bit(MESH_WORK_GROW_MPP_TABLE, &ifmsh->wrkq_flags);
+ ieee80211_queue_work(&local->hw, &ifmsh->work);
}
return 0;
@@ -466,6 +562,7 @@ int mesh_path_del(u8 *addr, struct ieee80211_sub_if_data *sdata)
err = -ENXIO;
enddel:
+ mesh_paths_generation++;
spin_unlock(&mesh_paths->hashwlock[hash_idx]);
read_unlock(&pathtbl_resize_lock);
return err;
@@ -481,11 +578,9 @@ enddel:
*/
void mesh_path_tx_pending(struct mesh_path *mpath)
{
- struct sk_buff *skb;
-
- while ((skb = skb_dequeue(&mpath->frame_queue)) &&
- (mpath->flags & MESH_PATH_ACTIVE))
- dev_queue_xmit(skb);
+ if (mpath->flags & MESH_PATH_ACTIVE)
+ ieee80211_add_pending_skbs(mpath->sdata->local,
+ &mpath->frame_queue);
}
/**
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c
index cb14253587f..ffcbad75e09 100644
--- a/net/mac80211/mesh_plink.c
+++ b/net/mac80211/mesh_plink.c
@@ -409,7 +409,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
baselen = (u8 *) mgmt->u.action.u.plink_action.variable - (u8 *) mgmt;
if (mgmt->u.action.u.plink_action.action_code == PLINK_CONFIRM) {
baseaddr += 4;
- baselen -= 4;
+ baselen += 4;
}
ieee802_11_parse_elems(baseaddr, len - baselen, &elems);
if (!elems.peer_link) {
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 07e7e41816b..c374d2d73fa 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -27,43 +27,99 @@
#include "rate.h"
#include "led.h"
-#define IEEE80211_ASSOC_SCANS_MAX_TRIES 2
#define IEEE80211_AUTH_TIMEOUT (HZ / 5)
#define IEEE80211_AUTH_MAX_TRIES 3
#define IEEE80211_ASSOC_TIMEOUT (HZ / 5)
#define IEEE80211_ASSOC_MAX_TRIES 3
-#define IEEE80211_MONITORING_INTERVAL (2 * HZ)
-#define IEEE80211_PROBE_WAIT (HZ / 5)
-#define IEEE80211_PROBE_IDLE_TIME (60 * HZ)
-#define IEEE80211_RETRY_AUTH_INTERVAL (1 * HZ)
+#define IEEE80211_MAX_PROBE_TRIES 5
+
+/*
+ * beacon loss detection timeout
+ * XXX: should depend on beacon interval
+ */
+#define IEEE80211_BEACON_LOSS_TIME (2 * HZ)
+/*
+ * Time the connection can be idle before we probe
+ * it to see if we can still talk to the AP.
+ */
+#define IEEE80211_CONNECTION_IDLE_TIME (30 * HZ)
+/*
+ * Time we wait for a probe response after sending
+ * a probe request because of beacon loss or for
+ * checking the connection still works.
+ */
+#define IEEE80211_PROBE_WAIT (HZ / 2)
#define TMR_RUNNING_TIMER 0
#define TMR_RUNNING_CHANSW 1
+/*
+ * All cfg80211 functions have to be called outside a locked
+ * section so that they can acquire a lock themselves... This
+ * is much simpler than queuing up things in cfg80211, but we
+ * do need some indirection for that here.
+ */
+enum rx_mgmt_action {
+ /* no action required */
+ RX_MGMT_NONE,
+
+ /* caller must call cfg80211_send_rx_auth() */
+ RX_MGMT_CFG80211_AUTH,
+
+ /* caller must call cfg80211_send_rx_assoc() */
+ RX_MGMT_CFG80211_ASSOC,
+
+ /* caller must call cfg80211_send_deauth() */
+ RX_MGMT_CFG80211_DEAUTH,
+
+ /* caller must call cfg80211_send_disassoc() */
+ RX_MGMT_CFG80211_DISASSOC,
+
+ /* caller must call cfg80211_auth_timeout() & free work */
+ RX_MGMT_CFG80211_AUTH_TO,
+
+ /* caller must call cfg80211_assoc_timeout() & free work */
+ RX_MGMT_CFG80211_ASSOC_TO,
+};
+
/* utils */
-static int ecw2cw(int ecw)
+static inline void ASSERT_MGD_MTX(struct ieee80211_if_managed *ifmgd)
{
- return (1 << ecw) - 1;
+ WARN_ON(!mutex_is_locked(&ifmgd->mtx));
}
-static u8 *ieee80211_bss_get_ie(struct ieee80211_bss *bss, u8 ie)
+/*
+ * We can have multiple work items (and connection probing)
+ * scheduling this timer, but we need to take care to only
+ * reschedule it when it should fire _earlier_ than it was
+ * asked for before, or if it's not pending right now. This
+ * function ensures that. Note that it then is required to
+ * run this function for all timeouts after the first one
+ * has happened -- the work that runs from this timer will
+ * do that.
+ */
+static void run_again(struct ieee80211_if_managed *ifmgd,
+ unsigned long timeout)
{
- u8 *end, *pos;
+ ASSERT_MGD_MTX(ifmgd);
- pos = bss->cbss.information_elements;
- if (pos == NULL)
- return NULL;
- end = pos + bss->cbss.len_information_elements;
+ if (!timer_pending(&ifmgd->timer) ||
+ time_before(timeout, ifmgd->timer.expires))
+ mod_timer(&ifmgd->timer, timeout);
+}
- while (pos + 1 < end) {
- if (pos + 2 + pos[1] > end)
- break;
- if (pos[0] == ie)
- return pos;
- pos += 2 + pos[1];
- }
+static void mod_beacon_timer(struct ieee80211_sub_if_data *sdata)
+{
+ if (sdata->local->hw.flags & IEEE80211_HW_BEACON_FILTER)
+ return;
- return NULL;
+ mod_timer(&sdata->u.mgd.bcn_mon_timer,
+ round_jiffies_up(jiffies + IEEE80211_BEACON_LOSS_TIME));
+}
+
+static int ecw2cw(int ecw)
+{
+ return (1 << ecw) - 1;
}
static int ieee80211_compatible_rates(struct ieee80211_bss *bss,
@@ -94,11 +150,10 @@ static int ieee80211_compatible_rates(struct ieee80211_bss *bss,
*/
static u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata,
struct ieee80211_ht_info *hti,
- u16 ap_ht_cap_flags)
+ const u8 *bssid, u16 ap_ht_cap_flags)
{
struct ieee80211_local *local = sdata->local;
struct ieee80211_supported_band *sband;
- struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
struct sta_info *sta;
u32 changed = 0;
u16 ht_opmode;
@@ -147,12 +202,10 @@ static u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata,
ieee80211_hw_config(local, 0);
rcu_read_lock();
-
- sta = sta_info_get(local, ifmgd->bssid);
+ sta = sta_info_get(local, bssid);
if (sta)
rate_control_rate_update(local, sband, sta,
IEEE80211_RC_HT_CHANGED);
-
rcu_read_unlock();
}
@@ -175,23 +228,24 @@ static u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata,
/* frame sending functions */
-static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
+static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata,
+ struct ieee80211_mgd_work *wk)
{
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
struct ieee80211_local *local = sdata->local;
struct sk_buff *skb;
struct ieee80211_mgmt *mgmt;
- u8 *pos, *ies, *ht_ie;
+ u8 *pos;
+ const u8 *ies, *ht_ie;
int i, len, count, rates_len, supp_rates_len;
u16 capab;
- struct ieee80211_bss *bss;
int wmm = 0;
struct ieee80211_supported_band *sband;
u32 rates = 0;
skb = dev_alloc_skb(local->hw.extra_tx_headroom +
- sizeof(*mgmt) + 200 + ifmgd->extra_ie_len +
- ifmgd->ssid_len);
+ sizeof(*mgmt) + 200 + wk->ie_len +
+ wk->ssid_len);
if (!skb) {
printk(KERN_DEBUG "%s: failed to allocate buffer for assoc "
"frame\n", sdata->dev->name);
@@ -210,45 +264,35 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
capab |= WLAN_CAPABILITY_SHORT_PREAMBLE;
}
- bss = ieee80211_rx_bss_get(local, ifmgd->bssid,
- local->hw.conf.channel->center_freq,
- ifmgd->ssid, ifmgd->ssid_len);
- if (bss) {
- if (bss->cbss.capability & WLAN_CAPABILITY_PRIVACY)
- capab |= WLAN_CAPABILITY_PRIVACY;
- if (bss->wmm_used)
- wmm = 1;
+ if (wk->bss->cbss.capability & WLAN_CAPABILITY_PRIVACY)
+ capab |= WLAN_CAPABILITY_PRIVACY;
+ if (wk->bss->wmm_used)
+ wmm = 1;
- /* get all rates supported by the device and the AP as
- * some APs don't like getting a superset of their rates
- * in the association request (e.g. D-Link DAP 1353 in
- * b-only mode) */
- rates_len = ieee80211_compatible_rates(bss, sband, &rates);
+ /* get all rates supported by the device and the AP as
+ * some APs don't like getting a superset of their rates
+ * in the association request (e.g. D-Link DAP 1353 in
+ * b-only mode) */
+ rates_len = ieee80211_compatible_rates(wk->bss, sband, &rates);
- if ((bss->cbss.capability & WLAN_CAPABILITY_SPECTRUM_MGMT) &&
- (local->hw.flags & IEEE80211_HW_SPECTRUM_MGMT))
- capab |= WLAN_CAPABILITY_SPECTRUM_MGMT;
-
- ieee80211_rx_bss_put(local, bss);
- } else {
- rates = ~0;
- rates_len = sband->n_bitrates;
- }
+ if ((wk->bss->cbss.capability & WLAN_CAPABILITY_SPECTRUM_MGMT) &&
+ (local->hw.flags & IEEE80211_HW_SPECTRUM_MGMT))
+ capab |= WLAN_CAPABILITY_SPECTRUM_MGMT;
mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
memset(mgmt, 0, 24);
- memcpy(mgmt->da, ifmgd->bssid, ETH_ALEN);
+ memcpy(mgmt->da, wk->bss->cbss.bssid, ETH_ALEN);
memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN);
- memcpy(mgmt->bssid, ifmgd->bssid, ETH_ALEN);
+ memcpy(mgmt->bssid, wk->bss->cbss.bssid, ETH_ALEN);
- if (ifmgd->flags & IEEE80211_STA_PREV_BSSID_SET) {
+ if (!is_zero_ether_addr(wk->prev_bssid)) {
skb_put(skb, 10);
mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
IEEE80211_STYPE_REASSOC_REQ);
mgmt->u.reassoc_req.capab_info = cpu_to_le16(capab);
mgmt->u.reassoc_req.listen_interval =
cpu_to_le16(local->hw.conf.listen_interval);
- memcpy(mgmt->u.reassoc_req.current_ap, ifmgd->prev_bssid,
+ memcpy(mgmt->u.reassoc_req.current_ap, wk->prev_bssid,
ETH_ALEN);
} else {
skb_put(skb, 4);
@@ -260,10 +304,10 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
}
/* SSID */
- ies = pos = skb_put(skb, 2 + ifmgd->ssid_len);
+ ies = pos = skb_put(skb, 2 + wk->ssid_len);
*pos++ = WLAN_EID_SSID;
- *pos++ = ifmgd->ssid_len;
- memcpy(pos, ifmgd->ssid, ifmgd->ssid_len);
+ *pos++ = wk->ssid_len;
+ memcpy(pos, wk->ssid, wk->ssid_len);
/* add all rates which were marked to be used above */
supp_rates_len = rates_len;
@@ -318,9 +362,9 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
}
}
- if (ifmgd->extra_ie) {
- pos = skb_put(skb, ifmgd->extra_ie_len);
- memcpy(pos, ifmgd->extra_ie, ifmgd->extra_ie_len);
+ if (wk->ie_len && wk->ie) {
+ pos = skb_put(skb, wk->ie_len);
+ memcpy(pos, wk->ie, wk->ie_len);
}
if (wmm && (ifmgd->flags & IEEE80211_STA_WMM_ENABLED)) {
@@ -345,9 +389,9 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
*/
if (wmm && (ifmgd->flags & IEEE80211_STA_WMM_ENABLED) &&
sband->ht_cap.ht_supported &&
- (ht_ie = ieee80211_bss_get_ie(bss, WLAN_EID_HT_INFORMATION)) &&
+ (ht_ie = ieee80211_bss_get_ie(&wk->bss->cbss, WLAN_EID_HT_INFORMATION)) &&
ht_ie[1] >= sizeof(struct ieee80211_ht_info) &&
- (!(ifmgd->flags & IEEE80211_STA_TKIP_WEP_USED))) {
+ (!(ifmgd->flags & IEEE80211_STA_DISABLE_11N))) {
struct ieee80211_ht_info *ht_info =
(struct ieee80211_ht_info *)(ht_ie + 2);
u16 cap = sband->ht_cap.cap;
@@ -382,18 +426,13 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
memcpy(pos, &sband->ht_cap.mcs, sizeof(sband->ht_cap.mcs));
}
- kfree(ifmgd->assocreq_ies);
- ifmgd->assocreq_ies_len = (skb->data + skb->len) - ies;
- ifmgd->assocreq_ies = kmalloc(ifmgd->assocreq_ies_len, GFP_KERNEL);
- if (ifmgd->assocreq_ies)
- memcpy(ifmgd->assocreq_ies, ies, ifmgd->assocreq_ies_len);
-
ieee80211_tx_skb(sdata, skb, 0);
}
static void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata,
- u16 stype, u16 reason)
+ const u8 *bssid, u16 stype, u16 reason,
+ void *cookie)
{
struct ieee80211_local *local = sdata->local;
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
@@ -410,18 +449,18 @@ static void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata,
mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
memset(mgmt, 0, 24);
- memcpy(mgmt->da, ifmgd->bssid, ETH_ALEN);
+ memcpy(mgmt->da, bssid, ETH_ALEN);
memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN);
- memcpy(mgmt->bssid, ifmgd->bssid, ETH_ALEN);
+ memcpy(mgmt->bssid, bssid, ETH_ALEN);
mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | stype);
skb_put(skb, 2);
/* u.deauth.reason_code == u.disassoc.reason_code */
mgmt->u.deauth.reason_code = cpu_to_le16(reason);
if (stype == IEEE80211_STYPE_DEAUTH)
- cfg80211_send_deauth(sdata->dev, (u8 *) mgmt, skb->len);
+ cfg80211_send_deauth(sdata->dev, (u8 *)mgmt, skb->len, cookie);
else
- cfg80211_send_disassoc(sdata->dev, (u8 *) mgmt, skb->len);
+ cfg80211_send_disassoc(sdata->dev, (u8 *)mgmt, skb->len, cookie);
ieee80211_tx_skb(sdata, skb, ifmgd->flags & IEEE80211_STA_MFP_ENABLED);
}
@@ -494,28 +533,26 @@ static void ieee80211_chswitch_work(struct work_struct *work)
{
struct ieee80211_sub_if_data *sdata =
container_of(work, struct ieee80211_sub_if_data, u.mgd.chswitch_work);
- struct ieee80211_bss *bss;
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
if (!netif_running(sdata->dev))
return;
- bss = ieee80211_rx_bss_get(sdata->local, ifmgd->bssid,
- sdata->local->hw.conf.channel->center_freq,
- ifmgd->ssid, ifmgd->ssid_len);
- if (!bss)
- goto exit;
+ mutex_lock(&ifmgd->mtx);
+ if (!ifmgd->associated)
+ goto out;
sdata->local->oper_channel = sdata->local->csa_channel;
+ ieee80211_hw_config(sdata->local, IEEE80211_CONF_CHANGE_CHANNEL);
+
/* XXX: shouldn't really modify cfg80211-owned data! */
- if (!ieee80211_hw_config(sdata->local, IEEE80211_CONF_CHANGE_CHANNEL))
- bss->cbss.channel = sdata->local->oper_channel;
+ ifmgd->associated->cbss.channel = sdata->local->oper_channel;
- ieee80211_rx_bss_put(sdata->local, bss);
-exit:
- ifmgd->flags &= ~IEEE80211_STA_CSA_RECEIVED;
ieee80211_wake_queues_by_reason(&sdata->local->hw,
IEEE80211_QUEUE_STOP_REASON_CSA);
+ out:
+ ifmgd->flags &= ~IEEE80211_STA_CSA_RECEIVED;
+ mutex_unlock(&ifmgd->mtx);
}
static void ieee80211_chswitch_timer(unsigned long data)
@@ -529,7 +566,7 @@ static void ieee80211_chswitch_timer(unsigned long data)
return;
}
- queue_work(sdata->local->hw.workqueue, &ifmgd->chswitch_work);
+ ieee80211_queue_work(&sdata->local->hw, &ifmgd->chswitch_work);
}
void ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
@@ -540,10 +577,12 @@ void ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
int new_freq = ieee80211_channel_to_frequency(sw_elem->new_ch_num);
- if (ifmgd->state != IEEE80211_STA_MLME_ASSOCIATED)
+ ASSERT_MGD_MTX(ifmgd);
+
+ if (!ifmgd->associated)
return;
- if (sdata->local->sw_scanning || sdata->local->hw_scanning)
+ if (sdata->local->scanning)
return;
/* Disregard subsequent beacons if we are already running a timer
@@ -559,7 +598,7 @@ void ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
sdata->local->csa_channel = new_ch;
if (sw_elem->count <= 1) {
- queue_work(sdata->local->hw.workqueue, &ifmgd->chswitch_work);
+ ieee80211_queue_work(&sdata->local->hw, &ifmgd->chswitch_work);
} else {
ieee80211_stop_queues_by_reason(&sdata->local->hw,
IEEE80211_QUEUE_STOP_REASON_CSA);
@@ -601,7 +640,7 @@ static void ieee80211_enable_ps(struct ieee80211_local *local,
* If we are scanning right now then the parameters will
* take effect when scan finishes.
*/
- if (local->hw_scanning || local->sw_scanning)
+ if (local->scanning)
return;
if (conf->dynamic_ps_timeout > 0 &&
@@ -651,8 +690,9 @@ void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency)
}
if (count == 1 && found->u.mgd.powersave &&
- (found->u.mgd.flags & IEEE80211_STA_ASSOCIATED) &&
- !(found->u.mgd.flags & IEEE80211_STA_PROBEREQ_POLL)) {
+ found->u.mgd.associated && list_empty(&found->u.mgd.work_list) &&
+ !(found->u.mgd.flags & (IEEE80211_STA_BEACON_POLL |
+ IEEE80211_STA_CONNECTION_POLL))) {
s32 beaconint_us;
if (latency < 0)
@@ -724,7 +764,7 @@ void ieee80211_dynamic_ps_timer(unsigned long data)
if (local->quiescing || local->suspended)
return;
- queue_work(local->hw.workqueue, &local->dynamic_ps_enable_work);
+ ieee80211_queue_work(&local->hw, &local->dynamic_ps_enable_work);
}
/* MLME */
@@ -806,9 +846,6 @@ static u32 ieee80211_handle_bss_capability(struct ieee80211_sub_if_data *sdata,
u16 capab, bool erp_valid, u8 erp)
{
struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf;
-#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
- struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
-#endif
u32 changed = 0;
bool use_protection;
bool use_short_preamble;
@@ -825,42 +862,16 @@ static u32 ieee80211_handle_bss_capability(struct ieee80211_sub_if_data *sdata,
use_short_slot = !!(capab & WLAN_CAPABILITY_SHORT_SLOT_TIME);
if (use_protection != bss_conf->use_cts_prot) {
-#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
- if (net_ratelimit()) {
- printk(KERN_DEBUG "%s: CTS protection %s (BSSID=%pM)\n",
- sdata->dev->name,
- use_protection ? "enabled" : "disabled",
- ifmgd->bssid);
- }
-#endif
bss_conf->use_cts_prot = use_protection;
changed |= BSS_CHANGED_ERP_CTS_PROT;
}
if (use_short_preamble != bss_conf->use_short_preamble) {
-#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
- if (net_ratelimit()) {
- printk(KERN_DEBUG "%s: switched to %s barker preamble"
- " (BSSID=%pM)\n",
- sdata->dev->name,
- use_short_preamble ? "short" : "long",
- ifmgd->bssid);
- }
-#endif
bss_conf->use_short_preamble = use_short_preamble;
changed |= BSS_CHANGED_ERP_PREAMBLE;
}
if (use_short_slot != bss_conf->use_short_slot) {
-#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
- if (net_ratelimit()) {
- printk(KERN_DEBUG "%s: switched to %s slot time"
- " (BSSID=%pM)\n",
- sdata->dev->name,
- use_short_slot ? "short" : "long",
- ifmgd->bssid);
- }
-#endif
bss_conf->use_short_slot = use_short_slot;
changed |= BSS_CHANGED_ERP_SLOT;
}
@@ -868,105 +879,31 @@ static u32 ieee80211_handle_bss_capability(struct ieee80211_sub_if_data *sdata,
return changed;
}
-static void ieee80211_sta_send_apinfo(struct ieee80211_sub_if_data *sdata)
-{
- union iwreq_data wrqu;
-
- memset(&wrqu, 0, sizeof(wrqu));
- if (sdata->u.mgd.flags & IEEE80211_STA_ASSOCIATED)
- memcpy(wrqu.ap_addr.sa_data, sdata->u.mgd.bssid, ETH_ALEN);
- wrqu.ap_addr.sa_family = ARPHRD_ETHER;
- wireless_send_event(sdata->dev, SIOCGIWAP, &wrqu, NULL);
-}
-
-static void ieee80211_sta_send_associnfo(struct ieee80211_sub_if_data *sdata)
-{
- struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
- char *buf;
- size_t len;
- int i;
- union iwreq_data wrqu;
-
- if (!ifmgd->assocreq_ies && !ifmgd->assocresp_ies)
- return;
-
- buf = kmalloc(50 + 2 * (ifmgd->assocreq_ies_len +
- ifmgd->assocresp_ies_len), GFP_KERNEL);
- if (!buf)
- return;
-
- len = sprintf(buf, "ASSOCINFO(");
- if (ifmgd->assocreq_ies) {
- len += sprintf(buf + len, "ReqIEs=");
- for (i = 0; i < ifmgd->assocreq_ies_len; i++) {
- len += sprintf(buf + len, "%02x",
- ifmgd->assocreq_ies[i]);
- }
- }
- if (ifmgd->assocresp_ies) {
- if (ifmgd->assocreq_ies)
- len += sprintf(buf + len, " ");
- len += sprintf(buf + len, "RespIEs=");
- for (i = 0; i < ifmgd->assocresp_ies_len; i++) {
- len += sprintf(buf + len, "%02x",
- ifmgd->assocresp_ies[i]);
- }
- }
- len += sprintf(buf + len, ")");
-
- if (len > IW_CUSTOM_MAX) {
- len = sprintf(buf, "ASSOCRESPIE=");
- for (i = 0; i < ifmgd->assocresp_ies_len; i++) {
- len += sprintf(buf + len, "%02x",
- ifmgd->assocresp_ies[i]);
- }
- }
-
- if (len <= IW_CUSTOM_MAX) {
- memset(&wrqu, 0, sizeof(wrqu));
- wrqu.data.length = len;
- wireless_send_event(sdata->dev, IWEVCUSTOM, &wrqu, buf);
- }
-
- kfree(buf);
-}
-
-
static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
+ struct ieee80211_mgd_work *wk,
u32 bss_info_changed)
{
- struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
struct ieee80211_local *local = sdata->local;
- struct ieee80211_conf *conf = &local_to_hw(local)->conf;
-
- struct ieee80211_bss *bss;
+ struct ieee80211_bss *bss = wk->bss;
bss_info_changed |= BSS_CHANGED_ASSOC;
- ifmgd->flags |= IEEE80211_STA_ASSOCIATED;
+ /* set timing information */
+ sdata->vif.bss_conf.beacon_int = bss->cbss.beacon_interval;
+ sdata->vif.bss_conf.timestamp = bss->cbss.tsf;
+ sdata->vif.bss_conf.dtim_period = bss->dtim_period;
- bss = ieee80211_rx_bss_get(local, ifmgd->bssid,
- conf->channel->center_freq,
- ifmgd->ssid, ifmgd->ssid_len);
- if (bss) {
- /* set timing information */
- sdata->vif.bss_conf.beacon_int = bss->cbss.beacon_interval;
- sdata->vif.bss_conf.timestamp = bss->cbss.tsf;
- sdata->vif.bss_conf.dtim_period = bss->dtim_period;
+ bss_info_changed |= BSS_CHANGED_BEACON_INT;
+ bss_info_changed |= ieee80211_handle_bss_capability(sdata,
+ bss->cbss.capability, bss->has_erp_value, bss->erp_value);
- bss_info_changed |= BSS_CHANGED_BEACON_INT;
- bss_info_changed |= ieee80211_handle_bss_capability(sdata,
- bss->cbss.capability, bss->has_erp_value, bss->erp_value);
+ sdata->u.mgd.associated = bss;
+ sdata->u.mgd.old_associate_work = wk;
+ memcpy(sdata->u.mgd.bssid, bss->cbss.bssid, ETH_ALEN);
- cfg80211_hold_bss(&bss->cbss);
+ /* just to be sure */
+ sdata->u.mgd.flags &= ~(IEEE80211_STA_CONNECTION_POLL |
+ IEEE80211_STA_BEACON_POLL);
- ieee80211_rx_bss_put(local, bss);
- }
-
- ifmgd->flags |= IEEE80211_STA_PREV_BSSID_SET;
- memcpy(ifmgd->prev_bssid, sdata->u.mgd.bssid, ETH_ALEN);
- ieee80211_sta_send_associnfo(sdata);
-
- ifmgd->last_probe = jiffies;
ieee80211_led_assoc(local, 1);
sdata->vif.bss_conf.assoc = 1;
@@ -982,176 +919,157 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
ieee80211_bss_info_change_notify(sdata, bss_info_changed);
- /* will be same as sdata */
- if (local->ps_sdata) {
- mutex_lock(&local->iflist_mtx);
- ieee80211_recalc_ps(local, -1);
- mutex_unlock(&local->iflist_mtx);
- }
+ mutex_lock(&local->iflist_mtx);
+ ieee80211_recalc_ps(local, -1);
+ mutex_unlock(&local->iflist_mtx);
netif_tx_start_all_queues(sdata->dev);
netif_carrier_on(sdata->dev);
-
- ieee80211_sta_send_apinfo(sdata);
}
-static void ieee80211_direct_probe(struct ieee80211_sub_if_data *sdata)
+static enum rx_mgmt_action __must_check
+ieee80211_direct_probe(struct ieee80211_sub_if_data *sdata,
+ struct ieee80211_mgd_work *wk)
{
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
struct ieee80211_local *local = sdata->local;
- ifmgd->direct_probe_tries++;
- if (ifmgd->direct_probe_tries > IEEE80211_AUTH_MAX_TRIES) {
+ wk->tries++;
+ if (wk->tries > IEEE80211_AUTH_MAX_TRIES) {
printk(KERN_DEBUG "%s: direct probe to AP %pM timed out\n",
- sdata->dev->name, ifmgd->bssid);
- ifmgd->state = IEEE80211_STA_MLME_DISABLED;
- ieee80211_recalc_idle(local);
- cfg80211_send_auth_timeout(sdata->dev, ifmgd->bssid);
+ sdata->dev->name, wk->bss->cbss.bssid);
/*
* Most likely AP is not in the range so remove the
- * bss information associated to the AP
+ * bss struct for that AP.
*/
- ieee80211_rx_bss_remove(sdata, ifmgd->bssid,
- sdata->local->hw.conf.channel->center_freq,
- ifmgd->ssid, ifmgd->ssid_len);
+ cfg80211_unlink_bss(local->hw.wiphy, &wk->bss->cbss);
/*
* We might have a pending scan which had no chance to run yet
- * due to state == IEEE80211_STA_MLME_DIRECT_PROBE.
- * Hence, queue the STAs work again
+ * due to work needing to be done. Hence, queue the STAs work
+ * again for that.
*/
- queue_work(local->hw.workqueue, &ifmgd->work);
- return;
+ ieee80211_queue_work(&local->hw, &ifmgd->work);
+ return RX_MGMT_CFG80211_AUTH_TO;
}
- printk(KERN_DEBUG "%s: direct probe to AP %pM try %d\n",
- sdata->dev->name, ifmgd->bssid,
- ifmgd->direct_probe_tries);
-
- ifmgd->state = IEEE80211_STA_MLME_DIRECT_PROBE;
+ printk(KERN_DEBUG "%s: direct probe to AP %pM (try %d)\n",
+ sdata->dev->name, wk->bss->cbss.bssid,
+ wk->tries);
- /* Direct probe is sent to broadcast address as some APs
+ /*
+ * Direct probe is sent to broadcast address as some APs
* will not answer to direct packet in unassociated state.
*/
- ieee80211_send_probe_req(sdata, NULL,
- ifmgd->ssid, ifmgd->ssid_len, NULL, 0);
+ ieee80211_send_probe_req(sdata, NULL, wk->ssid, wk->ssid_len, NULL, 0);
+
+ wk->timeout = jiffies + IEEE80211_AUTH_TIMEOUT;
+ run_again(ifmgd, wk->timeout);
- mod_timer(&ifmgd->timer, jiffies + IEEE80211_AUTH_TIMEOUT);
+ return RX_MGMT_NONE;
}
-static void ieee80211_authenticate(struct ieee80211_sub_if_data *sdata)
+static enum rx_mgmt_action __must_check
+ieee80211_authenticate(struct ieee80211_sub_if_data *sdata,
+ struct ieee80211_mgd_work *wk)
{
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
struct ieee80211_local *local = sdata->local;
- u8 *ies;
- size_t ies_len;
- ifmgd->auth_tries++;
- if (ifmgd->auth_tries > IEEE80211_AUTH_MAX_TRIES) {
+ wk->tries++;
+ if (wk->tries > IEEE80211_AUTH_MAX_TRIES) {
printk(KERN_DEBUG "%s: authentication with AP %pM"
" timed out\n",
- sdata->dev->name, ifmgd->bssid);
- ifmgd->state = IEEE80211_STA_MLME_DISABLED;
- ieee80211_recalc_idle(local);
- cfg80211_send_auth_timeout(sdata->dev, ifmgd->bssid);
- ieee80211_rx_bss_remove(sdata, ifmgd->bssid,
- sdata->local->hw.conf.channel->center_freq,
- ifmgd->ssid, ifmgd->ssid_len);
+ sdata->dev->name, wk->bss->cbss.bssid);
+
+ /*
+ * Most likely AP is not in the range so remove the
+ * bss struct for that AP.
+ */
+ cfg80211_unlink_bss(local->hw.wiphy, &wk->bss->cbss);
/*
* We might have a pending scan which had no chance to run yet
- * due to state == IEEE80211_STA_MLME_AUTHENTICATE.
- * Hence, queue the STAs work again
+ * due to work needing to be done. Hence, queue the STAs work
+ * again for that.
*/
- queue_work(local->hw.workqueue, &ifmgd->work);
- return;
+ ieee80211_queue_work(&local->hw, &ifmgd->work);
+ return RX_MGMT_CFG80211_AUTH_TO;
}
- ifmgd->state = IEEE80211_STA_MLME_AUTHENTICATE;
- printk(KERN_DEBUG "%s: authenticate with AP %pM\n",
- sdata->dev->name, ifmgd->bssid);
+ printk(KERN_DEBUG "%s: authenticate with AP %pM (try %d)\n",
+ sdata->dev->name, wk->bss->cbss.bssid, wk->tries);
- if (ifmgd->flags & IEEE80211_STA_EXT_SME) {
- ies = ifmgd->sme_auth_ie;
- ies_len = ifmgd->sme_auth_ie_len;
- } else {
- ies = NULL;
- ies_len = 0;
- }
- ieee80211_send_auth(sdata, 1, ifmgd->auth_alg, ies, ies_len,
- ifmgd->bssid, 0);
- ifmgd->auth_transaction = 2;
+ ieee80211_send_auth(sdata, 1, wk->auth_alg, wk->ie, wk->ie_len,
+ wk->bss->cbss.bssid, NULL, 0, 0);
+ wk->auth_transaction = 2;
- mod_timer(&ifmgd->timer, jiffies + IEEE80211_AUTH_TIMEOUT);
+ wk->timeout = jiffies + IEEE80211_AUTH_TIMEOUT;
+ run_again(ifmgd, wk->timeout);
+
+ return RX_MGMT_NONE;
}
-/*
- * The disassoc 'reason' argument can be either our own reason
- * if self disconnected or a reason code from the AP.
- */
static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
- bool deauth, bool self_disconnected,
- u16 reason)
+ bool deauth)
{
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
struct ieee80211_local *local = sdata->local;
- struct ieee80211_conf *conf = &local_to_hw(local)->conf;
- struct ieee80211_bss *bss;
struct sta_info *sta;
u32 changed = 0, config_changed = 0;
+ u8 bssid[ETH_ALEN];
+
+ ASSERT_MGD_MTX(ifmgd);
+
+ if (WARN_ON(!ifmgd->associated))
+ return;
+
+ memcpy(bssid, ifmgd->associated->cbss.bssid, ETH_ALEN);
+
+ ifmgd->associated = NULL;
+ memset(ifmgd->bssid, 0, ETH_ALEN);
if (deauth) {
- ifmgd->direct_probe_tries = 0;
- ifmgd->auth_tries = 0;
+ kfree(ifmgd->old_associate_work);
+ ifmgd->old_associate_work = NULL;
+ } else {
+ struct ieee80211_mgd_work *wk = ifmgd->old_associate_work;
+
+ wk->state = IEEE80211_MGD_STATE_IDLE;
+ list_add(&wk->list, &ifmgd->work_list);
}
- ifmgd->assoc_scan_tries = 0;
- ifmgd->assoc_tries = 0;
+
+ /*
+ * we need to commit the associated = NULL change because the
+ * scan code uses that to determine whether this iface should
+ * go to/wake up from powersave or not -- and could otherwise
+ * wake the queues erroneously.
+ */
+ smp_mb();
+
+ /*
+ * Thus, we can only afterwards stop the queues -- to account
+ * for the case where another CPU is finishing a scan at this
+ * time -- we don't want the scan code to enable queues.
+ */
netif_tx_stop_all_queues(sdata->dev);
netif_carrier_off(sdata->dev);
rcu_read_lock();
- sta = sta_info_get(local, ifmgd->bssid);
+ sta = sta_info_get(local, bssid);
if (sta)
ieee80211_sta_tear_down_BA_sessions(sta);
rcu_read_unlock();
- bss = ieee80211_rx_bss_get(local, ifmgd->bssid,
- conf->channel->center_freq,
- ifmgd->ssid, ifmgd->ssid_len);
-
- if (bss) {
- cfg80211_unhold_bss(&bss->cbss);
- ieee80211_rx_bss_put(local, bss);
- }
-
- if (self_disconnected) {
- if (deauth)
- ieee80211_send_deauth_disassoc(sdata,
- IEEE80211_STYPE_DEAUTH, reason);
- else
- ieee80211_send_deauth_disassoc(sdata,
- IEEE80211_STYPE_DISASSOC, reason);
- }
-
- ifmgd->flags &= ~IEEE80211_STA_ASSOCIATED;
changed |= ieee80211_reset_erp_info(sdata);
ieee80211_led_assoc(local, 0);
changed |= BSS_CHANGED_ASSOC;
sdata->vif.bss_conf.assoc = false;
- ieee80211_sta_send_apinfo(sdata);
-
- if (self_disconnected || reason == WLAN_REASON_DISASSOC_STA_HAS_LEFT) {
- ifmgd->state = IEEE80211_STA_MLME_DISABLED;
- ieee80211_rx_bss_remove(sdata, ifmgd->bssid,
- sdata->local->hw.conf.channel->center_freq,
- ifmgd->ssid, ifmgd->ssid_len);
- }
-
ieee80211_set_wmm_default(sdata);
ieee80211_recalc_idle(local);
@@ -1180,7 +1098,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
rcu_read_lock();
- sta = sta_info_get(local, ifmgd->bssid);
+ sta = sta_info_get(local, bssid);
if (!sta) {
rcu_read_unlock();
return;
@@ -1193,83 +1111,42 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
sta_info_destroy(sta);
}
-static int ieee80211_sta_wep_configured(struct ieee80211_sub_if_data *sdata)
-{
- if (!sdata || !sdata->default_key ||
- sdata->default_key->conf.alg != ALG_WEP)
- return 0;
- return 1;
-}
-
-static int ieee80211_privacy_mismatch(struct ieee80211_sub_if_data *sdata)
-{
- struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
- struct ieee80211_local *local = sdata->local;
- struct ieee80211_bss *bss;
- int bss_privacy;
- int wep_privacy;
- int privacy_invoked;
-
- if (!ifmgd || (ifmgd->flags & IEEE80211_STA_EXT_SME))
- return 0;
-
- bss = ieee80211_rx_bss_get(local, ifmgd->bssid,
- local->hw.conf.channel->center_freq,
- ifmgd->ssid, ifmgd->ssid_len);
- if (!bss)
- return 0;
-
- bss_privacy = !!(bss->cbss.capability & WLAN_CAPABILITY_PRIVACY);
- wep_privacy = !!ieee80211_sta_wep_configured(sdata);
- privacy_invoked = !!(ifmgd->flags & IEEE80211_STA_PRIVACY_INVOKED);
-
- ieee80211_rx_bss_put(local, bss);
-
- if ((bss_privacy == wep_privacy) || (bss_privacy == privacy_invoked))
- return 0;
-
- return 1;
-}
-
-static void ieee80211_associate(struct ieee80211_sub_if_data *sdata)
+static enum rx_mgmt_action __must_check
+ieee80211_associate(struct ieee80211_sub_if_data *sdata,
+ struct ieee80211_mgd_work *wk)
{
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
struct ieee80211_local *local = sdata->local;
- ifmgd->assoc_tries++;
- if (ifmgd->assoc_tries > IEEE80211_ASSOC_MAX_TRIES) {
+ wk->tries++;
+ if (wk->tries > IEEE80211_ASSOC_MAX_TRIES) {
printk(KERN_DEBUG "%s: association with AP %pM"
" timed out\n",
- sdata->dev->name, ifmgd->bssid);
- ifmgd->state = IEEE80211_STA_MLME_DISABLED;
- ieee80211_recalc_idle(local);
- cfg80211_send_assoc_timeout(sdata->dev, ifmgd->bssid);
- ieee80211_rx_bss_remove(sdata, ifmgd->bssid,
- sdata->local->hw.conf.channel->center_freq,
- ifmgd->ssid, ifmgd->ssid_len);
+ sdata->dev->name, wk->bss->cbss.bssid);
+
+ /*
+ * Most likely AP is not in the range so remove the
+ * bss struct for that AP.
+ */
+ cfg80211_unlink_bss(local->hw.wiphy, &wk->bss->cbss);
+
/*
* We might have a pending scan which had no chance to run yet
- * due to state == IEEE80211_STA_MLME_ASSOCIATE.
- * Hence, queue the STAs work again
+ * due to work needing to be done. Hence, queue the STAs work
+ * again for that.
*/
- queue_work(local->hw.workqueue, &ifmgd->work);
- return;
+ ieee80211_queue_work(&local->hw, &ifmgd->work);
+ return RX_MGMT_CFG80211_ASSOC_TO;
}
- ifmgd->state = IEEE80211_STA_MLME_ASSOCIATE;
- printk(KERN_DEBUG "%s: associate with AP %pM\n",
- sdata->dev->name, ifmgd->bssid);
- if (ieee80211_privacy_mismatch(sdata)) {
- printk(KERN_DEBUG "%s: mismatch in privacy configuration and "
- "mixed-cell disabled - abort association\n", sdata->dev->name);
- ifmgd->state = IEEE80211_STA_MLME_DISABLED;
- ieee80211_recalc_idle(local);
- return;
- }
+ printk(KERN_DEBUG "%s: associate with AP %pM (try %d)\n",
+ sdata->dev->name, wk->bss->cbss.bssid, wk->tries);
+ ieee80211_send_assoc(sdata, wk);
- ieee80211_send_assoc(sdata);
+ wk->timeout = jiffies + IEEE80211_ASSOC_TIMEOUT;
+ run_again(ifmgd, wk->timeout);
- mod_timer(&ifmgd->timer, jiffies + IEEE80211_ASSOC_TIMEOUT);
+ return RX_MGMT_NONE;
}
void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata,
@@ -1280,160 +1157,113 @@ void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata,
* from AP because we know that the connection is working both ways
* at that time. But multicast frames (and hence also beacons) must
* be ignored here, because we need to trigger the timer during
- * data idle periods for sending the periodical probe request to
- * the AP.
- */
- if (!is_multicast_ether_addr(hdr->addr1))
- mod_timer(&sdata->u.mgd.timer,
- jiffies + IEEE80211_MONITORING_INTERVAL);
-}
-
-void ieee80211_beacon_loss_work(struct work_struct *work)
-{
- struct ieee80211_sub_if_data *sdata =
- container_of(work, struct ieee80211_sub_if_data,
- u.mgd.beacon_loss_work);
- struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
-
- /*
- * The driver has already reported this event and we have
- * already sent a probe request. Maybe the AP died and the
- * driver keeps reporting until we disassociate... We have
- * to ignore that because otherwise we would continually
- * reset the timer and never check whether we received a
- * probe response!
+ * data idle periods for sending the periodic probe request to the
+ * AP we're connected to.
*/
- if (ifmgd->flags & IEEE80211_STA_PROBEREQ_POLL)
+ if (is_multicast_ether_addr(hdr->addr1))
return;
-#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
- if (net_ratelimit()) {
- printk(KERN_DEBUG "%s: driver reports beacon loss from AP %pM "
- "- sending probe request\n", sdata->dev->name,
- sdata->u.mgd.bssid);
- }
-#endif
-
- ifmgd->flags |= IEEE80211_STA_PROBEREQ_POLL;
-
- mutex_lock(&sdata->local->iflist_mtx);
- ieee80211_recalc_ps(sdata->local, -1);
- mutex_unlock(&sdata->local->iflist_mtx);
-
- ieee80211_send_probe_req(sdata, ifmgd->bssid, ifmgd->ssid,
- ifmgd->ssid_len, NULL, 0);
-
- mod_timer(&ifmgd->timer, jiffies + IEEE80211_PROBE_WAIT);
+ mod_timer(&sdata->u.mgd.conn_mon_timer,
+ round_jiffies_up(jiffies + IEEE80211_CONNECTION_IDLE_TIME));
}
-void ieee80211_beacon_loss(struct ieee80211_vif *vif)
+static void ieee80211_mgd_probe_ap_send(struct ieee80211_sub_if_data *sdata)
{
- struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
+ struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
+ const u8 *ssid;
+
+ ssid = ieee80211_bss_get_ie(&ifmgd->associated->cbss, WLAN_EID_SSID);
+ ieee80211_send_probe_req(sdata, ifmgd->associated->cbss.bssid,
+ ssid + 2, ssid[1], NULL, 0);
- queue_work(sdata->local->hw.workqueue,
- &sdata->u.mgd.beacon_loss_work);
+ ifmgd->probe_send_count++;
+ ifmgd->probe_timeout = jiffies + IEEE80211_PROBE_WAIT;
+ run_again(ifmgd, ifmgd->probe_timeout);
}
-EXPORT_SYMBOL(ieee80211_beacon_loss);
-static void ieee80211_associated(struct ieee80211_sub_if_data *sdata)
+static void ieee80211_mgd_probe_ap(struct ieee80211_sub_if_data *sdata,
+ bool beacon)
{
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
- struct ieee80211_local *local = sdata->local;
- struct sta_info *sta;
- unsigned long last_rx;
- bool disassoc = false;
+ bool already = false;
- /* TODO: start monitoring current AP signal quality and number of
- * missed beacons. Scan other channels every now and then and search
- * for better APs. */
- /* TODO: remove expired BSSes */
+ if (!netif_running(sdata->dev))
+ return;
- ifmgd->state = IEEE80211_STA_MLME_ASSOCIATED;
+ if (sdata->local->scanning)
+ return;
- rcu_read_lock();
+ mutex_lock(&ifmgd->mtx);
- sta = sta_info_get(local, ifmgd->bssid);
- if (!sta) {
- printk(KERN_DEBUG "%s: No STA entry for own AP %pM\n",
- sdata->dev->name, ifmgd->bssid);
- disassoc = true;
- rcu_read_unlock();
+ if (!ifmgd->associated)
goto out;
- }
-
- last_rx = sta->last_rx;
- rcu_read_unlock();
- if ((ifmgd->flags & IEEE80211_STA_PROBEREQ_POLL) &&
- time_after(jiffies, last_rx + IEEE80211_PROBE_WAIT)) {
- printk(KERN_DEBUG "%s: no probe response from AP %pM "
- "- disassociating\n",
- sdata->dev->name, ifmgd->bssid);
- disassoc = true;
- ifmgd->flags &= ~IEEE80211_STA_PROBEREQ_POLL;
- goto out;
- }
+#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
+ if (beacon && net_ratelimit())
+ printk(KERN_DEBUG "%s: detected beacon loss from AP "
+ "- sending probe request\n", sdata->dev->name);
+#endif
/*
- * Beacon filtering is only enabled with power save and then the
- * stack should not check for beacon loss.
+ * The driver/our work has already reported this event or the
+ * connection monitoring has kicked in and we have already sent
+ * a probe request. Or maybe the AP died and the driver keeps
+ * reporting until we disassociate...
+ *
+ * In either case we have to ignore the current call to this
+ * function (except for setting the correct probe reason bit)
+ * because otherwise we would reset the timer every time and
+ * never check whether we received a probe response!
*/
- if (!((local->hw.flags & IEEE80211_HW_BEACON_FILTER) &&
- (local->hw.conf.flags & IEEE80211_CONF_PS)) &&
- time_after(jiffies,
- ifmgd->last_beacon + IEEE80211_MONITORING_INTERVAL)) {
-#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
- if (net_ratelimit()) {
- printk(KERN_DEBUG "%s: beacon loss from AP %pM "
- "- sending probe request\n",
- sdata->dev->name, ifmgd->bssid);
- }
-#endif
- ifmgd->flags |= IEEE80211_STA_PROBEREQ_POLL;
- mutex_lock(&local->iflist_mtx);
- ieee80211_recalc_ps(local, -1);
- mutex_unlock(&local->iflist_mtx);
- ieee80211_send_probe_req(sdata, ifmgd->bssid, ifmgd->ssid,
- ifmgd->ssid_len, NULL, 0);
- mod_timer(&ifmgd->timer, jiffies + IEEE80211_PROBE_WAIT);
+ if (ifmgd->flags & (IEEE80211_STA_BEACON_POLL |
+ IEEE80211_STA_CONNECTION_POLL))
+ already = true;
+
+ if (beacon)
+ ifmgd->flags |= IEEE80211_STA_BEACON_POLL;
+ else
+ ifmgd->flags |= IEEE80211_STA_CONNECTION_POLL;
+
+ if (already)
goto out;
- }
- if (time_after(jiffies, last_rx + IEEE80211_PROBE_IDLE_TIME)) {
- ifmgd->flags |= IEEE80211_STA_PROBEREQ_POLL;
- mutex_lock(&local->iflist_mtx);
- ieee80211_recalc_ps(local, -1);
- mutex_unlock(&local->iflist_mtx);
- ieee80211_send_probe_req(sdata, ifmgd->bssid, ifmgd->ssid,
- ifmgd->ssid_len, NULL, 0);
- }
+ mutex_lock(&sdata->local->iflist_mtx);
+ ieee80211_recalc_ps(sdata->local, -1);
+ mutex_unlock(&sdata->local->iflist_mtx);
+ ifmgd->probe_send_count = 0;
+ ieee80211_mgd_probe_ap_send(sdata);
out:
- if (!disassoc)
- mod_timer(&ifmgd->timer,
- jiffies + IEEE80211_MONITORING_INTERVAL);
- else
- ieee80211_set_disassoc(sdata, true, true,
- WLAN_REASON_PREV_AUTH_NOT_VALID);
+ mutex_unlock(&ifmgd->mtx);
}
+void ieee80211_beacon_loss_work(struct work_struct *work)
+{
+ struct ieee80211_sub_if_data *sdata =
+ container_of(work, struct ieee80211_sub_if_data,
+ u.mgd.beacon_loss_work);
+
+ ieee80211_mgd_probe_ap(sdata, true);
+}
-static void ieee80211_auth_completed(struct ieee80211_sub_if_data *sdata)
+void ieee80211_beacon_loss(struct ieee80211_vif *vif)
{
- struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
+ struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
+ ieee80211_queue_work(&sdata->local->hw, &sdata->u.mgd.beacon_loss_work);
+}
+EXPORT_SYMBOL(ieee80211_beacon_loss);
+
+static void ieee80211_auth_completed(struct ieee80211_sub_if_data *sdata,
+ struct ieee80211_mgd_work *wk)
+{
+ wk->state = IEEE80211_MGD_STATE_IDLE;
printk(KERN_DEBUG "%s: authenticated\n", sdata->dev->name);
- ifmgd->flags |= IEEE80211_STA_AUTHENTICATED;
- if (ifmgd->flags & IEEE80211_STA_EXT_SME) {
- /* Wait for SME to request association */
- ifmgd->state = IEEE80211_STA_MLME_DISABLED;
- ieee80211_recalc_idle(sdata->local);
- } else
- ieee80211_associate(sdata);
}
static void ieee80211_auth_challenge(struct ieee80211_sub_if_data *sdata,
+ struct ieee80211_mgd_work *wk,
struct ieee80211_mgmt *mgmt,
size_t len)
{
@@ -1444,161 +1274,133 @@ static void ieee80211_auth_challenge(struct ieee80211_sub_if_data *sdata,
ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems);
if (!elems.challenge)
return;
- ieee80211_send_auth(sdata, 3, sdata->u.mgd.auth_alg,
+ ieee80211_send_auth(sdata, 3, wk->auth_alg,
elems.challenge - 2, elems.challenge_len + 2,
- sdata->u.mgd.bssid, 1);
- sdata->u.mgd.auth_transaction = 4;
+ wk->bss->cbss.bssid,
+ wk->key, wk->key_len, wk->key_idx);
+ wk->auth_transaction = 4;
}
-static void ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata,
- struct ieee80211_mgmt *mgmt,
- size_t len)
+static enum rx_mgmt_action __must_check
+ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata,
+ struct ieee80211_mgd_work *wk,
+ struct ieee80211_mgmt *mgmt, size_t len)
{
- struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
u16 auth_alg, auth_transaction, status_code;
- if (ifmgd->state != IEEE80211_STA_MLME_AUTHENTICATE)
- return;
+ if (wk->state != IEEE80211_MGD_STATE_AUTH)
+ return RX_MGMT_NONE;
if (len < 24 + 6)
- return;
+ return RX_MGMT_NONE;
- if (memcmp(ifmgd->bssid, mgmt->sa, ETH_ALEN) != 0)
- return;
+ if (memcmp(wk->bss->cbss.bssid, mgmt->sa, ETH_ALEN) != 0)
+ return RX_MGMT_NONE;
- if (memcmp(ifmgd->bssid, mgmt->bssid, ETH_ALEN) != 0)
- return;
+ if (memcmp(wk->bss->cbss.bssid, mgmt->bssid, ETH_ALEN) != 0)
+ return RX_MGMT_NONE;
auth_alg = le16_to_cpu(mgmt->u.auth.auth_alg);
auth_transaction = le16_to_cpu(mgmt->u.auth.auth_transaction);
status_code = le16_to_cpu(mgmt->u.auth.status_code);
- if (auth_alg != ifmgd->auth_alg ||
- auth_transaction != ifmgd->auth_transaction)
- return;
+ if (auth_alg != wk->auth_alg ||
+ auth_transaction != wk->auth_transaction)
+ return RX_MGMT_NONE;
if (status_code != WLAN_STATUS_SUCCESS) {
- if (status_code == WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG) {
- u8 algs[3];
- const int num_algs = ARRAY_SIZE(algs);
- int i, pos;
- algs[0] = algs[1] = algs[2] = 0xff;
- if (ifmgd->auth_algs & IEEE80211_AUTH_ALG_OPEN)
- algs[0] = WLAN_AUTH_OPEN;
- if (ifmgd->auth_algs & IEEE80211_AUTH_ALG_SHARED_KEY)
- algs[1] = WLAN_AUTH_SHARED_KEY;
- if (ifmgd->auth_algs & IEEE80211_AUTH_ALG_LEAP)
- algs[2] = WLAN_AUTH_LEAP;
- if (ifmgd->auth_alg == WLAN_AUTH_OPEN)
- pos = 0;
- else if (ifmgd->auth_alg == WLAN_AUTH_SHARED_KEY)
- pos = 1;
- else
- pos = 2;
- for (i = 0; i < num_algs; i++) {
- pos++;
- if (pos >= num_algs)
- pos = 0;
- if (algs[pos] == ifmgd->auth_alg ||
- algs[pos] == 0xff)
- continue;
- if (algs[pos] == WLAN_AUTH_SHARED_KEY &&
- !ieee80211_sta_wep_configured(sdata))
- continue;
- ifmgd->auth_alg = algs[pos];
- break;
- }
- }
- return;
+ list_del(&wk->list);
+ kfree(wk);
+ return RX_MGMT_CFG80211_AUTH;
}
- switch (ifmgd->auth_alg) {
+ switch (wk->auth_alg) {
case WLAN_AUTH_OPEN:
case WLAN_AUTH_LEAP:
case WLAN_AUTH_FT:
- ieee80211_auth_completed(sdata);
- cfg80211_send_rx_auth(sdata->dev, (u8 *) mgmt, len);
- break;
+ ieee80211_auth_completed(sdata, wk);
+ return RX_MGMT_CFG80211_AUTH;
case WLAN_AUTH_SHARED_KEY:
- if (ifmgd->auth_transaction == 4) {
- ieee80211_auth_completed(sdata);
- cfg80211_send_rx_auth(sdata->dev, (u8 *) mgmt, len);
+ if (wk->auth_transaction == 4) {
+ ieee80211_auth_completed(sdata, wk);
+ return RX_MGMT_CFG80211_AUTH;
} else
- ieee80211_auth_challenge(sdata, mgmt, len);
+ ieee80211_auth_challenge(sdata, wk, mgmt, len);
break;
}
+
+ return RX_MGMT_NONE;
}
-static void ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata,
- struct ieee80211_mgmt *mgmt,
- size_t len)
+static enum rx_mgmt_action __must_check
+ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata,
+ struct ieee80211_mgd_work *wk,
+ struct ieee80211_mgmt *mgmt, size_t len)
{
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
+ const u8 *bssid = NULL;
u16 reason_code;
if (len < 24 + 2)
- return;
+ return RX_MGMT_NONE;
- if (memcmp(ifmgd->bssid, mgmt->sa, ETH_ALEN))
- return;
+ ASSERT_MGD_MTX(ifmgd);
+
+ if (wk)
+ bssid = wk->bss->cbss.bssid;
+ else
+ bssid = ifmgd->associated->cbss.bssid;
reason_code = le16_to_cpu(mgmt->u.deauth.reason_code);
- if (ifmgd->flags & IEEE80211_STA_AUTHENTICATED)
- printk(KERN_DEBUG "%s: deauthenticated (Reason: %u)\n",
- sdata->dev->name, reason_code);
+ printk(KERN_DEBUG "%s: deauthenticated from %pM (Reason: %u)\n",
+ sdata->dev->name, bssid, reason_code);
- if (!(ifmgd->flags & IEEE80211_STA_EXT_SME) &&
- (ifmgd->state == IEEE80211_STA_MLME_AUTHENTICATE ||
- ifmgd->state == IEEE80211_STA_MLME_ASSOCIATE ||
- ifmgd->state == IEEE80211_STA_MLME_ASSOCIATED)) {
- ifmgd->state = IEEE80211_STA_MLME_DIRECT_PROBE;
- mod_timer(&ifmgd->timer, jiffies +
- IEEE80211_RETRY_AUTH_INTERVAL);
+ if (!wk) {
+ ieee80211_set_disassoc(sdata, true);
+ } else {
+ list_del(&wk->list);
+ kfree(wk);
}
- ieee80211_set_disassoc(sdata, true, false, 0);
- ifmgd->flags &= ~IEEE80211_STA_AUTHENTICATED;
- cfg80211_send_deauth(sdata->dev, (u8 *) mgmt, len);
+ return RX_MGMT_CFG80211_DEAUTH;
}
-static void ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata,
- struct ieee80211_mgmt *mgmt,
- size_t len)
+static enum rx_mgmt_action __must_check
+ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata,
+ struct ieee80211_mgmt *mgmt, size_t len)
{
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
u16 reason_code;
if (len < 24 + 2)
- return;
+ return RX_MGMT_NONE;
- if (memcmp(ifmgd->bssid, mgmt->sa, ETH_ALEN))
- return;
+ ASSERT_MGD_MTX(ifmgd);
- reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code);
+ if (WARN_ON(!ifmgd->associated))
+ return RX_MGMT_NONE;
- if (ifmgd->flags & IEEE80211_STA_ASSOCIATED)
- printk(KERN_DEBUG "%s: disassociated (Reason: %u)\n",
- sdata->dev->name, reason_code);
+ if (WARN_ON(memcmp(ifmgd->associated->cbss.bssid, mgmt->sa, ETH_ALEN)))
+ return RX_MGMT_NONE;
- if (!(ifmgd->flags & IEEE80211_STA_EXT_SME) &&
- ifmgd->state == IEEE80211_STA_MLME_ASSOCIATED) {
- ifmgd->state = IEEE80211_STA_MLME_ASSOCIATE;
- mod_timer(&ifmgd->timer, jiffies +
- IEEE80211_RETRY_AUTH_INTERVAL);
- }
+ reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code);
- ieee80211_set_disassoc(sdata, false, false, reason_code);
- cfg80211_send_disassoc(sdata->dev, (u8 *) mgmt, len);
+ printk(KERN_DEBUG "%s: disassociated (Reason: %u)\n",
+ sdata->dev->name, reason_code);
+
+ ieee80211_set_disassoc(sdata, false);
+ return RX_MGMT_CFG80211_DISASSOC;
}
-static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
- struct ieee80211_mgmt *mgmt,
- size_t len,
- int reassoc)
+static enum rx_mgmt_action __must_check
+ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
+ struct ieee80211_mgd_work *wk,
+ struct ieee80211_mgmt *mgmt, size_t len,
+ bool reassoc)
{
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
struct ieee80211_local *local = sdata->local;
@@ -1614,17 +1416,16 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
bool have_higher_than_11mbit = false, newsta = false;
u16 ap_ht_cap_flags;
- /* AssocResp and ReassocResp have identical structure, so process both
- * of them in this function. */
-
- if (ifmgd->state != IEEE80211_STA_MLME_ASSOCIATE)
- return;
+ /*
+ * AssocResp and ReassocResp have identical structure, so process both
+ * of them in this function.
+ */
if (len < 24 + 6)
- return;
+ return RX_MGMT_NONE;
- if (memcmp(ifmgd->bssid, mgmt->sa, ETH_ALEN) != 0)
- return;
+ if (memcmp(wk->bss->cbss.bssid, mgmt->sa, ETH_ALEN) != 0)
+ return RX_MGMT_NONE;
capab_info = le16_to_cpu(mgmt->u.assoc_resp.capab_info);
status_code = le16_to_cpu(mgmt->u.assoc_resp.status_code);
@@ -1647,26 +1448,18 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
printk(KERN_DEBUG "%s: AP rejected association temporarily; "
"comeback duration %u TU (%u ms)\n",
sdata->dev->name, tu, ms);
+ wk->timeout = jiffies + msecs_to_jiffies(ms);
if (ms > IEEE80211_ASSOC_TIMEOUT)
- mod_timer(&ifmgd->timer,
- jiffies + msecs_to_jiffies(ms));
- return;
+ run_again(ifmgd, jiffies + msecs_to_jiffies(ms));
+ return RX_MGMT_NONE;
}
if (status_code != WLAN_STATUS_SUCCESS) {
printk(KERN_DEBUG "%s: AP denied association (code=%d)\n",
sdata->dev->name, status_code);
- /* if this was a reassociation, ensure we try a "full"
- * association next time. This works around some broken APs
- * which do not correctly reject reassociation requests. */
- ifmgd->flags &= ~IEEE80211_STA_PREV_BSSID_SET;
- cfg80211_send_rx_assoc(sdata->dev, (u8 *) mgmt, len);
- if (ifmgd->flags & IEEE80211_STA_EXT_SME) {
- /* Wait for SME to decide what to do next */
- ifmgd->state = IEEE80211_STA_MLME_DISABLED;
- ieee80211_recalc_idle(local);
- }
- return;
+ list_del(&wk->list);
+ kfree(wk);
+ return RX_MGMT_CFG80211_ASSOC;
}
if ((aid & (BIT(15) | BIT(14))) != (BIT(15) | BIT(14)))
@@ -1677,51 +1470,35 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
if (!elems.supp_rates) {
printk(KERN_DEBUG "%s: no SuppRates element in AssocResp\n",
sdata->dev->name);
- return;
+ return RX_MGMT_NONE;
}
printk(KERN_DEBUG "%s: associated\n", sdata->dev->name);
ifmgd->aid = aid;
- ifmgd->ap_capab = capab_info;
-
- kfree(ifmgd->assocresp_ies);
- ifmgd->assocresp_ies_len = len - (pos - (u8 *) mgmt);
- ifmgd->assocresp_ies = kmalloc(ifmgd->assocresp_ies_len, GFP_KERNEL);
- if (ifmgd->assocresp_ies)
- memcpy(ifmgd->assocresp_ies, pos, ifmgd->assocresp_ies_len);
rcu_read_lock();
/* Add STA entry for the AP */
- sta = sta_info_get(local, ifmgd->bssid);
+ sta = sta_info_get(local, wk->bss->cbss.bssid);
if (!sta) {
newsta = true;
- sta = sta_info_alloc(sdata, ifmgd->bssid, GFP_ATOMIC);
+ rcu_read_unlock();
+
+ sta = sta_info_alloc(sdata, wk->bss->cbss.bssid, GFP_KERNEL);
if (!sta) {
printk(KERN_DEBUG "%s: failed to alloc STA entry for"
" the AP\n", sdata->dev->name);
- rcu_read_unlock();
- return;
+ return RX_MGMT_NONE;
}
- /* update new sta with its last rx activity */
- sta->last_rx = jiffies;
- }
+ set_sta_flags(sta, WLAN_STA_AUTH | WLAN_STA_ASSOC |
+ WLAN_STA_ASSOC_AP);
+ if (!(ifmgd->flags & IEEE80211_STA_CONTROL_PORT))
+ set_sta_flags(sta, WLAN_STA_AUTHORIZED);
- /*
- * FIXME: Do we really need to update the sta_info's information here?
- * We already know about the AP (we found it in our list) so it
- * should already be filled with the right info, no?
- * As is stands, all this is racy because typically we assume
- * the information that is filled in here (except flags) doesn't
- * change while a STA structure is alive. As such, it should move
- * to between the sta_info_alloc() and sta_info_insert() above.
- */
-
- set_sta_flags(sta, WLAN_STA_AUTH | WLAN_STA_ASSOC | WLAN_STA_ASSOC_AP);
- if (!(ifmgd->flags & IEEE80211_STA_CONTROL_PORT))
- set_sta_flags(sta, WLAN_STA_AUTHORIZED);
+ rcu_read_lock();
+ }
rates = 0;
basic_rates = 0;
@@ -1771,8 +1548,7 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
else
sdata->flags &= ~IEEE80211_SDATA_OPERATING_GMODE;
- /* If TKIP/WEP is used, no need to parse AP's HT capabilities */
- if (elems.ht_cap_elem && !(ifmgd->flags & IEEE80211_STA_TKIP_WEP_USED))
+ if (elems.ht_cap_elem && !(ifmgd->flags & IEEE80211_STA_DISABLE_11N))
ieee80211_ht_cap_ie_to_sta_ht_cap(sband,
elems.ht_cap_elem, &sta->sta.ht_cap);
@@ -1792,7 +1568,7 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
printk(KERN_DEBUG "%s: failed to insert STA entry for"
" the AP (error %d)\n", sdata->dev->name, err);
rcu_read_unlock();
- return;
+ return RX_MGMT_NONE;
}
}
@@ -1806,24 +1582,29 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
if (elems.ht_info_elem && elems.wmm_param &&
(ifmgd->flags & IEEE80211_STA_WMM_ENABLED) &&
- !(ifmgd->flags & IEEE80211_STA_TKIP_WEP_USED))
+ !(ifmgd->flags & IEEE80211_STA_DISABLE_11N))
changed |= ieee80211_enable_ht(sdata, elems.ht_info_elem,
+ wk->bss->cbss.bssid,
ap_ht_cap_flags);
+ /* delete work item -- must be before set_associated for PS */
+ list_del(&wk->list);
+
/* set AID and assoc capability,
* ieee80211_set_associated() will tell the driver */
bss_conf->aid = aid;
bss_conf->assoc_capability = capab_info;
- ieee80211_set_associated(sdata, changed);
+ /* this will take ownership of wk */
+ ieee80211_set_associated(sdata, wk, changed);
/*
- * initialise the time of last beacon to be the association time,
- * otherwise beacon loss check will trigger immediately
+ * Start timer to probe the connection to the AP now.
+ * Also start the timer that will detect beacon loss.
*/
- ifmgd->last_beacon = jiffies;
+ ieee80211_sta_rx_notify(sdata, (struct ieee80211_hdr *)mgmt);
+ mod_beacon_timer(sdata);
- ieee80211_associated(sdata);
- cfg80211_send_rx_assoc(sdata->dev, (u8 *) mgmt, len);
+ return RX_MGMT_CFG80211_ASSOC;
}
@@ -1851,23 +1632,25 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
bss = ieee80211_bss_info_update(local, rx_status, mgmt, len, elems,
channel, beacon);
- if (!bss)
+ if (bss)
+ ieee80211_rx_bss_put(local, bss);
+
+ if (!sdata->u.mgd.associated)
return;
if (elems->ch_switch_elem && (elems->ch_switch_elem_len == 3) &&
- (memcmp(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN) == 0)) {
+ (memcmp(mgmt->bssid, sdata->u.mgd.associated->cbss.bssid,
+ ETH_ALEN) == 0)) {
struct ieee80211_channel_sw_ie *sw_elem =
(struct ieee80211_channel_sw_ie *)elems->ch_switch_elem;
ieee80211_sta_process_chanswitch(sdata, sw_elem, bss);
}
-
- ieee80211_rx_bss_put(local, bss);
}
static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata,
- struct ieee80211_mgmt *mgmt,
- size_t len,
+ struct ieee80211_mgd_work *wk,
+ struct ieee80211_mgmt *mgmt, size_t len,
struct ieee80211_rx_status *rx_status)
{
struct ieee80211_if_managed *ifmgd;
@@ -1876,6 +1659,8 @@ static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata,
ifmgd = &sdata->u.mgd;
+ ASSERT_MGD_MTX(ifmgd);
+
if (memcmp(mgmt->da, sdata->dev->dev_addr, ETH_ALEN))
return; /* ignore ProbeResp to foreign address */
@@ -1889,17 +1674,32 @@ static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata,
ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems, false);
/* direct probe may be part of the association flow */
- if (ifmgd->state == IEEE80211_STA_MLME_DIRECT_PROBE) {
+ if (wk && wk->state == IEEE80211_MGD_STATE_PROBE) {
printk(KERN_DEBUG "%s direct probe responded\n",
sdata->dev->name);
- ieee80211_authenticate(sdata);
+ wk->tries = 0;
+ wk->state = IEEE80211_MGD_STATE_AUTH;
+ WARN_ON(ieee80211_authenticate(sdata, wk) != RX_MGMT_NONE);
}
- if (ifmgd->flags & IEEE80211_STA_PROBEREQ_POLL) {
- ifmgd->flags &= ~IEEE80211_STA_PROBEREQ_POLL;
+ if (ifmgd->associated &&
+ memcmp(mgmt->bssid, ifmgd->associated->cbss.bssid, ETH_ALEN) == 0 &&
+ ifmgd->flags & (IEEE80211_STA_BEACON_POLL |
+ IEEE80211_STA_CONNECTION_POLL)) {
+ ifmgd->flags &= ~(IEEE80211_STA_CONNECTION_POLL |
+ IEEE80211_STA_BEACON_POLL);
mutex_lock(&sdata->local->iflist_mtx);
ieee80211_recalc_ps(sdata->local, -1);
mutex_unlock(&sdata->local->iflist_mtx);
+ /*
+ * We've received a probe response, but are not sure whether
+ * we have or will be receiving any beacons or data, so let's
+ * schedule the timers again, just in case.
+ */
+ mod_beacon_timer(sdata);
+ mod_timer(&ifmgd->conn_mon_timer,
+ round_jiffies_up(jiffies +
+ IEEE80211_CONNECTION_IDLE_TIME));
}
}
@@ -1937,6 +1737,9 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
bool erp_valid, directed_tim = false;
u8 erp_value = 0;
u32 ncrc;
+ u8 *bssid;
+
+ ASSERT_MGD_MTX(ifmgd);
/* Process beacon from the current BSS */
baselen = (u8 *) mgmt->u.beacon.variable - (u8 *) mgmt;
@@ -1946,23 +1749,41 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
if (rx_status->freq != local->hw.conf.channel->center_freq)
return;
- if (!(ifmgd->flags & IEEE80211_STA_ASSOCIATED) ||
- memcmp(ifmgd->bssid, mgmt->bssid, ETH_ALEN) != 0)
+ /*
+ * We might have received a number of frames, among them a
+ * disassoc frame and a beacon...
+ */
+ if (!ifmgd->associated)
return;
- if (ifmgd->flags & IEEE80211_STA_PROBEREQ_POLL) {
+ bssid = ifmgd->associated->cbss.bssid;
+
+ /*
+ * And in theory even frames from a different AP we were just
+ * associated to a split-second ago!
+ */
+ if (memcmp(bssid, mgmt->bssid, ETH_ALEN) != 0)
+ return;
+
+ if (ifmgd->flags & IEEE80211_STA_BEACON_POLL) {
#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
if (net_ratelimit()) {
printk(KERN_DEBUG "%s: cancelling probereq poll due "
"to a received beacon\n", sdata->dev->name);
}
#endif
- ifmgd->flags &= ~IEEE80211_STA_PROBEREQ_POLL;
+ ifmgd->flags &= ~IEEE80211_STA_BEACON_POLL;
mutex_lock(&local->iflist_mtx);
ieee80211_recalc_ps(local, -1);
mutex_unlock(&local->iflist_mtx);
}
+ /*
+ * Push the beacon loss detection into the future since
+ * we are processing a beacon from the AP just now.
+ */
+ mod_beacon_timer(sdata);
+
ncrc = crc32_be(0, (void *)&mgmt->u.beacon.beacon_int, 4);
ncrc = ieee802_11_parse_elems_crc(mgmt->u.beacon.variable,
len - baselen, &elems,
@@ -2019,15 +1840,15 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
if (elems.ht_cap_elem && elems.ht_info_elem && elems.wmm_param &&
- !(ifmgd->flags & IEEE80211_STA_TKIP_WEP_USED)) {
+ !(ifmgd->flags & IEEE80211_STA_DISABLE_11N)) {
struct sta_info *sta;
struct ieee80211_supported_band *sband;
u16 ap_ht_cap_flags;
rcu_read_lock();
- sta = sta_info_get(local, ifmgd->bssid);
- if (!sta) {
+ sta = sta_info_get(local, bssid);
+ if (WARN_ON(!sta)) {
rcu_read_unlock();
return;
}
@@ -2042,15 +1863,11 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
rcu_read_unlock();
changed |= ieee80211_enable_ht(sdata, elems.ht_info_elem,
- ap_ht_cap_flags);
+ bssid, ap_ht_cap_flags);
}
+ /* Note: country IE parsing is done for us by cfg80211 */
if (elems.country_elem) {
- /* Note we are only reviewing this on beacons
- * for the BSSID we are associated to */
- regulatory_hint_11d(local->hw.wiphy,
- elems.country_elem, elems.country_elem_len);
-
/* TODO: IBSS also needs this */
if (elems.pwr_constr_elem)
ieee80211_handle_pwr_constr(sdata,
@@ -2063,8 +1880,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
}
ieee80211_rx_result ieee80211_sta_rx_mgmt(struct ieee80211_sub_if_data *sdata,
- struct sk_buff *skb,
- struct ieee80211_rx_status *rx_status)
+ struct sk_buff *skb)
{
struct ieee80211_local *local = sdata->local;
struct ieee80211_mgmt *mgmt;
@@ -2080,14 +1896,14 @@ ieee80211_rx_result ieee80211_sta_rx_mgmt(struct ieee80211_sub_if_data *sdata,
case IEEE80211_STYPE_PROBE_REQ:
case IEEE80211_STYPE_PROBE_RESP:
case IEEE80211_STYPE_BEACON:
- memcpy(skb->cb, rx_status, sizeof(*rx_status));
case IEEE80211_STYPE_AUTH:
case IEEE80211_STYPE_ASSOC_RESP:
case IEEE80211_STYPE_REASSOC_RESP:
case IEEE80211_STYPE_DEAUTH:
case IEEE80211_STYPE_DISASSOC:
+ case IEEE80211_STYPE_ACTION:
skb_queue_tail(&sdata->u.mgd.skb_queue, skb);
- queue_work(local->hw.workqueue, &sdata->u.mgd.work);
+ ieee80211_queue_work(&local->hw, &sdata->u.mgd.work);
return RX_QUEUED;
}
@@ -2097,40 +1913,119 @@ ieee80211_rx_result ieee80211_sta_rx_mgmt(struct ieee80211_sub_if_data *sdata,
static void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
struct sk_buff *skb)
{
+ struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
struct ieee80211_rx_status *rx_status;
struct ieee80211_mgmt *mgmt;
+ struct ieee80211_mgd_work *wk;
+ enum rx_mgmt_action rma = RX_MGMT_NONE;
u16 fc;
rx_status = (struct ieee80211_rx_status *) skb->cb;
mgmt = (struct ieee80211_mgmt *) skb->data;
fc = le16_to_cpu(mgmt->frame_control);
- switch (fc & IEEE80211_FCTL_STYPE) {
- case IEEE80211_STYPE_PROBE_RESP:
- ieee80211_rx_mgmt_probe_resp(sdata, mgmt, skb->len,
- rx_status);
- break;
- case IEEE80211_STYPE_BEACON:
- ieee80211_rx_mgmt_beacon(sdata, mgmt, skb->len,
- rx_status);
- break;
- case IEEE80211_STYPE_AUTH:
- ieee80211_rx_mgmt_auth(sdata, mgmt, skb->len);
+ mutex_lock(&ifmgd->mtx);
+
+ if (ifmgd->associated &&
+ memcmp(ifmgd->associated->cbss.bssid, mgmt->bssid,
+ ETH_ALEN) == 0) {
+ switch (fc & IEEE80211_FCTL_STYPE) {
+ case IEEE80211_STYPE_BEACON:
+ ieee80211_rx_mgmt_beacon(sdata, mgmt, skb->len,
+ rx_status);
+ break;
+ case IEEE80211_STYPE_PROBE_RESP:
+ ieee80211_rx_mgmt_probe_resp(sdata, NULL, mgmt,
+ skb->len, rx_status);
+ break;
+ case IEEE80211_STYPE_DEAUTH:
+ rma = ieee80211_rx_mgmt_deauth(sdata, NULL,
+ mgmt, skb->len);
+ break;
+ case IEEE80211_STYPE_DISASSOC:
+ rma = ieee80211_rx_mgmt_disassoc(sdata, mgmt, skb->len);
+ break;
+ case IEEE80211_STYPE_ACTION:
+ /* XXX: differentiate, can only happen for CSA now! */
+ ieee80211_sta_process_chanswitch(sdata,
+ &mgmt->u.action.u.chan_switch.sw_elem,
+ ifmgd->associated);
+ break;
+ }
+ mutex_unlock(&ifmgd->mtx);
+
+ switch (rma) {
+ case RX_MGMT_NONE:
+ /* no action */
+ break;
+ case RX_MGMT_CFG80211_DEAUTH:
+ cfg80211_send_deauth(sdata->dev, (u8 *)mgmt, skb->len,
+ NULL);
+ break;
+ case RX_MGMT_CFG80211_DISASSOC:
+ cfg80211_send_disassoc(sdata->dev, (u8 *)mgmt, skb->len,
+ NULL);
+ break;
+ default:
+ WARN(1, "unexpected: %d", rma);
+ }
+ goto out;
+ }
+
+ list_for_each_entry(wk, &ifmgd->work_list, list) {
+ if (memcmp(wk->bss->cbss.bssid, mgmt->bssid, ETH_ALEN) != 0)
+ continue;
+
+ switch (fc & IEEE80211_FCTL_STYPE) {
+ case IEEE80211_STYPE_PROBE_RESP:
+ ieee80211_rx_mgmt_probe_resp(sdata, wk, mgmt, skb->len,
+ rx_status);
+ break;
+ case IEEE80211_STYPE_AUTH:
+ rma = ieee80211_rx_mgmt_auth(sdata, wk, mgmt, skb->len);
+ break;
+ case IEEE80211_STYPE_ASSOC_RESP:
+ rma = ieee80211_rx_mgmt_assoc_resp(sdata, wk, mgmt,
+ skb->len, false);
+ break;
+ case IEEE80211_STYPE_REASSOC_RESP:
+ rma = ieee80211_rx_mgmt_assoc_resp(sdata, wk, mgmt,
+ skb->len, true);
+ break;
+ case IEEE80211_STYPE_DEAUTH:
+ rma = ieee80211_rx_mgmt_deauth(sdata, wk, mgmt,
+ skb->len);
+ break;
+ }
+ /*
+ * We've processed this frame for that work, so it can't
+ * belong to another work struct.
+ * NB: this is also required for correctness because the
+ * called functions can free 'wk', and for 'rma'!
+ */
break;
- case IEEE80211_STYPE_ASSOC_RESP:
- ieee80211_rx_mgmt_assoc_resp(sdata, mgmt, skb->len, 0);
+ }
+
+ mutex_unlock(&ifmgd->mtx);
+
+ switch (rma) {
+ case RX_MGMT_NONE:
+ /* no action */
break;
- case IEEE80211_STYPE_REASSOC_RESP:
- ieee80211_rx_mgmt_assoc_resp(sdata, mgmt, skb->len, 1);
+ case RX_MGMT_CFG80211_AUTH:
+ cfg80211_send_rx_auth(sdata->dev, (u8 *) mgmt, skb->len);
break;
- case IEEE80211_STYPE_DEAUTH:
- ieee80211_rx_mgmt_deauth(sdata, mgmt, skb->len);
+ case RX_MGMT_CFG80211_ASSOC:
+ cfg80211_send_rx_assoc(sdata->dev, (u8 *) mgmt, skb->len);
break;
- case IEEE80211_STYPE_DISASSOC:
- ieee80211_rx_mgmt_disassoc(sdata, mgmt, skb->len);
+ case RX_MGMT_CFG80211_DEAUTH:
+ cfg80211_send_deauth(sdata->dev, (u8 *)mgmt, skb->len, NULL);
break;
+ default:
+ WARN(1, "unexpected: %d", rma);
}
+ out:
kfree_skb(skb);
}
@@ -2146,215 +2041,220 @@ static void ieee80211_sta_timer(unsigned long data)
return;
}
- set_bit(IEEE80211_STA_REQ_RUN, &ifmgd->request);
- queue_work(local->hw.workqueue, &ifmgd->work);
+ ieee80211_queue_work(&local->hw, &ifmgd->work);
}
-static void ieee80211_sta_reset_auth(struct ieee80211_sub_if_data *sdata)
+static void ieee80211_sta_work(struct work_struct *work)
{
- struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
+ struct ieee80211_sub_if_data *sdata =
+ container_of(work, struct ieee80211_sub_if_data, u.mgd.work);
struct ieee80211_local *local = sdata->local;
+ struct ieee80211_if_managed *ifmgd;
+ struct sk_buff *skb;
+ struct ieee80211_mgd_work *wk, *tmp;
+ LIST_HEAD(free_work);
+ enum rx_mgmt_action rma;
+ bool anybusy = false;
- /* Reset own TSF to allow time synchronization work. */
- drv_reset_tsf(local);
+ if (!netif_running(sdata->dev))
+ return;
- ifmgd->wmm_last_param_set = -1; /* allow any WMM update */
+ if (local->scanning)
+ return;
+ if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION))
+ return;
- if (ifmgd->auth_algs & IEEE80211_AUTH_ALG_OPEN)
- ifmgd->auth_alg = WLAN_AUTH_OPEN;
- else if (ifmgd->auth_algs & IEEE80211_AUTH_ALG_SHARED_KEY)
- ifmgd->auth_alg = WLAN_AUTH_SHARED_KEY;
- else if (ifmgd->auth_algs & IEEE80211_AUTH_ALG_LEAP)
- ifmgd->auth_alg = WLAN_AUTH_LEAP;
- else if (ifmgd->auth_algs & IEEE80211_AUTH_ALG_FT)
- ifmgd->auth_alg = WLAN_AUTH_FT;
- else
- ifmgd->auth_alg = WLAN_AUTH_OPEN;
- ifmgd->auth_transaction = -1;
- ifmgd->flags &= ~IEEE80211_STA_ASSOCIATED;
- ifmgd->assoc_scan_tries = 0;
- ifmgd->direct_probe_tries = 0;
- ifmgd->auth_tries = 0;
- ifmgd->assoc_tries = 0;
- netif_tx_stop_all_queues(sdata->dev);
- netif_carrier_off(sdata->dev);
-}
+ /*
+ * ieee80211_queue_work() should have picked up most cases,
+ * here we'll pick the the rest.
+ */
+ if (WARN(local->suspended, "STA MLME work scheduled while "
+ "going to suspend\n"))
+ return;
-static int ieee80211_sta_config_auth(struct ieee80211_sub_if_data *sdata)
-{
- struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
- struct ieee80211_local *local = sdata->local;
- struct ieee80211_bss *bss;
- u8 *bssid = ifmgd->bssid, *ssid = ifmgd->ssid;
- u8 ssid_len = ifmgd->ssid_len;
- u16 capa_mask = WLAN_CAPABILITY_ESS;
- u16 capa_val = WLAN_CAPABILITY_ESS;
- struct ieee80211_channel *chan = local->oper_channel;
+ ifmgd = &sdata->u.mgd;
- if (!(ifmgd->flags & IEEE80211_STA_EXT_SME) &&
- ifmgd->flags & (IEEE80211_STA_AUTO_SSID_SEL |
- IEEE80211_STA_AUTO_BSSID_SEL |
- IEEE80211_STA_AUTO_CHANNEL_SEL)) {
- capa_mask |= WLAN_CAPABILITY_PRIVACY;
- if (sdata->default_key)
- capa_val |= WLAN_CAPABILITY_PRIVACY;
- }
+ /* first process frames to avoid timing out while a frame is pending */
+ while ((skb = skb_dequeue(&ifmgd->skb_queue)))
+ ieee80211_sta_rx_queued_mgmt(sdata, skb);
- if (ifmgd->flags & IEEE80211_STA_AUTO_CHANNEL_SEL)
- chan = NULL;
+ /* then process the rest of the work */
+ mutex_lock(&ifmgd->mtx);
- if (ifmgd->flags & IEEE80211_STA_AUTO_BSSID_SEL)
- bssid = NULL;
+ if (ifmgd->flags & (IEEE80211_STA_BEACON_POLL |
+ IEEE80211_STA_CONNECTION_POLL) &&
+ ifmgd->associated) {
+ u8 bssid[ETH_ALEN];
- if (ifmgd->flags & IEEE80211_STA_AUTO_SSID_SEL) {
- ssid = NULL;
- ssid_len = 0;
+ memcpy(bssid, ifmgd->associated->cbss.bssid, ETH_ALEN);
+ if (time_is_after_jiffies(ifmgd->probe_timeout))
+ run_again(ifmgd, ifmgd->probe_timeout);
+
+ else if (ifmgd->probe_send_count < IEEE80211_MAX_PROBE_TRIES) {
+#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
+ printk(KERN_DEBUG "No probe response from AP %pM"
+ " after %dms, try %d\n", bssid,
+ (1000 * IEEE80211_PROBE_WAIT)/HZ,
+ ifmgd->probe_send_count);
+#endif
+ ieee80211_mgd_probe_ap_send(sdata);
+ } else {
+ /*
+ * We actually lost the connection ... or did we?
+ * Let's make sure!
+ */
+ ifmgd->flags &= ~(IEEE80211_STA_CONNECTION_POLL |
+ IEEE80211_STA_BEACON_POLL);
+ printk(KERN_DEBUG "No probe response from AP %pM"
+ " after %dms, disconnecting.\n",
+ bssid, (1000 * IEEE80211_PROBE_WAIT)/HZ);
+ ieee80211_set_disassoc(sdata, true);
+ mutex_unlock(&ifmgd->mtx);
+ /*
+ * must be outside lock due to cfg80211,
+ * but that's not a problem.
+ */
+ ieee80211_send_deauth_disassoc(sdata, bssid,
+ IEEE80211_STYPE_DEAUTH,
+ WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY,
+ NULL);
+ mutex_lock(&ifmgd->mtx);
+ }
}
- bss = (void *)cfg80211_get_bss(local->hw.wiphy, chan,
- bssid, ssid, ssid_len,
- capa_mask, capa_val);
+ list_for_each_entry(wk, &ifmgd->work_list, list) {
+ if (wk->state != IEEE80211_MGD_STATE_IDLE) {
+ anybusy = true;
+ break;
+ }
+ }
- if (bss) {
- local->oper_channel = bss->cbss.channel;
- local->oper_channel_type = NL80211_CHAN_NO_HT;
- ieee80211_hw_config(local, 0);
+ ieee80211_recalc_idle(local);
- if (!(ifmgd->flags & IEEE80211_STA_SSID_SET))
- ieee80211_sta_set_ssid(sdata, bss->ssid,
- bss->ssid_len);
- ieee80211_sta_set_bssid(sdata, bss->cbss.bssid);
- ieee80211_sta_def_wmm_params(sdata, bss->supp_rates_len,
- bss->supp_rates);
- if (sdata->u.mgd.mfp == IEEE80211_MFP_REQUIRED)
- sdata->u.mgd.flags |= IEEE80211_STA_MFP_ENABLED;
- else
- sdata->u.mgd.flags &= ~IEEE80211_STA_MFP_ENABLED;
-
- /* Send out direct probe if no probe resp was received or
- * the one we have is outdated
- */
- if (!bss->last_probe_resp ||
- time_after(jiffies, bss->last_probe_resp
- + IEEE80211_SCAN_RESULT_EXPIRE))
- ifmgd->state = IEEE80211_STA_MLME_DIRECT_PROBE;
- else
- ifmgd->state = IEEE80211_STA_MLME_AUTHENTICATE;
+ if (!anybusy) {
+ mutex_unlock(&ifmgd->mtx);
- ieee80211_rx_bss_put(local, bss);
- ieee80211_sta_reset_auth(sdata);
- return 0;
- } else {
- if (ifmgd->assoc_scan_tries < IEEE80211_ASSOC_SCANS_MAX_TRIES) {
+ if (test_and_clear_bit(IEEE80211_STA_REQ_SCAN, &ifmgd->request))
+ ieee80211_queue_delayed_work(&local->hw,
+ &local->scan_work,
+ round_jiffies_relative(0));
+ return;
+ }
- ifmgd->assoc_scan_tries++;
+ list_for_each_entry_safe(wk, tmp, &ifmgd->work_list, list) {
+ if (time_is_after_jiffies(wk->timeout)) {
+ /*
+ * This work item isn't supposed to be worked on
+ * right now, but take care to adjust the timer
+ * properly.
+ */
+ run_again(ifmgd, wk->timeout);
+ continue;
+ }
- ieee80211_request_internal_scan(sdata, ifmgd->ssid,
- ssid_len);
+ switch (wk->state) {
+ default:
+ WARN_ON(1);
+ /* fall through */
+ case IEEE80211_MGD_STATE_IDLE:
+ /* nothing */
+ rma = RX_MGMT_NONE;
+ break;
+ case IEEE80211_MGD_STATE_PROBE:
+ rma = ieee80211_direct_probe(sdata, wk);
+ break;
+ case IEEE80211_MGD_STATE_AUTH:
+ rma = ieee80211_authenticate(sdata, wk);
+ break;
+ case IEEE80211_MGD_STATE_ASSOC:
+ rma = ieee80211_associate(sdata, wk);
+ break;
+ }
- ifmgd->state = IEEE80211_STA_MLME_AUTHENTICATE;
- set_bit(IEEE80211_STA_REQ_AUTH, &ifmgd->request);
- } else {
- ifmgd->assoc_scan_tries = 0;
- ifmgd->state = IEEE80211_STA_MLME_DISABLED;
- ieee80211_recalc_idle(local);
+ switch (rma) {
+ case RX_MGMT_NONE:
+ /* no action required */
+ break;
+ case RX_MGMT_CFG80211_AUTH_TO:
+ case RX_MGMT_CFG80211_ASSOC_TO:
+ list_del(&wk->list);
+ list_add(&wk->list, &free_work);
+ wk->tries = rma; /* small abuse but only local */
+ break;
+ default:
+ WARN(1, "unexpected: %d", rma);
}
}
- return -1;
-}
+ mutex_unlock(&ifmgd->mtx);
-static void ieee80211_sta_work(struct work_struct *work)
-{
- struct ieee80211_sub_if_data *sdata =
- container_of(work, struct ieee80211_sub_if_data, u.mgd.work);
- struct ieee80211_local *local = sdata->local;
- struct ieee80211_if_managed *ifmgd;
- struct sk_buff *skb;
+ list_for_each_entry_safe(wk, tmp, &free_work, list) {
+ switch (wk->tries) {
+ case RX_MGMT_CFG80211_AUTH_TO:
+ cfg80211_send_auth_timeout(sdata->dev,
+ wk->bss->cbss.bssid);
+ break;
+ case RX_MGMT_CFG80211_ASSOC_TO:
+ cfg80211_send_assoc_timeout(sdata->dev,
+ wk->bss->cbss.bssid);
+ break;
+ default:
+ WARN(1, "unexpected: %d", wk->tries);
+ }
- if (!netif_running(sdata->dev))
- return;
+ list_del(&wk->list);
+ kfree(wk);
+ }
- if (local->sw_scanning || local->hw_scanning)
- return;
+ ieee80211_recalc_idle(local);
+}
- if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION))
- return;
+static void ieee80211_sta_bcn_mon_timer(unsigned long data)
+{
+ struct ieee80211_sub_if_data *sdata =
+ (struct ieee80211_sub_if_data *) data;
+ struct ieee80211_local *local = sdata->local;
- /*
- * Nothing should have been stuffed into the workqueue during
- * the suspend->resume cycle. If this WARN is seen then there
- * is a bug with either the driver suspend or something in
- * mac80211 stuffing into the workqueue which we haven't yet
- * cleared during mac80211's suspend cycle.
- */
- if (WARN_ON(local->suspended))
+ if (local->quiescing)
return;
- ifmgd = &sdata->u.mgd;
-
- while ((skb = skb_dequeue(&ifmgd->skb_queue)))
- ieee80211_sta_rx_queued_mgmt(sdata, skb);
+ ieee80211_queue_work(&sdata->local->hw, &sdata->u.mgd.beacon_loss_work);
+}
- if (ifmgd->state != IEEE80211_STA_MLME_DIRECT_PROBE &&
- ifmgd->state != IEEE80211_STA_MLME_AUTHENTICATE &&
- ifmgd->state != IEEE80211_STA_MLME_ASSOCIATE &&
- test_and_clear_bit(IEEE80211_STA_REQ_SCAN, &ifmgd->request)) {
- queue_delayed_work(local->hw.workqueue, &local->scan_work,
- round_jiffies_relative(0));
- return;
- }
+static void ieee80211_sta_conn_mon_timer(unsigned long data)
+{
+ struct ieee80211_sub_if_data *sdata =
+ (struct ieee80211_sub_if_data *) data;
+ struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
+ struct ieee80211_local *local = sdata->local;
- if (test_and_clear_bit(IEEE80211_STA_REQ_AUTH, &ifmgd->request)) {
- if (ieee80211_sta_config_auth(sdata))
- return;
- clear_bit(IEEE80211_STA_REQ_RUN, &ifmgd->request);
- } else if (!test_and_clear_bit(IEEE80211_STA_REQ_RUN, &ifmgd->request))
+ if (local->quiescing)
return;
- ieee80211_recalc_idle(local);
-
- switch (ifmgd->state) {
- case IEEE80211_STA_MLME_DISABLED:
- break;
- case IEEE80211_STA_MLME_DIRECT_PROBE:
- ieee80211_direct_probe(sdata);
- break;
- case IEEE80211_STA_MLME_AUTHENTICATE:
- ieee80211_authenticate(sdata);
- break;
- case IEEE80211_STA_MLME_ASSOCIATE:
- ieee80211_associate(sdata);
- break;
- case IEEE80211_STA_MLME_ASSOCIATED:
- ieee80211_associated(sdata);
- break;
- default:
- WARN_ON(1);
- break;
- }
+ ieee80211_queue_work(&local->hw, &ifmgd->monitor_work);
+}
- if (ieee80211_privacy_mismatch(sdata)) {
- printk(KERN_DEBUG "%s: privacy configuration mismatch and "
- "mixed-cell disabled - disassociate\n", sdata->dev->name);
+static void ieee80211_sta_monitor_work(struct work_struct *work)
+{
+ struct ieee80211_sub_if_data *sdata =
+ container_of(work, struct ieee80211_sub_if_data,
+ u.mgd.monitor_work);
- ieee80211_set_disassoc(sdata, false, true,
- WLAN_REASON_UNSPECIFIED);
- }
+ ieee80211_mgd_probe_ap(sdata, false);
}
static void ieee80211_restart_sta_timer(struct ieee80211_sub_if_data *sdata)
{
if (sdata->vif.type == NL80211_IFTYPE_STATION) {
- /*
- * Need to update last_beacon to avoid beacon loss
- * test to trigger.
- */
- sdata->u.mgd.last_beacon = jiffies;
-
-
- queue_work(sdata->local->hw.workqueue,
+ sdata->u.mgd.flags &= ~(IEEE80211_STA_BEACON_POLL |
+ IEEE80211_STA_CONNECTION_POLL);
+
+ /* let's probe the connection once */
+ ieee80211_queue_work(&sdata->local->hw,
+ &sdata->u.mgd.monitor_work);
+ /* and do all the other regular work too */
+ ieee80211_queue_work(&sdata->local->hw,
&sdata->u.mgd.work);
}
}
@@ -2378,6 +2278,11 @@ void ieee80211_sta_quiesce(struct ieee80211_sub_if_data *sdata)
cancel_work_sync(&ifmgd->chswitch_work);
if (del_timer_sync(&ifmgd->chswitch_timer))
set_bit(TMR_RUNNING_CHANSW, &ifmgd->timers_running);
+
+ cancel_work_sync(&ifmgd->monitor_work);
+ /* these will just be re-established on connection */
+ del_timer_sync(&ifmgd->conn_mon_timer);
+ del_timer_sync(&ifmgd->bcn_mon_timer);
}
void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata)
@@ -2395,210 +2300,277 @@ void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata)
void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata)
{
struct ieee80211_if_managed *ifmgd;
- u32 hw_flags;
ifmgd = &sdata->u.mgd;
INIT_WORK(&ifmgd->work, ieee80211_sta_work);
+ INIT_WORK(&ifmgd->monitor_work, ieee80211_sta_monitor_work);
INIT_WORK(&ifmgd->chswitch_work, ieee80211_chswitch_work);
INIT_WORK(&ifmgd->beacon_loss_work, ieee80211_beacon_loss_work);
setup_timer(&ifmgd->timer, ieee80211_sta_timer,
(unsigned long) sdata);
+ setup_timer(&ifmgd->bcn_mon_timer, ieee80211_sta_bcn_mon_timer,
+ (unsigned long) sdata);
+ setup_timer(&ifmgd->conn_mon_timer, ieee80211_sta_conn_mon_timer,
+ (unsigned long) sdata);
setup_timer(&ifmgd->chswitch_timer, ieee80211_chswitch_timer,
(unsigned long) sdata);
skb_queue_head_init(&ifmgd->skb_queue);
+ INIT_LIST_HEAD(&ifmgd->work_list);
+
ifmgd->capab = WLAN_CAPABILITY_ESS;
- ifmgd->auth_algs = IEEE80211_AUTH_ALG_OPEN |
- IEEE80211_AUTH_ALG_SHARED_KEY;
- ifmgd->flags |= IEEE80211_STA_CREATE_IBSS |
- IEEE80211_STA_AUTO_BSSID_SEL |
- IEEE80211_STA_AUTO_CHANNEL_SEL;
+ ifmgd->flags = 0;
if (sdata->local->hw.queues >= 4)
ifmgd->flags |= IEEE80211_STA_WMM_ENABLED;
- hw_flags = sdata->local->hw.flags;
-
- if (hw_flags & IEEE80211_HW_SUPPORTS_PS) {
- ifmgd->powersave = CONFIG_MAC80211_DEFAULT_PS_VALUE;
- sdata->local->hw.conf.dynamic_ps_timeout = 500;
- }
+ mutex_init(&ifmgd->mtx);
}
-/* configuration hooks */
-void ieee80211_sta_req_auth(struct ieee80211_sub_if_data *sdata)
+/* scan finished notification */
+void ieee80211_mlme_notify_scan_completed(struct ieee80211_local *local)
{
- struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
- struct ieee80211_local *local = sdata->local;
-
- if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION))
- return;
-
- if ((ifmgd->flags & (IEEE80211_STA_BSSID_SET |
- IEEE80211_STA_AUTO_BSSID_SEL)) &&
- (ifmgd->flags & (IEEE80211_STA_SSID_SET |
- IEEE80211_STA_AUTO_SSID_SEL))) {
-
- if (ifmgd->state == IEEE80211_STA_MLME_ASSOCIATED)
- ieee80211_set_disassoc(sdata, true, true,
- WLAN_REASON_DEAUTH_LEAVING);
-
- if (ifmgd->ssid_len == 0) {
- /*
- * Only allow association to be started if a valid SSID
- * is configured.
- */
- return;
- }
+ struct ieee80211_sub_if_data *sdata = local->scan_sdata;
- if (!(ifmgd->flags & IEEE80211_STA_EXT_SME) ||
- ifmgd->state != IEEE80211_STA_MLME_ASSOCIATE)
- set_bit(IEEE80211_STA_REQ_AUTH, &ifmgd->request);
- else if (ifmgd->flags & IEEE80211_STA_EXT_SME)
- set_bit(IEEE80211_STA_REQ_RUN, &ifmgd->request);
- queue_work(local->hw.workqueue, &ifmgd->work);
- }
+ /* Restart STA timers */
+ rcu_read_lock();
+ list_for_each_entry_rcu(sdata, &local->interfaces, list)
+ ieee80211_restart_sta_timer(sdata);
+ rcu_read_unlock();
}
-int ieee80211_sta_commit(struct ieee80211_sub_if_data *sdata)
+int ieee80211_max_network_latency(struct notifier_block *nb,
+ unsigned long data, void *dummy)
{
- struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
+ s32 latency_usec = (s32) data;
+ struct ieee80211_local *local =
+ container_of(nb, struct ieee80211_local,
+ network_latency_notifier);
- if (ifmgd->ssid_len)
- ifmgd->flags |= IEEE80211_STA_SSID_SET;
- else
- ifmgd->flags &= ~IEEE80211_STA_SSID_SET;
+ mutex_lock(&local->iflist_mtx);
+ ieee80211_recalc_ps(local, latency_usec);
+ mutex_unlock(&local->iflist_mtx);
return 0;
}
-int ieee80211_sta_set_ssid(struct ieee80211_sub_if_data *sdata, char *ssid, size_t len)
+/* config hooks */
+int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,
+ struct cfg80211_auth_request *req)
{
- struct ieee80211_if_managed *ifmgd;
+ struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
+ const u8 *ssid;
+ struct ieee80211_mgd_work *wk;
+ u16 auth_alg;
- if (len > IEEE80211_MAX_SSID_LEN)
- return -EINVAL;
+ switch (req->auth_type) {
+ case NL80211_AUTHTYPE_OPEN_SYSTEM:
+ auth_alg = WLAN_AUTH_OPEN;
+ break;
+ case NL80211_AUTHTYPE_SHARED_KEY:
+ auth_alg = WLAN_AUTH_SHARED_KEY;
+ break;
+ case NL80211_AUTHTYPE_FT:
+ auth_alg = WLAN_AUTH_FT;
+ break;
+ case NL80211_AUTHTYPE_NETWORK_EAP:
+ auth_alg = WLAN_AUTH_LEAP;
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
- ifmgd = &sdata->u.mgd;
+ wk = kzalloc(sizeof(*wk) + req->ie_len, GFP_KERNEL);
+ if (!wk)
+ return -ENOMEM;
- if (ifmgd->ssid_len != len || memcmp(ifmgd->ssid, ssid, len) != 0) {
- if (ifmgd->state == IEEE80211_STA_MLME_ASSOCIATED)
- ieee80211_set_disassoc(sdata, true, true,
- WLAN_REASON_DEAUTH_LEAVING);
+ wk->bss = (void *)req->bss;
- /*
- * Do not use reassociation if SSID is changed (different ESS).
- */
- ifmgd->flags &= ~IEEE80211_STA_PREV_BSSID_SET;
- memset(ifmgd->ssid, 0, sizeof(ifmgd->ssid));
- memcpy(ifmgd->ssid, ssid, len);
- ifmgd->ssid_len = len;
+ if (req->ie && req->ie_len) {
+ memcpy(wk->ie, req->ie, req->ie_len);
+ wk->ie_len = req->ie_len;
}
- return ieee80211_sta_commit(sdata);
-}
+ if (req->key && req->key_len) {
+ wk->key_len = req->key_len;
+ wk->key_idx = req->key_idx;
+ memcpy(wk->key, req->key, req->key_len);
+ }
-int ieee80211_sta_get_ssid(struct ieee80211_sub_if_data *sdata, char *ssid, size_t *len)
-{
- struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
- memcpy(ssid, ifmgd->ssid, ifmgd->ssid_len);
- *len = ifmgd->ssid_len;
+ ssid = ieee80211_bss_get_ie(req->bss, WLAN_EID_SSID);
+ memcpy(wk->ssid, ssid + 2, ssid[1]);
+ wk->ssid_len = ssid[1];
+
+ wk->state = IEEE80211_MGD_STATE_PROBE;
+ wk->auth_alg = auth_alg;
+ wk->timeout = jiffies; /* run right away */
+
+ /*
+ * XXX: if still associated need to tell AP that we're going
+ * to sleep and then change channel etc.
+ */
+ sdata->local->oper_channel = req->bss->channel;
+ ieee80211_hw_config(sdata->local, 0);
+
+ mutex_lock(&ifmgd->mtx);
+ list_add(&wk->list, &sdata->u.mgd.work_list);
+ mutex_unlock(&ifmgd->mtx);
+
+ ieee80211_queue_work(&sdata->local->hw, &sdata->u.mgd.work);
return 0;
}
-int ieee80211_sta_set_bssid(struct ieee80211_sub_if_data *sdata, u8 *bssid)
+int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
+ struct cfg80211_assoc_request *req)
{
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
+ struct ieee80211_mgd_work *wk, *found = NULL;
+ int i, err;
- if (compare_ether_addr(bssid, ifmgd->bssid) != 0 &&
- ifmgd->state == IEEE80211_STA_MLME_ASSOCIATED)
- ieee80211_set_disassoc(sdata, true, true,
- WLAN_REASON_DEAUTH_LEAVING);
+ mutex_lock(&ifmgd->mtx);
- if (is_valid_ether_addr(bssid)) {
- memcpy(ifmgd->bssid, bssid, ETH_ALEN);
- ifmgd->flags |= IEEE80211_STA_BSSID_SET;
- } else {
- memset(ifmgd->bssid, 0, ETH_ALEN);
- ifmgd->flags &= ~IEEE80211_STA_BSSID_SET;
+ list_for_each_entry(wk, &ifmgd->work_list, list) {
+ if (&wk->bss->cbss == req->bss &&
+ wk->state == IEEE80211_MGD_STATE_IDLE) {
+ found = wk;
+ break;
+ }
}
- return ieee80211_sta_commit(sdata);
-}
+ if (!found) {
+ err = -ENOLINK;
+ goto out;
+ }
-int ieee80211_sta_set_extra_ie(struct ieee80211_sub_if_data *sdata,
- const char *ie, size_t len)
-{
- struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
+ list_del(&found->list);
- if (len == 0 && ifmgd->extra_ie_len == 0)
- return -EALREADY;
+ wk = krealloc(found, sizeof(*wk) + req->ie_len, GFP_KERNEL);
+ if (!wk) {
+ list_add(&found->list, &ifmgd->work_list);
+ err = -ENOMEM;
+ goto out;
+ }
- if (len == ifmgd->extra_ie_len && ifmgd->extra_ie &&
- memcmp(ifmgd->extra_ie, ie, len) == 0)
- return -EALREADY;
+ list_add(&wk->list, &ifmgd->work_list);
- kfree(ifmgd->extra_ie);
- if (len == 0) {
- ifmgd->extra_ie = NULL;
- ifmgd->extra_ie_len = 0;
- return 0;
- }
- ifmgd->extra_ie = kmalloc(len, GFP_KERNEL);
- if (!ifmgd->extra_ie) {
- ifmgd->extra_ie_len = 0;
- return -ENOMEM;
+ ifmgd->flags &= ~IEEE80211_STA_DISABLE_11N;
+
+ for (i = 0; i < req->crypto.n_ciphers_pairwise; i++)
+ if (req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_WEP40 ||
+ req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_TKIP ||
+ req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_WEP104)
+ ifmgd->flags |= IEEE80211_STA_DISABLE_11N;
+
+ sdata->local->oper_channel = req->bss->channel;
+ ieee80211_hw_config(sdata->local, 0);
+
+ if (req->ie && req->ie_len) {
+ memcpy(wk->ie, req->ie, req->ie_len);
+ wk->ie_len = req->ie_len;
+ } else
+ wk->ie_len = 0;
+
+ if (req->prev_bssid)
+ memcpy(wk->prev_bssid, req->prev_bssid, ETH_ALEN);
+
+ wk->state = IEEE80211_MGD_STATE_ASSOC;
+ wk->tries = 0;
+ wk->timeout = jiffies; /* run right away */
+
+ if (req->use_mfp) {
+ ifmgd->mfp = IEEE80211_MFP_REQUIRED;
+ ifmgd->flags |= IEEE80211_STA_MFP_ENABLED;
+ } else {
+ ifmgd->mfp = IEEE80211_MFP_DISABLED;
+ ifmgd->flags &= ~IEEE80211_STA_MFP_ENABLED;
}
- memcpy(ifmgd->extra_ie, ie, len);
- ifmgd->extra_ie_len = len;
- return 0;
-}
-int ieee80211_sta_deauthenticate(struct ieee80211_sub_if_data *sdata, u16 reason)
-{
- printk(KERN_DEBUG "%s: deauthenticating by local choice (reason=%d)\n",
- sdata->dev->name, reason);
+ if (req->crypto.control_port)
+ ifmgd->flags |= IEEE80211_STA_CONTROL_PORT;
+ else
+ ifmgd->flags &= ~IEEE80211_STA_CONTROL_PORT;
- ieee80211_set_disassoc(sdata, true, true, reason);
- return 0;
+ ieee80211_queue_work(&sdata->local->hw, &sdata->u.mgd.work);
+
+ err = 0;
+
+ out:
+ mutex_unlock(&ifmgd->mtx);
+ return err;
}
-int ieee80211_sta_disassociate(struct ieee80211_sub_if_data *sdata, u16 reason)
+int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
+ struct cfg80211_deauth_request *req,
+ void *cookie)
{
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
+ struct ieee80211_mgd_work *wk;
+ const u8 *bssid = NULL;
- printk(KERN_DEBUG "%s: disassociating by local choice (reason=%d)\n",
- sdata->dev->name, reason);
+ printk(KERN_DEBUG "%s: deauthenticating by local choice (reason=%d)\n",
+ sdata->dev->name, req->reason_code);
+
+ mutex_lock(&ifmgd->mtx);
+
+ if (ifmgd->associated && &ifmgd->associated->cbss == req->bss) {
+ bssid = req->bss->bssid;
+ ieee80211_set_disassoc(sdata, true);
+ } else list_for_each_entry(wk, &ifmgd->work_list, list) {
+ if (&wk->bss->cbss == req->bss) {
+ bssid = req->bss->bssid;
+ list_del(&wk->list);
+ kfree(wk);
+ break;
+ }
+ }
- if (!(ifmgd->flags & IEEE80211_STA_ASSOCIATED))
+ /*
+ * cfg80211 should catch this ... but it's racy since
+ * we can receive a deauth frame, process it, hand it
+ * to cfg80211 while that's in a locked section already
+ * trying to tell us that the user wants to disconnect.
+ */
+ if (!bssid) {
+ mutex_unlock(&ifmgd->mtx);
return -ENOLINK;
+ }
+
+ mutex_unlock(&ifmgd->mtx);
+
+ ieee80211_send_deauth_disassoc(sdata, bssid,
+ IEEE80211_STYPE_DEAUTH, req->reason_code,
+ cookie);
- ieee80211_set_disassoc(sdata, false, true, reason);
return 0;
}
-/* scan finished notification */
-void ieee80211_mlme_notify_scan_completed(struct ieee80211_local *local)
+int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata,
+ struct cfg80211_disassoc_request *req,
+ void *cookie)
{
- struct ieee80211_sub_if_data *sdata = local->scan_sdata;
+ struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
- /* Restart STA timers */
- rcu_read_lock();
- list_for_each_entry_rcu(sdata, &local->interfaces, list)
- ieee80211_restart_sta_timer(sdata);
- rcu_read_unlock();
-}
+ printk(KERN_DEBUG "%s: disassociating by local choice (reason=%d)\n",
+ sdata->dev->name, req->reason_code);
-int ieee80211_max_network_latency(struct notifier_block *nb,
- unsigned long data, void *dummy)
-{
- s32 latency_usec = (s32) data;
- struct ieee80211_local *local =
- container_of(nb, struct ieee80211_local,
- network_latency_notifier);
+ mutex_lock(&ifmgd->mtx);
- mutex_lock(&local->iflist_mtx);
- ieee80211_recalc_ps(local, latency_usec);
- mutex_unlock(&local->iflist_mtx);
+ /*
+ * cfg80211 should catch this ... but it's racy since
+ * we can receive a disassoc frame, process it, hand it
+ * to cfg80211 while that's in a locked section already
+ * trying to tell us that the user wants to disconnect.
+ */
+ if (&ifmgd->associated->cbss != req->bss) {
+ mutex_unlock(&ifmgd->mtx);
+ return -ENOLINK;
+ }
+
+ ieee80211_set_disassoc(sdata, false);
+
+ mutex_unlock(&ifmgd->mtx);
+ ieee80211_send_deauth_disassoc(sdata, req->bss->bssid,
+ IEEE80211_STYPE_DISASSOC, req->reason_code,
+ cookie);
return 0;
}
diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c
index 5e3d476972f..a5d2f1fb441 100644
--- a/net/mac80211/pm.c
+++ b/net/mac80211/pm.c
@@ -26,7 +26,7 @@ int __ieee80211_suspend(struct ieee80211_hw *hw)
/* make quiescing visible to timers everywhere */
mb();
- flush_workqueue(local->hw.workqueue);
+ flush_workqueue(local->workqueue);
/* Don't try to run timers while suspended. */
del_timer_sync(&local->sta_cleanup);
@@ -96,6 +96,10 @@ int __ieee80211_suspend(struct ieee80211_hw *hw)
if (!netif_running(sdata->dev))
continue;
+ /* disable beaconing */
+ ieee80211_bss_info_change_notify(sdata,
+ BSS_CHANGED_BEACON_ENABLED);
+
conf.vif = &sdata->vif;
conf.type = sdata->vif.type;
conf.mac_addr = sdata->dev->dev_addr;
@@ -113,7 +117,7 @@ int __ieee80211_suspend(struct ieee80211_hw *hw)
* shouldn't be doing (or cancel everything in the
* stop callback) that but better safe than sorry.
*/
- flush_workqueue(local->hw.workqueue);
+ flush_workqueue(local->workqueue);
local->suspended = true;
/* need suspended to be visible before quiescing is false */
diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c
index 4641f00a1e5..b33efc4fc26 100644
--- a/net/mac80211/rate.c
+++ b/net/mac80211/rate.c
@@ -198,6 +198,35 @@ static void rate_control_release(struct kref *kref)
kfree(ctrl_ref);
}
+static bool rc_no_data_or_no_ack(struct ieee80211_tx_rate_control *txrc)
+{
+ struct sk_buff *skb = txrc->skb;
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+ __le16 fc;
+
+ fc = hdr->frame_control;
+
+ return ((info->flags & IEEE80211_TX_CTL_NO_ACK) || !ieee80211_is_data(fc));
+}
+
+bool rate_control_send_low(struct ieee80211_sta *sta,
+ void *priv_sta,
+ struct ieee80211_tx_rate_control *txrc)
+{
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(txrc->skb);
+
+ if (!sta || !priv_sta || rc_no_data_or_no_ack(txrc)) {
+ info->control.rates[0].idx = rate_lowest_index(txrc->sband, sta);
+ info->control.rates[0].count =
+ (info->flags & IEEE80211_TX_CTL_NO_ACK) ?
+ 1 : txrc->hw->max_rate_tries;
+ return true;
+ }
+ return false;
+}
+EXPORT_SYMBOL(rate_control_send_low);
+
void rate_control_get_rate(struct ieee80211_sub_if_data *sdata,
struct sta_info *sta,
struct ieee80211_tx_rate_control *txrc)
@@ -258,7 +287,7 @@ int ieee80211_init_rate_ctrl_alg(struct ieee80211_local *local,
struct rate_control_ref *ref, *old;
ASSERT_RTNL();
- if (local->open_count || netif_running(local->mdev))
+ if (local->open_count)
return -EBUSY;
ref = rate_control_alloc(name, local);
diff --git a/net/mac80211/rc80211_minstrel.c b/net/mac80211/rc80211_minstrel.c
index 37771abd8f5..007164919e0 100644
--- a/net/mac80211/rc80211_minstrel.c
+++ b/net/mac80211/rc80211_minstrel.c
@@ -51,6 +51,7 @@
#include <linux/random.h>
#include <linux/ieee80211.h>
#include <net/mac80211.h>
+#include "mesh.h"
#include "rate.h"
#include "rc80211_minstrel.h"
@@ -70,20 +71,6 @@ rix_to_ndx(struct minstrel_sta_info *mi, int rix)
return i;
}
-static inline bool
-use_low_rate(struct sk_buff *skb)
-{
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
- u16 fc;
-
- fc = le16_to_cpu(hdr->frame_control);
-
- return ((info->flags & IEEE80211_TX_CTL_NO_ACK) ||
- (fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA);
-}
-
-
static void
minstrel_update_stats(struct minstrel_priv *mp, struct minstrel_sta_info *mi)
{
@@ -169,12 +156,16 @@ minstrel_tx_status(void *priv, struct ieee80211_supported_band *sband,
struct sk_buff *skb)
{
struct minstrel_sta_info *mi = priv_sta;
+ struct minstrel_priv *mp = (struct minstrel_priv *)priv;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct ieee80211_tx_rate *ar = info->status.rates;
+ struct ieee80211_local *local = hw_to_local(mp->hw);
+ struct sta_info *si;
int i, ndx;
int success;
success = !!(info->flags & IEEE80211_TX_STAT_ACK);
+ si = sta_info_get(local, sta->addr);
for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) {
if (ar[i].idx < 0)
@@ -186,8 +177,17 @@ minstrel_tx_status(void *priv, struct ieee80211_supported_band *sband,
mi->r[ndx].attempts += ar[i].count;
- if ((i != IEEE80211_TX_MAX_RATES - 1) && (ar[i + 1].idx < 0))
+ if ((i != IEEE80211_TX_MAX_RATES - 1) && (ar[i + 1].idx < 0)) {
mi->r[ndx].success += success;
+ if (si) {
+ si->fail_avg = (18050 - mi->r[ndx].probability)
+ / 180;
+ WARN_ON(si->fail_avg > 100);
+ if (si->fail_avg == 100 &&
+ ieee80211_vif_is_mesh(&si->sdata->vif))
+ mesh_plink_broken(si);
+ }
+ }
}
if ((info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) && (i >= 0))
@@ -232,7 +232,6 @@ minstrel_get_rate(void *priv, struct ieee80211_sta *sta,
void *priv_sta, struct ieee80211_tx_rate_control *txrc)
{
struct sk_buff *skb = txrc->skb;
- struct ieee80211_supported_band *sband = txrc->sband;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct minstrel_sta_info *mi = priv_sta;
struct minstrel_priv *mp = priv;
@@ -245,14 +244,8 @@ minstrel_get_rate(void *priv, struct ieee80211_sta *sta,
int mrr_ndx[3];
int sample_rate;
- if (!sta || !mi || use_low_rate(skb)) {
- ar[0].idx = rate_lowest_index(sband, sta);
- if (info->flags & IEEE80211_TX_CTL_NO_ACK)
- ar[0].count = 1;
- else
- ar[0].count = mp->max_retry;
+ if (rate_control_send_low(sta, priv_sta, txrc))
return;
- }
mrr = mp->has_mrr && !txrc->rts && !txrc->bss_conf->use_cts_prot;
diff --git a/net/mac80211/rc80211_pid_algo.c b/net/mac80211/rc80211_pid_algo.c
index a0bef767ceb..8c053be9dc2 100644
--- a/net/mac80211/rc80211_pid_algo.c
+++ b/net/mac80211/rc80211_pid_algo.c
@@ -276,11 +276,9 @@ rate_control_pid_get_rate(void *priv, struct ieee80211_sta *sta,
{
struct sk_buff *skb = txrc->skb;
struct ieee80211_supported_band *sband = txrc->sband;
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct rc_pid_sta_info *spinfo = priv_sta;
int rateidx;
- u16 fc;
if (txrc->rts)
info->control.rates[0].count =
@@ -290,16 +288,8 @@ rate_control_pid_get_rate(void *priv, struct ieee80211_sta *sta,
txrc->hw->conf.short_frame_max_tx_count;
/* Send management frames and NO_ACK data using lowest rate. */
- fc = le16_to_cpu(hdr->frame_control);
- if (!sta || !spinfo ||
- (fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA ||
- info->flags & IEEE80211_TX_CTL_NO_ACK) {
- info->control.rates[0].idx = rate_lowest_index(sband, sta);
- if (info->flags & IEEE80211_TX_CTL_NO_ACK)
- info->control.rates[0].count = 1;
-
+ if (rate_control_send_low(sta, priv_sta, txrc))
return;
- }
rateidx = spinfo->txrate_idx;
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 0936fc24942..4cd9e45b144 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -30,7 +30,6 @@
static u8 ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw,
struct tid_ampdu_rx *tid_agg_rx,
struct sk_buff *skb,
- struct ieee80211_rx_status *status,
u16 mpdu_seq_num,
int bar_req);
/*
@@ -59,11 +58,11 @@ static struct sk_buff *remove_monitor_info(struct ieee80211_local *local,
return skb;
}
-static inline int should_drop_frame(struct ieee80211_rx_status *status,
- struct sk_buff *skb,
+static inline int should_drop_frame(struct sk_buff *skb,
int present_fcs_len,
int radiotap_len)
{
+ struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
if (status->flag & (RX_FLAG_FAILED_FCS_CRC | RX_FLAG_FAILED_PLCP_CRC))
@@ -111,10 +110,10 @@ ieee80211_rx_radiotap_len(struct ieee80211_local *local,
static void
ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
struct sk_buff *skb,
- struct ieee80211_rx_status *status,
struct ieee80211_rate *rate,
int rtap_len)
{
+ struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
struct ieee80211_radiotap_header *rthdr;
unsigned char *pos;
@@ -220,9 +219,9 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
*/
static struct sk_buff *
ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb,
- struct ieee80211_rx_status *status,
struct ieee80211_rate *rate)
{
+ struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(origskb);
struct ieee80211_sub_if_data *sdata;
int needed_headroom = 0;
struct sk_buff *skb, *skb2;
@@ -248,8 +247,7 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb,
present_fcs_len = FCS_LEN;
if (!local->monitors) {
- if (should_drop_frame(status, origskb, present_fcs_len,
- rtap_len)) {
+ if (should_drop_frame(origskb, present_fcs_len, rtap_len)) {
dev_kfree_skb(origskb);
return NULL;
}
@@ -257,7 +255,7 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb,
return remove_monitor_info(local, origskb, rtap_len);
}
- if (should_drop_frame(status, origskb, present_fcs_len, rtap_len)) {
+ if (should_drop_frame(origskb, present_fcs_len, rtap_len)) {
/* only need to expand headroom if necessary */
skb = origskb;
origskb = NULL;
@@ -289,7 +287,7 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb,
/* if necessary, prepend radiotap information */
if (!(status->flag & RX_FLAG_RADIOTAP))
- ieee80211_add_rx_radiotap_header(local, skb, status, rate,
+ ieee80211_add_rx_radiotap_header(local, skb, rate,
needed_headroom);
skb_reset_mac_header(skb);
@@ -420,13 +418,13 @@ ieee80211_rx_h_passive_scan(struct ieee80211_rx_data *rx)
struct ieee80211_local *local = rx->local;
struct sk_buff *skb = rx->skb;
- if (unlikely(local->hw_scanning))
- return ieee80211_scan_rx(rx->sdata, skb, rx->status);
+ if (unlikely(test_bit(SCAN_HW_SCANNING, &local->scanning)))
+ return ieee80211_scan_rx(rx->sdata, skb);
- if (unlikely(local->sw_scanning)) {
+ if (unlikely(test_bit(SCAN_SW_SCANNING, &local->scanning) &&
+ (rx->flags & IEEE80211_RX_IN_SCAN))) {
/* drop all the other packets during a software scan anyway */
- if (ieee80211_scan_rx(rx->sdata, skb, rx->status)
- != RX_QUEUED)
+ if (ieee80211_scan_rx(rx->sdata, skb) != RX_QUEUED)
dev_kfree_skb(skb);
return RX_QUEUED;
}
@@ -491,12 +489,21 @@ ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx)
{
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
unsigned int hdrlen = ieee80211_hdrlen(hdr->frame_control);
+ char *dev_addr = rx->dev->dev_addr;
if (ieee80211_is_data(hdr->frame_control)) {
- if (!ieee80211_has_a4(hdr->frame_control))
- return RX_DROP_MONITOR;
- if (memcmp(hdr->addr4, rx->dev->dev_addr, ETH_ALEN) == 0)
- return RX_DROP_MONITOR;
+ if (is_multicast_ether_addr(hdr->addr1)) {
+ if (ieee80211_has_tods(hdr->frame_control) ||
+ !ieee80211_has_fromds(hdr->frame_control))
+ return RX_DROP_MONITOR;
+ if (memcmp(hdr->addr3, dev_addr, ETH_ALEN) == 0)
+ return RX_DROP_MONITOR;
+ } else {
+ if (!ieee80211_has_a4(hdr->frame_control))
+ return RX_DROP_MONITOR;
+ if (memcmp(hdr->addr4, dev_addr, ETH_ALEN) == 0)
+ return RX_DROP_MONITOR;
+ }
}
/* If there is not an established peer link and this is not a peer link
@@ -529,7 +536,7 @@ ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx)
if (ieee80211_is_data(hdr->frame_control) &&
is_multicast_ether_addr(hdr->addr1) &&
- mesh_rmc_check(hdr->addr4, msh_h_get(hdr, hdrlen), rx->sdata))
+ mesh_rmc_check(hdr->addr3, msh_h_get(hdr, hdrlen), rx->sdata))
return RX_DROP_MONITOR;
#undef msh_h_get
@@ -785,7 +792,7 @@ static void ap_sta_ps_start(struct sta_info *sta)
struct ieee80211_local *local = sdata->local;
atomic_inc(&sdata->bss->num_sta_ps);
- set_and_clear_sta_flags(sta, WLAN_STA_PS, WLAN_STA_PSPOLL);
+ set_sta_flags(sta, WLAN_STA_PS);
drv_sta_notify(local, &sdata->vif, STA_NOTIFY_SLEEP, &sta->sta);
#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
printk(KERN_DEBUG "%s: STA %pM aid %d enters power save mode\n",
@@ -801,7 +808,7 @@ static int ap_sta_ps_end(struct sta_info *sta)
atomic_dec(&sdata->bss->num_sta_ps);
- clear_sta_flags(sta, WLAN_STA_PS | WLAN_STA_PSPOLL);
+ clear_sta_flags(sta, WLAN_STA_PS);
drv_sta_notify(local, &sdata->vif, STA_NOTIFY_AWAKE, &sta->sta);
if (!skb_queue_empty(&sta->ps_tx_buf))
@@ -836,28 +843,22 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
if (!sta)
return RX_CONTINUE;
- /* Update last_rx only for IBSS packets which are for the current
- * BSSID to avoid keeping the current IBSS network alive in cases where
- * other STAs are using different BSSID. */
+ /*
+ * Update last_rx only for IBSS packets which are for the current
+ * BSSID to avoid keeping the current IBSS network alive in cases
+ * where other STAs start using different BSSID.
+ */
if (rx->sdata->vif.type == NL80211_IFTYPE_ADHOC) {
u8 *bssid = ieee80211_get_bssid(hdr, rx->skb->len,
NL80211_IFTYPE_ADHOC);
if (compare_ether_addr(bssid, rx->sdata->u.ibss.bssid) == 0)
sta->last_rx = jiffies;
- } else
- if (!is_multicast_ether_addr(hdr->addr1) ||
- rx->sdata->vif.type == NL80211_IFTYPE_STATION) {
- /* Update last_rx only for unicast frames in order to prevent
- * the Probe Request frames (the only broadcast frames from a
- * STA in infrastructure mode) from keeping a connection alive.
+ } else if (!is_multicast_ether_addr(hdr->addr1)) {
+ /*
* Mesh beacons will update last_rx when if they are found to
* match the current local configuration when processed.
*/
- if (rx->sdata->vif.type == NL80211_IFTYPE_STATION &&
- ieee80211_is_beacon(hdr->frame_control)) {
- rx->sdata->u.mgd.last_beacon = jiffies;
- } else
- sta->last_rx = jiffies;
+ sta->last_rx = jiffies;
}
if (!(rx->flags & IEEE80211_RX_RA_MATCH))
@@ -1125,14 +1126,15 @@ ieee80211_rx_h_ps_poll(struct ieee80211_rx_data *rx)
skb_queue_empty(&rx->sta->ps_tx_buf);
if (skb) {
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct ieee80211_hdr *hdr =
(struct ieee80211_hdr *) skb->data;
/*
- * Tell TX path to send one frame even though the STA may
+ * Tell TX path to send this frame even though the STA may
* still remain is PS mode after this frame exchange.
*/
- set_sta_flags(rx->sta, WLAN_STA_PSPOLL);
+ info->flags |= IEEE80211_TX_CTL_PSPOLL_RESPONSE;
#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
printk(KERN_DEBUG "STA %pM aid %d: PS Poll (entries after %d)\n",
@@ -1147,7 +1149,7 @@ ieee80211_rx_h_ps_poll(struct ieee80211_rx_data *rx)
else
hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREDATA);
- dev_queue_xmit(skb);
+ ieee80211_add_pending_skb(rx->local, skb);
if (no_pending_pkts)
sta_info_clear_tim_bit(rx->sta);
@@ -1487,10 +1489,13 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
struct ieee80211s_hdr *mesh_hdr;
unsigned int hdrlen;
struct sk_buff *skb = rx->skb, *fwd_skb;
+ struct ieee80211_local *local = rx->local;
+ struct ieee80211_sub_if_data *sdata;
hdr = (struct ieee80211_hdr *) skb->data;
hdrlen = ieee80211_hdrlen(hdr->frame_control);
mesh_hdr = (struct ieee80211s_hdr *) (skb->data + hdrlen);
+ sdata = IEEE80211_DEV_TO_SUB_IF(rx->dev);
if (!ieee80211_is_data(hdr->frame_control))
return RX_CONTINUE;
@@ -1499,11 +1504,10 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
/* illegal frame */
return RX_DROP_MONITOR;
- if (mesh_hdr->flags & MESH_FLAGS_AE_A5_A6){
- struct ieee80211_sub_if_data *sdata;
+ if (!is_multicast_ether_addr(hdr->addr1) &&
+ (mesh_hdr->flags & MESH_FLAGS_AE_A5_A6)) {
struct mesh_path *mppath;
- sdata = IEEE80211_DEV_TO_SUB_IF(rx->dev);
rcu_read_lock();
mppath = mpp_path_lookup(mesh_hdr->eaddr2, sdata);
if (!mppath) {
@@ -1518,7 +1522,9 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
rcu_read_unlock();
}
- if (compare_ether_addr(rx->dev->dev_addr, hdr->addr3) == 0)
+ /* Frame has reached destination. Don't forward */
+ if (!is_multicast_ether_addr(hdr->addr1) &&
+ compare_ether_addr(rx->dev->dev_addr, hdr->addr3) == 0)
return RX_CONTINUE;
mesh_hdr->ttl--;
@@ -1529,6 +1535,8 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
dropped_frames_ttl);
else {
struct ieee80211_hdr *fwd_hdr;
+ struct ieee80211_tx_info *info;
+
fwd_skb = skb_copy(skb, GFP_ATOMIC);
if (!fwd_skb && net_ratelimit())
@@ -1536,19 +1544,34 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
rx->dev->name);
fwd_hdr = (struct ieee80211_hdr *) fwd_skb->data;
- /*
- * Save TA to addr1 to send TA a path error if a
- * suitable next hop is not found
- */
- memcpy(fwd_hdr->addr1, fwd_hdr->addr2, ETH_ALEN);
memcpy(fwd_hdr->addr2, rx->dev->dev_addr, ETH_ALEN);
- fwd_skb->dev = rx->local->mdev;
- fwd_skb->iif = rx->dev->ifindex;
- dev_queue_xmit(fwd_skb);
+ info = IEEE80211_SKB_CB(fwd_skb);
+ memset(info, 0, sizeof(*info));
+ info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING;
+ info->control.vif = &rx->sdata->vif;
+ ieee80211_select_queue(local, fwd_skb);
+ if (!is_multicast_ether_addr(fwd_hdr->addr1)) {
+ int err;
+ /*
+ * Save TA to addr1 to send TA a path error if a
+ * suitable next hop is not found
+ */
+ memcpy(fwd_hdr->addr1, fwd_hdr->addr2,
+ ETH_ALEN);
+ err = mesh_nexthop_lookup(fwd_skb, sdata);
+ /* Failed to immediately resolve next hop:
+ * fwded frame was dropped or will be added
+ * later to the pending skb queue. */
+ if (err)
+ return RX_DROP_MONITOR;
+ }
+ IEEE80211_IFSTA_MESH_CTR_INC(&sdata->u.mesh,
+ fwded_frames);
+ ieee80211_add_pending_skb(local, fwd_skb);
}
}
- if (is_multicast_ether_addr(hdr->addr3) ||
+ if (is_multicast_ether_addr(hdr->addr1) ||
rx->dev->flags & IFF_PROMISC)
return RX_CONTINUE;
else
@@ -1620,7 +1643,7 @@ ieee80211_rx_h_ctrl(struct ieee80211_rx_data *rx)
/* manage reordering buffer according to requested */
/* sequence number */
rcu_read_lock();
- ieee80211_sta_manage_reorder_buf(hw, tid_agg_rx, NULL, NULL,
+ ieee80211_sta_manage_reorder_buf(hw, tid_agg_rx, NULL,
start_seq_num, 1);
rcu_read_unlock();
return RX_DROP_UNUSABLE;
@@ -1644,12 +1667,7 @@ static void ieee80211_process_sa_query_req(struct ieee80211_sub_if_data *sdata,
if (compare_ether_addr(mgmt->sa, sdata->u.mgd.bssid) != 0 ||
compare_ether_addr(mgmt->bssid, sdata->u.mgd.bssid) != 0) {
- /* Not from the current AP. */
- return;
- }
-
- if (sdata->u.mgd.state == IEEE80211_STA_MLME_ASSOCIATE) {
- /* Association in progress; ignore SA Query */
+ /* Not from the current AP or not associated yet. */
return;
}
@@ -1686,7 +1704,6 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
struct ieee80211_local *local = rx->local;
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(rx->dev);
struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) rx->skb->data;
- struct ieee80211_bss *bss;
int len = rx->skb->len;
if (!ieee80211_is_action(mgmt->frame_control))
@@ -1764,17 +1781,7 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
if (memcmp(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN))
return RX_DROP_MONITOR;
- bss = ieee80211_rx_bss_get(local, sdata->u.mgd.bssid,
- local->hw.conf.channel->center_freq,
- sdata->u.mgd.ssid,
- sdata->u.mgd.ssid_len);
- if (!bss)
- return RX_DROP_MONITOR;
-
- ieee80211_sta_process_chanswitch(sdata,
- &mgmt->u.action.u.chan_switch.sw_elem, bss);
- ieee80211_rx_bss_put(local, bss);
- break;
+ return ieee80211_sta_rx_mgmt(sdata, rx->skb);
}
break;
case WLAN_CATEGORY_SA_QUERY:
@@ -1817,19 +1824,18 @@ ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx)
return RX_DROP_MONITOR;
if (ieee80211_vif_is_mesh(&sdata->vif))
- return ieee80211_mesh_rx_mgmt(sdata, rx->skb, rx->status);
+ return ieee80211_mesh_rx_mgmt(sdata, rx->skb);
if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
- return ieee80211_ibss_rx_mgmt(sdata, rx->skb, rx->status);
+ return ieee80211_ibss_rx_mgmt(sdata, rx->skb);
if (sdata->vif.type == NL80211_IFTYPE_STATION)
- return ieee80211_sta_rx_mgmt(sdata, rx->skb, rx->status);
+ return ieee80211_sta_rx_mgmt(sdata, rx->skb);
return RX_DROP_MONITOR;
}
-static void ieee80211_rx_michael_mic_report(struct net_device *dev,
- struct ieee80211_hdr *hdr,
+static void ieee80211_rx_michael_mic_report(struct ieee80211_hdr *hdr,
struct ieee80211_rx_data *rx)
{
int keyidx;
@@ -1866,7 +1872,8 @@ static void ieee80211_rx_michael_mic_report(struct net_device *dev,
!ieee80211_is_auth(hdr->frame_control))
goto ignore;
- mac80211_ev_michael_mic_failure(rx->sdata, keyidx, hdr, NULL);
+ mac80211_ev_michael_mic_failure(rx->sdata, keyidx, hdr, NULL,
+ GFP_ATOMIC);
ignore:
dev_kfree_skb(rx->skb);
rx->skb = NULL;
@@ -2028,13 +2035,8 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata,
case NL80211_IFTYPE_STATION:
if (!bssid)
return 0;
- if (!ieee80211_bssid_match(bssid, sdata->u.mgd.bssid)) {
- if (!(rx->flags & IEEE80211_RX_IN_SCAN))
- return 0;
- rx->flags &= ~IEEE80211_RX_RA_MATCH;
- } else if (!multicast &&
- compare_ether_addr(sdata->dev->dev_addr,
- hdr->addr1) != 0) {
+ if (!multicast &&
+ compare_ether_addr(sdata->dev->dev_addr, hdr->addr1) != 0) {
if (!(sdata->dev->flags & IFF_PROMISC))
return 0;
rx->flags &= ~IEEE80211_RX_RA_MATCH;
@@ -2114,9 +2116,9 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata,
*/
static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
struct sk_buff *skb,
- struct ieee80211_rx_status *status,
struct ieee80211_rate *rate)
{
+ struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
struct ieee80211_local *local = hw_to_local(hw);
struct ieee80211_sub_if_data *sdata;
struct ieee80211_hdr *hdr;
@@ -2143,11 +2145,12 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
}
if ((status->flag & RX_FLAG_MMIC_ERROR)) {
- ieee80211_rx_michael_mic_report(local->mdev, hdr, &rx);
+ ieee80211_rx_michael_mic_report(hdr, &rx);
return;
}
- if (unlikely(local->sw_scanning || local->hw_scanning))
+ if (unlikely(test_bit(SCAN_HW_SCANNING, &local->scanning) ||
+ test_bit(SCAN_OFF_CHANNEL, &local->scanning)))
rx.flags |= IEEE80211_RX_IN_SCAN;
ieee80211_parse_qos(&rx);
@@ -2227,20 +2230,21 @@ static void ieee80211_release_reorder_frame(struct ieee80211_hw *hw,
{
struct ieee80211_supported_band *sband;
struct ieee80211_rate *rate;
- struct ieee80211_rx_status status;
+ struct sk_buff *skb = tid_agg_rx->reorder_buf[index];
+ struct ieee80211_rx_status *status;
- if (!tid_agg_rx->reorder_buf[index])
+ if (!skb)
goto no_frame;
+ status = IEEE80211_SKB_RXCB(skb);
+
/* release the reordered frames to stack */
- memcpy(&status, tid_agg_rx->reorder_buf[index]->cb, sizeof(status));
- sband = hw->wiphy->bands[status.band];
- if (status.flag & RX_FLAG_HT)
+ sband = hw->wiphy->bands[status->band];
+ if (status->flag & RX_FLAG_HT)
rate = sband->bitrates; /* TODO: HT rates */
else
- rate = &sband->bitrates[status.rate_idx];
- __ieee80211_rx_handle_packet(hw, tid_agg_rx->reorder_buf[index],
- &status, rate);
+ rate = &sband->bitrates[status->rate_idx];
+ __ieee80211_rx_handle_packet(hw, skb, rate);
tid_agg_rx->stored_mpdu_num--;
tid_agg_rx->reorder_buf[index] = NULL;
@@ -2265,7 +2269,6 @@ no_frame:
static u8 ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw,
struct tid_ampdu_rx *tid_agg_rx,
struct sk_buff *skb,
- struct ieee80211_rx_status *rxstatus,
u16 mpdu_seq_num,
int bar_req)
{
@@ -2324,8 +2327,6 @@ static u8 ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw,
/* put the frame in the reordering buffer */
tid_agg_rx->reorder_buf[index] = skb;
tid_agg_rx->reorder_time[index] = jiffies;
- memcpy(tid_agg_rx->reorder_buf[index]->cb, rxstatus,
- sizeof(*rxstatus));
tid_agg_rx->stored_mpdu_num++;
/* release the buffer until next missing frame */
index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn)
@@ -2374,8 +2375,7 @@ static u8 ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw,
}
static u8 ieee80211_rx_reorder_ampdu(struct ieee80211_local *local,
- struct sk_buff *skb,
- struct ieee80211_rx_status *status)
+ struct sk_buff *skb)
{
struct ieee80211_hw *hw = &local->hw;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
@@ -2424,7 +2424,7 @@ static u8 ieee80211_rx_reorder_ampdu(struct ieee80211_local *local,
/* according to mpdu sequence number deal with reordering buffer */
mpdu_seq_num = (sc & IEEE80211_SCTL_SEQ) >> 4;
- ret = ieee80211_sta_manage_reorder_buf(hw, tid_agg_rx, skb, status,
+ ret = ieee80211_sta_manage_reorder_buf(hw, tid_agg_rx, skb,
mpdu_seq_num, 0);
end_reorder:
return ret;
@@ -2434,12 +2434,12 @@ static u8 ieee80211_rx_reorder_ampdu(struct ieee80211_local *local,
* This is the receive path handler. It is called by a low level driver when an
* 802.11 MPDU is received from the hardware.
*/
-void __ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb,
- struct ieee80211_rx_status *status)
+void __ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb)
{
struct ieee80211_local *local = hw_to_local(hw);
struct ieee80211_rate *rate = NULL;
struct ieee80211_supported_band *sband;
+ struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
if (status->band < 0 ||
status->band >= IEEE80211_NUM_BANDS) {
@@ -2494,7 +2494,7 @@ void __ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb,
* if it was previously present.
* Also, frames with less than 16 bytes are dropped.
*/
- skb = ieee80211_rx_monitor(local, skb, status, rate);
+ skb = ieee80211_rx_monitor(local, skb, rate);
if (!skb) {
rcu_read_unlock();
return;
@@ -2512,8 +2512,8 @@ void __ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb,
* frames from other than operational channel), but that should not
* happen in normal networks.
*/
- if (!ieee80211_rx_reorder_ampdu(local, skb, status))
- __ieee80211_rx_handle_packet(hw, skb, status, rate);
+ if (!ieee80211_rx_reorder_ampdu(local, skb))
+ __ieee80211_rx_handle_packet(hw, skb, rate);
rcu_read_unlock();
}
@@ -2521,16 +2521,12 @@ EXPORT_SYMBOL(__ieee80211_rx);
/* This is a version of the rx handler that can be called from hard irq
* context. Post the skb on the queue and schedule the tasklet */
-void ieee80211_rx_irqsafe(struct ieee80211_hw *hw, struct sk_buff *skb,
- struct ieee80211_rx_status *status)
+void ieee80211_rx_irqsafe(struct ieee80211_hw *hw, struct sk_buff *skb)
{
struct ieee80211_local *local = hw_to_local(hw);
BUILD_BUG_ON(sizeof(struct ieee80211_rx_status) > sizeof(skb->cb));
- skb->dev = local->mdev;
- /* copy status into skb->cb for use by tasklet */
- memcpy(skb->cb, status, sizeof(*status));
skb->pkt_type = IEEE80211_RX_MSG;
skb_queue_tail(&local->skb_queue, skb);
tasklet_schedule(&local->tasklet);
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
index 2a8d09ad17f..e091cbc3434 100644
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -18,7 +18,6 @@
#include <linux/if_arp.h>
#include <linux/rtnetlink.h>
#include <net/mac80211.h>
-#include <net/iw_handler.h>
#include "ieee80211_i.h"
#include "driver-ops.h"
@@ -26,7 +25,7 @@
#define IEEE80211_PROBE_DELAY (HZ / 33)
#define IEEE80211_CHANNEL_TIME (HZ / 33)
-#define IEEE80211_PASSIVE_CHANNEL_TIME (HZ / 5)
+#define IEEE80211_PASSIVE_CHANNEL_TIME (HZ / 8)
struct ieee80211_bss *
ieee80211_rx_bss_get(struct ieee80211_local *local, u8 *bssid, int freq,
@@ -121,23 +120,10 @@ ieee80211_bss_info_update(struct ieee80211_local *local,
return bss;
}
-void ieee80211_rx_bss_remove(struct ieee80211_sub_if_data *sdata, u8 *bssid,
- int freq, u8 *ssid, u8 ssid_len)
-{
- struct ieee80211_bss *bss;
- struct ieee80211_local *local = sdata->local;
-
- bss = ieee80211_rx_bss_get(local, bssid, freq, ssid, ssid_len);
- if (bss) {
- cfg80211_unlink_bss(local->hw.wiphy, (void *)bss);
- ieee80211_rx_bss_put(local, bss);
- }
-}
-
ieee80211_rx_result
-ieee80211_scan_rx(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb,
- struct ieee80211_rx_status *rx_status)
+ieee80211_scan_rx(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb)
{
+ struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb);
struct ieee80211_mgmt *mgmt;
struct ieee80211_bss *bss;
u8 *elements;
@@ -278,7 +264,7 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted)
mutex_lock(&local->scan_mtx);
- if (WARN_ON(!local->hw_scanning && !local->sw_scanning)) {
+ if (WARN_ON(!local->scanning)) {
mutex_unlock(&local->scan_mtx);
return;
}
@@ -288,16 +274,15 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted)
return;
}
- if (local->hw_scanning)
+ if (test_bit(SCAN_HW_SCANNING, &local->scanning))
ieee80211_restore_scan_ies(local);
- if (local->scan_req != &local->int_scan_req)
+ if (local->scan_req != local->int_scan_req)
cfg80211_scan_done(local->scan_req, aborted);
local->scan_req = NULL;
- was_hw_scan = local->hw_scanning;
- local->hw_scanning = false;
- local->sw_scanning = false;
+ was_hw_scan = test_bit(SCAN_HW_SCANNING, &local->scanning);
+ local->scanning = 0;
local->scan_channel = NULL;
/* we only have to protect scan_req and hw/sw scan */
@@ -307,16 +292,13 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted)
if (was_hw_scan)
goto done;
- netif_tx_lock_bh(local->mdev);
- netif_addr_lock(local->mdev);
+ spin_lock_bh(&local->filter_lock);
local->filter_flags &= ~FIF_BCN_PRBRESP_PROMISC;
drv_configure_filter(local, FIF_BCN_PRBRESP_PROMISC,
&local->filter_flags,
- local->mdev->mc_count,
- local->mdev->mc_list);
-
- netif_addr_unlock(local->mdev);
- netif_tx_unlock_bh(local->mdev);
+ local->mc_count,
+ local->mc_list);
+ spin_unlock_bh(&local->filter_lock);
drv_sw_scan_complete(local);
@@ -327,7 +309,7 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted)
/* Tell AP we're back */
if (sdata->vif.type == NL80211_IFTYPE_STATION) {
- if (sdata->u.mgd.flags & IEEE80211_STA_ASSOCIATED) {
+ if (sdata->u.mgd.associated) {
ieee80211_scan_ps_disable(sdata);
netif_tx_wake_all_queues(sdata->dev);
}
@@ -382,30 +364,30 @@ static int ieee80211_start_sw_scan(struct ieee80211_local *local)
ieee80211_bss_info_change_notify(
sdata, BSS_CHANGED_BEACON_ENABLED);
- if (sdata->vif.type == NL80211_IFTYPE_STATION) {
- if (sdata->u.mgd.flags & IEEE80211_STA_ASSOCIATED) {
- netif_tx_stop_all_queues(sdata->dev);
- ieee80211_scan_ps_enable(sdata);
- }
- } else
+ /*
+ * only handle non-STA interfaces here, STA interfaces
+ * are handled in the scan state machine
+ */
+ if (sdata->vif.type != NL80211_IFTYPE_STATION)
netif_tx_stop_all_queues(sdata->dev);
}
mutex_unlock(&local->iflist_mtx);
- local->scan_state = SCAN_SET_CHANNEL;
+ local->next_scan_state = SCAN_DECISION;
local->scan_channel_idx = 0;
- netif_addr_lock_bh(local->mdev);
+ spin_lock_bh(&local->filter_lock);
local->filter_flags |= FIF_BCN_PRBRESP_PROMISC;
drv_configure_filter(local, FIF_BCN_PRBRESP_PROMISC,
&local->filter_flags,
- local->mdev->mc_count,
- local->mdev->mc_list);
- netif_addr_unlock_bh(local->mdev);
+ local->mc_count,
+ local->mc_list);
+ spin_unlock_bh(&local->filter_lock);
/* TODO: start scan as soon as all nullfunc frames are ACKed */
- queue_delayed_work(local->hw.workqueue, &local->scan_work,
- IEEE80211_CHANNEL_TIME);
+ ieee80211_queue_delayed_work(&local->hw,
+ &local->scan_work,
+ IEEE80211_CHANNEL_TIME);
return 0;
}
@@ -441,20 +423,18 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata,
local->scan_req = req;
local->scan_sdata = sdata;
- if (req != &local->int_scan_req &&
+ if (req != local->int_scan_req &&
sdata->vif.type == NL80211_IFTYPE_STATION &&
- (ifmgd->state == IEEE80211_STA_MLME_DIRECT_PROBE ||
- ifmgd->state == IEEE80211_STA_MLME_AUTHENTICATE ||
- ifmgd->state == IEEE80211_STA_MLME_ASSOCIATE)) {
- /* actually wait for the assoc to finish/time out */
+ !list_empty(&ifmgd->work_list)) {
+ /* actually wait for the work it's doing to finish/time out */
set_bit(IEEE80211_STA_REQ_SCAN, &ifmgd->request);
return 0;
}
if (local->ops->hw_scan)
- local->hw_scanning = true;
+ __set_bit(SCAN_HW_SCANNING, &local->scanning);
else
- local->sw_scanning = true;
+ __set_bit(SCAN_SW_SCANNING, &local->scanning);
/*
* Kicking off the scan need not be protected,
* only the scan variable stuff, since now
@@ -477,11 +457,9 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata,
mutex_lock(&local->scan_mtx);
if (rc) {
- if (local->ops->hw_scan) {
- local->hw_scanning = false;
+ if (local->ops->hw_scan)
ieee80211_restore_scan_ies(local);
- } else
- local->sw_scanning = false;
+ local->scanning = 0;
ieee80211_recalc_idle(local);
@@ -492,13 +470,195 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata,
return rc;
}
+static int ieee80211_scan_state_decision(struct ieee80211_local *local,
+ unsigned long *next_delay)
+{
+ bool associated = false;
+ struct ieee80211_sub_if_data *sdata;
+
+ /* if no more bands/channels left, complete scan and advance to the idle state */
+ if (local->scan_channel_idx >= local->scan_req->n_channels) {
+ ieee80211_scan_completed(&local->hw, false);
+ return 1;
+ }
+
+ /* check if at least one STA interface is associated */
+ mutex_lock(&local->iflist_mtx);
+ list_for_each_entry(sdata, &local->interfaces, list) {
+ if (!netif_running(sdata->dev))
+ continue;
+
+ if (sdata->vif.type == NL80211_IFTYPE_STATION) {
+ if (sdata->u.mgd.associated) {
+ associated = true;
+ break;
+ }
+ }
+ }
+ mutex_unlock(&local->iflist_mtx);
+
+ if (local->scan_channel) {
+ /*
+ * we're currently scanning a different channel, let's
+ * switch back to the operating channel now if at least
+ * one interface is associated. Otherwise just scan the
+ * next channel
+ */
+ if (associated)
+ local->next_scan_state = SCAN_ENTER_OPER_CHANNEL;
+ else
+ local->next_scan_state = SCAN_SET_CHANNEL;
+ } else {
+ /*
+ * we're on the operating channel currently, let's
+ * leave that channel now to scan another one
+ */
+ local->next_scan_state = SCAN_LEAVE_OPER_CHANNEL;
+ }
+
+ *next_delay = 0;
+ return 0;
+}
+
+static void ieee80211_scan_state_leave_oper_channel(struct ieee80211_local *local,
+ unsigned long *next_delay)
+{
+ struct ieee80211_sub_if_data *sdata;
+
+ /*
+ * notify the AP about us leaving the channel and stop all STA interfaces
+ */
+ mutex_lock(&local->iflist_mtx);
+ list_for_each_entry(sdata, &local->interfaces, list) {
+ if (!netif_running(sdata->dev))
+ continue;
+
+ if (sdata->vif.type == NL80211_IFTYPE_STATION) {
+ netif_tx_stop_all_queues(sdata->dev);
+ if (sdata->u.mgd.associated)
+ ieee80211_scan_ps_enable(sdata);
+ }
+ }
+ mutex_unlock(&local->iflist_mtx);
+
+ __set_bit(SCAN_OFF_CHANNEL, &local->scanning);
+
+ /* advance to the next channel to be scanned */
+ *next_delay = HZ / 10;
+ local->next_scan_state = SCAN_SET_CHANNEL;
+}
+
+static void ieee80211_scan_state_enter_oper_channel(struct ieee80211_local *local,
+ unsigned long *next_delay)
+{
+ struct ieee80211_sub_if_data *sdata = local->scan_sdata;
+
+ /* switch back to the operating channel */
+ local->scan_channel = NULL;
+ ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
+
+ /*
+ * notify the AP about us being back and restart all STA interfaces
+ */
+ mutex_lock(&local->iflist_mtx);
+ list_for_each_entry(sdata, &local->interfaces, list) {
+ if (!netif_running(sdata->dev))
+ continue;
+
+ /* Tell AP we're back */
+ if (sdata->vif.type == NL80211_IFTYPE_STATION) {
+ if (sdata->u.mgd.associated)
+ ieee80211_scan_ps_disable(sdata);
+ netif_tx_wake_all_queues(sdata->dev);
+ }
+ }
+ mutex_unlock(&local->iflist_mtx);
+
+ __clear_bit(SCAN_OFF_CHANNEL, &local->scanning);
+
+ *next_delay = HZ / 5;
+ local->next_scan_state = SCAN_DECISION;
+}
+
+static void ieee80211_scan_state_set_channel(struct ieee80211_local *local,
+ unsigned long *next_delay)
+{
+ int skip;
+ struct ieee80211_channel *chan;
+ struct ieee80211_sub_if_data *sdata = local->scan_sdata;
+
+ skip = 0;
+ chan = local->scan_req->channels[local->scan_channel_idx];
+
+ if (chan->flags & IEEE80211_CHAN_DISABLED ||
+ (sdata->vif.type == NL80211_IFTYPE_ADHOC &&
+ chan->flags & IEEE80211_CHAN_NO_IBSS))
+ skip = 1;
+
+ if (!skip) {
+ local->scan_channel = chan;
+ if (ieee80211_hw_config(local,
+ IEEE80211_CONF_CHANGE_CHANNEL))
+ skip = 1;
+ }
+
+ /* advance state machine to next channel/band */
+ local->scan_channel_idx++;
+
+ if (skip) {
+ /* if we skip this channel return to the decision state */
+ local->next_scan_state = SCAN_DECISION;
+ return;
+ }
+
+ /*
+ * Probe delay is used to update the NAV, cf. 11.1.3.2.2
+ * (which unfortunately doesn't say _why_ step a) is done,
+ * but it waits for the probe delay or until a frame is
+ * received - and the received frame would update the NAV).
+ * For now, we do not support waiting until a frame is
+ * received.
+ *
+ * In any case, it is not necessary for a passive scan.
+ */
+ if (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN ||
+ !local->scan_req->n_ssids) {
+ *next_delay = IEEE80211_PASSIVE_CHANNEL_TIME;
+ local->next_scan_state = SCAN_DECISION;
+ return;
+ }
+
+ /* active scan, send probes */
+ *next_delay = IEEE80211_PROBE_DELAY;
+ local->next_scan_state = SCAN_SEND_PROBE;
+}
+
+static void ieee80211_scan_state_send_probe(struct ieee80211_local *local,
+ unsigned long *next_delay)
+{
+ int i;
+ struct ieee80211_sub_if_data *sdata = local->scan_sdata;
+
+ for (i = 0; i < local->scan_req->n_ssids; i++)
+ ieee80211_send_probe_req(
+ sdata, NULL,
+ local->scan_req->ssids[i].ssid,
+ local->scan_req->ssids[i].ssid_len,
+ local->scan_req->ie, local->scan_req->ie_len);
+
+ /*
+ * After sending probe requests, wait for probe responses
+ * on the channel.
+ */
+ *next_delay = IEEE80211_CHANNEL_TIME;
+ local->next_scan_state = SCAN_DECISION;
+}
+
void ieee80211_scan_work(struct work_struct *work)
{
struct ieee80211_local *local =
container_of(work, struct ieee80211_local, scan_work.work);
struct ieee80211_sub_if_data *sdata = local->scan_sdata;
- struct ieee80211_channel *chan;
- int skip, i;
unsigned long next_delay = 0;
mutex_lock(&local->scan_mtx);
@@ -507,7 +667,7 @@ void ieee80211_scan_work(struct work_struct *work)
return;
}
- if (local->scan_req && !(local->sw_scanning || local->hw_scanning)) {
+ if (local->scan_req && !local->scanning) {
struct cfg80211_scan_request *req = local->scan_req;
int rc;
@@ -531,72 +691,32 @@ void ieee80211_scan_work(struct work_struct *work)
return;
}
- switch (local->scan_state) {
- case SCAN_SET_CHANNEL:
- /* if no more bands/channels left, complete scan */
- if (local->scan_channel_idx >= local->scan_req->n_channels) {
- ieee80211_scan_completed(&local->hw, false);
- return;
- }
- skip = 0;
- chan = local->scan_req->channels[local->scan_channel_idx];
-
- if (chan->flags & IEEE80211_CHAN_DISABLED ||
- (sdata->vif.type == NL80211_IFTYPE_ADHOC &&
- chan->flags & IEEE80211_CHAN_NO_IBSS))
- skip = 1;
-
- if (!skip) {
- local->scan_channel = chan;
- if (ieee80211_hw_config(local,
- IEEE80211_CONF_CHANGE_CHANNEL))
- skip = 1;
- }
-
- /* advance state machine to next channel/band */
- local->scan_channel_idx++;
-
- if (skip)
+ /*
+ * as long as no delay is required advance immediately
+ * without scheduling a new work
+ */
+ do {
+ switch (local->next_scan_state) {
+ case SCAN_DECISION:
+ if (ieee80211_scan_state_decision(local, &next_delay))
+ return;
break;
-
- /*
- * Probe delay is used to update the NAV, cf. 11.1.3.2.2
- * (which unfortunately doesn't say _why_ step a) is done,
- * but it waits for the probe delay or until a frame is
- * received - and the received frame would update the NAV).
- * For now, we do not support waiting until a frame is
- * received.
- *
- * In any case, it is not necessary for a passive scan.
- */
- if (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN ||
- !local->scan_req->n_ssids) {
- next_delay = IEEE80211_PASSIVE_CHANNEL_TIME;
+ case SCAN_SET_CHANNEL:
+ ieee80211_scan_state_set_channel(local, &next_delay);
+ break;
+ case SCAN_SEND_PROBE:
+ ieee80211_scan_state_send_probe(local, &next_delay);
+ break;
+ case SCAN_LEAVE_OPER_CHANNEL:
+ ieee80211_scan_state_leave_oper_channel(local, &next_delay);
+ break;
+ case SCAN_ENTER_OPER_CHANNEL:
+ ieee80211_scan_state_enter_oper_channel(local, &next_delay);
break;
}
+ } while (next_delay == 0);
- next_delay = IEEE80211_PROBE_DELAY;
- local->scan_state = SCAN_SEND_PROBE;
- break;
- case SCAN_SEND_PROBE:
- for (i = 0; i < local->scan_req->n_ssids; i++)
- ieee80211_send_probe_req(
- sdata, NULL,
- local->scan_req->ssids[i].ssid,
- local->scan_req->ssids[i].ssid_len,
- local->scan_req->ie, local->scan_req->ie_len);
-
- /*
- * After sending probe requests, wait for probe responses
- * on the channel.
- */
- next_delay = IEEE80211_CHANNEL_TIME;
- local->scan_state = SCAN_SET_CHANNEL;
- break;
- }
-
- queue_delayed_work(local->hw.workqueue, &local->scan_work,
- next_delay);
+ ieee80211_queue_delayed_work(&local->hw, &local->scan_work, next_delay);
}
int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata,
@@ -623,10 +743,10 @@ int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata,
if (local->scan_req)
goto unlock;
- memcpy(local->int_scan_req.ssids[0].ssid, ssid, IEEE80211_MAX_SSID_LEN);
- local->int_scan_req.ssids[0].ssid_len = ssid_len;
+ memcpy(local->int_scan_req->ssids[0].ssid, ssid, IEEE80211_MAX_SSID_LEN);
+ local->int_scan_req->ssids[0].ssid_len = ssid_len;
- ret = __ieee80211_start_scan(sdata, &sdata->local->int_scan_req);
+ ret = __ieee80211_start_scan(sdata, sdata->local->int_scan_req);
unlock:
mutex_unlock(&local->scan_mtx);
return ret;
@@ -643,7 +763,7 @@ void ieee80211_scan_cancel(struct ieee80211_local *local)
* queued -- mostly at suspend under RTNL.
*/
mutex_lock(&local->scan_mtx);
- swscan = local->sw_scanning;
+ swscan = test_bit(SCAN_SW_SCANNING, &local->scanning);
mutex_unlock(&local->scan_mtx);
if (swscan)
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index a360bceeba5..eec001491e6 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -349,6 +349,7 @@ int sta_info_insert(struct sta_info *sta)
goto out_free;
}
list_add(&sta->list, &local->sta_list);
+ local->sta_generation++;
local->num_sta++;
sta_info_hash_add(local, sta);
@@ -485,6 +486,7 @@ static void __sta_info_unlink(struct sta_info **sta)
}
local->num_sta--;
+ local->sta_generation++;
if (local->ops->sta_notify) {
if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index 49a1a1f7651..ccc3adf962c 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -30,7 +30,6 @@
* @WLAN_STA_ASSOC_AP: We're associated to that station, it is an AP.
* @WLAN_STA_WME: Station is a QoS-STA.
* @WLAN_STA_WDS: Station is one of our WDS peers.
- * @WLAN_STA_PSPOLL: Station has just PS-polled us.
* @WLAN_STA_CLEAR_PS_FILT: Clear PS filter in hardware (using the
* IEEE80211_TX_CTL_CLEAR_PS_FILT control flag) when the next
* frame to this station is transmitted.
@@ -47,7 +46,6 @@ enum ieee80211_sta_info_flags {
WLAN_STA_ASSOC_AP = 1<<5,
WLAN_STA_WME = 1<<6,
WLAN_STA_WDS = 1<<7,
- WLAN_STA_PSPOLL = 1<<8,
WLAN_STA_CLEAR_PS_FILT = 1<<9,
WLAN_STA_MFP = 1<<10,
WLAN_STA_SUSPEND = 1<<11
@@ -308,6 +306,23 @@ struct sta_info {
struct dentry *inactive_ms;
struct dentry *last_seq_ctrl;
struct dentry *agg_status;
+ struct dentry *aid;
+ struct dentry *dev;
+ struct dentry *rx_packets;
+ struct dentry *tx_packets;
+ struct dentry *rx_bytes;
+ struct dentry *tx_bytes;
+ struct dentry *rx_duplicates;
+ struct dentry *rx_fragments;
+ struct dentry *rx_dropped;
+ struct dentry *tx_fragments;
+ struct dentry *tx_filtered;
+ struct dentry *tx_retry_failed;
+ struct dentry *tx_retry_count;
+ struct dentry *last_signal;
+ struct dentry *last_qual;
+ struct dentry *last_noise;
+ struct dentry *wep_weak_iv_count;
bool add_has_run;
} debugfs;
#endif
@@ -342,17 +357,6 @@ static inline void clear_sta_flags(struct sta_info *sta, const u32 flags)
spin_unlock_irqrestore(&sta->flaglock, irqfl);
}
-static inline void set_and_clear_sta_flags(struct sta_info *sta,
- const u32 set, const u32 clear)
-{
- unsigned long irqfl;
-
- spin_lock_irqsave(&sta->flaglock, irqfl);
- sta->flags |= set;
- sta->flags &= ~clear;
- spin_unlock_irqrestore(&sta->flaglock, irqfl);
-}
-
static inline u32 test_sta_flags(struct sta_info *sta, const u32 flags)
{
u32 ret;
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 3a8922cd103..0c08d1e60cb 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -192,7 +192,7 @@ ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx)
if (unlikely(info->flags & IEEE80211_TX_CTL_INJECTED))
return TX_CONTINUE;
- if (unlikely(tx->local->sw_scanning) &&
+ if (unlikely(test_bit(SCAN_OFF_CHANNEL, &tx->local->scanning)) &&
!ieee80211_is_probe_req(hdr->frame_control) &&
!ieee80211_is_nullfunc(hdr->frame_control))
/*
@@ -317,30 +317,30 @@ ieee80211_tx_h_multicast_ps_buf(struct ieee80211_tx_data *tx)
if (!atomic_read(&tx->sdata->bss->num_sta_ps))
return TX_CONTINUE;
+ /* buffered in hardware */
+ if (!(tx->local->hw.flags & IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING)) {
+ info->flags |= IEEE80211_TX_CTL_SEND_AFTER_DTIM;
+
+ return TX_CONTINUE;
+ }
+
/* buffered in mac80211 */
- if (tx->local->hw.flags & IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING) {
- if (tx->local->total_ps_buffered >= TOTAL_MAX_TX_BUFFER)
- purge_old_ps_buffers(tx->local);
- if (skb_queue_len(&tx->sdata->bss->ps_bc_buf) >=
- AP_MAX_BC_BUFFER) {
+ if (tx->local->total_ps_buffered >= TOTAL_MAX_TX_BUFFER)
+ purge_old_ps_buffers(tx->local);
+
+ if (skb_queue_len(&tx->sdata->bss->ps_bc_buf) >= AP_MAX_BC_BUFFER) {
#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
- if (net_ratelimit()) {
- printk(KERN_DEBUG "%s: BC TX buffer full - "
- "dropping the oldest frame\n",
- tx->dev->name);
- }
+ if (net_ratelimit())
+ printk(KERN_DEBUG "%s: BC TX buffer full - dropping the oldest frame\n",
+ tx->dev->name);
#endif
- dev_kfree_skb(skb_dequeue(&tx->sdata->bss->ps_bc_buf));
- } else
- tx->local->total_ps_buffered++;
- skb_queue_tail(&tx->sdata->bss->ps_bc_buf, tx->skb);
- return TX_QUEUED;
- }
+ dev_kfree_skb(skb_dequeue(&tx->sdata->bss->ps_bc_buf));
+ } else
+ tx->local->total_ps_buffered++;
- /* buffered in hardware */
- info->flags |= IEEE80211_TX_CTL_SEND_AFTER_DTIM;
+ skb_queue_tail(&tx->sdata->bss->ps_bc_buf, tx->skb);
- return TX_CONTINUE;
+ return TX_QUEUED;
}
static int ieee80211_use_mfp(__le16 fc, struct sta_info *sta,
@@ -373,7 +373,7 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx)
staflags = get_sta_flags(sta);
if (unlikely((staflags & WLAN_STA_PS) &&
- !(staflags & WLAN_STA_PSPOLL))) {
+ !(info->flags & IEEE80211_TX_CTL_PSPOLL_RESPONSE))) {
#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
printk(KERN_DEBUG "STA %pM aid %d: PS buffer (entries "
"before %d)\n",
@@ -400,6 +400,7 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx)
sta_info_set_tim_bit(sta);
info->control.jiffies = jiffies;
+ info->control.vif = &tx->sdata->vif;
info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING;
skb_queue_tail(&sta->ps_tx_buf, tx->skb);
return TX_QUEUED;
@@ -411,24 +412,7 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx)
sta->sta.addr);
}
#endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
- if (test_and_clear_sta_flags(sta, WLAN_STA_PSPOLL)) {
- /*
- * The sleeping station with pending data is now snoozing.
- * It queried us for its buffered frames and will go back
- * to deep sleep once it got everything.
- *
- * inform the driver, in case the hardware does powersave
- * frame filtering and keeps a station blacklist on its own
- * (e.g: p54), so that frames can be delivered unimpeded.
- *
- * Note: It should be safe to disable the filter now.
- * As, it is really unlikely that we still have any pending
- * frame for this station in the hw's buffers/fifos left,
- * that is not rejected with a unsuccessful tx_status yet.
- */
- info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT;
- }
return TX_CONTINUE;
}
@@ -451,7 +435,7 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx)
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data;
- if (unlikely(tx->skb->do_not_encrypt))
+ if (unlikely(info->flags & IEEE80211_TX_INTFL_DONT_ENCRYPT))
tx->key = NULL;
else if (tx->sta && (key = rcu_dereference(tx->sta->key)))
tx->key = key;
@@ -497,7 +481,7 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx)
}
if (!tx->key || !(tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE))
- tx->skb->do_not_encrypt = 1;
+ info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
return TX_CONTINUE;
}
@@ -512,6 +496,7 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx)
int i, len;
bool inval = false, rts = false, short_preamble = false;
struct ieee80211_tx_rate_control txrc;
+ u32 sta_flags;
memset(&txrc, 0, sizeof(txrc));
@@ -544,7 +529,26 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx)
(tx->sta && test_sta_flags(tx->sta, WLAN_STA_SHORT_PREAMBLE))))
txrc.short_preamble = short_preamble = true;
+ sta_flags = tx->sta ? get_sta_flags(tx->sta) : 0;
+
+ /*
+ * Lets not bother rate control if we're associated and cannot
+ * talk to the sta. This should not happen.
+ */
+ if (WARN(test_bit(SCAN_SW_SCANNING, &tx->local->scanning) &&
+ (sta_flags & WLAN_STA_ASSOC) &&
+ !rate_usable_index_exists(sband, &tx->sta->sta),
+ "%s: Dropped data frame as no usable bitrate found while "
+ "scanning and associated. Target station: "
+ "%pM on %d GHz band\n",
+ tx->dev->name, hdr->addr1,
+ tx->channel->band ? 5 : 2))
+ return TX_DROP;
+ /*
+ * If we're associated with the sta at this point we know we can at
+ * least send the frame at the lowest bit rate.
+ */
rate_control_get_rate(tx->sdata, tx->sta, &txrc);
if (unlikely(info->control.rates[0].idx < 0))
@@ -676,7 +680,7 @@ ieee80211_tx_h_sequence(struct ieee80211_tx_data *tx)
* number, if we have no matching interface then we
* neither assign one ourselves nor ask the driver to.
*/
- if (unlikely(!info->control.vif))
+ if (unlikely(info->control.vif->type == NL80211_IFTYPE_MONITOR))
return TX_CONTINUE;
if (unlikely(ieee80211_is_ctl(hdr->frame_control)))
@@ -696,7 +700,6 @@ ieee80211_tx_h_sequence(struct ieee80211_tx_data *tx)
/* for pure STA mode without beacons, we can do it */
hdr->seq_ctrl = cpu_to_le16(tx->sdata->sequence_number);
tx->sdata->sequence_number += 0x10;
- tx->sdata->sequence_number &= IEEE80211_SCTL_SEQ;
return TX_CONTINUE;
}
@@ -754,9 +757,7 @@ static int ieee80211_fragment(struct ieee80211_local *local,
memcpy(tmp->cb, skb->cb, sizeof(tmp->cb));
skb_copy_queue_mapping(tmp, skb);
tmp->priority = skb->priority;
- tmp->do_not_encrypt = skb->do_not_encrypt;
tmp->dev = skb->dev;
- tmp->iif = skb->iif;
/* copy header and data */
memcpy(skb_put(tmp, hdrlen), skb->data, hdrlen);
@@ -784,7 +785,7 @@ ieee80211_tx_h_fragment(struct ieee80211_tx_data *tx)
/*
* Warn when submitting a fragmented A-MPDU frame and drop it.
- * This scenario is handled in __ieee80211_tx_prepare but extra
+ * This scenario is handled in ieee80211_tx_prepare but extra
* caution taken here as fragmented ampdu may cause Tx stop.
*/
if (WARN_ON(info->flags & IEEE80211_TX_CTL_AMPDU))
@@ -842,6 +843,23 @@ ieee80211_tx_h_fragment(struct ieee80211_tx_data *tx)
}
static ieee80211_tx_result debug_noinline
+ieee80211_tx_h_stats(struct ieee80211_tx_data *tx)
+{
+ struct sk_buff *skb = tx->skb;
+
+ if (!tx->sta)
+ return TX_CONTINUE;
+
+ tx->sta->tx_packets++;
+ do {
+ tx->sta->tx_fragments++;
+ tx->sta->tx_bytes += skb->len;
+ } while ((skb = skb->next));
+
+ return TX_CONTINUE;
+}
+
+static ieee80211_tx_result debug_noinline
ieee80211_tx_h_encrypt(struct ieee80211_tx_data *tx)
{
if (!tx->key)
@@ -885,23 +903,6 @@ ieee80211_tx_h_calculate_duration(struct ieee80211_tx_data *tx)
return TX_CONTINUE;
}
-static ieee80211_tx_result debug_noinline
-ieee80211_tx_h_stats(struct ieee80211_tx_data *tx)
-{
- struct sk_buff *skb = tx->skb;
-
- if (!tx->sta)
- return TX_CONTINUE;
-
- tx->sta->tx_packets++;
- do {
- tx->sta->tx_fragments++;
- tx->sta->tx_bytes += skb->len;
- } while ((skb = skb->next));
-
- return TX_CONTINUE;
-}
-
/* actual transmit path */
/*
@@ -923,11 +924,12 @@ static bool __ieee80211_parse_tx_radiotap(struct ieee80211_tx_data *tx,
struct ieee80211_radiotap_header *rthdr =
(struct ieee80211_radiotap_header *) skb->data;
struct ieee80211_supported_band *sband;
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
int ret = ieee80211_radiotap_iterator_init(&iterator, rthdr, skb->len);
sband = tx->local->hw.wiphy->bands[tx->channel->band];
- skb->do_not_encrypt = 1;
+ info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
tx->flags &= ~IEEE80211_TX_FRAGMENTED;
/*
@@ -965,7 +967,7 @@ static bool __ieee80211_parse_tx_radiotap(struct ieee80211_tx_data *tx,
skb_trim(skb, skb->len - FCS_LEN);
}
if (*iterator.this_arg & IEEE80211_RADIOTAP_F_WEP)
- tx->skb->do_not_encrypt = 0;
+ info->flags &= ~IEEE80211_TX_INTFL_DONT_ENCRYPT;
if (*iterator.this_arg & IEEE80211_RADIOTAP_F_FRAG)
tx->flags |= IEEE80211_TX_FRAGMENTED;
break;
@@ -998,13 +1000,12 @@ static bool __ieee80211_parse_tx_radiotap(struct ieee80211_tx_data *tx,
* initialises @tx
*/
static ieee80211_tx_result
-__ieee80211_tx_prepare(struct ieee80211_tx_data *tx,
- struct sk_buff *skb,
- struct net_device *dev)
+ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata,
+ struct ieee80211_tx_data *tx,
+ struct sk_buff *skb)
{
- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+ struct ieee80211_local *local = sdata->local;
struct ieee80211_hdr *hdr;
- struct ieee80211_sub_if_data *sdata;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
int hdrlen, tid;
u8 *qc, *state;
@@ -1012,9 +1013,9 @@ __ieee80211_tx_prepare(struct ieee80211_tx_data *tx,
memset(tx, 0, sizeof(*tx));
tx->skb = skb;
- tx->dev = dev; /* use original interface */
+ tx->dev = sdata->dev; /* use original interface */
tx->local = local;
- tx->sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+ tx->sdata = sdata;
tx->channel = local->hw.conf.channel;
/*
* Set this flag (used below to indicate "automatic fragmentation"),
@@ -1023,7 +1024,6 @@ __ieee80211_tx_prepare(struct ieee80211_tx_data *tx,
tx->flags |= IEEE80211_TX_FRAGMENTED;
/* process and remove the injection radiotap header */
- sdata = IEEE80211_DEV_TO_SUB_IF(dev);
if (unlikely(info->flags & IEEE80211_TX_CTL_INJECTED)) {
if (!__ieee80211_parse_tx_radiotap(tx, skb))
return TX_DROP;
@@ -1075,6 +1075,7 @@ __ieee80211_tx_prepare(struct ieee80211_tx_data *tx,
} else if (*state != HT_AGG_STATE_IDLE) {
/* in progress */
queued = true;
+ info->control.vif = &sdata->vif;
info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING;
__skb_queue_tail(&tid_tx->pending, skb);
}
@@ -1119,50 +1120,29 @@ __ieee80211_tx_prepare(struct ieee80211_tx_data *tx,
return TX_CONTINUE;
}
-/*
- * NB: @tx is uninitialised when passed in here
- */
-static int ieee80211_tx_prepare(struct ieee80211_local *local,
- struct ieee80211_tx_data *tx,
- struct sk_buff *skb)
-{
- struct net_device *dev;
-
- dev = dev_get_by_index(&init_net, skb->iif);
- if (unlikely(dev && !is_ieee80211_device(local, dev))) {
- dev_put(dev);
- dev = NULL;
- }
- if (unlikely(!dev))
- return -ENODEV;
- /*
- * initialises tx with control
- *
- * return value is safe to ignore here because this function
- * can only be invoked for multicast frames
- *
- * XXX: clean up
- */
- __ieee80211_tx_prepare(tx, skb, dev);
- dev_put(dev);
- return 0;
-}
-
static int __ieee80211_tx(struct ieee80211_local *local,
struct sk_buff **skbp,
- struct sta_info *sta)
+ struct sta_info *sta,
+ bool txpending)
{
struct sk_buff *skb = *skbp, *next;
struct ieee80211_tx_info *info;
+ struct ieee80211_sub_if_data *sdata;
+ unsigned long flags;
int ret, len;
bool fragm = false;
- local->mdev->trans_start = jiffies;
-
while (skb) {
- if (ieee80211_queue_stopped(&local->hw,
- skb_get_queue_mapping(skb)))
- return IEEE80211_TX_PENDING;
+ int q = skb_get_queue_mapping(skb);
+
+ spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
+ ret = IEEE80211_TX_OK;
+ if (local->queue_stop_reasons[q] ||
+ (!txpending && !skb_queue_empty(&local->pending[q])))
+ ret = IEEE80211_TX_PENDING;
+ spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
+ if (ret != IEEE80211_TX_OK)
+ return ret;
info = IEEE80211_SKB_CB(skb);
@@ -1172,13 +1152,35 @@ static int __ieee80211_tx(struct ieee80211_local *local,
next = skb->next;
len = skb->len;
+
+ if (next)
+ info->flags |= IEEE80211_TX_CTL_MORE_FRAMES;
+
+ sdata = vif_to_sdata(info->control.vif);
+
+ switch (sdata->vif.type) {
+ case NL80211_IFTYPE_MONITOR:
+ info->control.vif = NULL;
+ break;
+ case NL80211_IFTYPE_AP_VLAN:
+ info->control.vif = &container_of(sdata->bss,
+ struct ieee80211_sub_if_data, u.ap)->vif;
+ break;
+ default:
+ /* keep */
+ break;
+ }
+
ret = drv_tx(local, skb);
if (WARN_ON(ret != NETDEV_TX_OK && skb->len != len)) {
dev_kfree_skb(skb);
ret = NETDEV_TX_OK;
}
- if (ret != NETDEV_TX_OK)
+ if (ret != NETDEV_TX_OK) {
+ info->control.vif = &sdata->vif;
return IEEE80211_TX_AGAIN;
+ }
+
*skbp = skb = next;
ieee80211_led_tx(local, 1);
fragm = true;
@@ -1210,9 +1212,9 @@ static int invoke_tx_handlers(struct ieee80211_tx_data *tx)
CALL_TXH(ieee80211_tx_h_sequence)
CALL_TXH(ieee80211_tx_h_fragment)
/* handlers after fragment must be aware of tx info fragmentation! */
+ CALL_TXH(ieee80211_tx_h_stats)
CALL_TXH(ieee80211_tx_h_encrypt)
CALL_TXH(ieee80211_tx_h_calculate_duration)
- CALL_TXH(ieee80211_tx_h_stats)
#undef CALL_TXH
txh_done:
@@ -1234,10 +1236,10 @@ static int invoke_tx_handlers(struct ieee80211_tx_data *tx)
return 0;
}
-static void ieee80211_tx(struct net_device *dev, struct sk_buff *skb,
- bool txpending)
+static void ieee80211_tx(struct ieee80211_sub_if_data *sdata,
+ struct sk_buff *skb, bool txpending)
{
- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+ struct ieee80211_local *local = sdata->local;
struct ieee80211_tx_data tx;
ieee80211_tx_result res_prepare;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
@@ -1248,8 +1250,6 @@ static void ieee80211_tx(struct net_device *dev, struct sk_buff *skb,
queue = skb_get_queue_mapping(skb);
- WARN_ON(!txpending && !skb_queue_empty(&local->pending[queue]));
-
if (unlikely(skb->len < 10)) {
dev_kfree_skb(skb);
return;
@@ -1258,7 +1258,7 @@ static void ieee80211_tx(struct net_device *dev, struct sk_buff *skb,
rcu_read_lock();
/* initialises tx */
- res_prepare = __ieee80211_tx_prepare(&tx, skb, dev);
+ res_prepare = ieee80211_tx_prepare(sdata, &tx, skb);
if (unlikely(res_prepare == TX_DROP)) {
dev_kfree_skb(skb);
@@ -1277,7 +1277,7 @@ static void ieee80211_tx(struct net_device *dev, struct sk_buff *skb,
retries = 0;
retry:
- ret = __ieee80211_tx(local, &tx.skb, tx.sta);
+ ret = __ieee80211_tx(local, &tx.skb, tx.sta, txpending);
switch (ret) {
case IEEE80211_TX_OK:
break;
@@ -1295,34 +1295,35 @@ static void ieee80211_tx(struct net_device *dev, struct sk_buff *skb,
spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
- if (__netif_subqueue_stopped(local->mdev, queue)) {
+ if (local->queue_stop_reasons[queue] ||
+ !skb_queue_empty(&local->pending[queue])) {
+ /*
+ * if queue is stopped, queue up frames for later
+ * transmission from the tasklet
+ */
do {
next = skb->next;
skb->next = NULL;
if (unlikely(txpending))
- skb_queue_head(&local->pending[queue],
- skb);
+ __skb_queue_head(&local->pending[queue],
+ skb);
else
- skb_queue_tail(&local->pending[queue],
- skb);
+ __skb_queue_tail(&local->pending[queue],
+ skb);
} while ((skb = next));
- /*
- * Make sure nobody will enable the queue on us
- * (without going through the tasklet) nor disable the
- * netdev queue underneath the pending handling code.
- */
- __set_bit(IEEE80211_QUEUE_STOP_REASON_PENDING,
- &local->queue_stop_reasons[queue]);
-
spin_unlock_irqrestore(&local->queue_stop_reason_lock,
flags);
} else {
+ /*
+ * otherwise retry, but this is a race condition or
+ * a driver bug (which we warn about if it persists)
+ */
spin_unlock_irqrestore(&local->queue_stop_reason_lock,
flags);
retries++;
- if (WARN(retries > 10, "tx refused but queue active"))
+ if (WARN(retries > 10, "tx refused but queue active\n"))
goto drop;
goto retry;
}
@@ -1383,44 +1384,25 @@ static int ieee80211_skb_resize(struct ieee80211_local *local,
return 0;
}
-int ieee80211_master_start_xmit(struct sk_buff *skb, struct net_device *dev)
+static void ieee80211_xmit(struct ieee80211_sub_if_data *sdata,
+ struct sk_buff *skb)
{
- struct ieee80211_master_priv *mpriv = netdev_priv(dev);
- struct ieee80211_local *local = mpriv->local;
+ struct ieee80211_local *local = sdata->local;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
- struct net_device *odev = NULL;
- struct ieee80211_sub_if_data *osdata;
+ struct ieee80211_sub_if_data *tmp_sdata;
int headroom;
bool may_encrypt;
- enum {
- NOT_MONITOR,
- FOUND_SDATA,
- UNKNOWN_ADDRESS,
- } monitor_iface = NOT_MONITOR;
-
- if (skb->iif)
- odev = dev_get_by_index(&init_net, skb->iif);
- if (unlikely(odev && !is_ieee80211_device(local, odev))) {
- dev_put(odev);
- odev = NULL;
- }
- if (unlikely(!odev)) {
-#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
- printk(KERN_DEBUG "%s: Discarded packet with nonexistent "
- "originating device\n", dev->name);
-#endif
- dev_kfree_skb(skb);
- return NETDEV_TX_OK;
- }
+
+ dev_hold(sdata->dev);
if ((local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) &&
local->hw.conf.dynamic_ps_timeout > 0 &&
- !local->sw_scanning && !local->hw_scanning && local->ps_sdata) {
+ !(local->scanning) && local->ps_sdata) {
if (local->hw.conf.flags & IEEE80211_CONF_PS) {
ieee80211_stop_queues_by_reason(&local->hw,
IEEE80211_QUEUE_STOP_REASON_PS);
- queue_work(local->hw.workqueue,
+ ieee80211_queue_work(&local->hw,
&local->dynamic_ps_disable_work);
}
@@ -1428,31 +1410,13 @@ int ieee80211_master_start_xmit(struct sk_buff *skb, struct net_device *dev)
msecs_to_jiffies(local->hw.conf.dynamic_ps_timeout));
}
- memset(info, 0, sizeof(*info));
-
info->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS;
- osdata = IEEE80211_DEV_TO_SUB_IF(odev);
-
- if (ieee80211_vif_is_mesh(&osdata->vif) &&
- ieee80211_is_data(hdr->frame_control)) {
- if (is_multicast_ether_addr(hdr->addr3))
- memcpy(hdr->addr1, hdr->addr3, ETH_ALEN);
- else
- if (mesh_nexthop_lookup(skb, osdata)) {
- dev_put(odev);
- return NETDEV_TX_OK;
- }
- if (memcmp(odev->dev_addr, hdr->addr4, ETH_ALEN) != 0)
- IEEE80211_IFSTA_MESH_CTR_INC(&osdata->u.mesh,
- fwded_frames);
- } else if (unlikely(osdata->vif.type == NL80211_IFTYPE_MONITOR)) {
- struct ieee80211_sub_if_data *sdata;
+ if (unlikely(sdata->vif.type == NL80211_IFTYPE_MONITOR)) {
int hdrlen;
u16 len_rthdr;
info->flags |= IEEE80211_TX_CTL_INJECTED;
- monitor_iface = UNKNOWN_ADDRESS;
len_rthdr = ieee80211_get_radiotap_len(skb->data);
hdr = (struct ieee80211_hdr *)(skb->data + len_rthdr);
@@ -1471,20 +1435,17 @@ int ieee80211_master_start_xmit(struct sk_buff *skb, struct net_device *dev)
*/
rcu_read_lock();
- list_for_each_entry_rcu(sdata, &local->interfaces,
+ list_for_each_entry_rcu(tmp_sdata, &local->interfaces,
list) {
- if (!netif_running(sdata->dev))
+ if (!netif_running(tmp_sdata->dev))
continue;
- if (sdata->vif.type != NL80211_IFTYPE_AP)
+ if (tmp_sdata->vif.type != NL80211_IFTYPE_AP)
continue;
- if (compare_ether_addr(sdata->dev->dev_addr,
+ if (compare_ether_addr(tmp_sdata->dev->dev_addr,
hdr->addr2)) {
- dev_hold(sdata->dev);
- dev_put(odev);
- osdata = sdata;
- odev = osdata->dev;
- skb->iif = sdata->dev->ifindex;
- monitor_iface = FOUND_SDATA;
+ dev_hold(tmp_sdata->dev);
+ dev_put(sdata->dev);
+ sdata = tmp_sdata;
break;
}
}
@@ -1492,31 +1453,34 @@ int ieee80211_master_start_xmit(struct sk_buff *skb, struct net_device *dev)
}
}
- may_encrypt = !skb->do_not_encrypt;
+ may_encrypt = !(info->flags & IEEE80211_TX_INTFL_DONT_ENCRYPT);
- headroom = osdata->local->tx_headroom;
+ headroom = local->tx_headroom;
if (may_encrypt)
headroom += IEEE80211_ENCRYPT_HEADROOM;
headroom -= skb_headroom(skb);
headroom = max_t(int, 0, headroom);
- if (ieee80211_skb_resize(osdata->local, skb, headroom, may_encrypt)) {
+ if (ieee80211_skb_resize(local, skb, headroom, may_encrypt)) {
dev_kfree_skb(skb);
- dev_put(odev);
- return NETDEV_TX_OK;
+ dev_put(sdata->dev);
+ return;
}
- if (osdata->vif.type == NL80211_IFTYPE_AP_VLAN)
- osdata = container_of(osdata->bss,
- struct ieee80211_sub_if_data,
- u.ap);
- if (likely(monitor_iface != UNKNOWN_ADDRESS))
- info->control.vif = &osdata->vif;
+ info->control.vif = &sdata->vif;
- ieee80211_tx(odev, skb, false);
- dev_put(odev);
+ if (ieee80211_vif_is_mesh(&sdata->vif) &&
+ ieee80211_is_data(hdr->frame_control) &&
+ !is_multicast_ether_addr(hdr->addr1))
+ if (mesh_nexthop_lookup(skb, sdata)) {
+ /* skb queued: don't free */
+ dev_put(sdata->dev);
+ return;
+ }
- return NETDEV_TX_OK;
+ ieee80211_select_queue(local, skb);
+ ieee80211_tx(sdata, skb, false);
+ dev_put(sdata->dev);
}
int ieee80211_monitor_start_xmit(struct sk_buff *skb,
@@ -1526,6 +1490,7 @@ int ieee80211_monitor_start_xmit(struct sk_buff *skb,
struct ieee80211_channel *chan = local->hw.conf.channel;
struct ieee80211_radiotap_header *prthdr =
(struct ieee80211_radiotap_header *)skb->data;
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
u16 len_rthdr;
/*
@@ -1563,15 +1528,6 @@ int ieee80211_monitor_start_xmit(struct sk_buff *skb,
if (unlikely(skb->len < len_rthdr))
goto fail; /* skb too short for claimed rt header extent */
- skb->dev = local->mdev;
-
- /* needed because we set skb device to master */
- skb->iif = dev->ifindex;
-
- /* sometimes we do encrypt injected frames, will be fixed
- * up in radiotap parser if not wanted */
- skb->do_not_encrypt = 0;
-
/*
* fix up the pointers accounting for the radiotap
* header still being in there. We are being given
@@ -1586,8 +1542,10 @@ int ieee80211_monitor_start_xmit(struct sk_buff *skb,
skb_set_network_header(skb, len_rthdr);
skb_set_transport_header(skb, len_rthdr);
- /* pass the radiotap header up to the next stage intact */
- dev_queue_xmit(skb);
+ memset(info, 0, sizeof(*info));
+
+ /* pass the radiotap header up to xmit */
+ ieee80211_xmit(IEEE80211_DEV_TO_SUB_IF(dev), skb);
return NETDEV_TX_OK;
fail:
@@ -1615,6 +1573,7 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb,
{
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
struct ieee80211_local *local = sdata->local;
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
int ret = NETDEV_TX_BUSY, head_need;
u16 ethertype, hdrlen, meshhdrlen = 0;
__le16 fc;
@@ -1627,7 +1586,7 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb,
u32 sta_flags = 0;
if (unlikely(skb->len < ETH_HLEN)) {
- ret = 0;
+ ret = NETDEV_TX_OK;
goto fail;
}
@@ -1660,52 +1619,58 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb,
break;
#ifdef CONFIG_MAC80211_MESH
case NL80211_IFTYPE_MESH_POINT:
- fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS);
if (!sdata->u.mesh.mshcfg.dot11MeshTTL) {
/* Do not send frames with mesh_ttl == 0 */
sdata->u.mesh.mshstats.dropped_frames_ttl++;
- ret = 0;
+ ret = NETDEV_TX_OK;
goto fail;
}
- memset(&mesh_hdr, 0, sizeof(mesh_hdr));
if (compare_ether_addr(dev->dev_addr,
skb->data + ETH_ALEN) == 0) {
- /* RA TA DA SA */
- memset(hdr.addr1, 0, ETH_ALEN);
- memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN);
- memcpy(hdr.addr3, skb->data, ETH_ALEN);
- memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN);
- meshhdrlen = ieee80211_new_mesh_header(&mesh_hdr, sdata);
+ hdrlen = ieee80211_fill_mesh_addresses(&hdr, &fc,
+ skb->data, skb->data + ETH_ALEN);
+ meshhdrlen = ieee80211_new_mesh_header(&mesh_hdr,
+ sdata, NULL, NULL, NULL);
} else {
/* packet from other interface */
struct mesh_path *mppath;
+ int is_mesh_mcast = 1;
+ char *mesh_da;
- memset(hdr.addr1, 0, ETH_ALEN);
- memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN);
- memcpy(hdr.addr4, dev->dev_addr, ETH_ALEN);
-
+ rcu_read_lock();
if (is_multicast_ether_addr(skb->data))
- memcpy(hdr.addr3, skb->data, ETH_ALEN);
+ /* DA TA mSA AE:SA */
+ mesh_da = skb->data;
else {
- rcu_read_lock();
mppath = mpp_path_lookup(skb->data, sdata);
- if (mppath)
- memcpy(hdr.addr3, mppath->mpp, ETH_ALEN);
- else
- memset(hdr.addr3, 0xff, ETH_ALEN);
- rcu_read_unlock();
+ if (mppath) {
+ /* RA TA mDA mSA AE:DA SA */
+ mesh_da = mppath->mpp;
+ is_mesh_mcast = 0;
+ } else
+ /* DA TA mSA AE:SA */
+ mesh_da = dev->broadcast;
}
+ hdrlen = ieee80211_fill_mesh_addresses(&hdr, &fc,
+ mesh_da, dev->dev_addr);
+ rcu_read_unlock();
+ if (is_mesh_mcast)
+ meshhdrlen =
+ ieee80211_new_mesh_header(&mesh_hdr,
+ sdata,
+ skb->data + ETH_ALEN,
+ NULL,
+ NULL);
+ else
+ meshhdrlen =
+ ieee80211_new_mesh_header(&mesh_hdr,
+ sdata,
+ NULL,
+ skb->data,
+ skb->data + ETH_ALEN);
- mesh_hdr.flags |= MESH_FLAGS_AE_A5_A6;
- mesh_hdr.ttl = sdata->u.mesh.mshcfg.dot11MeshTTL;
- put_unaligned(cpu_to_le32(sdata->u.mesh.mesh_seqnum), &mesh_hdr.seqnum);
- memcpy(mesh_hdr.eaddr1, skb->data, ETH_ALEN);
- memcpy(mesh_hdr.eaddr2, skb->data + ETH_ALEN, ETH_ALEN);
- sdata->u.mesh.mesh_seqnum++;
- meshhdrlen = 18;
}
- hdrlen = 30;
break;
#endif
case NL80211_IFTYPE_STATION:
@@ -1724,7 +1689,7 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb,
hdrlen = 24;
break;
default:
- ret = 0;
+ ret = NETDEV_TX_OK;
goto fail;
}
@@ -1766,7 +1731,7 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb,
I802_DEBUG_INC(local->tx_handlers_drop_unauth_port);
- ret = 0;
+ ret = NETDEV_TX_OK;
goto fail;
}
@@ -1842,9 +1807,6 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb,
nh_pos += hdrlen;
h_pos += hdrlen;
- skb->iif = dev->ifindex;
-
- skb->dev = local->mdev;
dev->stats.tx_packets++;
dev->stats.tx_bytes += skb->len;
@@ -1855,13 +1817,15 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb,
skb_set_network_header(skb, nh_pos);
skb_set_transport_header(skb, h_pos);
+ memset(info, 0, sizeof(*info));
+
dev->trans_start = jiffies;
- dev_queue_xmit(skb);
+ ieee80211_xmit(sdata, skb);
- return 0;
+ return NETDEV_TX_OK;
fail:
- if (!ret)
+ if (ret == NETDEV_TX_OK)
dev_kfree_skb(skb);
return ret;
@@ -1887,101 +1851,74 @@ static bool ieee80211_tx_pending_skb(struct ieee80211_local *local,
struct ieee80211_sub_if_data *sdata;
struct sta_info *sta;
struct ieee80211_hdr *hdr;
- struct net_device *dev;
int ret;
bool result = true;
- /* does interface still exist? */
- dev = dev_get_by_index(&init_net, skb->iif);
- if (!dev) {
- dev_kfree_skb(skb);
- return true;
- }
-
- /* validate info->control.vif against skb->iif */
- sdata = IEEE80211_DEV_TO_SUB_IF(dev);
- if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
- sdata = container_of(sdata->bss,
- struct ieee80211_sub_if_data,
- u.ap);
-
- if (unlikely(info->control.vif && info->control.vif != &sdata->vif)) {
- dev_kfree_skb(skb);
- result = true;
- goto out;
- }
+ sdata = vif_to_sdata(info->control.vif);
if (info->flags & IEEE80211_TX_INTFL_NEED_TXPROCESSING) {
- ieee80211_tx(dev, skb, true);
+ ieee80211_tx(sdata, skb, true);
} else {
hdr = (struct ieee80211_hdr *)skb->data;
sta = sta_info_get(local, hdr->addr1);
- ret = __ieee80211_tx(local, &skb, sta);
+ ret = __ieee80211_tx(local, &skb, sta, true);
if (ret != IEEE80211_TX_OK)
result = false;
}
- out:
- dev_put(dev);
-
return result;
}
/*
- * Transmit all pending packets. Called from tasklet, locks master device
- * TX lock so that no new packets can come in.
+ * Transmit all pending packets. Called from tasklet.
*/
void ieee80211_tx_pending(unsigned long data)
{
struct ieee80211_local *local = (struct ieee80211_local *)data;
- struct net_device *dev = local->mdev;
unsigned long flags;
int i;
- bool next;
+ bool txok;
rcu_read_lock();
- netif_tx_lock_bh(dev);
+ spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
for (i = 0; i < local->hw.queues; i++) {
/*
* If queue is stopped by something other than due to pending
* frames, or we have no pending frames, proceed to next queue.
*/
- spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
- next = false;
- if (local->queue_stop_reasons[i] !=
- BIT(IEEE80211_QUEUE_STOP_REASON_PENDING) ||
+ if (local->queue_stop_reasons[i] ||
skb_queue_empty(&local->pending[i]))
- next = true;
- spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
-
- if (next)
continue;
- /*
- * start the queue now to allow processing our packets,
- * we're under the tx lock here anyway so nothing will
- * happen as a result of this
- */
- netif_start_subqueue(local->mdev, i);
-
while (!skb_queue_empty(&local->pending[i])) {
- struct sk_buff *skb = skb_dequeue(&local->pending[i]);
+ struct sk_buff *skb = __skb_dequeue(&local->pending[i]);
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+ struct ieee80211_sub_if_data *sdata;
- if (!ieee80211_tx_pending_skb(local, skb)) {
- skb_queue_head(&local->pending[i], skb);
- break;
+ if (WARN_ON(!info->control.vif)) {
+ kfree_skb(skb);
+ continue;
}
- }
- /* Start regular packet processing again. */
- if (skb_queue_empty(&local->pending[i]))
- ieee80211_wake_queue_by_reason(&local->hw, i,
- IEEE80211_QUEUE_STOP_REASON_PENDING);
+ sdata = vif_to_sdata(info->control.vif);
+ dev_hold(sdata->dev);
+ spin_unlock_irqrestore(&local->queue_stop_reason_lock,
+ flags);
+
+ txok = ieee80211_tx_pending_skb(local, skb);
+ dev_put(sdata->dev);
+ if (!txok)
+ __skb_queue_head(&local->pending[i], skb);
+ spin_lock_irqsave(&local->queue_stop_reason_lock,
+ flags);
+ if (!txok)
+ break;
+ }
}
+ spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
- netif_tx_unlock_bh(dev);
rcu_read_unlock();
}
@@ -2156,8 +2093,7 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw,
info = IEEE80211_SKB_CB(skb);
- skb->do_not_encrypt = 1;
-
+ info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
info->band = band;
/*
* XXX: For now, always use the lowest rate
@@ -2228,9 +2164,6 @@ ieee80211_get_buffered_bc(struct ieee80211_hw *hw,
sdata = vif_to_sdata(vif);
bss = &sdata->u.ap;
- if (!bss)
- return NULL;
-
rcu_read_lock();
beacon = rcu_dereference(bss->beacon);
@@ -2256,7 +2189,7 @@ ieee80211_get_buffered_bc(struct ieee80211_hw *hw,
cpu_to_le16(IEEE80211_FCTL_MOREDATA);
}
- if (!ieee80211_tx_prepare(local, &tx, skb))
+ if (!ieee80211_tx_prepare(sdata, &tx, skb))
break;
dev_kfree_skb_any(skb);
}
@@ -2276,3 +2209,24 @@ ieee80211_get_buffered_bc(struct ieee80211_hw *hw,
return skb;
}
EXPORT_SYMBOL(ieee80211_get_buffered_bc);
+
+void ieee80211_tx_skb(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb,
+ int encrypt)
+{
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+ skb_set_mac_header(skb, 0);
+ skb_set_network_header(skb, 0);
+ skb_set_transport_header(skb, 0);
+
+ if (!encrypt)
+ info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
+
+ /*
+ * The other path calling ieee80211_xmit is from the tasklet,
+ * and while we can handle concurrent transmissions locking
+ * requirements are that we do not come into tx with bhs on.
+ */
+ local_bh_disable();
+ ieee80211_xmit(sdata, skb);
+ local_bh_enable();
+}
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 915e7776931..e55d57f559e 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -31,6 +31,7 @@
#include "mesh.h"
#include "wme.h"
#include "led.h"
+#include "wep.h"
/* privid for wiphys to determine whether they belong to us or not */
void *mac80211_wiphy_privid = &mac80211_wiphy_privid;
@@ -274,16 +275,12 @@ static void __ieee80211_wake_queue(struct ieee80211_hw *hw, int queue,
__clear_bit(reason, &local->queue_stop_reasons[queue]);
- if (!skb_queue_empty(&local->pending[queue]) &&
- local->queue_stop_reasons[queue] ==
- BIT(IEEE80211_QUEUE_STOP_REASON_PENDING))
- tasklet_schedule(&local->tx_pending_tasklet);
-
if (local->queue_stop_reasons[queue] != 0)
/* someone still has this queue stopped */
return;
- netif_wake_subqueue(local->mdev, queue);
+ if (!skb_queue_empty(&local->pending[queue]))
+ tasklet_schedule(&local->tx_pending_tasklet);
}
void ieee80211_wake_queue_by_reason(struct ieee80211_hw *hw, int queue,
@@ -312,14 +309,6 @@ static void __ieee80211_stop_queue(struct ieee80211_hw *hw, int queue,
if (WARN_ON(queue >= hw->queues))
return;
- /*
- * Only stop if it was previously running, this is necessary
- * for correct pending packets handling because there we may
- * start (but not wake) the queue and rely on that.
- */
- if (!local->queue_stop_reasons[queue])
- netif_stop_subqueue(local->mdev, queue);
-
__set_bit(reason, &local->queue_stop_reasons[queue]);
}
@@ -347,11 +336,16 @@ void ieee80211_add_pending_skb(struct ieee80211_local *local,
struct ieee80211_hw *hw = &local->hw;
unsigned long flags;
int queue = skb_get_queue_mapping(skb);
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+
+ if (WARN_ON(!info->control.vif)) {
+ kfree(skb);
+ return;
+ }
spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
__ieee80211_stop_queue(hw, queue, IEEE80211_QUEUE_STOP_REASON_SKB_ADD);
- __ieee80211_stop_queue(hw, queue, IEEE80211_QUEUE_STOP_REASON_PENDING);
- skb_queue_tail(&local->pending[queue], skb);
+ __skb_queue_tail(&local->pending[queue], skb);
__ieee80211_wake_queue(hw, queue, IEEE80211_QUEUE_STOP_REASON_SKB_ADD);
spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
}
@@ -370,18 +364,21 @@ int ieee80211_add_pending_skbs(struct ieee80211_local *local,
IEEE80211_QUEUE_STOP_REASON_SKB_ADD);
while ((skb = skb_dequeue(skbs))) {
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+
+ if (WARN_ON(!info->control.vif)) {
+ kfree(skb);
+ continue;
+ }
+
ret++;
queue = skb_get_queue_mapping(skb);
- skb_queue_tail(&local->pending[queue], skb);
+ __skb_queue_tail(&local->pending[queue], skb);
}
- for (i = 0; i < hw->queues; i++) {
- if (ret)
- __ieee80211_stop_queue(hw, i,
- IEEE80211_QUEUE_STOP_REASON_PENDING);
+ for (i = 0; i < hw->queues; i++)
__ieee80211_wake_queue(hw, i,
IEEE80211_QUEUE_STOP_REASON_SKB_ADD);
- }
spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
return ret;
@@ -412,11 +409,16 @@ EXPORT_SYMBOL(ieee80211_stop_queues);
int ieee80211_queue_stopped(struct ieee80211_hw *hw, int queue)
{
struct ieee80211_local *local = hw_to_local(hw);
+ unsigned long flags;
+ int ret;
if (WARN_ON(queue >= hw->queues))
return true;
- return __netif_subqueue_stopped(local->mdev, queue);
+ spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
+ ret = !!local->queue_stop_reasons[queue];
+ spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
+ return ret;
}
EXPORT_SYMBOL(ieee80211_queue_stopped);
@@ -509,6 +511,46 @@ void ieee80211_iterate_active_interfaces_atomic(
}
EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces_atomic);
+/*
+ * Nothing should have been stuffed into the workqueue during
+ * the suspend->resume cycle. If this WARN is seen then there
+ * is a bug with either the driver suspend or something in
+ * mac80211 stuffing into the workqueue which we haven't yet
+ * cleared during mac80211's suspend cycle.
+ */
+static bool ieee80211_can_queue_work(struct ieee80211_local *local)
+{
+ if (WARN(local->suspended, "queueing ieee80211 work while "
+ "going to suspend\n"))
+ return false;
+
+ return true;
+}
+
+void ieee80211_queue_work(struct ieee80211_hw *hw, struct work_struct *work)
+{
+ struct ieee80211_local *local = hw_to_local(hw);
+
+ if (!ieee80211_can_queue_work(local))
+ return;
+
+ queue_work(local->workqueue, work);
+}
+EXPORT_SYMBOL(ieee80211_queue_work);
+
+void ieee80211_queue_delayed_work(struct ieee80211_hw *hw,
+ struct delayed_work *dwork,
+ unsigned long delay)
+{
+ struct ieee80211_local *local = hw_to_local(hw);
+
+ if (!ieee80211_can_queue_work(local))
+ return;
+
+ queue_delayed_work(local->workqueue, dwork, delay);
+}
+EXPORT_SYMBOL(ieee80211_queue_delayed_work);
+
void ieee802_11_parse_elems(u8 *start, size_t len,
struct ieee802_11_elems *elems)
{
@@ -760,20 +802,6 @@ void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata,
ieee80211_set_wmm_default(sdata);
}
-void ieee80211_tx_skb(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb,
- int encrypt)
-{
- skb->dev = sdata->local->mdev;
- skb_set_mac_header(skb, 0);
- skb_set_network_header(skb, 0);
- skb_set_transport_header(skb, 0);
-
- skb->iif = sdata->dev->ifindex;
- skb->do_not_encrypt = !encrypt;
-
- dev_queue_xmit(skb);
-}
-
u32 ieee80211_mandatory_rates(struct ieee80211_local *local,
enum ieee80211_band band)
{
@@ -804,12 +832,13 @@ u32 ieee80211_mandatory_rates(struct ieee80211_local *local,
void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata,
u16 transaction, u16 auth_alg,
- u8 *extra, size_t extra_len,
- const u8 *bssid, int encrypt)
+ u8 *extra, size_t extra_len, const u8 *bssid,
+ const u8 *key, u8 key_len, u8 key_idx)
{
struct ieee80211_local *local = sdata->local;
struct sk_buff *skb;
struct ieee80211_mgmt *mgmt;
+ int err;
skb = dev_alloc_skb(local->hw.extra_tx_headroom +
sizeof(*mgmt) + 6 + extra_len);
@@ -824,8 +853,6 @@ void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata,
memset(mgmt, 0, 24 + 6);
mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
IEEE80211_STYPE_AUTH);
- if (encrypt)
- mgmt->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED);
memcpy(mgmt->da, bssid, ETH_ALEN);
memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN);
memcpy(mgmt->bssid, bssid, ETH_ALEN);
@@ -835,7 +862,13 @@ void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata,
if (extra)
memcpy(skb_put(skb, extra_len), extra, extra_len);
- ieee80211_tx_skb(sdata, skb, encrypt);
+ if (auth_alg == WLAN_AUTH_SHARED_KEY && transaction == 3) {
+ mgmt->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED);
+ err = ieee80211_wep_encrypt(local, skb, key, key_len, key_idx);
+ WARN_ON(err);
+ }
+
+ ieee80211_tx_skb(sdata, skb, 0);
}
int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer,
@@ -1043,9 +1076,9 @@ int ieee80211_reconfig(struct ieee80211_local *local)
/* reconfigure hardware */
ieee80211_hw_config(local, ~0);
- netif_addr_lock_bh(local->mdev);
+ spin_lock_bh(&local->filter_lock);
ieee80211_configure_filter(local);
- netif_addr_unlock_bh(local->mdev);
+ spin_unlock_bh(&local->filter_lock);
/* Finally also reconfigure all the BSS information */
list_for_each_entry(sdata, &local->interfaces, list) {
@@ -1121,3 +1154,4 @@ int ieee80211_reconfig(struct ieee80211_local *local)
#endif
return 0;
}
+
diff --git a/net/mac80211/wep.c b/net/mac80211/wep.c
index ef73105b306..8a980f13694 100644
--- a/net/mac80211/wep.c
+++ b/net/mac80211/wep.c
@@ -67,10 +67,10 @@ static inline bool ieee80211_wep_weak_iv(u32 iv, int keylen)
static void ieee80211_wep_get_iv(struct ieee80211_local *local,
- struct ieee80211_key *key, u8 *iv)
+ int keylen, int keyidx, u8 *iv)
{
local->wep_iv++;
- if (ieee80211_wep_weak_iv(local->wep_iv, key->conf.keylen))
+ if (ieee80211_wep_weak_iv(local->wep_iv, keylen))
local->wep_iv += 0x0100;
if (!iv)
@@ -79,13 +79,13 @@ static void ieee80211_wep_get_iv(struct ieee80211_local *local,
*iv++ = (local->wep_iv >> 16) & 0xff;
*iv++ = (local->wep_iv >> 8) & 0xff;
*iv++ = local->wep_iv & 0xff;
- *iv++ = key->conf.keyidx << 6;
+ *iv++ = keyidx << 6;
}
static u8 *ieee80211_wep_add_iv(struct ieee80211_local *local,
struct sk_buff *skb,
- struct ieee80211_key *key)
+ int keylen, int keyidx)
{
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
unsigned int hdrlen;
@@ -100,7 +100,7 @@ static u8 *ieee80211_wep_add_iv(struct ieee80211_local *local,
hdrlen = ieee80211_hdrlen(hdr->frame_control);
newhdr = skb_push(skb, WEP_IV_LEN);
memmove(newhdr, newhdr + WEP_IV_LEN, hdrlen);
- ieee80211_wep_get_iv(local, key, newhdr + hdrlen);
+ ieee80211_wep_get_iv(local, keylen, keyidx, newhdr + hdrlen);
return newhdr + hdrlen;
}
@@ -144,26 +144,17 @@ void ieee80211_wep_encrypt_data(struct crypto_blkcipher *tfm, u8 *rc4key,
*
* WEP frame payload: IV + TX key idx, RC4(data), ICV = RC4(CRC32(data))
*/
-int ieee80211_wep_encrypt(struct ieee80211_local *local, struct sk_buff *skb,
- struct ieee80211_key *key)
+int ieee80211_wep_encrypt(struct ieee80211_local *local,
+ struct sk_buff *skb,
+ const u8 *key, int keylen, int keyidx)
{
- u32 klen;
- u8 *rc4key, *iv;
+ u8 *iv;
size_t len;
+ u8 rc4key[3 + WLAN_KEY_LEN_WEP104];
- if (!key || key->conf.alg != ALG_WEP)
- return -1;
-
- klen = 3 + key->conf.keylen;
- rc4key = kmalloc(klen, GFP_ATOMIC);
- if (!rc4key)
- return -1;
-
- iv = ieee80211_wep_add_iv(local, skb, key);
- if (!iv) {
- kfree(rc4key);
+ iv = ieee80211_wep_add_iv(local, skb, keylen, keyidx);
+ if (!iv)
return -1;
- }
len = skb->len - (iv + WEP_IV_LEN - skb->data);
@@ -171,16 +162,14 @@ int ieee80211_wep_encrypt(struct ieee80211_local *local, struct sk_buff *skb,
memcpy(rc4key, iv, 3);
/* Copy rest of the WEP key (the secret part) */
- memcpy(rc4key + 3, key->conf.key, key->conf.keylen);
+ memcpy(rc4key + 3, key, keylen);
/* Add room for ICV */
skb_put(skb, WEP_ICV_LEN);
- ieee80211_wep_encrypt_data(local->wep_tx_tfm, rc4key, klen,
+ ieee80211_wep_encrypt_data(local->wep_tx_tfm, rc4key, keylen + 3,
iv + WEP_IV_LEN, len);
- kfree(rc4key);
-
return 0;
}
@@ -216,8 +205,9 @@ int ieee80211_wep_decrypt_data(struct crypto_blkcipher *tfm, u8 *rc4key,
* failure. If frame is OK, IV and ICV will be removed, i.e., decrypted payload
* is moved to the beginning of the skb and skb length will be reduced.
*/
-int ieee80211_wep_decrypt(struct ieee80211_local *local, struct sk_buff *skb,
- struct ieee80211_key *key)
+static int ieee80211_wep_decrypt(struct ieee80211_local *local,
+ struct sk_buff *skb,
+ struct ieee80211_key *key)
{
u32 klen;
u8 *rc4key;
@@ -314,12 +304,16 @@ static int wep_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
if (!(tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) {
- if (ieee80211_wep_encrypt(tx->local, skb, tx->key))
+ if (ieee80211_wep_encrypt(tx->local, skb, tx->key->conf.key,
+ tx->key->conf.keylen,
+ tx->key->conf.keyidx))
return -1;
} else {
info->control.hw_key = &tx->key->conf;
if (tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV) {
- if (!ieee80211_wep_add_iv(tx->local, skb, tx->key))
+ if (!ieee80211_wep_add_iv(tx->local, skb,
+ tx->key->conf.keylen,
+ tx->key->conf.keyidx))
return -1;
}
}
diff --git a/net/mac80211/wep.h b/net/mac80211/wep.h
index d3f0db48314..fe29d7e5759 100644
--- a/net/mac80211/wep.h
+++ b/net/mac80211/wep.h
@@ -20,12 +20,11 @@ int ieee80211_wep_init(struct ieee80211_local *local);
void ieee80211_wep_free(struct ieee80211_local *local);
void ieee80211_wep_encrypt_data(struct crypto_blkcipher *tfm, u8 *rc4key,
size_t klen, u8 *data, size_t data_len);
+int ieee80211_wep_encrypt(struct ieee80211_local *local,
+ struct sk_buff *skb,
+ const u8 *key, int keylen, int keyidx);
int ieee80211_wep_decrypt_data(struct crypto_blkcipher *tfm, u8 *rc4key,
size_t klen, u8 *data, size_t data_len);
-int ieee80211_wep_encrypt(struct ieee80211_local *local, struct sk_buff *skb,
- struct ieee80211_key *key);
-int ieee80211_wep_decrypt(struct ieee80211_local *local, struct sk_buff *skb,
- struct ieee80211_key *key);
bool ieee80211_wep_is_weak_iv(struct sk_buff *skb, struct ieee80211_key *key);
ieee80211_rx_result
diff --git a/net/mac80211/wext.c b/net/mac80211/wext.c
deleted file mode 100644
index 1da81f45674..00000000000
--- a/net/mac80211/wext.c
+++ /dev/null
@@ -1,633 +0,0 @@
-/*
- * Copyright 2002-2005, Instant802 Networks, Inc.
- * Copyright 2005-2006, Devicescape Software, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/netdevice.h>
-#include <linux/types.h>
-#include <linux/slab.h>
-#include <linux/skbuff.h>
-#include <linux/etherdevice.h>
-#include <linux/if_arp.h>
-#include <linux/wireless.h>
-#include <net/iw_handler.h>
-#include <asm/uaccess.h>
-
-#include <net/mac80211.h>
-#include "ieee80211_i.h"
-#include "led.h"
-#include "rate.h"
-#include "wpa.h"
-#include "aes_ccm.h"
-
-
-static int ieee80211_ioctl_siwgenie(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_point *data, char *extra)
-{
- struct ieee80211_sub_if_data *sdata;
-
- sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-
- if (sdata->vif.type == NL80211_IFTYPE_STATION) {
- int ret = ieee80211_sta_set_extra_ie(sdata, extra, data->length);
- if (ret && ret != -EALREADY)
- return ret;
- sdata->u.mgd.flags &= ~IEEE80211_STA_AUTO_BSSID_SEL;
- sdata->u.mgd.flags &= ~IEEE80211_STA_EXT_SME;
- sdata->u.mgd.flags &= ~IEEE80211_STA_CONTROL_PORT;
- if (ret != -EALREADY)
- ieee80211_sta_req_auth(sdata);
- return 0;
- }
-
- return -EOPNOTSUPP;
-}
-
-static int ieee80211_ioctl_siwfreq(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_freq *freq, char *extra)
-{
- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
- struct ieee80211_local *local = sdata->local;
- struct ieee80211_channel *chan;
-
- if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
- return cfg80211_ibss_wext_siwfreq(dev, info, freq, extra);
- else if (sdata->vif.type == NL80211_IFTYPE_STATION)
- sdata->u.mgd.flags &= ~IEEE80211_STA_AUTO_CHANNEL_SEL;
-
- /* freq->e == 0: freq->m = channel; otherwise freq = m * 10^e */
- if (freq->e == 0) {
- if (freq->m < 0) {
- if (sdata->vif.type == NL80211_IFTYPE_STATION)
- sdata->u.mgd.flags |=
- IEEE80211_STA_AUTO_CHANNEL_SEL;
- return 0;
- } else
- chan = ieee80211_get_channel(local->hw.wiphy,
- ieee80211_channel_to_frequency(freq->m));
- } else {
- int i, div = 1000000;
- for (i = 0; i < freq->e; i++)
- div /= 10;
- if (div <= 0)
- return -EINVAL;
- chan = ieee80211_get_channel(local->hw.wiphy, freq->m / div);
- }
-
- if (!chan)
- return -EINVAL;
-
- if (chan->flags & IEEE80211_CHAN_DISABLED)
- return -EINVAL;
-
- /*
- * no change except maybe auto -> fixed, ignore the HT
- * setting so you can fix a channel you're on already
- */
- if (local->oper_channel == chan)
- return 0;
-
- if (sdata->vif.type == NL80211_IFTYPE_STATION)
- ieee80211_sta_req_auth(sdata);
-
- local->oper_channel = chan;
- local->oper_channel_type = NL80211_CHAN_NO_HT;
- ieee80211_hw_config(local, 0);
-
- return 0;
-}
-
-
-static int ieee80211_ioctl_giwfreq(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_freq *freq, char *extra)
-{
- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-
- if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
- return cfg80211_ibss_wext_giwfreq(dev, info, freq, extra);
-
- freq->m = local->oper_channel->center_freq;
- freq->e = 6;
-
- return 0;
-}
-
-
-static int ieee80211_ioctl_siwessid(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_point *data, char *ssid)
-{
- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
- size_t len = data->length;
- int ret;
-
- if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
- return cfg80211_ibss_wext_siwessid(dev, info, data, ssid);
-
- /* iwconfig uses nul termination in SSID.. */
- if (len > 0 && ssid[len - 1] == '\0')
- len--;
-
- if (sdata->vif.type == NL80211_IFTYPE_STATION) {
- if (data->flags)
- sdata->u.mgd.flags &= ~IEEE80211_STA_AUTO_SSID_SEL;
- else
- sdata->u.mgd.flags |= IEEE80211_STA_AUTO_SSID_SEL;
-
- ret = ieee80211_sta_set_ssid(sdata, ssid, len);
- if (ret)
- return ret;
-
- sdata->u.mgd.flags &= ~IEEE80211_STA_EXT_SME;
- sdata->u.mgd.flags &= ~IEEE80211_STA_CONTROL_PORT;
- ieee80211_sta_req_auth(sdata);
- return 0;
- }
-
- return -EOPNOTSUPP;
-}
-
-
-static int ieee80211_ioctl_giwessid(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_point *data, char *ssid)
-{
- size_t len;
- struct ieee80211_sub_if_data *sdata;
-
- sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-
- if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
- return cfg80211_ibss_wext_giwessid(dev, info, data, ssid);
-
- if (sdata->vif.type == NL80211_IFTYPE_STATION) {
- int res = ieee80211_sta_get_ssid(sdata, ssid, &len);
- if (res == 0) {
- data->length = len;
- data->flags = 1;
- } else
- data->flags = 0;
- return res;
- }
-
- return -EOPNOTSUPP;
-}
-
-
-static int ieee80211_ioctl_siwap(struct net_device *dev,
- struct iw_request_info *info,
- struct sockaddr *ap_addr, char *extra)
-{
- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-
- if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
- return cfg80211_ibss_wext_siwap(dev, info, ap_addr, extra);
-
- if (sdata->vif.type == NL80211_IFTYPE_STATION) {
- int ret;
-
- if (is_zero_ether_addr((u8 *) &ap_addr->sa_data))
- sdata->u.mgd.flags |= IEEE80211_STA_AUTO_BSSID_SEL |
- IEEE80211_STA_AUTO_CHANNEL_SEL;
- else if (is_broadcast_ether_addr((u8 *) &ap_addr->sa_data))
- sdata->u.mgd.flags |= IEEE80211_STA_AUTO_BSSID_SEL;
- else
- sdata->u.mgd.flags &= ~IEEE80211_STA_AUTO_BSSID_SEL;
- ret = ieee80211_sta_set_bssid(sdata, (u8 *) &ap_addr->sa_data);
- if (ret)
- return ret;
- sdata->u.mgd.flags &= ~IEEE80211_STA_EXT_SME;
- sdata->u.mgd.flags &= ~IEEE80211_STA_CONTROL_PORT;
- ieee80211_sta_req_auth(sdata);
- return 0;
- } else if (sdata->vif.type == NL80211_IFTYPE_WDS) {
- /*
- * If it is necessary to update the WDS peer address
- * while the interface is running, then we need to do
- * more work here, namely if it is running we need to
- * add a new and remove the old STA entry, this is
- * normally handled by _open() and _stop().
- */
- if (netif_running(dev))
- return -EBUSY;
-
- memcpy(&sdata->u.wds.remote_addr, (u8 *) &ap_addr->sa_data,
- ETH_ALEN);
-
- return 0;
- }
-
- return -EOPNOTSUPP;
-}
-
-
-static int ieee80211_ioctl_giwap(struct net_device *dev,
- struct iw_request_info *info,
- struct sockaddr *ap_addr, char *extra)
-{
- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-
- if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
- return cfg80211_ibss_wext_giwap(dev, info, ap_addr, extra);
-
- if (sdata->vif.type == NL80211_IFTYPE_STATION) {
- if (sdata->u.mgd.state == IEEE80211_STA_MLME_ASSOCIATED) {
- ap_addr->sa_family = ARPHRD_ETHER;
- memcpy(&ap_addr->sa_data, sdata->u.mgd.bssid, ETH_ALEN);
- } else
- memset(&ap_addr->sa_data, 0, ETH_ALEN);
- return 0;
- } else if (sdata->vif.type == NL80211_IFTYPE_WDS) {
- ap_addr->sa_family = ARPHRD_ETHER;
- memcpy(&ap_addr->sa_data, sdata->u.wds.remote_addr, ETH_ALEN);
- return 0;
- }
-
- return -EOPNOTSUPP;
-}
-
-
-static int ieee80211_ioctl_siwrate(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_param *rate, char *extra)
-{
- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
- int i, err = -EINVAL;
- u32 target_rate = rate->value / 100000;
- struct ieee80211_sub_if_data *sdata;
- struct ieee80211_supported_band *sband;
-
- sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-
- sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
-
- /* target_rate = -1, rate->fixed = 0 means auto only, so use all rates
- * target_rate = X, rate->fixed = 1 means only rate X
- * target_rate = X, rate->fixed = 0 means all rates <= X */
- sdata->max_ratectrl_rateidx = -1;
- sdata->force_unicast_rateidx = -1;
- if (rate->value < 0)
- return 0;
-
- for (i=0; i< sband->n_bitrates; i++) {
- struct ieee80211_rate *brate = &sband->bitrates[i];
- int this_rate = brate->bitrate;
-
- if (target_rate == this_rate) {
- sdata->max_ratectrl_rateidx = i;
- if (rate->fixed)
- sdata->force_unicast_rateidx = i;
- err = 0;
- break;
- }
- }
- return err;
-}
-
-static int ieee80211_ioctl_giwrate(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_param *rate, char *extra)
-{
- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
- struct sta_info *sta;
- struct ieee80211_sub_if_data *sdata;
- struct ieee80211_supported_band *sband;
-
- sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-
- if (sdata->vif.type != NL80211_IFTYPE_STATION)
- return -EOPNOTSUPP;
-
- sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
-
- rcu_read_lock();
-
- sta = sta_info_get(local, sdata->u.mgd.bssid);
-
- if (sta && !(sta->last_tx_rate.flags & IEEE80211_TX_RC_MCS))
- rate->value = sband->bitrates[sta->last_tx_rate.idx].bitrate;
- else
- rate->value = 0;
-
- rcu_read_unlock();
-
- if (!sta)
- return -ENODEV;
-
- rate->value *= 100000;
-
- return 0;
-}
-
-static int ieee80211_ioctl_siwpower(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_param *wrq,
- char *extra)
-{
- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
- struct ieee80211_conf *conf = &local->hw.conf;
- int timeout = 0;
- bool ps;
-
- if (!(local->hw.flags & IEEE80211_HW_SUPPORTS_PS))
- return -EOPNOTSUPP;
-
- if (sdata->vif.type != NL80211_IFTYPE_STATION)
- return -EINVAL;
-
- if (wrq->disabled) {
- ps = false;
- timeout = 0;
- goto set;
- }
-
- switch (wrq->flags & IW_POWER_MODE) {
- case IW_POWER_ON: /* If not specified */
- case IW_POWER_MODE: /* If set all mask */
- case IW_POWER_ALL_R: /* If explicitely state all */
- ps = true;
- break;
- default: /* Otherwise we ignore */
- return -EINVAL;
- }
-
- if (wrq->flags & ~(IW_POWER_MODE | IW_POWER_TIMEOUT))
- return -EINVAL;
-
- if (wrq->flags & IW_POWER_TIMEOUT)
- timeout = wrq->value / 1000;
-
- set:
- if (ps == sdata->u.mgd.powersave && timeout == conf->dynamic_ps_timeout)
- return 0;
-
- sdata->u.mgd.powersave = ps;
- conf->dynamic_ps_timeout = timeout;
-
- if (local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS)
- ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
-
- ieee80211_recalc_ps(local, -1);
-
- return 0;
-}
-
-static int ieee80211_ioctl_giwpower(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu,
- char *extra)
-{
- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-
- wrqu->power.disabled = !sdata->u.mgd.powersave;
-
- return 0;
-}
-
-static int ieee80211_ioctl_siwauth(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_param *data, char *extra)
-{
- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
- int ret = 0;
-
- switch (data->flags & IW_AUTH_INDEX) {
- case IW_AUTH_WPA_VERSION:
- case IW_AUTH_CIPHER_GROUP:
- case IW_AUTH_WPA_ENABLED:
- case IW_AUTH_RX_UNENCRYPTED_EAPOL:
- case IW_AUTH_KEY_MGMT:
- case IW_AUTH_CIPHER_GROUP_MGMT:
- break;
- case IW_AUTH_CIPHER_PAIRWISE:
- if (sdata->vif.type == NL80211_IFTYPE_STATION) {
- if (data->value & (IW_AUTH_CIPHER_WEP40 |
- IW_AUTH_CIPHER_WEP104 | IW_AUTH_CIPHER_TKIP))
- sdata->u.mgd.flags |=
- IEEE80211_STA_TKIP_WEP_USED;
- else
- sdata->u.mgd.flags &=
- ~IEEE80211_STA_TKIP_WEP_USED;
- }
- break;
- case IW_AUTH_DROP_UNENCRYPTED:
- sdata->drop_unencrypted = !!data->value;
- break;
- case IW_AUTH_PRIVACY_INVOKED:
- if (sdata->vif.type != NL80211_IFTYPE_STATION)
- ret = -EINVAL;
- else {
- sdata->u.mgd.flags &= ~IEEE80211_STA_PRIVACY_INVOKED;
- /*
- * Privacy invoked by wpa_supplicant, store the
- * value and allow associating to a protected
- * network without having a key up front.
- */
- if (data->value)
- sdata->u.mgd.flags |=
- IEEE80211_STA_PRIVACY_INVOKED;
- }
- break;
- case IW_AUTH_80211_AUTH_ALG:
- if (sdata->vif.type == NL80211_IFTYPE_STATION)
- sdata->u.mgd.auth_algs = data->value;
- else
- ret = -EOPNOTSUPP;
- break;
- case IW_AUTH_MFP:
- if (!(sdata->local->hw.flags & IEEE80211_HW_MFP_CAPABLE)) {
- ret = -EOPNOTSUPP;
- break;
- }
- if (sdata->vif.type == NL80211_IFTYPE_STATION) {
- switch (data->value) {
- case IW_AUTH_MFP_DISABLED:
- sdata->u.mgd.mfp = IEEE80211_MFP_DISABLED;
- break;
- case IW_AUTH_MFP_OPTIONAL:
- sdata->u.mgd.mfp = IEEE80211_MFP_OPTIONAL;
- break;
- case IW_AUTH_MFP_REQUIRED:
- sdata->u.mgd.mfp = IEEE80211_MFP_REQUIRED;
- break;
- default:
- ret = -EINVAL;
- }
- } else
- ret = -EOPNOTSUPP;
- break;
- default:
- ret = -EOPNOTSUPP;
- break;
- }
- return ret;
-}
-
-/* Get wireless statistics. Called by /proc/net/wireless and by SIOCGIWSTATS */
-static struct iw_statistics *ieee80211_get_wireless_stats(struct net_device *dev)
-{
- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
- struct iw_statistics *wstats = &local->wstats;
- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
- struct sta_info *sta = NULL;
-
- rcu_read_lock();
-
- if (sdata->vif.type == NL80211_IFTYPE_STATION)
- sta = sta_info_get(local, sdata->u.mgd.bssid);
-
- if (!sta) {
- wstats->discard.fragment = 0;
- wstats->discard.misc = 0;
- wstats->qual.qual = 0;
- wstats->qual.level = 0;
- wstats->qual.noise = 0;
- wstats->qual.updated = IW_QUAL_ALL_INVALID;
- } else {
- wstats->qual.updated = 0;
- /*
- * mirror what cfg80211 does for iwrange/scan results,
- * otherwise userspace gets confused.
- */
- if (local->hw.flags & (IEEE80211_HW_SIGNAL_UNSPEC |
- IEEE80211_HW_SIGNAL_DBM)) {
- wstats->qual.updated |= IW_QUAL_LEVEL_UPDATED;
- wstats->qual.updated |= IW_QUAL_QUAL_UPDATED;
- } else {
- wstats->qual.updated |= IW_QUAL_LEVEL_INVALID;
- wstats->qual.updated |= IW_QUAL_QUAL_INVALID;
- }
-
- if (local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC) {
- wstats->qual.level = sta->last_signal;
- wstats->qual.qual = sta->last_signal;
- } else if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM) {
- int sig = sta->last_signal;
-
- wstats->qual.updated |= IW_QUAL_DBM;
- wstats->qual.level = sig;
- if (sig < -110)
- sig = -110;
- else if (sig > -40)
- sig = -40;
- wstats->qual.qual = sig + 110;
- }
-
- if (local->hw.flags & IEEE80211_HW_NOISE_DBM) {
- /*
- * This assumes that if driver reports noise, it also
- * reports signal in dBm.
- */
- wstats->qual.noise = sta->last_noise;
- wstats->qual.updated |= IW_QUAL_NOISE_UPDATED;
- } else {
- wstats->qual.updated |= IW_QUAL_NOISE_INVALID;
- }
- }
-
- rcu_read_unlock();
-
- return wstats;
-}
-
-static int ieee80211_ioctl_giwauth(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_param *data, char *extra)
-{
- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
- int ret = 0;
-
- switch (data->flags & IW_AUTH_INDEX) {
- case IW_AUTH_80211_AUTH_ALG:
- if (sdata->vif.type == NL80211_IFTYPE_STATION)
- data->value = sdata->u.mgd.auth_algs;
- else
- ret = -EOPNOTSUPP;
- break;
- default:
- ret = -EOPNOTSUPP;
- break;
- }
- return ret;
-}
-
-
-/* Structures to export the Wireless Handlers */
-
-static const iw_handler ieee80211_handler[] =
-{
- (iw_handler) NULL, /* SIOCSIWCOMMIT */
- (iw_handler) cfg80211_wext_giwname, /* SIOCGIWNAME */
- (iw_handler) NULL, /* SIOCSIWNWID */
- (iw_handler) NULL, /* SIOCGIWNWID */
- (iw_handler) ieee80211_ioctl_siwfreq, /* SIOCSIWFREQ */
- (iw_handler) ieee80211_ioctl_giwfreq, /* SIOCGIWFREQ */
- (iw_handler) cfg80211_wext_siwmode, /* SIOCSIWMODE */
- (iw_handler) cfg80211_wext_giwmode, /* SIOCGIWMODE */
- (iw_handler) NULL, /* SIOCSIWSENS */
- (iw_handler) NULL, /* SIOCGIWSENS */
- (iw_handler) NULL /* not used */, /* SIOCSIWRANGE */
- (iw_handler) cfg80211_wext_giwrange, /* SIOCGIWRANGE */
- (iw_handler) NULL /* not used */, /* SIOCSIWPRIV */
- (iw_handler) NULL /* kernel code */, /* SIOCGIWPRIV */
- (iw_handler) NULL /* not used */, /* SIOCSIWSTATS */
- (iw_handler) NULL /* kernel code */, /* SIOCGIWSTATS */
- (iw_handler) NULL, /* SIOCSIWSPY */
- (iw_handler) NULL, /* SIOCGIWSPY */
- (iw_handler) NULL, /* SIOCSIWTHRSPY */
- (iw_handler) NULL, /* SIOCGIWTHRSPY */
- (iw_handler) ieee80211_ioctl_siwap, /* SIOCSIWAP */
- (iw_handler) ieee80211_ioctl_giwap, /* SIOCGIWAP */
- (iw_handler) cfg80211_wext_siwmlme, /* SIOCSIWMLME */
- (iw_handler) NULL, /* SIOCGIWAPLIST */
- (iw_handler) cfg80211_wext_siwscan, /* SIOCSIWSCAN */
- (iw_handler) cfg80211_wext_giwscan, /* SIOCGIWSCAN */
- (iw_handler) ieee80211_ioctl_siwessid, /* SIOCSIWESSID */
- (iw_handler) ieee80211_ioctl_giwessid, /* SIOCGIWESSID */
- (iw_handler) NULL, /* SIOCSIWNICKN */
- (iw_handler) NULL, /* SIOCGIWNICKN */
- (iw_handler) NULL, /* -- hole -- */
- (iw_handler) NULL, /* -- hole -- */
- (iw_handler) ieee80211_ioctl_siwrate, /* SIOCSIWRATE */
- (iw_handler) ieee80211_ioctl_giwrate, /* SIOCGIWRATE */
- (iw_handler) cfg80211_wext_siwrts, /* SIOCSIWRTS */
- (iw_handler) cfg80211_wext_giwrts, /* SIOCGIWRTS */
- (iw_handler) cfg80211_wext_siwfrag, /* SIOCSIWFRAG */
- (iw_handler) cfg80211_wext_giwfrag, /* SIOCGIWFRAG */
- (iw_handler) cfg80211_wext_siwtxpower, /* SIOCSIWTXPOW */
- (iw_handler) cfg80211_wext_giwtxpower, /* SIOCGIWTXPOW */
- (iw_handler) cfg80211_wext_siwretry, /* SIOCSIWRETRY */
- (iw_handler) cfg80211_wext_giwretry, /* SIOCGIWRETRY */
- (iw_handler) cfg80211_wext_siwencode, /* SIOCSIWENCODE */
- (iw_handler) cfg80211_wext_giwencode, /* SIOCGIWENCODE */
- (iw_handler) ieee80211_ioctl_siwpower, /* SIOCSIWPOWER */
- (iw_handler) ieee80211_ioctl_giwpower, /* SIOCGIWPOWER */
- (iw_handler) NULL, /* -- hole -- */
- (iw_handler) NULL, /* -- hole -- */
- (iw_handler) ieee80211_ioctl_siwgenie, /* SIOCSIWGENIE */
- (iw_handler) NULL, /* SIOCGIWGENIE */
- (iw_handler) ieee80211_ioctl_siwauth, /* SIOCSIWAUTH */
- (iw_handler) ieee80211_ioctl_giwauth, /* SIOCGIWAUTH */
- (iw_handler) cfg80211_wext_siwencodeext, /* SIOCSIWENCODEEXT */
- (iw_handler) NULL, /* SIOCGIWENCODEEXT */
- (iw_handler) NULL, /* SIOCSIWPMKSA */
- (iw_handler) NULL, /* -- hole -- */
-};
-
-const struct iw_handler_def ieee80211_iw_handler_def =
-{
- .num_standard = ARRAY_SIZE(ieee80211_handler),
- .standard = (iw_handler *) ieee80211_handler,
- .get_wireless_stats = ieee80211_get_wireless_stats,
-};
diff --git a/net/mac80211/wme.c b/net/mac80211/wme.c
index 116a923b14d..b19b7696f3a 100644
--- a/net/mac80211/wme.c
+++ b/net/mac80211/wme.c
@@ -85,10 +85,8 @@ static u16 classify80211(struct ieee80211_local *local, struct sk_buff *skb)
return ieee802_1d_to_ac[skb->priority];
}
-u16 ieee80211_select_queue(struct net_device *dev, struct sk_buff *skb)
+void ieee80211_select_queue(struct ieee80211_local *local, struct sk_buff *skb)
{
- struct ieee80211_master_priv *mpriv = netdev_priv(dev);
- struct ieee80211_local *local = mpriv->local;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
u16 queue;
u8 tid;
@@ -113,5 +111,5 @@ u16 ieee80211_select_queue(struct net_device *dev, struct sk_buff *skb)
*p = 0;
}
- return queue;
+ skb_set_queue_mapping(skb, queue);
}
diff --git a/net/mac80211/wme.h b/net/mac80211/wme.h
index 7520d2e014d..d4fd87ca511 100644
--- a/net/mac80211/wme.h
+++ b/net/mac80211/wme.h
@@ -20,6 +20,7 @@
extern const int ieee802_1d_to_ac[8];
-u16 ieee80211_select_queue(struct net_device *dev, struct sk_buff *skb);
+void ieee80211_select_queue(struct ieee80211_local *local,
+ struct sk_buff *skb);
#endif /* _WME_H */
diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c
index dcfae8884b8..70778694877 100644
--- a/net/mac80211/wpa.c
+++ b/net/mac80211/wpa.c
@@ -122,7 +122,8 @@ ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx)
return RX_DROP_UNUSABLE;
mac80211_ev_michael_mic_failure(rx->sdata, rx->key->conf.keyidx,
- (void *) skb->data, NULL);
+ (void *) skb->data, NULL,
+ GFP_ATOMIC);
return RX_DROP_UNUSABLE;
}
diff --git a/net/netfilter/ipvs/ip_vs_app.c b/net/netfilter/ipvs/ip_vs_app.c
index 201b8ea3020..3c7e42735b6 100644
--- a/net/netfilter/ipvs/ip_vs_app.c
+++ b/net/netfilter/ipvs/ip_vs_app.c
@@ -18,6 +18,9 @@
*
*/
+#define KMSG_COMPONENT "IPVS"
+#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
+
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/skbuff.h>
@@ -262,12 +265,12 @@ static inline void vs_fix_seq(const struct ip_vs_seq *vseq, struct tcphdr *th)
if (vseq->delta || vseq->previous_delta) {
if(after(seq, vseq->init_seq)) {
th->seq = htonl(seq + vseq->delta);
- IP_VS_DBG(9, "vs_fix_seq(): added delta (%d) to seq\n",
- vseq->delta);
+ IP_VS_DBG(9, "%s(): added delta (%d) to seq\n",
+ __func__, vseq->delta);
} else {
th->seq = htonl(seq + vseq->previous_delta);
- IP_VS_DBG(9, "vs_fix_seq(): added previous_delta "
- "(%d) to seq\n", vseq->previous_delta);
+ IP_VS_DBG(9, "%s(): added previous_delta (%d) to seq\n",
+ __func__, vseq->previous_delta);
}
}
}
@@ -291,14 +294,14 @@ vs_fix_ack_seq(const struct ip_vs_seq *vseq, struct tcphdr *th)
to receive next, so compare it with init_seq+delta */
if(after(ack_seq, vseq->init_seq+vseq->delta)) {
th->ack_seq = htonl(ack_seq - vseq->delta);
- IP_VS_DBG(9, "vs_fix_ack_seq(): subtracted delta "
- "(%d) from ack_seq\n", vseq->delta);
+ IP_VS_DBG(9, "%s(): subtracted delta "
+ "(%d) from ack_seq\n", __func__, vseq->delta);
} else {
th->ack_seq = htonl(ack_seq - vseq->previous_delta);
- IP_VS_DBG(9, "vs_fix_ack_seq(): subtracted "
+ IP_VS_DBG(9, "%s(): subtracted "
"previous_delta (%d) from ack_seq\n",
- vseq->previous_delta);
+ __func__, vseq->previous_delta);
}
}
}
diff --git a/net/netfilter/ipvs/ip_vs_conn.c b/net/netfilter/ipvs/ip_vs_conn.c
index 77bfdfeb966..27c30cf933d 100644
--- a/net/netfilter/ipvs/ip_vs_conn.c
+++ b/net/netfilter/ipvs/ip_vs_conn.c
@@ -22,6 +22,9 @@
*
*/
+#define KMSG_COMPONENT "IPVS"
+#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
+
#include <linux/interrupt.h>
#include <linux/in.h>
#include <linux/net.h>
@@ -150,8 +153,8 @@ static inline int ip_vs_conn_hash(struct ip_vs_conn *cp)
atomic_inc(&cp->refcnt);
ret = 1;
} else {
- IP_VS_ERR("ip_vs_conn_hash(): request for already hashed, "
- "called from %p\n", __builtin_return_address(0));
+ pr_err("%s(): request for already hashed, called from %pF\n",
+ __func__, __builtin_return_address(0));
ret = 0;
}
@@ -689,7 +692,7 @@ ip_vs_conn_new(int af, int proto, const union nf_inet_addr *caddr, __be16 cport,
cp = kmem_cache_zalloc(ip_vs_conn_cachep, GFP_ATOMIC);
if (cp == NULL) {
- IP_VS_ERR_RL("ip_vs_conn_new: no memory available.\n");
+ IP_VS_ERR_RL("%s(): no memory\n", __func__);
return NULL;
}
@@ -1073,10 +1076,10 @@ int __init ip_vs_conn_init(void)
return -ENOMEM;
}
- IP_VS_INFO("Connection hash table configured "
- "(size=%d, memory=%ldKbytes)\n",
- IP_VS_CONN_TAB_SIZE,
- (long)(IP_VS_CONN_TAB_SIZE*sizeof(struct list_head))/1024);
+ pr_info("Connection hash table configured "
+ "(size=%d, memory=%ldKbytes)\n",
+ IP_VS_CONN_TAB_SIZE,
+ (long)(IP_VS_CONN_TAB_SIZE*sizeof(struct list_head))/1024);
IP_VS_DBG(0, "Each connection entry needs %Zd bytes at least\n",
sizeof(struct ip_vs_conn));
diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c
index 8dddb17a947..b227750af75 100644
--- a/net/netfilter/ipvs/ip_vs_core.c
+++ b/net/netfilter/ipvs/ip_vs_core.c
@@ -24,6 +24,9 @@
*
*/
+#define KMSG_COMPONENT "IPVS"
+#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
+
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/ip.h>
@@ -388,9 +391,9 @@ ip_vs_schedule(struct ip_vs_service *svc, const struct sk_buff *skb)
*/
if (!svc->fwmark && pptr[1] != svc->port) {
if (!svc->port)
- IP_VS_ERR("Schedule: port zero only supported "
- "in persistent services, "
- "check your ipvs configuration\n");
+ pr_err("Schedule: port zero only supported "
+ "in persistent services, "
+ "check your ipvs configuration\n");
return NULL;
}
@@ -462,7 +465,7 @@ int ip_vs_leave(struct ip_vs_service *svc, struct sk_buff *skb,
ip_vs_service_put(svc);
/* create a new connection entry */
- IP_VS_DBG(6, "ip_vs_leave: create a cache_bypass entry\n");
+ IP_VS_DBG(6, "%s(): create a cache_bypass entry\n", __func__);
cp = ip_vs_conn_new(svc->af, iph.protocol,
&iph.saddr, pptr[0],
&iph.daddr, pptr[1],
@@ -664,8 +667,8 @@ static int handle_response_icmp(int af, struct sk_buff *skb,
unsigned int verdict = NF_DROP;
if (IP_VS_FWD_METHOD(cp) != 0) {
- IP_VS_ERR("shouldn't reach here, because the box is on the "
- "half connection in the tun/dr module.\n");
+ pr_err("shouldn't reach here, because the box is on the "
+ "half connection in the tun/dr module.\n");
}
/* Ensure the checksum is correct */
@@ -1487,7 +1490,7 @@ static int __init ip_vs_init(void)
ret = ip_vs_control_init();
if (ret < 0) {
- IP_VS_ERR("can't setup control.\n");
+ pr_err("can't setup control.\n");
goto cleanup_estimator;
}
@@ -1495,23 +1498,23 @@ static int __init ip_vs_init(void)
ret = ip_vs_app_init();
if (ret < 0) {
- IP_VS_ERR("can't setup application helper.\n");
+ pr_err("can't setup application helper.\n");
goto cleanup_protocol;
}
ret = ip_vs_conn_init();
if (ret < 0) {
- IP_VS_ERR("can't setup connection table.\n");
+ pr_err("can't setup connection table.\n");
goto cleanup_app;
}
ret = nf_register_hooks(ip_vs_ops, ARRAY_SIZE(ip_vs_ops));
if (ret < 0) {
- IP_VS_ERR("can't register hooks.\n");
+ pr_err("can't register hooks.\n");
goto cleanup_conn;
}
- IP_VS_INFO("ipvs loaded.\n");
+ pr_info("ipvs loaded.\n");
return ret;
cleanup_conn:
@@ -1534,7 +1537,7 @@ static void __exit ip_vs_cleanup(void)
ip_vs_protocol_cleanup();
ip_vs_control_cleanup();
ip_vs_estimator_cleanup();
- IP_VS_INFO("ipvs unloaded.\n");
+ pr_info("ipvs unloaded.\n");
}
module_init(ip_vs_init);
diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c
index 7c1333c67ff..fba2892b99e 100644
--- a/net/netfilter/ipvs/ip_vs_ctl.c
+++ b/net/netfilter/ipvs/ip_vs_ctl.c
@@ -18,6 +18,9 @@
*
*/
+#define KMSG_COMPONENT "IPVS"
+#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
+
#include <linux/module.h>
#include <linux/init.h>
#include <linux/types.h>
@@ -340,8 +343,8 @@ static int ip_vs_svc_hash(struct ip_vs_service *svc)
unsigned hash;
if (svc->flags & IP_VS_SVC_F_HASHED) {
- IP_VS_ERR("ip_vs_svc_hash(): request for already hashed, "
- "called from %p\n", __builtin_return_address(0));
+ pr_err("%s(): request for already hashed, called from %pF\n",
+ __func__, __builtin_return_address(0));
return 0;
}
@@ -374,8 +377,8 @@ static int ip_vs_svc_hash(struct ip_vs_service *svc)
static int ip_vs_svc_unhash(struct ip_vs_service *svc)
{
if (!(svc->flags & IP_VS_SVC_F_HASHED)) {
- IP_VS_ERR("ip_vs_svc_unhash(): request for unhash flagged, "
- "called from %p\n", __builtin_return_address(0));
+ pr_err("%s(): request for unhash flagged, called from %pF\n",
+ __func__, __builtin_return_address(0));
return 0;
}
@@ -841,7 +844,7 @@ ip_vs_new_dest(struct ip_vs_service *svc, struct ip_vs_dest_user_kern *udest,
dest = kzalloc(sizeof(struct ip_vs_dest), GFP_ATOMIC);
if (dest == NULL) {
- IP_VS_ERR("ip_vs_new_dest: kmalloc failed.\n");
+ pr_err("%s(): no memory.\n", __func__);
return -ENOMEM;
}
@@ -885,13 +888,13 @@ ip_vs_add_dest(struct ip_vs_service *svc, struct ip_vs_dest_user_kern *udest)
EnterFunction(2);
if (udest->weight < 0) {
- IP_VS_ERR("ip_vs_add_dest(): server weight less than zero\n");
+ pr_err("%s(): server weight less than zero\n", __func__);
return -ERANGE;
}
if (udest->l_threshold > udest->u_threshold) {
- IP_VS_ERR("ip_vs_add_dest(): lower threshold is higher than "
- "upper threshold\n");
+ pr_err("%s(): lower threshold is higher than upper threshold\n",
+ __func__);
return -ERANGE;
}
@@ -903,7 +906,7 @@ ip_vs_add_dest(struct ip_vs_service *svc, struct ip_vs_dest_user_kern *udest)
dest = ip_vs_lookup_dest(svc, &daddr, dport);
if (dest != NULL) {
- IP_VS_DBG(1, "ip_vs_add_dest(): dest already exists\n");
+ IP_VS_DBG(1, "%s(): dest already exists\n", __func__);
return -EEXIST;
}
@@ -997,13 +1000,13 @@ ip_vs_edit_dest(struct ip_vs_service *svc, struct ip_vs_dest_user_kern *udest)
EnterFunction(2);
if (udest->weight < 0) {
- IP_VS_ERR("ip_vs_edit_dest(): server weight less than zero\n");
+ pr_err("%s(): server weight less than zero\n", __func__);
return -ERANGE;
}
if (udest->l_threshold > udest->u_threshold) {
- IP_VS_ERR("ip_vs_edit_dest(): lower threshold is higher than "
- "upper threshold\n");
+ pr_err("%s(): lower threshold is higher than upper threshold\n",
+ __func__);
return -ERANGE;
}
@@ -1015,7 +1018,7 @@ ip_vs_edit_dest(struct ip_vs_service *svc, struct ip_vs_dest_user_kern *udest)
dest = ip_vs_lookup_dest(svc, &daddr, dport);
if (dest == NULL) {
- IP_VS_DBG(1, "ip_vs_edit_dest(): dest doesn't exist\n");
+ IP_VS_DBG(1, "%s(): dest doesn't exist\n", __func__);
return -ENOENT;
}
@@ -1115,7 +1118,7 @@ ip_vs_del_dest(struct ip_vs_service *svc, struct ip_vs_dest_user_kern *udest)
dest = ip_vs_lookup_dest(svc, &udest->addr, dport);
if (dest == NULL) {
- IP_VS_DBG(1, "ip_vs_del_dest(): destination not found!\n");
+ IP_VS_DBG(1, "%s(): destination not found!\n", __func__);
return -ENOENT;
}
@@ -1161,8 +1164,7 @@ ip_vs_add_service(struct ip_vs_service_user_kern *u,
/* Lookup the scheduler by 'u->sched_name' */
sched = ip_vs_scheduler_get(u->sched_name);
if (sched == NULL) {
- IP_VS_INFO("Scheduler module ip_vs_%s not found\n",
- u->sched_name);
+ pr_info("Scheduler module ip_vs_%s not found\n", u->sched_name);
ret = -ENOENT;
goto out_mod_dec;
}
@@ -1176,7 +1178,7 @@ ip_vs_add_service(struct ip_vs_service_user_kern *u,
svc = kzalloc(sizeof(struct ip_vs_service), GFP_ATOMIC);
if (svc == NULL) {
- IP_VS_DBG(1, "ip_vs_add_service: kmalloc failed.\n");
+ IP_VS_DBG(1, "%s(): no memory\n", __func__);
ret = -ENOMEM;
goto out_err;
}
@@ -1259,8 +1261,7 @@ ip_vs_edit_service(struct ip_vs_service *svc, struct ip_vs_service_user_kern *u)
*/
sched = ip_vs_scheduler_get(u->sched_name);
if (sched == NULL) {
- IP_VS_INFO("Scheduler module ip_vs_%s not found\n",
- u->sched_name);
+ pr_info("Scheduler module ip_vs_%s not found\n", u->sched_name);
return -ENOENT;
}
old_sched = sched;
@@ -2077,8 +2078,8 @@ do_ip_vs_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
return -EPERM;
if (len != set_arglen[SET_CMDID(cmd)]) {
- IP_VS_ERR("set_ctl: len %u != %u\n",
- len, set_arglen[SET_CMDID(cmd)]);
+ pr_err("set_ctl: len %u != %u\n",
+ len, set_arglen[SET_CMDID(cmd)]);
return -EINVAL;
}
@@ -2129,9 +2130,9 @@ do_ip_vs_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
/* Check for valid protocol: TCP or UDP, even for fwmark!=0 */
if (usvc.protocol != IPPROTO_TCP && usvc.protocol != IPPROTO_UDP) {
- IP_VS_ERR("set_ctl: invalid protocol: %d %pI4:%d %s\n",
- usvc.protocol, &usvc.addr.ip,
- ntohs(usvc.port), usvc.sched_name);
+ pr_err("set_ctl: invalid protocol: %d %pI4:%d %s\n",
+ usvc.protocol, &usvc.addr.ip,
+ ntohs(usvc.port), usvc.sched_name);
ret = -EFAULT;
goto out_unlock;
}
@@ -2356,8 +2357,8 @@ do_ip_vs_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
return -EPERM;
if (*len < get_arglen[GET_CMDID(cmd)]) {
- IP_VS_ERR("get_ctl: len %u < %u\n",
- *len, get_arglen[GET_CMDID(cmd)]);
+ pr_err("get_ctl: len %u < %u\n",
+ *len, get_arglen[GET_CMDID(cmd)]);
return -EINVAL;
}
@@ -2402,7 +2403,7 @@ do_ip_vs_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
size = sizeof(*get) +
sizeof(struct ip_vs_service_entry) * get->num_services;
if (*len != size) {
- IP_VS_ERR("length: %u != %u\n", *len, size);
+ pr_err("length: %u != %u\n", *len, size);
ret = -EINVAL;
goto out;
}
@@ -2442,7 +2443,7 @@ do_ip_vs_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
size = sizeof(*get) +
sizeof(struct ip_vs_dest_entry) * get->num_dests;
if (*len != size) {
- IP_VS_ERR("length: %u != %u\n", *len, size);
+ pr_err("length: %u != %u\n", *len, size);
ret = -EINVAL;
goto out;
}
@@ -3170,7 +3171,7 @@ static int ip_vs_genl_get_cmd(struct sk_buff *skb, struct genl_info *info)
else if (cmd == IPVS_CMD_GET_CONFIG)
reply_cmd = IPVS_CMD_SET_CONFIG;
else {
- IP_VS_ERR("unknown Generic Netlink command\n");
+ pr_err("unknown Generic Netlink command\n");
return -EINVAL;
}
@@ -3231,11 +3232,11 @@ static int ip_vs_genl_get_cmd(struct sk_buff *skb, struct genl_info *info)
}
genlmsg_end(msg, reply);
- ret = genlmsg_unicast(msg, info->snd_pid);
+ ret = genlmsg_reply(msg, info);
goto out;
nla_put_failure:
- IP_VS_ERR("not enough space in Netlink message\n");
+ pr_err("not enough space in Netlink message\n");
ret = -EMSGSIZE;
out_err:
@@ -3366,13 +3367,13 @@ int __init ip_vs_control_init(void)
ret = nf_register_sockopt(&ip_vs_sockopts);
if (ret) {
- IP_VS_ERR("cannot register sockopt.\n");
+ pr_err("cannot register sockopt.\n");
return ret;
}
ret = ip_vs_genl_register();
if (ret) {
- IP_VS_ERR("cannot register Generic Netlink interface.\n");
+ pr_err("cannot register Generic Netlink interface.\n");
nf_unregister_sockopt(&ip_vs_sockopts);
return ret;
}
diff --git a/net/netfilter/ipvs/ip_vs_dh.c b/net/netfilter/ipvs/ip_vs_dh.c
index a9dac74bb13..fe3e18834b9 100644
--- a/net/netfilter/ipvs/ip_vs_dh.c
+++ b/net/netfilter/ipvs/ip_vs_dh.c
@@ -35,6 +35,9 @@
*
*/
+#define KMSG_COMPONENT "IPVS"
+#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
+
#include <linux/ip.h>
#include <linux/module.h>
#include <linux/kernel.h>
@@ -147,7 +150,7 @@ static int ip_vs_dh_init_svc(struct ip_vs_service *svc)
tbl = kmalloc(sizeof(struct ip_vs_dh_bucket)*IP_VS_DH_TAB_SIZE,
GFP_ATOMIC);
if (tbl == NULL) {
- IP_VS_ERR("ip_vs_dh_init_svc(): no memory\n");
+ pr_err("%s(): no memory\n", __func__);
return -ENOMEM;
}
svc->sched_data = tbl;
@@ -214,7 +217,7 @@ ip_vs_dh_schedule(struct ip_vs_service *svc, const struct sk_buff *skb)
ip_vs_fill_iphdr(svc->af, skb_network_header(skb), &iph);
- IP_VS_DBG(6, "ip_vs_dh_schedule(): Scheduling...\n");
+ IP_VS_DBG(6, "%s(): Scheduling...\n", __func__);
tbl = (struct ip_vs_dh_bucket *)svc->sched_data;
dest = ip_vs_dh_get(svc->af, tbl, &iph.daddr);
diff --git a/net/netfilter/ipvs/ip_vs_est.c b/net/netfilter/ipvs/ip_vs_est.c
index 2eb2860dabb..702b53ca937 100644
--- a/net/netfilter/ipvs/ip_vs_est.c
+++ b/net/netfilter/ipvs/ip_vs_est.c
@@ -11,6 +11,10 @@
* Changes:
*
*/
+
+#define KMSG_COMPONENT "IPVS"
+#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
+
#include <linux/kernel.h>
#include <linux/jiffies.h>
#include <linux/slab.h>
diff --git a/net/netfilter/ipvs/ip_vs_ftp.c b/net/netfilter/ipvs/ip_vs_ftp.c
index 428edbf481c..33e2c799cba 100644
--- a/net/netfilter/ipvs/ip_vs_ftp.c
+++ b/net/netfilter/ipvs/ip_vs_ftp.c
@@ -22,6 +22,9 @@
*
*/
+#define KMSG_COMPONENT "IPVS"
+#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
+
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/kernel.h>
@@ -382,8 +385,8 @@ static int __init ip_vs_ftp_init(void)
ret = register_ip_vs_app_inc(app, app->protocol, ports[i]);
if (ret)
break;
- IP_VS_INFO("%s: loaded support on port[%d] = %d\n",
- app->name, i, ports[i]);
+ pr_info("%s: loaded support on port[%d] = %d\n",
+ app->name, i, ports[i]);
}
if (ret)
diff --git a/net/netfilter/ipvs/ip_vs_lblc.c b/net/netfilter/ipvs/ip_vs_lblc.c
index 3eb5e2660c4..c1757f3620c 100644
--- a/net/netfilter/ipvs/ip_vs_lblc.c
+++ b/net/netfilter/ipvs/ip_vs_lblc.c
@@ -39,6 +39,9 @@
* me to write this module.
*/
+#define KMSG_COMPONENT "IPVS"
+#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
+
#include <linux/ip.h>
#include <linux/module.h>
#include <linux/kernel.h>
@@ -199,7 +202,7 @@ ip_vs_lblc_new(struct ip_vs_lblc_table *tbl, const union nf_inet_addr *daddr,
if (!en) {
en = kmalloc(sizeof(*en), GFP_ATOMIC);
if (!en) {
- IP_VS_ERR("ip_vs_lblc_new(): no memory\n");
+ pr_err("%s(): no memory\n", __func__);
return NULL;
}
@@ -332,7 +335,7 @@ static int ip_vs_lblc_init_svc(struct ip_vs_service *svc)
*/
tbl = kmalloc(sizeof(*tbl), GFP_ATOMIC);
if (tbl == NULL) {
- IP_VS_ERR("ip_vs_lblc_init_svc(): no memory\n");
+ pr_err("%s(): no memory\n", __func__);
return -ENOMEM;
}
svc->sched_data = tbl;
@@ -477,7 +480,7 @@ ip_vs_lblc_schedule(struct ip_vs_service *svc, const struct sk_buff *skb)
ip_vs_fill_iphdr(svc->af, skb_network_header(skb), &iph);
- IP_VS_DBG(6, "ip_vs_lblc_schedule(): Scheduling...\n");
+ IP_VS_DBG(6, "%s(): Scheduling...\n", __func__);
/* First look in our cache */
read_lock(&svc->sched_lock);
diff --git a/net/netfilter/ipvs/ip_vs_lblcr.c b/net/netfilter/ipvs/ip_vs_lblcr.c
index c04ce56c7f0..715b57f9540 100644
--- a/net/netfilter/ipvs/ip_vs_lblcr.c
+++ b/net/netfilter/ipvs/ip_vs_lblcr.c
@@ -37,6 +37,9 @@
*
*/
+#define KMSG_COMPONENT "IPVS"
+#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
+
#include <linux/ip.h>
#include <linux/module.h>
#include <linux/kernel.h>
@@ -108,7 +111,7 @@ ip_vs_dest_set_insert(struct ip_vs_dest_set *set, struct ip_vs_dest *dest)
e = kmalloc(sizeof(*e), GFP_ATOMIC);
if (e == NULL) {
- IP_VS_ERR("ip_vs_dest_set_insert(): no memory\n");
+ pr_err("%s(): no memory\n", __func__);
return NULL;
}
@@ -202,8 +205,9 @@ static inline struct ip_vs_dest *ip_vs_dest_set_min(struct ip_vs_dest_set *set)
}
}
- IP_VS_DBG_BUF(6, "ip_vs_dest_set_min: server %s:%d "
+ IP_VS_DBG_BUF(6, "%s(): server %s:%d "
"activeconns %d refcnt %d weight %d overhead %d\n",
+ __func__,
IP_VS_DBG_ADDR(least->af, &least->addr),
ntohs(least->port),
atomic_read(&least->activeconns),
@@ -249,8 +253,9 @@ static inline struct ip_vs_dest *ip_vs_dest_set_max(struct ip_vs_dest_set *set)
}
}
- IP_VS_DBG_BUF(6, "ip_vs_dest_set_max: server %s:%d "
+ IP_VS_DBG_BUF(6, "%s(): server %s:%d "
"activeconns %d refcnt %d weight %d overhead %d\n",
+ __func__,
IP_VS_DBG_ADDR(most->af, &most->addr), ntohs(most->port),
atomic_read(&most->activeconns),
atomic_read(&most->refcnt),
@@ -374,7 +379,7 @@ ip_vs_lblcr_new(struct ip_vs_lblcr_table *tbl, const union nf_inet_addr *daddr,
if (!en) {
en = kmalloc(sizeof(*en), GFP_ATOMIC);
if (!en) {
- IP_VS_ERR("ip_vs_lblcr_new(): no memory\n");
+ pr_err("%s(): no memory\n", __func__);
return NULL;
}
@@ -508,7 +513,7 @@ static int ip_vs_lblcr_init_svc(struct ip_vs_service *svc)
*/
tbl = kmalloc(sizeof(*tbl), GFP_ATOMIC);
if (tbl == NULL) {
- IP_VS_ERR("ip_vs_lblcr_init_svc(): no memory\n");
+ pr_err("%s(): no memory\n", __func__);
return -ENOMEM;
}
svc->sched_data = tbl;
@@ -654,7 +659,7 @@ ip_vs_lblcr_schedule(struct ip_vs_service *svc, const struct sk_buff *skb)
ip_vs_fill_iphdr(svc->af, skb_network_header(skb), &iph);
- IP_VS_DBG(6, "ip_vs_lblcr_schedule(): Scheduling...\n");
+ IP_VS_DBG(6, "%s(): Scheduling...\n", __func__);
/* First look in our cache */
read_lock(&svc->sched_lock);
diff --git a/net/netfilter/ipvs/ip_vs_lc.c b/net/netfilter/ipvs/ip_vs_lc.c
index d0dadc8a65f..4f69db1fac5 100644
--- a/net/netfilter/ipvs/ip_vs_lc.c
+++ b/net/netfilter/ipvs/ip_vs_lc.c
@@ -14,6 +14,9 @@
*
*/
+#define KMSG_COMPONENT "IPVS"
+#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
+
#include <linux/module.h>
#include <linux/kernel.h>
@@ -44,7 +47,7 @@ ip_vs_lc_schedule(struct ip_vs_service *svc, const struct sk_buff *skb)
struct ip_vs_dest *dest, *least = NULL;
unsigned int loh = 0, doh;
- IP_VS_DBG(6, "ip_vs_lc_schedule(): Scheduling...\n");
+ IP_VS_DBG(6, "%s(): Scheduling...\n", __func__);
/*
* Simply select the server with the least number of
diff --git a/net/netfilter/ipvs/ip_vs_nq.c b/net/netfilter/ipvs/ip_vs_nq.c
index 694952db502..c413e183082 100644
--- a/net/netfilter/ipvs/ip_vs_nq.c
+++ b/net/netfilter/ipvs/ip_vs_nq.c
@@ -31,6 +31,9 @@
*
*/
+#define KMSG_COMPONENT "IPVS"
+#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
+
#include <linux/module.h>
#include <linux/kernel.h>
@@ -57,7 +60,7 @@ ip_vs_nq_schedule(struct ip_vs_service *svc, const struct sk_buff *skb)
struct ip_vs_dest *dest, *least = NULL;
unsigned int loh = 0, doh;
- IP_VS_DBG(6, "ip_vs_nq_schedule(): Scheduling...\n");
+ IP_VS_DBG(6, "%s(): Scheduling...\n", __func__);
/*
* We calculate the load of each dest server as follows:
diff --git a/net/netfilter/ipvs/ip_vs_proto.c b/net/netfilter/ipvs/ip_vs_proto.c
index a01520e3d6b..3e767167454 100644
--- a/net/netfilter/ipvs/ip_vs_proto.c
+++ b/net/netfilter/ipvs/ip_vs_proto.c
@@ -13,6 +13,9 @@
*
*/
+#define KMSG_COMPONENT "IPVS"
+#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
+
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/skbuff.h>
@@ -124,7 +127,8 @@ ip_vs_create_timeout_table(int *table, int size)
* Set timeout value for state specified by name
*/
int
-ip_vs_set_state_timeout(int *table, int num, char **names, char *name, int to)
+ip_vs_set_state_timeout(int *table, int num, const char *const *names,
+ const char *name, int to)
{
int i;
@@ -181,7 +185,7 @@ ip_vs_tcpudp_debug_packet_v4(struct ip_vs_protocol *pp,
&ih->daddr, ntohs(pptr[1]));
}
- printk(KERN_DEBUG "IPVS: %s: %s\n", msg, buf);
+ pr_debug("%s: %s\n", msg, buf);
}
#ifdef CONFIG_IP_VS_IPV6
@@ -215,7 +219,7 @@ ip_vs_tcpudp_debug_packet_v6(struct ip_vs_protocol *pp,
&ih->daddr, ntohs(pptr[1]));
}
- printk(KERN_DEBUG "IPVS: %s: %s\n", msg, buf);
+ pr_debug("%s: %s\n", msg, buf);
}
#endif
@@ -259,7 +263,7 @@ int __init ip_vs_protocol_init(void)
#ifdef CONFIG_IP_VS_PROTO_ESP
REGISTER_PROTOCOL(&ip_vs_protocol_esp);
#endif
- IP_VS_INFO("Registered protocols (%s)\n", &protocols[2]);
+ pr_info("Registered protocols (%s)\n", &protocols[2]);
return 0;
}
diff --git a/net/netfilter/ipvs/ip_vs_proto_ah_esp.c b/net/netfilter/ipvs/ip_vs_proto_ah_esp.c
index 79f56c1e7c1..c30b43c36cd 100644
--- a/net/netfilter/ipvs/ip_vs_proto_ah_esp.c
+++ b/net/netfilter/ipvs/ip_vs_proto_ah_esp.c
@@ -10,6 +10,9 @@
*
*/
+#define KMSG_COMPONENT "IPVS"
+#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
+
#include <linux/in.h>
#include <linux/ip.h>
#include <linux/module.h>
@@ -138,7 +141,7 @@ ah_esp_debug_packet_v4(struct ip_vs_protocol *pp, const struct sk_buff *skb,
sprintf(buf, "%s %pI4->%pI4",
pp->name, &ih->saddr, &ih->daddr);
- printk(KERN_DEBUG "IPVS: %s: %s\n", msg, buf);
+ pr_debug("%s: %s\n", msg, buf);
}
#ifdef CONFIG_IP_VS_IPV6
@@ -156,7 +159,7 @@ ah_esp_debug_packet_v6(struct ip_vs_protocol *pp, const struct sk_buff *skb,
sprintf(buf, "%s %pI6->%pI6",
pp->name, &ih->saddr, &ih->daddr);
- printk(KERN_DEBUG "IPVS: %s: %s\n", msg, buf);
+ pr_debug("%s: %s\n", msg, buf);
}
#endif
diff --git a/net/netfilter/ipvs/ip_vs_proto_tcp.c b/net/netfilter/ipvs/ip_vs_proto_tcp.c
index 8cba4180285..91d28e07374 100644
--- a/net/netfilter/ipvs/ip_vs_proto_tcp.c
+++ b/net/netfilter/ipvs/ip_vs_proto_tcp.c
@@ -13,6 +13,9 @@
*
*/
+#define KMSG_COMPONENT "IPVS"
+#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
+
#include <linux/kernel.h>
#include <linux/ip.h>
#include <linux/tcp.h> /* for tcphdr */
@@ -374,7 +377,7 @@ static int tcp_timeouts[IP_VS_TCP_S_LAST+1] = {
[IP_VS_TCP_S_LAST] = 2*HZ,
};
-static char * tcp_state_name_table[IP_VS_TCP_S_LAST+1] = {
+static const char *const tcp_state_name_table[IP_VS_TCP_S_LAST+1] = {
[IP_VS_TCP_S_NONE] = "NONE",
[IP_VS_TCP_S_ESTABLISHED] = "ESTABLISHED",
[IP_VS_TCP_S_SYN_SENT] = "SYN_SENT",
@@ -661,7 +664,7 @@ tcp_app_conn_bind(struct ip_vs_conn *cp)
break;
spin_unlock(&tcp_app_lock);
- IP_VS_DBG_BUF(9, "%s: Binding conn %s:%u->"
+ IP_VS_DBG_BUF(9, "%s(): Binding conn %s:%u->"
"%s:%u to app %s on port %u\n",
__func__,
IP_VS_DBG_ADDR(cp->af, &cp->caddr),
diff --git a/net/netfilter/ipvs/ip_vs_proto_udp.c b/net/netfilter/ipvs/ip_vs_proto_udp.c
index d2930a71084..e7a6885e016 100644
--- a/net/netfilter/ipvs/ip_vs_proto_udp.c
+++ b/net/netfilter/ipvs/ip_vs_proto_udp.c
@@ -13,6 +13,9 @@
*
*/
+#define KMSG_COMPONENT "IPVS"
+#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
+
#include <linux/in.h>
#include <linux/ip.h>
#include <linux/kernel.h>
@@ -442,7 +445,7 @@ static int udp_app_conn_bind(struct ip_vs_conn *cp)
break;
spin_unlock(&udp_app_lock);
- IP_VS_DBG_BUF(9, "%s: Binding conn %s:%u->"
+ IP_VS_DBG_BUF(9, "%s(): Binding conn %s:%u->"
"%s:%u to app %s on port %u\n",
__func__,
IP_VS_DBG_ADDR(cp->af, &cp->caddr),
@@ -469,7 +472,7 @@ static int udp_timeouts[IP_VS_UDP_S_LAST+1] = {
[IP_VS_UDP_S_LAST] = 2*HZ,
};
-static char * udp_state_name_table[IP_VS_UDP_S_LAST+1] = {
+static const char *const udp_state_name_table[IP_VS_UDP_S_LAST+1] = {
[IP_VS_UDP_S_NORMAL] = "UDP",
[IP_VS_UDP_S_LAST] = "BUG!",
};
diff --git a/net/netfilter/ipvs/ip_vs_rr.c b/net/netfilter/ipvs/ip_vs_rr.c
index 2d16ab7f8c1..e210f37d8ea 100644
--- a/net/netfilter/ipvs/ip_vs_rr.c
+++ b/net/netfilter/ipvs/ip_vs_rr.c
@@ -19,6 +19,9 @@
*
*/
+#define KMSG_COMPONENT "IPVS"
+#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
+
#include <linux/module.h>
#include <linux/kernel.h>
@@ -48,7 +51,7 @@ ip_vs_rr_schedule(struct ip_vs_service *svc, const struct sk_buff *skb)
struct list_head *p, *q;
struct ip_vs_dest *dest;
- IP_VS_DBG(6, "ip_vs_rr_schedule(): Scheduling...\n");
+ IP_VS_DBG(6, "%s(): Scheduling...\n", __func__);
write_lock(&svc->sched_lock);
p = (struct list_head *)svc->sched_data;
diff --git a/net/netfilter/ipvs/ip_vs_sched.c b/net/netfilter/ipvs/ip_vs_sched.c
index a46ad9e3501..bbc1ac79595 100644
--- a/net/netfilter/ipvs/ip_vs_sched.c
+++ b/net/netfilter/ipvs/ip_vs_sched.c
@@ -17,6 +17,9 @@
*
*/
+#define KMSG_COMPONENT "IPVS"
+#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
+
#include <linux/module.h>
#include <linux/spinlock.h>
#include <linux/interrupt.h>
@@ -44,11 +47,11 @@ int ip_vs_bind_scheduler(struct ip_vs_service *svc,
int ret;
if (svc == NULL) {
- IP_VS_ERR("ip_vs_bind_scheduler(): svc arg NULL\n");
+ pr_err("%s(): svc arg NULL\n", __func__);
return -EINVAL;
}
if (scheduler == NULL) {
- IP_VS_ERR("ip_vs_bind_scheduler(): scheduler arg NULL\n");
+ pr_err("%s(): scheduler arg NULL\n", __func__);
return -EINVAL;
}
@@ -57,7 +60,7 @@ int ip_vs_bind_scheduler(struct ip_vs_service *svc,
if (scheduler->init_service) {
ret = scheduler->init_service(svc);
if (ret) {
- IP_VS_ERR("ip_vs_bind_scheduler(): init error\n");
+ pr_err("%s(): init error\n", __func__);
return ret;
}
}
@@ -74,19 +77,19 @@ int ip_vs_unbind_scheduler(struct ip_vs_service *svc)
struct ip_vs_scheduler *sched;
if (svc == NULL) {
- IP_VS_ERR("ip_vs_unbind_scheduler(): svc arg NULL\n");
+ pr_err("%s(): svc arg NULL\n", __func__);
return -EINVAL;
}
sched = svc->scheduler;
if (sched == NULL) {
- IP_VS_ERR("ip_vs_unbind_scheduler(): svc isn't bound\n");
+ pr_err("%s(): svc isn't bound\n", __func__);
return -EINVAL;
}
if (sched->done_service) {
if (sched->done_service(svc) != 0) {
- IP_VS_ERR("ip_vs_unbind_scheduler(): done error\n");
+ pr_err("%s(): done error\n", __func__);
return -EINVAL;
}
}
@@ -103,8 +106,7 @@ static struct ip_vs_scheduler *ip_vs_sched_getbyname(const char *sched_name)
{
struct ip_vs_scheduler *sched;
- IP_VS_DBG(2, "ip_vs_sched_getbyname(): sched_name \"%s\"\n",
- sched_name);
+ IP_VS_DBG(2, "%s(): sched_name \"%s\"\n", __func__, sched_name);
read_lock_bh(&__ip_vs_sched_lock);
@@ -170,12 +172,12 @@ int register_ip_vs_scheduler(struct ip_vs_scheduler *scheduler)
struct ip_vs_scheduler *sched;
if (!scheduler) {
- IP_VS_ERR("register_ip_vs_scheduler(): NULL arg\n");
+ pr_err("%s(): NULL arg\n", __func__);
return -EINVAL;
}
if (!scheduler->name) {
- IP_VS_ERR("register_ip_vs_scheduler(): NULL scheduler_name\n");
+ pr_err("%s(): NULL scheduler_name\n", __func__);
return -EINVAL;
}
@@ -187,8 +189,8 @@ int register_ip_vs_scheduler(struct ip_vs_scheduler *scheduler)
if (!list_empty(&scheduler->n_list)) {
write_unlock_bh(&__ip_vs_sched_lock);
ip_vs_use_count_dec();
- IP_VS_ERR("register_ip_vs_scheduler(): [%s] scheduler "
- "already linked\n", scheduler->name);
+ pr_err("%s(): [%s] scheduler already linked\n",
+ __func__, scheduler->name);
return -EINVAL;
}
@@ -200,9 +202,8 @@ int register_ip_vs_scheduler(struct ip_vs_scheduler *scheduler)
if (strcmp(scheduler->name, sched->name) == 0) {
write_unlock_bh(&__ip_vs_sched_lock);
ip_vs_use_count_dec();
- IP_VS_ERR("register_ip_vs_scheduler(): [%s] scheduler "
- "already existed in the system\n",
- scheduler->name);
+ pr_err("%s(): [%s] scheduler already existed "
+ "in the system\n", __func__, scheduler->name);
return -EINVAL;
}
}
@@ -212,7 +213,7 @@ int register_ip_vs_scheduler(struct ip_vs_scheduler *scheduler)
list_add(&scheduler->n_list, &ip_vs_schedulers);
write_unlock_bh(&__ip_vs_sched_lock);
- IP_VS_INFO("[%s] scheduler registered.\n", scheduler->name);
+ pr_info("[%s] scheduler registered.\n", scheduler->name);
return 0;
}
@@ -224,15 +225,15 @@ int register_ip_vs_scheduler(struct ip_vs_scheduler *scheduler)
int unregister_ip_vs_scheduler(struct ip_vs_scheduler *scheduler)
{
if (!scheduler) {
- IP_VS_ERR( "unregister_ip_vs_scheduler(): NULL arg\n");
+ pr_err("%s(): NULL arg\n", __func__);
return -EINVAL;
}
write_lock_bh(&__ip_vs_sched_lock);
if (list_empty(&scheduler->n_list)) {
write_unlock_bh(&__ip_vs_sched_lock);
- IP_VS_ERR("unregister_ip_vs_scheduler(): [%s] scheduler "
- "is not in the list. failed\n", scheduler->name);
+ pr_err("%s(): [%s] scheduler is not in the list. failed\n",
+ __func__, scheduler->name);
return -EINVAL;
}
@@ -245,7 +246,7 @@ int unregister_ip_vs_scheduler(struct ip_vs_scheduler *scheduler)
/* decrease the module use count */
ip_vs_use_count_dec();
- IP_VS_INFO("[%s] scheduler unregistered.\n", scheduler->name);
+ pr_info("[%s] scheduler unregistered.\n", scheduler->name);
return 0;
}
diff --git a/net/netfilter/ipvs/ip_vs_sed.c b/net/netfilter/ipvs/ip_vs_sed.c
index 20e4657d2f3..1ab75a9dc40 100644
--- a/net/netfilter/ipvs/ip_vs_sed.c
+++ b/net/netfilter/ipvs/ip_vs_sed.c
@@ -35,6 +35,9 @@
*
*/
+#define KMSG_COMPONENT "IPVS"
+#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
+
#include <linux/module.h>
#include <linux/kernel.h>
@@ -61,7 +64,7 @@ ip_vs_sed_schedule(struct ip_vs_service *svc, const struct sk_buff *skb)
struct ip_vs_dest *dest, *least;
unsigned int loh, doh;
- IP_VS_DBG(6, "ip_vs_sed_schedule(): Scheduling...\n");
+ IP_VS_DBG(6, "%s(): Scheduling...\n", __func__);
/*
* We calculate the load of each dest server as follows:
diff --git a/net/netfilter/ipvs/ip_vs_sh.c b/net/netfilter/ipvs/ip_vs_sh.c
index 75709ebeb63..8e6cfd36e6f 100644
--- a/net/netfilter/ipvs/ip_vs_sh.c
+++ b/net/netfilter/ipvs/ip_vs_sh.c
@@ -32,6 +32,9 @@
*
*/
+#define KMSG_COMPONENT "IPVS"
+#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
+
#include <linux/ip.h>
#include <linux/module.h>
#include <linux/kernel.h>
@@ -144,7 +147,7 @@ static int ip_vs_sh_init_svc(struct ip_vs_service *svc)
tbl = kmalloc(sizeof(struct ip_vs_sh_bucket)*IP_VS_SH_TAB_SIZE,
GFP_ATOMIC);
if (tbl == NULL) {
- IP_VS_ERR("ip_vs_sh_init_svc(): no memory\n");
+ pr_err("%s(): no memory\n", __func__);
return -ENOMEM;
}
svc->sched_data = tbl;
diff --git a/net/netfilter/ipvs/ip_vs_sync.c b/net/netfilter/ipvs/ip_vs_sync.c
index 5c48378a852..e177f0dc208 100644
--- a/net/netfilter/ipvs/ip_vs_sync.c
+++ b/net/netfilter/ipvs/ip_vs_sync.c
@@ -17,6 +17,9 @@
* Justin Ossevoort : Fix endian problem on sync message size.
*/
+#define KMSG_COMPONENT "IPVS"
+#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
+
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/inetdevice.h>
@@ -243,7 +246,7 @@ void ip_vs_sync_conn(struct ip_vs_conn *cp)
if (!curr_sb) {
if (!(curr_sb=ip_vs_sync_buff_create())) {
spin_unlock(&curr_sb_lock);
- IP_VS_ERR("ip_vs_sync_buff_create failed.\n");
+ pr_err("ip_vs_sync_buff_create failed.\n");
return;
}
}
@@ -409,7 +412,7 @@ static void ip_vs_process_message(const char *buffer, const size_t buflen)
if (dest)
atomic_dec(&dest->refcnt);
if (!cp) {
- IP_VS_ERR("ip_vs_conn_new failed\n");
+ pr_err("ip_vs_conn_new failed\n");
return;
}
} else if (!cp->dest) {
@@ -577,8 +580,8 @@ static int bind_mcastif_addr(struct socket *sock, char *ifname)
addr = inet_select_addr(dev, 0, RT_SCOPE_UNIVERSE);
if (!addr)
- IP_VS_ERR("You probably need to specify IP address on "
- "multicast interface.\n");
+ pr_err("You probably need to specify IP address on "
+ "multicast interface.\n");
IP_VS_DBG(7, "binding socket with (%s) %pI4\n",
ifname, &addr);
@@ -602,13 +605,13 @@ static struct socket * make_send_sock(void)
/* First create a socket */
result = sock_create_kern(PF_INET, SOCK_DGRAM, IPPROTO_UDP, &sock);
if (result < 0) {
- IP_VS_ERR("Error during creation of socket; terminating\n");
+ pr_err("Error during creation of socket; terminating\n");
return ERR_PTR(result);
}
result = set_mcast_if(sock->sk, ip_vs_master_mcast_ifn);
if (result < 0) {
- IP_VS_ERR("Error setting outbound mcast interface\n");
+ pr_err("Error setting outbound mcast interface\n");
goto error;
}
@@ -617,14 +620,14 @@ static struct socket * make_send_sock(void)
result = bind_mcastif_addr(sock, ip_vs_master_mcast_ifn);
if (result < 0) {
- IP_VS_ERR("Error binding address of the mcast interface\n");
+ pr_err("Error binding address of the mcast interface\n");
goto error;
}
result = sock->ops->connect(sock, (struct sockaddr *) &mcast_addr,
sizeof(struct sockaddr), 0);
if (result < 0) {
- IP_VS_ERR("Error connecting to the multicast addr\n");
+ pr_err("Error connecting to the multicast addr\n");
goto error;
}
@@ -647,7 +650,7 @@ static struct socket * make_receive_sock(void)
/* First create a socket */
result = sock_create_kern(PF_INET, SOCK_DGRAM, IPPROTO_UDP, &sock);
if (result < 0) {
- IP_VS_ERR("Error during creation of socket; terminating\n");
+ pr_err("Error during creation of socket; terminating\n");
return ERR_PTR(result);
}
@@ -657,7 +660,7 @@ static struct socket * make_receive_sock(void)
result = sock->ops->bind(sock, (struct sockaddr *) &mcast_addr,
sizeof(struct sockaddr));
if (result < 0) {
- IP_VS_ERR("Error binding to the multicast addr\n");
+ pr_err("Error binding to the multicast addr\n");
goto error;
}
@@ -666,7 +669,7 @@ static struct socket * make_receive_sock(void)
(struct in_addr *) &mcast_addr.sin_addr,
ip_vs_backup_mcast_ifn);
if (result < 0) {
- IP_VS_ERR("Error joining to the multicast group\n");
+ pr_err("Error joining to the multicast group\n");
goto error;
}
@@ -706,7 +709,7 @@ ip_vs_send_sync_msg(struct socket *sock, struct ip_vs_sync_mesg *msg)
msg->size = htons(msg->size);
if (ip_vs_send_async(sock, (char *)msg, msize) != msize)
- IP_VS_ERR("ip_vs_send_async error\n");
+ pr_err("ip_vs_send_async error\n");
}
static int
@@ -737,9 +740,9 @@ static int sync_thread_master(void *data)
struct ip_vs_sync_thread_data *tinfo = data;
struct ip_vs_sync_buff *sb;
- IP_VS_INFO("sync thread started: state = MASTER, mcast_ifn = %s, "
- "syncid = %d\n",
- ip_vs_master_mcast_ifn, ip_vs_master_syncid);
+ pr_info("sync thread started: state = MASTER, mcast_ifn = %s, "
+ "syncid = %d\n",
+ ip_vs_master_mcast_ifn, ip_vs_master_syncid);
while (!kthread_should_stop()) {
while ((sb = sb_dequeue())) {
@@ -780,9 +783,9 @@ static int sync_thread_backup(void *data)
struct ip_vs_sync_thread_data *tinfo = data;
int len;
- IP_VS_INFO("sync thread started: state = BACKUP, mcast_ifn = %s, "
- "syncid = %d\n",
- ip_vs_backup_mcast_ifn, ip_vs_backup_syncid);
+ pr_info("sync thread started: state = BACKUP, mcast_ifn = %s, "
+ "syncid = %d\n",
+ ip_vs_backup_mcast_ifn, ip_vs_backup_syncid);
while (!kthread_should_stop()) {
wait_event_interruptible(*tinfo->sock->sk->sk_sleep,
@@ -794,7 +797,7 @@ static int sync_thread_backup(void *data)
len = ip_vs_receive(tinfo->sock, tinfo->buf,
sync_recv_mesg_maxlen);
if (len <= 0) {
- IP_VS_ERR("receiving message error\n");
+ pr_err("receiving message error\n");
break;
}
@@ -824,7 +827,7 @@ int start_sync_thread(int state, char *mcast_ifn, __u8 syncid)
int (*threadfn)(void *data);
int result = -ENOMEM;
- IP_VS_DBG(7, "%s: pid %d\n", __func__, task_pid_nr(current));
+ IP_VS_DBG(7, "%s(): pid %d\n", __func__, task_pid_nr(current));
IP_VS_DBG(7, "Each ip_vs_sync_conn entry needs %Zd bytes\n",
sizeof(struct ip_vs_sync_conn));
@@ -901,14 +904,14 @@ out:
int stop_sync_thread(int state)
{
- IP_VS_DBG(7, "%s: pid %d\n", __func__, task_pid_nr(current));
+ IP_VS_DBG(7, "%s(): pid %d\n", __func__, task_pid_nr(current));
if (state == IP_VS_STATE_MASTER) {
if (!sync_master_thread)
return -ESRCH;
- IP_VS_INFO("stopping master sync thread %d ...\n",
- task_pid_nr(sync_master_thread));
+ pr_info("stopping master sync thread %d ...\n",
+ task_pid_nr(sync_master_thread));
/*
* The lock synchronizes with sb_queue_tail(), so that we don't
@@ -925,8 +928,8 @@ int stop_sync_thread(int state)
if (!sync_backup_thread)
return -ESRCH;
- IP_VS_INFO("stopping backup sync thread %d ...\n",
- task_pid_nr(sync_backup_thread));
+ pr_info("stopping backup sync thread %d ...\n",
+ task_pid_nr(sync_backup_thread));
ip_vs_sync_state &= ~IP_VS_STATE_BACKUP;
kthread_stop(sync_backup_thread);
diff --git a/net/netfilter/ipvs/ip_vs_wlc.c b/net/netfilter/ipvs/ip_vs_wlc.c
index 8e942565b47..bbddfdb10db 100644
--- a/net/netfilter/ipvs/ip_vs_wlc.c
+++ b/net/netfilter/ipvs/ip_vs_wlc.c
@@ -19,6 +19,9 @@
*
*/
+#define KMSG_COMPONENT "IPVS"
+#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
+
#include <linux/module.h>
#include <linux/kernel.h>
diff --git a/net/netfilter/ipvs/ip_vs_wrr.c b/net/netfilter/ipvs/ip_vs_wrr.c
index f7d74ef1ecf..70ff82cda57 100644
--- a/net/netfilter/ipvs/ip_vs_wrr.c
+++ b/net/netfilter/ipvs/ip_vs_wrr.c
@@ -18,6 +18,9 @@
*
*/
+#define KMSG_COMPONENT "IPVS"
+#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
+
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/net.h>
@@ -94,7 +97,7 @@ static int ip_vs_wrr_init_svc(struct ip_vs_service *svc)
*/
mark = kmalloc(sizeof(struct ip_vs_wrr_mark), GFP_ATOMIC);
if (mark == NULL) {
- IP_VS_ERR("ip_vs_wrr_init_svc(): no memory\n");
+ pr_err("%s(): no memory\n", __func__);
return -ENOMEM;
}
mark->cl = &svc->destinations;
@@ -141,7 +144,7 @@ ip_vs_wrr_schedule(struct ip_vs_service *svc, const struct sk_buff *skb)
struct ip_vs_wrr_mark *mark = svc->sched_data;
struct list_head *p;
- IP_VS_DBG(6, "ip_vs_wrr_schedule(): Scheduling...\n");
+ IP_VS_DBG(6, "%s(): Scheduling...\n", __func__);
/*
* This loop will always terminate, because mark->cw in (0, max_weight]
diff --git a/net/netfilter/ipvs/ip_vs_xmit.c b/net/netfilter/ipvs/ip_vs_xmit.c
index 5874657af7f..30b3189bd29 100644
--- a/net/netfilter/ipvs/ip_vs_xmit.c
+++ b/net/netfilter/ipvs/ip_vs_xmit.c
@@ -13,6 +13,9 @@
*
*/
+#define KMSG_COMPONENT "IPVS"
+#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
+
#include <linux/kernel.h>
#include <linux/tcp.h> /* for tcphdr */
#include <net/ip.h>
@@ -235,8 +238,8 @@ ip_vs_bypass_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
EnterFunction(10);
if (ip_route_output_key(&init_net, &rt, &fl)) {
- IP_VS_DBG_RL("ip_vs_bypass_xmit(): ip_route_output error, dest: %pI4\n",
- &iph->daddr);
+ IP_VS_DBG_RL("%s(): ip_route_output error, dest: %pI4\n",
+ __func__, &iph->daddr);
goto tx_error_icmp;
}
@@ -245,7 +248,7 @@ ip_vs_bypass_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
if ((skb->len > mtu) && (iph->frag_off & htons(IP_DF))) {
ip_rt_put(rt);
icmp_send(skb, ICMP_DEST_UNREACH,ICMP_FRAG_NEEDED, htonl(mtu));
- IP_VS_DBG_RL("ip_vs_bypass_xmit(): frag needed\n");
+ IP_VS_DBG_RL("%s(): frag needed\n", __func__);
goto tx_error;
}
@@ -299,8 +302,8 @@ ip_vs_bypass_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
rt = (struct rt6_info *)ip6_route_output(&init_net, NULL, &fl);
if (!rt) {
- IP_VS_DBG_RL("ip_vs_bypass_xmit_v6(): ip6_route_output error, dest: %pI6\n",
- &iph->daddr);
+ IP_VS_DBG_RL("%s(): ip6_route_output error, dest: %pI6\n",
+ __func__, &iph->daddr);
goto tx_error_icmp;
}
@@ -309,7 +312,7 @@ ip_vs_bypass_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
if (skb->len > mtu) {
dst_release(&rt->u.dst);
icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu, skb->dev);
- IP_VS_DBG_RL("ip_vs_bypass_xmit_v6(): frag needed\n");
+ IP_VS_DBG_RL("%s(): frag needed\n", __func__);
goto tx_error;
}
@@ -536,9 +539,9 @@ ip_vs_tunnel_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
EnterFunction(10);
if (skb->protocol != htons(ETH_P_IP)) {
- IP_VS_DBG_RL("ip_vs_tunnel_xmit(): protocol error, "
+ IP_VS_DBG_RL("%s(): protocol error, "
"ETH_P_IP: %d, skb protocol: %d\n",
- htons(ETH_P_IP), skb->protocol);
+ __func__, htons(ETH_P_IP), skb->protocol);
goto tx_error;
}
@@ -550,7 +553,7 @@ ip_vs_tunnel_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
mtu = dst_mtu(&rt->u.dst) - sizeof(struct iphdr);
if (mtu < 68) {
ip_rt_put(rt);
- IP_VS_DBG_RL("ip_vs_tunnel_xmit(): mtu less than 68\n");
+ IP_VS_DBG_RL("%s(): mtu less than 68\n", __func__);
goto tx_error;
}
if (skb_dst(skb))
@@ -562,7 +565,7 @@ ip_vs_tunnel_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
&& mtu < ntohs(old_iph->tot_len)) {
icmp_send(skb, ICMP_DEST_UNREACH,ICMP_FRAG_NEEDED, htonl(mtu));
ip_rt_put(rt);
- IP_VS_DBG_RL("ip_vs_tunnel_xmit(): frag needed\n");
+ IP_VS_DBG_RL("%s(): frag needed\n", __func__);
goto tx_error;
}
@@ -578,7 +581,7 @@ ip_vs_tunnel_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
if (!new_skb) {
ip_rt_put(rt);
kfree_skb(skb);
- IP_VS_ERR_RL("ip_vs_tunnel_xmit(): no memory\n");
+ IP_VS_ERR_RL("%s(): no memory\n", __func__);
return NF_STOLEN;
}
kfree_skb(skb);
@@ -646,9 +649,9 @@ ip_vs_tunnel_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
EnterFunction(10);
if (skb->protocol != htons(ETH_P_IPV6)) {
- IP_VS_DBG_RL("ip_vs_tunnel_xmit_v6(): protocol error, "
+ IP_VS_DBG_RL("%s(): protocol error, "
"ETH_P_IPV6: %d, skb protocol: %d\n",
- htons(ETH_P_IPV6), skb->protocol);
+ __func__, htons(ETH_P_IPV6), skb->protocol);
goto tx_error;
}
@@ -662,7 +665,7 @@ ip_vs_tunnel_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
/* TODO IPv6: do we need this check in IPv6? */
if (mtu < 1280) {
dst_release(&rt->u.dst);
- IP_VS_DBG_RL("ip_vs_tunnel_xmit_v6(): mtu less than 1280\n");
+ IP_VS_DBG_RL("%s(): mtu less than 1280\n", __func__);
goto tx_error;
}
if (skb_dst(skb))
@@ -671,7 +674,7 @@ ip_vs_tunnel_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
if (mtu < ntohs(old_iph->payload_len) + sizeof(struct ipv6hdr)) {
icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu, skb->dev);
dst_release(&rt->u.dst);
- IP_VS_DBG_RL("ip_vs_tunnel_xmit_v6(): frag needed\n");
+ IP_VS_DBG_RL("%s(): frag needed\n", __func__);
goto tx_error;
}
@@ -687,7 +690,7 @@ ip_vs_tunnel_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
if (!new_skb) {
dst_release(&rt->u.dst);
kfree_skb(skb);
- IP_VS_ERR_RL("ip_vs_tunnel_xmit_v6(): no memory\n");
+ IP_VS_ERR_RL("%s(): no memory\n", __func__);
return NF_STOLEN;
}
kfree_skb(skb);
@@ -760,7 +763,7 @@ ip_vs_dr_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
if ((iph->frag_off & htons(IP_DF)) && skb->len > mtu) {
icmp_send(skb, ICMP_DEST_UNREACH,ICMP_FRAG_NEEDED, htonl(mtu));
ip_rt_put(rt);
- IP_VS_DBG_RL("ip_vs_dr_xmit(): frag needed\n");
+ IP_VS_DBG_RL("%s(): frag needed\n", __func__);
goto tx_error;
}
@@ -813,7 +816,7 @@ ip_vs_dr_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
if (skb->len > mtu) {
icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu, skb->dev);
dst_release(&rt->u.dst);
- IP_VS_DBG_RL("ip_vs_dr_xmit_v6(): frag needed\n");
+ IP_VS_DBG_RL("%s(): frag needed\n", __func__);
goto tx_error;
}
@@ -888,7 +891,7 @@ ip_vs_icmp_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
if ((skb->len > mtu) && (ip_hdr(skb)->frag_off & htons(IP_DF))) {
ip_rt_put(rt);
icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(mtu));
- IP_VS_DBG_RL("ip_vs_in_icmp(): frag needed\n");
+ IP_VS_DBG_RL("%s(): frag needed\n", __func__);
goto tx_error;
}
@@ -963,7 +966,7 @@ ip_vs_icmp_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
if (skb->len > mtu) {
dst_release(&rt->u.dst);
icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu, skb->dev);
- IP_VS_DBG_RL("ip_vs_in_icmp(): frag needed\n");
+ IP_VS_DBG_RL("%s(): frag needed\n", __func__);
goto tx_error;
}
diff --git a/net/netlabel/netlabel_kapi.c b/net/netlabel/netlabel_kapi.c
index 16e6c4378ff..6ce00205f34 100644
--- a/net/netlabel/netlabel_kapi.c
+++ b/net/netlabel/netlabel_kapi.c
@@ -185,8 +185,7 @@ int netlbl_cfg_unlbl_map_add(const char *domain,
return 0;
cfg_unlbl_map_add_failure:
- if (entry != NULL)
- kfree(entry->domain);
+ kfree(entry->domain);
kfree(entry);
kfree(addrmap);
kfree(map4);
@@ -385,8 +384,7 @@ int netlbl_cfg_cipsov4_map_add(u32 doi,
cfg_cipsov4_map_add_failure:
cipso_v4_doi_putdef(doi_def);
- if (entry != NULL)
- kfree(entry->domain);
+ kfree(entry->domain);
kfree(entry);
kfree(addrmap);
kfree(addrinfo);
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index 2936fa3b6dc..da3163d15ef 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -83,6 +83,11 @@ struct netlink_sock {
struct module *module;
};
+struct listeners_rcu_head {
+ struct rcu_head rcu_head;
+ void *ptr;
+};
+
#define NETLINK_KERNEL_SOCKET 0x1
#define NETLINK_RECV_PKTINFO 0x2
#define NETLINK_BROADCAST_SEND_ERROR 0x4
@@ -1356,7 +1361,7 @@ static int netlink_recvmsg(struct kiocb *kiocb, struct socket *sock,
struct netlink_sock *nlk = nlk_sk(sk);
int noblock = flags&MSG_DONTWAIT;
size_t copied;
- struct sk_buff *skb;
+ struct sk_buff *skb, *frag __maybe_unused = NULL;
int err;
if (flags&MSG_OOB)
@@ -1368,6 +1373,35 @@ static int netlink_recvmsg(struct kiocb *kiocb, struct socket *sock,
if (skb == NULL)
goto out;
+#ifdef CONFIG_COMPAT_NETLINK_MESSAGES
+ if (unlikely(skb_shinfo(skb)->frag_list)) {
+ bool need_compat = !!(flags & MSG_CMSG_COMPAT);
+
+ /*
+ * If this skb has a frag_list, then here that means that
+ * we will have to use the frag_list skb for compat tasks
+ * and the regular skb for non-compat tasks.
+ *
+ * The skb might (and likely will) be cloned, so we can't
+ * just reset frag_list and go on with things -- we need to
+ * keep that. For the compat case that's easy -- simply get
+ * a reference to the compat skb and free the regular one
+ * including the frag. For the non-compat case, we need to
+ * avoid sending the frag to the user -- so assign NULL but
+ * restore it below before freeing the skb.
+ */
+ if (need_compat) {
+ struct sk_buff *compskb = skb_shinfo(skb)->frag_list;
+ skb_get(compskb);
+ kfree_skb(skb);
+ skb = compskb;
+ } else {
+ frag = skb_shinfo(skb)->frag_list;
+ skb_shinfo(skb)->frag_list = NULL;
+ }
+ }
+#endif
+
msg->msg_namelen = 0;
copied = skb->len;
@@ -1398,6 +1432,11 @@ static int netlink_recvmsg(struct kiocb *kiocb, struct socket *sock,
siocb->scm->creds = *NETLINK_CREDS(skb);
if (flags & MSG_TRUNC)
copied = skb->len;
+
+#ifdef CONFIG_COMPAT_NETLINK_MESSAGES
+ skb_shinfo(skb)->frag_list = frag;
+#endif
+
skb_free_datagram(sk, skb);
if (nlk->cb && atomic_read(&sk->sk_rmem_alloc) <= sk->sk_rcvbuf / 2)
@@ -1453,7 +1492,8 @@ netlink_kernel_create(struct net *net, int unit, unsigned int groups,
if (groups < 32)
groups = 32;
- listeners = kzalloc(NLGRPSZ(groups), GFP_KERNEL);
+ listeners = kzalloc(NLGRPSZ(groups) + sizeof(struct listeners_rcu_head),
+ GFP_KERNEL);
if (!listeners)
goto out_sock_release;
@@ -1501,6 +1541,14 @@ netlink_kernel_release(struct sock *sk)
EXPORT_SYMBOL(netlink_kernel_release);
+static void netlink_free_old_listeners(struct rcu_head *rcu_head)
+{
+ struct listeners_rcu_head *lrh;
+
+ lrh = container_of(rcu_head, struct listeners_rcu_head, rcu_head);
+ kfree(lrh->ptr);
+}
+
/**
* netlink_change_ngroups - change number of multicast groups
*
@@ -1516,6 +1564,7 @@ EXPORT_SYMBOL(netlink_kernel_release);
int netlink_change_ngroups(struct sock *sk, unsigned int groups)
{
unsigned long *listeners, *old = NULL;
+ struct listeners_rcu_head *old_rcu_head;
struct netlink_table *tbl = &nl_table[sk->sk_protocol];
int err = 0;
@@ -1524,7 +1573,9 @@ int netlink_change_ngroups(struct sock *sk, unsigned int groups)
netlink_table_grab();
if (NLGRPSZ(tbl->groups) < NLGRPSZ(groups)) {
- listeners = kzalloc(NLGRPSZ(groups), GFP_ATOMIC);
+ listeners = kzalloc(NLGRPSZ(groups) +
+ sizeof(struct listeners_rcu_head),
+ GFP_ATOMIC);
if (!listeners) {
err = -ENOMEM;
goto out_ungrab;
@@ -1532,16 +1583,24 @@ int netlink_change_ngroups(struct sock *sk, unsigned int groups)
old = tbl->listeners;
memcpy(listeners, old, NLGRPSZ(tbl->groups));
rcu_assign_pointer(tbl->listeners, listeners);
+ /*
+ * Free the old memory after an RCU grace period so we
+ * don't leak it. We use call_rcu() here in order to be
+ * able to call this function from atomic contexts. The
+ * allocation of this memory will have reserved enough
+ * space for struct listeners_rcu_head at the end.
+ */
+ old_rcu_head = (void *)(tbl->listeners +
+ NLGRPLONGS(tbl->groups));
+ old_rcu_head->ptr = old;
+ call_rcu(&old_rcu_head->rcu_head, netlink_free_old_listeners);
}
tbl->groups = groups;
out_ungrab:
netlink_table_ungrab();
- synchronize_rcu();
- kfree(old);
return err;
}
-EXPORT_SYMBOL(netlink_change_ngroups);
/**
* netlink_clear_multicast_users - kick off multicast listeners
@@ -1564,7 +1623,6 @@ void netlink_clear_multicast_users(struct sock *ksk, unsigned int group)
netlink_table_ungrab();
}
-EXPORT_SYMBOL(netlink_clear_multicast_users);
void netlink_set_nonroot(int protocol, unsigned int flags)
{
diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c
index eed4c6a8afc..575c6434150 100644
--- a/net/netlink/genetlink.c
+++ b/net/netlink/genetlink.c
@@ -18,8 +18,6 @@
#include <net/sock.h>
#include <net/genetlink.h>
-struct sock *genl_sock = NULL;
-
static DEFINE_MUTEX(genl_mutex); /* serialization of message processing */
static inline void genl_lock(void)
@@ -175,10 +173,31 @@ int genl_register_mc_group(struct genl_family *family,
mc_groups_longs++;
}
- err = netlink_change_ngroups(genl_sock,
- mc_groups_longs * BITS_PER_LONG);
- if (err)
- goto out;
+ if (family->netnsok) {
+ struct net *net;
+
+ rcu_read_lock();
+ for_each_net_rcu(net) {
+ err = netlink_change_ngroups(net->genl_sock,
+ mc_groups_longs * BITS_PER_LONG);
+ if (err) {
+ /*
+ * No need to roll back, can only fail if
+ * memory allocation fails and then the
+ * number of _possible_ groups has been
+ * increased on some sockets which is ok.
+ */
+ rcu_read_unlock();
+ goto out;
+ }
+ }
+ rcu_read_unlock();
+ } else {
+ err = netlink_change_ngroups(init_net.genl_sock,
+ mc_groups_longs * BITS_PER_LONG);
+ if (err)
+ goto out;
+ }
grp->id = id;
set_bit(id, mc_groups);
@@ -195,8 +214,14 @@ EXPORT_SYMBOL(genl_register_mc_group);
static void __genl_unregister_mc_group(struct genl_family *family,
struct genl_multicast_group *grp)
{
+ struct net *net;
BUG_ON(grp->family != family);
- netlink_clear_multicast_users(genl_sock, grp->id);
+
+ rcu_read_lock();
+ for_each_net_rcu(net)
+ netlink_clear_multicast_users(net->genl_sock, grp->id);
+ rcu_read_unlock();
+
clear_bit(grp->id, mc_groups);
list_del(&grp->list);
genl_ctrl_event(CTRL_CMD_DELMCAST_GRP, grp);
@@ -467,6 +492,7 @@ static int genl_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
{
struct genl_ops *ops;
struct genl_family *family;
+ struct net *net = sock_net(skb->sk);
struct genl_info info;
struct genlmsghdr *hdr = nlmsg_data(nlh);
int hdrlen, err;
@@ -475,6 +501,10 @@ static int genl_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
if (family == NULL)
return -ENOENT;
+ /* this family doesn't exist in this netns */
+ if (!family->netnsok && !net_eq(net, &init_net))
+ return -ENOENT;
+
hdrlen = GENL_HDRLEN + family->hdrsize;
if (nlh->nlmsg_len < nlmsg_msg_size(hdrlen))
return -EINVAL;
@@ -492,7 +522,7 @@ static int genl_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
return -EOPNOTSUPP;
genl_unlock();
- err = netlink_dump_start(genl_sock, skb, nlh,
+ err = netlink_dump_start(net->genl_sock, skb, nlh,
ops->dumpit, ops->done);
genl_lock();
return err;
@@ -514,6 +544,7 @@ static int genl_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
info.genlhdr = nlmsg_data(nlh);
info.userhdr = nlmsg_data(nlh) + GENL_HDRLEN;
info.attrs = family->attrbuf;
+ genl_info_net_set(&info, net);
return ops->doit(skb, &info);
}
@@ -534,6 +565,7 @@ static struct genl_family genl_ctrl = {
.name = "nlctrl",
.version = 0x2,
.maxattr = CTRL_ATTR_MAX,
+ .netnsok = true,
};
static int ctrl_fill_info(struct genl_family *family, u32 pid, u32 seq,
@@ -650,6 +682,7 @@ static int ctrl_dumpfamily(struct sk_buff *skb, struct netlink_callback *cb)
int i, n = 0;
struct genl_family *rt;
+ struct net *net = sock_net(skb->sk);
int chains_to_skip = cb->args[0];
int fams_to_skip = cb->args[1];
@@ -658,6 +691,8 @@ static int ctrl_dumpfamily(struct sk_buff *skb, struct netlink_callback *cb)
continue;
n = 0;
list_for_each_entry(rt, genl_family_chain(i), family_list) {
+ if (!rt->netnsok && !net_eq(net, &init_net))
+ continue;
if (++n < fams_to_skip)
continue;
if (ctrl_fill_info(rt, NETLINK_CB(cb->skb).pid,
@@ -729,6 +764,7 @@ static int ctrl_getfamily(struct sk_buff *skb, struct genl_info *info)
if (info->attrs[CTRL_ATTR_FAMILY_ID]) {
u16 id = nla_get_u16(info->attrs[CTRL_ATTR_FAMILY_ID]);
res = genl_family_find_byid(id);
+ err = -ENOENT;
}
if (info->attrs[CTRL_ATTR_FAMILY_NAME]) {
@@ -736,49 +772,61 @@ static int ctrl_getfamily(struct sk_buff *skb, struct genl_info *info)
name = nla_data(info->attrs[CTRL_ATTR_FAMILY_NAME]);
res = genl_family_find_byname(name);
+ err = -ENOENT;
}
- if (res == NULL) {
- err = -ENOENT;
- goto errout;
+ if (res == NULL)
+ return err;
+
+ if (!res->netnsok && !net_eq(genl_info_net(info), &init_net)) {
+ /* family doesn't exist here */
+ return -ENOENT;
}
msg = ctrl_build_family_msg(res, info->snd_pid, info->snd_seq,
CTRL_CMD_NEWFAMILY);
- if (IS_ERR(msg)) {
- err = PTR_ERR(msg);
- goto errout;
- }
+ if (IS_ERR(msg))
+ return PTR_ERR(msg);
- err = genlmsg_reply(msg, info);
-errout:
- return err;
+ return genlmsg_reply(msg, info);
}
static int genl_ctrl_event(int event, void *data)
{
struct sk_buff *msg;
+ struct genl_family *family;
+ struct genl_multicast_group *grp;
- if (genl_sock == NULL)
+ /* genl is still initialising */
+ if (!init_net.genl_sock)
return 0;
switch (event) {
case CTRL_CMD_NEWFAMILY:
case CTRL_CMD_DELFAMILY:
- msg = ctrl_build_family_msg(data, 0, 0, event);
- if (IS_ERR(msg))
- return PTR_ERR(msg);
-
- genlmsg_multicast(msg, 0, GENL_ID_CTRL, GFP_KERNEL);
+ family = data;
+ msg = ctrl_build_family_msg(family, 0, 0, event);
break;
case CTRL_CMD_NEWMCAST_GRP:
case CTRL_CMD_DELMCAST_GRP:
+ grp = data;
+ family = grp->family;
msg = ctrl_build_mcgrp_msg(data, 0, 0, event);
- if (IS_ERR(msg))
- return PTR_ERR(msg);
-
- genlmsg_multicast(msg, 0, GENL_ID_CTRL, GFP_KERNEL);
break;
+ default:
+ return -EINVAL;
+ }
+
+ if (IS_ERR(msg))
+ return PTR_ERR(msg);
+
+ if (!family->netnsok) {
+ genlmsg_multicast_netns(&init_net, msg, 0,
+ GENL_ID_CTRL, GFP_KERNEL);
+ } else {
+ rcu_read_lock();
+ genlmsg_multicast_allns(msg, 0, GENL_ID_CTRL, GFP_ATOMIC);
+ rcu_read_unlock();
}
return 0;
@@ -795,6 +843,33 @@ static struct genl_multicast_group notify_grp = {
.name = "notify",
};
+static int __net_init genl_pernet_init(struct net *net)
+{
+ /* we'll bump the group number right afterwards */
+ net->genl_sock = netlink_kernel_create(net, NETLINK_GENERIC, 0,
+ genl_rcv, &genl_mutex,
+ THIS_MODULE);
+
+ if (!net->genl_sock && net_eq(net, &init_net))
+ panic("GENL: Cannot initialize generic netlink\n");
+
+ if (!net->genl_sock)
+ return -ENOMEM;
+
+ return 0;
+}
+
+static void __net_exit genl_pernet_exit(struct net *net)
+{
+ netlink_kernel_release(net->genl_sock);
+ net->genl_sock = NULL;
+}
+
+static struct pernet_operations genl_pernet_ops = {
+ .init = genl_pernet_init,
+ .exit = genl_pernet_exit,
+};
+
static int __init genl_init(void)
{
int i, err;
@@ -804,36 +879,67 @@ static int __init genl_init(void)
err = genl_register_family(&genl_ctrl);
if (err < 0)
- goto errout;
+ goto problem;
err = genl_register_ops(&genl_ctrl, &genl_ctrl_ops);
if (err < 0)
- goto errout_register;
+ goto problem;
netlink_set_nonroot(NETLINK_GENERIC, NL_NONROOT_RECV);
- /* we'll bump the group number right afterwards */
- genl_sock = netlink_kernel_create(&init_net, NETLINK_GENERIC, 0,
- genl_rcv, &genl_mutex, THIS_MODULE);
- if (genl_sock == NULL)
- panic("GENL: Cannot initialize generic netlink\n");
+ err = register_pernet_subsys(&genl_pernet_ops);
+ if (err)
+ goto problem;
err = genl_register_mc_group(&genl_ctrl, &notify_grp);
if (err < 0)
- goto errout_register;
+ goto problem;
return 0;
-errout_register:
- genl_unregister_family(&genl_ctrl);
-errout:
+problem:
panic("GENL: Cannot register controller: %d\n", err);
}
subsys_initcall(genl_init);
-EXPORT_SYMBOL(genl_sock);
EXPORT_SYMBOL(genl_register_ops);
EXPORT_SYMBOL(genl_unregister_ops);
EXPORT_SYMBOL(genl_register_family);
EXPORT_SYMBOL(genl_unregister_family);
+
+static int genlmsg_mcast(struct sk_buff *skb, u32 pid, unsigned long group,
+ gfp_t flags)
+{
+ struct sk_buff *tmp;
+ struct net *net, *prev = NULL;
+ int err;
+
+ for_each_net_rcu(net) {
+ if (prev) {
+ tmp = skb_clone(skb, flags);
+ if (!tmp) {
+ err = -ENOMEM;
+ goto error;
+ }
+ err = nlmsg_multicast(prev->genl_sock, tmp,
+ pid, group, flags);
+ if (err)
+ goto error;
+ }
+
+ prev = net;
+ }
+
+ return nlmsg_multicast(prev->genl_sock, skb, pid, group, flags);
+ error:
+ kfree_skb(skb);
+ return err;
+}
+
+int genlmsg_multicast_allns(struct sk_buff *skb, u32 pid, unsigned int group,
+ gfp_t flags)
+{
+ return genlmsg_mcast(skb, pid, group, flags);
+}
+EXPORT_SYMBOL(genlmsg_multicast_allns);
diff --git a/net/netrom/nr_dev.c b/net/netrom/nr_dev.c
index 351372463fe..c7b7838a051 100644
--- a/net/netrom/nr_dev.c
+++ b/net/netrom/nr_dev.c
@@ -177,13 +177,13 @@ static int nr_xmit(struct sk_buff *skb, struct net_device *dev)
if (!nr_route_frame(skb, NULL)) {
kfree_skb(skb);
stats->tx_errors++;
- return 0;
+ return NETDEV_TX_OK;
}
stats->tx_packets++;
stats->tx_bytes += len;
- return 0;
+ return NETDEV_TX_OK;
}
static const struct header_ops nr_header_ops = {
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index ebe5718baa3..d3d52c66cdc 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -137,8 +137,7 @@ dev->hard_header == NULL (ll header is added by device, we cannot control it)
/* Private packet socket structures. */
-struct packet_mclist
-{
+struct packet_mclist {
struct packet_mclist *next;
int ifindex;
int count;
@@ -149,8 +148,7 @@ struct packet_mclist
/* identical to struct packet_mreq except it has
* a longer address field.
*/
-struct packet_mreq_max
-{
+struct packet_mreq_max {
int mr_ifindex;
unsigned short mr_type;
unsigned short mr_alen;
@@ -162,7 +160,7 @@ static int packet_set_ring(struct sock *sk, struct tpacket_req *req,
int closing, int tx_ring);
struct packet_ring_buffer {
- char * *pg_vec;
+ char **pg_vec;
unsigned int head;
unsigned int frames_per_block;
unsigned int frame_size;
@@ -239,7 +237,7 @@ static void __packet_set_status(struct packet_sock *po, void *frame, int status)
flush_dcache_page(virt_to_page(&h.h2->tp_status));
break;
default:
- printk(KERN_ERR "TPACKET version not supported\n");
+ pr_err("TPACKET version not supported\n");
BUG();
}
@@ -265,7 +263,7 @@ static int __packet_get_status(struct packet_sock *po, void *frame)
flush_dcache_page(virt_to_page(&h.h2->tp_status));
return h.h2->tp_status;
default:
- printk(KERN_ERR "TPACKET version not supported\n");
+ pr_err("TPACKET version not supported\n");
BUG();
return 0;
}
@@ -327,7 +325,7 @@ static void packet_sock_destruct(struct sock *sk)
WARN_ON(atomic_read(&sk->sk_wmem_alloc));
if (!sock_flag(sk, SOCK_DEAD)) {
- printk("Attempt to release alive packet socket: %p\n", sk);
+ pr_err("Attempt to release alive packet socket: %p\n", sk);
return;
}
@@ -339,7 +337,8 @@ static const struct proto_ops packet_ops;
static const struct proto_ops packet_ops_spkt;
-static int packet_rcv_spkt(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev)
+static int packet_rcv_spkt(struct sk_buff *skb, struct net_device *dev,
+ struct packet_type *pt, struct net_device *orig_dev)
{
struct sock *sk;
struct sockaddr_pkt *spkt;
@@ -368,7 +367,8 @@ static int packet_rcv_spkt(struct sk_buff *skb, struct net_device *dev, struct
if (dev_net(dev) != sock_net(sk))
goto out;
- if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL)
+ skb = skb_share_check(skb, GFP_ATOMIC);
+ if (skb == NULL)
goto oom;
/* drop any routing info */
@@ -394,7 +394,7 @@ static int packet_rcv_spkt(struct sk_buff *skb, struct net_device *dev, struct
* to prevent sockets using all the memory up.
*/
- if (sock_queue_rcv_skb(sk,skb) == 0)
+ if (sock_queue_rcv_skb(sk, skb) == 0)
return 0;
out:
@@ -413,25 +413,23 @@ static int packet_sendmsg_spkt(struct kiocb *iocb, struct socket *sock,
struct msghdr *msg, size_t len)
{
struct sock *sk = sock->sk;
- struct sockaddr_pkt *saddr=(struct sockaddr_pkt *)msg->msg_name;
+ struct sockaddr_pkt *saddr = (struct sockaddr_pkt *)msg->msg_name;
struct sk_buff *skb;
struct net_device *dev;
- __be16 proto=0;
+ __be16 proto = 0;
int err;
/*
* Get and verify the address.
*/
- if (saddr)
- {
+ if (saddr) {
if (msg->msg_namelen < sizeof(struct sockaddr))
- return(-EINVAL);
- if (msg->msg_namelen==sizeof(struct sockaddr_pkt))
- proto=saddr->spkt_protocol;
- }
- else
- return(-ENOTCONN); /* SOCK_PACKET must be sent giving an address */
+ return -EINVAL;
+ if (msg->msg_namelen == sizeof(struct sockaddr_pkt))
+ proto = saddr->spkt_protocol;
+ } else
+ return -ENOTCONN; /* SOCK_PACKET must be sent giving an address */
/*
* Find the device first to size check it
@@ -448,8 +446,8 @@ static int packet_sendmsg_spkt(struct kiocb *iocb, struct socket *sock,
goto out_unlock;
/*
- * You may not queue a frame bigger than the mtu. This is the lowest level
- * raw protocol and you must do your own fragmentation at this level.
+ * You may not queue a frame bigger than the mtu. This is the lowest level
+ * raw protocol and you must do your own fragmentation at this level.
*/
err = -EMSGSIZE;
@@ -460,9 +458,9 @@ static int packet_sendmsg_spkt(struct kiocb *iocb, struct socket *sock,
skb = sock_wmalloc(sk, len + LL_RESERVED_SPACE(dev), 0, GFP_KERNEL);
/*
- * If the write buffer is full, then tough. At this level the user gets to
- * deal with the problem - do your own algorithmic backoffs. That's far
- * more flexible.
+ * If the write buffer is full, then tough. At this level the user
+ * gets to deal with the problem - do your own algorithmic backoffs.
+ * That's far more flexible.
*/
if (skb == NULL)
@@ -488,7 +486,7 @@ static int packet_sendmsg_spkt(struct kiocb *iocb, struct socket *sock,
}
/* Returns -EFAULT on error */
- err = memcpy_fromiovec(skb_put(skb,len), msg->msg_iov, len);
+ err = memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len);
skb->protocol = proto;
skb->dev = dev;
skb->priority = sk->sk_priority;
@@ -501,7 +499,7 @@ static int packet_sendmsg_spkt(struct kiocb *iocb, struct socket *sock,
dev_queue_xmit(skb);
dev_put(dev);
- return(len);
+ return len;
out_free:
kfree_skb(skb);
@@ -537,12 +535,13 @@ static inline unsigned int run_filter(struct sk_buff *skb, struct sock *sk,
we will not harm anyone.
*/
-static int packet_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev)
+static int packet_rcv(struct sk_buff *skb, struct net_device *dev,
+ struct packet_type *pt, struct net_device *orig_dev)
{
struct sock *sk;
struct sockaddr_ll *sll;
struct packet_sock *po;
- u8 * skb_head = skb->data;
+ u8 *skb_head = skb->data;
int skb_len = skb->len;
unsigned int snaplen, res;
@@ -648,7 +647,8 @@ drop:
}
#ifdef CONFIG_PACKET_MMAP
-static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev)
+static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev,
+ struct packet_type *pt, struct net_device *orig_dev)
{
struct sock *sk;
struct packet_sock *po;
@@ -658,7 +658,7 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev, struct packe
struct tpacket2_hdr *h2;
void *raw;
} h;
- u8 * skb_head = skb->data;
+ u8 *skb_head = skb->data;
int skb_len = skb->len;
unsigned int snaplen, res;
unsigned long status = TP_STATUS_LOSING|TP_STATUS_USER;
@@ -821,7 +821,7 @@ ring_is_full:
static void tpacket_destruct_skb(struct sk_buff *skb)
{
struct packet_sock *po = pkt_sk(skb->sk);
- void * ph;
+ void *ph;
BUG_ON(skb == NULL);
@@ -836,9 +836,9 @@ static void tpacket_destruct_skb(struct sk_buff *skb)
sock_wfree(skb);
}
-static int tpacket_fill_skb(struct packet_sock *po, struct sk_buff * skb,
- void * frame, struct net_device *dev, int size_max,
- __be16 proto, unsigned char * addr)
+static int tpacket_fill_skb(struct packet_sock *po, struct sk_buff *skb,
+ void *frame, struct net_device *dev, int size_max,
+ __be16 proto, unsigned char *addr)
{
union {
struct tpacket_hdr *h1;
@@ -867,8 +867,7 @@ static int tpacket_fill_skb(struct packet_sock *po, struct sk_buff * skb,
break;
}
if (unlikely(tp_len > size_max)) {
- printk(KERN_ERR "packet size is too long (%d > %d)\n",
- tp_len, size_max);
+ pr_err("packet size is too long (%d > %d)\n", tp_len, size_max);
return -EMSGSIZE;
}
@@ -883,12 +882,11 @@ static int tpacket_fill_skb(struct packet_sock *po, struct sk_buff * skb,
NULL, tp_len);
if (unlikely(err < 0))
return -EINVAL;
- } else if (dev->hard_header_len ) {
+ } else if (dev->hard_header_len) {
/* net device doesn't like empty head */
if (unlikely(tp_len <= dev->hard_header_len)) {
- printk(KERN_ERR "packet size is too short "
- "(%d < %d)\n", tp_len,
- dev->hard_header_len);
+ pr_err("packet size is too short (%d < %d)\n",
+ tp_len, dev->hard_header_len);
return -EINVAL;
}
@@ -917,9 +915,8 @@ static int tpacket_fill_skb(struct packet_sock *po, struct sk_buff * skb,
nr_frags = skb_shinfo(skb)->nr_frags;
if (unlikely(nr_frags >= MAX_SKB_FRAGS)) {
- printk(KERN_ERR "Packet exceed the number "
- "of skb frags(%lu)\n",
- MAX_SKB_FRAGS);
+ pr_err("Packet exceed the number of skb frags(%lu)\n",
+ MAX_SKB_FRAGS);
return -EFAULT;
}
@@ -944,8 +941,8 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg)
struct net_device *dev;
__be16 proto;
int ifindex, err, reserve = 0;
- void * ph;
- struct sockaddr_ll *saddr=(struct sockaddr_ll *)msg->msg_name;
+ void *ph;
+ struct sockaddr_ll *saddr = (struct sockaddr_ll *)msg->msg_name;
int tp_len, size_max;
unsigned char *addr;
int len_sum = 0;
@@ -1038,8 +1035,7 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg)
goto out_xmit;
packet_increment_head(&po->tx_ring);
len_sum += tp_len;
- }
- while (likely((ph != NULL) || ((!(msg->msg_flags & MSG_DONTWAIT))
+ } while (likely((ph != NULL) || ((!(msg->msg_flags & MSG_DONTWAIT))
&& (atomic_read(&po->tx_ring.pending))))
);
@@ -1064,7 +1060,7 @@ static int packet_snd(struct socket *sock,
struct msghdr *msg, size_t len)
{
struct sock *sk = sock->sk;
- struct sockaddr_ll *saddr=(struct sockaddr_ll *)msg->msg_name;
+ struct sockaddr_ll *saddr = (struct sockaddr_ll *)msg->msg_name;
struct sk_buff *skb;
struct net_device *dev;
__be16 proto;
@@ -1110,7 +1106,7 @@ static int packet_snd(struct socket *sock,
skb = sock_alloc_send_skb(sk, len + LL_ALLOCATED_SPACE(dev),
msg->msg_flags & MSG_DONTWAIT, &err);
- if (skb==NULL)
+ if (skb == NULL)
goto out_unlock;
skb_reserve(skb, LL_RESERVED_SPACE(dev));
@@ -1122,7 +1118,7 @@ static int packet_snd(struct socket *sock,
goto out_free;
/* Returns -EFAULT on error */
- err = memcpy_fromiovec(skb_put(skb,len), msg->msg_iov, len);
+ err = memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len);
if (err)
goto out_free;
@@ -1140,7 +1136,7 @@ static int packet_snd(struct socket *sock,
dev_put(dev);
- return(len);
+ return len;
out_free:
kfree_skb(skb);
@@ -1283,9 +1279,10 @@ out_unlock:
* Bind a packet socket to a device
*/
-static int packet_bind_spkt(struct socket *sock, struct sockaddr *uaddr, int addr_len)
+static int packet_bind_spkt(struct socket *sock, struct sockaddr *uaddr,
+ int addr_len)
{
- struct sock *sk=sock->sk;
+ struct sock *sk = sock->sk;
char name[15];
struct net_device *dev;
int err = -ENODEV;
@@ -1296,7 +1293,7 @@ static int packet_bind_spkt(struct socket *sock, struct sockaddr *uaddr, int add
if (addr_len != sizeof(struct sockaddr))
return -EINVAL;
- strlcpy(name,uaddr->sa_data,sizeof(name));
+ strlcpy(name, uaddr->sa_data, sizeof(name));
dev = dev_get_by_name(sock_net(sk), name);
if (dev) {
@@ -1308,8 +1305,8 @@ static int packet_bind_spkt(struct socket *sock, struct sockaddr *uaddr, int add
static int packet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
{
- struct sockaddr_ll *sll = (struct sockaddr_ll*)uaddr;
- struct sock *sk=sock->sk;
+ struct sockaddr_ll *sll = (struct sockaddr_ll *)uaddr;
+ struct sock *sk = sock->sk;
struct net_device *dev = NULL;
int err;
@@ -1404,7 +1401,7 @@ static int packet_create(struct net *net, struct socket *sock, int protocol)
sk_add_node(sk, &net->packet.sklist);
sock_prot_inuse_add(net, &packet_proto, 1);
write_unlock_bh(&net->packet.sklist_lock);
- return(0);
+ return 0;
out:
return err;
}
@@ -1441,7 +1438,7 @@ static int packet_recvmsg(struct kiocb *iocb, struct socket *sock,
* but then it will block.
*/
- skb=skb_recv_datagram(sk,flags,flags&MSG_DONTWAIT,&err);
+ skb = skb_recv_datagram(sk, flags, flags & MSG_DONTWAIT, &err);
/*
* An error occurred so return it. Because skb_recv_datagram()
@@ -1469,10 +1466,9 @@ static int packet_recvmsg(struct kiocb *iocb, struct socket *sock,
*/
copied = skb->len;
- if (copied > len)
- {
- copied=len;
- msg->msg_flags|=MSG_TRUNC;
+ if (copied > len) {
+ copied = len;
+ msg->msg_flags |= MSG_TRUNC;
}
err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
@@ -1539,7 +1535,7 @@ static int packet_getname(struct socket *sock, struct sockaddr *uaddr,
struct net_device *dev;
struct sock *sk = sock->sk;
struct packet_sock *po = pkt_sk(sk);
- struct sockaddr_ll *sll = (struct sockaddr_ll*)uaddr;
+ struct sockaddr_ll *sll = (struct sockaddr_ll *)uaddr;
if (peer)
return -EOPNOTSUPP;
@@ -1584,14 +1580,15 @@ static int packet_dev_mc(struct net_device *dev, struct packet_mclist *i,
else
return dev_unicast_delete(dev, i->addr);
break;
- default:;
+ default:
+ break;
}
return 0;
}
static void packet_dev_mclist(struct net_device *dev, struct packet_mclist *i, int what)
{
- for ( ; i; i=i->next) {
+ for ( ; i; i = i->next) {
if (i->ifindex == dev->ifindex)
packet_dev_mc(dev, i, what);
}
@@ -1693,7 +1690,8 @@ static void packet_flush_mclist(struct sock *sk)
struct net_device *dev;
po->mclist = ml->next;
- if ((dev = dev_get_by_index(sock_net(sk), ml->ifindex)) != NULL) {
+ dev = dev_get_by_index(sock_net(sk), ml->ifindex);
+ if (dev != NULL) {
packet_dev_mc(dev, ml, -1);
dev_put(dev);
}
@@ -1723,7 +1721,7 @@ packet_setsockopt(struct socket *sock, int level, int optname, char __user *optv
return -EINVAL;
if (len > sizeof(mreq))
len = sizeof(mreq);
- if (copy_from_user(&mreq,optval,len))
+ if (copy_from_user(&mreq, optval, len))
return -EFAULT;
if (len < (mreq.mr_alen + offsetof(struct packet_mreq, mr_address)))
return -EINVAL;
@@ -1740,9 +1738,9 @@ packet_setsockopt(struct socket *sock, int level, int optname, char __user *optv
{
struct tpacket_req req;
- if (optlen<sizeof(req))
+ if (optlen < sizeof(req))
return -EINVAL;
- if (copy_from_user(&req,optval,sizeof(req)))
+ if (copy_from_user(&req, optval, sizeof(req)))
return -EFAULT;
return packet_set_ring(sk, &req, 0, optname == PACKET_TX_RING);
}
@@ -1750,9 +1748,9 @@ packet_setsockopt(struct socket *sock, int level, int optname, char __user *optv
{
int val;
- if (optlen!=sizeof(val))
+ if (optlen != sizeof(val))
return -EINVAL;
- if (copy_from_user(&val,optval,sizeof(val)))
+ if (copy_from_user(&val, optval, sizeof(val)))
return -EFAULT;
pkt_sk(sk)->copy_thresh = val;
@@ -1985,51 +1983,51 @@ static int packet_ioctl(struct socket *sock, unsigned int cmd,
struct sock *sk = sock->sk;
switch (cmd) {
- case SIOCOUTQ:
- {
- int amount = sk_wmem_alloc_get(sk);
+ case SIOCOUTQ:
+ {
+ int amount = sk_wmem_alloc_get(sk);
- return put_user(amount, (int __user *)arg);
- }
- case SIOCINQ:
- {
- struct sk_buff *skb;
- int amount = 0;
-
- spin_lock_bh(&sk->sk_receive_queue.lock);
- skb = skb_peek(&sk->sk_receive_queue);
- if (skb)
- amount = skb->len;
- spin_unlock_bh(&sk->sk_receive_queue.lock);
- return put_user(amount, (int __user *)arg);
- }
- case SIOCGSTAMP:
- return sock_get_timestamp(sk, (struct timeval __user *)arg);
- case SIOCGSTAMPNS:
- return sock_get_timestampns(sk, (struct timespec __user *)arg);
+ return put_user(amount, (int __user *)arg);
+ }
+ case SIOCINQ:
+ {
+ struct sk_buff *skb;
+ int amount = 0;
+
+ spin_lock_bh(&sk->sk_receive_queue.lock);
+ skb = skb_peek(&sk->sk_receive_queue);
+ if (skb)
+ amount = skb->len;
+ spin_unlock_bh(&sk->sk_receive_queue.lock);
+ return put_user(amount, (int __user *)arg);
+ }
+ case SIOCGSTAMP:
+ return sock_get_timestamp(sk, (struct timeval __user *)arg);
+ case SIOCGSTAMPNS:
+ return sock_get_timestampns(sk, (struct timespec __user *)arg);
#ifdef CONFIG_INET
- case SIOCADDRT:
- case SIOCDELRT:
- case SIOCDARP:
- case SIOCGARP:
- case SIOCSARP:
- case SIOCGIFADDR:
- case SIOCSIFADDR:
- case SIOCGIFBRDADDR:
- case SIOCSIFBRDADDR:
- case SIOCGIFNETMASK:
- case SIOCSIFNETMASK:
- case SIOCGIFDSTADDR:
- case SIOCSIFDSTADDR:
- case SIOCSIFFLAGS:
- if (!net_eq(sock_net(sk), &init_net))
- return -ENOIOCTLCMD;
- return inet_dgram_ops.ioctl(sock, cmd, arg);
+ case SIOCADDRT:
+ case SIOCDELRT:
+ case SIOCDARP:
+ case SIOCGARP:
+ case SIOCSARP:
+ case SIOCGIFADDR:
+ case SIOCSIFADDR:
+ case SIOCGIFBRDADDR:
+ case SIOCSIFBRDADDR:
+ case SIOCGIFNETMASK:
+ case SIOCSIFNETMASK:
+ case SIOCGIFDSTADDR:
+ case SIOCSIFDSTADDR:
+ case SIOCSIFFLAGS:
+ if (!net_eq(sock_net(sk), &init_net))
+ return -ENOIOCTLCMD;
+ return inet_dgram_ops.ioctl(sock, cmd, arg);
#endif
- default:
- return -ENOIOCTLCMD;
+ default:
+ return -ENOIOCTLCMD;
}
return 0;
}
@@ -2039,7 +2037,7 @@ static int packet_ioctl(struct socket *sock, unsigned int cmd,
#define packet_poll datagram_poll
#else
-static unsigned int packet_poll(struct file * file, struct socket *sock,
+static unsigned int packet_poll(struct file *file, struct socket *sock,
poll_table *wait)
{
struct sock *sk = sock->sk;
@@ -2069,7 +2067,7 @@ static unsigned int packet_poll(struct file * file, struct socket *sock,
static void packet_mm_open(struct vm_area_struct *vma)
{
struct file *file = vma->vm_file;
- struct socket * sock = file->private_data;
+ struct socket *sock = file->private_data;
struct sock *sk = sock->sk;
if (sk)
@@ -2079,7 +2077,7 @@ static void packet_mm_open(struct vm_area_struct *vma)
static void packet_mm_close(struct vm_area_struct *vma)
{
struct file *file = vma->vm_file;
- struct socket * sock = file->private_data;
+ struct socket *sock = file->private_data;
struct sock *sk = sock->sk;
if (sk)
@@ -2087,8 +2085,8 @@ static void packet_mm_close(struct vm_area_struct *vma)
}
static struct vm_operations_struct packet_mmap_ops = {
- .open = packet_mm_open,
- .close =packet_mm_close,
+ .open = packet_mm_open,
+ .close = packet_mm_close,
};
static void free_pg_vec(char **pg_vec, unsigned int order, unsigned int len)
@@ -2239,8 +2237,8 @@ static int packet_set_ring(struct sock *sk, struct tpacket_req *req,
skb_queue_purge(rb_queue);
#undef XC
if (atomic_read(&po->mapped))
- printk(KERN_DEBUG "packet_mmap: vma is busy: %d\n",
- atomic_read(&po->mapped));
+ pr_err("packet_mmap: vma is busy: %d\n",
+ atomic_read(&po->mapped));
}
mutex_unlock(&po->pg_vec_lock);
@@ -2303,7 +2301,7 @@ static int packet_mmap(struct file *file, struct socket *sock,
int pg_num;
for (pg_num = 0; pg_num < rb->pg_vec_pages;
- pg_num++,page++) {
+ pg_num++, page++) {
err = vm_insert_page(vma, start, page);
if (unlikely(err))
goto out;
@@ -2372,7 +2370,7 @@ static struct net_proto_family packet_family_ops = {
};
static struct notifier_block packet_netdev_notifier = {
- .notifier_call =packet_notifier,
+ .notifier_call = packet_notifier,
};
#ifdef CONFIG_PROC_FS
@@ -2402,7 +2400,7 @@ static void *packet_seq_next(struct seq_file *seq, void *v, loff_t *pos)
++*pos;
return (v == SEQ_START_TOKEN)
? sk_head(&net->packet.sklist)
- : sk_next((struct sock*)v) ;
+ : sk_next((struct sock *)v) ;
}
static void packet_seq_stop(struct seq_file *seq, void *v)
@@ -2430,7 +2428,7 @@ static int packet_seq_show(struct seq_file *seq, void *v)
po->running,
atomic_read(&s->sk_rmem_alloc),
sock_i_uid(s),
- sock_i_ino(s) );
+ sock_i_ino(s));
}
return 0;
diff --git a/net/phonet/datagram.c b/net/phonet/datagram.c
index e087862ed7e..ef5c75c372e 100644
--- a/net/phonet/datagram.c
+++ b/net/phonet/datagram.c
@@ -159,8 +159,11 @@ out_nofree:
static int pn_backlog_rcv(struct sock *sk, struct sk_buff *skb)
{
int err = sock_queue_rcv_skb(sk, skb);
- if (err < 0)
+ if (err < 0) {
kfree_skb(skb);
+ if (err == -ENOMEM)
+ atomic_inc(&sk->sk_drops);
+ }
return err ? NET_RX_DROP : NET_RX_SUCCESS;
}
diff --git a/net/phonet/pep-gprs.c b/net/phonet/pep-gprs.c
index 480839dfc56..4667af51ed7 100644
--- a/net/phonet/pep-gprs.c
+++ b/net/phonet/pep-gprs.c
@@ -195,7 +195,7 @@ static int gprs_xmit(struct sk_buff *skb, struct net_device *dev)
break;
default:
dev_kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
}
skb_orphan(skb);
@@ -215,7 +215,7 @@ static int gprs_xmit(struct sk_buff *skb, struct net_device *dev)
netif_stop_queue(dev);
if (pep_writeable(sk))
netif_wake_queue(dev);
- return 0;
+ return NETDEV_TX_OK;
}
static int gprs_set_mtu(struct net_device *dev, int new_mtu)
diff --git a/net/phonet/pep.c b/net/phonet/pep.c
index eef833ea6d7..b8252d289cd 100644
--- a/net/phonet/pep.c
+++ b/net/phonet/pep.c
@@ -346,8 +346,10 @@ static int pipe_do_rcv(struct sock *sk, struct sk_buff *skb)
break;
case PNS_PEP_CTRL_REQ:
- if (skb_queue_len(&pn->ctrlreq_queue) >= PNPIPE_CTRLREQ_MAX)
+ if (skb_queue_len(&pn->ctrlreq_queue) >= PNPIPE_CTRLREQ_MAX) {
+ atomic_inc(&sk->sk_drops);
break;
+ }
__skb_pull(skb, 4);
queue = &pn->ctrlreq_queue;
goto queue;
@@ -358,10 +360,13 @@ static int pipe_do_rcv(struct sock *sk, struct sk_buff *skb)
err = sock_queue_rcv_skb(sk, skb);
if (!err)
return 0;
+ if (err == -ENOMEM)
+ atomic_inc(&sk->sk_drops);
break;
}
if (pn->rx_credits == 0) {
+ atomic_inc(&sk->sk_drops);
err = -ENOBUFS;
break;
}
diff --git a/net/phonet/pn_dev.c b/net/phonet/pn_dev.c
index c2b77a69869..5ae4c01e838 100644
--- a/net/phonet/pn_dev.c
+++ b/net/phonet/pn_dev.c
@@ -27,6 +27,7 @@
#include <linux/net.h>
#include <linux/netdevice.h>
#include <linux/phonet.h>
+#include <linux/proc_fs.h>
#include <net/sock.h>
#include <net/netns/generic.h>
#include <net/phonet/pn_dev.h>
@@ -218,6 +219,11 @@ static int phonet_init_net(struct net *net)
if (!pnn)
return -ENOMEM;
+ if (!proc_net_fops_create(net, "phonet", 0, &pn_sock_seq_fops)) {
+ kfree(pnn);
+ return -ENOMEM;
+ }
+
INIT_LIST_HEAD(&pnn->pndevs.list);
spin_lock_init(&pnn->pndevs.lock);
net_assign_generic(net, phonet_net_id, pnn);
@@ -233,6 +239,8 @@ static void phonet_exit_net(struct net *net)
for_each_netdev(net, dev)
phonet_device_destroy(dev);
rtnl_unlock();
+
+ proc_net_remove(net, "phonet");
kfree(pnn);
}
diff --git a/net/phonet/socket.c b/net/phonet/socket.c
index ada2a35bf7a..5f26c3711a1 100644
--- a/net/phonet/socket.c
+++ b/net/phonet/socket.c
@@ -412,3 +412,100 @@ found:
return 0;
}
EXPORT_SYMBOL(pn_sock_get_port);
+
+static struct sock *pn_sock_get_idx(struct seq_file *seq, loff_t pos)
+{
+ struct net *net = seq_file_net(seq);
+ struct hlist_node *node;
+ struct sock *sknode;
+
+ sk_for_each(sknode, node, &pnsocks.hlist) {
+ if (!net_eq(net, sock_net(sknode)))
+ continue;
+ if (!pos)
+ return sknode;
+ pos--;
+ }
+ return NULL;
+}
+
+static struct sock *pn_sock_get_next(struct seq_file *seq, struct sock *sk)
+{
+ struct net *net = seq_file_net(seq);
+
+ do
+ sk = sk_next(sk);
+ while (sk && !net_eq(net, sock_net(sk)));
+
+ return sk;
+}
+
+static void *pn_sock_seq_start(struct seq_file *seq, loff_t *pos)
+ __acquires(pnsocks.lock)
+{
+ spin_lock_bh(&pnsocks.lock);
+ return *pos ? pn_sock_get_idx(seq, *pos - 1) : SEQ_START_TOKEN;
+}
+
+static void *pn_sock_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+ struct sock *sk;
+
+ if (v == SEQ_START_TOKEN)
+ sk = pn_sock_get_idx(seq, 0);
+ else
+ sk = pn_sock_get_next(seq, v);
+ (*pos)++;
+ return sk;
+}
+
+static void pn_sock_seq_stop(struct seq_file *seq, void *v)
+ __releases(pnsocks.lock)
+{
+ spin_unlock_bh(&pnsocks.lock);
+}
+
+static int pn_sock_seq_show(struct seq_file *seq, void *v)
+{
+ int len;
+
+ if (v == SEQ_START_TOKEN)
+ seq_printf(seq, "%s%n", "pt loc rem rs st tx_queue rx_queue "
+ " uid inode ref pointer drops", &len);
+ else {
+ struct sock *sk = v;
+ struct pn_sock *pn = pn_sk(sk);
+
+ seq_printf(seq, "%2d %04X:%04X:%02X %02X %08X:%08X %5d %lu "
+ "%d %p %d%n",
+ sk->sk_protocol, pn->sobject, 0, pn->resource,
+ sk->sk_state,
+ sk_wmem_alloc_get(sk), sk_rmem_alloc_get(sk),
+ sock_i_uid(sk), sock_i_ino(sk),
+ atomic_read(&sk->sk_refcnt), sk,
+ atomic_read(&sk->sk_drops), &len);
+ }
+ seq_printf(seq, "%*s\n", 127 - len, "");
+ return 0;
+}
+
+static const struct seq_operations pn_sock_seq_ops = {
+ .start = pn_sock_seq_start,
+ .next = pn_sock_seq_next,
+ .stop = pn_sock_seq_stop,
+ .show = pn_sock_seq_show,
+};
+
+static int pn_sock_open(struct inode *inode, struct file *file)
+{
+ return seq_open_net(inode, file, &pn_sock_seq_ops,
+ sizeof(struct seq_net_private));
+}
+
+const struct file_operations pn_sock_seq_fops = {
+ .owner = THIS_MODULE,
+ .open = pn_sock_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release_net,
+};
diff --git a/net/rds/connection.c b/net/rds/connection.c
index d14445c4830..b420a20d84f 100644
--- a/net/rds/connection.c
+++ b/net/rds/connection.c
@@ -126,7 +126,7 @@ static struct rds_connection *__rds_conn_create(__be32 laddr, __be32 faddr,
struct rds_transport *trans, gfp_t gfp,
int is_outgoing)
{
- struct rds_connection *conn, *tmp, *parent = NULL;
+ struct rds_connection *conn, *parent = NULL;
struct hlist_head *head = rds_conn_bucket(laddr, faddr);
unsigned long flags;
int ret;
@@ -155,7 +155,6 @@ static struct rds_connection *__rds_conn_create(__be32 laddr, __be32 faddr,
}
INIT_HLIST_NODE(&conn->c_hash_node);
- conn->c_version = RDS_PROTOCOL_3_0;
conn->c_laddr = laddr;
conn->c_faddr = faddr;
spin_lock_init(&conn->c_lock);
@@ -211,26 +210,40 @@ static struct rds_connection *__rds_conn_create(__be32 laddr, __be32 faddr,
trans->t_name ? trans->t_name : "[unknown]",
is_outgoing ? "(outgoing)" : "");
+ /*
+ * Since we ran without holding the conn lock, someone could
+ * have created the same conn (either normal or passive) in the
+ * interim. We check while holding the lock. If we won, we complete
+ * init and return our conn. If we lost, we rollback and return the
+ * other one.
+ */
spin_lock_irqsave(&rds_conn_lock, flags);
- if (parent == NULL) {
- tmp = rds_conn_lookup(head, laddr, faddr, trans);
- if (tmp == NULL)
- hlist_add_head(&conn->c_hash_node, head);
- } else {
- tmp = parent->c_passive;
- if (!tmp)
+ if (parent) {
+ /* Creating passive conn */
+ if (parent->c_passive) {
+ trans->conn_free(conn->c_transport_data);
+ kmem_cache_free(rds_conn_slab, conn);
+ conn = parent->c_passive;
+ } else {
parent->c_passive = conn;
- }
-
- if (tmp) {
- trans->conn_free(conn->c_transport_data);
- kmem_cache_free(rds_conn_slab, conn);
- conn = tmp;
+ rds_cong_add_conn(conn);
+ rds_conn_count++;
+ }
} else {
- rds_cong_add_conn(conn);
- rds_conn_count++;
+ /* Creating normal conn */
+ struct rds_connection *found;
+
+ found = rds_conn_lookup(head, laddr, faddr, trans);
+ if (found) {
+ trans->conn_free(conn->c_transport_data);
+ kmem_cache_free(rds_conn_slab, conn);
+ conn = found;
+ } else {
+ hlist_add_head(&conn->c_hash_node, head);
+ rds_cong_add_conn(conn);
+ rds_conn_count++;
+ }
}
-
spin_unlock_irqrestore(&rds_conn_lock, flags);
out:
diff --git a/net/rds/ib.c b/net/rds/ib.c
index b9bcd32431e..868559ac42d 100644
--- a/net/rds/ib.c
+++ b/net/rds/ib.c
@@ -43,11 +43,14 @@
unsigned int fmr_pool_size = RDS_FMR_POOL_SIZE;
unsigned int fmr_message_size = RDS_FMR_SIZE + 1; /* +1 allows for unaligned MRs */
+unsigned int rds_ib_retry_count = RDS_IB_DEFAULT_RETRY_COUNT;
module_param(fmr_pool_size, int, 0444);
MODULE_PARM_DESC(fmr_pool_size, " Max number of fmr per HCA");
module_param(fmr_message_size, int, 0444);
MODULE_PARM_DESC(fmr_message_size, " Max size of a RDMA transfer");
+module_param(rds_ib_retry_count, int, 0444);
+MODULE_PARM_DESC(rds_ib_retry_count, " Number of hw retries before reporting an error");
struct list_head rds_ib_devices;
@@ -82,9 +85,6 @@ void rds_ib_add_one(struct ib_device *device)
rds_ibdev->max_wrs = dev_attr->max_qp_wr;
rds_ibdev->max_sge = min(dev_attr->max_sge, RDS_IB_MAX_SGE);
- rds_ibdev->fmr_page_shift = max(9, ffs(dev_attr->page_size_cap) - 1);
- rds_ibdev->fmr_page_size = 1 << rds_ibdev->fmr_page_shift;
- rds_ibdev->fmr_page_mask = ~((u64) rds_ibdev->fmr_page_size - 1);
rds_ibdev->fmr_max_remaps = dev_attr->max_map_per_fmr?: 32;
rds_ibdev->max_fmrs = dev_attr->max_fmr ?
min_t(unsigned int, dev_attr->max_fmr, fmr_pool_size) :
diff --git a/net/rds/ib.h b/net/rds/ib.h
index 455ae73047f..1378b854cac 100644
--- a/net/rds/ib.h
+++ b/net/rds/ib.h
@@ -15,6 +15,8 @@
#define RDS_IB_DEFAULT_RECV_WR 1024
#define RDS_IB_DEFAULT_SEND_WR 256
+#define RDS_IB_DEFAULT_RETRY_COUNT 2
+
#define RDS_IB_SUPPORTED_PROTOCOLS 0x00000003 /* minor versions supported */
extern struct list_head rds_ib_devices;
@@ -157,9 +159,6 @@ struct rds_ib_device {
struct ib_pd *pd;
struct ib_mr *mr;
struct rds_ib_mr_pool *mr_pool;
- int fmr_page_shift;
- int fmr_page_size;
- u64 fmr_page_mask;
unsigned int fmr_max_remaps;
unsigned int max_fmrs;
int max_sge;
@@ -247,6 +246,7 @@ extern struct ib_client rds_ib_client;
extern unsigned int fmr_pool_size;
extern unsigned int fmr_message_size;
+extern unsigned int rds_ib_retry_count;
extern spinlock_t ib_nodev_conns_lock;
extern struct list_head ib_nodev_conns;
@@ -355,17 +355,25 @@ extern ctl_table rds_ib_sysctl_table[];
/*
* Helper functions for getting/setting the header and data SGEs in
* RDS packets (not RDMA)
+ *
+ * From version 3.1 onwards, header is in front of data in the sge.
*/
static inline struct ib_sge *
rds_ib_header_sge(struct rds_ib_connection *ic, struct ib_sge *sge)
{
- return &sge[0];
+ if (ic->conn->c_version > RDS_PROTOCOL_3_0)
+ return &sge[0];
+ else
+ return &sge[1];
}
static inline struct ib_sge *
rds_ib_data_sge(struct rds_ib_connection *ic, struct ib_sge *sge)
{
- return &sge[1];
+ if (ic->conn->c_version > RDS_PROTOCOL_3_0)
+ return &sge[1];
+ else
+ return &sge[0];
}
#endif
diff --git a/net/rds/ib_cm.c b/net/rds/ib_cm.c
index f8e40e1a603..c2d372f13db 100644
--- a/net/rds/ib_cm.c
+++ b/net/rds/ib_cm.c
@@ -98,21 +98,34 @@ void rds_ib_cm_connect_complete(struct rds_connection *conn, struct rdma_cm_even
struct ib_qp_attr qp_attr;
int err;
- if (event->param.conn.private_data_len) {
+ if (event->param.conn.private_data_len >= sizeof(*dp)) {
dp = event->param.conn.private_data;
- rds_ib_set_protocol(conn,
+ /* make sure it isn't empty data */
+ if (dp->dp_protocol_major) {
+ rds_ib_set_protocol(conn,
RDS_PROTOCOL(dp->dp_protocol_major,
- dp->dp_protocol_minor));
- rds_ib_set_flow_control(conn, be32_to_cpu(dp->dp_credit));
+ dp->dp_protocol_minor));
+ rds_ib_set_flow_control(conn, be32_to_cpu(dp->dp_credit));
+ }
}
printk(KERN_NOTICE "RDS/IB: connected to %pI4 version %u.%u%s\n",
- &conn->c_laddr,
+ &conn->c_faddr,
RDS_PROTOCOL_MAJOR(conn->c_version),
RDS_PROTOCOL_MINOR(conn->c_version),
ic->i_flowctl ? ", flow control" : "");
+ /*
+ * Init rings and fill recv. this needs to wait until protocol negotiation
+ * is complete, since ring layout is different from 3.0 to 3.1.
+ */
+ rds_ib_send_init_ring(ic);
+ rds_ib_recv_init_ring(ic);
+ /* Post receive buffers - as a side effect, this will update
+ * the posted credit count. */
+ rds_ib_recv_refill(conn, GFP_KERNEL, GFP_HIGHUSER, 1);
+
/* Tune RNR behavior */
rds_ib_tune_rnr(ic, &qp_attr);
@@ -145,7 +158,7 @@ static void rds_ib_cm_fill_conn_param(struct rds_connection *conn,
/* XXX tune these? */
conn_param->responder_resources = 1;
conn_param->initiator_depth = 1;
- conn_param->retry_count = 7;
+ conn_param->retry_count = min_t(unsigned int, rds_ib_retry_count, 7);
conn_param->rnr_retry_count = 7;
if (dp) {
@@ -190,9 +203,9 @@ static void rds_ib_qp_event_handler(struct ib_event *event, void *data)
rdma_notify(ic->i_cm_id, IB_EVENT_COMM_EST);
break;
default:
- printk(KERN_WARNING "RDS/ib: unhandled QP event %u "
- "on connection to %pI4\n", event->event,
- &conn->c_faddr);
+ rds_ib_conn_error(conn, "RDS/IB: Fatal QP Event %u "
+ "- connection %pI4->%pI4, reconnecting\n",
+ event->event, &conn->c_laddr, &conn->c_faddr);
break;
}
}
@@ -321,7 +334,7 @@ static int rds_ib_setup_qp(struct rds_connection *conn)
rdsdebug("send allocation failed\n");
goto out;
}
- rds_ib_send_init_ring(ic);
+ memset(ic->i_sends, 0, ic->i_send_ring.w_nr * sizeof(struct rds_ib_send_work));
ic->i_recvs = vmalloc(ic->i_recv_ring.w_nr * sizeof(struct rds_ib_recv_work));
if (ic->i_recvs == NULL) {
@@ -329,14 +342,10 @@ static int rds_ib_setup_qp(struct rds_connection *conn)
rdsdebug("recv allocation failed\n");
goto out;
}
+ memset(ic->i_recvs, 0, ic->i_recv_ring.w_nr * sizeof(struct rds_ib_recv_work));
- rds_ib_recv_init_ring(ic);
rds_ib_recv_init_ack(ic);
- /* Post receive buffers - as a side effect, this will update
- * the posted credit count. */
- rds_ib_recv_refill(conn, GFP_KERNEL, GFP_HIGHUSER, 1);
-
rdsdebug("conn %p pd %p mr %p cq %p %p\n", conn, ic->i_pd, ic->i_mr,
ic->i_send_cq, ic->i_recv_cq);
@@ -344,19 +353,32 @@ out:
return ret;
}
-static u32 rds_ib_protocol_compatible(const struct rds_ib_connect_private *dp)
+static u32 rds_ib_protocol_compatible(struct rdma_cm_event *event)
{
+ const struct rds_ib_connect_private *dp = event->param.conn.private_data;
u16 common;
u32 version = 0;
- /* rdma_cm private data is odd - when there is any private data in the
+ /*
+ * rdma_cm private data is odd - when there is any private data in the
* request, we will be given a pretty large buffer without telling us the
* original size. The only way to tell the difference is by looking at
* the contents, which are initialized to zero.
* If the protocol version fields aren't set, this is a connection attempt
* from an older version. This could could be 3.0 or 2.0 - we can't tell.
- * We really should have changed this for OFED 1.3 :-( */
- if (dp->dp_protocol_major == 0)
+ * We really should have changed this for OFED 1.3 :-(
+ */
+
+ /* Be paranoid. RDS always has privdata */
+ if (!event->param.conn.private_data_len) {
+ printk(KERN_NOTICE "RDS incoming connection has no private data, "
+ "rejecting\n");
+ return 0;
+ }
+
+ /* Even if len is crap *now* I still want to check it. -ASG */
+ if (event->param.conn.private_data_len < sizeof (*dp)
+ || dp->dp_protocol_major == 0)
return RDS_PROTOCOL_3_0;
common = be16_to_cpu(dp->dp_protocol_minor_mask) & RDS_IB_SUPPORTED_PROTOCOLS;
@@ -388,7 +410,7 @@ int rds_ib_cm_handle_connect(struct rdma_cm_id *cm_id,
int err, destroy = 1;
/* Check whether the remote protocol version matches ours. */
- version = rds_ib_protocol_compatible(dp);
+ version = rds_ib_protocol_compatible(event);
if (!version)
goto out;
diff --git a/net/rds/ib_rdma.c b/net/rds/ib_rdma.c
index 81033af9302..ef3ab5b7283 100644
--- a/net/rds/ib_rdma.c
+++ b/net/rds/ib_rdma.c
@@ -211,7 +211,7 @@ struct rds_ib_mr_pool *rds_ib_create_mr_pool(struct rds_ib_device *rds_ibdev)
pool->fmr_attr.max_pages = fmr_message_size;
pool->fmr_attr.max_maps = rds_ibdev->fmr_max_remaps;
- pool->fmr_attr.page_shift = rds_ibdev->fmr_page_shift;
+ pool->fmr_attr.page_shift = PAGE_SHIFT;
pool->max_free_pinned = rds_ibdev->max_fmrs * fmr_message_size / 4;
/* We never allow more than max_items MRs to be allocated.
@@ -349,13 +349,13 @@ static int rds_ib_map_fmr(struct rds_ib_device *rds_ibdev, struct rds_ib_mr *ibm
unsigned int dma_len = ib_sg_dma_len(dev, &scat[i]);
u64 dma_addr = ib_sg_dma_address(dev, &scat[i]);
- if (dma_addr & ~rds_ibdev->fmr_page_mask) {
+ if (dma_addr & ~PAGE_MASK) {
if (i > 0)
return -EINVAL;
else
++page_cnt;
}
- if ((dma_addr + dma_len) & ~rds_ibdev->fmr_page_mask) {
+ if ((dma_addr + dma_len) & ~PAGE_MASK) {
if (i < sg_dma_len - 1)
return -EINVAL;
else
@@ -365,7 +365,7 @@ static int rds_ib_map_fmr(struct rds_ib_device *rds_ibdev, struct rds_ib_mr *ibm
len += dma_len;
}
- page_cnt += len >> rds_ibdev->fmr_page_shift;
+ page_cnt += len >> PAGE_SHIFT;
if (page_cnt > fmr_message_size)
return -EINVAL;
@@ -378,9 +378,9 @@ static int rds_ib_map_fmr(struct rds_ib_device *rds_ibdev, struct rds_ib_mr *ibm
unsigned int dma_len = ib_sg_dma_len(dev, &scat[i]);
u64 dma_addr = ib_sg_dma_address(dev, &scat[i]);
- for (j = 0; j < dma_len; j += rds_ibdev->fmr_page_size)
+ for (j = 0; j < dma_len; j += PAGE_SIZE)
dma_pages[page_cnt++] =
- (dma_addr & rds_ibdev->fmr_page_mask) + j;
+ (dma_addr & PAGE_MASK) + j;
}
ret = ib_map_phys_fmr(ibmr->fmr,
diff --git a/net/rds/ib_recv.c b/net/rds/ib_recv.c
index 5709bad2832..cd7a6cfcab0 100644
--- a/net/rds/ib_recv.c
+++ b/net/rds/ib_recv.c
@@ -555,6 +555,47 @@ u64 rds_ib_piggyb_ack(struct rds_ib_connection *ic)
return rds_ib_get_ack(ic);
}
+static struct rds_header *rds_ib_get_header(struct rds_connection *conn,
+ struct rds_ib_recv_work *recv,
+ u32 data_len)
+{
+ struct rds_ib_connection *ic = conn->c_transport_data;
+ void *hdr_buff = &ic->i_recv_hdrs[recv - ic->i_recvs];
+ void *addr;
+ u32 misplaced_hdr_bytes;
+
+ /*
+ * Support header at the front (RDS 3.1+) as well as header-at-end.
+ *
+ * Cases:
+ * 1) header all in header buff (great!)
+ * 2) header all in data page (copy all to header buff)
+ * 3) header split across hdr buf + data page
+ * (move bit in hdr buff to end before copying other bit from data page)
+ */
+ if (conn->c_version > RDS_PROTOCOL_3_0 || data_len == RDS_FRAG_SIZE)
+ return hdr_buff;
+
+ if (data_len <= (RDS_FRAG_SIZE - sizeof(struct rds_header))) {
+ addr = kmap_atomic(recv->r_frag->f_page, KM_SOFTIRQ0);
+ memcpy(hdr_buff,
+ addr + recv->r_frag->f_offset + data_len,
+ sizeof(struct rds_header));
+ kunmap_atomic(addr, KM_SOFTIRQ0);
+ return hdr_buff;
+ }
+
+ misplaced_hdr_bytes = (sizeof(struct rds_header) - (RDS_FRAG_SIZE - data_len));
+
+ memmove(hdr_buff + misplaced_hdr_bytes, hdr_buff, misplaced_hdr_bytes);
+
+ addr = kmap_atomic(recv->r_frag->f_page, KM_SOFTIRQ0);
+ memcpy(hdr_buff, addr + recv->r_frag->f_offset + data_len,
+ sizeof(struct rds_header) - misplaced_hdr_bytes);
+ kunmap_atomic(addr, KM_SOFTIRQ0);
+ return hdr_buff;
+}
+
/*
* It's kind of lame that we're copying from the posted receive pages into
* long-lived bitmaps. We could have posted the bitmaps and rdma written into
@@ -645,7 +686,7 @@ struct rds_ib_ack_state {
};
static void rds_ib_process_recv(struct rds_connection *conn,
- struct rds_ib_recv_work *recv, u32 byte_len,
+ struct rds_ib_recv_work *recv, u32 data_len,
struct rds_ib_ack_state *state)
{
struct rds_ib_connection *ic = conn->c_transport_data;
@@ -655,9 +696,9 @@ static void rds_ib_process_recv(struct rds_connection *conn,
/* XXX shut down the connection if port 0,0 are seen? */
rdsdebug("ic %p ibinc %p recv %p byte len %u\n", ic, ibinc, recv,
- byte_len);
+ data_len);
- if (byte_len < sizeof(struct rds_header)) {
+ if (data_len < sizeof(struct rds_header)) {
rds_ib_conn_error(conn, "incoming message "
"from %pI4 didn't inclue a "
"header, disconnecting and "
@@ -665,9 +706,9 @@ static void rds_ib_process_recv(struct rds_connection *conn,
&conn->c_faddr);
return;
}
- byte_len -= sizeof(struct rds_header);
+ data_len -= sizeof(struct rds_header);
- ihdr = &ic->i_recv_hdrs[recv - ic->i_recvs];
+ ihdr = rds_ib_get_header(conn, recv, data_len);
/* Validate the checksum. */
if (!rds_message_verify_checksum(ihdr)) {
@@ -687,7 +728,7 @@ static void rds_ib_process_recv(struct rds_connection *conn,
if (ihdr->h_credit)
rds_ib_send_add_credits(conn, ihdr->h_credit);
- if (ihdr->h_sport == 0 && ihdr->h_dport == 0 && byte_len == 0) {
+ if (ihdr->h_sport == 0 && ihdr->h_dport == 0 && data_len == 0) {
/* This is an ACK-only packet. The fact that it gets
* special treatment here is that historically, ACKs
* were rather special beasts.
diff --git a/net/rds/ib_stats.c b/net/rds/ib_stats.c
index 02e3e3d50d4..8d8488306fe 100644
--- a/net/rds/ib_stats.c
+++ b/net/rds/ib_stats.c
@@ -39,7 +39,7 @@
DEFINE_PER_CPU(struct rds_ib_statistics, rds_ib_stats) ____cacheline_aligned;
-static char *rds_ib_stat_names[] = {
+static const char *const rds_ib_stat_names[] = {
"ib_connect_raced",
"ib_listen_closed_stale",
"ib_tx_cq_call",
diff --git a/net/rds/ib_sysctl.c b/net/rds/ib_sysctl.c
index d87830db93a..84b5ffcb280 100644
--- a/net/rds/ib_sysctl.c
+++ b/net/rds/ib_sysctl.c
@@ -53,7 +53,17 @@ unsigned long rds_ib_sysctl_max_unsig_bytes = (16 << 20);
static unsigned long rds_ib_sysctl_max_unsig_bytes_min = 1;
static unsigned long rds_ib_sysctl_max_unsig_bytes_max = ~0UL;
-unsigned int rds_ib_sysctl_flow_control = 1;
+/*
+ * This sysctl does nothing.
+ *
+ * Backwards compatibility with RDS 3.0 wire protocol
+ * disables initial FC credit exchange.
+ * If it's ever possible to drop 3.0 support,
+ * setting this to 1 and moving init/refill of send/recv
+ * rings from ib_cm_connect_complete() back into ib_setup_qp()
+ * will cause credits to be added before protocol negotiation.
+ */
+unsigned int rds_ib_sysctl_flow_control = 0;
ctl_table rds_ib_sysctl_table[] = {
{
diff --git a/net/rds/iw.c b/net/rds/iw.c
index d16e1cbc8e8..f5e9a29a80a 100644
--- a/net/rds/iw.c
+++ b/net/rds/iw.c
@@ -83,23 +83,16 @@ void rds_iw_add_one(struct ib_device *device)
rds_iwdev->max_wrs = dev_attr->max_qp_wr;
rds_iwdev->max_sge = min(dev_attr->max_sge, RDS_IW_MAX_SGE);
- rds_iwdev->page_shift = max(PAGE_SHIFT, ffs(dev_attr->page_size_cap) - 1);
-
rds_iwdev->dev = device;
rds_iwdev->pd = ib_alloc_pd(device);
if (IS_ERR(rds_iwdev->pd))
goto free_dev;
if (!rds_iwdev->dma_local_lkey) {
- if (device->node_type != RDMA_NODE_RNIC) {
- rds_iwdev->mr = ib_get_dma_mr(rds_iwdev->pd,
- IB_ACCESS_LOCAL_WRITE);
- } else {
- rds_iwdev->mr = ib_get_dma_mr(rds_iwdev->pd,
- IB_ACCESS_REMOTE_READ |
- IB_ACCESS_REMOTE_WRITE |
- IB_ACCESS_LOCAL_WRITE);
- }
+ rds_iwdev->mr = ib_get_dma_mr(rds_iwdev->pd,
+ IB_ACCESS_REMOTE_READ |
+ IB_ACCESS_REMOTE_WRITE |
+ IB_ACCESS_LOCAL_WRITE);
if (IS_ERR(rds_iwdev->mr))
goto err_pd;
} else
diff --git a/net/rds/iw.h b/net/rds/iw.h
index 0715dde323e..dd72b62bd50 100644
--- a/net/rds/iw.h
+++ b/net/rds/iw.h
@@ -181,7 +181,6 @@ struct rds_iw_device {
struct ib_pd *pd;
struct ib_mr *mr;
struct rds_iw_mr_pool *mr_pool;
- int page_shift;
int max_sge;
unsigned int max_wrs;
unsigned int dma_local_lkey:1;
diff --git a/net/rds/iw_rdma.c b/net/rds/iw_rdma.c
index dcdb37da80f..de4a1b16bf7 100644
--- a/net/rds/iw_rdma.c
+++ b/net/rds/iw_rdma.c
@@ -263,18 +263,12 @@ static void rds_iw_set_scatterlist(struct rds_iw_scatterlist *sg,
}
static u64 *rds_iw_map_scatterlist(struct rds_iw_device *rds_iwdev,
- struct rds_iw_scatterlist *sg,
- unsigned int dma_page_shift)
+ struct rds_iw_scatterlist *sg)
{
struct ib_device *dev = rds_iwdev->dev;
u64 *dma_pages = NULL;
- u64 dma_mask;
- unsigned int dma_page_size;
int i, j, ret;
- dma_page_size = 1 << dma_page_shift;
- dma_mask = dma_page_size - 1;
-
WARN_ON(sg->dma_len);
sg->dma_len = ib_dma_map_sg(dev, sg->list, sg->len, DMA_BIDIRECTIONAL);
@@ -295,18 +289,18 @@ static u64 *rds_iw_map_scatterlist(struct rds_iw_device *rds_iwdev,
sg->bytes += dma_len;
end_addr = dma_addr + dma_len;
- if (dma_addr & dma_mask) {
+ if (dma_addr & PAGE_MASK) {
if (i > 0)
goto out_unmap;
- dma_addr &= ~dma_mask;
+ dma_addr &= ~PAGE_MASK;
}
- if (end_addr & dma_mask) {
+ if (end_addr & PAGE_MASK) {
if (i < sg->dma_len - 1)
goto out_unmap;
- end_addr = (end_addr + dma_mask) & ~dma_mask;
+ end_addr = (end_addr + PAGE_MASK) & ~PAGE_MASK;
}
- sg->dma_npages += (end_addr - dma_addr) >> dma_page_shift;
+ sg->dma_npages += (end_addr - dma_addr) >> PAGE_SHIFT;
}
/* Now gather the dma addrs into one list */
@@ -325,8 +319,8 @@ static u64 *rds_iw_map_scatterlist(struct rds_iw_device *rds_iwdev,
u64 end_addr;
end_addr = dma_addr + dma_len;
- dma_addr &= ~dma_mask;
- for (; dma_addr < end_addr; dma_addr += dma_page_size)
+ dma_addr &= ~PAGE_MASK;
+ for (; dma_addr < end_addr; dma_addr += PAGE_SIZE)
dma_pages[j++] = dma_addr;
BUG_ON(j > sg->dma_npages);
}
@@ -727,7 +721,7 @@ static int rds_iw_rdma_build_fastreg(struct rds_iw_mapping *mapping)
f_wr.wr.fast_reg.rkey = mapping->m_rkey;
f_wr.wr.fast_reg.page_list = ibmr->page_list;
f_wr.wr.fast_reg.page_list_len = mapping->m_sg.dma_len;
- f_wr.wr.fast_reg.page_shift = ibmr->device->page_shift;
+ f_wr.wr.fast_reg.page_shift = PAGE_SHIFT;
f_wr.wr.fast_reg.access_flags = IB_ACCESS_LOCAL_WRITE |
IB_ACCESS_REMOTE_READ |
IB_ACCESS_REMOTE_WRITE;
@@ -780,9 +774,7 @@ static int rds_iw_map_fastreg(struct rds_iw_mr_pool *pool,
rds_iw_set_scatterlist(&mapping->m_sg, sg, sg_len);
- dma_pages = rds_iw_map_scatterlist(rds_iwdev,
- &mapping->m_sg,
- rds_iwdev->page_shift);
+ dma_pages = rds_iw_map_scatterlist(rds_iwdev, &mapping->m_sg);
if (IS_ERR(dma_pages)) {
ret = PTR_ERR(dma_pages);
dma_pages = NULL;
diff --git a/net/rds/iw_send.c b/net/rds/iw_send.c
index 44a6a0551f2..1f5abe3cf2b 100644
--- a/net/rds/iw_send.c
+++ b/net/rds/iw_send.c
@@ -779,7 +779,7 @@ static void rds_iw_build_send_fastreg(struct rds_iw_device *rds_iwdev, struct rd
send->s_wr.wr.fast_reg.rkey = send->s_mr->rkey;
send->s_wr.wr.fast_reg.page_list = send->s_page_list;
send->s_wr.wr.fast_reg.page_list_len = nent;
- send->s_wr.wr.fast_reg.page_shift = rds_iwdev->page_shift;
+ send->s_wr.wr.fast_reg.page_shift = PAGE_SHIFT;
send->s_wr.wr.fast_reg.access_flags = IB_ACCESS_REMOTE_WRITE;
send->s_wr.wr.fast_reg.iova_start = sg_addr;
diff --git a/net/rds/iw_stats.c b/net/rds/iw_stats.c
index ccc7e8f0bf0..d33ea790484 100644
--- a/net/rds/iw_stats.c
+++ b/net/rds/iw_stats.c
@@ -39,7 +39,7 @@
DEFINE_PER_CPU(struct rds_iw_statistics, rds_iw_stats) ____cacheline_aligned;
-static char *rds_iw_stat_names[] = {
+static const char *const rds_iw_stat_names[] = {
"iw_connect_raced",
"iw_listen_closed_stale",
"iw_tx_cq_call",
diff --git a/net/rds/rdma_transport.c b/net/rds/rdma_transport.c
index 7d0f901c93d..7a6c748cb56 100644
--- a/net/rds/rdma_transport.c
+++ b/net/rds/rdma_transport.c
@@ -101,7 +101,7 @@ int rds_rdma_cm_event_handler(struct rdma_cm_id *cm_id,
break;
case RDMA_CM_EVENT_DISCONNECTED:
- printk(KERN_WARNING "RDS/IW: DISCONNECT event - dropping connection "
+ printk(KERN_WARNING "RDS/RDMA: DISCONNECT event - dropping connection "
"%pI4->%pI4\n", &conn->c_laddr,
&conn->c_faddr);
rds_conn_drop(conn);
@@ -132,12 +132,12 @@ static int __init rds_rdma_listen_init(void)
cm_id = rdma_create_id(rds_rdma_cm_event_handler, NULL, RDMA_PS_TCP);
if (IS_ERR(cm_id)) {
ret = PTR_ERR(cm_id);
- printk(KERN_ERR "RDS/IW: failed to setup listener, "
+ printk(KERN_ERR "RDS/RDMA: failed to setup listener, "
"rdma_create_id() returned %d\n", ret);
goto out;
}
- sin.sin_family = PF_INET,
+ sin.sin_family = AF_INET,
sin.sin_addr.s_addr = (__force u32)htonl(INADDR_ANY);
sin.sin_port = (__force u16)htons(RDS_PORT);
@@ -147,14 +147,14 @@ static int __init rds_rdma_listen_init(void)
*/
ret = rdma_bind_addr(cm_id, (struct sockaddr *)&sin);
if (ret) {
- printk(KERN_ERR "RDS/IW: failed to setup listener, "
+ printk(KERN_ERR "RDS/RDMA: failed to setup listener, "
"rdma_bind_addr() returned %d\n", ret);
goto out;
}
ret = rdma_listen(cm_id, 128);
if (ret) {
- printk(KERN_ERR "RDS/IW: failed to setup listener, "
+ printk(KERN_ERR "RDS/RDMA: failed to setup listener, "
"rdma_listen() returned %d\n", ret);
goto out;
}
diff --git a/net/rds/rds.h b/net/rds/rds.h
index dbe11123678..290566c69d2 100644
--- a/net/rds/rds.h
+++ b/net/rds/rds.h
@@ -652,7 +652,8 @@ DECLARE_PER_CPU_SHARED_ALIGNED(struct rds_statistics, rds_stats);
int __init rds_stats_init(void);
void rds_stats_exit(void);
void rds_stats_info_copy(struct rds_info_iterator *iter,
- uint64_t *values, char **names, size_t nr);
+ uint64_t *values, const char *const *names,
+ size_t nr);
/* sysctl.c */
int __init rds_sysctl_init(void);
diff --git a/net/rds/recv.c b/net/rds/recv.c
index f2118c51cfa..86bc1a06ebb 100644
--- a/net/rds/recv.c
+++ b/net/rds/recv.c
@@ -409,18 +409,18 @@ int rds_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg,
if (msg_flags & MSG_OOB)
goto out;
- /* If there are pending notifications, do those - and nothing else */
- if (!list_empty(&rs->rs_notify_queue)) {
- ret = rds_notify_queue_get(rs, msg);
- goto out;
- }
+ while (1) {
+ /* If there are pending notifications, do those - and nothing else */
+ if (!list_empty(&rs->rs_notify_queue)) {
+ ret = rds_notify_queue_get(rs, msg);
+ break;
+ }
- if (rs->rs_cong_notify) {
- ret = rds_notify_cong(rs, msg);
- goto out;
- }
+ if (rs->rs_cong_notify) {
+ ret = rds_notify_cong(rs, msg);
+ break;
+ }
- while (1) {
if (!rds_next_incoming(rs, &inc)) {
if (nonblock) {
ret = -EAGAIN;
@@ -428,7 +428,9 @@ int rds_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg,
}
timeo = wait_event_interruptible_timeout(*sk->sk_sleep,
- rds_next_incoming(rs, &inc),
+ (!list_empty(&rs->rs_notify_queue)
+ || rs->rs_cong_notify
+ || rds_next_incoming(rs, &inc)),
timeo);
rdsdebug("recvmsg woke inc %p timeo %ld\n", inc,
timeo);
diff --git a/net/rds/stats.c b/net/rds/stats.c
index 637146893cf..91d8c58b833 100644
--- a/net/rds/stats.c
+++ b/net/rds/stats.c
@@ -40,7 +40,7 @@ DEFINE_PER_CPU_SHARED_ALIGNED(struct rds_statistics, rds_stats);
/* :.,$s/unsigned long\>.*\<s_\(.*\);/"\1",/g */
-static char *rds_stat_names[] = {
+static const char *const rds_stat_names[] = {
"conn_reset",
"recv_drop_bad_checksum",
"recv_drop_old_seq",
@@ -77,7 +77,7 @@ static char *rds_stat_names[] = {
};
void rds_stats_info_copy(struct rds_info_iterator *iter,
- uint64_t *values, char **names, size_t nr)
+ uint64_t *values, const char *const *names, size_t nr)
{
struct rds_info_counter ctr;
size_t i;
diff --git a/net/rfkill/core.c b/net/rfkill/core.c
index 2fc4a1724eb..dbeaf298382 100644
--- a/net/rfkill/core.c
+++ b/net/rfkill/core.c
@@ -589,11 +589,13 @@ static const char *rfkill_get_type_str(enum rfkill_type type)
return "wimax";
case RFKILL_TYPE_WWAN:
return "wwan";
+ case RFKILL_TYPE_GPS:
+ return "gps";
default:
BUG();
}
- BUILD_BUG_ON(NUM_RFKILL_TYPES != RFKILL_TYPE_WWAN + 1);
+ BUILD_BUG_ON(NUM_RFKILL_TYPES != RFKILL_TYPE_GPS + 1);
}
static ssize_t rfkill_type_show(struct device *dev,
@@ -1091,10 +1093,16 @@ static ssize_t rfkill_fop_write(struct file *file, const char __user *buf,
struct rfkill_event ev;
/* we don't need the 'hard' variable but accept it */
- if (count < sizeof(ev) - 1)
+ if (count < RFKILL_EVENT_SIZE_V1 - 1)
return -EINVAL;
- if (copy_from_user(&ev, buf, sizeof(ev) - 1))
+ /*
+ * Copy as much data as we can accept into our 'ev' buffer,
+ * but tell userspace how much we've copied so it can determine
+ * our API version even in a write() call, if it cares.
+ */
+ count = min(count, sizeof(ev));
+ if (copy_from_user(&ev, buf, count))
return -EFAULT;
if (ev.op != RFKILL_OP_CHANGE && ev.op != RFKILL_OP_CHANGE_ALL)
diff --git a/net/rose/rose_dev.c b/net/rose/rose_dev.c
index 389d6e0d774..c711e2edf5c 100644
--- a/net/rose/rose_dev.c
+++ b/net/rose/rose_dev.c
@@ -141,7 +141,7 @@ static int rose_xmit(struct sk_buff *skb, struct net_device *dev)
}
dev_kfree_skb(skb);
stats->tx_errors++;
- return 0;
+ return NETDEV_TX_OK;
}
static const struct header_ops rose_header_ops = {
diff --git a/net/rxrpc/ar-ack.c b/net/rxrpc/ar-ack.c
index 3ac1672e107..c9f1f0a3a2f 100644
--- a/net/rxrpc/ar-ack.c
+++ b/net/rxrpc/ar-ack.c
@@ -20,7 +20,7 @@
static unsigned rxrpc_ack_defer = 1;
-static const char *rxrpc_acks[] = {
+static const char *const rxrpc_acks[] = {
"---", "REQ", "DUP", "OOS", "WIN", "MEM", "PNG", "PNR", "DLY", "IDL",
"-?-"
};
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c
index 27d03816ec3..693df7ae33d 100644
--- a/net/sched/sch_generic.c
+++ b/net/sched/sch_generic.c
@@ -37,15 +37,11 @@
* - updates to tree and tree walking are only done under the rtnl mutex.
*/
-static inline int qdisc_qlen(struct Qdisc *q)
-{
- return q->q.qlen;
-}
-
static inline int dev_requeue_skb(struct sk_buff *skb, struct Qdisc *q)
{
q->gso_skb = skb;
q->qstats.requeues++;
+ q->q.qlen++; /* it's still part of the queue */
__netif_schedule(q);
return 0;
@@ -61,9 +57,11 @@ static inline struct sk_buff *dequeue_skb(struct Qdisc *q)
/* check the reason of requeuing without tx lock first */
txq = netdev_get_tx_queue(dev, skb_get_queue_mapping(skb));
- if (!netif_tx_queue_stopped(txq) && !netif_tx_queue_frozen(txq))
+ if (!netif_tx_queue_stopped(txq) &&
+ !netif_tx_queue_frozen(txq)) {
q->gso_skb = NULL;
- else
+ q->q.qlen--;
+ } else
skb = NULL;
} else {
skb = q->dequeue(q);
@@ -103,44 +101,23 @@ static inline int handle_dev_cpu_collision(struct sk_buff *skb,
}
/*
- * NOTE: Called under qdisc_lock(q) with locally disabled BH.
- *
- * __QDISC_STATE_RUNNING guarantees only one CPU can process
- * this qdisc at a time. qdisc_lock(q) serializes queue accesses for
- * this queue.
- *
- * netif_tx_lock serializes accesses to device driver.
- *
- * qdisc_lock(q) and netif_tx_lock are mutually exclusive,
- * if one is grabbed, another must be free.
- *
- * Note, that this procedure can be called by a watchdog timer
+ * Transmit one skb, and handle the return status as required. Holding the
+ * __QDISC_STATE_RUNNING bit guarantees that only one CPU can execute this
+ * function.
*
* Returns to the caller:
* 0 - queue is empty or throttled.
* >0 - queue is not empty.
- *
*/
-static inline int qdisc_restart(struct Qdisc *q)
+int sch_direct_xmit(struct sk_buff *skb, struct Qdisc *q,
+ struct net_device *dev, struct netdev_queue *txq,
+ spinlock_t *root_lock)
{
- struct netdev_queue *txq;
int ret = NETDEV_TX_BUSY;
- struct net_device *dev;
- spinlock_t *root_lock;
- struct sk_buff *skb;
-
- /* Dequeue packet */
- if (unlikely((skb = dequeue_skb(q)) == NULL))
- return 0;
-
- root_lock = qdisc_lock(q);
/* And release qdisc */
spin_unlock(root_lock);
- dev = qdisc_dev(q);
- txq = netdev_get_tx_queue(dev, skb_get_queue_mapping(skb));
-
HARD_TX_LOCK(dev, txq, smp_processor_id());
if (!netif_tx_queue_stopped(txq) &&
!netif_tx_queue_frozen(txq))
@@ -177,6 +154,44 @@ static inline int qdisc_restart(struct Qdisc *q)
return ret;
}
+/*
+ * NOTE: Called under qdisc_lock(q) with locally disabled BH.
+ *
+ * __QDISC_STATE_RUNNING guarantees only one CPU can process
+ * this qdisc at a time. qdisc_lock(q) serializes queue accesses for
+ * this queue.
+ *
+ * netif_tx_lock serializes accesses to device driver.
+ *
+ * qdisc_lock(q) and netif_tx_lock are mutually exclusive,
+ * if one is grabbed, another must be free.
+ *
+ * Note, that this procedure can be called by a watchdog timer
+ *
+ * Returns to the caller:
+ * 0 - queue is empty or throttled.
+ * >0 - queue is not empty.
+ *
+ */
+static inline int qdisc_restart(struct Qdisc *q)
+{
+ struct netdev_queue *txq;
+ struct net_device *dev;
+ spinlock_t *root_lock;
+ struct sk_buff *skb;
+
+ /* Dequeue packet */
+ skb = dequeue_skb(q);
+ if (unlikely(!skb))
+ return 0;
+
+ root_lock = qdisc_lock(q);
+ dev = qdisc_dev(q);
+ txq = netdev_get_tx_queue(dev, skb_get_queue_mapping(skb));
+
+ return sch_direct_xmit(skb, q, dev, txq, root_lock);
+}
+
void __qdisc_run(struct Qdisc *q)
{
unsigned long start_time = jiffies;
@@ -547,8 +562,11 @@ void qdisc_reset(struct Qdisc *qdisc)
if (ops->reset)
ops->reset(qdisc);
- kfree_skb(qdisc->gso_skb);
- qdisc->gso_skb = NULL;
+ if (qdisc->gso_skb) {
+ kfree_skb(qdisc->gso_skb);
+ qdisc->gso_skb = NULL;
+ qdisc->q.qlen = 0;
+ }
}
EXPORT_SYMBOL(qdisc_reset);
@@ -605,6 +623,9 @@ static void attach_one_default_qdisc(struct net_device *dev,
printk(KERN_INFO "%s: activation failed\n", dev->name);
return;
}
+
+ /* Can by-pass the queue discipline for default qdisc */
+ qdisc->flags |= TCQ_F_CAN_BYPASS;
} else {
qdisc = &noqueue_qdisc;
}
diff --git a/net/sched/sch_teql.c b/net/sched/sch_teql.c
index 9c002b6e053..12434b6c204 100644
--- a/net/sched/sch_teql.c
+++ b/net/sched/sch_teql.c
@@ -314,7 +314,7 @@ restart:
netif_wake_queue(dev);
txq->tx_packets++;
txq->tx_bytes += length;
- return 0;
+ return NETDEV_TX_OK;
}
__netif_tx_unlock(slave_txq);
}
@@ -323,7 +323,7 @@ restart:
break;
case 1:
master->slaves = NEXT_SLAVE(q);
- return 0;
+ return NETDEV_TX_OK;
default:
nores = 1;
break;
@@ -345,7 +345,7 @@ restart:
drop:
txq->tx_dropped++;
dev_kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
}
static int teql_master_open(struct net_device *dev)
diff --git a/net/sctp/debug.c b/net/sctp/debug.c
index 7ff548a30cf..bf24fa697de 100644
--- a/net/sctp/debug.c
+++ b/net/sctp/debug.c
@@ -52,7 +52,7 @@ int sctp_debug_flag = 1; /* Initially enable DEBUG */
#endif /* SCTP_DEBUG */
/* These are printable forms of Chunk ID's from section 3.1. */
-static const char *sctp_cid_tbl[SCTP_NUM_BASE_CHUNK_TYPES] = {
+static const char *const sctp_cid_tbl[SCTP_NUM_BASE_CHUNK_TYPES] = {
"DATA",
"INIT",
"INIT_ACK",
@@ -97,7 +97,7 @@ const char *sctp_cname(const sctp_subtype_t cid)
}
/* These are printable forms of the states. */
-const char *sctp_state_tbl[SCTP_STATE_NUM_STATES] = {
+const char *const sctp_state_tbl[SCTP_STATE_NUM_STATES] = {
"STATE_EMPTY",
"STATE_CLOSED",
"STATE_COOKIE_WAIT",
@@ -110,7 +110,7 @@ const char *sctp_state_tbl[SCTP_STATE_NUM_STATES] = {
};
/* Events that could change the state of an association. */
-const char *sctp_evttype_tbl[] = {
+const char *const sctp_evttype_tbl[] = {
"EVENT_T_unknown",
"EVENT_T_CHUNK",
"EVENT_T_TIMEOUT",
@@ -119,7 +119,7 @@ const char *sctp_evttype_tbl[] = {
};
/* Return value of a state function */
-const char *sctp_status_tbl[] = {
+const char *const sctp_status_tbl[] = {
"DISPOSITION_DISCARD",
"DISPOSITION_CONSUME",
"DISPOSITION_NOMEM",
@@ -132,7 +132,7 @@ const char *sctp_status_tbl[] = {
};
/* Printable forms of primitives */
-static const char *sctp_primitive_tbl[SCTP_NUM_PRIMITIVE_TYPES] = {
+static const char *const sctp_primitive_tbl[SCTP_NUM_PRIMITIVE_TYPES] = {
"PRIMITIVE_ASSOCIATE",
"PRIMITIVE_SHUTDOWN",
"PRIMITIVE_ABORT",
@@ -149,7 +149,7 @@ const char *sctp_pname(const sctp_subtype_t id)
return "unknown_primitive";
}
-static const char *sctp_other_tbl[] = {
+static const char *const sctp_other_tbl[] = {
"NO_PENDING_TSN",
"ICMP_PROTO_UNREACH",
};
@@ -162,7 +162,7 @@ const char *sctp_oname(const sctp_subtype_t id)
return "unknown 'other' event";
}
-static const char *sctp_timer_tbl[] = {
+static const char *const sctp_timer_tbl[] = {
"TIMEOUT_NONE",
"TIMEOUT_T1_COOKIE",
"TIMEOUT_T1_INIT",
diff --git a/net/tipc/netlink.c b/net/tipc/netlink.c
index 3c57005e44d..7bda8e3d139 100644
--- a/net/tipc/netlink.c
+++ b/net/tipc/netlink.c
@@ -62,7 +62,7 @@ static int handle_cmd(struct sk_buff *skb, struct genl_info *info)
rep_nlh = nlmsg_hdr(rep_buf);
memcpy(rep_nlh, req_nlh, hdr_space);
rep_nlh->nlmsg_len = rep_buf->len;
- genlmsg_unicast(rep_buf, NETLINK_CB(skb).pid);
+ genlmsg_unicast(&init_net, rep_buf, NETLINK_CB(skb).pid);
}
return 0;
diff --git a/net/tipc/socket.c b/net/tipc/socket.c
index 1848693ebb8..e8254e809b7 100644
--- a/net/tipc/socket.c
+++ b/net/tipc/socket.c
@@ -1748,6 +1748,12 @@ static int getsockopt(struct socket *sock,
value = jiffies_to_msecs(sk->sk_rcvtimeo);
/* no need to set "res", since already 0 at this point */
break;
+ case TIPC_NODE_RECVQ_DEPTH:
+ value = (u32)atomic_read(&tipc_queue_size);
+ break;
+ case TIPC_SOCK_RECVQ_DEPTH:
+ value = skb_queue_len(&sk->sk_receive_queue);
+ break;
default:
res = -EINVAL;
}
diff --git a/net/wireless/Kconfig b/net/wireless/Kconfig
index 4428dd5e911..c6031d5b135 100644
--- a/net/wireless/Kconfig
+++ b/net/wireless/Kconfig
@@ -2,6 +2,21 @@ config CFG80211
tristate "Improved wireless configuration API"
depends on RFKILL || !RFKILL
+config NL80211_TESTMODE
+ bool "nl80211 testmode command"
+ depends on CFG80211
+ help
+ The nl80211 testmode command helps implementing things like
+ factory calibration or validation tools for wireless chips.
+
+ Select this option ONLY for kernels that are specifically
+ built for such purposes.
+
+ Debugging tools that are supposed to end up in the hands of
+ users should better be implemented with debugfs.
+
+ Say N.
+
config CFG80211_REG_DEBUG
bool "cfg80211 regulatory debugging"
depends on CFG80211
@@ -11,6 +26,22 @@ config CFG80211_REG_DEBUG
If unsure, say N.
+config CFG80211_DEFAULT_PS
+ bool "enable powersave by default"
+ depends on CFG80211
+ default y
+ help
+ This option enables powersave mode by default.
+
+ If this causes your applications to misbehave you should fix your
+ applications instead -- they need to register their network
+ latency requirement, see Documentation/power/pm_qos_interface.txt.
+
+config CFG80211_DEFAULT_PS_VALUE
+ int
+ default 1 if CFG80211_DEFAULT_PS
+ default 0
+
config CFG80211_DEBUGFS
bool "cfg80211 DebugFS entries"
depends on CFG80211 && DEBUG_FS
@@ -35,19 +66,13 @@ config WIRELESS_OLD_REGULATORY
config WIRELESS_EXT
bool "Wireless extensions"
- default n
+ default y
---help---
This option enables the legacy wireless extensions
(wireless network interface configuration via ioctls.)
- Wireless extensions will be replaced by cfg80211 and
- will be required only by legacy drivers that implement
- wireless extension handlers. This option does not
- affect the wireless-extension backward compatibility
- code in cfg80211.
-
- Say N (if you can) unless you know you need wireless
- extensions for external modules.
+ Say Y unless you've upgraded all your userspace to use
+ nl80211 instead of wireless extensions.
config WIRELESS_EXT_SYSFS
bool "Wireless extensions sysfs files"
diff --git a/net/wireless/Makefile b/net/wireless/Makefile
index f78c4832a9c..3ecaa917997 100644
--- a/net/wireless/Makefile
+++ b/net/wireless/Makefile
@@ -5,8 +5,9 @@ obj-$(CONFIG_LIB80211_CRYPT_WEP) += lib80211_crypt_wep.o
obj-$(CONFIG_LIB80211_CRYPT_CCMP) += lib80211_crypt_ccmp.o
obj-$(CONFIG_LIB80211_CRYPT_TKIP) += lib80211_crypt_tkip.o
-cfg80211-y += core.o sysfs.o radiotap.o util.o reg.o scan.o nl80211.o mlme.o ibss.o
+cfg80211-y += core.o sysfs.o radiotap.o util.o reg.o scan.o nl80211.o
+cfg80211-y += mlme.o ibss.o sme.o chan.o
cfg80211-$(CONFIG_CFG80211_DEBUGFS) += debugfs.o
-cfg80211-$(CONFIG_WIRELESS_EXT) += wext-compat.o
+cfg80211-$(CONFIG_WIRELESS_EXT) += wext-compat.o wext-sme.o
ccflags-y += -D__CHECK_ENDIAN__
diff --git a/net/wireless/chan.c b/net/wireless/chan.c
new file mode 100644
index 00000000000..a46ac6c9b36
--- /dev/null
+++ b/net/wireless/chan.c
@@ -0,0 +1,89 @@
+/*
+ * This file contains helper code to handle channel
+ * settings and keeping track of what is possible at
+ * any point in time.
+ *
+ * Copyright 2009 Johannes Berg <johannes@sipsolutions.net>
+ */
+
+#include <net/cfg80211.h>
+#include "core.h"
+
+struct ieee80211_channel *
+rdev_fixed_channel(struct cfg80211_registered_device *rdev,
+ struct wireless_dev *for_wdev)
+{
+ struct wireless_dev *wdev;
+ struct ieee80211_channel *result = NULL;
+
+ WARN_ON(!mutex_is_locked(&rdev->devlist_mtx));
+
+ list_for_each_entry(wdev, &rdev->netdev_list, list) {
+ if (wdev == for_wdev)
+ continue;
+
+ /*
+ * Lock manually to tell lockdep about allowed
+ * nesting here if for_wdev->mtx is held already.
+ * This is ok as it's all under the rdev devlist
+ * mutex and as such can only be done once at any
+ * given time.
+ */
+ mutex_lock_nested(&wdev->mtx, SINGLE_DEPTH_NESTING);
+ if (wdev->current_bss)
+ result = wdev->current_bss->pub.channel;
+ wdev_unlock(wdev);
+
+ if (result)
+ break;
+ }
+
+ return result;
+}
+
+int rdev_set_freq(struct cfg80211_registered_device *rdev,
+ struct wireless_dev *for_wdev,
+ int freq, enum nl80211_channel_type channel_type)
+{
+ struct ieee80211_channel *chan;
+ struct ieee80211_sta_ht_cap *ht_cap;
+ int result;
+
+ if (rdev_fixed_channel(rdev, for_wdev))
+ return -EBUSY;
+
+ if (!rdev->ops->set_channel)
+ return -EOPNOTSUPP;
+
+ chan = ieee80211_get_channel(&rdev->wiphy, freq);
+
+ /* Primary channel not allowed */
+ if (!chan || chan->flags & IEEE80211_CHAN_DISABLED)
+ return -EINVAL;
+
+ if (channel_type == NL80211_CHAN_HT40MINUS &&
+ chan->flags & IEEE80211_CHAN_NO_HT40MINUS)
+ return -EINVAL;
+ else if (channel_type == NL80211_CHAN_HT40PLUS &&
+ chan->flags & IEEE80211_CHAN_NO_HT40PLUS)
+ return -EINVAL;
+
+ ht_cap = &rdev->wiphy.bands[chan->band]->ht_cap;
+
+ if (channel_type != NL80211_CHAN_NO_HT) {
+ if (!ht_cap->ht_supported)
+ return -EINVAL;
+
+ if (!(ht_cap->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) ||
+ ht_cap->cap & IEEE80211_HT_CAP_40MHZ_INTOLERANT)
+ return -EINVAL;
+ }
+
+ result = rdev->ops->set_channel(&rdev->wiphy, chan, channel_type);
+ if (result)
+ return result;
+
+ rdev->channel = chan;
+
+ return 0;
+}
diff --git a/net/wireless/core.c b/net/wireless/core.c
index d5850292b3d..bc99e4ec746 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -19,6 +19,7 @@
#include "core.h"
#include "sysfs.h"
#include "debugfs.h"
+#include "wext-compat.h"
/* name for sysfs, %d is appended */
#define PHY_NAME "phy"
@@ -30,12 +31,11 @@ MODULE_DESCRIPTION("wireless configuration support");
/* RCU might be appropriate here since we usually
* only read the list, and that can happen quite
* often because we need to do it for each command */
-LIST_HEAD(cfg80211_drv_list);
+LIST_HEAD(cfg80211_rdev_list);
+int cfg80211_rdev_list_generation;
/*
- * This is used to protect the cfg80211_drv_list, cfg80211_regdomain,
- * country_ie_regdomain, the reg_beacon_list and the the last regulatory
- * request receipt (last_request).
+ * This is used to protect the cfg80211_rdev_list
*/
DEFINE_MUTEX(cfg80211_mutex);
@@ -43,18 +43,18 @@ DEFINE_MUTEX(cfg80211_mutex);
static struct dentry *ieee80211_debugfs_dir;
/* requires cfg80211_mutex to be held! */
-struct cfg80211_registered_device *cfg80211_drv_by_wiphy_idx(int wiphy_idx)
+struct cfg80211_registered_device *cfg80211_rdev_by_wiphy_idx(int wiphy_idx)
{
- struct cfg80211_registered_device *result = NULL, *drv;
+ struct cfg80211_registered_device *result = NULL, *rdev;
if (!wiphy_idx_valid(wiphy_idx))
return NULL;
assert_cfg80211_lock();
- list_for_each_entry(drv, &cfg80211_drv_list, list) {
- if (drv->wiphy_idx == wiphy_idx) {
- result = drv;
+ list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
+ if (rdev->wiphy_idx == wiphy_idx) {
+ result = rdev;
break;
}
}
@@ -64,32 +64,32 @@ struct cfg80211_registered_device *cfg80211_drv_by_wiphy_idx(int wiphy_idx)
int get_wiphy_idx(struct wiphy *wiphy)
{
- struct cfg80211_registered_device *drv;
+ struct cfg80211_registered_device *rdev;
if (!wiphy)
return WIPHY_IDX_STALE;
- drv = wiphy_to_dev(wiphy);
- return drv->wiphy_idx;
+ rdev = wiphy_to_dev(wiphy);
+ return rdev->wiphy_idx;
}
-/* requires cfg80211_drv_mutex to be held! */
+/* requires cfg80211_rdev_mutex to be held! */
struct wiphy *wiphy_idx_to_wiphy(int wiphy_idx)
{
- struct cfg80211_registered_device *drv;
+ struct cfg80211_registered_device *rdev;
if (!wiphy_idx_valid(wiphy_idx))
return NULL;
assert_cfg80211_lock();
- drv = cfg80211_drv_by_wiphy_idx(wiphy_idx);
- if (!drv)
+ rdev = cfg80211_rdev_by_wiphy_idx(wiphy_idx);
+ if (!rdev)
return NULL;
- return &drv->wiphy;
+ return &rdev->wiphy;
}
/* requires cfg80211_mutex to be held! */
struct cfg80211_registered_device *
-__cfg80211_drv_from_info(struct genl_info *info)
+__cfg80211_rdev_from_info(struct genl_info *info)
{
int ifindex;
struct cfg80211_registered_device *bywiphyidx = NULL, *byifidx = NULL;
@@ -99,14 +99,14 @@ __cfg80211_drv_from_info(struct genl_info *info)
assert_cfg80211_lock();
if (info->attrs[NL80211_ATTR_WIPHY]) {
- bywiphyidx = cfg80211_drv_by_wiphy_idx(
+ bywiphyidx = cfg80211_rdev_by_wiphy_idx(
nla_get_u32(info->attrs[NL80211_ATTR_WIPHY]));
err = -ENODEV;
}
if (info->attrs[NL80211_ATTR_IFINDEX]) {
ifindex = nla_get_u32(info->attrs[NL80211_ATTR_IFINDEX]);
- dev = dev_get_by_index(&init_net, ifindex);
+ dev = dev_get_by_index(genl_info_net(info), ifindex);
if (dev) {
if (dev->ieee80211_ptr)
byifidx =
@@ -134,54 +134,48 @@ __cfg80211_drv_from_info(struct genl_info *info)
struct cfg80211_registered_device *
cfg80211_get_dev_from_info(struct genl_info *info)
{
- struct cfg80211_registered_device *drv;
+ struct cfg80211_registered_device *rdev;
mutex_lock(&cfg80211_mutex);
- drv = __cfg80211_drv_from_info(info);
+ rdev = __cfg80211_rdev_from_info(info);
/* if it is not an error we grab the lock on
* it to assure it won't be going away while
* we operate on it */
- if (!IS_ERR(drv))
- mutex_lock(&drv->mtx);
+ if (!IS_ERR(rdev))
+ mutex_lock(&rdev->mtx);
mutex_unlock(&cfg80211_mutex);
- return drv;
+ return rdev;
}
struct cfg80211_registered_device *
-cfg80211_get_dev_from_ifindex(int ifindex)
+cfg80211_get_dev_from_ifindex(struct net *net, int ifindex)
{
- struct cfg80211_registered_device *drv = ERR_PTR(-ENODEV);
+ struct cfg80211_registered_device *rdev = ERR_PTR(-ENODEV);
struct net_device *dev;
mutex_lock(&cfg80211_mutex);
- dev = dev_get_by_index(&init_net, ifindex);
+ dev = dev_get_by_index(net, ifindex);
if (!dev)
goto out;
if (dev->ieee80211_ptr) {
- drv = wiphy_to_dev(dev->ieee80211_ptr->wiphy);
- mutex_lock(&drv->mtx);
+ rdev = wiphy_to_dev(dev->ieee80211_ptr->wiphy);
+ mutex_lock(&rdev->mtx);
} else
- drv = ERR_PTR(-ENODEV);
+ rdev = ERR_PTR(-ENODEV);
dev_put(dev);
out:
mutex_unlock(&cfg80211_mutex);
- return drv;
-}
-
-void cfg80211_put_dev(struct cfg80211_registered_device *drv)
-{
- BUG_ON(IS_ERR(drv));
- mutex_unlock(&drv->mtx);
+ return rdev;
}
/* requires cfg80211_mutex to be held */
int cfg80211_dev_rename(struct cfg80211_registered_device *rdev,
char *newname)
{
- struct cfg80211_registered_device *drv;
+ struct cfg80211_registered_device *rdev2;
int wiphy_idx, taken = -1, result, digits;
assert_cfg80211_lock();
@@ -207,8 +201,8 @@ int cfg80211_dev_rename(struct cfg80211_registered_device *rdev,
return 0;
/* Ensure another device does not already have this name. */
- list_for_each_entry(drv, &cfg80211_drv_list, list)
- if (strcmp(newname, dev_name(&drv->wiphy.dev)) == 0)
+ list_for_each_entry(rdev2, &cfg80211_rdev_list, list)
+ if (strcmp(newname, dev_name(&rdev2->wiphy.dev)) == 0)
return -EINVAL;
result = device_rename(&rdev->wiphy.dev, newname);
@@ -228,28 +222,64 @@ int cfg80211_dev_rename(struct cfg80211_registered_device *rdev,
return 0;
}
+int cfg80211_switch_netns(struct cfg80211_registered_device *rdev,
+ struct net *net)
+{
+ struct wireless_dev *wdev;
+ int err = 0;
+
+ if (!rdev->wiphy.netnsok)
+ return -EOPNOTSUPP;
+
+ list_for_each_entry(wdev, &rdev->netdev_list, list) {
+ wdev->netdev->features &= ~NETIF_F_NETNS_LOCAL;
+ err = dev_change_net_namespace(wdev->netdev, net, "wlan%d");
+ if (err)
+ break;
+ wdev->netdev->features |= NETIF_F_NETNS_LOCAL;
+ }
+
+ if (err) {
+ /* failed -- clean up to old netns */
+ net = wiphy_net(&rdev->wiphy);
+
+ list_for_each_entry_continue_reverse(wdev, &rdev->netdev_list,
+ list) {
+ wdev->netdev->features &= ~NETIF_F_NETNS_LOCAL;
+ err = dev_change_net_namespace(wdev->netdev, net,
+ "wlan%d");
+ WARN_ON(err);
+ wdev->netdev->features |= NETIF_F_NETNS_LOCAL;
+ }
+ }
+
+ wiphy_net_set(&rdev->wiphy, net);
+
+ return err;
+}
+
static void cfg80211_rfkill_poll(struct rfkill *rfkill, void *data)
{
- struct cfg80211_registered_device *drv = data;
+ struct cfg80211_registered_device *rdev = data;
- drv->ops->rfkill_poll(&drv->wiphy);
+ rdev->ops->rfkill_poll(&rdev->wiphy);
}
static int cfg80211_rfkill_set_block(void *data, bool blocked)
{
- struct cfg80211_registered_device *drv = data;
+ struct cfg80211_registered_device *rdev = data;
struct wireless_dev *wdev;
if (!blocked)
return 0;
rtnl_lock();
- mutex_lock(&drv->devlist_mtx);
+ mutex_lock(&rdev->devlist_mtx);
- list_for_each_entry(wdev, &drv->netdev_list, list)
+ list_for_each_entry(wdev, &rdev->netdev_list, list)
dev_close(wdev->netdev);
- mutex_unlock(&drv->devlist_mtx);
+ mutex_unlock(&rdev->devlist_mtx);
rtnl_unlock();
return 0;
@@ -257,10 +287,76 @@ static int cfg80211_rfkill_set_block(void *data, bool blocked)
static void cfg80211_rfkill_sync_work(struct work_struct *work)
{
- struct cfg80211_registered_device *drv;
+ struct cfg80211_registered_device *rdev;
+
+ rdev = container_of(work, struct cfg80211_registered_device, rfkill_sync);
+ cfg80211_rfkill_set_block(rdev, rfkill_blocked(rdev->rfkill));
+}
+
+static void cfg80211_process_events(struct wireless_dev *wdev)
+{
+ struct cfg80211_event *ev;
+ unsigned long flags;
+
+ spin_lock_irqsave(&wdev->event_lock, flags);
+ while (!list_empty(&wdev->event_list)) {
+ ev = list_first_entry(&wdev->event_list,
+ struct cfg80211_event, list);
+ list_del(&ev->list);
+ spin_unlock_irqrestore(&wdev->event_lock, flags);
+
+ wdev_lock(wdev);
+ switch (ev->type) {
+ case EVENT_CONNECT_RESULT:
+ __cfg80211_connect_result(
+ wdev->netdev, ev->cr.bssid,
+ ev->cr.req_ie, ev->cr.req_ie_len,
+ ev->cr.resp_ie, ev->cr.resp_ie_len,
+ ev->cr.status,
+ ev->cr.status == WLAN_STATUS_SUCCESS,
+ NULL);
+ break;
+ case EVENT_ROAMED:
+ __cfg80211_roamed(wdev, ev->rm.bssid,
+ ev->rm.req_ie, ev->rm.req_ie_len,
+ ev->rm.resp_ie, ev->rm.resp_ie_len);
+ break;
+ case EVENT_DISCONNECTED:
+ __cfg80211_disconnected(wdev->netdev,
+ ev->dc.ie, ev->dc.ie_len,
+ ev->dc.reason, true);
+ break;
+ case EVENT_IBSS_JOINED:
+ __cfg80211_ibss_joined(wdev->netdev, ev->ij.bssid);
+ break;
+ }
+ wdev_unlock(wdev);
+
+ kfree(ev);
+
+ spin_lock_irqsave(&wdev->event_lock, flags);
+ }
+ spin_unlock_irqrestore(&wdev->event_lock, flags);
+}
+
+static void cfg80211_event_work(struct work_struct *work)
+{
+ struct cfg80211_registered_device *rdev;
+ struct wireless_dev *wdev;
+
+ rdev = container_of(work, struct cfg80211_registered_device,
+ event_work);
+
+ rtnl_lock();
+ cfg80211_lock_rdev(rdev);
+ mutex_lock(&rdev->devlist_mtx);
+
+ list_for_each_entry(wdev, &rdev->netdev_list, list)
+ cfg80211_process_events(wdev);
- drv = container_of(work, struct cfg80211_registered_device, rfkill_sync);
- cfg80211_rfkill_set_block(drv, rfkill_blocked(drv->rfkill));
+ mutex_unlock(&rdev->devlist_mtx);
+ cfg80211_unlock_rdev(rdev);
+ rtnl_unlock();
}
/* exported functions */
@@ -269,76 +365,88 @@ struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv)
{
static int wiphy_counter;
- struct cfg80211_registered_device *drv;
+ struct cfg80211_registered_device *rdev;
int alloc_size;
- WARN_ON(!ops->add_key && ops->del_key);
- WARN_ON(ops->add_key && !ops->del_key);
+ WARN_ON(ops->add_key && (!ops->del_key || !ops->set_default_key));
+ WARN_ON(ops->auth && (!ops->assoc || !ops->deauth || !ops->disassoc));
+ WARN_ON(ops->connect && !ops->disconnect);
+ WARN_ON(ops->join_ibss && !ops->leave_ibss);
+ WARN_ON(ops->add_virtual_intf && !ops->del_virtual_intf);
+ WARN_ON(ops->add_station && !ops->del_station);
+ WARN_ON(ops->add_mpath && !ops->del_mpath);
- alloc_size = sizeof(*drv) + sizeof_priv;
+ alloc_size = sizeof(*rdev) + sizeof_priv;
- drv = kzalloc(alloc_size, GFP_KERNEL);
- if (!drv)
+ rdev = kzalloc(alloc_size, GFP_KERNEL);
+ if (!rdev)
return NULL;
- drv->ops = ops;
+ rdev->ops = ops;
mutex_lock(&cfg80211_mutex);
- drv->wiphy_idx = wiphy_counter++;
+ rdev->wiphy_idx = wiphy_counter++;
- if (unlikely(!wiphy_idx_valid(drv->wiphy_idx))) {
+ if (unlikely(!wiphy_idx_valid(rdev->wiphy_idx))) {
wiphy_counter--;
mutex_unlock(&cfg80211_mutex);
/* ugh, wrapped! */
- kfree(drv);
+ kfree(rdev);
return NULL;
}
mutex_unlock(&cfg80211_mutex);
/* give it a proper name */
- dev_set_name(&drv->wiphy.dev, PHY_NAME "%d", drv->wiphy_idx);
+ dev_set_name(&rdev->wiphy.dev, PHY_NAME "%d", rdev->wiphy_idx);
+
+ mutex_init(&rdev->mtx);
+ mutex_init(&rdev->devlist_mtx);
+ INIT_LIST_HEAD(&rdev->netdev_list);
+ spin_lock_init(&rdev->bss_lock);
+ INIT_LIST_HEAD(&rdev->bss_list);
+ INIT_WORK(&rdev->scan_done_wk, __cfg80211_scan_done);
- mutex_init(&drv->mtx);
- mutex_init(&drv->devlist_mtx);
- INIT_LIST_HEAD(&drv->netdev_list);
- spin_lock_init(&drv->bss_lock);
- INIT_LIST_HEAD(&drv->bss_list);
+ device_initialize(&rdev->wiphy.dev);
+ rdev->wiphy.dev.class = &ieee80211_class;
+ rdev->wiphy.dev.platform_data = rdev;
- device_initialize(&drv->wiphy.dev);
- drv->wiphy.dev.class = &ieee80211_class;
- drv->wiphy.dev.platform_data = drv;
+ rdev->wiphy.ps_default = CONFIG_CFG80211_DEFAULT_PS_VALUE;
- drv->rfkill_ops.set_block = cfg80211_rfkill_set_block;
- drv->rfkill = rfkill_alloc(dev_name(&drv->wiphy.dev),
- &drv->wiphy.dev, RFKILL_TYPE_WLAN,
- &drv->rfkill_ops, drv);
+ wiphy_net_set(&rdev->wiphy, &init_net);
- if (!drv->rfkill) {
- kfree(drv);
+ rdev->rfkill_ops.set_block = cfg80211_rfkill_set_block;
+ rdev->rfkill = rfkill_alloc(dev_name(&rdev->wiphy.dev),
+ &rdev->wiphy.dev, RFKILL_TYPE_WLAN,
+ &rdev->rfkill_ops, rdev);
+
+ if (!rdev->rfkill) {
+ kfree(rdev);
return NULL;
}
- INIT_WORK(&drv->rfkill_sync, cfg80211_rfkill_sync_work);
+ INIT_WORK(&rdev->rfkill_sync, cfg80211_rfkill_sync_work);
+ INIT_WORK(&rdev->conn_work, cfg80211_conn_work);
+ INIT_WORK(&rdev->event_work, cfg80211_event_work);
/*
* Initialize wiphy parameters to IEEE 802.11 MIB default values.
* Fragmentation and RTS threshold are disabled by default with the
* special -1 value.
*/
- drv->wiphy.retry_short = 7;
- drv->wiphy.retry_long = 4;
- drv->wiphy.frag_threshold = (u32) -1;
- drv->wiphy.rts_threshold = (u32) -1;
+ rdev->wiphy.retry_short = 7;
+ rdev->wiphy.retry_long = 4;
+ rdev->wiphy.frag_threshold = (u32) -1;
+ rdev->wiphy.rts_threshold = (u32) -1;
- return &drv->wiphy;
+ return &rdev->wiphy;
}
EXPORT_SYMBOL(wiphy_new);
int wiphy_register(struct wiphy *wiphy)
{
- struct cfg80211_registered_device *drv = wiphy_to_dev(wiphy);
+ struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
int res;
enum ieee80211_band band;
struct ieee80211_supported_band *sband;
@@ -346,9 +454,6 @@ int wiphy_register(struct wiphy *wiphy)
int i;
u16 ifmodes = wiphy->interface_modes;
- if (WARN_ON(wiphy->max_scan_ssids < 1))
- return -EINVAL;
-
/* sanity check ifmodes */
WARN_ON(!ifmodes);
ifmodes &= ((1 << __NL80211_IFTYPE_AFTER_LAST) - 1) & ~1;
@@ -395,11 +500,11 @@ int wiphy_register(struct wiphy *wiphy)
/* check and set up bitrates */
ieee80211_set_bitrate_flags(wiphy);
- res = device_add(&drv->wiphy.dev);
+ res = device_add(&rdev->wiphy.dev);
if (res)
return res;
- res = rfkill_register(drv->rfkill);
+ res = rfkill_register(rdev->rfkill);
if (res)
goto out_rm_dev;
@@ -408,16 +513,17 @@ int wiphy_register(struct wiphy *wiphy)
/* set up regulatory info */
wiphy_update_regulatory(wiphy, NL80211_REGDOM_SET_BY_CORE);
- list_add(&drv->list, &cfg80211_drv_list);
+ list_add(&rdev->list, &cfg80211_rdev_list);
+ cfg80211_rdev_list_generation++;
mutex_unlock(&cfg80211_mutex);
/* add to debugfs */
- drv->wiphy.debugfsdir =
- debugfs_create_dir(wiphy_name(&drv->wiphy),
+ rdev->wiphy.debugfsdir =
+ debugfs_create_dir(wiphy_name(&rdev->wiphy),
ieee80211_debugfs_dir);
- if (IS_ERR(drv->wiphy.debugfsdir))
- drv->wiphy.debugfsdir = NULL;
+ if (IS_ERR(rdev->wiphy.debugfsdir))
+ rdev->wiphy.debugfsdir = NULL;
if (wiphy->custom_regulatory) {
struct regulatory_request request;
@@ -430,48 +536,48 @@ int wiphy_register(struct wiphy *wiphy)
nl80211_send_reg_change_event(&request);
}
- cfg80211_debugfs_drv_add(drv);
+ cfg80211_debugfs_rdev_add(rdev);
return 0;
out_rm_dev:
- device_del(&drv->wiphy.dev);
+ device_del(&rdev->wiphy.dev);
return res;
}
EXPORT_SYMBOL(wiphy_register);
void wiphy_rfkill_start_polling(struct wiphy *wiphy)
{
- struct cfg80211_registered_device *drv = wiphy_to_dev(wiphy);
+ struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
- if (!drv->ops->rfkill_poll)
+ if (!rdev->ops->rfkill_poll)
return;
- drv->rfkill_ops.poll = cfg80211_rfkill_poll;
- rfkill_resume_polling(drv->rfkill);
+ rdev->rfkill_ops.poll = cfg80211_rfkill_poll;
+ rfkill_resume_polling(rdev->rfkill);
}
EXPORT_SYMBOL(wiphy_rfkill_start_polling);
void wiphy_rfkill_stop_polling(struct wiphy *wiphy)
{
- struct cfg80211_registered_device *drv = wiphy_to_dev(wiphy);
+ struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
- rfkill_pause_polling(drv->rfkill);
+ rfkill_pause_polling(rdev->rfkill);
}
EXPORT_SYMBOL(wiphy_rfkill_stop_polling);
void wiphy_unregister(struct wiphy *wiphy)
{
- struct cfg80211_registered_device *drv = wiphy_to_dev(wiphy);
+ struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
- rfkill_unregister(drv->rfkill);
+ rfkill_unregister(rdev->rfkill);
/* protect the device list */
mutex_lock(&cfg80211_mutex);
- BUG_ON(!list_empty(&drv->netdev_list));
+ BUG_ON(!list_empty(&rdev->netdev_list));
/*
- * Try to grab drv->mtx. If a command is still in progress,
+ * Try to grab rdev->mtx. If a command is still in progress,
* hopefully the driver will refuse it since it's tearing
* down the device already. We wait for this command to complete
* before unlinking the item from the list.
@@ -480,33 +586,39 @@ void wiphy_unregister(struct wiphy *wiphy)
* get to lock contention here if userspace issues a command
* that identified the hardware by wiphy index.
*/
- mutex_lock(&drv->mtx);
+ mutex_lock(&rdev->mtx);
/* unlock again before freeing */
- mutex_unlock(&drv->mtx);
+ mutex_unlock(&rdev->mtx);
- cfg80211_debugfs_drv_del(drv);
+ cfg80211_debugfs_rdev_del(rdev);
/* If this device got a regulatory hint tell core its
* free to listen now to a new shiny device regulatory hint */
reg_device_remove(wiphy);
- list_del(&drv->list);
- device_del(&drv->wiphy.dev);
- debugfs_remove(drv->wiphy.debugfsdir);
+ list_del(&rdev->list);
+ cfg80211_rdev_list_generation++;
+ device_del(&rdev->wiphy.dev);
+ debugfs_remove(rdev->wiphy.debugfsdir);
mutex_unlock(&cfg80211_mutex);
+
+ flush_work(&rdev->scan_done_wk);
+ cancel_work_sync(&rdev->conn_work);
+ kfree(rdev->scan_req);
+ flush_work(&rdev->event_work);
}
EXPORT_SYMBOL(wiphy_unregister);
-void cfg80211_dev_free(struct cfg80211_registered_device *drv)
+void cfg80211_dev_free(struct cfg80211_registered_device *rdev)
{
struct cfg80211_internal_bss *scan, *tmp;
- rfkill_destroy(drv->rfkill);
- mutex_destroy(&drv->mtx);
- mutex_destroy(&drv->devlist_mtx);
- list_for_each_entry_safe(scan, tmp, &drv->bss_list, list)
+ rfkill_destroy(rdev->rfkill);
+ mutex_destroy(&rdev->mtx);
+ mutex_destroy(&rdev->devlist_mtx);
+ list_for_each_entry_safe(scan, tmp, &rdev->bss_list, list)
cfg80211_put_bss(&scan->pub);
- kfree(drv);
+ kfree(rdev);
}
void wiphy_free(struct wiphy *wiphy)
@@ -517,10 +629,10 @@ EXPORT_SYMBOL(wiphy_free);
void wiphy_rfkill_set_hw_state(struct wiphy *wiphy, bool blocked)
{
- struct cfg80211_registered_device *drv = wiphy_to_dev(wiphy);
+ struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
- if (rfkill_set_hw_state(drv->rfkill, blocked))
- schedule_work(&drv->rfkill_sync);
+ if (rfkill_set_hw_state(rdev->rfkill, blocked))
+ schedule_work(&rdev->rfkill_sync);
}
EXPORT_SYMBOL(wiphy_rfkill_set_hw_state);
@@ -529,56 +641,125 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb,
void *ndev)
{
struct net_device *dev = ndev;
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
struct cfg80211_registered_device *rdev;
- if (!dev->ieee80211_ptr)
+ if (!wdev)
return NOTIFY_DONE;
- rdev = wiphy_to_dev(dev->ieee80211_ptr->wiphy);
+ rdev = wiphy_to_dev(wdev->wiphy);
- WARN_ON(dev->ieee80211_ptr->iftype == NL80211_IFTYPE_UNSPECIFIED);
+ WARN_ON(wdev->iftype == NL80211_IFTYPE_UNSPECIFIED);
switch (state) {
case NETDEV_REGISTER:
+ mutex_init(&wdev->mtx);
+ INIT_LIST_HEAD(&wdev->event_list);
+ spin_lock_init(&wdev->event_lock);
mutex_lock(&rdev->devlist_mtx);
- list_add(&dev->ieee80211_ptr->list, &rdev->netdev_list);
+ list_add(&wdev->list, &rdev->netdev_list);
+ rdev->devlist_generation++;
+ /* can only change netns with wiphy */
+ dev->features |= NETIF_F_NETNS_LOCAL;
+
if (sysfs_create_link(&dev->dev.kobj, &rdev->wiphy.dev.kobj,
"phy80211")) {
printk(KERN_ERR "wireless: failed to add phy80211 "
"symlink to netdev!\n");
}
- dev->ieee80211_ptr->netdev = dev;
+ wdev->netdev = dev;
+ wdev->sme_state = CFG80211_SME_IDLE;
+ mutex_unlock(&rdev->devlist_mtx);
#ifdef CONFIG_WIRELESS_EXT
- dev->ieee80211_ptr->wext.default_key = -1;
- dev->ieee80211_ptr->wext.default_mgmt_key = -1;
+ if (!dev->wireless_handlers)
+ dev->wireless_handlers = &cfg80211_wext_handler;
+ wdev->wext.default_key = -1;
+ wdev->wext.default_mgmt_key = -1;
+ wdev->wext.connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC;
+ wdev->wext.ps = wdev->wiphy->ps_default;
+ wdev->wext.ps_timeout = 100;
+ if (rdev->ops->set_power_mgmt)
+ if (rdev->ops->set_power_mgmt(wdev->wiphy, dev,
+ wdev->wext.ps,
+ wdev->wext.ps_timeout)) {
+ /* assume this means it's off */
+ wdev->wext.ps = false;
+ }
#endif
- mutex_unlock(&rdev->devlist_mtx);
break;
case NETDEV_GOING_DOWN:
- if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC)
+ switch (wdev->iftype) {
+ case NL80211_IFTYPE_ADHOC:
+ cfg80211_leave_ibss(rdev, dev, true);
break;
- if (!dev->ieee80211_ptr->ssid_len)
+ case NL80211_IFTYPE_STATION:
+ wdev_lock(wdev);
+#ifdef CONFIG_WIRELESS_EXT
+ kfree(wdev->wext.ie);
+ wdev->wext.ie = NULL;
+ wdev->wext.ie_len = 0;
+ wdev->wext.connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC;
+#endif
+ __cfg80211_disconnect(rdev, dev,
+ WLAN_REASON_DEAUTH_LEAVING, true);
+ cfg80211_mlme_down(rdev, dev);
+ wdev_unlock(wdev);
+ break;
+ default:
break;
- cfg80211_leave_ibss(rdev, dev, true);
+ }
break;
case NETDEV_UP:
#ifdef CONFIG_WIRELESS_EXT
- if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC)
+ cfg80211_lock_rdev(rdev);
+ mutex_lock(&rdev->devlist_mtx);
+ wdev_lock(wdev);
+ switch (wdev->iftype) {
+ case NL80211_IFTYPE_ADHOC:
+ cfg80211_ibss_wext_join(rdev, wdev);
break;
- if (!dev->ieee80211_ptr->wext.ibss.ssid_len)
+ case NL80211_IFTYPE_STATION:
+ cfg80211_mgd_wext_connect(rdev, wdev);
break;
- cfg80211_join_ibss(rdev, dev, &dev->ieee80211_ptr->wext.ibss);
- break;
+ default:
+ break;
+ }
+ wdev_unlock(wdev);
+ mutex_unlock(&rdev->devlist_mtx);
+ cfg80211_unlock_rdev(rdev);
#endif
+ break;
case NETDEV_UNREGISTER:
+ cfg80211_lock_rdev(rdev);
+
+ if (WARN_ON(rdev->scan_req && rdev->scan_req->dev == dev)) {
+ rdev->scan_req->aborted = true;
+ ___cfg80211_scan_done(rdev);
+ }
+
mutex_lock(&rdev->devlist_mtx);
- if (!list_empty(&dev->ieee80211_ptr->list)) {
+ /*
+ * It is possible to get NETDEV_UNREGISTER
+ * multiple times. To detect that, check
+ * that the interface is still on the list
+ * of registered interfaces, and only then
+ * remove and clean it up.
+ */
+ if (!list_empty(&wdev->list)) {
sysfs_remove_link(&dev->dev.kobj, "phy80211");
- list_del_init(&dev->ieee80211_ptr->list);
+ list_del_init(&wdev->list);
+ rdev->devlist_generation++;
+ mutex_destroy(&wdev->mtx);
+#ifdef CONFIG_WIRELESS_EXT
+ kfree(wdev->wext.keys);
+#endif
}
mutex_unlock(&rdev->devlist_mtx);
+ cfg80211_unlock_rdev(rdev);
break;
case NETDEV_PRE_UP:
+ if (!(wdev->wiphy->interface_modes & BIT(wdev->iftype)))
+ return notifier_from_errno(-EOPNOTSUPP);
if (rfkill_blocked(rdev->rfkill))
return notifier_from_errno(-ERFKILL);
break;
@@ -591,10 +772,32 @@ static struct notifier_block cfg80211_netdev_notifier = {
.notifier_call = cfg80211_netdev_notifier_call,
};
-static int cfg80211_init(void)
+static void __net_exit cfg80211_pernet_exit(struct net *net)
+{
+ struct cfg80211_registered_device *rdev;
+
+ rtnl_lock();
+ mutex_lock(&cfg80211_mutex);
+ list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
+ if (net_eq(wiphy_net(&rdev->wiphy), net))
+ WARN_ON(cfg80211_switch_netns(rdev, &init_net));
+ }
+ mutex_unlock(&cfg80211_mutex);
+ rtnl_unlock();
+}
+
+static struct pernet_operations cfg80211_pernet_ops = {
+ .exit = cfg80211_pernet_exit,
+};
+
+static int __init cfg80211_init(void)
{
int err;
+ err = register_pernet_device(&cfg80211_pernet_ops);
+ if (err)
+ goto out_fail_pernet;
+
err = wiphy_sysfs_init();
if (err)
goto out_fail_sysfs;
@@ -622,9 +825,10 @@ out_fail_nl80211:
out_fail_notifier:
wiphy_sysfs_exit();
out_fail_sysfs:
+ unregister_pernet_device(&cfg80211_pernet_ops);
+out_fail_pernet:
return err;
}
-
subsys_initcall(cfg80211_init);
static void cfg80211_exit(void)
@@ -634,5 +838,6 @@ static void cfg80211_exit(void)
unregister_netdevice_notifier(&cfg80211_netdev_notifier);
wiphy_sysfs_exit();
regulatory_exit();
+ unregister_pernet_device(&cfg80211_pernet_ops);
}
module_exit(cfg80211_exit);
diff --git a/net/wireless/core.h b/net/wireless/core.h
index bfa340c7abb..c603f528632 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -49,6 +49,7 @@ struct cfg80211_registered_device {
/* associate netdev list */
struct mutex devlist_mtx;
struct list_head netdev_list;
+ int devlist_generation;
/* BSSes/scanning */
spinlock_t bss_lock;
@@ -57,6 +58,17 @@ struct cfg80211_registered_device {
u32 bss_generation;
struct cfg80211_scan_request *scan_req; /* protected by RTNL */
unsigned long suspend_at;
+ struct work_struct scan_done_wk;
+
+#ifdef CONFIG_NL80211_TESTMODE
+ struct genl_info *testmode_info;
+#endif
+
+ struct work_struct conn_work;
+ struct work_struct event_work;
+
+ /* current channel */
+ struct ieee80211_channel *channel;
#ifdef CONFIG_CFG80211_DEBUGFS
/* Debugfs entries */
@@ -89,13 +101,14 @@ bool wiphy_idx_valid(int wiphy_idx)
}
extern struct mutex cfg80211_mutex;
-extern struct list_head cfg80211_drv_list;
+extern struct list_head cfg80211_rdev_list;
+extern int cfg80211_rdev_list_generation;
#define assert_cfg80211_lock() WARN_ON(!mutex_is_locked(&cfg80211_mutex))
/*
* You can use this to mark a wiphy_idx as not having an associated wiphy.
- * It guarantees cfg80211_drv_by_wiphy_idx(wiphy_idx) will return NULL
+ * It guarantees cfg80211_rdev_by_wiphy_idx(wiphy_idx) will return NULL
*/
#define WIPHY_IDX_STALE -1
@@ -104,17 +117,40 @@ struct cfg80211_internal_bss {
struct rb_node rbn;
unsigned long ts;
struct kref ref;
- bool hold, ies_allocated;
+ atomic_t hold;
+ bool ies_allocated;
/* must be last because of priv member */
struct cfg80211_bss pub;
};
-struct cfg80211_registered_device *cfg80211_drv_by_wiphy_idx(int wiphy_idx);
+static inline struct cfg80211_internal_bss *bss_from_pub(struct cfg80211_bss *pub)
+{
+ return container_of(pub, struct cfg80211_internal_bss, pub);
+}
+
+static inline void cfg80211_ref_bss(struct cfg80211_internal_bss *bss)
+{
+ kref_get(&bss->ref);
+}
+
+static inline void cfg80211_hold_bss(struct cfg80211_internal_bss *bss)
+{
+ atomic_inc(&bss->hold);
+}
+
+static inline void cfg80211_unhold_bss(struct cfg80211_internal_bss *bss)
+{
+ int r = atomic_dec_return(&bss->hold);
+ WARN_ON(r < 0);
+}
+
+
+struct cfg80211_registered_device *cfg80211_rdev_by_wiphy_idx(int wiphy_idx);
int get_wiphy_idx(struct wiphy *wiphy);
struct cfg80211_registered_device *
-__cfg80211_drv_from_info(struct genl_info *info);
+__cfg80211_rdev_from_info(struct genl_info *info);
/*
* This function returns a pointer to the driver
@@ -122,12 +158,12 @@ __cfg80211_drv_from_info(struct genl_info *info);
* If successful, it returns non-NULL and also locks
* the driver's mutex!
*
- * This means that you need to call cfg80211_put_dev()
+ * This means that you need to call cfg80211_unlock_rdev()
* before being allowed to acquire &cfg80211_mutex!
*
* This is necessary because we need to lock the global
* mutex to get an item off the list safely, and then
- * we lock the drv mutex so it doesn't go away under us.
+ * we lock the rdev mutex so it doesn't go away under us.
*
* We don't want to keep cfg80211_mutex locked
* for all the time in order to allow requests on
@@ -139,19 +175,93 @@ __cfg80211_drv_from_info(struct genl_info *info);
extern struct cfg80211_registered_device *
cfg80211_get_dev_from_info(struct genl_info *info);
-/* requires cfg80211_drv_mutex to be held! */
+/* requires cfg80211_rdev_mutex to be held! */
struct wiphy *wiphy_idx_to_wiphy(int wiphy_idx);
/* identical to cfg80211_get_dev_from_info but only operate on ifindex */
extern struct cfg80211_registered_device *
-cfg80211_get_dev_from_ifindex(int ifindex);
+cfg80211_get_dev_from_ifindex(struct net *net, int ifindex);
+
+int cfg80211_switch_netns(struct cfg80211_registered_device *rdev,
+ struct net *net);
+
+static inline void cfg80211_lock_rdev(struct cfg80211_registered_device *rdev)
+{
+ mutex_lock(&rdev->mtx);
+}
+
+static inline void cfg80211_unlock_rdev(struct cfg80211_registered_device *rdev)
+{
+ BUG_ON(IS_ERR(rdev) || !rdev);
+ mutex_unlock(&rdev->mtx);
+}
+
+static inline void wdev_lock(struct wireless_dev *wdev)
+ __acquires(wdev)
+{
+ mutex_lock(&wdev->mtx);
+ __acquire(wdev->mtx);
+}
+
+static inline void wdev_unlock(struct wireless_dev *wdev)
+ __releases(wdev)
+{
+ __release(wdev->mtx);
+ mutex_unlock(&wdev->mtx);
+}
+
+#define ASSERT_RDEV_LOCK(rdev) WARN_ON(!mutex_is_locked(&(rdev)->mtx));
+#define ASSERT_WDEV_LOCK(wdev) WARN_ON(!mutex_is_locked(&(wdev)->mtx));
+
+enum cfg80211_event_type {
+ EVENT_CONNECT_RESULT,
+ EVENT_ROAMED,
+ EVENT_DISCONNECTED,
+ EVENT_IBSS_JOINED,
+};
+
+struct cfg80211_event {
+ struct list_head list;
+ enum cfg80211_event_type type;
+
+ union {
+ struct {
+ u8 bssid[ETH_ALEN];
+ const u8 *req_ie;
+ const u8 *resp_ie;
+ size_t req_ie_len;
+ size_t resp_ie_len;
+ u16 status;
+ } cr;
+ struct {
+ u8 bssid[ETH_ALEN];
+ const u8 *req_ie;
+ const u8 *resp_ie;
+ size_t req_ie_len;
+ size_t resp_ie_len;
+ } rm;
+ struct {
+ const u8 *ie;
+ size_t ie_len;
+ u16 reason;
+ } dc;
+ struct {
+ u8 bssid[ETH_ALEN];
+ } ij;
+ };
+};
+
+struct cfg80211_cached_keys {
+ struct key_params params[6];
+ u8 data[6][WLAN_MAX_KEY_LEN];
+ int def, defmgmt;
+};
-extern void cfg80211_put_dev(struct cfg80211_registered_device *drv);
/* free object */
-extern void cfg80211_dev_free(struct cfg80211_registered_device *drv);
+extern void cfg80211_dev_free(struct cfg80211_registered_device *rdev);
-extern int cfg80211_dev_rename(struct cfg80211_registered_device *drv,
+extern int cfg80211_dev_rename(struct cfg80211_registered_device *rdev,
char *newname);
void ieee80211_set_bitrate_flags(struct wiphy *wiphy);
@@ -163,15 +273,109 @@ void cfg80211_bss_age(struct cfg80211_registered_device *dev,
unsigned long age_secs);
/* IBSS */
+int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev,
+ struct net_device *dev,
+ struct cfg80211_ibss_params *params,
+ struct cfg80211_cached_keys *connkeys);
int cfg80211_join_ibss(struct cfg80211_registered_device *rdev,
struct net_device *dev,
- struct cfg80211_ibss_params *params);
+ struct cfg80211_ibss_params *params,
+ struct cfg80211_cached_keys *connkeys);
void cfg80211_clear_ibss(struct net_device *dev, bool nowext);
int cfg80211_leave_ibss(struct cfg80211_registered_device *rdev,
struct net_device *dev, bool nowext);
+void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid);
+int cfg80211_ibss_wext_join(struct cfg80211_registered_device *rdev,
+ struct wireless_dev *wdev);
+
+/* MLME */
+int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
+ struct net_device *dev,
+ struct ieee80211_channel *chan,
+ enum nl80211_auth_type auth_type,
+ const u8 *bssid,
+ const u8 *ssid, int ssid_len,
+ const u8 *ie, int ie_len,
+ const u8 *key, int key_len, int key_idx);
+int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
+ struct net_device *dev, struct ieee80211_channel *chan,
+ enum nl80211_auth_type auth_type, const u8 *bssid,
+ const u8 *ssid, int ssid_len,
+ const u8 *ie, int ie_len,
+ const u8 *key, int key_len, int key_idx);
+int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
+ struct net_device *dev,
+ struct ieee80211_channel *chan,
+ const u8 *bssid, const u8 *prev_bssid,
+ const u8 *ssid, int ssid_len,
+ const u8 *ie, int ie_len, bool use_mfp,
+ struct cfg80211_crypto_settings *crypt);
+int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
+ struct net_device *dev, struct ieee80211_channel *chan,
+ const u8 *bssid, const u8 *prev_bssid,
+ const u8 *ssid, int ssid_len,
+ const u8 *ie, int ie_len, bool use_mfp,
+ struct cfg80211_crypto_settings *crypt);
+int __cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev,
+ struct net_device *dev, const u8 *bssid,
+ const u8 *ie, int ie_len, u16 reason);
+int cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev,
+ struct net_device *dev, const u8 *bssid,
+ const u8 *ie, int ie_len, u16 reason);
+int cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev,
+ struct net_device *dev, const u8 *bssid,
+ const u8 *ie, int ie_len, u16 reason);
+void cfg80211_mlme_down(struct cfg80211_registered_device *rdev,
+ struct net_device *dev);
+void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
+ const u8 *req_ie, size_t req_ie_len,
+ const u8 *resp_ie, size_t resp_ie_len,
+ u16 status, bool wextev,
+ struct cfg80211_bss *bss);
+
+/* SME */
+int __cfg80211_connect(struct cfg80211_registered_device *rdev,
+ struct net_device *dev,
+ struct cfg80211_connect_params *connect,
+ struct cfg80211_cached_keys *connkeys,
+ const u8 *prev_bssid);
+int cfg80211_connect(struct cfg80211_registered_device *rdev,
+ struct net_device *dev,
+ struct cfg80211_connect_params *connect,
+ struct cfg80211_cached_keys *connkeys);
+int __cfg80211_disconnect(struct cfg80211_registered_device *rdev,
+ struct net_device *dev, u16 reason,
+ bool wextev);
+int cfg80211_disconnect(struct cfg80211_registered_device *rdev,
+ struct net_device *dev, u16 reason,
+ bool wextev);
+void __cfg80211_roamed(struct wireless_dev *wdev, const u8 *bssid,
+ const u8 *req_ie, size_t req_ie_len,
+ const u8 *resp_ie, size_t resp_ie_len);
+int cfg80211_mgd_wext_connect(struct cfg80211_registered_device *rdev,
+ struct wireless_dev *wdev);
+
+void cfg80211_conn_work(struct work_struct *work);
+bool cfg80211_sme_failed_reassoc(struct wireless_dev *wdev);
/* internal helpers */
-int cfg80211_validate_key_settings(struct key_params *params, int key_idx,
+int cfg80211_validate_key_settings(struct cfg80211_registered_device *rdev,
+ struct key_params *params, int key_idx,
const u8 *mac_addr);
+void __cfg80211_disconnected(struct net_device *dev, const u8 *ie,
+ size_t ie_len, u16 reason, bool from_ap);
+void cfg80211_sme_scan_done(struct net_device *dev);
+void cfg80211_sme_rx_auth(struct net_device *dev, const u8 *buf, size_t len);
+void cfg80211_sme_disassoc(struct net_device *dev, int idx);
+void __cfg80211_scan_done(struct work_struct *wk);
+void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev);
+void cfg80211_upload_connect_keys(struct wireless_dev *wdev);
+
+struct ieee80211_channel *
+rdev_fixed_channel(struct cfg80211_registered_device *rdev,
+ struct wireless_dev *for_wdev);
+int rdev_set_freq(struct cfg80211_registered_device *rdev,
+ struct wireless_dev *for_wdev,
+ int freq, enum nl80211_channel_type channel_type);
#endif /* __NET_WIRELESS_CORE_H */
diff --git a/net/wireless/debugfs.c b/net/wireless/debugfs.c
index 679ddfcec1e..13d93d84f90 100644
--- a/net/wireless/debugfs.c
+++ b/net/wireless/debugfs.c
@@ -104,15 +104,15 @@ static const struct file_operations ht40allow_map_ops = {
};
#define DEBUGFS_ADD(name) \
- drv->debugfs.name = debugfs_create_file(#name, S_IRUGO, phyd, \
- &drv->wiphy, &name## _ops);
+ rdev->debugfs.name = debugfs_create_file(#name, S_IRUGO, phyd, \
+ &rdev->wiphy, &name## _ops);
#define DEBUGFS_DEL(name) \
- debugfs_remove(drv->debugfs.name); \
- drv->debugfs.name = NULL;
+ debugfs_remove(rdev->debugfs.name); \
+ rdev->debugfs.name = NULL;
-void cfg80211_debugfs_drv_add(struct cfg80211_registered_device *drv)
+void cfg80211_debugfs_rdev_add(struct cfg80211_registered_device *rdev)
{
- struct dentry *phyd = drv->wiphy.debugfsdir;
+ struct dentry *phyd = rdev->wiphy.debugfsdir;
DEBUGFS_ADD(rts_threshold);
DEBUGFS_ADD(fragmentation_threshold);
@@ -121,7 +121,7 @@ void cfg80211_debugfs_drv_add(struct cfg80211_registered_device *drv)
DEBUGFS_ADD(ht40allow_map);
}
-void cfg80211_debugfs_drv_del(struct cfg80211_registered_device *drv)
+void cfg80211_debugfs_rdev_del(struct cfg80211_registered_device *rdev)
{
DEBUGFS_DEL(rts_threshold);
DEBUGFS_DEL(fragmentation_threshold);
diff --git a/net/wireless/debugfs.h b/net/wireless/debugfs.h
index c226983ae66..6419b6d6ce3 100644
--- a/net/wireless/debugfs.h
+++ b/net/wireless/debugfs.h
@@ -2,13 +2,13 @@
#define __CFG80211_DEBUGFS_H
#ifdef CONFIG_CFG80211_DEBUGFS
-void cfg80211_debugfs_drv_add(struct cfg80211_registered_device *drv);
-void cfg80211_debugfs_drv_del(struct cfg80211_registered_device *drv);
+void cfg80211_debugfs_rdev_add(struct cfg80211_registered_device *rdev);
+void cfg80211_debugfs_rdev_del(struct cfg80211_registered_device *rdev);
#else
static inline
-void cfg80211_debugfs_drv_add(struct cfg80211_registered_device *drv) {}
+void cfg80211_debugfs_rdev_add(struct cfg80211_registered_device *rdev) {}
static inline
-void cfg80211_debugfs_drv_del(struct cfg80211_registered_device *drv) {}
+void cfg80211_debugfs_rdev_del(struct cfg80211_registered_device *rdev) {}
#endif
#endif /* __CFG80211_DEBUGFS_H */
diff --git a/net/wireless/ibss.c b/net/wireless/ibss.c
index a4a1c3498ff..42840a01be7 100644
--- a/net/wireless/ibss.c
+++ b/net/wireless/ibss.c
@@ -7,10 +7,11 @@
#include <linux/etherdevice.h>
#include <linux/if_arp.h>
#include <net/cfg80211.h>
+#include "wext-compat.h"
#include "nl80211.h"
-void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid, gfp_t gfp)
+void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid)
{
struct wireless_dev *wdev = dev->ieee80211_ptr;
struct cfg80211_bss *bss;
@@ -24,9 +25,6 @@ void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid, gfp_t gfp)
if (WARN_ON(!wdev->ssid_len))
return;
- if (memcmp(bssid, wdev->bssid, ETH_ALEN) == 0)
- return;
-
bss = cfg80211_get_bss(wdev->wiphy, NULL, bssid,
wdev->ssid, wdev->ssid_len,
WLAN_CAPABILITY_IBSS, WLAN_CAPABILITY_IBSS);
@@ -36,39 +34,74 @@ void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid, gfp_t gfp)
if (wdev->current_bss) {
cfg80211_unhold_bss(wdev->current_bss);
- cfg80211_put_bss(wdev->current_bss);
+ cfg80211_put_bss(&wdev->current_bss->pub);
}
- cfg80211_hold_bss(bss);
- wdev->current_bss = bss;
- memcpy(wdev->bssid, bssid, ETH_ALEN);
+ cfg80211_hold_bss(bss_from_pub(bss));
+ wdev->current_bss = bss_from_pub(bss);
- nl80211_send_ibss_bssid(wiphy_to_dev(wdev->wiphy), dev, bssid, gfp);
+ cfg80211_upload_connect_keys(wdev);
+
+ nl80211_send_ibss_bssid(wiphy_to_dev(wdev->wiphy), dev, bssid,
+ GFP_KERNEL);
#ifdef CONFIG_WIRELESS_EXT
memset(&wrqu, 0, sizeof(wrqu));
memcpy(wrqu.ap_addr.sa_data, bssid, ETH_ALEN);
wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL);
#endif
}
+
+void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid, gfp_t gfp)
+{
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+ struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
+ struct cfg80211_event *ev;
+ unsigned long flags;
+
+ ev = kzalloc(sizeof(*ev), gfp);
+ if (!ev)
+ return;
+
+ ev->type = EVENT_IBSS_JOINED;
+ memcpy(ev->cr.bssid, bssid, ETH_ALEN);
+
+ spin_lock_irqsave(&wdev->event_lock, flags);
+ list_add_tail(&ev->list, &wdev->event_list);
+ spin_unlock_irqrestore(&wdev->event_lock, flags);
+ schedule_work(&rdev->event_work);
+}
EXPORT_SYMBOL(cfg80211_ibss_joined);
-int cfg80211_join_ibss(struct cfg80211_registered_device *rdev,
- struct net_device *dev,
- struct cfg80211_ibss_params *params)
+int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev,
+ struct net_device *dev,
+ struct cfg80211_ibss_params *params,
+ struct cfg80211_cached_keys *connkeys)
{
struct wireless_dev *wdev = dev->ieee80211_ptr;
+ struct ieee80211_channel *chan;
int err;
+ ASSERT_WDEV_LOCK(wdev);
+
+ chan = rdev_fixed_channel(rdev, wdev);
+ if (chan && chan != params->channel)
+ return -EBUSY;
+
if (wdev->ssid_len)
return -EALREADY;
+ if (WARN_ON(wdev->connect_keys))
+ kfree(wdev->connect_keys);
+ wdev->connect_keys = connkeys;
+
#ifdef CONFIG_WIRELESS_EXT
wdev->wext.ibss.channel = params->channel;
#endif
err = rdev->ops->join_ibss(&rdev->wiphy, dev, params);
-
- if (err)
+ if (err) {
+ wdev->connect_keys = NULL;
return err;
+ }
memcpy(wdev->ssid, params->ssid, params->ssid_len);
wdev->ssid_len = params->ssid_len;
@@ -76,45 +109,107 @@ int cfg80211_join_ibss(struct cfg80211_registered_device *rdev,
return 0;
}
-void cfg80211_clear_ibss(struct net_device *dev, bool nowext)
+int cfg80211_join_ibss(struct cfg80211_registered_device *rdev,
+ struct net_device *dev,
+ struct cfg80211_ibss_params *params,
+ struct cfg80211_cached_keys *connkeys)
+{
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+ int err;
+
+ mutex_lock(&rdev->devlist_mtx);
+ wdev_lock(wdev);
+ err = __cfg80211_join_ibss(rdev, dev, params, connkeys);
+ wdev_unlock(wdev);
+ mutex_unlock(&rdev->devlist_mtx);
+
+ return err;
+}
+
+static void __cfg80211_clear_ibss(struct net_device *dev, bool nowext)
{
struct wireless_dev *wdev = dev->ieee80211_ptr;
+ struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
+ int i;
+
+ ASSERT_WDEV_LOCK(wdev);
+
+ kfree(wdev->connect_keys);
+ wdev->connect_keys = NULL;
+
+ /*
+ * Delete all the keys ... pairwise keys can't really
+ * exist any more anyway, but default keys might.
+ */
+ if (rdev->ops->del_key)
+ for (i = 0; i < 6; i++)
+ rdev->ops->del_key(wdev->wiphy, dev, i, NULL);
if (wdev->current_bss) {
cfg80211_unhold_bss(wdev->current_bss);
- cfg80211_put_bss(wdev->current_bss);
+ cfg80211_put_bss(&wdev->current_bss->pub);
}
wdev->current_bss = NULL;
wdev->ssid_len = 0;
- memset(wdev->bssid, 0, ETH_ALEN);
#ifdef CONFIG_WIRELESS_EXT
if (!nowext)
wdev->wext.ibss.ssid_len = 0;
#endif
}
-int cfg80211_leave_ibss(struct cfg80211_registered_device *rdev,
- struct net_device *dev, bool nowext)
+void cfg80211_clear_ibss(struct net_device *dev, bool nowext)
+{
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+
+ wdev_lock(wdev);
+ __cfg80211_clear_ibss(dev, nowext);
+ wdev_unlock(wdev);
+}
+
+static int __cfg80211_leave_ibss(struct cfg80211_registered_device *rdev,
+ struct net_device *dev, bool nowext)
{
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
int err;
+ ASSERT_WDEV_LOCK(wdev);
+
+ if (!wdev->ssid_len)
+ return -ENOLINK;
+
err = rdev->ops->leave_ibss(&rdev->wiphy, dev);
if (err)
return err;
- cfg80211_clear_ibss(dev, nowext);
+ __cfg80211_clear_ibss(dev, nowext);
return 0;
}
+int cfg80211_leave_ibss(struct cfg80211_registered_device *rdev,
+ struct net_device *dev, bool nowext)
+{
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+ int err;
+
+ wdev_lock(wdev);
+ err = __cfg80211_leave_ibss(rdev, dev, nowext);
+ wdev_unlock(wdev);
+
+ return err;
+}
+
#ifdef CONFIG_WIRELESS_EXT
-static int cfg80211_ibss_wext_join(struct cfg80211_registered_device *rdev,
- struct wireless_dev *wdev)
+int cfg80211_ibss_wext_join(struct cfg80211_registered_device *rdev,
+ struct wireless_dev *wdev)
{
+ struct cfg80211_cached_keys *ck = NULL;
enum ieee80211_band band;
- int i;
+ int i, err;
+
+ ASSERT_WDEV_LOCK(wdev);
if (!wdev->wext.ibss.beacon_interval)
wdev->wext.ibss.beacon_interval = 100;
@@ -154,43 +249,66 @@ static int cfg80211_ibss_wext_join(struct cfg80211_registered_device *rdev,
if (!netif_running(wdev->netdev))
return 0;
- return cfg80211_join_ibss(wiphy_to_dev(wdev->wiphy),
- wdev->netdev, &wdev->wext.ibss);
+ if (wdev->wext.keys)
+ wdev->wext.keys->def = wdev->wext.default_key;
+
+ wdev->wext.ibss.privacy = wdev->wext.default_key != -1;
+
+ if (wdev->wext.keys) {
+ ck = kmemdup(wdev->wext.keys, sizeof(*ck), GFP_KERNEL);
+ if (!ck)
+ return -ENOMEM;
+ for (i = 0; i < 6; i++)
+ ck->params[i].key = ck->data[i];
+ }
+ err = __cfg80211_join_ibss(rdev, wdev->netdev,
+ &wdev->wext.ibss, ck);
+ if (err)
+ kfree(ck);
+
+ return err;
}
int cfg80211_ibss_wext_siwfreq(struct net_device *dev,
struct iw_request_info *info,
- struct iw_freq *freq, char *extra)
+ struct iw_freq *wextfreq, char *extra)
{
struct wireless_dev *wdev = dev->ieee80211_ptr;
- struct ieee80211_channel *chan;
- int err;
+ struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
+ struct ieee80211_channel *chan = NULL;
+ int err, freq;
/* call only for ibss! */
if (WARN_ON(wdev->iftype != NL80211_IFTYPE_ADHOC))
return -EINVAL;
- if (!wiphy_to_dev(wdev->wiphy)->ops->join_ibss)
+ if (!rdev->ops->join_ibss)
return -EOPNOTSUPP;
- chan = cfg80211_wext_freq(wdev->wiphy, freq);
- if (chan && IS_ERR(chan))
- return PTR_ERR(chan);
+ freq = cfg80211_wext_freq(wdev->wiphy, wextfreq);
+ if (freq < 0)
+ return freq;
- if (chan &&
- (chan->flags & IEEE80211_CHAN_NO_IBSS ||
- chan->flags & IEEE80211_CHAN_DISABLED))
- return -EINVAL;
+ if (freq) {
+ chan = ieee80211_get_channel(wdev->wiphy, freq);
+ if (!chan)
+ return -EINVAL;
+ if (chan->flags & IEEE80211_CHAN_NO_IBSS ||
+ chan->flags & IEEE80211_CHAN_DISABLED)
+ return -EINVAL;
+ }
if (wdev->wext.ibss.channel == chan)
return 0;
- if (wdev->ssid_len) {
- err = cfg80211_leave_ibss(wiphy_to_dev(wdev->wiphy),
- dev, true);
- if (err)
- return err;
- }
+ wdev_lock(wdev);
+ err = 0;
+ if (wdev->ssid_len)
+ err = __cfg80211_leave_ibss(rdev, dev, true);
+ wdev_unlock(wdev);
+
+ if (err)
+ return err;
if (chan) {
wdev->wext.ibss.channel = chan;
@@ -200,10 +318,14 @@ int cfg80211_ibss_wext_siwfreq(struct net_device *dev,
wdev->wext.ibss.channel_fixed = false;
}
- return cfg80211_ibss_wext_join(wiphy_to_dev(wdev->wiphy), wdev);
+ mutex_lock(&rdev->devlist_mtx);
+ wdev_lock(wdev);
+ err = cfg80211_ibss_wext_join(rdev, wdev);
+ wdev_unlock(wdev);
+ mutex_unlock(&rdev->devlist_mtx);
+
+ return err;
}
-/* temporary symbol - mark GPL - in the future the handler won't be */
-EXPORT_SYMBOL_GPL(cfg80211_ibss_wext_siwfreq);
int cfg80211_ibss_wext_giwfreq(struct net_device *dev,
struct iw_request_info *info,
@@ -216,10 +338,12 @@ int cfg80211_ibss_wext_giwfreq(struct net_device *dev,
if (WARN_ON(wdev->iftype != NL80211_IFTYPE_ADHOC))
return -EINVAL;
+ wdev_lock(wdev);
if (wdev->current_bss)
- chan = wdev->current_bss->channel;
+ chan = wdev->current_bss->pub.channel;
else if (wdev->wext.ibss.channel)
chan = wdev->wext.ibss.channel;
+ wdev_unlock(wdev);
if (chan) {
freq->m = chan->center_freq;
@@ -230,14 +354,13 @@ int cfg80211_ibss_wext_giwfreq(struct net_device *dev,
/* no channel if not joining */
return -EINVAL;
}
-/* temporary symbol - mark GPL - in the future the handler won't be */
-EXPORT_SYMBOL_GPL(cfg80211_ibss_wext_giwfreq);
int cfg80211_ibss_wext_siwessid(struct net_device *dev,
struct iw_request_info *info,
struct iw_point *data, char *ssid)
{
struct wireless_dev *wdev = dev->ieee80211_ptr;
+ struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
size_t len = data->length;
int err;
@@ -245,15 +368,17 @@ int cfg80211_ibss_wext_siwessid(struct net_device *dev,
if (WARN_ON(wdev->iftype != NL80211_IFTYPE_ADHOC))
return -EINVAL;
- if (!wiphy_to_dev(wdev->wiphy)->ops->join_ibss)
+ if (!rdev->ops->join_ibss)
return -EOPNOTSUPP;
- if (wdev->ssid_len) {
- err = cfg80211_leave_ibss(wiphy_to_dev(wdev->wiphy),
- dev, true);
- if (err)
- return err;
- }
+ wdev_lock(wdev);
+ err = 0;
+ if (wdev->ssid_len)
+ err = __cfg80211_leave_ibss(rdev, dev, true);
+ wdev_unlock(wdev);
+
+ if (err)
+ return err;
/* iwconfig uses nul termination in SSID.. */
if (len > 0 && ssid[len - 1] == '\0')
@@ -263,10 +388,14 @@ int cfg80211_ibss_wext_siwessid(struct net_device *dev,
memcpy(wdev->wext.ibss.ssid, ssid, len);
wdev->wext.ibss.ssid_len = len;
- return cfg80211_ibss_wext_join(wiphy_to_dev(wdev->wiphy), wdev);
+ mutex_lock(&rdev->devlist_mtx);
+ wdev_lock(wdev);
+ err = cfg80211_ibss_wext_join(rdev, wdev);
+ wdev_unlock(wdev);
+ mutex_unlock(&rdev->devlist_mtx);
+
+ return err;
}
-/* temporary symbol - mark GPL - in the future the handler won't be */
-EXPORT_SYMBOL_GPL(cfg80211_ibss_wext_siwessid);
int cfg80211_ibss_wext_giwessid(struct net_device *dev,
struct iw_request_info *info,
@@ -280,6 +409,7 @@ int cfg80211_ibss_wext_giwessid(struct net_device *dev,
data->flags = 0;
+ wdev_lock(wdev);
if (wdev->ssid_len) {
data->flags = 1;
data->length = wdev->ssid_len;
@@ -289,17 +419,17 @@ int cfg80211_ibss_wext_giwessid(struct net_device *dev,
data->length = wdev->wext.ibss.ssid_len;
memcpy(ssid, wdev->wext.ibss.ssid, data->length);
}
+ wdev_unlock(wdev);
return 0;
}
-/* temporary symbol - mark GPL - in the future the handler won't be */
-EXPORT_SYMBOL_GPL(cfg80211_ibss_wext_giwessid);
int cfg80211_ibss_wext_siwap(struct net_device *dev,
struct iw_request_info *info,
struct sockaddr *ap_addr, char *extra)
{
struct wireless_dev *wdev = dev->ieee80211_ptr;
+ struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
u8 *bssid = ap_addr->sa_data;
int err;
@@ -307,7 +437,7 @@ int cfg80211_ibss_wext_siwap(struct net_device *dev,
if (WARN_ON(wdev->iftype != NL80211_IFTYPE_ADHOC))
return -EINVAL;
- if (!wiphy_to_dev(wdev->wiphy)->ops->join_ibss)
+ if (!rdev->ops->join_ibss)
return -EOPNOTSUPP;
if (ap_addr->sa_family != ARPHRD_ETHER)
@@ -326,12 +456,14 @@ int cfg80211_ibss_wext_siwap(struct net_device *dev,
compare_ether_addr(bssid, wdev->wext.ibss.bssid) == 0)
return 0;
- if (wdev->ssid_len) {
- err = cfg80211_leave_ibss(wiphy_to_dev(wdev->wiphy),
- dev, true);
- if (err)
- return err;
- }
+ wdev_lock(wdev);
+ err = 0;
+ if (wdev->ssid_len)
+ err = __cfg80211_leave_ibss(rdev, dev, true);
+ wdev_unlock(wdev);
+
+ if (err)
+ return err;
if (bssid) {
memcpy(wdev->wext.bssid, bssid, ETH_ALEN);
@@ -339,10 +471,14 @@ int cfg80211_ibss_wext_siwap(struct net_device *dev,
} else
wdev->wext.ibss.bssid = NULL;
- return cfg80211_ibss_wext_join(wiphy_to_dev(wdev->wiphy), wdev);
+ mutex_lock(&rdev->devlist_mtx);
+ wdev_lock(wdev);
+ err = cfg80211_ibss_wext_join(rdev, wdev);
+ wdev_unlock(wdev);
+ mutex_unlock(&rdev->devlist_mtx);
+
+ return err;
}
-/* temporary symbol - mark GPL - in the future the handler won't be */
-EXPORT_SYMBOL_GPL(cfg80211_ibss_wext_siwap);
int cfg80211_ibss_wext_giwap(struct net_device *dev,
struct iw_request_info *info,
@@ -356,14 +492,16 @@ int cfg80211_ibss_wext_giwap(struct net_device *dev,
ap_addr->sa_family = ARPHRD_ETHER;
- if (wdev->wext.ibss.bssid) {
+ wdev_lock(wdev);
+ if (wdev->current_bss)
+ memcpy(ap_addr->sa_data, wdev->current_bss->pub.bssid, ETH_ALEN);
+ else if (wdev->wext.ibss.bssid)
memcpy(ap_addr->sa_data, wdev->wext.ibss.bssid, ETH_ALEN);
- return 0;
- }
+ else
+ memset(ap_addr->sa_data, 0, ETH_ALEN);
+
+ wdev_unlock(wdev);
- memcpy(ap_addr->sa_data, wdev->bssid, ETH_ALEN);
return 0;
}
-/* temporary symbol - mark GPL - in the future the handler won't be */
-EXPORT_SYMBOL_GPL(cfg80211_ibss_wext_giwap);
#endif
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c
index 42184361a10..da64071ceb8 100644
--- a/net/wireless/mlme.c
+++ b/net/wireless/mlme.c
@@ -8,75 +8,643 @@
#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/nl80211.h>
+#include <linux/wireless.h>
#include <net/cfg80211.h>
+#include <net/iw_handler.h>
#include "core.h"
#include "nl80211.h"
void cfg80211_send_rx_auth(struct net_device *dev, const u8 *buf, size_t len)
{
- struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+ struct wiphy *wiphy = wdev->wiphy;
struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
- nl80211_send_rx_auth(rdev, dev, buf, len);
+ struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf;
+ u8 *bssid = mgmt->bssid;
+ int i;
+ u16 status = le16_to_cpu(mgmt->u.auth.status_code);
+ bool done = false;
+
+ wdev_lock(wdev);
+
+ for (i = 0; i < MAX_AUTH_BSSES; i++) {
+ if (wdev->authtry_bsses[i] &&
+ memcmp(wdev->authtry_bsses[i]->pub.bssid, bssid,
+ ETH_ALEN) == 0) {
+ if (status == WLAN_STATUS_SUCCESS) {
+ wdev->auth_bsses[i] = wdev->authtry_bsses[i];
+ } else {
+ cfg80211_unhold_bss(wdev->authtry_bsses[i]);
+ cfg80211_put_bss(&wdev->authtry_bsses[i]->pub);
+ }
+ wdev->authtry_bsses[i] = NULL;
+ done = true;
+ break;
+ }
+ }
+
+ WARN_ON(!done);
+
+ nl80211_send_rx_auth(rdev, dev, buf, len, GFP_KERNEL);
+ cfg80211_sme_rx_auth(dev, buf, len);
+
+ wdev_unlock(wdev);
}
EXPORT_SYMBOL(cfg80211_send_rx_auth);
void cfg80211_send_rx_assoc(struct net_device *dev, const u8 *buf, size_t len)
{
- struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
+ u16 status_code;
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+ struct wiphy *wiphy = wdev->wiphy;
struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
- nl80211_send_rx_assoc(rdev, dev, buf, len);
+ struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf;
+ u8 *ie = mgmt->u.assoc_resp.variable;
+ int i, ieoffs = offsetof(struct ieee80211_mgmt, u.assoc_resp.variable);
+ struct cfg80211_internal_bss *bss = NULL;
+
+ wdev_lock(wdev);
+
+ status_code = le16_to_cpu(mgmt->u.assoc_resp.status_code);
+
+ /*
+ * This is a bit of a hack, we don't notify userspace of
+ * a (re-)association reply if we tried to send a reassoc
+ * and got a reject -- we only try again with an assoc
+ * frame instead of reassoc.
+ */
+ if (status_code != WLAN_STATUS_SUCCESS && wdev->conn &&
+ cfg80211_sme_failed_reassoc(wdev))
+ goto out;
+
+ nl80211_send_rx_assoc(rdev, dev, buf, len, GFP_KERNEL);
+
+ if (status_code == WLAN_STATUS_SUCCESS) {
+ for (i = 0; i < MAX_AUTH_BSSES; i++) {
+ if (!wdev->auth_bsses[i])
+ continue;
+ if (memcmp(wdev->auth_bsses[i]->pub.bssid, mgmt->bssid,
+ ETH_ALEN) == 0) {
+ bss = wdev->auth_bsses[i];
+ wdev->auth_bsses[i] = NULL;
+ /* additional reference to drop hold */
+ cfg80211_ref_bss(bss);
+ break;
+ }
+ }
+
+ WARN_ON(!bss);
+ }
+
+ /* this consumes one bss reference (unless bss is NULL) */
+ __cfg80211_connect_result(dev, mgmt->bssid, NULL, 0, ie, len - ieoffs,
+ status_code,
+ status_code == WLAN_STATUS_SUCCESS,
+ bss ? &bss->pub : NULL);
+ /* drop hold now, and also reference acquired above */
+ if (bss) {
+ cfg80211_unhold_bss(bss);
+ cfg80211_put_bss(&bss->pub);
+ }
+
+ out:
+ wdev_unlock(wdev);
}
EXPORT_SYMBOL(cfg80211_send_rx_assoc);
-void cfg80211_send_deauth(struct net_device *dev, const u8 *buf, size_t len)
+static void __cfg80211_send_deauth(struct net_device *dev,
+ const u8 *buf, size_t len)
{
- struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+ struct wiphy *wiphy = wdev->wiphy;
struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
- nl80211_send_deauth(rdev, dev, buf, len);
+ struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf;
+ const u8 *bssid = mgmt->bssid;
+ int i;
+ bool done = false;
+
+ ASSERT_WDEV_LOCK(wdev);
+
+ nl80211_send_deauth(rdev, dev, buf, len, GFP_KERNEL);
+
+ if (wdev->current_bss &&
+ memcmp(wdev->current_bss->pub.bssid, bssid, ETH_ALEN) == 0) {
+ done = true;
+ cfg80211_unhold_bss(wdev->current_bss);
+ cfg80211_put_bss(&wdev->current_bss->pub);
+ wdev->current_bss = NULL;
+ } else for (i = 0; i < MAX_AUTH_BSSES; i++) {
+ if (wdev->auth_bsses[i] &&
+ memcmp(wdev->auth_bsses[i]->pub.bssid, bssid, ETH_ALEN) == 0) {
+ cfg80211_unhold_bss(wdev->auth_bsses[i]);
+ cfg80211_put_bss(&wdev->auth_bsses[i]->pub);
+ wdev->auth_bsses[i] = NULL;
+ done = true;
+ break;
+ }
+ if (wdev->authtry_bsses[i] &&
+ memcmp(wdev->authtry_bsses[i]->pub.bssid, bssid, ETH_ALEN) == 0) {
+ cfg80211_unhold_bss(wdev->authtry_bsses[i]);
+ cfg80211_put_bss(&wdev->authtry_bsses[i]->pub);
+ wdev->authtry_bsses[i] = NULL;
+ done = true;
+ break;
+ }
+ }
+
+ WARN_ON(!done);
+
+ if (wdev->sme_state == CFG80211_SME_CONNECTED) {
+ u16 reason_code;
+ bool from_ap;
+
+ reason_code = le16_to_cpu(mgmt->u.deauth.reason_code);
+
+ from_ap = memcmp(mgmt->sa, dev->dev_addr, ETH_ALEN) != 0;
+ __cfg80211_disconnected(dev, NULL, 0, reason_code, from_ap);
+ } else if (wdev->sme_state == CFG80211_SME_CONNECTING) {
+ __cfg80211_connect_result(dev, mgmt->bssid, NULL, 0, NULL, 0,
+ WLAN_STATUS_UNSPECIFIED_FAILURE,
+ false, NULL);
+ }
+}
+
+
+void cfg80211_send_deauth(struct net_device *dev, const u8 *buf, size_t len,
+ void *cookie)
+{
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+
+ BUG_ON(cookie && wdev != cookie);
+
+ if (cookie) {
+ /* called within callback */
+ __cfg80211_send_deauth(dev, buf, len);
+ } else {
+ wdev_lock(wdev);
+ __cfg80211_send_deauth(dev, buf, len);
+ wdev_unlock(wdev);
+ }
}
EXPORT_SYMBOL(cfg80211_send_deauth);
-void cfg80211_send_disassoc(struct net_device *dev, const u8 *buf, size_t len)
+static void __cfg80211_send_disassoc(struct net_device *dev,
+ const u8 *buf, size_t len)
{
- struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+ struct wiphy *wiphy = wdev->wiphy;
struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
- nl80211_send_disassoc(rdev, dev, buf, len);
+ struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf;
+ const u8 *bssid = mgmt->bssid;
+ int i;
+ u16 reason_code;
+ bool from_ap;
+ bool done = false;
+
+ ASSERT_WDEV_LOCK(wdev);
+
+ nl80211_send_disassoc(rdev, dev, buf, len, GFP_KERNEL);
+
+ if (wdev->sme_state != CFG80211_SME_CONNECTED)
+ return;
+
+ if (wdev->current_bss &&
+ memcmp(wdev->current_bss->pub.bssid, bssid, ETH_ALEN) == 0) {
+ for (i = 0; i < MAX_AUTH_BSSES; i++) {
+ if (wdev->authtry_bsses[i] || wdev->auth_bsses[i])
+ continue;
+ wdev->auth_bsses[i] = wdev->current_bss;
+ wdev->current_bss = NULL;
+ done = true;
+ cfg80211_sme_disassoc(dev, i);
+ break;
+ }
+ WARN_ON(!done);
+ } else
+ WARN_ON(1);
+
+
+ reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code);
+
+ from_ap = memcmp(mgmt->sa, dev->dev_addr, ETH_ALEN) != 0;
+ __cfg80211_disconnected(dev, NULL, 0, reason_code, from_ap);
}
-EXPORT_SYMBOL(cfg80211_send_disassoc);
-static void cfg80211_wext_disconnected(struct net_device *dev)
+void cfg80211_send_disassoc(struct net_device *dev, const u8 *buf, size_t len,
+ void *cookie)
{
-#ifdef CONFIG_WIRELESS_EXT
- union iwreq_data wrqu;
- memset(&wrqu, 0, sizeof(wrqu));
- wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL);
-#endif
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+
+ BUG_ON(cookie && wdev != cookie);
+
+ if (cookie) {
+ /* called within callback */
+ __cfg80211_send_disassoc(dev, buf, len);
+ } else {
+ wdev_lock(wdev);
+ __cfg80211_send_disassoc(dev, buf, len);
+ wdev_unlock(wdev);
+ }
}
+EXPORT_SYMBOL(cfg80211_send_disassoc);
void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr)
{
- struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+ struct wiphy *wiphy = wdev->wiphy;
struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
- nl80211_send_auth_timeout(rdev, dev, addr);
- cfg80211_wext_disconnected(dev);
+ int i;
+ bool done = false;
+
+ wdev_lock(wdev);
+
+ nl80211_send_auth_timeout(rdev, dev, addr, GFP_KERNEL);
+ if (wdev->sme_state == CFG80211_SME_CONNECTING)
+ __cfg80211_connect_result(dev, addr, NULL, 0, NULL, 0,
+ WLAN_STATUS_UNSPECIFIED_FAILURE,
+ false, NULL);
+
+ for (i = 0; addr && i < MAX_AUTH_BSSES; i++) {
+ if (wdev->authtry_bsses[i] &&
+ memcmp(wdev->authtry_bsses[i]->pub.bssid,
+ addr, ETH_ALEN) == 0) {
+ cfg80211_unhold_bss(wdev->authtry_bsses[i]);
+ cfg80211_put_bss(&wdev->authtry_bsses[i]->pub);
+ wdev->authtry_bsses[i] = NULL;
+ done = true;
+ break;
+ }
+ }
+
+ WARN_ON(!done);
+
+ wdev_unlock(wdev);
}
EXPORT_SYMBOL(cfg80211_send_auth_timeout);
void cfg80211_send_assoc_timeout(struct net_device *dev, const u8 *addr)
{
- struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+ struct wiphy *wiphy = wdev->wiphy;
struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
- nl80211_send_assoc_timeout(rdev, dev, addr);
- cfg80211_wext_disconnected(dev);
+ int i;
+ bool done = false;
+
+ wdev_lock(wdev);
+
+ nl80211_send_assoc_timeout(rdev, dev, addr, GFP_KERNEL);
+ if (wdev->sme_state == CFG80211_SME_CONNECTING)
+ __cfg80211_connect_result(dev, addr, NULL, 0, NULL, 0,
+ WLAN_STATUS_UNSPECIFIED_FAILURE,
+ false, NULL);
+
+ for (i = 0; addr && i < MAX_AUTH_BSSES; i++) {
+ if (wdev->auth_bsses[i] &&
+ memcmp(wdev->auth_bsses[i]->pub.bssid,
+ addr, ETH_ALEN) == 0) {
+ cfg80211_unhold_bss(wdev->auth_bsses[i]);
+ cfg80211_put_bss(&wdev->auth_bsses[i]->pub);
+ wdev->auth_bsses[i] = NULL;
+ done = true;
+ break;
+ }
+ }
+
+ WARN_ON(!done);
+
+ wdev_unlock(wdev);
}
EXPORT_SYMBOL(cfg80211_send_assoc_timeout);
void cfg80211_michael_mic_failure(struct net_device *dev, const u8 *addr,
enum nl80211_key_type key_type, int key_id,
- const u8 *tsc)
+ const u8 *tsc, gfp_t gfp)
{
struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
- nl80211_michael_mic_failure(rdev, dev, addr, key_type, key_id, tsc);
+#ifdef CONFIG_WIRELESS_EXT
+ union iwreq_data wrqu;
+ char *buf = kmalloc(128, gfp);
+
+ if (buf) {
+ sprintf(buf, "MLME-MICHAELMICFAILURE.indication("
+ "keyid=%d %scast addr=%pM)", key_id,
+ key_type == NL80211_KEYTYPE_GROUP ? "broad" : "uni",
+ addr);
+ memset(&wrqu, 0, sizeof(wrqu));
+ wrqu.data.length = strlen(buf);
+ wireless_send_event(dev, IWEVCUSTOM, &wrqu, buf);
+ kfree(buf);
+ }
+#endif
+
+ nl80211_michael_mic_failure(rdev, dev, addr, key_type, key_id, tsc, gfp);
}
EXPORT_SYMBOL(cfg80211_michael_mic_failure);
+
+/* some MLME handling for userspace SME */
+int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
+ struct net_device *dev,
+ struct ieee80211_channel *chan,
+ enum nl80211_auth_type auth_type,
+ const u8 *bssid,
+ const u8 *ssid, int ssid_len,
+ const u8 *ie, int ie_len,
+ const u8 *key, int key_len, int key_idx)
+{
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+ struct cfg80211_auth_request req;
+ struct cfg80211_internal_bss *bss;
+ int i, err, slot = -1, nfree = 0;
+
+ ASSERT_WDEV_LOCK(wdev);
+
+ if (auth_type == NL80211_AUTHTYPE_SHARED_KEY)
+ if (!key || !key_len || key_idx < 0 || key_idx > 4)
+ return -EINVAL;
+
+ if (wdev->current_bss &&
+ memcmp(bssid, wdev->current_bss->pub.bssid, ETH_ALEN) == 0)
+ return -EALREADY;
+
+ for (i = 0; i < MAX_AUTH_BSSES; i++) {
+ if (wdev->authtry_bsses[i] &&
+ memcmp(bssid, wdev->authtry_bsses[i]->pub.bssid,
+ ETH_ALEN) == 0)
+ return -EALREADY;
+ if (wdev->auth_bsses[i] &&
+ memcmp(bssid, wdev->auth_bsses[i]->pub.bssid,
+ ETH_ALEN) == 0)
+ return -EALREADY;
+ }
+
+ memset(&req, 0, sizeof(req));
+
+ req.ie = ie;
+ req.ie_len = ie_len;
+ req.auth_type = auth_type;
+ req.bss = cfg80211_get_bss(&rdev->wiphy, chan, bssid, ssid, ssid_len,
+ WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
+ req.key = key;
+ req.key_len = key_len;
+ req.key_idx = key_idx;
+ if (!req.bss)
+ return -ENOENT;
+
+ bss = bss_from_pub(req.bss);
+
+ for (i = 0; i < MAX_AUTH_BSSES; i++) {
+ if (!wdev->auth_bsses[i] && !wdev->authtry_bsses[i]) {
+ slot = i;
+ nfree++;
+ }
+ }
+
+ /* we need one free slot for disassoc and one for this auth */
+ if (nfree < 2) {
+ err = -ENOSPC;
+ goto out;
+ }
+
+ wdev->authtry_bsses[slot] = bss;
+ cfg80211_hold_bss(bss);
+
+ err = rdev->ops->auth(&rdev->wiphy, dev, &req);
+ if (err) {
+ wdev->authtry_bsses[slot] = NULL;
+ cfg80211_unhold_bss(bss);
+ }
+
+ out:
+ if (err)
+ cfg80211_put_bss(req.bss);
+ return err;
+}
+
+int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
+ struct net_device *dev, struct ieee80211_channel *chan,
+ enum nl80211_auth_type auth_type, const u8 *bssid,
+ const u8 *ssid, int ssid_len,
+ const u8 *ie, int ie_len,
+ const u8 *key, int key_len, int key_idx)
+{
+ int err;
+
+ wdev_lock(dev->ieee80211_ptr);
+ err = __cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid,
+ ssid, ssid_len, ie, ie_len,
+ key, key_len, key_idx);
+ wdev_unlock(dev->ieee80211_ptr);
+
+ return err;
+}
+
+int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
+ struct net_device *dev,
+ struct ieee80211_channel *chan,
+ const u8 *bssid, const u8 *prev_bssid,
+ const u8 *ssid, int ssid_len,
+ const u8 *ie, int ie_len, bool use_mfp,
+ struct cfg80211_crypto_settings *crypt)
+{
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+ struct cfg80211_assoc_request req;
+ struct cfg80211_internal_bss *bss;
+ int i, err, slot = -1;
+
+ ASSERT_WDEV_LOCK(wdev);
+
+ memset(&req, 0, sizeof(req));
+
+ if (wdev->current_bss)
+ return -EALREADY;
+
+ req.ie = ie;
+ req.ie_len = ie_len;
+ memcpy(&req.crypto, crypt, sizeof(req.crypto));
+ req.use_mfp = use_mfp;
+ req.prev_bssid = prev_bssid;
+ req.bss = cfg80211_get_bss(&rdev->wiphy, chan, bssid, ssid, ssid_len,
+ WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
+ if (!req.bss)
+ return -ENOENT;
+
+ bss = bss_from_pub(req.bss);
+
+ for (i = 0; i < MAX_AUTH_BSSES; i++) {
+ if (bss == wdev->auth_bsses[i]) {
+ slot = i;
+ break;
+ }
+ }
+
+ if (slot < 0) {
+ err = -ENOTCONN;
+ goto out;
+ }
+
+ err = rdev->ops->assoc(&rdev->wiphy, dev, &req);
+ out:
+ /* still a reference in wdev->auth_bsses[slot] */
+ cfg80211_put_bss(req.bss);
+ return err;
+}
+
+int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
+ struct net_device *dev,
+ struct ieee80211_channel *chan,
+ const u8 *bssid, const u8 *prev_bssid,
+ const u8 *ssid, int ssid_len,
+ const u8 *ie, int ie_len, bool use_mfp,
+ struct cfg80211_crypto_settings *crypt)
+{
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+ int err;
+
+ wdev_lock(wdev);
+ err = __cfg80211_mlme_assoc(rdev, dev, chan, bssid, prev_bssid,
+ ssid, ssid_len, ie, ie_len, use_mfp, crypt);
+ wdev_unlock(wdev);
+
+ return err;
+}
+
+int __cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev,
+ struct net_device *dev, const u8 *bssid,
+ const u8 *ie, int ie_len, u16 reason)
+{
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+ struct cfg80211_deauth_request req;
+ int i;
+
+ ASSERT_WDEV_LOCK(wdev);
+
+ memset(&req, 0, sizeof(req));
+ req.reason_code = reason;
+ req.ie = ie;
+ req.ie_len = ie_len;
+ if (wdev->current_bss &&
+ memcmp(wdev->current_bss->pub.bssid, bssid, ETH_ALEN) == 0) {
+ req.bss = &wdev->current_bss->pub;
+ } else for (i = 0; i < MAX_AUTH_BSSES; i++) {
+ if (wdev->auth_bsses[i] &&
+ memcmp(bssid, wdev->auth_bsses[i]->pub.bssid, ETH_ALEN) == 0) {
+ req.bss = &wdev->auth_bsses[i]->pub;
+ break;
+ }
+ if (wdev->authtry_bsses[i] &&
+ memcmp(bssid, wdev->authtry_bsses[i]->pub.bssid, ETH_ALEN) == 0) {
+ req.bss = &wdev->authtry_bsses[i]->pub;
+ break;
+ }
+ }
+
+ if (!req.bss)
+ return -ENOTCONN;
+
+ return rdev->ops->deauth(&rdev->wiphy, dev, &req, wdev);
+}
+
+int cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev,
+ struct net_device *dev, const u8 *bssid,
+ const u8 *ie, int ie_len, u16 reason)
+{
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+ int err;
+
+ wdev_lock(wdev);
+ err = __cfg80211_mlme_deauth(rdev, dev, bssid, ie, ie_len, reason);
+ wdev_unlock(wdev);
+
+ return err;
+}
+
+static int __cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev,
+ struct net_device *dev, const u8 *bssid,
+ const u8 *ie, int ie_len, u16 reason)
+{
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+ struct cfg80211_disassoc_request req;
+
+ ASSERT_WDEV_LOCK(wdev);
+
+ if (wdev->sme_state != CFG80211_SME_CONNECTED)
+ return -ENOTCONN;
+
+ if (WARN_ON(!wdev->current_bss))
+ return -ENOTCONN;
+
+ memset(&req, 0, sizeof(req));
+ req.reason_code = reason;
+ req.ie = ie;
+ req.ie_len = ie_len;
+ if (memcmp(wdev->current_bss->pub.bssid, bssid, ETH_ALEN) == 0)
+ req.bss = &wdev->current_bss->pub;
+ else
+ return -ENOTCONN;
+
+ return rdev->ops->disassoc(&rdev->wiphy, dev, &req, wdev);
+}
+
+int cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev,
+ struct net_device *dev, const u8 *bssid,
+ const u8 *ie, int ie_len, u16 reason)
+{
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+ int err;
+
+ wdev_lock(wdev);
+ err = __cfg80211_mlme_disassoc(rdev, dev, bssid, ie, ie_len, reason);
+ wdev_unlock(wdev);
+
+ return err;
+}
+
+void cfg80211_mlme_down(struct cfg80211_registered_device *rdev,
+ struct net_device *dev)
+{
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+ struct cfg80211_deauth_request req;
+ int i;
+
+ ASSERT_WDEV_LOCK(wdev);
+
+ if (!rdev->ops->deauth)
+ return;
+
+ memset(&req, 0, sizeof(req));
+ req.reason_code = WLAN_REASON_DEAUTH_LEAVING;
+ req.ie = NULL;
+ req.ie_len = 0;
+
+ if (wdev->current_bss) {
+ req.bss = &wdev->current_bss->pub;
+ rdev->ops->deauth(&rdev->wiphy, dev, &req, wdev);
+ if (wdev->current_bss) {
+ cfg80211_unhold_bss(wdev->current_bss);
+ cfg80211_put_bss(&wdev->current_bss->pub);
+ wdev->current_bss = NULL;
+ }
+ }
+
+ for (i = 0; i < MAX_AUTH_BSSES; i++) {
+ if (wdev->auth_bsses[i]) {
+ req.bss = &wdev->auth_bsses[i]->pub;
+ rdev->ops->deauth(&rdev->wiphy, dev, &req, wdev);
+ if (wdev->auth_bsses[i]) {
+ cfg80211_unhold_bss(wdev->auth_bsses[i]);
+ cfg80211_put_bss(&wdev->auth_bsses[i]->pub);
+ wdev->auth_bsses[i] = NULL;
+ }
+ }
+ if (wdev->authtry_bsses[i]) {
+ req.bss = &wdev->authtry_bsses[i]->pub;
+ rdev->ops->deauth(&rdev->wiphy, dev, &req, wdev);
+ if (wdev->authtry_bsses[i]) {
+ cfg80211_unhold_bss(wdev->authtry_bsses[i]);
+ cfg80211_put_bss(&wdev->authtry_bsses[i]->pub);
+ wdev->authtry_bsses[i] = NULL;
+ }
+ }
+ }
+}
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 634496b3ed7..a8aaadeb677 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -14,8 +14,10 @@
#include <linux/rtnetlink.h>
#include <linux/netlink.h>
#include <linux/etherdevice.h>
+#include <net/net_namespace.h>
#include <net/genetlink.h>
#include <net/cfg80211.h>
+#include <net/sock.h>
#include "core.h"
#include "nl80211.h"
#include "reg.h"
@@ -27,27 +29,29 @@ static struct genl_family nl80211_fam = {
.hdrsize = 0, /* no private header */
.version = 1, /* no particular meaning now */
.maxattr = NL80211_ATTR_MAX,
+ .netnsok = true,
};
-/* internal helper: get drv and dev */
-static int get_drv_dev_by_info_ifindex(struct nlattr **attrs,
- struct cfg80211_registered_device **drv,
+/* internal helper: get rdev and dev */
+static int get_rdev_dev_by_info_ifindex(struct genl_info *info,
+ struct cfg80211_registered_device **rdev,
struct net_device **dev)
{
+ struct nlattr **attrs = info->attrs;
int ifindex;
if (!attrs[NL80211_ATTR_IFINDEX])
return -EINVAL;
ifindex = nla_get_u32(attrs[NL80211_ATTR_IFINDEX]);
- *dev = dev_get_by_index(&init_net, ifindex);
+ *dev = dev_get_by_index(genl_info_net(info), ifindex);
if (!*dev)
return -ENODEV;
- *drv = cfg80211_get_dev_from_ifindex(ifindex);
- if (IS_ERR(*drv)) {
+ *rdev = cfg80211_get_dev_from_ifindex(genl_info_net(info), ifindex);
+ if (IS_ERR(*rdev)) {
dev_put(*dev);
- return PTR_ERR(*drv);
+ return PTR_ERR(*rdev);
}
return 0;
@@ -71,7 +75,9 @@ static struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] __read_mostly = {
[NL80211_ATTR_IFNAME] = { .type = NLA_NUL_STRING, .len = IFNAMSIZ-1 },
[NL80211_ATTR_MAC] = { .type = NLA_BINARY, .len = ETH_ALEN },
+ [NL80211_ATTR_PREV_BSSID] = { .type = NLA_BINARY, .len = ETH_ALEN },
+ [NL80211_ATTR_KEY] = { .type = NLA_NESTED, },
[NL80211_ATTR_KEY_DATA] = { .type = NLA_BINARY,
.len = WLAN_MAX_KEY_LEN },
[NL80211_ATTR_KEY_IDX] = { .type = NLA_U8 },
@@ -128,6 +134,21 @@ static struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] __read_mostly = {
.len = sizeof(struct nl80211_sta_flag_update),
},
[NL80211_ATTR_CONTROL_PORT] = { .type = NLA_FLAG },
+ [NL80211_ATTR_PRIVACY] = { .type = NLA_FLAG },
+ [NL80211_ATTR_CIPHER_SUITE_GROUP] = { .type = NLA_U32 },
+ [NL80211_ATTR_WPA_VERSIONS] = { .type = NLA_U32 },
+ [NL80211_ATTR_PID] = { .type = NLA_U32 },
+};
+
+/* policy for the attributes */
+static struct nla_policy
+nl80211_key_policy[NL80211_KEY_MAX + 1] __read_mostly = {
+ [NL80211_KEY_DATA] = { .type = NLA_BINARY, .len = WLAN_MAX_KEY_LEN },
+ [NL80211_KEY_IDX] = { .type = NLA_U8 },
+ [NL80211_KEY_CIPHER] = { .type = NLA_U32 },
+ [NL80211_KEY_SEQ] = { .type = NLA_BINARY, .len = 8 },
+ [NL80211_KEY_DEFAULT] = { .type = NLA_FLAG },
+ [NL80211_KEY_DEFAULT_MGMT] = { .type = NLA_FLAG },
};
/* IE validation */
@@ -194,6 +215,177 @@ static int nl80211_msg_put_channel(struct sk_buff *msg,
/* netlink command implementations */
+struct key_parse {
+ struct key_params p;
+ int idx;
+ bool def, defmgmt;
+};
+
+static int nl80211_parse_key_new(struct nlattr *key, struct key_parse *k)
+{
+ struct nlattr *tb[NL80211_KEY_MAX + 1];
+ int err = nla_parse_nested(tb, NL80211_KEY_MAX, key,
+ nl80211_key_policy);
+ if (err)
+ return err;
+
+ k->def = !!tb[NL80211_KEY_DEFAULT];
+ k->defmgmt = !!tb[NL80211_KEY_DEFAULT_MGMT];
+
+ if (tb[NL80211_KEY_IDX])
+ k->idx = nla_get_u8(tb[NL80211_KEY_IDX]);
+
+ if (tb[NL80211_KEY_DATA]) {
+ k->p.key = nla_data(tb[NL80211_KEY_DATA]);
+ k->p.key_len = nla_len(tb[NL80211_KEY_DATA]);
+ }
+
+ if (tb[NL80211_KEY_SEQ]) {
+ k->p.seq = nla_data(tb[NL80211_KEY_SEQ]);
+ k->p.seq_len = nla_len(tb[NL80211_KEY_SEQ]);
+ }
+
+ if (tb[NL80211_KEY_CIPHER])
+ k->p.cipher = nla_get_u32(tb[NL80211_KEY_CIPHER]);
+
+ return 0;
+}
+
+static int nl80211_parse_key_old(struct genl_info *info, struct key_parse *k)
+{
+ if (info->attrs[NL80211_ATTR_KEY_DATA]) {
+ k->p.key = nla_data(info->attrs[NL80211_ATTR_KEY_DATA]);
+ k->p.key_len = nla_len(info->attrs[NL80211_ATTR_KEY_DATA]);
+ }
+
+ if (info->attrs[NL80211_ATTR_KEY_SEQ]) {
+ k->p.seq = nla_data(info->attrs[NL80211_ATTR_KEY_SEQ]);
+ k->p.seq_len = nla_len(info->attrs[NL80211_ATTR_KEY_SEQ]);
+ }
+
+ if (info->attrs[NL80211_ATTR_KEY_IDX])
+ k->idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]);
+
+ if (info->attrs[NL80211_ATTR_KEY_CIPHER])
+ k->p.cipher = nla_get_u32(info->attrs[NL80211_ATTR_KEY_CIPHER]);
+
+ k->def = !!info->attrs[NL80211_ATTR_KEY_DEFAULT];
+ k->defmgmt = !!info->attrs[NL80211_ATTR_KEY_DEFAULT_MGMT];
+
+ return 0;
+}
+
+static int nl80211_parse_key(struct genl_info *info, struct key_parse *k)
+{
+ int err;
+
+ memset(k, 0, sizeof(*k));
+ k->idx = -1;
+
+ if (info->attrs[NL80211_ATTR_KEY])
+ err = nl80211_parse_key_new(info->attrs[NL80211_ATTR_KEY], k);
+ else
+ err = nl80211_parse_key_old(info, k);
+
+ if (err)
+ return err;
+
+ if (k->def && k->defmgmt)
+ return -EINVAL;
+
+ if (k->idx != -1) {
+ if (k->defmgmt) {
+ if (k->idx < 4 || k->idx > 5)
+ return -EINVAL;
+ } else if (k->def) {
+ if (k->idx < 0 || k->idx > 3)
+ return -EINVAL;
+ } else {
+ if (k->idx < 0 || k->idx > 5)
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+
+static struct cfg80211_cached_keys *
+nl80211_parse_connkeys(struct cfg80211_registered_device *rdev,
+ struct nlattr *keys)
+{
+ struct key_parse parse;
+ struct nlattr *key;
+ struct cfg80211_cached_keys *result;
+ int rem, err, def = 0;
+
+ result = kzalloc(sizeof(*result), GFP_KERNEL);
+ if (!result)
+ return ERR_PTR(-ENOMEM);
+
+ result->def = -1;
+ result->defmgmt = -1;
+
+ nla_for_each_nested(key, keys, rem) {
+ memset(&parse, 0, sizeof(parse));
+ parse.idx = -1;
+
+ err = nl80211_parse_key_new(key, &parse);
+ if (err)
+ goto error;
+ err = -EINVAL;
+ if (!parse.p.key)
+ goto error;
+ if (parse.idx < 0 || parse.idx > 4)
+ goto error;
+ if (parse.def) {
+ if (def)
+ goto error;
+ def = 1;
+ result->def = parse.idx;
+ } else if (parse.defmgmt)
+ goto error;
+ err = cfg80211_validate_key_settings(rdev, &parse.p,
+ parse.idx, NULL);
+ if (err)
+ goto error;
+ result->params[parse.idx].cipher = parse.p.cipher;
+ result->params[parse.idx].key_len = parse.p.key_len;
+ result->params[parse.idx].key = result->data[parse.idx];
+ memcpy(result->data[parse.idx], parse.p.key, parse.p.key_len);
+ }
+
+ return result;
+ error:
+ kfree(result);
+ return ERR_PTR(err);
+}
+
+static int nl80211_key_allowed(struct wireless_dev *wdev)
+{
+ ASSERT_WDEV_LOCK(wdev);
+
+ if (!netif_running(wdev->netdev))
+ return -ENETDOWN;
+
+ switch (wdev->iftype) {
+ case NL80211_IFTYPE_AP:
+ case NL80211_IFTYPE_AP_VLAN:
+ break;
+ case NL80211_IFTYPE_ADHOC:
+ if (!wdev->current_bss)
+ return -ENOLINK;
+ break;
+ case NL80211_IFTYPE_STATION:
+ if (wdev->sme_state != CFG80211_SME_CONNECTED)
+ return -ENOLINK;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
struct cfg80211_registered_device *dev)
{
@@ -216,6 +408,9 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, dev->wiphy_idx);
NLA_PUT_STRING(msg, NL80211_ATTR_WIPHY_NAME, wiphy_name(&dev->wiphy));
+ NLA_PUT_U32(msg, NL80211_ATTR_GENERATION,
+ cfg80211_rdev_list_generation);
+
NLA_PUT_U8(msg, NL80211_ATTR_WIPHY_RETRY_SHORT,
dev->wiphy.retry_short);
NLA_PUT_U8(msg, NL80211_ATTR_WIPHY_RETRY_LONG,
@@ -345,8 +540,23 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
CMD(deauth, DEAUTHENTICATE);
CMD(disassoc, DISASSOCIATE);
CMD(join_ibss, JOIN_IBSS);
+ if (dev->wiphy.netnsok) {
+ i++;
+ NLA_PUT_U32(msg, i, NL80211_CMD_SET_WIPHY_NETNS);
+ }
#undef CMD
+
+ if (dev->ops->connect || dev->ops->auth) {
+ i++;
+ NLA_PUT_U32(msg, i, NL80211_CMD_CONNECT);
+ }
+
+ if (dev->ops->disconnect || dev->ops->deauth) {
+ i++;
+ NLA_PUT_U32(msg, i, NL80211_CMD_DISCONNECT);
+ }
+
nla_nest_end(msg, nl_cmds);
return genlmsg_end(msg, hdr);
@@ -363,7 +573,9 @@ static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb)
struct cfg80211_registered_device *dev;
mutex_lock(&cfg80211_mutex);
- list_for_each_entry(dev, &cfg80211_drv_list, list) {
+ list_for_each_entry(dev, &cfg80211_rdev_list, list) {
+ if (!net_eq(wiphy_net(&dev->wiphy), sock_net(skb->sk)))
+ continue;
if (++idx <= start)
continue;
if (nl80211_send_wiphy(skb, NETLINK_CB(cb->skb).pid,
@@ -396,14 +608,14 @@ static int nl80211_get_wiphy(struct sk_buff *skb, struct genl_info *info)
if (nl80211_send_wiphy(msg, info->snd_pid, info->snd_seq, 0, dev) < 0)
goto out_free;
- cfg80211_put_dev(dev);
+ cfg80211_unlock_rdev(dev);
- return genlmsg_unicast(msg, info->snd_pid);
+ return genlmsg_reply(msg, info);
out_free:
nlmsg_free(msg);
out_err:
- cfg80211_put_dev(dev);
+ cfg80211_unlock_rdev(dev);
return -ENOBUFS;
}
@@ -445,7 +657,7 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
mutex_lock(&cfg80211_mutex);
- rdev = __cfg80211_drv_from_info(info);
+ rdev = __cfg80211_rdev_from_info(info);
if (IS_ERR(rdev)) {
mutex_unlock(&cfg80211_mutex);
result = PTR_ERR(rdev);
@@ -492,15 +704,8 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) {
enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT;
- struct ieee80211_channel *chan;
- struct ieee80211_sta_ht_cap *ht_cap;
u32 freq;
- if (!rdev->ops->set_channel) {
- result = -EOPNOTSUPP;
- goto bad_res;
- }
-
result = -EINVAL;
if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) {
@@ -514,38 +719,10 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
}
freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]);
- chan = ieee80211_get_channel(&rdev->wiphy, freq);
- /* Primary channel not allowed */
- if (!chan || chan->flags & IEEE80211_CHAN_DISABLED)
- goto bad_res;
-
- if (channel_type == NL80211_CHAN_HT40MINUS &&
- (chan->flags & IEEE80211_CHAN_NO_HT40MINUS))
- goto bad_res;
- else if (channel_type == NL80211_CHAN_HT40PLUS &&
- (chan->flags & IEEE80211_CHAN_NO_HT40PLUS))
- goto bad_res;
-
- /*
- * At this point we know if that if HT40 was requested
- * we are allowed to use it and the extension channel
- * exists.
- */
-
- ht_cap = &rdev->wiphy.bands[chan->band]->ht_cap;
-
- /* no HT capabilities or intolerant */
- if (channel_type != NL80211_CHAN_NO_HT) {
- if (!ht_cap->ht_supported)
- goto bad_res;
- if (!(ht_cap->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) ||
- (ht_cap->cap & IEEE80211_HT_CAP_40MHZ_INTOLERANT))
- goto bad_res;
- }
-
- result = rdev->ops->set_channel(&rdev->wiphy, chan,
- channel_type);
+ mutex_lock(&rdev->devlist_mtx);
+ result = rdev_set_freq(rdev, NULL, freq, channel_type);
+ mutex_unlock(&rdev->devlist_mtx);
if (result)
goto bad_res;
}
@@ -651,6 +828,11 @@ static int nl80211_send_iface(struct sk_buff *msg, u32 pid, u32 seq, int flags,
NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx);
NLA_PUT_STRING(msg, NL80211_ATTR_IFNAME, dev->name);
NLA_PUT_U32(msg, NL80211_ATTR_IFTYPE, dev->ieee80211_ptr->iftype);
+
+ NLA_PUT_U32(msg, NL80211_ATTR_GENERATION,
+ rdev->devlist_generation ^
+ (cfg80211_rdev_list_generation << 2));
+
return genlmsg_end(msg, hdr);
nla_put_failure:
@@ -664,32 +846,34 @@ static int nl80211_dump_interface(struct sk_buff *skb, struct netlink_callback *
int if_idx = 0;
int wp_start = cb->args[0];
int if_start = cb->args[1];
- struct cfg80211_registered_device *dev;
+ struct cfg80211_registered_device *rdev;
struct wireless_dev *wdev;
mutex_lock(&cfg80211_mutex);
- list_for_each_entry(dev, &cfg80211_drv_list, list) {
+ list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
+ if (!net_eq(wiphy_net(&rdev->wiphy), sock_net(skb->sk)))
+ continue;
if (wp_idx < wp_start) {
wp_idx++;
continue;
}
if_idx = 0;
- mutex_lock(&dev->devlist_mtx);
- list_for_each_entry(wdev, &dev->netdev_list, list) {
+ mutex_lock(&rdev->devlist_mtx);
+ list_for_each_entry(wdev, &rdev->netdev_list, list) {
if (if_idx < if_start) {
if_idx++;
continue;
}
if (nl80211_send_iface(skb, NETLINK_CB(cb->skb).pid,
cb->nlh->nlmsg_seq, NLM_F_MULTI,
- dev, wdev->netdev) < 0) {
- mutex_unlock(&dev->devlist_mtx);
+ rdev, wdev->netdev) < 0) {
+ mutex_unlock(&rdev->devlist_mtx);
goto out;
}
if_idx++;
}
- mutex_unlock(&dev->devlist_mtx);
+ mutex_unlock(&rdev->devlist_mtx);
wp_idx++;
}
@@ -709,7 +893,7 @@ static int nl80211_get_interface(struct sk_buff *skb, struct genl_info *info)
struct net_device *netdev;
int err;
- err = get_drv_dev_by_info_ifindex(info->attrs, &dev, &netdev);
+ err = get_rdev_dev_by_info_ifindex(info, &dev, &netdev);
if (err)
return err;
@@ -722,15 +906,15 @@ static int nl80211_get_interface(struct sk_buff *skb, struct genl_info *info)
goto out_free;
dev_put(netdev);
- cfg80211_put_dev(dev);
+ cfg80211_unlock_rdev(dev);
- return genlmsg_unicast(msg, info->snd_pid);
+ return genlmsg_reply(msg, info);
out_free:
nlmsg_free(msg);
out_err:
dev_put(netdev);
- cfg80211_put_dev(dev);
+ cfg80211_unlock_rdev(dev);
return -ENOBUFS;
}
@@ -765,9 +949,9 @@ static int parse_monitor_flags(struct nlattr *nla, u32 *mntrflags)
static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
{
- struct cfg80211_registered_device *drv;
+ struct cfg80211_registered_device *rdev;
struct vif_params params;
- int err, ifindex;
+ int err;
enum nl80211_iftype otype, ntype;
struct net_device *dev;
u32 _flags, *flags = NULL;
@@ -777,13 +961,11 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
rtnl_lock();
- err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
+ err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
if (err)
goto unlock_rtnl;
- ifindex = dev->ifindex;
otype = ntype = dev->ieee80211_ptr->iftype;
- dev_put(dev);
if (info->attrs[NL80211_ATTR_IFTYPE]) {
ntype = nla_get_u32(info->attrs[NL80211_ATTR_IFTYPE]);
@@ -795,8 +977,8 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
}
}
- if (!drv->ops->change_virtual_intf ||
- !(drv->wiphy.interface_modes & (1 << ntype))) {
+ if (!rdev->ops->change_virtual_intf ||
+ !(rdev->wiphy.interface_modes & (1 << ntype))) {
err = -EOPNOTSUPP;
goto unlock;
}
@@ -826,21 +1008,21 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
}
if (change)
- err = drv->ops->change_virtual_intf(&drv->wiphy, ifindex,
+ err = rdev->ops->change_virtual_intf(&rdev->wiphy, dev,
ntype, flags, &params);
else
err = 0;
- dev = __dev_get_by_index(&init_net, ifindex);
- WARN_ON(!dev || (!err && dev->ieee80211_ptr->iftype != ntype));
+ WARN_ON(!err && dev->ieee80211_ptr->iftype != ntype);
- if (dev && !err && (ntype != otype)) {
+ if (!err && (ntype != otype)) {
if (otype == NL80211_IFTYPE_ADHOC)
cfg80211_clear_ibss(dev, false);
}
unlock:
- cfg80211_put_dev(drv);
+ dev_put(dev);
+ cfg80211_unlock_rdev(rdev);
unlock_rtnl:
rtnl_unlock();
return err;
@@ -848,7 +1030,7 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
{
- struct cfg80211_registered_device *drv;
+ struct cfg80211_registered_device *rdev;
struct vif_params params;
int err;
enum nl80211_iftype type = NL80211_IFTYPE_UNSPECIFIED;
@@ -867,14 +1049,14 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
rtnl_lock();
- drv = cfg80211_get_dev_from_info(info);
- if (IS_ERR(drv)) {
- err = PTR_ERR(drv);
+ rdev = cfg80211_get_dev_from_info(info);
+ if (IS_ERR(rdev)) {
+ err = PTR_ERR(rdev);
goto unlock_rtnl;
}
- if (!drv->ops->add_virtual_intf ||
- !(drv->wiphy.interface_modes & (1 << type))) {
+ if (!rdev->ops->add_virtual_intf ||
+ !(rdev->wiphy.interface_modes & (1 << type))) {
err = -EOPNOTSUPP;
goto unlock;
}
@@ -888,12 +1070,12 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
err = parse_monitor_flags(type == NL80211_IFTYPE_MONITOR ?
info->attrs[NL80211_ATTR_MNTR_FLAGS] : NULL,
&flags);
- err = drv->ops->add_virtual_intf(&drv->wiphy,
+ err = rdev->ops->add_virtual_intf(&rdev->wiphy,
nla_data(info->attrs[NL80211_ATTR_IFNAME]),
type, err ? NULL : &flags, &params);
unlock:
- cfg80211_put_dev(drv);
+ cfg80211_unlock_rdev(rdev);
unlock_rtnl:
rtnl_unlock();
return err;
@@ -901,27 +1083,26 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
static int nl80211_del_interface(struct sk_buff *skb, struct genl_info *info)
{
- struct cfg80211_registered_device *drv;
- int ifindex, err;
+ struct cfg80211_registered_device *rdev;
+ int err;
struct net_device *dev;
rtnl_lock();
- err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
+ err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
if (err)
goto unlock_rtnl;
- ifindex = dev->ifindex;
- dev_put(dev);
- if (!drv->ops->del_virtual_intf) {
+ if (!rdev->ops->del_virtual_intf) {
err = -EOPNOTSUPP;
goto out;
}
- err = drv->ops->del_virtual_intf(&drv->wiphy, ifindex);
+ err = rdev->ops->del_virtual_intf(&rdev->wiphy, dev);
out:
- cfg80211_put_dev(drv);
+ cfg80211_unlock_rdev(rdev);
+ dev_put(dev);
unlock_rtnl:
rtnl_unlock();
return err;
@@ -930,10 +1111,12 @@ static int nl80211_del_interface(struct sk_buff *skb, struct genl_info *info)
struct get_key_cookie {
struct sk_buff *msg;
int error;
+ int idx;
};
static void get_key_callback(void *c, struct key_params *params)
{
+ struct nlattr *key;
struct get_key_cookie *cookie = c;
if (params->key)
@@ -948,6 +1131,26 @@ static void get_key_callback(void *c, struct key_params *params)
NLA_PUT_U32(cookie->msg, NL80211_ATTR_KEY_CIPHER,
params->cipher);
+ key = nla_nest_start(cookie->msg, NL80211_ATTR_KEY);
+ if (!key)
+ goto nla_put_failure;
+
+ if (params->key)
+ NLA_PUT(cookie->msg, NL80211_KEY_DATA,
+ params->key_len, params->key);
+
+ if (params->seq)
+ NLA_PUT(cookie->msg, NL80211_KEY_SEQ,
+ params->seq_len, params->seq);
+
+ if (params->cipher)
+ NLA_PUT_U32(cookie->msg, NL80211_KEY_CIPHER,
+ params->cipher);
+
+ NLA_PUT_U8(cookie->msg, NL80211_ATTR_KEY_IDX, cookie->idx);
+
+ nla_nest_end(cookie->msg, key);
+
return;
nla_put_failure:
cookie->error = 1;
@@ -955,7 +1158,7 @@ static void get_key_callback(void *c, struct key_params *params)
static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info)
{
- struct cfg80211_registered_device *drv;
+ struct cfg80211_registered_device *rdev;
int err;
struct net_device *dev;
u8 key_idx = 0;
@@ -977,11 +1180,11 @@ static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info)
rtnl_lock();
- err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
+ err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
if (err)
goto unlock_rtnl;
- if (!drv->ops->get_key) {
+ if (!rdev->ops->get_key) {
err = -EOPNOTSUPP;
goto out;
}
@@ -1001,13 +1204,14 @@ static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info)
}
cookie.msg = msg;
+ cookie.idx = key_idx;
NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex);
NLA_PUT_U8(msg, NL80211_ATTR_KEY_IDX, key_idx);
if (mac_addr)
NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr);
- err = drv->ops->get_key(&drv->wiphy, dev, key_idx, mac_addr,
+ err = rdev->ops->get_key(&rdev->wiphy, dev, key_idx, mac_addr,
&cookie, get_key_callback);
if (err)
@@ -1017,7 +1221,7 @@ static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info)
goto nla_put_failure;
genlmsg_end(msg, hdr);
- err = genlmsg_unicast(msg, info->snd_pid);
+ err = genlmsg_reply(msg, info);
goto out;
nla_put_failure:
@@ -1025,7 +1229,7 @@ static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info)
free_msg:
nlmsg_free(msg);
out:
- cfg80211_put_dev(drv);
+ cfg80211_unlock_rdev(rdev);
dev_put(dev);
unlock_rtnl:
rtnl_unlock();
@@ -1035,57 +1239,57 @@ static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info)
static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info)
{
- struct cfg80211_registered_device *drv;
+ struct cfg80211_registered_device *rdev;
+ struct key_parse key;
int err;
struct net_device *dev;
- u8 key_idx;
int (*func)(struct wiphy *wiphy, struct net_device *netdev,
u8 key_index);
- if (!info->attrs[NL80211_ATTR_KEY_IDX])
- return -EINVAL;
-
- key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]);
+ err = nl80211_parse_key(info, &key);
+ if (err)
+ return err;
- if (info->attrs[NL80211_ATTR_KEY_DEFAULT_MGMT]) {
- if (key_idx < 4 || key_idx > 5)
- return -EINVAL;
- } else if (key_idx > 3)
+ if (key.idx < 0)
return -EINVAL;
- /* currently only support setting default key */
- if (!info->attrs[NL80211_ATTR_KEY_DEFAULT] &&
- !info->attrs[NL80211_ATTR_KEY_DEFAULT_MGMT])
+ /* only support setting default key */
+ if (!key.def && !key.defmgmt)
return -EINVAL;
rtnl_lock();
- err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
+ err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
if (err)
goto unlock_rtnl;
- if (info->attrs[NL80211_ATTR_KEY_DEFAULT])
- func = drv->ops->set_default_key;
+ if (key.def)
+ func = rdev->ops->set_default_key;
else
- func = drv->ops->set_default_mgmt_key;
+ func = rdev->ops->set_default_mgmt_key;
if (!func) {
err = -EOPNOTSUPP;
goto out;
}
- err = func(&drv->wiphy, dev, key_idx);
+ wdev_lock(dev->ieee80211_ptr);
+ err = nl80211_key_allowed(dev->ieee80211_ptr);
+ if (!err)
+ err = func(&rdev->wiphy, dev, key.idx);
+
#ifdef CONFIG_WIRELESS_EXT
if (!err) {
- if (func == drv->ops->set_default_key)
- dev->ieee80211_ptr->wext.default_key = key_idx;
+ if (func == rdev->ops->set_default_key)
+ dev->ieee80211_ptr->wext.default_key = key.idx;
else
- dev->ieee80211_ptr->wext.default_mgmt_key = key_idx;
+ dev->ieee80211_ptr->wext.default_mgmt_key = key.idx;
}
#endif
+ wdev_unlock(dev->ieee80211_ptr);
out:
- cfg80211_put_dev(drv);
+ cfg80211_unlock_rdev(rdev);
dev_put(dev);
unlock_rtnl:
@@ -1096,62 +1300,47 @@ static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info)
static int nl80211_new_key(struct sk_buff *skb, struct genl_info *info)
{
- struct cfg80211_registered_device *drv;
- int err, i;
+ struct cfg80211_registered_device *rdev;
+ int err;
struct net_device *dev;
- struct key_params params;
- u8 key_idx = 0;
+ struct key_parse key;
u8 *mac_addr = NULL;
- memset(&params, 0, sizeof(params));
+ err = nl80211_parse_key(info, &key);
+ if (err)
+ return err;
- if (!info->attrs[NL80211_ATTR_KEY_CIPHER])
+ if (!key.p.key)
return -EINVAL;
- if (info->attrs[NL80211_ATTR_KEY_DATA]) {
- params.key = nla_data(info->attrs[NL80211_ATTR_KEY_DATA]);
- params.key_len = nla_len(info->attrs[NL80211_ATTR_KEY_DATA]);
- }
-
- if (info->attrs[NL80211_ATTR_KEY_SEQ]) {
- params.seq = nla_data(info->attrs[NL80211_ATTR_KEY_SEQ]);
- params.seq_len = nla_len(info->attrs[NL80211_ATTR_KEY_SEQ]);
- }
-
- if (info->attrs[NL80211_ATTR_KEY_IDX])
- key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]);
-
- params.cipher = nla_get_u32(info->attrs[NL80211_ATTR_KEY_CIPHER]);
-
if (info->attrs[NL80211_ATTR_MAC])
mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
- if (cfg80211_validate_key_settings(&params, key_idx, mac_addr))
- return -EINVAL;
-
rtnl_lock();
- err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
+ err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
if (err)
goto unlock_rtnl;
- for (i = 0; i < drv->wiphy.n_cipher_suites; i++)
- if (params.cipher == drv->wiphy.cipher_suites[i])
- break;
- if (i == drv->wiphy.n_cipher_suites) {
- err = -EINVAL;
+ if (!rdev->ops->add_key) {
+ err = -EOPNOTSUPP;
goto out;
}
- if (!drv->ops->add_key) {
- err = -EOPNOTSUPP;
+ if (cfg80211_validate_key_settings(rdev, &key.p, key.idx, mac_addr)) {
+ err = -EINVAL;
goto out;
}
- err = drv->ops->add_key(&drv->wiphy, dev, key_idx, mac_addr, &params);
+ wdev_lock(dev->ieee80211_ptr);
+ err = nl80211_key_allowed(dev->ieee80211_ptr);
+ if (!err)
+ err = rdev->ops->add_key(&rdev->wiphy, dev, key.idx,
+ mac_addr, &key.p);
+ wdev_unlock(dev->ieee80211_ptr);
out:
- cfg80211_put_dev(drv);
+ cfg80211_unlock_rdev(rdev);
dev_put(dev);
unlock_rtnl:
rtnl_unlock();
@@ -1161,45 +1350,47 @@ static int nl80211_new_key(struct sk_buff *skb, struct genl_info *info)
static int nl80211_del_key(struct sk_buff *skb, struct genl_info *info)
{
- struct cfg80211_registered_device *drv;
+ struct cfg80211_registered_device *rdev;
int err;
struct net_device *dev;
- u8 key_idx = 0;
u8 *mac_addr = NULL;
+ struct key_parse key;
- if (info->attrs[NL80211_ATTR_KEY_IDX])
- key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]);
-
- if (key_idx > 5)
- return -EINVAL;
+ err = nl80211_parse_key(info, &key);
+ if (err)
+ return err;
if (info->attrs[NL80211_ATTR_MAC])
mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
rtnl_lock();
- err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
+ err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
if (err)
goto unlock_rtnl;
- if (!drv->ops->del_key) {
+ if (!rdev->ops->del_key) {
err = -EOPNOTSUPP;
goto out;
}
- err = drv->ops->del_key(&drv->wiphy, dev, key_idx, mac_addr);
+ wdev_lock(dev->ieee80211_ptr);
+ err = nl80211_key_allowed(dev->ieee80211_ptr);
+ if (!err)
+ err = rdev->ops->del_key(&rdev->wiphy, dev, key.idx, mac_addr);
#ifdef CONFIG_WIRELESS_EXT
if (!err) {
- if (key_idx == dev->ieee80211_ptr->wext.default_key)
+ if (key.idx == dev->ieee80211_ptr->wext.default_key)
dev->ieee80211_ptr->wext.default_key = -1;
- else if (key_idx == dev->ieee80211_ptr->wext.default_mgmt_key)
+ else if (key.idx == dev->ieee80211_ptr->wext.default_mgmt_key)
dev->ieee80211_ptr->wext.default_mgmt_key = -1;
}
#endif
+ wdev_unlock(dev->ieee80211_ptr);
out:
- cfg80211_put_dev(drv);
+ cfg80211_unlock_rdev(rdev);
dev_put(dev);
unlock_rtnl:
@@ -1212,7 +1403,7 @@ static int nl80211_addset_beacon(struct sk_buff *skb, struct genl_info *info)
{
int (*call)(struct wiphy *wiphy, struct net_device *dev,
struct beacon_parameters *info);
- struct cfg80211_registered_device *drv;
+ struct cfg80211_registered_device *rdev;
int err;
struct net_device *dev;
struct beacon_parameters params;
@@ -1223,7 +1414,7 @@ static int nl80211_addset_beacon(struct sk_buff *skb, struct genl_info *info)
rtnl_lock();
- err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
+ err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
if (err)
goto unlock_rtnl;
@@ -1242,10 +1433,10 @@ static int nl80211_addset_beacon(struct sk_buff *skb, struct genl_info *info)
goto out;
}
- call = drv->ops->add_beacon;
+ call = rdev->ops->add_beacon;
break;
case NL80211_CMD_SET_BEACON:
- call = drv->ops->set_beacon;
+ call = rdev->ops->set_beacon;
break;
default:
WARN_ON(1);
@@ -1291,10 +1482,10 @@ static int nl80211_addset_beacon(struct sk_buff *skb, struct genl_info *info)
goto out;
}
- err = call(&drv->wiphy, dev, &params);
+ err = call(&rdev->wiphy, dev, &params);
out:
- cfg80211_put_dev(drv);
+ cfg80211_unlock_rdev(rdev);
dev_put(dev);
unlock_rtnl:
rtnl_unlock();
@@ -1304,17 +1495,17 @@ static int nl80211_addset_beacon(struct sk_buff *skb, struct genl_info *info)
static int nl80211_del_beacon(struct sk_buff *skb, struct genl_info *info)
{
- struct cfg80211_registered_device *drv;
+ struct cfg80211_registered_device *rdev;
int err;
struct net_device *dev;
rtnl_lock();
- err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
+ err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
if (err)
goto unlock_rtnl;
- if (!drv->ops->del_beacon) {
+ if (!rdev->ops->del_beacon) {
err = -EOPNOTSUPP;
goto out;
}
@@ -1323,10 +1514,10 @@ static int nl80211_del_beacon(struct sk_buff *skb, struct genl_info *info)
err = -EOPNOTSUPP;
goto out;
}
- err = drv->ops->del_beacon(&drv->wiphy, dev);
+ err = rdev->ops->del_beacon(&rdev->wiphy, dev);
out:
- cfg80211_put_dev(drv);
+ cfg80211_unlock_rdev(rdev);
dev_put(dev);
unlock_rtnl:
rtnl_unlock();
@@ -1433,6 +1624,8 @@ static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq,
NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex);
NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr);
+ NLA_PUT_U32(msg, NL80211_ATTR_GENERATION, sinfo->generation);
+
sinfoattr = nla_nest_start(msg, NL80211_ATTR_STA_INFO);
if (!sinfoattr)
goto nla_put_failure;
@@ -1520,13 +1713,13 @@ static int nl80211_dump_station(struct sk_buff *skb,
rtnl_lock();
- netdev = __dev_get_by_index(&init_net, ifidx);
+ netdev = __dev_get_by_index(sock_net(skb->sk), ifidx);
if (!netdev) {
err = -ENODEV;
goto out_rtnl;
}
- dev = cfg80211_get_dev_from_ifindex(ifidx);
+ dev = cfg80211_get_dev_from_ifindex(sock_net(skb->sk), ifidx);
if (IS_ERR(dev)) {
err = PTR_ERR(dev);
goto out_rtnl;
@@ -1560,7 +1753,7 @@ static int nl80211_dump_station(struct sk_buff *skb,
cb->args[1] = sta_idx;
err = skb->len;
out_err:
- cfg80211_put_dev(dev);
+ cfg80211_unlock_rdev(dev);
out_rtnl:
rtnl_unlock();
@@ -1569,7 +1762,7 @@ static int nl80211_dump_station(struct sk_buff *skb,
static int nl80211_get_station(struct sk_buff *skb, struct genl_info *info)
{
- struct cfg80211_registered_device *drv;
+ struct cfg80211_registered_device *rdev;
int err;
struct net_device *dev;
struct station_info sinfo;
@@ -1585,16 +1778,16 @@ static int nl80211_get_station(struct sk_buff *skb, struct genl_info *info)
rtnl_lock();
- err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
+ err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
if (err)
goto out_rtnl;
- if (!drv->ops->get_station) {
+ if (!rdev->ops->get_station) {
err = -EOPNOTSUPP;
goto out;
}
- err = drv->ops->get_station(&drv->wiphy, dev, mac_addr, &sinfo);
+ err = rdev->ops->get_station(&rdev->wiphy, dev, mac_addr, &sinfo);
if (err)
goto out;
@@ -1606,13 +1799,13 @@ static int nl80211_get_station(struct sk_buff *skb, struct genl_info *info)
dev, mac_addr, &sinfo) < 0)
goto out_free;
- err = genlmsg_unicast(msg, info->snd_pid);
+ err = genlmsg_reply(msg, info);
goto out;
out_free:
nlmsg_free(msg);
out:
- cfg80211_put_dev(drv);
+ cfg80211_unlock_rdev(rdev);
dev_put(dev);
out_rtnl:
rtnl_unlock();
@@ -1623,14 +1816,16 @@ static int nl80211_get_station(struct sk_buff *skb, struct genl_info *info)
/*
* Get vlan interface making sure it is on the right wiphy.
*/
-static int get_vlan(struct nlattr *vlanattr,
+static int get_vlan(struct genl_info *info,
struct cfg80211_registered_device *rdev,
struct net_device **vlan)
{
+ struct nlattr *vlanattr = info->attrs[NL80211_ATTR_STA_VLAN];
*vlan = NULL;
if (vlanattr) {
- *vlan = dev_get_by_index(&init_net, nla_get_u32(vlanattr));
+ *vlan = dev_get_by_index(genl_info_net(info),
+ nla_get_u32(vlanattr));
if (!*vlan)
return -ENODEV;
if (!(*vlan)->ieee80211_ptr)
@@ -1643,7 +1838,7 @@ static int get_vlan(struct nlattr *vlanattr,
static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)
{
- struct cfg80211_registered_device *drv;
+ struct cfg80211_registered_device *rdev;
int err;
struct net_device *dev;
struct station_parameters params;
@@ -1685,11 +1880,11 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)
rtnl_lock();
- err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
+ err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
if (err)
goto out_rtnl;
- err = get_vlan(info->attrs[NL80211_ATTR_STA_VLAN], drv, &params.vlan);
+ err = get_vlan(info, rdev, &params.vlan);
if (err)
goto out;
@@ -1738,17 +1933,17 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)
if (err)
goto out;
- if (!drv->ops->change_station) {
+ if (!rdev->ops->change_station) {
err = -EOPNOTSUPP;
goto out;
}
- err = drv->ops->change_station(&drv->wiphy, dev, mac_addr, &params);
+ err = rdev->ops->change_station(&rdev->wiphy, dev, mac_addr, &params);
out:
if (params.vlan)
dev_put(params.vlan);
- cfg80211_put_dev(drv);
+ cfg80211_unlock_rdev(rdev);
dev_put(dev);
out_rtnl:
rtnl_unlock();
@@ -1758,7 +1953,7 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)
static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
{
- struct cfg80211_registered_device *drv;
+ struct cfg80211_registered_device *rdev;
int err;
struct net_device *dev;
struct station_parameters params;
@@ -1798,11 +1993,11 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
rtnl_lock();
- err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
+ err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
if (err)
goto out_rtnl;
- err = get_vlan(info->attrs[NL80211_ATTR_STA_VLAN], drv, &params.vlan);
+ err = get_vlan(info, rdev, &params.vlan);
if (err)
goto out;
@@ -1838,7 +2033,7 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
if (err)
goto out;
- if (!drv->ops->add_station) {
+ if (!rdev->ops->add_station) {
err = -EOPNOTSUPP;
goto out;
}
@@ -1848,12 +2043,12 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
goto out;
}
- err = drv->ops->add_station(&drv->wiphy, dev, mac_addr, &params);
+ err = rdev->ops->add_station(&rdev->wiphy, dev, mac_addr, &params);
out:
if (params.vlan)
dev_put(params.vlan);
- cfg80211_put_dev(drv);
+ cfg80211_unlock_rdev(rdev);
dev_put(dev);
out_rtnl:
rtnl_unlock();
@@ -1863,7 +2058,7 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
static int nl80211_del_station(struct sk_buff *skb, struct genl_info *info)
{
- struct cfg80211_registered_device *drv;
+ struct cfg80211_registered_device *rdev;
int err;
struct net_device *dev;
u8 *mac_addr = NULL;
@@ -1873,7 +2068,7 @@ static int nl80211_del_station(struct sk_buff *skb, struct genl_info *info)
rtnl_lock();
- err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
+ err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
if (err)
goto out_rtnl;
@@ -1884,15 +2079,15 @@ static int nl80211_del_station(struct sk_buff *skb, struct genl_info *info)
goto out;
}
- if (!drv->ops->del_station) {
+ if (!rdev->ops->del_station) {
err = -EOPNOTSUPP;
goto out;
}
- err = drv->ops->del_station(&drv->wiphy, dev, mac_addr);
+ err = rdev->ops->del_station(&rdev->wiphy, dev, mac_addr);
out:
- cfg80211_put_dev(drv);
+ cfg80211_unlock_rdev(rdev);
dev_put(dev);
out_rtnl:
rtnl_unlock();
@@ -1916,6 +2111,8 @@ static int nl80211_send_mpath(struct sk_buff *msg, u32 pid, u32 seq,
NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, dst);
NLA_PUT(msg, NL80211_ATTR_MPATH_NEXT_HOP, ETH_ALEN, next_hop);
+ NLA_PUT_U32(msg, NL80211_ATTR_GENERATION, pinfo->generation);
+
pinfoattr = nla_nest_start(msg, NL80211_ATTR_MPATH_INFO);
if (!pinfoattr)
goto nla_put_failure;
@@ -1979,13 +2176,13 @@ static int nl80211_dump_mpath(struct sk_buff *skb,
rtnl_lock();
- netdev = __dev_get_by_index(&init_net, ifidx);
+ netdev = __dev_get_by_index(sock_net(skb->sk), ifidx);
if (!netdev) {
err = -ENODEV;
goto out_rtnl;
}
- dev = cfg80211_get_dev_from_ifindex(ifidx);
+ dev = cfg80211_get_dev_from_ifindex(sock_net(skb->sk), ifidx);
if (IS_ERR(dev)) {
err = PTR_ERR(dev);
goto out_rtnl;
@@ -2023,7 +2220,7 @@ static int nl80211_dump_mpath(struct sk_buff *skb,
cb->args[1] = path_idx;
err = skb->len;
out_err:
- cfg80211_put_dev(dev);
+ cfg80211_unlock_rdev(dev);
out_rtnl:
rtnl_unlock();
@@ -2032,7 +2229,7 @@ static int nl80211_dump_mpath(struct sk_buff *skb,
static int nl80211_get_mpath(struct sk_buff *skb, struct genl_info *info)
{
- struct cfg80211_registered_device *drv;
+ struct cfg80211_registered_device *rdev;
int err;
struct net_device *dev;
struct mpath_info pinfo;
@@ -2049,11 +2246,11 @@ static int nl80211_get_mpath(struct sk_buff *skb, struct genl_info *info)
rtnl_lock();
- err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
+ err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
if (err)
goto out_rtnl;
- if (!drv->ops->get_mpath) {
+ if (!rdev->ops->get_mpath) {
err = -EOPNOTSUPP;
goto out;
}
@@ -2063,7 +2260,7 @@ static int nl80211_get_mpath(struct sk_buff *skb, struct genl_info *info)
goto out;
}
- err = drv->ops->get_mpath(&drv->wiphy, dev, dst, next_hop, &pinfo);
+ err = rdev->ops->get_mpath(&rdev->wiphy, dev, dst, next_hop, &pinfo);
if (err)
goto out;
@@ -2075,13 +2272,13 @@ static int nl80211_get_mpath(struct sk_buff *skb, struct genl_info *info)
dev, dst, next_hop, &pinfo) < 0)
goto out_free;
- err = genlmsg_unicast(msg, info->snd_pid);
+ err = genlmsg_reply(msg, info);
goto out;
out_free:
nlmsg_free(msg);
out:
- cfg80211_put_dev(drv);
+ cfg80211_unlock_rdev(rdev);
dev_put(dev);
out_rtnl:
rtnl_unlock();
@@ -2091,7 +2288,7 @@ static int nl80211_get_mpath(struct sk_buff *skb, struct genl_info *info)
static int nl80211_set_mpath(struct sk_buff *skb, struct genl_info *info)
{
- struct cfg80211_registered_device *drv;
+ struct cfg80211_registered_device *rdev;
int err;
struct net_device *dev;
u8 *dst = NULL;
@@ -2108,11 +2305,11 @@ static int nl80211_set_mpath(struct sk_buff *skb, struct genl_info *info)
rtnl_lock();
- err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
+ err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
if (err)
goto out_rtnl;
- if (!drv->ops->change_mpath) {
+ if (!rdev->ops->change_mpath) {
err = -EOPNOTSUPP;
goto out;
}
@@ -2127,10 +2324,10 @@ static int nl80211_set_mpath(struct sk_buff *skb, struct genl_info *info)
goto out;
}
- err = drv->ops->change_mpath(&drv->wiphy, dev, dst, next_hop);
+ err = rdev->ops->change_mpath(&rdev->wiphy, dev, dst, next_hop);
out:
- cfg80211_put_dev(drv);
+ cfg80211_unlock_rdev(rdev);
dev_put(dev);
out_rtnl:
rtnl_unlock();
@@ -2139,7 +2336,7 @@ static int nl80211_set_mpath(struct sk_buff *skb, struct genl_info *info)
}
static int nl80211_new_mpath(struct sk_buff *skb, struct genl_info *info)
{
- struct cfg80211_registered_device *drv;
+ struct cfg80211_registered_device *rdev;
int err;
struct net_device *dev;
u8 *dst = NULL;
@@ -2156,11 +2353,11 @@ static int nl80211_new_mpath(struct sk_buff *skb, struct genl_info *info)
rtnl_lock();
- err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
+ err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
if (err)
goto out_rtnl;
- if (!drv->ops->add_mpath) {
+ if (!rdev->ops->add_mpath) {
err = -EOPNOTSUPP;
goto out;
}
@@ -2175,10 +2372,10 @@ static int nl80211_new_mpath(struct sk_buff *skb, struct genl_info *info)
goto out;
}
- err = drv->ops->add_mpath(&drv->wiphy, dev, dst, next_hop);
+ err = rdev->ops->add_mpath(&rdev->wiphy, dev, dst, next_hop);
out:
- cfg80211_put_dev(drv);
+ cfg80211_unlock_rdev(rdev);
dev_put(dev);
out_rtnl:
rtnl_unlock();
@@ -2188,7 +2385,7 @@ static int nl80211_new_mpath(struct sk_buff *skb, struct genl_info *info)
static int nl80211_del_mpath(struct sk_buff *skb, struct genl_info *info)
{
- struct cfg80211_registered_device *drv;
+ struct cfg80211_registered_device *rdev;
int err;
struct net_device *dev;
u8 *dst = NULL;
@@ -2198,19 +2395,19 @@ static int nl80211_del_mpath(struct sk_buff *skb, struct genl_info *info)
rtnl_lock();
- err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
+ err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
if (err)
goto out_rtnl;
- if (!drv->ops->del_mpath) {
+ if (!rdev->ops->del_mpath) {
err = -EOPNOTSUPP;
goto out;
}
- err = drv->ops->del_mpath(&drv->wiphy, dev, dst);
+ err = rdev->ops->del_mpath(&rdev->wiphy, dev, dst);
out:
- cfg80211_put_dev(drv);
+ cfg80211_unlock_rdev(rdev);
dev_put(dev);
out_rtnl:
rtnl_unlock();
@@ -2220,7 +2417,7 @@ static int nl80211_del_mpath(struct sk_buff *skb, struct genl_info *info)
static int nl80211_set_bss(struct sk_buff *skb, struct genl_info *info)
{
- struct cfg80211_registered_device *drv;
+ struct cfg80211_registered_device *rdev;
int err;
struct net_device *dev;
struct bss_parameters params;
@@ -2249,11 +2446,11 @@ static int nl80211_set_bss(struct sk_buff *skb, struct genl_info *info)
rtnl_lock();
- err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
+ err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
if (err)
goto out_rtnl;
- if (!drv->ops->change_bss) {
+ if (!rdev->ops->change_bss) {
err = -EOPNOTSUPP;
goto out;
}
@@ -2263,10 +2460,10 @@ static int nl80211_set_bss(struct sk_buff *skb, struct genl_info *info)
goto out;
}
- err = drv->ops->change_bss(&drv->wiphy, dev, &params);
+ err = rdev->ops->change_bss(&rdev->wiphy, dev, &params);
out:
- cfg80211_put_dev(drv);
+ cfg80211_unlock_rdev(rdev);
dev_put(dev);
out_rtnl:
rtnl_unlock();
@@ -2357,7 +2554,7 @@ static int nl80211_req_set_reg(struct sk_buff *skb, struct genl_info *info)
static int nl80211_get_mesh_params(struct sk_buff *skb,
struct genl_info *info)
{
- struct cfg80211_registered_device *drv;
+ struct cfg80211_registered_device *rdev;
struct mesh_config cur_params;
int err;
struct net_device *dev;
@@ -2368,17 +2565,17 @@ static int nl80211_get_mesh_params(struct sk_buff *skb,
rtnl_lock();
/* Look up our device */
- err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
+ err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
if (err)
goto out_rtnl;
- if (!drv->ops->get_mesh_params) {
+ if (!rdev->ops->get_mesh_params) {
err = -EOPNOTSUPP;
goto out;
}
/* Get the mesh params */
- err = drv->ops->get_mesh_params(&drv->wiphy, dev, &cur_params);
+ err = rdev->ops->get_mesh_params(&rdev->wiphy, dev, &cur_params);
if (err)
goto out;
@@ -2424,7 +2621,7 @@ static int nl80211_get_mesh_params(struct sk_buff *skb,
cur_params.dot11MeshHWMPnetDiameterTraversalTime);
nla_nest_end(msg, pinfoattr);
genlmsg_end(msg, hdr);
- err = genlmsg_unicast(msg, info->snd_pid);
+ err = genlmsg_reply(msg, info);
goto out;
nla_put_failure:
@@ -2432,7 +2629,7 @@ static int nl80211_get_mesh_params(struct sk_buff *skb,
err = -EMSGSIZE;
out:
/* Cleanup */
- cfg80211_put_dev(drv);
+ cfg80211_unlock_rdev(rdev);
dev_put(dev);
out_rtnl:
rtnl_unlock();
@@ -2470,7 +2667,7 @@ static int nl80211_set_mesh_params(struct sk_buff *skb, struct genl_info *info)
{
int err;
u32 mask;
- struct cfg80211_registered_device *drv;
+ struct cfg80211_registered_device *rdev;
struct net_device *dev;
struct mesh_config cfg;
struct nlattr *tb[NL80211_MESHCONF_ATTR_MAX + 1];
@@ -2485,11 +2682,11 @@ static int nl80211_set_mesh_params(struct sk_buff *skb, struct genl_info *info)
rtnl_lock();
- err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
+ err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
if (err)
goto out_rtnl;
- if (!drv->ops->set_mesh_params) {
+ if (!rdev->ops->set_mesh_params) {
err = -EOPNOTSUPP;
goto out;
}
@@ -2534,11 +2731,11 @@ static int nl80211_set_mesh_params(struct sk_buff *skb, struct genl_info *info)
nla_get_u16);
/* Apply changes */
- err = drv->ops->set_mesh_params(&drv->wiphy, dev, &cfg, mask);
+ err = rdev->ops->set_mesh_params(&rdev->wiphy, dev, &cfg, mask);
out:
/* cleanup */
- cfg80211_put_dev(drv);
+ cfg80211_unlock_rdev(rdev);
dev_put(dev);
out_rtnl:
rtnl_unlock();
@@ -2612,7 +2809,7 @@ static int nl80211_get_reg(struct sk_buff *skb, struct genl_info *info)
nla_nest_end(msg, nl_reg_rules);
genlmsg_end(msg, hdr);
- err = genlmsg_unicast(msg, info->snd_pid);
+ err = genlmsg_reply(msg, info);
goto out;
nla_put_failure:
@@ -2698,16 +2895,41 @@ static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info)
return r;
}
+static int validate_scan_freqs(struct nlattr *freqs)
+{
+ struct nlattr *attr1, *attr2;
+ int n_channels = 0, tmp1, tmp2;
+
+ nla_for_each_nested(attr1, freqs, tmp1) {
+ n_channels++;
+ /*
+ * Some hardware has a limited channel list for
+ * scanning, and it is pretty much nonsensical
+ * to scan for a channel twice, so disallow that
+ * and don't require drivers to check that the
+ * channel list they get isn't longer than what
+ * they can scan, as long as they can scan all
+ * the channels they registered at once.
+ */
+ nla_for_each_nested(attr2, freqs, tmp2)
+ if (attr1 != attr2 &&
+ nla_get_u32(attr1) == nla_get_u32(attr2))
+ return 0;
+ }
+
+ return n_channels;
+}
+
static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
{
- struct cfg80211_registered_device *drv;
+ struct cfg80211_registered_device *rdev;
struct net_device *dev;
struct cfg80211_scan_request *request;
struct cfg80211_ssid *ssid;
struct ieee80211_channel *channel;
struct nlattr *attr;
struct wiphy *wiphy;
- int err, tmp, n_ssids = 0, n_channels = 0, i;
+ int err, tmp, n_ssids = 0, n_channels, i;
enum ieee80211_band band;
size_t ie_len;
@@ -2716,13 +2938,13 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
rtnl_lock();
- err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
+ err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
if (err)
goto out_rtnl;
- wiphy = &drv->wiphy;
+ wiphy = &rdev->wiphy;
- if (!drv->ops->scan) {
+ if (!rdev->ops->scan) {
err = -EOPNOTSUPP;
goto out;
}
@@ -2732,19 +2954,21 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
goto out;
}
- if (drv->scan_req) {
+ if (rdev->scan_req) {
err = -EBUSY;
goto out;
}
if (info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]) {
- nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_FREQUENCIES], tmp)
- n_channels++;
+ n_channels = validate_scan_freqs(
+ info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]);
if (!n_channels) {
err = -EINVAL;
goto out;
}
} else {
+ n_channels = 0;
+
for (band = 0; band < IEEE80211_NUM_BANDS; band++)
if (wiphy->bands[band])
n_channels += wiphy->bands[band]->n_channels;
@@ -2778,10 +3002,9 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
goto out;
}
- request->channels = (void *)((char *)request + sizeof(*request));
request->n_channels = n_channels;
if (n_ssids)
- request->ssids = (void *)(request->channels + n_channels);
+ request->ssids = (void *)&request->channels[n_channels];
request->n_ssids = n_ssids;
if (ie_len) {
if (request->ssids)
@@ -2836,19 +3059,24 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
request->ie_len);
}
- request->ifidx = dev->ifindex;
- request->wiphy = &drv->wiphy;
+ request->dev = dev;
+ request->wiphy = &rdev->wiphy;
- drv->scan_req = request;
- err = drv->ops->scan(&drv->wiphy, dev, request);
+ rdev->scan_req = request;
+ err = rdev->ops->scan(&rdev->wiphy, dev, request);
+
+ if (!err) {
+ nl80211_send_scan_start(rdev, dev);
+ dev_hold(dev);
+ }
out_free:
if (err) {
- drv->scan_req = NULL;
+ rdev->scan_req = NULL;
kfree(request);
}
out:
- cfg80211_put_dev(drv);
+ cfg80211_unlock_rdev(rdev);
dev_put(dev);
out_rtnl:
rtnl_unlock();
@@ -2858,20 +3086,23 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
static int nl80211_send_bss(struct sk_buff *msg, u32 pid, u32 seq, int flags,
struct cfg80211_registered_device *rdev,
- struct net_device *dev,
- struct cfg80211_bss *res)
+ struct wireless_dev *wdev,
+ struct cfg80211_internal_bss *intbss)
{
+ struct cfg80211_bss *res = &intbss->pub;
void *hdr;
struct nlattr *bss;
+ int i;
+
+ ASSERT_WDEV_LOCK(wdev);
hdr = nl80211hdr_put(msg, pid, seq, flags,
NL80211_CMD_NEW_SCAN_RESULTS);
if (!hdr)
return -1;
- NLA_PUT_U32(msg, NL80211_ATTR_SCAN_GENERATION,
- rdev->bss_generation);
- NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex);
+ NLA_PUT_U32(msg, NL80211_ATTR_GENERATION, rdev->bss_generation);
+ NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, wdev->netdev->ifindex);
bss = nla_nest_start(msg, NL80211_ATTR_BSS);
if (!bss)
@@ -2900,6 +3131,28 @@ static int nl80211_send_bss(struct sk_buff *msg, u32 pid, u32 seq, int flags,
break;
}
+ switch (wdev->iftype) {
+ case NL80211_IFTYPE_STATION:
+ if (intbss == wdev->current_bss)
+ NLA_PUT_U32(msg, NL80211_BSS_STATUS,
+ NL80211_BSS_STATUS_ASSOCIATED);
+ else for (i = 0; i < MAX_AUTH_BSSES; i++) {
+ if (intbss != wdev->auth_bsses[i])
+ continue;
+ NLA_PUT_U32(msg, NL80211_BSS_STATUS,
+ NL80211_BSS_STATUS_AUTHENTICATED);
+ break;
+ }
+ break;
+ case NL80211_IFTYPE_ADHOC:
+ if (intbss == wdev->current_bss)
+ NLA_PUT_U32(msg, NL80211_BSS_STATUS,
+ NL80211_BSS_STATUS_IBSS_JOINED);
+ break;
+ default:
+ break;
+ }
+
nla_nest_end(msg, bss);
return genlmsg_end(msg, hdr);
@@ -2912,9 +3165,10 @@ static int nl80211_send_bss(struct sk_buff *msg, u32 pid, u32 seq, int flags,
static int nl80211_dump_scan(struct sk_buff *skb,
struct netlink_callback *cb)
{
- struct cfg80211_registered_device *dev;
- struct net_device *netdev;
+ struct cfg80211_registered_device *rdev;
+ struct net_device *dev;
struct cfg80211_internal_bss *scan;
+ struct wireless_dev *wdev;
int ifidx = cb->args[0];
int start = cb->args[1], idx = 0;
int err;
@@ -2935,58 +3189,83 @@ static int nl80211_dump_scan(struct sk_buff *skb,
cb->args[0] = ifidx;
}
- netdev = dev_get_by_index(&init_net, ifidx);
- if (!netdev)
+ dev = dev_get_by_index(sock_net(skb->sk), ifidx);
+ if (!dev)
return -ENODEV;
- dev = cfg80211_get_dev_from_ifindex(ifidx);
- if (IS_ERR(dev)) {
- err = PTR_ERR(dev);
+ rdev = cfg80211_get_dev_from_ifindex(sock_net(skb->sk), ifidx);
+ if (IS_ERR(rdev)) {
+ err = PTR_ERR(rdev);
goto out_put_netdev;
}
- spin_lock_bh(&dev->bss_lock);
- cfg80211_bss_expire(dev);
+ wdev = dev->ieee80211_ptr;
- list_for_each_entry(scan, &dev->bss_list, list) {
+ wdev_lock(wdev);
+ spin_lock_bh(&rdev->bss_lock);
+ cfg80211_bss_expire(rdev);
+
+ list_for_each_entry(scan, &rdev->bss_list, list) {
if (++idx <= start)
continue;
if (nl80211_send_bss(skb,
NETLINK_CB(cb->skb).pid,
cb->nlh->nlmsg_seq, NLM_F_MULTI,
- dev, netdev, &scan->pub) < 0) {
+ rdev, wdev, scan) < 0) {
idx--;
goto out;
}
}
out:
- spin_unlock_bh(&dev->bss_lock);
+ spin_unlock_bh(&rdev->bss_lock);
+ wdev_unlock(wdev);
cb->args[1] = idx;
err = skb->len;
- cfg80211_put_dev(dev);
+ cfg80211_unlock_rdev(rdev);
out_put_netdev:
- dev_put(netdev);
+ dev_put(dev);
return err;
}
static bool nl80211_valid_auth_type(enum nl80211_auth_type auth_type)
{
- return auth_type == NL80211_AUTHTYPE_OPEN_SYSTEM ||
- auth_type == NL80211_AUTHTYPE_SHARED_KEY ||
- auth_type == NL80211_AUTHTYPE_FT ||
- auth_type == NL80211_AUTHTYPE_NETWORK_EAP;
+ return auth_type <= NL80211_AUTHTYPE_MAX;
+}
+
+static bool nl80211_valid_wpa_versions(u32 wpa_versions)
+{
+ return !(wpa_versions & ~(NL80211_WPA_VERSION_1 |
+ NL80211_WPA_VERSION_2));
+}
+
+static bool nl80211_valid_akm_suite(u32 akm)
+{
+ return akm == WLAN_AKM_SUITE_8021X ||
+ akm == WLAN_AKM_SUITE_PSK;
}
+static bool nl80211_valid_cipher_suite(u32 cipher)
+{
+ return cipher == WLAN_CIPHER_SUITE_WEP40 ||
+ cipher == WLAN_CIPHER_SUITE_WEP104 ||
+ cipher == WLAN_CIPHER_SUITE_TKIP ||
+ cipher == WLAN_CIPHER_SUITE_CCMP ||
+ cipher == WLAN_CIPHER_SUITE_AES_CMAC;
+}
+
+
static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info)
{
- struct cfg80211_registered_device *drv;
+ struct cfg80211_registered_device *rdev;
struct net_device *dev;
- struct cfg80211_auth_request req;
- struct wiphy *wiphy;
- int err;
+ struct ieee80211_channel *chan;
+ const u8 *bssid, *ssid, *ie = NULL;
+ int err, ssid_len, ie_len = 0;
+ enum nl80211_auth_type auth_type;
+ struct key_parse key;
if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
return -EINVAL;
@@ -2997,13 +3276,38 @@ static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info)
if (!info->attrs[NL80211_ATTR_AUTH_TYPE])
return -EINVAL;
+ if (!info->attrs[NL80211_ATTR_SSID])
+ return -EINVAL;
+
+ if (!info->attrs[NL80211_ATTR_WIPHY_FREQ])
+ return -EINVAL;
+
+ err = nl80211_parse_key(info, &key);
+ if (err)
+ return err;
+
+ if (key.idx >= 0) {
+ if (!key.p.key || !key.p.key_len)
+ return -EINVAL;
+ if ((key.p.cipher != WLAN_CIPHER_SUITE_WEP40 ||
+ key.p.key_len != WLAN_KEY_LEN_WEP40) &&
+ (key.p.cipher != WLAN_CIPHER_SUITE_WEP104 ||
+ key.p.key_len != WLAN_KEY_LEN_WEP104))
+ return -EINVAL;
+ if (key.idx > 4)
+ return -EINVAL;
+ } else {
+ key.p.key_len = 0;
+ key.p.key = NULL;
+ }
+
rtnl_lock();
- err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
+ err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
if (err)
goto unlock_rtnl;
- if (!drv->ops->auth) {
+ if (!rdev->ops->auth) {
err = -EOPNOTSUPP;
goto out;
}
@@ -3018,69 +3322,130 @@ static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info)
goto out;
}
- wiphy = &drv->wiphy;
- memset(&req, 0, sizeof(req));
-
- req.peer_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
-
- if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) {
- req.chan = ieee80211_get_channel(
- wiphy,
- nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]));
- if (!req.chan) {
- err = -EINVAL;
- goto out;
- }
+ bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
+ chan = ieee80211_get_channel(&rdev->wiphy,
+ nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]));
+ if (!chan || (chan->flags & IEEE80211_CHAN_DISABLED)) {
+ err = -EINVAL;
+ goto out;
}
- if (info->attrs[NL80211_ATTR_SSID]) {
- req.ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
- req.ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]);
- }
+ ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
+ ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]);
if (info->attrs[NL80211_ATTR_IE]) {
- req.ie = nla_data(info->attrs[NL80211_ATTR_IE]);
- req.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
+ ie = nla_data(info->attrs[NL80211_ATTR_IE]);
+ ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
}
- req.auth_type = nla_get_u32(info->attrs[NL80211_ATTR_AUTH_TYPE]);
- if (!nl80211_valid_auth_type(req.auth_type)) {
+ auth_type = nla_get_u32(info->attrs[NL80211_ATTR_AUTH_TYPE]);
+ if (!nl80211_valid_auth_type(auth_type)) {
err = -EINVAL;
goto out;
}
- err = drv->ops->auth(&drv->wiphy, dev, &req);
+ err = cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid,
+ ssid, ssid_len, ie, ie_len,
+ key.p.key, key.p.key_len, key.idx);
out:
- cfg80211_put_dev(drv);
+ cfg80211_unlock_rdev(rdev);
dev_put(dev);
unlock_rtnl:
rtnl_unlock();
return err;
}
+static int nl80211_crypto_settings(struct genl_info *info,
+ struct cfg80211_crypto_settings *settings,
+ int cipher_limit)
+{
+ memset(settings, 0, sizeof(*settings));
+
+ settings->control_port = info->attrs[NL80211_ATTR_CONTROL_PORT];
+
+ if (info->attrs[NL80211_ATTR_CIPHER_SUITES_PAIRWISE]) {
+ void *data;
+ int len, i;
+
+ data = nla_data(info->attrs[NL80211_ATTR_CIPHER_SUITES_PAIRWISE]);
+ len = nla_len(info->attrs[NL80211_ATTR_CIPHER_SUITES_PAIRWISE]);
+ settings->n_ciphers_pairwise = len / sizeof(u32);
+
+ if (len % sizeof(u32))
+ return -EINVAL;
+
+ if (settings->n_ciphers_pairwise > cipher_limit)
+ return -EINVAL;
+
+ memcpy(settings->ciphers_pairwise, data, len);
+
+ for (i = 0; i < settings->n_ciphers_pairwise; i++)
+ if (!nl80211_valid_cipher_suite(
+ settings->ciphers_pairwise[i]))
+ return -EINVAL;
+ }
+
+ if (info->attrs[NL80211_ATTR_CIPHER_SUITE_GROUP]) {
+ settings->cipher_group =
+ nla_get_u32(info->attrs[NL80211_ATTR_CIPHER_SUITE_GROUP]);
+ if (!nl80211_valid_cipher_suite(settings->cipher_group))
+ return -EINVAL;
+ }
+
+ if (info->attrs[NL80211_ATTR_WPA_VERSIONS]) {
+ settings->wpa_versions =
+ nla_get_u32(info->attrs[NL80211_ATTR_WPA_VERSIONS]);
+ if (!nl80211_valid_wpa_versions(settings->wpa_versions))
+ return -EINVAL;
+ }
+
+ if (info->attrs[NL80211_ATTR_AKM_SUITES]) {
+ void *data;
+ int len, i;
+
+ data = nla_data(info->attrs[NL80211_ATTR_AKM_SUITES]);
+ len = nla_len(info->attrs[NL80211_ATTR_AKM_SUITES]);
+ settings->n_akm_suites = len / sizeof(u32);
+
+ if (len % sizeof(u32))
+ return -EINVAL;
+
+ memcpy(settings->akm_suites, data, len);
+
+ for (i = 0; i < settings->n_ciphers_pairwise; i++)
+ if (!nl80211_valid_akm_suite(settings->akm_suites[i]))
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
static int nl80211_associate(struct sk_buff *skb, struct genl_info *info)
{
- struct cfg80211_registered_device *drv;
+ struct cfg80211_registered_device *rdev;
struct net_device *dev;
- struct cfg80211_assoc_request req;
- struct wiphy *wiphy;
- int err;
+ struct cfg80211_crypto_settings crypto;
+ struct ieee80211_channel *chan, *fixedchan;
+ const u8 *bssid, *ssid, *ie = NULL, *prev_bssid = NULL;
+ int err, ssid_len, ie_len = 0;
+ bool use_mfp = false;
if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
return -EINVAL;
if (!info->attrs[NL80211_ATTR_MAC] ||
- !info->attrs[NL80211_ATTR_SSID])
+ !info->attrs[NL80211_ATTR_SSID] ||
+ !info->attrs[NL80211_ATTR_WIPHY_FREQ])
return -EINVAL;
rtnl_lock();
- err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
+ err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
if (err)
goto unlock_rtnl;
- if (!drv->ops->assoc) {
+ if (!rdev->ops->assoc) {
err = -EOPNOTSUPP;
goto out;
}
@@ -3095,46 +3460,54 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info)
goto out;
}
- wiphy = &drv->wiphy;
- memset(&req, 0, sizeof(req));
+ bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
- req.peer_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
+ chan = ieee80211_get_channel(&rdev->wiphy,
+ nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]));
+ if (!chan || (chan->flags & IEEE80211_CHAN_DISABLED)) {
+ err = -EINVAL;
+ goto out;
+ }
- if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) {
- req.chan = ieee80211_get_channel(
- wiphy,
- nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]));
- if (!req.chan) {
- err = -EINVAL;
- goto out;
- }
+ mutex_lock(&rdev->devlist_mtx);
+ fixedchan = rdev_fixed_channel(rdev, NULL);
+ if (fixedchan && chan != fixedchan) {
+ err = -EBUSY;
+ mutex_unlock(&rdev->devlist_mtx);
+ goto out;
}
+ mutex_unlock(&rdev->devlist_mtx);
- req.ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
- req.ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]);
+ ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
+ ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]);
if (info->attrs[NL80211_ATTR_IE]) {
- req.ie = nla_data(info->attrs[NL80211_ATTR_IE]);
- req.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
+ ie = nla_data(info->attrs[NL80211_ATTR_IE]);
+ ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
}
if (info->attrs[NL80211_ATTR_USE_MFP]) {
- enum nl80211_mfp use_mfp =
+ enum nl80211_mfp mfp =
nla_get_u32(info->attrs[NL80211_ATTR_USE_MFP]);
- if (use_mfp == NL80211_MFP_REQUIRED)
- req.use_mfp = true;
- else if (use_mfp != NL80211_MFP_NO) {
+ if (mfp == NL80211_MFP_REQUIRED)
+ use_mfp = true;
+ else if (mfp != NL80211_MFP_NO) {
err = -EINVAL;
goto out;
}
}
- req.control_port = info->attrs[NL80211_ATTR_CONTROL_PORT];
+ if (info->attrs[NL80211_ATTR_PREV_BSSID])
+ prev_bssid = nla_data(info->attrs[NL80211_ATTR_PREV_BSSID]);
- err = drv->ops->assoc(&drv->wiphy, dev, &req);
+ err = nl80211_crypto_settings(info, &crypto, 1);
+ if (!err)
+ err = cfg80211_mlme_assoc(rdev, dev, chan, bssid, prev_bssid,
+ ssid, ssid_len, ie, ie_len, use_mfp,
+ &crypto);
out:
- cfg80211_put_dev(drv);
+ cfg80211_unlock_rdev(rdev);
dev_put(dev);
unlock_rtnl:
rtnl_unlock();
@@ -3143,11 +3516,11 @@ unlock_rtnl:
static int nl80211_deauthenticate(struct sk_buff *skb, struct genl_info *info)
{
- struct cfg80211_registered_device *drv;
+ struct cfg80211_registered_device *rdev;
struct net_device *dev;
- struct cfg80211_deauth_request req;
- struct wiphy *wiphy;
- int err;
+ const u8 *ie = NULL, *bssid;
+ int err, ie_len = 0;
+ u16 reason_code;
if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
return -EINVAL;
@@ -3160,11 +3533,11 @@ static int nl80211_deauthenticate(struct sk_buff *skb, struct genl_info *info)
rtnl_lock();
- err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
+ err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
if (err)
goto unlock_rtnl;
- if (!drv->ops->deauth) {
+ if (!rdev->ops->deauth) {
err = -EOPNOTSUPP;
goto out;
}
@@ -3179,27 +3552,24 @@ static int nl80211_deauthenticate(struct sk_buff *skb, struct genl_info *info)
goto out;
}
- wiphy = &drv->wiphy;
- memset(&req, 0, sizeof(req));
-
- req.peer_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
+ bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
- req.reason_code = nla_get_u16(info->attrs[NL80211_ATTR_REASON_CODE]);
- if (req.reason_code == 0) {
+ reason_code = nla_get_u16(info->attrs[NL80211_ATTR_REASON_CODE]);
+ if (reason_code == 0) {
/* Reason Code 0 is reserved */
err = -EINVAL;
goto out;
}
if (info->attrs[NL80211_ATTR_IE]) {
- req.ie = nla_data(info->attrs[NL80211_ATTR_IE]);
- req.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
+ ie = nla_data(info->attrs[NL80211_ATTR_IE]);
+ ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
}
- err = drv->ops->deauth(&drv->wiphy, dev, &req);
+ err = cfg80211_mlme_deauth(rdev, dev, bssid, ie, ie_len, reason_code);
out:
- cfg80211_put_dev(drv);
+ cfg80211_unlock_rdev(rdev);
dev_put(dev);
unlock_rtnl:
rtnl_unlock();
@@ -3208,11 +3578,11 @@ unlock_rtnl:
static int nl80211_disassociate(struct sk_buff *skb, struct genl_info *info)
{
- struct cfg80211_registered_device *drv;
+ struct cfg80211_registered_device *rdev;
struct net_device *dev;
- struct cfg80211_disassoc_request req;
- struct wiphy *wiphy;
- int err;
+ const u8 *ie = NULL, *bssid;
+ int err, ie_len = 0;
+ u16 reason_code;
if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
return -EINVAL;
@@ -3225,11 +3595,11 @@ static int nl80211_disassociate(struct sk_buff *skb, struct genl_info *info)
rtnl_lock();
- err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
+ err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
if (err)
goto unlock_rtnl;
- if (!drv->ops->disassoc) {
+ if (!rdev->ops->disassoc) {
err = -EOPNOTSUPP;
goto out;
}
@@ -3244,27 +3614,24 @@ static int nl80211_disassociate(struct sk_buff *skb, struct genl_info *info)
goto out;
}
- wiphy = &drv->wiphy;
- memset(&req, 0, sizeof(req));
-
- req.peer_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
+ bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
- req.reason_code = nla_get_u16(info->attrs[NL80211_ATTR_REASON_CODE]);
- if (req.reason_code == 0) {
+ reason_code = nla_get_u16(info->attrs[NL80211_ATTR_REASON_CODE]);
+ if (reason_code == 0) {
/* Reason Code 0 is reserved */
err = -EINVAL;
goto out;
}
if (info->attrs[NL80211_ATTR_IE]) {
- req.ie = nla_data(info->attrs[NL80211_ATTR_IE]);
- req.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
+ ie = nla_data(info->attrs[NL80211_ATTR_IE]);
+ ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
}
- err = drv->ops->disassoc(&drv->wiphy, dev, &req);
+ err = cfg80211_mlme_disassoc(rdev, dev, bssid, ie, ie_len, reason_code);
out:
- cfg80211_put_dev(drv);
+ cfg80211_unlock_rdev(rdev);
dev_put(dev);
unlock_rtnl:
rtnl_unlock();
@@ -3273,10 +3640,11 @@ unlock_rtnl:
static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info)
{
- struct cfg80211_registered_device *drv;
+ struct cfg80211_registered_device *rdev;
struct net_device *dev;
struct cfg80211_ibss_params ibss;
struct wiphy *wiphy;
+ struct cfg80211_cached_keys *connkeys = NULL;
int err;
memset(&ibss, 0, sizeof(ibss));
@@ -3300,11 +3668,11 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info)
rtnl_lock();
- err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
+ err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
if (err)
goto unlock_rtnl;
- if (!drv->ops->join_ibss) {
+ if (!rdev->ops->join_ibss) {
err = -EOPNOTSUPP;
goto out;
}
@@ -3319,7 +3687,7 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info)
goto out;
}
- wiphy = &drv->wiphy;
+ wiphy = &rdev->wiphy;
if (info->attrs[NL80211_ATTR_MAC])
ibss.bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
@@ -3341,30 +3709,43 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info)
}
ibss.channel_fixed = !!info->attrs[NL80211_ATTR_FREQ_FIXED];
+ ibss.privacy = !!info->attrs[NL80211_ATTR_PRIVACY];
+
+ if (ibss.privacy && info->attrs[NL80211_ATTR_KEYS]) {
+ connkeys = nl80211_parse_connkeys(rdev,
+ info->attrs[NL80211_ATTR_KEYS]);
+ if (IS_ERR(connkeys)) {
+ err = PTR_ERR(connkeys);
+ connkeys = NULL;
+ goto out;
+ }
+ }
- err = cfg80211_join_ibss(drv, dev, &ibss);
+ err = cfg80211_join_ibss(rdev, dev, &ibss, connkeys);
out:
- cfg80211_put_dev(drv);
+ cfg80211_unlock_rdev(rdev);
dev_put(dev);
unlock_rtnl:
+ if (err)
+ kfree(connkeys);
rtnl_unlock();
return err;
}
static int nl80211_leave_ibss(struct sk_buff *skb, struct genl_info *info)
{
- struct cfg80211_registered_device *drv;
+ struct cfg80211_registered_device *rdev;
struct net_device *dev;
int err;
rtnl_lock();
- err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
+ err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
if (err)
goto unlock_rtnl;
- if (!drv->ops->leave_ibss) {
+ if (!rdev->ops->leave_ibss) {
err = -EOPNOTSUPP;
goto out;
}
@@ -3379,12 +3760,309 @@ static int nl80211_leave_ibss(struct sk_buff *skb, struct genl_info *info)
goto out;
}
- err = cfg80211_leave_ibss(drv, dev, false);
+ err = cfg80211_leave_ibss(rdev, dev, false);
+
+out:
+ cfg80211_unlock_rdev(rdev);
+ dev_put(dev);
+unlock_rtnl:
+ rtnl_unlock();
+ return err;
+}
+
+#ifdef CONFIG_NL80211_TESTMODE
+static struct genl_multicast_group nl80211_testmode_mcgrp = {
+ .name = "testmode",
+};
+
+static int nl80211_testmode_do(struct sk_buff *skb, struct genl_info *info)
+{
+ struct cfg80211_registered_device *rdev;
+ int err;
+
+ if (!info->attrs[NL80211_ATTR_TESTDATA])
+ return -EINVAL;
+
+ rtnl_lock();
+
+ rdev = cfg80211_get_dev_from_info(info);
+ if (IS_ERR(rdev)) {
+ err = PTR_ERR(rdev);
+ goto unlock_rtnl;
+ }
+
+ err = -EOPNOTSUPP;
+ if (rdev->ops->testmode_cmd) {
+ rdev->testmode_info = info;
+ err = rdev->ops->testmode_cmd(&rdev->wiphy,
+ nla_data(info->attrs[NL80211_ATTR_TESTDATA]),
+ nla_len(info->attrs[NL80211_ATTR_TESTDATA]));
+ rdev->testmode_info = NULL;
+ }
+
+ cfg80211_unlock_rdev(rdev);
+
+ unlock_rtnl:
+ rtnl_unlock();
+ return err;
+}
+
+static struct sk_buff *
+__cfg80211_testmode_alloc_skb(struct cfg80211_registered_device *rdev,
+ int approxlen, u32 pid, u32 seq, gfp_t gfp)
+{
+ struct sk_buff *skb;
+ void *hdr;
+ struct nlattr *data;
+
+ skb = nlmsg_new(approxlen + 100, gfp);
+ if (!skb)
+ return NULL;
+
+ hdr = nl80211hdr_put(skb, pid, seq, 0, NL80211_CMD_TESTMODE);
+ if (!hdr) {
+ kfree_skb(skb);
+ return NULL;
+ }
+
+ NLA_PUT_U32(skb, NL80211_ATTR_WIPHY, rdev->wiphy_idx);
+ data = nla_nest_start(skb, NL80211_ATTR_TESTDATA);
+
+ ((void **)skb->cb)[0] = rdev;
+ ((void **)skb->cb)[1] = hdr;
+ ((void **)skb->cb)[2] = data;
+
+ return skb;
+
+ nla_put_failure:
+ kfree_skb(skb);
+ return NULL;
+}
+
+struct sk_buff *cfg80211_testmode_alloc_reply_skb(struct wiphy *wiphy,
+ int approxlen)
+{
+ struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
+
+ if (WARN_ON(!rdev->testmode_info))
+ return NULL;
+
+ return __cfg80211_testmode_alloc_skb(rdev, approxlen,
+ rdev->testmode_info->snd_pid,
+ rdev->testmode_info->snd_seq,
+ GFP_KERNEL);
+}
+EXPORT_SYMBOL(cfg80211_testmode_alloc_reply_skb);
+
+int cfg80211_testmode_reply(struct sk_buff *skb)
+{
+ struct cfg80211_registered_device *rdev = ((void **)skb->cb)[0];
+ void *hdr = ((void **)skb->cb)[1];
+ struct nlattr *data = ((void **)skb->cb)[2];
+
+ if (WARN_ON(!rdev->testmode_info)) {
+ kfree_skb(skb);
+ return -EINVAL;
+ }
+
+ nla_nest_end(skb, data);
+ genlmsg_end(skb, hdr);
+ return genlmsg_reply(skb, rdev->testmode_info);
+}
+EXPORT_SYMBOL(cfg80211_testmode_reply);
+
+struct sk_buff *cfg80211_testmode_alloc_event_skb(struct wiphy *wiphy,
+ int approxlen, gfp_t gfp)
+{
+ struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
+
+ return __cfg80211_testmode_alloc_skb(rdev, approxlen, 0, 0, gfp);
+}
+EXPORT_SYMBOL(cfg80211_testmode_alloc_event_skb);
+
+void cfg80211_testmode_event(struct sk_buff *skb, gfp_t gfp)
+{
+ void *hdr = ((void **)skb->cb)[1];
+ struct nlattr *data = ((void **)skb->cb)[2];
+
+ nla_nest_end(skb, data);
+ genlmsg_end(skb, hdr);
+ genlmsg_multicast(skb, 0, nl80211_testmode_mcgrp.id, gfp);
+}
+EXPORT_SYMBOL(cfg80211_testmode_event);
+#endif
+
+static int nl80211_connect(struct sk_buff *skb, struct genl_info *info)
+{
+ struct cfg80211_registered_device *rdev;
+ struct net_device *dev;
+ struct cfg80211_connect_params connect;
+ struct wiphy *wiphy;
+ struct cfg80211_cached_keys *connkeys = NULL;
+ int err;
+
+ memset(&connect, 0, sizeof(connect));
+
+ if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
+ return -EINVAL;
+
+ if (!info->attrs[NL80211_ATTR_SSID] ||
+ !nla_len(info->attrs[NL80211_ATTR_SSID]))
+ return -EINVAL;
+
+ if (info->attrs[NL80211_ATTR_AUTH_TYPE]) {
+ connect.auth_type =
+ nla_get_u32(info->attrs[NL80211_ATTR_AUTH_TYPE]);
+ if (!nl80211_valid_auth_type(connect.auth_type))
+ return -EINVAL;
+ } else
+ connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC;
+
+ connect.privacy = info->attrs[NL80211_ATTR_PRIVACY];
+
+ err = nl80211_crypto_settings(info, &connect.crypto,
+ NL80211_MAX_NR_CIPHER_SUITES);
+ if (err)
+ return err;
+ rtnl_lock();
+
+ err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
+ if (err)
+ goto unlock_rtnl;
+
+ if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION) {
+ err = -EOPNOTSUPP;
+ goto out;
+ }
+
+ if (!netif_running(dev)) {
+ err = -ENETDOWN;
+ goto out;
+ }
+
+ wiphy = &rdev->wiphy;
+
+ if (info->attrs[NL80211_ATTR_MAC])
+ connect.bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
+ connect.ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
+ connect.ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]);
+
+ if (info->attrs[NL80211_ATTR_IE]) {
+ connect.ie = nla_data(info->attrs[NL80211_ATTR_IE]);
+ connect.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
+ }
+
+ if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) {
+ connect.channel =
+ ieee80211_get_channel(wiphy,
+ nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]));
+ if (!connect.channel ||
+ connect.channel->flags & IEEE80211_CHAN_DISABLED) {
+ err = -EINVAL;
+ goto out;
+ }
+ }
+
+ if (connect.privacy && info->attrs[NL80211_ATTR_KEYS]) {
+ connkeys = nl80211_parse_connkeys(rdev,
+ info->attrs[NL80211_ATTR_KEYS]);
+ if (IS_ERR(connkeys)) {
+ err = PTR_ERR(connkeys);
+ connkeys = NULL;
+ goto out;
+ }
+ }
+
+ err = cfg80211_connect(rdev, dev, &connect, connkeys);
out:
- cfg80211_put_dev(drv);
+ cfg80211_unlock_rdev(rdev);
dev_put(dev);
unlock_rtnl:
+ if (err)
+ kfree(connkeys);
+ rtnl_unlock();
+ return err;
+}
+
+static int nl80211_disconnect(struct sk_buff *skb, struct genl_info *info)
+{
+ struct cfg80211_registered_device *rdev;
+ struct net_device *dev;
+ int err;
+ u16 reason;
+
+ if (!info->attrs[NL80211_ATTR_REASON_CODE])
+ reason = WLAN_REASON_DEAUTH_LEAVING;
+ else
+ reason = nla_get_u16(info->attrs[NL80211_ATTR_REASON_CODE]);
+
+ if (reason == 0)
+ return -EINVAL;
+
+ rtnl_lock();
+
+ err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
+ if (err)
+ goto unlock_rtnl;
+
+ if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION) {
+ err = -EOPNOTSUPP;
+ goto out;
+ }
+
+ if (!netif_running(dev)) {
+ err = -ENETDOWN;
+ goto out;
+ }
+
+ err = cfg80211_disconnect(rdev, dev, reason, true);
+
+out:
+ cfg80211_unlock_rdev(rdev);
+ dev_put(dev);
+unlock_rtnl:
+ rtnl_unlock();
+ return err;
+}
+
+static int nl80211_wiphy_netns(struct sk_buff *skb, struct genl_info *info)
+{
+ struct cfg80211_registered_device *rdev;
+ struct net *net;
+ int err;
+ u32 pid;
+
+ if (!info->attrs[NL80211_ATTR_PID])
+ return -EINVAL;
+
+ pid = nla_get_u32(info->attrs[NL80211_ATTR_PID]);
+
+ rtnl_lock();
+
+ rdev = cfg80211_get_dev_from_info(info);
+ if (IS_ERR(rdev)) {
+ err = PTR_ERR(rdev);
+ goto out;
+ }
+
+ net = get_net_ns_by_pid(pid);
+ if (IS_ERR(net)) {
+ err = PTR_ERR(net);
+ goto out;
+ }
+
+ err = 0;
+
+ /* check if anything to do */
+ if (net_eq(wiphy_net(&rdev->wiphy), net))
+ goto out_put_net;
+
+ err = cfg80211_switch_netns(rdev, net);
+ out_put_net:
+ put_net(net);
+ out:
+ cfg80211_unlock_rdev(rdev);
rtnl_unlock();
return err;
}
@@ -3602,6 +4280,32 @@ static struct genl_ops nl80211_ops[] = {
.policy = nl80211_policy,
.flags = GENL_ADMIN_PERM,
},
+#ifdef CONFIG_NL80211_TESTMODE
+ {
+ .cmd = NL80211_CMD_TESTMODE,
+ .doit = nl80211_testmode_do,
+ .policy = nl80211_policy,
+ .flags = GENL_ADMIN_PERM,
+ },
+#endif
+ {
+ .cmd = NL80211_CMD_CONNECT,
+ .doit = nl80211_connect,
+ .policy = nl80211_policy,
+ .flags = GENL_ADMIN_PERM,
+ },
+ {
+ .cmd = NL80211_CMD_DISCONNECT,
+ .doit = nl80211_disconnect,
+ .policy = nl80211_policy,
+ .flags = GENL_ADMIN_PERM,
+ },
+ {
+ .cmd = NL80211_CMD_SET_WIPHY_NETNS,
+ .doit = nl80211_wiphy_netns,
+ .policy = nl80211_policy,
+ .flags = GENL_ADMIN_PERM,
+ },
};
static struct genl_multicast_group nl80211_mlme_mcgrp = {
.name = "mlme",
@@ -3633,7 +4337,8 @@ void nl80211_notify_dev_rename(struct cfg80211_registered_device *rdev)
return;
}
- genlmsg_multicast(msg, 0, nl80211_config_mcgrp.id, GFP_KERNEL);
+ genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
+ nl80211_config_mcgrp.id, GFP_KERNEL);
}
static int nl80211_add_scan_req(struct sk_buff *msg,
@@ -3643,6 +4348,8 @@ static int nl80211_add_scan_req(struct sk_buff *msg,
struct nlattr *nest;
int i;
+ ASSERT_RDEV_LOCK(rdev);
+
if (WARN_ON(!req))
return 0;
@@ -3668,11 +4375,11 @@ static int nl80211_add_scan_req(struct sk_buff *msg,
return -ENOBUFS;
}
-static int nl80211_send_scan_donemsg(struct sk_buff *msg,
- struct cfg80211_registered_device *rdev,
- struct net_device *netdev,
- u32 pid, u32 seq, int flags,
- u32 cmd)
+static int nl80211_send_scan_msg(struct sk_buff *msg,
+ struct cfg80211_registered_device *rdev,
+ struct net_device *netdev,
+ u32 pid, u32 seq, int flags,
+ u32 cmd)
{
void *hdr;
@@ -3693,6 +4400,25 @@ static int nl80211_send_scan_donemsg(struct sk_buff *msg,
return -EMSGSIZE;
}
+void nl80211_send_scan_start(struct cfg80211_registered_device *rdev,
+ struct net_device *netdev)
+{
+ struct sk_buff *msg;
+
+ msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
+ if (!msg)
+ return;
+
+ if (nl80211_send_scan_msg(msg, rdev, netdev, 0, 0, 0,
+ NL80211_CMD_TRIGGER_SCAN) < 0) {
+ nlmsg_free(msg);
+ return;
+ }
+
+ genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
+ nl80211_scan_mcgrp.id, GFP_KERNEL);
+}
+
void nl80211_send_scan_done(struct cfg80211_registered_device *rdev,
struct net_device *netdev)
{
@@ -3702,13 +4428,14 @@ void nl80211_send_scan_done(struct cfg80211_registered_device *rdev,
if (!msg)
return;
- if (nl80211_send_scan_donemsg(msg, rdev, netdev, 0, 0, 0,
- NL80211_CMD_NEW_SCAN_RESULTS) < 0) {
+ if (nl80211_send_scan_msg(msg, rdev, netdev, 0, 0, 0,
+ NL80211_CMD_NEW_SCAN_RESULTS) < 0) {
nlmsg_free(msg);
return;
}
- genlmsg_multicast(msg, 0, nl80211_scan_mcgrp.id, GFP_KERNEL);
+ genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
+ nl80211_scan_mcgrp.id, GFP_KERNEL);
}
void nl80211_send_scan_aborted(struct cfg80211_registered_device *rdev,
@@ -3720,13 +4447,14 @@ void nl80211_send_scan_aborted(struct cfg80211_registered_device *rdev,
if (!msg)
return;
- if (nl80211_send_scan_donemsg(msg, rdev, netdev, 0, 0, 0,
- NL80211_CMD_SCAN_ABORTED) < 0) {
+ if (nl80211_send_scan_msg(msg, rdev, netdev, 0, 0, 0,
+ NL80211_CMD_SCAN_ABORTED) < 0) {
nlmsg_free(msg);
return;
}
- genlmsg_multicast(msg, 0, nl80211_scan_mcgrp.id, GFP_KERNEL);
+ genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
+ nl80211_scan_mcgrp.id, GFP_KERNEL);
}
/*
@@ -3775,7 +4503,10 @@ void nl80211_send_reg_change_event(struct regulatory_request *request)
return;
}
- genlmsg_multicast(msg, 0, nl80211_regulatory_mcgrp.id, GFP_KERNEL);
+ rcu_read_lock();
+ genlmsg_multicast_allns(msg, 0, nl80211_regulatory_mcgrp.id,
+ GFP_ATOMIC);
+ rcu_read_unlock();
return;
@@ -3787,12 +4518,12 @@ nla_put_failure:
static void nl80211_send_mlme_event(struct cfg80211_registered_device *rdev,
struct net_device *netdev,
const u8 *buf, size_t len,
- enum nl80211_commands cmd)
+ enum nl80211_commands cmd, gfp_t gfp)
{
struct sk_buff *msg;
void *hdr;
- msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
+ msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
if (!msg)
return;
@@ -3811,7 +4542,8 @@ static void nl80211_send_mlme_event(struct cfg80211_registered_device *rdev,
return;
}
- genlmsg_multicast(msg, 0, nl80211_mlme_mcgrp.id, GFP_ATOMIC);
+ genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
+ nl80211_mlme_mcgrp.id, gfp);
return;
nla_put_failure:
@@ -3820,42 +4552,45 @@ static void nl80211_send_mlme_event(struct cfg80211_registered_device *rdev,
}
void nl80211_send_rx_auth(struct cfg80211_registered_device *rdev,
- struct net_device *netdev, const u8 *buf, size_t len)
+ struct net_device *netdev, const u8 *buf,
+ size_t len, gfp_t gfp)
{
nl80211_send_mlme_event(rdev, netdev, buf, len,
- NL80211_CMD_AUTHENTICATE);
+ NL80211_CMD_AUTHENTICATE, gfp);
}
void nl80211_send_rx_assoc(struct cfg80211_registered_device *rdev,
struct net_device *netdev, const u8 *buf,
- size_t len)
+ size_t len, gfp_t gfp)
{
- nl80211_send_mlme_event(rdev, netdev, buf, len, NL80211_CMD_ASSOCIATE);
+ nl80211_send_mlme_event(rdev, netdev, buf, len,
+ NL80211_CMD_ASSOCIATE, gfp);
}
void nl80211_send_deauth(struct cfg80211_registered_device *rdev,
- struct net_device *netdev, const u8 *buf, size_t len)
+ struct net_device *netdev, const u8 *buf,
+ size_t len, gfp_t gfp)
{
nl80211_send_mlme_event(rdev, netdev, buf, len,
- NL80211_CMD_DEAUTHENTICATE);
+ NL80211_CMD_DEAUTHENTICATE, gfp);
}
void nl80211_send_disassoc(struct cfg80211_registered_device *rdev,
struct net_device *netdev, const u8 *buf,
- size_t len)
+ size_t len, gfp_t gfp)
{
nl80211_send_mlme_event(rdev, netdev, buf, len,
- NL80211_CMD_DISASSOCIATE);
+ NL80211_CMD_DISASSOCIATE, gfp);
}
static void nl80211_send_mlme_timeout(struct cfg80211_registered_device *rdev,
struct net_device *netdev, int cmd,
- const u8 *addr)
+ const u8 *addr, gfp_t gfp)
{
struct sk_buff *msg;
void *hdr;
- msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
+ msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
if (!msg)
return;
@@ -3875,7 +4610,8 @@ static void nl80211_send_mlme_timeout(struct cfg80211_registered_device *rdev,
return;
}
- genlmsg_multicast(msg, 0, nl80211_mlme_mcgrp.id, GFP_ATOMIC);
+ genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
+ nl80211_mlme_mcgrp.id, gfp);
return;
nla_put_failure:
@@ -3884,16 +4620,145 @@ static void nl80211_send_mlme_timeout(struct cfg80211_registered_device *rdev,
}
void nl80211_send_auth_timeout(struct cfg80211_registered_device *rdev,
- struct net_device *netdev, const u8 *addr)
+ struct net_device *netdev, const u8 *addr,
+ gfp_t gfp)
{
nl80211_send_mlme_timeout(rdev, netdev, NL80211_CMD_AUTHENTICATE,
- addr);
+ addr, gfp);
}
void nl80211_send_assoc_timeout(struct cfg80211_registered_device *rdev,
- struct net_device *netdev, const u8 *addr)
+ struct net_device *netdev, const u8 *addr,
+ gfp_t gfp)
{
- nl80211_send_mlme_timeout(rdev, netdev, NL80211_CMD_ASSOCIATE, addr);
+ nl80211_send_mlme_timeout(rdev, netdev, NL80211_CMD_ASSOCIATE,
+ addr, gfp);
+}
+
+void nl80211_send_connect_result(struct cfg80211_registered_device *rdev,
+ struct net_device *netdev, const u8 *bssid,
+ const u8 *req_ie, size_t req_ie_len,
+ const u8 *resp_ie, size_t resp_ie_len,
+ u16 status, gfp_t gfp)
+{
+ struct sk_buff *msg;
+ void *hdr;
+
+ msg = nlmsg_new(NLMSG_GOODSIZE, gfp);
+ if (!msg)
+ return;
+
+ hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_CONNECT);
+ if (!hdr) {
+ nlmsg_free(msg);
+ return;
+ }
+
+ NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx);
+ NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex);
+ if (bssid)
+ NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, bssid);
+ NLA_PUT_U16(msg, NL80211_ATTR_STATUS_CODE, status);
+ if (req_ie)
+ NLA_PUT(msg, NL80211_ATTR_REQ_IE, req_ie_len, req_ie);
+ if (resp_ie)
+ NLA_PUT(msg, NL80211_ATTR_RESP_IE, resp_ie_len, resp_ie);
+
+ if (genlmsg_end(msg, hdr) < 0) {
+ nlmsg_free(msg);
+ return;
+ }
+
+ genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
+ nl80211_mlme_mcgrp.id, gfp);
+ return;
+
+ nla_put_failure:
+ genlmsg_cancel(msg, hdr);
+ nlmsg_free(msg);
+
+}
+
+void nl80211_send_roamed(struct cfg80211_registered_device *rdev,
+ struct net_device *netdev, const u8 *bssid,
+ const u8 *req_ie, size_t req_ie_len,
+ const u8 *resp_ie, size_t resp_ie_len, gfp_t gfp)
+{
+ struct sk_buff *msg;
+ void *hdr;
+
+ msg = nlmsg_new(NLMSG_GOODSIZE, gfp);
+ if (!msg)
+ return;
+
+ hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_ROAM);
+ if (!hdr) {
+ nlmsg_free(msg);
+ return;
+ }
+
+ NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx);
+ NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex);
+ NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, bssid);
+ if (req_ie)
+ NLA_PUT(msg, NL80211_ATTR_REQ_IE, req_ie_len, req_ie);
+ if (resp_ie)
+ NLA_PUT(msg, NL80211_ATTR_RESP_IE, resp_ie_len, resp_ie);
+
+ if (genlmsg_end(msg, hdr) < 0) {
+ nlmsg_free(msg);
+ return;
+ }
+
+ genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
+ nl80211_mlme_mcgrp.id, gfp);
+ return;
+
+ nla_put_failure:
+ genlmsg_cancel(msg, hdr);
+ nlmsg_free(msg);
+
+}
+
+void nl80211_send_disconnected(struct cfg80211_registered_device *rdev,
+ struct net_device *netdev, u16 reason,
+ const u8 *ie, size_t ie_len, bool from_ap)
+{
+ struct sk_buff *msg;
+ void *hdr;
+
+ msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
+ if (!msg)
+ return;
+
+ hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_DISCONNECT);
+ if (!hdr) {
+ nlmsg_free(msg);
+ return;
+ }
+
+ NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx);
+ NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex);
+ if (from_ap && reason)
+ NLA_PUT_U16(msg, NL80211_ATTR_REASON_CODE, reason);
+ if (from_ap)
+ NLA_PUT_FLAG(msg, NL80211_ATTR_DISCONNECTED_BY_AP);
+ if (ie)
+ NLA_PUT(msg, NL80211_ATTR_IE, ie_len, ie);
+
+ if (genlmsg_end(msg, hdr) < 0) {
+ nlmsg_free(msg);
+ return;
+ }
+
+ genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
+ nl80211_mlme_mcgrp.id, GFP_KERNEL);
+ return;
+
+ nla_put_failure:
+ genlmsg_cancel(msg, hdr);
+ nlmsg_free(msg);
+
}
void nl80211_send_ibss_bssid(struct cfg80211_registered_device *rdev,
@@ -3922,7 +4787,8 @@ void nl80211_send_ibss_bssid(struct cfg80211_registered_device *rdev,
return;
}
- genlmsg_multicast(msg, 0, nl80211_mlme_mcgrp.id, gfp);
+ genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
+ nl80211_mlme_mcgrp.id, gfp);
return;
nla_put_failure:
@@ -3933,12 +4799,12 @@ void nl80211_send_ibss_bssid(struct cfg80211_registered_device *rdev,
void nl80211_michael_mic_failure(struct cfg80211_registered_device *rdev,
struct net_device *netdev, const u8 *addr,
enum nl80211_key_type key_type, int key_id,
- const u8 *tsc)
+ const u8 *tsc, gfp_t gfp)
{
struct sk_buff *msg;
void *hdr;
- msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
+ msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
if (!msg)
return;
@@ -3962,7 +4828,8 @@ void nl80211_michael_mic_failure(struct cfg80211_registered_device *rdev,
return;
}
- genlmsg_multicast(msg, 0, nl80211_mlme_mcgrp.id, GFP_ATOMIC);
+ genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
+ nl80211_mlme_mcgrp.id, gfp);
return;
nla_put_failure:
@@ -4015,7 +4882,10 @@ void nl80211_send_beacon_hint_event(struct wiphy *wiphy,
return;
}
- genlmsg_multicast(msg, 0, nl80211_regulatory_mcgrp.id, GFP_ATOMIC);
+ rcu_read_lock();
+ genlmsg_multicast_allns(msg, 0, nl80211_regulatory_mcgrp.id,
+ GFP_ATOMIC);
+ rcu_read_unlock();
return;
@@ -4051,6 +4921,12 @@ int nl80211_init(void)
if (err)
goto err_out;
+#ifdef CONFIG_NL80211_TESTMODE
+ err = genl_register_mc_group(&nl80211_fam, &nl80211_testmode_mcgrp);
+ if (err)
+ goto err_out;
+#endif
+
return 0;
err_out:
genl_unregister_family(&nl80211_fam);
diff --git a/net/wireless/nl80211.h b/net/wireless/nl80211.h
index 5c12ad13499..44cc2a76a1b 100644
--- a/net/wireless/nl80211.h
+++ b/net/wireless/nl80211.h
@@ -3,39 +3,54 @@
#include "core.h"
-extern int nl80211_init(void);
-extern void nl80211_exit(void);
-extern void nl80211_notify_dev_rename(struct cfg80211_registered_device *rdev);
-extern void nl80211_send_scan_done(struct cfg80211_registered_device *rdev,
- struct net_device *netdev);
-extern void nl80211_send_scan_aborted(struct cfg80211_registered_device *rdev,
- struct net_device *netdev);
-extern void nl80211_send_reg_change_event(struct regulatory_request *request);
-extern void nl80211_send_rx_auth(struct cfg80211_registered_device *rdev,
- struct net_device *netdev,
- const u8 *buf, size_t len);
-extern void nl80211_send_rx_assoc(struct cfg80211_registered_device *rdev,
- struct net_device *netdev,
- const u8 *buf, size_t len);
-extern void nl80211_send_deauth(struct cfg80211_registered_device *rdev,
+int nl80211_init(void);
+void nl80211_exit(void);
+void nl80211_notify_dev_rename(struct cfg80211_registered_device *rdev);
+void nl80211_send_scan_start(struct cfg80211_registered_device *rdev,
+ struct net_device *netdev);
+void nl80211_send_scan_done(struct cfg80211_registered_device *rdev,
+ struct net_device *netdev);
+void nl80211_send_scan_aborted(struct cfg80211_registered_device *rdev,
+ struct net_device *netdev);
+void nl80211_send_reg_change_event(struct regulatory_request *request);
+void nl80211_send_rx_auth(struct cfg80211_registered_device *rdev,
+ struct net_device *netdev,
+ const u8 *buf, size_t len, gfp_t gfp);
+void nl80211_send_rx_assoc(struct cfg80211_registered_device *rdev,
+ struct net_device *netdev,
+ const u8 *buf, size_t len, gfp_t gfp);
+void nl80211_send_deauth(struct cfg80211_registered_device *rdev,
+ struct net_device *netdev,
+ const u8 *buf, size_t len, gfp_t gfp);
+void nl80211_send_disassoc(struct cfg80211_registered_device *rdev,
+ struct net_device *netdev,
+ const u8 *buf, size_t len, gfp_t gfp);
+void nl80211_send_auth_timeout(struct cfg80211_registered_device *rdev,
+ struct net_device *netdev,
+ const u8 *addr, gfp_t gfp);
+void nl80211_send_assoc_timeout(struct cfg80211_registered_device *rdev,
struct net_device *netdev,
- const u8 *buf, size_t len);
-extern void nl80211_send_disassoc(struct cfg80211_registered_device *rdev,
- struct net_device *netdev,
- const u8 *buf, size_t len);
-extern void nl80211_send_auth_timeout(struct cfg80211_registered_device *rdev,
- struct net_device *netdev,
- const u8 *addr);
-extern void nl80211_send_assoc_timeout(struct cfg80211_registered_device *rdev,
- struct net_device *netdev,
- const u8 *addr);
-extern void
+ const u8 *addr, gfp_t gfp);
+void nl80211_send_connect_result(struct cfg80211_registered_device *rdev,
+ struct net_device *netdev, const u8 *bssid,
+ const u8 *req_ie, size_t req_ie_len,
+ const u8 *resp_ie, size_t resp_ie_len,
+ u16 status, gfp_t gfp);
+void nl80211_send_roamed(struct cfg80211_registered_device *rdev,
+ struct net_device *netdev, const u8 *bssid,
+ const u8 *req_ie, size_t req_ie_len,
+ const u8 *resp_ie, size_t resp_ie_len, gfp_t gfp);
+void nl80211_send_disconnected(struct cfg80211_registered_device *rdev,
+ struct net_device *netdev, u16 reason,
+ const u8 *ie, size_t ie_len, bool from_ap);
+
+void
nl80211_michael_mic_failure(struct cfg80211_registered_device *rdev,
struct net_device *netdev, const u8 *addr,
enum nl80211_key_type key_type,
- int key_id, const u8 *tsc);
+ int key_id, const u8 *tsc, gfp_t gfp);
-extern void
+void
nl80211_send_beacon_hint_event(struct wiphy *wiphy,
struct ieee80211_channel *channel_before,
struct ieee80211_channel *channel_after);
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 75a406d3361..f256dfffbf4 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -62,6 +62,16 @@ const struct ieee80211_regdomain *cfg80211_regdomain;
*/
static const struct ieee80211_regdomain *country_ie_regdomain;
+/*
+ * Protects static reg.c components:
+ * - cfg80211_world_regdom
+ * - cfg80211_regdom
+ * - country_ie_regdomain
+ * - last_request
+ */
+DEFINE_MUTEX(reg_mutex);
+#define assert_reg_lock() WARN_ON(!mutex_is_locked(&reg_mutex))
+
/* Used to queue up regulatory hints */
static LIST_HEAD(reg_requests_list);
static spinlock_t reg_requests_lock;
@@ -113,11 +123,7 @@ static const struct ieee80211_regdomain world_regdom = {
static const struct ieee80211_regdomain *cfg80211_world_regdom =
&world_regdom;
-#ifdef CONFIG_WIRELESS_OLD_REGULATORY
-static char *ieee80211_regdom = "US";
-#else
static char *ieee80211_regdom = "00";
-#endif
module_param(ieee80211_regdom, charp, 0444);
MODULE_PARM_DESC(ieee80211_regdom, "IEEE 802.11 regulatory domain code");
@@ -1012,7 +1018,6 @@ static void handle_channel(struct wiphy *wiphy, enum ieee80211_band band,
map_regdom_flags(reg_rule->flags) | bw_flags;
chan->max_antenna_gain = chan->orig_mag =
(int) MBI_TO_DBI(power_rule->max_antenna_gain);
- chan->max_bandwidth = KHZ_TO_MHZ(desired_bw_khz);
chan->max_power = chan->orig_mpwr =
(int) MBM_TO_DBM(power_rule->max_eirp);
return;
@@ -1021,7 +1026,6 @@ static void handle_channel(struct wiphy *wiphy, enum ieee80211_band band,
chan->flags = flags | bw_flags | map_regdom_flags(reg_rule->flags);
chan->max_antenna_gain = min(chan->orig_mag,
(int) MBI_TO_DBI(power_rule->max_antenna_gain));
- chan->max_bandwidth = KHZ_TO_MHZ(desired_bw_khz);
if (chan->orig_mpwr)
chan->max_power = min(chan->orig_mpwr,
(int) MBM_TO_DBM(power_rule->max_eirp));
@@ -1061,10 +1065,10 @@ static bool ignore_reg_update(struct wiphy *wiphy,
static void update_all_wiphy_regulatory(enum nl80211_reg_initiator initiator)
{
- struct cfg80211_registered_device *drv;
+ struct cfg80211_registered_device *rdev;
- list_for_each_entry(drv, &cfg80211_drv_list, list)
- wiphy_update_regulatory(&drv->wiphy, initiator);
+ list_for_each_entry(rdev, &cfg80211_rdev_list, list)
+ wiphy_update_regulatory(&rdev->wiphy, initiator);
}
static void handle_reg_beacon(struct wiphy *wiphy,
@@ -1298,7 +1302,7 @@ static void handle_channel_custom(struct wiphy *wiphy,
struct ieee80211_supported_band *sband;
struct ieee80211_channel *chan;
- assert_cfg80211_lock();
+ assert_reg_lock();
sband = wiphy->bands[band];
BUG_ON(chan_idx >= sband->n_channels);
@@ -1323,7 +1327,6 @@ static void handle_channel_custom(struct wiphy *wiphy,
chan->flags |= map_regdom_flags(reg_rule->flags) | bw_flags;
chan->max_antenna_gain = (int) MBI_TO_DBI(power_rule->max_antenna_gain);
- chan->max_bandwidth = KHZ_TO_MHZ(desired_bw_khz);
chan->max_power = (int) MBM_TO_DBM(power_rule->max_eirp);
}
@@ -1347,14 +1350,14 @@ void wiphy_apply_custom_regulatory(struct wiphy *wiphy,
enum ieee80211_band band;
unsigned int bands_set = 0;
- mutex_lock(&cfg80211_mutex);
+ mutex_lock(&reg_mutex);
for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
if (!wiphy->bands[band])
continue;
handle_band_custom(wiphy, band, regd);
bands_set++;
}
- mutex_unlock(&cfg80211_mutex);
+ mutex_unlock(&reg_mutex);
/*
* no point in calling this if it won't have any effect
@@ -1421,7 +1424,7 @@ static int ignore_request(struct wiphy *wiphy,
if (last_wiphy != wiphy) {
/*
* Two cards with two APs claiming different
- * different Country IE alpha2s. We could
+ * Country IE alpha2s. We could
* intersect them, but that seems unlikely
* to be correct. Reject second one for now.
*/
@@ -1500,7 +1503,7 @@ static int ignore_request(struct wiphy *wiphy,
* Returns zero if all went fine, %-EALREADY if a regulatory domain had
* already been set or other standard error codes.
*
- * Caller must hold &cfg80211_mutex
+ * Caller must hold &cfg80211_mutex and &reg_mutex
*/
static int __regulatory_hint(struct wiphy *wiphy,
struct regulatory_request *pending_request)
@@ -1575,6 +1578,7 @@ static void reg_process_hint(struct regulatory_request *reg_request)
BUG_ON(!reg_request->alpha2);
mutex_lock(&cfg80211_mutex);
+ mutex_lock(&reg_mutex);
if (wiphy_idx_valid(reg_request->wiphy_idx))
wiphy = wiphy_idx_to_wiphy(reg_request->wiphy_idx);
@@ -1590,6 +1594,7 @@ static void reg_process_hint(struct regulatory_request *reg_request)
if (r == -EALREADY && wiphy && wiphy->strict_regulatory)
wiphy_update_regulatory(wiphy, reg_request->initiator);
out:
+ mutex_unlock(&reg_mutex);
mutex_unlock(&cfg80211_mutex);
}
@@ -1615,9 +1620,13 @@ static void reg_process_pending_hints(void)
/* Processes beacon hints -- this has nothing to do with country IEs */
static void reg_process_pending_beacon_hints(void)
{
- struct cfg80211_registered_device *drv;
+ struct cfg80211_registered_device *rdev;
struct reg_beacon *pending_beacon, *tmp;
+ /*
+ * No need to hold the reg_mutex here as we just touch wiphys
+ * and do not read or access regulatory variables.
+ */
mutex_lock(&cfg80211_mutex);
/* This goes through the _pending_ beacon list */
@@ -1634,8 +1643,8 @@ static void reg_process_pending_beacon_hints(void)
list_del_init(&pending_beacon->list);
/* Applies the beacon hint to current wiphys */
- list_for_each_entry(drv, &cfg80211_drv_list, list)
- wiphy_update_new_beacon(&drv->wiphy, pending_beacon);
+ list_for_each_entry(rdev, &cfg80211_rdev_list, list)
+ wiphy_update_new_beacon(&rdev->wiphy, pending_beacon);
/* Remembers the beacon hint for new wiphys or reg changes */
list_add_tail(&pending_beacon->list, &reg_beacon_list);
@@ -1739,12 +1748,13 @@ int regulatory_hint(struct wiphy *wiphy, const char *alpha2)
}
EXPORT_SYMBOL(regulatory_hint);
+/* Caller must hold reg_mutex */
static bool reg_same_country_ie_hint(struct wiphy *wiphy,
u32 country_ie_checksum)
{
struct wiphy *request_wiphy;
- assert_cfg80211_lock();
+ assert_reg_lock();
if (unlikely(last_request->initiator !=
NL80211_REGDOM_SET_BY_COUNTRY_IE))
@@ -1767,6 +1777,10 @@ static bool reg_same_country_ie_hint(struct wiphy *wiphy,
return false;
}
+/*
+ * We hold wdev_lock() here so we cannot hold cfg80211_mutex() and
+ * therefore cannot iterate over the rdev list here.
+ */
void regulatory_hint_11d(struct wiphy *wiphy,
u8 *country_ie,
u8 country_ie_len)
@@ -1777,12 +1791,10 @@ void regulatory_hint_11d(struct wiphy *wiphy,
enum environment_cap env = ENVIRON_ANY;
struct regulatory_request *request;
- mutex_lock(&cfg80211_mutex);
+ mutex_lock(&reg_mutex);
- if (unlikely(!last_request)) {
- mutex_unlock(&cfg80211_mutex);
- return;
- }
+ if (unlikely(!last_request))
+ goto out;
/* IE len must be evenly divisible by 2 */
if (country_ie_len & 0x01)
@@ -1808,54 +1820,14 @@ void regulatory_hint_11d(struct wiphy *wiphy,
env = ENVIRON_OUTDOOR;
/*
- * We will run this for *every* beacon processed for the BSSID, so
- * we optimize an early check to exit out early if we don't have to
- * do anything
+ * We will run this only upon a successful connection on cfg80211.
+ * We leave conflict resolution to the workqueue, where can hold
+ * cfg80211_mutex.
*/
if (likely(last_request->initiator ==
NL80211_REGDOM_SET_BY_COUNTRY_IE &&
- wiphy_idx_valid(last_request->wiphy_idx))) {
- struct cfg80211_registered_device *drv_last_ie;
-
- drv_last_ie =
- cfg80211_drv_by_wiphy_idx(last_request->wiphy_idx);
-
- /*
- * Lets keep this simple -- we trust the first AP
- * after we intersect with CRDA
- */
- if (likely(&drv_last_ie->wiphy == wiphy)) {
- /*
- * Ignore IEs coming in on this wiphy with
- * the same alpha2 and environment cap
- */
- if (likely(alpha2_equal(drv_last_ie->country_ie_alpha2,
- alpha2) &&
- env == drv_last_ie->env)) {
- goto out;
- }
- /*
- * the wiphy moved on to another BSSID or the AP
- * was reconfigured. XXX: We need to deal with the
- * case where the user suspends and goes to goes
- * to another country, and then gets IEs from an
- * AP with different settings
- */
- goto out;
- } else {
- /*
- * Ignore IEs coming in on two separate wiphys with
- * the same alpha2 and environment cap
- */
- if (likely(alpha2_equal(drv_last_ie->country_ie_alpha2,
- alpha2) &&
- env == drv_last_ie->env)) {
- goto out;
- }
- /* We could potentially intersect though */
- goto out;
- }
- }
+ wiphy_idx_valid(last_request->wiphy_idx)))
+ goto out;
rd = country_ie_2_rd(country_ie, country_ie_len, &checksum);
if (!rd)
@@ -1890,7 +1862,7 @@ void regulatory_hint_11d(struct wiphy *wiphy,
request->country_ie_checksum = checksum;
request->country_ie_env = env;
- mutex_unlock(&cfg80211_mutex);
+ mutex_unlock(&reg_mutex);
queue_regulatory_request(request);
@@ -1899,9 +1871,8 @@ void regulatory_hint_11d(struct wiphy *wiphy,
free_rd_out:
kfree(rd);
out:
- mutex_unlock(&cfg80211_mutex);
+ mutex_unlock(&reg_mutex);
}
-EXPORT_SYMBOL(regulatory_hint_11d);
static bool freq_is_chan_12_13_14(u16 freq)
{
@@ -1996,14 +1967,14 @@ static void print_regdomain(const struct ieee80211_regdomain *rd)
if (last_request->initiator ==
NL80211_REGDOM_SET_BY_COUNTRY_IE) {
- struct cfg80211_registered_device *drv;
- drv = cfg80211_drv_by_wiphy_idx(
+ struct cfg80211_registered_device *rdev;
+ rdev = cfg80211_rdev_by_wiphy_idx(
last_request->wiphy_idx);
- if (drv) {
+ if (rdev) {
printk(KERN_INFO "cfg80211: Current regulatory "
"domain updated by AP to: %c%c\n",
- drv->country_ie_alpha2[0],
- drv->country_ie_alpha2[1]);
+ rdev->country_ie_alpha2[0],
+ rdev->country_ie_alpha2[1]);
} else
printk(KERN_INFO "cfg80211: Current regulatory "
"domain intersected: \n");
@@ -2064,7 +2035,7 @@ static inline void reg_country_ie_process_debug(
static int __set_regdom(const struct ieee80211_regdomain *rd)
{
const struct ieee80211_regdomain *intersected_rd = NULL;
- struct cfg80211_registered_device *drv = NULL;
+ struct cfg80211_registered_device *rdev = NULL;
struct wiphy *request_wiphy;
/* Some basic sanity checks first */
@@ -2203,11 +2174,11 @@ static int __set_regdom(const struct ieee80211_regdomain *rd)
if (!intersected_rd)
return -EINVAL;
- drv = wiphy_to_dev(request_wiphy);
+ rdev = wiphy_to_dev(request_wiphy);
- drv->country_ie_alpha2[0] = rd->alpha2[0];
- drv->country_ie_alpha2[1] = rd->alpha2[1];
- drv->env = last_request->country_ie_env;
+ rdev->country_ie_alpha2[0] = rd->alpha2[0];
+ rdev->country_ie_alpha2[1] = rd->alpha2[1];
+ rdev->env = last_request->country_ie_env;
BUG_ON(intersected_rd == rd);
@@ -2232,10 +2203,13 @@ int set_regdom(const struct ieee80211_regdomain *rd)
assert_cfg80211_lock();
+ mutex_lock(&reg_mutex);
+
/* Note that this doesn't update the wiphys, this is done below */
r = __set_regdom(rd);
if (r) {
kfree(rd);
+ mutex_unlock(&reg_mutex);
return r;
}
@@ -2250,6 +2224,8 @@ int set_regdom(const struct ieee80211_regdomain *rd)
nl80211_send_reg_change_event(last_request);
+ mutex_unlock(&reg_mutex);
+
return r;
}
@@ -2260,16 +2236,20 @@ void reg_device_remove(struct wiphy *wiphy)
assert_cfg80211_lock();
+ mutex_lock(&reg_mutex);
+
kfree(wiphy->regd);
if (last_request)
request_wiphy = wiphy_idx_to_wiphy(last_request->wiphy_idx);
if (!request_wiphy || request_wiphy != wiphy)
- return;
+ goto out;
last_request->wiphy_idx = WIPHY_IDX_STALE;
last_request->country_ie_env = ENVIRON_ANY;
+out:
+ mutex_unlock(&reg_mutex);
}
int regulatory_init(void)
@@ -2288,22 +2268,12 @@ int regulatory_init(void)
printk(KERN_INFO "cfg80211: Using static regulatory domain info\n");
print_regdomain_info(cfg80211_regdomain);
- /*
- * The old code still requests for a new regdomain and if
- * you have CRDA you get it updated, otherwise you get
- * stuck with the static values. Since "EU" is not a valid
- * ISO / IEC 3166 alpha2 code we can't expect userpace to
- * give us a regulatory domain for it. We need last_request
- * iniitalized though so lets just send a request which we
- * know will be ignored... this crap will be removed once
- * OLD_REG dies.
- */
- err = regulatory_hint_core(ieee80211_regdom);
#else
cfg80211_regdomain = cfg80211_world_regdom;
- err = regulatory_hint_core(ieee80211_regdom);
#endif
+ /* We always try to get an update for the static regdomain */
+ err = regulatory_hint_core(cfg80211_regdomain->alpha2);
if (err) {
if (err == -ENOMEM)
return err;
@@ -2322,6 +2292,13 @@ int regulatory_init(void)
#endif
}
+ /*
+ * Finally, if the user set the module parameter treat it
+ * as a user hint.
+ */
+ if (!is_world_regdom(ieee80211_regdom))
+ regulatory_hint_user(ieee80211_regdom);
+
return 0;
}
@@ -2333,6 +2310,7 @@ void regulatory_exit(void)
cancel_work_sync(&reg_work);
mutex_lock(&cfg80211_mutex);
+ mutex_lock(&reg_mutex);
reset_regdomains();
@@ -2371,5 +2349,6 @@ void regulatory_exit(void)
}
spin_unlock(&reg_requests_lock);
+ mutex_unlock(&reg_mutex);
mutex_unlock(&cfg80211_mutex);
}
diff --git a/net/wireless/reg.h b/net/wireless/reg.h
index 4e167a8e11b..3362c7c069b 100644
--- a/net/wireless/reg.h
+++ b/net/wireless/reg.h
@@ -37,4 +37,19 @@ int regulatory_hint_found_beacon(struct wiphy *wiphy,
struct ieee80211_channel *beacon_chan,
gfp_t gfp);
+/**
+ * regulatory_hint_11d - hints a country IE as a regulatory domain
+ * @wiphy: the wireless device giving the hint (used only for reporting
+ * conflicts)
+ * @country_ie: pointer to the country IE
+ * @country_ie_len: length of the country IE
+ *
+ * We will intersect the rd with the what CRDA tells us should apply
+ * for the alpha2 this country IE belongs to, this prevents APs from
+ * sending us incorrect or outdated information against a country.
+ */
+void regulatory_hint_11d(struct wiphy *wiphy,
+ u8 *country_ie,
+ u8 country_ie_len);
+
#endif /* __NET_WIRELESS_REG_H */
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index 7e595ce24ee..fe575a24c95 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -14,29 +14,36 @@
#include <net/iw_handler.h>
#include "core.h"
#include "nl80211.h"
+#include "wext-compat.h"
-#define IEEE80211_SCAN_RESULT_EXPIRE (10 * HZ)
+#define IEEE80211_SCAN_RESULT_EXPIRE (15 * HZ)
-void cfg80211_scan_done(struct cfg80211_scan_request *request, bool aborted)
+void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev)
{
+ struct cfg80211_scan_request *request;
struct net_device *dev;
#ifdef CONFIG_WIRELESS_EXT
union iwreq_data wrqu;
#endif
- dev = dev_get_by_index(&init_net, request->ifidx);
- if (!dev)
- goto out;
+ request = rdev->scan_req;
- WARN_ON(request != wiphy_to_dev(request->wiphy)->scan_req);
+ dev = request->dev;
+
+ /*
+ * This must be before sending the other events!
+ * Otherwise, wpa_supplicant gets completely confused with
+ * wext events.
+ */
+ cfg80211_sme_scan_done(dev);
- if (aborted)
- nl80211_send_scan_aborted(wiphy_to_dev(request->wiphy), dev);
+ if (request->aborted)
+ nl80211_send_scan_aborted(rdev, dev);
else
- nl80211_send_scan_done(wiphy_to_dev(request->wiphy), dev);
+ nl80211_send_scan_done(rdev, dev);
#ifdef CONFIG_WIRELESS_EXT
- if (!aborted) {
+ if (!request->aborted) {
memset(&wrqu, 0, sizeof(wrqu));
wireless_send_event(dev, SIOCGIWSCAN, &wrqu, NULL);
@@ -45,10 +52,29 @@ void cfg80211_scan_done(struct cfg80211_scan_request *request, bool aborted)
dev_put(dev);
- out:
- wiphy_to_dev(request->wiphy)->scan_req = NULL;
+ rdev->scan_req = NULL;
kfree(request);
}
+
+void __cfg80211_scan_done(struct work_struct *wk)
+{
+ struct cfg80211_registered_device *rdev;
+
+ rdev = container_of(wk, struct cfg80211_registered_device,
+ scan_done_wk);
+
+ cfg80211_lock_rdev(rdev);
+ ___cfg80211_scan_done(rdev);
+ cfg80211_unlock_rdev(rdev);
+}
+
+void cfg80211_scan_done(struct cfg80211_scan_request *request, bool aborted)
+{
+ WARN_ON(request != wiphy_to_dev(request->wiphy)->scan_req);
+
+ request->aborted = aborted;
+ schedule_work(&wiphy_to_dev(request->wiphy)->scan_done_wk);
+}
EXPORT_SYMBOL(cfg80211_scan_done);
static void bss_release(struct kref *ref)
@@ -62,6 +88,8 @@ static void bss_release(struct kref *ref)
if (bss->ies_allocated)
kfree(bss->pub.information_elements);
+ BUG_ON(atomic_read(&bss->hold));
+
kfree(bss);
}
@@ -84,8 +112,9 @@ void cfg80211_bss_expire(struct cfg80211_registered_device *dev)
bool expired = false;
list_for_each_entry_safe(bss, tmp, &dev->bss_list, list) {
- if (bss->hold ||
- !time_after(jiffies, bss->ts + IEEE80211_SCAN_RESULT_EXPIRE))
+ if (atomic_read(&bss->hold))
+ continue;
+ if (!time_after(jiffies, bss->ts + IEEE80211_SCAN_RESULT_EXPIRE))
continue;
list_del(&bss->list);
rb_erase(&bss->rbn, &dev->bss_tree);
@@ -539,6 +568,7 @@ void cfg80211_unlink_bss(struct wiphy *wiphy, struct cfg80211_bss *pub)
spin_lock_bh(&dev->bss_lock);
list_del(&bss->list);
+ dev->bss_generation++;
rb_erase(&bss->rbn, &dev->bss_tree);
spin_unlock_bh(&dev->bss_lock);
@@ -547,30 +577,6 @@ void cfg80211_unlink_bss(struct wiphy *wiphy, struct cfg80211_bss *pub)
}
EXPORT_SYMBOL(cfg80211_unlink_bss);
-void cfg80211_hold_bss(struct cfg80211_bss *pub)
-{
- struct cfg80211_internal_bss *bss;
-
- if (!pub)
- return;
-
- bss = container_of(pub, struct cfg80211_internal_bss, pub);
- bss->hold = true;
-}
-EXPORT_SYMBOL(cfg80211_hold_bss);
-
-void cfg80211_unhold_bss(struct cfg80211_bss *pub)
-{
- struct cfg80211_internal_bss *bss;
-
- if (!pub)
- return;
-
- bss = container_of(pub, struct cfg80211_internal_bss, pub);
- bss->hold = false;
-}
-EXPORT_SYMBOL(cfg80211_unhold_bss);
-
#ifdef CONFIG_WIRELESS_EXT
int cfg80211_wext_siwscan(struct net_device *dev,
struct iw_request_info *info,
@@ -586,7 +592,7 @@ int cfg80211_wext_siwscan(struct net_device *dev,
if (!netif_running(dev))
return -ENETDOWN;
- rdev = cfg80211_get_dev_from_ifindex(dev->ifindex);
+ rdev = cfg80211_get_dev_from_ifindex(dev_net(dev), dev->ifindex);
if (IS_ERR(rdev))
return PTR_ERR(rdev);
@@ -611,9 +617,9 @@ int cfg80211_wext_siwscan(struct net_device *dev,
}
creq->wiphy = wiphy;
- creq->ifidx = dev->ifindex;
- creq->ssids = (void *)(creq + 1);
- creq->channels = (void *)(creq->ssids + 1);
+ creq->dev = dev;
+ /* SSIDs come after channels */
+ creq->ssids = (void *)&creq->channels[n_channels];
creq->n_channels = n_channels;
creq->n_ssids = 1;
@@ -648,9 +654,12 @@ int cfg80211_wext_siwscan(struct net_device *dev,
if (err) {
rdev->scan_req = NULL;
kfree(creq);
+ } else {
+ nl80211_send_scan_start(rdev, dev);
+ dev_hold(dev);
}
out:
- cfg80211_put_dev(rdev);
+ cfg80211_unlock_rdev(rdev);
return err;
}
EXPORT_SYMBOL_GPL(cfg80211_wext_siwscan);
@@ -941,7 +950,7 @@ int cfg80211_wext_giwscan(struct net_device *dev,
if (!netif_running(dev))
return -ENETDOWN;
- rdev = cfg80211_get_dev_from_ifindex(dev->ifindex);
+ rdev = cfg80211_get_dev_from_ifindex(dev_net(dev), dev->ifindex);
if (IS_ERR(rdev))
return PTR_ERR(rdev);
@@ -959,7 +968,7 @@ int cfg80211_wext_giwscan(struct net_device *dev,
}
out:
- cfg80211_put_dev(rdev);
+ cfg80211_unlock_rdev(rdev);
return res;
}
EXPORT_SYMBOL_GPL(cfg80211_wext_giwscan);
diff --git a/net/wireless/sme.c b/net/wireless/sme.c
new file mode 100644
index 00000000000..8e2ef54ea71
--- /dev/null
+++ b/net/wireless/sme.c
@@ -0,0 +1,932 @@
+/*
+ * SME code for cfg80211's connect emulation.
+ *
+ * Copyright 2009 Johannes Berg <johannes@sipsolutions.net>
+ * Copyright (C) 2009 Intel Corporation. All rights reserved.
+ */
+
+#include <linux/etherdevice.h>
+#include <linux/if_arp.h>
+#include <linux/workqueue.h>
+#include <linux/wireless.h>
+#include <net/iw_handler.h>
+#include <net/cfg80211.h>
+#include <net/rtnetlink.h>
+#include "nl80211.h"
+#include "reg.h"
+
+struct cfg80211_conn {
+ struct cfg80211_connect_params params;
+ /* these are sub-states of the _CONNECTING sme_state */
+ enum {
+ CFG80211_CONN_IDLE,
+ CFG80211_CONN_SCANNING,
+ CFG80211_CONN_SCAN_AGAIN,
+ CFG80211_CONN_AUTHENTICATE_NEXT,
+ CFG80211_CONN_AUTHENTICATING,
+ CFG80211_CONN_ASSOCIATE_NEXT,
+ CFG80211_CONN_ASSOCIATING,
+ } state;
+ u8 bssid[ETH_ALEN], prev_bssid[ETH_ALEN];
+ u8 *ie;
+ size_t ie_len;
+ bool auto_auth, prev_bssid_valid;
+};
+
+
+static int cfg80211_conn_scan(struct wireless_dev *wdev)
+{
+ struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
+ struct cfg80211_scan_request *request;
+ int n_channels, err;
+
+ ASSERT_RTNL();
+ ASSERT_RDEV_LOCK(rdev);
+ ASSERT_WDEV_LOCK(wdev);
+
+ if (rdev->scan_req)
+ return -EBUSY;
+
+ if (wdev->conn->params.channel) {
+ n_channels = 1;
+ } else {
+ enum ieee80211_band band;
+ n_channels = 0;
+
+ for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
+ if (!wdev->wiphy->bands[band])
+ continue;
+ n_channels += wdev->wiphy->bands[band]->n_channels;
+ }
+ }
+ request = kzalloc(sizeof(*request) + sizeof(request->ssids[0]) +
+ sizeof(request->channels[0]) * n_channels,
+ GFP_KERNEL);
+ if (!request)
+ return -ENOMEM;
+
+ if (wdev->conn->params.channel)
+ request->channels[0] = wdev->conn->params.channel;
+ else {
+ int i = 0, j;
+ enum ieee80211_band band;
+
+ for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
+ if (!wdev->wiphy->bands[band])
+ continue;
+ for (j = 0; j < wdev->wiphy->bands[band]->n_channels;
+ i++, j++)
+ request->channels[i] =
+ &wdev->wiphy->bands[band]->channels[j];
+ }
+ }
+ request->n_channels = n_channels;
+ request->ssids = (void *)&request->channels[n_channels];
+ request->n_ssids = 1;
+
+ memcpy(request->ssids[0].ssid, wdev->conn->params.ssid,
+ wdev->conn->params.ssid_len);
+ request->ssids[0].ssid_len = wdev->conn->params.ssid_len;
+
+ request->dev = wdev->netdev;
+ request->wiphy = &rdev->wiphy;
+
+ rdev->scan_req = request;
+
+ err = rdev->ops->scan(wdev->wiphy, wdev->netdev, request);
+ if (!err) {
+ wdev->conn->state = CFG80211_CONN_SCANNING;
+ nl80211_send_scan_start(rdev, wdev->netdev);
+ dev_hold(wdev->netdev);
+ } else {
+ rdev->scan_req = NULL;
+ kfree(request);
+ }
+ return err;
+}
+
+static int cfg80211_conn_do_work(struct wireless_dev *wdev)
+{
+ struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
+ struct cfg80211_connect_params *params;
+ const u8 *prev_bssid = NULL;
+ int err;
+
+ ASSERT_WDEV_LOCK(wdev);
+
+ if (!wdev->conn)
+ return 0;
+
+ params = &wdev->conn->params;
+
+ switch (wdev->conn->state) {
+ case CFG80211_CONN_SCAN_AGAIN:
+ return cfg80211_conn_scan(wdev);
+ case CFG80211_CONN_AUTHENTICATE_NEXT:
+ BUG_ON(!rdev->ops->auth);
+ wdev->conn->state = CFG80211_CONN_AUTHENTICATING;
+ return __cfg80211_mlme_auth(rdev, wdev->netdev,
+ params->channel, params->auth_type,
+ params->bssid,
+ params->ssid, params->ssid_len,
+ NULL, 0,
+ params->key, params->key_len,
+ params->key_idx);
+ case CFG80211_CONN_ASSOCIATE_NEXT:
+ BUG_ON(!rdev->ops->assoc);
+ wdev->conn->state = CFG80211_CONN_ASSOCIATING;
+ if (wdev->conn->prev_bssid_valid)
+ prev_bssid = wdev->conn->prev_bssid;
+ err = __cfg80211_mlme_assoc(rdev, wdev->netdev,
+ params->channel, params->bssid,
+ prev_bssid,
+ params->ssid, params->ssid_len,
+ params->ie, params->ie_len,
+ false, &params->crypto);
+ if (err)
+ __cfg80211_mlme_deauth(rdev, wdev->netdev, params->bssid,
+ NULL, 0,
+ WLAN_REASON_DEAUTH_LEAVING);
+ return err;
+ default:
+ return 0;
+ }
+}
+
+void cfg80211_conn_work(struct work_struct *work)
+{
+ struct cfg80211_registered_device *rdev =
+ container_of(work, struct cfg80211_registered_device, conn_work);
+ struct wireless_dev *wdev;
+
+ rtnl_lock();
+ cfg80211_lock_rdev(rdev);
+ mutex_lock(&rdev->devlist_mtx);
+
+ list_for_each_entry(wdev, &rdev->netdev_list, list) {
+ wdev_lock(wdev);
+ if (!netif_running(wdev->netdev)) {
+ wdev_unlock(wdev);
+ continue;
+ }
+ if (wdev->sme_state != CFG80211_SME_CONNECTING) {
+ wdev_unlock(wdev);
+ continue;
+ }
+ if (cfg80211_conn_do_work(wdev))
+ __cfg80211_connect_result(
+ wdev->netdev,
+ wdev->conn->params.bssid,
+ NULL, 0, NULL, 0,
+ WLAN_STATUS_UNSPECIFIED_FAILURE,
+ false, NULL);
+ wdev_unlock(wdev);
+ }
+
+ mutex_unlock(&rdev->devlist_mtx);
+ cfg80211_unlock_rdev(rdev);
+ rtnl_unlock();
+}
+
+static bool cfg80211_get_conn_bss(struct wireless_dev *wdev)
+{
+ struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
+ struct cfg80211_bss *bss;
+ u16 capa = WLAN_CAPABILITY_ESS;
+
+ ASSERT_WDEV_LOCK(wdev);
+
+ if (wdev->conn->params.privacy)
+ capa |= WLAN_CAPABILITY_PRIVACY;
+
+ bss = cfg80211_get_bss(wdev->wiphy, NULL, wdev->conn->params.bssid,
+ wdev->conn->params.ssid,
+ wdev->conn->params.ssid_len,
+ WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_PRIVACY,
+ capa);
+ if (!bss)
+ return false;
+
+ memcpy(wdev->conn->bssid, bss->bssid, ETH_ALEN);
+ wdev->conn->params.bssid = wdev->conn->bssid;
+ wdev->conn->params.channel = bss->channel;
+ wdev->conn->state = CFG80211_CONN_AUTHENTICATE_NEXT;
+ schedule_work(&rdev->conn_work);
+
+ cfg80211_put_bss(bss);
+ return true;
+}
+
+static void __cfg80211_sme_scan_done(struct net_device *dev)
+{
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+ struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
+
+ ASSERT_WDEV_LOCK(wdev);
+
+ if (wdev->sme_state != CFG80211_SME_CONNECTING)
+ return;
+
+ if (!wdev->conn)
+ return;
+
+ if (wdev->conn->state != CFG80211_CONN_SCANNING &&
+ wdev->conn->state != CFG80211_CONN_SCAN_AGAIN)
+ return;
+
+ if (!cfg80211_get_conn_bss(wdev)) {
+ /* not found */
+ if (wdev->conn->state == CFG80211_CONN_SCAN_AGAIN)
+ schedule_work(&rdev->conn_work);
+ else
+ __cfg80211_connect_result(
+ wdev->netdev,
+ wdev->conn->params.bssid,
+ NULL, 0, NULL, 0,
+ WLAN_STATUS_UNSPECIFIED_FAILURE,
+ false, NULL);
+ }
+}
+
+void cfg80211_sme_scan_done(struct net_device *dev)
+{
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+
+ mutex_lock(&wiphy_to_dev(wdev->wiphy)->devlist_mtx);
+ wdev_lock(wdev);
+ __cfg80211_sme_scan_done(dev);
+ wdev_unlock(wdev);
+ mutex_unlock(&wiphy_to_dev(wdev->wiphy)->devlist_mtx);
+}
+
+void cfg80211_sme_rx_auth(struct net_device *dev,
+ const u8 *buf, size_t len)
+{
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+ struct wiphy *wiphy = wdev->wiphy;
+ struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
+ struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf;
+ u16 status_code = le16_to_cpu(mgmt->u.auth.status_code);
+
+ ASSERT_WDEV_LOCK(wdev);
+
+ /* should only RX auth frames when connecting */
+ if (wdev->sme_state != CFG80211_SME_CONNECTING)
+ return;
+
+ if (WARN_ON(!wdev->conn))
+ return;
+
+ if (status_code == WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG &&
+ wdev->conn->auto_auth &&
+ wdev->conn->params.auth_type != NL80211_AUTHTYPE_NETWORK_EAP) {
+ /* select automatically between only open, shared, leap */
+ switch (wdev->conn->params.auth_type) {
+ case NL80211_AUTHTYPE_OPEN_SYSTEM:
+ if (wdev->connect_keys)
+ wdev->conn->params.auth_type =
+ NL80211_AUTHTYPE_SHARED_KEY;
+ else
+ wdev->conn->params.auth_type =
+ NL80211_AUTHTYPE_NETWORK_EAP;
+ break;
+ case NL80211_AUTHTYPE_SHARED_KEY:
+ wdev->conn->params.auth_type =
+ NL80211_AUTHTYPE_NETWORK_EAP;
+ break;
+ default:
+ /* huh? */
+ wdev->conn->params.auth_type =
+ NL80211_AUTHTYPE_OPEN_SYSTEM;
+ break;
+ }
+ wdev->conn->state = CFG80211_CONN_AUTHENTICATE_NEXT;
+ schedule_work(&rdev->conn_work);
+ } else if (status_code != WLAN_STATUS_SUCCESS) {
+ __cfg80211_connect_result(dev, mgmt->bssid, NULL, 0, NULL, 0,
+ status_code, false, NULL);
+ } else if (wdev->sme_state == CFG80211_SME_CONNECTING &&
+ wdev->conn->state == CFG80211_CONN_AUTHENTICATING) {
+ wdev->conn->state = CFG80211_CONN_ASSOCIATE_NEXT;
+ schedule_work(&rdev->conn_work);
+ }
+}
+
+bool cfg80211_sme_failed_reassoc(struct wireless_dev *wdev)
+{
+ struct wiphy *wiphy = wdev->wiphy;
+ struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
+
+ if (WARN_ON(!wdev->conn))
+ return false;
+
+ if (!wdev->conn->prev_bssid_valid)
+ return false;
+
+ /*
+ * Some stupid APs don't accept reassoc, so we
+ * need to fall back to trying regular assoc.
+ */
+ wdev->conn->prev_bssid_valid = false;
+ wdev->conn->state = CFG80211_CONN_ASSOCIATE_NEXT;
+ schedule_work(&rdev->conn_work);
+
+ return true;
+}
+
+void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
+ const u8 *req_ie, size_t req_ie_len,
+ const u8 *resp_ie, size_t resp_ie_len,
+ u16 status, bool wextev,
+ struct cfg80211_bss *bss)
+{
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+ u8 *country_ie;
+#ifdef CONFIG_WIRELESS_EXT
+ union iwreq_data wrqu;
+#endif
+
+ ASSERT_WDEV_LOCK(wdev);
+
+ if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION))
+ return;
+
+ if (wdev->sme_state == CFG80211_SME_CONNECTED)
+ nl80211_send_roamed(wiphy_to_dev(wdev->wiphy), dev,
+ bssid, req_ie, req_ie_len,
+ resp_ie, resp_ie_len, GFP_KERNEL);
+ else
+ nl80211_send_connect_result(wiphy_to_dev(wdev->wiphy), dev,
+ bssid, req_ie, req_ie_len,
+ resp_ie, resp_ie_len,
+ status, GFP_KERNEL);
+
+#ifdef CONFIG_WIRELESS_EXT
+ if (wextev) {
+ if (req_ie && status == WLAN_STATUS_SUCCESS) {
+ memset(&wrqu, 0, sizeof(wrqu));
+ wrqu.data.length = req_ie_len;
+ wireless_send_event(dev, IWEVASSOCREQIE, &wrqu, req_ie);
+ }
+
+ if (resp_ie && status == WLAN_STATUS_SUCCESS) {
+ memset(&wrqu, 0, sizeof(wrqu));
+ wrqu.data.length = resp_ie_len;
+ wireless_send_event(dev, IWEVASSOCRESPIE, &wrqu, resp_ie);
+ }
+
+ memset(&wrqu, 0, sizeof(wrqu));
+ wrqu.ap_addr.sa_family = ARPHRD_ETHER;
+ if (bssid && status == WLAN_STATUS_SUCCESS) {
+ memcpy(wrqu.ap_addr.sa_data, bssid, ETH_ALEN);
+ memcpy(wdev->wext.prev_bssid, bssid, ETH_ALEN);
+ wdev->wext.prev_bssid_valid = true;
+ }
+ wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL);
+ }
+#endif
+
+ if (wdev->current_bss) {
+ cfg80211_unhold_bss(wdev->current_bss);
+ cfg80211_put_bss(&wdev->current_bss->pub);
+ wdev->current_bss = NULL;
+ }
+
+ if (status == WLAN_STATUS_SUCCESS &&
+ wdev->sme_state == CFG80211_SME_IDLE)
+ goto success;
+
+ if (wdev->sme_state != CFG80211_SME_CONNECTING)
+ return;
+
+ if (wdev->conn)
+ wdev->conn->state = CFG80211_CONN_IDLE;
+
+ if (status != WLAN_STATUS_SUCCESS) {
+ wdev->sme_state = CFG80211_SME_IDLE;
+ kfree(wdev->conn);
+ wdev->conn = NULL;
+ kfree(wdev->connect_keys);
+ wdev->connect_keys = NULL;
+ wdev->ssid_len = 0;
+ return;
+ }
+
+ success:
+ if (!bss)
+ bss = cfg80211_get_bss(wdev->wiphy, NULL, bssid,
+ wdev->ssid, wdev->ssid_len,
+ WLAN_CAPABILITY_ESS,
+ WLAN_CAPABILITY_ESS);
+
+ if (WARN_ON(!bss))
+ return;
+
+ cfg80211_hold_bss(bss_from_pub(bss));
+ wdev->current_bss = bss_from_pub(bss);
+
+ wdev->sme_state = CFG80211_SME_CONNECTED;
+ cfg80211_upload_connect_keys(wdev);
+
+ country_ie = (u8 *) ieee80211_bss_get_ie(bss, WLAN_EID_COUNTRY);
+
+ if (!country_ie)
+ return;
+
+ /*
+ * ieee80211_bss_get_ie() ensures we can access:
+ * - country_ie + 2, the start of the country ie data, and
+ * - and country_ie[1] which is the IE length
+ */
+ regulatory_hint_11d(wdev->wiphy,
+ country_ie + 2,
+ country_ie[1]);
+}
+
+void cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
+ const u8 *req_ie, size_t req_ie_len,
+ const u8 *resp_ie, size_t resp_ie_len,
+ u16 status, gfp_t gfp)
+{
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+ struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
+ struct cfg80211_event *ev;
+ unsigned long flags;
+
+ ev = kzalloc(sizeof(*ev) + req_ie_len + resp_ie_len, gfp);
+ if (!ev)
+ return;
+
+ ev->type = EVENT_CONNECT_RESULT;
+ memcpy(ev->cr.bssid, bssid, ETH_ALEN);
+ ev->cr.req_ie = ((u8 *)ev) + sizeof(*ev);
+ ev->cr.req_ie_len = req_ie_len;
+ memcpy((void *)ev->cr.req_ie, req_ie, req_ie_len);
+ ev->cr.resp_ie = ((u8 *)ev) + sizeof(*ev) + req_ie_len;
+ ev->cr.resp_ie_len = resp_ie_len;
+ memcpy((void *)ev->cr.resp_ie, resp_ie, resp_ie_len);
+ ev->cr.status = status;
+
+ spin_lock_irqsave(&wdev->event_lock, flags);
+ list_add_tail(&ev->list, &wdev->event_list);
+ spin_unlock_irqrestore(&wdev->event_lock, flags);
+ schedule_work(&rdev->event_work);
+}
+EXPORT_SYMBOL(cfg80211_connect_result);
+
+void __cfg80211_roamed(struct wireless_dev *wdev, const u8 *bssid,
+ const u8 *req_ie, size_t req_ie_len,
+ const u8 *resp_ie, size_t resp_ie_len)
+{
+ struct cfg80211_bss *bss;
+#ifdef CONFIG_WIRELESS_EXT
+ union iwreq_data wrqu;
+#endif
+
+ ASSERT_WDEV_LOCK(wdev);
+
+ if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION))
+ return;
+
+ if (WARN_ON(wdev->sme_state != CFG80211_SME_CONNECTED))
+ return;
+
+ /* internal error -- how did we get to CONNECTED w/o BSS? */
+ if (WARN_ON(!wdev->current_bss)) {
+ return;
+ }
+
+ cfg80211_unhold_bss(wdev->current_bss);
+ cfg80211_put_bss(&wdev->current_bss->pub);
+ wdev->current_bss = NULL;
+
+ bss = cfg80211_get_bss(wdev->wiphy, NULL, bssid,
+ wdev->ssid, wdev->ssid_len,
+ WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
+
+ if (WARN_ON(!bss))
+ return;
+
+ cfg80211_hold_bss(bss_from_pub(bss));
+ wdev->current_bss = bss_from_pub(bss);
+
+ nl80211_send_roamed(wiphy_to_dev(wdev->wiphy), wdev->netdev, bssid,
+ req_ie, req_ie_len, resp_ie, resp_ie_len,
+ GFP_KERNEL);
+
+#ifdef CONFIG_WIRELESS_EXT
+ if (req_ie) {
+ memset(&wrqu, 0, sizeof(wrqu));
+ wrqu.data.length = req_ie_len;
+ wireless_send_event(wdev->netdev, IWEVASSOCREQIE,
+ &wrqu, req_ie);
+ }
+
+ if (resp_ie) {
+ memset(&wrqu, 0, sizeof(wrqu));
+ wrqu.data.length = resp_ie_len;
+ wireless_send_event(wdev->netdev, IWEVASSOCRESPIE,
+ &wrqu, resp_ie);
+ }
+
+ memset(&wrqu, 0, sizeof(wrqu));
+ wrqu.ap_addr.sa_family = ARPHRD_ETHER;
+ memcpy(wrqu.ap_addr.sa_data, bssid, ETH_ALEN);
+ memcpy(wdev->wext.prev_bssid, bssid, ETH_ALEN);
+ wdev->wext.prev_bssid_valid = true;
+ wireless_send_event(wdev->netdev, SIOCGIWAP, &wrqu, NULL);
+#endif
+}
+
+void cfg80211_roamed(struct net_device *dev, const u8 *bssid,
+ const u8 *req_ie, size_t req_ie_len,
+ const u8 *resp_ie, size_t resp_ie_len, gfp_t gfp)
+{
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+ struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
+ struct cfg80211_event *ev;
+ unsigned long flags;
+
+ ev = kzalloc(sizeof(*ev) + req_ie_len + resp_ie_len, gfp);
+ if (!ev)
+ return;
+
+ ev->type = EVENT_ROAMED;
+ memcpy(ev->rm.bssid, bssid, ETH_ALEN);
+ ev->rm.req_ie = ((u8 *)ev) + sizeof(*ev);
+ ev->rm.req_ie_len = req_ie_len;
+ memcpy((void *)ev->rm.req_ie, req_ie, req_ie_len);
+ ev->rm.resp_ie = ((u8 *)ev) + sizeof(*ev) + req_ie_len;
+ ev->rm.resp_ie_len = resp_ie_len;
+ memcpy((void *)ev->rm.resp_ie, resp_ie, resp_ie_len);
+
+ spin_lock_irqsave(&wdev->event_lock, flags);
+ list_add_tail(&ev->list, &wdev->event_list);
+ spin_unlock_irqrestore(&wdev->event_lock, flags);
+ schedule_work(&rdev->event_work);
+}
+EXPORT_SYMBOL(cfg80211_roamed);
+
+void __cfg80211_disconnected(struct net_device *dev, const u8 *ie,
+ size_t ie_len, u16 reason, bool from_ap)
+{
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+ struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
+ int i;
+#ifdef CONFIG_WIRELESS_EXT
+ union iwreq_data wrqu;
+#endif
+
+ ASSERT_WDEV_LOCK(wdev);
+
+ if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION))
+ return;
+
+ if (WARN_ON(wdev->sme_state != CFG80211_SME_CONNECTED))
+ return;
+
+ if (wdev->current_bss) {
+ cfg80211_unhold_bss(wdev->current_bss);
+ cfg80211_put_bss(&wdev->current_bss->pub);
+ }
+
+ wdev->current_bss = NULL;
+ wdev->sme_state = CFG80211_SME_IDLE;
+ wdev->ssid_len = 0;
+
+ if (wdev->conn) {
+ const u8 *bssid;
+ int ret;
+
+ kfree(wdev->conn->ie);
+ wdev->conn->ie = NULL;
+ kfree(wdev->conn);
+ wdev->conn = NULL;
+
+ /*
+ * If this disconnect was due to a disassoc, we
+ * we might still have an auth BSS around. For
+ * the userspace SME that's currently expected,
+ * but for the kernel SME (nl80211 CONNECT or
+ * wireless extensions) we want to clear up all
+ * state.
+ */
+ for (i = 0; i < MAX_AUTH_BSSES; i++) {
+ if (!wdev->auth_bsses[i])
+ continue;
+ bssid = wdev->auth_bsses[i]->pub.bssid;
+ ret = __cfg80211_mlme_deauth(rdev, dev, bssid, NULL, 0,
+ WLAN_REASON_DEAUTH_LEAVING);
+ WARN(ret, "deauth failed: %d\n", ret);
+ }
+ }
+
+ nl80211_send_disconnected(rdev, dev, reason, ie, ie_len, from_ap);
+
+ /*
+ * Delete all the keys ... pairwise keys can't really
+ * exist any more anyway, but default keys might.
+ */
+ if (rdev->ops->del_key)
+ for (i = 0; i < 6; i++)
+ rdev->ops->del_key(wdev->wiphy, dev, i, NULL);
+
+#ifdef CONFIG_WIRELESS_EXT
+ memset(&wrqu, 0, sizeof(wrqu));
+ wrqu.ap_addr.sa_family = ARPHRD_ETHER;
+ wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL);
+#endif
+}
+
+void cfg80211_disconnected(struct net_device *dev, u16 reason,
+ u8 *ie, size_t ie_len, gfp_t gfp)
+{
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+ struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
+ struct cfg80211_event *ev;
+ unsigned long flags;
+
+ ev = kzalloc(sizeof(*ev) + ie_len, gfp);
+ if (!ev)
+ return;
+
+ ev->type = EVENT_DISCONNECTED;
+ ev->dc.ie = ((u8 *)ev) + sizeof(*ev);
+ ev->dc.ie_len = ie_len;
+ memcpy((void *)ev->dc.ie, ie, ie_len);
+ ev->dc.reason = reason;
+
+ spin_lock_irqsave(&wdev->event_lock, flags);
+ list_add_tail(&ev->list, &wdev->event_list);
+ spin_unlock_irqrestore(&wdev->event_lock, flags);
+ schedule_work(&rdev->event_work);
+}
+EXPORT_SYMBOL(cfg80211_disconnected);
+
+int __cfg80211_connect(struct cfg80211_registered_device *rdev,
+ struct net_device *dev,
+ struct cfg80211_connect_params *connect,
+ struct cfg80211_cached_keys *connkeys,
+ const u8 *prev_bssid)
+{
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+ struct ieee80211_channel *chan;
+ int err;
+
+ ASSERT_WDEV_LOCK(wdev);
+
+ if (wdev->sme_state != CFG80211_SME_IDLE)
+ return -EALREADY;
+
+ chan = rdev_fixed_channel(rdev, wdev);
+ if (chan && chan != connect->channel)
+ return -EBUSY;
+
+ if (WARN_ON(wdev->connect_keys)) {
+ kfree(wdev->connect_keys);
+ wdev->connect_keys = NULL;
+ }
+
+ if (connkeys && connkeys->def >= 0) {
+ int idx;
+ u32 cipher;
+
+ idx = connkeys->def;
+ cipher = connkeys->params[idx].cipher;
+ /* If given a WEP key we may need it for shared key auth */
+ if (cipher == WLAN_CIPHER_SUITE_WEP40 ||
+ cipher == WLAN_CIPHER_SUITE_WEP104) {
+ connect->key_idx = idx;
+ connect->key = connkeys->params[idx].key;
+ connect->key_len = connkeys->params[idx].key_len;
+
+ /*
+ * If ciphers are not set (e.g. when going through
+ * iwconfig), we have to set them appropriately here.
+ */
+ if (connect->crypto.cipher_group == 0)
+ connect->crypto.cipher_group = cipher;
+
+ if (connect->crypto.n_ciphers_pairwise == 0) {
+ connect->crypto.n_ciphers_pairwise = 1;
+ connect->crypto.ciphers_pairwise[0] = cipher;
+ }
+ }
+ }
+
+ if (!rdev->ops->connect) {
+ if (!rdev->ops->auth || !rdev->ops->assoc)
+ return -EOPNOTSUPP;
+
+ if (WARN_ON(wdev->conn))
+ return -EINPROGRESS;
+
+ wdev->conn = kzalloc(sizeof(*wdev->conn), GFP_KERNEL);
+ if (!wdev->conn)
+ return -ENOMEM;
+
+ /*
+ * Copy all parameters, and treat explicitly IEs, BSSID, SSID.
+ */
+ memcpy(&wdev->conn->params, connect, sizeof(*connect));
+ if (connect->bssid) {
+ wdev->conn->params.bssid = wdev->conn->bssid;
+ memcpy(wdev->conn->bssid, connect->bssid, ETH_ALEN);
+ }
+
+ if (connect->ie) {
+ wdev->conn->ie = kmemdup(connect->ie, connect->ie_len,
+ GFP_KERNEL);
+ wdev->conn->params.ie = wdev->conn->ie;
+ if (!wdev->conn->ie) {
+ kfree(wdev->conn);
+ wdev->conn = NULL;
+ return -ENOMEM;
+ }
+ }
+
+ if (connect->auth_type == NL80211_AUTHTYPE_AUTOMATIC) {
+ wdev->conn->auto_auth = true;
+ /* start with open system ... should mostly work */
+ wdev->conn->params.auth_type =
+ NL80211_AUTHTYPE_OPEN_SYSTEM;
+ } else {
+ wdev->conn->auto_auth = false;
+ }
+
+ memcpy(wdev->ssid, connect->ssid, connect->ssid_len);
+ wdev->ssid_len = connect->ssid_len;
+ wdev->conn->params.ssid = wdev->ssid;
+ wdev->conn->params.ssid_len = connect->ssid_len;
+
+ /* don't care about result -- but fill bssid & channel */
+ if (!wdev->conn->params.bssid || !wdev->conn->params.channel)
+ cfg80211_get_conn_bss(wdev);
+
+ wdev->sme_state = CFG80211_SME_CONNECTING;
+ wdev->connect_keys = connkeys;
+
+ if (prev_bssid) {
+ memcpy(wdev->conn->prev_bssid, prev_bssid, ETH_ALEN);
+ wdev->conn->prev_bssid_valid = true;
+ }
+
+ /* we're good if we have both BSSID and channel */
+ if (wdev->conn->params.bssid && wdev->conn->params.channel) {
+ wdev->conn->state = CFG80211_CONN_AUTHENTICATE_NEXT;
+ err = cfg80211_conn_do_work(wdev);
+ } else {
+ /* otherwise we'll need to scan for the AP first */
+ err = cfg80211_conn_scan(wdev);
+ /*
+ * If we can't scan right now, then we need to scan again
+ * after the current scan finished, since the parameters
+ * changed (unless we find a good AP anyway).
+ */
+ if (err == -EBUSY) {
+ err = 0;
+ wdev->conn->state = CFG80211_CONN_SCAN_AGAIN;
+ }
+ }
+ if (err) {
+ kfree(wdev->conn);
+ wdev->conn = NULL;
+ wdev->sme_state = CFG80211_SME_IDLE;
+ wdev->connect_keys = NULL;
+ wdev->ssid_len = 0;
+ }
+
+ return err;
+ } else {
+ wdev->sme_state = CFG80211_SME_CONNECTING;
+ wdev->connect_keys = connkeys;
+ err = rdev->ops->connect(&rdev->wiphy, dev, connect);
+ if (err) {
+ wdev->connect_keys = NULL;
+ wdev->sme_state = CFG80211_SME_IDLE;
+ return err;
+ }
+
+ memcpy(wdev->ssid, connect->ssid, connect->ssid_len);
+ wdev->ssid_len = connect->ssid_len;
+
+ return 0;
+ }
+}
+
+int cfg80211_connect(struct cfg80211_registered_device *rdev,
+ struct net_device *dev,
+ struct cfg80211_connect_params *connect,
+ struct cfg80211_cached_keys *connkeys)
+{
+ int err;
+
+ mutex_lock(&rdev->devlist_mtx);
+ wdev_lock(dev->ieee80211_ptr);
+ err = __cfg80211_connect(rdev, dev, connect, connkeys, NULL);
+ wdev_unlock(dev->ieee80211_ptr);
+ mutex_unlock(&rdev->devlist_mtx);
+
+ return err;
+}
+
+int __cfg80211_disconnect(struct cfg80211_registered_device *rdev,
+ struct net_device *dev, u16 reason, bool wextev)
+{
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+ int err;
+
+ ASSERT_WDEV_LOCK(wdev);
+
+ if (wdev->sme_state == CFG80211_SME_IDLE)
+ return -EINVAL;
+
+ kfree(wdev->connect_keys);
+ wdev->connect_keys = NULL;
+
+ if (!rdev->ops->disconnect) {
+ if (!rdev->ops->deauth)
+ return -EOPNOTSUPP;
+
+ /* was it connected by userspace SME? */
+ if (!wdev->conn) {
+ cfg80211_mlme_down(rdev, dev);
+ return 0;
+ }
+
+ if (wdev->sme_state == CFG80211_SME_CONNECTING &&
+ (wdev->conn->state == CFG80211_CONN_SCANNING ||
+ wdev->conn->state == CFG80211_CONN_SCAN_AGAIN)) {
+ wdev->sme_state = CFG80211_SME_IDLE;
+ kfree(wdev->conn);
+ wdev->conn = NULL;
+ wdev->ssid_len = 0;
+ return 0;
+ }
+
+ /* wdev->conn->params.bssid must be set if > SCANNING */
+ err = __cfg80211_mlme_deauth(rdev, dev,
+ wdev->conn->params.bssid,
+ NULL, 0, reason);
+ if (err)
+ return err;
+ } else {
+ err = rdev->ops->disconnect(&rdev->wiphy, dev, reason);
+ if (err)
+ return err;
+ }
+
+ if (wdev->sme_state == CFG80211_SME_CONNECTED)
+ __cfg80211_disconnected(dev, NULL, 0, 0, false);
+ else if (wdev->sme_state == CFG80211_SME_CONNECTING)
+ __cfg80211_connect_result(dev, NULL, NULL, 0, NULL, 0,
+ WLAN_STATUS_UNSPECIFIED_FAILURE,
+ wextev, NULL);
+
+ return 0;
+}
+
+int cfg80211_disconnect(struct cfg80211_registered_device *rdev,
+ struct net_device *dev,
+ u16 reason, bool wextev)
+{
+ int err;
+
+ wdev_lock(dev->ieee80211_ptr);
+ err = __cfg80211_disconnect(rdev, dev, reason, wextev);
+ wdev_unlock(dev->ieee80211_ptr);
+
+ return err;
+}
+
+void cfg80211_sme_disassoc(struct net_device *dev, int idx)
+{
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+ struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
+ u8 bssid[ETH_ALEN];
+
+ ASSERT_WDEV_LOCK(wdev);
+
+ if (!wdev->conn)
+ return;
+
+ if (wdev->conn->state == CFG80211_CONN_IDLE)
+ return;
+
+ /*
+ * Ok, so the association was made by this SME -- we don't
+ * want it any more so deauthenticate too.
+ */
+
+ if (!wdev->auth_bsses[idx])
+ return;
+
+ memcpy(bssid, wdev->auth_bsses[idx]->pub.bssid, ETH_ALEN);
+ if (__cfg80211_mlme_deauth(rdev, dev, bssid,
+ NULL, 0, WLAN_REASON_DEAUTH_LEAVING)) {
+ /* whatever -- assume gone anyway */
+ cfg80211_unhold_bss(wdev->auth_bsses[idx]);
+ cfg80211_put_bss(&wdev->auth_bsses[idx]->pub);
+ wdev->auth_bsses[idx] = NULL;
+ }
+}
diff --git a/net/wireless/util.c b/net/wireless/util.c
index 25550692dda..693275a16a2 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -141,9 +141,12 @@ void ieee80211_set_bitrate_flags(struct wiphy *wiphy)
set_mandatory_flags_band(wiphy->bands[band], band);
}
-int cfg80211_validate_key_settings(struct key_params *params, int key_idx,
+int cfg80211_validate_key_settings(struct cfg80211_registered_device *rdev,
+ struct key_params *params, int key_idx,
const u8 *mac_addr)
{
+ int i;
+
if (key_idx > 5)
return -EINVAL;
@@ -197,6 +200,12 @@ int cfg80211_validate_key_settings(struct key_params *params, int key_idx,
}
}
+ for (i = 0; i < rdev->wiphy.n_cipher_suites; i++)
+ if (params->cipher == rdev->wiphy.cipher_suites[i])
+ break;
+ if (i == rdev->wiphy.n_cipher_suites)
+ return -EINVAL;
+
return 0;
}
@@ -265,11 +274,11 @@ static int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr)
switch (ae) {
case 0:
return 6;
- case 1:
+ case MESH_FLAGS_AE_A4:
return 12;
- case 2:
+ case MESH_FLAGS_AE_A5_A6:
return 18;
- case 3:
+ case (MESH_FLAGS_AE_A4 | MESH_FLAGS_AE_A5_A6):
return 24;
default:
return 6;
@@ -324,10 +333,18 @@ int ieee80211_data_to_8023(struct sk_buff *skb, u8 *addr,
}
break;
case cpu_to_le16(IEEE80211_FCTL_FROMDS):
- if (iftype != NL80211_IFTYPE_STATION ||
+ if ((iftype != NL80211_IFTYPE_STATION &&
+ iftype != NL80211_IFTYPE_MESH_POINT) ||
(is_multicast_ether_addr(dst) &&
!compare_ether_addr(src, addr)))
return -1;
+ if (iftype == NL80211_IFTYPE_MESH_POINT) {
+ struct ieee80211s_hdr *meshdr =
+ (struct ieee80211s_hdr *) (skb->data + hdrlen);
+ hdrlen += ieee80211_get_mesh_hdrlen(meshdr);
+ if (meshdr->flags & MESH_FLAGS_AE_A4)
+ memcpy(src, meshdr->eaddr1, ETH_ALEN);
+ }
break;
case cpu_to_le16(0):
if (iftype != NL80211_IFTYPE_ADHOC)
@@ -502,3 +519,58 @@ unsigned int cfg80211_classify8021d(struct sk_buff *skb)
return dscp >> 5;
}
EXPORT_SYMBOL(cfg80211_classify8021d);
+
+const u8 *ieee80211_bss_get_ie(struct cfg80211_bss *bss, u8 ie)
+{
+ u8 *end, *pos;
+
+ pos = bss->information_elements;
+ if (pos == NULL)
+ return NULL;
+ end = pos + bss->len_information_elements;
+
+ while (pos + 1 < end) {
+ if (pos + 2 + pos[1] > end)
+ break;
+ if (pos[0] == ie)
+ return pos;
+ pos += 2 + pos[1];
+ }
+
+ return NULL;
+}
+EXPORT_SYMBOL(ieee80211_bss_get_ie);
+
+void cfg80211_upload_connect_keys(struct wireless_dev *wdev)
+{
+ struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
+ struct net_device *dev = wdev->netdev;
+ int i;
+
+ if (!wdev->connect_keys)
+ return;
+
+ for (i = 0; i < 6; i++) {
+ if (!wdev->connect_keys->params[i].cipher)
+ continue;
+ if (rdev->ops->add_key(wdev->wiphy, dev, i, NULL,
+ &wdev->connect_keys->params[i])) {
+ printk(KERN_ERR "%s: failed to set key %d\n",
+ dev->name, i);
+ continue;
+ }
+ if (wdev->connect_keys->def == i)
+ if (rdev->ops->set_default_key(wdev->wiphy, dev, i)) {
+ printk(KERN_ERR "%s: failed to set defkey %d\n",
+ dev->name, i);
+ continue;
+ }
+ if (wdev->connect_keys->defmgmt == i)
+ if (rdev->ops->set_default_mgmt_key(wdev->wiphy, dev, i))
+ printk(KERN_ERR "%s: failed to set mgtdef %d\n",
+ dev->name, i);
+ }
+
+ kfree(wdev->connect_keys);
+ wdev->connect_keys = NULL;
+}
diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c
index d030c531567..c4491749221 100644
--- a/net/wireless/wext-compat.c
+++ b/net/wireless/wext-compat.c
@@ -14,6 +14,7 @@
#include <linux/etherdevice.h>
#include <net/iw_handler.h>
#include <net/cfg80211.h>
+#include "wext-compat.h"
#include "core.h"
int cfg80211_wext_giwname(struct net_device *dev,
@@ -103,7 +104,7 @@ int cfg80211_wext_siwmode(struct net_device *dev, struct iw_request_info *info,
memset(&vifparams, 0, sizeof(vifparams));
- ret = rdev->ops->change_virtual_intf(wdev->wiphy, dev->ifindex, type,
+ ret = rdev->ops->change_virtual_intf(wdev->wiphy, dev, type,
NULL, &vifparams);
WARN_ON(!ret && wdev->iftype != type);
@@ -154,7 +155,7 @@ int cfg80211_wext_giwrange(struct net_device *dev,
struct wireless_dev *wdev = dev->ieee80211_ptr;
struct iw_range *range = (struct iw_range *) extra;
enum ieee80211_band band;
- int c = 0;
+ int i, c = 0;
if (!wdev)
return -EOPNOTSUPP;
@@ -173,9 +174,6 @@ int cfg80211_wext_giwrange(struct net_device *dev,
range->min_frag = 256;
range->max_frag = 2346;
- range->encoding_size[0] = 5;
- range->encoding_size[1] = 13;
- range->num_encoding_sizes = 2;
range->max_encoding_tokens = 4;
range->max_qual.updated = IW_QUAL_NOISE_INVALID;
@@ -204,11 +202,31 @@ int cfg80211_wext_giwrange(struct net_device *dev,
range->avg_qual.noise = range->max_qual.noise / 2;
range->avg_qual.updated = range->max_qual.updated;
- range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 |
- IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP;
+ for (i = 0; i < wdev->wiphy->n_cipher_suites; i++) {
+ switch (wdev->wiphy->cipher_suites[i]) {
+ case WLAN_CIPHER_SUITE_TKIP:
+ range->enc_capa |= (IW_ENC_CAPA_CIPHER_TKIP |
+ IW_ENC_CAPA_WPA);
+ break;
+
+ case WLAN_CIPHER_SUITE_CCMP:
+ range->enc_capa |= (IW_ENC_CAPA_CIPHER_CCMP |
+ IW_ENC_CAPA_WPA2);
+ break;
+
+ case WLAN_CIPHER_SUITE_WEP40:
+ range->encoding_size[range->num_encoding_sizes++] =
+ WLAN_KEY_LEN_WEP40;
+ break;
+
+ case WLAN_CIPHER_SUITE_WEP104:
+ range->encoding_size[range->num_encoding_sizes++] =
+ WLAN_KEY_LEN_WEP104;
+ break;
+ }
+ }
for (band = 0; band < IEEE80211_NUM_BANDS; band ++) {
- int i;
struct ieee80211_supported_band *sband;
sband = wdev->wiphy->bands[band];
@@ -236,97 +254,40 @@ int cfg80211_wext_giwrange(struct net_device *dev,
IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWAP);
IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWSCAN);
- range->scan_capa |= IW_SCAN_CAPA_ESSID;
+ if (wdev->wiphy->max_scan_ssids > 0)
+ range->scan_capa |= IW_SCAN_CAPA_ESSID;
return 0;
}
EXPORT_SYMBOL_GPL(cfg80211_wext_giwrange);
-int cfg80211_wext_siwmlme(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_point *data, char *extra)
-{
- struct wireless_dev *wdev = dev->ieee80211_ptr;
- struct iw_mlme *mlme = (struct iw_mlme *)extra;
- struct cfg80211_registered_device *rdev;
- union {
- struct cfg80211_disassoc_request disassoc;
- struct cfg80211_deauth_request deauth;
- } cmd;
-
- if (!wdev)
- return -EOPNOTSUPP;
-
- rdev = wiphy_to_dev(wdev->wiphy);
-
- if (wdev->iftype != NL80211_IFTYPE_STATION)
- return -EINVAL;
-
- if (mlme->addr.sa_family != ARPHRD_ETHER)
- return -EINVAL;
-
- memset(&cmd, 0, sizeof(cmd));
-
- switch (mlme->cmd) {
- case IW_MLME_DEAUTH:
- if (!rdev->ops->deauth)
- return -EOPNOTSUPP;
- cmd.deauth.peer_addr = mlme->addr.sa_data;
- cmd.deauth.reason_code = mlme->reason_code;
- return rdev->ops->deauth(wdev->wiphy, dev, &cmd.deauth);
- case IW_MLME_DISASSOC:
- if (!rdev->ops->disassoc)
- return -EOPNOTSUPP;
- cmd.disassoc.peer_addr = mlme->addr.sa_data;
- cmd.disassoc.reason_code = mlme->reason_code;
- return rdev->ops->disassoc(wdev->wiphy, dev, &cmd.disassoc);
- default:
- return -EOPNOTSUPP;
- }
-}
-EXPORT_SYMBOL_GPL(cfg80211_wext_siwmlme);
-
/**
* cfg80211_wext_freq - get wext frequency for non-"auto"
* @wiphy: the wiphy
* @freq: the wext freq encoding
*
- * Returns a channel, %NULL for auto, or an ERR_PTR for errors!
+ * Returns a frequency, or a negative error code, or 0 for auto.
*/
-struct ieee80211_channel *cfg80211_wext_freq(struct wiphy *wiphy,
- struct iw_freq *freq)
+int cfg80211_wext_freq(struct wiphy *wiphy, struct iw_freq *freq)
{
- struct ieee80211_channel *chan;
- int f;
-
/*
- * Parse frequency - return NULL for auto and
+ * Parse frequency - return 0 for auto and
* -EINVAL for impossible things.
*/
if (freq->e == 0) {
if (freq->m < 0)
- return NULL;
- f = ieee80211_channel_to_frequency(freq->m);
+ return 0;
+ return ieee80211_channel_to_frequency(freq->m);
} else {
int i, div = 1000000;
for (i = 0; i < freq->e; i++)
div /= 10;
if (div <= 0)
- return ERR_PTR(-EINVAL);
- f = freq->m / div;
+ return -EINVAL;
+ return freq->m / div;
}
-
- /*
- * Look up channel struct and return -EINVAL when
- * it cannot be found.
- */
- chan = ieee80211_get_channel(wiphy, f);
- if (!chan)
- return ERR_PTR(-EINVAL);
- return chan;
}
-EXPORT_SYMBOL_GPL(cfg80211_wext_freq);
int cfg80211_wext_siwrts(struct net_device *dev,
struct iw_request_info *info,
@@ -479,15 +440,32 @@ int cfg80211_wext_giwretry(struct net_device *dev,
}
EXPORT_SYMBOL_GPL(cfg80211_wext_giwretry);
-static int cfg80211_set_encryption(struct cfg80211_registered_device *rdev,
- struct net_device *dev, const u8 *addr,
- bool remove, bool tx_key, int idx,
- struct key_params *params)
+static int __cfg80211_set_encryption(struct cfg80211_registered_device *rdev,
+ struct net_device *dev, const u8 *addr,
+ bool remove, bool tx_key, int idx,
+ struct key_params *params)
{
struct wireless_dev *wdev = dev->ieee80211_ptr;
- int err;
+ int err, i;
+
+ if (!wdev->wext.keys) {
+ wdev->wext.keys = kzalloc(sizeof(*wdev->wext.keys),
+ GFP_KERNEL);
+ if (!wdev->wext.keys)
+ return -ENOMEM;
+ for (i = 0; i < 6; i++)
+ wdev->wext.keys->params[i].key =
+ wdev->wext.keys->data[i];
+ }
+
+ if (wdev->iftype != NL80211_IFTYPE_ADHOC &&
+ wdev->iftype != NL80211_IFTYPE_STATION)
+ return -EOPNOTSUPP;
if (params->cipher == WLAN_CIPHER_SUITE_AES_CMAC) {
+ if (!wdev->current_bss)
+ return -ENOLINK;
+
if (!rdev->ops->set_default_mgmt_key)
return -EOPNOTSUPP;
@@ -497,8 +475,14 @@ static int cfg80211_set_encryption(struct cfg80211_registered_device *rdev,
return -EINVAL;
if (remove) {
- err = rdev->ops->del_key(&rdev->wiphy, dev, idx, addr);
+ err = 0;
+ if (wdev->current_bss)
+ err = rdev->ops->del_key(&rdev->wiphy, dev, idx, addr);
if (!err) {
+ if (!addr) {
+ wdev->wext.keys->params[idx].key_len = 0;
+ wdev->wext.keys->params[idx].cipher = 0;
+ }
if (idx == wdev->wext.default_key)
wdev->wext.default_key = -1;
else if (idx == wdev->wext.default_mgmt_key)
@@ -512,36 +496,65 @@ static int cfg80211_set_encryption(struct cfg80211_registered_device *rdev,
return 0;
return err;
- } else {
- if (addr)
- tx_key = false;
+ }
- if (cfg80211_validate_key_settings(params, idx, addr))
- return -EINVAL;
+ if (addr)
+ tx_key = false;
+ if (cfg80211_validate_key_settings(rdev, params, idx, addr))
+ return -EINVAL;
+
+ err = 0;
+ if (wdev->current_bss)
err = rdev->ops->add_key(&rdev->wiphy, dev, idx, addr, params);
- if (err)
- return err;
+ if (err)
+ return err;
+
+ if (!addr) {
+ wdev->wext.keys->params[idx] = *params;
+ memcpy(wdev->wext.keys->data[idx],
+ params->key, params->key_len);
+ wdev->wext.keys->params[idx].key =
+ wdev->wext.keys->data[idx];
+ }
- if (tx_key || (!addr && wdev->wext.default_key == -1)) {
+ if ((params->cipher == WLAN_CIPHER_SUITE_WEP40 ||
+ params->cipher == WLAN_CIPHER_SUITE_WEP104) &&
+ (tx_key || (!addr && wdev->wext.default_key == -1))) {
+ if (wdev->current_bss)
err = rdev->ops->set_default_key(&rdev->wiphy,
dev, idx);
- if (!err)
- wdev->wext.default_key = idx;
- return err;
- }
+ if (!err)
+ wdev->wext.default_key = idx;
+ return err;
+ }
- if (params->cipher == WLAN_CIPHER_SUITE_AES_CMAC &&
- (tx_key || (!addr && wdev->wext.default_mgmt_key == -1))) {
+ if (params->cipher == WLAN_CIPHER_SUITE_AES_CMAC &&
+ (tx_key || (!addr && wdev->wext.default_mgmt_key == -1))) {
+ if (wdev->current_bss)
err = rdev->ops->set_default_mgmt_key(&rdev->wiphy,
dev, idx);
- if (!err)
- wdev->wext.default_mgmt_key = idx;
- return err;
- }
-
- return 0;
+ if (!err)
+ wdev->wext.default_mgmt_key = idx;
+ return err;
}
+
+ return 0;
+}
+
+static int cfg80211_set_encryption(struct cfg80211_registered_device *rdev,
+ struct net_device *dev, const u8 *addr,
+ bool remove, bool tx_key, int idx,
+ struct key_params *params)
+{
+ int err;
+
+ wdev_lock(dev->ieee80211_ptr);
+ err = __cfg80211_set_encryption(rdev, dev, addr, remove,
+ tx_key, idx, params);
+ wdev_unlock(dev->ieee80211_ptr);
+
+ return err;
}
int cfg80211_wext_siwencode(struct net_device *dev,
@@ -554,6 +567,10 @@ int cfg80211_wext_siwencode(struct net_device *dev,
bool remove = false;
struct key_params params;
+ if (wdev->iftype != NL80211_IFTYPE_STATION &&
+ wdev->iftype != NL80211_IFTYPE_ADHOC)
+ return -EOPNOTSUPP;
+
/* no use -- only MFP (set_default_mgmt_key) is optional */
if (!rdev->ops->del_key ||
!rdev->ops->add_key ||
@@ -574,9 +591,14 @@ int cfg80211_wext_siwencode(struct net_device *dev,
remove = true;
else if (erq->length == 0) {
/* No key data - just set the default TX key index */
- err = rdev->ops->set_default_key(&rdev->wiphy, dev, idx);
+ err = 0;
+ wdev_lock(wdev);
+ if (wdev->current_bss)
+ err = rdev->ops->set_default_key(&rdev->wiphy,
+ dev, idx);
if (!err)
wdev->wext.default_key = idx;
+ wdev_unlock(wdev);
return err;
}
@@ -609,6 +631,10 @@ int cfg80211_wext_siwencodeext(struct net_device *dev,
struct key_params params;
u32 cipher;
+ if (wdev->iftype != NL80211_IFTYPE_STATION &&
+ wdev->iftype != NL80211_IFTYPE_ADHOC)
+ return -EOPNOTSUPP;
+
/* no use -- only MFP (set_default_mgmt_key) is optional */
if (!rdev->ops->del_key ||
!rdev->ops->add_key ||
@@ -682,37 +708,15 @@ int cfg80211_wext_siwencodeext(struct net_device *dev,
}
EXPORT_SYMBOL_GPL(cfg80211_wext_siwencodeext);
-struct giwencode_cookie {
- size_t buflen;
- char *keybuf;
-};
-
-static void giwencode_get_key_cb(void *cookie, struct key_params *params)
-{
- struct giwencode_cookie *data = cookie;
-
- if (!params->key) {
- data->buflen = 0;
- return;
- }
-
- data->buflen = min_t(size_t, data->buflen, params->key_len);
- memcpy(data->keybuf, params->key, data->buflen);
-}
-
int cfg80211_wext_giwencode(struct net_device *dev,
struct iw_request_info *info,
struct iw_point *erq, char *keybuf)
{
struct wireless_dev *wdev = dev->ieee80211_ptr;
- struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
- int idx, err;
- struct giwencode_cookie data = {
- .keybuf = keybuf,
- .buflen = erq->length,
- };
+ int idx;
- if (!rdev->ops->get_key)
+ if (wdev->iftype != NL80211_IFTYPE_STATION &&
+ wdev->iftype != NL80211_IFTYPE_ADHOC)
return -EOPNOTSUPP;
idx = erq->flags & IW_ENCODE_INDEX;
@@ -727,24 +731,69 @@ int cfg80211_wext_giwencode(struct net_device *dev,
erq->flags = idx + 1;
- err = rdev->ops->get_key(&rdev->wiphy, dev, idx, NULL, &data,
- giwencode_get_key_cb);
- if (!err) {
- erq->length = data.buflen;
- erq->flags |= IW_ENCODE_ENABLED;
- return 0;
- }
-
- if (err == -ENOENT) {
+ if (!wdev->wext.keys || !wdev->wext.keys->params[idx].cipher) {
erq->flags |= IW_ENCODE_DISABLED;
erq->length = 0;
return 0;
}
- return err;
+ erq->length = min_t(size_t, erq->length,
+ wdev->wext.keys->params[idx].key_len);
+ memcpy(keybuf, wdev->wext.keys->params[idx].key, erq->length);
+ erq->flags |= IW_ENCODE_ENABLED;
+
+ return 0;
}
EXPORT_SYMBOL_GPL(cfg80211_wext_giwencode);
+int cfg80211_wext_siwfreq(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_freq *wextfreq, char *extra)
+{
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+ struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
+ int freq, err;
+
+ switch (wdev->iftype) {
+ case NL80211_IFTYPE_STATION:
+ return cfg80211_mgd_wext_siwfreq(dev, info, wextfreq, extra);
+ case NL80211_IFTYPE_ADHOC:
+ return cfg80211_ibss_wext_siwfreq(dev, info, wextfreq, extra);
+ default:
+ freq = cfg80211_wext_freq(wdev->wiphy, wextfreq);
+ if (freq < 0)
+ return freq;
+ if (freq == 0)
+ return -EINVAL;
+ mutex_lock(&rdev->devlist_mtx);
+ err = rdev_set_freq(rdev, NULL, freq, NL80211_CHAN_NO_HT);
+ mutex_unlock(&rdev->devlist_mtx);
+ return err;
+ }
+}
+
+int cfg80211_wext_giwfreq(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_freq *freq, char *extra)
+{
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+ struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
+
+ switch (wdev->iftype) {
+ case NL80211_IFTYPE_STATION:
+ return cfg80211_mgd_wext_giwfreq(dev, info, freq, extra);
+ case NL80211_IFTYPE_ADHOC:
+ return cfg80211_ibss_wext_giwfreq(dev, info, freq, extra);
+ default:
+ if (!rdev->channel)
+ return -EINVAL;
+ freq->m = rdev->channel->center_freq;
+ freq->e = 6;
+ return 0;
+ }
+}
+EXPORT_SYMBOL_GPL(cfg80211_wext_giwfreq);
+
int cfg80211_wext_siwtxpower(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *data, char *extra)
@@ -827,3 +876,547 @@ int cfg80211_wext_giwtxpower(struct net_device *dev,
return 0;
}
EXPORT_SYMBOL_GPL(cfg80211_wext_giwtxpower);
+
+static int cfg80211_set_auth_alg(struct wireless_dev *wdev,
+ s32 auth_alg)
+{
+ int nr_alg = 0;
+
+ if (!auth_alg)
+ return -EINVAL;
+
+ if (auth_alg & ~(IW_AUTH_ALG_OPEN_SYSTEM |
+ IW_AUTH_ALG_SHARED_KEY |
+ IW_AUTH_ALG_LEAP))
+ return -EINVAL;
+
+ if (auth_alg & IW_AUTH_ALG_OPEN_SYSTEM) {
+ nr_alg++;
+ wdev->wext.connect.auth_type = NL80211_AUTHTYPE_OPEN_SYSTEM;
+ }
+
+ if (auth_alg & IW_AUTH_ALG_SHARED_KEY) {
+ nr_alg++;
+ wdev->wext.connect.auth_type = NL80211_AUTHTYPE_SHARED_KEY;
+ }
+
+ if (auth_alg & IW_AUTH_ALG_LEAP) {
+ nr_alg++;
+ wdev->wext.connect.auth_type = NL80211_AUTHTYPE_NETWORK_EAP;
+ }
+
+ if (nr_alg > 1)
+ wdev->wext.connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC;
+
+ return 0;
+}
+
+static int cfg80211_set_wpa_version(struct wireless_dev *wdev, u32 wpa_versions)
+{
+ wdev->wext.connect.crypto.wpa_versions = 0;
+
+ if (wpa_versions & ~(IW_AUTH_WPA_VERSION_WPA |
+ IW_AUTH_WPA_VERSION_WPA2|
+ IW_AUTH_WPA_VERSION_DISABLED))
+ return -EINVAL;
+
+ if ((wpa_versions & IW_AUTH_WPA_VERSION_DISABLED) &&
+ (wpa_versions & (IW_AUTH_WPA_VERSION_WPA|
+ IW_AUTH_WPA_VERSION_WPA2)))
+ return -EINVAL;
+
+ if (wpa_versions & IW_AUTH_WPA_VERSION_DISABLED)
+ wdev->wext.connect.crypto.wpa_versions &=
+ ~(NL80211_WPA_VERSION_1|NL80211_WPA_VERSION_2);
+
+ if (wpa_versions & IW_AUTH_WPA_VERSION_WPA)
+ wdev->wext.connect.crypto.wpa_versions |=
+ NL80211_WPA_VERSION_1;
+
+ if (wpa_versions & IW_AUTH_WPA_VERSION_WPA2)
+ wdev->wext.connect.crypto.wpa_versions |=
+ NL80211_WPA_VERSION_2;
+
+ return 0;
+}
+
+static int cfg80211_set_cipher_group(struct wireless_dev *wdev, u32 cipher)
+{
+ wdev->wext.connect.crypto.cipher_group = 0;
+
+ if (cipher & IW_AUTH_CIPHER_WEP40)
+ wdev->wext.connect.crypto.cipher_group =
+ WLAN_CIPHER_SUITE_WEP40;
+ else if (cipher & IW_AUTH_CIPHER_WEP104)
+ wdev->wext.connect.crypto.cipher_group =
+ WLAN_CIPHER_SUITE_WEP104;
+ else if (cipher & IW_AUTH_CIPHER_TKIP)
+ wdev->wext.connect.crypto.cipher_group =
+ WLAN_CIPHER_SUITE_TKIP;
+ else if (cipher & IW_AUTH_CIPHER_CCMP)
+ wdev->wext.connect.crypto.cipher_group =
+ WLAN_CIPHER_SUITE_CCMP;
+ else if (cipher & IW_AUTH_CIPHER_AES_CMAC)
+ wdev->wext.connect.crypto.cipher_group =
+ WLAN_CIPHER_SUITE_AES_CMAC;
+ else
+ return -EINVAL;
+
+ return 0;
+}
+
+static int cfg80211_set_cipher_pairwise(struct wireless_dev *wdev, u32 cipher)
+{
+ int nr_ciphers = 0;
+ u32 *ciphers_pairwise = wdev->wext.connect.crypto.ciphers_pairwise;
+
+ if (cipher & IW_AUTH_CIPHER_WEP40) {
+ ciphers_pairwise[nr_ciphers] = WLAN_CIPHER_SUITE_WEP40;
+ nr_ciphers++;
+ }
+
+ if (cipher & IW_AUTH_CIPHER_WEP104) {
+ ciphers_pairwise[nr_ciphers] = WLAN_CIPHER_SUITE_WEP104;
+ nr_ciphers++;
+ }
+
+ if (cipher & IW_AUTH_CIPHER_TKIP) {
+ ciphers_pairwise[nr_ciphers] = WLAN_CIPHER_SUITE_TKIP;
+ nr_ciphers++;
+ }
+
+ if (cipher & IW_AUTH_CIPHER_CCMP) {
+ ciphers_pairwise[nr_ciphers] = WLAN_CIPHER_SUITE_CCMP;
+ nr_ciphers++;
+ }
+
+ if (cipher & IW_AUTH_CIPHER_AES_CMAC) {
+ ciphers_pairwise[nr_ciphers] = WLAN_CIPHER_SUITE_AES_CMAC;
+ nr_ciphers++;
+ }
+
+ BUILD_BUG_ON(NL80211_MAX_NR_CIPHER_SUITES < 5);
+
+ wdev->wext.connect.crypto.n_ciphers_pairwise = nr_ciphers;
+
+ return 0;
+}
+
+
+static int cfg80211_set_key_mgt(struct wireless_dev *wdev, u32 key_mgt)
+{
+ int nr_akm_suites = 0;
+
+ if (key_mgt & ~(IW_AUTH_KEY_MGMT_802_1X |
+ IW_AUTH_KEY_MGMT_PSK))
+ return -EINVAL;
+
+ if (key_mgt & IW_AUTH_KEY_MGMT_802_1X) {
+ wdev->wext.connect.crypto.akm_suites[nr_akm_suites] =
+ WLAN_AKM_SUITE_8021X;
+ nr_akm_suites++;
+ }
+
+ if (key_mgt & IW_AUTH_KEY_MGMT_PSK) {
+ wdev->wext.connect.crypto.akm_suites[nr_akm_suites] =
+ WLAN_AKM_SUITE_PSK;
+ nr_akm_suites++;
+ }
+
+ wdev->wext.connect.crypto.n_akm_suites = nr_akm_suites;
+
+ return 0;
+}
+
+int cfg80211_wext_siwauth(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *data, char *extra)
+{
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+
+ if (wdev->iftype != NL80211_IFTYPE_STATION)
+ return -EOPNOTSUPP;
+
+ switch (data->flags & IW_AUTH_INDEX) {
+ case IW_AUTH_PRIVACY_INVOKED:
+ wdev->wext.connect.privacy = data->value;
+ return 0;
+ case IW_AUTH_WPA_VERSION:
+ return cfg80211_set_wpa_version(wdev, data->value);
+ case IW_AUTH_CIPHER_GROUP:
+ return cfg80211_set_cipher_group(wdev, data->value);
+ case IW_AUTH_KEY_MGMT:
+ return cfg80211_set_key_mgt(wdev, data->value);
+ case IW_AUTH_CIPHER_PAIRWISE:
+ return cfg80211_set_cipher_pairwise(wdev, data->value);
+ case IW_AUTH_80211_AUTH_ALG:
+ return cfg80211_set_auth_alg(wdev, data->value);
+ case IW_AUTH_WPA_ENABLED:
+ case IW_AUTH_RX_UNENCRYPTED_EAPOL:
+ case IW_AUTH_DROP_UNENCRYPTED:
+ case IW_AUTH_MFP:
+ return 0;
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+EXPORT_SYMBOL_GPL(cfg80211_wext_siwauth);
+
+int cfg80211_wext_giwauth(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *data, char *extra)
+{
+ /* XXX: what do we need? */
+
+ return -EOPNOTSUPP;
+}
+EXPORT_SYMBOL_GPL(cfg80211_wext_giwauth);
+
+int cfg80211_wext_siwpower(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *wrq, char *extra)
+{
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+ struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
+ bool ps = wdev->wext.ps;
+ int timeout = wdev->wext.ps_timeout;
+ int err;
+
+ if (wdev->iftype != NL80211_IFTYPE_STATION)
+ return -EINVAL;
+
+ if (!rdev->ops->set_power_mgmt)
+ return -EOPNOTSUPP;
+
+ if (wrq->disabled) {
+ ps = false;
+ } else {
+ switch (wrq->flags & IW_POWER_MODE) {
+ case IW_POWER_ON: /* If not specified */
+ case IW_POWER_MODE: /* If set all mask */
+ case IW_POWER_ALL_R: /* If explicitely state all */
+ ps = true;
+ break;
+ default: /* Otherwise we ignore */
+ return -EINVAL;
+ }
+
+ if (wrq->flags & ~(IW_POWER_MODE | IW_POWER_TIMEOUT))
+ return -EINVAL;
+
+ if (wrq->flags & IW_POWER_TIMEOUT)
+ timeout = wrq->value / 1000;
+ }
+
+ err = rdev->ops->set_power_mgmt(wdev->wiphy, dev, ps, timeout);
+ if (err)
+ return err;
+
+ wdev->wext.ps = ps;
+ wdev->wext.ps_timeout = timeout;
+
+ return 0;
+
+}
+EXPORT_SYMBOL_GPL(cfg80211_wext_siwpower);
+
+int cfg80211_wext_giwpower(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *wrq, char *extra)
+{
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+
+ wrq->disabled = !wdev->wext.ps;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(cfg80211_wext_giwpower);
+
+static int cfg80211_wds_wext_siwap(struct net_device *dev,
+ struct iw_request_info *info,
+ struct sockaddr *addr, char *extra)
+{
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+ struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
+ int err;
+
+ if (WARN_ON(wdev->iftype != NL80211_IFTYPE_WDS))
+ return -EINVAL;
+
+ if (addr->sa_family != ARPHRD_ETHER)
+ return -EINVAL;
+
+ if (netif_running(dev))
+ return -EBUSY;
+
+ if (!rdev->ops->set_wds_peer)
+ return -EOPNOTSUPP;
+
+ err = rdev->ops->set_wds_peer(wdev->wiphy, dev, (u8 *) &addr->sa_data);
+ if (err)
+ return err;
+
+ memcpy(&wdev->wext.bssid, (u8 *) &addr->sa_data, ETH_ALEN);
+
+ return 0;
+}
+
+static int cfg80211_wds_wext_giwap(struct net_device *dev,
+ struct iw_request_info *info,
+ struct sockaddr *addr, char *extra)
+{
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+
+ if (WARN_ON(wdev->iftype != NL80211_IFTYPE_WDS))
+ return -EINVAL;
+
+ addr->sa_family = ARPHRD_ETHER;
+ memcpy(&addr->sa_data, wdev->wext.bssid, ETH_ALEN);
+
+ return 0;
+}
+
+int cfg80211_wext_siwrate(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *rate, char *extra)
+{
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+ struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
+ struct cfg80211_bitrate_mask mask;
+
+ if (!rdev->ops->set_bitrate_mask)
+ return -EOPNOTSUPP;
+
+ mask.fixed = 0;
+ mask.maxrate = 0;
+
+ if (rate->value < 0) {
+ /* nothing */
+ } else if (rate->fixed) {
+ mask.fixed = rate->value / 1000; /* kbps */
+ } else {
+ mask.maxrate = rate->value / 1000; /* kbps */
+ }
+
+ return rdev->ops->set_bitrate_mask(wdev->wiphy, dev, NULL, &mask);
+}
+EXPORT_SYMBOL_GPL(cfg80211_wext_siwrate);
+
+int cfg80211_wext_giwrate(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *rate, char *extra)
+{
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+ struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
+ /* we are under RTNL - globally locked - so can use a static struct */
+ static struct station_info sinfo;
+ u8 addr[ETH_ALEN];
+ int err;
+
+ if (wdev->iftype != NL80211_IFTYPE_STATION)
+ return -EOPNOTSUPP;
+
+ if (!rdev->ops->get_station)
+ return -EOPNOTSUPP;
+
+ err = 0;
+ wdev_lock(wdev);
+ if (wdev->current_bss)
+ memcpy(addr, wdev->current_bss->pub.bssid, ETH_ALEN);
+ else
+ err = -EOPNOTSUPP;
+ wdev_unlock(wdev);
+ if (err)
+ return err;
+
+ err = rdev->ops->get_station(&rdev->wiphy, dev, addr, &sinfo);
+ if (err)
+ return err;
+
+ if (!(sinfo.filled & STATION_INFO_TX_BITRATE))
+ return -EOPNOTSUPP;
+
+ rate->value = 0;
+
+ if (!(sinfo.txrate.flags & RATE_INFO_FLAGS_MCS))
+ rate->value = 100000 * sinfo.txrate.legacy;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(cfg80211_wext_giwrate);
+
+/* Get wireless statistics. Called by /proc/net/wireless and by SIOCGIWSTATS */
+struct iw_statistics *cfg80211_wireless_stats(struct net_device *dev)
+{
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+ struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
+ /* we are under RTNL - globally locked - so can use static structs */
+ static struct iw_statistics wstats;
+ static struct station_info sinfo;
+ u8 bssid[ETH_ALEN];
+
+ if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION)
+ return NULL;
+
+ if (!rdev->ops->get_station)
+ return NULL;
+
+ /* Grab BSSID of current BSS, if any */
+ wdev_lock(wdev);
+ if (!wdev->current_bss) {
+ wdev_unlock(wdev);
+ return NULL;
+ }
+ memcpy(bssid, wdev->current_bss->pub.bssid, ETH_ALEN);
+ wdev_unlock(wdev);
+
+ if (rdev->ops->get_station(&rdev->wiphy, dev, bssid, &sinfo))
+ return NULL;
+
+ memset(&wstats, 0, sizeof(wstats));
+
+ switch (rdev->wiphy.signal_type) {
+ case CFG80211_SIGNAL_TYPE_MBM:
+ if (sinfo.filled & STATION_INFO_SIGNAL) {
+ int sig = sinfo.signal;
+ wstats.qual.updated |= IW_QUAL_LEVEL_UPDATED;
+ wstats.qual.updated |= IW_QUAL_QUAL_UPDATED;
+ wstats.qual.updated |= IW_QUAL_DBM;
+ wstats.qual.level = sig;
+ if (sig < -110)
+ sig = -110;
+ else if (sig > -40)
+ sig = -40;
+ wstats.qual.qual = sig + 110;
+ break;
+ }
+ case CFG80211_SIGNAL_TYPE_UNSPEC:
+ if (sinfo.filled & STATION_INFO_SIGNAL) {
+ wstats.qual.updated |= IW_QUAL_LEVEL_UPDATED;
+ wstats.qual.updated |= IW_QUAL_QUAL_UPDATED;
+ wstats.qual.level = sinfo.signal;
+ wstats.qual.qual = sinfo.signal;
+ break;
+ }
+ default:
+ wstats.qual.updated |= IW_QUAL_LEVEL_INVALID;
+ wstats.qual.updated |= IW_QUAL_QUAL_INVALID;
+ }
+
+ wstats.qual.updated |= IW_QUAL_NOISE_INVALID;
+
+ return &wstats;
+}
+EXPORT_SYMBOL_GPL(cfg80211_wireless_stats);
+
+int cfg80211_wext_siwap(struct net_device *dev,
+ struct iw_request_info *info,
+ struct sockaddr *ap_addr, char *extra)
+{
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+
+ switch (wdev->iftype) {
+ case NL80211_IFTYPE_ADHOC:
+ return cfg80211_ibss_wext_siwap(dev, info, ap_addr, extra);
+ case NL80211_IFTYPE_STATION:
+ return cfg80211_mgd_wext_siwap(dev, info, ap_addr, extra);
+ case NL80211_IFTYPE_WDS:
+ return cfg80211_wds_wext_siwap(dev, info, ap_addr, extra);
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+EXPORT_SYMBOL_GPL(cfg80211_wext_siwap);
+
+int cfg80211_wext_giwap(struct net_device *dev,
+ struct iw_request_info *info,
+ struct sockaddr *ap_addr, char *extra)
+{
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+
+ switch (wdev->iftype) {
+ case NL80211_IFTYPE_ADHOC:
+ return cfg80211_ibss_wext_giwap(dev, info, ap_addr, extra);
+ case NL80211_IFTYPE_STATION:
+ return cfg80211_mgd_wext_giwap(dev, info, ap_addr, extra);
+ case NL80211_IFTYPE_WDS:
+ return cfg80211_wds_wext_giwap(dev, info, ap_addr, extra);
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+EXPORT_SYMBOL_GPL(cfg80211_wext_giwap);
+
+int cfg80211_wext_siwessid(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *data, char *ssid)
+{
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+
+ switch (wdev->iftype) {
+ case NL80211_IFTYPE_ADHOC:
+ return cfg80211_ibss_wext_siwessid(dev, info, data, ssid);
+ case NL80211_IFTYPE_STATION:
+ return cfg80211_mgd_wext_siwessid(dev, info, data, ssid);
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+EXPORT_SYMBOL_GPL(cfg80211_wext_siwessid);
+
+int cfg80211_wext_giwessid(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *data, char *ssid)
+{
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+
+ switch (wdev->iftype) {
+ case NL80211_IFTYPE_ADHOC:
+ return cfg80211_ibss_wext_giwessid(dev, info, data, ssid);
+ case NL80211_IFTYPE_STATION:
+ return cfg80211_mgd_wext_giwessid(dev, info, data, ssid);
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+EXPORT_SYMBOL_GPL(cfg80211_wext_giwessid);
+
+static const iw_handler cfg80211_handlers[] = {
+ [IW_IOCTL_IDX(SIOCGIWNAME)] = (iw_handler) cfg80211_wext_giwname,
+ [IW_IOCTL_IDX(SIOCSIWFREQ)] = (iw_handler) cfg80211_wext_siwfreq,
+ [IW_IOCTL_IDX(SIOCGIWFREQ)] = (iw_handler) cfg80211_wext_giwfreq,
+ [IW_IOCTL_IDX(SIOCSIWMODE)] = (iw_handler) cfg80211_wext_siwmode,
+ [IW_IOCTL_IDX(SIOCGIWMODE)] = (iw_handler) cfg80211_wext_giwmode,
+ [IW_IOCTL_IDX(SIOCGIWRANGE)] = (iw_handler) cfg80211_wext_giwrange,
+ [IW_IOCTL_IDX(SIOCSIWAP)] = (iw_handler) cfg80211_wext_siwap,
+ [IW_IOCTL_IDX(SIOCGIWAP)] = (iw_handler) cfg80211_wext_giwap,
+ [IW_IOCTL_IDX(SIOCSIWMLME)] = (iw_handler) cfg80211_wext_siwmlme,
+ [IW_IOCTL_IDX(SIOCSIWSCAN)] = (iw_handler) cfg80211_wext_siwscan,
+ [IW_IOCTL_IDX(SIOCGIWSCAN)] = (iw_handler) cfg80211_wext_giwscan,
+ [IW_IOCTL_IDX(SIOCSIWESSID)] = (iw_handler) cfg80211_wext_siwessid,
+ [IW_IOCTL_IDX(SIOCGIWESSID)] = (iw_handler) cfg80211_wext_giwessid,
+ [IW_IOCTL_IDX(SIOCSIWRATE)] = (iw_handler) cfg80211_wext_siwrate,
+ [IW_IOCTL_IDX(SIOCGIWRATE)] = (iw_handler) cfg80211_wext_giwrate,
+ [IW_IOCTL_IDX(SIOCSIWRTS)] = (iw_handler) cfg80211_wext_siwrts,
+ [IW_IOCTL_IDX(SIOCGIWRTS)] = (iw_handler) cfg80211_wext_giwrts,
+ [IW_IOCTL_IDX(SIOCSIWFRAG)] = (iw_handler) cfg80211_wext_siwfrag,
+ [IW_IOCTL_IDX(SIOCGIWFRAG)] = (iw_handler) cfg80211_wext_giwfrag,
+ [IW_IOCTL_IDX(SIOCSIWTXPOW)] = (iw_handler) cfg80211_wext_siwtxpower,
+ [IW_IOCTL_IDX(SIOCGIWTXPOW)] = (iw_handler) cfg80211_wext_giwtxpower,
+ [IW_IOCTL_IDX(SIOCSIWRETRY)] = (iw_handler) cfg80211_wext_siwretry,
+ [IW_IOCTL_IDX(SIOCGIWRETRY)] = (iw_handler) cfg80211_wext_giwretry,
+ [IW_IOCTL_IDX(SIOCSIWENCODE)] = (iw_handler) cfg80211_wext_siwencode,
+ [IW_IOCTL_IDX(SIOCGIWENCODE)] = (iw_handler) cfg80211_wext_giwencode,
+ [IW_IOCTL_IDX(SIOCSIWPOWER)] = (iw_handler) cfg80211_wext_siwpower,
+ [IW_IOCTL_IDX(SIOCGIWPOWER)] = (iw_handler) cfg80211_wext_giwpower,
+ [IW_IOCTL_IDX(SIOCSIWGENIE)] = (iw_handler) cfg80211_wext_siwgenie,
+ [IW_IOCTL_IDX(SIOCSIWAUTH)] = (iw_handler) cfg80211_wext_siwauth,
+ [IW_IOCTL_IDX(SIOCGIWAUTH)] = (iw_handler) cfg80211_wext_giwauth,
+ [IW_IOCTL_IDX(SIOCSIWENCODEEXT)]= (iw_handler) cfg80211_wext_siwencodeext,
+};
+
+const struct iw_handler_def cfg80211_wext_handler = {
+ .num_standard = ARRAY_SIZE(cfg80211_handlers),
+ .standard = cfg80211_handlers,
+ .get_wireless_stats = cfg80211_wireless_stats,
+};
diff --git a/net/wireless/wext-compat.h b/net/wireless/wext-compat.h
new file mode 100644
index 00000000000..20b3daef696
--- /dev/null
+++ b/net/wireless/wext-compat.h
@@ -0,0 +1,49 @@
+#ifndef __WEXT_COMPAT
+#define __WEXT_COMPAT
+
+#include <net/iw_handler.h>
+#include <linux/wireless.h>
+
+int cfg80211_ibss_wext_siwfreq(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_freq *freq, char *extra);
+int cfg80211_ibss_wext_giwfreq(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_freq *freq, char *extra);
+int cfg80211_ibss_wext_siwap(struct net_device *dev,
+ struct iw_request_info *info,
+ struct sockaddr *ap_addr, char *extra);
+int cfg80211_ibss_wext_giwap(struct net_device *dev,
+ struct iw_request_info *info,
+ struct sockaddr *ap_addr, char *extra);
+int cfg80211_ibss_wext_siwessid(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *data, char *ssid);
+int cfg80211_ibss_wext_giwessid(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *data, char *ssid);
+
+int cfg80211_mgd_wext_siwfreq(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_freq *freq, char *extra);
+int cfg80211_mgd_wext_giwfreq(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_freq *freq, char *extra);
+int cfg80211_mgd_wext_siwap(struct net_device *dev,
+ struct iw_request_info *info,
+ struct sockaddr *ap_addr, char *extra);
+int cfg80211_mgd_wext_giwap(struct net_device *dev,
+ struct iw_request_info *info,
+ struct sockaddr *ap_addr, char *extra);
+int cfg80211_mgd_wext_siwessid(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *data, char *ssid);
+int cfg80211_mgd_wext_giwessid(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *data, char *ssid);
+
+int cfg80211_wext_freq(struct wiphy *wiphy, struct iw_freq *freq);
+
+
+extern const struct iw_handler_def cfg80211_wext_handler;
+#endif /* __WEXT_COMPAT */
diff --git a/net/wireless/wext-sme.c b/net/wireless/wext-sme.c
new file mode 100644
index 00000000000..d16cd9ea4d0
--- /dev/null
+++ b/net/wireless/wext-sme.c
@@ -0,0 +1,404 @@
+/*
+ * cfg80211 wext compat for managed mode.
+ *
+ * Copyright 2009 Johannes Berg <johannes@sipsolutions.net>
+ * Copyright (C) 2009 Intel Corporation. All rights reserved.
+ */
+
+#include <linux/etherdevice.h>
+#include <linux/if_arp.h>
+#include <net/cfg80211.h>
+#include "wext-compat.h"
+#include "nl80211.h"
+
+int cfg80211_mgd_wext_connect(struct cfg80211_registered_device *rdev,
+ struct wireless_dev *wdev)
+{
+ struct cfg80211_cached_keys *ck = NULL;
+ const u8 *prev_bssid = NULL;
+ int err, i;
+
+ ASSERT_RDEV_LOCK(rdev);
+ ASSERT_WDEV_LOCK(wdev);
+
+ if (!netif_running(wdev->netdev))
+ return 0;
+
+ wdev->wext.connect.ie = wdev->wext.ie;
+ wdev->wext.connect.ie_len = wdev->wext.ie_len;
+ wdev->wext.connect.privacy = wdev->wext.default_key != -1;
+
+ if (wdev->wext.keys) {
+ wdev->wext.keys->def = wdev->wext.default_key;
+ wdev->wext.keys->defmgmt = wdev->wext.default_mgmt_key;
+ }
+
+ if (!wdev->wext.connect.ssid_len)
+ return 0;
+
+ if (wdev->wext.keys) {
+ ck = kmemdup(wdev->wext.keys, sizeof(*ck), GFP_KERNEL);
+ if (!ck)
+ return -ENOMEM;
+ for (i = 0; i < 6; i++)
+ ck->params[i].key = ck->data[i];
+ }
+
+ if (wdev->wext.prev_bssid_valid)
+ prev_bssid = wdev->wext.prev_bssid;
+
+ err = __cfg80211_connect(rdev, wdev->netdev,
+ &wdev->wext.connect, ck, prev_bssid);
+ if (err)
+ kfree(ck);
+
+ return err;
+}
+
+int cfg80211_mgd_wext_siwfreq(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_freq *wextfreq, char *extra)
+{
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+ struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
+ struct ieee80211_channel *chan = NULL;
+ int err, freq;
+
+ /* call only for station! */
+ if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION))
+ return -EINVAL;
+
+ freq = cfg80211_wext_freq(wdev->wiphy, wextfreq);
+ if (freq < 0)
+ return freq;
+
+ if (freq) {
+ chan = ieee80211_get_channel(wdev->wiphy, freq);
+ if (!chan)
+ return -EINVAL;
+ if (chan->flags & IEEE80211_CHAN_DISABLED)
+ return -EINVAL;
+ }
+
+ cfg80211_lock_rdev(rdev);
+ mutex_lock(&rdev->devlist_mtx);
+ wdev_lock(wdev);
+
+ if (wdev->sme_state != CFG80211_SME_IDLE) {
+ bool event = true;
+
+ if (wdev->wext.connect.channel == chan) {
+ err = 0;
+ goto out;
+ }
+
+ /* if SSID set, we'll try right again, avoid event */
+ if (wdev->wext.connect.ssid_len)
+ event = false;
+ err = __cfg80211_disconnect(rdev, dev,
+ WLAN_REASON_DEAUTH_LEAVING, event);
+ if (err)
+ goto out;
+ }
+
+
+ wdev->wext.connect.channel = chan;
+
+ /* SSID is not set, we just want to switch channel */
+ if (chan && !wdev->wext.connect.ssid_len) {
+ err = rdev_set_freq(rdev, wdev, freq, NL80211_CHAN_NO_HT);
+ goto out;
+ }
+
+ err = cfg80211_mgd_wext_connect(rdev, wdev);
+ out:
+ wdev_unlock(wdev);
+ mutex_unlock(&rdev->devlist_mtx);
+ cfg80211_unlock_rdev(rdev);
+ return err;
+}
+
+int cfg80211_mgd_wext_giwfreq(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_freq *freq, char *extra)
+{
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+ struct ieee80211_channel *chan = NULL;
+
+ /* call only for station! */
+ if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION))
+ return -EINVAL;
+
+ wdev_lock(wdev);
+ if (wdev->current_bss)
+ chan = wdev->current_bss->pub.channel;
+ else if (wdev->wext.connect.channel)
+ chan = wdev->wext.connect.channel;
+ wdev_unlock(wdev);
+
+ if (chan) {
+ freq->m = chan->center_freq;
+ freq->e = 6;
+ return 0;
+ }
+
+ /* no channel if not joining */
+ return -EINVAL;
+}
+
+int cfg80211_mgd_wext_siwessid(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *data, char *ssid)
+{
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+ struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
+ size_t len = data->length;
+ int err;
+
+ /* call only for station! */
+ if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION))
+ return -EINVAL;
+
+ if (!data->flags)
+ len = 0;
+
+ /* iwconfig uses nul termination in SSID.. */
+ if (len > 0 && ssid[len - 1] == '\0')
+ len--;
+
+ cfg80211_lock_rdev(rdev);
+ mutex_lock(&rdev->devlist_mtx);
+ wdev_lock(wdev);
+
+ err = 0;
+
+ if (wdev->sme_state != CFG80211_SME_IDLE) {
+ bool event = true;
+
+ if (wdev->wext.connect.ssid && len &&
+ len == wdev->wext.connect.ssid_len &&
+ memcmp(wdev->wext.connect.ssid, ssid, len) == 0)
+ goto out;
+
+ /* if SSID set now, we'll try to connect, avoid event */
+ if (len)
+ event = false;
+ err = __cfg80211_disconnect(rdev, dev,
+ WLAN_REASON_DEAUTH_LEAVING, event);
+ if (err)
+ goto out;
+ }
+
+ wdev->wext.prev_bssid_valid = false;
+ wdev->wext.connect.ssid = wdev->wext.ssid;
+ memcpy(wdev->wext.ssid, ssid, len);
+ wdev->wext.connect.ssid_len = len;
+
+ wdev->wext.connect.crypto.control_port = false;
+
+ err = cfg80211_mgd_wext_connect(rdev, wdev);
+ out:
+ wdev_unlock(wdev);
+ mutex_unlock(&rdev->devlist_mtx);
+ cfg80211_unlock_rdev(rdev);
+ return err;
+}
+
+int cfg80211_mgd_wext_giwessid(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *data, char *ssid)
+{
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+
+ /* call only for station! */
+ if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION))
+ return -EINVAL;
+
+ data->flags = 0;
+
+ wdev_lock(wdev);
+ if (wdev->current_bss) {
+ const u8 *ie = ieee80211_bss_get_ie(&wdev->current_bss->pub,
+ WLAN_EID_SSID);
+ if (ie) {
+ data->flags = 1;
+ data->length = ie[1];
+ memcpy(ssid, ie + 2, data->length);
+ }
+ } else if (wdev->wext.connect.ssid && wdev->wext.connect.ssid_len) {
+ data->flags = 1;
+ data->length = wdev->wext.connect.ssid_len;
+ memcpy(ssid, wdev->wext.connect.ssid, data->length);
+ } else
+ data->flags = 0;
+ wdev_unlock(wdev);
+
+ return 0;
+}
+
+int cfg80211_mgd_wext_siwap(struct net_device *dev,
+ struct iw_request_info *info,
+ struct sockaddr *ap_addr, char *extra)
+{
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+ struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
+ u8 *bssid = ap_addr->sa_data;
+ int err;
+
+ /* call only for station! */
+ if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION))
+ return -EINVAL;
+
+ if (ap_addr->sa_family != ARPHRD_ETHER)
+ return -EINVAL;
+
+ /* automatic mode */
+ if (is_zero_ether_addr(bssid) || is_broadcast_ether_addr(bssid))
+ bssid = NULL;
+
+ cfg80211_lock_rdev(rdev);
+ mutex_lock(&rdev->devlist_mtx);
+ wdev_lock(wdev);
+
+ if (wdev->sme_state != CFG80211_SME_IDLE) {
+ err = 0;
+ /* both automatic */
+ if (!bssid && !wdev->wext.connect.bssid)
+ goto out;
+
+ /* fixed already - and no change */
+ if (wdev->wext.connect.bssid && bssid &&
+ compare_ether_addr(bssid, wdev->wext.connect.bssid) == 0)
+ goto out;
+
+ err = __cfg80211_disconnect(rdev, dev,
+ WLAN_REASON_DEAUTH_LEAVING, false);
+ if (err)
+ goto out;
+ }
+
+ if (bssid) {
+ memcpy(wdev->wext.bssid, bssid, ETH_ALEN);
+ wdev->wext.connect.bssid = wdev->wext.bssid;
+ } else
+ wdev->wext.connect.bssid = NULL;
+
+ err = cfg80211_mgd_wext_connect(rdev, wdev);
+ out:
+ wdev_unlock(wdev);
+ mutex_unlock(&rdev->devlist_mtx);
+ cfg80211_unlock_rdev(rdev);
+ return err;
+}
+
+int cfg80211_mgd_wext_giwap(struct net_device *dev,
+ struct iw_request_info *info,
+ struct sockaddr *ap_addr, char *extra)
+{
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+
+ /* call only for station! */
+ if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION))
+ return -EINVAL;
+
+ ap_addr->sa_family = ARPHRD_ETHER;
+
+ wdev_lock(wdev);
+ if (wdev->current_bss)
+ memcpy(ap_addr->sa_data, wdev->current_bss->pub.bssid, ETH_ALEN);
+ else if (wdev->wext.connect.bssid)
+ memcpy(ap_addr->sa_data, wdev->wext.connect.bssid, ETH_ALEN);
+ else
+ memset(ap_addr->sa_data, 0, ETH_ALEN);
+ wdev_unlock(wdev);
+
+ return 0;
+}
+
+int cfg80211_wext_siwgenie(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *data, char *extra)
+{
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+ struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
+ u8 *ie = extra;
+ int ie_len = data->length, err;
+
+ if (wdev->iftype != NL80211_IFTYPE_STATION)
+ return -EOPNOTSUPP;
+
+ if (!ie_len)
+ ie = NULL;
+
+ wdev_lock(wdev);
+
+ /* no change */
+ err = 0;
+ if (wdev->wext.ie_len == ie_len &&
+ memcmp(wdev->wext.ie, ie, ie_len) == 0)
+ goto out;
+
+ if (ie_len) {
+ ie = kmemdup(extra, ie_len, GFP_KERNEL);
+ if (!ie) {
+ err = -ENOMEM;
+ goto out;
+ }
+ } else
+ ie = NULL;
+
+ kfree(wdev->wext.ie);
+ wdev->wext.ie = ie;
+ wdev->wext.ie_len = ie_len;
+
+ if (wdev->sme_state != CFG80211_SME_IDLE) {
+ err = __cfg80211_disconnect(rdev, dev,
+ WLAN_REASON_DEAUTH_LEAVING, false);
+ if (err)
+ goto out;
+ }
+
+ /* userspace better not think we'll reconnect */
+ err = 0;
+ out:
+ wdev_unlock(wdev);
+ return err;
+}
+EXPORT_SYMBOL_GPL(cfg80211_wext_siwgenie);
+
+int cfg80211_wext_siwmlme(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *data, char *extra)
+{
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+ struct iw_mlme *mlme = (struct iw_mlme *)extra;
+ struct cfg80211_registered_device *rdev;
+ int err;
+
+ if (!wdev)
+ return -EOPNOTSUPP;
+
+ rdev = wiphy_to_dev(wdev->wiphy);
+
+ if (wdev->iftype != NL80211_IFTYPE_STATION)
+ return -EINVAL;
+
+ if (mlme->addr.sa_family != ARPHRD_ETHER)
+ return -EINVAL;
+
+ wdev_lock(wdev);
+ switch (mlme->cmd) {
+ case IW_MLME_DEAUTH:
+ case IW_MLME_DISASSOC:
+ err = __cfg80211_disconnect(rdev, dev, mlme->reason_code,
+ true);
+ break;
+ default:
+ err = -EOPNOTSUPP;
+ break;
+ }
+ wdev_unlock(wdev);
+
+ return err;
+}
+EXPORT_SYMBOL_GPL(cfg80211_wext_siwmlme);
diff --git a/net/wireless/wext.c b/net/wireless/wext.c
index 252c2010c2e..5b4a0cee441 100644
--- a/net/wireless/wext.c
+++ b/net/wireless/wext.c
@@ -417,6 +417,21 @@ static const int event_type_size[] = {
IW_EV_QUAL_LEN, /* IW_HEADER_TYPE_QUAL */
};
+#ifdef CONFIG_COMPAT
+static const int compat_event_type_size[] = {
+ IW_EV_COMPAT_LCP_LEN, /* IW_HEADER_TYPE_NULL */
+ 0,
+ IW_EV_COMPAT_CHAR_LEN, /* IW_HEADER_TYPE_CHAR */
+ 0,
+ IW_EV_COMPAT_UINT_LEN, /* IW_HEADER_TYPE_UINT */
+ IW_EV_COMPAT_FREQ_LEN, /* IW_HEADER_TYPE_FREQ */
+ IW_EV_COMPAT_ADDR_LEN, /* IW_HEADER_TYPE_ADDR */
+ 0,
+ IW_EV_COMPAT_POINT_LEN, /* Without variable payload */
+ IW_EV_COMPAT_PARAM_LEN, /* IW_HEADER_TYPE_PARAM */
+ IW_EV_COMPAT_QUAL_LEN, /* IW_HEADER_TYPE_QUAL */
+};
+#endif
/************************ COMMON SUBROUTINES ************************/
/*
@@ -610,6 +625,11 @@ static void wireless_seq_printf_stats(struct seq_file *seq,
{
/* Get stats from the driver */
struct iw_statistics *stats = get_wireless_stats(dev);
+ static struct iw_statistics nullstats = {};
+
+ /* show device if it's wireless regardless of current stats */
+ if (!stats && dev->wireless_handlers)
+ stats = &nullstats;
if (stats) {
seq_printf(seq, "%6s: %04x %3d%c %3d%c %3d%c %6d %6d %6d "
@@ -628,7 +648,9 @@ static void wireless_seq_printf_stats(struct seq_file *seq,
stats->discard.nwid, stats->discard.code,
stats->discard.fragment, stats->discard.retries,
stats->discard.misc, stats->miss.beacon);
- stats->qual.updated &= ~IW_QUAL_ALL_UPDATED;
+
+ if (stats != &nullstats)
+ stats->qual.updated &= ~IW_QUAL_ALL_UPDATED;
}
}
@@ -1250,65 +1272,57 @@ int compat_wext_handle_ioctl(struct net *net, unsigned int cmd,
}
#endif
-/************************* EVENT PROCESSING *************************/
-/*
- * Process events generated by the wireless layer or the driver.
- * Most often, the event will be propagated through rtnetlink
- */
+static int __net_init wext_pernet_init(struct net *net)
+{
+ skb_queue_head_init(&net->wext_nlevents);
+ return 0;
+}
-/* ---------------------------------------------------------------- */
-/*
- * Locking...
- * ----------
- *
- * Thanks to Herbert Xu <herbert@gondor.apana.org.au> for fixing
- * the locking issue in here and implementing this code !
- *
- * The issue : wireless_send_event() is often called in interrupt context,
- * while the Netlink layer can never be called in interrupt context.
- * The fully formed RtNetlink events are queued, and then a tasklet is run
- * to feed those to Netlink.
- * The skb_queue is interrupt safe, and its lock is not held while calling
- * Netlink, so there is no possibility of dealock.
- * Jean II
- */
+static void __net_exit wext_pernet_exit(struct net *net)
+{
+ skb_queue_purge(&net->wext_nlevents);
+}
-static struct sk_buff_head wireless_nlevent_queue;
+static struct pernet_operations wext_pernet_ops = {
+ .init = wext_pernet_init,
+ .exit = wext_pernet_exit,
+};
static int __init wireless_nlevent_init(void)
{
- skb_queue_head_init(&wireless_nlevent_queue);
- return 0;
+ return register_pernet_subsys(&wext_pernet_ops);
}
subsys_initcall(wireless_nlevent_init);
-static void wireless_nlevent_process(unsigned long data)
+/* Process events generated by the wireless layer or the driver. */
+static void wireless_nlevent_process(struct work_struct *work)
{
struct sk_buff *skb;
+ struct net *net;
- while ((skb = skb_dequeue(&wireless_nlevent_queue)))
- rtnl_notify(skb, &init_net, 0, RTNLGRP_LINK, NULL, GFP_ATOMIC);
+ rtnl_lock();
+
+ for_each_net(net) {
+ while ((skb = skb_dequeue(&net->wext_nlevents)))
+ rtnl_notify(skb, net, 0, RTNLGRP_LINK, NULL,
+ GFP_KERNEL);
+ }
+
+ rtnl_unlock();
}
-static DECLARE_TASKLET(wireless_nlevent_tasklet, wireless_nlevent_process, 0);
+static DECLARE_WORK(wireless_nlevent_work, wireless_nlevent_process);
-/* ---------------------------------------------------------------- */
-/*
- * Fill a rtnetlink message with our event data.
- * Note that we propage only the specified event and don't dump the
- * current wireless config. Dumping the wireless config is far too
- * expensive (for each parameter, the driver need to query the hardware).
- */
-static int rtnetlink_fill_iwinfo(struct sk_buff *skb, struct net_device *dev,
- int type, char *event, int event_len)
+static struct nlmsghdr *rtnetlink_ifinfo_prep(struct net_device *dev,
+ struct sk_buff *skb)
{
struct ifinfomsg *r;
struct nlmsghdr *nlh;
- nlh = nlmsg_put(skb, 0, 0, type, sizeof(*r), 0);
- if (nlh == NULL)
- return -EMSGSIZE;
+ nlh = nlmsg_put(skb, 0, 0, RTM_NEWLINK, sizeof(*r), 0);
+ if (!nlh)
+ return NULL;
r = nlmsg_data(nlh);
r->ifi_family = AF_UNSPEC;
@@ -1319,48 +1333,14 @@ static int rtnetlink_fill_iwinfo(struct sk_buff *skb, struct net_device *dev,
r->ifi_change = 0; /* Wireless changes don't affect those flags */
NLA_PUT_STRING(skb, IFLA_IFNAME, dev->name);
- /* Add the wireless events in the netlink packet */
- NLA_PUT(skb, IFLA_WIRELESS, event_len, event);
- return nlmsg_end(skb, nlh);
-
-nla_put_failure:
+ return nlh;
+ nla_put_failure:
nlmsg_cancel(skb, nlh);
- return -EMSGSIZE;
+ return NULL;
}
-/* ---------------------------------------------------------------- */
-/*
- * Create and broadcast and send it on the standard rtnetlink socket
- * This is a pure clone rtmsg_ifinfo() in net/core/rtnetlink.c
- * Andrzej Krzysztofowicz mandated that I used a IFLA_XXX field
- * within a RTM_NEWLINK event.
- */
-static void rtmsg_iwinfo(struct net_device *dev, char *event, int event_len)
-{
- struct sk_buff *skb;
- int err;
-
- if (!net_eq(dev_net(dev), &init_net))
- return;
-
- skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
- if (!skb)
- return;
- err = rtnetlink_fill_iwinfo(skb, dev, RTM_NEWLINK, event, event_len);
- if (err < 0) {
- WARN_ON(err == -EMSGSIZE);
- kfree_skb(skb);
- return;
- }
-
- NETLINK_CB(skb).dst_group = RTNLGRP_LINK;
- skb_queue_tail(&wireless_nlevent_queue, skb);
- tasklet_schedule(&wireless_nlevent_tasklet);
-}
-
-/* ---------------------------------------------------------------- */
/*
* Main event dispatcher. Called from other parts and drivers.
* Send the event on the appropriate channels.
@@ -1369,7 +1349,7 @@ static void rtmsg_iwinfo(struct net_device *dev, char *event, int event_len)
void wireless_send_event(struct net_device * dev,
unsigned int cmd,
union iwreq_data * wrqu,
- char * extra)
+ const char * extra)
{
const struct iw_ioctl_description * descr = NULL;
int extra_len = 0;
@@ -1379,6 +1359,25 @@ void wireless_send_event(struct net_device * dev,
int wrqu_off = 0; /* Offset in wrqu */
/* Don't "optimise" the following variable, it will crash */
unsigned cmd_index; /* *MUST* be unsigned */
+ struct sk_buff *skb;
+ struct nlmsghdr *nlh;
+ struct nlattr *nla;
+#ifdef CONFIG_COMPAT
+ struct __compat_iw_event *compat_event;
+ struct compat_iw_point compat_wrqu;
+ struct sk_buff *compskb;
+#endif
+
+ /*
+ * Nothing in the kernel sends scan events with data, be safe.
+ * This is necessary because we cannot fix up scan event data
+ * for compat, due to being contained in 'extra', but normally
+ * applications are required to retrieve the scan data anyway
+ * and no data is included in the event, this codifies that
+ * practice.
+ */
+ if (WARN_ON(cmd == SIOCGIWSCAN && extra))
+ extra = NULL;
/* Get the description of the Event */
if (cmd <= SIOCIWLAST) {
@@ -1426,25 +1425,107 @@ void wireless_send_event(struct net_device * dev,
hdr_len = event_type_size[descr->header_type];
event_len = hdr_len + extra_len;
- /* Create temporary buffer to hold the event */
- event = kmalloc(event_len, GFP_ATOMIC);
- if (event == NULL)
+ /*
+ * The problem for 64/32 bit.
+ *
+ * On 64-bit, a regular event is laid out as follows:
+ * | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
+ * | event.len | event.cmd | p a d d i n g |
+ * | wrqu data ... (with the correct size) |
+ *
+ * This padding exists because we manipulate event->u,
+ * and 'event' is not packed.
+ *
+ * An iw_point event is laid out like this instead:
+ * | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
+ * | event.len | event.cmd | p a d d i n g |
+ * | iwpnt.len | iwpnt.flg | p a d d i n g |
+ * | extra data ...
+ *
+ * The second padding exists because struct iw_point is extended,
+ * but this depends on the platform...
+ *
+ * On 32-bit, all the padding shouldn't be there.
+ */
+
+ skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
+ if (!skb)
+ return;
+
+ /* Send via the RtNetlink event channel */
+ nlh = rtnetlink_ifinfo_prep(dev, skb);
+ if (WARN_ON(!nlh)) {
+ kfree_skb(skb);
+ return;
+ }
+
+ /* Add the wireless events in the netlink packet */
+ nla = nla_reserve(skb, IFLA_WIRELESS, event_len);
+ if (!nla) {
+ kfree_skb(skb);
return;
+ }
+ event = nla_data(nla);
- /* Fill event */
+ /* Fill event - first clear to avoid data leaking */
+ memset(event, 0, hdr_len);
event->len = event_len;
event->cmd = cmd;
memcpy(&event->u, ((char *) wrqu) + wrqu_off, hdr_len - IW_EV_LCP_LEN);
- if (extra)
+ if (extra_len)
memcpy(((char *) event) + hdr_len, extra, extra_len);
+ nlmsg_end(skb, nlh);
+#ifdef CONFIG_COMPAT
+ hdr_len = compat_event_type_size[descr->header_type];
+ event_len = hdr_len + extra_len;
+
+ compskb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
+ if (!compskb) {
+ kfree_skb(skb);
+ return;
+ }
+
/* Send via the RtNetlink event channel */
- rtmsg_iwinfo(dev, (char *) event, event_len);
+ nlh = rtnetlink_ifinfo_prep(dev, compskb);
+ if (WARN_ON(!nlh)) {
+ kfree_skb(skb);
+ kfree_skb(compskb);
+ return;
+ }
- /* Cleanup */
- kfree(event);
+ /* Add the wireless events in the netlink packet */
+ nla = nla_reserve(compskb, IFLA_WIRELESS, event_len);
+ if (!nla) {
+ kfree_skb(skb);
+ kfree_skb(compskb);
+ return;
+ }
+ compat_event = nla_data(nla);
- return; /* Always success, I guess ;-) */
+ compat_event->len = event_len;
+ compat_event->cmd = cmd;
+ if (descr->header_type == IW_HEADER_TYPE_POINT) {
+ compat_wrqu.length = wrqu->data.length;
+ compat_wrqu.flags = wrqu->data.flags;
+ memcpy(&compat_event->pointer,
+ ((char *) &compat_wrqu) + IW_EV_COMPAT_POINT_OFF,
+ hdr_len - IW_EV_COMPAT_LCP_LEN);
+ if (extra_len)
+ memcpy(((char *) compat_event) + hdr_len,
+ extra, extra_len);
+ } else {
+ /* extra_len must be zero, so no if (extra) needed */
+ memcpy(&compat_event->pointer, wrqu,
+ hdr_len - IW_EV_COMPAT_LCP_LEN);
+ }
+
+ nlmsg_end(compskb, nlh);
+
+ skb_shinfo(skb)->frag_list = compskb;
+#endif
+ skb_queue_tail(&dev_net(dev)->wext_nlevents, skb);
+ schedule_work(&wireless_nlevent_work);
}
EXPORT_SYMBOL(wireless_send_event);